chikkenbukket 0.9.1

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