Slimstat Analytics - Version 4.1.3

Version Description

  • [Note] We've updated the following add-ons to be compatible with Slimstat 4.x: Custom DB, Heatmap, Track Cookies. Go get your copy today.
  • [Update] Say hello to IPv6 internet addresses. Slimstat is now compatible with this technology, and will not throw an error when users visit the site using an IPv6 address. Please note: the column type in the database has changed from INT UNSIGNED to VARCHAR(39). Update your custom code accordingly.
  • [Update] Category names are now displayed instead of their URLs, when the corresponding option is enabled (thank you, Keith Gengler).
  • [Update] Now the database API can be given a table alias for when JOINS are necessary, to avoid MySQL errors or ambiguous column names.
  • [Fix] Map overlay was being displayed not in full width, because of some class name changes we implemented in Slimstat 4.
  • [Fix] Tracking of internal link coordinates (heatmap) was not accurate if the link tag had markup inside it (thank you, dragon013).
Download this release

Release Info

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

Code changes from version 4.1.2 to 4.1.3

admin/config/index.php CHANGED
@@ -49,10 +49,10 @@ switch ($config_tabs[$current_tab-1]){
49
  $options_on_this_page = array(
50
  'reports_basic_header' => array('description' => __('Formats and Conversions','wp-slimstat'), 'type' => 'section_header'),
51
  'use_european_separators' => array('description' => __('Number Format','wp-slimstat'), 'type' => 'yesno', 'long_description' => __('Choose the number format you want to use for your reports.','wp-slimstat'), 'custom_label_yes' => '1.234,56', 'custom_label_no' => '1,234.56'),
52
- 'date_format' => array('description' => __('Date Format','wp-slimstat'), 'type' => 'text', 'long_description' => __("<a href='http://php.net/manual/en/function.date.php' target='_blank'>PHP Format</a> to use when displaying a pageview's date.",'wp-slimstat')),
53
- 'time_format' => array('description' => __('Time Format','wp-slimstat'), 'type' => 'text', 'long_description' => __("<a href='http://php.net/manual/en/function.date.php' target='_blank'>PHP Format</a> to use when displaying a pageview's time.",'wp-slimstat')),
54
  'show_display_name' => array('description' => __('Use Display Name','wp-slimstat'), 'type' => 'yesno', 'long_description' => __('By default, users are listed by their usernames. Use this option to visualize their display names instead.','wp-slimstat')),
55
- 'convert_resource_urls_to_titles' => array('description' => __('Use Post Titles','wp-slimstat'), 'type' => 'yesno', 'long_description' => __('Slimstat converts your permalinks into post and page titles. Disable this feature if you need to see the URL in your reports.','wp-slimstat')),
56
  'convert_ip_addresses' => array('description' => __('Convert IP Addresses','wp-slimstat'), 'type' => 'yesno', 'long_description' => __('Display provider names instead of IP addresses.','wp-slimstat')),
57
 
58
  'reports_functionality_header' => array('description' => __('Functionality','wp-slimstat'), 'type' => 'section_header'),
49
  $options_on_this_page = array(
50
  'reports_basic_header' => array('description' => __('Formats and Conversions','wp-slimstat'), 'type' => 'section_header'),
51
  'use_european_separators' => array('description' => __('Number Format','wp-slimstat'), 'type' => 'yesno', 'long_description' => __('Choose the number format you want to use for your reports.','wp-slimstat'), 'custom_label_yes' => '1.234,56', 'custom_label_no' => '1,234.56'),
52
+ 'date_format' => array('description' => __('Date Format','wp-slimstat'), 'type' => 'text', 'long_description' => __("<a href='http://php.net/manual/en/function.date.php' target='_blank'>PHP Format</a> to use when displaying a pageview's date.", 'wp-slimstat')),
53
+ 'time_format' => array('description' => __('Time Format','wp-slimstat'), 'type' => 'text', 'long_description' => __("<a href='http://php.net/manual/en/function.date.php' target='_blank'>PHP Format</a> to use when displaying a pageview's time.", 'wp-slimstat')),
54
  'show_display_name' => array('description' => __('Use Display Name','wp-slimstat'), 'type' => 'yesno', 'long_description' => __('By default, users are listed by their usernames. Use this option to visualize their display names instead.','wp-slimstat')),
55
+ 'convert_resource_urls_to_titles' => array('description' => __('Use Titles','wp-slimstat'), 'type' => 'yesno', 'long_description' => __('Slimstat converts your permalinks into post, page and category titles. Disable this feature if you need to see the URL in your reports.', 'wp-slimstat')),
56
  'convert_ip_addresses' => array('description' => __('Convert IP Addresses','wp-slimstat'), 'type' => 'yesno', 'long_description' => __('Display provider names instead of IP addresses.','wp-slimstat')),
57
 
58
  'reports_functionality_header' => array('description' => __('Functionality','wp-slimstat'), 'type' => 'section_header'),
admin/view/right-now.php CHANGED
@@ -37,8 +37,6 @@ else {
37
 
38
  // Loop through the results
39
  for($i=0; $i<$count_page_results; $i++){
40
-
41
- $results[$i]['ip'] = long2ip($results[$i]['ip']);
42
  $host_by_ip = $results[$i]['ip'];
43
  if (wp_slimstat::$options['convert_ip_addresses'] == 'yes'){
44
  $gethostbyaddr = gethostbyaddr( $results[$i]['ip'] );
@@ -106,7 +104,6 @@ else {
106
  // Originating IP Address
107
  $other_ip_address = '';
108
  if (!empty($results[$i]['other_ip'])){
109
- $results[$i]['other_ip'] = long2ip($results[$i]['other_ip']);
110
  $other_ip_address = "<a class='slimstat-filter-link' href='".wp_slimstat_reports::fs_url('other_ip equals '.$results[$i]['other_ip'])."'>(".__('Originating IP','wp-slimstat').": {$results[$i]['other_ip']})</a>";
111
  }
112
 
@@ -137,7 +134,7 @@ else {
137
  if (!empty($results[$i]['blog_id'])){
138
  $base_url = $parse_url['scheme'].'://'.$base_host;
139
  }
140
- $results[$i]['resource'] = "<a class='slimstat-font-logout' target='_blank' title='".htmlentities(__('Open this URL in a new window','wp-slimstat'), ENT_QUOTES, 'UTF-8')."' href='".$base_url.htmlentities($results[$i]['resource'], ENT_QUOTES, 'UTF-8')."'></a> $base_url<a class='slimstat-filter-link' href='".wp_slimstat_reports::fs_url('resource equals '.$results[$i]['resource'])."'>".wp_slimstat_reports::get_resource_title($results[$i]['resource']).'</a>';
141
  }
142
  else{
143
  $results[$i]['resource'] = __('Local search results page','wp-slimstat');
37
 
38
  // Loop through the results
39
  for($i=0; $i<$count_page_results; $i++){
 
 
40
  $host_by_ip = $results[$i]['ip'];
41
  if (wp_slimstat::$options['convert_ip_addresses'] == 'yes'){
42
  $gethostbyaddr = gethostbyaddr( $results[$i]['ip'] );
104
  // Originating IP Address
105
  $other_ip_address = '';
106
  if (!empty($results[$i]['other_ip'])){
 
107
  $other_ip_address = "<a class='slimstat-filter-link' href='".wp_slimstat_reports::fs_url('other_ip equals '.$results[$i]['other_ip'])."'>(".__('Originating IP','wp-slimstat').": {$results[$i]['other_ip']})</a>";
108
  }
109
 
134
  if (!empty($results[$i]['blog_id'])){
135
  $base_url = $parse_url['scheme'].'://'.$base_host;
136
  }
137
+ $results[$i]['resource'] = "<a class='slimstat-font-logout' target='_blank' title='".htmlentities(__('Open this URL in a new window','wp-slimstat'), ENT_QUOTES, 'UTF-8')."' href='".$base_url.htmlentities($results[$i]['resource'], ENT_QUOTES, 'UTF-8')."'></a> $base_url<a class='slimstat-filter-link' href='".wp_slimstat_reports::fs_url('resource equals '.$results[$i]['resource'])."'>".wp_slimstat_reports::get_resource_title( $results[$i][ 'resource' ], $results[$i][ 'category' ] ).'</a>';
138
  }
139
  else{
140
  $results[$i]['resource'] = __('Local search results page','wp-slimstat');
admin/view/wp-slimstat-db.php CHANGED
@@ -35,7 +35,7 @@ class wp_slimstat_db {
35
  'no_filter_selected_1' => array( '&nbsp;', 'none' ),
36
  'browser' => array( __( 'Browser', 'wp-slimstat' ), 'varchar' ),
37
  'country' => array( __( 'Country Code', 'wp-slimstat' ), 'varchar' ),
38
- 'ip' => array( __( 'IP Address', 'wp-slimstat' ), 'int' ),
39
  'searchterms' => array( __( 'Search Terms', 'wp-slimstat' ), 'varchar' ),
40
  'language' => array( __( 'Language Code', 'wp-slimstat' ), 'varchar' ),
41
  'platform' => array( __( 'Operating System', 'wp-slimstat' ), 'varchar' ),
@@ -54,7 +54,7 @@ class wp_slimstat_db {
54
  'server_latency' => array( __( 'Server Latency', 'wp-slimstat' ), 'int' ),
55
  'author' => array( __( 'Post Author', 'wp-slimstat' ), 'varchar' ),
56
  'category' => array( __( 'Post Category ID', 'wp-slimstat' ), 'varchar' ),
57
- 'other_ip' => array( __( 'Originating IP', 'wp-slimstat' ), 'int' ),
58
  'content_type' => array( __( 'Resource Content Type', 'wp-slimstat' ), 'varchar' ),
59
  'content_id' => array( __( 'Resource ID', 'wp-slimstat' ), 'int' ),
60
  'screen_width' => array( __( 'Screen Width', 'wp-slimstat' ), 'int' ),
@@ -95,16 +95,13 @@ class wp_slimstat_db {
95
 
96
  // Hook for the array of normalized filters
97
  self::$filters_normalized = apply_filters( 'slimstat_db_filters_normalized', self::$filters_normalized, $_filters );
98
-
99
- self::$sql_where[ 'columns' ] = self::_get_sql_where( self::$filters_normalized[ 'columns' ] );
100
- self::$sql_where[ 'time_range' ] = '(dt BETWEEN '.self::$filters_normalized[ 'utime' ][ 'start' ].' AND '.self::$filters_normalized[ 'utime' ][ 'end' ].')';
101
  }
102
  // end init
103
 
104
  /**
105
  * Builds the array of WHERE clauses to be used later in our SQL queries
106
  */
107
- protected static function _get_sql_where( $_filters_normalized = array() ) {
108
  $sql_array = array();
109
 
110
  foreach ( $_filters_normalized as $a_filter_column => $a_filter_data ) {
@@ -113,7 +110,7 @@ class wp_slimstat_db {
113
  continue;
114
  }
115
 
116
- $sql_array[] = self::_get_single_where_clause( $a_filter_column, $a_filter_data[ 0 ], $a_filter_data[ 1 ] );
117
  }
118
 
119
  // Flatten array
@@ -124,29 +121,33 @@ class wp_slimstat_db {
124
  return '';
125
  }
126
 
127
- public static function get_combined_where( $_where = '', $_column = '*', $_use_time_range = true ) {
 
 
 
 
128
 
129
  if ( empty( $_where ) ) {
130
- if ( !empty( self::$sql_where[ 'columns' ] ) ) {
131
- $_where = self::$sql_where[ 'columns' ];
132
-
133
  if ($_use_time_range) {
134
- $_where .= ' AND '.self::$sql_where[ 'time_range' ];
135
  }
136
  }
137
  elseif ( $_use_time_range ) {
138
- $_where = self::$sql_where[ 'time_range' ];
139
  }
140
  else {
141
  $_where = '1=1';
142
  }
143
  }
144
  else {
145
- if ( $_where != '1=1' && !empty( self::$sql_where[ 'columns' ] ) ) {
146
- $_where .= ' AND '.self::$sql_where[ 'columns' ];
147
  }
148
  if ( $_use_time_range ) {
149
- $_where .= ' AND '.self::$sql_where[ 'time_range' ];
150
  }
151
  }
152
 
@@ -165,14 +166,18 @@ class wp_slimstat_db {
165
  /**
166
  * Translates user-friendly operators into SQL conditions
167
  */
168
- protected static function _get_single_where_clause( $_column = 'id', $_operator = 'equals', $_value = '' ) {
169
  $filter_empty = ( self::$columns_names[ $_column ] [ 1 ] == 'varchar' ) ? 'IS NULL' : '= 0';
170
  $filter_not_empty = ( self::$columns_names[ $_column ] [ 1 ] == 'varchar' ) ? 'IS NOT NULL' : '<> 0';
171
 
 
 
 
 
 
172
  switch( $_column ) {
173
  case 'ip':
174
  case 'other_ip':
175
- $_column = "INET_NTOA( $_column )";
176
  $filter_empty = '= "0.0.0.0"';
177
  break;
178
  default:
@@ -182,64 +187,64 @@ class wp_slimstat_db {
182
  $where = array( '', $_value );
183
  switch ( $_operator ) {
184
  case 'is_not_equal_to':
185
- $where[0] = "$_column <> %s";
186
  break;
187
 
188
  case 'contains':
189
- $where = array( "$_column LIKE %s", '%'.$_value.'%' );
190
  break;
191
 
192
  case 'includes_in_set':
193
- $where[0] = "FIND_IN_SET(%s, $_column) > 0";
194
  break;
195
 
196
  case 'does_not_contain':
197
- $where = array( "$_column NOT LIKE %s", '%'.$_value.'%' );
198
  break;
199
 
200
  case 'starts_with':
201
- $where = array( "$_column LIKE %s", $_value.'%' );
202
  break;
203
 
204
  case 'ends_with':
205
- $where = array( "$_column LIKE %s", '%'.$_value );
206
  break;
207
 
208
  case 'sounds_like':
209
- $where[0] = "SOUNDEX($_column) = SOUNDEX(%s)";
210
  break;
211
 
212
  case 'is_empty':
213
- $where = array( "$_column $filter_empty", array() );
214
  break;
215
 
216
  case 'is_not_empty':
217
- $where = array( "$_column $filter_not_empty", array() );
218
  break;
219
 
220
  case 'is_greater_than':
221
- $where[0] = "$_column > %d";
222
  break;
223
 
224
  case 'is_less_than':
225
- $where[0] = "$_column < %d";
226
  break;
227
 
228
  case 'between':
229
  $range = explode(',', $_value);
230
- $where = array( "$_column BETWEEN %d AND %d", array( $range[0], $range[1] ) );
231
  break;
232
 
233
  case 'matches':
234
- $where[0] = "$_column REGEXP %s";
235
  break;
236
 
237
  case 'does_not_match':
238
- $where[0] = "$_column NOT REGEXP %s";
239
  break;
240
 
241
  default:
242
- $where[0] = "$_column = %s";
243
  break;
244
  }
245
 
@@ -300,8 +305,10 @@ class wp_slimstat_db {
300
 
301
  switch( $a_filter[ 1 ] ) {
302
  case 'strtotime':
303
- $custom_date = strtotime( $a_filter[ 3 ].' UTC' );
304
 
 
 
305
  $filters_normalized[ 'date' ][ 'day' ] = date( 'j', $custom_date );
306
  $filters_normalized[ 'date' ][ 'month' ] = date( 'n', $custom_date );
307
  $filters_normalized[ 'date' ][ 'year' ] = date( 'Y', $custom_date );
@@ -483,14 +490,14 @@ class wp_slimstat_db {
483
  $sign = ( $filters_normalized[ 'date' ][ 'interval_direction' ] == 'plus' )?'+':'-';
484
 
485
  $filters_normalized[ 'utime' ][ 'end' ] = $filters_normalized[ 'utime' ][ 'start' ] + intval( $sign.(
486
- ( !empty( $filters_normalized[ 'date' ][ 'interval' ] )?intval( $filters_normalized[ 'date' ][ 'interval' ] + 1 ):0 ) * 86400 +
487
  ( !empty( $filters_normalized[ 'date' ][ 'interval_hours' ] )?intval( $filters_normalized[ 'date' ][ 'interval_hours' ] ):0 ) * 3600 +
488
  ( !empty( $filters_normalized[ 'date' ][ 'interval_minutes' ] )?intval( $filters_normalized[ 'date' ][ 'interval_minutes' ] ):0 ) * 60
489
  ) ) - 1;
490
 
491
  // Swap boundaries if we're going back in time
492
  if ( $filters_normalized[ 'date' ][ 'interval_direction' ] == 'minus' ) {
493
- list( $filters_normalized[ 'utime' ][ 'start' ], $filters_normalized[ 'utime' ][ 'end' ] ) = array( $filters_normalized[ 'utime' ][ 'end' ] + 86401, $filters_normalized[ 'utime' ][ 'start' ] + 86399 );
494
  }
495
  }
496
 
35
  'no_filter_selected_1' => array( '&nbsp;', 'none' ),
36
  'browser' => array( __( 'Browser', 'wp-slimstat' ), 'varchar' ),
37
  'country' => array( __( 'Country Code', 'wp-slimstat' ), 'varchar' ),
38
+ 'ip' => array( __( 'IP Address', 'wp-slimstat' ), 'varchar' ),
39
  'searchterms' => array( __( 'Search Terms', 'wp-slimstat' ), 'varchar' ),
40
  'language' => array( __( 'Language Code', 'wp-slimstat' ), 'varchar' ),
41
  'platform' => array( __( 'Operating System', 'wp-slimstat' ), 'varchar' ),
54
  'server_latency' => array( __( 'Server Latency', 'wp-slimstat' ), 'int' ),
55
  'author' => array( __( 'Post Author', 'wp-slimstat' ), 'varchar' ),
56
  'category' => array( __( 'Post Category ID', 'wp-slimstat' ), 'varchar' ),
57
+ 'other_ip' => array( __( 'Originating IP', 'wp-slimstat' ), 'varchar' ),
58
  'content_type' => array( __( 'Resource Content Type', 'wp-slimstat' ), 'varchar' ),
59
  'content_id' => array( __( 'Resource ID', 'wp-slimstat' ), 'int' ),
60
  'screen_width' => array( __( 'Screen Width', 'wp-slimstat' ), 'int' ),
95
 
96
  // Hook for the array of normalized filters
97
  self::$filters_normalized = apply_filters( 'slimstat_db_filters_normalized', self::$filters_normalized, $_filters );
 
 
 
98
  }
99
  // end init
100
 
101
  /**
102
  * Builds the array of WHERE clauses to be used later in our SQL queries
103
  */
104
+ protected static function _get_sql_where( $_filters_normalized = array(), $_slim_stats_table_alias = '' ) {
105
  $sql_array = array();
106
 
107
  foreach ( $_filters_normalized as $a_filter_column => $a_filter_data ) {
110
  continue;
111
  }
112
 
113
+ $sql_array[] = self::_get_single_where_clause( $a_filter_column, $a_filter_data[ 0 ], $a_filter_data[ 1 ], $_slim_stats_table_alias );
114
  }
115
 
116
  // Flatten array
121
  return '';
122
  }
123
 
124
+ public static function get_combined_where( $_where = '', $_column = '*', $_use_time_range = true, $_slim_stats_table_alias = '' ) {
125
+ $dt_with_alias = 'dt';
126
+ if ( !empty( $_slim_stats_table_alias ) ) {
127
+ $dt_with_alias = $_slim_stats_table_alias . '.' . $dt_with_alias;
128
+ }
129
 
130
  if ( empty( $_where ) ) {
131
+ if ( !empty( self::$filters_normalized[ 'columns' ] ) ) {
132
+ $_where = self::_get_sql_where( self::$filters_normalized[ 'columns' ], $_slim_stats_table_alias );
133
+
134
  if ($_use_time_range) {
135
+ $_where .= " AND $dt_with_alias BETWEEN " . self::$filters_normalized[ 'utime' ][ 'start' ] . ' AND ' . self::$filters_normalized[ 'utime' ][ 'end' ];
136
  }
137
  }
138
  elseif ( $_use_time_range ) {
139
+ $_where = "$dt_with_alias BETWEEN " . self::$filters_normalized[ 'utime' ][ 'start' ] . ' AND ' . self::$filters_normalized[ 'utime' ][ 'end' ];
140
  }
141
  else {
142
  $_where = '1=1';
143
  }
144
  }
145
  else {
146
+ if ( $_where != '1=1' && !empty( self::$filters_normalized[ 'columns' ] ) ) {
147
+ $_where .= ' AND ' . self::_get_sql_where( self::$filters_normalized[ 'columns' ], $_slim_stats_table_alias );
148
  }
149
  if ( $_use_time_range ) {
150
+ $_where .= " AND $dt_with_alias BETWEEN " . self::$filters_normalized[ 'utime' ][ 'start' ] . ' AND ' . self::$filters_normalized[ 'utime' ][ 'end' ];
151
  }
152
  }
153
 
166
  /**
167
  * Translates user-friendly operators into SQL conditions
168
  */
169
+ protected static function _get_single_where_clause( $_column = 'id', $_operator = 'equals', $_value = '', $_slim_stats_table_alias = 'b' ) {
170
  $filter_empty = ( self::$columns_names[ $_column ] [ 1 ] == 'varchar' ) ? 'IS NULL' : '= 0';
171
  $filter_not_empty = ( self::$columns_names[ $_column ] [ 1 ] == 'varchar' ) ? 'IS NOT NULL' : '<> 0';
172
 
173
+ $column_with_alias = $_column;
174
+ if ( !empty( $_slim_stats_table_alias ) ) {
175
+ $column_with_alias = $_slim_stats_table_alias . '.' . $_column;
176
+ }
177
+
178
  switch( $_column ) {
179
  case 'ip':
180
  case 'other_ip':
 
181
  $filter_empty = '= "0.0.0.0"';
182
  break;
183
  default:
187
  $where = array( '', $_value );
188
  switch ( $_operator ) {
189
  case 'is_not_equal_to':
190
+ $where[0] = "$column_with_alias <> %s";
191
  break;
192
 
193
  case 'contains':
194
+ $where = array( "$column_with_alias LIKE %s", '%'.$_value.'%' );
195
  break;
196
 
197
  case 'includes_in_set':
198
+ $where[0] = "FIND_IN_SET(%s, $column_with_alias) > 0";
199
  break;
200
 
201
  case 'does_not_contain':
202
+ $where = array( "$column_with_alias NOT LIKE %s", '%'.$_value.'%' );
203
  break;
204
 
205
  case 'starts_with':
206
+ $where = array( "$column_with_alias LIKE %s", $_value.'%' );
207
  break;
208
 
209
  case 'ends_with':
210
+ $where = array( "$column_with_alias LIKE %s", '%'.$_value );
211
  break;
212
 
213
  case 'sounds_like':
214
+ $where[0] = "SOUNDEX($column_with_alias) = SOUNDEX(%s)";
215
  break;
216
 
217
  case 'is_empty':
218
+ $where = array( "$column_with_alias $filter_empty", array() );
219
  break;
220
 
221
  case 'is_not_empty':
222
+ $where = array( "$column_with_alias $filter_not_empty", array() );
223
  break;
224
 
225
  case 'is_greater_than':
226
+ $where[0] = "$column_with_alias > %d";
227
  break;
228
 
229
  case 'is_less_than':
230
+ $where[0] = "$column_with_alias < %d";
231
  break;
232
 
233
  case 'between':
234
  $range = explode(',', $_value);
235
+ $where = array( "$column_with_alias BETWEEN %d AND %d", array( $range[0], $range[1] ) );
236
  break;
237
 
238
  case 'matches':
239
+ $where[0] = "$column_with_alias REGEXP %s";
240
  break;
241
 
242
  case 'does_not_match':
243
+ $where[0] = "$column_with_alias NOT REGEXP %s";
244
  break;
245
 
246
  default:
247
+ $where[0] = "$column_with_alias = %s";
248
  break;
249
  }
250
 
305
 
306
  switch( $a_filter[ 1 ] ) {
307
  case 'strtotime':
308
+ $custom_date = strtotime( $a_filter[ 3 ], date_i18n( 'U' ) );
309
 
310
+ $filters_normalized[ 'date' ][ 'minute' ] = date( 'i', $custom_date );
311
+ $filters_normalized[ 'date' ][ 'hour' ] = date( 'H', $custom_date );
312
  $filters_normalized[ 'date' ][ 'day' ] = date( 'j', $custom_date );
313
  $filters_normalized[ 'date' ][ 'month' ] = date( 'n', $custom_date );
314
  $filters_normalized[ 'date' ][ 'year' ] = date( 'Y', $custom_date );
490
  $sign = ( $filters_normalized[ 'date' ][ 'interval_direction' ] == 'plus' )?'+':'-';
491
 
492
  $filters_normalized[ 'utime' ][ 'end' ] = $filters_normalized[ 'utime' ][ 'start' ] + intval( $sign.(
493
+ ( !empty( $filters_normalized[ 'date' ][ 'interval' ] )?intval( $filters_normalized[ 'date' ][ 'interval' ] + 1):0 ) * 86400 +
494
  ( !empty( $filters_normalized[ 'date' ][ 'interval_hours' ] )?intval( $filters_normalized[ 'date' ][ 'interval_hours' ] ):0 ) * 3600 +
495
  ( !empty( $filters_normalized[ 'date' ][ 'interval_minutes' ] )?intval( $filters_normalized[ 'date' ][ 'interval_minutes' ] ):0 ) * 60
496
  ) ) - 1;
497
 
498
  // Swap boundaries if we're going back in time
499
  if ( $filters_normalized[ 'date' ][ 'interval_direction' ] == 'minus' ) {
500
+ list( $filters_normalized[ 'utime' ][ 'start' ], $filters_normalized[ 'utime' ][ 'end' ] ) = array( $filters_normalized[ 'utime' ][ 'end' ] + 1, $filters_normalized[ 'utime' ][ 'start' ] - 1 );
501
  }
502
  }
503
 
admin/view/wp-slimstat-reports.php CHANGED
@@ -711,7 +711,7 @@ class wp_slimstat_reports {
711
  'slim_p6_01' => array(
712
  'title' => __( 'World Map', 'wp-slimstat' ),
713
  'callback' => array( __CLASS__, 'show_world_map' ),
714
- 'classes' => array( 'tall' ),
715
  'screens' => array( 'wp-slim-view-6' ),
716
  'tooltip' => ''
717
  )
@@ -927,11 +927,6 @@ class wp_slimstat_reports {
927
  $element_pre_value = '';
928
  $element_value = $results[ $i ][ $_args[ 'columns' ] ];
929
 
930
- // Convert the IP address
931
- if (!empty($results[$i]['ip'])){
932
- $results[$i]['ip'] = long2ip($results[$i]['ip']);
933
- }
934
-
935
  // Some columns require a special pre-treatment
936
  switch ( $_args[ 'columns' ] ){
937
 
@@ -942,27 +937,11 @@ class wp_slimstat_reports {
942
  $element_value = $results[$i]['browser'].((isset($results[$i]['browser_version']) && intval($results[$i]['browser_version']) != 0)?' '.$results[$i]['browser_version']:'');
943
  break;
944
 
945
- case 'category':
946
- $row_details .= '<br>'.__('Category ID','wp-slimstat').": {$results[$i]['category']}";
947
- $cat_ids = explode(',', $results[$i]['category']);
948
- if (!empty($cat_ids)){
949
- $element_value = '';
950
- foreach ($cat_ids as $a_cat_id){
951
- if (empty($a_cat_id)) continue;
952
- $cat_name = get_cat_name($a_cat_id);
953
- if (empty($cat_name)) {
954
- $tag = get_term($a_cat_id, 'post_tag');
955
- if (!empty($tag->name)) $cat_name = $tag->name;
956
- }
957
- $element_value .= ', '.(!empty($cat_name)?$cat_name:$a_cat_id);
958
- }
959
- $element_value = substr($element_value, 2);
960
- }
961
- break;
962
  case 'country':
963
  $row_details .= '<br>'.__('Country Code','wp-slimstat').": {$results[$i]['country']}";
964
  $element_value = __('c-'.$results[$i]['country'], 'wp-slimstat');
965
  break;
 
966
  case 'ip':
967
  if (wp_slimstat::$options['convert_ip_addresses'] == 'yes'){
968
  $element_value = gethostbyaddr($results[$i]['ip']);
@@ -982,8 +961,9 @@ class wp_slimstat_reports {
982
  $element_value = __($results[$i]['platform'], 'wp-slimstat');
983
  break;
984
 
 
985
  case 'resource':
986
- $resource_title = self::get_resource_title( $results[ $i ][ 'resource' ] );
987
  if ( $resource_title != $results[ $i ][ 'resource' ] ) {
988
  $row_details = '<br>'.htmlentities($results[$i]['resource'], ENT_QUOTES, 'UTF-8');
989
  }
@@ -1039,7 +1019,7 @@ class wp_slimstat_reports {
1039
  $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;
1040
  }
1041
  if (!empty($results[$i]['ip']) && $_args[ 'columns' ] != 'ip' && wp_slimstat::$options['convert_ip_addresses'] != 'yes'){
1042
- $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'])?' / '.long2ip($results[$i]['other_ip']):'').'<a title="WHOIS: '.$results[$i]['ip'].'" class="slimstat-font-location-1 whois" href="'.wp_slimstat::$options['ip_lookup_service'].$results[$i]['ip'].'"></a>';
1043
  }
1044
  if (!empty($row_details)){
1045
  $row_details = "<b class='slimstat-row-details$is_expanded'>$row_details</b>";
@@ -1636,17 +1616,47 @@ class wp_slimstat_reports {
1636
  /**
1637
  * Attempts to convert a permalink into a post title
1638
  */
1639
- public static function get_resource_title($_resource = ''){
1640
- if (wp_slimstat::$options['convert_resource_urls_to_titles'] == 'yes'){
1641
- if ( get_option( 'permalink_structure' , false ) ) {
1642
- $_resource = strtok($_resource, '?');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1643
  }
1644
- $post_id = url_to_postid( $_resource );
1645
- if ( $post_id > 0 ) {
1646
- return get_the_title( $post_id );
 
 
 
 
 
 
 
 
1647
  }
1648
  }
1649
- return htmlentities(urldecode($_resource), ENT_QUOTES, 'UTF-8');
 
1650
  }
1651
 
1652
  public static function inline_help( $_text = '', $_echo = true ) {
711
  'slim_p6_01' => array(
712
  'title' => __( 'World Map', 'wp-slimstat' ),
713
  'callback' => array( __CLASS__, 'show_world_map' ),
714
+ 'classes' => array( 'full-width tall' ),
715
  'screens' => array( 'wp-slim-view-6' ),
716
  'tooltip' => ''
717
  )
927
  $element_pre_value = '';
928
  $element_value = $results[ $i ][ $_args[ 'columns' ] ];
929
 
 
 
 
 
 
930
  // Some columns require a special pre-treatment
931
  switch ( $_args[ 'columns' ] ){
932
 
937
  $element_value = $results[$i]['browser'].((isset($results[$i]['browser_version']) && intval($results[$i]['browser_version']) != 0)?' '.$results[$i]['browser_version']:'');
938
  break;
939
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
940
  case 'country':
941
  $row_details .= '<br>'.__('Country Code','wp-slimstat').": {$results[$i]['country']}";
942
  $element_value = __('c-'.$results[$i]['country'], 'wp-slimstat');
943
  break;
944
+
945
  case 'ip':
946
  if (wp_slimstat::$options['convert_ip_addresses'] == 'yes'){
947
  $element_value = gethostbyaddr($results[$i]['ip']);
961
  $element_value = __($results[$i]['platform'], 'wp-slimstat');
962
  break;
963
 
964
+ case 'category':
965
  case 'resource':
966
+ $resource_title = self::get_resource_title( $results[ $i ][ 'resource' ], !empty( $results[ $i ][ 'category' ] ) ? $results[ $i ][ 'category' ] : '' );
967
  if ( $resource_title != $results[ $i ][ 'resource' ] ) {
968
  $row_details = '<br>'.htmlentities($results[$i]['resource'], ENT_QUOTES, 'UTF-8');
969
  }
1019
  $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;
1020
  }
1021
  if (!empty($results[$i]['ip']) && $_args[ 'columns' ] != 'ip' && wp_slimstat::$options['convert_ip_addresses'] != 'yes'){
1022
+ $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::$options['ip_lookup_service'].$results[$i]['ip'].'"></a>';
1023
  }
1024
  if (!empty($row_details)){
1025
  $row_details = "<b class='slimstat-row-details$is_expanded'>$row_details</b>";
1616
  /**
1617
  * Attempts to convert a permalink into a post title
1618
  */
1619
+ public static function get_resource_title( $_resource = '' ) {
1620
+ $resource_title = $_resource;
1621
+
1622
+ if ( wp_slimstat::$options[ 'convert_resource_urls_to_titles' ] != 'yes' ) {
1623
+ return htmlentities( urldecode( $resource_title ), ENT_QUOTES, 'UTF-8' );
1624
+ }
1625
+
1626
+ // Is this a post or a page?
1627
+ $post_id = url_to_postid( $_resource );
1628
+ if ( $post_id > 0 ) {
1629
+ $resource_title = get_the_title( $post_id );
1630
+ }
1631
+
1632
+ // Is this a category or tag permalink?
1633
+ else {
1634
+ $term_names = array();
1635
+ $home_url = get_home_url();
1636
+ $relative_home = parse_url( $home_url, PHP_URL_PATH );
1637
+
1638
+ $all_terms = get_terms( 'category' );
1639
+ foreach ( $all_terms as $a_term ) {
1640
+ $term_link = get_term_link( $a_term, 'category' );
1641
+ if ( !is_wp_error( $term_link ) && str_replace( $home_url, $relative_home, $term_link ) == $_resource ) {
1642
+ $term_names[] = $a_term->name;
1643
+ }
1644
  }
1645
+
1646
+ $all_terms = get_terms( 'tag' );
1647
+ foreach ( $all_terms as $a_term ) {
1648
+ $term_link = get_term_link( $a_term, 'tag' );
1649
+ if ( !is_wp_error( $term_link ) && str_replace( $home_url, $relative_home, $term_link ) == $_resource ) {
1650
+ $term_names[] = $a_term->name;
1651
+ }
1652
+ }
1653
+
1654
+ if ( !empty( $term_names ) ) {
1655
+ $resource_title = implode( ',', $term_names );
1656
  }
1657
  }
1658
+
1659
+ return htmlentities( urldecode( $resource_title ), ENT_QUOTES, 'UTF-8' );
1660
  }
1661
 
1662
  public static function inline_help( $_text = '', $_echo = true ) {
admin/wp-slimstat-admin.php CHANGED
@@ -11,7 +11,8 @@ class wp_slimstat_admin{
11
  */
12
  public static function init(){
13
  if ((wp_slimstat::$options['enable_ads_network'] == 'yes' || wp_slimstat::$options['enable_ads_network'] == 'no')){
14
- self::$admin_notice = "A few weeks ago we started hitting the limits imposed on our site by our existing hosting provider. It was clearly time to find a new home for Slimstat. We've been working on migrating our web platform (website and add-on repository API) to a new more powerful server, and a new domain: <a href='http://www.wp-slimstat.com' target='_blank'>wp-slimstat.com</a>. Our dev team has also released updates for our premium add-ons Export to Excel, Email Reports and User Overview, which are now fully compatible with Slimstat 4. Go get your copy today.";
 
15
  self::$admin_notice .= '<br/><br/><a id="slimstat-hide-admin-notice" href="#" class="button-secondary">I got it, thanks</a>';
16
  }
17
  else {
@@ -222,8 +223,8 @@ class wp_slimstat_admin{
222
  $stats_table_sql = "
223
  CREATE TABLE IF NOT EXISTS {$GLOBALS['wpdb']->prefix}slim_stats (
224
  id INT UNSIGNED NOT NULL auto_increment,
225
- ip INT UNSIGNED DEFAULT 0,
226
- other_ip INT UNSIGNED DEFAULT 0,
227
  username VARCHAR(255) DEFAULT NULL,
228
  country VARCHAR(16) DEFAULT NULL,
229
  referer VARCHAR(2048) DEFAULT NULL,
@@ -500,6 +501,17 @@ class wp_slimstat_admin{
500
  }
501
  // --- END: Updates for version 4.0 ---
502
 
 
 
 
 
 
 
 
 
 
 
 
503
  // Now we can update the version stored in the database
504
  wp_slimstat::$options['version'] = wp_slimstat::$version;
505
 
11
  */
12
  public static function init(){
13
  if ((wp_slimstat::$options['enable_ads_network'] == 'yes' || wp_slimstat::$options['enable_ads_network'] == 'no')){
14
+ self::$admin_notice = "A few users have been asking us to support IPv6. You will be pleased to know that we got to work and updated our table structure to accommodate this request. Unfortunately MaxMind only supports IPv6 in their new GeoLite2 format, <a href='https://github.com/maxmind/GeoIP2-php#requirements' target='_blank'>which requires PHP 5.3</a>. We know for a fact that some of our users are still on PHP 5.2, and we would like to hear your opinion on this matter: should we enforce the minimum requirement of PHP 5.3 in order to detect the Country associated to IPv6 addresses? Or do you think it's better to be compatible with PHP 5.2? Let us know through the forum or via our support service. Thank you.";
15
+ // 4.1.4 self::$admin_notice = "Can you believe it? We have passed 1.5 million downloads! To thank you for your loyalty and continued support, we are offering a 15% discount on all orders (including the bundles!) till the end of the month. Just enter <code>15OFF</code> in the corresponding field at checkout. Have you already purchased one of our add-ons? We have an even bigger surprise for you: as a way to thank you for your patience while we updated our extensions to make them compatible with Slimstat 4, we are giving away 50 codes to download one <strong>free</strong> add-on from our store. Including the new ones we're about to announce. Contact us to get your code (please mention your license key in your message).";
16
  self::$admin_notice .= '<br/><br/><a id="slimstat-hide-admin-notice" href="#" class="button-secondary">I got it, thanks</a>';
17
  }
18
  else {
223
  $stats_table_sql = "
224
  CREATE TABLE IF NOT EXISTS {$GLOBALS['wpdb']->prefix}slim_stats (
225
  id INT UNSIGNED NOT NULL auto_increment,
226
+ ip VARCHAR(39) DEFAULT NULL,
227
+ other_ip VARCHAR(39) DEFAULT NULL,
228
  username VARCHAR(255) DEFAULT NULL,
229
  country VARCHAR(16) DEFAULT NULL,
230
  referer VARCHAR(2048) DEFAULT NULL,
501
  }
502
  // --- END: Updates for version 4.0 ---
503
 
504
+ // --- Updates for version 4.1.3 ---
505
+ if (version_compare(wp_slimstat::$options['version'], '4.1.3', '<')){
506
+ // Change column type to add IPv6 support
507
+ $my_wpdb->query( "ALTER TABLE {$GLOBALS['wpdb']->prefix}slim_stats ADD ip_temp VARCHAR(39) DEFAULT NULL AFTER id, ADD other_ip_temp VARCHAR(39) DEFAULT NULL AFTER id" );
508
+ $my_wpdb->query( "UPDATE {$GLOBALS['wpdb']->prefix}slim_stats SET ip_temp = INET_NTOA(ip), other_ip_temp = INET_NTOA(other_ip)" );
509
+ $my_wpdb->query( "ALTER TABLE {$GLOBALS['wpdb']->prefix}slim_stats DROP COLUMN ip, DROP COLUMN other_ip" );
510
+ $my_wpdb->query( "ALTER TABLE {$GLOBALS['wpdb']->prefix}slim_stats CHANGE ip_temp ip VARCHAR(39) DEFAULT NULL AFTER id" );
511
+ $my_wpdb->query( "ALTER TABLE {$GLOBALS['wpdb']->prefix}slim_stats CHANGE other_ip_temp other_ip VARCHAR(39) DEFAULT NULL AFTER ip" );
512
+ }
513
+ // --- END: Updates for version 4.1.3 ---
514
+
515
  // Now we can update the version stored in the database
516
  wp_slimstat::$options['version'] = wp_slimstat::$version;
517
 
readme.txt CHANGED
@@ -4,13 +4,13 @@ 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: 4.1.2
8
 
9
  == Description ==
10
  [youtube https://www.youtube.com/watch?v=iJCtjxArq4U]
11
 
12
  = Key Features =
13
- * Real-time activity log, server latency, heatmaps, email reports, export data to Excel, and much more
14
  * Compatible with W3 Total Cache, WP SuperCache and most caching plugins
15
  * Accurate IP geolocation, browser and platform detection (courtesy of [MaxMind](http://www.maxmind.com/) and [Browscap](http://browscap.org))
16
  * Available in multiple languages: English, Chinese (沐熙工作室), Farsi ([Dean](http://www.mangallery.net)), French (Michael Bastin, Jean-Michel Venet, Yves Pouplard, Henrick Kac), German (TechnoViel), Italian, Japanese (h_a_l_f), Portuguese, Russian ([Vitaly](http://www.visbiz.org/)), Spanish ([WebHostingHub](http://www.webhostinghub.com/)), Swedish (Per Soderman). Is your language missing or incomplete? [Contact Us](http://support.wp-slimstat.com/) if you would like to share your localization.
@@ -59,6 +59,14 @@ Our knowledge base is available on our [support center](http://docs.wp-slimstat.
59
 
60
  == Changelog ==
61
 
 
 
 
 
 
 
 
 
62
  = 4.1.2 =
63
  * [Note] A few weeks ago we started hitting the limits imposed on our site by our existing hosting provider. It was clearly time to find a new home for Slimstat. We've been working on migrating our web platform (website and add-on repository API) to a new more powerful server, and a new domain: [wp-slimstat.com](http://www.wp-slimstat.com).
64
  * [Note] Our dev team has released updates for our premium add-ons Export to Excel, Email Reports and User Overview, which are now fully compatible with Slimstat 4. Go get your copy today.
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: 4.1.3
8
 
9
  == Description ==
10
  [youtube https://www.youtube.com/watch?v=iJCtjxArq4U]
11
 
12
  = Key Features =
13
+ * Real-time activity log, server latency, heatmaps, email reports, export data to Excel, full IPv6 support, and much more
14
  * Compatible with W3 Total Cache, WP SuperCache and most caching plugins
15
  * Accurate IP geolocation, browser and platform detection (courtesy of [MaxMind](http://www.maxmind.com/) and [Browscap](http://browscap.org))
16
  * Available in multiple languages: English, Chinese (沐熙工作室), Farsi ([Dean](http://www.mangallery.net)), French (Michael Bastin, Jean-Michel Venet, Yves Pouplard, Henrick Kac), German (TechnoViel), Italian, Japanese (h_a_l_f), Portuguese, Russian ([Vitaly](http://www.visbiz.org/)), Spanish ([WebHostingHub](http://www.webhostinghub.com/)), Swedish (Per Soderman). Is your language missing or incomplete? [Contact Us](http://support.wp-slimstat.com/) if you would like to share your localization.
59
 
60
  == Changelog ==
61
 
62
+ = 4.1.3 =
63
+ * [Note] We've updated the following add-ons to be compatible with Slimstat 4.x: Custom DB, Heatmap, Track Cookies. Go get your copy today.
64
+ * [Update] Say hello to IPv6 internet addresses. Slimstat is now compatible with this technology, and will not throw an error when users visit the site using an IPv6 address. Please note: the column type in the database has changed from INT UNSIGNED to VARCHAR(39). Update your custom code accordingly.
65
+ * [Update] Category names are now displayed instead of their URLs, when the corresponding option is enabled (thank you, Keith Gengler).
66
+ * [Update] Now the database API can be given a table alias for when JOINS are necessary, to avoid MySQL errors or ambiguous column names.
67
+ * [Fix] Map overlay was being displayed not in full width, because of some class name changes we implemented in Slimstat 4.
68
+ * [Fix] Tracking of internal link coordinates (heatmap) was not accurate if the link tag had markup inside it (thank you, [dragon013](https://wordpress.org/support/topic/for-links-a-doublelink-is-needed)).
69
+
70
  = 4.1.2 =
71
  * [Note] A few weeks ago we started hitting the limits imposed on our site by our existing hosting provider. It was clearly time to find a new home for Slimstat. We've been working on migrating our web platform (website and add-on repository API) to a new more powerful server, and a new domain: [wp-slimstat.com](http://www.wp-slimstat.com).
72
  * [Note] Our dev team has released updates for our premium add-ons Export to Excel, Email Reports and User Overview, which are now fully compatible with Slimstat 4. Go get your copy today.
wp-slimstat.js CHANGED
@@ -1,4 +1,5 @@
1
  var SlimStat = {
 
2
  _id: "undefined" != typeof SlimStatParams.id ? SlimStatParams.id : "-1.0",
3
  _base64_key_str: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
4
  _plugins: {
@@ -31,138 +32,470 @@ var SlimStat = {
31
  active_x_strings: ["AgControl.AgControl"]
32
  }
33
  },
34
- _utf8_encode: function(e) {
35
- var t, n, i = "";
36
- for (e = e.replace(/\r\n/g, "\n"), t = 0; t < e.length; t++) n = e.charCodeAt(t), 128 > n ? i += String.fromCharCode(n) : n > 127 && 2048 > n ? (i += String.fromCharCode(n >> 6 | 192), i += String.fromCharCode(63 & n | 128)) : (i += String.fromCharCode(n >> 12 | 224), i += String.fromCharCode(n >> 6 & 63 | 128), i += String.fromCharCode(63 & n | 128));
37
- return i
38
- },
39
- _base64_encode: function(e) {
40
- var t, n, i, a, r, s, o, l = "",
41
- d = 0;
42
- for (e = SlimStat._utf8_encode(e); d < e.length;) t = e.charCodeAt(d++), n = e.charCodeAt(d++), i = e.charCodeAt(d++), a = t >> 2, r = (3 & t) << 4 | n >> 4, s = (15 & n) << 2 | i >> 6, o = 63 & i, isNaN(n) ? s = o = 64 : isNaN(i) && (o = 64), l = l + SlimStat._base64_key_str.charAt(a) + SlimStat._base64_key_str.charAt(r) + SlimStat._base64_key_str.charAt(s) + this._base64_key_str.charAt(o);
43
- return l
44
- },
45
- _detect_single_plugin_not_ie: function(e) {
46
- var t, n, i, a;
47
- for (i in navigator.plugins) {
48
- t = "" + navigator.plugins[i].name + navigator.plugins[i].description, n = 0;
49
- for (a in SlimStat._plugins[e].substrings) - 1 != t.indexOf(SlimStat._plugins[e].substrings[a]) && n++;
50
- if (n == SlimStat._plugins[e].substrings.length) return !0
51
- }
52
- return !1
53
- },
54
- _detect_single_plugin_ie: function(e) {
55
- var t;
56
- for (t in SlimStat._plugins[e].active_x_strings) try {
57
- return new ActiveXObject(SlimStat._plugins[e].active_x_strings[t]), !0
58
- } catch (n) {
59
- return !1
60
- }
61
- },
62
- _detect_single_plugin: function(e) {
63
- return this.detect = navigator.plugins.length ? this._detect_single_plugin_not_ie : this._detect_single_plugin_ie, this.detect(e)
64
- },
65
- detect_plugins: function() {
66
- var e = "",
67
- t = [];
68
- for (e in SlimStat._plugins) SlimStat._detect_single_plugin(e) && t.push(e);
69
- return t.join(",")
70
- },
71
- get_page_performance: function() {
72
- 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
73
- },
74
- get_server_latency: function() {
75
- 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
76
- },
77
- send_to_server: function(e, t) {
78
- if ("undefined" == typeof SlimStatParams.ajaxurl || "undefined" == typeof e) return "function" == typeof t && t(), !1;
79
- try {
80
- window.XMLHttpRequest ? request = new XMLHttpRequest : window.ActiveXObject && (request = new ActiveXObject("Microsoft.XMLHTTP"))
81
- } catch (n) {
82
- return "function" == typeof t && t(), !1
83
- }
84
- return slimstat_data_with_client_info = e + "&sw=" + screen.width + "&sh=" + screen.height + "&bw=" + window.innerWidth + "&bh=" + window.innerHeight + "&sl=" + SlimStat.get_server_latency() + "&pp=" + SlimStat.get_page_performance() + "&pl=" + SlimStat.detect_plugins(), request ? (request.open("POST", SlimStatParams.ajaxurl, !0), request.setRequestHeader("Content-type", "application/x-www-form-urlencoded"), request.send(slimstat_data_with_client_info), request.onreadystatechange = function() {
85
- 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())
86
- }, !0) : !1
87
- },
88
- ss_track: function(e, t, n, i) {
89
- if (e || (e = window.event), type = "undefined" == typeof t ? 0 : parseInt(t), note_array = [], parsed_id = parseInt(SlimStat._id), isNaN(parsed_id) || parsed_id <= 0) return "function" == typeof i && i(), !1;
90
- if (node = "undefined" != typeof e.target ? e.target : "undefined" != typeof e.srcElement ? e.srcElement : !1, !node) return "function" == typeof i && i(), !1;
91
- switch (3 == node.nodeType && (node = node.parentNode), parent_node = node.parentNode, resource_url = "", node.nodeName) {
92
- case "FORM":
93
- node.action.length > 0 && (resource_url = node.action);
94
- break;
95
- case "INPUT":
96
- for (;
97
- "undefined" != typeof parent_node && "FORM" != parent_node.nodeName && "BODY" != parent_node.nodeName;) parent_node = parent_node.parentNode;
98
- if ("undefined" != typeof parent_node.action && parent_node.action.length > 0) {
99
- resource_url = parent_node.action;
100
- break
101
- }
102
- default:
103
- if ("A" != node.nodeName) {
104
- if ("function" == typeof node.getAttribute && "undefined" != node.getAttribute("id") && node.getAttribute("id").length) {
105
- resource_url = node.getAttribute("id");
106
- break
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  }
108
- for (;
109
- "undefined" != typeof node.parentNode && null != node.parentNode && "A" != node.nodeName && "BODY" != node.nodeName;) node = node.parentNode
110
- }
111
- "undefined" != typeof node.hash && node.hash.length > 0 && node.hostname == location.hostname ? resource_url = node.hash : "undefined" != typeof node.href && (resource_url = node.href), "function" == typeof node.getAttribute && ("undefined" != typeof node.getAttribute("title") && null != node.getAttribute("title") && node.getAttribute("title").length > 0 && note_array.push("Title:" + node.getAttribute("title")), "undefined" != typeof node.getAttribute("id") && null != node.getAttribute("id") && node.getAttribute("id").length > 0 && note_array.push("ID:" + node.getAttribute("id")))
112
- }
113
- return pos_x = -1, pos_y = -1, position = "", "undefined" != typeof e.pageX && "undefined" != typeof e.pageY ? (pos_x = e.pageX, pos_y = 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, pos_y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop), pos_x > 0 && pos_y > 0 && (position = pos_x + "," + pos_y), event_description = e.type, "click" != e.type && "undefined" != typeof e.which && (event_description += "keypress" == e.type ? "; keypress:" + String.fromCharCode(parseInt(e.which)) : "; which:" + e.which), "undefined" != typeof n && n.length > 0 && note_array.push(n), note_string = SlimStat._base64_encode(note_array.join(", ")), requested_op = "update", 1 == type && (resource_url = SlimStat._base64_encode(resource_url.substring(resource_url.indexOf(location.hostname) + location.hostname.length)), requested_op = "add"), SlimStat.send_to_server("action=slimtrack&op=" + requested_op + "&id=" + SlimStat._id + "&ty=" + type + "&ref=" + SlimStat._base64_encode(document.referrer) + "&res=" + resource_url + "&pos=" + position + "&des=" + SlimStat._base64_encode(event_description) + "&no=" + note_string, i), !0
114
- },
115
- add_event: function(e, t, n) {
116
- e && e.addEventListener ? e.addEventListener(t, n, !1) : e && e.attachEvent ? (e["e" + t + n] = n, e[t + n] = function() {
117
- e["e" + t + n](window.event)
118
- }, e.attachEvent("on" + t, e[t + n])) : e["on" + t] = e["e" + t + n]
119
- },
120
- event_fire: function(e, t) {
121
- var n = e;
122
- if (document.createEvent) {
123
- var i = document.createEvent("MouseEvents");
124
- i.initEvent(t, !0, !1), n.dispatchEvent(i)
125
- } else if (document.createEventObject) {
126
- var i = document.createEventObject();
127
- n.fireEvent("on" + t, i)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  },
130
- in_array: function(e, t) {
131
- for (var n = 0; n < t.length; n++)
132
- if (t[n].trim() == e) return !0;
133
- return !1
134
- },
135
- in_array_substring: function(e, t) {
136
- for (var n = 0; n < t.length; n++)
137
- if (-1 != e.indexOf(t[n].trim())) return !0;
138
- return !1
139
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  };
141
- SlimStat.add_event(window, "load", function() {
142
- if ("undefined" == typeof SlimStatParams.disable_outbound_tracking) {
143
- all_links = document.getElementsByTagName("a");
144
- 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(",") : [], i = 0; i < all_links.length; i++)! function() {
145
- var a = all_links[i];
146
- if (a.slimstat_actual_click = !1, a.slimstat_type = !a.href || a.hostname != location.hostname && -1 != a.href.indexOf("://") ? 0 : 2, a.slimstat_track_me = !0, a.slimstat_callback = !0, 2 != a.slimstat_type || "undefined" != typeof SlimStatParams.track_internal_links && "false" != SlimStatParams.track_internal_links || (a.slimstat_track_me = !1), a.slimstat_track_me && (t.length > 0 || n.length > 0)) {
147
- classes_current_link = "undefined" != typeof a.className && a.className.length > 0 ? a.className.split(" ") : [];
148
- for (var r = 0; r < classes_current_link.length; r++)
149
- if (SlimStat.in_array_substring(classes_current_link[r], t) && (a.slimstat_callback = !1), SlimStat.in_array_substring(classes_current_link[r], n)) {
150
- a.slimstat_track_me = !1;
151
- break
152
- }
153
- a.slimstat_track_me && "undefined" != typeof a.attributes.rel && a.attributes.rel.value.length > 0 && (SlimStat.in_array_substring(a.attributes.rel.value, t) && (a.slimstat_callback = !1), SlimStat.in_array_substring(a.attributes.rel.value, n) && (a.slimstat_track_me = !1)), a.slimstat_track_me && "undefined" != typeof a.href && a.href.length > 0 && (SlimStat.in_array_substring(a.href, t) && (a.slimstat_callback = !1), SlimStat.in_array_substring(a.href, n) && (a.slimstat_track_me = !1))
154
- }
155
- e.length > 0 && 2 == a.slimstat_type && a.pathname.indexOf(".") > 0 && (extension_current_link = a.pathname.split(".").pop().replace(/[\/\-]/g, ""), a.slimstat_track_me = SlimStat.in_array(extension_current_link, e), a.slimstat_type = 1), a.slimstat_track_me && a.target && !a.target.match(/^_(self|parent|top)$/i) && (a.slimstat_callback = !1), a.setAttribute("data-slimstat-tracking", a.slimstat_track_me), a.setAttribute("data-slimstat-callback", a.slimstat_callback), SlimStat.add_event(a, "click", function(e) {
156
- this.slimstat_track_me && !this.slimstat_actual_click && (this.slimstat_callback ? ("function" == typeof e.preventDefault && e.preventDefault(), this.slimstat_actual_click = !0, SlimStat.ss_track(e, this.slimstat_type, "", function() {
157
- SlimStat.event_fire(a, "click")
158
- })) : SlimStat.ss_track(e, this.slimstat_type, "", function() {}))
159
- })
160
- }()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  }
162
- });
 
163
  var slimstat_data = "action=slimtrack";
164
- "undefined" != typeof SlimStatParams.id && parseInt(SlimStatParams.id) > 0 ? slimstat_data += "&op=update&id=" + SlimStatParams.id : "undefined" != typeof SlimStatParams.ci && (slimstat_data += "&op=add&id=" + SlimStatParams.ci + "&ref=" + SlimStat._base64_encode(document.referrer) + "&res=" + SlimStat._base64_encode(window.location.href)), slimstat_data.length && SlimStat.add_event(window, "load", function() {
165
- setTimeout(function() {
166
- SlimStat.send_to_server(slimstat_data)
167
- }, 0)
168
- });
 
 
 
 
 
 
 
 
 
 
1
  var SlimStat = {
2
+ // Private Properties
3
  _id: "undefined" != typeof SlimStatParams.id ? SlimStatParams.id : "-1.0",
4
  _base64_key_str: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
5
  _plugins: {
32
  active_x_strings: ["AgControl.AgControl"]
33
  }
34
  },
35
+
36
+ _utf8_encode : function (string) {
37
+ var n, c, utftext = "";
38
+
39
+ string = string.replace(/\r\n/g,"\n");
40
+
41
+ for (n = 0; n < string.length; n++) {
42
+ c = string.charCodeAt(n);
43
+
44
+ if (c < 128) {
45
+ utftext += String.fromCharCode(c);
46
+ }
47
+ else if((c > 127) && (c < 2048)) {
48
+ utftext += String.fromCharCode((c >> 6) | 192);
49
+ utftext += String.fromCharCode((c & 63) | 128);
50
+ }
51
+ else {
52
+ utftext += String.fromCharCode((c >> 12) | 224);
53
+ utftext += String.fromCharCode(((c >> 6) & 63) | 128);
54
+ utftext += String.fromCharCode((c & 63) | 128);
55
+ }
56
+ }
57
+ return utftext;
58
+ },
59
+
60
+ // Base64 Encode - http://www.webtoolkit.info/
61
+ _base64_encode : function ( input ) {
62
+ var chr1, chr2, chr3, enc1, enc2, enc3, enc4, output = "", i = 0;
63
+
64
+ input = SlimStat._utf8_encode(input);
65
+
66
+ while (i < input.length) {
67
+ chr1 = input.charCodeAt(i++);
68
+ chr2 = input.charCodeAt(i++);
69
+ chr3 = input.charCodeAt(i++);
70
+
71
+ enc1 = chr1 >> 2;
72
+ enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
73
+ enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
74
+ enc4 = chr3 & 63;
75
+
76
+ if (isNaN(chr2)) {
77
+ enc3 = enc4 = 64;
78
+ } else if (isNaN(chr3)) {
79
+ enc4 = 64;
80
+ }
81
+
82
+ output = output + SlimStat._base64_key_str.charAt(enc1) + SlimStat._base64_key_str.charAt(enc2) + SlimStat._base64_key_str.charAt(enc3) + this._base64_key_str.charAt(enc4);
83
+ }
84
+ return output;
85
+ },
86
+
87
+ _detect_single_plugin_not_ie : function ( plugin_name ) {
88
+ var plugin, haystack, found, i, j;
89
+
90
+ for ( i in navigator.plugins ) {
91
+ haystack = '' + navigator.plugins[ i ].name + navigator.plugins[ i ].description;
92
+ found = 0;
93
+
94
+ for ( j in SlimStat._plugins[ plugin_name ].substrings ) {
95
+ if ( haystack.indexOf( SlimStat._plugins[ plugin_name ].substrings[ j ] ) != -1 ) {
96
+ found++;
97
+ }
98
+ }
99
+
100
+ if ( found == SlimStat._plugins[ plugin_name ].substrings.length ) {
101
+ return true;
102
+ }
103
+ }
104
+ return false;
105
+ },
106
+
107
+ _detect_single_plugin_ie : function ( plugin_name ) {
108
+ var i;
109
+
110
+ for (i in SlimStat._plugins[plugin_name].active_x_strings) {
111
+ try {
112
+ new ActiveXObject( SlimStat._plugins[plugin_name].active_x_strings[i] );
113
+ return true;
114
+ }
115
+ catch(e) {
116
+ return false;
117
+ }
118
+ }
119
+ },
120
+
121
+ _detect_single_plugin : function ( plugin_name ) {
122
+ if( navigator.plugins.length ) {
123
+ this.detect = this._detect_single_plugin_not_ie;
124
+ }
125
+ else {
126
+ this.detect = this._detect_single_plugin_ie;
127
+ }
128
+ return this.detect( plugin_name );
129
+ },
130
+
131
+ detect_plugins : function () {
132
+ var a_plugin, plugins = [];
133
+
134
+ for (a_plugin in SlimStat._plugins) {
135
+ if (SlimStat._detect_single_plugin(a_plugin)) {
136
+ plugins.push( a_plugin );
137
+ }
138
+ }
139
+ return plugins.join( "," );
140
+ },
141
+
142
+ get_page_performance : function () {
143
+ slim_performance = window.performance || window.mozPerformance || window.msPerformance || window.webkitPerformance || {};
144
+ if ( "undefined" == typeof slim_performance.timing ){
145
+ return 0;
146
+ }
147
+
148
+ return slim_performance.timing.loadEventEnd - slim_performance.timing.responseEnd;
149
+ },
150
+
151
+ get_server_latency : function () {
152
+ slim_performance = window.performance || window.mozPerformance || window.msPerformance || window.webkitPerformance || {};
153
+ if ( "undefined" == typeof slim_performance.timing ){
154
+ return 0;
155
+ }
156
+
157
+ return slim_performance.timing.responseEnd - slim_performance.timing.connectEnd;
158
+ },
159
+
160
+ send_to_server : function ( data, callback ) {
161
+ if ( "undefined" == typeof SlimStatParams.ajaxurl || 'undefined' == typeof data ){
162
+ if ( "function" == typeof callback ){
163
+ callback();
164
+ }
165
+ return false;
166
+ }
167
+
168
+ try {
169
+ if ( window.XMLHttpRequest ) {
170
+ request = new XMLHttpRequest();
171
+ }
172
+ else if ( window.ActiveXObject ) { // code for IE6, IE5
173
+ request = new ActiveXObject( "Microsoft.XMLHTTP" );
174
+ }
175
+ } catch ( failed ) {
176
+ if ( "function" == typeof callback ){
177
+ callback();
178
+ }
179
+ return false;
180
+ }
181
+
182
+ slimstat_data_with_client_info = data + "&sw=" + screen.width + "&sh=" + screen.height + "&bw=" + window.innerWidth + "&bh=" + window.innerHeight + "&sl=" + SlimStat.get_server_latency() + "&pp=" + SlimStat.get_page_performance() + "&pl=" + SlimStat.detect_plugins()
183
+
184
+ if ( request ) {
185
+ request.open( "POST", SlimStatParams.ajaxurl, true );
186
+ request.setRequestHeader( "Content-type", "application/x-www-form-urlencoded" );
187
+ request.send( slimstat_data_with_client_info );
188
+
189
+ request.onreadystatechange = function() {
190
+ if ( 4 == request.readyState ) {
191
+ if ( "undefined" == typeof SlimStatParams.id ) {
192
+ parsed_id = parseInt( request.responseText );
193
+ if ( !isNaN( parsed_id ) && parsed_id > 0 ) {
194
+ SlimStat._id = request.responseText;
195
+ }
196
+ }
197
+ else {
198
+ SlimStat._id = SlimStatParams.id;
199
  }
200
+ if ( "function" == typeof callback ) {
201
+ callback();
202
+ }
203
+ }
204
+ }
205
+ return true;
206
+ }
207
+
208
+ return false;
209
+ },
210
+
211
+ ss_track : function (e, c, note, callback) {
212
+ // Check function params
213
+ e = e ? e : window.event;
214
+ type = ( "undefined" == typeof c ) ? 0 : parseInt( c );
215
+ note_array = [];
216
+
217
+ parsed_id = parseInt( SlimStat._id );
218
+ if ( isNaN( parsed_id ) || parsed_id <= 0 ) {
219
+ if ( "function" == typeof callback ) {
220
+ callback();
221
+ }
222
+ return false;
223
+ }
224
+
225
+ node = ( "undefined" != typeof e.target ) ? e.target : ( ( "undefined" != typeof e.srcElement ) ? e.srcElement : false );
226
+ if ( !node ) {
227
+ if ("function" == typeof callback ) {
228
+ callback();
229
+ }
230
+ return false;
231
+ }
232
+
233
+ // Safari bug
234
+ if ( 3 == node.nodeType ) {
235
+ node = node.parentNode;
236
+ }
237
+
238
+ parent_node = node.parentNode;
239
+ resource_url = '';
240
+
241
+ // This handler can be attached to any element, but only A carries the extra info we need
242
+ switch ( node.nodeName ) {
243
+ case 'FORM':
244
+ if ( "undefined" != typeof node.action && node.action ) {
245
+ resource_url = node.action;
246
+ }
247
+ break;
248
+
249
+ case 'INPUT':
250
+ // Let's look for a FORM element
251
+ while ( "undefined" != typeof parent_node && parent_node.nodeName != "FORM" && parent_node.nodeName != "BODY" ) {
252
+ parent_node = parent_node.parentNode;
253
+ }
254
+ if ( "undefined" != typeof parent_node.action && parent_node.action ) {
255
+ resource_url = parent_node.action;
256
+ break;
257
+ }
258
+
259
+ default:
260
+ // Any other element
261
+ if ( "A" != node.nodeName ) {
262
+ while ( "undefined" != typeof node.parentNode && null != node.parentNode && "A" != node.nodeName && "BODY" != node.nodeName ) {
263
+ node = node.parentNode;
264
+ }
265
+ }
266
+
267
+ // Anchor in the same page
268
+ if ( "undefined" != typeof node.hash && node.hash && node.hostname == location.hostname ) {
269
+ resource_url = node.hash;
270
+ }
271
+ else if ( "undefined" != typeof node.href ) {
272
+ resource_url = node.href;
273
+ }
274
+
275
+ // If this element has a title, we can record that as well
276
+ if ( "function" == typeof node.getAttribute){
277
+ if ( "undefined" != typeof node.getAttribute("title") && node.getAttribute("title") ) {
278
+ note_array.push( "Title:" + node.getAttribute( "title" ) );
279
+ }
280
+ if ( "undefined" != typeof node.getAttribute("id") && node.getAttribute("id") ) {
281
+ note_array.push( "ID:" + node.getAttribute( "id" ) );
282
+ }
283
+ }
284
  }
285
+
286
+ // Event coordinates
287
+ pos_x = -1;
288
+ pos_y = -1;
289
+ position = "";
290
+
291
+ if ( "undefined" != typeof e.pageX && "undefined" != typeof e.pageY ) {
292
+ pos_x = e.pageX;
293
+ pos_y = e.pageY;
294
+ }
295
+ else if ( "undefined" != typeof e.clientX && "undefined" != typeof e.clientY &&
296
+ "undefined" != typeof document.body.scrollLeft && "undefined" != typeof document.documentElement.scrollLeft &&
297
+ "undefined" != typeof document.body.scrollTop && "undefined" != typeof document.documentElement.scrollTop ) {
298
+ pos_x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
299
+ pos_y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
300
+ }
301
+
302
+ if ( pos_x > 0 && pos_y > 0 ) {
303
+ position = pos_x + "," + pos_y;
304
+ }
305
+
306
+ // Event description and button pressed
307
+ event_description = e.type;
308
+ if ( "click" != e.type && "undefined" != typeof e.which ) {
309
+ if ( "keypress" == e.type ){
310
+ event_description += '; keypress:' + String.fromCharCode( parseInt( e.which ) );
311
+ }
312
+ else{
313
+ event_description += '; which:' + e.which;
314
+ }
315
+ }
316
+
317
+ // Custom description for this event
318
+ if ( "undefined" != typeof note && note ){
319
+ note_array.push( note );
320
+ }
321
+
322
+ note_string = SlimStat._base64_encode( note_array.join( ", " ) );
323
+ requested_op = "update";
324
+
325
+ if ( 1 == type ) {
326
+ resource_url = SlimStat._base64_encode( resource_url.substring( resource_url.indexOf( location.hostname ) + location.hostname.length ) );
327
+ requested_op = "add";
328
+ }
329
+ else{
330
+ resource_url = SlimStat._base64_encode( resource_url );
331
+ }
332
+
333
+ SlimStat.send_to_server( "action=slimtrack&op=" + requested_op + "&id=" + SlimStat._id + "&ty=" + type + "&ref=" + SlimStat._base64_encode( document.referrer ) + "&res=" + resource_url + "&pos=" + position + "&des=" + SlimStat._base64_encode( event_description ) + "&no=" + note_string, callback );
334
+
335
+ return true;
336
  },
337
+
338
+ add_event : function ( obj, type, fn ) {
339
+ if ( obj && obj.addEventListener ) {
340
+ obj.addEventListener( type, fn, false );
341
+ }
342
+ else if ( obj && obj.attachEvent ) {
343
+ obj[ "e" + type + fn ] = fn;
344
+ obj[ type + fn ] = function() { obj[ "e" + type + fn ] ( window.event ); }
345
+ obj.attachEvent( "on"+type, obj[type+fn] );
346
+ }
347
+ else {
348
+ obj[ "on" + type ] = obj[ "e" + type + fn ];
349
+ }
350
+ },
351
+
352
+ event_fire : function ( obj, evt ) {
353
+ var fire_on_this = obj;
354
+
355
+ if ( document.createEvent ) {
356
+ var ev_obj = document.createEvent( 'MouseEvents' );
357
+ ev_obj.initEvent( evt, true, false );
358
+ fire_on_this.dispatchEvent( ev_obj );
359
+ }
360
+ else if ( document.createEventObject ) {
361
+ var ev_obj = document.createEventObject();
362
+ fire_on_this.fireEvent( 'on' + evt, ev_obj );
363
+ }
364
+ },
365
+
366
+ in_array : function ( needle, haystack ) {
367
+ for ( var i = 0; i < haystack.length; i++ ) {
368
+ if ( haystack[ i ].trim() == needle ) {
369
+ return true;
370
+ }
371
+ }
372
+ return false;
373
+ },
374
+
375
+ in_array_substring : function ( needle, haystack_of_substrings ) {
376
+ for ( var i = 0; i < haystack_of_substrings.length; i++ ) {
377
+ if ( needle.indexOf( haystack_of_substrings[ i ].trim() ) != -1 ) {
378
+ return true;
379
+ }
380
+ }
381
+ return false;
382
+ }
383
  };
384
+
385
+ SlimStat.add_event( window, "load", function() {
386
+ if ( "undefined" == typeof SlimStatParams.disable_outbound_tracking ) {
387
+ all_links = document.getElementsByTagName( "a" );
388
+ var extensions_to_track = ( "undefined" != typeof SlimStatParams.extensions_to_track && SlimStatParams.extensions_to_track ) ? SlimStatParams.extensions_to_track.split( ',' ) : [];
389
+ var to_ignore = ( "undefined" != typeof SlimStatParams.outbound_classes_rel_href_to_ignore && SlimStatParams.outbound_classes_rel_href_to_ignore ) ? SlimStatParams.outbound_classes_rel_href_to_ignore.split( ',' ) : [];
390
+ var to_not_track = ( "undefined" != typeof SlimStatParams.outbound_classes_rel_href_to_not_track && SlimStatParams.outbound_classes_rel_href_to_not_track ) ? SlimStatParams.outbound_classes_rel_href_to_not_track.split( ',' ) : [];
391
+
392
+ for (var i = 0; i < all_links.length; i++) {
393
+ // We need a closure to keep track of some variables and carry them thorughout the process
394
+ (function() {
395
+ var cur_link = all_links[i];
396
+
397
+ // Types
398
+ // 0: external
399
+ // 1: download
400
+ // 2: internal
401
+
402
+ cur_link.slimstat_actual_click = false;
403
+ cur_link.slimstat_type = ( cur_link.href && ( cur_link.hostname == location.hostname || cur_link.href.indexOf('://') == -1 ) ) ? 2 : 0;
404
+ cur_link.slimstat_track_me = true;
405
+ cur_link.slimstat_callback = true;
406
+
407
+ // Track other internal links?
408
+ if ( 2 == cur_link.slimstat_type && ( "undefined" == typeof SlimStatParams.track_internal_links || "false" == SlimStatParams.track_internal_links ) ) {
409
+ cur_link.slimstat_track_me = false;
410
+ }
411
+
412
+ // Do not invoke the callback or don't track links with given classes
413
+ if (cur_link.slimstat_track_me && (to_ignore.length > 0 || to_not_track.length > 0)) {
414
+ classes_current_link = ( "undefined" != typeof cur_link.className && cur_link.className ) ? cur_link.className.split(" ") : [];
415
+
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;
419
+ }
420
+ if ( SlimStat.in_array_substring( classes_current_link[ cl ], to_not_track ) ) {
421
+ cur_link.slimstat_track_me = false;
422
+ break;
423
+ }
424
+ }
425
+ }
426
+
427
+ // Do not invoke the callback on links with given rel
428
+ if ( cur_link.slimstat_track_me && "undefined" != typeof cur_link.attributes.rel && cur_link.attributes.rel.value ) {
429
+ if ( SlimStat.in_array_substring( cur_link.attributes.rel.value, to_ignore ) ) {
430
+ cur_link.slimstat_callback = false;
431
+ }
432
+ if ( SlimStat.in_array_substring( cur_link.attributes.rel.value, to_not_track ) ) {
433
+ cur_link.slimstat_track_me = false;
434
+ }
435
+ }
436
+
437
+ // Do not invoke the callback on links with given href
438
+ if ( cur_link.slimstat_track_me && "undefined" != typeof cur_link.href && cur_link.href ) {
439
+ if ( SlimStat.in_array_substring( cur_link.href, to_ignore ) ) {
440
+ cur_link.slimstat_callback = false;
441
+ }
442
+ if ( SlimStat.in_array_substring( cur_link.href, to_not_track ) ) {
443
+ cur_link.slimstat_track_me = false;
444
+ }
445
+ }
446
+
447
+ // Track downloads (internal)
448
+ if ( extensions_to_track.length > 0 && 2 == cur_link.slimstat_type && cur_link.pathname.indexOf('.') > 0 ) {
449
+ extension_current_link = cur_link.pathname.split('.').pop().replace(/[\/\-]/g, '');
450
+ cur_link.slimstat_track_me = SlimStat.in_array( extension_current_link, extensions_to_track );
451
+ cur_link.slimstat_type = 1;
452
+ }
453
+
454
+ // Do not invoke the callback on links that open a new window
455
+ if (cur_link.slimstat_track_me && cur_link.target && !cur_link.target.match(/^_(self|parent|top)$/i)){
456
+ cur_link.slimstat_callback = false;
457
+ }
458
+
459
+ // Set attributes in source code
460
+ cur_link.setAttribute("data-slimstat-tracking", cur_link.slimstat_track_me);
461
+ cur_link.setAttribute("data-slimstat-callback", cur_link.slimstat_callback);
462
+ cur_link.setAttribute("data-slimstat-type", cur_link.slimstat_type);
463
+
464
+ SlimStat.add_event(cur_link, "click", function(e) {
465
+
466
+ if (this.slimstat_track_me && !this.slimstat_actual_click){
467
+ if (this.slimstat_callback){
468
+ if ("function" == typeof e.preventDefault) {
469
+ e.preventDefault();
470
+ }
471
+ this.slimstat_actual_click = true;
472
+ SlimStat.ss_track(e, this.slimstat_type, "", function() {
473
+ SlimStat.event_fire(cur_link, 'click');
474
+ });
475
+ }
476
+ else{
477
+ SlimStat.ss_track(e, this.slimstat_type, "", function() {});
478
+ }
479
+ }
480
+ });
481
+ })();
482
+ }
483
  }
484
+ } );
485
+
486
  var slimstat_data = "action=slimtrack";
487
+ if ( "undefined" != typeof SlimStatParams.id && parseInt( SlimStatParams.id ) > 0 ) {
488
+ slimstat_data += "&op=update&id=" + SlimStatParams.id;
489
+ }
490
+ else if ( "undefined" != typeof SlimStatParams.ci ) {
491
+ slimstat_data += "&op=add&id=" + SlimStatParams.ci + "&ref=" + SlimStat._base64_encode( document.referrer ) + "&res=" + SlimStat._base64_encode( window.location.href );
492
+ }
493
+
494
+ // Gathers all the information and sends it to the server
495
+ if ( slimstat_data.length ) {
496
+ SlimStat.add_event( window, 'load', function(){
497
+ setTimeout( function(){
498
+ SlimStat.send_to_server(slimstat_data);
499
+ }, 0 );
500
+ } );
501
+ }
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,i="";for(e=e.replace(/\r\n/g,"\n"),t=0;t<e.length;t++)n=e.charCodeAt(t),128>n?i+=String.fromCharCode(n):n>127&&2048>n?(i+=String.fromCharCode(n>>6|192),i+=String.fromCharCode(63&n|128)):(i+=String.fromCharCode(n>>12|224),i+=String.fromCharCode(n>>6&63|128),i+=String.fromCharCode(63&n|128));return i},_base64_encode:function(e){var t,n,i,a,r,s,o,l="",d=0;for(e=SlimStat._utf8_encode(e);d<e.length;)t=e.charCodeAt(d++),n=e.charCodeAt(d++),i=e.charCodeAt(d++),a=t>>2,r=(3&t)<<4|n>>4,s=(15&n)<<2|i>>6,o=63&i,isNaN(n)?s=o=64:isNaN(i)&&(o=64),l=l+SlimStat._base64_key_str.charAt(a)+SlimStat._base64_key_str.charAt(r)+SlimStat._base64_key_str.charAt(s)+this._base64_key_str.charAt(o);return l},_detect_single_plugin_not_ie:function(e){var t,n,i,a;for(i in navigator.plugins){t=""+navigator.plugins[i].name+navigator.plugins[i].description,n=0;for(a in SlimStat._plugins[e].substrings)-1!=t.indexOf(SlimStat._plugins[e].substrings[a])&&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.push(e);return t.join(",")},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}return slimstat_data_with_client_info=e+"&sw="+screen.width+"&sh="+screen.height+"&bw="+window.innerWidth+"&bh="+window.innerHeight+"&sl="+SlimStat.get_server_latency()+"&pp="+SlimStat.get_page_performance()+"&pl="+SlimStat.detect_plugins(),request?(request.open("POST",SlimStatParams.ajaxurl,!0),request.setRequestHeader("Content-type","application/x-www-form-urlencoded"),request.send(slimstat_data_with_client_info),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):!1},ss_track:function(e,t,n,i){if(e||(e=window.event),type="undefined"==typeof t?0:parseInt(t),note_array=[],parsed_id=parseInt(SlimStat._id),isNaN(parsed_id)||parsed_id<=0)return"function"==typeof i&&i(),!1;if(node="undefined"!=typeof e.target?e.target:"undefined"!=typeof e.srcElement?e.srcElement:!1,!node)return"function"==typeof i&&i(),!1;switch(3==node.nodeType&&(node=node.parentNode),parent_node=node.parentNode,resource_url="",node.nodeName){case"FORM":node.action.length>0&&(resource_url=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){resource_url=parent_node.action;break}default:if("A"!=node.nodeName){if("function"==typeof node.getAttribute&&"undefined"!=node.getAttribute("id")&&node.getAttribute("id").length){resource_url=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?resource_url=node.hash:"undefined"!=typeof node.href&&(resource_url=node.href),"function"==typeof node.getAttribute&&("undefined"!=typeof node.getAttribute("title")&&null!=node.getAttribute("title")&&node.getAttribute("title").length>0&&note_array.push("Title:"+node.getAttribute("title")),"undefined"!=typeof node.getAttribute("id")&&null!=node.getAttribute("id")&&node.getAttribute("id").length>0&&note_array.push("ID:"+node.getAttribute("id")))}return pos_x=-1,pos_y=-1,position="","undefined"!=typeof e.pageX&&"undefined"!=typeof e.pageY?(pos_x=e.pageX,pos_y=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,pos_y=e.clientY+document.body.scrollTop+document.documentElement.scrollTop),pos_x>0&&pos_y>0&&(position=pos_x+","+pos_y),event_description=e.type,"click"!=e.type&&"undefined"!=typeof e.which&&(event_description+="keypress"==e.type?"; keypress:"+String.fromCharCode(parseInt(e.which)):"; which:"+e.which),"undefined"!=typeof n&&n.length>0&&note_array.push(n),note_string=SlimStat._base64_encode(note_array.join(", ")),requested_op="update",1==type&&(resource_url=SlimStat._base64_encode(resource_url.substring(resource_url.indexOf(location.hostname)+location.hostname.length)),requested_op="add"),SlimStat.send_to_server("action=slimtrack&op="+requested_op+"&id="+SlimStat._id+"&ty="+type+"&ref="+SlimStat._base64_encode(document.referrer)+"&res="+SlimStat._base64_encode(resource_url)+"&pos="+position+"&des="+SlimStat._base64_encode(event_description)+"&no="+note_string,i),!0},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 i=document.createEvent("MouseEvents");i.initEvent(t,!0,!1),n.dispatchEvent(i)}else if(document.createEventObject){var i=document.createEventObject();n.fireEvent("on"+t,i)}},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(","):[],i=0;i<all_links.length;i++)!function(){var a=all_links[i];if(a.slimstat_actual_click=!1,a.slimstat_type=!a.href||a.hostname!=location.hostname&&-1!=a.href.indexOf("://")?0:2,a.slimstat_track_me=!0,a.slimstat_callback=!0,2!=a.slimstat_type||"undefined"!=typeof SlimStatParams.track_internal_links&&"false"!=SlimStatParams.track_internal_links||(a.slimstat_track_me=!1),a.slimstat_track_me&&(t.length>0||n.length>0)){classes_current_link="undefined"!=typeof a.className&&a.className.length>0?a.className.split(" "):[];for(var r=0;r<classes_current_link.length;r++)if(SlimStat.in_array_substring(classes_current_link[r],t)&&(a.slimstat_callback=!1),SlimStat.in_array_substring(classes_current_link[r],n)){a.slimstat_track_me=!1;break}a.slimstat_track_me&&"undefined"!=typeof a.attributes.rel&&a.attributes.rel.value.length>0&&(SlimStat.in_array_substring(a.attributes.rel.value,t)&&(a.slimstat_callback=!1),SlimStat.in_array_substring(a.attributes.rel.value,n)&&(a.slimstat_track_me=!1)),a.slimstat_track_me&&"undefined"!=typeof a.href&&a.href.length>0&&(SlimStat.in_array_substring(a.href,t)&&(a.slimstat_callback=!1),SlimStat.in_array_substring(a.href,n)&&(a.slimstat_track_me=!1))}e.length>0&&2==a.slimstat_type&&a.pathname.indexOf(".")>0&&(extension_current_link=a.pathname.split(".").pop().replace(/[\/\-]/g,""),a.slimstat_track_me=SlimStat.in_array(extension_current_link,e),a.slimstat_type=1),a.slimstat_track_me&&a.target&&!a.target.match(/^_(self|parent|top)$/i)&&(a.slimstat_callback=!1),a.setAttribute("data-slimstat-tracking",a.slimstat_track_me),a.setAttribute("data-slimstat-callback",a.slimstat_callback),SlimStat.add_event(a,"click",function(e){this.slimstat_track_me&&!this.slimstat_actual_click&&(this.slimstat_callback?("function"==typeof e.preventDefault&&e.preventDefault(),this.slimstat_actual_click=!0,SlimStat.ss_track(e,this.slimstat_type,"",function(){SlimStat.event_fire(a,"click")})):SlimStat.ss_track(e,this.slimstat_type,"",function(){}))})}()}});var slimstat_data="action=slimtrack";"undefined"!=typeof SlimStatParams.id&&parseInt(SlimStatParams.id)>0?slimstat_data+="&op=update&id="+SlimStatParams.id:"undefined"!=typeof SlimStatParams.ci&&(slimstat_data+="&op=add&id="+SlimStatParams.ci+"&ref="+SlimStat._base64_encode(document.referrer)+"&res="+SlimStat._base64_encode(window.location.href)),slimstat_data.length&&SlimStat.add_event(window,"load",function(){setTimeout(function(){SlimStat.send_to_server(slimstat_data)},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,s,o,l="",_=0;for(e=SlimStat._utf8_encode(e);_<e.length;)t=e.charCodeAt(_++),n=e.charCodeAt(_++),a=e.charCodeAt(_++),i=t>>2,r=(3&t)<<4|n>>4,s=(15&n)<<2|a>>6,o=63&a,isNaN(n)?s=o=64:isNaN(a)&&(o=64),l=l+SlimStat._base64_key_str.charAt(i)+SlimStat._base64_key_str.charAt(r)+SlimStat._base64_key_str.charAt(s)+this._base64_key_str.charAt(o);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.push(e);return t.join(",")},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}return slimstat_data_with_client_info=e+"&sw="+screen.width+"&sh="+screen.height+"&bw="+window.innerWidth+"&bh="+window.innerHeight+"&sl="+SlimStat.get_server_latency()+"&pp="+SlimStat.get_page_performance()+"&pl="+SlimStat.detect_plugins(),request?(request.open("POST",SlimStatParams.ajaxurl,!0),request.setRequestHeader("Content-type","application/x-www-form-urlencoded"),request.send(slimstat_data_with_client_info),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):!1},ss_track:function(e,t,n,a){if(e=e?e:window.event,type="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,resource_url="",node.nodeName){case"FORM":"undefined"!=typeof node.action&&node.action&&(resource_url=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){resource_url=parent_node.action;break}default:if("A"!=node.nodeName)for(;"undefined"!=typeof node.parentNode&&null!=node.parentNode&&"A"!=node.nodeName&&"BODY"!=node.nodeName;)node=node.parentNode;"undefined"!=typeof node.hash&&node.hash&&node.hostname==location.hostname?resource_url=node.hash:"undefined"!=typeof node.href&&(resource_url=node.href),"function"==typeof node.getAttribute&&("undefined"!=typeof node.getAttribute("title")&&node.getAttribute("title")&&note_array.push("Title:"+node.getAttribute("title")),"undefined"!=typeof node.getAttribute("id")&&node.getAttribute("id")&&note_array.push("ID:"+node.getAttribute("id")))}return pos_x=-1,pos_y=-1,position="","undefined"!=typeof e.pageX&&"undefined"!=typeof e.pageY?(pos_x=e.pageX,pos_y=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,pos_y=e.clientY+document.body.scrollTop+document.documentElement.scrollTop),pos_x>0&&pos_y>0&&(position=pos_x+","+pos_y),event_description=e.type,"click"!=e.type&&"undefined"!=typeof e.which&&(event_description+="keypress"==e.type?"; keypress:"+String.fromCharCode(parseInt(e.which)):"; which:"+e.which),"undefined"!=typeof n&&n&&note_array.push(n),note_string=SlimStat._base64_encode(note_array.join(", ")),requested_op="update",1==type?(resource_url=SlimStat._base64_encode(resource_url.substring(resource_url.indexOf(location.hostname)+location.hostname.length)),requested_op="add"):resource_url=SlimStat._base64_encode(resource_url),SlimStat.send_to_server("action=slimtrack&op="+requested_op+"&id="+SlimStat._id+"&ty="+type+"&ref="+SlimStat._base64_encode(document.referrer)+"&res="+resource_url+"&pos="+position+"&des="+SlimStat._base64_encode(event_description)+"&no="+note_string,a),!0},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?SlimStatParams.extensions_to_track.split(","):[],t="undefined"!=typeof SlimStatParams.outbound_classes_rel_href_to_ignore&&SlimStatParams.outbound_classes_rel_href_to_ignore?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?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,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?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&&(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&&(SlimStat.in_array_substring(i.href,t)&&(i.slimstat_callback=!1),SlimStat.in_array_substring(i.href,n)&&(i.slimstat_track_me=!1)),e.length>0&&2==i.slimstat_type&&i.pathname.indexOf(".")>0&&(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&&i.target&&!i.target.match(/^_(self|parent|top)$/i)&&(i.slimstat_callback=!1),i.setAttribute("data-slimstat-tracking",i.slimstat_track_me),i.setAttribute("data-slimstat-callback",i.slimstat_callback),i.setAttribute("data-slimstat-type",i.slimstat_type),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=!0,SlimStat.ss_track(e,this.slimstat_type,"",function(){SlimStat.event_fire(i,"click")})):SlimStat.ss_track(e,this.slimstat_type,"",function(){}))})}()}});var slimstat_data="action=slimtrack";"undefined"!=typeof SlimStatParams.id&&parseInt(SlimStatParams.id)>0?slimstat_data+="&op=update&id="+SlimStatParams.id:"undefined"!=typeof SlimStatParams.ci&&(slimstat_data+="&op=add&id="+SlimStatParams.ci+"&ref="+SlimStat._base64_encode(document.referrer)+"&res="+SlimStat._base64_encode(window.location.href)),slimstat_data.length&&SlimStat.add_event(window,"load",function(){setTimeout(function(){SlimStat.send_to_server(slimstat_data)},0)});
wp-slimstat.php CHANGED
@@ -3,15 +3,15 @@
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: 4.1.2
7
  Author: Camu
8
  Author URI: http://www.wp-slimstat.com/
9
  */
10
 
11
- if (!empty(wp_slimstat::$options)) return true;
12
 
13
- class wp_slimstat{
14
- public static $version = '4.1.2';
15
  public static $options = array();
16
 
17
  public static $wpdb = '';
@@ -202,9 +202,9 @@ class wp_slimstat{
202
  self::$stat = apply_filters('slimstat_filter_pageview_stat_init', self::$stat);
203
 
204
  // Third-party tools can decide that this pageview should not be tracked, by setting its datestamp to zero
205
- if (empty(self::$stat) || empty(self::$stat['dt'])){
206
- self::$stat['id'] = -213;
207
- self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('Pageview filtered by third-party code','wp-slimstat'), date_i18n('U'));
208
  return $_argument;
209
  }
210
 
@@ -221,7 +221,7 @@ class wp_slimstat{
221
  $referer = parse_url( self::$stat[ 'referer' ] );
222
  if ( !$referer ){
223
  self::$stat[ 'id' ] = -208;
224
- self::$options[ 'last_tracker_error' ] = array( 200, __( 'Malformed URL', 'wp-slimstat' ), date_i18n( 'U' ) );
225
  return $_argument;
226
  }
227
 
@@ -239,8 +239,8 @@ class wp_slimstat{
239
  foreach(self::string_to_array(self::$options['ignore_referers']) as $a_filter){
240
  $pattern = str_replace( array('\*', '\!') , array('(.*)', '.'), preg_quote($a_filter, '/'));
241
  if (preg_match("@^$pattern$@i", self::$stat['referer'])){
242
- self::$stat['id'] = -207;
243
- self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('Referrer is blacklisted','wp-slimstat'), date_i18n('U'));
244
  return $_argument;
245
  }
246
  }
@@ -318,26 +318,27 @@ class wp_slimstat{
318
  $pattern = str_replace( array('\*', '\!') , array('(.*)', '.'), preg_quote($a_filter, '/'));
319
  if (preg_match("@^$pattern$@i", self::$stat['resource'])){
320
  self::$stat['id'] = -209;
321
- self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('Permalink is blacklisted','wp-slimstat'), date_i18n('U'));
322
  return $_argument;
323
  }
324
  }
325
  }
326
 
327
  // User's IP address
328
- list(self::$stat['ip'], self::$stat['other_ip']) = self::_get_ip2long_remote_ip();
329
- if (empty(self::$stat['ip'])){
330
- self::$stat['id'] = -203;
331
- self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('Empty IP Address','wp-slimstat'), date_i18n('U'));
 
332
  return $_argument;
333
  }
334
 
335
  // Should we ignore this user?
336
- if (!empty($GLOBALS['current_user']->ID)){
337
  // Don't track logged-in users, if the corresponding option is enabled
338
  if (self::$options['track_users'] == 'no'){
339
  self::$stat['id'] = -214;
340
- self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('Logged in user not tracked','wp-slimstat'), date_i18n('U'));
341
  return $_argument;
342
  }
343
 
@@ -345,14 +346,14 @@ class wp_slimstat{
345
  foreach(self::string_to_array(self::$options['ignore_capabilities']) as $a_capability){
346
  if (array_key_exists(strtolower($a_capability), $GLOBALS['current_user']->allcaps)){
347
  self::$stat['id'] = -200;
348
- self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('User with given capability not tracked','wp-slimstat'), date_i18n('U'));
349
  return $_argument;
350
  }
351
  }
352
 
353
  if (is_string(self::$options['ignore_users']) && strpos(self::$options['ignore_users'], $GLOBALS['current_user']->data->user_login) !== false){
354
  self::$stat['id'] = -201;
355
- self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('User is blacklisted','wp-slimstat'), date_i18n('U'));
356
  return $_argument;
357
  }
358
 
@@ -362,11 +363,17 @@ class wp_slimstat{
362
  }
363
  elseif (isset($_COOKIE['comment_author_'.COOKIEHASH])){
364
  // Is this a spammer?
365
- $spam_comment = self::$wpdb->get_row("SELECT comment_author, COUNT(*) comment_count FROM {$GLOBALS['wpdb']->prefix}comments WHERE INET_ATON(comment_author_IP) = '".sprintf("%u", self::$stat['ip'])."' AND comment_approved = 'spam' GROUP BY comment_author LIMIT 0,1", ARRAY_A);
366
- if (isset($spam_comment['comment_count']) && $spam_comment['comment_count'] > 0){
367
- if (self::$options['ignore_spammers'] == 'yes'){
368
- self::$stat['id'] = -202;
369
- self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('Spammer not tracked','wp-slimstat'), date_i18n('U'));
 
 
 
 
 
 
370
  return $_argument;
371
  }
372
  else{
@@ -379,43 +386,52 @@ class wp_slimstat{
379
  }
380
 
381
  // Should we ignore this IP address?
382
- foreach(self::string_to_array(self::$options['ignore_ip']) as $a_ip_range){
383
- $mask = 32;
384
  $ip_to_ignore = $a_ip_range;
385
 
386
- if (strpos($ip_to_ignore, '/') !== false){
387
- list($ip_to_ignore, $mask) = @explode('/', trim($ip_to_ignore));
388
- if (empty($mask) || !is_numeric($mask)){
389
- $mask = 32;
390
- }
391
  }
392
 
393
- $long_ip_to_ignore = ip2long($ip_to_ignore);
394
- $long_mask = bindec( str_pad('', $mask, '1') . str_pad('', 32-$mask, '0') );
395
- $long_masked_user_ip = self::$stat['ip'] & $long_mask;
396
- $long_masked_other_ip = self::$stat['other_ip'] & $long_mask;
397
- $long_masked_ip_to_ignore = $long_ip_to_ignore & $long_mask;
398
- if ($long_masked_user_ip == $long_masked_ip_to_ignore || $long_masked_other_ip == $long_masked_ip_to_ignore){
399
  self::$stat['id'] = -204;
400
- self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('IP Address is blacklisted','wp-slimstat'), date_i18n('U'));
401
  return $_argument;
402
  }
403
  }
404
 
405
  // Country and Language
406
  self::$stat['language'] = self::_get_language();
407
- self::$stat['country'] = self::get_country(self::$stat['ip']);
408
 
409
  // Anonymize IP Address?
410
- if (self::$options['anonymize_ip'] == 'yes'){
411
- self::$stat['ip'] = self::$stat['ip']&4294967040;
412
- self::$stat['other_ip'] = self::$stat['other_ip']&4294967040;
 
 
 
 
 
 
 
 
 
 
 
413
  }
414
 
415
  // Is this country blacklisted?
416
- if (is_string(self::$options['ignore_countries']) && stripos(self::$options['ignore_countries'], self::$stat['country']) !== false){
417
  self::$stat['id'] = -206;
418
- self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('Country is blacklisted','wp-slimstat'), date_i18n('U'));
419
  return $_argument;
420
  }
421
 
@@ -424,7 +440,7 @@ class wp_slimstat{
424
  (isset($_SERVER['HTTP_X_PURPOSE']) && (strtolower($_SERVER['HTTP_X_PURPOSE']) == 'preview'))){
425
  if (self::$options['ignore_prefetch'] == 'yes'){
426
  self::$stat['id'] = -210;
427
- self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('Prefetch requests are ignored','wp-slimstat'), date_i18n('U'));
428
  return $_argument;
429
  }
430
  else{
@@ -438,7 +454,7 @@ class wp_slimstat{
438
  // Are we ignoring bots?
439
  if ((self::$options['javascript_mode'] == 'yes' || self::$options['ignore_bots'] == 'yes') && self::$browser['browser_type']%2 != 0){
440
  self::$stat['id'] = -211;
441
- self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('Bot not tracked','wp-slimstat'), date_i18n('U'));
442
  return $_argument;
443
  }
444
 
@@ -447,7 +463,7 @@ class wp_slimstat{
447
  $pattern = str_replace( array('\*', '\!') , array('(.*)', '.'), preg_quote($a_filter, '/'));
448
  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'])){
449
  self::$stat['id'] = -212;
450
- self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('Browser is blacklisted','wp-slimstat'), date_i18n('U'));
451
  return $_argument;
452
  }
453
  }
@@ -464,16 +480,10 @@ class wp_slimstat{
464
  // Third-party tools can decide that this pageview should not be tracked, by setting its datestamp to zero
465
  if (empty(self::$stat) || empty(self::$stat['dt'])){
466
  self::$stat['id'] = -213;
467
- self::$options['last_tracker_error'] = array(abs(self::$stat['id']), __('Pageview filtered by third-party code','wp-slimstat'), date_i18n('U'));
468
  return $_argument;
469
  }
470
 
471
- // Because PHP's integer type is signed, and many IP addresses will result in negative integers on 32-bit architectures, we need to use the "%u" formatter
472
- if (!empty(self::$stat['other_ip']) && self::$stat['other_ip'] != self::$stat['ip']){
473
- self::$stat['other_ip'] = sprintf("%u", self::$stat['other_ip']);
474
- }
475
- self::$stat['ip'] = sprintf("%u", self::$stat['ip']);
476
-
477
  // Implode the notes
478
  self::$stat['notes'] = implode(';', self::$stat['notes']);
479
 
@@ -483,8 +493,8 @@ class wp_slimstat{
483
  // Something went wrong during the insert
484
  if (empty(self::$stat['id'])){
485
  self::$stat['id'] = -215;
486
- self::$options['last_tracker_error'] = array(abs(self::$stat['id']), self::$wpdb->last_error, date_i18n('U'));
487
-
488
  // Attempt to init the environment (new blog in a MU network?)
489
  include_once(WP_PLUGIN_DIR.'/wp-slimstat/admin/wp-slimstat-admin.php');
490
  wp_slimstat_admin::init_environment(true);
@@ -510,8 +520,8 @@ class wp_slimstat{
510
  /**
511
  * Searches for the country code associated to a given IP address
512
  */
513
- public static function get_country($_ipnum = 0){
514
- $float_ipnum = (float)sprintf("%u", $_ipnum);
515
  $country_output = 'xx';
516
 
517
  // Is this a RFC1918 (local) IP?
@@ -535,7 +545,7 @@ class wp_slimstat{
535
  add_action('shutdown', array(__CLASS__, 'download_maxmind_database'));
536
 
537
  if (false === ($handle = fopen(self::$maxmind_path, "rb"))){
538
- return apply_filters('slimstat_get_country', 'xx', $_ipnum);
539
  }
540
  }
541
  }
@@ -553,7 +563,7 @@ class wp_slimstat{
553
  }
554
  }
555
 
556
- if ($_ipnum & (1 << $depth)) {
557
  if ($x[1] >= 16776960 && !empty($country_codes[$x[1] - 16776960])) {
558
  $country_output = $country_codes[$x[1] - 16776960];
559
  break;
@@ -571,7 +581,7 @@ class wp_slimstat{
571
  }
572
  }
573
 
574
- return apply_filters('slimstat_get_country', $country_output, $_ipnum);
575
  }
576
  // end get_country
577
 
@@ -594,37 +604,37 @@ class wp_slimstat{
594
  /**
595
  * Tries to find the user's REAL IP address
596
  */
597
- protected static function _get_ip2long_remote_ip(){
598
- $long_ip = array(0, 0);
599
 
600
- if (isset($_SERVER["REMOTE_ADDR"]) && filter_var($_SERVER["REMOTE_ADDR"], FILTER_VALIDATE_IP) !== false){
601
- $long_ip[0] = ip2long($_SERVER["REMOTE_ADDR"]);
602
  }
603
 
604
- if (isset($_SERVER["HTTP_CLIENT_IP"]) && filter_var($_SERVER["HTTP_CLIENT_IP"], FILTER_VALIDATE_IP) !== false){
605
- $long_ip[1] = ip2long($_SERVER["HTTP_CLIENT_IP"]);
606
  }
607
 
608
- if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])){
609
- foreach (explode(",",$_SERVER["HTTP_X_FORWARDED_FOR"]) as $a_ip){
610
- if (filter_var($a_ip, FILTER_VALIDATE_IP) !== false){
611
- $long_ip[1] = ip2long($a_ip);
612
  break;
613
  }
614
  }
615
  }
616
 
617
- if (isset($_SERVER["HTTP_FORWARDED"]) && filter_var($_SERVER["HTTP_FORWARDED"], FILTER_VALIDATE_IP) !== false){
618
- $long_ip[1] = ip2long($_SERVER["HTTP_FORWARDED"]);
619
  }
620
 
621
- if (isset($_SERVER["HTTP_X_FORWARDED"]) && filter_var($_SERVER["HTTP_X_FORWARDED"], FILTER_VALIDATE_IP) !== false){
622
- $long_ip[1] = ip2long($_SERVER["HTTP_X_FORWARDED"]);
623
  }
624
 
625
- return $long_ip;
626
  }
627
- // end _get_ip2long_remote_ip
628
 
629
  /**
630
  * Extracts the accepted language from browser headers
@@ -1090,7 +1100,8 @@ class wp_slimstat{
1090
  // Do we have an id for this request?
1091
  if ( empty( self::$data_js[ 'id' ] ) || empty( self::$data_js[ 'op' ] ) ) {
1092
  do_action( 'slimstat_track_exit_102' );
1093
- self::$options[ 'last_tracker_error' ] = array( 102, __( 'Invalid payload string', 'wp-slimstat' ), date_i18n( 'U' ) );
 
1094
  self::slimstat_save_options();
1095
  exit('-102.0');
1096
  }
@@ -1099,7 +1110,8 @@ class wp_slimstat{
1099
  list(self::$data_js['id'], $nonce) = explode('.', self::$data_js['id']);
1100
  if ($nonce !== md5(self::$data_js['id'].self::$options['secret'])){
1101
  do_action('slimstat_track_exit_103');
1102
- self::$options['last_tracker_error'] = array(103, __('Invalid data signature','wp-slimstat'), date_i18n('U'));
 
1103
  self::slimstat_save_options();
1104
  exit('-103.0');
1105
  }
@@ -1157,6 +1169,40 @@ class wp_slimstat{
1157
  return 0;
1158
  }
1159
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1160
  /**
1161
  * Opens given domains during CORS requests to admin-ajax.php
1162
  */
@@ -1315,11 +1361,7 @@ class wp_slimstat{
1315
  break;
1316
 
1317
  case 'hostname':
1318
- $output[ $result_idx ][ $a_column ] .= gethostbyaddr( long2ip( $a_result[ 'ip' ] ) );
1319
- break;
1320
-
1321
- case 'ip':
1322
- $output[ $result_idx ][ $a_column ] .= long2ip( $a_result['ip'] );
1323
  break;
1324
 
1325
  case 'count':
@@ -1445,7 +1487,7 @@ class wp_slimstat{
1445
  'enable_ads_network' => 'null',
1446
 
1447
  // Maintenance
1448
- 'last_tracker_error' => array(0, '', date_i18n('U')),
1449
 
1450
  // Network-wide Settings
1451
  'locked_options' => ''
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: 4.1.3
7
  Author: Camu
8
  Author URI: http://www.wp-slimstat.com/
9
  */
10
 
11
+ if ( !empty( wp_slimstat::$options ) ) return true;
12
 
13
+ class wp_slimstat {
14
+ public static $version = '4.1.3';
15
  public static $options = array();
16
 
17
  public static $wpdb = '';
202
  self::$stat = apply_filters('slimstat_filter_pageview_stat_init', self::$stat);
203
 
204
  // Third-party tools can decide that this pageview should not be tracked, by setting its datestamp to zero
205
+ if ( empty( self::$stat ) || empty( self::$stat[ 'dt' ] ) ) {
206
+ self::$stat[ 'id' ] = -213;
207
+ self::_set_error_array( __( 'Pageview filtered by third-party code', 'wp-slimstat' ) );
208
  return $_argument;
209
  }
210
 
221
  $referer = parse_url( self::$stat[ 'referer' ] );
222
  if ( !$referer ){
223
  self::$stat[ 'id' ] = -208;
224
+ self::_set_error_array( __( 'Malformed URL', 'wp-slimstat' ) );
225
  return $_argument;
226
  }
227
 
239
  foreach(self::string_to_array(self::$options['ignore_referers']) as $a_filter){
240
  $pattern = str_replace( array('\*', '\!') , array('(.*)', '.'), preg_quote($a_filter, '/'));
241
  if (preg_match("@^$pattern$@i", self::$stat['referer'])){
242
+ self::$stat[ 'id' ] = -207;
243
+ self::_set_error_array( __( 'Referrer is blacklisted', 'wp-slimstat') );
244
  return $_argument;
245
  }
246
  }
318
  $pattern = str_replace( array('\*', '\!') , array('(.*)', '.'), preg_quote($a_filter, '/'));
319
  if (preg_match("@^$pattern$@i", self::$stat['resource'])){
320
  self::$stat['id'] = -209;
321
+ self::_set_error_array( __( 'Permalink is blacklisted', 'wp-slimstat' ) );
322
  return $_argument;
323
  }
324
  }
325
  }
326
 
327
  // User's IP address
328
+ list ( self::$stat[ 'ip' ], self::$stat[ 'other_ip' ] ) = self::_get_remote_ip();
329
+
330
+ if ( empty( self::$stat[ 'ip' ] ) || self::$stat[ 'ip' ] == '0.0.0.0' ) {
331
+ self::$stat[ 'id' ] = -203;
332
+ self::_set_error_array( __( 'Empty or not supported IP address format (IPv6)', 'wp-slimstat' ) );
333
  return $_argument;
334
  }
335
 
336
  // Should we ignore this user?
337
+ if ( !empty( $GLOBALS[ 'current_user' ]->ID ) ) {
338
  // Don't track logged-in users, if the corresponding option is enabled
339
  if (self::$options['track_users'] == 'no'){
340
  self::$stat['id'] = -214;
341
+ self::_set_error_array( __( 'Logged in user not tracked', 'wp-slimstat' ) );
342
  return $_argument;
343
  }
344
 
346
  foreach(self::string_to_array(self::$options['ignore_capabilities']) as $a_capability){
347
  if (array_key_exists(strtolower($a_capability), $GLOBALS['current_user']->allcaps)){
348
  self::$stat['id'] = -200;
349
+ self::_set_error_array( __( 'User with given capability not tracked', 'wp-slimstat' ) );
350
  return $_argument;
351
  }
352
  }
353
 
354
  if (is_string(self::$options['ignore_users']) && strpos(self::$options['ignore_users'], $GLOBALS['current_user']->data->user_login) !== false){
355
  self::$stat['id'] = -201;
356
+ self::_set_error_array( sprintf( __('User %s is blacklisted', 'wp-slimstat'), $GLOBALS['current_user']->data->user_login ) );
357
  return $_argument;
358
  }
359
 
363
  }
364
  elseif (isset($_COOKIE['comment_author_'.COOKIEHASH])){
365
  // Is this a spammer?
366
+ $spam_comment = self::$wpdb->get_row( self::$wpdb->prepare( "
367
+ SELECT comment_author, COUNT(*) comment_count
368
+ FROM {$GLOBALS['wpdb']->prefix}comments
369
+ WHERE comment_author_IP = %s AND comment_approved = 'spam'
370
+ GROUP BY comment_author
371
+ LIMIT 0,1", self::$stat[ 'ip' ] ), ARRAY_A );
372
+
373
+ if ( !empty( $spam_comment[ 'comment_count' ] ) ) {
374
+ if ( self::$options[ 'ignore_spammers' ] == 'yes' ){
375
+ self::$stat[ 'id' ] = -202;
376
+ self::_set_error_array( sprintf( __( 'Spammer %s not tracked', 'wp-slimstat' ), $spam_comment[ 'comment_author' ] ) );
377
  return $_argument;
378
  }
379
  else{
386
  }
387
 
388
  // Should we ignore this IP address?
389
+ foreach ( self::string_to_array( self::$options[ 'ignore_ip' ] ) as $a_ip_range ) {
 
390
  $ip_to_ignore = $a_ip_range;
391
 
392
+ if ( strpos( $ip_to_ignore, '/' ) !== false ) {
393
+ list( $ip_to_ignore, $cidr_mask ) = explode( '/', trim( $ip_to_ignore ) );
394
+ }
395
+ else{
396
+ $cidr_mask = self::_get_mask_length( $ip_to_ignore );
397
  }
398
 
399
+ $long_masked_ip_to_ignore = substr( self::_dtr_pton( $ip_to_ignore ), 0, $cidr_mask );
400
+ $long_masked_user_ip = substr( self::_dtr_pton( self::$stat[ 'ip' ] ), 0, $cidr_mask );
401
+ $long_masked_user_other_ip = substr( self::_dtr_pton( self::$stat[ 'other_ip' ] ), 0 , $cidr_mask );
402
+
403
+ if ( $long_masked_user_ip === $long_masked_ip_to_ignore || $long_masked_user_other_ip === $long_masked_ip_to_ignore ) {
 
404
  self::$stat['id'] = -204;
405
+ self::_set_error_array( sprintf( __('IP address %s is blacklisted', 'wp-slimstat'), self::$stat[ 'ip' ] . ( !empty( self::$stat[ 'other_ip' ] ) ? ' (' . self::$stat[ 'other_ip' ] . ')' : '' ) ) );
406
  return $_argument;
407
  }
408
  }
409
 
410
  // Country and Language
411
  self::$stat['language'] = self::_get_language();
412
+ self::$stat['country'] = self::get_country(self::$stat[ 'ip' ]);
413
 
414
  // Anonymize IP Address?
415
+ if ( self::$options[ 'anonymize_ip' ] == 'yes' ) {
416
+ // IPv4 or IPv6
417
+ $needle = '.';
418
+ $replace = '.0';
419
+ if ( self::_get_mask_length( self::$stat['ip'] ) == 128 ) {
420
+ $needle = ':';
421
+ $replace = ':0000';
422
+ }
423
+
424
+ self::$stat[ 'ip' ] = substr( self::$stat[ 'ip' ], 0, strrpos( self::$stat[ 'ip' ], $needle ) ) . $replace;
425
+
426
+ if ( !empty( self::$stat[ 'other_ip' ] ) ) {
427
+ self::$stat[ 'other_ip' ] = substr( self::$stat[ 'other_ip' ], 0, strrpos( self::$stat[ 'other_ip' ], $needle ) ) . $replace;
428
+ }
429
  }
430
 
431
  // Is this country blacklisted?
432
+ if ( is_string( self::$options[ 'ignore_countries' ] ) && stripos( self::$options[ 'ignore_countries' ], self::$stat[ 'country' ] ) !== false ) {
433
  self::$stat['id'] = -206;
434
+ self::_set_error_array( sprintf( __('Country %s is blacklisted', 'wp-slimstat'), self::$stat[ 'country' ] ) );
435
  return $_argument;
436
  }
437
 
440
  (isset($_SERVER['HTTP_X_PURPOSE']) && (strtolower($_SERVER['HTTP_X_PURPOSE']) == 'preview'))){
441
  if (self::$options['ignore_prefetch'] == 'yes'){
442
  self::$stat['id'] = -210;
443
+ self::_set_error_array( __( 'Prefetch requests are ignored', 'wp-slimstat' ) );
444
  return $_argument;
445
  }
446
  else{
454
  // Are we ignoring bots?
455
  if ((self::$options['javascript_mode'] == 'yes' || self::$options['ignore_bots'] == 'yes') && self::$browser['browser_type']%2 != 0){
456
  self::$stat['id'] = -211;
457
+ self::_set_error_array( __( 'Bot not tracked', 'wp-slimstat' ) );
458
  return $_argument;
459
  }
460
 
463
  $pattern = str_replace( array('\*', '\!') , array('(.*)', '.'), preg_quote($a_filter, '/'));
464
  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'])){
465
  self::$stat['id'] = -212;
466
+ self::_set_error_array( sprintf( __( 'Browser %s is blacklisted', 'wp-slimstat' ), self::$browser['browser'] ) );
467
  return $_argument;
468
  }
469
  }
480
  // Third-party tools can decide that this pageview should not be tracked, by setting its datestamp to zero
481
  if (empty(self::$stat) || empty(self::$stat['dt'])){
482
  self::$stat['id'] = -213;
483
+ self::_set_error_array( __( 'Pageview filtered by third-party code', 'wp-slimstat' ) );
484
  return $_argument;
485
  }
486
 
 
 
 
 
 
 
487
  // Implode the notes
488
  self::$stat['notes'] = implode(';', self::$stat['notes']);
489
 
493
  // Something went wrong during the insert
494
  if (empty(self::$stat['id'])){
495
  self::$stat['id'] = -215;
496
+ self::_set_error_array( self::$wpdb->last_error );
497
+
498
  // Attempt to init the environment (new blog in a MU network?)
499
  include_once(WP_PLUGIN_DIR.'/wp-slimstat/admin/wp-slimstat-admin.php');
500
  wp_slimstat_admin::init_environment(true);
520
  /**
521
  * Searches for the country code associated to a given IP address
522
  */
523
+ public static function get_country( $_ip_address = '0.0.0.0' ){
524
+ $float_ipnum = (float)sprintf( "%u", $_ip_address );
525
  $country_output = 'xx';
526
 
527
  // Is this a RFC1918 (local) IP?
545
  add_action('shutdown', array(__CLASS__, 'download_maxmind_database'));
546
 
547
  if (false === ($handle = fopen(self::$maxmind_path, "rb"))){
548
+ return apply_filters( 'slimstat_get_country', 'xx', $_ip_address );
549
  }
550
  }
551
  }
563
  }
564
  }
565
 
566
+ if ( !empty( $_ip_address ) & ( 1 << $depth ) ) {
567
  if ($x[1] >= 16776960 && !empty($country_codes[$x[1] - 16776960])) {
568
  $country_output = $country_codes[$x[1] - 16776960];
569
  break;
581
  }
582
  }
583
 
584
+ return apply_filters( 'slimstat_get_country', $country_output, $_ip_address );
585
  }
586
  // end get_country
587
 
604
  /**
605
  * Tries to find the user's REAL IP address
606
  */
607
+ protected static function _get_remote_ip(){
608
+ $ip_array = array( '', '' );
609
 
610
+ if ( !empty( $_SERVER[ 'REMOTE_ADDR' ] ) && filter_var( $_SERVER[ 'REMOTE_ADDR' ], FILTER_VALIDATE_IP ) !== false ) {
611
+ $ip_array[ 0 ] = $_SERVER["REMOTE_ADDR"];
612
  }
613
 
614
+ if ( !empty( $_SERVER[ 'HTTP_CLIENT_IP' ] ) && filter_var( $_SERVER[ 'HTTP_CLIENT_IP' ], FILTER_VALIDATE_IP ) !== false ) {
615
+ $ip_array[ 1 ] = $_SERVER["HTTP_CLIENT_IP"];
616
  }
617
 
618
+ if ( !empty( $_SERVER[ 'HTTP_X_FORWARDED_FOR' ] ) ) {
619
+ foreach ( explode( ',', $_SERVER[ 'HTTP_X_FORWARDED_FOR' ] ) as $a_ip ) {
620
+ if ( filter_var( $a_ip, FILTER_VALIDATE_IP ) !== false ) {
621
+ $ip_array[ 1 ] = $a_ip;
622
  break;
623
  }
624
  }
625
  }
626
 
627
+ if ( !empty( $_SERVER[ 'HTTP_FORWARDED' ] ) && filter_var( $_SERVER[ 'HTTP_FORWARDED' ], FILTER_VALIDATE_IP ) !== false ) {
628
+ $ip_array[ 1 ] = $_SERVER[ 'HTTP_FORWARDED' ];
629
  }
630
 
631
+ if ( !empty( $_SERVER[ 'HTTP_X_FORWARDED' ] ) && filter_var( $_SERVER[ 'HTTP_X_FORWARDED' ], FILTER_VALIDATE_IP ) !== false ) {
632
+ $ip_array[ 1 ] = $_SERVER[ 'HTTP_X_FORWARDED' ];
633
  }
634
 
635
+ return $ip_array;
636
  }
637
+ // end _get_remote_ip
638
 
639
  /**
640
  * Extracts the accepted language from browser headers
1100
  // Do we have an id for this request?
1101
  if ( empty( self::$data_js[ 'id' ] ) || empty( self::$data_js[ 'op' ] ) ) {
1102
  do_action( 'slimstat_track_exit_102' );
1103
+ self::$stat[ 'id' ] = -102;
1104
+ self::_set_error_array( __( 'Invalid payload string. Try clearing your WordPress cache.', 'wp-slimstat' ) );
1105
  self::slimstat_save_options();
1106
  exit('-102.0');
1107
  }
1110
  list(self::$data_js['id'], $nonce) = explode('.', self::$data_js['id']);
1111
  if ($nonce !== md5(self::$data_js['id'].self::$options['secret'])){
1112
  do_action('slimstat_track_exit_103');
1113
+ self::$stat[ 'id' ] = -102;
1114
+ self::_set_error_array( __( 'Invalid data signature. Try clearing your WordPress cache.', 'wp-slimstat' ) );
1115
  self::slimstat_save_options();
1116
  exit('-103.0');
1117
  }
1169
  return 0;
1170
  }
1171
 
1172
+ protected static function _set_error_array( $_error_message = '' ) {
1173
+ $error_code = abs( self::$stat[ 'id' ] );
1174
+ self::$options['last_tracker_error'] = array( $error_code, $_error_message, date_i18n( 'U' ) );
1175
+ }
1176
+
1177
+ protected static function _dtr_pton( $ip ){
1178
+ if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) {
1179
+ $unpacked = unpack( 'A4', inet_pton( $ip ) );
1180
+ }
1181
+ else if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
1182
+ $unpacked = unpack( 'A16', inet_pton( $ip ) );
1183
+ }
1184
+
1185
+ $binary_ip = '';
1186
+ if ( !empty( $unpacked ) ) {
1187
+ $unpacked = str_split( $unpacked[ 1 ] );
1188
+ foreach ( $unpacked as $char ) {
1189
+ $binary_ip .= str_pad( decbin( ord( $char ) ), 8, '0', STR_PAD_LEFT );
1190
+ }
1191
+ }
1192
+ return $binary_ip;
1193
+ }
1194
+
1195
+ protected static function _get_mask_length( $ip ){
1196
+ if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) {
1197
+ return 32;
1198
+ }
1199
+ else if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
1200
+ return 128;
1201
+ }
1202
+
1203
+ return false;
1204
+ }
1205
+
1206
  /**
1207
  * Opens given domains during CORS requests to admin-ajax.php
1208
  */
1361
  break;
1362
 
1363
  case 'hostname':
1364
+ $output[ $result_idx ][ $a_column ] .= gethostbyaddr( $a_result[ 'ip' ] );
 
 
 
 
1365
  break;
1366
 
1367
  case 'count':
1487
  'enable_ads_network' => 'null',
1488
 
1489
  // Maintenance
1490
+ 'last_tracker_error' => array( 0, '', 0 ),
1491
 
1492
  // Network-wide Settings
1493
  'locked_options' => ''