user_agent_sanitizer 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +20 -0
- data/README.md +45 -0
- data/Rakefile +45 -0
- data/lib/user_agent_sanitizer.rb +62 -0
- data/spec/spec_helper.rb +0 -0
- data/spec/user_agent_sanitizer_spec.rb +52 -0
- data/user_agent_sanitizer.gemspec +25 -0
- metadata +59 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Wes Oldenbeuving
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
User agent sanitizer
|
2
|
+
====================
|
3
|
+
|
4
|
+
Parse a HTTP user agent and attempt to return something that means something to a human.
|
5
|
+
|
6
|
+
Example:
|
7
|
+
|
8
|
+
require 'user_agent_sanitizer'
|
9
|
+
|
10
|
+
UserAgentSanitizer.sanitize_user_agent('Mozilla/5.0 (iPhone; CPU iPhone OS 5_0_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A405 Safari/7534.48.3')
|
11
|
+
# => 'iPhone'
|
12
|
+
|
13
|
+
UserAgentSanitizer.sanitize_user_agent('Mozilla/5.0 (Linux; U; Android 2.3.3; nl-nl; SAMSUNG GT-I9100/I9100BUKE5 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1')
|
14
|
+
# => 'Samsung GT-I9100'
|
15
|
+
|
16
|
+
Installation
|
17
|
+
------------
|
18
|
+
|
19
|
+
Via rubygems
|
20
|
+
|
21
|
+
gem install user_agent_sanitizer
|
22
|
+
|
23
|
+
Bundler:
|
24
|
+
|
25
|
+
# Gemfile
|
26
|
+
gem 'user_agent_sanitizer'
|
27
|
+
|
28
|
+
From source:
|
29
|
+
|
30
|
+
rake install
|
31
|
+
|
32
|
+
New devices
|
33
|
+
-----------
|
34
|
+
|
35
|
+
Every time I encounter a new user agent that does not resolve to something useful, I add it as a test case and tweak the parser until all tested headers are correctly parsed. See [the spec](http://github.com/Narnach/user_agent_sanitizer/blob/master/spec/user_agent_sanitizer_spec.rb)
|
36
|
+
|
37
|
+
Contributing
|
38
|
+
------------
|
39
|
+
|
40
|
+
Create a Github issue and/or send a pull request.
|
41
|
+
|
42
|
+
Contributors
|
43
|
+
------------
|
44
|
+
|
45
|
+
* [Wes 'Narnach' Oldenbeuving](http://narnach.com/)
|
data/Rakefile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rdoc/task'
|
3
|
+
require "rake/gempackagetask"
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Generate documentation for the file_wrapper plugin.'
|
9
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'FileWrapper'
|
12
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
13
|
+
rdoc.rdoc_files.include('README')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
begin
|
18
|
+
# Parse gemspec using the github safety level.
|
19
|
+
data = File.read('user_agent_sanitizer.gemspec')
|
20
|
+
spec = nil
|
21
|
+
Thread.new { spec = eval("$SAFE = 3\n%s" % data)}.join
|
22
|
+
|
23
|
+
# Create the gem tasks
|
24
|
+
Rake::GemPackageTask.new(spec) do |package|
|
25
|
+
package.gem_spec = spec
|
26
|
+
end
|
27
|
+
rescue Exception => e
|
28
|
+
printf "WARNING: Error caught (%s): %s\n", e.class.name, e.message
|
29
|
+
end
|
30
|
+
|
31
|
+
desc 'Package and install the gem for the current version'
|
32
|
+
task :install => :gem do
|
33
|
+
system "sudo gem install -l pkg/file_wrapper-%s.gem" % spec.version
|
34
|
+
end
|
35
|
+
|
36
|
+
require 'rspec/core/rake_task'
|
37
|
+
|
38
|
+
desc 'Default: run specs.'
|
39
|
+
task :default => :spec
|
40
|
+
|
41
|
+
desc "Run specs"
|
42
|
+
RSpec::Core::RakeTask.new do |t|
|
43
|
+
t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
|
44
|
+
# Put spec opts in a file named .rspec in root
|
45
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module UserAgentSanitizer
|
2
|
+
extend self
|
3
|
+
|
4
|
+
BRANDS=["nokia", "samsung", "SonyEricsson", "BlackBerry", "htc", "sec", 'gt', 'iphone']
|
5
|
+
|
6
|
+
def sanitize_user_agent(string)
|
7
|
+
string = string.to_s
|
8
|
+
return nil if string.empty?
|
9
|
+
result = basic_user_agent_recognizer(string)
|
10
|
+
result.gsub!(/^SAMSUNG/i, 'Samsung')
|
11
|
+
result.gsub!(/^GT/i, 'Samsung GT')
|
12
|
+
result.gsub!(/^Samsung GT\s+/i, 'Samsung GT-')
|
13
|
+
result.gsub!(/^Desire(_\w+)/i, 'HTC Desire')
|
14
|
+
result = "SonyEricsson #{$1}" if result =~ /^SonyEricsson(\w+)/i
|
15
|
+
result.strip!
|
16
|
+
result.squeeze!(" ")
|
17
|
+
result
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def basic_user_agent_recognizer(string)
|
23
|
+
case string
|
24
|
+
when /(Mac OS X) (\d+_\d+_\d+)/
|
25
|
+
return "#{$1} #{$2.gsub("_", ".")}"
|
26
|
+
when /(LG|sagem)[\-\/](\w+)/i
|
27
|
+
return "#{$1} #{$2}"
|
28
|
+
when /(MSIE) (\d+(\.\d+)*)/
|
29
|
+
return "#{$1} #{$2}"
|
30
|
+
when /(Blackberry) ?(\d+)/i
|
31
|
+
return "#{$1} #{$2}"
|
32
|
+
when /(HTC)[_\/]([a-z0-9]+)?/i
|
33
|
+
return [$1, $2].compact.join(" ")
|
34
|
+
when /(Samsung)[\/\-]([a-z0-9]+)([\/\-]([a-z0-9]+))?/i
|
35
|
+
return [$1, $2, $4].compact.join(" ")
|
36
|
+
when /\((Linux; U; Android.*)\)/
|
37
|
+
return $1.split(";").last.split("/").first.gsub(/build/i, "").strip
|
38
|
+
when /(iPod)/
|
39
|
+
return $1
|
40
|
+
when /((#{BRANDS.join("|")}).*?)\//i
|
41
|
+
result=$1
|
42
|
+
|
43
|
+
result.gsub!(/build/i, "")
|
44
|
+
result.gsub!(/-1/, "")
|
45
|
+
result.gsub!(/-/, " ")
|
46
|
+
|
47
|
+
if result=~/(.+?);/
|
48
|
+
result = $1
|
49
|
+
end
|
50
|
+
|
51
|
+
if result=~/(\D+)([A-Z]+\d+)/
|
52
|
+
result="#{$1} #{$2}"
|
53
|
+
elsif result=~/(\D+)(\d+)/
|
54
|
+
result="#{$1} #{$2}"
|
55
|
+
end
|
56
|
+
|
57
|
+
return result
|
58
|
+
else
|
59
|
+
return string
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/spec/spec_helper.rb
ADDED
File without changes
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'user_agent_sanitizer'
|
4
|
+
|
5
|
+
describe UserAgentSanitizer do
|
6
|
+
describe "sanitize_user_agent" do
|
7
|
+
{
|
8
|
+
'BlackBerry8520/4.6.1.296 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/150' => 'BlackBerry 8520',
|
9
|
+
'BlackBerry8900/4.6.1.199 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/302' => 'BlackBerry 8900',
|
10
|
+
'LG-GD510/V100 Teleca/WAP2.0 Profile/MIDP-2.1 Configuration/CLDC-1.1' => 'LG GD510',
|
11
|
+
'LG/KU990/v10a Browser/Obigo-Q05A/3.6 MMS/LG-MMS-V1.0/1.2 Java/ASVM/1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1' => 'LG KU990',
|
12
|
+
'Mozilla/5.0 (Linux; U; Android 2.1-update1; nl-nl; Desire_A8181 Build/ERE27) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17' => 'HTC Desire',
|
13
|
+
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; GTB0.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30618)' => 'MSIE 7.0',
|
14
|
+
'Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; nl) AppleWebKit/534.1+ (KHTML, like Gecko) Version/6.0.0.246 Mobile Safari/534.1+' => 'BlackBerry 9800',
|
15
|
+
'Mozilla/5.0 (iPhone; CPU iPhone OS 5_0_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A405 Safari/7534.48.3' => 'iPhone',
|
16
|
+
'Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8L1 Safari/6533.18.5' => 'iPhone',
|
17
|
+
'Mozilla/5.0 (iPhone; U; CPU like Mac OS X; nl-nl) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/4A102 Safari/419.3' => 'iPhone',
|
18
|
+
'Mozilla/5.0 (iPod; U; CPU iPhone OS 4_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8F190 Safari/6533.18.5' => 'iPod',
|
19
|
+
'Mozilla/5.0 (SAMSUNG; SAMSUNG-GT-S8500/S8500XXJEC; U; Bada/1.0; nl-nl) AppleWebKit/533.1 (KHTML, like Gecko) Dolfin/2.0 Mobile WVGA SMM-MMS/1.2.0 OPN-B' => 'Samsung GT-S8500',
|
20
|
+
'HTC_Touch2_T3333 Opera/9.50 (Windows NT 5.1; U; nl)' => 'HTC Touch2',
|
21
|
+
'Mozilla/5.0 (Linux; U; Android 1.5; en-gb; HTC Magic Build/CRB17) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1' => 'HTC Magic',
|
22
|
+
'Mozilla/5.0 (Linux; U; Android 1.5; nl-nl; GT-I5700 Build/CUPCAKE) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1' => 'Samsung GT-I5700',
|
23
|
+
'Mozilla/5.0 (Linux; U; Android 2.1; nl-nl; HTC Legend Build/ERD79) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17' => 'HTC Legend',
|
24
|
+
'Mozilla/5.0 (Linux; U; Android 2.2.1; es-es; Vodafone 858 Build/Vodafone858C02B617) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1' => 'Vodafone 858',
|
25
|
+
'Mozilla/5.0 (Linux; U; Android 2.2; es-es; Light Pro Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1' => 'Light Pro',
|
26
|
+
'Mozilla/5.0 (Linux; U; Android 2.2; nl-nl; HTC_DesireZ_A7272 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1' => 'HTC DesireZ',
|
27
|
+
'Mozilla/5.0 (Linux; U; Android 2.3.3; nl-nl; GT-I9100 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1' => 'Samsung GT-I9100',
|
28
|
+
'Mozilla/5.0 (Linux; U; Android 2.3.3; nl-nl; HTC/DesireS/1.32.161.2 Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1' => 'HTC DesireS',
|
29
|
+
'Mozilla/5.0 (Linux; U; Android 2.3.3; nl-nl; SAMSUNG GT-I9100/I9100BUKE5 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1' => 'Samsung GT-I9100',
|
30
|
+
'Mozilla/5.0 (Linux; U; Android 2.3.5; es-es; ZTE Skate Build/V1.0.0B03) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1' => 'ZTE Skate',
|
31
|
+
'Mozilla/5.0 (Linux; U; Android 2.3.6; en-us; Nexus One Build/GRK39F) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1' => 'Nexus One',
|
32
|
+
'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_5; nl-nl) AppleWebKit/525.18 (KHTML, like Gecko) Version/3.1.2 Safari/525.20.1' => 'Mac OS X 10.5.5',
|
33
|
+
'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; en-us) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10' => 'Mac OS X 10.6.2',
|
34
|
+
'Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 NokiaE90-1/07.24.0.3; Profile/MIDP-2.0 Configuration/CLDC-1.1 ) AppleWebKit/413 (KHTML, like Gecko) Safari/413' => 'Nokia E90',
|
35
|
+
'Mozilla/5.0 (SymbianOS/9.3; U; Series60/3.2 NokiaE75-1/110.48.125 Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/413 (KHTML, like Gecko) Safari/413' => 'Nokia E75',
|
36
|
+
'Mozilla/5.0 (SymbianOS/9.4; U; Series60/5.0 Samsung/I8910; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 Safari/525' => 'Samsung I8910',
|
37
|
+
'Opera/9.80 (BlackBerry; Opera Mini/5.1.22303/24.871; U; pt) Presto/2.5.25 Version/10.54' => 'BlackBerry',
|
38
|
+
'SAGEM-my411C/1.0/ MIDP-2.0 Configuration/CLDC-1.1 Browser/UP.Browser/7.2.6.c.1.386 (GUI)' => 'SAGEM my411C',
|
39
|
+
'SAMSUNG-GT-C3510/C3510XXIL4 NetFront/3.5 Profile/MIDP-2.0 Configuration/CLDC-1.1' => 'Samsung GT-C3510',
|
40
|
+
'SAMSUNG-SGH-L600/L600ASGI3 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Browser/6.2.3.3.c.1.101 (GUI) MMP/2.0' => 'Samsung SGH L600',
|
41
|
+
'SEC-SGHM620/1.0 Openwave/6.2.3 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Browser/6.2.3.3.c.1.101 (GUI) MMP/2.0' => 'SEC SGH M620',
|
42
|
+
'SonyEricssonW995/R1FA Browser/NetFront/3.4 Profile/MIDP-2.1 Configuration/CLDC-1.1 JavaPlatform/JP-8.4.3' => 'SonyEricsson W995',
|
43
|
+
'Mozilla/5.0 (Linux; U; Android 1.6; nl-nl; SonyEricssonX10i Build/R1FA016) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1' => 'SonyEricsson X10i',
|
44
|
+
'' => nil,
|
45
|
+
nil => nil,
|
46
|
+
}.each do |user_agent, device_name|
|
47
|
+
it "should return #{device_name.inspect} for #{user_agent.inspect}" do
|
48
|
+
UserAgentSanitizer.sanitize_user_agent(user_agent).should == device_name
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
# Project
|
3
|
+
s.name = 'user_agent_sanitizer'
|
4
|
+
s.summary = "Browser user agent sanitizer"
|
5
|
+
s.description = "Browser user agent sanitizer, with a focus on sanitizing mobile phone user agents to brand + model number"
|
6
|
+
s.version = '1.0.0'
|
7
|
+
s.date = '2002-06-15'
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Wes Oldenbeuving"]
|
10
|
+
s.email = "narnach@gmail.com"
|
11
|
+
s.homepage = "http://www.github.com/Narnach/user_agent_sanitizer"
|
12
|
+
|
13
|
+
# Files
|
14
|
+
s.require_path = "lib"
|
15
|
+
s.files = ['user_agent_sanitizer.gemspec', 'LICENSE', 'README.md', 'Rakefile', 'lib/user_agent_sanitizer.rb', 'spec/user_agent_sanitizer_spec.rb', 'spec/spec_helper.rb']
|
16
|
+
s.test_files = ['spec/user_agent_sanitizer_spec.rb']
|
17
|
+
|
18
|
+
# rdoc
|
19
|
+
s.has_rdoc = true
|
20
|
+
s.extra_rdoc_files = %w[ README.md LICENSE]
|
21
|
+
s.rdoc_options << '--inline-source' << '--line-numbers' << '--main' << 'README.md'
|
22
|
+
|
23
|
+
# Requirements
|
24
|
+
s.required_ruby_version = ">= 1.9.3"
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: user_agent_sanitizer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Wes Oldenbeuving
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2002-06-15 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Browser user agent sanitizer, with a focus on sanitizing mobile phone
|
15
|
+
user agents to brand + model number
|
16
|
+
email: narnach@gmail.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files:
|
20
|
+
- README.md
|
21
|
+
- LICENSE
|
22
|
+
files:
|
23
|
+
- user_agent_sanitizer.gemspec
|
24
|
+
- LICENSE
|
25
|
+
- README.md
|
26
|
+
- Rakefile
|
27
|
+
- lib/user_agent_sanitizer.rb
|
28
|
+
- spec/user_agent_sanitizer_spec.rb
|
29
|
+
- spec/spec_helper.rb
|
30
|
+
homepage: http://www.github.com/Narnach/user_agent_sanitizer
|
31
|
+
licenses: []
|
32
|
+
post_install_message:
|
33
|
+
rdoc_options:
|
34
|
+
- --inline-source
|
35
|
+
- --line-numbers
|
36
|
+
- --main
|
37
|
+
- README.md
|
38
|
+
require_paths:
|
39
|
+
- lib
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.9.3
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ! '>='
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
requirements: []
|
53
|
+
rubyforge_project:
|
54
|
+
rubygems_version: 1.8.11
|
55
|
+
signing_key:
|
56
|
+
specification_version: 3
|
57
|
+
summary: Browser user agent sanitizer
|
58
|
+
test_files:
|
59
|
+
- spec/user_agent_sanitizer_spec.rb
|