Skip to content

Commit

Permalink
Patch to work with Passengers' file upload behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
peakpg committed Mar 2, 2011
1 parent 7aa8284 commit adf8465
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 2 deletions.
2 changes: 2 additions & 0 deletions README.rdoc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ For more information on WebDAV see: http://en.wikipedia.org/wiki/WebDAV
* Users must have 'Administer CMS' permissions in order to access resources via WebDAV.
* Users can use their normal cms username and password.

Note: Currently this module is tested to work on Passenger and Mongrel. Other rack servers may work, but implementations for file upload differ slightly.

=== Clients

In order to take advantage of this module, users will need a WebDAV client. Many FTP clients will support this, including:
Expand Down
26 changes: 24 additions & 2 deletions lib/bcms_webdav/resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,13 @@ def get(request, response)

# Handle uploading file.
def put(request, response)
temp_file = extract_tempfile(request)

temp_file = request.body
add_rails_like_methods(temp_file)

section = find_section_for(path)

file_block = FileBlock.new(:name=>path, :attachment_file=>request.body, :attachment_section => section, :attachment_file_path=>path, :publish_on_save=>true)
file_block = FileBlock.new(:name=>path, :attachment_file=>temp_file, :attachment_section => section, :attachment_file_path=>path, :publish_on_save=>true)
unless file_block.save
log "Couldn't save file."
file_block.errors.each do |error|
Expand All @@ -154,6 +154,28 @@ def find_section_for(path)

private

# Different webservers have slightly different behavior for uploaded files.
# 1. Webrick/mongrel - body is a TempFile
# 2. Passenger - body is a PhusionPassenger::Utils::RewindableInput
#
# Until Rails 3, which may have a consistent middleware for extracting a Tempfile, we have to do it this way.
def extract_tempfile(request)
input = request.body
if input
# Handle Mongrel
return input if input.is_a?(Tempfile)

# Handle Passenger
# This is highly brittle and terrible.
if input.respond_to?(:make_rewindable, true)
input.size # Force creation of Tempfile
return input.instance_variable_get(:@rewindable_io)
end
end


end

def log_exists(type, path)
log "Resource of type '#{type}' with path '#{path}' exists."
end
Expand Down
27 changes: 27 additions & 0 deletions test/unit/web_dav_resource_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ def teardown

end


test 'users with administrate permissions can access resources' do
mock_user = mock()
User.expects(:authenticate).with("abc", "123").returns(mock_user)
Expand Down Expand Up @@ -292,9 +293,35 @@ def setup
test "parse missing slash section" do
path = Bcms::WebDAV::Path.new('test.jpg')
assert_equal "test.jpg", path.file_name
end

test "extract tempfile from mongrel style requests" do
tempfile = Tempfile.new("testing")
@request.expects(:body).returns(tempfile)

assert_equal tempfile, @resource.send(:extract_tempfile, @request)

end

test "extract tempfile from passenger style requests" do
class FakeRewindable
def size
@rewindable_io = 'EXPECTED'
end
private

# Matches passengers rewindable input signature
def make_rewindable
'do nothing'
end
end

rewindable_input = FakeRewindable.new
@request.expects(:body).returns(rewindable_input)

assert_equal 'EXPECTED', @resource.send(:extract_tempfile, @request)
end

private
def resource_for(path)
Bcms::WebDAV::Resource.new(path, path, @request, @response, {})
Expand Down

0 comments on commit adf8465

Please sign in to comment.