mongrel_send_file 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/COPYING ADDED
@@ -0,0 +1 @@
1
+ No copying restrictions/license given.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2005 Rick Olson
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,45 @@
1
+ == mongrel_send_file GemPlugin
2
+
3
+ This is a simple plugin to handle the sending of secure files from a rails app. Here's the typical process:
4
+
5
+ - Rails app authorizes user to download file
6
+ - Rails app sets file info in the session, redirects to custom URL like /file/UNIQUE_HASH/filename
7
+ - Mongrel handler pulls the full filename path and content type from the session using the unique hash, sends it to the user
8
+
9
+ == Usage
10
+
11
+ After installing the gem, you'll need to setup the handler for your Rails app:
12
+
13
+ # config/mongrel_send_file.conf
14
+ uri "/file/", :handler => plugin("/handlers/sendfile", :session_key => '_my_session_id', :session_files_key => :files), :in_front => true
15
+
16
+ # rails action that sends the file
17
+ def download
18
+ # do whatever it is you do to find get the filename/content type
19
+ @attachment = Attachment.find(params[:id])
20
+
21
+ # this doesn't matter as long as it's unique
22
+ filehash = Digest::SHA1.hexdigest( Time.now.to_s.split('//').sort_by { rand }.join )
23
+
24
+ # initialize session. Use the :session_files_key option here
25
+ session[:files] ||= {}
26
+
27
+ # set the value for this file with a 5 minute expiration time
28
+ session[:files][filehash] = [5.minutes.from_now.to_i, @attachment.full_filename, @attachment.content_type]
29
+
30
+ # redirect to the path served by mongrel_send_file
31
+ redirect_to "/file/#{filehash}/#{@attachment.filename}"
32
+ end
33
+
34
+ # startup mongrel with this command
35
+ mongrel_rails -S config/mongrel_send_file.conf
36
+
37
+ == Note
38
+
39
+ I wrote this for a couple Rails apps that use the SqlSessionStore plugin [1]. So, it's very opinionated about how
40
+ it gets the info from the session. This app should work with any app that runs on Mongrel (not just rails), just monkey
41
+ patch the SendFile#find_session method. Submit suggestions as patches if you have them too.
42
+
43
+ [1] - http://railsexpress.de/blog/articles/2006/09/15/sqlsessionstore-now-available-as-a-plugin
44
+
45
+
@@ -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', 'lib/**/*.rb']
14
+
15
+ desc "Does a full compile, test run"
16
+ task :default => [:test, :package]
17
+
18
+ version = "0.1"
19
+ name = "mongrel_send_file"
20
+
21
+ setup_gem(name, version) do |spec|
22
+ spec.summary = "The mongrel_send_file GemPlugin"
23
+ spec.description = spec.summary
24
+ spec.author = "Nobody"
25
+ spec.add_dependency('mongrel', '>= 0.3.13.4')
26
+ spec.add_dependency('gem_plugin', '>= 0.2.1')
27
+ spec.files += Dir.glob("resources/**/*")
28
+ end
29
+
30
+
31
+ task :install => [:test, :package] do
32
+ sh %{gem install pkg/#{name}-#{version}.gem}
33
+ end
34
+
35
+ task :uninstall => [:clean] do
36
+ sh %{gem uninstall #{name}}
37
+ end
38
+
@@ -0,0 +1,44 @@
1
+ require 'mongrel'
2
+ require 'gem_plugin'
3
+ require 'digest/sha1'
4
+ class SendFile < GemPlugin::Plugin "/handlers"
5
+ include Mongrel::HttpHandlerPlugin
6
+
7
+ def process(request, response)
8
+ files = find_session(request)
9
+ files.each do |hash, args|
10
+ files.delete(hash) if args.first < Time.now.utc.to_i
11
+ end
12
+
13
+ pieces = request.params['PATH_INFO'].split('/')
14
+ pieces.pop # filename
15
+ hash = pieces.pop
16
+ if files[hash].nil?
17
+ response.start(404){}
18
+ else
19
+ send_file(files[hash][1], files[hash][2], response)
20
+ end
21
+ end
22
+
23
+ protected
24
+ def send_file(filename, content_type, response)
25
+ file_status = File.stat(filename)
26
+ response.status = 200
27
+ # Set the last modified times as well and etag for all files
28
+ response.header[Mongrel::Const::LAST_MODIFIED] = file_status.mtime.httpdate
29
+ # Calculated the same as apache, not sure how well the works on win32
30
+ response.header[Mongrel::Const::ETAG] = Mongrel::Const::ETAG_FORMAT % [file_status.mtime.to_i, file_status.size, file_status.ino]
31
+ # set the content type to something generic for now
32
+ response.header[Mongrel::Const::CONTENT_TYPE] = content_type
33
+ # send a status with out content length
34
+ response.send_status(file_status.size)
35
+ response.send_header
36
+ response.send_file(filename)
37
+ end
38
+
39
+ def find_session(request)
40
+ cookie = Mongrel::HttpRequest.query_parse(request.params['HTTP_COOKIE'])
41
+ session = SqlSessionStore.session_class.find_session(cookie[@options[:session_key]])
42
+ Marshal.load(Base64.decode64(session.data))[@options[:session_files_key] || :files]
43
+ end
44
+ 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,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11
3
+ specification_version: 1
4
+ name: mongrel_send_file
5
+ version: !ruby/object:Gem::Version
6
+ version: "0.1"
7
+ date: 2006-10-16 00:00:00 -05:00
8
+ summary: The mongrel_send_file GemPlugin
9
+ require_paths:
10
+ - lib
11
+ email:
12
+ homepage:
13
+ rubyforge_project:
14
+ description: The mongrel_send_file GemPlugin
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
+ authors:
29
+ - Nobody
30
+ files:
31
+ - COPYING
32
+ - LICENSE
33
+ - README
34
+ - Rakefile
35
+ - lib/mongrel_send_file
36
+ - lib/mongrel_send_file/init.rb
37
+ - tools/rakehelp.rb
38
+ - resources/defaults.yml
39
+ test_files: []
40
+
41
+ rdoc_options: []
42
+
43
+ extra_rdoc_files:
44
+ - README
45
+ executables: []
46
+
47
+ extensions: []
48
+
49
+ requirements: []
50
+
51
+ dependencies:
52
+ - !ruby/object:Gem::Dependency
53
+ name: mongrel
54
+ version_requirement:
55
+ version_requirements: !ruby/object:Gem::Version::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: 0.3.13.4
60
+ version:
61
+ - !ruby/object:Gem::Dependency
62
+ name: gem_plugin
63
+ version_requirement:
64
+ version_requirements: !ruby/object:Gem::Version::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 0.2.1
69
+ version: