Slimstat Analytics - Version 3.9.7

Version Description

  • [Note] The uninstall routine now deletes the archive table (wp_slim_stats_archive) along with all the other tables (thank you, KalleL)
  • [New] Some users who are using our "track external sites" feature, were getting an error saying that no 'Access-Control-Allow-Origin' header was present on the requested resource. We've added a new option under Settings > Advanced that allows you to specify what domains to allow. Please refer to this page for more information about the security implications of allowing an external domain to submit AJAX requests to your server.
  • [New] Added debugging information (most recent tracker error code) under Slimstat > Settings > Maintenance tab > Debugging. This information is useful to troubleshoot issues with the tracker. Please include it when sending a support request.
  • [Fix] The option to delete pageviews based on given filters (Settings > Maintenance > Data Maintenance) was not working as expected (thank you, kentahayashi)
  • [Fix] The uninstall script was not deleting all the tables as expected (thank you, KalleL)
  • [Fix] We've implemented Marc-Alexandre's new recommendations to further tighten up our SQL queries.
  • [Fix] The new encryption key was affecting the way external sites could be tracked. You can now track non-WP sites again: please make sure to copy and paste the new tracking code (Settings > Advanced) right before your closing BODY tag at the end of your pages.
Download this release

Release Info

Developer coolmann
Plugin Icon 128x128 Slimstat Analytics
Version 3.9.7
Comparing to
See all releases

Code changes from version 3.9.6 to 3.9.7

admin/config/index.php CHANGED
@@ -28,8 +28,8 @@ switch ($config_tabs[$current_tab-1]){
28
  'add_posts_column' => array( 'description' => __('Add Stats to Posts and Pages','wp-slimstat'), 'type' => 'yesno', 'long_description' => __('Add a new column to the Edit Posts/Pages screens, with the number of hits per post.','wp-slimstat') ),
29
 
30
  'general_database_header' => array('description' => __('Database','wp-slimstat'), 'type' => 'section_header'),
31
- 'auto_purge_delete' => array( 'description' => __('Delete records','wp-slimstat'), 'type' => 'yesno', 'long_description' => __('If database space is not an issue, you can decide to archive older records in another table, instead of deleting them. This way performance is preserved, but you will still be able to access your data at a later time, if needed.','wp-slimstat') ),
32
- 'auto_purge' => array( 'description' => __('Retain data for','wp-slimstat'), 'type' => 'integer', 'long_description' => __("Clean-up log entries older than the number of days specified here above. Enter <strong>0</strong> (number zero) if you want to preserve your data regardless of its age.",'wp-slimstat').(wp_get_schedule('wp_slimstat_purge')?' '.__('Next clean-up on','wp-slimstat').' <strong>'.date_i18n(get_option('date_format').', '.get_option('time_format'), wp_next_scheduled('wp_slimstat_purge')).'</strong>. '.sprintf(__('Entries logged on or before %s will be permanently deleted.','wp-slimstat'), date_i18n(get_option('date_format'), strtotime('-'.wp_slimstat::$options['auto_purge'].' days'))):''), 'after_input_field' => __('days','wp-slimstat') )
33
  );
34
 
35
  // If autopurge = 0, we can unschedule our cron job. If autopurge > 0 and the hook was not scheduled, we schedule it
@@ -215,7 +215,6 @@ switch ($config_tabs[$current_tab-1]){
215
  }
216
  break;
217
  case __('Advanced','wp-slimstat'):
218
- $this_domain = parse_url(get_bloginfo('url'));
219
  $encoded_ci = 'YTo0OntzOjEyOiJjb250ZW50X3R5cGUiO3M6ODoiZXh0ZXJuYWwiO3M6ODoiY2F0ZWdvcnkiO3M6MDoiIjtzOjEwOiJjb250ZW50X2lkIjtpOjA7czo2OiJhdXRob3IiO3M6MTM6ImV4dGVybmFsLXBhZ2UiO30=';
220
  $encoded_ci = $encoded_ci.'.'.md5($encoded_ci.wp_slimstat::$options['secret']);
221
 
@@ -228,7 +227,7 @@ switch ($config_tabs[$current_tab-1]){
228
  'extensions_to_track' => array('description' => __('Extensions to Track','wp-slimstat'), 'type' => 'textarea', 'long_description' => __("List all the file extensions that you want to be treated as Downloads. Please note that links pointing to external resources (i.e. PDFs on a different website) are considered Downloads and not Outbound Links (and tracked as such), if their extension matches one of the ones listed here below.",'wp-slimstat')),
229
 
230
  'advanced_external_pages_header' => array('description' => __('External Pages','wp-slimstat'), 'type' => 'section_header'),
231
- 'external_pages_script' => array('type' => 'static', 'skip_update' => 'yes', 'description' => __('Add the following code to all the non-WP pages you want to track','wp-slimstat'), 'long_description' => '&lt;script type="text/javascript"&gt;
232
  /* &lt;![CDATA[ */
233
  var SlimStatParams = {
234
  ajaxurl: "'.admin_url('admin-ajax.php').'",
@@ -238,7 +237,7 @@ var SlimStatParams = {
238
  /* ]]&gt; */
239
  &lt;/script&gt;
240
  &lt;script type="text/javascript" src="http://cdn.jsdelivr.net/wp/wp-slimstat/trunk/wp-slimstat.js"&gt;&lt;/script&gt;'),
241
-
242
  'advanced_misc_header' => array('description' => __('Miscellaneous','wp-slimstat'), 'type' => 'section_header'),
243
  'show_sql_debug' => array('description' => __('Debug Mode','wp-slimstat'), 'type' => 'yesno', 'long_description' => __('Display the SQL queries used to retrieve the data.','wp-slimstat')),
244
  'ip_lookup_service' => array('description' => __('IP Lookup','wp-slimstat'), 'type' => 'text', 'long_description' => __('Customize the Geolocation service to be used in the reports.','wp-slimstat')),
28
  'add_posts_column' => array( 'description' => __('Add Stats to Posts and Pages','wp-slimstat'), 'type' => 'yesno', 'long_description' => __('Add a new column to the Edit Posts/Pages screens, with the number of hits per post.','wp-slimstat') ),
29
 
30
  'general_database_header' => array('description' => __('Database','wp-slimstat'), 'type' => 'section_header'),
31
+ 'auto_purge' => array( 'description' => __('Retain data for','wp-slimstat'), 'type' => 'integer', 'long_description' => __("Clean-up log entries older than the number of days specified here above. Enter <strong>0</strong> (number zero) if you want to preserve your data regardless of its age.",'wp-slimstat').(wp_get_schedule('wp_slimstat_purge')?' '.__('Next clean-up on','wp-slimstat').' <strong>'.date_i18n(get_option('date_format').', '.get_option('time_format'), wp_next_scheduled('wp_slimstat_purge')).'</strong>. '.sprintf(__('Entries logged on or before %s will be archived or deleted according to the option here below.','wp-slimstat'), date_i18n(get_option('date_format'), strtotime('-'.wp_slimstat::$options['auto_purge'].' days'))):''), 'after_input_field' => __('days','wp-slimstat') ),
32
+ 'auto_purge_delete' => array( 'description' => __('Delete records','wp-slimstat'), 'type' => 'yesno', 'long_description' => __('If DB space is not an issue, you can decide to archive older records in another table, instead of deleting them. This way performance is preserved, but you will still be able to access your data at a later time, if needed. Please note that the archive table (<code>wp_slim_stats_archive</code>) will be <strong>deleted</strong> along with all the other tables, when Slimstat is uninstalled. Make sure to backup your data before you proceed.','wp-slimstat') )
33
  );
34
 
35
  // If autopurge = 0, we can unschedule our cron job. If autopurge > 0 and the hook was not scheduled, we schedule it
215
  }
216
  break;
217
  case __('Advanced','wp-slimstat'):
 
218
  $encoded_ci = 'YTo0OntzOjEyOiJjb250ZW50X3R5cGUiO3M6ODoiZXh0ZXJuYWwiO3M6ODoiY2F0ZWdvcnkiO3M6MDoiIjtzOjEwOiJjb250ZW50X2lkIjtpOjA7czo2OiJhdXRob3IiO3M6MTM6ImV4dGVybmFsLXBhZ2UiO30=';
219
  $encoded_ci = $encoded_ci.'.'.md5($encoded_ci.wp_slimstat::$options['secret']);
220
 
227
  'extensions_to_track' => array('description' => __('Extensions to Track','wp-slimstat'), 'type' => 'textarea', 'long_description' => __("List all the file extensions that you want to be treated as Downloads. Please note that links pointing to external resources (i.e. PDFs on a different website) are considered Downloads and not Outbound Links (and tracked as such), if their extension matches one of the ones listed here below.",'wp-slimstat')),
228
 
229
  'advanced_external_pages_header' => array('description' => __('External Pages','wp-slimstat'), 'type' => 'section_header'),
230
+ 'external_pages_script' => array('type' => 'static', 'skip_update' => 'yes', 'description' => __('Add the following code to all the non-WP pages you want to track, right before the closing BODY tag','wp-slimstat'), 'long_description' => '&lt;script type="text/javascript"&gt;
231
  /* &lt;![CDATA[ */
232
  var SlimStatParams = {
233
  ajaxurl: "'.admin_url('admin-ajax.php').'",
237
  /* ]]&gt; */
238
  &lt;/script&gt;
239
  &lt;script type="text/javascript" src="http://cdn.jsdelivr.net/wp/wp-slimstat/trunk/wp-slimstat.js"&gt;&lt;/script&gt;'),
240
+ 'external_domains' => array('description' => __('Allow External Domains','wp-slimstat'), 'type' => 'textarea', 'long_description' => __("If you are getting an error saying that no 'Access-Control-Allow-Origin' header is present on the requested resource, when using the external tracking code here above, list the domains (complete with scheme, separated by commas) you would like to allow. For example: <code>http://my.domain.ext</code> (no trailing slash). Please see <a href='http://www.w3.org/TR/cors/#security' target='_blank'>this W3 resource</a> for more information on the security implications of allowing CORS requests.",'wp-slimstat')),
241
  'advanced_misc_header' => array('description' => __('Miscellaneous','wp-slimstat'), 'type' => 'section_header'),
242
  'show_sql_debug' => array('description' => __('Debug Mode','wp-slimstat'), 'type' => 'yesno', 'long_description' => __('Display the SQL queries used to retrieve the data.','wp-slimstat')),
243
  'ip_lookup_service' => array('description' => __('IP Lookup','wp-slimstat'), 'type' => 'text', 'long_description' => __('Customize the Geolocation service to be used in the reports.','wp-slimstat')),
admin/config/maintenance.php CHANGED
@@ -1,6 +1,8 @@
1
  <?php
2
  // Avoid direct access to this piece of code
3
- if (!function_exists('add_action') || (!empty($_POST) && !check_admin_referer('maintenance_wp_slimstat','maintenance_wp_slimstat_nonce'))) exit(0);
 
 
4
 
5
  include_once(dirname(dirname(__FILE__))."/view/wp-slimstat-reports.php");
6
  wp_slimstat_reports::init();
@@ -24,8 +26,8 @@ if (!empty($_REQUEST['action'])){
24
  if (key_exists($_POST['f'], wp_slimstat_reports::$dropdown_filter_names)){
25
  $rows_affected = wp_slimstat::$wpdb->query('
26
  DELETE t1.*
27
- FROM '.wp_slimstat_db::$sql_filters['from']['all_tables'].'
28
- WHERE 1=1 '.wp_slimstat_db::$sql_filters['where']);
29
  }
30
  wp_slimstat_admin::show_alert_message(intval($rows_affected).' '.__('records deleted from your database.','wp-slimstat'), 'updated below-h2');
31
  break;
@@ -66,7 +68,7 @@ if (!empty($_REQUEST['action'])){
66
  wp_slimstat::$wpdb->query("ALTER TABLE {$GLOBALS['wpdb']->prefix}slim_stats DROP INDEX stats_browser_idx");
67
  wp_slimstat::$wpdb->query("ALTER TABLE {$GLOBALS['wpdb']->base_prefix}slim_browsers DROP INDEX browser_all_idx");
68
  wp_slimstat::$wpdb->query("ALTER TABLE {$GLOBALS['wpdb']->base_prefix}slim_screenres DROP INDEX screenres_all_idx");
69
- wp_slimstat_admin::show_alert_message(__('Indexing has been successfully disabled. Enjoy the extra database space you just gained!','wp-slimstat'), 'updated below-h2');
70
  break;
71
  case 'import-settings':
72
  $new_options = @unserialize(stripslashes($_POST['import-slimstat-settings']));
@@ -116,7 +118,7 @@ $suffixes = array('bytes', 'KB', 'MB', 'GB', 'TB');
116
 
117
  echo '<tr '.(($i%2==0)?'class="alternate"':'').">
118
  <th scope='row'>{$a_table['Name']}</th>
119
- <td>".$a_table['Data_length_with_suffix'].'<br/>'.number_format($a_table['Rows'], 0).' '.__('records','wp-slimstat').'</td>
120
  </tr>';
121
  }
122
  ?>
@@ -160,39 +162,46 @@ $suffixes = array('bytes', 'KB', 'MB', 'GB', 'TB');
160
  </td>
161
  </tr>
162
  <tr class="alternate">
163
- <th scope="row"><?php _e('Truncate Tables','wp-slimstat') ?></th>
164
- <td>
165
  <a class="button-secondary" href="<?php echo wp_slimstat_admin::$config_url.$current_tab ?>&amp;action=truncate-table"
166
  onclick="return(confirm('<?php _e('Are you sure you want to PERMANENTLY DELETE ALL the records from your database?','wp-slimstat'); ?>'))"><?php _e('Delete All Records','wp-slimstat'); ?></a>
 
 
167
  <span class="description"><?php _e('Erase all the information collected so far by Slimstat, including the archive. This operation <strong>does not</strong> reset your settings.','wp-slimstat') ?></span>
168
  </td>
169
  </tr>
170
  <tr>
171
- <th scope="row"><?php _e('Restore archive','wp-slimstat') ?></th>
172
- <td>
173
  <a class="button-secondary" href="<?php echo wp_slimstat_admin::$config_url.$current_tab ?>&amp;action=restore-archived-records"
174
- onclick="return(confirm('<?php _e('Are you sure you want to restore all the archived pageviews?','wp-slimstat'); ?>'))"><?php _e("Get 'em back",'wp-slimstat'); ?></a>
 
 
175
  <span class="description"><?php _e("Move all the archived pageviews back to the main Slimstat table. Please note that, unless you disabled the daily purge, this data will be archived again at the next scheduled clean-up.",'wp-slimstat') ?></span>
176
  </td>
177
  </tr>
178
  <tr class="alternate">
179
- <th scope="row"><?php _e('Empty Archive','wp-slimstat') ?></th>
180
- <td>
181
  <a class="button-secondary" href="<?php echo wp_slimstat_admin::$config_url.$current_tab ?>&amp;action=truncate-archive"
182
  onclick="return(confirm('<?php _e('Are you sure you want to PERMANENTLY DELETE ALL the records from your archive?','wp-slimstat'); ?>'))"><?php _e('Delete Archive','wp-slimstat'); ?></a>
 
 
183
  <span class="description"><?php _e("Erase all the archived records. This operation cannot be undone.",'wp-slimstat') ?></span>
184
  </td>
185
  </tr>
186
  <tr>
187
- <th scope="row"><?php _e('Performance','wp-slimstat') ?></th>
188
- <?php if (empty($check_index)): ?>
189
- <td>
190
  <a class="button-secondary" href="<?php echo wp_slimstat_admin::$config_url.$current_tab ?>&amp;action=activate-indexes"><?php _e("Improve Performance",'wp-slimstat'); ?></a>
 
 
 
191
  <span class="description"><?php _e("Please note that you will need about 30% more DB space to store the extra information required.",'wp-slimstat') ?></span>
192
  </td>
193
  <?php else: ?>
194
- <td>
195
  <a class="button-secondary" href="<?php echo wp_slimstat_admin::$config_url.$current_tab ?>&amp;action=deactivate-indexes"><?php _e('Save DB Space','wp-slimstat'); ?></a>
 
 
196
  <span class="description"><?php _e("Please note that by removing table indexes, Slimstat's performance will be affected.",'wp-slimstat') ?></span>
197
  </td>
198
  <?php endif ?>
@@ -202,7 +211,7 @@ $suffixes = array('bytes', 'KB', 'MB', 'GB', 'TB');
202
  </tr>
203
  <tr>
204
  <td colspan="2">
205
- <strong><?php _e("Here below you can find the current configuration string for Slimstat. You can update your settings by pasting a new string here below and clicking on Import.",'wp-slimstat') ?></strong>
206
  <form action="<?php echo wp_slimstat_admin::$config_url.$current_tab ?>" method="post">
207
  <?php wp_nonce_field( 'maintenance_wp_slimstat', 'maintenance_wp_slimstat_nonce', true, true ) ?>
208
  <input type="hidden" name="action" value="import-settings" />
@@ -212,6 +221,16 @@ $suffixes = array('bytes', 'KB', 'MB', 'GB', 'TB');
212
  </form>
213
  </td>
214
  </tr>
 
 
 
 
 
 
 
 
 
 
215
  <tr>
216
  <td colspan="2" class="slimstat-options-section-header"><?php _e('Miscellaneous','wp-slimstat') ?></td>
217
  </tr>
1
  <?php
2
  // Avoid direct access to this piece of code
3
+ if (!function_exists('add_action') || (!empty($_POST) && !check_admin_referer('maintenance_wp_slimstat','maintenance_wp_slimstat_nonce'))){
4
+ exit(0);
5
+ }
6
 
7
  include_once(dirname(dirname(__FILE__))."/view/wp-slimstat-reports.php");
8
  wp_slimstat_reports::init();
26
  if (key_exists($_POST['f'], wp_slimstat_reports::$dropdown_filter_names)){
27
  $rows_affected = wp_slimstat::$wpdb->query('
28
  DELETE t1.*
29
+ FROM '.wp_slimstat_db::$sql_filters['from']['all'].'
30
+ WHERE 1=1 '.wp_slimstat_db::$sql_filters['where']['all']);
31
  }
32
  wp_slimstat_admin::show_alert_message(intval($rows_affected).' '.__('records deleted from your database.','wp-slimstat'), 'updated below-h2');
33
  break;
68
  wp_slimstat::$wpdb->query("ALTER TABLE {$GLOBALS['wpdb']->prefix}slim_stats DROP INDEX stats_browser_idx");
69
  wp_slimstat::$wpdb->query("ALTER TABLE {$GLOBALS['wpdb']->base_prefix}slim_browsers DROP INDEX browser_all_idx");
70
  wp_slimstat::$wpdb->query("ALTER TABLE {$GLOBALS['wpdb']->base_prefix}slim_screenres DROP INDEX screenres_all_idx");
71
+ wp_slimstat_admin::show_alert_message(__('Indexing has been successfully disabled. Enjoy the extra database space!','wp-slimstat'), 'updated below-h2');
72
  break;
73
  case 'import-settings':
74
  $new_options = @unserialize(stripslashes($_POST['import-slimstat-settings']));
118
 
119
  echo '<tr '.(($i%2==0)?'class="alternate"':'').">
120
  <th scope='row'>{$a_table['Name']}</th>
121
+ <td>".$a_table['Data_length_with_suffix'].' ('.number_format($a_table['Rows'], 0).' '.__('records','wp-slimstat').')</td>
122
  </tr>';
123
  }
124
  ?>
162
  </td>
163
  </tr>
164
  <tr class="alternate">
165
+ <th scope="row">
 
166
  <a class="button-secondary" href="<?php echo wp_slimstat_admin::$config_url.$current_tab ?>&amp;action=truncate-table"
167
  onclick="return(confirm('<?php _e('Are you sure you want to PERMANENTLY DELETE ALL the records from your database?','wp-slimstat'); ?>'))"><?php _e('Delete All Records','wp-slimstat'); ?></a>
168
+ </th>
169
+ <td>
170
  <span class="description"><?php _e('Erase all the information collected so far by Slimstat, including the archive. This operation <strong>does not</strong> reset your settings.','wp-slimstat') ?></span>
171
  </td>
172
  </tr>
173
  <tr>
174
+ <th scope="row">
 
175
  <a class="button-secondary" href="<?php echo wp_slimstat_admin::$config_url.$current_tab ?>&amp;action=restore-archived-records"
176
+ onclick="return(confirm('<?php _e('Are you sure you want to restore all the archived pageviews?','wp-slimstat'); ?>'))"><?php _e("Restore Archive",'wp-slimstat'); ?></a>
177
+ </th>
178
+ <td>
179
  <span class="description"><?php _e("Move all the archived pageviews back to the main Slimstat table. Please note that, unless you disabled the daily purge, this data will be archived again at the next scheduled clean-up.",'wp-slimstat') ?></span>
180
  </td>
181
  </tr>
182
  <tr class="alternate">
183
+ <th scope="row">
 
184
  <a class="button-secondary" href="<?php echo wp_slimstat_admin::$config_url.$current_tab ?>&amp;action=truncate-archive"
185
  onclick="return(confirm('<?php _e('Are you sure you want to PERMANENTLY DELETE ALL the records from your archive?','wp-slimstat'); ?>'))"><?php _e('Delete Archive','wp-slimstat'); ?></a>
186
+ </th>
187
+ <td>
188
  <span class="description"><?php _e("Erase all the archived records. This operation cannot be undone.",'wp-slimstat') ?></span>
189
  </td>
190
  </tr>
191
  <tr>
192
+ <?php if (empty($check_index)): ?>
193
+ <th scope="row">
 
194
  <a class="button-secondary" href="<?php echo wp_slimstat_admin::$config_url.$current_tab ?>&amp;action=activate-indexes"><?php _e("Improve Performance",'wp-slimstat'); ?></a>
195
+ </th>
196
+ <td>
197
+
198
  <span class="description"><?php _e("Please note that you will need about 30% more DB space to store the extra information required.",'wp-slimstat') ?></span>
199
  </td>
200
  <?php else: ?>
201
+ <th scope="row">
202
  <a class="button-secondary" href="<?php echo wp_slimstat_admin::$config_url.$current_tab ?>&amp;action=deactivate-indexes"><?php _e('Save DB Space','wp-slimstat'); ?></a>
203
+ </th>
204
+ <td>
205
  <span class="description"><?php _e("Please note that by removing table indexes, Slimstat's performance will be affected.",'wp-slimstat') ?></span>
206
  </td>
207
  <?php endif ?>
211
  </tr>
212
  <tr>
213
  <td colspan="2">
214
+ <strong><?php _e("Here below you can find the current configuration string for Slimstat. You can update your settings by pasting a new string inside the text area and clicking the Import button.",'wp-slimstat') ?></strong>
215
  <form action="<?php echo wp_slimstat_admin::$config_url.$current_tab ?>" method="post">
216
  <?php wp_nonce_field( 'maintenance_wp_slimstat', 'maintenance_wp_slimstat_nonce', true, true ) ?>
217
  <input type="hidden" name="action" value="import-settings" />
221
  </form>
222
  </td>
223
  </tr>
224
+ <tr>
225
+ <td colspan="2" class="slimstat-options-section-header"><?php _e('Debugging','wp-slimstat') ?></td>
226
+ </tr>
227
+ <tr>
228
+ <th scope="row"><?php _e('Tracker Error Code','wp-slimstat') ?></th>
229
+ <td>
230
+ <?php echo is_array(wp_slimstat::$options['last_tracker_error'])?'<code>'.wp_slimstat::$options['last_tracker_error'][0].' '.wp_slimstat::$options['last_tracker_error'][1].'</code> '.__('recorded on','wp-slimstat').' '.date_i18n(wp_slimstat::$options['date_format'], wp_slimstat::$options['last_tracker_error'][2], true).' '.__('at','wp-slimstat').' '.date_i18n(wp_slimstat::$options['time_format'], wp_slimstat::$options['last_tracker_error'][2], true):__('No Errors so far','wp-slimstat'); ?>
231
+ <span class="description"><?php _e('The information here above is useful to troubleshoot issues with the tracker. Please include this code when sending a support request.','wp-slimstat') ?></span>
232
+ </td>
233
+ </tr>
234
  <tr>
235
  <td colspan="2" class="slimstat-options-section-header"><?php _e('Miscellaneous','wp-slimstat') ?></td>
236
  </tr>
admin/wp-slimstat-admin.php CHANGED
@@ -12,11 +12,10 @@ class wp_slimstat_admin{
12
  */
13
  public static function init(){
14
  if ((wp_slimstat::$options['enable_ads_network'] == 'yes' || wp_slimstat::$options['enable_ads_network'] == 'no')){
15
- self::$admin_notice = "The security of our users' data is our top priority, and for this reason we tightened our SQL queries and made our encryption key harder to guess. If you are using a caching plugin, please <strong>flush its cache</strong> so that the tracking code can be regenerated with the new key. Also, if you are using Slimstat to track external websites, please make sure to replace the tracking code with the new one available under Settings > Advanced. As usual, feel free to contact us if you have any questions.";
16
 
17
- // 3.9.7 self::$admin_notice = "The wait is over: our heatmap add-on is finally available <a href='http://slimstat.getused.to.it/downloads/heatmap/' target='_blank'>on our store</a>. We would like to thank all our users who helped us shape this initial release. Go grab your own copy today! PS: have you noticed those new add-on overview videos on our website?";
18
  // 3.9.8 self::$admin_notice = "We've been working on the documentation for Slimstat. Now you can find <a href='https://slimstat.freshdesk.com/support/solutions' target='_blank'>detailed information</a> about all the actions and filters available in our source code. Developers, use them to build your own custom add-ons! We are also adding video tours of our add-ons, and organizing the source code to make it easier to read and understand.";
19
- // 3.9.9 self::$admin_notice = "Happy birthday, Slimstat. Nine years ago version 0.8.7 was released to the public, starting the unbelievable journey that has taken us here today. We would like to thank all the 25,000 users who appreciate and support our work in many great ways. We wouldn't have more than 1.3 million downloads, 700 5-star reviews, 16 add-ons, video tutorials, etc... if it weren't for you!";
20
  }
21
  else {
22
  self::$admin_notice = "
12
  */
13
  public static function init(){
14
  if ((wp_slimstat::$options['enable_ads_network'] == 'yes' || wp_slimstat::$options['enable_ads_network'] == 'no')){
15
+ self::$admin_notice = "The wait is finally over: our heatmap add-on is now available <a href='http://slimstat.getused.to.it/downloads/heatmap/' target='_blank'>on our store</a>. We would like to thank all our users who helped us shape this extension. Go grab your own copy today! PS: have you noticed those new add-on overview videos on our website?";
16
 
 
17
  // 3.9.8 self::$admin_notice = "We've been working on the documentation for Slimstat. Now you can find <a href='https://slimstat.freshdesk.com/support/solutions' target='_blank'>detailed information</a> about all the actions and filters available in our source code. Developers, use them to build your own custom add-ons! We are also adding video tours of our add-ons, and organizing the source code to make it easier to read and understand.";
18
+ // 3.9.9 self::$admin_notice = "Happy birthday, Slimstat. Nine years ago version 0.8.7 was released to the public, starting the unbelievable journey that has taken us here today. We would like to thank all the 25,000 users who appreciate and support our work in many great ways. We wouldn't have more than 1.3 million downloads, 4.8 out of 5 overall rating, 16 add-ons, video tutorials, etc... if it weren't for you!";
19
  }
20
  else {
21
  self::$admin_notice = "
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i
4
  Tags: analytics, tracking, reports, analyze, wassup, geolocation, online users, spider, tracker, pageviews, stats, maxmind, statistics, statpress
5
  Requires at least: 3.8
6
  Tested up to: 4.2
7
- Stable tag: 3.9.6
8
 
9
  == Description ==
10
  Visit our [website](http://slimstat.getused.to.it/) for more information and to [watch our introductory videos](http://slimstat.getused.to.it/features/video-tutorials/).
@@ -63,6 +63,15 @@ Our knowledge base is available on our [support center](https://slimstat.freshde
63
 
64
  == Changelog ==
65
 
 
 
 
 
 
 
 
 
 
66
  = 3.9.6 =
67
  * [Note] The security of our users' data is our top priority, and for this reason we tightened our SQL queries and made our encryption key harder to guess. If you are using a caching plugin, please flush its cache so that the tracking code can be regenerated with the new key. Also, if you are using Slimstat to track external websites, please make sure to replace the tracking code with the new one available under Settings > Advanced. As usual, feel free to contact us if you have any questions.
68
  * [Note] Added un-minified js tracker to the repo, for those who would like to take a look at how things work.
4
  Tags: analytics, tracking, reports, analyze, wassup, geolocation, online users, spider, tracker, pageviews, stats, maxmind, statistics, statpress
5
  Requires at least: 3.8
6
  Tested up to: 4.2
7
+ Stable tag: 3.9.7
8
 
9
  == Description ==
10
  Visit our [website](http://slimstat.getused.to.it/) for more information and to [watch our introductory videos](http://slimstat.getused.to.it/features/video-tutorials/).
63
 
64
  == Changelog ==
65
 
66
+ = 3.9.7 =
67
+ * [Note] The uninstall routine now deletes the archive table (wp_slim_stats_archive) along with all the other tables (thank you, KalleL)
68
+ * [New] Some users who are using our "track external sites" feature, were getting an error saying that no 'Access-Control-Allow-Origin' header was present on the requested resource. We've added a new option under Settings > Advanced that allows you to specify what domains to allow. Please refer to [this page](http://www.w3.org/TR/cors/#security) for more information about the security implications of allowing an external domain to submit AJAX requests to your server.
69
+ * [New] Added debugging information (most recent tracker error code) under Slimstat > Settings > Maintenance tab > Debugging. This information is useful to troubleshoot issues with the tracker. Please include it when sending a support request.
70
+ * [Fix] The option to delete pageviews based on given filters (Settings > Maintenance > Data Maintenance) was not working as expected (thank you, [kentahayashi](https://wordpress.org/support/topic/cant-delete-pageviews-on-version-396))
71
+ * [Fix] The uninstall script was not deleting all the tables as expected (thank you, [KalleL](https://wordpress.org/support/topic/unable-to-uninstall-wp-slimstat-from-db))
72
+ * [Fix] We've implemented [Marc-Alexandre's new recommendations](http://blog.sucuri.net/2015/02/security-advisory-wp-slimstat-3-9-5-and-lower.html) to further tighten up our SQL queries.
73
+ * [Fix] The new encryption key was affecting the way external sites could be tracked. You can now track non-WP sites again: please make sure to copy and paste the new tracking code (Settings > Advanced) right before your closing BODY tag at the end of your pages.
74
+
75
  = 3.9.6 =
76
  * [Note] The security of our users' data is our top priority, and for this reason we tightened our SQL queries and made our encryption key harder to guess. If you are using a caching plugin, please flush its cache so that the tracking code can be regenerated with the new key. Also, if you are using Slimstat to track external websites, please make sure to replace the tracking code with the new one available under Settings > Advanced. As usual, feel free to contact us if you have any questions.
77
  * [Note] Added un-minified js tracker to the repo, for those who would like to take a look at how things work.
uninstall.php CHANGED
@@ -13,29 +13,30 @@ else {
13
  if (function_exists('is_multisite') && is_multisite()) {
14
  $blogids = $GLOBALS['wpdb']->get_col($GLOBALS['wpdb']->prepare("
15
  SELECT blog_id
16
- FROM $wpdb->blogs
17
  WHERE site_id = %d
18
  AND deleted = 0
19
  AND spam = 0", $GLOBALS['wpdb']->siteid));
20
 
21
  foreach ($blogids as $blog_id) {
22
  switch_to_blog($blog_id);
23
- slimstat_uninstall($slimstat_wpdb);
 
24
  }
25
- restore_current_blog();
26
  }
27
  else{
28
- slimstat_uninstall($slimstat_wpdb);
29
  }
30
 
31
  $slimstat_wpdb->query("DROP TABLE IF EXISTS {$GLOBALS['wpdb']->base_prefix}slim_browsers");
32
  $slimstat_wpdb->query("DROP TABLE IF EXISTS {$GLOBALS['wpdb']->base_prefix}slim_screenres");
33
  $slimstat_wpdb->query("DROP TABLE IF EXISTS {$GLOBALS['wpdb']->base_prefix}slim_content_info");
34
 
35
- function slimstat_uninstall($_wpdb = ''){
36
  // Goodbye data...
37
  $_wpdb->query("DROP TABLE IF EXISTS {$GLOBALS['wpdb']->prefix}slim_outbound");
38
  $_wpdb->query("DROP TABLE IF EXISTS {$GLOBALS['wpdb']->prefix}slim_stats");
 
39
 
40
  // Goodbye options...
41
  delete_option('slimstat_options');
13
  if (function_exists('is_multisite') && is_multisite()) {
14
  $blogids = $GLOBALS['wpdb']->get_col($GLOBALS['wpdb']->prepare("
15
  SELECT blog_id
16
+ FROM {$GLOBALS['wpdb']->blogs}
17
  WHERE site_id = %d
18
  AND deleted = 0
19
  AND spam = 0", $GLOBALS['wpdb']->siteid));
20
 
21
  foreach ($blogids as $blog_id) {
22
  switch_to_blog($blog_id);
23
+ slimstat_uninstall($slimstat_wpdb, $slimstat_options);
24
+ restore_current_blog();
25
  }
 
26
  }
27
  else{
28
+ slimstat_uninstall($slimstat_wpdb, $slimstat_options);
29
  }
30
 
31
  $slimstat_wpdb->query("DROP TABLE IF EXISTS {$GLOBALS['wpdb']->base_prefix}slim_browsers");
32
  $slimstat_wpdb->query("DROP TABLE IF EXISTS {$GLOBALS['wpdb']->base_prefix}slim_screenres");
33
  $slimstat_wpdb->query("DROP TABLE IF EXISTS {$GLOBALS['wpdb']->base_prefix}slim_content_info");
34
 
35
+ function slimstat_uninstall($_wpdb = '', $_options = array()){
36
  // Goodbye data...
37
  $_wpdb->query("DROP TABLE IF EXISTS {$GLOBALS['wpdb']->prefix}slim_outbound");
38
  $_wpdb->query("DROP TABLE IF EXISTS {$GLOBALS['wpdb']->prefix}slim_stats");
39
+ $_wpdb->query("DROP TABLE IF EXISTS {$GLOBALS['wpdb']->prefix}slim_stats_archive");
40
 
41
  // Goodbye options...
42
  delete_option('slimstat_options');
wp-slimstat.js CHANGED
@@ -411,8 +411,9 @@ SlimStat.add_event(window, 'load', function() {
411
  }
412
 
413
  // Do not invoke the callback or don't track links with given classes
414
- if (cur_link.slimstat_track_me && to_ignore.length > 0){
415
  classes_current_link = (typeof cur_link.className != 'undefined' && cur_link.className.length > 0) ? cur_link.className.split(' '):[];
 
416
  for (var cl = 0; cl < classes_current_link.length; cl++){
417
  if (SlimStat.in_array_substring(classes_current_link[cl], to_ignore)) {
418
  cur_link.slimstat_callback = false;
411
  }
412
 
413
  // Do not invoke the callback or don't track links with given classes
414
+ if (cur_link.slimstat_track_me && (to_ignore.length > 0 || to_not_track.length > 0)){
415
  classes_current_link = (typeof cur_link.className != 'undefined' && cur_link.className.length > 0) ? cur_link.className.split(' '):[];
416
+
417
  for (var cl = 0; cl < classes_current_link.length; cl++){
418
  if (SlimStat.in_array_substring(classes_current_link[cl], to_ignore)) {
419
  cur_link.slimstat_callback = false;
wp-slimstat.min.js CHANGED
@@ -1 +1 @@
1
- var SlimStat={_id:"undefined"!=typeof SlimStatParams.id?SlimStatParams.id:"-1.0",_base64_key_str:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",_plugins:{acrobat:{substrings:["Adobe","Acrobat"],active_x_strings:["AcroPDF.PDF","PDF.PDFCtrl.5"]},director:{substrings:["Shockwave","Director"],active_x_strings:["SWCtl.SWCtl"]},flash:{substrings:["Shockwave","Flash"],active_x_strings:["ShockwaveFlash.ShockwaveFlash"]},mediaplayer:{substrings:["Windows Media"],active_x_strings:["WMPlayer.OCX"]},quicktime:{substrings:["QuickTime"],active_x_strings:["QuickTime.QuickTime"]},real:{substrings:["RealPlayer"],active_x_strings:["rmocx.RealPlayer G2 Control","RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)","RealVideo.RealVideo(tm) ActiveX Control (32-bit)"]},silverlight:{substrings:["Silverlight"],active_x_strings:["AgControl.AgControl"]}},_utf8_encode:function(e){var t,n,a="";for(e=e.replace(/\r\n/g,"\n"),t=0;t<e.length;t++)n=e.charCodeAt(t),128>n?a+=String.fromCharCode(n):n>127&&2048>n?(a+=String.fromCharCode(n>>6|192),a+=String.fromCharCode(63&n|128)):(a+=String.fromCharCode(n>>12|224),a+=String.fromCharCode(n>>6&63|128),a+=String.fromCharCode(63&n|128));return a},_base64_encode:function(e){var t,n,a,i,r,o,s,l="",d=0;for(e=SlimStat._utf8_encode(e);d<e.length;)t=e.charCodeAt(d++),n=e.charCodeAt(d++),a=e.charCodeAt(d++),i=t>>2,r=(3&t)<<4|n>>4,o=(15&n)<<2|a>>6,s=63&a,isNaN(n)?o=s=64:isNaN(a)&&(s=64),l=l+SlimStat._base64_key_str.charAt(i)+SlimStat._base64_key_str.charAt(r)+SlimStat._base64_key_str.charAt(o)+this._base64_key_str.charAt(s);return l},_detect_single_plugin_not_ie:function(e){var t,n,a,i;for(a in navigator.plugins){t=""+navigator.plugins[a].name+navigator.plugins[a].description,n=0;for(i in SlimStat._plugins[e].substrings)-1!=t.indexOf(SlimStat._plugins[e].substrings[i])&&n++;if(n==SlimStat._plugins[e].substrings.length)return!0}return!1},_detect_single_plugin_ie:function(e){var t;for(t in SlimStat._plugins[e].active_x_strings)try{return new ActiveXObject(SlimStat._plugins[e].active_x_strings[t]),!0}catch(n){return!1}},_detect_single_plugin:function(e){return this.detect=navigator.plugins.length?this._detect_single_plugin_not_ie:this._detect_single_plugin_ie,this.detect(e)},detect_plugins:function(){var e,t="";for(e in SlimStat._plugins)SlimStat._detect_single_plugin(e)&&(t+=e+"|");return t},has_smoothing:function(){if("undefined"!=typeof screen.fontSmoothingEnabled)return Number(screen.fontSmoothingEnabled);if("undefined"!=typeof SlimStatParams.detect_smoothing)return 0;try{var e=document.createElement("canvas");e.width="35",e.height="35",e.style.display="none",document.body.appendChild(e);var t=e.getContext("2d");t.textBaseline="top",t.font="32px Arial",t.fillStyle="black",t.strokeStyle="black",t.fillText("O",0,0);for(var n=8;32>=n;n++)for(var a=1;32>=a;a++){var i=t.getImageData(a,n,1,1).data,r=i[3];if(255!=r&&0!=r)return 1}return 0}catch(o){return 0}},get_page_performance:function(){return slim_performance=window.performance||window.mozPerformance||window.msPerformance||window.webkitPerformance||{},"undefined"==typeof slim_performance.timing?0:slim_performance.timing.loadEventEnd-slim_performance.timing.responseEnd},get_server_latency:function(){return slim_performance=window.performance||window.mozPerformance||window.msPerformance||window.webkitPerformance||{},"undefined"==typeof slim_performance.timing?0:slim_performance.timing.responseEnd-slim_performance.timing.connectEnd},send_to_server:function(e,t){if("undefined"==typeof SlimStatParams.ajaxurl||"undefined"==typeof e)return"function"==typeof t&&t(),!1;try{window.XMLHttpRequest?request=new XMLHttpRequest:window.ActiveXObject&&(request=new ActiveXObject("Microsoft.XMLHTTP"))}catch(n){return"function"==typeof t&&t(),!1}if(request){var a="action=slimtrack_js&data="+SlimStat._base64_encode(e);return request.open("POST",SlimStatParams.ajaxurl,!0),request.setRequestHeader("Content-type","application/x-www-form-urlencoded"),request.send(a),request.onreadystatechange=function(){4==request.readyState&&("undefined"==typeof SlimStatParams.id?(parsed_id=parseInt(request.responseText),!isNaN(parsed_id)&&parsed_id>0&&(SlimStat._id=request.responseText)):SlimStat._id=SlimStatParams.id,"function"==typeof t&&t())},!0}return!1},ss_track:function(e,t,n,a){if(e||(e=window.event),code="undefined"==typeof t?0:parseInt(t),note_array=[],parsed_id=parseInt(SlimStat._id),isNaN(parsed_id)||parsed_id<=0)return"function"==typeof a&&a(),!1;if(node="undefined"!=typeof e.target?e.target:"undefined"!=typeof e.srcElement?e.srcElement:!1,!node)return"function"==typeof a&&a(),!1;switch(3==node.nodeType&&(node=node.parentNode),parent_node=node.parentNode,node_hostname="",node_pathname=location.pathname,node.nodeName){case"FORM":node.action.length>0&&(node_pathname=escape(node.action));break;case"INPUT":for(;"undefined"!=typeof parent_node&&"FORM"!=parent_node.nodeName&&"BODY"!=parent_node.nodeName;)parent_node=parent_node.parentNode;if("undefined"!=typeof parent_node.action&&parent_node.action.length>0){node_pathname=escape(parent_node.action);break}default:if("A"!=node.nodeName){if("function"==typeof node.getAttribute&&"undefined"!=node.getAttribute("id")&&null!=node.getAttribute("id")&&node.getAttribute("id").length>0){node_pathname=node.getAttribute("id");break}for(;"undefined"!=typeof node.parentNode&&null!=node.parentNode&&"A"!=node.nodeName&&"BODY"!=node.nodeName;)node=node.parentNode}"undefined"!=typeof node.hash&&node.hash.length>0&&node.hostname==location.hostname?node_pathname=escape(node.hash):(node_hostname="undefined"!=typeof node.hostname?node.hostname:"","undefined"!=typeof node.href&&(node_pathname=escape(node.href))),"function"==typeof node.getAttribute&&("undefined"!=node.getAttribute("title")&&null!=node.getAttribute("title")&&node.getAttribute("title").length>0&&note_array.push("Title:"+node.getAttribute("title")),"undefined"!=node.getAttribute("id")&&null!=node.getAttribute("id")&&node.getAttribute("id").length>0&&note_array.push("ID:"+node.getAttribute("id")))}slimstat_info="&obd="+node_hostname+"&obr="+node_pathname,pos_x=-1;var i=-1;return"undefined"!=typeof e.pageX&&"undefined"!=typeof e.pageY?(pos_x=e.pageX,i=e.pageY):"undefined"!=typeof e.clientX&&"undefined"!=typeof e.clientY&&"undefined"!=typeof document.body.scrollLeft&&"undefined"!=typeof document.documentElement.scrollLeft&&"undefined"!=typeof document.body.scrollTop&&"undefined"!=typeof document.documentElement.scrollTop&&(pos_x=e.clientX+document.body.scrollLeft+document.documentElement.scrollLeft,i=e.clientY+document.body.scrollTop+document.documentElement.scrollTop),pos_x>0&&i>0&&(slimstat_info+=(slimstat_info.length>0?"&":"?")+"po="+pos_x+","+i),note_array.push("Event:"+e.type),"undefined"!=typeof n&&n.length>0&&note_array.push(n),"click"!=e.type&&"undefined"!=typeof e.which&&note_array.push("keypress"==e.type?"Key:"+String.fromCharCode(parseInt(e.which)):"Type:"+e.which),SlimStat.send_to_server("id="+SlimStat._id+"&ty="+code+slimstat_info+"&no="+escape(note_array.join(", ")),a),!0},slimstat_plusone:function(e){SlimStat.send_to_server("ty=4&obr="+escape("#google-plus-"+e.state))},add_event:function(e,t,n){e&&e.addEventListener?e.addEventListener(t,n,!1):e&&e.attachEvent?(e["e"+t+n]=n,e[t+n]=function(){e["e"+t+n](window.event)},e.attachEvent("on"+t,e[t+n])):e["on"+t]=e["e"+t+n]},event_fire:function(e,t){var n=e;if(document.createEvent){var a=document.createEvent("MouseEvents");a.initEvent(t,!0,!1),n.dispatchEvent(a)}else if(document.createEventObject){var a=document.createEventObject();n.fireEvent("on"+t,a)}},in_array:function(e,t){for(var n=0;n<t.length;n++)if(t[n].trim()==e)return!0;return!1},in_array_substring:function(e,t){for(var n=0;n<t.length;n++)if(-1!=e.indexOf(t[n].trim()))return!0;return!1}};SlimStat.add_event(window,"load",function(){if("undefined"==typeof SlimStatParams.disable_outbound_tracking){all_links=document.getElementsByTagName("a");for(var e="undefined"!=typeof SlimStatParams.extensions_to_track&&SlimStatParams.extensions_to_track.length>0?SlimStatParams.extensions_to_track.split(","):[],t="undefined"!=typeof SlimStatParams.outbound_classes_rel_href_to_ignore&&SlimStatParams.outbound_classes_rel_href_to_ignore.length>0?SlimStatParams.outbound_classes_rel_href_to_ignore.split(","):[],n="undefined"!=typeof SlimStatParams.outbound_classes_rel_href_to_not_track&&SlimStatParams.outbound_classes_rel_href_to_not_track.length>0?SlimStatParams.outbound_classes_rel_href_to_not_track.split(","):[],a=0;a<all_links.length;a++)!function(){var i=all_links[a];if(i.slimstat_actual_click=!1,i.slimstat_type=!i.href||i.hostname!=location.hostname&&-1!=i.href.indexOf("://")?0:2,i.slimstat_track_me=!0,i.slimstat_callback=!0,e.length>0&&i.pathname.indexOf(".")>0&&i.hostname==location.hostname&&(extension_current_link=i.pathname.split(".").pop().replace(/[\/\-]/g,""),i.slimstat_track_me=SlimStat.in_array(extension_current_link,e),i.slimstat_type=1),!i.slimstat_track_me||2!=i.slimstat_type||"undefined"!=typeof SlimStatParams.track_internal_links&&"false"!=SlimStatParams.track_internal_links||(i.slimstat_track_me=!1),i.slimstat_track_me&&t.length>0){classes_current_link="undefined"!=typeof i.className&&i.className.length>0?i.className.split(" "):[];for(var r=0;r<classes_current_link.length;r++)if(SlimStat.in_array_substring(classes_current_link[r],t)&&(i.slimstat_callback=!1),SlimStat.in_array_substring(classes_current_link[r],n)){i.slimstat_track_me=!1;break}}i.slimstat_track_me&&"undefined"!=typeof i.attributes.rel&&i.attributes.rel.value.length>0&&(SlimStat.in_array_substring(i.attributes.rel.value,t)&&(i.slimstat_callback=!1),SlimStat.in_array_substring(i.attributes.rel.value,n)&&(i.slimstat_track_me=!1)),i.slimstat_track_me&&"undefined"!=typeof i.href&&i.href.length>0&&(SlimStat.in_array_substring(i.href,t)&&(i.slimstat_callback=!1),SlimStat.in_array_substring(i.href,n)&&(i.slimstat_track_me=!1)),i.slimstat_track_me&&i.target&&!i.target.match(/^_(self|parent|top)$/i)&&(i.slimstat_callback=!1),SlimStat.add_event(i,"click",function(e){this.slimstat_track_me&&(this.slimstat_actual_click||(this.slimstat_callback?("function"==typeof e.preventDefault&&e.preventDefault(),this.slimstat_actual_click=!this.slimstat_actual_click,SlimStat.ss_track(e,this.slimstat_type,"",function(){SlimStat.event_fire(i,"click")})):SlimStat.ss_track(e,this.slimstat_type,"",function(){})))})}()}});var current_data="";"undefined"!=typeof SlimStatParams.id&&parseInt(SlimStatParams.id)>0?current_data="id="+SlimStatParams.id:"undefined"!=typeof SlimStatParams.ci&&(current_data="ci="+SlimStatParams.ci+"&ref="+SlimStat._base64_encode(document.referrer)+"&res="+SlimStat._base64_encode(window.location.href)),current_data.length&&SlimStat.add_event(window,"load",function(){setTimeout(function(){SlimStat.send_to_server(current_data+"&sw="+(screen.width||window.innerWidth||document.documentElement.clientWidth||document.body.offsetWidth)+"&sh="+(screen.height||window.innerHeight||document.documentElement.clientHeight||document.body.offsetHeight)+"&cd="+screen.colorDepth+"&aa="+SlimStat.has_smoothing()+"&sl="+SlimStat.get_server_latency()+"&pp="+SlimStat.get_page_performance()+"&pl="+SlimStat.detect_plugins())},0)});
1
+ var SlimStat={_id:"undefined"!=typeof SlimStatParams.id?SlimStatParams.id:"-1.0",_base64_key_str:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",_plugins:{acrobat:{substrings:["Adobe","Acrobat"],active_x_strings:["AcroPDF.PDF","PDF.PDFCtrl.5"]},director:{substrings:["Shockwave","Director"],active_x_strings:["SWCtl.SWCtl"]},flash:{substrings:["Shockwave","Flash"],active_x_strings:["ShockwaveFlash.ShockwaveFlash"]},mediaplayer:{substrings:["Windows Media"],active_x_strings:["WMPlayer.OCX"]},quicktime:{substrings:["QuickTime"],active_x_strings:["QuickTime.QuickTime"]},real:{substrings:["RealPlayer"],active_x_strings:["rmocx.RealPlayer G2 Control","RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)","RealVideo.RealVideo(tm) ActiveX Control (32-bit)"]},silverlight:{substrings:["Silverlight"],active_x_strings:["AgControl.AgControl"]}},_utf8_encode:function(e){var t,n,a="";for(e=e.replace(/\r\n/g,"\n"),t=0;t<e.length;t++)n=e.charCodeAt(t),128>n?a+=String.fromCharCode(n):n>127&&2048>n?(a+=String.fromCharCode(n>>6|192),a+=String.fromCharCode(63&n|128)):(a+=String.fromCharCode(n>>12|224),a+=String.fromCharCode(n>>6&63|128),a+=String.fromCharCode(63&n|128));return a},_base64_encode:function(e){var t,n,a,i,r,o,s,l="",d=0;for(e=SlimStat._utf8_encode(e);d<e.length;)t=e.charCodeAt(d++),n=e.charCodeAt(d++),a=e.charCodeAt(d++),i=t>>2,r=(3&t)<<4|n>>4,o=(15&n)<<2|a>>6,s=63&a,isNaN(n)?o=s=64:isNaN(a)&&(s=64),l=l+SlimStat._base64_key_str.charAt(i)+SlimStat._base64_key_str.charAt(r)+SlimStat._base64_key_str.charAt(o)+this._base64_key_str.charAt(s);return l},_detect_single_plugin_not_ie:function(e){var t,n,a,i;for(a in navigator.plugins){t=""+navigator.plugins[a].name+navigator.plugins[a].description,n=0;for(i in SlimStat._plugins[e].substrings)-1!=t.indexOf(SlimStat._plugins[e].substrings[i])&&n++;if(n==SlimStat._plugins[e].substrings.length)return!0}return!1},_detect_single_plugin_ie:function(e){var t;for(t in SlimStat._plugins[e].active_x_strings)try{return new ActiveXObject(SlimStat._plugins[e].active_x_strings[t]),!0}catch(n){return!1}},_detect_single_plugin:function(e){return this.detect=navigator.plugins.length?this._detect_single_plugin_not_ie:this._detect_single_plugin_ie,this.detect(e)},detect_plugins:function(){var e,t="";for(e in SlimStat._plugins)SlimStat._detect_single_plugin(e)&&(t+=e+"|");return t},has_smoothing:function(){if("undefined"!=typeof screen.fontSmoothingEnabled)return Number(screen.fontSmoothingEnabled);if("undefined"!=typeof SlimStatParams.detect_smoothing)return 0;try{var e=document.createElement("canvas");e.width="35",e.height="35",e.style.display="none",document.body.appendChild(e);var t=e.getContext("2d");t.textBaseline="top",t.font="32px Arial",t.fillStyle="black",t.strokeStyle="black",t.fillText("O",0,0);for(var n=8;32>=n;n++)for(var a=1;32>=a;a++){var i=t.getImageData(a,n,1,1).data,r=i[3];if(255!=r&&0!=r)return 1}return 0}catch(o){return 0}},get_page_performance:function(){return slim_performance=window.performance||window.mozPerformance||window.msPerformance||window.webkitPerformance||{},"undefined"==typeof slim_performance.timing?0:slim_performance.timing.loadEventEnd-slim_performance.timing.responseEnd},get_server_latency:function(){return slim_performance=window.performance||window.mozPerformance||window.msPerformance||window.webkitPerformance||{},"undefined"==typeof slim_performance.timing?0:slim_performance.timing.responseEnd-slim_performance.timing.connectEnd},send_to_server:function(e,t){if("undefined"==typeof SlimStatParams.ajaxurl||"undefined"==typeof e)return"function"==typeof t&&t(),!1;try{window.XMLHttpRequest?request=new XMLHttpRequest:window.ActiveXObject&&(request=new ActiveXObject("Microsoft.XMLHTTP"))}catch(n){return"function"==typeof t&&t(),!1}if(request){var a="action=slimtrack_js&data="+SlimStat._base64_encode(e);return request.open("POST",SlimStatParams.ajaxurl,!0),request.setRequestHeader("Content-type","application/x-www-form-urlencoded"),request.send(a),request.onreadystatechange=function(){4==request.readyState&&("undefined"==typeof SlimStatParams.id?(parsed_id=parseInt(request.responseText),!isNaN(parsed_id)&&parsed_id>0&&(SlimStat._id=request.responseText)):SlimStat._id=SlimStatParams.id,"function"==typeof t&&t())},!0}return!1},ss_track:function(e,t,n,a){if(e||(e=window.event),code="undefined"==typeof t?0:parseInt(t),note_array=[],parsed_id=parseInt(SlimStat._id),isNaN(parsed_id)||parsed_id<=0)return"function"==typeof a&&a(),!1;if(node="undefined"!=typeof e.target?e.target:"undefined"!=typeof e.srcElement?e.srcElement:!1,!node)return"function"==typeof a&&a(),!1;switch(3==node.nodeType&&(node=node.parentNode),parent_node=node.parentNode,node_hostname="",node_pathname=location.pathname,node.nodeName){case"FORM":node.action.length>0&&(node_pathname=escape(node.action));break;case"INPUT":for(;"undefined"!=typeof parent_node&&"FORM"!=parent_node.nodeName&&"BODY"!=parent_node.nodeName;)parent_node=parent_node.parentNode;if("undefined"!=typeof parent_node.action&&parent_node.action.length>0){node_pathname=escape(parent_node.action);break}default:if("A"!=node.nodeName){if("function"==typeof node.getAttribute&&"undefined"!=node.getAttribute("id")&&null!=node.getAttribute("id")&&node.getAttribute("id").length>0){node_pathname=node.getAttribute("id");break}for(;"undefined"!=typeof node.parentNode&&null!=node.parentNode&&"A"!=node.nodeName&&"BODY"!=node.nodeName;)node=node.parentNode}"undefined"!=typeof node.hash&&node.hash.length>0&&node.hostname==location.hostname?node_pathname=escape(node.hash):(node_hostname="undefined"!=typeof node.hostname?node.hostname:"","undefined"!=typeof node.href&&(node_pathname=escape(node.href))),"function"==typeof node.getAttribute&&("undefined"!=node.getAttribute("title")&&null!=node.getAttribute("title")&&node.getAttribute("title").length>0&&note_array.push("Title:"+node.getAttribute("title")),"undefined"!=node.getAttribute("id")&&null!=node.getAttribute("id")&&node.getAttribute("id").length>0&&note_array.push("ID:"+node.getAttribute("id")))}slimstat_info="&obd="+node_hostname+"&obr="+node_pathname,pos_x=-1;var i=-1;return"undefined"!=typeof e.pageX&&"undefined"!=typeof e.pageY?(pos_x=e.pageX,i=e.pageY):"undefined"!=typeof e.clientX&&"undefined"!=typeof e.clientY&&"undefined"!=typeof document.body.scrollLeft&&"undefined"!=typeof document.documentElement.scrollLeft&&"undefined"!=typeof document.body.scrollTop&&"undefined"!=typeof document.documentElement.scrollTop&&(pos_x=e.clientX+document.body.scrollLeft+document.documentElement.scrollLeft,i=e.clientY+document.body.scrollTop+document.documentElement.scrollTop),pos_x>0&&i>0&&(slimstat_info+=(slimstat_info.length>0?"&":"?")+"po="+pos_x+","+i),note_array.push("Event:"+e.type),"undefined"!=typeof n&&n.length>0&&note_array.push(n),"click"!=e.type&&"undefined"!=typeof e.which&&note_array.push("keypress"==e.type?"Key:"+String.fromCharCode(parseInt(e.which)):"Type:"+e.which),SlimStat.send_to_server("id="+SlimStat._id+"&ty="+code+slimstat_info+"&no="+escape(note_array.join(", ")),a),!0},slimstat_plusone:function(e){SlimStat.send_to_server("ty=4&obr="+escape("#google-plus-"+e.state))},add_event:function(e,t,n){e&&e.addEventListener?e.addEventListener(t,n,!1):e&&e.attachEvent?(e["e"+t+n]=n,e[t+n]=function(){e["e"+t+n](window.event)},e.attachEvent("on"+t,e[t+n])):e["on"+t]=e["e"+t+n]},event_fire:function(e,t){var n=e;if(document.createEvent){var a=document.createEvent("MouseEvents");a.initEvent(t,!0,!1),n.dispatchEvent(a)}else if(document.createEventObject){var a=document.createEventObject();n.fireEvent("on"+t,a)}},in_array:function(e,t){for(var n=0;n<t.length;n++)if(t[n].trim()==e)return!0;return!1},in_array_substring:function(e,t){for(var n=0;n<t.length;n++)if(-1!=e.indexOf(t[n].trim()))return!0;return!1}};SlimStat.add_event(window,"load",function(){if("undefined"==typeof SlimStatParams.disable_outbound_tracking){all_links=document.getElementsByTagName("a");for(var e="undefined"!=typeof SlimStatParams.extensions_to_track&&SlimStatParams.extensions_to_track.length>0?SlimStatParams.extensions_to_track.split(","):[],t="undefined"!=typeof SlimStatParams.outbound_classes_rel_href_to_ignore&&SlimStatParams.outbound_classes_rel_href_to_ignore.length>0?SlimStatParams.outbound_classes_rel_href_to_ignore.split(","):[],n="undefined"!=typeof SlimStatParams.outbound_classes_rel_href_to_not_track&&SlimStatParams.outbound_classes_rel_href_to_not_track.length>0?SlimStatParams.outbound_classes_rel_href_to_not_track.split(","):[],a=0;a<all_links.length;a++)!function(){var i=all_links[a];if(i.slimstat_actual_click=!1,i.slimstat_type=!i.href||i.hostname!=location.hostname&&-1!=i.href.indexOf("://")?0:2,i.slimstat_track_me=!0,i.slimstat_callback=!0,e.length>0&&i.pathname.indexOf(".")>0&&i.hostname==location.hostname&&(extension_current_link=i.pathname.split(".").pop().replace(/[\/\-]/g,""),i.slimstat_track_me=SlimStat.in_array(extension_current_link,e),i.slimstat_type=1),!i.slimstat_track_me||2!=i.slimstat_type||"undefined"!=typeof SlimStatParams.track_internal_links&&"false"!=SlimStatParams.track_internal_links||(i.slimstat_track_me=!1),i.slimstat_track_me&&(t.length>0||n.length>0)){classes_current_link="undefined"!=typeof i.className&&i.className.length>0?i.className.split(" "):[];for(var r=0;r<classes_current_link.length;r++)if(SlimStat.in_array_substring(classes_current_link[r],t)&&(i.slimstat_callback=!1),SlimStat.in_array_substring(classes_current_link[r],n)){i.slimstat_track_me=!1;break}}i.slimstat_track_me&&"undefined"!=typeof i.attributes.rel&&i.attributes.rel.value.length>0&&(SlimStat.in_array_substring(i.attributes.rel.value,t)&&(i.slimstat_callback=!1),SlimStat.in_array_substring(i.attributes.rel.value,n)&&(i.slimstat_track_me=!1)),i.slimstat_track_me&&"undefined"!=typeof i.href&&i.href.length>0&&(SlimStat.in_array_substring(i.href,t)&&(i.slimstat_callback=!1),SlimStat.in_array_substring(i.href,n)&&(i.slimstat_track_me=!1)),i.slimstat_track_me&&i.target&&!i.target.match(/^_(self|parent|top)$/i)&&(i.slimstat_callback=!1),SlimStat.add_event(i,"click",function(e){this.slimstat_track_me&&(this.slimstat_actual_click||(this.slimstat_callback?("function"==typeof e.preventDefault&&e.preventDefault(),this.slimstat_actual_click=!this.slimstat_actual_click,SlimStat.ss_track(e,this.slimstat_type,"",function(){SlimStat.event_fire(i,"click")})):SlimStat.ss_track(e,this.slimstat_type,"",function(){})))})}()}});var current_data="";"undefined"!=typeof SlimStatParams.id&&parseInt(SlimStatParams.id)>0?current_data="id="+SlimStatParams.id:"undefined"!=typeof SlimStatParams.ci&&(current_data="ci="+SlimStatParams.ci+"&ref="+SlimStat._base64_encode(document.referrer)+"&res="+SlimStat._base64_encode(window.location.href)),current_data.length&&SlimStat.add_event(window,"load",function(){setTimeout(function(){SlimStat.send_to_server(current_data+"&sw="+(screen.width||window.innerWidth||document.documentElement.clientWidth||document.body.offsetWidth)+"&sh="+(screen.height||window.innerHeight||document.documentElement.clientHeight||document.body.offsetHeight)+"&cd="+screen.colorDepth+"&aa="+SlimStat.has_smoothing()+"&sl="+SlimStat.get_server_latency()+"&pp="+SlimStat.get_page_performance()+"&pl="+SlimStat.detect_plugins())},0)});
wp-slimstat.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: WP Slimstat
4
  Plugin URI: http://wordpress.org/plugins/wp-slimstat/
5
  Description: The leading web analytics plugin for WordPress
6
- Version: 3.9.6
7
  Author: Camu
8
  Author URI: http://slimstat.getused.to.it/
9
  */
@@ -11,7 +11,7 @@ Author URI: http://slimstat.getused.to.it/
11
  if (!empty(wp_slimstat::$options)) return true;
12
 
13
  class wp_slimstat{
14
- public static $version = '3.9.6';
15
  public static $options = array();
16
 
17
  public static $wpdb = '';
@@ -49,6 +49,9 @@ class wp_slimstat{
49
  // Hook a DB clean-up routine to the daily cronjob
50
  add_action('wp_slimstat_purge', array(__CLASS__, 'wp_slimstat_purge'));
51
 
 
 
 
52
  // Enable the tracker (both server- and client-side)
53
  if (!is_admin() || self::$options['track_admin_pages'] == 'yes'){
54
  // Allow add-ons to turn off the tracker based on other conditions
@@ -66,7 +69,9 @@ class wp_slimstat{
66
  // Slimstat tracks screen resolutions, outbound links and other client-side information using javascript
67
  if ((self::$options['enable_javascript'] == 'yes' || self::$options['javascript_mode'] == 'yes') && self::$options['is_tracking'] == 'yes' && $is_tracking_filter_js){
68
  add_action($action_to_hook, array(__CLASS__, 'wp_slimstat_enqueue_tracking_script'), 15);
69
- if (self::$options['track_users'] == 'yes') add_action('login_enqueue_scripts', array(__CLASS__, 'wp_slimstat_enqueue_tracking_script'), 10);
 
 
70
  }
71
 
72
  if (self::$options['enable_ads_network'] == 'yes'){
@@ -86,6 +91,8 @@ class wp_slimstat{
86
  $data_string = base64_decode($_REQUEST['data']);
87
  if ($data_string === false){
88
  do_action('slimstat_track_exit_101');
 
 
89
  exit('-101.0');
90
  }
91
 
@@ -95,21 +102,27 @@ class wp_slimstat{
95
 
96
  if (empty(self::$data_js['ci']) && empty(self::$data_js['id'])){
97
  do_action('slimstat_track_exit_102');
 
 
98
  exit('-102.0');
99
  }
100
 
101
  if (!empty(self::$data_js['ci'])){
102
  list(self::$data_js['ci'], $nonce) = explode('.', self::$data_js['ci']);
103
- if ($nonce != md5(self::$data_js['ci'].self::$options['secret'])){
104
  do_action('slimstat_track_exit_103');
 
 
105
  exit('-103.0');
106
  }
107
  }
108
  else{
109
  self::$stat = array();
110
  list(self::$data_js['id'], $nonce) = explode('.', self::$data_js['id']);
111
- if ($nonce != md5(self::$data_js['id'].self::$options['secret'])){
112
  do_action('slimstat_track_exit_104');
 
 
113
  exit('-104.0');
114
  }
115
  self::$stat['id'] = self::$data_js['id'];
@@ -176,6 +189,7 @@ class wp_slimstat{
176
  default:
177
  do_action('slimstat_track_exit_'.$abs_error_code, self::$stat);
178
  }
 
179
  exit(self::$stat['id'].'.0');
180
  }
181
 
@@ -197,6 +211,7 @@ class wp_slimstat{
197
  // Third-party tools can decide that this pageview should not be tracked, by setting its datestamp to zero
198
  if (empty(self::$stat) || empty(self::$stat['dt'])){
199
  self::$stat['id'] = -213;
 
200
  return $_argument;
201
  }
202
 
@@ -213,6 +228,7 @@ class wp_slimstat{
213
  // This must be a 'seriously malformed' URL
214
  if (!$referer){
215
  self::$stat['id'] = -208;
 
216
  return $_argument;
217
  }
218
 
@@ -231,19 +247,34 @@ class wp_slimstat{
231
  $pattern = str_replace( array('\*', '\!') , array('(.*)', '.'), preg_quote($a_filter, '/'));
232
  if (preg_match("@^$pattern$@i", self::$stat['referer'])){
233
  self::$stat['id'] = -207;
 
234
  return $_argument;
235
  }
236
  }
237
  }
238
 
 
 
 
 
 
 
239
  // We want to record both hits and searches (performed through the site search form)
240
- if (is_array(self::$data_js) && isset(self::$data_js['res'])){
 
 
 
 
 
 
 
241
  $parsed_permalink = parse_url(base64_decode(self::$data_js['res']));
242
  self::$stat['searchterms'] = self::_get_search_terms($referer);
243
 
244
  // Was this an internal search?
245
- if (empty(self::$stat['searchterms']))
246
  self::$stat['searchterms'] = self::_get_search_terms($parsed_permalink);
 
247
 
248
  self::$stat['resource'] = !is_array($parsed_permalink)?self::$data_js['res']:$parsed_permalink['path'].(!empty($parsed_permalink['query'])?'?'.urldecode($parsed_permalink['query']):'');
249
  }
@@ -255,6 +286,8 @@ class wp_slimstat{
255
  self::$stat['searchterms'] = str_replace('\\', '', $_REQUEST['s']);
256
  self::$stat['resource'] = ''; // Mark the resource to remember that this is a 'local search'
257
  }
 
 
258
  if (strpos(self::$stat['resource'], 'wp-admin/admin-ajax.php')!==false || (!empty($_GET['page']) && strpos($_GET['page'], 'wp-slim-')!==false)){
259
  return $_argument;
260
  }
@@ -265,6 +298,7 @@ class wp_slimstat{
265
  $pattern = str_replace( array('\*', '\!') , array('(.*)', '.'), preg_quote($a_filter, '/'));
266
  if (preg_match("@^$pattern$@i", self::$stat['resource'])){
267
  self::$stat['id'] = -209;
 
268
  return $_argument;
269
  }
270
  }
@@ -274,6 +308,7 @@ class wp_slimstat{
274
  list(self::$stat['ip'], self::$stat['other_ip']) = self::_get_ip2long_remote_ip();
275
  if (empty(self::$stat['ip'])){
276
  self::$stat['id'] = -203;
 
277
  return $_argument;
278
  }
279
 
@@ -282,6 +317,7 @@ class wp_slimstat{
282
  // Don't track logged-in users, if the corresponding option is enabled
283
  if (self::$options['track_users'] == 'no'){
284
  self::$stat['id'] = -214;
 
285
  return $_argument;
286
  }
287
 
@@ -289,12 +325,14 @@ class wp_slimstat{
289
  foreach(self::string_to_array(self::$options['ignore_capabilities']) as $a_capability){
290
  if (array_key_exists(strtolower($a_capability), $GLOBALS['current_user']->allcaps)){
291
  self::$stat['id'] = -200;
 
292
  return $_argument;
293
  }
294
  }
295
 
296
  if (is_string(self::$options['ignore_users']) && strpos(self::$options['ignore_users'], $GLOBALS['current_user']->data->user_login) !== false){
297
  self::$stat['id'] = -201;
 
298
  return $_argument;
299
  }
300
 
@@ -308,6 +346,7 @@ class wp_slimstat{
308
  if (isset($spam_comment['comment_count']) && $spam_comment['comment_count'] > 0){
309
  if (self::$options['ignore_spammers'] == 'yes'){
310
  self::$stat['id'] = -202;
 
311
  return $_argument;
312
  }
313
  else{
@@ -326,7 +365,9 @@ class wp_slimstat{
326
 
327
  if (strpos($ip_to_ignore, '/') !== false){
328
  list($ip_to_ignore, $mask) = @explode('/', trim($ip_to_ignore));
329
- if (empty($mask) || !is_numeric($mask)) $mask = 32;
 
 
330
  }
331
 
332
  $long_ip_to_ignore = ip2long($ip_to_ignore);
@@ -336,6 +377,7 @@ class wp_slimstat{
336
  $long_masked_ip_to_ignore = $long_ip_to_ignore & $long_mask;
337
  if ($long_masked_user_ip == $long_masked_ip_to_ignore || $long_masked_other_ip == $long_masked_ip_to_ignore){
338
  self::$stat['id'] = -204;
 
339
  return $_argument;
340
  }
341
  }
@@ -353,6 +395,7 @@ class wp_slimstat{
353
  // Is this country blacklisted?
354
  if (is_string(self::$options['ignore_countries']) && stripos(self::$options['ignore_countries'], self::$stat['country']) !== false){
355
  self::$stat['id'] = -206;
 
356
  return $_argument;
357
  }
358
 
@@ -361,6 +404,7 @@ class wp_slimstat{
361
  (isset($_SERVER["HTTP_X_PURPOSE"]) && (strtolower($_SERVER['HTTP_X_PURPOSE']) == 'preview'))){
362
  if (self::$options['ignore_prefetch'] == 'yes'){
363
  self::$stat['id'] = -210;
 
364
  return $_argument;
365
  }
366
  else{
@@ -368,16 +412,13 @@ class wp_slimstat{
368
  }
369
  }
370
 
371
- // Information about this resource
372
- $content_info = (is_array(self::$data_js) && isset(self::$data_js['ci']))?unserialize(base64_decode(self::$data_js['ci'])):self::_get_content_info();
373
- if (!is_array($content_info)) $content_info = array('content_type' => 'unknown');
374
-
375
  // Detect user agent
376
  self::$browser = self::_get_browser();
377
 
378
  // Are we ignoring bots?
379
  if ((self::$options['javascript_mode'] == 'yes' || self::$options['ignore_bots'] == 'yes') && self::$browser['type']%2 != 0){
380
  self::$stat['id'] = -211;
 
381
  return $_argument;
382
  }
383
 
@@ -386,6 +427,7 @@ class wp_slimstat{
386
  $pattern = str_replace( array('\*', '\!') , array('(.*)', '.'), preg_quote($a_filter, '/'));
387
  if (preg_match("~^$pattern$~i", self::$browser['browser'].'/'.self::$browser['version']) || preg_match("~^$pattern$~i", self::$browser['browser']) || preg_match("~^$pattern$~i", self::$browser['user_agent'])){
388
  self::$stat['id'] = -212;
 
389
  return $_argument;
390
  }
391
  }
@@ -402,6 +444,7 @@ class wp_slimstat{
402
  // Third-party tools can decide that this pageview should not be tracked, by setting its datestamp to zero
403
  if (empty(self::$stat) || empty(self::$stat['dt'])){
404
  self::$stat['id'] = -213;
 
405
  return $_argument;
406
  }
407
 
@@ -421,6 +464,7 @@ class wp_slimstat{
421
  // Something went wrong during the insert
422
  if (empty(self::$stat['id'])){
423
  self::$stat['id'] = -215;
 
424
 
425
  // Attempt to init the environment (new blog in a MU network?)
426
  include_once(WP_PLUGIN_DIR.'/wp-slimstat/admin/wp-slimstat-admin.php');
@@ -993,7 +1037,7 @@ class wp_slimstat{
993
  list($identifier, $control_code) = explode('.', $_COOKIE['slimstat_tracking_code']);
994
 
995
  // Make sure only authorized information is recorded
996
- if ($control_code != md5($identifier.self::$options['secret'])) return false;
997
 
998
  $is_new_session = (strpos($identifier, 'id') !== false);
999
  $identifier = intval($identifier);
@@ -1042,8 +1086,14 @@ class wp_slimstat{
1042
  if (empty($data)){
1043
  return -1;
1044
  }
1045
-
1046
- $select_sql = "SELECT $_id_column FROM $_table WHERE `".self::$wpdb->prepare(implode('` = %s AND `', array_keys($data)).'` = %s', $data);
 
 
 
 
 
 
1047
 
1048
  // Let's see if this row is already in our lookup table
1049
  $id = self::$wpdb->get_var($select_sql);
@@ -1074,14 +1124,33 @@ class wp_slimstat{
1074
  return -1;
1075
  }
1076
 
 
 
 
 
 
 
1077
  self::$wpdb->query(self::$wpdb->prepare("
1078
- INSERT IGNORE INTO $_table (`".implode("`, `", array_keys($_data)).'`)
1079
  VALUES ('.substr(str_repeat('%s,', count($_data)), 0, -1).")", $_data));
1080
 
1081
  return intval(self::$wpdb->insert_id);
1082
  }
1083
  // end insert_row
1084
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1085
  /**
1086
  * Converts a series of comma separated values into an array
1087
  */
@@ -1106,7 +1175,7 @@ class wp_slimstat{
1106
  'version' => self::$version,
1107
  'secret' => wp_hash(uniqid(time(), true)),
1108
  'show_admin_notice' => 0,
1109
-
1110
  // General
1111
  'is_tracking' => $val_yes,
1112
  'track_admin_pages' => $val_no,
@@ -1165,11 +1234,15 @@ class wp_slimstat{
1165
  'extend_session' => $val_no,
1166
  'enable_cdn' => $val_yes,
1167
  'extensions_to_track' => 'pdf,doc,xls,zip',
 
1168
  'show_sql_debug' => $val_no,
1169
  'ip_lookup_service' => 'http://www.infosniper.net/?ip_address=',
1170
  'custom_css' => '',
1171
  'enable_ads_network' => 'null',
1172
 
 
 
 
1173
  // Network-wide Settings
1174
  'locked_options' => ''
1175
  );
@@ -1182,14 +1255,17 @@ class wp_slimstat{
1182
  * Saves the options in the database, if necessary
1183
  */
1184
  public static function slimstat_save_options(){
1185
- if (self::$options_signature == md5(serialize(self::$options))) return true;
 
 
 
1186
  if (!is_network_admin()){
1187
  update_option('slimstat_options', wp_slimstat::$options);
1188
  }
1189
  else {
1190
  update_site_option('slimstat_options', wp_slimstat::$options);
1191
  }
1192
-
1193
  return 0;
1194
  }
1195
 
3
  Plugin Name: WP Slimstat
4
  Plugin URI: http://wordpress.org/plugins/wp-slimstat/
5
  Description: The leading web analytics plugin for WordPress
6
+ Version: 3.9.7
7
  Author: Camu
8
  Author URI: http://slimstat.getused.to.it/
9
  */
11
  if (!empty(wp_slimstat::$options)) return true;
12
 
13
  class wp_slimstat{
14
+ public static $version = '3.9.7';
15
  public static $options = array();
16
 
17
  public static $wpdb = '';
49
  // Hook a DB clean-up routine to the daily cronjob
50
  add_action('wp_slimstat_purge', array(__CLASS__, 'wp_slimstat_purge'));
51
 
52
+ // Allow external domains on CORS requests
53
+ add_filter( 'allowed_http_origins', array(__CLASS__, 'open_cors_admin_ajax' ) );
54
+
55
  // Enable the tracker (both server- and client-side)
56
  if (!is_admin() || self::$options['track_admin_pages'] == 'yes'){
57
  // Allow add-ons to turn off the tracker based on other conditions
69
  // Slimstat tracks screen resolutions, outbound links and other client-side information using javascript
70
  if ((self::$options['enable_javascript'] == 'yes' || self::$options['javascript_mode'] == 'yes') && self::$options['is_tracking'] == 'yes' && $is_tracking_filter_js){
71
  add_action($action_to_hook, array(__CLASS__, 'wp_slimstat_enqueue_tracking_script'), 15);
72
+ if (self::$options['track_users'] == 'yes'){
73
+ add_action('login_enqueue_scripts', array(__CLASS__, 'wp_slimstat_enqueue_tracking_script'), 10);
74
+ }
75
  }
76
 
77
  if (self::$options['enable_ads_network'] == 'yes'){
91
  $data_string = base64_decode($_REQUEST['data']);
92
  if ($data_string === false){
93
  do_action('slimstat_track_exit_101');
94
+ self::$options['last_tracker_error'] = array(101, __('Invalid data format','wp-slimstat'), date_i18n('U'));
95
+ self::slimstat_save_options();
96
  exit('-101.0');
97
  }
98
 
102
 
103
  if (empty(self::$data_js['ci']) && empty(self::$data_js['id'])){
104
  do_action('slimstat_track_exit_102');
105
+ self::$options['last_tracker_error'] = array(102, __('Missing payload string','wp-slimstat'), date_i18n('U'));
106
+ self::slimstat_save_options();
107
  exit('-102.0');
108
  }
109
 
110
  if (!empty(self::$data_js['ci'])){
111
  list(self::$data_js['ci'], $nonce) = explode('.', self::$data_js['ci']);
112
+ if ($nonce !== md5(self::$data_js['ci'].self::$options['secret'])){
113
  do_action('slimstat_track_exit_103');
114
+ self::$options['last_tracker_error'] = array(103, __('Invalid data signature (ci)','wp-slimstat'), date_i18n('U'));
115
+ self::slimstat_save_options();
116
  exit('-103.0');
117
  }
118
  }
119
  else{
120
  self::$stat = array();
121
  list(self::$data_js['id'], $nonce) = explode('.', self::$data_js['id']);
122
+ if ($nonce !== md5(self::$data_js['id'].self::$options['secret'])){
123
  do_action('slimstat_track_exit_104');
124
+ self::$options['last_tracker_error'] = array(104, __('Invalid data signature (id)','wp-slimstat'), date_i18n('U'));
125
+ self::slimstat_save_options();
126
  exit('-104.0');
127
  }
128
  self::$stat['id'] = self::$data_js['id'];
189
  default:
190
  do_action('slimstat_track_exit_'.$abs_error_code, self::$stat);
191
  }
192
+ self::slimstat_save_options();
193
  exit(self::$stat['id'].'.0');
194
  }
195
 
211
  // Third-party tools can decide that this pageview should not be tracked, by setting its datestamp to zero
212
  if (empty(self::$stat) || empty(self::$stat['dt'])){
213
  self::$stat['id'] = -213;
214
+ self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('ID set to zero by third-party tool','wp-slimstat'), date_i18n('U'));
215
  return $_argument;
216
  }
217
 
228
  // This must be a 'seriously malformed' URL
229
  if (!$referer){
230
  self::$stat['id'] = -208;
231
+ self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('Malformed URL','wp-slimstat'), date_i18n('U'));
232
  return $_argument;
233
  }
234
 
247
  $pattern = str_replace( array('\*', '\!') , array('(.*)', '.'), preg_quote($a_filter, '/'));
248
  if (preg_match("@^$pattern$@i", self::$stat['referer'])){
249
  self::$stat['id'] = -207;
250
+ self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('Referrer is blacklisted','wp-slimstat'), date_i18n('U'));
251
  return $_argument;
252
  }
253
  }
254
  }
255
 
256
+ // Information about this resource
257
+ $content_info = (is_array(self::$data_js) && isset(self::$data_js['ci']))?unserialize(base64_decode(self::$data_js['ci'])):self::_get_content_info();
258
+ if (!is_array($content_info)){
259
+ $content_info = array('content_type' => 'unknown');
260
+ }
261
+
262
  // We want to record both hits and searches (performed through the site search form)
263
+
264
+ if ($content_info['content_type'] == 'external'){
265
+ self::$stat['resource'] = $_SERVER['HTTP_REFERER'];
266
+ self::$stat['domain'] = '';
267
+ self::$stat['referer'] = '';
268
+ }
269
+ elseif (is_array(self::$data_js) && isset(self::$data_js['res'])){
270
+
271
  $parsed_permalink = parse_url(base64_decode(self::$data_js['res']));
272
  self::$stat['searchterms'] = self::_get_search_terms($referer);
273
 
274
  // Was this an internal search?
275
+ if (empty(self::$stat['searchterms'])){
276
  self::$stat['searchterms'] = self::_get_search_terms($parsed_permalink);
277
+ }
278
 
279
  self::$stat['resource'] = !is_array($parsed_permalink)?self::$data_js['res']:$parsed_permalink['path'].(!empty($parsed_permalink['query'])?'?'.urldecode($parsed_permalink['query']):'');
280
  }
286
  self::$stat['searchterms'] = str_replace('\\', '', $_REQUEST['s']);
287
  self::$stat['resource'] = ''; // Mark the resource to remember that this is a 'local search'
288
  }
289
+
290
+ // Do not track report pages in the admin
291
  if (strpos(self::$stat['resource'], 'wp-admin/admin-ajax.php')!==false || (!empty($_GET['page']) && strpos($_GET['page'], 'wp-slim-')!==false)){
292
  return $_argument;
293
  }
298
  $pattern = str_replace( array('\*', '\!') , array('(.*)', '.'), preg_quote($a_filter, '/'));
299
  if (preg_match("@^$pattern$@i", self::$stat['resource'])){
300
  self::$stat['id'] = -209;
301
+ self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('Permalink is blacklisted','wp-slimstat'), date_i18n('U'));
302
  return $_argument;
303
  }
304
  }
308
  list(self::$stat['ip'], self::$stat['other_ip']) = self::_get_ip2long_remote_ip();
309
  if (empty(self::$stat['ip'])){
310
  self::$stat['id'] = -203;
311
+ self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('Empty IP Address','wp-slimstat'), date_i18n('U'));
312
  return $_argument;
313
  }
314
 
317
  // Don't track logged-in users, if the corresponding option is enabled
318
  if (self::$options['track_users'] == 'no'){
319
  self::$stat['id'] = -214;
320
+ self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('Logged in user not tracked','wp-slimstat'), date_i18n('U'));
321
  return $_argument;
322
  }
323
 
325
  foreach(self::string_to_array(self::$options['ignore_capabilities']) as $a_capability){
326
  if (array_key_exists(strtolower($a_capability), $GLOBALS['current_user']->allcaps)){
327
  self::$stat['id'] = -200;
328
+ self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('User with given capability not tracked','wp-slimstat'), date_i18n('U'));
329
  return $_argument;
330
  }
331
  }
332
 
333
  if (is_string(self::$options['ignore_users']) && strpos(self::$options['ignore_users'], $GLOBALS['current_user']->data->user_login) !== false){
334
  self::$stat['id'] = -201;
335
+ self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('User is blacklisted','wp-slimstat'), date_i18n('U'));
336
  return $_argument;
337
  }
338
 
346
  if (isset($spam_comment['comment_count']) && $spam_comment['comment_count'] > 0){
347
  if (self::$options['ignore_spammers'] == 'yes'){
348
  self::$stat['id'] = -202;
349
+ self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('Spammer not tracked','wp-slimstat'), date_i18n('U'));
350
  return $_argument;
351
  }
352
  else{
365
 
366
  if (strpos($ip_to_ignore, '/') !== false){
367
  list($ip_to_ignore, $mask) = @explode('/', trim($ip_to_ignore));
368
+ if (empty($mask) || !is_numeric($mask)){
369
+ $mask = 32;
370
+ }
371
  }
372
 
373
  $long_ip_to_ignore = ip2long($ip_to_ignore);
377
  $long_masked_ip_to_ignore = $long_ip_to_ignore & $long_mask;
378
  if ($long_masked_user_ip == $long_masked_ip_to_ignore || $long_masked_other_ip == $long_masked_ip_to_ignore){
379
  self::$stat['id'] = -204;
380
+ self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('IP Address is blacklisted','wp-slimstat'), date_i18n('U'));
381
  return $_argument;
382
  }
383
  }
395
  // Is this country blacklisted?
396
  if (is_string(self::$options['ignore_countries']) && stripos(self::$options['ignore_countries'], self::$stat['country']) !== false){
397
  self::$stat['id'] = -206;
398
+ self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('Country is blacklisted','wp-slimstat'), date_i18n('U'));
399
  return $_argument;
400
  }
401
 
404
  (isset($_SERVER["HTTP_X_PURPOSE"]) && (strtolower($_SERVER['HTTP_X_PURPOSE']) == 'preview'))){
405
  if (self::$options['ignore_prefetch'] == 'yes'){
406
  self::$stat['id'] = -210;
407
+ self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('Prefetch requests are ignored','wp-slimstat'), date_i18n('U'));
408
  return $_argument;
409
  }
410
  else{
412
  }
413
  }
414
 
 
 
 
 
415
  // Detect user agent
416
  self::$browser = self::_get_browser();
417
 
418
  // Are we ignoring bots?
419
  if ((self::$options['javascript_mode'] == 'yes' || self::$options['ignore_bots'] == 'yes') && self::$browser['type']%2 != 0){
420
  self::$stat['id'] = -211;
421
+ self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('Bot not tracked','wp-slimstat'), date_i18n('U'));
422
  return $_argument;
423
  }
424
 
427
  $pattern = str_replace( array('\*', '\!') , array('(.*)', '.'), preg_quote($a_filter, '/'));
428
  if (preg_match("~^$pattern$~i", self::$browser['browser'].'/'.self::$browser['version']) || preg_match("~^$pattern$~i", self::$browser['browser']) || preg_match("~^$pattern$~i", self::$browser['user_agent'])){
429
  self::$stat['id'] = -212;
430
+ self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('Browser is blacklisted','wp-slimstat'), date_i18n('U'));
431
  return $_argument;
432
  }
433
  }
444
  // Third-party tools can decide that this pageview should not be tracked, by setting its datestamp to zero
445
  if (empty(self::$stat) || empty(self::$stat['dt'])){
446
  self::$stat['id'] = -213;
447
+ self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('ID set to zero by third-party tool','wp-slimstat'), date_i18n('U'));
448
  return $_argument;
449
  }
450
 
464
  // Something went wrong during the insert
465
  if (empty(self::$stat['id'])){
466
  self::$stat['id'] = -215;
467
+ self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('Database not ready','wp-slimstat'), date_i18n('U'));
468
 
469
  // Attempt to init the environment (new blog in a MU network?)
470
  include_once(WP_PLUGIN_DIR.'/wp-slimstat/admin/wp-slimstat-admin.php');
1037
  list($identifier, $control_code) = explode('.', $_COOKIE['slimstat_tracking_code']);
1038
 
1039
  // Make sure only authorized information is recorded
1040
+ if ($control_code !== md5($identifier.self::$options['secret'])) return false;
1041
 
1042
  $is_new_session = (strpos($identifier, 'id') !== false);
1043
  $identifier = intval($identifier);
1086
  if (empty($data)){
1087
  return -1;
1088
  }
1089
+
1090
+ // Remove unwanted characters (SQL injections, anyone?)
1091
+ $data_keys = array();
1092
+ foreach (array_keys($data) as $a_key){
1093
+ $data_keys[] = sanitize_key($a_key);
1094
+ }
1095
+
1096
+ $select_sql = "SELECT $_id_column FROM $_table WHERE ".self::$wpdb->prepare(implode(' = %s AND ', $data_keys).' = %s', $data);
1097
 
1098
  // Let's see if this row is already in our lookup table
1099
  $id = self::$wpdb->get_var($select_sql);
1124
  return -1;
1125
  }
1126
 
1127
+ // Remove unwanted characters (SQL injections, anyone?)
1128
+ $data_keys = array();
1129
+ foreach (array_keys($_data) as $a_key){
1130
+ $data_keys[] = sanitize_key($a_key);
1131
+ }
1132
+
1133
  self::$wpdb->query(self::$wpdb->prepare("
1134
+ INSERT IGNORE INTO $_table (".implode(", ", $data_keys).')
1135
  VALUES ('.substr(str_repeat('%s,', count($_data)), 0, -1).")", $_data));
1136
 
1137
  return intval(self::$wpdb->insert_id);
1138
  }
1139
  // end insert_row
1140
 
1141
+ /**
1142
+ * Opens given domains during CORS requests to admin-ajax.php
1143
+ */
1144
+ public static function open_cors_admin_ajax( $_allowed_origins ){
1145
+ $exploded_domains = self::string_to_array( self::$options['external_domains'] );
1146
+
1147
+ if (!empty($exploded_domains) && !empty($exploded_domains[0])){
1148
+ $_allowed_origins = array_merge($_allowed_origins, $exploded_domains);
1149
+ }
1150
+
1151
+ return $_allowed_origins;
1152
+ }
1153
+
1154
  /**
1155
  * Converts a series of comma separated values into an array
1156
  */
1175
  'version' => self::$version,
1176
  'secret' => wp_hash(uniqid(time(), true)),
1177
  'show_admin_notice' => 0,
1178
+
1179
  // General
1180
  'is_tracking' => $val_yes,
1181
  'track_admin_pages' => $val_no,
1234
  'extend_session' => $val_no,
1235
  'enable_cdn' => $val_yes,
1236
  'extensions_to_track' => 'pdf,doc,xls,zip',
1237
+ 'external_domains' => '',
1238
  'show_sql_debug' => $val_no,
1239
  'ip_lookup_service' => 'http://www.infosniper.net/?ip_address=',
1240
  'custom_css' => '',
1241
  'enable_ads_network' => 'null',
1242
 
1243
+ // Maintenance
1244
+ 'last_tracker_error' => array(0, '', date_i18n('U')),
1245
+
1246
  // Network-wide Settings
1247
  'locked_options' => ''
1248
  );
1255
  * Saves the options in the database, if necessary
1256
  */
1257
  public static function slimstat_save_options(){
1258
+ if (self::$options_signature === md5(serialize(self::$options))){
1259
+ return true;
1260
+ }
1261
+
1262
  if (!is_network_admin()){
1263
  update_option('slimstat_options', wp_slimstat::$options);
1264
  }
1265
  else {
1266
  update_site_option('slimstat_options', wp_slimstat::$options);
1267
  }
1268
+
1269
  return 0;
1270
  }
1271