aws 2.3.34 → 2.4.0

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.
@@ -2,141 +2,141 @@
2
2
  # want a dependency on it, so if it's not present, define the few
3
3
  # extensions that we want to use...
4
4
  unless defined? ActiveSupport
5
- # These are ActiveSupport-;like extensions to do a few handy things in the gems
6
- # Derived from ActiveSupport, so the AS copyright notice applies:
7
- #
8
- #
9
- #
10
- # Copyright (c) 2005 David Heinemeier Hansson
11
- #
12
- # Permission is hereby granted, free of charge, to any person obtaining
13
- # a copy of this software and associated documentation files (the
14
- # "Software"), to deal in the Software without restriction, including
15
- # without limitation the rights to use, copy, modify, merge, publish,
16
- # distribute, sublicense, and/or sell copies of the Software, and to
17
- # permit persons to whom the Software is furnished to do so, subject to
18
- # the following conditions:
19
- #
20
- # The above copyright notice and this permission notice shall be
21
- # included in all copies or substantial portions of the Software.
22
- #
23
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30
- #++
31
- #
32
- #
33
- class String #:nodoc:
5
+ # These are ActiveSupport-;like extensions to do a few handy things in the gems
6
+ # Derived from ActiveSupport, so the AS copyright notice applies:
7
+ #
8
+ #
9
+ #
10
+ # Copyright (c) 2005 David Heinemeier Hansson
11
+ #
12
+ # Permission is hereby granted, free of charge, to any person obtaining
13
+ # a copy of this software and associated documentation files (the
14
+ # "Software"), to deal in the Software without restriction, including
15
+ # without limitation the rights to use, copy, modify, merge, publish,
16
+ # distribute, sublicense, and/or sell copies of the Software, and to
17
+ # permit persons to whom the Software is furnished to do so, subject to
18
+ # the following conditions:
19
+ #
20
+ # The above copyright notice and this permission notice shall be
21
+ # included in all copies or substantial portions of the Software.
22
+ #
23
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30
+ #++
31
+ #
32
+ #
33
+ class String #:nodoc:
34
34
 
35
- # Constantize tries to find a declared constant with the name specified
36
- # in the string. It raises a NameError when the name is not in CamelCase
37
- # or is not initialized.
38
- #
39
- # Examples
40
- # "Module".constantize #=> Module
41
- # "Class".constantize #=> Class
42
- def constantize()
43
- camel_cased_word = self
44
- names = camel_cased_word.split('::')
45
- names.shift if names.empty? || names.first.empty?
35
+ # Constantize tries to find a declared constant with the name specified
36
+ # in the string. It raises a NameError when the name is not in CamelCase
37
+ # or is not initialized.
38
+ #
39
+ # Examples
40
+ # "Module".constantize #=> Module
41
+ # "Class".constantize #=> Class
42
+ def constantize()
43
+ camel_cased_word = self
44
+ names = camel_cased_word.split('::')
45
+ names.shift if names.empty? || names.first.empty?
46
46
 
47
- constant = Object
48
- names.each do |name|
47
+ constant = Object
48
+ names.each do |name|
49
49
  # constant = constant.const_get(name, false) || constant.const_missing(name)
50
- if Module.method(:const_get).arity == 1
51
- # ruby 1.8
52
- constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
53
- else
54
- # ruby 1.9
55
- constant = constant.const_get(name, false) || constant.const_missing(name)
56
- end
57
- end
58
- constant
50
+ if Module.method(:const_get).arity == 1
51
+ # ruby 1.8
52
+ constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
53
+ else
54
+ # ruby 1.9
55
+ constant = constant.const_get(name, false) || constant.const_missing(name)
59
56
  end
60
-
57
+ end
58
+ constant
61
59
  end
62
60
 
61
+ end
63
62
 
64
- class Object #:nodoc:
65
- # "", " ", nil, [], and {} are blank
66
- def blank?
67
- if respond_to?(:empty?) && respond_to?(:strip)
68
- empty? or strip.empty?
69
- elsif respond_to?(:empty?)
70
- empty?
71
- else
72
- !self
73
- end
74
- end
75
- end
76
63
 
77
- class NilClass #:nodoc:
78
- def blank?
79
- true
80
- end
64
+ class Object #:nodoc:
65
+ # "", " ", nil, [], and {} are blank
66
+ def blank?
67
+ if respond_to?(:empty?) && respond_to?(:strip)
68
+ empty? or strip.empty?
69
+ elsif respond_to?(:empty?)
70
+ empty?
71
+ else
72
+ !self
73
+ end
81
74
  end
75
+ end
82
76
 
83
- class FalseClass #:nodoc:
84
- def blank?
85
- true
86
- end
77
+ class NilClass #:nodoc:
78
+ def blank?
79
+ true
87
80
  end
81
+ end
88
82
 
89
- class TrueClass #:nodoc:
90
- def blank?
91
- false
92
- end
83
+ class FalseClass #:nodoc:
84
+ def blank?
85
+ true
93
86
  end
87
+ end
94
88
 
95
- class Array #:nodoc:
96
- alias_method :blank?, :empty?
89
+ class TrueClass #:nodoc:
90
+ def blank?
91
+ false
97
92
  end
93
+ end
98
94
 
99
- class Hash #:nodoc:
100
- alias_method :blank?, :empty?
95
+ class Array #:nodoc:
96
+ alias_method :blank?, :empty?
97
+ end
101
98
 
102
- # Return a new hash with all keys converted to symbols.
103
- def symbolize_keys
104
- inject({}) do |options, (key, value)|
105
- options[key.to_sym] = value
106
- options
107
- end
108
- end
99
+ class Hash #:nodoc:
100
+ alias_method :blank?, :empty?
109
101
 
110
- # Slice a hash to include only the given keys. This is useful for
111
- # limiting an options hash to valid keys before passing to a method:
112
- #
113
- # def search(criteria = {})
114
- # assert_valid_keys(:mass, :velocity, :time)
115
- # end
116
- #
117
- # search(options.slice(:mass, :velocity, :time))
118
- #
119
- # If you have an array of keys you want to limit to, you should splat them:
120
- #
121
- # valid_keys = [:mass, :velocity, :time]
122
- # search(options.slice(*valid_keys))
123
- def slice(*keys)
124
- keys = keys.map! { |key| convert_key(key) } if respond_to?(:convert_key)
125
- hash = self.class.new
126
- keys.each { |k| hash[k] = self[k] if has_key?(k) }
127
- hash
128
- end
102
+ # Return a new hash with all keys converted to symbols.
103
+ def symbolize_keys
104
+ inject({}) do |options, (key, value)|
105
+ options[key.to_sym] = value
106
+ options
107
+ end
129
108
  end
130
109
 
131
- class String #:nodoc:
132
- def blank?
133
- empty? || strip.empty?
134
- end
110
+ # Slice a hash to include only the given keys. This is useful for
111
+ # limiting an options hash to valid keys before passing to a method:
112
+ #
113
+ # def search(criteria = {})
114
+ # assert_valid_keys(:mass, :velocity, :time)
115
+ # end
116
+ #
117
+ # search(options.slice(:mass, :velocity, :time))
118
+ #
119
+ # If you have an array of keys you want to limit to, you should splat them:
120
+ #
121
+ # valid_keys = [:mass, :velocity, :time]
122
+ # search(options.slice(*valid_keys))
123
+ def slice(*keys)
124
+ keys = keys.map! { |key| convert_key(key) } if respond_to?(:convert_key)
125
+ hash = self.class.new
126
+ keys.each { |k| hash[k] = self[k] if has_key?(k) }
127
+ hash
135
128
  end
129
+ end
136
130
 
137
- class Numeric #:nodoc:
138
- def blank?
139
- false
140
- end
131
+ class String #:nodoc:
132
+ def blank?
133
+ empty? || strip.empty?
134
+ end
135
+ end
136
+
137
+ class Numeric #:nodoc:
138
+ def blank?
139
+ false
141
140
  end
141
+ end
142
142
  end
@@ -0,0 +1,207 @@
1
+ module Aws
2
+
3
+ class AwsUtils #:nodoc:
4
+ @@digest1 = OpenSSL::Digest::Digest.new("sha1")
5
+ @@digest256 = nil
6
+ if OpenSSL::OPENSSL_VERSION_NUMBER > 0x00908000
7
+ @@digest256 = OpenSSL::Digest::Digest.new("sha256") rescue nil # Some installation may not support sha256
8
+ end
9
+
10
+ def self.sign(aws_secret_access_key, auth_string)
11
+ Base64.encode64(OpenSSL::HMAC.digest(@@digest1, aws_secret_access_key, auth_string)).strip
12
+ end
13
+
14
+
15
+ # Set a timestamp and a signature version
16
+ def self.fix_service_params(service_hash, signature)
17
+ service_hash["Timestamp"] ||= Time.now.utc.strftime("%Y-%m-%dT%H:%M:%S.000Z") unless service_hash["Expires"]
18
+ service_hash["SignatureVersion"] = signature
19
+ service_hash
20
+ end
21
+
22
+ # Signature Version 0
23
+ # A deprecated guy (should work till septemper 2009)
24
+ def self.sign_request_v0(aws_secret_access_key, service_hash)
25
+ fix_service_params(service_hash, '0')
26
+ string_to_sign = "#{service_hash['Action']}#{service_hash['Timestamp'] || service_hash['Expires']}"
27
+ service_hash['Signature'] = AwsUtils::sign(aws_secret_access_key, string_to_sign)
28
+ service_hash.to_a.collect { |key, val| "#{amz_escape(key)}=#{amz_escape(val.to_s)}" }.join("&")
29
+ end
30
+
31
+ # Signature Version 1
32
+ # Another deprecated guy (should work till septemper 2009)
33
+ def self.sign_request_v1(aws_secret_access_key, service_hash)
34
+ fix_service_params(service_hash, '1')
35
+ string_to_sign = service_hash.sort { |a, b| (a[0].to_s.downcase)<=>(b[0].to_s.downcase) }.to_s
36
+ service_hash['Signature'] = AwsUtils::sign(aws_secret_access_key, string_to_sign)
37
+ service_hash.to_a.collect { |key, val| "#{amz_escape(key)}=#{amz_escape(val.to_s)}" }.join("&")
38
+ end
39
+
40
+ # Signature Version 2
41
+ # EC2, SQS and SDB requests must be signed by this guy.
42
+ # See: http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/index.html?REST_RESTAuth.html
43
+ # http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1928
44
+ def self.sign_request_v2(aws_secret_access_key, service_hash, http_verb, host, uri)
45
+ fix_service_params(service_hash, '2')
46
+ # select a signing method (make an old openssl working with sha1)
47
+ # make 'HmacSHA256' to be a default one
48
+ service_hash['SignatureMethod'] = 'HmacSHA256' unless ['HmacSHA256', 'HmacSHA1'].include?(service_hash['SignatureMethod'])
49
+ service_hash['SignatureMethod'] = 'HmacSHA1' unless @@digest256
50
+ # select a digest
51
+ digest = (service_hash['SignatureMethod'] == 'HmacSHA256' ? @@digest256 : @@digest1)
52
+ # form string to sign
53
+ canonical_string = service_hash.keys.sort.map do |key|
54
+ "#{amz_escape(key)}=#{amz_escape(service_hash[key])}"
55
+ end.join('&')
56
+ string_to_sign = "#{http_verb.to_s.upcase}\n#{host.downcase}\n#{uri}\n#{canonical_string}"
57
+ # sign the string
58
+ signature = escape_sig(Base64.encode64(OpenSSL::HMAC.digest(digest, aws_secret_access_key, string_to_sign)).strip)
59
+ ret = "#{canonical_string}&Signature=#{signature}"
60
+ # puts 'full=' + ret.inspect
61
+ ret
62
+ end
63
+
64
+ HEX = [
65
+ "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07",
66
+ "%08", "%09", "%0A", "%0B", "%0C", "%0D", "%0E", "%0F",
67
+ "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17",
68
+ "%18", "%19", "%1A", "%1B", "%1C", "%1D", "%1E", "%1F",
69
+ "%20", "%21", "%22", "%23", "%24", "%25", "%26", "%27",
70
+ "%28", "%29", "%2A", "%2B", "%2C", "%2D", "%2E", "%2F",
71
+ "%30", "%31", "%32", "%33", "%34", "%35", "%36", "%37",
72
+ "%38", "%39", "%3A", "%3B", "%3C", "%3D", "%3E", "%3F",
73
+ "%40", "%41", "%42", "%43", "%44", "%45", "%46", "%47",
74
+ "%48", "%49", "%4A", "%4B", "%4C", "%4D", "%4E", "%4F",
75
+ "%50", "%51", "%52", "%53", "%54", "%55", "%56", "%57",
76
+ "%58", "%59", "%5A", "%5B", "%5C", "%5D", "%5E", "%5F",
77
+ "%60", "%61", "%62", "%63", "%64", "%65", "%66", "%67",
78
+ "%68", "%69", "%6A", "%6B", "%6C", "%6D", "%6E", "%6F",
79
+ "%70", "%71", "%72", "%73", "%74", "%75", "%76", "%77",
80
+ "%78", "%79", "%7A", "%7B", "%7C", "%7D", "%7E", "%7F",
81
+ "%80", "%81", "%82", "%83", "%84", "%85", "%86", "%87",
82
+ "%88", "%89", "%8A", "%8B", "%8C", "%8D", "%8E", "%8F",
83
+ "%90", "%91", "%92", "%93", "%94", "%95", "%96", "%97",
84
+ "%98", "%99", "%9A", "%9B", "%9C", "%9D", "%9E", "%9F",
85
+ "%A0", "%A1", "%A2", "%A3", "%A4", "%A5", "%A6", "%A7",
86
+ "%A8", "%A9", "%AA", "%AB", "%AC", "%AD", "%AE", "%AF",
87
+ "%B0", "%B1", "%B2", "%B3", "%B4", "%B5", "%B6", "%B7",
88
+ "%B8", "%B9", "%BA", "%BB", "%BC", "%BD", "%BE", "%BF",
89
+ "%C0", "%C1", "%C2", "%C3", "%C4", "%C5", "%C6", "%C7",
90
+ "%C8", "%C9", "%CA", "%CB", "%CC", "%CD", "%CE", "%CF",
91
+ "%D0", "%D1", "%D2", "%D3", "%D4", "%D5", "%D6", "%D7",
92
+ "%D8", "%D9", "%DA", "%DB", "%DC", "%DD", "%DE", "%DF",
93
+ "%E0", "%E1", "%E2", "%E3", "%E4", "%E5", "%E6", "%E7",
94
+ "%E8", "%E9", "%EA", "%EB", "%EC", "%ED", "%EE", "%EF",
95
+ "%F0", "%F1", "%F2", "%F3", "%F4", "%F5", "%F6", "%F7",
96
+ "%F8", "%F9", "%FA", "%FB", "%FC", "%FD", "%FE", "%FF"
97
+ ]
98
+ TO_REMEMBER = 'AZaz09 -_.!~*\'()'
99
+ ASCII = {} # {'A'=>65, 'Z'=>90, 'a'=>97, 'z'=>122, '0'=>48, '9'=>57, ' '=>32, '-'=>45, '_'=>95, '.'=>}
100
+ TO_REMEMBER.each_char do |c| #unpack("c*").each do |c|
101
+ ASCII[c] = c.unpack("c")[0]
102
+ end
103
+ # puts 'ascii=' + ASCII.inspect
104
+
105
+ # Escape a string accordingly Amazon rulles
106
+ # http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/index.html?REST_RESTAuth.html
107
+ def self.amz_escape(param)
108
+
109
+ param = param.to_s
110
+ # param = param.force_encoding("UTF-8")
111
+
112
+ e = "x" # escape2(param.to_s)
113
+ # puts 'ESCAPED=' + e.inspect
114
+
115
+
116
+ #return CGI.escape(param.to_s).gsub("%7E", "~").gsub("+", "%20") # from: http://umlaut.rubyforge.org/svn/trunk/lib/aws_product_sign.rb
117
+
118
+ #param.to_s.gsub(/([^a-zA-Z0-9._~-]+)/n) do
119
+ # '%' + $1.unpack('H2' * $1.size).join('%').upcase
120
+ #end
121
+
122
+ # puts 'e in=' + e.inspect
123
+ # converter = Iconv.new('ASCII', 'UTF-8')
124
+ # e = converter.iconv(e) #.unpack('U*').select{ |cp| cp < 127 }.pack('U*')
125
+ # puts 'e out=' + e.inspect
126
+
127
+ e2 = CGI.escape(param)
128
+ e2 = e2.gsub("%7E", "~")
129
+ e2 = e2.gsub("+", "%20")
130
+ e2 = e2.gsub("*", "%2A")
131
+
132
+ # puts 'E2=' + e2.inspect
133
+ # puts e == e2.to_s
134
+
135
+ e2
136
+
137
+ end
138
+
139
+ def self.escape2(s)
140
+ # home grown
141
+ ret = ""
142
+ s.unpack("U*") do |ch|
143
+ # puts 'ch=' + ch.inspect
144
+ if ASCII['A'] <= ch && ch <= ASCII['Z'] # A to Z
145
+ ret << ch
146
+ elsif ASCII['a'] <= ch && ch <= ASCII['z'] # a to z
147
+ ret << ch
148
+ elsif ASCII['0'] <= ch && ch <= ASCII['9'] # 0 to 9
149
+ ret << ch
150
+ elsif ch == ASCII[' '] # space
151
+ ret << "%20" # "+"
152
+ elsif ch == ASCII['-'] || ch == ASCII['_'] || ch == ASCII['.'] || ch == ASCII['~']
153
+ ret << ch
154
+ elsif ch <= 0x007f # other ascii
155
+ ret << HEX[ch]
156
+ elsif ch <= 0x07FF # non-ascii
157
+ ret << HEX[0xc0 | (ch >> 6)]
158
+ ret << HEX[0x80 | (ch & 0x3F)]
159
+ else
160
+ ret << HEX[0xe0 | (ch >> 12)]
161
+ ret << HEX[0x80 | ((ch >> 6) & 0x3F)]
162
+ ret << HEX[0x80 | (ch & 0x3F)]
163
+ end
164
+
165
+ end
166
+ ret
167
+
168
+ end
169
+
170
+ def self.escape_sig(raw)
171
+ e = CGI.escape(raw)
172
+ end
173
+
174
+ # From Amazon's SQS Dev Guide, a brief description of how to escape:
175
+ # "URL encode the computed signature and other query parameters as specified in
176
+ # RFC1738, section 2.2. In addition, because the + character is interpreted as a blank space
177
+ # by Sun Java classes that perform URL decoding, make sure to encode the + character
178
+ # although it is not required by RFC1738."
179
+ # Avoid using CGI::escape to escape URIs.
180
+ # CGI::escape will escape characters in the protocol, host, and port
181
+ # sections of the URI. Only target chars in the query
182
+ # string should be escaped.
183
+ def self.URLencode(raw)
184
+ e = URI.escape(raw)
185
+ e.gsub(/\+/, "%2b")
186
+ end
187
+
188
+
189
+ def self.allow_only(allowed_keys, params)
190
+ bogus_args = []
191
+ params.keys.each { |p| bogus_args.push(p) unless allowed_keys.include?(p) }
192
+ raise AwsError.new("The following arguments were given but are not legal for the function call #{caller_method}: #{bogus_args.inspect}") if bogus_args.length > 0
193
+ end
194
+
195
+ def self.mandatory_arguments(required_args, params)
196
+ rargs = required_args.dup
197
+ params.keys.each { |p| rargs.delete(p) }
198
+ raise AwsError.new("The following mandatory arguments were not provided to #{caller_method}: #{rargs.inspect}") if rargs.length > 0
199
+ end
200
+
201
+ def self.caller_method
202
+ caller[1]=~/`(.*?)'/
203
+ $1
204
+ end
205
+
206
+ end
207
+ end