wurfl 1.0.2 → 1.1.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.
@@ -0,0 +1,40 @@
1
+ require "wurfl/command"
2
+
3
+ # A simple command line tool to make sure that a wurfl file properly parses.
4
+ # Used to make sure changes to Wurfl/Patch files are OK.
5
+ class Wurfl::Command::Sanitycheck < Wurfl::Command
6
+ def execute
7
+ if ARGV.size != 1
8
+ puts "Must have the path of the wurfl file to check"
9
+ exit 1
10
+ end
11
+ lines = File.open(ARGV[0],"r").readlines
12
+
13
+ curdev = nil
14
+ c = 0
15
+
16
+ lines.each do |line|
17
+ line = line.strip
18
+ if line =~ /^(<d)evice.*[^\/]>$/
19
+ curdev = line
20
+ elsif line =~ /^(<d)evice.*\/>$/
21
+ if curdev
22
+ puts "#{c}:A device was not closed and we got a new device! #{curdev}"
23
+ end
24
+ curdev = nil
25
+ elsif line =~ /^(<\/d)evice>$/
26
+ if curdev.nil?
27
+ puts "#{c}:A closing device with no opening! #{curdev}"
28
+ end
29
+ curdev=nil
30
+ end
31
+ c += 1
32
+ end
33
+
34
+ if curdev
35
+ puts "The curent device was not closed #{curdev}"
36
+ end
37
+
38
+ puts "Done"
39
+ end
40
+ end
@@ -0,0 +1,28 @@
1
+ require "wurfl/command"
2
+ require "wurfl/uaproftowurfl"
3
+
4
+ class Wurfl::Command::Uaproftowurfl
5
+ def execute
6
+ if ARGV.size == 0
7
+ usage
8
+ end
9
+
10
+ uaprof = Wurfl::UAProfToWURLF.new
11
+
12
+ # Parse all the files and merge them into one UAProf.
13
+ # Following profs take precedence of previous ones
14
+ ARGV.each do |file|
15
+ uaprof.parse_UAProf(file)
16
+ end
17
+
18
+ # Now output the mapped WURFL to standard out
19
+ uaprof.output_WURFL
20
+ end
21
+
22
+ def usage
23
+ puts "Usage: wurfltools.rb uaproftowurfl uaprof_files"
24
+ puts "No files passed to parse."
25
+ exit 1
26
+ end
27
+ end
28
+
@@ -0,0 +1,224 @@
1
+ require "wurfl/command"
2
+ require "getoptlong"
3
+ require "net/http"
4
+
5
+ require "wurfl/uaproftowurfl"
6
+ require "wurfl/handset"
7
+ require "wurfl/utils"
8
+ include Wurfl::Utils
9
+
10
+ # An addition to the UAProf to Wurfl to generate a WurflHandset from the UAProf.
11
+ class Wurfl::UAProfToWURLF
12
+ def make_wurfl_handset
13
+ hand = Wurfl::Handset.new("UAProf",@wurfl["user_agent"])
14
+ @wurflgroups.each do |group|
15
+ @wurfl[group].sort.each do |key,value|
16
+ hand[key] = value
17
+ end
18
+ end
19
+ return hand
20
+ end
21
+ end
22
+
23
+
24
+ class Wurfl::Command::Uaprofwurflcomparator
25
+ def parse_mapping_file(file)
26
+ if !File.exist?(file)
27
+ $stderr.puts "Mapping File does not exist. File passed was #{file}."
28
+ return Array.new
29
+ end
30
+ mappings = Array.new
31
+ f = File.new(file)
32
+ f.each do |line|
33
+ if m = /^"(.*)" "(.*)"$/.match(line.strip)
34
+ uaprof = m[1]
35
+ useragent = m[2]
36
+ mappings<< [uaprof,useragent]
37
+ else
38
+ $stderr.puts "Irregular format for line: #{line}" if line.strip != ""
39
+ end
40
+ end
41
+ f.close
42
+
43
+ return mappings
44
+ end
45
+
46
+ def get_uaprofile(uaprof,profiledir,check=false)
47
+ file = strip_uaprof(uaprof)
48
+ if File.exists?("#{profiledir}/#{file}") && check
49
+ return file
50
+ end
51
+
52
+ get_and_save_uaprof_file(uaprof,profiledir)
53
+ return file
54
+ end
55
+
56
+ def strip_uaprof(uaprof)
57
+ uaprof_file = nil
58
+ if m = /([^\/]*)$/.match(uaprof)
59
+ uaprof_file = m[1]
60
+ else
61
+ $stderr.puts "Cannot find the base UAProf file in URI: #{uaprof}"
62
+ end
63
+ return uaprof_file
64
+ end
65
+
66
+ def load_pstore(pstorefile)
67
+ hands = Hash.new
68
+ begin
69
+ handsid, = load_wurfl_pstore(pstorefile)
70
+ handsid.each { |id,val| hands[val.user_agent] = val }
71
+ rescue => err
72
+ $stderr.puts "Error: Cannot load PStore file. #{pstorefile}"
73
+ $stderr.puts err.message
74
+ exit 1
75
+ end
76
+ return hands
77
+ end
78
+
79
+ def get_and_save_uaprof_file(uaprof_url,savedirectory,limit=0)
80
+ base,path,port = parse_url(uaprof_url)
81
+
82
+ raise "Too many redirects from original url" if limit > 3
83
+ raise "Unparseable URL: #{url}" if base.nil?
84
+
85
+ port = 80 if port.nil?
86
+ http = Net::HTTP.new(base,port)
87
+ begin
88
+ resp, data = http.get(path)
89
+ if resp.code == "301"
90
+ # get location and call self again
91
+ http.finish
92
+ limit += 1
93
+ get_and_save_uaprof_file(resp['location'],savedirectory,limit)
94
+ return
95
+ elsif resp.code != "200"
96
+ raise "Unexpected HTTP Response code:#{resp.code} for #{uaprof_url}"
97
+ end
98
+ rescue => err
99
+ raise
100
+ end
101
+
102
+ f = File.new("#{savedirectory}/#{strip_uaprof(path)}","w")
103
+ f.write(data)
104
+ f.close
105
+
106
+ end
107
+
108
+ def parse_url(url)
109
+ m = /(http:\/\/)?(.*?)(:(\d*))?\/(.*)/i.match(url.strip)
110
+
111
+ return nil if m.nil?
112
+ return m[2],"/#{m[5]}",m[4]
113
+ end
114
+
115
+ def usage
116
+ puts "Usage: wurfltools.rb uaprofwurflcomparator -d profiledirectory -f mappingfile [-w wurfldb] [-c] [-h | --help]"
117
+ puts "Examples:"
118
+ puts "wurfltools.rb uaprofwurflcomparator -d ./profiles -f all-profile.2003-08.log -c -w wurfl.db"
119
+ exit 1
120
+ end
121
+
122
+ def help
123
+ puts "-d --directory : The directory to store the UA Profiles found in the log file."
124
+ puts "-f --file : The log file that has a UAProfile to User-Agent mapping per line."
125
+ puts "-c --check : A flag that will make sure to check if the profile is already in the directory or not. If it is not then it will download it."
126
+ puts "-w --wurfldb : A Ruby PStore Database of the WURFL, that is used to compare against the UAProfiles."
127
+ puts "-h --help : This message."
128
+ exit 1
129
+ end
130
+
131
+ def execute
132
+ profiledirectory = mappingfile = pstorefile = nil
133
+ existancecheck = false
134
+ begin
135
+ opt = GetoptLong.new(
136
+ ["-d","--directory", GetoptLong::REQUIRED_ARGUMENT],
137
+ ["-f","--file", GetoptLong::REQUIRED_ARGUMENT],
138
+ ["-c","--check", GetoptLong::NO_ARGUMENT],
139
+ ["-h","--help", GetoptLong::NO_ARGUMENT],
140
+ ["-w","--wurfldb", GetoptLong::REQUIRED_ARGUMENT]
141
+ )
142
+
143
+ opt.each { |arg,val|
144
+ case arg
145
+ when "-d"
146
+ profiledirectory = val.strip
147
+ when "-f"
148
+ mappingfile = val.strip
149
+ when "-c"
150
+ existancecheck = true
151
+ when "-h"
152
+ help
153
+ when "-w"
154
+ pstorefile = val.strip
155
+ else
156
+ usage
157
+ end
158
+ }
159
+ usage if mappingfile.nil? || profiledirectory.nil?
160
+ rescue => err
161
+ usage
162
+ end
163
+
164
+ profiles = Hash.new
165
+ duplicates = Hash.new
166
+ mappings = parse_mapping_file(mappingfile)
167
+ mappings.each do |uaprof,useragent|
168
+ begin
169
+ prof_file = get_uaprofile(uaprof,profiledirectory,existancecheck)
170
+ uaprof_mapper = UAProfToWURLF.new
171
+ if profiles.key?(useragent)
172
+ duplicates[useragent] = Array.new if !duplicates.key?(useragent)
173
+ duplicates[useragent]<<uaprof
174
+ next
175
+ end
176
+ uaprof_mapper.parse_UAProf("#{profiledirectory}/#{prof_file}")
177
+ profiles[useragent] = uaprof_mapper
178
+ rescue => err
179
+ $stderr.puts "Error: File #{prof_file}; User-Agent:#{useragent}"
180
+ $stderr.puts "Error:#{err.message}"
181
+ end
182
+ end
183
+
184
+ duplicates.each do |key,profs|
185
+ $stderr.puts "Duplicates exist for #{key}"
186
+ profs.each {|prof| $stderr.puts "-- #{prof}" }
187
+ end
188
+
189
+ exit 0 if !pstorefile
190
+
191
+ wurflhandsets = load_pstore(pstorefile)
192
+
193
+ puts "Comparing WURFL Handsets"
194
+ profiles.each do |key,val|
195
+ puts "",""
196
+
197
+ if !wurflhandsets.key?(key)
198
+ puts "UAProf has a new Handset: #{key}"
199
+ puts "--------------------------------"
200
+ val.output_WURFL
201
+ puts "--------------------------------"
202
+ else
203
+ uahand = val.make_wurfl_handset
204
+ res = uahand.compare(wurflhandsets[key])
205
+ if res.size > 0
206
+ puts "#{key} : For UAProf and WURFL differ"
207
+ res.each do |dkey,dval,did|
208
+ next if did == "generic"
209
+ #Key UAPROF Value WURFL Value WURFL source id
210
+ puts " Key:#{dkey}; UVAL:#{uahand[dkey]}; WVAL:#{dval}; WSRCID:#{did}"
211
+ end
212
+ #val["user_agent"] = key
213
+ puts ""
214
+ puts "WURFL Changes are:"
215
+ puts ""
216
+ val.output_WURFL(res.map {|entry| entry[0]})
217
+ else
218
+ puts "#{key} : For UAProf and WURFL match"
219
+ end
220
+ end
221
+ end
222
+ end
223
+ end
224
+
data/wurfl.gemspec CHANGED
@@ -2,14 +2,15 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{wurfl}
5
- s.version = "1.0.2"
5
+ s.version = "1.1.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Paul McMahon", "Zev Blut"]
9
- s.date = %q{2009-06-02}
9
+ s.date = %q{2009-06-09}
10
+ s.default_executable = %q{wurfltools.rb}
10
11
  s.description = %q{TODO}
11
12
  s.email = %q{info@mobalean.com}
12
- s.executables = ["uaproftowurfl.rb", "wurflsanitycheck.rb", "wurflinspector.rb", "wurflloader.rb", "uaprofwurflcomparator.rb", "wurflcomparator.rb"]
13
+ s.executables = ["wurfltools.rb"]
13
14
  s.extra_rdoc_files = [
14
15
  "LICENSE",
15
16
  "README.rdoc"
@@ -20,12 +21,14 @@ Gem::Specification.new do |s|
20
21
  "README.rdoc",
21
22
  "Rakefile",
22
23
  "VERSION",
23
- "bin/uaproftowurfl.rb",
24
- "bin/uaprofwurflcomparator.rb",
25
- "bin/wurflcomparator.rb",
26
- "bin/wurflinspector.rb",
27
- "bin/wurflloader.rb",
28
- "bin/wurflsanitycheck.rb",
24
+ "bin/wurfltools.rb",
25
+ "lib/wurfl/command.rb",
26
+ "lib/wurfl/command/comparator.rb",
27
+ "lib/wurfl/command/inspector.rb",
28
+ "lib/wurfl/command/loader.rb",
29
+ "lib/wurfl/command/sanitycheck.rb",
30
+ "lib/wurfl/command/uaproftowurfl.rb",
31
+ "lib/wurfl/command/uaprofwurflcomparator.rb",
29
32
  "lib/wurfl/handset.rb",
30
33
  "lib/wurfl/loader.rb",
31
34
  "lib/wurfl/uaproftowurfl.rb",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wurfl
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul McMahon
@@ -10,19 +10,14 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2009-06-02 00:00:00 +09:00
14
- default_executable:
13
+ date: 2009-06-09 00:00:00 +09:00
14
+ default_executable: wurfltools.rb
15
15
  dependencies: []
16
16
 
17
17
  description: TODO
18
18
  email: info@mobalean.com
19
19
  executables:
20
- - uaproftowurfl.rb
21
- - wurflsanitycheck.rb
22
- - wurflinspector.rb
23
- - wurflloader.rb
24
- - uaprofwurflcomparator.rb
25
- - wurflcomparator.rb
20
+ - wurfltools.rb
26
21
  extensions: []
27
22
 
28
23
  extra_rdoc_files:
@@ -34,12 +29,14 @@ files:
34
29
  - README.rdoc
35
30
  - Rakefile
36
31
  - VERSION
37
- - bin/uaproftowurfl.rb
38
- - bin/uaprofwurflcomparator.rb
39
- - bin/wurflcomparator.rb
40
- - bin/wurflinspector.rb
41
- - bin/wurflloader.rb
42
- - bin/wurflsanitycheck.rb
32
+ - bin/wurfltools.rb
33
+ - lib/wurfl/command.rb
34
+ - lib/wurfl/command/comparator.rb
35
+ - lib/wurfl/command/inspector.rb
36
+ - lib/wurfl/command/loader.rb
37
+ - lib/wurfl/command/sanitycheck.rb
38
+ - lib/wurfl/command/uaproftowurfl.rb
39
+ - lib/wurfl/command/uaprofwurflcomparator.rb
43
40
  - lib/wurfl/handset.rb
44
41
  - lib/wurfl/loader.rb
45
42
  - lib/wurfl/uaproftowurfl.rb
data/bin/uaproftowurfl.rb DELETED
@@ -1,28 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
4
- require "wurfl/uaproftowurfl"
5
-
6
- # The code below is called if this file is executed from the command line.
7
-
8
- def usage
9
- puts "Usage: usaprofparser.rb uaprof_files"
10
- puts "No files passed to parse."
11
- exit 1
12
- end
13
-
14
- if ARGV.size == 0
15
- usage
16
- end
17
-
18
- uaprof = Wurfl::UAProfToWURLF.new
19
-
20
- # Parse all the files and merge them into one UAProf.
21
- # Following profs take precedence of previous ones
22
- ARGV.each do |file|
23
- uaprof.parse_UAProf(file)
24
- end
25
-
26
- # Now output the mapped WURFL to standard out
27
- uaprof.output_WURFL
28
-
@@ -1,223 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
4
-
5
- require "getoptlong"
6
- require "net/http"
7
-
8
- require "wurfl/uaproftowurfl"
9
- require "wurfl/handset"
10
- require "wurfl/utils"
11
- include Wurfl::Utils
12
-
13
- # An addition to the UAProf to Wurfl to generate a WurflHandset from the UAProf.
14
- class Wurfl::UAProfToWURLF
15
- def make_wurfl_handset
16
- hand = Wurfl::Handset.new("UAProf",@wurfl["user_agent"])
17
- @wurflgroups.each do |group|
18
- @wurfl[group].sort.each do |key,value|
19
- hand[key] = value
20
- end
21
- end
22
- return hand
23
- end
24
- end
25
-
26
-
27
- def parse_mapping_file(file)
28
- if !File.exist?(file)
29
- $stderr.puts "Mapping File does not exist. File passed was #{file}."
30
- return Array.new
31
- end
32
- mappings = Array.new
33
- f = File.new(file)
34
- f.each do |line|
35
- if m = /^"(.*)" "(.*)"$/.match(line.strip)
36
- uaprof = m[1]
37
- useragent = m[2]
38
- mappings<< [uaprof,useragent]
39
- else
40
- $stderr.puts "Irregular format for line: #{line}" if line.strip != ""
41
- end
42
- end
43
- f.close
44
-
45
- return mappings
46
- end
47
-
48
- def get_uaprofile(uaprof,profiledir,check=false)
49
- file = strip_uaprof(uaprof)
50
- if File.exists?("#{profiledir}/#{file}") && check
51
- return file
52
- end
53
-
54
- get_and_save_uaprof_file(uaprof,profiledir)
55
- return file
56
- end
57
-
58
- def strip_uaprof(uaprof)
59
- uaprof_file = nil
60
- if m = /([^\/]*)$/.match(uaprof)
61
- uaprof_file = m[1]
62
- else
63
- $stderr.puts "Cannot find the base UAProf file in URI: #{uaprof}"
64
- end
65
- return uaprof_file
66
- end
67
-
68
- def load_pstore(pstorefile)
69
- hands = Hash.new
70
- begin
71
- handsid, = load_wurfl_pstore(pstorefile)
72
- handsid.each { |id,val| hands[val.user_agent] = val }
73
- rescue => err
74
- $stderr.puts "Error: Cannot load PStore file. #{pstorefile}"
75
- $stderr.puts err.message
76
- exit 1
77
- end
78
- return hands
79
- end
80
-
81
- def get_and_save_uaprof_file(uaprof_url,savedirectory,limit=0)
82
- base,path,port = parse_url(uaprof_url)
83
-
84
- raise "Too many redirects from original url" if limit > 3
85
- raise "Unparseable URL: #{url}" if base.nil?
86
-
87
- port = 80 if port.nil?
88
- http = Net::HTTP.new(base,port)
89
- begin
90
- resp, data = http.get(path)
91
- if resp.code == "301"
92
- # get location and call self again
93
- http.finish
94
- limit += 1
95
- get_and_save_uaprof_file(resp['location'],savedirectory,limit)
96
- return
97
- elsif resp.code != "200"
98
- raise "Unexpected HTTP Response code:#{resp.code} for #{uaprof_url}"
99
- end
100
- rescue => err
101
- raise
102
- end
103
-
104
- f = File.new("#{savedirectory}/#{strip_uaprof(path)}","w")
105
- f.write(data)
106
- f.close
107
-
108
- end
109
-
110
- def parse_url(url)
111
- m = /(http:\/\/)?(.*?)(:(\d*))?\/(.*)/i.match(url.strip)
112
-
113
- return nil if m.nil?
114
- return m[2],"/#{m[5]}",m[4]
115
- end
116
-
117
- def usage
118
- puts "Usage: uaprofwurflcomparator.rb -d profiledirectory -f mappingfile [-w wurfldb] [-c] [-h | --help]"
119
- puts "Examples:"
120
- puts "uaprofwurflcomparator.rb -d ./profiles -f all-profile.2003-08.log -c -w wurfl.db"
121
- exit 1
122
- end
123
-
124
- def help
125
- puts "-d --directory : The directory to store the UA Profiles found in the log file."
126
- puts "-f --file : The log file that has a UAProfile to User-Agent mapping per line."
127
- puts "-c --check : A flag that will make sure to check if the profile is already in the directory or not. If it is not then it will download it."
128
- puts "-w --wurfldb : A Ruby PStore Database of the WURFL, that is used to compare against the UAProfiles."
129
- puts "-h --help : This message."
130
- exit 1
131
- end
132
-
133
- profiledirectory = mappingfile = pstorefile = nil
134
- existancecheck = false
135
- begin
136
- opt = GetoptLong.new(
137
- ["-d","--directory", GetoptLong::REQUIRED_ARGUMENT],
138
- ["-f","--file", GetoptLong::REQUIRED_ARGUMENT],
139
- ["-c","--check", GetoptLong::NO_ARGUMENT],
140
- ["-h","--help", GetoptLong::NO_ARGUMENT],
141
- ["-w","--wurfldb", GetoptLong::REQUIRED_ARGUMENT]
142
- )
143
-
144
- opt.each { |arg,val|
145
- case arg
146
- when "-d"
147
- profiledirectory = val.strip
148
- when "-f"
149
- mappingfile = val.strip
150
- when "-c"
151
- existancecheck = true
152
- when "-h"
153
- help
154
- when "-w"
155
- pstorefile = val.strip
156
- else
157
- usage
158
- end
159
- }
160
- usage if mappingfile.nil? || profiledirectory.nil?
161
- rescue => err
162
- usage
163
- end
164
-
165
- profiles = Hash.new
166
- duplicates = Hash.new
167
- mappings = parse_mapping_file(mappingfile)
168
- mappings.each do |uaprof,useragent|
169
- begin
170
- prof_file = get_uaprofile(uaprof,profiledirectory,existancecheck)
171
- uaprof_mapper = UAProfToWURLF.new
172
- if profiles.key?(useragent)
173
- duplicates[useragent] = Array.new if !duplicates.key?(useragent)
174
- duplicates[useragent]<<uaprof
175
- next
176
- end
177
- uaprof_mapper.parse_UAProf("#{profiledirectory}/#{prof_file}")
178
- profiles[useragent] = uaprof_mapper
179
- rescue => err
180
- $stderr.puts "Error: File #{prof_file}; User-Agent:#{useragent}"
181
- $stderr.puts "Error:#{err.message}"
182
- end
183
- end
184
-
185
- duplicates.each do |key,profs|
186
- $stderr.puts "Duplicates exist for #{key}"
187
- profs.each {|prof| $stderr.puts "-- #{prof}" }
188
- end
189
-
190
- exit 0 if !pstorefile
191
-
192
- wurflhandsets = load_pstore(pstorefile)
193
-
194
- puts "Comparing WURFL Handsets"
195
- profiles.each do |key,val|
196
- puts "",""
197
-
198
- if !wurflhandsets.key?(key)
199
- puts "UAProf has a new Handset: #{key}"
200
- puts "--------------------------------"
201
- val.output_WURFL
202
- puts "--------------------------------"
203
- else
204
- uahand = val.make_wurfl_handset
205
- res = uahand.compare(wurflhandsets[key])
206
- if res.size > 0
207
- puts "#{key} : For UAProf and WURFL differ"
208
- res.each do |dkey,dval,did|
209
- next if did == "generic"
210
- #Key UAPROF Value WURFL Value WURFL source id
211
- puts " Key:#{dkey}; UVAL:#{uahand[dkey]}; WVAL:#{dval}; WSRCID:#{did}"
212
- end
213
- #val["user_agent"] = key
214
- puts ""
215
- puts "WURFL Changes are:"
216
- puts ""
217
- val.output_WURFL(res.map {|entry| entry[0]})
218
- else
219
- puts "#{key} : For UAProf and WURFL match"
220
- end
221
- end
222
- end
223
-