aws 2.3.34 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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