qoobaa-d2s3 0.1.1

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/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.markdown
2
+ lib/**/*.rb
3
+ features/**/*.feature
4
+ generators/**
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Matthew Williams, Jakub Kuźma
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,62 @@
1
+ # **d2s3**
2
+ d2s3 (direct to s3) is a simple Ruby on Rails helper that generates an upload form that will take a given file and upload it directly to your S3 bucket, bypassing your server. This has various benefits, the biggest being that a large upload will not tie up your server from serving other requests. This plugin is based on the instructions from the following Amazon tutorial: [http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1434](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1434/ "Browser Uploads to S3 using HTML POST Forms")
3
+
4
+ ### Why?
5
+ This was built as a solution to a problem we had where images being uploaded to be processed by [Paperclip](http://thoughtbot.com/projects/paperclip "Thoughtbot - Paperclip") were consuming [Thin](http://code.macournoyer.com/thin/ "Thin - Another Web Server") servers so they were unable to process other requests.
6
+
7
+ #### An example workflow using d2s3
8
+ 1. Upload file with the `s3_upload_form_tag` helper form tag
9
+ 2. With the data returned from the GET HTTP request from Amazon, create a message using Amazon's SQS service with the appropriate information needed to later process the image with [Paperclip](http://thoughtbot.com/projects/paperclip "Thoughtbot - Paperclip")
10
+ 3. Create an API end point for a background process to access that accepts information to process the image with Paperclip. In our case, it accepts the ID of a photo album and the path to the photo to be processed
11
+ 4. Running a back end process that monitors the SQS queue for new images and processes them immediately
12
+
13
+ We don't have immediate processing of our images with this workflow, but it's very quick assuming how large the queue is and how many back end processes we have actually running through the queue.
14
+
15
+ ### Example d2s3 usage
16
+ <%= s3_upload_form_tag :key => 'uploads',
17
+ :redirect => image_processing_url,
18
+ :acl => 'public-read',
19
+ :max_filesize => 5.megabytes,
20
+ :submit_button => '<input type="submit" value="Upload" class="button" id="upload-button">',
21
+ :form => {:style => 'display: inline;'} %>
22
+
23
+ The above helper will generate the following similar HTML form, generating all of the appropriate field keys, policy, and signature based on your Amazon Web Services YAML configuration file. The form parameter also accepts a class and id for further customization.
24
+
25
+ <form action="https://YOUR_S3_BUCKET.s3.amazonaws.com/" method="post" enctype="multipart/form-data" style="display: inline;">
26
+ <input type="hidden" name="key" value="uploads/${filename}">
27
+ <input type="hidden" name="AWSAccessKeyId" value="YOUR_AWS_ACCESS_KEY">
28
+ <input type="hidden" name="acl" value="public-read">
29
+ <input type="hidden" name="success_action_redirect" value="/image_processing_url">
30
+ <input type="hidden" name="policy" value="YOUR_POLICY_DOCUMENT_BASE64_ENCODED">
31
+ <input type="hidden" name="signature" value="YOUR_CALCULATED_SIGNATURE">
32
+ <input name="file" type="file"><input type="submit" value="Upload" class="button" id="upload-button">
33
+ </form>
34
+
35
+ ### Return HTTP GET request from Amazon made to the redirect you declared
36
+ Parameters: {"bucket"=>"BUCKET_NAME",
37
+ "etag"=>"ETAG_HASH",
38
+ "action"=>"YOUR_REDIRECT_URL",
39
+ "controller"=>"CONTROLLER",
40
+ "key"=>"PATH/FILENAME.EXTENSION"}
41
+
42
+ ### Options:
43
+ * **:redirect**
44
+ * Directs the form where the GET request from Amazon should be made once the HTTP POST is successful
45
+ * **:acl**
46
+ * Accepts either 'public-read' or 'private'. If blank, it defaults to 'public-read'
47
+ * **:expiration_date**
48
+ * Accepts time in the form of "3.hours" or "25.minutes". If blank, it defaults to a 10 hour window before the policy on the upload expires
49
+ * **:max_filesize**
50
+ * Accepts a max file size in the format of "5.megabytes". If blank, it defaults to 1.megabyte
51
+ * **:submit_button**
52
+ * Accepts any text to represent the submit button for the form. This allows for a very custom submit button. If blank, it defaults to `<input type="submit" value="Upload">`
53
+ * **:form => {:id => '', :class => '', :style => ''}**
54
+ * Accepts a hash of :class, :id, and :style to add customization to the form as a whole
55
+
56
+
57
+ ### **TODO**
58
+ * write more tests
59
+
60
+ _**Matthew Williams, Jakub Kuźma, 2009**_
61
+
62
+ Thanks to the [s3-swf-upload](http://github.com/elcgit/s3-swf-upload-plugin/tree/master "s3-swf-upload GitHub Project Page") plugin which code was borrowed from to make this project happen.
data/Rakefile ADDED
@@ -0,0 +1,58 @@
1
+ #coding: UTF-8
2
+
3
+ require 'rubygems'
4
+ require 'rake'
5
+
6
+ begin
7
+ require 'jeweler'
8
+ Jeweler::Tasks.new do |gem|
9
+ gem.name = "d2s3"
10
+ gem.summary = %Q{direct to s3}
11
+ gem.email = "qoobaa@gmail.com"
12
+ gem.homepage = "http://github.com/qoobaa/d2s3"
13
+ gem.authors = ["Matthew Williams", "Jakub Kuźma"]
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
19
+ end
20
+
21
+ require 'rake/testtask'
22
+ Rake::TestTask.new(:test) do |test|
23
+ test.libs << 'lib' << 'test'
24
+ test.pattern = 'test/**/*_test.rb'
25
+ test.verbose = true
26
+ end
27
+
28
+ begin
29
+ require 'rcov/rcovtask'
30
+ Rcov::RcovTask.new do |test|
31
+ test.libs << 'test'
32
+ test.pattern = 'test/**/*_test.rb'
33
+ test.verbose = true
34
+ end
35
+ rescue LoadError
36
+ task :rcov do
37
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
38
+ end
39
+ end
40
+
41
+
42
+ task :default => :test
43
+
44
+ require 'rake/rdoctask'
45
+ Rake::RDocTask.new do |rdoc|
46
+ if File.exist?('VERSION.yml')
47
+ config = YAML.load(File.read('VERSION.yml'))
48
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
49
+ else
50
+ version = ""
51
+ end
52
+
53
+ rdoc.rdoc_dir = 'rdoc'
54
+ rdoc.title = "d2s3 #{version}"
55
+ rdoc.rdoc_files.include('README*')
56
+ rdoc.rdoc_files.include('lib/**/*.rb')
57
+ end
58
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.1
data/d2s3.gemspec ADDED
@@ -0,0 +1,51 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{d2s3}
5
+ s.version = "0.1.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Matthew Williams", "Jakub Kuźma"]
9
+ s.date = %q{2009-06-16}
10
+ s.email = %q{qoobaa@gmail.com}
11
+ s.extra_rdoc_files = [
12
+ "LICENSE",
13
+ "README.markdown"
14
+ ]
15
+ s.files = [
16
+ ".document",
17
+ ".gitignore",
18
+ "LICENSE",
19
+ "README.markdown",
20
+ "Rakefile",
21
+ "VERSION",
22
+ "d2s3.gemspec",
23
+ "generators/d2s3/d2s3.rb",
24
+ "generators/d2s3/templates/initializers/d2s3.rb",
25
+ "lib/d2s3.rb",
26
+ "lib/d2s3/configuration.rb",
27
+ "lib/d2s3/signature.rb",
28
+ "lib/d2s3/view_helpers.rb",
29
+ "test/signature_test.rb",
30
+ "test/test_helper.rb"
31
+ ]
32
+ s.homepage = %q{http://github.com/qoobaa/d2s3}
33
+ s.rdoc_options = ["--charset=UTF-8"]
34
+ s.require_paths = ["lib"]
35
+ s.rubygems_version = %q{1.3.4}
36
+ s.summary = %q{direct to s3}
37
+ s.test_files = [
38
+ "test/signature_test.rb",
39
+ "test/test_helper.rb"
40
+ ]
41
+
42
+ if s.respond_to? :specification_version then
43
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
44
+ s.specification_version = 3
45
+
46
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
47
+ else
48
+ end
49
+ else
50
+ end
51
+ end
@@ -0,0 +1,17 @@
1
+ require 'rbconfig'
2
+
3
+ class D2S3Generator < Rails::Generator::Base
4
+ def manifest
5
+ record do |m|
6
+ m.directory "config"
7
+ m.directory "config/initializers"
8
+ m.file "initializers/d2s3.rb", "config/initializers/d2s3.rb"
9
+ end
10
+ end
11
+
12
+ protected
13
+
14
+ def banner
15
+ "Usage: #{$0} d2s3"
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ D2S3.configuration do |config|
2
+ config.access_key_id = "your_access_key_id"
3
+ config.secret_access_key = "your_secret_access_key"
4
+ config.bucket = "your_application_name"
5
+ end
@@ -0,0 +1,18 @@
1
+ require "singleton"
2
+
3
+ module D2S3
4
+ class Configuration
5
+ include Singleton
6
+
7
+ ATTRIBUTES = [:access_key_id, :secret_access_key, :bucket]
8
+
9
+ attr_accessor *ATTRIBUTES
10
+ end
11
+
12
+ def self.configuration
13
+ if block_given?
14
+ yield Configuration.instance
15
+ end
16
+ Configuration.instance
17
+ end
18
+ end
@@ -0,0 +1,194 @@
1
+ module D2S3
2
+ module Signature
3
+ HEXCASE = false # hex output format. false - lowercase; true - uppercase
4
+ B64PAD = "=" # base-64 pad character. "=" for strict RFC compliance
5
+ CHRSH = 8 # bits per input character. 8 - ASCII; 16 - Unicode
6
+
7
+ def hex_sha1(s)
8
+ return binb2hex(core_sha1(str2binb(s), s.length * CHRSH))
9
+ end
10
+
11
+ def b64_hmac_sha1(key, data)
12
+ return binb2b64(core_hmac_sha1(key, data))
13
+ end
14
+
15
+ # 32-bit left shift
16
+ def js_shl(num, count)
17
+ v = (num << count) & 0xffffffff
18
+ v > 2**31 ? v - 2**32 : v
19
+ end
20
+
21
+ # 32-bit zero-fill right shift (>>>)
22
+ def js_shr_zf(num, count)
23
+ num >> count & (2**(32-count)-1)
24
+ end
25
+
26
+ # Calculate the SHA-1 of an array of big-endian words, and a bit length
27
+ def core_sha1(x, len)
28
+ # append padding
29
+ x[len >> 5] ||= 0
30
+ x[len >> 5] |= 0x80 << (24 - len % 32)
31
+ x[((len + 64 >> 9) << 4) + 15] = len
32
+
33
+ w = Array.new(80, 0)
34
+ a = 1732584193
35
+ b = -271733879
36
+ c = -1732584194
37
+ d = 271733878
38
+ e = -1009589776
39
+
40
+ #for(var i = 0; i < x.length; i += 16)
41
+ i = 0
42
+ while(i < x.length)
43
+ olda = a
44
+ oldb = b
45
+ oldc = c
46
+ oldd = d
47
+ olde = e
48
+
49
+ #for(var j = 0; j < 80; j++)
50
+ j = 0
51
+ while(j < 80)
52
+ if(j < 16)
53
+ w[j] = x[i + j] || 0
54
+ else
55
+ w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1)
56
+ end
57
+
58
+ t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
59
+ safe_add(safe_add(e, w[j]), sha1_kt(j)))
60
+ e = d
61
+ d = c
62
+ c = rol(b, 30)
63
+ b = a
64
+ a = t
65
+ j += 1
66
+ end
67
+
68
+ a = safe_add(a, olda)
69
+ b = safe_add(b, oldb)
70
+ c = safe_add(c, oldc)
71
+ d = safe_add(d, oldd)
72
+ e = safe_add(e, olde)
73
+ i += 16
74
+ end
75
+ return [a, b, c, d, e]
76
+ end
77
+
78
+ # Perform the appropriate triplet combination function for the current
79
+ # iteration
80
+ def sha1_ft(t, b, c, d)
81
+ return (b & c) | ((~b) & d) if(t < 20)
82
+ return b ^ c ^ d if(t < 40)
83
+ return (b & c) | (b & d) | (c & d) if(t < 60)
84
+ return b ^ c ^ d;
85
+ end
86
+
87
+ # Determine the appropriate additive constant for the current iteration
88
+ def sha1_kt(t)
89
+ return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
90
+ (t < 60) ? -1894007588 : -899497514
91
+ end
92
+
93
+ # Calculate the HMAC-SHA1 of a key and some data
94
+ def core_hmac_sha1(key, data)
95
+ bkey = str2binb(key)
96
+ if(bkey.length > 16)
97
+ bkey = core_sha1(bkey, key.length * CHRSH)
98
+ end
99
+
100
+ ipad = Array.new(16, 0)
101
+ opad = Array.new(16, 0)
102
+ #for(var i = 0; i < 16; i++)
103
+ i = 0
104
+ while(i < 16)
105
+ ipad[i] = (bkey[i] || 0) ^ 0x36363636
106
+ opad[i] = (bkey[i] || 0) ^ 0x5C5C5C5C
107
+ i += 1
108
+ end
109
+
110
+ hash = core_sha1((ipad + str2binb(data)), 512 + data.length * CHRSH)
111
+ return core_sha1((opad + hash), 512 + 160)
112
+ end
113
+
114
+ # Add integers, wrapping at 2^32. This uses 16-bit operations internally
115
+ # to work around bugs in some JS interpreters.
116
+ def safe_add(x, y)
117
+ v = (x+y) % (2**32)
118
+ return v > 2**31 ? v- 2**32 : v
119
+ end
120
+
121
+ # Bitwise rotate a 32-bit number to the left.
122
+ def rol(num, cnt)
123
+ #return (num << cnt) | (num >>> (32 - cnt))
124
+ return (js_shl(num, cnt)) | (js_shr_zf(num, 32 - cnt))
125
+ end
126
+
127
+ # Convert an 8-bit or 16-bit string to an array of big-endian words
128
+ # In 8-bit function, characters >255 have their hi-byte silently ignored.
129
+ def str2binb(str)
130
+ bin = []
131
+ mask = (1 << CHRSH) - 1
132
+ #for(var i = 0; i < str.length * CHRSH; i += CHRSH)
133
+ i = 0
134
+ while(i < str.length * CHRSH)
135
+ bin[i>>5] ||= 0
136
+ byte = str.respond_to?(:getbyte) ? str.getbyte(i / CHRSH) : str[i / CHRSH]
137
+ bin[i>>5] |= (byte & mask) << (32 - CHRSH - i%32)
138
+ i += CHRSH
139
+ end
140
+ return bin
141
+ end
142
+
143
+ # Convert an array of big-endian words to a string
144
+ # function binb2str(bin)
145
+ # {
146
+ # var str = "";
147
+ # var mask = (1 << CHRSH) - 1;
148
+ # for(var i = 0; i < bin.length * 32; i += CHRSH)
149
+ # str += String.fromCharCode((bin[i>>5] >>> (32 - CHRSH - i%32)) & mask);
150
+ # return str;
151
+ # }
152
+ #
153
+
154
+ # Convert an array of big-endian words to a hex string.
155
+ def binb2hex(binarray)
156
+ hex_tab = HEXCASE ? "0123456789ABCDEF" : "0123456789abcdef"
157
+ str = ""
158
+ #for(var i = 0; i < binarray.length * 4; i++)
159
+ i = 0
160
+ while(i < binarray.length * 4)
161
+ str += hex_tab[(binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF].chr +
162
+ hex_tab[(binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF].chr
163
+ i += 1
164
+ end
165
+ return str;
166
+ end
167
+
168
+ # Convert an array of big-endian words to a base-64 string
169
+ def binb2b64(binarray)
170
+ tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
171
+ str = ""
172
+
173
+ #for(var i = 0; i < binarray.length * 4; i += 3)
174
+ i = 0
175
+ while(i < binarray.length * 4)
176
+ triplet = (((binarray[i >> 2].to_i >> 8 * (3 - i %4)) & 0xFF) << 16) |
177
+ (((binarray[i+1 >> 2].to_i >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 ) |
178
+ ((binarray[i+2 >> 2].to_i >> 8 * (3 - (i+2)%4)) & 0xFF)
179
+ #for(var j = 0; j < 4; j++)
180
+ j = 0
181
+ while(j < 4)
182
+ if(i * 8 + j * 6 > binarray.length * 32)
183
+ str += B64PAD
184
+ else
185
+ str += tab[(triplet >> 6*(3-j)) & 0x3F].chr
186
+ end
187
+ j += 1
188
+ end
189
+ i += 3
190
+ end
191
+ return str
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,50 @@
1
+ require 'base64'
2
+
3
+ module D2S3
4
+ module ViewHelpers
5
+ include D2S3::Signature
6
+
7
+ def s3_upload_form_tag(options = {})
8
+ bucket = configuration.bucket
9
+ access_key_id = configuration.access_key_id
10
+ protocol = options[:protocol] || "http"
11
+ key = options[:key] || ''
12
+ redirect = options[:redirect] || '/'
13
+ acl = options[:acl] || 'public-read'
14
+ expiration_date = (options[:expiration_date] || 10.hours).from_now.strftime('%Y-%m-%dT%H:%M:%S.000Z')
15
+ max_filesize = options[:max_filesize] || 1.megabyte
16
+ submit_button = options[:submit_button] || '<input type="submit" value="#{I18n.t("button.upload")}">'
17
+
18
+ options[:form] ||= {}
19
+ options[:form][:id] ||= 'upload-form'
20
+ options[:form][:class] ||= 'upload-form'
21
+
22
+ policy = Base64.encode64(
23
+ %({"expiration": "#{expiration_date}",
24
+ "conditions": [
25
+ {"bucket": "#{bucket}"},
26
+ ["starts-with", "$key", "#{key}"],
27
+ {"acl": "#{acl}"},
28
+ {"success_action_redirect": "#{redirect}"},
29
+ ["content-length-range", 0, #{max_filesize}]
30
+ ]
31
+ })).gsub(/\n|\r/, '')
32
+
33
+ signature = b64_hmac_sha1(D2S3::S3Config.secret_access_key, policy)
34
+ out = ""
35
+ out << %(
36
+ <form action="#{protocol}://#{bucket}.s3.amazonaws.com/" method="post" enctype="multipart/form-data" id="#{options[:form][:id]}" class="#{options[:form][:class]}" style="#{options[:form][:style]}">
37
+ <input type="hidden" name="key" value="#{key}/${filename}">
38
+ <input type="hidden" name="AWSAccessKeyId" value="#{access_key_id}">
39
+ <input type="hidden" name="acl" value="#{acl}">
40
+ <input type="hidden" name="success_action_redirect" value="#{redirect}">
41
+ <input type="hidden" name="policy" value="#{policy}">
42
+ <input type="hidden" name="signature" value="#{signature}">
43
+ <input name="file" type="file">#{submit_button}
44
+ </form>
45
+ )
46
+ end
47
+ end
48
+ end
49
+
50
+ ActionView::Base.send(:include, D2S3::ViewHelpers) if defined?(ActionView::Base)
data/lib/d2s3.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'd2s3/signature'
2
+ require 'd2s3/configuration'
3
+ require 'd2s3/view_helpers'
@@ -0,0 +1,57 @@
1
+ require 'test_helper'
2
+
3
+ include D2S3::Signature
4
+
5
+ class SignatureTest < Test::Unit::TestCase
6
+ should "return correct core_sha1 values" do
7
+ str = "abc"
8
+ assert [-519653305, -1566383753, -2070791546, -753729183, -204968198], core_sha1(str2binb(str), str.length)
9
+ end
10
+
11
+ should "return correct str2binb values" do
12
+ assert [1718578976, 1650553376, 1751480608, 1952998770, 1694498816], str2binb('foo bar hey there')
13
+ end
14
+
15
+ should "return correct hex_sha1 value" do
16
+ assert "a9993e364706816aba3e25717850c26c9cd0d89d", hex_sha1("abc")
17
+ end
18
+
19
+ should "return correct b64_hmac_sha1 value" do
20
+ assert "frFXMR9cNoJdsSPnjebZpBhUKzI=", b64_hmac_sha1("foo", "abc")
21
+ end
22
+
23
+ context "with num=1732584193 and cnt=5" do
24
+ setup do
25
+ @num = 1732584193
26
+ @cnt = 5
27
+ end
28
+
29
+ should "return correct roll value" do
30
+ assert -391880660, rol(@num, @cnt)
31
+ end
32
+
33
+ should "return correct safe_add value" do
34
+ assert -519653305, safe_add(2042729798, @num)
35
+ end
36
+
37
+ should "return correct js_shl value" do
38
+ assert -391880672, js_shl(@num, @cnt)
39
+ end
40
+
41
+ should "return correct js_shr_zf value" do
42
+ assert 12, js_shr_zf(@num, 32 - @cnt)
43
+ end
44
+
45
+ should "return correct sha1_ft value" do
46
+ assert -1732584194, sha1_ft(0, -271733879, -1732584194, 271733878)
47
+ end
48
+
49
+ should "return correct sha1_kt value" do
50
+ assert 1518500249, sha1_kt(0)
51
+ end
52
+
53
+ should "return correct safe_add value" do
54
+ assert 286718899, safe_add(safe_add(rol(@num, @cnt), sha1_ft(0, -271733879, -1732584194, 271733878)), safe_add(safe_add(-1009589776, 1902273280), sha1_kt(0)))
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'd2s3'
8
+
9
+ class Test::Unit::TestCase
10
+ end
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: qoobaa-d2s3
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Matthew Williams
8
+ - "Jakub Ku\xC5\xBAma"
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-06-16 00:00:00 -07:00
14
+ default_executable:
15
+ dependencies: []
16
+
17
+ description:
18
+ email: qoobaa@gmail.com
19
+ executables: []
20
+
21
+ extensions: []
22
+
23
+ extra_rdoc_files:
24
+ - LICENSE
25
+ - README.markdown
26
+ files:
27
+ - .document
28
+ - .gitignore
29
+ - LICENSE
30
+ - README.markdown
31
+ - Rakefile
32
+ - VERSION
33
+ - d2s3.gemspec
34
+ - generators/d2s3/d2s3.rb
35
+ - generators/d2s3/templates/initializers/d2s3.rb
36
+ - lib/d2s3.rb
37
+ - lib/d2s3/configuration.rb
38
+ - lib/d2s3/signature.rb
39
+ - lib/d2s3/view_helpers.rb
40
+ - test/signature_test.rb
41
+ - test/test_helper.rb
42
+ has_rdoc: false
43
+ homepage: http://github.com/qoobaa/d2s3
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.2.0
65
+ signing_key:
66
+ specification_version: 3
67
+ summary: direct to s3
68
+ test_files:
69
+ - test/signature_test.rb
70
+ - test/test_helper.rb