mobile-subscriber 1.0.0.alpha4 → 1.0.0.alpha5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|