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 +1 -0
- data/LICENSE +20 -0
- data/README +45 -0
- data/Rakefile +38 -0
- data/lib/mongrel_send_file/init.rb +44 -0
- data/resources/defaults.yml +2 -0
- data/tools/rakehelp.rb +105 -0
- metadata +69 -0
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
|
+
|
data/Rakefile
ADDED
@@ -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
|
data/tools/rakehelp.rb
ADDED
@@ -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:
|