spy-vs-spy 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/lib/spy-vs-spy.rb +473 -7
  2. data/spy-vs-spy.gemspec +69 -10
  3. data/test/firefox/firefox-3.1b2.txt +9 -0
  4. data/test/firefox/firefox-3.1b2pre.txt +4 -0
  5. data/test/firefox/firefox-3.1b3.txt +32 -0
  6. data/test/firefox/firefox-3.1b3pre.txt +2 -0
  7. data/test/firefox/firefox-3.5.1.txt +41 -0
  8. data/test/firefox/firefox-3.5.12.txt +1 -0
  9. data/test/firefox/firefox-3.5.2.txt +27 -0
  10. data/test/firefox/firefox-3.5.3.txt +22 -0
  11. data/test/firefox/firefox-3.5.3pre.txt +1 -0
  12. data/test/firefox/firefox-3.5.4.txt +3 -0
  13. data/test/firefox/firefox-3.5.5.txt +3 -0
  14. data/test/firefox/firefox-3.5.txt +40 -0
  15. data/test/firefox/firefox-3.5b4.txt +9 -0
  16. data/test/firefox/firefox-3.5b4pre.txt +3 -0
  17. data/test/firefox/firefox-3.6.txt +2 -0
  18. data/test/firefox/firefox-3.6a1pre.txt +6 -0
  19. data/test/firefox/firefox-3.6b1.txt +1 -0
  20. data/test/firefox/firefox-3.8.txt +3 -0
  21. data/test/msie/msie-5.5.txt +177 -0
  22. data/test/msie/msie-5.5b1.txt +1 -0
  23. data/test/msie/msie-6,0.txt +1 -0
  24. data/test/msie/msie-6.0.1.txt +1 -0
  25. data/test/msie/msie-6.0.txt +1817 -0
  26. data/test/msie/msie-6.0b.txt +14 -0
  27. data/test/msie/msie-6.1.txt +2 -0
  28. data/test/msie/msie-7.0.txt +1208 -0
  29. data/test/msie/msie-7.0b.txt +12 -0
  30. data/test/msie/msie-8.0.txt +340 -0
  31. data/test/safari/safari-1.0.3.txt +10 -0
  32. data/test/safari/safari-1.0.txt +8 -0
  33. data/test/safari/safari-1.2.2.txt +9 -0
  34. data/test/safari/safari-1.2.3.txt +10 -0
  35. data/test/safari/safari-1.2.4.txt +21 -0
  36. data/test/safari/safari-1.2.txt +5 -0
  37. data/test/safari/safari-1.3.1.txt +24 -0
  38. data/test/safari/safari-1.3.2.txt +14 -0
  39. data/test/safari/safari-1.3.txt +13 -0
  40. data/test/safari/safari-2.0.1.txt +9 -0
  41. data/test/safari/safari-2.0.2.txt +25 -0
  42. data/test/safari/safari-2.0.3.txt +37 -0
  43. data/test/safari/safari-2.0.4.txt +44 -0
  44. data/test/safari/safari-2.0.txt +21 -0
  45. data/test/safari/safari-3.0.1.txt +8 -0
  46. data/test/safari/safari-3.0.2.txt +14 -0
  47. data/test/safari/safari-3.0.3.txt +20 -0
  48. data/test/safari/safari-3.0.4.txt +37 -0
  49. data/test/safari/safari-3.0.txt +53 -0
  50. data/test/safari/safari-3.1.1.txt +77 -0
  51. data/test/safari/safari-3.1.2.txt +48 -0
  52. data/test/safari/safari-3.1.txt +22 -0
  53. data/test/safari/safari-3.2.1.txt +37 -0
  54. data/test/safari/safari-3.2.2.txt +9 -0
  55. data/test/safari/safari-3.2.3.txt +2 -0
  56. data/test/safari/safari-3.2.txt +7 -0
  57. data/test/safari/safari-4.0.1.txt +2 -0
  58. data/test/safari/safari-4.0.2.txt +12 -0
  59. data/test/safari/safari-4.0.3.txt +5 -0
  60. data/test/safari/safari-4.0.txt +66 -0
  61. data/test/safari/safari-4.0dp1.txt +8 -0
  62. data/test/safari/safari.txt +31 -0
  63. data/test/ss-test.rb +143 -3
  64. metadata +62 -2
data/lib/spy-vs-spy.rb CHANGED
@@ -21,7 +21,16 @@
21
21
  see LICENSE file for details
22
22
 
23
23
  =end
24
+ class String
25
+ def starts_with?(str)
26
+ str = str.to_str
27
+ head = self[0, str.length]
28
+ head == str
29
+ end
30
+ end
31
+
24
32
  module SoldierOfCode
33
+
25
34
  class SpyVsSpy
26
35
 
27
36
  def initialize(app)
@@ -38,14 +47,429 @@ module SoldierOfCode
38
47
  end
39
48
 
40
49
  def deconstruct(agent)
41
- ParseUserAgent.new(agent)
50
+ ParseUserAgent.new.parse(agent)
42
51
  end
43
52
 
44
53
  end
45
54
 
46
55
  class ParseUserAgent
47
56
 
48
- attr_reader :ostype, :browser, :os_version, :browser_version_major
57
+ @@safari = {
58
+ "1.0" => ["85.5", "85.6", "85.7"],
59
+ "1,0.3" => ["85.8.1", "85.8", "85"],
60
+ "1.2" => ["125", "125.1"],
61
+ "1.2.2" => ["85.8", "125.7", "125.8"],
62
+ "1.2.3" => ["100", "125.9"],
63
+ "1.2.4" => ["125", "125.11", "125.12", "125.12_Adobe", "125.5.5"],
64
+ "1.3" => ["312"],
65
+ "1.3.1" => ["312.3.3", "312.3.1", "312.3"],
66
+ "1.3.2" => ["312.5", "312.6", "312.5_Adobe"],
67
+ "2.0" => ["412", "412.2.2", "412.2_Adobe"],
68
+ "2.0.1" => ["412.5", "412.6", "412.5_Adobe"],
69
+ "2.0.2" => ["416.13", "416.12", "312", "416.13_Adobe", "416.12_Adobe"],
70
+ "2.0.3" => ["417.9.3", "417.8_Adobe", "417.9.2", "417.8", "412.2"],
71
+ "2.0.4" => ["419.3"],
72
+ "3.0" => ["523.13", "522.11.3", "523.12.9", "523.6.1", "522.11.1", "522.11", "522.8.3", "522.7"],
73
+ "3.0.1" => ["522.12.2"],
74
+ "3.0.2" => ["522.13.1", "522.12"],
75
+ "3.0.3" => ["522.15.5", "523.6", "522.12.1"],
76
+ "3.0.4" => ["523.11", "523.12.2", "523.10", "523.10.6", "523.15", "523.12"],
77
+ "3.1.1" => ["525.17", "525.18", "525.20"],
78
+ "3.2.1" => ["525.27.1"]
79
+ }
80
+
81
+ attr_reader :ostype, :browser, :os_version, :browser_version_major, :browser_version_minor, :browser_version_sub, :mobile_browser, :console_browser
82
+
83
+ #
84
+ #
85
+ # =======================================
86
+ # description:
87
+ # ----------------
88
+ #
89
+ # params:
90
+ # ----------------
91
+ #
92
+ # returns:
93
+ # ----------------
94
+ def parse(agent)
95
+
96
+ pass1 = Regexp.new("^([^\\(]*)?[ ]*?(\\([^\\)]*\\))?[ ]*([^\\(]*)?[ ]*?(\\([^\\)]*\\))?[ ]*(.*)")
97
+ pass1.match(agent)
98
+
99
+ @product_token = $1 || ''
100
+ @detail = $2 || ''
101
+ @engine = $3 || ''
102
+ @renderer = $4 || ''
103
+ @identifier = $5 || ''
104
+
105
+ #puts "#{__FILE__}:#{__LINE__} #{__method__} [#{@product_token}] [#{@detail}] [#{@engine}] [#{@renderer}] [#{@identifier}]"
106
+
107
+ @platform = identify_platform(agent)
108
+ @mobile = is_mobile?(agent)
109
+ @ostype = identify_os
110
+
111
+ matched = process_safari(agent)
112
+ matched = process_firefox(agent) unless matched
113
+ matched = process_ie(agent) unless matched
114
+ matched = process_opera(agent) unless matched
115
+ matched = process_netscape(agent) unless matched
116
+
117
+ self
118
+ end
119
+
120
+ #
121
+ #
122
+ # =======================================
123
+ # description:
124
+ # ----------------
125
+ #
126
+ # params:
127
+ # ----------------
128
+ #
129
+ # returns:
130
+ # ----------------
131
+ def identify_platform(agent)
132
+ platform = "Desktop"
133
+ ["PLAYSTATION 3", "wii", "PlayStation Portable", "Xbox", "iPhone", "iPod", "BlackBerry", "Android", "HTC-", "LG", "Motorola", "Nokia", "Treo", "Pre/", "Samsung", "SonyEricsson"].each do |agt|
134
+ platform = agt if @platform=="Desktop" && agent.include?(agt)
135
+ end
136
+ platform
137
+ end
138
+
139
+ #
140
+ #
141
+ # =======================================
142
+ # description:
143
+ # ----------------
144
+ #
145
+ # params:
146
+ # ----------------
147
+ #
148
+ # returns:
149
+ # ----------------
150
+ def is_mobile?(agent)
151
+ ["iPhone", "iPod", "BlackBerry", "Android", "HTC-", "LG", "Motorola", "Nokia", "Treo", "Pre/", "Samsung", "SonyEricsson"].each do |mobile_agt|
152
+ return true if agent.include?(mobile_agt)
153
+ end
154
+ end
155
+
156
+ #
157
+ #
158
+ # =======================================
159
+ # description:
160
+ # ----------------
161
+ #
162
+ # params:
163
+ # ----------------
164
+ #
165
+ # returns:
166
+ # ----------------
167
+ def identify_os
168
+ os_list = ["Mac OS X", "Linux", "Windows"]
169
+ os = nil
170
+ os_list.each do |o|
171
+ os = o if @detail.include?(o)
172
+ end
173
+ os
174
+ end
175
+
176
+ #
177
+ #
178
+ # =======================================
179
+ # description:
180
+ # ----------------
181
+ #
182
+ # params:
183
+ # ----------------
184
+ #
185
+ # returns:
186
+ # ----------------
187
+ def process_safari(agent_string)
188
+ @identifier = @engine if @identifier == ""
189
+
190
+ if agent_string.include?("Safari")
191
+ @browser = "Safari"
192
+ end
193
+
194
+ if @identifier.include?("Safari") || @renderer.include?("Safari") || @detail.include?("iPhone") || @identifier.include?("iPhone")
195
+ @browser = "Safari"
196
+
197
+ identifier_sub = nil
198
+ @identifier.gsub(/[\\:\?'"%!@#\$\^&\*\(\)\+]/, '').split(" ").each do |ident|
199
+ identifier_sub = ident.sub("Safari\/", "") if ident.include?("Safari")
200
+ identifier_sub.gsub!(/[\+]/, '') if identifier_sub && identifier_sub.include?("+")
201
+ end
202
+ if identifier_sub == nil && @renderer.include?("Safari")
203
+ renderer_gsub_gsub = @renderer.sub("\(", "").sub("\)", "")
204
+ renderer_gsub_gsub.strip.split(",").each do |sec|
205
+ identifier_sub = sec.sub("Safari\/", "").strip if sec.include?("Safari")
206
+ end
207
+ end
208
+
209
+ @@safari.each do |k, v|
210
+ version_numbers = k.gsub(",", ".").split(".")
211
+ v.each do |num|
212
+ if identifier_sub == num
213
+ @browser_version_major = version_numbers[0] if version_numbers.size > 0
214
+ @browser_version_minor = version_numbers[1] if version_numbers.size > 1
215
+ @browser_version_sub = version_numbers[2] if version_numbers.size > 2
216
+ end
217
+ break if @browser_version_major
218
+ end
219
+ # Special case 58.8 - check WebKit numbers
220
+ # Special case 312 - check AppleWebKit
221
+ # Special case 419.3 - could me mobile v3 check AppleWebKit for 420+
222
+
223
+ if identifier_sub == "312" then
224
+ engine_sub = @engine.sub("AppleWebKit/", "")
225
+ if engine_sub.include? "416.11" then
226
+ @browser_version_major = '2'
227
+ @browser_version_minor = '0'
228
+ @browser_version_sub = '2'
229
+ else
230
+ end
231
+ end
232
+
233
+ if identifier_sub == "419.3" then
234
+ engine_sub = @engine.sub("AppleWebKit/", "")
235
+ if engine_sub.include?("420") then
236
+ @browser_version_major = '3'
237
+ @browser_version_minor = '0'
238
+ @browser_version_sub = nil
239
+ else
240
+ end
241
+ end
242
+
243
+ if (identifier_sub == "Safari") || (@identifier == "Safari/")then
244
+ engine_sub = @engine.sub("AppleWebKit/", "")
245
+ if engine_sub.include?("418.9") || engine_sub.include?("418.8") then
246
+ @browser_version_major = '2'
247
+ @browser_version_minor = '0'
248
+ @browser_version_sub = '4'
249
+ else
250
+ end
251
+ end
252
+
253
+ ident_sub = nil
254
+ if @identifier.include?("Version") then
255
+ @identifier.split(" ").each do |ident|
256
+ ident_sub = ident.sub("Version\/", "") if ident.include?("Version")
257
+ if ident_sub then
258
+ vs = ident_sub.gsub(",", ".").split(".")
259
+ @browser_version_major = vs[0] if vs.size > 0
260
+ @browser_version_minor = vs[1] if vs.size > 1
261
+ @browser_version_sub = vs[2] if vs.size > 2
262
+ end
263
+ end
264
+ end
265
+
266
+ if @identifier == "Safari/412 Privoxy/3.0" then
267
+ @browser_version_major = '2'
268
+ @browser_version_minor = '0'
269
+ @browser_version_sub = nil
270
+ end
271
+
272
+ break if @browser_version_major
273
+ end
274
+ end
275
+
276
+ if @browser == nil && agent_string.include?("Mac OS X") && agent_string.include?("AppleWebKit")
277
+ @browser = "Safari"
278
+ end
279
+
280
+ return true if @browser && @browser_version_major
281
+ false
282
+ end
283
+
284
+ #
285
+ #
286
+ # =======================================
287
+ # description:
288
+ # ----------------
289
+ #
290
+ # params:
291
+ # ----------------
292
+ #
293
+ # returns:
294
+ # ----------------
295
+ def process_ie(agent)
296
+ # @detail
297
+ if agent.include?("MSIE")
298
+ @browser = "MSIE"
299
+ end
300
+ if @detail.include?("MSIE")
301
+ @detail.gsub(/[\\:\?'"%!@#\$\^&\*\(\)\+]/, '').split(";").each do |sec|
302
+ if sec.strip.starts_with?("MSIE ") then
303
+ s = sec.strip.sub("MSIE ", "").sub("06", "0.6").sub(",", ".").split(".")
304
+ @browser_version_major = s[0] if s.size > 0
305
+ @browser_version_minor = s[1] if s.size > 1
306
+ end
307
+
308
+ break if @browser_version_major
309
+ end
310
+ end
311
+
312
+ unless @browser_version_major
313
+ if agent.include?("MSIE 6.0")
314
+ @browser = "MSIE"
315
+ @browser_version_major = '6'
316
+ @browser_version_minor = '0'
317
+ end
318
+ if agent.include?("MSIE 7.0")
319
+ @browser = "MSIE"
320
+ @browser_version_major = '7'
321
+ @browser_version_minor = '0'
322
+ end
323
+ if agent.include?("MSIE 8.0")
324
+ @browser = "MSIE"
325
+ @browser_version_major = '8'
326
+ @browser_version_minor = '0'
327
+ end
328
+ end
329
+ end
330
+
331
+ #
332
+ #
333
+ # =======================================
334
+ # description:
335
+ # ----------------
336
+ #
337
+ # params:
338
+ # ----------------
339
+ #
340
+ # returns:
341
+ # ----------------
342
+ def process_firefox(agent)
343
+ @identifier = @engine if @identifier == ""
344
+
345
+ if agent.include?("Firefox")
346
+ @browser = "Firefox"
347
+ end
348
+
349
+ if @identifier.include?("Firefox") || @renderer.include?("Firefox") || @engine.include?("Firefox")
350
+ @browser = "Firefox"
351
+
352
+
353
+ identifier_sub = nil
354
+ @identifier.gsub(/[\\:\?'"%!@#\$\^&\*\(\)\+]/, '').split(" ").each do |ident|
355
+ identifier_sub = ident.sub("Firefox\/", "").sub("Gecko/", "") if ident.include?("Firefox")
356
+ identifier_sub.gsub!(/[\+]/, '') if identifier_sub && identifier_sub.include?("+")
357
+ end
358
+ if identifier_sub == nil && @renderer.include?("Firefox")
359
+ renderer_gsub_gsub = @renderer.sub("\(", "").sub("\)", "")
360
+ renderer_gsub_gsub.strip.split(",").each do |sec|
361
+ identifier_sub = sec.sub("Firefox\/", "").strip if sec.include?("Firefox")
362
+ end
363
+ end
364
+ if identifier_sub == nil && @engine.include?("Firefox")
365
+ @engine.gsub(/[\\:\?'"%!@#\$\^&\*\(\)\+]/, '').split(" ").each do |ident|
366
+ identifier_sub = ident.sub("Firefox\/", "").sub("Gecko/", "") if ident.include?("Firefox")
367
+ identifier_sub.gsub!(/[\+]/, '') if identifier_sub && identifier_sub.include?("+")
368
+ end
369
+ end
370
+
371
+ if identifier_sub
372
+ version_numbers = identifier_sub.split(".")
373
+ @browser_version_major = version_numbers[0] if version_numbers.size > 0
374
+ @browser_version_minor = version_numbers[1] if version_numbers.size > 1
375
+ @browser_version_sub = version_numbers[2] if version_numbers.size > 2
376
+ end
377
+
378
+ end
379
+ return true if @browser && @browser_version_major
380
+ false
381
+ end
382
+
383
+ #
384
+ #
385
+ # =======================================
386
+ # description:
387
+ # ----------------
388
+ #
389
+ # params:
390
+ # ----------------
391
+ #
392
+ # returns:
393
+ # ----------------
394
+ def process_opera(agent)
395
+
396
+ end
397
+
398
+ #
399
+ #
400
+ # =======================================
401
+ # description:
402
+ # ----------------
403
+ #
404
+ # params:
405
+ # ----------------
406
+ #
407
+ # returns:
408
+ # ----------------
409
+ def process_netscape(agent)
410
+
411
+ end
412
+
413
+ =begin
414
+
415
+ def known_browser(browser)
416
+
417
+ browsers = %w[ Firefox Safari MSIE ]
418
+ flag = false
419
+ browsers.each do |b|
420
+ flag = true if b == browser
421
+ end
422
+
423
+ flag
424
+ end
425
+
426
+ def known_safari_agent_string(string)
427
+ agents = []
428
+ agents << "AppleWebKit"
429
+ agents << "iPhone"
430
+
431
+ agents.each do |agent|
432
+ return true if string.include?(agent)
433
+ end
434
+ false
435
+ end
436
+
437
+ def mobile_browser?(string)
438
+ agents = []
439
+ agents << "iPhone"
440
+
441
+ agents.each do |agent|
442
+ if string.include?(agent)
443
+ @mobile_browser = agent
444
+ return true
445
+ end
446
+ end
447
+ false
448
+ end
449
+
450
+ def console_browser?(string)
451
+ agents = []
452
+
453
+ agents.each do |agent|
454
+ if string.include?(agent)
455
+ @console_browser = agent
456
+ return true
457
+ end
458
+ end
459
+ false
460
+ end
461
+
462
+ def is_safari?(str)
463
+ s = []
464
+ s << "iPhone"
465
+ s << "Safari"
466
+
467
+ flag = false
468
+ s.each do |st|
469
+ flag = true if str.include?(st)
470
+ end
471
+ flag
472
+ end
49
473
 
50
474
  def parse(user_agent)
51
475
  if '-' == user_agent
@@ -69,24 +493,66 @@ module SoldierOfCode
69
493
  # cycle through the agents to set browser and version (MSIE is set later)
70
494
  if @agents && @agents.length > 0
71
495
  @agents.each {|agent|
496
+
72
497
  parts = agent.split('/')
73
498
  @browser = parts[0]
74
499
  @browser_version = parts[1]
500
+
75
501
  if @browser == 'Firefox'
76
502
  @browser_version_major = parts[1].slice(0, 3)
77
503
  @browser_version_minor = parts[1].sub(@browser_version_major, '').sub('.', '')
504
+
78
505
  elsif @browser == 'Safari'
79
- if parts[1].slice(0, 3).to_f < 400
80
- @browser_version_major = '1'
81
- else
82
- @browser_version_major = '2'
506
+ rx = Regexp.new("Version/([0-9]+)\.([0-9]+)\.([0-9]+)")
507
+ rx.match(user_agent)
508
+
509
+ @browser_version_major = $1
510
+ @browser_version_minor = $2
511
+ @browser_version_sub = $3
512
+
513
+ unless $1
514
+
515
+ v1_0_3 = []
516
+ v1_0_3 << "85.8.1"
517
+ v1_0_3 << "85"
518
+ v1_0_3 << "85.8"
519
+
520
+
521
+ vs = parts[1].split("\.")
522
+ vs1 = vs[0].to_i
523
+ if vs1 < 126
524
+ @browser_version_major = '1'
525
+
526
+ if vs[1].to_i < 8
527
+ @browser_version_minor = '0'
528
+ @browser_version_sub = '0'
529
+ elsif vs[1].to_i >= 8
530
+ @browser_version_minor = '0'
531
+ @browser_version_sub = '3'
532
+ end
533
+
534
+ end
535
+
83
536
  end
537
+
84
538
  else
539
+ # puts "#{__FILE__}:#{__LINE__} #{__method__} here---"
85
540
  @browser_version_major = parts[1].slice(0, 1)
86
541
  end
87
542
  }
88
543
  end
89
544
 
545
+
546
+ if !known_browser(@browser) then
547
+
548
+ @browser = 'Safari' if is_safari?(user_agent) || known_safari_agent_string(user_agent)
549
+
550
+ end
551
+
552
+ # I'm thinking of making this a lazy call....
553
+ mobile_browser?(user_agent)
554
+ console_browser?(user_agent)
555
+
90
556
  # grab all of the properties (within parens)
91
557
  # should be in relation to the agent if possible
92
558
  @detail = @user_agent
@@ -135,6 +601,6 @@ module SoldierOfCode
135
601
  self
136
602
  end
137
603
 
138
-
604
+ =end
139
605
  end
140
606
  end
data/spy-vs-spy.gemspec CHANGED
@@ -1,17 +1,76 @@
1
1
  Gem::Specification.new do |s|
2
- s.name = "spy-vs-spy"
3
- s.version = "0.0.1"
4
- s.date = "2009-11-19"
5
- s.summary = "UserAgent Detection Middleware for Rack."
6
- s.email = "kaptiankrispy@soldierofcode.com"
2
+ s.name = "spy-vs-spy"
3
+ s.version = "0.0.3"
4
+ s.date = "2009-11-23"
5
+ s.summary = "UserAgent Detection Middleware for Rack."
6
+ s.email = "kaptiankrispy@soldierofcode.com"
7
7
  s.homepage = "http://github.com/kuccello/Spy-Vs-Spy"
8
8
  s.description = ""
9
9
  s.has_rdoc = true
10
- s.authors = ["Kristan 'Krispy' Uccello"]
11
- s.files = ["README",
12
- "spy-vs-spy.gemspec",
13
- "lib/spy-vs-spy.rb"]
14
- s.test_files = ["test/ss-test.rb"]
10
+ s.authors = ["Kristan 'Krispy' Uccello"]
11
+ s.files = ["README",
12
+ "spy-vs-spy.gemspec",
13
+ "lib/spy-vs-spy.rb"]
14
+ s.test_files = ["test/ss-test.rb", "test/msie/msie-5.5.txt",
15
+ "test/msie/msie-5.5b1.txt",
16
+ "test/msie/msie-6,0.txt",
17
+ "test/msie/msie-6.0.1.txt",
18
+ "test/msie/msie-6.0.txt",
19
+ "test/msie/msie-6.0b.txt",
20
+ "test/msie/msie-6.1.txt",
21
+ "test/msie/msie-7.0.txt",
22
+ "test/msie/msie-7.0b.txt",
23
+ "test/msie/msie-8.0.txt",
24
+ "test/safari/safari-1.0.3.txt",
25
+ "test/safari/safari-1.2.3.txt",
26
+ "test/safari/safari-1.3.1.txt",
27
+ "test/safari/safari-2.0.1.txt",
28
+ "test/safari/safari-2.0.4.txt",
29
+ "test/safari/safari-3.0.2.txt",
30
+ "test/safari/safari-3.0.txt",
31
+ "test/safari/safari-3.1.txt",
32
+ "test/safari/safari-3.2.3.txt",
33
+ "test/safari/safari-4.0.2.txt",
34
+ "test/safari/safari-4.0dp1.txt",
35
+ "test/safari/safari-1.0.txt",
36
+ "test/safari/safari-1.2.4.txt",
37
+ "test/safari/safari-1.3.2.txt",
38
+ "test/safari/safari-2.0.2.txt",
39
+ "test/safari/safari-2.0.txt",
40
+ "test/safari/safari-3.0.3.txt",
41
+ "test/safari/safari-3.1.1.txt",
42
+ "test/safari/safari-3.2.1.txt",
43
+ "test/safari/safari-3.2.txt",
44
+ "test/safari/safari-4.0.3.txt",
45
+ "test/safari/safari.txt",
46
+ "test/safari/safari-1.2.2.txt",
47
+ "test/safari/safari-1.2.txt",
48
+ "test/safari/safari-1.3.txt",
49
+ "test/safari/safari-2.0.3.txt",
50
+ "test/safari/safari-3.0.1.txt",
51
+ "test/safari/safari-3.0.4.txt",
52
+ "test/safari/safari-3.1.2.txt",
53
+ "test/safari/safari-3.2.2.txt",
54
+ "test/safari/safari-4.0.1.txt",
55
+ "test/safari/safari-4.0.txt",
56
+ "test/firefox/firefox-3.1b2.txt",
57
+ "test/firefox/firefox-3.1b3.txt",
58
+ "test/firefox/firefox-3.5.1.txt",
59
+ "test/firefox/firefox-3.5.2.txt",
60
+ "test/firefox/firefox-3.5.3pre.txt",
61
+ "test/firefox/firefox-3.5.5.txt",
62
+ "test/firefox/firefox-3.5b4.txt",
63
+ "test/firefox/firefox-3.6.txt",
64
+ "test/firefox/firefox-3.6b1.txt",
65
+ "test/firefox/firefox-3.1b2pre.txt",
66
+ "test/firefox/firefox-3.1b3pre.txt",
67
+ "test/firefox/firefox-3.5.12.txt",
68
+ "test/firefox/firefox-3.5.3.txt",
69
+ "test/firefox/firefox-3.5.4.txt",
70
+ "test/firefox/firefox-3.5.txt",
71
+ "test/firefox/firefox-3.5b4pre.txt",
72
+ "test/firefox/firefox-3.6a1pre.txt",
73
+ "test/firefox/firefox-3.8.txt"]
15
74
  s.rdoc_options = ["--main", "README"]
16
75
  s.extra_rdoc_files = ["README"]
17
76
  end
@@ -0,0 +1,9 @@
1
+ Mozilla/5.0 (X11; U; DragonFly i386; de; rv:1.9.1b2) Gecko/20081201 Firefox/3.1b2
2
+ Mozilla/5.0 (Windows; U; Windows NT 6.1; de-AT; rv:1.9.1b2) Gecko/20081201 Firefox/3.1b2
3
+ Mozilla/5.0 (Windows; U; Windows NT 6.0; sv-SE; rv:1.9.1b2) Gecko/20081201 Firefox/3.1b2
4
+ Mozilla/5.0 (Windows; U; Windows NT 6.0; it; rv:1.9.1b2) Gecko/20081201 Firefox/3.1b2
5
+ Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.1b2) Gecko/20081201 Firefox/3.1b2
6
+ Mozilla/5.0 (Windows; U; Windows NT 6.0; de-AT; rv:1.9.1b2) Gecko/20081201 Firefox/3.1b2
7
+ Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.1b2) Gecko/20081201 Firefox/3.1b2
8
+ Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.9.1b2) Gecko/20081201 Firefox/3.1b2
9
+ Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; ko; rv:1.9.1b2) Gecko/20081201 Firefox/3.1b2
@@ -0,0 +1,4 @@
1
+ Mozilla/5.0 (Windows; U; Windows NT 6.0; x64; en-US; rv:1.9.1b2pre) Gecko/20081026 Firefox/3.1b2pre
2
+ Mozilla/5.0 (Windows; U; Windows NT 6.0 x64; en-US; rv:1.9.1b2pre) Gecko/20081026 Firefox/3.1b2pre
3
+ Mozilla/5.0 (Windows; U; Windows NT 6.0 ; x64; en-US; rv:1.9.1b2pre) Gecko/20081026 Firefox/3.1b2pre
4
+ Mozilla/5.0 (Windows; U; Windows NT 5.1 ; x64; en-US; rv:1.9.1b2pre) Gecko/20081026 Firefox/3.1b2pre
@@ -0,0 +1,32 @@
1
+ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1b3) Gecko/20090327 Fedora/3.1-0.11.beta3.fc11 Firefox/3.1b3
2
+ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1b3) Gecko/20090312 Firefox/3.1b3
3
+ Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1b3) Gecko/20090407 Firefox/3.1b3
4
+ Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3
5
+ Mozilla/5.0 (Windows; U; Windows NT 6.1; pl; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3 GTB5 (.NET CLR 3.5.30729)
6
+ Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3
7
+ Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1) Gecko/20090624 Firefox/3.1b3;MEGAUPLOAD 1.0 (.NET CLR 3.5.30729)
8
+ Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3 GTB5 (.NET CLR 3.5.30729)
9
+ Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3 (.NET CLR 3.5.30729)
10
+ Mozilla/5.0 (Windows; U; Windows NT 6.1; de; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3
11
+ Mozilla/5.0 (Windows; U; Windows NT 6.0; fr; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3
12
+ Mozilla/5.0 (Windows; U; Windows NT 6.0; es-AR; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3
13
+ Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1b3) Gecko/20090405 Firefox/3.1b3
14
+ Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3 (.NET CLR 3.5.30729)
15
+ Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3
16
+ Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3 (.NET CLR 3.5.30729)
17
+ Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3
18
+ Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3
19
+ Mozilla/5.0 (Windows; U; Windows NT 5.1; nl; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3 (.NET CLR 3.5.30729)
20
+ Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3 (.NET CLR 3.5.30729)
21
+ Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3
22
+ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3 GTB5 (.NET CLR 3.5.30729)
23
+ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3 (.NET CLR 3.5.30729)
24
+ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3 (.NET CLR 3.5.21022)
25
+ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3 (.NET CLR 3.5.30729)
26
+ Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.5; en-US; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3
27
+ Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3
28
+ Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; fr; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3
29
+ Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; es-ES; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3
30
+ Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3 GTB5
31
+ Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-GB; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3
32
+ Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; sv-SE; rv:1.9.1b3) Gecko/20090305 Firefox/3.1b3
@@ -0,0 +1,2 @@
1
+ Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.9.1b3pre) Gecko/20090105 Firefox/3.1b3pre
2
+ Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20090204 Firefox/3.1b3pre