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.
- checksums.yaml +4 -4
- data/lib/mobile-subscriber.rb +13 -3
- data/lib/mobile_subscriber/dictionaries/dialing_and_country_codes.rb +468 -28
- data/lib/mobile_subscriber/http/known_imsi_headers.rb +22 -0
- data/lib/mobile_subscriber/http/known_msisdn_headers.rb +68 -0
- data/lib/mobile_subscriber/http/request_info.rb +166 -0
- data/lib/mobile_subscriber/identity.rb +97 -1
- data/lib/mobile_subscriber/version.rb +1 -1
- data/mobile_subscriber.thor +41 -0
- data/spec/factories/mobile_requests.rb +28 -0
- data/spec/factories/mobile_requests_from_claro.rb +257 -0
- data/spec/factories/mobile_requests_from_iusacell.rb +13 -0
- data/spec/factories/mobile_requests_from_movistar.rb +15 -0
- data/spec/factories/mobile_requests_from_telcel.rb +14 -0
- data/spec/factories/mobile_requests_from_vivo.rb +13 -0
- data/spec/features/claro_user_detection_spec.rb +170 -0
- data/spec/features/iusacell_user_detection_spec.rb +19 -0
- data/spec/features/movistar_user_detection_spec.rb +19 -0
- data/spec/features/telcel_user_detection_spec.rb +19 -0
- data/spec/models/{isdn_spec.rb → identity_spec.rb} +5 -5
- data/spec/shared_examples/identity_detection_in_argentina.rb +11 -0
- data/spec/shared_examples/identity_detection_in_brazil.rb +12 -0
- data/spec/shared_examples/identity_detection_in_chile.rb +12 -0
- data/spec/shared_examples/identity_detection_in_colombia.rb +12 -0
- data/spec/shared_examples/identity_detection_in_costa_rica.rb +15 -0
- data/spec/shared_examples/identity_detection_in_dominican_republic.rb +12 -0
- data/spec/shared_examples/identity_detection_in_ecuador.rb +12 -0
- data/spec/shared_examples/identity_detection_in_el_salvador.rb +15 -0
- data/spec/shared_examples/identity_detection_in_guatemala.rb +15 -0
- data/spec/shared_examples/identity_detection_in_honduras.rb +11 -0
- data/spec/shared_examples/identity_detection_in_mexico.rb +11 -0
- data/spec/shared_examples/identity_detection_in_nicaragua.rb +12 -0
- data/spec/shared_examples/identity_detection_in_panama.rb +12 -0
- data/spec/shared_examples/identity_detection_in_peru.rb +12 -0
- data/spec/shared_examples/identity_detection_in_puerto_rico.rb +14 -0
- data/spec/shared_examples/of_msisdn_detection_from_http_request.rb +3 -188
- data/templates/dialing_and_country_codes.rb.erb +20 -0
- metadata +58 -28
- data/lib/mobile_subscriber/detection/from_msisdn_http_request_header.rb +0 -48
- data/lib/mobile_subscriber/detection/from_x_nokia_msisdn_http_request_header.rb +0 -58
- data/lib/mobile_subscriber/detection/from_x_up_calling_line_id_http_request_header.rb +0 -65
- data/lib/mobile_subscriber/detection/from_x_up_ch_msisdn_http_request_header.rb +0 -35
- data/lib/mobile_subscriber/detection/from_x_up_subno_http_request_header.rb +0 -44
- data/lib/mobile_subscriber/detection/from_x_wap_msisdn_http_request_header.rb +0 -37
- data/lib/mobile_subscriber/detection/from_x_wap_sesiones3g_mdn_http_request_header.rb +0 -39
- data/lib/mobile_subscriber/detection/from_x_ztgo_beareraddress_http_request_header.rb +0 -36
- data/lib/mobile_subscriber/detection/http_request_info.rb +0 -77
- data/lib/mobile_subscriber/isdn.rb +0 -89
- data/spec/detection/from_msisdn_http_request_header_spec.rb +0 -53
- data/spec/detection/from_x_nokia_msisdn_http_request_header_spec.rb +0 -99
- data/spec/detection/from_x_up_calling_line_id_http_request_header_spec.rb +0 -39
- data/spec/detection/from_x_up_subno_http_request_header_spec.rb +0 -43
- data/spec/detection/from_x_wap_msisdn_http_request_header_spec.rb +0 -32
- data/spec/detection/from_x_wap_sesiones3g_mdn_http_request_header_spec.rb +0 -29
- 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
|
-
|
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
|
data/mobile_subscriber.thor
CHANGED
@@ -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
|