imobile 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +2 -0
- data/imobile.gemspec +1 -1
- data/lib/imobile/push_notification.rb +58 -6
- data/test/crypto_app_fprint_test.rb +2 -0
- data/test/push_notification_test.rb +9 -0
- data/test/validate_receipt_test.rb +2 -0
- metadata +1 -1
data/CHANGELOG
CHANGED
data/imobile.gemspec
CHANGED
@@ -96,21 +96,73 @@ module PushNotifications
|
|
96
96
|
end
|
97
97
|
|
98
98
|
# Decodes an APNs certificate.
|
99
|
-
def self.decode_push_certificate(certificate_blob)
|
99
|
+
def self.decode_push_certificate(certificate_blob)
|
100
|
+
if use_new_certificate_decoder?
|
101
|
+
# Ruby 1.8.7 and above.
|
102
|
+
data = decode_push_certificate_new certificate_blob
|
103
|
+
else
|
104
|
+
# Ruby 1.8.6.
|
105
|
+
data = decode_push_certificate_heroku certificate_blob
|
106
|
+
end
|
107
|
+
data[:server_type] = server_type data[:certificate]
|
108
|
+
data
|
109
|
+
end
|
110
|
+
|
111
|
+
# Checks whether the new certificate decoding code is supported.
|
112
|
+
def self.use_new_certificate_decoder?
|
113
|
+
OpenSSL::PKCS12.respond_to? :new
|
114
|
+
end
|
115
|
+
|
116
|
+
# Decodes an APNs certificate, using the new (1.8.7+) OpenSSL methods.
|
117
|
+
def self.decode_push_certificate_new(certificate_blob)
|
100
118
|
pkcs12 = OpenSSL::PKCS12.new certificate_blob
|
101
119
|
|
102
120
|
certificate = pkcs12.certificate
|
103
121
|
key = pkcs12.key
|
122
|
+
|
123
|
+
{ :certificate => certificate, :key => key }
|
124
|
+
end
|
125
|
+
|
126
|
+
# Decodes an APNs certificate, using the openssl command-line tool.
|
127
|
+
#
|
128
|
+
# This works on Heroku, which uses Ruby 1.8.6.
|
129
|
+
def self.decode_push_certificate_heroku(certificate_blob)
|
130
|
+
# Most of the filesystem on Heroku is read-only. On the other hand, not
|
131
|
+
# everyone runs on Heroku. Find a reasonable temporary dir.
|
132
|
+
if defined? RAILS_ROOT
|
133
|
+
temp_dir = File.join RAILS_ROOT, 'tmp'
|
134
|
+
elsif File.exists? '/tmp'
|
135
|
+
temp_dir = '/tmp'
|
136
|
+
else
|
137
|
+
temp_dir = '.'
|
138
|
+
end
|
139
|
+
|
140
|
+
pkcs12_file_name = File.join temp_dir, "apns_#{Process.pid}.p12"
|
141
|
+
pem_file_name = File.join temp_dir, "apns_#{Process.pid}.pem"
|
142
|
+
out_file_name = File.join temp_dir, "apns_#{Process.pid}.err"
|
143
|
+
|
144
|
+
# Use the command-line openssl tool to break up the pkcs12 file.
|
145
|
+
File.open(pkcs12_file_name, 'wb') { |f| f.write certificate_blob }
|
146
|
+
Kernel.system "openssl pkcs12 -in #{pkcs12_file_name} -clcerts -nodes " +
|
147
|
+
"-out #{pem_file_name} -password pass: 2> #{out_file_name}"
|
148
|
+
pem_blob = File.read pem_file_name
|
149
|
+
[pkcs12_file_name, pem_file_name, out_file_name].each { |f| File.delete f }
|
150
|
+
|
151
|
+
certificate = OpenSSL::X509::Certificate.new pem_blob
|
152
|
+
key = OpenSSL::PKey::RSA.new pem_blob
|
153
|
+
{ :certificate => certificate, :key => key }
|
154
|
+
end
|
155
|
+
|
156
|
+
# The Apple Push Notification server type that a certificate works with.
|
157
|
+
def self.server_type(certificate)
|
104
158
|
case certificate.subject.to_s
|
105
159
|
when /Apple Development Push/
|
106
|
-
|
160
|
+
return :sandbox
|
107
161
|
when /Apple Production Push/
|
108
|
-
|
162
|
+
return :production
|
109
163
|
else
|
110
164
|
raise "Invalid push certificate - #{certificate.inspect}"
|
111
|
-
end
|
112
|
-
|
113
|
-
{ :certificate => certificate, :key => key, :server_type => server_type }
|
165
|
+
end
|
114
166
|
end
|
115
167
|
|
116
168
|
# Encodes a push notification in a binary string for APNs consumption.
|
@@ -13,6 +13,8 @@ require 'flexmock/test_unit'
|
|
13
13
|
|
14
14
|
class CryptoAppFprintTest < Test::Unit::TestCase
|
15
15
|
def setup
|
16
|
+
super
|
17
|
+
|
16
18
|
testdata_path = File.join(File.dirname(__FILE__), '..', 'testdata')
|
17
19
|
@device_attrs = File.open(File.join(testdata_path,
|
18
20
|
'device_attributes.yml')) do |f|
|
@@ -13,6 +13,8 @@ require 'flexmock/test_unit'
|
|
13
13
|
|
14
14
|
class PushNotificationTest < Test::Unit::TestCase
|
15
15
|
def setup
|
16
|
+
super
|
17
|
+
|
16
18
|
testdata_path = File.join(File.dirname(__FILE__), '..', 'testdata')
|
17
19
|
@dev_cert_path = File.join(testdata_path, 'apns_developer.p12')
|
18
20
|
@prod_cert_path = File.join(testdata_path, 'apns_production.p12')
|
@@ -46,6 +48,13 @@ class PushNotificationTest < Test::Unit::TestCase
|
|
46
48
|
"Wrong data in prod certificate #{cert_data[:certificate].inspect}")
|
47
49
|
end
|
48
50
|
|
51
|
+
def test_read_push_certificate_on_heroku
|
52
|
+
flexmock(Imobile::PushNotifications).
|
53
|
+
should_receive(:use_new_certificate_decoder?).and_return(false)
|
54
|
+
|
55
|
+
test_read_push_certificate
|
56
|
+
end
|
57
|
+
|
49
58
|
def test_pack_push_token
|
50
59
|
assert_equal @dev_token, Imobile.pack_hex_push_token(@hex_dev_token)
|
51
60
|
end
|
@@ -10,6 +10,8 @@ require 'test/unit'
|
|
10
10
|
|
11
11
|
class ValidateReceiptTest < Test::Unit::TestCase
|
12
12
|
def setup
|
13
|
+
super
|
14
|
+
|
13
15
|
testdata_path = File.join(File.dirname(__FILE__), '..', 'testdata')
|
14
16
|
@forged_sandbox_blob = File.read File.join(testdata_path,
|
15
17
|
'forged_sandbox_receipt')
|