apple_push_notification 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ .DS_Store
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2009 Fabien Penso, Sam Soffes
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.
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the apple_push_notification plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.libs << 'test'
12
+ t.pattern = 'test/**/*_test.rb'
13
+ t.verbose = true
14
+ end
15
+
16
+ desc 'Generate documentation for the apple_push_notification plugin.'
17
+ Rake::RDocTask.new(:rdoc) do |rdoc|
18
+ rdoc.rdoc_dir = 'rdoc'
19
+ rdoc.title = 'ApplePushNotification'
20
+ rdoc.options << '--line-numbers' << '--inline-source'
21
+ rdoc.rdoc_files.include('README')
22
+ rdoc.rdoc_files.include('lib/**/*.rb')
23
+ end
24
+
25
+ begin
26
+ require 'jeweler'
27
+ Jeweler::Tasks.new do |gemspec|
28
+ gemspec.name = "apple_push_notification"
29
+ gemspec.summary = "Rails plugin for Apple Push Notifications"
30
+ gemspec.description = "Rails plugin for Apple Push Notifications"
31
+ gemspec.email = "sam@samsoff.es"
32
+ gemspec.homepage = "http://github.com/samsoffes/apple_push_notification"
33
+ gemspec.authors = ["Sam Soffes", "Fabien Penso"]
34
+ end
35
+ Jeweler::GemcutterTasks.new
36
+ rescue LoadError
37
+ puts "Jeweler not available. Install it with: sudo gem install jeweler -s http://gemcutter.org"
38
+ end
data/Readme.markdown ADDED
@@ -0,0 +1,62 @@
1
+ # Apple Push Notification
2
+
3
+ This plugin helps you use the Apple Push Notification system.
4
+
5
+ ## Converting Your Certificate
6
+
7
+ Once you have the certificate from Apple for your application, export your key
8
+ and the apple certificate as p12 files. Here's how:
9
+
10
+ 1. Click the disclosure arrow next to your certificate in Keychain Access and select the certificate and the key.
11
+ 2. Right click and choose `Export 2 items...`.
12
+ 3. Choose the p12 format from the drop down and name it `cert.p12`.
13
+
14
+ Now covert the p12 file to a pem file:
15
+
16
+ $ openssl pkcs12 -in cert.p12 -out apn_development.pem -nodes -clcerts && rm -f cert.p12
17
+
18
+ Put `apn_development.pem` in `config/certs` in your rails app. For production, name your certificate `apn_production.pem` and put it in the same directory. See the environment section for more about environments.
19
+
20
+ ## Installing
21
+
22
+ Install as a gem:
23
+
24
+ # Add to config/environment.rb:
25
+ config.gem "apple_push_notification", :source => "http://gemcutter.org/"
26
+
27
+ # At command prompt:
28
+ $ sudo rake gems:install
29
+
30
+ or as a plugin:
31
+
32
+ $ script/plugin install git://github.com/samsoffes/apple_push_notification.git
33
+
34
+ Once you have installed apple\_push\_notification, run the following command:
35
+
36
+ $ rake apn:migrate
37
+
38
+ ## Environment
39
+
40
+ By default, the development environment will always be used. This makes it easy to test your app in production before your iPhone application is approved and your production certificate is active. You can easily override this by adding this line in an initializer or environment file.
41
+
42
+ ApplePushNotification.enviroment = Rails.env.to_sym
43
+
44
+ You can also simply set `ApplePushNotification.enviroment` to `:development` or `:production`. Setting the `ApplePushNotification.enviroment` chooses the appropriate certificate in your `certs` folder and Apple push notification server.
45
+
46
+ ## Example
47
+
48
+ $ ./script/console
49
+ >> a = ApplePushNotification.new
50
+ >> a.device_token = "XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX"
51
+ >> a.badge = 5
52
+ >> a.sound = true
53
+ >> a.alert = "Hello world"
54
+ >> a.send_notification
55
+ => nil
56
+
57
+ ### Notes
58
+
59
+ * The spaces in `device_token` are optional.
60
+ * The `sound` can be the filename (i.e. `explosion.aiff`) or `true` which will play the default notification sound.
61
+
62
+ Copyright (c) 2009 Fabien Penso. Released under the MIT license. Modified by [Sam Soffes](http://samsoff.es).
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/init.rb ADDED
File without changes
data/install.rb ADDED
File without changes
@@ -0,0 +1,101 @@
1
+ require 'socket'
2
+ require 'openssl'
3
+
4
+ class ApplePushNotification < ActiveRecord::Base
5
+
6
+ attr_accessor :paylod, :sound, :badge, :alert
7
+ attr_accessible :device_token
8
+
9
+ PORT = 2195
10
+
11
+ cattr_accessor :enviroment
12
+ self.enviroment = :development
13
+
14
+ validates_uniqueness_of :device_token
15
+
16
+ def send_notification
17
+ raise "Missing cert: #{_path}" unless @@cert
18
+
19
+ ctx = OpenSSL::SSL::SSLContext.new
20
+ ctx.key = OpenSSL::PKey::RSA.new(@@cert)
21
+ ctx.cert = OpenSSL::X509::Certificate.new(@@cert)
22
+
23
+ s = TCPSocket.new(@@host, PORT)
24
+ ssl = OpenSSL::SSL::SSLSocket.new(s, ctx)
25
+ ssl.sync = true
26
+ ssl.connect
27
+
28
+ ssl.write(self.apn_message_for_sending)
29
+
30
+ ssl.close
31
+ s.close
32
+
33
+ rescue SocketError => error
34
+ raise "Error while sending notifications: #{error}"
35
+ end
36
+
37
+ def self.enviroment= enviroment
38
+ @@enviroment = enviroment.to_sym
39
+ @@host = self.production? ? "gateway.push.apple.com" : "gateway.sandbox.push.apple.com"
40
+ cert = self.production? ? "apn_production.pem" : "apn_development.pem"
41
+ path = File.join(File.expand_path(RAILS_ROOT), "config", "certs", cert)
42
+ @@cert = File.exists?(path) ? File.read(path) : nil
43
+ end
44
+
45
+ def self.development?
46
+ @@enviroment != :production
47
+ end
48
+
49
+ def self.production?
50
+ @@enviroment == :production
51
+ end
52
+
53
+ def self.send_notifications(notifications)
54
+ ctx = OpenSSL::SSL::SSLContext.new
55
+ ctx.key = OpenSSL::PKey::RSA.new(@@cert)
56
+ ctx.cert = OpenSSL::X509::Certificate.new(@@cert)
57
+
58
+ s = TCPSocket.new(@@host, PORT)
59
+ ssl = OpenSSL::SSL::SSLSocket.new(s, ctx)
60
+ ssl.sync = true
61
+ ssl.connect
62
+
63
+ for notif in notifications do
64
+ ssl.write(notif.apn_message_for_sending)
65
+ end
66
+
67
+ ssl.close
68
+ s.close
69
+ rescue SocketError => error
70
+ raise "Error while sending notifications: #{error}"
71
+ end
72
+
73
+ protected
74
+
75
+ def to_apple_json
76
+ json = self.apple_array.to_json
77
+ logger.debug "Sending #{json}"
78
+ json
79
+ end
80
+
81
+ def apn_message_for_sending
82
+ json = self.to_apple_json
83
+ message = "\0\0 #{self.device_token_hexa}\0#{json.length.chr}#{json}"
84
+ raise "The maximum size allowed for a notification payload is 256 bytes." if message.size.to_i > 256
85
+ message
86
+ end
87
+
88
+ def device_token_hexa
89
+ [self.device_token.delete(' ')].pack('H*')
90
+ end
91
+
92
+ def apple_array
93
+ result = {}
94
+ result['aps'] = {}
95
+ result['aps']['alert'] = alert if alert
96
+ result['aps']['badge'] = badge.to_i if badge
97
+ result['aps']['sound'] = sound if sound and sound.is_a? String
98
+ result['aps']['sound'] = 'default' if sound and sound.is_a? TrueClass
99
+ result
100
+ end
101
+ end
@@ -0,0 +1,9 @@
1
+ require File.join(File.dirname(__FILE__), "app", "models", "apple_push_notification.rb")
2
+
3
+ %w{ models }.each do |dir|
4
+ path = File.join(File.dirname(__FILE__), 'app', dir)
5
+ $LOAD_PATH << path
6
+ puts "Adding #{path}"
7
+ ActiveSupport::Dependencies.load_paths << path
8
+ ActiveSupport::Dependencies.load_once_paths.delete(path)
9
+ end
@@ -0,0 +1,18 @@
1
+ class CreateApplePushNotifications < ActiveRecord::Migration
2
+ def self.up
3
+ # This is used to store the device UID informations
4
+ create_table :apple_push_notifications do |t|
5
+ t.string :device_token, :size => 71
6
+ t.integer :errors_nb, :default => 0 # used for storing errors from apple feedbacks
7
+ t.string :device_language, :size => 5 # if you don't want to send localized strings
8
+
9
+ t.timestamps
10
+ end
11
+
12
+ add_index :apple_push_notifications, :device_token
13
+ end
14
+
15
+ def self.down
16
+ drop_table :apple_push_notifications
17
+ end
18
+ end
@@ -0,0 +1,10 @@
1
+ namespace :apn do
2
+ desc "migrates ugin's migration files into the database."
3
+ task :migrate => :environment do
4
+
5
+ ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
6
+ ActiveRecord::Migrator.migrate(File.expand_path(File.dirname(__FILE__) + "/../lib/db/migrate"), ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
7
+
8
+ Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
9
+ end
10
+ end
@@ -0,0 +1,8 @@
1
+ require 'test_helper'
2
+
3
+ class ApplePushNotificationTest < ActiveSupport::TestCase
4
+ # Someone could be awesome and write a test
5
+ test "the truth" do
6
+ assert true
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+ require 'active_support/test_case'
data/uninstall.rb ADDED
@@ -0,0 +1 @@
1
+ # Uninstall hook code here
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: apple_push_notification
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Sam Soffes
8
+ - Fabien Penso
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-11-10 00:00:00 -06:00
14
+ default_executable:
15
+ dependencies: []
16
+
17
+ description: Rails plugin for Apple Push Notifications
18
+ email: sam@samsoff.es
19
+ executables: []
20
+
21
+ extensions: []
22
+
23
+ extra_rdoc_files:
24
+ - LICENSE
25
+ files:
26
+ - .gitignore
27
+ - LICENSE
28
+ - Rakefile
29
+ - Readme.markdown
30
+ - VERSION
31
+ - init.rb
32
+ - install.rb
33
+ - lib/app/models/apple_push_notification.rb
34
+ - lib/apple_push_notification.rb
35
+ - lib/db/migrate/20090406132059_create_apple_push_notifications.rb
36
+ - tasks/apple_push_notification_tasks.rake
37
+ - test/apple_push_notification_test.rb
38
+ - test/test_helper.rb
39
+ - uninstall.rb
40
+ has_rdoc: true
41
+ homepage: http://github.com/samsoffes/apple_push_notification
42
+ licenses: []
43
+
44
+ post_install_message:
45
+ rdoc_options:
46
+ - --charset=UTF-8
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: "0"
60
+ version:
61
+ requirements: []
62
+
63
+ rubyforge_project:
64
+ rubygems_version: 1.3.5
65
+ signing_key:
66
+ specification_version: 3
67
+ summary: Rails plugin for Apple Push Notifications
68
+ test_files:
69
+ - test/apple_push_notification_test.rb
70
+ - test/test_helper.rb