costan-imobile 0.0.5 → 0.0.6

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.
data/CHANGELOG CHANGED
@@ -1,3 +1,5 @@
1
+ v0.0.6. New push certificates read method for Ruby 1.8.6 on Heroku.
2
+
1
3
  v0.0.5. Renamed device_token to push_token throughout the API.
2
4
 
3
5
  v0.0.4. Updated CryptoSupport with the push token device attribute.
data/imobile.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{imobile}
5
- s.version = "0.0.5"
5
+ s.version = "0.0.6"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Victor Costan"]
@@ -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
- server_type = :sandbox
160
+ return :sandbox
107
161
  when /Apple Production Push/
108
- server_type = :production
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')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: costan-imobile
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Victor Costan