mobile-subscriber 1.0.0.alpha4 → 1.0.0.alpha5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/lib/mobile-subscriber.rb +13 -3
  3. data/lib/mobile_subscriber/dictionaries/dialing_and_country_codes.rb +468 -28
  4. data/lib/mobile_subscriber/http/known_imsi_headers.rb +22 -0
  5. data/lib/mobile_subscriber/http/known_msisdn_headers.rb +68 -0
  6. data/lib/mobile_subscriber/http/request_info.rb +166 -0
  7. data/lib/mobile_subscriber/identity.rb +97 -1
  8. data/lib/mobile_subscriber/version.rb +1 -1
  9. data/mobile_subscriber.thor +41 -0
  10. data/spec/factories/mobile_requests.rb +28 -0
  11. data/spec/factories/mobile_requests_from_claro.rb +257 -0
  12. data/spec/factories/mobile_requests_from_iusacell.rb +13 -0
  13. data/spec/factories/mobile_requests_from_movistar.rb +15 -0
  14. data/spec/factories/mobile_requests_from_telcel.rb +14 -0
  15. data/spec/factories/mobile_requests_from_vivo.rb +13 -0
  16. data/spec/features/claro_user_detection_spec.rb +170 -0
  17. data/spec/features/iusacell_user_detection_spec.rb +19 -0
  18. data/spec/features/movistar_user_detection_spec.rb +19 -0
  19. data/spec/features/telcel_user_detection_spec.rb +19 -0
  20. data/spec/models/{isdn_spec.rb → identity_spec.rb} +5 -5
  21. data/spec/shared_examples/identity_detection_in_argentina.rb +11 -0
  22. data/spec/shared_examples/identity_detection_in_brazil.rb +12 -0
  23. data/spec/shared_examples/identity_detection_in_chile.rb +12 -0
  24. data/spec/shared_examples/identity_detection_in_colombia.rb +12 -0
  25. data/spec/shared_examples/identity_detection_in_costa_rica.rb +15 -0
  26. data/spec/shared_examples/identity_detection_in_dominican_republic.rb +12 -0
  27. data/spec/shared_examples/identity_detection_in_ecuador.rb +12 -0
  28. data/spec/shared_examples/identity_detection_in_el_salvador.rb +15 -0
  29. data/spec/shared_examples/identity_detection_in_guatemala.rb +15 -0
  30. data/spec/shared_examples/identity_detection_in_honduras.rb +11 -0
  31. data/spec/shared_examples/identity_detection_in_mexico.rb +11 -0
  32. data/spec/shared_examples/identity_detection_in_nicaragua.rb +12 -0
  33. data/spec/shared_examples/identity_detection_in_panama.rb +12 -0
  34. data/spec/shared_examples/identity_detection_in_peru.rb +12 -0
  35. data/spec/shared_examples/identity_detection_in_puerto_rico.rb +14 -0
  36. data/spec/shared_examples/of_msisdn_detection_from_http_request.rb +3 -188
  37. data/templates/dialing_and_country_codes.rb.erb +20 -0
  38. metadata +58 -28
  39. data/lib/mobile_subscriber/detection/from_msisdn_http_request_header.rb +0 -48
  40. data/lib/mobile_subscriber/detection/from_x_nokia_msisdn_http_request_header.rb +0 -58
  41. data/lib/mobile_subscriber/detection/from_x_up_calling_line_id_http_request_header.rb +0 -65
  42. data/lib/mobile_subscriber/detection/from_x_up_ch_msisdn_http_request_header.rb +0 -35
  43. data/lib/mobile_subscriber/detection/from_x_up_subno_http_request_header.rb +0 -44
  44. data/lib/mobile_subscriber/detection/from_x_wap_msisdn_http_request_header.rb +0 -37
  45. data/lib/mobile_subscriber/detection/from_x_wap_sesiones3g_mdn_http_request_header.rb +0 -39
  46. data/lib/mobile_subscriber/detection/from_x_ztgo_beareraddress_http_request_header.rb +0 -36
  47. data/lib/mobile_subscriber/detection/http_request_info.rb +0 -77
  48. data/lib/mobile_subscriber/isdn.rb +0 -89
  49. data/spec/detection/from_msisdn_http_request_header_spec.rb +0 -53
  50. data/spec/detection/from_x_nokia_msisdn_http_request_header_spec.rb +0 -99
  51. data/spec/detection/from_x_up_calling_line_id_http_request_header_spec.rb +0 -39
  52. data/spec/detection/from_x_up_subno_http_request_header_spec.rb +0 -43
  53. data/spec/detection/from_x_wap_msisdn_http_request_header_spec.rb +0 -32
  54. data/spec/detection/from_x_wap_sesiones3g_mdn_http_request_header_spec.rb +0 -29
  55. data/spec/factories/requests.rb +0 -229
@@ -0,0 +1,22 @@
1
+ module MobileSubscriber::HTTP
2
+
3
+ # Known IMSI Header and MCC/MNC Tuples:
4
+ KNOWN_IMSI_HEADER_MCC_MNC = {
5
+
6
+ 'X-Imsi' => [
7
+ ['714', '03'], # Claro Panamá
8
+ ],
9
+
10
+ 'X-Nokia-Imsi' => [
11
+ ['704', '01' ], # Claro Guatemala
12
+ ['716', '10' ], # Claro Perú
13
+ ['722', '310'], # Claro Argentina
14
+ ['722', '320'], # Claro Argentina
15
+ ['722', '330'], # Claro Argentina
16
+ ],
17
+
18
+ 'X-Cisco-Imsi' => [
19
+ ['330', '110'], # Claro Puerto Rico
20
+ ]
21
+ }
22
+ end
@@ -0,0 +1,68 @@
1
+ module MobileSubscriber::HTTP
2
+
3
+ KNOWN_MSISDN_HEADER_MCC_MNC = {
4
+
5
+ 'Msisdn' => [
6
+ ['370', '02'], # Claro República Dominicana
7
+ ['714', '03'], # Claro Paraguay
8
+ ['724', '05'], # Claro Brasil A
9
+ ['724', '38'], # Claro Brasil B
10
+ ['740', '01'], # Claro Ecuador
11
+ ],
12
+
13
+ 'X-Cisco-Msisdn' => [
14
+ ['330', '110'], # Claro Puerto Rico
15
+ ],
16
+
17
+ 'X-Nokia-Msisdn' => [
18
+ ['334', '020'], # Telcel México
19
+ ['704', '01' ], # Claro Guatemala
20
+ ['706', '01' ], # Claro El Salvador
21
+ ['708', '001'], # Claro Honduras
22
+ ['710', '21' ], # Claro Nicaragua
23
+ ['712', '03' ], # Claro Costa Rica
24
+ ['722', '310'], # Claro Argentina A
25
+ ['722', '320'], # Claro Argentina B
26
+ ['722', '330'], # Claro Argentina C
27
+ ],
28
+
29
+ 'X-Up-Calling-Line-Id' => [
30
+ ['334', '030'], # Movistar México
31
+ ['716', '06' ], # Movistar Perú
32
+ ['716', '10' ], # Claro Perú
33
+ ['722', '010'], # Movistar Argentina
34
+ ['722', '070'], # Movistar Argentina
35
+ ['724', '02' ], # TIM (Telecom Italia Mobile) Brasil A
36
+ ['724', '03' ], # TIM (Telecom Italia Mobile) Brasil B
37
+ ['724', '04' ], # TIM (Telecom Italia Mobile) Brasil C
38
+ ['724', '30' ], # OI Brasil
39
+ ['724', '31' ], # OI Brasil
40
+ ],
41
+
42
+ 'X-Up-Ch-Msisdn' => [
43
+ ['724', '06'], # Vivo Brasil
44
+ ['724', '10'], # Vivo Brasil
45
+ ['724', '11'], # Vivo Brasil
46
+ ['724', '23'], # Vivo Brasil
47
+ ],
48
+
49
+ 'X-Up-Subno' => [
50
+ ['732', '101'], # Claro Colombia and former Comcel Colombia
51
+ ['714', '03' ], # Claro Panamá
52
+ ],
53
+
54
+ 'X-Wap-Msisdn' => [
55
+ ['730', '03' ], # Claro Chile
56
+ ],
57
+
58
+ 'X-Wap-Sesiones3g-Mdn' => [
59
+ ['334', '040'], # Iusacell México
60
+ ['334', '050'], # Iusacell México
61
+ ],
62
+
63
+ 'X-Ztgo-Beareraddress' => [
64
+ ['740', '00'], # Movistar Ecuador
65
+ ],
66
+ }
67
+
68
+ end
@@ -0,0 +1,166 @@
1
+ require 'mobile_subscriber/http/known_imsi_headers'
2
+ require 'mobile_subscriber/http/known_msisdn_headers'
3
+
4
+ module MobileSubscriber::HTTP
5
+
6
+ class RequestInfo
7
+
8
+ attr_reader :remote_ip, :headers,
9
+ :imsi, :detected_imsi_header_name,
10
+ :msisdn, :detected_msisdn_header_name,
11
+ :mcc, :mnc
12
+
13
+ def initialize(env)
14
+
15
+ @remote_ip = env['REMOTE_ADDR']
16
+
17
+ # Reference Links:
18
+ # - http://www.slideshare.net/DefCamp/mobile-networks-exploiting-http-headers-and-data-traffic
19
+ # - http://www.mulliner.org/collin/academic/publications/mobile_web_privacy_icin10_mulliner.pdf
20
+ @headers = [
21
+ # HTTP Headers that contain important request details for validation
22
+ 'Max-Forwards', # Para validar el número de forwards que el cliente permite... muy pobre..
23
+ 'Via',
24
+ 'X-Forwarded-For', # lista de IP's que originaron la petición, en caso de pasar por proxies:
25
+
26
+ # HTTP headers that contain the MSISDN:
27
+ # http://www.mulliner.org/collin/academic/publications/mobile_web_privacy_icin10_mulliner.pdf
28
+ 'Cookie',
29
+ 'Igcli',
30
+ 'Msisdn',
31
+ 'Rapmin',
32
+ 'X-Cisco-Msisdn',
33
+ 'X-Cisco-Imsi',
34
+ 'X-Fh-Msisdn',
35
+ "X-H3-G-Msisdn",
36
+ 'X-Hts-Clid',
37
+ 'X-Imsi',
38
+ 'X-Jinny-Cid',
39
+ 'X-Msisdn',
40
+ 'X-Msp-Clid',
41
+ 'X-Msp-Msisdn',
42
+ 'X-Network-Info',
43
+ 'X-Nokia-Imsi', # This is a VERY useful one... if you have it!
44
+ 'X-Nokia-Msisdn',
45
+ 'X-Nx-Clid',
46
+ 'X-Orange-Cli',
47
+ 'X-Up-Calling-Line',
48
+ 'X-Up-Calling-Line-Id', # Not in referenced literature
49
+ 'X-Up-Ch-Msisdn', # Not in referenced literature
50
+ 'X-Up-Lsid',
51
+ 'X-Up-Subno', # Not in referenced literature
52
+ 'X-Wap-Fh-Subscriber-Info',
53
+ 'X-Wap-Msisdn',
54
+ 'X-Wap-Sesiones3g-Mdn', # Not in referenced literature
55
+ 'X-Wsb-Cli',
56
+ 'X-Ztgo-Beareraddress', # Not in referenced literature
57
+
58
+ # Headers that contain bearer information:
59
+ # http://www.mulliner.org/collin/academic/publications/mobile_web_privacy_icin10_mulliner.pdf
60
+ 'Bearer',
61
+ 'Bearer-Indication',
62
+ 'New-Bearer-Header',
63
+ 'Nokia-Bearer',
64
+ 'X-Nokia-Bearer',
65
+ 'X-Nokia-Musicshop-Bearer',
66
+ 'X-Up-Bear-Type', # NOT A TYPO
67
+ 'X-Up-Bearer-Type',
68
+ 'X-Bearer-Type',
69
+
70
+ # Headers that contain roaming information:
71
+ # http://www.mulliner.org/collin/academic/publications/mobile_web_privacy_icin10_mulliner.pdf
72
+ 'X-Orange-Roaming',
73
+ 'X-Nokia-Roaming',
74
+ 'X-Roaming',
75
+ 'X-Sdp-Roaming'
76
+ ].inject({}.with_indifferent_access) do |collected_headers, header_name|
77
+ header_env_key = "HTTP_#{header_name.split('-').map(&:upcase).join('_')}"
78
+
79
+ if env.has_key? header_env_key
80
+ collected_headers[header_name] = env[header_env_key].strip
81
+ end
82
+
83
+ collected_headers
84
+ end
85
+
86
+ # IMSI Extraction:
87
+ # Extract the first IMSI Header Value:
88
+ @imsi, @detected_imsi_header_name = MobileSubscriber::HTTP::KNOWN_IMSI_HEADER_MCC_MNC.inject([nil,nil]) do |result, keyval|
89
+ header_name = keyval[0]
90
+ if result.compact.blank? and current_imsi = headers[header_name]
91
+ result = [current_imsi, header_name] if current_imsi.length >= 14
92
+ end
93
+ result
94
+ end
95
+
96
+ # MSISDN Extraction:
97
+ # Extract the first MSISDN Header Value:
98
+ @msisdn, @detected_msisdn_header_name = MobileSubscriber::HTTP::KNOWN_MSISDN_HEADER_MCC_MNC.inject([nil,nil]) do |result, keyval|
99
+ header_name = keyval[0]
100
+ if result.compact.blank? and current_msisdn = headers[header_name]
101
+ result = [current_msisdn, header_name] if current_msisdn.length >= 8
102
+ end
103
+ result
104
+ end
105
+
106
+ # Mobile Operator Info Extraction:
107
+ extract_mobile_operator_info!
108
+
109
+ end
110
+
111
+ def has_imsi?
112
+ imsi.present?
113
+ end
114
+
115
+ def has_msisdn?
116
+ msisdn.present?
117
+ end
118
+
119
+ private
120
+
121
+ def extract_mobile_operator_info!
122
+
123
+ tuples_by_imsi = if has_imsi?
124
+ MobileSubscriber::HTTP::KNOWN_IMSI_HEADER_MCC_MNC[detected_imsi_header_name]
125
+ end
126
+
127
+ tuples_by_msisdn = if has_msisdn?
128
+ MobileSubscriber::HTTP::KNOWN_MSISDN_HEADER_MCC_MNC[detected_msisdn_header_name]
129
+ end
130
+
131
+ tuples_to_check = if tuples_by_imsi.present? && tuples_by_msisdn.present?
132
+ # Intersect known data from request - less tuples to check later
133
+ tuples_by_imsi & tuples_by_msisdn
134
+ elsif tuples_by_imsi.present?
135
+ tuples_by_imsi
136
+ elsif tuples_by_msisdn.present?
137
+ tuples_by_msisdn
138
+ end
139
+
140
+ detected_mobile_operator_info = if tuples_to_check.present? && tuples_to_check.any?
141
+ if has_imsi?
142
+ tuples_to_check.detect { |tuple| imsi.start_with?(tuple.join) }
143
+ elsif has_msisdn?
144
+
145
+ msisdn_country_code = (1..4).to_a.reverse.inject(nil) do |code, prefix_length|
146
+ current_prefix = msisdn[0,prefix_length]
147
+ if code.nil?
148
+ code = MobileSubscriber::DIALING_COUNTRY_CODES[current_prefix]
149
+ end
150
+ code
151
+ end
152
+
153
+ msisdn_mcc = MobileSubscriber::MCC_ISO_COUNTRY_CODES.detect { |key, val| val == msisdn_country_code }.first
154
+
155
+ # TODO Check for duplicates!
156
+ tuples_to_check.detect { |tuple| tuple.first == msisdn_mcc }
157
+
158
+ end
159
+ end
160
+
161
+ @mcc, @mnc = detected_mobile_operator_info if detected_mobile_operator_info.present?
162
+
163
+ end
164
+
165
+ end
166
+ end
@@ -1 +1,97 @@
1
- # Placeholder for the new Mobile User class
1
+ require 'mobile_subscriber/dictionaries/mobile_and_iso_country_codes'
2
+ require 'mobile_subscriber/dictionaries/dialing_and_country_codes'
3
+ require 'mobile_subscriber/dictionaries/operator_data'
4
+
5
+ module MobileSubscriber
6
+
7
+ # Identity class
8
+ class Identity
9
+
10
+ attr_reader :mcc, :mnc, :msisdn, :imsi, :http_request_info
11
+
12
+ alias_method :mobile_country_code, :mcc
13
+ alias_method :mobile_network_code, :mnc
14
+ alias_method :international_mobile_subscriber_identity, :imsi
15
+ alias_method :mobile_station_international_subscriber_directory_number, :msisdn
16
+
17
+ def initialize(attributes={})
18
+ @msisdn = attributes.delete :msisdn
19
+ @imsi = attributes.delete :imsi
20
+ @mcc = attributes.delete :mcc
21
+ @mnc = attributes.delete :mnc
22
+ @http_request_info = attributes.delete :http_request_info
23
+ end
24
+
25
+ def id
26
+ if imsi.present?
27
+ "imsi:#{imsi}"
28
+ else
29
+ "msisdn:#{msisdn}"
30
+ end
31
+ end
32
+ alias_method :to_s, :id
33
+
34
+ def dialing_code
35
+ if mcc.present?
36
+ dialing_codes = MobileSubscriber::DIALING_COUNTRY_CODES.select do |k,v|
37
+ v == iso_3166_country_code
38
+ end.keys
39
+
40
+ if msisdn.present?
41
+ max_length = dialing_codes.map(&:length).max
42
+ msisdn[0,max_length]
43
+ else
44
+ dialing_codes.first
45
+ end
46
+ end
47
+ end
48
+ alias_method :country_dialing_code, :dialing_code
49
+
50
+ def iso_3166_country_code
51
+ MobileSubscriber::MCC_ISO_COUNTRY_CODES[mcc] if mcc.present?
52
+ end
53
+
54
+ def mobile_network_brand
55
+ MobileSubscriber::OPERATOR_DATA[[mcc, mnc]][:brand] if mcc.present? && mnc.present?
56
+ end
57
+
58
+ def mobile_network_operator
59
+ MobileSubscriber::OPERATOR_DATA[[mcc, mnc]][:operator] if mcc.present? && mnc.present?
60
+ end
61
+
62
+ def inspect
63
+ "<MobileSubscriber::Identity #{self.id} (#{self.http_validated? ? '' : 'not '}validated by HTTP)>"
64
+ end
65
+
66
+ def http_validated?
67
+ @http_validated ||= false
68
+ end
69
+
70
+ # Creates a new MobileSubscriber::ISDN from a Rack::Request object
71
+ def self.new_from_request(request)
72
+ http_request_info = MobileSubscriber::HTTP::RequestInfo.new request.env
73
+
74
+ # TODO: Validate request for forged data HERE
75
+
76
+ if http_request_info.has_imsi? || http_request_info.has_msisdn?
77
+ validated_identity = new(
78
+ msisdn: http_request_info.msisdn,
79
+ imsi: http_request_info.imsi,
80
+ mcc: http_request_info.mcc,
81
+ mnc: http_request_info.mnc,
82
+ http_request_info: http_request_info
83
+ )
84
+ validated_identity.send :http_validated!
85
+ validated_identity
86
+ end
87
+ end
88
+
89
+ protected
90
+
91
+ def http_validated!
92
+ @http_validated = true
93
+ end
94
+
95
+ end
96
+
97
+ end
@@ -1,3 +1,3 @@
1
1
  module MobileSubscriber
2
- VERSION = "1.0.0.alpha4"
2
+ VERSION = "1.0.0.alpha5"
3
3
  end
@@ -96,4 +96,45 @@ class MobileSubscriber < Thor
96
96
 
97
97
  end
98
98
 
99
+ # Scrapes the Wikipedia entry of 'Mobile country code' to generate the dictionaries.
100
+ desc "update_country_dialing_codes", "Update the country dialing codes dictionary from countrycode.org"
101
+ def update_country_dialing_codes()
102
+
103
+ # Get the Wikipedia HTML and parse HTML with nokogiri:
104
+ page = Nokogiri::HTML(open "http://countrycode.org/")
105
+
106
+ funky_stripper = -> (str, pttrn) { str.chars.select { |c| c =~ pttrn }.join }
107
+
108
+ # Iterate over the main table > tbody > tr:
109
+ @country_code_data = page.css('table#main_table_blue > tbody > tr').inject([]) do |list, t_row|
110
+ t_cells = t_row.css('td')
111
+
112
+ # Capture the country name:
113
+ name = t_cells[0].text.strip
114
+
115
+ # Capture the iso codes:
116
+ # WTF strip does not work here to clear spaces!
117
+ alpha_2, alpha_3 = t_cells[1].text.split('/').map { |str| funky_stripper.call(str, /[A-Z]/) }
118
+
119
+ # Capture the dialing code:
120
+ dialing = funky_stripper.call(t_cells[2].text, /\d/)
121
+
122
+ # Add to list if alpha_2 and dialing code are both present:
123
+ if alpha_2.present? && dialing.present?
124
+ list << {
125
+ country_name: name,
126
+ iso_code_2: alpha_2,
127
+ iso_code_3: alpha_3,
128
+ dialing_code: dialing
129
+ }
130
+ end
131
+
132
+ # Return updated list:
133
+ list
134
+ end
135
+
136
+ template 'templates/dialing_and_country_codes.rb.erb', 'lib/mobile_subscriber/dictionaries/dialing_and_country_codes.rb'
137
+
138
+ end
139
+
99
140
  end
@@ -0,0 +1,28 @@
1
+ # Read about factories at https://github.com/thoughtbot/factory_girl
2
+
3
+ FactoryGirl.define do
4
+
5
+ factory :common_mobile_request_env, class: Hash do
6
+ initialize_with do
7
+ {
8
+ "HTTP_HOST" => "www.example.com",
9
+ "HTTP_CONNECTION" => "close",
10
+ "HTTP_CACHE_CONTROL" => "no-cache, max-age=0",
11
+ "HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
12
+ "HTTP_USER_AGENT" => "Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X; en-us) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53",
13
+ "HTTP_ACCEPT_ENCODING" => "gzip, deflate, sdch",
14
+ "HTTP_ACCEPT_LANGUAGE" => "en-US,en;q=0.8,es;q=0.6",
15
+ "HTTP_VERSION" => "HTTP/1.1"
16
+ }
17
+ end
18
+ end
19
+
20
+ factory :mobile_request, class: Rack::Request do
21
+ initialize_with do
22
+ new build(:common_mobile_request_env).merge(
23
+ "REMOTE_ADDR" => "201.144.162.4"
24
+ )
25
+ end
26
+ end
27
+
28
+ end
@@ -0,0 +1,257 @@
1
+ # Read about factories at https://github.com/thoughtbot/factory_girl
2
+
3
+ FactoryGirl.define do
4
+
5
+ # Real request captured on claroapps.com at 2015-03-13
6
+ factory :mobile_request_from_claro_argentina, parent: :mobile_request do
7
+ initialize_with do
8
+ new build(:common_mobile_request_env).merge(
9
+ "REMOTE_ADDR" => "23.15.7.188",
10
+ "HTTP_ACCEPT" => "multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*",
11
+ "HTTP_ACCEPT_CHARSET"=> "utf-8,utf-16,iso-8859-1,iso-10646-ucs-2,Shift_JIS,Big5",
12
+ "HTTP_ACCEPT_ENCODING"=>"gzip",
13
+ "HTTP_ACCEPT_LANGUAGE"=>"es",
14
+ "HTTP_AKAMAI_ORIGIN_HOP"=>"1",
15
+ "HTTP_CACHE_CONTROL"=>"no-cache, max-age=0",
16
+ "HTTP_CONNECTION"=>"close",
17
+ "HTTP_CONNECT_TIME"=>"4",
18
+ "HTTP_COOKIE" => "request_method=GET; HttpOnly=; ",
19
+ "HTTP_COOKIE2"=>"$Version=1",
20
+ "HTTP_HOST"=>"www.claroapps.com",
21
+ "HTTP_PRAGMA"=>"no-cache",
22
+ "HTTP_TOTAL_ROUTE_TIME"=>"0",
23
+ "HTTP_USER_AGENT"=> "SonyEricssonW580i/R8BE Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1",
24
+ "HTTP_VERSION"=>"HTTP/1.1",
25
+ "HTTP_VIA"=>"1.1 akamai.net(ghost) (AkamaiGHost), 1.1 vegur",
26
+ "HTTP_X_AKAMAI_CONFIG_LOG_DETAIL"=>"true",
27
+ "HTTP_X_FORWARDED_FOR"=>"172.65.159.141, 170.51.255.15, 23.15.7.188",
28
+ "HTTP_X_FORWARDED_PORT"=>"80",
29
+ "HTTP_X_FORWARDED_PROTO"=>"http",
30
+ "HTTP_X_NOKIA_BEARER"=>"CSD or GPRS or 3G",
31
+ "HTTP_X_NOKIA_CHARGINGID"=>"-335177295",
32
+ "HTTP_X_NOKIA_GATEWAY"=>"NBG/4.0/1",
33
+ "HTTP_X_NOKIA_GGSNIPADDRESS"=>"170.51.252.245",
34
+ "HTTP_X_NOKIA_IMSI"=>"722310115238848",
35
+ "HTTP_X_NOKIA_IPADDRESS"=>"172.65.159.141",
36
+ "HTTP_X_NOKIA_LOCALSOCKET"=>"192.168.16.239:8080",
37
+ "HTTP_X_NOKIA_MAXDOWNLINKBITRATE"=>"0",
38
+ "HTTP_X_NOKIA_MAXUPLINKBITRATE"=>"0",
39
+ "HTTP_X_NOKIA_MSISDN"=>"5491126368595",
40
+ "HTTP_X_NOKIA_PREPAIDID"=>"4",
41
+ "HTTP_X_NOKIA_REMOTESOCKET"=>"172.65.159.141:16513",
42
+ "HTTP_X_NOKIA_ROAMINGID"=>"1",
43
+ "HTTP_X_NOKIA_SGSNIPADDRESS"=>"186.158.128.49",
44
+ "HTTP_X_REQUEST"=>"3e0f82f8-b086-4ad2-8793-c60e6a94c443",
45
+ "HTTP_X_REQUEST_START"=>"1426256922162",
46
+ "HTTP_X_WAP_PROFILE"=>"\"http://wap.sonyericsson.com/UAprof/W580iR201.xml\""
47
+ )
48
+ end
49
+ end
50
+
51
+ factory :mobile_request_from_claro_brasil, parent: :mobile_request do
52
+ initialize_with do
53
+ new build(:common_mobile_request_env).merge(
54
+ "REMOTE_ADDR" => "201.23.176.202",
55
+ "HTTP_MSISDN" => "5500000000000"
56
+ )
57
+ end
58
+ end
59
+
60
+ # TODO: Replace with a real example:
61
+ factory :mobile_request_from_claro_dominican_republic, parent: :mobile_request do
62
+ initialize_with do
63
+ new build(:common_mobile_request_env).merge(
64
+ "REMOTE_ADDR" => "181.37.104.3",
65
+ "HTTP_MSISDN" => "18098591800"
66
+ )
67
+ end
68
+ end
69
+
70
+ # http://ns.myip.ms/view/ip_owners/181034/Claro_Chile_S_a.html
71
+ factory :mobile_request_from_claro_chile, parent: :mobile_request do
72
+ initialize_with do
73
+ new build(:common_mobile_request_env).merge(
74
+ "REMOTE_ADDR" => "191.116.39.114",
75
+ "HTTP_X_WAP_MSISDN" => "56024440000"
76
+ )
77
+ end
78
+ end
79
+
80
+ factory :mobile_request_from_claro_colombia, parent: :mobile_request do
81
+ initialize_with do
82
+ new build(:common_mobile_request_env).merge(
83
+ "REMOTE_ADDR" => "200.26.137.100",
84
+ "HTTP_X_UP_SUBNO" => "57000000000"
85
+ )
86
+ end
87
+ end
88
+
89
+ # TODO: Replace with a real example request:
90
+ factory :mobile_request_from_claro_costa_rica, parent: :mobile_request do
91
+ initialize_with do
92
+ new build(:common_mobile_request_env).merge(
93
+ "REMOTE_ADDR" => "186.26.126.37",
94
+ "HTTP_X_NOKIA_MSISDN" => "50600000000"
95
+ )
96
+ end
97
+ end
98
+
99
+ # Real request taken on 2015-04-09 16:07:05
100
+ factory :mobile_request_from_claro_puerto_rico, parent: :mobile_request do
101
+ initialize_with do
102
+ new build(:common_mobile_request_env).merge(
103
+ "REMOTE_ADDR" => "63.235.37.23",
104
+ "HTTP_ACCEPT" => "application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5",
105
+ "HTTP_ACCEPT_CHARSET" =>"utf-8, iso-8859-1, utf-16, *;q=0.7",
106
+ "HTTP_ACCEPT_ENCODING" =>"gzip",
107
+ "HTTP_ACCEPT_LANGUAGE" =>"en-US",
108
+ "HTTP_AKAMAI_ORIGIN_HOP" =>"1",
109
+ "HTTP_CACHE_CONTROL" =>"no-cache, max-age=0",
110
+ "HTTP_CONNECT_TIME" =>"0",
111
+ "HTTP_CONNECTION" =>"close",
112
+ "HTTP_HOST" =>"api.claroapps.com",
113
+ "HTTP_PRAGMA" =>"no-cache",
114
+ "HTTP_TOTAL_ROUTE_TIME" =>"0",
115
+ "HTTP_USER_AGENT" => "Mozilla/5.0 (Linux; U; Android 2.3.6; en-us; GT-I9070 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
116
+ "HTTP_VERSION" =>"HTTP/1.1",
117
+ "HTTP_VIA" =>"1.1 akamai.net(ghost) (AkamaiGHost), 1.1 vegur",
118
+
119
+ "HTTP_X_AKAMAI_CONFIG_LOG_DETAIL" =>"true",
120
+
121
+ "HTTP_X_CISCO_IMSI" =>"330110010202360",
122
+ "HTTP_X_CISCO_MSISDN" =>"17873131471",
123
+
124
+ "HTTP_X_FORWARDED_FOR" =>"63.135.255.59, 63.235.37.23",
125
+ "HTTP_X_FORWARDED_PORT" =>"80",
126
+ "HTTP_X_FORWARDED_PROTO" =>"http",
127
+
128
+ "HTTP_X_REQUEST_ID" =>"4b67a488-619e-4366-9437-f5e5e746f971",
129
+ "HTTP_X_REQUEST_START" =>"1428595625229",
130
+ "HTTP_X_WAP_PROFILE" =>"http://wap.samsungmobile.com/uaprof/GT-I9070.xml"
131
+ )
132
+ end
133
+ end
134
+
135
+ # http://myip.ms/view/ip_owners/80612/Conecel.html
136
+ factory :mobile_request_from_claro_ecuador, parent: :mobile_request do
137
+ initialize_with do
138
+ new build(:common_mobile_request_env).merge(
139
+ "REMOTE_ADDR" => "190.63.1.10",
140
+ "HTTP_MSISDN" => "59342690000"
141
+ )
142
+ end
143
+ end
144
+
145
+ # Request from a client through Claro Guatemala network:
146
+ # (Built from an actual ATP test)
147
+ factory :mobile_request_from_claro_guatemala, parent: :mobile_request do
148
+ initialize_with do
149
+ new build(:common_mobile_request_env).merge(
150
+ "REMOTE_ADDR" => "216.230.152.158",
151
+ "HTTP_X_NOKIA_MSISDN" => "50241865146",
152
+ "HTTP_X_NOKIA_IMSI" => "704012013128442",
153
+ "HTTP_X_FORWARDED_FOR" => "190.212.233.218, 204.0.3.199"
154
+ )
155
+ end
156
+ end
157
+
158
+ # TODO: Replace with a real example:
159
+ factory :mobile_request_from_claro_honduras, parent: :mobile_request do
160
+ initialize_with do
161
+ new build(:common_mobile_request_env).merge(
162
+ "REMOTE_ADDR" => "190.107.157.31",
163
+ "HTTP_X_NOKIA_MSISDN" => "50430000000"
164
+ )
165
+ end
166
+ end
167
+
168
+ # TODO: Replace with a real example request:
169
+ factory :mobile_request_from_claro_nicaragua, parent: :mobile_request do
170
+ initialize_with do
171
+ new build(:common_mobile_request_env).merge(
172
+ "REMOTE_ADDR" => "190.212.88.8",
173
+ "HTTP_X_NOKIA_MSISDN" => "50500000000"
174
+ )
175
+ end
176
+ end
177
+
178
+ # TODO: Replace with a real example request:
179
+ factory :mobile_request_from_claro_el_salvador, parent: :mobile_request do
180
+ initialize_with do
181
+ new build(:common_mobile_request_env).merge(
182
+ "REMOTE_ADDR" => "190.86.139.225",
183
+ "HTTP_X_NOKIA_MSISDN" => "50300000000"
184
+ )
185
+ end
186
+ end
187
+
188
+ # Real request recorded at claroapps.com at 2015-03-24
189
+ factory :mobile_request_from_claro_peru, parent: :mobile_request do
190
+ initialize_with do
191
+ new build(:common_mobile_request_env).merge(
192
+ "REMOTE_ADDR" => "216.246.75.208", # This IP belongs to a U.S. datacenter which acts as proxy for the real user...
193
+
194
+ "HTTP_ACCEPT_LANGUAGE" => "es-PE,es-419;q=0.8,es;q=0.6",
195
+ "HTTP_AKAMAI_ORIGIN_HOP" => "1",
196
+ "HTTP_CONNECT_TIME" => "3",
197
+ "HTTP_PRAGMA" => "no-cache",
198
+ "HTTP_TOTAL_ROUTE_TIME" => "5",
199
+ "HTTP_VERSION" => "HTTP/1.1",
200
+ "HTTP_VIA" => "1.1 akamai.net(ghost) (AkamaiGHost), 1.1 vegur",
201
+
202
+ # X Headers:
203
+ "HTTP_X_AKAMAI_CONFIG_LOG_DETAIL" => "true",
204
+
205
+ # The leftmost IP is the:
206
+ # - Closer to the User (or the actual user IP)
207
+ # - Less trustable
208
+ "HTTP_X_FORWARDED_FOR" => "190.113.210.147, 216.246.75.208",
209
+ "HTTP_X_NOKIA_IMSI" => "716100316259449",
210
+ "HTTP_X_REQUEST" => "272aa345-55cc-45b2-b879-79678957817f",
211
+
212
+ "HTTP_X_REQUEST_START" => "1427225820026",
213
+ "HTTP_X_FORWARDED_PORT" => "80",
214
+ "HTTP_X_FORWARDED_PROTO" => "http",
215
+ "HTTP_X_UP_CALLING_LINE_ID" => "51941037249"
216
+ )
217
+ end
218
+ end
219
+
220
+ # Real request sample captured at claroapps.com on 2015-03-13
221
+ factory :mobile_request_from_claro_panama, parent: :mobile_request do
222
+ initialize_with do
223
+ new build(:common_mobile_request_env).merge(
224
+ "REMOTE_ADDR" => "216.246.75.196",
225
+
226
+ # Client generated headers:
227
+ "HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
228
+ "HTTP_ACCEPT_ENCODING" => "gzip",
229
+ "HTTP_ACCEPT_LANGUAGE" => "es-es",
230
+ "HTTP_CONNECTION" => "close",
231
+ "HTTP_HOST" => "api.claroapps.com",
232
+ "HTTP_PRAGMA" => "no-cache",
233
+ "HTTP_USER_AGENT" => "Mozilla/5.0 (iPhone; CPU iPhone OS 8_1_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B466 Safari/600.1.4",
234
+ "HTTP_VERSION" => "HTTP/1.1",
235
+
236
+ # Mobile Network generated headers:
237
+ "HTTP_X_APN" => "web.claro.com.pa",
238
+ "HTTP_X_IMSI" => "714030003647380",
239
+ "HTTP_X_UP_SUBNO" => "50762526353",
240
+
241
+ # Akamai generated/modified headers:
242
+ "HTTP_AKAMAI_ORIGIN_HOP" => "1",
243
+ "HTTP_CONNECT_TIME" => "1",
244
+ "HTTP_CACHE_CONTROL" => "no-cache, max-age=0",
245
+ "HTTP_X_AKAMAI_CONFIG_LOG_DETAIL" => "true",
246
+ "HTTP_TOTAL_ROUTE_TIME" => "0",
247
+ "HTTP_VIA" => "1.1 akamai.net(ghost) (AkamaiGHost), 1.1 vegur",
248
+ "HTTP_X_FORWARDED_FOR" => "181.179.0.28, 216.246.75.196",
249
+ "HTTP_X_FORWARDED_PORT" => "80",
250
+ "HTTP_X_FORWARDED_PROTO" => "http",
251
+ "HTTP_X_REQUEST" => "d141e3e0-0282-4f44-9e45-470a834976a1",
252
+ "HTTP_X_REQUEST_START" => "1426248962827"
253
+ )
254
+ end
255
+ end
256
+
257
+ end