? connectspeed.jpg
? xstatistics.install
? xstatistics.js
? xstatistics.mysql
? xstatistics.patch
Index: README.txt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/xstatistics/README.txt,v
retrieving revision 1.3
diff -u -F^f -r1.3 README.txt
--- README.txt	17 Mar 2006 22:47:58 -0000	1.3
+++ README.txt	27 Jun 2006 16:55:57 -0000
@@ -6,6 +6,11 @@
 analyzing (what were they looking for), path-reports and other
 interesting reports.
 
+Xstatistics also gathers user information from a JavaScript that runs
+on the user's browser. This JavaScript reports operating system, screen
+resolution, various plugin and java data, and attempts to establish a 
+connection speed. The JavaScript only runs once per session for each user.
+
 NOTE: You must enable the core "statistics" module and enable the
 "Count Content Views" to get the full value out of this package.
 
Index: xstatistics.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/xstatistics/xstatistics.module,v
retrieving revision 1.8
diff -u -F^f -r1.8 xstatistics.module
--- xstatistics.module	3 Apr 2006 14:28:06 -0000	1.8
+++ xstatistics.module	27 Jun 2006 16:55:57 -0000
@@ -23,7 +23,15 @@ function xstatistics_menu($may_cache) {
     $items[] = array('title' => t('usage'),
                      'path' => 'admin/logs/usage',
                      'callback' => 'xstatistics_usage',
-                     'access' => user_access('access statistics'));
+                     'access' => user_access('access statistics'));
+    $items[] = array('path' => 'xstatistics',
+                     'callback' => 'xstatistics_javascript_reporting',
+                     'access' => user_access('access content'),
+                     'type' => MENU_CALLBACK);
+  } else {
+    if (!$_SESSION['xstatistics_reported']) {
+      $path = drupal_get_path('module', 'xstatistics');      drupal_add_js($path . '/xstatistics.js');
+    }
   }
   return $items;
 }
@@ -62,7 +70,64 @@ function xstatistics_summary() {
           array(t("People subscribed to your RSS feed"), $count_RSS_subscr['hostname'])
           );
 
-  $output = theme('table',$header, $rows);
+  $output = theme('table',$header, $rows);
+  
+  // summary stats based on JavaScript reporting
+  // first get the total users right now:
+  $result = db_query("SELECT COUNT(*) AS users FROM {xstatistics_user}");
+  
+  if ($total_row = db_fetch_object($result)) {
+  
+    $total_users = $total_row->users;
+    
+    // operating system totals
+    $operating_systems = db_query("SELECT COUNT(*) AS users, os FROM {xstatistics_user} GROUP BY os ORDER BY users DESC");
+    $os_header = array(t('Number of Visitors'), t('Percentage of Visitors'), t('Operating System'));
+    $os_rows = array();
+    while ($row = db_fetch_object($operating_systems)) {
+      $os_rows[] = array($row->users, ($row->users/$total_users) * 100, $row->os);
+    }
+    
+    $output .= theme('table', $os_header, $os_rows);
+    
+    // resolutions
+    $resolutions = db_query("SELECT COUNT(*) AS users, resx, resy FROM {xstatistics_user} GROUP BY resx, resy ORDER BY users DESC");
+    $res_header = array(t('Number of Visitors'), t('Percentage of Visitors'), t('Resolution'));
+    $res_rows = array();
+    while ($row = db_fetch_object($resolutions)) {
+      $res_rows[] = array($row->users, ($row->users/$total_users) * 100, $row->resx . "x" . $row->resy);
+    }
+    
+    $output .= theme('table', $res_header, $res_rows);
+    
+    // languages
+    $langs = db_query("SELECT COUNT(*) AS users, lang FROM {xstatistics_user} GROUP BY lang ORDER BY users DESC");
+    $lang_header = array(t('Number of Visitors'), t('Percentage of Visitors'), t('Language'));
+    $lang_rows = array();
+    while ($row = db_fetch_object($langs)) {
+      $lang_rows[] = array($row->users, ($row->users/$total_users) * 100, $row->lang);
+    }
+    
+    $output .= theme('table', $lang_header, $lang_rows);
+    
+    // plugins
+    $plugins = db_query("select sum(java) as numjava, sum(director) as numdir, sum(flash) as numfla, sum(pdf) as numpdf, sum(qt) as numqt, sum(realplayer) as numreal, sum(wma) as numwma from {xstatistics_user}");
+    $plug_row = db_fetch_object($plugins);
+    
+    $plug_header = array(t('Plugin'), t('Number of Visitors'), t('Percentage of Visitors'));
+    $plug_rows = array(
+      array(t('Java'), $plug_row->numjava, ($plug_row->numjava/$total_users) * 100),
+      array(t('Director'), $plug_row->numdir, ($plug_row->numdir/$total_users) * 100),
+      array(t('Flash'), $plug_row->numfla, ($plug_row->numfla/$total_users) * 100),
+      array(t('PDF'), $plug_row->numpdf, ($plug_row->numpdf/$total_users) * 100),
+      array(t('QuickTime'), $plug_row->numqt, ($plug_row->numqt/$total_users) * 100),
+      array(t('RealPlayer'), $plug_row->numreal, ($plug_row->numreal/$total_users) * 100),
+      array(t('WindowsMedia'), $plug_row->numwma, ($plug_row->numwma/$total_users) * 100),
+    );
+      
+    $output .= theme('table', $plug_header, $plug_rows);
+  }
+  
   print theme('page',$output);
 }
 
@@ -88,4 +153,80 @@ function xstatistics_usage() {
 
   $output = theme('table', $header, $rows);
   print theme('page', $output);
+}
+
+function xstatistics_user($op, &$edit, &$account, $category = NULL) {
+  switch($op) {
+    case 'login':
+      $_SESSION['xstatistics_reported'] = false;
+      break;
+  }
+}
+function xstatistics_javascript_reporting() {
+  /* From the xstatistics.js file :
+  
+  var geturl = xo.url + "?";
+  geturl = geturl + "&java=" + xo.enabled_java;
+  geturl = geturl + "&os=" + escape(xo.agent_os);
+  geturl = geturl + "&resx=" + xo.screen_resx;
+  geturl = geturl + "&resy=" + xo.screen_resy;
+  geturl = geturl + "&color=" + xo.color_depth;
+  geturl = geturl + "&lang=" + escape(xo.user_lang);
+  
+  geturl = geturl + "&director=" + xo.enabled_dir;
+  geturl = geturl + "&flash=" + xo.enabled_flash;
+  geturl = geturl + "&pdf=" + xo.enabled_pdf;
+  geturl = geturl + "&qt=" + xo.enabled_qt;
+  geturl = geturl + "&real=" + xo.enabled_real;
+  geturl = geturl + "&wma=" + xo.enabled_wma;
+  
+  if (xmlhttp.status == 200) {      var connectSpeed = compute_speed(xo.start, end, xo.filesize);
+      geturl = geturl + "&speed=" + connectSpeed;  }
+  
+  */
+  
+  global $user;
+  
+  db_query("INSERT INTO {xstatistics_user} (uid, timestamp, java, os, resx, resy, lang, director, flash, pdf, qt, realplayer, wma, speed) VALUES (%d, %d, %d, '%s', %d, %d, '%s', %d, %d, %d, %d, %d, %d, %d)",
+    $user->uid,
+    time(),
+    _xstatistics_boolean_to_int(filter_xss($_GET['java'])),
+    filter_xss($_GET['os']),
+    filter_xss($_GET['resx']),
+    filter_xss($_GET['resy']),
+    filter_xss($_GET['lang']),
+    _xstatistics_boolean_to_int(filter_xss($_GET['director'])),
+    _xstatistics_boolean_to_int(filter_xss($_GET['flash'])),
+    _xstatistics_boolean_to_int(filter_xss($_GET['pdf'])),
+    _xstatistics_boolean_to_int(filter_xss($_GET['qt'])),
+    _xstatistics_boolean_to_int(filter_xss($_GET['realplayer'])),
+    _xstatistics_boolean_to_int(filter_xss($_GET['wma'])),
+    filter_xss($_GET['speed']));
+    
+  $_SESSION['xstatistics_reported'] = true;
+  
+  exit(); // don't return a page, no need for that kind of overhead.
+}
+
+function xstatistics_footer() {
+
+  if (!$_SESSION['xstatistics_reported']) {
+    $mypath = drupal_get_path('module', 'xstatistics');
+    $filesize = 3676;
+    
+    $ajax_uri = url('xstatistics', NULL, NULL, true);
+    $img_uri = url("$mypath/connectspeed.jpg", 't=' . time(), NULL, true);
+    
+    $output = '<script language="javascript1.1">';
+    $output .= "if (isJsEnabled()) { var stats = new XSTAT(\"$ajax_uri\", \"$img_uri\", $filesize);"; 
+    $output .= "stats.run();";
+    $output .= "stats.send(); }";
+    $output .= '</script>';
+    
+    return $output;
+  }
+}
+
+function _xstatistics_boolean_to_int($boolstring) {
+  return $boolstring == 'true';
 }
