apns-p 1.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ .DS_Store
2
+ pkg
3
+ temp
4
+ Gemfile.lock
5
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in apns.gemspec
4
+ gemspec
5
+
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2009 James Pozdena
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,132 @@
1
+ h1. APNS-P
2
+
3
+ A gem for the Apple Push Notification Service. Now with Passbook notification support.
4
+
5
+ h2. Install
6
+
7
+ h3. Terminal
8
+
9
+ sudo gem install apns
10
+
11
+ h3. Bundler
12
+
13
+ gem "apns-p"
14
+
15
+ h2. Use
16
+
17
+ require "apns"
18
+
19
+ h2. Setup:
20
+
21
+ Convert your certificate
22
+
23
+ In Keychain access export your certificate as a p12. Then run the following command to convert it to a .pem
24
+
25
+ <pre>
26
+ <code>
27
+ openssl pkcs12 -in cert.p12 -out cert.pem -nodes -clcerts
28
+ </code>
29
+ </pre>
30
+
31
+ After you have your .pem file. Set what host, port, certificate file location on the APNS class:
32
+
33
+ <pre>
34
+ <code>
35
+ APNS.host = 'gateway.push.apple.com'
36
+ # gateway.sandbox.push.apple.com is default
37
+
38
+ APNS.pem = '/path/to/pem/file'
39
+ # this is the file you just created
40
+
41
+ APNS.port = 2195
42
+ # this is also the default. Shouldn't ever have to set this, but just in case Apple goes crazy, you can.
43
+ </code>
44
+ </pre>
45
+
46
+ h2. Example (Single notification):
47
+
48
+ Then to send a push notification you can either just send a string as the alert or give it a hash for the alert, badge and sound.
49
+
50
+ <pre>
51
+ <code>
52
+ device_token = '123abc456def'
53
+
54
+ APNS.send_notification(device_token, 'Hello iPhone!' )
55
+
56
+ APNS.send_notification(device_token, :alert => 'Hello iPhone!', :badge => 1, :sound => 'default')
57
+ </code>
58
+ </pre>
59
+
60
+ h2. Example (Multiple notifications):
61
+
62
+ You can also send multiple notifications using the same connection to Apple:
63
+
64
+ <pre>
65
+ <code>
66
+ device_token = '123abc456def'
67
+
68
+ n1 = APNS::Notification.new(device_token, 'Hello iPhone!' )
69
+
70
+ n2 = APNS::Notification.new(device_token, :alert => 'Hello iPhone!', :badge => 1, :sound => 'default')
71
+
72
+ APNS.send_notifications([n1, n2])
73
+ </code>
74
+ </pre>
75
+
76
+ h2. Example (Passbook notifications):
77
+
78
+ These notifications are signed with the Passbook cert, thus passing along the PassTypeId
79
+
80
+ <pre>
81
+ <code>
82
+ device_token = '123abc456def'
83
+
84
+ device_token2 = 'abc123def456'
85
+
86
+ n1 = APNS::Notification.new(device_token)
87
+
88
+ n2 = APNS::Notification.new(device_token2)
89
+
90
+ APNS.send_notifications([n1, n2])
91
+ </code>
92
+ </pre>
93
+
94
+ h2. Send other info along with aps
95
+
96
+ You can send other application specific information as well.
97
+
98
+ <pre>
99
+ <code>
100
+ APNS.send_notification(device_token, :alert => 'Hello iPhone!', :badge => 1, :sound => 'default',
101
+ :other => {:sent => 'with apns gem'})
102
+ </code>
103
+ </pre>
104
+
105
+ This will add the other hash to the same level as the aps hash:
106
+
107
+ <pre>
108
+ <code>
109
+ {"aps":{"alert":"Hello iPhone!","badge":1,"sound":"default"},"sent":"with apns gem"}
110
+ </code>
111
+ </pre>
112
+
113
+
114
+ h2. Getting your iPhone's device token
115
+
116
+ After you setup push notification for your application with Apple. You need to ask Apple for you application specific device token.
117
+
118
+ ApplicationAppDelegate.m
119
+ <pre>
120
+ <code>
121
+ - (void)applicationDidFinishLaunching:(UIApplication *)application {
122
+ // Register with apple that this app will use push notification
123
+ [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert |
124
+ UIRemoteNotificationTypeSound | UIRemoteNotificationTypeBadge)];
125
+ }
126
+
127
+ - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
128
+ // Show the device token obtained from apple to the log
129
+ NSLog(@"deviceToken: %@", deviceToken);
130
+ }
131
+ </code>
132
+ </pre>
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new
5
+
6
+ task :default => :spec
7
+ task :test => :spec
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'apns/version'
5
+
6
+ SUMMARY = "Simple Apple push notification service gem with Passbook support"
7
+ DESCRIPTION =<<DESC
8
+ A simple Apple push notification service gem with Passbook support. Send
9
+ an empty payload on an Apple Push Notification using the Passbook cert
10
+ to trigger a pull from the Passbook.
11
+ DESC
12
+
13
+ Gem::Specification.new do |gem|
14
+ gem.name = "apns-p"
15
+ gem.version = APNS::VERSION
16
+ gem.authors = ["Keith Swallow"]
17
+ gem.email = ["keithcelt@gmail.com"]
18
+ gem.date = "2012-12-03"
19
+ gem.platform = Gem::Platform::RUBY
20
+ gem.summary = SUMMARY
21
+ gem.description = DESCRIPTION
22
+ gem.homepage = "http://github.com/keithcelt/apns-p"
23
+
24
+ gem.files = `git ls-files`.split($/)
25
+ gem.test_files = gem.files.grep(%r{^spec/})
26
+ gem.extra_rdoc_files = ["MIT-LICENSE"]
27
+ gem.require_paths = ["lib"]
28
+
29
+ gem.add_runtime_dependency 'json'
30
+ gem.add_development_dependency 'rspec'
31
+ gem.add_development_dependency 'rake'
32
+ end
@@ -0,0 +1,3 @@
1
+ require "apns/core"
2
+ require "apns/notification"
3
+ require "apns/version"
@@ -0,0 +1,84 @@
1
+ module APNS
2
+ require 'socket'
3
+ require 'openssl'
4
+ require 'json'
5
+
6
+ @host = 'gateway.sandbox.push.apple.com'
7
+ @port = 2195
8
+ # openssl pkcs12 -in mycert.p12 -out client-cert.pem -nodes -clcerts
9
+ @pem = nil # this should be the path of the pem file not the contentes
10
+ @pass = nil
11
+
12
+ class << self
13
+ attr_accessor :host, :pem, :port, :pass
14
+ end
15
+
16
+ def self.send_notification(device_token, message)
17
+ n = APNS::Notification.new(device_token, message)
18
+ self.send_notifications([n])
19
+ end
20
+
21
+ def self.send_notifications(notifications)
22
+ return unless notifications
23
+ sock, ssl = self.open_connection
24
+
25
+ notifications.each do |n|
26
+ ssl.write(n.packed)
27
+ end
28
+
29
+ ssl.close
30
+ sock.close
31
+ end
32
+
33
+ def self.feedback
34
+ sock, ssl = self.feedback_connection
35
+
36
+ apns_feedback = []
37
+
38
+ while message = ssl.read(38)
39
+ timestamp, token_size, token = message.unpack('N1n1H*')
40
+ apns_feedback << [Time.at(timestamp), token]
41
+ end
42
+
43
+ ssl.close
44
+ sock.close
45
+
46
+ return apns_feedback
47
+ end
48
+
49
+ protected
50
+
51
+ def self.open_connection
52
+ raise "The path to your pem file is not set. (APNS.pem = /path/to/cert.pem)" unless self.pem
53
+ raise "The path to your pem file does not exist!" unless File.exist?(self.pem)
54
+
55
+ context = OpenSSL::SSL::SSLContext.new
56
+ context.cert = OpenSSL::X509::Certificate.new(File.read(self.pem))
57
+ context.key = OpenSSL::PKey::RSA.new(File.read(self.pem), self.pass)
58
+
59
+ sock = TCPSocket.new(self.host, self.port)
60
+ ssl = OpenSSL::SSL::SSLSocket.new(sock,context)
61
+ ssl.connect
62
+
63
+ return sock, ssl
64
+ end
65
+
66
+ def self.feedback_connection
67
+ raise "The path to your pem file is not set. (APNS.pem = /path/to/cert.pem)" unless self.pem
68
+ raise "The path to your pem file does not exist!" unless File.exist?(self.pem)
69
+
70
+ context = OpenSSL::SSL::SSLContext.new
71
+ context.cert = OpenSSL::X509::Certificate.new(File.read(self.pem))
72
+ context.key = OpenSSL::PKey::RSA.new(File.read(self.pem), self.pass)
73
+
74
+ fhost = self.host.gsub('gateway','feedback')
75
+ puts fhost
76
+
77
+ sock = TCPSocket.new(fhost, 2196)
78
+ ssl = OpenSSL::SSL::SSLSocket.new(sock,context)
79
+ ssl.connect
80
+
81
+ return sock, ssl
82
+ end
83
+
84
+ end
@@ -0,0 +1,37 @@
1
+ module APNS
2
+ class Notification
3
+
4
+ attr_accessor :device_token, :alert, :badge, :sound, :other
5
+
6
+ def initialize(device_token, message=nil)
7
+ @device_token = device_token
8
+ if message.is_a?(Hash)
9
+ @alert = message[:alert]
10
+ @badge = message[:badge]
11
+ @sound = message[:sound]
12
+ @other = message[:other]
13
+ elsif message.is_a?(String)
14
+ @alert = message
15
+ end
16
+ end
17
+
18
+ def packed
19
+ [0, 0, 32, packed_token, 0, json_message.bytesize,
20
+ json_message].pack("ccca*cca*")
21
+ end
22
+
23
+ def packed_token
24
+ [device_token.gsub(/[\s|<|>]/,'')].pack('H*')
25
+ end
26
+
27
+ def json_message
28
+ return "{}" unless (alert || badge || sound)
29
+ aps = {'aps'=> {} }
30
+ aps['aps']['alert'] = alert if alert
31
+ aps['aps']['badge'] = badge if badge
32
+ aps['aps']['sound'] = sound if sound
33
+ aps.merge!(other) if other
34
+ aps.to_json
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,3 @@
1
+ module APNS
2
+ VERSION = "1.0.0.pre"
3
+ end
@@ -0,0 +1,49 @@
1
+ require"spec_helper"
2
+
3
+ describe APNS::Notification do
4
+
5
+ it "allows a nil message" do
6
+ lambda {
7
+ APNS::Notification.new("device_token")
8
+ }.should_not raise_error
9
+ end
10
+
11
+ it "takes a string as the message" do
12
+ n = APNS::Notification.new("device_token", "Hello")
13
+ n.alert.should == "Hello"
14
+ end
15
+
16
+ it "takes a hash as the message" do
17
+ n = APNS::Notification.new("device_token", {:alert => "Hello iPhone", :badge => 3})
18
+ n.alert.should == "Hello iPhone"
19
+ n.badge.should == 3
20
+ end
21
+
22
+ describe "#json_message" do
23
+
24
+ it "allows an empty payload" do
25
+ n = APNS::Notification.new("device_token")
26
+ n.json_message.should == "{}"
27
+ end
28
+
29
+ it "returns JSON with notification information" do
30
+ n = APNS::Notification.new("device_token", {:alert => "Hello iPhone", :badge => 3, :sound => "awesome.caf"})
31
+ n.json_message.should include "alert\":\"Hello iPhone"
32
+ n.json_message.should include "badge\":3"
33
+ n.json_message.should include "sound\":\"awesome.caf"
34
+ end
35
+
36
+ it "omits keys that are empty in the JSON" do
37
+ n = APNS::Notification.new("device_token", {:badge => 3})
38
+ n.json_message.should == "{\"aps\":{\"badge\":3}}"
39
+ end
40
+
41
+ end
42
+
43
+ describe "#package_token" do
44
+ it "packages the token" do
45
+ n = APNS::Notification.new("<5b51030d d5bad758 fbad5004 bad35c31 e4e0f550 f77f20d4 f737bf8d 3d5524c6>", "a")
46
+ Base64.encode64(n.packed_token).should == "W1EDDdW611j7rVAEutNcMeTg9VD3fyDU9ze/jT1VJMY=\n"
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,6 @@
1
+ require "rubygems"
2
+ gem "rspec"
3
+ require "rspec"
4
+ require File.join(File.dirname(__FILE__), "..", "lib", "apns")
5
+ require "base64"
6
+ require "apns"
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: apns-p
3
+ version: !ruby/object:Gem::Version
4
+ hash: 1692402070
5
+ prerelease: 6
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ - pre
11
+ version: 1.0.0.pre
12
+ platform: ruby
13
+ authors:
14
+ - Keith Swallow
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2012-12-03 00:00:00 Z
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: json
23
+ version_requirements: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ type: :runtime
33
+ requirement: *id001
34
+ prerelease: false
35
+ - !ruby/object:Gem::Dependency
36
+ name: rspec
37
+ version_requirements: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ hash: 3
43
+ segments:
44
+ - 0
45
+ version: "0"
46
+ type: :development
47
+ requirement: *id002
48
+ prerelease: false
49
+ - !ruby/object:Gem::Dependency
50
+ name: rake
51
+ version_requirements: &id003 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ hash: 3
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ type: :development
61
+ requirement: *id003
62
+ prerelease: false
63
+ description: |
64
+ A simple Apple push notification service gem with Passbook support. Send
65
+ an empty payload on an Apple Push Notification using the Passbook cert
66
+ to trigger a pull from the Passbook.
67
+
68
+ email:
69
+ - keithcelt@gmail.com
70
+ executables: []
71
+
72
+ extensions: []
73
+
74
+ extra_rdoc_files:
75
+ - MIT-LICENSE
76
+ files:
77
+ - .gitignore
78
+ - Gemfile
79
+ - MIT-LICENSE
80
+ - README.textile
81
+ - Rakefile
82
+ - apns.gemspec
83
+ - lib/apns.rb
84
+ - lib/apns/core.rb
85
+ - lib/apns/notification.rb
86
+ - lib/apns/version.rb
87
+ - spec/apns/notification_spec.rb
88
+ - spec/spec_helper.rb
89
+ homepage: http://github.com/keithcelt/apns-p
90
+ licenses: []
91
+
92
+ post_install_message:
93
+ rdoc_options: []
94
+
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ hash: 3
103
+ segments:
104
+ - 0
105
+ version: "0"
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ">"
110
+ - !ruby/object:Gem::Version
111
+ hash: 25
112
+ segments:
113
+ - 1
114
+ - 3
115
+ - 1
116
+ version: 1.3.1
117
+ requirements: []
118
+
119
+ rubyforge_project:
120
+ rubygems_version: 1.8.24
121
+ signing_key:
122
+ specification_version: 3
123
+ summary: Simple Apple push notification service gem with Passbook support
124
+ test_files:
125
+ - spec/apns/notification_spec.rb
126
+ - spec/spec_helper.rb