]> projects.mako.cc - selectricity/commitdiff
Install sitealizer stats
authorJohn Dong <jdong@mit.edu>
Tue, 28 Aug 2007 17:29:22 +0000 (13:29 -0400)
committerJohn Dong <jdong@mit.edu>
Tue, 28 Aug 2007 17:29:22 +0000 (13:29 -0400)
47 files changed:
app/controllers/site_controller.rb
config/routes.rb
public/images/sitealizer/bar.gif [new file with mode: 0644]
public/images/sitealizer/uv.png [new file with mode: 0644]
public/images/sitealizer/vh.png [new file with mode: 0644]
vendor/plugins/sitealizer/CHANGELOG [new file with mode: 0644]
vendor/plugins/sitealizer/LICENSE [new file with mode: 0644]
vendor/plugins/sitealizer/README [new file with mode: 0644]
vendor/plugins/sitealizer/Rakefile [new file with mode: 0644]
vendor/plugins/sitealizer/init.rb [new file with mode: 0644]
vendor/plugins/sitealizer/install.rb [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/assets/images/bar.gif [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/assets/images/uv.png [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/assets/images/vh.png [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/controllers/sitealizer_controller.rb [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/models/site_tracker.rb [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/views/layouts/sitealizer.rhtml [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/views/sitealizer/_browsers.rhtml [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/views/sitealizer/_daily_stats.rhtml [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/views/sitealizer/_hits_summary.rhtml [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/views/sitealizer/_hosts.rhtml [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/views/sitealizer/_keywords.rhtml [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/views/sitealizer/_languages.rhtml [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/views/sitealizer/_main_frame.rhtml [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/views/sitealizer/_monthly_hits.rhtml [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/views/sitealizer/_page_urls.rhtml [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/views/sitealizer/_platforms.rhtml [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/views/sitealizer/_referers.rhtml [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/views/sitealizer/_robots.rhtml [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/views/sitealizer/_search_engines.rhtml [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/views/sitealizer/hourly_stats.rhtml [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/views/sitealizer/index.rhtml [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/views/sitealizer/login.rhtml [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/views/sitealizer/menu.rhtml [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/views/sitealizer/referrer_stats.rhtml [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/views/sitealizer/search_stats.rhtml [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/views/sitealizer/summary.rhtml [new file with mode: 0644]
vendor/plugins/sitealizer/lib/app/views/sitealizer/visitor_info.rhtml [new file with mode: 0644]
vendor/plugins/sitealizer/lib/config.yml [new file with mode: 0644]
vendor/plugins/sitealizer/lib/last_update [new file with mode: 0644]
vendor/plugins/sitealizer/lib/sitealizer.rb [new file with mode: 0644]
vendor/plugins/sitealizer/lib/sitealizer/parser.rb [new file with mode: 0644]
vendor/plugins/sitealizer/lib/tasks/sitealizer.rake [new file with mode: 0644]
vendor/plugins/sitealizer/test/fixtures/sitealizer.yml [new file with mode: 0644]
vendor/plugins/sitealizer/test/sitealizer_controller_test.rb [new file with mode: 0644]
vendor/plugins/sitealizer/test/sitealizer_parser_test.rb [new file with mode: 0644]
vendor/plugins/sitealizer/test/test_helper.rb [new file with mode: 0644]

index 522bbb2cf4dbe3b5e26145a9040b233ac3732187..d432a03b9fb5457277d6dafc9a0660a369bd45eb 100644 (file)
@@ -3,6 +3,8 @@ class SiteController < ApplicationController
   require_dependency "user"
   require_dependency "election"
   require_dependency "account"
   require_dependency "user"
   require_dependency "election"
   require_dependency "account"
+  include Sitealizer
+  before_filter :use_sitealizer
 
   def index
     @quickvotes = QuickVote.find(:all).sort {|a,b| b.enddate <=> a.enddate}[0..1]
 
   def index
     @quickvotes = QuickVote.find(:all).sort {|a,b| b.enddate <=> a.enddate}[0..1]
index 735f5d7c92f2448bf9ba945c624652a0e0b6e67c..82474df671b63add51df0e59463c75874aaebf78 100644 (file)
@@ -12,7 +12,7 @@ ActionController::Routing::Routes.draw do |map|
   # You can have the root of your site routed by hooking up '' 
   # -- just remember to delete public/index.html.
   map.connect '', :controller => "site", :action => "index"
   # You can have the root of your site routed by hooking up '' 
   # -- just remember to delete public/index.html.
   map.connect '', :controller => "site", :action => "index"
+  map.connect '/sitealizer/:action', :controller => 'sitealizer' 
   map.connect 'quickvote/:action/:id',
                :controller => 'quickvote',
                :requirements => { :action => /(create|add_candidate|sort_candidates|my_quickvotes)/ }
   map.connect 'quickvote/:action/:id',
                :controller => 'quickvote',
                :requirements => { :action => /(create|add_candidate|sort_candidates|my_quickvotes)/ }
diff --git a/public/images/sitealizer/bar.gif b/public/images/sitealizer/bar.gif
new file mode 100644 (file)
index 0000000..41727a8
Binary files /dev/null and b/public/images/sitealizer/bar.gif differ
diff --git a/public/images/sitealizer/uv.png b/public/images/sitealizer/uv.png
new file mode 100644 (file)
index 0000000..7d39356
Binary files /dev/null and b/public/images/sitealizer/uv.png differ
diff --git a/public/images/sitealizer/vh.png b/public/images/sitealizer/vh.png
new file mode 100644 (file)
index 0000000..13e52f9
Binary files /dev/null and b/public/images/sitealizer/vh.png differ
diff --git a/vendor/plugins/sitealizer/CHANGELOG b/vendor/plugins/sitealizer/CHANGELOG
new file mode 100644 (file)
index 0000000..7ff96a8
--- /dev/null
@@ -0,0 +1,6 @@
+=== 03-20-2007: Version 1.1
+<b>NEW</b>:: Added 3 rake tasks
+<b>FIX</b>:: General bug fixes
+
+=== 03-8-2007: Version 1.0
+Initial release
\ No newline at end of file
diff --git a/vendor/plugins/sitealizer/LICENSE b/vendor/plugins/sitealizer/LICENSE
new file mode 100644 (file)
index 0000000..6b9adf6
--- /dev/null
@@ -0,0 +1,22 @@
+Copyright (c) 2007 Thiago Jackiw
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+The "Created with Sitealizer" footer text should not be removed from the 
+locations where it's currently shown (under the '/sitealizer' controller)
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/vendor/plugins/sitealizer/README b/vendor/plugins/sitealizer/README
new file mode 100644 (file)
index 0000000..4f70b35
--- /dev/null
@@ -0,0 +1,82 @@
+= Sitealizer Web Stats plugin for Rails 
+This plugin lets you track visitors, referrers, robots, search terms and more. And it shouldn’t influence your site’s performance because it only saves the basic visitor information (after every 10(default) visits) in a threaded process and all the data processing is done when viewing the stats.
+
+== Author
+Thiago Jackiw:: tjackiw at gmail dot com
+
+== Current Release
+The current stable release is v1.1 released on 03-20-2007. 
+
+== License Info
+Please refer to the LICENSE[link:files/LICENSE.html]
+
+== Installation
+On your Rails' root directory, just type
+
+  script/plugin install http://opensvn.csie.org/sitealizer
+
+and add the following line to your config/routes.rb:
+
+  map.connect '/sitealizer/:action', :controller => 'sitealizer'
+
+== Upgrading from SiteMeter
+If you had previously installed 'sitemeter' you need to run the following command after installing Sitealizer, otherwise your stats <b>will not be imported</b>:
+
+  rake sitealizer:remove_sitemeter
+
+You also need to change: 
+
+  * include SiteMeter TO Include Sitealizer
+  * before_filter :use_site_meter TO before_filter :use_sitealizer
+  * map.connect '/sitemeter/:action', :controller => 'sitemeter' TO map.connect '/sitealizer/:action', :controller => 'sitealizer'
+
+== Configuration
+There are four configuration options that can be changed under sitealizer/lib/config.yml:
+<em>access_type</em>:: Accepts <em>private</em> or <em>public</em> as the value. <em>Private</em>: you have to enter the username and password below in order to view the stats. <em>Public</em>: Anyone can view your site's stats
+<em>username</em>:: This username will be used to log in to your Sitealizer
+<em>password</em>:: This password will be used to log in to your Sitealizer
+<em>queue_size</em>:: The number of visitors in the queue before saving the stats to the DB. Default is 10. Minimum size shouldn't be under 5
+
+== Usage
+To track the visitors on your entire application, just edit your ApplicationController(application.rb):
+
+  class ApplicationController < ActionController::Base
+    include Sitealizer
+    before_filter :use_sitealizer
+  end
+
+Or to track specific controllers:
+
+  class ApplicationController < ActionController::Base
+    include Sitealizer
+  end
+
+  class MyController < ApplicationController
+    before_filter :use_sitealizer
+  end
+
+== Viewing the stats
+To view your stats just add "/sitealizer" to your main url:
+
+  http://www.example.com/sitealizer
+
+== Using Sitealizer?
+I’d like to include your site on the list below. Please send me an email (tjackiw at gmail dot com) with your site’s url.
+* www.californiabusinesslist.com
+* www.nottr.com
+* www.bacotp.com
+
+== Getting help
+You can always send me an email (tjackiw at gmail dot com) if you have any questions.
+
+== Bugs/Patches
+Please report the bugs you find by opening tickets here[https://opensvn.csie.org/traccgi/sitealizer/newticket]
+
+== Special Thanks to:
+* RubyForge (www.rubyforge.org)
+
+== Other plugins by the Author:
+* acts_as_solr (http://acts-as-solr.rubyforge.org)
+
+== Release Information
+Released under the MIT license.
\ No newline at end of file
diff --git a/vendor/plugins/sitealizer/Rakefile b/vendor/plugins/sitealizer/Rakefile
new file mode 100644 (file)
index 0000000..e9601a3
--- /dev/null
@@ -0,0 +1,22 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+desc 'Default: run unit tests.'
+task :default => :test
+
+desc 'Test the sitealizer plugin.'
+Rake::TestTask.new(:test) do |t|
+  t.libs << 'lib'
+  t.pattern = 'test/**/*_test.rb'
+  t.verbose = true
+end
+
+desc 'Generate documentation for the sitealizer plugin.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+  rdoc.rdoc_dir = 'rdoc'
+  rdoc.title    = 'Sitealizer'
+  rdoc.options << '--line-numbers' << '--inline-source'
+  rdoc.rdoc_files.include('README')
+  rdoc.rdoc_files.include('lib/**/*.rb')
+end
diff --git a/vendor/plugins/sitealizer/init.rb b/vendor/plugins/sitealizer/init.rb
new file mode 100644 (file)
index 0000000..faf44fb
--- /dev/null
@@ -0,0 +1,36 @@
+# Copyright (c) 2007 Thiago Jackiw
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+# 
+# The "Created with Sitealizer" footer text should not be removed from the 
+# locations where it's currently shown (under the '/sitealizer' controller)
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+require 'sitealizer'
+
+unless SiteTracker.table_exists?
+  ActiveRecord::Schema.create_table(SiteTracker.table_name) do |t|
+    t.column :path,           :string
+    t.column :ip,             :string
+    t.column :referer,        :string
+    t.column :language,       :string
+    t.column :user_agent,     :string
+    t.column :created_at,     :datetime
+    t.column :created_on,     :date
+  end
+end
\ No newline at end of file
diff --git a/vendor/plugins/sitealizer/install.rb b/vendor/plugins/sitealizer/install.rb
new file mode 100644 (file)
index 0000000..4eaa784
--- /dev/null
@@ -0,0 +1,22 @@
+require 'ftools'
+
+dest_dir = File.dirname(__FILE__)+'/../../../public/images/sitealizer'
+File.makedirs(dest_dir) unless File.exists?(dest_dir)
+
+Dir[File.dirname(__FILE__)+'/lib/app/assets/images/*'].each do |src|
+  File.copy(src, dest_dir+'/')
+end
+
+puts "
+Sitealizer v.1.1 installed
+
+Don't forget to add the following line to your config/routes.rb:
+  map.connect '/sitealizer/:action', :controller => 'sitealizer'
+
+== IMPORTANT ==
+If you had previously installed 'sitemeter' you need to run the following if you want to import your stats:
+  rake sitealizer:remove_sitemeter
+  
+Please visit http://sitealizer.rubyforge.org if you have any questions
+
+"
\ No newline at end of file
diff --git a/vendor/plugins/sitealizer/lib/app/assets/images/bar.gif b/vendor/plugins/sitealizer/lib/app/assets/images/bar.gif
new file mode 100644 (file)
index 0000000..41727a8
Binary files /dev/null and b/vendor/plugins/sitealizer/lib/app/assets/images/bar.gif differ
diff --git a/vendor/plugins/sitealizer/lib/app/assets/images/uv.png b/vendor/plugins/sitealizer/lib/app/assets/images/uv.png
new file mode 100644 (file)
index 0000000..7d39356
Binary files /dev/null and b/vendor/plugins/sitealizer/lib/app/assets/images/uv.png differ
diff --git a/vendor/plugins/sitealizer/lib/app/assets/images/vh.png b/vendor/plugins/sitealizer/lib/app/assets/images/vh.png
new file mode 100644 (file)
index 0000000..13e52f9
Binary files /dev/null and b/vendor/plugins/sitealizer/lib/app/assets/images/vh.png differ
diff --git a/vendor/plugins/sitealizer/lib/app/controllers/sitealizer_controller.rb b/vendor/plugins/sitealizer/lib/app/controllers/sitealizer_controller.rb
new file mode 100644 (file)
index 0000000..85cbbbd
--- /dev/null
@@ -0,0 +1,118 @@
+require 'digest/sha1'
+SA_CONFIG = YAML::load_file(File.dirname(__FILE__)+'/../../config.yml')
+
+class SitealizerController < ActionController::Base
+  
+  before_filter :check_access_type, :except => [:login, :logout]
+  layout 'sitealizer'
+  
+  def self.template_root
+    "#{RAILS_ROOT}/vendor/plugins/sitealizer/lib/app/views"
+  end
+  
+  def login
+    return unless request.post?
+    if params[:username] == SA_CONFIG['sitealizer']['username'].to_s && params[:password] == SA_CONFIG['sitealizer']['password'].to_s
+      cookies[:sitealizer] = {:value => Digest::SHA1.hexdigest("--#{Time.now.to_i}--#{params[:username]}--")}
+      redirect_to :action => 'index'
+    else
+      flash[:notice] = "Username/Password Invalid"
+    end
+  end
+  
+  def logout
+    cookies.delete :sitealizer
+    redirect_to :action => 'login'
+  end
+  
+  def index
+    if !params[:month] && !params[:year]
+      params[:month] = sprintf("%02d",Time.now.month)
+      params[:year]  = Time.now.year
+    end
+  end
+  
+  def menu
+    months = []
+    years  = []
+    f = SiteTracker.find(:all, :limit => 1, :order => 'created_on ASC')
+    l = SiteTracker.find(:all, :limit => 1, :order => 'created_on DESC')
+    first = !f.empty? ? f.first.created_on : Date.today
+    last  = !l.empty? ? l.first.created_on : Date.today
+    (first.to_date..last.to_date).each{|d| months << d.month unless months.include?(d.month)}
+    (first.to_date..last.to_date).each{|d| years << d.year unless years.include?(d.year)}
+    @months = months.sort.map{|m| 
+      m=sprintf('%02d',m); 
+      "<option #{"selected" if m.to_i == params[:month].to_i  } value=#{m}>#{m}</option>"
+    }
+    @years  = years.sort.map{|y| 
+      "<option #{"selected" if y == params[:year].to_i} value=#{y}>#{y}</option>"
+    }
+    @cookie = cookies[:sitealizer]
+  end
+  
+  def summary
+    @year = nil
+    @month = nil
+    begin
+      if "#{params[:year]}-#{params[:month]}-1".to_time
+        @year = params[:year]
+        @month = params[:month]
+      end
+    rescue
+      @year = Time.now.year
+      @month = sprintf("%02d",Time.now.month)
+    end
+    @total_hits  = SiteTracker.count_hits(:year => @year, :month => @month)
+    @unique_hits = SiteTracker.count_hits(:count => 'DISTINCT ip', :year => @year, :month => @month)
+    @daily_hits  = SiteTracker.find_daily_hits(:year => @year, :month => @month)
+    @month_hits  = SiteTracker.find_monthly_hits(:year => @year)
+    @year_hits   = SiteTracker.count_hits(:date => "#{@year}-%")
+    @year_uniq   = SiteTracker.count_hits(:date => "#{@year}-%", :count => "DISTINCT ip")
+    file = File.dirname(__FILE__)+'/../../last_update'
+    @last_update = File.exists?(file) ? open(file,'r'){|f| f.read.to_time.to_s(:long)} : "Not updated yet"
+  end
+  
+  def hourly_stats
+    @year  = params[:year] || Time.now.year
+    @month = params[:month] || sprintf("%02d",Time.now.month)
+    @total_hits  = SiteTracker.count_hits(:year => @year, :month => @month)
+    @hourly_hits = SiteTracker.find_hourly_hits(:year => @year, :month => @month)
+  end
+  
+  def search_stats
+    @year  = params[:year] || Time.now.year
+    @month = params[:month] || sprintf("%02d",Time.now.month)
+    @keywords = SiteTracker.find_search_terms(:year => @year, :month => @month)
+    @engines  = SiteTracker.find_domains(:year => @year, :month => @month, :host => request.host)
+    @robots   = SiteTracker.find_robots(:year => @year, :month => @month)    
+  end
+  
+  def visitor_info
+    @year  = params[:year] || Time.now.year
+    @month = params[:month] || sprintf("%02d",Time.now.month) 
+    @total_hits  = SiteTracker.count_hits(:year => @year, :month => @month)
+    @browsers    = SiteTracker.find_browsers(:year => @year, :month => @month)
+    @platforms   = SiteTracker.find_platforms(:year => @year, :month => @month)
+    @hosts       = SiteTracker.find_hosts(:year => @year, :month => @month)
+    @languages   = SiteTracker.find_languages(:year => @year, :month => @month)
+  end
+  
+  def referrer_stats
+    @year  = params[:year] || Time.now.year
+    @month = params[:month] || sprintf("%02d",Time.now.month)  
+    @total_hits  = SiteTracker.count_hits(:year => @year, :month => @month)
+    @referers    = SiteTracker.find_referers(:year => @year, :month => @month)
+    @page_urls   = SiteTracker.find_page_urls(:year => @year, :month => @month)
+  end
+  
+  protected
+  def check_access_type
+    if SA_CONFIG['sitealizer']['access_type'] == 'private'
+      unless cookies[:sitealizer]
+        redirect_to :action => 'login'
+      end
+    end
+  end
+
+end
\ No newline at end of file
diff --git a/vendor/plugins/sitealizer/lib/app/models/site_tracker.rb b/vendor/plugins/sitealizer/lib/app/models/site_tracker.rb
new file mode 100644 (file)
index 0000000..4d02302
--- /dev/null
@@ -0,0 +1,145 @@
+class SiteTracker < ActiveRecord::Base
+  set_table_name 'sitealizer'
+  
+  def self.find_browsers(params={})
+    browsers = {}
+    tmp = []
+    r = find_by_sql("SELECT user_agent, COUNT(*) AS total FROM sitealizer WHERE created_on "+
+                    "LIKE '#{params[:year]}-#{params[:month]}%' GROUP BY user_agent ORDER BY total DESC")
+    r.each{|env|
+      browser_info = Sitealizer::Parser::UserAgent.browser_info(env.user_agent)
+      tmp << {:total => env.total, :browser => browser_info[:type], :version => browser_info[:version]}
+    }
+    tmp.each{|set| n = "#{set[:browser]}|#{set[:version]}"; browsers[n] = (browsers[n]||0) + set[:total].to_i}
+    browsers = browsers.inject([]){|a,v| 
+      name = v[0].split("|")
+      a << {:browser => {:type => name[0], :version => name[1]}, :total => v[1]}
+    }
+    return browsers.sort{|x,y| y[:total] <=> x[:total]}
+  end
+  
+  def self.find_platforms(params={})
+    platforms = {}
+    tmp = []
+    r = find_by_sql("SELECT user_agent, COUNT(*) AS total FROM sitealizer WHERE created_on "+
+                    "LIKE '#{params[:year]}-#{params[:month]}%' GROUP BY user_agent ORDER BY total DESC")
+    r.each{|env|
+      tmp << {:total => env.total, :name => Sitealizer::Parser::UserAgent.get_platform(env.user_agent)}
+    }
+    tmp.each{|set| platforms[set[:name]] = (platforms[set[:name]]||0) + set[:total].to_i}
+    platforms = platforms.inject([]){|a,v| a << {:name => v[0], :total => v[1]}}
+    return platforms.sort{|x,y| y[:total] <=> x[:total]}
+  end
+  
+  def self.find_robots(params={})
+    robots = {}
+    tmp = []
+    r = find_by_sql("SELECT user_agent, COUNT(*) AS total FROM sitealizer WHERE created_on "+
+                    "LIKE '#{params[:year]}-#{params[:month]}%' GROUP BY user_agent ORDER BY total DESC")
+    r.each{|env|
+      bot = Sitealizer::Parser::Robot.get_name(env.user_agent)
+      tmp << {:total => env.total, :name => bot} if bot
+    }
+    tmp.each{|set| robots[set[:name]] = (robots[set[:name]]||0) + set[:total].to_i}
+    robots = robots.inject([]){|a,v| a << {:name => v[0], :total => v[1]}}
+    return robots.sort{|x,y| y[:total] <=> x[:total]}
+  end
+  
+  def self.find_search_terms(params={})
+    terms = {}
+    tmp = []
+    r = find_by_sql("SELECT referer, COUNT(*) AS total FROM sitealizer WHERE created_on "+
+                    "LIKE '#{params[:year]}-#{params[:month]}%' GROUP BY referer ORDER BY total DESC LIMIT 30")
+    r.each{|env|
+      term = Sitealizer::Parser::Keyword.get_terms(env.referer)
+      tmp << {:total => env.total, :query => term} if term
+    }
+    tmp.each{|set| terms[set[:query]] = (terms[set[:query]]||0) + set[:total].to_i}
+    terms = terms.inject([]){|a,v| a << {:query => v[0], :total => v[1]}}
+    return terms.sort{|x,y| y[:total] <=> x[:total]}
+  end
+  
+  def self.find_domains(params={})
+    domains = {}
+    tmp = []
+    r = find_by_sql("SELECT referer, COUNT(*) AS total FROM sitealizer WHERE created_on "+
+                    "LIKE '#{params[:year]}-#{params[:month]}%' GROUP BY referer ORDER BY total DESC LIMIT 30")
+    r.each{|env|
+      domain = Sitealizer::Parser::Keyword.get_domain(env.referer, params[:host])
+      tmp << {:total => env.total, :domain => domain} if domain
+    }
+    tmp.each{|set| domains[set[:domain]] = (domains[set[:domain]]||0) + set[:total].to_i}
+    domains = domains.inject([]){|a,v| a << {:domain => v[0], :total => v[1]}}
+    return domains.sort{|x,y| y[:total] <=> x[:total]}
+  end
+  
+  def self.find_referers(params={})
+    find_by_sql("SELECT referer, COUNT(*) AS total " +
+                "FROM sitealizer WHERE created_on LIKE '#{params[:year]}-#{params[:month]}%' "+ 
+                "GROUP BY referer ORDER BY total DESC LIMIT 30")
+  end
+  
+  def self.find_page_urls(params={})
+    find_by_sql("SELECT path, COUNT(*) AS total " +
+                "FROM sitealizer WHERE created_on LIKE '#{params[:year]}-#{params[:month]}%' "+ 
+                "GROUP BY path ORDER BY total DESC LIMIT 30")
+  end
+  
+  def self.find_hosts(params={})
+    find_by_sql("SELECT ip, COUNT(*) AS total FROM sitealizer WHERE "+
+                "created_on LIKE '#{params[:year]}-#{params[:month]}%' "+ 
+                "GROUP BY ip ORDER BY total DESC LIMIT 30")
+  end
+  
+  def self.find_languages(params={})
+    find_by_sql("SELECT language, COUNT(*) AS total FROM sitealizer WHERE "+
+                "created_on LIKE '#{params[:year]}-#{params[:month]}%'  "+ 
+                "GROUP BY language ORDER BY total DESC LIMIT 15")
+  end
+  
+  def self.count_hits(params={})
+    count = !params[:count] ? "*" : params[:count]
+    date  = !params[:date] ? "#{params[:year]}-#{params[:month]}%" : params[:date]
+    count_by_sql("SELECT COUNT(#{count}) FROM sitealizer WHERE created_on LIKE '#{date}'")
+  end
+  
+  def self.find_monthly_hits(params={})
+    dataset = []
+    12.times{|month| month+=1
+      created = "#{params[:year]}-#{sprintf("%02d",month)}-%"
+      date = "#{params[:year]}-#{month}-1".to_time.strftime('%B %Y')
+      date_short = "#{params[:year]}-#{month}-1".to_time.strftime('%b %Y')
+      visits = count_by_sql("SELECT COUNT(DISTINCT ip) FROM sitealizer WHERE created_on LIKE '#{created}'")
+      hits   = count_by_sql("SELECT COUNT(*) FROM sitealizer WHERE created_on LIKE '#{created}'")
+      dataset << [date_short, visits, hits, date]
+    }
+    dataset    
+  end
+  
+  def self.find_daily_hits(params={})
+    dataset = []
+    days_in_mon = Date.civil(params[:year].to_i, params[:month].to_i, -1).day
+    days_in_mon.times{|day| day+=1
+      created = "#{params[:year]}-#{params[:month]}-#{sprintf("%02d",day)}"
+      date = "#{params[:year]}-#{params[:month]}-#{day}".to_time.strftime('%b %d %Y')
+      visits = count_by_sql("SELECT COUNT(DISTINCT ip) FROM sitealizer WHERE created_on = '#{created}'")
+      hits   = count_by_sql("SELECT COUNT(*) FROM sitealizer WHERE created_on = '#{created}'")
+      dataset << [day, visits, hits, date]
+    }
+    dataset
+  end
+  
+  def self.find_hourly_hits(params={})
+    dataset = []
+    24.times{|hour|
+      hour = sprintf("%02d",hour)
+      visits = count_by_sql("SELECT COUNT(DISTINCT ip) FROM sitealizer "+
+                            "WHERE created_at LIKE '#{params[:year]}-#{params[:month]}% #{hour}:%'")
+      hits = count_by_sql("SELECT COUNT(*) FROM sitealizer WHERE "+
+                          "created_at LIKE '#{params[:year]}-#{params[:month]}% #{hour}:%'")
+      dataset << [hour.to_s, visits, hits]
+    }
+    dataset
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/plugins/sitealizer/lib/app/views/layouts/sitealizer.rhtml b/vendor/plugins/sitealizer/lib/app/views/layouts/sitealizer.rhtml
new file mode 100644 (file)
index 0000000..ace9f87
--- /dev/null
@@ -0,0 +1,66 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+  <head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+  <meta http-equiv="description" content="Sitealizer Web Stats">
+  <title>Sitealizer Web Stats for <%=request.host%></title>
+
+<style type="text/css">
+<!--
+  body {font: 12px helvetica, verdana, arial, sans-serif; background-color: #FFFFFF; margin-top: 0; margin-bottom: 0;}
+  #border{border: 2px #004EC1 solid; padding: 10px;}
+  #title{
+       font-family: Georgia;
+       font-size:150%; 
+       font-weight: bold; 
+       background-color: #e4effc; 
+       padding:5px;
+       color: #000;
+       border:1px #004EC1 solid; 
+  }
+  #sub_title{
+       font-family: Georgia;
+       font-size:130%; 
+       font-weight: bold; 
+       padding:5px;
+       color: #000;
+       border-bottom:1px #000 solid; 
+  }
+  th { 
+       border-color: #ECECEC; 
+       border-left-width: 0px; 
+       border-right-width: 1px; 
+       border-top-width: 0px; 
+       border-bottom-width: 1px; 
+       padding: 3px; 
+       font-family: Georgia;
+       font-weight: bold;
+       font-size:90%; 
+       color: #000; 
+       background-color:#ededdc;
+  }
+  td { 
+       border-color: #ECECEC; 
+       border-left-width: 0px; 
+       border-right-width: 1px; 
+       border-top-width: 0px; 
+       border-bottom-width: 1px; 
+       font: 11px verdana, arial, helvetica, sans-serif; 
+       color: #000000; 
+  }
+  b { font-weight: bold; }
+  a { font: 11px verdana, arial, helvetica, sans-serif; }
+  a:link    { color: #0011BB; text-decoration: none; }
+  a:visited { color: #0011BB; text-decoration: none; }
+  a:hover   { color: #605040; text-decoration: underline; }
+  #menu { padding:5px; font-size:100%; display:block;  background-color:#ededdc;}
+  #menu_border{border: 1px #004EC1 solid; padding: 5px;}
+//-->
+</style>
+</head>
+  <%=yield%>
+  <p align=center style="color:#999; font-size:10px">
+       Created with <%=link_to 'Sitealizer', 'http://sitealizer.rubyforge.org', :target => '_blank'%>
+  </p>
+</html>
\ No newline at end of file
diff --git a/vendor/plugins/sitealizer/lib/app/views/sitealizer/_browsers.rhtml b/vendor/plugins/sitealizer/lib/app/views/sitealizer/_browsers.rhtml
new file mode 100644 (file)
index 0000000..a60fb39
--- /dev/null
@@ -0,0 +1,23 @@
+<% max_total = @browsers.inject(0) {|m,a| a[:total].to_i > m ? a[:total].to_i : m }%>
+<br><br>
+
+<table align=center width=90% border=1 cellpadding=3>
+<tr nowrap>
+<th width=1>#</th>     
+<th width=10>Hits</th>
+<th>Browser</th>
+<th width=70>Version</th>
+<th width=10>Percentage</th>
+<th width=200></th>
+</tr>
+<% i=1; @browsers.each do |browser| width=((browser[:total].to_f/max_total)*200).round; width = 1 if width < 1 %>
+<tr nowrap>
+<td align=center><%= i %></td>
+<td align=center><%= browser[:total] %></td>
+<td><%= browser[:browser][:type] %></td>
+<td align=left><%= browser[:browser][:version] ? browser[:browser][:version] : 'Unknown' %>&nbsp;</td>
+<td align=center><%= sprintf("%000.2f",(browser[:total].to_f/@total_hits)*100) %>%</td>
+<td align=left><%=image_tag 'sitealizer/bar.gif', :width => width, :height => 3%></td>
+</tr>
+<%i+=1; end %>
+</table>
diff --git a/vendor/plugins/sitealizer/lib/app/views/sitealizer/_daily_stats.rhtml b/vendor/plugins/sitealizer/lib/app/views/sitealizer/_daily_stats.rhtml
new file mode 100644 (file)
index 0000000..06f2592
--- /dev/null
@@ -0,0 +1,67 @@
+<br>
+<% 
+unique_max_total = @daily_hits.inject(0) {|m,a| a[1].to_i > m ? a[1].to_i : m }
+hits_max_total = @daily_hits.inject(0) {|m,a| a[2].to_i > m ? a[2].to_i : m }
+%>
+<table cellpadding=0 cellspacing=0 align=center width=98%>
+<tr valign=bottom>
+<td valign=top align=left width=60 nowrap>
+       <img align="bottom" src="/images/sitealizer/uv.png" height="10" width="4"/> Unique<br>
+       <img align="bottom" src="/images/sitealizer/vh.png" height="10" width="4"/> Hits
+</td>
+<% 
+@daily_hits.each do |daily_hits| 
+unique_height = 0
+hits_height   = 0
+if unique_max_total > 0
+       unique_height = ((daily_hits[1].to_f/unique_max_total)*100).round
+       unique_height = 1 if unique_height < 1  
+end    
+if hits_max_total > 0
+       hits_height   = ((daily_hits[2].to_f/hits_max_total)*100).round
+       hits_height   = 1 if hits_height < 1    
+end
+%>
+<td>
+       <table>
+       <tr valign=bottom nowrap>
+       <td nowrap>
+       <img align="bottom" src="/images/sitealizer/uv.png" height="<%=unique_height%>" width="4"/>
+       <img align="bottom" src="/images/sitealizer/vh.png" height="<%=hits_height%>" width="4"/>
+       </td>
+       </tr>
+       <tr valign=bottom nowrap>
+       <td>
+               <%=daily_hits[0]%>
+       </td>
+       </tr>
+       </table>
+</td>
+<%end%>
+</tr>
+</table>
+
+<br><br>
+
+<table align=center width=70% border=1 cellpadding=3>
+<tr align=center nowrap>
+<th align=center>Day</th>
+<th align=center>Hits</th>
+<th align=center>Percentage</th>
+<th align=center>Unique Visits</th>
+</tr>
+<%i=1; @daily_hits.each do |daily_hits| %>
+<tr nowrap>
+<td align=center><%= daily_hits[3] %></td>
+<td align=center><%= daily_hits[2] %></td>
+<td align=center><%= sprintf("%000.2f",(daily_hits[2].to_f/@total_hits)*100) %>%</td>
+<td align=center><%= daily_hits[1] %></td>
+</tr>
+<% i+=1; end %>
+<tr align=center nowrap bgcolor="#DDDDDD">
+<td align=left><b>Totals:</td>
+<td align=center><b><%=@total_hits%></b></td>
+<td></td>      
+<td align=center><b><%=@unique_hits%></b></td>
+</tr>
+</table>
\ No newline at end of file
diff --git a/vendor/plugins/sitealizer/lib/app/views/sitealizer/_hits_summary.rhtml b/vendor/plugins/sitealizer/lib/app/views/sitealizer/_hits_summary.rhtml
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/vendor/plugins/sitealizer/lib/app/views/sitealizer/_hosts.rhtml b/vendor/plugins/sitealizer/lib/app/views/sitealizer/_hosts.rhtml
new file mode 100644 (file)
index 0000000..47fe35c
--- /dev/null
@@ -0,0 +1,21 @@
+<% max_total = @hosts.inject(0) {|m,a| a['total'].to_i > m ? a['total'].to_i : m }%>
+<br><br>
+
+<table align=center width=90% border=1 cellpadding=3>
+<tr nowrap>
+<th width=1>#</th>     
+<th width=10>Hits</th>
+<th>Hostname</th>      
+<th width=10>Percentage</th>
+<th width=200></th>
+</tr>
+<% i=1; @hosts.each do |host|width=((host.total.to_f/max_total)*200).round; width = 1 if width < 1 %>
+<tr nowrap>
+<td><%= i %></td>
+<td align=center><%= host.total %></td>
+<td align=left><%= link_to host.ip, "http://cqcounter.com/whois/?query=#{host.ip}", :target=>'_blank' %></td>    
+<td align=center><%= sprintf("%000.2f",(host.total.to_f/@total_hits)*100) %>%</td>
+<td align=left><%=image_tag 'sitealizer/bar.gif', :width => width, :height => 3%></td>
+</tr>
+<% i+=1; end %>
+</table>
diff --git a/vendor/plugins/sitealizer/lib/app/views/sitealizer/_keywords.rhtml b/vendor/plugins/sitealizer/lib/app/views/sitealizer/_keywords.rhtml
new file mode 100644 (file)
index 0000000..d80a17b
--- /dev/null
@@ -0,0 +1,19 @@
+<% max_total = @keywords.inject(0) {|m,a| a[:total].to_i > m ? a[:total].to_i : m }%>
+<br><br>
+
+<table align=center width=90% border=1 cellpadding=3>
+<tr nowrap>
+<th width=1>#</th>     
+<th width=10>Hits</th>
+<th>Search String</th>
+<th width=175></th>
+</tr>
+<% i=1; @keywords.each do |keyword| width=((keyword[:total].to_f/max_total)*175).round; width = 1 if width < 1 %>
+<tr nowrap>
+<td align=center><%= i %></td>
+<td align=center><%= keyword[:total] %></td>    
+<td align=left ><%= keyword[:query] %></td>
+<td align=left><%=image_tag 'sitealizer/bar.gif', :width => width, :height => 3%></td>
+</tr>
+<% i+=1; end %>
+</table>
diff --git a/vendor/plugins/sitealizer/lib/app/views/sitealizer/_languages.rhtml b/vendor/plugins/sitealizer/lib/app/views/sitealizer/_languages.rhtml
new file mode 100644 (file)
index 0000000..ddcb8f7
--- /dev/null
@@ -0,0 +1,21 @@
+<% max_total = @languages.inject(0) {|m,a| a['total'].to_i > m ? a['total'].to_i : m }%>
+<br><br>
+
+<table align=center width=90% border=1 cellpadding=3>
+<tr nowrap>
+<th width=1>#</th>     
+<th width=10>Hits</th>
+<th>Language</th>      
+<th width=10>Percentage</th>
+<th width=200></th>
+</tr>
+<% i=1; @languages.each do |lang|width=((lang.total.to_f/max_total)*200).round; width = 1 if width < 1 %>
+<tr nowrap>
+<td align=center><%= i %></td>
+<td align=center><%= lang.total %></td>
+<td align=left><%= lang.language.nil? ? 'Unknown' : Sitealizer::Parser::Language.get_name(lang.language.downcase) %></td>    
+<td align=center><%= sprintf("%000.2f",(lang.total.to_f/@total_hits)*100) %>%</td>
+<td align=left><%=image_tag 'sitealizer/bar.gif', :width => width, :height => 3%></td>
+</tr>
+<% i+=1; end %>
+</table>
\ No newline at end of file
diff --git a/vendor/plugins/sitealizer/lib/app/views/sitealizer/_main_frame.rhtml b/vendor/plugins/sitealizer/lib/app/views/sitealizer/_main_frame.rhtml
new file mode 100644 (file)
index 0000000..333b1e8
--- /dev/null
@@ -0,0 +1,84 @@
+<h1>Welcome</h1>
+<a href='/sitealizer/logout' target='_top'>logout</a>
+
+<br><br>
+
+<%
+uv_max_m = @monthly_history[:dataset].inject(0) {|m,a| a[1] > m ? a[1] : m }
+hi_max_m = @monthly_history[:dataset].inject(0) {|m,a| a[2] > m ? a[2] : m }
+%>
+<h3>Monthly History</h3>
+<table>
+<tr>
+<%@monthly_history[:dataset].each do |data| uv_height_m=((data[1].to_f/uv_max_m)*100).round; hi_height_m=((data[2].to_f/hi_max_m)*100).round%>
+<td>
+       <table>
+       <tr>
+       <td>
+       <img align="bottom" src="/images/sitealizer/uv.png" height="<%=uv_height_m%>" width="6"/>
+       <img align="bottom" src="/images/sitealizer/vh.png" height="<%=hi_height_m%>" width="6"/>
+       </td>
+       </tr>
+       <tr>
+       <td>
+               <%=data[0]%>
+       </td>
+       </tr>
+       </table>
+</td>
+<%end%>
+</tr>
+</table>
+<table width=500>
+<tr valign=middle height=25>
+       <td align=center><b>Month</b></td>
+       <td align=center><b>Unique Visitors</b></td>
+       <td align=center><b>Visits</b></td>
+       <td align=center><b>Pages</b></td>
+       <td align=center><b>Hits</b></td>
+</tr>
+<%=@monthly_history[:html]%>
+</table>
+
+
+<br><br>
+
+<%=uv_max_d = @daily_history[:dataset].inject(0) {|m,a| a[1] > m ? a[1] : m }%>
+<%=hi_max_d = @daily_history[:dataset].inject(0) {|m,a| a[2] > m ? a[2] : m }%>
+<h3>Daily History</h3>
+<table cellpadding=2 cellspacing=1>
+<tr valign=bottom>
+<%@daily_history[:dataset].each do |data|%>
+<%uv_height_d=((data[1].to_f/uv_max_d)*100).round%>
+<%hi_height_d=((data[2].to_f/hi_max_d)*100).round%>
+
+<td nowrap>
+       <table cellpadding=0 cellspacing=0 width=100%>
+       <tr valign=bottom>
+       <td nowrap>
+       <img align="bottom" src="/images/sitealizer/uv.png" height="<%=uv_height_d > 0 ? uv_height_d : 1%>" width="2"/>
+       <img align="bottom" src="/images/sitealizer/vh.png" height="<%=hi_height_d > 0 ? hi_height_d : 1%>" width="2"/>
+       </td>
+       </tr>
+       <tr valign=bottom>
+       <td>
+               <%=data[0]%>
+       </td>
+       </tr>
+       </table>
+</td>
+<%end%>
+</tr>
+</table>
+<table width=500>
+<tr valign=middle height=25>
+       <td align=center><b>Month</b></td>
+       <td align=center><b>Unique Visitors</b></td>
+       <td align=center><b>Visits</b></td>
+       <td align=center><b>Pages</b></td>
+       <td align=center><b>Hits</b></td>
+</tr>
+<%=@daily_history[:html]%>
+</table>
+
+<%=render :partial => 'test'%>
\ No newline at end of file
diff --git a/vendor/plugins/sitealizer/lib/app/views/sitealizer/_monthly_hits.rhtml b/vendor/plugins/sitealizer/lib/app/views/sitealizer/_monthly_hits.rhtml
new file mode 100644 (file)
index 0000000..dfbb94e
--- /dev/null
@@ -0,0 +1,67 @@
+<br>
+<% 
+unique_max_total = @month_hits.inject(0) {|m,a| a[1].to_i > m ? a[1].to_i : m }
+hits_max_total = @month_hits.inject(0) {|m,a| a[2].to_i > m ? a[2].to_i : m }
+%>
+<table cellpadding=0 cellspacing=0 align=center width=65%>
+<tr valign=bottom>
+<td valign=top align=left width=60 nowrap>
+       <img align="bottom" src="/images/sitealizer/uv.png" height="10" width="4"/> Unique<br>
+       <img align="bottom" src="/images/sitealizer/vh.png" height="10" width="4"/> Hits
+</td>
+<% 
+@month_hits.each do |month_hits|
+unique_height = 0
+hits_height   = 0
+if unique_max_total > 0
+       unique_height = ((month_hits[1].to_f/unique_max_total)*100).round
+       unique_height = 1 if unique_height < 1          
+end
+if hits_max_total > 0
+       hits_height   = ((month_hits[2].to_f/hits_max_total)*100).round
+       hits_height   = 1 if hits_height < 1    
+end
+%>
+<td>
+       <table>
+       <tr valign=bottom nowrap align=center>
+       <td>
+       <img align="bottom" src="/images/sitealizer/uv.png" height="<%=unique_height%>" width="4"/>
+       <img align="bottom" src="/images/sitealizer/vh.png" height="<%=hits_height%>" width="4"/>
+       </td>
+       </tr>
+       <tr valign=bottom nowrap align=center>
+       <td>
+               <span style="font-size:10px"><%=month_hits[0]%></span>
+       </td>
+       </tr>
+       </table>
+</td>
+<%end%>
+</tr>
+</table>
+
+<br><br>
+
+<table align=center width=70% border=1 cellpadding=3>
+<tr align=center nowrap>
+<th align=center>Month</th>
+<th align=center>Hits</th>
+<th align=center>Percentage</th>
+<th align=center>Unique Visits</th>
+</tr>
+<%i=1; @month_hits.each do |month_hits| %>
+<tr nowrap>
+<td align=left><%= month_hits[0] %></td>
+<td align=center><%= month_hits[2] %></td>
+<td align=center><%= sprintf("%000.2f",(month_hits[2].to_f/@year_hits)*100) %>%</td>
+<td align=center><%= month_hits[1] %></td>
+</tr>
+<% i+=1; end %>
+<tr align=center nowrap bgcolor="#DDDDDD">
+<td align=left><b>Totals:</td>
+<td align=center><b><%=@year_hits%></b></td>
+<td></td>      
+<td align=center><b><%=@year_uniq%></b></td>
+</tr>
+</table>
\ No newline at end of file
diff --git a/vendor/plugins/sitealizer/lib/app/views/sitealizer/_page_urls.rhtml b/vendor/plugins/sitealizer/lib/app/views/sitealizer/_page_urls.rhtml
new file mode 100644 (file)
index 0000000..45225e5
--- /dev/null
@@ -0,0 +1,20 @@
+<% max_total = @page_urls.inject(0) {|m,a| a['total'].to_i > m ? a['total'].to_i : m }%>
+<br><br>
+<table align=center width=98% border=1 cellpadding=3>
+<tr nowrap>
+<th width=1>#</th>     
+<th width=30>Hits</th>
+<th>Page URL</th>      
+<th width=30>Percentage</th>
+<th width=100></th>
+</tr>
+<% i=1; @page_urls.each do |url| width=((url.total.to_f/max_total)*100).round; width = 1 if width < 1 %>
+<tr nowrap>
+<td align=center><%= i %></td>
+<td align=center><%= url.total %></td>    
+<td align=left nowrap><%= link_to truncate(url.path, 73), url.path, {:target=>'_blank'} %></td>
+<td align=center><%= sprintf("%000.2f",(url.total.to_f/@total_hits)*100) %>%</td>
+<td align=left><%=image_tag 'sitealizer/bar.gif', :width => width, :height => 3%></td>
+</tr>
+<% i+=1; end %>
+</table>
diff --git a/vendor/plugins/sitealizer/lib/app/views/sitealizer/_platforms.rhtml b/vendor/plugins/sitealizer/lib/app/views/sitealizer/_platforms.rhtml
new file mode 100644 (file)
index 0000000..681dc59
--- /dev/null
@@ -0,0 +1,21 @@
+<% max_total = @platforms.inject(0) {|m,a| a[:total].to_i > m ? a[:total].to_i : m }%>
+<br><br>
+
+<table align=center width=90% border=1 cellpadding=3>
+<tr nowrap>
+<th width=1>#</th>
+<th width=10>Hits</th>
+<th>Operating System</th>
+<th width=10>Percentage</th>
+<th width=200></th>
+</tr>
+<% i=1; @platforms.each do |platform| width=((platform[:total].to_f/max_total)*200).round; width = 1 if width < 1 %>
+<tr nowrap>
+<td align=center><%= i %></td>
+<td align=center><%= platform[:total] %></td>    
+<td align=left><%= platform[:name] %></td>
+<td align=center><%= sprintf("%000.2f",(platform[:total].to_f/@total_hits)*100) %>%</td>
+<td align=left><%=image_tag 'sitealizer/bar.gif', :width => width, :height => 3%></td>
+</tr>
+<% i+=1; end %>
+</table>
diff --git a/vendor/plugins/sitealizer/lib/app/views/sitealizer/_referers.rhtml b/vendor/plugins/sitealizer/lib/app/views/sitealizer/_referers.rhtml
new file mode 100644 (file)
index 0000000..9d4015b
--- /dev/null
@@ -0,0 +1,22 @@
+<% max_total = @referers.inject(0) {|m,a| a['total'].to_i > m ? a['total'].to_i : m }%>
+<br><br>
+
+<table align=center width=98% border=1 cellpadding=3>
+<tr nowrap>
+<th width=1>#</th>     
+<th width=10>Hits</th>
+<th>Referer</th>      
+<th width=10>Percentage</th>
+<th width=100></th>
+</tr>
+<% i=1; @referers.each do |referer| width=((referer.total.to_f/max_total)*100).round; width = 1 if width <= 1 %>
+<tr nowrap>
+<td align=center><%= i %></td>
+<td align=center><%= referer.total %></td>    
+<td align=left >
+<%= referer.referer.nil? ? "Direct Request / Bookmarks" : link_to(truncate(referer.referer, 73), referer.referer, {:target=>'_blank'}) %></td>
+<td align=center><%= sprintf("%000.2f",(referer.total.to_f/@total_hits)*100) %>%</td>
+<td align=left><%=image_tag 'sitealizer/bar.gif', :width => width, :height => 3%></td>
+</tr>
+<% i+=1; end %>
+</table>
diff --git a/vendor/plugins/sitealizer/lib/app/views/sitealizer/_robots.rhtml b/vendor/plugins/sitealizer/lib/app/views/sitealizer/_robots.rhtml
new file mode 100644 (file)
index 0000000..9b7be8a
--- /dev/null
@@ -0,0 +1,19 @@
+<% max_total = @robots.inject(0) {|m,a| a[:total].to_i > m ? a[:total].to_i : m }%>
+<br><br>
+
+<table align=center width=90% border=1 cellpadding=3>
+<tr nowrap>
+<th width=1>#</th>     
+<th width=10>Hits</th>      
+<th>Robot/Crawler</th>
+<th width=175></th>
+</tr>
+<% i=1; @robots.each do |robot| width=((robot[:total].to_f/max_total)*175).round; width = 1 if width < 1 %>
+<tr nowrap>
+<td><%= i %></td>
+<td align=center><%= robot[:total] %></td>    
+<td align=left><%= robot[:name] %></td>
+<td align=left><%=image_tag 'sitealizer/bar.gif', :width => width, :height => 3%></td>
+</tr>
+<% i+=1; end %>
+</table>
diff --git a/vendor/plugins/sitealizer/lib/app/views/sitealizer/_search_engines.rhtml b/vendor/plugins/sitealizer/lib/app/views/sitealizer/_search_engines.rhtml
new file mode 100644 (file)
index 0000000..961dc0a
--- /dev/null
@@ -0,0 +1,19 @@
+<% max_total = @engines.inject(0) {|m,a| a[:total].to_i > m ? a[:total].to_i : m }%>
+<br><br>
+
+<table align=center width=90% border=1 cellpadding=3>
+<tr align=left nowrap>
+<th width=1>#</th>     
+<th width=10>Hits</th>
+<th align=center>Domain</th>
+<th width=175></th>
+</tr>
+<% i=1; @engines.each do |engine| width=((engine[:total].to_f/max_total)*175).round; width = 1 if width < 1 %>
+<tr nowrap>
+<td align=center><%= i %></td>
+<td align=center><%= engine[:total] %></td>
+<td align=left><%= engine[:domain] %></td>
+<td align=left><%=image_tag 'sitealizer/bar.gif', :width => width, :height => 3%></td>
+</tr>
+<% i+=1; end %>
+</table>
diff --git a/vendor/plugins/sitealizer/lib/app/views/sitealizer/hourly_stats.rhtml b/vendor/plugins/sitealizer/lib/app/views/sitealizer/hourly_stats.rhtml
new file mode 100644 (file)
index 0000000..436c886
--- /dev/null
@@ -0,0 +1,39 @@
+<div style="margin-top:12px">
+<table align=center width=95% cellpadding=0>
+</tr>
+<td>
+<div id='border'>
+<div id='title'>Hourly Statistics - <%=params[:month]%>-<%=params[:year]%></div>
+
+<% hits_max_total = @hourly_hits.inject(0) {|m,a| a[2].to_i > m ? a[2].to_i : m } %>
+<br><br>
+<table align=center border=1 width=70% cellpadding=3>
+<tr>
+<th>Hour</th>
+<th>Hits</th>
+<th>Percentage</th>
+
+<th></th>
+</tr>
+<% 
+@hourly_hits.each do |hourly_hits| 
+width = 0
+if hits_max_total > 0
+       width = ((hourly_hits[2].to_f/hits_max_total)*200).round 
+       width = 1 if width < 1
+end
+%>
+<tr>
+<td align=center><%= hourly_hits[0] %></td>
+<td align=center><%= hourly_hits[2] %></td>
+<td align=center><%= sprintf("%000.2f",(hourly_hits[2].to_f/@total_hits)*100) %>%</td>
+
+<td align=left><%=image_tag 'sitealizer/bar.gif', :width => width, :height => 3%></td>
+</tr>
+<% end %>
+</table>
+</div>
+</td>
+</tr>
+</table>
+</div>
\ No newline at end of file
diff --git a/vendor/plugins/sitealizer/lib/app/views/sitealizer/index.rhtml b/vendor/plugins/sitealizer/lib/app/views/sitealizer/index.rhtml
new file mode 100644 (file)
index 0000000..e731922
--- /dev/null
@@ -0,0 +1,8 @@
+<frameset cols="250,*">
+<frame name="left" src="/sitealizer/menu<%="?month=#{params[:month]}&year=#{params[:year]}" if params[:month] && params[:year]%>" noresize="noresize" frameborder="0" />
+<frame name="main" src="/sitealizer/summary<%="?month=#{params[:month]}&year=#{params[:year]}" if params[:month] && params[:year]%>" noresize="noresize" scrolling="auto" frameborder="0" />
+<noframes>
+<body>Your browser does not support frames.<br><br>
+</body>
+</noframes>
+</frameset>
\ No newline at end of file
diff --git a/vendor/plugins/sitealizer/lib/app/views/sitealizer/login.rhtml b/vendor/plugins/sitealizer/lib/app/views/sitealizer/login.rhtml
new file mode 100644 (file)
index 0000000..d290522
--- /dev/null
@@ -0,0 +1,20 @@
+<div style="margin-top:20px">
+<table width=300 align=center cellpadding=0  id='menu_border'>
+<tr align=center>
+<td>
+       <div id='sub_title' style="color:#004EC1">Sitealizer Login</div>
+       
+       <%="<p>#{flash[:notice]}</p>" if flash[:notice]%>
+       
+       <form action='/sitealizer/login' method='post'>
+               <p style="color:#004EC1; font-weight:bold">
+                       Username: <%= text_field_tag :username%>
+               </p>
+               <p style="color:#004EC1; font-weight:bold">
+                       Password: <%= password_field_tag :password%>
+               </p>
+               <%=submit_tag 'Login'%>
+       </form>
+</td>
+</tr>
+</table>
\ No newline at end of file
diff --git a/vendor/plugins/sitealizer/lib/app/views/sitealizer/menu.rhtml b/vendor/plugins/sitealizer/lib/app/views/sitealizer/menu.rhtml
new file mode 100644 (file)
index 0000000..a4a15af
--- /dev/null
@@ -0,0 +1,74 @@
+<div style="margin-top:12px">
+<table width=95% align=center cellpadding=0  id='menu_border'>
+<tr valign=top height=50><td><div id='menu_border'>Statistics for:<br><b><%=request.host%></b></div></td></tr>
+<tr>
+<td>
+       <form action='/sitealizer' target='_top'>
+       Period: <%=select_tag :month, @months%> <%=select_tag :year, @years%>
+       <%=submit_tag 'OK'%>
+       </form>
+</td>
+</tr>
+<tr>
+<td>
+<span id='menu'>
+<%if params[:year] && params[:month]%>
+       <%= link_to "[Summary]", 
+                               "/sitealizer/summary?month=#{params[:month]}&year=#{params[:year]}", 
+                               :target => 'main'%>
+<%else%>
+       <%= link_to "[Summary]", "/sitealizer/summary", :target => 'main'%>
+<%end%>
+</span><br>
+
+<span id='menu'>
+<%if params[:year] && params[:month]%>
+       <%= link_to "[Hourly Stats]", 
+                               "/sitealizer/hourly_stats?month=#{params[:month]}&year=#{params[:year]}", 
+                               :target => 'main'%>
+<%else%>       
+       <%= link_to "[Hourly Stats]", "/sitealizer/hourly_stats", :target => 'main'%>
+<%end%>
+</span><br>
+
+<span id='menu'>
+<%if params[:year] && params[:month]%>
+       <%= link_to "[Referrer Stats]", 
+                               "/sitealizer/referrer_stats?month=#{params[:month]}&year=#{params[:year]}", 
+                               :target => 'main'%>
+<%else%>
+       <%= link_to "[Referrer Stats]", "/sitealizer/referrer_stats", :target => 'main'%>
+<%end%>
+</span><br>
+
+<span id='menu'>
+<%if params[:year] && params[:month]%>
+       <%= link_to "[Search Stats]", 
+                               "/sitealizer/search_stats?month=#{params[:month]}&year=#{params[:year]}", 
+                               :target => 'main'%>
+<%else%>
+       <%= link_to "[Search Stats]", "/sitealizer/search_stats", :target => 'main'%>
+<%end%>
+</span><br>
+
+<span id='menu'>
+<%if params[:year] && params[:month]%> 
+       <%= link_to "[Visitor Info]", 
+                               "/sitealizer/visitor_info?month=#{params[:month]}&year=#{params[:year]}", 
+                               :target => 'main'%>
+<%else%>
+       <%= link_to "[Visitor Info]", "/sitealizer/visitor_info", :target => 'main'%>
+<%end%>
+</span>
+
+<%if @cookie%>
+<br>
+<span id='menu'>
+       <%= link_to "[Logout]", "/sitealizer/logout", :target => '_top'%>
+</span>
+<%end%>
+
+</td>
+</tr>
+</table>
+</div>
\ No newline at end of file
diff --git a/vendor/plugins/sitealizer/lib/app/views/sitealizer/referrer_stats.rhtml b/vendor/plugins/sitealizer/lib/app/views/sitealizer/referrer_stats.rhtml
new file mode 100644 (file)
index 0000000..2e3bc0d
--- /dev/null
@@ -0,0 +1,20 @@
+<div style="margin-top:12px">
+<table align=center width=95% cellpadding=0>
+</tr>
+<td>
+       <div id='border'>
+       <div id='title'>Referrer Statistics</div>
+       <p>
+               <div id='sub_title'>Page URLs - Top 30</div>
+               <div><%=render :partial => 'page_urls'%></div>
+       </p>
+       <br>
+       <p>
+               <div id='sub_title'>Referrers - Top 30</div>
+               <div><%=render :partial => 'referers'%></div>
+       </p>
+       </div>
+</td>
+</tr>
+</table>
+</div>
\ No newline at end of file
diff --git a/vendor/plugins/sitealizer/lib/app/views/sitealizer/search_stats.rhtml b/vendor/plugins/sitealizer/lib/app/views/sitealizer/search_stats.rhtml
new file mode 100644 (file)
index 0000000..55ceacc
--- /dev/null
@@ -0,0 +1,25 @@
+<div style="margin-top:12px">
+<table align=center width=95% cellpadding=0>
+</tr>
+<td>
+<div id='border'>
+       <div id='title'>Search Statistics</div>
+       <p>
+               <div id='sub_title'>Robots/Crawlers</div>
+               <div><%=render :partial => 'robots'%></div>
+       </p>
+       <br>
+       <p>
+               <div id='sub_title'>Top Domains</div>
+               <div><%=render :partial => 'search_engines'%></div>
+       </p>
+       <br>
+       <p>
+               <div id='sub_title'>Search Strings - Top 30</div>
+               <div><%=render :partial => 'keywords'%></div>
+       </p>
+</div>
+</td>
+</tr>
+</table>
+</div>
\ No newline at end of file
diff --git a/vendor/plugins/sitealizer/lib/app/views/sitealizer/summary.rhtml b/vendor/plugins/sitealizer/lib/app/views/sitealizer/summary.rhtml
new file mode 100644 (file)
index 0000000..bc4b5d9
--- /dev/null
@@ -0,0 +1,22 @@
+<div style="margin-top:12px">
+<table align=center width=95% cellpadding=0>
+</tr>
+<td>
+       <div id='border'>
+       <div id='title'>Summary - <%="#{@year}-#{@month}-1".to_time.strftime('%B %Y')%></div>
+       <p>Last Update: <%=@last_update%></p>
+       <p>
+               <div id='sub_title'>Monthly Hits</div>
+               <div><%=render :partial => 'monthly_hits'%></div>
+       </p>
+       <br>
+       <p>
+               <div id='sub_title'>Daily Hits</div>
+               <div><%=render :partial => 'daily_stats'%></div>
+       </p>
+       <br>
+</div>
+</td>
+</tr>
+</table>
+</div>
\ No newline at end of file
diff --git a/vendor/plugins/sitealizer/lib/app/views/sitealizer/visitor_info.rhtml b/vendor/plugins/sitealizer/lib/app/views/sitealizer/visitor_info.rhtml
new file mode 100644 (file)
index 0000000..8266f03
--- /dev/null
@@ -0,0 +1,30 @@
+<div style="margin-top:12px">
+<table align=center width=95% cellpadding=0>
+</tr>
+<td>
+<div id='border'>
+       <div id='title'>Visitor Information</div>
+       <p>
+               <div id='sub_title'>Hosts - Top 30</div>
+               <div><%=render :partial => 'hosts'%></div>
+       </p>
+       <br>
+       <p>
+               <div id='sub_title'>Operating Systems</div>
+               <div><%=render :partial => 'platforms'%></div>
+       </p>
+       <br>
+       <p>
+               <div id='sub_title'>Browsers</div>
+               <div><%=render :partial => 'browsers'%></div>
+       </p>
+       <br>
+       <p>
+               <div id='sub_title'>Languages - Top 15</div>
+               <div><%=render :partial => 'languages'%></div>
+       </p>
+</div>
+</td>
+</tr>
+</table>
+</div>
\ No newline at end of file
diff --git a/vendor/plugins/sitealizer/lib/config.yml b/vendor/plugins/sitealizer/lib/config.yml
new file mode 100644 (file)
index 0000000..b765d92
--- /dev/null
@@ -0,0 +1,18 @@
+# Sitealizer config
+#
+# This is the only configuration you need to change if you don't want to 
+# leave it with the default config values.
+# 
+# Access types:
+# - private: You have to enter the username and password below in order to view the stats
+# - public: Anyone can view your site's stats
+# 
+# Queue size:
+# - The number of visitors in the queue before saving the stats to the DB.
+#   Minimum size shouldn't be under 5
+# 
+sitealizer:
+  access_type: public
+  username: admin
+  password: admin
+  queue_size: 10
diff --git a/vendor/plugins/sitealizer/lib/last_update b/vendor/plugins/sitealizer/lib/last_update
new file mode 100644 (file)
index 0000000..e6e4dc3
--- /dev/null
@@ -0,0 +1 @@
+Tue Aug 28 13:24:45 -0400 2007
diff --git a/vendor/plugins/sitealizer/lib/sitealizer.rb b/vendor/plugins/sitealizer/lib/sitealizer.rb
new file mode 100644 (file)
index 0000000..85ed3b6
--- /dev/null
@@ -0,0 +1,78 @@
+# Copyright (c) 2007 Thiago Jackiw
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+# 
+# The "Created with Sitealizer" footer text should not be removed from the 
+# locations where it's currently shown (under the '/sitealizer' controller)
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+require 'yaml'
+
+require 'app/models/site_tracker'
+require 'app/controllers/sitealizer_controller'
+require 'sitealizer/parser'
+
+SA_CONFIG = YAML::load_file(File.dirname(__FILE__)+'/config.yml') unless defined?(SA_CONFIG)
+
+module Sitealizer
+  
+    def initialize #:nodoc:
+      $visits = [] unless $visits
+    end
+
+    # This is the before_filter method that you will call when
+    # using the Sitealizer Web Stats plugin
+    # 
+    #   class ApplicationController < ActionController::Base
+    #     include Sitealizer
+    #     before_filter :use_sitealizer
+    #   end
+    # 
+    def use_sitealizer
+      $visits << request.env
+      if $visits.size == SA_CONFIG['sitealizer']['queue_size']
+        thread = Thread.start{store_visits}
+        thread.join
+        $visits = []
+      end
+    end
+    
+    private
+    def store_visits
+      begin
+        mutex = Mutex.new
+        mutex.lock
+        $visits.each do |env|
+          SiteTracker.create(
+            :user_agent => env['HTTP_USER_AGENT'],
+            :language => env['HTTP_ACCEPT_LANGUAGE'],
+            :path => env['PATH_INFO'],
+            :ip => env['REMOTE_ADDR'],
+            :referer => env['HTTP_REFERER']
+          )
+        end
+        open(File.dirname(__FILE__)+'/last_update','w'){|f| f.puts Time.now.to_s}
+        mutex.unlock
+      rescue => e
+        RAILS_ENV == 'production' ? logger.info(e) : logger.debug(e)
+      ensure
+        mutex.unlock
+      end
+    end
+
+end
\ No newline at end of file
diff --git a/vendor/plugins/sitealizer/lib/sitealizer/parser.rb b/vendor/plugins/sitealizer/lib/sitealizer/parser.rb
new file mode 100644 (file)
index 0000000..baae881
--- /dev/null
@@ -0,0 +1,347 @@
+# Copyright (c) 2007 Thiago Jackiw
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+# 
+# The "Created with Sitealizer" footer text should not be removed from the 
+# locations where it's currently shown (under the '/sitealizer' controller)
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+require 'uri'
+
+module Sitealizer
+  
+  # The Parser module is used only when processing the stats and
+  # not when saving the user info, this way it won't influence
+  # on your site's performance 
+  # 
+  module Parser
+    
+    class UserAgent
+      
+      # Process the user agent string and returns 
+      # the users's platform:
+      # 
+      #   Sitealizer::Parser::UserAgent.get_platform("(Macintosh; U; PPC Mac OS X; en)")
+      #   => "Macintosh"
+      # 
+      def self.get_platform(user_agent)
+        platform = nil
+        if user_agent =~ /Win/i
+          platform = "Windows"
+        elsif user_agent =~ /Mac/i
+          platform = "Macintosh"
+        elsif user_agent =~ /Linux/i
+          platform = "Linux";
+        elsif user_agent =~ /SunOS/i
+          platform = "Sun Solaris";
+        elsif user_agent =~ /BSD/i
+          platform = "FreeBSD";
+        else
+          platform = "Other"
+        end
+        return platform
+      end
+
+      # Process the user agent string and returns
+      # the user's browser info as a hash:
+      # 
+      #   user_agent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; nl; rv:1.8) Gecko/20051107 Firefox/1.5"
+      #   Sitealizer::Parser::UserAgent.browser_info(user_agent)
+      #   => {:type => 'Firefox', :version => '1.5'}
+      # 
+      def self.browser_info(user_agent)
+        browser = {
+          :type => nil,
+          :version => nil
+        }
+        #Internet Exlorer
+        if user_agent =~ /MSIE/i && user_agent.scan(/AOL|America Online Browser/i).empty?
+          browser[:type] = "MSIE";
+          browser[:version] = user_agent.scan(/MSIE ([\d\.]+)/i).to_s
+        #Firefox/Firebird/Phoenix
+        elsif user_agent =~ /Firefox|Firebird|Phoenix/i
+          browser[:type] = "Firefox";
+          browser[:version] = user_agent.scan(/[Firefox|Firebird|Phoenix].\/(\d.+)/i).to_s
+        #Galeon
+        elsif user_agent =~ /Galeon/i
+          browser[:type] = "Galeon";
+          browser[:version] = user_agent.scan(/Galeon\/([\d\.]+)/i).to_s
+        #Safari
+        elsif user_agent =~ /Safari/i
+          browser[:type] = "Safari";
+          browser[:version] = nil
+        #Opera
+        elsif user_agent =~ /Opera/i
+          browser[:type] = "Opera";
+          browser[:version] = user_agent.scan(/Opera[ |\/]([\d\.]+)/i).to_s
+        #AOL/America Online Browser
+        elsif user_agent =~ /AOL|America Online Browser/i
+          browser[:type] = "AOL"
+          browser[:version] = if user_agent =~ /AOL/i
+              user_agent.scan(/AOL[ |\/]([\d.]+)/i).uniq.to_s
+            else
+              user_agent.scan(/America Online Browser ([\d\.]+)/i).to_s
+           end
+        #Camino
+        elsif user_agent =~ /Camino/i
+          browser[:type] = "Camino";
+          browser[:version] = user_agent.scan(/Camino\/([\d\.]+)/i).to_s
+        #Konqueror
+        elsif user_agent =~ /Konqueror/i
+          browser[:type] = "Konqueror";
+          browser[:version] = user_agent.scan(/Konqueror\/([\d.]+)/i).to_s
+        #K-Meleon
+        elsif user_agent =~ /K-Meleon/i
+          browser[:type] = "K-Meleon";
+          browser[:version] = user_agent.scan(/K-Meleon\/([\d.]+)/i).to_s
+        #Firefox BonEcho
+        elsif user_agent =~ /BonEcho/i
+          browser[:type] = "Firefox BonEcho";
+          browser[:version] = user_agent.scan(/BonEcho\/([\d.]+)/i).to_s
+        #Netscape
+        elsif user_agent =~ /Netscape/i
+          browser[:type] = "Netscape";
+          browser[:version] = user_agent.scan(/Netscape\/([\d.]+)/i).to_s
+        #PSP
+        elsif user_agent =~ /PlayStation Portable/i
+          browser[:type] = "PlayStation Portable (PSP)";
+          browser[:version] = user_agent.scan(/PlayStation Portable\); ([\d\.]+)/i).to_s
+        #PlayStation 3
+        elsif user_agent =~ /PlayStation 3/i
+          browser[:type] = "PlayStation 3";
+          browser[:version] = user_agent.scan(/PlayStation 3; ([\d\.]+)/i).to_s
+        #Lynx
+        elsif user_agent =~ /Lynx/i
+          browser[:type] = "Lynx";
+          browser[:version] = user_agent.scan(/Lynx\/([\d\.]+)/i).to_s
+        else
+          browser[:type] = "Other";
+          browser[:version] = nil
+        end
+        return browser
+      end
+    end
+   
+    class Keyword
+      
+      # Process the referrers and returns
+      # the search terms if they're available:
+      # 
+      #   referer = "http://search.msn.com/results.aspx?srch=105&FORM=AS5&q=sitealizer"
+      #   Sitealizer::Parser::Keyword.get_terms(referer)
+      #   => 'sitealizer'
+      #
+      def self.get_terms(string)
+        return if string.nil?
+        begin
+          search_string = nil
+          domain = URI::split(string)[2]
+          if domain =~ /[google|alltheweb|search\.msn|ask|altavista|]\./ && string =~ /[?|&]q=/i
+            search_string = CGI.unescape(string.scan(/[?|&]q=([^&]*)/).flatten.to_s)
+          elsif domain =~ /yahoo\./i && string =~ /[?|&]p=/i
+            search_string = CGI.unescape(string.scan(/[?|&]p=([^&]*)/).flatten.to_s)
+          elsif domain =~ /search\.aol\./i && string =~ /[?|&]query=/i
+            search_string = CGI.unescape(string.scan(/[?|&]query=([^&]*)/).flatten.to_s)
+          end
+          return search_string          
+        rescue
+          return nil
+        end    
+      end
+      
+      # Process the referrers and returns the referer domain. 
+      # <em>Host</em> is your site's url (request.host) but 
+      # you don't have to worry about this, it's all handled
+      # by the sitealizer controller
+      # 
+      #   referer = "http://search.msn.com/results.aspx?srch=105&FORM=AS5&q=sitealizer"
+      #   Sitealizer::Parser::Keyword.get_domain(referer, 'localhost')
+      #   => "search.msn.com"
+      #
+      def self.get_domain(string, host)
+        return if string.nil?
+        domain = nil
+        domain = URI::split(string)[2]
+        return domain != host ? domain : nil
+      end
+    end
+    
+    class Robot
+      
+      # Process the robots (when available) found on the
+      # user agent strings and returns its name:
+      # 
+      #   user_agent = "Googlebot/2.X (+http://www.googlebot.com/bot.html)"
+      #   Sitealizer::Parser::Robot.get_name(user_agent)
+      #   => "Googlebot"
+      #      
+      def self.get_name(agent)
+        robot = nil
+        if agent =~ /Atomz/i
+          robot = 'Atomz.com'
+        elsif agent =~ /Googlebot/i
+          robot = 'Googlebot'
+        elsif agent =~ /InfoSeek/i
+          robot = 'InfoSeek'
+        elsif agent =~ /Ask Jeeves/i
+          robot = 'Ask Jeeves'
+        elsif agent =~ /Lycos/i
+          robot = 'Lycos'
+        elsif agent =~ /MSNBOT/i
+          robot = 'MSNBot'
+        elsif agent =~ /Slurp/i && agent.scan(/Yahoo/i).empty?
+          robot = 'Inktomi'
+        elsif agent =~ /Yahoo/i
+          robot = 'Yahoo Slurp'
+        end
+        return robot
+      end      
+    end
+    
+    class Language
+
+      # Process the user language and returns the
+      # 'human readable' format if found, otherwise
+      # its raw code gets returned:
+      # 
+      #   Sitealizer::Parser::Language.get_name('en-us')
+      #   => "English/United States"
+      #
+      def self.get_name(lang)
+        lang = lang.scan(/([^,;].*)/).to_s
+        lang = lang.slice(0,5)
+        languages = {"af" => "Afrikaans",
+                     "sq" => "Albanian",
+                     "eu" => "Basque",
+                     "bg" => "Bulgarian",
+                     "be" => "Byelorussian",
+                     "ca" => "Catalan",
+                     "zh" => "Chinese",
+                     "zh-cn" => "Chinese/China",
+                     "zh-tw" => "Chinese/Taiwan",
+                     "zh-hk" => "Chinese/Hong Kong",
+                     "zh-sg" => "Chinese/singapore",
+                     "hr" => "Croatian",
+                     "cs" => "Czech",
+                     "da" => "Danish",
+                     "nl" => "Dutch",
+                     "nl-nl" => "Dutch/Netherlands",
+                     "nl-be" => "Dutch/Belgium",
+                     "en" => "English",
+                     "en-gb" => "English/United Kingdom",
+                     "en-us" => "English/United States",
+                     "en-au" => "English/Australian",
+                     "en-ca" => "English/Canada",
+                     "en-nz" => "English/New Zealand",
+                     "en-ie" => "English/Ireland",
+                     "en-za" => "English/South Africa",
+                     "en-jm" => "English/Jamaica",
+                     "en-bz" => "English/Belize",
+                     "en-tt" => "English/Trinidad",
+                     "et" => "Estonian",
+                     "fo" => "Faeroese",
+                     "fa" => "Farsi",
+                     "fi" => "Finnish",
+                     "fr" => "French",
+                     "fr-be" => "French/Belgium",
+                     "fr-fr" => "French/France",
+                     "fr,fr" => "French/France",
+                     "fr-ch" => "French/Switzerland",
+                     "fr-ca" => "French/Canada",
+                     "fr-lu" => "French/Luxembourg",
+                     "gd" => "Gaelic",
+                     "gl" => "Galician",
+                     "de" => "German",
+                     "de-at" => "German/Austria",
+                     "de-de" => "German/Germany",
+                     "de-ch" => "German/Switzerland",
+                     "de-lu" => "German/Luxembourg",
+                     "de-li" => "German/Liechtenstein",
+                     "el" => "Greek",
+                     "he" => "Hebrew",
+                     "he-il" => "Hebrew/Israel",
+                     "hi" => "Hindi",
+                     "hu" => "Hungarian",
+                     "ie-ee" => "Internet Explorer/Easter Egg",
+                     "is" => "Icelandic",
+                     "id" => "Indonesian",
+                     "in" => "Indonesian",
+                     "ga" => "Irish",
+                     "it" => "Italian",
+                     "it-ch" => "Italian/ Switzerland",
+                     "ja" => "Japanese",
+                     "ko" => "Korean",
+                     "lv" => "Latvian",
+                     "lt" => "Lithuanian",
+                     "mk" => "Macedonian",
+                     "ms" => "Malaysian",
+                     "mt" => "Maltese",
+                     "no" => "Norwegian",
+                     "pl" => "Polish",
+                     "pt-pt" => "Portuguese",
+                     "pt-br" => "Portuguese/Brazil",
+                     "rm" => "Rhaeto-Romanic",
+                     "ro" => "Romanian",
+                     "ro-mo" => "Romanian/Moldavia",
+                     "ru-ru" => "Russian",
+                     "ru-mo" => "Russian /Moldavia",
+                     "gd" => "Scots Gaelic",
+                     "sr" => "Serbian",
+                     "sk" => "Slovack",
+                     "sl" => "Slovenian",
+                     "sb" => "Sorbian",
+                     "es" => "Spanish",
+                     "es-do" => "Spanish",
+                     "es-ar" => "Spanish/Argentina",
+                     "es-co" => "Spanish/Colombia",
+                     "es-mx" => "Spanish/Mexico",
+                     "es-es" => "Spanish/Spain",
+                     "es-gt" => "Spanish/Guatemala",
+                     "es-cr" => "Spanish/Costa Rica",
+                     "es-pa" => "Spanish/Panama",
+                     "es-ve" => "Spanish/Venezuela",
+                     "es-pe" => "Spanish/Peru",
+                     "es-ec" => "Spanish/Ecuador",
+                     "es-cl" => "Spanish/Chile",
+                     "es-uy" => "Spanish/Uruguay",
+                     "es-py" => "Spanish/Paraguay",
+                     "es-bo" => "Spanish/Bolivia",
+                     "es-sv" => "Spanish/El salvador",
+                     "es-hn" => "Spanish/Honduras",
+                     "es-ni" => "Spanish/Nicaragua",
+                     "es-pr" => "Spanish/Puerto Rico",
+                     "sx" => "Sutu",
+                     "sv" => "Swedish",
+                     "sv-se" => "Swedish/Sweden",
+                     "sv-fi" => "Swedish/Finland",
+                     "ts" => "Thai",
+                     "tn" => "Tswana",
+                     "tr" => "Turkish",
+                     "uk" => "Ukrainian",
+                     "ur" => "Urdu",
+                     "vi" => "Vietnamese",
+                     "xh" => "Xshosa",
+                     "ji" => "Yiddish",
+                     "zu" => "Zulu"}
+        return languages.fetch(lang, lang) 
+      end
+    end
+    
+  end
+  
+end
\ No newline at end of file
diff --git a/vendor/plugins/sitealizer/lib/tasks/sitealizer.rake b/vendor/plugins/sitealizer/lib/tasks/sitealizer.rake
new file mode 100644 (file)
index 0000000..c103377
--- /dev/null
@@ -0,0 +1,36 @@
+namespace :sitealizer do
+  desc "Removes the old 'sitemeter' and import the stored stats to Sitealizer"
+  task :remove_sitemeter => :environment do
+    ActiveRecord::Schema.drop_table('sitealizer') if SiteTracker.count == 0
+    if ActiveRecord::Schema.tables.include?('sitemeter') && !ActiveRecord::Schema.tables.include?('sitealizer')
+      ActiveRecord::Schema.rename_table('sitemeter','sitealizer')
+      puts "Sitealizer => Completed renaming table from 'sitemeter' to 'sitealizer'" 
+    end
+    ['/public/images/sitemeter','/vendor/plugins/sitemeter'].each do |path|
+      if File.exists?(RAILS_ROOT + path)
+        FileUtils.rm_rf(RAILS_ROOT + path)
+        puts "Sitealizer => Completed removing 'sitemeter' files from " + path 
+      end
+    end
+  end
+  
+  desc "Updates Sitealizer to the latest version"
+  task :update do
+    $verbose = false
+    `svn --version` rescue nil
+    unless !$?.nil? && $?.success?
+      $stderr.puts "ERROR: Must have subversion (svn) available in the PATH to update your Sitealizer plugin"
+      exit 1
+    end
+    FileUtils.rm_rf(RAILS_ROOT+"vendor/plugins/sitealizer")
+    system("svn export http://opensvn.csie.org/sitealizer vendor/plugins/sitealizer")
+    system("ruby vendor/plugins/sitealizer/install.rb")
+  end
+  
+  desc "Removes the Sitealizer plugin"
+  task :uninstall => :environment do
+    ActiveRecord::Schema.drop_table('sitealizer') if ActiveRecord::Schema.tables.include?('sitealizer')
+    FileUtils.rm_rf(RAILS_ROOT+'/vendor/plugins/sitemeter') if File.exists?(RAILS_ROOT+'/vendor/plugins/sitemeter')
+    puts "Sitealizer => plugin uninstalled\n\n"
+  end
+end
\ No newline at end of file
diff --git a/vendor/plugins/sitealizer/test/fixtures/sitealizer.yml b/vendor/plugins/sitealizer/test/fixtures/sitealizer.yml
new file mode 100644 (file)
index 0000000..8ec5106
--- /dev/null
@@ -0,0 +1,89 @@
+one:
+  id: 1
+  path: /account
+  ip: 123.4.5.678
+  referer: <%=nil%>
+  language: en
+  user_agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418.9.1 (KHTML, like Gecko) Safari/419.3
+  created_at: 2007-03-01 00:08:47
+  created_on: 2007-03-01
+  
+two:
+  id: 2
+  path: /
+  ip: 41.41.41.41
+  referer: http://search.yahoo.com/search?p=sitealizer&fr=yfp-t-501&toggle=1&cop=mss&ei=UTF-8
+  language: en
+  user_agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)
+  created_at: 2007-03-01 00:38:47
+  created_on: 2007-03-01
+
+three:
+  id: 3
+  path: /account
+  ip: 41.41.41.41
+  referer: /
+  language: en
+  user_agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)
+  created_at: 2007-03-01 00:39:15
+  created_on: 2007-03-01
+
+four:
+  id: 4
+  path: /
+  ip: 31.31.31.31
+  referer: http://www.altavista.com/web/results?itag=ody&q=sitealizer+rails+plugin&kgs=1&kls=0
+  language: fr-fr
+  user_agent: Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 6.0)
+  created_at: 2007-03-02 00:05:47
+  created_on: 2007-03-02
+
+five:
+  id: 5
+  path: /
+  ip: 51.51.51.51
+  referer: http://search.aol.com/aolcom/search?invocationType=topsearchbox.search&query=sitealizer
+  language: pt-pt
+  user_agent: Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 6.0)
+  created_at: <%=20.hours.ago.to_s(:db)%>
+  created_on: <%=20.hours.ago.to_s(:db)%>
+  
+six:
+  id: 6
+  path: /
+  ip: 3.3.3.3
+  referer: http://search.aol.com/aolcom/search?invocationType=topsearchbox.search&query=sitealizer
+  language: en
+  user_agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)
+  created_at: <%=16.hours.ago.to_s(:db)%>
+  created_on: <%=16.hours.ago.to_s(:db)%>
+  
+msnbot:
+  id: 7
+  path: /
+  ip: 2.2.2.2
+  referer: <%=nil%>
+  language: <%=nil%>
+  user_agent: MSNBOT/0.1 (http://search.msn.com/msnbot.htm)
+  created_at: <%=15.hours.ago.to_s(:db)%>
+  created_on: <%=15.hours.ago.to_s(:db)%>
+  
+googlebot:
+  id: 8
+  path: /
+  ip: 1.1.1.1
+  referer: <%=nil%>
+  language: <%=nil%>
+  user_agent: Googlebot/2.X (+http://www.googlebot.com/bot.html)
+  created_at: <%=12.hours.ago.to_s(:db)%>
+  created_on: <%=12.hours.ago.to_s(:db)%>
+
+googlebot2:
+  id: 9
+  path: /
+  ip: 1.1.1.1
+  referer: <%=nil%>
+  language: <%=nil%>
+  user_agent: Googlebot/2.X (+http://www.googlebot.com/bot.html)
+  created_at: <%=5.hours.ago.to_s(:db)%>
+  created_on: <%=5.hours.ago.to_s(:db)%>
\ No newline at end of file
diff --git a/vendor/plugins/sitealizer/test/sitealizer_controller_test.rb b/vendor/plugins/sitealizer/test/sitealizer_controller_test.rb
new file mode 100644 (file)
index 0000000..17270cd
--- /dev/null
@@ -0,0 +1,208 @@
+require File.dirname(__FILE__) + '/test_helper'
+
+class SitealizerController 
+  def rescue_action(e) raise e end
+  SA_CONFIG   = {'sitealizer' => {'username' => 'test', 'password' => 'test', 'access_type' => 'public'}}
+end
+
+class SitealizerControllerTest < Test::Unit::TestCase
+  set_fixture_class :sitealizer => 'SiteTracker'
+  fixtures :sitealizer
+  
+  def setup
+    @controller = SitealizerController.new
+    @request    = ActionController::TestRequest.new
+    @response   = ActionController::TestResponse.new
+  end
+
+  def test_login
+    get :login
+    assert_template 'login'
+    
+    post :login, :username => 'test', :password => 'test'
+    assert_response :redirect
+    assert_redirected_to :action => 'index'
+    assert_not_nil @response.cookies["sitealizer"][0]
+  end
+  
+  def test_login_fails
+    post :login, :username => 'me', :password => 'me'
+    assert_not_nil flash[:notice]
+    assert_template 'login'
+  end
+  
+  def test_logout
+    get :logout
+    assert @response.cookies["sitealizer"].empty?
+    assert_response :redirect
+    assert_redirected_to :action => 'login'
+  end
+  
+  def test_index
+    get :index
+    assert_template 'index'
+    get :index, :year => '2006', :month => '03'
+    assert_template 'index'
+  end
+  
+  def test_menu
+    get :menu
+    assert_template 'menu'
+    assert_not_nil assigns(:months)
+    assert_not_nil assigns(:years)
+  end
+  
+  def test_summary
+    get :summary
+    assert_equal 9, assigns(:total_hits)
+    assert_equal 7, assigns(:unique_hits)
+    assert_equal 9, assigns(:year_hits)
+    assert_equal 7, assigns(:year_uniq)  
+    assert_equal [1, 2, 3, "Mar 01 2007"], assigns(:daily_hits).first
+    assert_equal ["Mar 2007", 7, 9, "March 2007"], assigns(:month_hits)[2]
+    assert_template 'summary'
+  end
+
+  def test_summary_no_records
+    get :summary, :year => '2006', :month => '01'
+    [:total_hits, :unique_hits, :year_hits, :year_uniq].each do |var|
+      assert_equal 0, assigns(var)
+    end
+    
+    expected = [[1, 0, 0, "Jan 01 2006"], [2, 0, 0, "Jan 02 2006"], [3, 0, 0, "Jan 03 2006"], 
+                [4, 0, 0, "Jan 04 2006"], [5, 0, 0, "Jan 05 2006"], [6, 0, 0, "Jan 06 2006"], 
+                [7, 0, 0, "Jan 07 2006"], [8, 0, 0, "Jan 08 2006"], [9, 0, 0, "Jan 09 2006"], 
+                [10, 0, 0, "Jan 10 2006"], [11, 0, 0, "Jan 11 2006"], [12, 0, 0, "Jan 12 2006"], 
+                [13, 0, 0, "Jan 13 2006"], [14, 0, 0, "Jan 14 2006"], [15, 0, 0, "Jan 15 2006"], 
+                [16, 0, 0, "Jan 16 2006"], [17, 0, 0, "Jan 17 2006"], [18, 0, 0, "Jan 18 2006"], 
+                [19, 0, 0, "Jan 19 2006"], [20, 0, 0, "Jan 20 2006"], [21, 0, 0, "Jan 21 2006"], 
+                [22, 0, 0, "Jan 22 2006"], [23, 0, 0, "Jan 23 2006"], [24, 0, 0, "Jan 24 2006"], 
+                [25, 0, 0, "Jan 25 2006"], [26, 0, 0, "Jan 26 2006"], [27, 0, 0, "Jan 27 2006"], 
+                [28, 0, 0, "Jan 28 2006"], [29, 0, 0, "Jan 29 2006"], [30, 0, 0, "Jan 30 2006"], 
+                [31, 0, 0, "Jan 31 2006"]]
+    assert_equal expected, assigns(:daily_hits)
+
+    expected = [["Jan 2006", 0, 0, "January 2006"], ["Feb 2006", 0, 0, "February 2006"], 
+                ["Mar 2006", 0, 0, "March 2006"], ["Apr 2006", 0, 0, "April 2006"], 
+                ["May 2006", 0, 0, "May 2006"], ["Jun 2006", 0, 0, "June 2006"], 
+                ["Jul 2006", 0, 0, "July 2006"], ["Aug 2006", 0, 0, "August 2006"], 
+                ["Sep 2006", 0, 0, "September 2006"], ["Oct 2006", 0, 0, "October 2006"], 
+                ["Nov 2006", 0, 0, "November 2006"], ["Dec 2006", 0, 0, "December 2006"]]
+    assert_equal expected, assigns(:month_hits)
+    
+    assert_template 'summary'
+  end
+
+  def test_hourly_stats
+    get :hourly_stats
+    assert_equal 9, assigns(:total_hits)
+    
+    # Hour, Visits, Hits
+    assert_equal ["00", 3, 4], assigns(:hourly_hits).first
+    assert_template 'hourly_stats'
+  end
+  
+  def test_hourly_stats_no_records
+    get :hourly_stats, :year => '2006', :month => '01'
+    expected = [["00", 0, 0], ["01", 0, 0], ["02", 0, 0], ["03", 0, 0], ["04", 0, 0], ["05", 0, 0], 
+                ["06", 0, 0], ["07", 0, 0], ["08", 0, 0], ["09", 0, 0], ["10", 0, 0], ["11", 0, 0], 
+                ["12", 0, 0], ["13", 0, 0], ["14", 0, 0], ["15", 0, 0], ["16", 0, 0], ["17", 0, 0], 
+                ["18", 0, 0], ["19", 0, 0], ["20", 0, 0], ["21", 0, 0], ["22", 0, 0], ["23", 0, 0]]
+    assert_equal expected, assigns(:hourly_hits)
+    assert_template 'hourly_stats'
+  end
+  
+  def test_search_stats
+    get :search_stats
+
+    assert_equal 2, assigns(:keywords).size
+    expected = [{:total => 3, :query => "sitealizer"},{:total => 1, :query => "sitealizer rails plugin"}]
+    expected.each do |term|
+      assert_equal term, assigns(:keywords)[expected.index(term)]
+    end    
+    
+    assert_equal 2, assigns(:robots).size
+    expected = [{:total => 2, :name => "Googlebot"},{:total => 1, :name => "MSNBot"}]
+    expected.each do |robot|
+      assert_equal robot, assigns(:robots)[expected.index(robot)]
+    end
+
+    assert_equal 3, assigns(:engines).size
+    expected = [{:total=>2, :domain=>"search.aol.com"}, {:total=>1, :domain=>"www.altavista.com"}, 
+                {:total=>1, :domain=>"search.yahoo.com"}]
+    expected.each do |engine|
+      assert_equal engine, assigns(:engines)[expected.index(engine)]
+    end
+    
+    assert_template 'search_stats'
+  end
+  
+  def test_search_stats_no_records
+    get :search_stats, :year => '2006', :month => '01'
+    [:keywords, :engines, :robots].each do |var|
+      assert assigns(var).empty?
+    end
+    assert_template 'search_stats'    
+  end
+  
+  def test_visitor_info
+    get :visitor_info
+    
+    assert_equal 4, assigns(:browsers).size
+    expected = ["Netscape","Other","MSIE","Safari"]
+    expected.each do |browser|
+      assert_equal browser, assigns(:browsers)[expected.index(browser)][:browser][:type]
+    end
+    
+    assert_equal 3, assigns(:platforms).size
+    expected = ["Windows","Other","Macintosh"]
+    expected.each do |platform|
+      assert_equal platform, assigns(:platforms)[expected.index(platform)][:name]
+    end
+    
+    assert_equal 7, assigns(:hosts).size
+    expected = ["41.41.41.41","1.1.1.1","123.4.5.678","31.31.31.31","51.51.51.51","3.3.3.3","2.2.2.2"]
+    expected.each do |host|
+      assert_equal host, assigns(:hosts)[expected.index(host)]["ip"]
+    end
+    
+    assert_equal 4, assigns(:languages).size
+    expected = ["en",nil,"fr-fr","pt-pt"]
+    expected.each do |language|
+      assert_equal language, assigns(:languages)[expected.index(language)][:language]
+    end
+    
+    assert_template 'visitor_info'
+  end
+  
+  def test_visitor_info_no_records
+    get :visitor_info, :year => '2006', :month => '01'
+    assert_equal 0, assigns(:total_hits)
+    [:browsers, :platforms, :hosts, :languages].each do |var|
+      assert assigns(var).empty?
+    end
+    assert_template 'visitor_info'    
+  end
+  
+  def test_referrer_stats
+    get :referrer_stats
+    assert_not_nil assigns(:page_urls)
+    assert_equal 2, assigns(:page_urls).size
+    [[0,"/"],[1,"/account"]].each do |page|
+      assert_equal page[1], assigns(:page_urls)[page[0]].path
+    end
+    assert_not_nil assigns(:referers)
+    assert_equal 5, assigns(:referers).size
+    assert_template 'referrer_stats'
+  end
+  
+  def test_referrer_stats_no_records
+    get :referrer_stats, :year => '2007', :month => '01'
+    assert_equal 0, assigns(:total_hits)
+    [:page_urls, :referers].each do |var|
+      assert assigns(var).empty?
+    end
+    assert_template 'referrer_stats'
+  end
+  
+end
diff --git a/vendor/plugins/sitealizer/test/sitealizer_parser_test.rb b/vendor/plugins/sitealizer/test/sitealizer_parser_test.rb
new file mode 100644 (file)
index 0000000..16a1ff6
--- /dev/null
@@ -0,0 +1,169 @@
+require 'test/unit'
+require 'cgi'
+require File.dirname(__FILE__) + '/../lib/sitealizer/parser'
+
+class SitealizerParserTest < Test::Unit::TestCase
+  
+  def test_user_agent_platform
+    user_agent = "(Macintosh; U; PPC Mac OS X; en)"
+    assert_equal "Macintosh", Sitealizer::Parser::UserAgent.get_platform(user_agent)
+    
+    user_agent = "(Windows; U; Windows NT 5.1; nl; rv:1.8)"
+    assert_equal "Windows", Sitealizer::Parser::UserAgent.get_platform(user_agent)
+    
+    user_agent = "(X11; U; Linux i686; en-US; rv:1.8.0.2)"
+    assert_equal "Linux", Sitealizer::Parser::UserAgent.get_platform(user_agent)
+    
+    user_agent = "(compatible; MSIE 5.0; SunOS 5.9 sun4u; X11)"
+    assert_equal "Sun Solaris", Sitealizer::Parser::UserAgent.get_platform(user_agent)
+    
+    user_agent = "X11; U; FreeBSD i386; en-US; rv:1.7.8)"
+    assert_equal "FreeBSD", Sitealizer::Parser::UserAgent.get_platform(user_agent)
+    
+    user_agent = "Some unknown user agent"
+    assert_equal "Other", Sitealizer::Parser::UserAgent.get_platform(user_agent)
+  end
+  
+  def test_user_agent_browser
+    user_agent = "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418.9.1 (KHTML, like Gecko) Safari/419.3"
+    assert_equal({:type => 'Safari', :version => nil}, 
+                 Sitealizer::Parser::UserAgent.browser_info(user_agent))
+    
+    user_agent = "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.1) Gecko/20061026 BonEcho/2.0"
+    assert_equal({:type => 'Firefox BonEcho', :version => '2.0'}, 
+                 Sitealizer::Parser::UserAgent.browser_info(user_agent))
+
+    user_agent = "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 6.0)"
+    assert_equal({:type => 'MSIE', :version => '7.0'}, 
+                 Sitealizer::Parser::UserAgent.browser_info(user_agent))
+    
+    user_agent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; nl; rv:1.8) Gecko/20051107 Firefox/1.5"
+    assert_equal({:type => 'Firefox', :version => '1.5'}, 
+                 Sitealizer::Parser::UserAgent.browser_info(user_agent))
+    
+    user_agent = "Mozilla/5.0 (Windows NT 5.1; U; en) Opera 8.50"
+    assert_equal({:type => 'Opera', :version => '8.50'}, 
+                 Sitealizer::Parser::UserAgent.browser_info(user_agent))
+    
+    user_agent = "Mozilla/4.0 (compatible; MSIE 6.0; America Online Browser 1.1; rev1.2; Windows NT 5.1;)"
+    assert_equal({:type => 'AOL', :version => '1.1'}, 
+                 Sitealizer::Parser::UserAgent.browser_info(user_agent))
+    
+    user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; AOL 6.0; Windows 98)"
+    assert_equal({:type => 'AOL', :version => '6.0'}, 
+                 Sitealizer::Parser::UserAgent.browser_info(user_agent))
+    
+    user_agent = "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.0.3) Gecko/20060427 Camino/1.0.1"
+    assert_equal({:type => 'Camino', :version => '1.0.1'}, 
+                 Sitealizer::Parser::UserAgent.browser_info(user_agent))
+    
+    user_agent = "Mozilla/5.0 (compatible; Konqueror/3.4; Linux) KHTML/3.4.2 (like Gecko)"
+    assert_equal({:type => 'Konqueror', :version => '3.4'}, 
+                 Sitealizer::Parser::UserAgent.browser_info(user_agent))
+    
+    user_agent = "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.7.13) Gecko/20050610 K-Meleon/0.9"
+    assert_equal({:type => 'K-Meleon', :version => '0.9'}, 
+                 Sitealizer::Parser::UserAgent.browser_info(user_agent))
+    
+    user_agent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)"
+    assert_equal({:type => 'Netscape', :version => '7.1'}, 
+                 Sitealizer::Parser::UserAgent.browser_info(user_agent))
+    
+    user_agent = "Mozilla/4.0 (PSP (PlayStation Portable); 2.00)"
+    assert_equal({:type => 'PlayStation Portable (PSP)', :version => '2.00'}, 
+                 Sitealizer::Parser::UserAgent.browser_info(user_agent))
+    
+    user_agent = "Mozilla/5.0 (PLAYSTATION 3; 1.00)"
+    assert_equal({:type => 'PlayStation 3', :version => '1.00'}, 
+                 Sitealizer::Parser::UserAgent.browser_info(user_agent))
+    
+    user_agent = "Lynx/2.8.5rel.1 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.8a"
+    assert_equal({:type => 'Lynx', :version => '2.8.5'}, 
+                 Sitealizer::Parser::UserAgent.browser_info(user_agent))
+    
+    user_agent = "Another user agent"
+    assert_equal({:type => 'Other', :version => nil}, 
+                 Sitealizer::Parser::UserAgent.browser_info(user_agent))
+    
+  end
+  
+  def test_keyword_get_terms
+    referer = "http://search.yahoo.com/search?p=sitealizer&fr=yfp-t-501&toggle=1&cop=mss&ei=UTF-8"
+    assert_equal "sitealizer", Sitealizer::Parser::Keyword.get_terms(referer)
+    
+    referer = "http://search.msn.com/results.aspx?srch=105&FORM=AS5&q=sitealizer"
+    assert_equal "sitealizer", Sitealizer::Parser::Keyword.get_terms(referer)
+    
+    referer = "http://www.google.com/search?sourceid=navclient&ie=UTF-8&rlz=1T4DMUS_enUS202US205&q=sitealizer"
+    assert_equal "sitealizer", Sitealizer::Parser::Keyword.get_terms(referer)
+    
+    referer = "http://search.aol.com/aolcom/search?invocationType=topsearchbox.search&query=sitealizer"
+    assert_equal "sitealizer", Sitealizer::Parser::Keyword.get_terms(referer)
+    
+    referer = "http://alltheweb.com/search?cat=web&cs=iso88591&q=sitealizer&rys=0&itag=crv&_sb_lang=pref"
+    assert_equal "sitealizer", Sitealizer::Parser::Keyword.get_terms(referer)
+    
+    referer = "http://www.ask.com/web?q=sitealizer&qsrc=0&o=333&l=dir"
+    assert_equal "sitealizer", Sitealizer::Parser::Keyword.get_terms(referer)
+    
+    referer = "http://www.altavista.com/web/results?itag=ody&q=sitealizer&kgs=1&kls=0"
+    assert_equal "sitealizer", Sitealizer::Parser::Keyword.get_terms(referer)
+  end
+  
+  def test_keyword_get_domain
+    referer = "http://search.yahoo.com/search?p=sitealizer&fr=yfp-t-501&toggle=1&cop=mss&ei=UTF-8"
+    assert_equal "search.yahoo.com", Sitealizer::Parser::Keyword.get_domain(referer, 'localhost')
+    
+    referer = "http://search.msn.com/results.aspx?srch=105&FORM=AS5&q=sitealizer"
+    assert_equal "search.msn.com", Sitealizer::Parser::Keyword.get_domain(referer, 'localhost')
+    
+    referer = "http://www.google.com/search?sourceid=navclient&ie=UTF-8&rlz=1T4DMUS_enUS202US205&q=sitealizer"
+    assert_equal "www.google.com", Sitealizer::Parser::Keyword.get_domain(referer, 'localhost')
+    
+    referer = "http://search.aol.com/aolcom/search?invocationType=topsearchbox.search&query=sitealizer"
+    assert_equal "search.aol.com", Sitealizer::Parser::Keyword.get_domain(referer, 'localhost')
+    
+    referer = "http://alltheweb.com/search?cat=web&cs=iso88591&q=sitealizer&rys=0&itag=crv&_sb_lang=pref"
+    assert_equal "alltheweb.com", Sitealizer::Parser::Keyword.get_domain(referer, 'localhost')
+    
+    referer = "http://www.ask.com/web?q=sitealizer&qsrc=0&o=333&l=dir"
+    assert_equal "www.ask.com", Sitealizer::Parser::Keyword.get_domain(referer, 'localhost')
+    
+    referer = "http://www.altavista.com/web/results?itag=ody&q=sitealizer&kgs=1&kls=0"
+    assert_equal "www.altavista.com", Sitealizer::Parser::Keyword.get_domain(referer, 'localhost')
+  end
+  
+  def test_robot_get_name
+    user_agent = "Atomz/1.0"
+    assert_equal "Atomz.com", Sitealizer::Parser::Robot.get_name(user_agent)
+    
+    user_agent = "Googlebot/2.X (+http://www.googlebot.com/bot.html)"
+    assert_equal "Googlebot", Sitealizer::Parser::Robot.get_name(user_agent)
+    
+    user_agent = "InfoSeek Robot 1.0"
+    assert_equal "InfoSeek", Sitealizer::Parser::Robot.get_name(user_agent)
+    
+    user_agent = "Mozilla/2.0 (compatible; Ask Jeeves/Teoma)"
+    assert_equal "Ask Jeeves", Sitealizer::Parser::Robot.get_name(user_agent)
+    
+    user_agent = "Lycos/x."
+    assert_equal "Lycos", Sitealizer::Parser::Robot.get_name(user_agent)
+    
+    user_agent = "MSNBOT/0.1 (http://search.msn.com/msnbot.htm)"
+    assert_equal "MSNBot", Sitealizer::Parser::Robot.get_name(user_agent)
+    
+    user_agent = "Slurp/2.0"
+    assert_equal "Inktomi", Sitealizer::Parser::Robot.get_name(user_agent)
+    
+    user_agent = "Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp )"
+    assert_equal "Yahoo Slurp", Sitealizer::Parser::Robot.get_name(user_agent)
+  end
+  
+  def test_language_get_name
+    [["en","English"],["pt-pt","Portuguese"],["en-nz","English/New Zealand"],["es-mx","Spanish/Mexico",],
+     ["ru-ru","Russian"],["de-at","German/Austria"],["fr-fr","French/France"],["zh-cn","Chinese/China"]].each do |l|
+      assert_equal l[1], Sitealizer::Parser::Language.get_name(l[0])
+    end
+  end
+  
+end
diff --git a/vendor/plugins/sitealizer/test/test_helper.rb b/vendor/plugins/sitealizer/test/test_helper.rb
new file mode 100644 (file)
index 0000000..dc92338
--- /dev/null
@@ -0,0 +1,7 @@
+require File.dirname(__FILE__) + '/../../../../config/environment'
+require 'rubygems'
+require 'test/unit'
+require 'active_record/fixtures'
+require 'action_controller/test_process'
+
+Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures/"
\ No newline at end of file

Benjamin Mako Hill || Want to submit a patch?