Class: HD4

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

Overview

HD4 Class

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Base

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

Constructor Details

#initialize(config = nil) ⇒ HD4

This is the main constructor for the class HD4

param mixed config can be a hash of config options or a fully qualified path to an alternate config file. return void



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/handset_detection/hd4.rb', line 43

def initialize(config=nil)
  @realm = 'APIv4'
  @reply = nil
  @raw_reply = nil
  @detect_request = {} 
  @error = ''
  @logger = nil
  @debug = false
  @config = { 
    'username' => '',
    'secret' => '',
    'site_id' => '',
    'use_proxy' => 0,
    'proxy_server' => '',
    'proxy_port' => '',
    'proxy_user' => '',
    'proxy_pass' => '',
    'use_local' => false,
    'api_server' => 'api.handsetdetection.com',
    'timeout' => 10,
    'debug' => false,
    'filesdir' => '',
    'retries' => 3,
    'cache_requests' => false,
    'geoip' => false,
    'log_unknown' => true
  }
  @tree = {} 
  if config.blank?
    if defined? Rails
      config = File.join Rails.root, 'config', 'hdconfig.yml'
    else
      config = 'hdconfig.yml'
    end
  end
  super()
  set_config config
  if @config['username'].blank?
    raise 'Error : API username not set. Download a premade config from your Site Settings.'
  elsif @config['secret'].blank?
    raise 'Error : API secret not set. Download a premade config from your Site Settings.'
  end
end

Instance Attribute Details

#cacheObject (readonly)

Returns the value of attribute cache.



36
37
38
# File 'lib/handset_detection/hd4.rb', line 36

def cache
  @cache
end

Instance Method Details

#community_fetch_archiveObject

Community Fetch Archive - Fetch the community archive version

param void return hd_specs data on success, false otherwise



427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
# File 'lib/handset_detection/hd4.rb', line 427

def community_fetch_archive
  path = community_get_zip_path
  unless @config['local_archive_source'].blank?
    FileUtils.cp File.join(@config['local_archive_source'], "communityultimate.zip"), path
    return install_archive path 
  end

  return false unless remote "community/fetcharchive", '', 'zip', false
  data = get_raw_reply
  if data.blank?
    return set_error 299, 'Error : FetchArchive failed. Bad Download. File is zero length'
  elsif data.length < 900000
    begin
      trythis = JSON.parse data
      if not trythis.blank? and trythis.include?('status') and trythis.include?('message')
        return set_error trythis['status'].to_int, trythis['message']
      end
    rescue Exception
      return set_error 299, "Error : FetchArchive failed. Cannot parse the file."
    end
    return set_error 299, "Error : FetchArchive failed. Bad Download. File too short at #{data.length} bytes."
  end

  begin
    File.open(path, 'wb') { |f| f.write data  }
  rescue
    return set_error 299, "Error : FetchArchive failed. Could not write #{path}"
  end
 return install_archive path 
end

#community_get_zip_pathObject

Get the local file path of the Ultimate database ZIP file.

return string path



382
383
384
# File 'lib/handset_detection/hd4.rb', line 382

def community_get_zip_path
  File.join(@config['filesdir'], "communityultimate.zip")
end

#device_detect(data = {}) ⇒ Object

Device Detect

param array data : Data for device detection : HTTP Headers usually return bool true on success, false otherwise. Use getReply to inspect results on success.



328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
# File 'lib/handset_detection/hd4.rb', line 328

def device_detect(data={})
  id = data['id'].blank? ? @config['site_id'] : data['id']
  data.delete 'id'
  request_body = data.blank? ? @detect_request: data
  fast_key = ''
  
  # If caching enabled then check cache
  unless @config['cache_requests'].blank?
    headers = {}
    request_body.each { |k, v| headers[k.downcase] = v }
    headers = Hash[headers.sort]
    fast_key = JSON.generate(headers).gsub(/ /, '')
    if reply = @cache.read(fast_key)
      @reply = reply
      @raw_reply = ''
      return set_error 0, "OK"
    end
  end
  
  if @config['use_local']
    # log("Starting Local Detection")
    result = @device.local_detect(request_body)
    set_error @device.get_status, @device.get_message
    set_reply @device.get_reply
    # log"Finishing Local Detection : result is #{result}"
    # Log unknown headers if enabled
    if @config['log_unknown'] == true and not result
      send_remote_syslog request_body
    end
  else
    # log "Starting API Detection"
    result = remote "device/detect/#{id}", request_body
    # log "Finishing API Detection : result is #{result}"
  end

  # If we got a result then cache it
  if result and not @config['cache_requests'].blank?
    @cache.write fast_key, reply
  end
  result
end

#device_fetch_archiveObject

Fetch an archive from handset detection which contains all the device specs and matching trees as individual json files.

param void return hd_specs data on success, false otherwise



391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
# File 'lib/handset_detection/hd4.rb', line 391

def device_fetch_archive
  path = device_get_zip_path
  unless @config['local_archive_source'].blank?
    FileUtils.cp File.join(@config['local_archive_source'], "ultimate.zip"), path
    return install_archive path 
  end

  return false unless remote("device/fetcharchive", '', 'zip')
  data = get_raw_reply
  if data.blank? 
    return set_error 299, 'Error : FetchArchive failed. Bad Download. File is zero length'
  elsif data.length < 9000000
    begin
      trythis = JSON.parse data
      if trythis and trythis.include?('status') and trythis.include('message')
        return set_error trythis['status'].to_i, trythis['message']
      end
    rescue Exception
      return set_error 299, "Error : FetchArchive failed. Cannot parse the file."
    end
    return set_error 299, "Error : FetchArchive failed. Bad Download. File too short at #{data.length} bytes."
  end

  begin
    File.open(path, 'wb') { |f| f.write(get_raw_reply) }
  rescue
    return set_error 299, "Error : FetchArchive failed. Could not write #{path}"
  end
  return install_archive path 
end

#device_get_zip_pathObject

Get the local file path of the Ultimate database ZIP file.

return string path



374
375
376
# File 'lib/handset_detection/hd4.rb', line 374

def device_get_zip_path
  File.join(@config['filesdir'], "ultimate.zip")
end

#device_models(vendor) ⇒ Object

List all models for a given vendor

param string vendor The device vendor eg Apple return bool true on success, false otherwise. Use getReply to inspect results on success.



277
278
279
280
281
282
283
284
285
286
287
# File 'lib/handset_detection/hd4.rb', line 277

def device_models(vendor)
  unless @config['use_local']
    return remote "device/models/#{vendor}", nil
  end

  if @device.local_models vendor
    @reply = @device.get_reply
  end

  set_error @device.get_status, @device.get_message
end

#device_vendorsObject

List all known vendors

param void return bool true on success, false otherwise. Use getReply to inspect results on success.



266
267
268
269
270
# File 'lib/handset_detection/hd4.rb', line 266

def device_vendors
  return remote("device/vendors", nil) unless @config['use_local']
  @reply = @device.get_reply if @device.local_vendors
  set_error @device.get_status, @device.get_message
end

#device_view(vendor, model) ⇒ Object

Find properties for a specific device

param string vendor The device vendor eg. Nokia param string model The deviec model eg. N95 return bool true on success, false otherwise. Use getReply to inspect results on success.



295
296
297
298
299
300
301
302
303
# File 'lib/handset_detection/hd4.rb', line 295

def device_view(vendor, model)
  unless @config['use_local']
    return remote "device/view/#{vendor}/#{model}", nil 
  end
  if @device.local_view vendor, model
    @reply = @device.get_reply
  end
  set_error @device.get_status, @device.get_message
end

#device_what_has(key, value) ⇒ Object

Find which devices have property ‘X’.

param string key Property to inquire about eg ‘network’, ‘connectors’ etc… param string value Value to inquire about eg ‘CDMA’, ‘USB’ etc … return bool true on success, false otherwise. Use getReply to inspect results on success.



311
312
313
314
315
316
317
318
319
320
321
# File 'lib/handset_detection/hd4.rb', line 311

def device_what_has(key, value)
  unless @config['use_local']
    return remote("device/whathas/#{key}/#{value}", nil)
  end
  
  if @device.local_what_has key, value
    @reply = @device.get_reply
  end
    
  set_error @device.get_status, @device.get_message
end

#get_api_serverObject



210
211
212
# File 'lib/handset_detection/hd4.rb', line 210

def get_api_server
   @config['api_server']
end

#get_detect_requestObject



214
215
216
# File 'lib/handset_detection/hd4.rb', line 214

def get_detect_request
   @detect_request
end

#get_errorObject



174
175
176
# File 'lib/handset_detection/hd4.rb', line 174

def get_error
   @error
end

#get_error_msgObject



178
179
180
# File 'lib/handset_detection/hd4.rb', line 178

def get_error_msg
   @error
end

#get_files_dirObject



218
219
220
# File 'lib/handset_detection/hd4.rb', line 218

def get_files_dir
   @config['filesdir']
end

#get_local_detectionObject



150
151
152
# File 'lib/handset_detection/hd4.rb', line 150

def get_local_detection
   @config['use_local']
end

#get_proxy_passObject



158
159
160
# File 'lib/handset_detection/hd4.rb', line 158

def get_proxy_pass
   @config['proxy_pass']
end

#get_proxy_portObject



170
171
172
# File 'lib/handset_detection/hd4.rb', line 170

def get_proxy_port
   @config['proxy_port']
end

#get_proxy_serverObject



166
167
168
# File 'lib/handset_detection/hd4.rb', line 166

def get_proxy_server
   @config['proxy_server']
end

#get_proxy_userObject



154
155
156
# File 'lib/handset_detection/hd4.rb', line 154

def get_proxy_user
   @config['proxy_user']
end

#get_raw_replyObject



198
199
200
# File 'lib/handset_detection/hd4.rb', line 198

def get_raw_reply
   @raw_reply
end

#get_replyObject



194
195
196
# File 'lib/handset_detection/hd4.rb', line 194

def get_reply
   @reply
end

#get_secretObject



182
183
184
# File 'lib/handset_detection/hd4.rb', line 182

def get_secret
   @config['secret']
end

#get_site_idObject



202
203
204
# File 'lib/handset_detection/hd4.rb', line 202

def get_site_id
   @config['site_id']
end

#get_timeoutObject



190
191
192
# File 'lib/handset_detection/hd4.rb', line 190

def get_timeout
   @config['timeout']
end

#get_use_localObject



206
207
208
# File 'lib/handset_detection/hd4.rb', line 206

def get_use_local
   @config['use_local']
end

#get_use_proxyObject



162
163
164
# File 'lib/handset_detection/hd4.rb', line 162

def get_use_proxy
   @config['use_proxy']
end

#get_usernameObject



186
187
188
# File 'lib/handset_detection/hd4.rb', line 186

def get_username
   @config['username']
end

#install_archive(file) ⇒ Object

Install an ultimate archive file

param string $file Fully qualified path to file return boolean true on success, false otherwise



463
464
465
466
467
468
469
470
471
472
473
474
# File 'lib/handset_detection/hd4.rb', line 463

def install_archive(file)
  # Unzip the archive and cache the individual files
  Zip::File.open(file) do |zip_file|
    #  return $this->setError(299, "Error : Failed to open ". $file)
    zip_file.each do |entry|
      filename = File.join Dir.tmpdir, entry.name
      entry.extract(filename) {true}
      @store.move_in filename, entry.name
    end
  end
  true
end

#is_helper_useful(headers) ⇒ Object

This method can indicate if using the js Helper would yeild more accurate results.

param hash headers return true if helpful, false otherwise.



481
482
483
# File 'lib/handset_detection/hd4.rb', line 481

def is_helper_useful(headers)
  @device.is_helper_useful headers
end

#set_api_server(value) ⇒ Object



135
136
137
# File 'lib/handset_detection/hd4.rb', line 135

def set_api_server(value) 
   @config['api_server'] = value
end

#set_config(cfg) ⇒ Object

Set config file

param hash config An assoc array of config data return true on success, false otherwise



227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/handset_detection/hd4.rb', line 227

def set_config(cfg)
  if cfg.is_a? Hash
    @config = cfg
  elsif cfg.is_a? String
    @config = YAML::load_file cfg
  end
  
  if @config['filesdir'].blank?
    @config['filesdir'] = File.dirname __FILE__ 
  end

  @store = Store::get_instance
  @store.set_config @config, true
  @cache = Cache.new(@config)
  @device = Device.new(@config)
  true
end

#set_detect_var(key, value) ⇒ Object



123
124
125
# File 'lib/handset_detection/hd4.rb', line 123

def set_detect_var(key, value) 
   @detect_request[key.downcase] = value
end

#set_files_dir(directory) ⇒ Object



143
144
145
146
147
148
# File 'lib/handset_detection/hd4.rb', line 143

def set_files_dir(directory)
  @config['filesdir'] = directory
  unless @store.set_directory(directory)
    raise "Error : Failed to create cache directory in #{directory}. Set your filesdir config setting or check directory permissions."
  end
end

#set_local_detection(enable) ⇒ Object



87
88
89
# File 'lib/handset_detection/hd4.rb', line 87

def set_local_detection(enable)
   @config['use_local'] = enable
end

#set_logger(function) ⇒ Object



139
140
141
# File 'lib/handset_detection/hd4.rb', line 139

def set_logger(function) 
   @config['logger'] = function
end

#set_proxy_pass(pass) ⇒ Object



95
96
97
# File 'lib/handset_detection/hd4.rb', line 95

def set_proxy_pass(pass)
   @config['proxy_pass'] = pass
end

#set_proxy_port(number) ⇒ Object



107
108
109
# File 'lib/handset_detection/hd4.rb', line 107

def set_proxy_port(number) 
  @config['proxy_port'] = number
end

#set_proxy_server(name) ⇒ Object



103
104
105
# File 'lib/handset_detection/hd4.rb', line 103

def set_proxy_server(name) 
   @config['proxy_server'] = name
end

#set_proxy_user(user) ⇒ Object



91
92
93
# File 'lib/handset_detection/hd4.rb', line 91

def set_proxy_user(user)
   @config['proxy_user'] = user
end

#set_secret(secret) ⇒ Object



111
112
113
# File 'lib/handset_detection/hd4.rb', line 111

def set_secret(secret) 
   @config['secret'] = secret
end

#set_server_headers(env) ⇒ Object

Setup the api kit with HTTP headers from the web server environment.

This is likely what you want to send if you’re invoking this class for each new website visitor. You can override or add to these with set_detect_var(key, value)

param env A hash holding web server environment variables. In Rails: request.env or request.headers return void



253
254
255
256
257
258
259
# File 'lib/handset_detection/hd4.rb', line 253

def set_server_headers(env)
  env.each do |k, v|
    next unless k.match(/^HTTP_/)
    name = k.sub(/^HTTP_/, '').split(/_/).map { |x| x.capitalize }.join('-')
    @detect_request[name] = v
  end
end

#set_site_id(siteid) ⇒ Object



127
128
129
# File 'lib/handset_detection/hd4.rb', line 127

def set_site_id(siteid) 
   @config['site_id'] = siteid.to_i
end

#set_timeout(timeout) ⇒ Object



119
120
121
# File 'lib/handset_detection/hd4.rb', line 119

def set_timeout(timeout) 
   @config['timeout'] = timeout
end

#set_use_local(value) ⇒ Object



131
132
133
# File 'lib/handset_detection/hd4.rb', line 131

def set_use_local(value) 
   @config['use_local'] = value
end

#set_use_proxy(proxy) ⇒ Object



99
100
101
# File 'lib/handset_detection/hd4.rb', line 99

def set_use_proxy(proxy)
   @config['use_proxy'] = proxy
end

#set_username(user) ⇒ Object



115
116
117
# File 'lib/handset_detection/hd4.rb', line 115

def set_username(user) 
   @config['username'] = user
end