mongrel_crypted_download 0.4

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/COPYING ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2008 Andriy Bazyuta
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the "Software"),
5
+ to deal in the Software without restriction, including without limitation
6
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
7
+ and/or sell copies of the Software, and to permit persons to whom the
8
+ Software is furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included
11
+ in all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2008 Andriy Bazyuta
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the "Software"),
5
+ to deal in the Software without restriction, including without limitation
6
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
7
+ and/or sell copies of the Software, and to permit persons to whom the
8
+ Software is furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included
11
+ in all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README ADDED
@@ -0,0 +1,69 @@
1
+ == Mongrel_crypted_download GemPlugin
2
+ IMPORTANT!!
3
+ Required encrypted_strings plugin http://agilewebdevelopment.com/plugins/encrypted_strings
4
+
5
+ The need to send secured files in a fast and reliable way is common.
6
+
7
+ Sending a file from inside of a web application can be slow
8
+ and also utilizes an entire application thread/process until the user
9
+ is done downloading the file. Also is crypt path by encrypted_strings plugin http://agilewebdevelopment.com/plugins/encrypted_strings
10
+
11
+
12
+
13
+ <uri-prefix> is a directory that does not exist in the directory structure of the application but does
14
+ exist in the directory structure of the server.
15
+ example: /download_file
16
+
17
+ <relative-path> is the crypted by encrypted_strings plugin path to the file.
18
+ example: /public/attachments/
19
+
20
+ <file-name> is the name of file without path.
21
+
22
+ <timestamp> is the number of seconds since epoch until the time when this download expires
23
+ example (in ruby on rails): 1.minute.from_now.to_i.to_s
24
+
25
+ <token> is the SHA1 hash of the concatenation of the following items:
26
+
27
+
28
+ To use the plugin you need to do the following:
29
+
30
+ 1) setup the handler within a configuration script and pass in the secret string.
31
+
32
+ example configuration script:
33
+
34
+ uri "/download_file", :handler => plugin('/handlers/crypteddownload')
35
+
36
+ 2) In your application, form a secured URI by creating the proper parameters and
37
+ perform an SHA1 hash of the parameters to create the proper token
38
+
39
+ example code (ruby on rails):
40
+
41
+ @track = Track.find(params[:id])
42
+ @attachment = Attachment.find(params[:id])
43
+
44
+ url = CryptedDownload.generate(@attachment.filename, "/public"+@attachment.public_filename.gsub(/#{@attachment.filename}/, ''), "/download_files", request)
45
+
46
+ redirect_to url
47
+
48
+
49
+ 3) Start mongel by passing in the location of the configuration script from step 1 with the -S command
50
+ line switch
51
+
52
+ example:
53
+
54
+ mongrel_rails start -S config/mongrel_crypted_download.conf
55
+
56
+
57
+ Error messages
58
+
59
+ If any of the parameters in the URI or the secret_string are missing
60
+ the handler returns a 500 Application Error.
61
+
62
+ If the token passed in as a parameter does not match the token generated
63
+ by the handler (if someone tries to guess the token) the handler returns
64
+ a 403 Forbidden error.
65
+
66
+ If the timestamp is earlier than the current server time, meaning that the file is
67
+ no longer a valid download then the handler returns a 408 Request Time-out Error.
68
+ This error is not technically correct but it makes the most sense in the context of
69
+ the handler.
@@ -0,0 +1,38 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/clean'
4
+ require 'rake/gempackagetask'
5
+ require 'rake/rdoctask'
6
+ require 'tools/rakehelp'
7
+ require 'fileutils'
8
+ include FileUtils
9
+
10
+ setup_tests
11
+ setup_clean ["pkg", "lib/*.bundle", "*.gem", ".config"]
12
+
13
+ setup_rdoc ['README', 'LICENSE', 'COPYING', 'lib/**/*.rb', 'doc/**/*.rdoc']
14
+
15
+ desc "Does a full compile, test run"
16
+ task :default => [:test, :package]
17
+
18
+ version="0.4"
19
+ name="mongrel_crypted_download"
20
+
21
+ setup_gem(name, version) do |spec|
22
+ spec.summary = "Mongrel Crypted Download Plugin"
23
+ spec.description = spec.summary
24
+ spec.author="Andriy Bazyuta"
25
+ spec.add_dependency('gem_plugin', '>= 0.2.1')
26
+ spec.add_dependency('mongrel', '>= 0.3.13')
27
+ spec.files += Dir.glob("resources/**/*")
28
+ end
29
+
30
+
31
+ task :install => [:test, :package] do
32
+ sh %{sudo gem install pkg/#{name}-#{version}.gem}
33
+ end
34
+
35
+ task :uninstall => [:clean] do
36
+ sh %{sudo gem uninstall #{name}}
37
+ end
38
+
@@ -0,0 +1,62 @@
1
+ require 'gem_plugin'
2
+ require 'mongrel'
3
+ require 'digest/sha1'
4
+
5
+ class CryptedDownload < GemPlugin::Plugin "/handlers"
6
+ include Mongrel::HttpHandlerPlugin
7
+
8
+ def process(request, response)
9
+ query = Mongrel::HttpRequest.query_parse(request.params['QUERY_STRING'])
10
+ cookies = Mongrel::HttpRequest.query_parse(request.params['HTTP_COOKIE'])
11
+ secret_string = cookies.keys.first
12
+
13
+ query['path'] = CGI::unescape(query['path'])
14
+
15
+ if secret_string.nil? or query['token'].nil? or query['timestamp'].nil? or query['path'].nil?
16
+ response.start(500){}
17
+ elsif query['timestamp'].to_i < Time.now.to_i
18
+ response.start(408){}
19
+ elsif query['token'] == Digest::SHA1.hexdigest("#{secret_string}#{query['path']}#{query['timestamp']}").to_s
20
+ send_file(File.expand_path("." + query['path'].decrypt(:symmetric, :key => secret_string) + query['file-name']), response)
21
+ else
22
+ response.start(403){}
23
+ end
24
+ end
25
+
26
+ def self.generate(file_name, path, uri_prefix, request)
27
+ secret_string = request.cookies.keys.first
28
+
29
+ path = path.encrypt(:symmetric, :key => secret_string)
30
+ timestamp = 1.minute.from_now.to_i.to_s
31
+ token = Digest::SHA1.hexdigest(secret_string + path + timestamp)
32
+ path = CGI::escape(path)
33
+
34
+ return "#{uri_prefix}/?token=#{token}&path=#{path}&file-name=#{file_name}&timestamp=#{timestamp}"
35
+
36
+ end
37
+
38
+
39
+
40
+ private
41
+
42
+ # Sends the contents of a file back to the user.
43
+ def send_file(path, response)
44
+ # first we setup the headers and status then we do a very fast send on the socket directly
45
+ file_status = File.stat(path)
46
+
47
+ response.status = 200
48
+ # Set the last modified times as well and etag for all files
49
+ response.header[Mongrel::Const::LAST_MODIFIED] = file_status.mtime.httpdate
50
+ # Calculated the same as apache, not sure how well the works on win32
51
+ response.header[Mongrel::Const::ETAG] = Mongrel::Const::ETAG_FORMAT % [file_status.mtime.to_i, file_status.size, file_status.ino]
52
+ #set the content type to something generic for now
53
+ response.header[Mongrel::Const::CONTENT_TYPE] = @default_content_type
54
+ #set the content disposition and filename
55
+ response.header['Content-Disposition'] = "attachment; filename=\"#{File.basename(path)}\""
56
+
57
+ # send a status with out content length
58
+ response.send_status(file_status.size)
59
+ response.send_header
60
+ response.send_file(path)
61
+ end
62
+ end
@@ -0,0 +1,2 @@
1
+ ---
2
+ :debug: false
@@ -0,0 +1,105 @@
1
+
2
+ def make(makedir)
3
+ Dir.chdir(makedir) do
4
+ sh(PLATFORM =~ /win32/ ? 'nmake' : 'make')
5
+ end
6
+ end
7
+
8
+
9
+ def extconf(dir)
10
+ Dir.chdir(dir) do ruby "extconf.rb" end
11
+ end
12
+
13
+
14
+ def setup_tests
15
+ Rake::TestTask.new do |t|
16
+ t.libs << "test"
17
+ t.test_files = FileList['test/test*.rb']
18
+ t.verbose = true
19
+ end
20
+ end
21
+
22
+
23
+ def setup_clean otherfiles
24
+ files = ['build/*', '**/*.o', '**/*.so', '**/*.a', 'lib/*-*', '**/*.log'] + otherfiles
25
+ CLEAN.include(files)
26
+ end
27
+
28
+
29
+ def setup_rdoc files
30
+ Rake::RDocTask.new do |rdoc|
31
+ rdoc.rdoc_dir = 'doc/rdoc'
32
+ rdoc.options << '--line-numbers'
33
+ rdoc.rdoc_files.add(files)
34
+ end
35
+ end
36
+
37
+
38
+ def setup_extension(dir, extension)
39
+ ext = "ext/#{dir}"
40
+ ext_so = "#{ext}/#{extension}.#{Config::CONFIG['DLEXT']}"
41
+ ext_files = FileList[
42
+ "#{ext}/*.c",
43
+ "#{ext}/*.h",
44
+ "#{ext}/extconf.rb",
45
+ "#{ext}/Makefile",
46
+ "lib"
47
+ ]
48
+
49
+ task "lib" do
50
+ directory "lib"
51
+ end
52
+
53
+ desc "Builds just the #{extension} extension"
54
+ task extension.to_sym => ["#{ext}/Makefile", ext_so ]
55
+
56
+ file "#{ext}/Makefile" => ["#{ext}/extconf.rb"] do
57
+ extconf "#{ext}"
58
+ end
59
+
60
+ file ext_so => ext_files do
61
+ make "#{ext}"
62
+ cp ext_so, "lib"
63
+ end
64
+ end
65
+
66
+
67
+ def base_gem_spec(pkg_name, pkg_version)
68
+ pkg_version = pkg_version
69
+ pkg_name = pkg_name
70
+ pkg_file_name = "#{pkg_name}-#{pkg_version}"
71
+ Gem::Specification.new do |s|
72
+ s.name = pkg_name
73
+ s.version = pkg_version
74
+ s.platform = Gem::Platform::RUBY
75
+ s.has_rdoc = true
76
+ s.extra_rdoc_files = [ "README" ]
77
+
78
+ s.files = %w(COPYING LICENSE README Rakefile) +
79
+ Dir.glob("{bin,doc/rdoc,test,lib}/**/*") +
80
+ Dir.glob("ext/**/*.{h,c,rb}") +
81
+ Dir.glob("examples/**/*.rb") +
82
+ Dir.glob("tools/*.rb")
83
+
84
+ s.require_path = "lib"
85
+ s.extensions = FileList["ext/**/extconf.rb"].to_a
86
+ s.bindir = "bin"
87
+ end
88
+ end
89
+
90
+ def setup_gem(pkg_name, pkg_version)
91
+ spec = base_gem_spec(pkg_name, pkg_version)
92
+ yield spec if block_given?
93
+
94
+ Rake::GemPackageTask.new(spec) do |p|
95
+ p.gem_spec = spec
96
+ p.need_tar = true
97
+ end
98
+ end
99
+
100
+ def setup_win32_gem(pkg_name, pkg_version)
101
+ spec = base_gem_spec(pkg_name, pkg_version)
102
+ yield spec if block_given?
103
+
104
+ Gem::Builder.new(spec).build
105
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mongrel_crypted_download
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.4"
5
+ platform: ruby
6
+ authors:
7
+ - Andriy Bazyuta
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-06-19 00:00:00 +03:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: gem_plugin
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.2.1
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: mongrel
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: 0.3.13
32
+ version:
33
+ description: Mongrel Crypted Download Plugin
34
+ email:
35
+ executables: []
36
+
37
+ extensions: []
38
+
39
+ extra_rdoc_files:
40
+ - README
41
+ files:
42
+ - COPYING
43
+ - LICENSE
44
+ - README
45
+ - Rakefile
46
+ - lib/mongrel_crypted_download
47
+ - lib/mongrel_crypted_download/init.rb
48
+ - tools/rakehelp.rb
49
+ - resources/defaults.yaml
50
+ has_rdoc: true
51
+ homepage:
52
+ post_install_message:
53
+ rdoc_options: []
54
+
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: "0"
62
+ version:
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ version:
69
+ requirements: []
70
+
71
+ rubyforge_project:
72
+ rubygems_version: 0.9.5
73
+ signing_key:
74
+ specification_version: 2
75
+ summary: Mongrel Crypted Download Plugin
76
+ test_files: []
77
+