apns-lookout 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MWViOGY3NTUzZDRkNDJhZTllNTYyOGY5Nzc3YmY1MjQ0MjkxOWExNw==
5
+ data.tar.gz: !binary |-
6
+ M2JjZmM5NTVlMDYyYWI5MjllMGViZGI1ZTQwYzFhODEyNTJmMjE1Mw==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ MjhiNTEyOThhZGZhZjUxNTc0ZGU1Yzc4MjZiMTkwMTQxMWMzNDMzMWQ2NGUz
10
+ MmQ2YWM3ZjM1ODFmMWQ4NDZjN2VjYzRiMWQxZTZhMjlhNmY2ZWViMDMyMDQz
11
+ NmRiMTYyZTYyN2M0ZGMwMTY0ZWYzMjRmYzc4MzMwYTViYzEyOGE=
12
+ data.tar.gz: !binary |-
13
+ YjgxMzA4MTVmYTc0MDlmNDA1NzlmNGVmZmZhNmJiOWJlNzEyMGZhYzljOTc0
14
+ MWQxNjNmZDJlOTY3YzZiZDk3M2RmZDI1YTQyNmIyZmYzYmI3N2M5NGNmNDVl
15
+ YTgzMWFlOWFmYjI4MDk0YzVlZmNjM2MwNmZkY2Q4NzYyZTE0NTE=
@@ -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,135 @@
1
+ h1. APNS
2
+
3
+ a gem for the Apple Push Notification Service.
4
+
5
+ h2. Install
6
+
7
+ sudo gem install apns
8
+
9
+ h2. Setup:
10
+
11
+ Convert your certificate
12
+
13
+ In Keychain access export your certificate as a p12. Then run the following command to convert it to a .pem
14
+
15
+ <pre>
16
+ <code>
17
+ openssl pkcs12 -in cert.p12 -out cert.pem -nodes -clcerts
18
+ </code>
19
+ </pre>
20
+
21
+ After you have your .pem file. Set what host, port, certificate file location on the APNS class:
22
+
23
+ <pre>
24
+ <code>
25
+ APNS.host = 'gateway.push.apple.com'
26
+ # gateway.sandbox.push.apple.com is default
27
+
28
+ APNS.pem = '/path/to/pem/file'
29
+ # this is the file you just created
30
+
31
+ APNS.port = 2195
32
+ # this is also the default. Shouldn't ever have to set this, but just in case Apple goes crazy, you can.
33
+ </code>
34
+ </pre>
35
+
36
+ h2. Example (Single notification):
37
+
38
+ 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.
39
+
40
+ <pre>
41
+ <code>
42
+ device_token = '123abc456def'
43
+
44
+ APNS.send_notification(device_token, 'Hello iPhone!' )
45
+
46
+ APNS.send_notification(device_token, :alert => 'Hello iPhone!', :badge => 1, :sound => 'default')
47
+ </code>
48
+ </pre>
49
+
50
+ h2. Example (Multiple notifications):
51
+
52
+ You can also send multiple notifications using the same connection to Apple:
53
+
54
+ <pre>
55
+ <code>
56
+ device_token = '123abc456def'
57
+
58
+ n1 = APNS::Notification.new(device_token, 'Hello iPhone!' )
59
+
60
+ n2 = APNS::Notification.new(device_token, :alert => 'Hello iPhone!', :badge => 1, :sound => 'default')
61
+
62
+ APNS.send_notifications([n1, n2])
63
+ </code>
64
+ </pre>
65
+
66
+
67
+ h2. Send other info along with aps
68
+
69
+ You can send other application specific information as well.
70
+
71
+ <pre>
72
+ <code>
73
+ APNS.send_notification(device_token, :alert => 'Hello iPhone!', :badge => 1, :sound => 'default',
74
+ :other => {:sent => 'with apns gem'})
75
+ </code>
76
+ </pre>
77
+
78
+ This will add the other hash to the same level as the aps hash:
79
+
80
+ <pre>
81
+ <code>
82
+ {"aps":{"alert":"Hello iPhone!","badge":1,"sound":"default"},"sent":"with apns gem"}
83
+ </code>
84
+ </pre>
85
+
86
+
87
+ h2. Getting your iPhone's device token
88
+
89
+ After you setup push notification for your application with Apple. You need to ask Apple for you application specific device token.
90
+
91
+ h3. ApplicationAppDelegate.m
92
+
93
+ <pre>
94
+ <code>
95
+ - (void)applicationDidFinishLaunching:(UIApplication *)application
96
+ {
97
+ // Register with apple that this app will use push notification
98
+ [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert |
99
+ UIRemoteNotificationTypeSound | UIRemoteNotificationTypeBadge)];
100
+
101
+ // Your app startup logic...
102
+ return YES;
103
+ }
104
+
105
+ - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
106
+ {
107
+ // Convert the binary data token into an NSString (see below for the implementation of this function)
108
+ NSString *deviceTokenAsString = stringFromDeviceTokenData(deviceToken);
109
+
110
+ // Show the device token obtained from apple to the log
111
+ NSLog(@"deviceToken: %@", deviceTokenAsString);
112
+ }
113
+ </code>
114
+ </pre>
115
+
116
+ h3. stringFromDeviceTokenData function
117
+
118
+ This snippet comes from "this stackoverflow post's anwser":http://stackoverflow.com/a/1990880/855846.
119
+ <pre>
120
+ <code>
121
+ NSString* stringFromDeviceTokenData(NSData *deviceToken)
122
+ {
123
+ const char *data = [deviceToken bytes];
124
+ NSMutableString* token = [NSMutableString string];
125
+
126
+ for (int i = 0; i < [deviceToken length]; i++) {
127
+ [token appendFormat:@"%02.2hhX", data[i]];
128
+ }
129
+
130
+ return [[token copy] autorelease];
131
+ }
132
+ </code>
133
+ </pre>
134
+
135
+ For more information on Apple Push Notifications you can see Apple Developer Documentation "here":http://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/IPhoneOSClientImp/IPhoneOSClientImp.html#//apple_ref/doc/uid/TP40008194-CH103-SW2.
@@ -0,0 +1,53 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+ require 'rubygems/specification'
4
+ require 'date'
5
+ require 'spec/rake/spectask'
6
+
7
+ GEM = 'apns'
8
+ GEM_NAME = 'apns'
9
+ GEM_VERSION = '0.9.0'
10
+ AUTHORS = ['James Pozdena']
11
+ EMAIL = "jpoz@jpoz.net"
12
+ HOMEPAGE = "http://github.com/jpoz/apns"
13
+ SUMMARY = "Simple Apple push notification service gem"
14
+
15
+ spec = Gem::Specification.new do |s|
16
+ s.name = GEM
17
+ s.version = GEM_VERSION
18
+ s.platform = Gem::Platform::RUBY
19
+ s.has_rdoc = true
20
+ s.extra_rdoc_files = ["MIT-LICENSE"]
21
+ s.summary = SUMMARY
22
+ s.description = s.summary
23
+ s.authors = AUTHORS
24
+ s.email = EMAIL
25
+ s.homepage = HOMEPAGE
26
+ s.require_path = 'lib'
27
+ s.autorequire = GEM
28
+ s.files = %w(MIT-LICENSE README.textile Rakefile) + Dir.glob("{lib}/**/*")
29
+ end
30
+
31
+ task :default => :spec
32
+
33
+ desc "Run specs"
34
+ Spec::Rake::SpecTask.new do |t|
35
+ t.spec_files = FileList['spec/**/*_spec.rb']
36
+ t.spec_opts = %w(-fs --color)
37
+ end
38
+
39
+ Rake::GemPackageTask.new(spec) do |pkg|
40
+ pkg.gem_spec = spec
41
+ end
42
+
43
+ desc "install the gem locally"
44
+ task :install => [:package] do
45
+ sh %{sudo gem install pkg/#{GEM}-#{GEM_VERSION}}
46
+ end
47
+
48
+ desc "create a gemspec file"
49
+ task :make_spec do
50
+ File.open("#{GEM}.gemspec", "w") do |file|
51
+ file.puts spec.to_ruby
52
+ end
53
+ end
@@ -0,0 +1,2 @@
1
+ require 'apns/core'
2
+ require 'apns/notification'
@@ -0,0 +1,98 @@
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
+ sock, ssl = self.open_connection
23
+
24
+ packed_nofications = self.packed_nofications(notifications)
25
+
26
+ notifications.each do |n|
27
+ ssl.write(packed_nofications)
28
+ end
29
+
30
+ ssl.close
31
+ sock.close
32
+ end
33
+
34
+ def self.packed_nofications(notifications)
35
+ bytes = ''
36
+
37
+ notifications.each do |notification|
38
+ # Each notification frame consists of
39
+ # 1. (e.g. protocol version) 2 (unsigned char [1 byte])
40
+ # 2. size of the full frame (unsigend int [4 byte], big endian)
41
+ pn = notification.packaged_notification
42
+ bytes << ([2, pn.bytesize].pack('CN') + pn)
43
+ end
44
+
45
+ bytes
46
+ end
47
+
48
+ def self.feedback
49
+ sock, ssl = self.feedback_connection
50
+
51
+ apns_feedback = []
52
+
53
+ while message = ssl.read(38)
54
+ timestamp, token_size, token = message.unpack('N1n1H*')
55
+ apns_feedback << [Time.at(timestamp), token]
56
+ end
57
+
58
+ ssl.close
59
+ sock.close
60
+
61
+ return apns_feedback
62
+ end
63
+
64
+ protected
65
+
66
+ def self.open_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
+ sock = TCPSocket.new(self.host, self.port)
75
+ ssl = OpenSSL::SSL::SSLSocket.new(sock,context)
76
+ ssl.connect
77
+
78
+ return sock, ssl
79
+ end
80
+
81
+ def self.feedback_connection
82
+ raise "The path to your pem file is not set. (APNS.pem = /path/to/cert.pem)" unless self.pem
83
+ raise "The path to your pem file does not exist!" unless File.exist?(self.pem)
84
+
85
+ context = OpenSSL::SSL::SSLContext.new
86
+ context.cert = OpenSSL::X509::Certificate.new(File.read(self.pem))
87
+ context.key = OpenSSL::PKey::RSA.new(File.read(self.pem), self.pass)
88
+
89
+ fhost = self.host.gsub('gateway','feedback')
90
+ puts fhost
91
+
92
+ sock = TCPSocket.new(fhost, 2196)
93
+ ssl = OpenSSL::SSL::SSLSocket.new(sock,context)
94
+ ssl.connect
95
+
96
+ return sock, ssl
97
+ end
98
+ end
@@ -0,0 +1,69 @@
1
+ module APNS
2
+ require 'openssl'
3
+
4
+ class Notification
5
+ attr_accessor :device_token, :alert, :badge, :sound, :other, :priority
6
+ attr_accessor :message_identifier, :expiration_date
7
+ attr_accessor :content_available
8
+
9
+ def initialize(device_token, message)
10
+ self.device_token = device_token
11
+ if message.is_a?(Hash)
12
+ self.alert = message[:alert]
13
+ self.badge = message[:badge]
14
+ self.sound = message[:sound]
15
+ self.other = message[:other]
16
+ self.message_identifier = message[:message_identifier]
17
+ self.content_available = !message[:content_available].nil?
18
+ self.expiration_date = message[:expiration_date]
19
+ self.priority = if self.content_available
20
+ message[:priority] || 5
21
+ else
22
+ message[:priority] || 10
23
+ end
24
+ elsif message.is_a?(String)
25
+ self.alert = message
26
+ else
27
+ raise "Notification needs to have either a hash or string"
28
+ end
29
+
30
+ self.message_identifier ||= OpenSSL::Random.random_bytes(4)
31
+ end
32
+
33
+ def packaged_notification
34
+ pt = self.packaged_token
35
+ pm = self.packaged_message
36
+ pi = self.message_identifier
37
+ pe = (self.expiration_date || 0).to_i
38
+ pr = (self.priority || 10).to_i
39
+
40
+ # Each item consist of
41
+ # 1. unsigned char [1 byte] is the item (type) number according to Apple's docs
42
+ # 2. short [big endian, 2 byte] is the size of this item
43
+ # 3. item data, depending on the type fixed or variable length
44
+ data = ''
45
+ data << [1, pt.bytesize, pt].pack("CnA*")
46
+ data << [2, pm.bytesize, pm].pack("CnA*")
47
+ data << [3, pi.bytesize, pi].pack("CnA*")
48
+ data << [4, 4, pe].pack("CnN")
49
+ data << [5, 1, pr].pack("CnC")
50
+
51
+ data
52
+ end
53
+
54
+ def packaged_token
55
+ [device_token.gsub(/[\s|<|>]/,'')].pack('H*')
56
+ end
57
+
58
+ def packaged_message
59
+ aps = {'aps'=> {} }
60
+ aps['aps']['alert'] = self.alert if self.alert
61
+ aps['aps']['badge'] = self.badge if self.badge
62
+ aps['aps']['sound'] = self.sound if self.sound
63
+ aps['aps']['content-available'] = 1 if self.content_available
64
+
65
+ aps.merge!(self.other) if self.other
66
+ aps.to_json
67
+ end
68
+ end
69
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: apns-lookout
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ platform: ruby
6
+ authors:
7
+ - James Pozdena
8
+ - Thomas Kollbach
9
+ - Susheel Daswani
10
+ autorequire: apns
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2013-06-25 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ! '>='
27
+ - !ruby/object:Gem::Version
28
+ version: '0'
29
+ description: ! 'Simple Apple push notification service gem.
30
+
31
+ It supports the 3rd wire format (command 2) with support for content-availible (Newsstand),
32
+ expiration dates and delivery priority (background pushes)}
33
+
34
+ '
35
+ email:
36
+ - jpoz@jpoz.net
37
+ - thomas@kollba.ch
38
+ executables: []
39
+ extensions: []
40
+ extra_rdoc_files:
41
+ - MIT-LICENSE
42
+ files:
43
+ - MIT-LICENSE
44
+ - README.textile
45
+ - Rakefile
46
+ - lib/apns.rb
47
+ - lib/apns/core.rb
48
+ - lib/apns/notification.rb
49
+ homepage: http://github.com/jpoz/apns
50
+ licenses: []
51
+ metadata: {}
52
+ post_install_message:
53
+ rdoc_options: []
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ! '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ requirements: []
67
+ rubyforge_project:
68
+ rubygems_version: 2.2.1
69
+ signing_key:
70
+ specification_version: 4
71
+ summary: Simple Apple push notification service gem for Lookout use
72
+ test_files: []