Class: Extra

Inherits:
Base show all
Defined in:
lib/handset_detection/extra.rb

Instance Method Summary collapse

Methods inherited from Base

#clean_str, #extra_clean_str, #get_branch, #get_match, #get_message, #get_reply, #get_status, #has_bi_keys, #log, #post, #remote, #send_remote_syslog, #set_error, #set_reply

Constructor Details

#initialize(config = {}) ⇒ Extra

Returns a new instance of Extra.



30
31
32
33
34
35
# File 'lib/handset_detection/extra.rb', line 30

def initialize(config={})
  @data = nil
  @store = nil
  super()
  set_config config
end

Instance Method Details

#break_version_apart(version_number) ⇒ Object

Breaks a version number apart into its Major, minor and point release numbers for comparison.

Big Assumption : That version numbers separate their release bits by ‘.’ !!! might need to do some analysis on the string to rip it up right.

param string version_number return hash of (‘major’ => x, ‘minor’ => y and ‘point’ => z) on success, null otherwise



185
186
187
188
189
190
191
192
# File 'lib/handset_detection/extra.rb', line 185

def break_version_apart(version_number)
  tmp = "#{version_number}.0.0.0".split('.', 4)
  reply = {}
  reply['major'] = tmp[0].blank? ? '0' : tmp[0]
  reply['minor'] = tmp[1].blank? ? '0' : tmp[1]
  reply['point'] = tmp[2].blank? ? '0' : tmp[2]
  reply
end

#compare_platform_versions(va, vb) ⇒ Object

Compares two platform version numbers

param string va Version A param string vb Version B return < 0 if a < b, 0 if a == b and > 0 if a > b : Also returns 0 if data is absent from either.



214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/handset_detection/extra.rb', line 214

def compare_platform_versions(va, vb)
  return 0 if va.blank? or vb.blank?
  version_a = break_version_apart va
  version_b = break_version_apart vb
  major = compare_smartly version_a['major'], version_b['major']
  minor = compare_smartly version_a['minor'], version_b['minor']
  point = compare_smartly version_a['point'], version_b['point']
  return major if major != 0
  return minor if minor != 0
  return point if point != 0
  return 0
end

#compare_smartly(a, b) ⇒ Object

Helper for comparing two strings (numerically if possible)

param string a Generally a number, but might be a string param string b Generally a number, but might be a string return int



200
201
202
203
204
205
206
# File 'lib/handset_detection/extra.rb', line 200

def compare_smartly(a, b)
  begin
    return Integer(a) - Integer(b)
  rescue
    return a <=> b
  end
end

#find_by_id(_id) ⇒ Object

Find a device by its id

param string _id return hash device on success, false otherwise



84
85
86
# File 'lib/handset_detection/extra.rb', line 84

def find_by_id(_id)
  @store.read "Extra_#{_id}"
end

#match_extra(cls, headers) ⇒ Object

Matches all HTTP header extras - platform, browser and app

param string cls Is ‘platform’,‘browser’ or ‘app’ return an Extra on success, false otherwise



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/handset_detection/extra.rb', line 57

def match_extra(cls, headers)
  headers.delete 'profile'
  order = @detection_config["#{cls}-ua-order"]

  headers.keys.each do |key|
    # Append any x- headers to the list of headers to check
    if (not order.include?(key)) and /^x-/i.match(key)
      order << key
    end
  end 
  order.each do |field|
    unless headers[field].blank?
      _id = get_match 'user-agent', headers[field], cls, field, cls
      if _id
        extra = find_by_id _id
        return extra
      end
    end
  end 
  false
end

#match_language(headers) ⇒ Object

Can learn language from language header or agent

param hash headers A key => value hash of sanitized http headers return hash Extra on success, false otherwise



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/handset_detection/extra.rb', line 93

def match_language(headers)
  extra = { 'Extra' => { 'hd_specs' => {}} }

  # Mock up a fake Extra for merge into detection reply.
  extra['_id'] = 0.to_int
  extra['Extra']['hd_specs']['general_language'] = ''
  extra['Extra']['hd_specs']['general_language_full'] = ''

  # Try directly from http header first
  unless headers['language'].blank?
    candidate = headers['language']
    if @detection_languages.include?(candidate) and @detection_languages[candidate]
      extra['Extra']['hd_specs']['general_language'] = candidate
      extra['Extra']['hd_specs']['general_language_full'] = @detection_languages[candidate]
      return extra
    end
  end

  check_order = @detection_config['language-ua-order'] + headers.keys
  language_list = @detection_languages
  check_order.each do |header|
    if headers.include?(header) and not headers[header].blank?
      agent = headers[header]
      language_list.each do |code, full|
        if /[; \(]#{code}[; \)]/i.match(agent)
          extra['Extra']['hd_specs']['general_language'] = code
          extra['Extra']['hd_specs']['general_language_full'] = full
          return extra
        end
      end 
    end
  end 
  false
end

#set(data) ⇒ Object



48
49
50
# File 'lib/handset_detection/extra.rb', line 48

def set(data)
  @data = data
end

#set_config(config) ⇒ Object

Set Config variables

param hash config A config hash return boolean true on success, false otherwise



42
43
44
45
46
# File 'lib/handset_detection/extra.rb', line 42

def set_config(config)
  @store = Store::get_instance
  @store.set_config config
  true
end

#verify_platform(specs = nil) ⇒ Object

Returns false if this device definitively cannot run this platform and platform version. Returns true if its possible of if there is any doubt.

Note : The detected platform must match the device platform. This is the stock OS as shipped on the device. If someone is running a variant (eg CyanogenMod) then all bets are off.

param string specs The specs we want to check. return boolean false if these specs can not run the detected OS, true otherwise.



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/handset_detection/extra.rb', line 137

def verify_platform(specs=nil)
  platform = @data
  platform = {} unless platform
  if platform.include? 'Extra' and platform['Extra'].include? 'hd_specs'
    platform_name    = platform['Extra']['hd_specs']['general_platform']        .to_s.downcase.strip if platform['Extra']['hd_specs'].include? 'general_platform'
    platform_version = platform['Extra']['hd_specs']['general_platform_version'].to_s.downcase.strip if platform['Extra']['hd_specs'].include? 'general_platform_version'
  else
    platform_name = nil
    platform_version = nil
  end
  device_platform_name        = specs['general_platform']            .to_s.downcase.strip
  device_platform_version_min = specs['general_platform_version']    .to_s.downcase.strip
  device_platform_version_max = specs['general_platform_version_max'].to_s.downcase.strip

  # Its possible that we didnt pickup the platform correctly or the device has no platform info
  # Return true in this case because we cant give a concrete false (it might run this version).
  if platform.blank? or platform_name.blank? or device_platform_name.blank?
    return true
  end

  # Make sure device is running stock OS / Platform
  # Return true in this case because its possible the device can run a different OS (mods / hacks etc..)
  if platform_name != device_platform_name
    return true
  end

  # Detected version is lower than the min version - so definetly false.
  if not platform_version.blank? and not device_platform_version_min.blank? and compare_platform_versions(platform_version, device_platform_version_min) <= -1
    return false
  end

  # Detected version is greater than the max version - so definetly false.
  if not platform_version.blank? and not device_platform_version_max.blank? and compare_platform_versions(platform_version, device_platform_version_max) >= 1
    return false
  end

  # Maybe Ok ..
  true
end