OpenS3 0.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/bin/opens3 ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'rack'
5
+ require 'opens3/opens3'
6
+ require 'opens3/tools'
7
+ require 'opens3/rack_file'
8
+ require 'json'
9
+ require 'yaml'
10
+ require 'digest/md5'
11
+ require 'trollop'
12
+ require 'uri'
13
+ require 'digest'
14
+
15
+ opts = Trollop::options do
16
+ opt :dir, "Set OpenS3 storage directory", :short => '-d', :type => :string
17
+ opt :port, "Set OpenS3 server port", :short => '-p', :type => :int
18
+ opt :config, "Set config file", :short => '-c', :type => :string
19
+ opt :token, "Set token string", :short => '-t', :type => :string
20
+ end
21
+
22
+ if opts[:dir] and opts[:port] and opts[:token] and !opts[:config]
23
+ @port = opts[:port]
24
+ @dir = opts[:dir]
25
+ @token = opts[:token]
26
+
27
+ elsif !opts[:dir] and !opts[:token] and !opts[:port] and opts[:config]
28
+ unless !File.exists?(opts[:config])
29
+ cfg = YAML::load(File.open(opts[:config]))
30
+ @port = cfg['port']
31
+ @dir = cfg['dir']
32
+ @token = cfg['token']
33
+ end
34
+ end
35
+
36
+ if @port and @dir and @token
37
+ Rack::Handler::Thin.run OpenS3.new(@dir,@token), :Port => @port.to_i
38
+ else
39
+ puts "No port/directory/token or config file specified"
40
+ end
data/lib/opens3.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'opens3/opens3'
2
+ require 'opens3/tools'
3
+ require 'opens3/rack_file'
@@ -0,0 +1,165 @@
1
+ class OpenS3
2
+
3
+ def initialize(path, token=nil)
4
+ @file_path = path
5
+ @srv_token = token ? Digest::SHA512.hexdigest(token) : Digest::SHA512.hexdigest("OpenS3")
6
+ puts "Token: #{@srv_token}"
7
+ end
8
+
9
+ def call(env)
10
+
11
+ handle_url(env)
12
+ end
13
+
14
+ def handle_url(data)
15
+
16
+ req = Rack::Request.new(data)
17
+ @path = req.path
18
+ parsed_query = Rack::Utils.parse_nested_query(req.query_string)
19
+ get_token = parsed_query['token']
20
+ post_token = req.params['token']
21
+ if @path == '/'
22
+ [200, {"Content-Type" => "text/html"}, %{<!DOCTYPE html5><html><head><title></title></head><body><form action="http://localhost:8000/upload" enctype="multipart/form-data" method="post">Select file: <input name="file" type="file" /><br /><input type="text" name="bucket" placeholder="bucket name"/><input type="submit" value="Send" /><input type="text" name="token"></form></body></html>}]
23
+ elsif @path == '/info'
24
+ send_server_info(req)
25
+ else
26
+ if req.post?
27
+ if post_token == @srv_token
28
+ params = req.params['file']
29
+ bucket = req.params['bucket']
30
+ if !params.nil?
31
+ case @path
32
+ when '/upload'
33
+ upload_file(params, bucket)
34
+ else
35
+ send_error(:wrong_path)
36
+ end
37
+ else
38
+ send_error(:no_file)
39
+ end
40
+
41
+ else
42
+ send_error(:token_error)
43
+ end
44
+ elsif req.get?
45
+ if get_token == @srv_token
46
+ case @path
47
+
48
+ when '/file'
49
+ download_file(req.query_string)
50
+ when '/list'
51
+ send_file_list(req.query_string)
52
+
53
+ else
54
+ send_error(:wrong_path)
55
+ end
56
+ else
57
+ send_error(:token_error)
58
+ end
59
+ end
60
+
61
+
62
+ end
63
+
64
+ end
65
+
66
+ def upload_file(params, bucket)
67
+ if bucket.nil? or bucket.empty?
68
+ send_error(:bucket_not_specified)
69
+ else
70
+
71
+ f = RackFile.new(params[:tempfile], params[:filename], params[:type], bucket, @file_path).save
72
+ if f
73
+ @response = {:saved=>true, :url=>URI.escape("/file?name=#{params[:filename]}&bucket=#{bucket}")}
74
+ [200, {"Content-Type" => "application/json"}, "#{@response.to_json}"]
75
+ else
76
+ send_error(:file_already_exists)
77
+ end
78
+
79
+ end
80
+
81
+ end
82
+
83
+ def send_file_list(bucket)
84
+ query = Rack::Utils.parse_nested_query(bucket)
85
+ if query['bucket'].nil?
86
+ send_error(:bucket_not_specified)
87
+ else
88
+ if Dir.exists?("#{@file_path}/#{query['bucket']}")
89
+ files = Dir["#{@file_path}/#{query['bucket']}/*/"].map { |a| File.basename(a) }
90
+ file_names = Array.new
91
+ files.each do |d|
92
+ meta = YAML::load(File.open("#{@file_path}/#{query['bucket']}/#{d}/meta"))
93
+ file_names.push(meta['filename'])
94
+ end
95
+ [200, {"Content-Type" => "application/json"}, "#{file_names.to_json}"]
96
+ else
97
+ send_error(:bucket_not_found)
98
+ end
99
+ end
100
+
101
+ end
102
+
103
+ def download_file(query)
104
+
105
+ query = Rack::Utils.parse_nested_query(query)
106
+ file_name = query['name']
107
+ expiry = Time.at(query['expire'].to_i)
108
+ if expiry < Time.now or expiry.nil?
109
+ send_error(:expired_link)
110
+ else
111
+ if query['bucket'].nil?
112
+ send_error(:bucket_not_specified)
113
+ else
114
+ if !query['name'].nil?
115
+ if Dir.exists?("#{@file_path}/#{query['bucket']}")
116
+ files = Dir["#{@file_path}/#{query['bucket']}/*/"].map { |a| File.basename(a) }
117
+ files.each do |d|
118
+ meta = YAML::load(File.open("#{@file_path}/#{query['bucket']}/#{d}/meta"))
119
+ if meta['filename'] == file_name
120
+ @good_folder = d
121
+ @good_meta = meta
122
+ end
123
+ end
124
+ if @good_folder.nil?
125
+ send_error(:file_not_found)
126
+ else
127
+ [200, {"Content-Type" => "#{@good_meta['type']}; charset=UTF-8", "Content-Disposition" => "attachment; filename=#{@good_meta['filename']}"}, File.open("#{@file_path}/#{query['bucket']}/#{@good_folder}/content")]
128
+ end
129
+ else
130
+ send_error(:file_not_found)
131
+ end
132
+ else
133
+ [200, {"Content-Type" => "application/json"}, "#{{:error=>true}.to_json}"]
134
+ end
135
+ end
136
+ end
137
+
138
+ end
139
+
140
+ def send_error(type)
141
+ case type
142
+ when :wrong_path
143
+ [404, {"Content-Type" => "application/json"}, "#{{:error=>true, :type=>100}.to_json}"]
144
+ when :file_not_found
145
+ [404, {"Content-Type" => "application/json"}, "#{{:error=>true, :type=>101}.to_json}"]
146
+ when :file_already_exists
147
+ [200, {"Content-Type" => "application/json"}, "#{{:error=>true, :type=>102}.to_json}"]
148
+ when :bucket_not_found
149
+ [404, {"Content-Type" => "application/json"}, "#{{:error=>true, :type=>103}.to_json}"]
150
+ when :bucket_not_specified
151
+ [400, {"Content-Type" => "application/json"}, "#{{:error=>true, :type=>104}.to_json}"]
152
+ when :expired_link
153
+ [200, {"Content-Type" => "application/json"}, "#{{:error=>true, :type=>105}.to_json}"]
154
+ when :token_error
155
+ [403, {"Content-Type" => "application/json"}, "#{{:error=>true, :type=>106}.to_json}"]
156
+ when :no_file
157
+ [200, {"Content-Type" => "application/json"}, "#{{:error=>true, :type=>107}.to_json}"]
158
+ end
159
+ end
160
+
161
+ def send_server_info(request)
162
+ [200, {"Content-Type" => "application/json"}, "#{{:hostname=>request.host_with_port}.to_json}"]
163
+ end
164
+ end
165
+
@@ -0,0 +1,30 @@
1
+ class RackFile
2
+ def initialize(temp_file, filename, type, bucket, path)
3
+ @temp_file = temp_file.path
4
+ @filename = filename
5
+ @type = type
6
+ @bucket = bucket
7
+ @path = path
8
+ end
9
+
10
+ def save
11
+ begin
12
+ key = String.new.random_string
13
+ file_md5 = Digest::MD5.hexdigest(@temp_file)
14
+ folder_name = Digest::MD5.hexdigest("#{@file_md5}-#{Time.now}-#{key}")
15
+ path = "#{@path}/#{@bucket}/#{@filename}"
16
+ FileUtils.mkdir_p(path)
17
+ meta = Hash.new
18
+ meta['type']= @type
19
+ meta['md5'] = file_md5
20
+ meta['filename'] = @filename
21
+ meta = meta.to_yaml
22
+ File.open("#{path}/meta", 'w') do |out|
23
+ out.write(meta)
24
+ end
25
+ FileUtils.mv(@temp_file, "#{path}/content")
26
+ rescue SystemCallError
27
+ false
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,5 @@
1
+ class String
2
+ def random_string
3
+ (0...8).map{65.+(rand(25)).chr}.join
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: OpenS3
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Pablo Merino
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-21 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: json
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rack
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: trollop
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Build your own storage server
63
+ email: pablo.perso1995@gmail.cin
64
+ executables:
65
+ - opens3
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - lib/opens3/opens3.rb
70
+ - lib/opens3/rack_file.rb
71
+ - lib/opens3/tools.rb
72
+ - lib/opens3.rb
73
+ - !binary |-
74
+ YmluL29wZW5zMw==
75
+ homepage: https://github.com/pablo-merino/opens3
76
+ licenses: []
77
+ post_install_message:
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubyforge_project: nowarning
95
+ rubygems_version: 1.8.21
96
+ signing_key:
97
+ specification_version: 3
98
+ summary: A storage server
99
+ test_files: []