chikkenbukket 0.9.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.
@@ -0,0 +1,4 @@
1
+ == 0.9.1 / 2007-06-04
2
+
3
+ * 1 First release as a gem and some basic testing.
4
+
@@ -0,0 +1,7 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/chikken_in_a_bukket
6
+ lib/chikken_in_a_bukket.rb
7
+ test/test_chikken_in_a_bukket.rb
@@ -0,0 +1,46 @@
1
+ ChikkenInABukket
2
+ by Alex Vollmer
3
+ http://chikkenbukket.rubyforge.org/
4
+
5
+ == DESCRIPTION:
6
+
7
+ Chikken in a Bukket provides a simple, lightweight interface to your Amazon S3 account.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * Initial release as a gem
12
+
13
+ == REQUIREMENTS:
14
+
15
+ * s33r
16
+ * camping
17
+ * actionpack
18
+
19
+ == INSTALL:
20
+
21
+ To install simply execute "sudo gem install -y chikken_in_a_bukket"
22
+
23
+ == LICENSE:
24
+
25
+ (The MIT License)
26
+
27
+ Copyright (c) 2007 FIX
28
+
29
+ Permission is hereby granted, free of charge, to any person obtaining
30
+ a copy of this software and associated documentation files (the
31
+ 'Software'), to deal in the Software without restriction, including
32
+ without limitation the rights to use, copy, modify, merge, publish,
33
+ distribute, sublicense, and/or sell copies of the Software, and to
34
+ permit persons to whom the Software is furnished to do so, subject to
35
+ the following conditions:
36
+
37
+ The above copyright notice and this permission notice shall be
38
+ included in all copies or substantial portions of the Software.
39
+
40
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
41
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
42
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
43
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
44
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
45
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
46
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,18 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/chikken_in_a_bukket.rb'
6
+
7
+ Hoe.new('chikkenbukket', ChikkenInaBukket::VERSION) do |p|
8
+ p.rubyforge_name = 'chikkenbukket'
9
+ p.description = 'Lightweight browser access to your Amazon S3 account';
10
+ p.summary = 'Simple browser access to S3'
11
+ p.url = 'http://chikkenbukket.rubyforge.org'
12
+ p.author = 'Alex Vollmer'
13
+ p.email = 'alex.vollmer@gmail.com'
14
+ p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
15
+ p.extra_deps = [['s33r', '>= 0.5.2'], ['actionpack', '>= 1.13.2'], ['camping', '>= 1.5']]
16
+ end
17
+
18
+ # vim: syntax=Ruby
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ gem 'camping'
5
+
6
+ ARGV << File.join(File.dirname(__FILE__), "../lib/chikken_in_a_bukket.rb")
7
+ load 'camping'
@@ -0,0 +1,1009 @@
1
+ require 'pp'
2
+ require 'rubygems'
3
+ require 'base64'
4
+ require 'camping'
5
+ require 's33r'
6
+ require 'action_pack'
7
+ require 'action_view/helpers/number_helper'
8
+
9
+ Camping.goes :ChikkenInaBukket
10
+
11
+ module ChikkenInaBukket
12
+
13
+ VERSION = '0.9.1'
14
+
15
+ class Config
16
+ @@access_key = nil
17
+ @@secret_key = nil
18
+ @@conn = nil
19
+ @@configured = false
20
+
21
+ def self.initialize
22
+ begin
23
+ @@config = open("#{ENV['HOME']}/.chikken_in_a_bukket.yml") { |f| YAML.load(f) }
24
+
25
+ @@access_key = @@config["access_key_id"]
26
+ @@secret_key = @@config["secret_access_key"]
27
+
28
+ @@conn = S33r::Client.new(:access => @@access_key,
29
+ :secret => @@secret_key,
30
+ :use_ssl => @@config["use_ssl"])
31
+ @@configured = true
32
+ rescue Errno::ENOENT => e
33
+ @@configured = false
34
+ end
35
+ end
36
+
37
+ def self.configured?
38
+ @@configured
39
+ end
40
+
41
+ def self.connection
42
+ @@conn
43
+ end
44
+
45
+ def self.access_key
46
+ @@access_key
47
+ end
48
+
49
+ def self.secret_key
50
+ @@secret_key
51
+ end
52
+ end
53
+
54
+ Config.initialize
55
+ end
56
+
57
+ module ChikkenInaBukket::Controllers
58
+ class BackgroundImage < R '/background.gif'
59
+ def get
60
+ @headers['Content-Type'] = 'image/gif'
61
+ @headers['Content-Length'] = ChikkenInaBukket::BACKGROUND.length
62
+ Base64.decode64(ChikkenInaBukket::BACKGROUND)
63
+ end
64
+ end
65
+
66
+ class BucketImage < R '/bucket.png'
67
+ def get
68
+ @headers['Content-Type'] = 'image/png'
69
+ @headers['Content-Length'] = ChikkenInaBukket::BUCKET.length
70
+ Base64.decode64(ChikkenInaBukket::BUCKET)
71
+ end
72
+ end
73
+
74
+ class Stylesheet < R '/style.css'
75
+ def get
76
+ @headers['Content-Type'] = 'text/css'
77
+ <<-CSS
78
+ body {
79
+ font: "Lucida Grande", "Trebuchet MS", Verdana, sans-serif;
80
+ font-size: 80%;
81
+ background-color: white;
82
+ background-image: url('/background.gif');
83
+ background-position: top;
84
+ background-repeat: repeat-x;
85
+ padding: 10px;
86
+ }
87
+
88
+ .separator {
89
+ padding-left: 5px;
90
+ padding-right: 5px;
91
+ }
92
+
93
+ a, a:visited {
94
+ color: #666;
95
+ }
96
+
97
+ div.bucket {
98
+ position: absolute;
99
+ right: 10px;
100
+ bottom: 10px;
101
+ }
102
+
103
+ fieldset {
104
+ width: 50%;
105
+ padding: 10px;
106
+ }
107
+
108
+ input {
109
+ margin-right: 10px;
110
+ }
111
+
112
+ input {
113
+ background-color: #eee;
114
+ }
115
+
116
+ label {
117
+ display: block;
118
+ }
119
+
120
+ span.delete {
121
+ padding: 10px;
122
+ font-size: 80%;
123
+ font-weight: bold;
124
+ }
125
+
126
+ .flash {
127
+ color: #af2219;
128
+ font-weight: bold;
129
+ }
130
+ CSS
131
+ end
132
+ end
133
+
134
+ class Index < R '/'
135
+ def get
136
+ unless Config.configured?
137
+ return redirect(Configuration)
138
+ else
139
+ @buckets = Config.connection.bucket_names
140
+ render :index
141
+ end
142
+ end
143
+
144
+ def post
145
+ begin
146
+ @bucket = Config.connection.create_bucket(@input[:bucket])
147
+ @objs = []
148
+ return redirect(Buckets, @bucket.name)
149
+ rescue S33r::S3Exception::S3OriginatedException => e
150
+ @buckets = Config.connection.bucket_names
151
+ if e.s3_code == 'BucketAlreadyExists'
152
+ @flash = "Sorry, the bucket #{@input[:bucket]} already exists. Try another name."
153
+ else
154
+ @flash = "Error #{e.s3_message}"
155
+ end
156
+ render :index
157
+ end
158
+ end
159
+ end
160
+
161
+ class Buckets < R '/buckets/(.+)'
162
+ include ActionView::Helpers::NumberHelper
163
+
164
+ MAX_KEYS = 15
165
+
166
+ def get(bucket)
167
+ bucket.sub!(/\/$/, '')
168
+ options = {}
169
+
170
+ case @input[:action]
171
+ when "next"
172
+ options[:marker] = @input[:last_key]
173
+ options[:max_keys] = MAX_KEYS + 1
174
+ when "previous"
175
+ unless @input[:action] == "first"
176
+ options[:marker] = @input[:first_key]
177
+ options[:max_keys] = MAX_KEYS + 1
178
+ end
179
+ else
180
+ options[:max_keys] = MAX_KEYS
181
+ end
182
+
183
+ listing = Config.connection.list_bucket(bucket, options)
184
+ @objs = listing.entries.map { |x| x[1] }
185
+ @objs.sort! { |a,b| a.key <=> b.key }
186
+ @bucket = bucket
187
+
188
+ if @input[:first_key] and @input[:first_key] != @objs.first.key
189
+ if @input[:first_key] == "first"
190
+ @previous_url = navigation_url(bucket)
191
+ else
192
+ @previous_url =
193
+ navigation_url(bucket,
194
+ :first_key => @input[:first_key],
195
+ :last_key => @objs.last.key,
196
+ :action => "previous")
197
+ end
198
+ end
199
+
200
+ if listing.is_truncated
201
+ @next_url =
202
+ navigation_url(bucket,
203
+ :first_key => (@input[:action] ? @objs.first.key : "first"),
204
+ :last_key => @objs.last.key,
205
+ :action => "next")
206
+ end
207
+
208
+ render :bucket
209
+ end
210
+
211
+ private
212
+ def navigation_url(bucket, options={})
213
+ url = "#{R(Buckets, bucket)}/"
214
+ query = options.keys.map { |key| "#{key}=#{CGI.escape(options[key])}" }.join("&")
215
+ url <<"?#{query}" unless query.empty?
216
+ url
217
+ end
218
+ end
219
+
220
+ class DeleteBucket < R '/delete_bucket/(.+)'
221
+ def get(bucket)
222
+ Config.connection.delete_bucket(bucket)
223
+ return redirect(Index)
224
+ end
225
+ end
226
+
227
+ class Delete < R '/delete/(.+?)/(.+)'
228
+ def get(bucket, key)
229
+ @bucket = Config.connection.get_bucket(bucket)
230
+ @bucket.delete(key)
231
+ return redirect(Buckets, bucket)
232
+ end
233
+ end
234
+
235
+ class Details < R '/details/(.+?)/(.+)'
236
+ include ActionView::Helpers::NumberHelper
237
+
238
+ def get(bucket, key)
239
+ @bucket = Config.connection.get_bucket(bucket)
240
+ @obj = @bucket.object(key, :lazy => true)
241
+ @url = @bucket.s3_url(:bucket => bucket,
242
+ :key => key,
243
+ :authenticated => true,
244
+ :access => ChikkenInaBukket::Config.access_key,
245
+ :secret => ChikkenInaBukket::Config.secret_key)
246
+ render :detail
247
+ end
248
+ end
249
+
250
+ class AddFile < R '/add_file/(.+)'
251
+ def get(bucket)
252
+ @bucket = bucket
253
+ render :add_file_form
254
+ end
255
+
256
+ def post(bucket)
257
+ Config.connection.put(@input.File['tempfile'].path,
258
+ :key => @input.File['filename'],
259
+ :bucket => bucket,
260
+ :content_type => @input.File['type'],
261
+ :file => true,
262
+ :render_as_attachment => true)
263
+ redirect R(Buckets, bucket)
264
+ end
265
+ end
266
+
267
+ class Configuration < R '/configuration'
268
+ def get
269
+ render :configuration
270
+ end
271
+
272
+ def post
273
+ open(ENV["HOME"] + "/.chikken_in_a_bukket.yml", "w") do |file|
274
+ file << {
275
+ "access_key_id" => @input[:access_key],
276
+ "secret_access_key" => @input[:secret_key]
277
+ }.to_yaml
278
+ end
279
+ Config.initialize
280
+ return redirect(Index)
281
+ end
282
+ end
283
+ end
284
+
285
+ module ChikkenInaBukket::Views
286
+
287
+ def separator
288
+ span "|", :class => "separator"
289
+ end
290
+
291
+ def config_link
292
+ a "S3 Configuration", :href => R(Configuration)
293
+ end
294
+
295
+ def delete_bucket_link(bucket, *text)
296
+ a (text.first ? text.first : "Delete"),
297
+ :href => R(DeleteBucket, bucket),
298
+ :onclick => "return confirm('Are you sure you want to delete the bucket #{bucket}?');"
299
+ end
300
+
301
+ def layout
302
+ html do
303
+ head do
304
+ title 'Chikken in a Bukket'
305
+ link :rel => 'stylesheet',
306
+ :type => 'text/css',
307
+ :href => '/style.css',
308
+ :media => 'screen'
309
+ end
310
+
311
+ body do
312
+ self << yield
313
+ div :class => 'bucket' do
314
+ img :src => R(BucketImage)
315
+ end
316
+ end
317
+ end
318
+ end
319
+
320
+ def index
321
+ h1 "Welcome to your S3 Storage"
322
+ h2 "Your current buckets are:"
323
+ if @flash
324
+ h3 @flash, :class => 'flash'
325
+ end
326
+ ul do
327
+ @buckets.each do |bucket|
328
+ li do
329
+ a bucket, :href => R(Buckets, bucket)
330
+ span :class => 'delete' do
331
+ delete_bucket_link(bucket, "[Delete]")
332
+ end
333
+ end
334
+ end
335
+ end
336
+
337
+ form :action => "/", :method => "post" do
338
+ fieldset do
339
+ label "Create a new bucket"
340
+ input :type => "text", :name => "bucket", :size => 25, :class => "bucket"
341
+ input :type => "submit", :name => "Submit", :value => "Make it so!"
342
+ end
343
+ end
344
+
345
+ hr
346
+ config_link
347
+ end
348
+
349
+ def bucket
350
+ h1 "Files in bucket #{@bucket}"
351
+ h3 "#{@objs.length} objects in this bucket"
352
+ a "All buckets", :href => R(Index)
353
+ separator
354
+ delete_bucket_link(@bucket, "Delete this bucket")
355
+ separator
356
+ config_link
357
+ separator
358
+ a "Upload a file", :href => R(AddFile, @bucket)
359
+
360
+ ul do
361
+ @objs.each do |f|
362
+ li do
363
+ a "#{f.key} (#{number_to_human_size f.size})",
364
+ :href => R(Details, @bucket, f.key)
365
+ span :class => 'delete' do
366
+ a "[Delete]",
367
+ :href => R(Delete, @bucket, f.key),
368
+ :onclick => "return confirm('Are you sure you want to delete #{f.key}?');"
369
+ end
370
+ end
371
+ end
372
+ end
373
+
374
+ if @previous_url
375
+ a "Back", :href => @previous_url
376
+ end
377
+ separator if @previous_url and @next_url
378
+ if @next_url
379
+ a "More", :href => @next_url
380
+ end
381
+ end
382
+
383
+ def detail
384
+ h1 "Attributes for #{@obj.key}"
385
+ a "All buckets", :href => R(Index)
386
+ separator
387
+ a "Back to #{@bucket.name}", :href => R(Buckets, @bucket.name)
388
+ separator
389
+ config_link
390
+
391
+ ul do
392
+ li "Content-Type: #{@obj.content_type}"
393
+ li "E-Tag: #{@obj.etag}"
394
+ li "Last-Modified: #{@obj.last_modified}"
395
+ li "Size: #{number_to_human_size(@obj.size)}"
396
+ end
397
+ a "Download this file", :href => @url
398
+ separator
399
+ a "Delete this file", :href => R(Delete, @bucket.name, @obj.key), :onclick => "return confirm('Are you sure you want to delete this object?')"
400
+ end
401
+
402
+ def add_file_form
403
+ h1 "Add a new file to #{@bucket}"
404
+ fieldset do
405
+ legend "File to upload"
406
+ form :method => "post", :enctype => "multipart/form-data" do
407
+ input :name => "File", :type => "file", :size => 30
408
+ p { input :type => "submit", :value => "Upload" }
409
+ end
410
+ end
411
+ end
412
+
413
+ def configuration
414
+ h1 "Your S3 Configuration"
415
+ a "Return to top", :href => R(Index)
416
+ p "You're not letting anyone look at this over your shoulder, are you?"
417
+ form :action => R(Configuration),
418
+ :method => "post",
419
+ :onsubmit => "return confirm('Are you sure you want to change these?');" do
420
+
421
+ label "Access Key:", :for => 'access_key'
422
+ input :value => ChikkenInaBukket::Config.access_key,
423
+ :name => "access_key",
424
+ :type => "text",
425
+ :id => "access_key",
426
+ :size => 30
427
+ label "Secret Key", :for => "secret_key"
428
+ input :value => ChikkenInaBukket::Config.secret_key,
429
+ :name => "secret_key",
430
+ :type => "text",
431
+ :id => "secret_key",
432
+ :size => 40
433
+ br
434
+
435
+ p do
436
+ input :type => "submit", :name => "submit", :value => "Change 'em!"
437
+ input :type => "reset", :name => "reset", :value => "Nah, forget it"
438
+ end
439
+ end
440
+ end
441
+ end
442
+
443
+ module ChikkenInaBukket
444
+ BACKGROUND = <<EOF
445
+ R0lGODlhMgAyAOe2AOXl5eXl5ubl5ebl5uXm5eXm5ubm5ebm5ubm5+fm5ufm
446
+ 5+bn5ubn5+fn5ufn5+fn6Ojn5+jn6Ofo5+fo6Ojo5+jo6Ojo6eno6Ono6ejp
447
+ 6Ojp6enp6Onp6enp6urp6erp6unq6enq6urq6erq6urq6+vq6uvq6+rr6urr
448
+ 6+vr6uvr6+vr7Ozr6+zr7Ovs6+vs7Ozs6+zs7Ozs7e3s7O3s7ezt7Ozt7e3t
449
+ 7O3t7e3t7u7t7e7t7u3u7e3u7u7u7e7u7u7u7+/u7u/u7+7v7u7v7+/v7u/v
450
+ 7+/v8PDv7/Dv8O/w7+/w8PDw7/Dw8PDw8fHw8PHw8fDx8PDx8fHx8PHx8fHx
451
+ 8vLx8fLx8vHy8fHy8vLy8fLy8vLy8/Py8vPy8/Lz8vLz8/Pz8vPz8/Pz9PTz
452
+ 8/Tz9PP08/P09PT08/T09PT09fX09PX09fT19PT19fX19PX19fX19vb19fb1
453
+ 9vX29fX29vb29fb29vb29/f29vf29/b39vb39/f39vf39/f3+Pj39/j3+Pf4
454
+ 9/f4+Pj49/j4+Pj4+fn4+Pn4+fj5+Pj5+fn5+Pn5+fn5+vr5+fr5+vn6+fn6
455
+ +vr6+fr6+vr6+/v6+vv6+/r7+vr7+/v7+vv7+/v7/Pz7+/z7/Pv8+/v8/Pz8
456
+ +/z8/Pz8/f38/P38/fz9/Pz9/f39/P39/f39/v79/f79/v3+/f3+/v7+/f7+
457
+ /v7+///+/v/+//7//v7//////v//////////////////////////////////
458
+ ////////////////////////////////////////////////////////////
459
+ ////////////////////////////////////////////////////////////
460
+ ////////////////////////////////////////////////////////////
461
+ ////////////////////////////////////////////////////////////
462
+ /////////////////////ywAAAAAMgAyAAAI/gAFHCggIMCAAgMEEEgIoAAA
463
+ AwYGQiywcIABghcfDghAMICAiwECQEwY4IDFAxEPqFzJsqXLly0XwHTZYAED
464
+ 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
506
+ EOF
507
+
508
+ BUCKET = <<EOF
509
+ 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
623
+ NMtA0w1SmRJlKa12m26vR5LEbG5vY1kWqqGRSolh5dnrDChOznLi9nt4ZW0n
624
+ 3RmMtj7+5w9fGgyHJEmiXs9uDwOa3sBxuhG44o3GVCEKs2rq7T09HLl333Hn
625
+ bVSqE6xfeAER+hRyOZaPnCTLFKIY0ixAU03SJGO6PsNea4fnnz9LqVqh1exT
626
+ ry+hqT7nXtpiarJGp9miPRiR02BqqkDoQd6GD7zvPSwv19lZvYxIY7JeD6Xg
627
+ YKcaUeBSKzoIywIZkQzGaI6DlrOQvk/BsSnUTkAQ0Om4lJ0iG2vXqE5OUTtx
628
+ DAa9fVbVqkxP1JhGgfo0UaOJpqv7a7ZhSD5nY+ULPHn2ORJV4LoumqGzvrnJ
629
+ dDqL0DVm5mbR44RStcQzZ59nsZhnt7XH8vIyTs4kU3QGbsDEwiznL68yffoe
630
+ Jmfn07ULlzMppVIul0u+748B50Ds/HK9ah4ob7RDa7YHpVi+UaYKQPwfP/U/
631
+ /PriTJ3W7jbjfptapcTy/DxJnLK2vsneXpPB0CWJM3zfx3VddE2jVCpgWyo5
632
+ 26JWm9hvu0wkWZqQxCmKIpislogjl0E/YpzA/XfOc2JlkfGgR2NjjaNzc6gy
633
+ Q4QBQqSopRKiVtl/l1Gf8XCAqQgwdISqQBSSBT5C1clVq2RBABIkAqfgQLGA
634
+ 3++zvblFMB6Tn1+E7W2ElFx45TwXz19AVRTGoxF2IYeXxTR6XXabDaSAME4o
635
+ VStMTddZWjnC1PQ0jz35BEIorK6vgSIwbYtTt5xG1S0Us8DVrQa1uUXueOhb
636
+ affGbLc6g7XNLc/3fb3X6325HpU3aGJLbuIRZ68lwcprlTRhqqA6Rb71O9/N
637
+ VquHVShjFkrU6tOkQiGMEqRQsZwclmWRJSkCWF5aYGl+jpnJKseWF3EsHVWm
638
+ VIoWUvoYusRQE04eW+CBb1nh3pMOS3Mz7G1usHruFUyh0trdY9DrE/oBoe+T
639
+ tFrE11YZrl5ic/3afq0a+xB4kCWkcchw0GPc7YA7JnA9yqUSaRKxc20V+kOE
640
+ hNAd44+G0G7SbzUxCkVOnz7NyrEV5pYWyJXyrG9vIVWFFEmGQOgGc0uLzC0t
641
+ kgAvvPQSQlUIoohipcxwPOLue+7lzJ13c9vtZ/j27/xO6gtLPH/hEomqIy0H
642
+ hMC2bWtqarJgGEbuep1qXr8fHtoNWPq6OiW0V2EpgLCmlqxLT306KM8souVL
643
+ NLpD8pbNOIi45dbb6Hb7kKokSYrIJGHgI5MEU1XIYolj24g0RiQBpAGqGjM/
644
+ U8UwLWScYFsKZD55Q9DYXKNSzNFp7BDmbe45cRJNQBj6DFo9wjDAye8v3c3P
645
+ TRPHMZHn4Y9GGIaJqqqYioY7HtHtdLBzBZxiCSEEO1vbhHHC9Pwcs5N1/DAA
646
+ O0f5llugOyC/sIBlmjQaDY6ePsnQ83jiueexcnnyxZB+v4+iKJRKJcrlCs1m
647
+ k729PW6//QytVotquYKuaQghePHFF5k/dppCrYpdKjO7dGSfWKqq5AuFwuzs
648
+ bO3zjz66ex2ww2DqrwPQN9yjdPCXFUD5hV/4+f9NZDG3njrOx//ko/RaTUqF
649
+ IvX6DFJCEie0mi2CwEMmGaN+D1VkjIcdSoU8g34XTdVApmRZwqkTR6lUHOoT
650
+ ZfK2BrGPoUq21zrcddsRji4tcHR5iUsXLhOGIYVikemlJWorRygWHcadNteu
651
+ XkVBkiUJSRyTJjGWaWEUCxhSMhwMSSQMRkOQ+68zHg0xdI1CvkgUBOSKBajX
652
+ IQxAESgSNjc3EJpK9fgxHnn4M9Sqk9xx+x0cWT7CRLWGEAqe69PYa+KOXZCC
653
+ 1aurqEJlOBhh6gY5y2a71eXc+g4Tiyt8+/e8h9a+9IpYqOKTf/mXzRdfeGl4
654
+ PWamBzzf6IB9+OV7cpN2GHmoXn1d8vtXcbU8s1xU7RKLd7+Z933ow+x0eqzv
655
+ 7rLTbLHXaLG9t8vGxjqe52FZBr6f0Gm3IUkRaULs+5Qci7l6lVrJplZzsE3o
656
+ tDfotbeJ/B6hNyQaQ07TmJmcoOwUUIVCEmcMh2O6u7uM1tbobG0RBAG5nEUY
657
+ eJiWTrVcxLFNhExBSjTLplou0+l0OHfu3P6WinKFSrFE7AfEYw+SFG9rh+zs
658
+ WfADiEJYOcKtD95Po9ch7nV5z3veS6lYpNvpEIUhtmXhDoakQUS9OoE7dPni
659
+ 40+wfnWVcX/AoN1FR+Het72d+sQkq+sbvO1d78JeWuLy2ip7vT5+GMSe7385
660
+ c1WuE+vgOMhM5TAWvPquvNd2lFZdGa44IgeIUZyx/tQzPPQjP0pBV/mz/+cP
661
+ 2dzeotdsEwchYSyplkvUa1W8fodKsUCtksMbDogDnyTysWyLyWqBOBggE5/l
662
+ hWm2NtfxgwiZJHz3u45z68nj+GOXq1euEscJUggUVUUKhbHn4o4HJJGHEBn1
663
+ qQksy0Ax9ot9mUpwxyDF/nNFwbBMhoMe7ZbFVH2GQqFAJjOUNEVXVdrNFupg
664
+ REzGtK7C3Ay33HkHimlTSnXauy0GgwFzc3NMHK3hCRchFRRUZqdmae22kLEk
665
+ DVNs22I8GLN77iKWYfM97/l+TjxwP/gBXhRTnahxdXUtDINQHnKRxAEwbzTe
666
+ yIboV0+UVhxhfvnzwonbJ3XpkJzf4K4PfJAf/rG/TzdwabsjgkTFcopMzS4y
667
+ OTNPqTbF5MwcpuWwfX1SWo0maRgwUS6QRSF5y0SmGdVSlcXFZXwPjFyO5154
668
+ kfMXLuF6AUY+T6M35MVXLvDS+Qs0OwNSBIlUcf0I08njBwmjwZA4zRCqQppJ
669
+ 4jRB6Bazc8vcdeZ+DLPAxUtrBEGCMTGFqZnEQUh7Z4dyLo8SRRiZYPvcefwX
670
+ X0E5fhJyDvrRRRZOLGNV8rxy7RKf+fzneOKxx+ltbaP5MfOlCt/x9ndw6pbT
671
+ 1GbnmDtxCiVf4c8efpSZ+WO8+X0fgkTw+c98lsFgQD5np9ubm/7e7l58iHnK
672
+ q7SOfl36fsUNvj0qoP7aT//Ln/6zP/xjTi5XKd91gm+59w4uXdui34KFmRMk
673
+ QrK71+D0rXfywgsv48cxXuAxHARYuopjWli6iWPm2Li2ye5uG8+N6fVd/DjA
674
+ dor4UYxhW+QrFXpeSLPfR6oaumXhRxEpYJgWYZyg6ya6ZTP2fPqjEaaTRzEN
675
+ xoFPkAqc/CyaUaI/8Gh2+mimwc7aBnO33crm+VdwewPyhglxRrfRRiYSmUr0
676
+ 3gi1kKe9ew1RsfjLxx/h6C2nkEnKZK7EpGLjJOBoOpevrRLaJuWVo1zrj3hx
677
+ dZv7Hno3x9//34Fi8fIXnmCn0cLO5UEI/9f+r3+3fXX1mi+ljA+tn4bX20wP
678
+ j/BArE1uEFe/NlB/7n/6+Z9+4mOfYDTcIBvuUZ+b5S3f/X7q+izb2y0a3T0U
679
+ U6fZ6tLu9Vnf3GPl2DKnTp2iWCjQ63bxPQ8pNAZDF6HaKLrJxk6Tbl8iiZme
680
+ myVfKlEolSnVJvHCkHarRa/XJ00TyqUS9ek6s7PTNBotBIIoipGArluESUqU
681
+ pFhWEaHYDN2ARrvF5tYmiqaSphGLU1UGvS6jQQ9dUyGThGFIKjMMy8KwTHQJ
682
+ SRxRn5rG9UKiMCXyEqqlKkqQcfXqVS5vbRCYGjsyZrXf5+gdd/PjP/kzLL/t
683
+ e2Dos/Hcs2w2m6i6ycz8vPzon/757kc/8cmulDK5wbaN6ACQ/gFAgwML6Afr
684
+ VvnVLr19pd+Yd9AyOPupR2i8YqM0+yzd/mbuef8Pcs8PfJgvfeJ3+I9/8Nvs
685
+ bmxR0HWKkxXGscpao4uMfGLXRxUKez2XV853mV8uMb98hJlllTlFIYtDMGy2
686
+ Gm1295rkbBtvNIQkoew4HFtZYrY+gW0a2JpKzjBJopgkTtE0hdCPSJIETdMw
687
+ dJXhuM/2zg5xMiQVAXHmUspXiWVIfWEaVReotoFdyGHV8rhxhKKnhKlH1ozI
688
+ jRSEF3Ekm+DjT36W3d6A9uIiJdthbGj4SkIajpk9eQs/+N3fw9E3PQSxCVfW
689
+ 6V3Z5EsvPoNaKTGzckRubu+O/uCP/rhzg94jeYO9rTezBW+2B1e+7pJmx+/+
690
+ 2K/84i89/2W2/vCH/9uuudN4586LT6ENulw5+xJ+e8RCaR5RqzH3ljv5ru95
691
+ J7ffcYbByOXylTVGYx8visgXK0hFY+QFSNVAsSBCJV+p7XfkC5Vmu02729sv
692
+ Q4BRf4BIExRFMDUxwdEjKxi6TqvZpNftUXDyDAZ9Bv0xQmioqk6aZEhUNN1i
693
+ 5LpsbW1hGCpjd4Q/5ZyDAAAgAElEQVRt2VimiR/ERGHM4tIKYy9AUQ2cUpEg
694
+ ThkHAaqioEud/mqHqOOTmg4vrW7Q9iOafoinCCqLi9x6/3286/3fz9s/+CGq
695
+ iyvQ84ieeoHLn/gcX/r8Fwgtk+LcLIXqZPpPf+4Xr1y6uhrcwDk6KL3+AZYG
696
+ Bzr94zciv6/KVEVVv4Kpx9507Pe2/81//qWLIcwZJqgme89f5mc+/dMsPvhm
697
+ PvRPPsjEHcc5dd99nHrnd8F6g0c/9Zf8xZ9+lNV2i5ySIVSDROh0ghQpMnqX
698
+ r1Gv1wnDEC+SrG41ma0XMWzB4kQdJYkYD/sMxz7bey0ECeP+vmyqus3ubpfx
699
+ 2GN62kA1JWmaEQ6GNJpDfD+ksdVkcXGRyeI0xUKZUq5ENIqRpsLTXzxPs91i
700
+ 5dgxziycpCzy7F58hc1reygYlNQpdne3CMpFNoIYe/Eo88eP8eD99/Hgt78D
701
+ aqX9eU4iuLxN69NPcO4vvoDZiDixsMSWblEoleiORsFzL7zo3YSdN+r/TQ+1
702
+ ir6hVRrtJpILIKaN0m8Byq7fHM/YUxUgK1TLaH5MvVhiY30ddXKasR/y1Isv
703
+ 8Mg/fZpf/OVfYKpQxfYlZqHKQz/6T3joR/4BbK9y9pGHef7pL9LttlH9mGJ1
704
+ ko3NLRi6pGmKbtgMUrDClKjRxRu7lC0DJ2djl8vEqkGaQKzZZEJhHEE/hCBV
705
+ GKcq8SjC8wKazSatVofRWDIcwCDcAUVDbyfk8gHu2EfRVNzApz8Y0I4sktwU
706
+ QpFcXu8xGo2wCgXGwRrF2UVuf8sD/PdveQu333sfzuLiXyemu7vgDknOvsBL
707
+ jzyK3OnxplyNfFXwwuYW9uklDMvm5ctXvRscK5DdZFXmsN/7evbdvOGYyow9
708
+ 5Vz/u7KwvEDBzqN4EUcmZvjYS+e4/T0fYOXd7+RK7zIJKiM35JOf+TxnzjzA
709
+ ZC1iqpqHpVPc9fcWues974XIY7S2xsOffRTtpZdpNFv0ej0aO7uMhtAdu6gp
710
+ VMwxc1MKt91yionyJJ0kYTyMiMKUOBhTSRW23ZgsVYkGMXHXxwsixuOYRl9y
711
+ /JbTOFLBKJTx3JCd3SZJ3ydIEoQCXiQZugpnG1f43PltJqcqlAoFFueXmTq5
712
+ wnd/x9spzc+izizDOASnBrECV6/BxibB+fOsP/8c3u42K6UyJacGux2yzpCp
713
+ ao3YMtFMi9/47d9t3mDvTHYTE/+NAPs19f3+1bdMvPXWuSff/h3bwdpVnJzF
714
+ B37wQ6z88v/Jky88zf23zVIoVjE9yWc+9XmOnnqQS8+dQ/pDbj2+wEw1hyFi
715
+ rLlpCnfezfu+5UHel2Yw9CCKeOyzn6Oxu83alcu09nbYvHye0NBopxreXoeN
716
+ tXXGowE500RIKPQCGo0+iqKS8yR+EKBbNo5TQUw7PNfro+cKWP0B/jBgY7MB
717
+ CCrlSXTbZuXMHdx/4ij1mSmmZie545aTmDN1sPT9xqh0CJa5P60Dn+SFZ9l+
718
+ 6SKDi9cwOn20Xpt5Q8PJVUlaXQJ3EwMFxVYJ1f3uitQw02KhqNxEdg/H1pt1
719
+ 8N/MHuRryX6/IjMzqkXc1RiRKJx/7hmSL3yBk299M0HcJ2/qJKMx3iDmJ37y
720
+ ZzCdPG53h7fffzf/6O//EEVbZf2pp8iXiiB0EgROvsTEzCxv+eCH91MyKffv
721
+ gQ++C65HMh7S63ZoNfYYDAakcchoNLre+5QjXyyjqhqeH+IFPq6SQb1E2x1y
722
+ fO4IBT2Po5rM1RdQFA27Pg05CxQJSgbi+jzKbN+VGnaR167ibe2xt9ZguNVG
723
+ 6cc4EcxnCqVUIfJj7LELWYCmZwhbYXvQIbN05PIcrpKytbUzUjX14Hwe3GZx
724
+ I0Bv1hp6sz02bwjUg01OXxkLCjYeKaW8zWCvw0sXL/L+D72faGgy3Nulkiuj
725
+ Kyb9YYdarkScKXzhyadYu/IyP/2TP46uZ9gyQ8qUcRDT6A65vL4JUtn3bhUV
726
+ TdMolEv7fbWmTsEpUFquMXnsNKgaGBpYFmQZaAZo+n6SLq4bZWoCagShC8KC
727
+ TNmXzkzZb3WRGbRb+0mOP8AbDxj0e4x6XUa9LupwSHEwwvFCSoGgHqmYwkRL
728
+ IrLRAGU8ws4SSENIQsgSQgI8PSMuqegVG3I2jz3x5GBn30E63H90+JyI+FXA
729
+ fbXy5nU3nt1s74YEstxkBU+k6Pk8Ydbik5/+NG/90R9FC4YokUA9sszyynGe
730
+ WWuztrbOu9/xFt773W+nYmfcdusxHn74E1y+fJHvfe8PUEhg5AV0hy5xlKHr
731
+ JpZhouoa13b2iCVoqiBnmRiailAkhqaiGxqKoiClRBEqqq4hFA2hqdi2w4Sh
732
+ oosIWi06jz5FTejgZxBEZK02im0S+C6xkhKREaUxWZzgpAklBGYmcTQVLUoR
733
+ IZCI61+MGDVyQfogYpARpB5kKYGaEqoKac5BL1dQczke/txnh1s7O5EQIpVS
734
+ 3iiWxq8CaHoTs0F+vWLqX0lAdW6aVMBOs4FTLDHoD3H7Y47M1aGukey12Ov0
735
+ KRZL3Pfgg/yz//HHKNkSRw0wlIi3PfAAfhzQ2N1Ed8qgmuRsB+noOLkCpmmR
736
+ ScGpiQXCJEFmKaoAhYxMRqhCoBvqfj+QKtB0E8O20A0LNG1/RAFsb8DIZ/XR
737
+ x9kdekxGkkIqEWGIXSqiRi6qoWKYGpkq0FDRVQ10GwwDDHMftCDYX8lJM5Ap
738
+ KAkYGbguJD5EEZmy37CeCR1pFxFOCWFYVCsV7eLV1ew6oMlNmBod6s5PDrFU
739
+ vpGYqrxOQL8C2Kn5eVRdI4lSCjmH0A14+exLEGTgxfzG7/0eT597mfX1NU4f
740
+ O8ZCvU7e1CnYJu6wS7mQo5y3iYIAmcToikC3THTDQKjq/gkrQQJSRUFHRUdV
741
+ 9X0W6w552yFv50mjmChKCIL93d9JHO7PV5pAHEHegkoRs1YiVSVCS1FkgIEH
742
+ fgvdiNH1GFOPsbUUXYkhiyDyIPT25Xk8AJmApe4PPSWTY6JoQBwPIQ4hSZGp
743
+ gpKaKLKAopQx9Cq6blMqFjRVVQ/38b6a9EY32RWXfT1i6o3i6j6w8/PkLJuq
744
+ 7uBKnWDQ4dzZl3jnm95EksU8/PhjjLOExcVF5uoTbK9fY7KsMxz0MBSFyB+D
745
+ yDh18ijoDoli4acqaaYhURFSwUwFKCYqMRkKChlKJpFZQkKGQOJYNhkpSZoS
746
+ +x4BGY4qEFYOLANEAaoTLN9xJ9fafeKRS4ZENXVIAqJOD2lpCNtEmDk01UYo
747
+ 2n5sTyEVGYqqIJCQpiBjSHyC2CdNXIgCRKagpQKp6qTYpLpBZlfJnAqqk88Q
748
+ oKkqQgiklOkNpDe6CZjJ65Be+UaZ+l/88m6SPAZIJqYpmA7BcIyt6kxXJ8jp
749
+ FlalRn5yCrNWIdBhZ2eHcDTi+C2nKTkW40EHp+hgFR0G3Q6oCmkc4nseaRST
750
+ JPus2z+HISYYucSujwxitDjDACxFIafpOLqOiCJ0KTGEJAt93F4Xr9+FcHzd
751
+ BLUhEhTnj9PwMrY6IxqDMVmqkAQJRrmK6RRRjfz+LgHVBjUHwoZMQy2W9jsX
752
+ yfYz8fGQ2HfJkgBVgpAZUkoyoRCh4+sWrlXAK1QJi2UubG9427t7kaIo8jqg
753
+ NytlohvE1MMbkr/udSqAnNG0BwCNok5cEIRNH1toyKHHlWdfYP3pL1I/vsjs
754
+ 7DzJU89xamWZf/+bv8mZ4zMszZeYXZojGXfQTEEulwPDQfUlBiYYBTJh46Yx
755
+ UbZ/boKmSTIk8npHQxJnpGkMQYamqygScoUcuqahEeGHHoE7xjZUFCGvT0sC
756
+ J5cxp0pokYfhaii5HErgg5cSiYxASxGmwDRiDMMAJSUVkmG/g4LESQSa3Bct
757
+ NU2RMiVNIhxUFBRioSARaKmKqpgMCzk6Wio/+8gXBq12NxyN3fiQhCYHWkJv
758
+ liC94az3jcTU/3JFIDfCvneeQE0pGTZTwoJWi6XFKTS/Ty5TyAsLrzug4tj8
759
+ /u/+No3GNqNRl0QkNNpNXC+EcQoUManhd3VGDUnq5hFJhSjQGA6HSAIKJQPV
760
+ hlEwxE8C0HS8WJIqDt1+QneQEAYKo6HHsNMjDlyIx9DfA9kD2WLqtjqrvVW0
761
+ kkr32vo+NzITQ9hYqoOGgpLGpHGPLGuTiQG2LlBlRhB6BL4LboASZKgx6Ako
762
+ gxBSFUVTUVUVNlrkvICJWxZpeoNUAKqqSPHqpsONjsFLbmA6vO5zH7TXCeZX
763
+ xtW8gpgu4iURqxcvsFBcYt3zodNGmyizsrBE6LooTo5/9BM/zt13HmN6qcq4
764
+ dY1mp40uYLI+w972BqWSxC45lEs5vEDgRQlZpqDrCpNTdXb2rtLZbJEv5nEK
765
+ DhJBkuxvUVRVCYqGYVogNUzfIsMl8kaYROB6ZP0OigXH7zxF+0sLDHaHLDsO
766
+ +CloKRkKmZJdL3HT/W2XaoaMBVoCSgSk+68tFUmmsJ8FxxIqFcatNvp0nTBJ
767
+ cYoFPMtmq9fHU/Wg1WwHY9dNMylf7ZDKV+vxlW/UInwjTD30LTGpzxwl5xQo
768
+ 5x3uOHmMxsYaP/YTP0Ws5XHDEN1SqU4XufXOE0gtZePaZfw4xMjZaLbOXncT
769
+ qXp0RlfZbZyl2X8ZL71CxAZhtkaQ7LC1u0omoFAuIXSNgTek3esQpRGViQpB
770
+ HBCEHp4/YjTuMXb7+L67L9GKitt1CVMTqTpop+7g1G1nGLo+48AHXSFLQuI4
771
+ JE0TZJrtjyQjizKUMENzQwwvwghilEwyMCUDM4U0I0oTBkpAf9Jiyx+QWip7
772
+ aoizMEPVLNJsd/2nz7407Pb60YF4mt2gpHkj4PL1Kmn+S3ClzeTs/lpk3jLw
773
+ 29tMFPI0ByFNN6U2M4dmqDzwtgeoL82iO3lGQcLF1W2eff4ibiioTEyjWgqp
774
+ 4uEmTdxoCzfeJpZNFHOAlU/RbB3LyRPJlLHngqZj5nOMA5e1jXUyMlL2kxWQ
775
+ pDIlzRKiJCSLE2Ilzyg28aXN1jMv8+gTzxIrGtXpGbzRkCSJSNMYmUWILEVI
776
+ BZFJRAIilhAlEMQQRiRxSJBFhDLdb/BWBEOZklUKKFLFKOUZOhqyWoRiPuv1
777
+ R7EfBFmaZvIm8fTVwHy1xfGvK1P/6lsilKWiPbFMvlShWDCJuns4AmLF4a63
778
+ fhefffQx9lpNFo8d47NfeJIraw1O3Ho/k9O38vTZDZ58+gq9kaQ9cAmSmEwL
779
+ CdMBvdEOncEWftghFSGu7zH2Y/w4IVMUEALX88iQzC7ME2cxUmSo+n7XoGEY
780
+ pGlMf9BjY7vBVsOlOnuajz/8BN//oR/n/Oomlalpzl08T256gowUSYyU+7sK
781
+ lEyiZAq6VFBTcX2aY9Iswo8DRBCjRCmpqiJ1HduwMVoxJQy0kytkc1OMNYHH
782
+ vo7HcSxvUOe/GrDpDdZT3/Dhz9pXJ79ISrPodo52Y5fFqXkuuBG9fsTUwkmE
783
+ avKhH/phfvwnfoqZyQnq1WnKxTJvefP9fN97/yF3P3AnQWcTa7iNF3UZDJuM
784
+ /TFCt8gX8khUhgOPlAJZpuB5Kd1hm6uXLvLUU09hGBbvePu3cebMXQRBSBon
785
+ qESMx2OyLMHUVYQqyNcW+NF//L/SGa1jFPJsNDt0Z3xuW16m39jDtHUQKkKm
786
+ yDRBCGX/iHchQEgQGYgMmSUoSYpQJAoCHYgTDTlMMa7zorexTkPRKE+ViEBm
787
+ AqI4vlGLyuF10+RVLME3tDj+RkA93AUuAcT88drZD36gs3X1M1hOjrImcP2U
788
+ f/iP/xmf+PP/wNnnHufXfv13+dgf/QkXX7rChfPXWLvs8+v/9o85emSad3/v
789
+ 23nggVsolvPYOQupjVFUk0K+gqY4uIGkXJ5GM2yUfhvFNJianOXIsZNEYcLx
790
+ 4yeYKNUI/QBLU9G1DCdnksZjdD0lTSz+6I8+x59/7kso1pg3LR7l1mqOgTui
791
+ F4TUDJVMZEgJWbaf+UohEAjI9P3VGzUGJUPLwE4FmSpQMzACSaiCKv5a6Lpr
792
+ 27i3HCesFEhNQ66urXtxnMhXWQxPb3JAVvYaluDX/RylrwjW0jSZnJ0iGw2o
793
+ 56dR04CnHn+SM2fu5tmnn+R//l/+dywlR9GZIMgG1GePUy77nL30NLv/vs1H
794
+ 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
1007
+ EOF
1008
+ end
1009
+
@@ -0,0 +1,154 @@
1
+ require 'rubygems'
2
+ require 'mosquito'
3
+ require File.dirname(__FILE__) + "/../lib/chikken_in_a_bukket"
4
+
5
+ class ObjectStub
6
+ attr_reader :key
7
+
8
+ def initialize(key)
9
+ @key = key
10
+ end
11
+
12
+ def size
13
+ 100
14
+ end
15
+ end
16
+
17
+ class BucketStub
18
+ attr_reader :name, :objects
19
+
20
+ def initialize(name)
21
+ @name = name
22
+ @objects = {}
23
+ end
24
+
25
+ def add_object(key)
26
+ @objects[key] = ObjectStub.new(key)
27
+ end
28
+
29
+ def to_s
30
+ @name
31
+ end
32
+
33
+ end
34
+
35
+ class ConnectionStub
36
+
37
+ def initialize
38
+ @buckets = {}
39
+ end
40
+
41
+ def add_bucket(name)
42
+ bucket = BucketStub.new(name)
43
+ if block_given?
44
+ yield bucket
45
+ end
46
+ @buckets[name] = bucket
47
+ end
48
+
49
+ def bucket_names
50
+ @buckets.keys
51
+ end
52
+
53
+ def create_bucket(name)
54
+ if @buckets.keys.member?(name)
55
+ raise S33r::S3Exception::S3OriginatedException.new('BucketAlreadyExists')
56
+ else
57
+ bucket = BucketStub.new(name)
58
+ @buckets[name] = bucket
59
+ bucket
60
+ end
61
+ end
62
+
63
+ def list_bucket(bucket, options={})
64
+ listing = @buckets[bucket].objects
65
+ class << listing
66
+ def is_truncated
67
+ false
68
+ end
69
+ end
70
+ listing
71
+ end
72
+ end
73
+
74
+ class ChikkenInaBukket::Config
75
+
76
+ @@connection = nil
77
+
78
+ def self.connection
79
+ @@connection
80
+ end
81
+
82
+ def self.connection=(conn)
83
+ @@connection = conn
84
+ end
85
+
86
+ def self.configured=(val)
87
+ @@configured = val
88
+ end
89
+
90
+ end
91
+
92
+ class TestChikkenInaBukket < Camping::FunctionalTest
93
+
94
+ def setup
95
+ super
96
+ @connection = ConnectionStub.new
97
+ ChikkenInaBukket::Config.connection = @connection
98
+
99
+ @connection.add_bucket("bucket1") do |bucket|
100
+ bucket.add_object("key 1")
101
+ bucket.add_object("key 2")
102
+ end
103
+
104
+ @connection.add_bucket("bucket2") do |bucket|
105
+ bucket.add_object("key 3")
106
+ bucket.add_object("key 4")
107
+ end
108
+ end
109
+
110
+ def test_get_slash_no_config_file
111
+ ChikkenInaBukket::Config.configured = false
112
+
113
+ get '/'
114
+ assert_response :redirect
115
+ assert_redirected_to "/configuration"
116
+ end
117
+
118
+ def test_get_slash
119
+ get '/'
120
+ assert_response :success
121
+ assert_match_body /bucket1/
122
+ assert_match_body /bucket2/
123
+ end
124
+
125
+ def test_create_bucket
126
+ post '/', :bucket => "bucket3"
127
+ assert_response :redirect
128
+ assert_redirected_to '/buckets/bucket3'
129
+ end
130
+
131
+ def test_create_bucket_already_exists
132
+ post '/', :bucket => "bucket1"
133
+ assert_response :success
134
+ assert_match_body /Sorry, the bucket bucket1 already exists. Try another name./
135
+ end
136
+
137
+ def test_create_bucket_unknown_error
138
+ class << @connection
139
+ def create_bucket(bucket)
140
+ raise S33r::S3Exception::S3OriginatedException.new('SomeOtherError', 'your error here')
141
+ end
142
+ end
143
+ post '/', :bucket => "bucket3"
144
+ assert_response :success
145
+ assert_match_body /Error your error here/
146
+ end
147
+
148
+ def test_get_buckets
149
+ get '/buckets/bucket1'
150
+ assert_response :success
151
+ assert_match_body /key 1/
152
+ assert_match_body /key 2/
153
+ end
154
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.2
3
+ specification_version: 1
4
+ name: chikkenbukket
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.9.1
7
+ date: 2007-06-08 00:00:00 -07:00
8
+ summary: Simple browser access to S3
9
+ require_paths:
10
+ - lib
11
+ email: alex.vollmer@gmail.com
12
+ homepage: http://chikkenbukket.rubyforge.org
13
+ rubyforge_project: chikkenbukket
14
+ description: Lightweight browser access to your Amazon S3 account
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Alex Vollmer
31
+ files:
32
+ - History.txt
33
+ - Manifest.txt
34
+ - README.txt
35
+ - Rakefile
36
+ - bin/chikken_in_a_bukket
37
+ - lib/chikken_in_a_bukket.rb
38
+ - test/test_chikken_in_a_bukket.rb
39
+ test_files:
40
+ - test/test_chikken_in_a_bukket.rb
41
+ rdoc_options: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ executables:
46
+ - chikken_in_a_bukket
47
+ extensions: []
48
+
49
+ requirements: []
50
+
51
+ dependencies:
52
+ - !ruby/object:Gem::Dependency
53
+ name: s33r
54
+ version_requirement:
55
+ version_requirements: !ruby/object:Gem::Version::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: 0.5.2
60
+ version:
61
+ - !ruby/object:Gem::Dependency
62
+ name: actionpack
63
+ version_requirement:
64
+ version_requirements: !ruby/object:Gem::Version::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 1.13.2
69
+ version:
70
+ - !ruby/object:Gem::Dependency
71
+ name: camping
72
+ version_requirement:
73
+ version_requirements: !ruby/object:Gem::Version::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: "1.5"
78
+ version:
79
+ - !ruby/object:Gem::Dependency
80
+ name: hoe
81
+ version_requirement:
82
+ version_requirements: !ruby/object:Gem::Version::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: 1.2.0
87
+ version: