Class: RackDAV::FileResource

Inherits:
Resource show all
Includes:
WEBrick::HTTPUtils
Defined in:
lib/rack_dav/file_resource.rb

Instance Attribute Summary

Attributes inherited from Resource

#options, #path

Instance Method Summary collapse

Methods inherited from Resource

#==, #child, #descendants, #display_name, #get_property, #initialize, #lockable?, #name, #parent, #property_names, #remove_property, #set_property

Constructor Details

This class inherits a constructor from RackDAV::Resource

Instance Method Details

#childrenObject

If this is a collection, return the child resources.



10
11
12
13
14
# File 'lib/rack_dav/file_resource.rb', line 10

def children
  Dir[file_path + '/*'].map do |path|
    child File.basename(path)
  end
end

#collection?Boolean

Is this resource a collection?

Returns:

  • (Boolean)


17
18
19
# File 'lib/rack_dav/file_resource.rb', line 17

def collection?
  File.directory?(file_path)
end

#content_lengthObject

Return the size in bytes for this resource.



65
66
67
# File 'lib/rack_dav/file_resource.rb', line 65

def content_length
  stat.size
end

#content_typeObject

Return the mime type of this resource.



56
57
58
59
60
61
62
# File 'lib/rack_dav/file_resource.rb', line 56

def content_type
  if stat.directory?
    "text/html"
  else
    mime_type(file_path, DefaultMimeTypes)
  end
end

#copy(dest) ⇒ Object

HTTP COPY request.

Copy this resource to given destination resource.



138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/rack_dav/file_resource.rb', line 138

def copy(dest)
  if stat.directory?
    dest.make_collection
  else
    open(file_path, "rb") do |file|
      dest.write(file)
    end

    list_custom_properties.each do |prop|
      dest.set_custom_property(prop, get_custom_property(prop))
    end
  end
end

#creation_dateObject

Return the creation time.



27
28
29
# File 'lib/rack_dav/file_resource.rb', line 27

def creation_date
  stat.ctime
end

#deleteObject

HTTP DELETE request.

Delete this resource.



127
128
129
130
131
132
133
# File 'lib/rack_dav/file_resource.rb', line 127

def delete
  if stat.directory?
    Dir.rmdir(file_path)
  else
    File.unlink(file_path)
  end
end

#etagObject

Return an Etag, an unique hash value for this resource.



42
43
44
# File 'lib/rack_dav/file_resource.rb', line 42

def etag
  sprintf('%x-%x-%x', stat.ino, stat.size, stat.mtime.to_i)
end

#exist?Boolean

Does this recource exist?

Returns:

  • (Boolean)


22
23
24
# File 'lib/rack_dav/file_resource.rb', line 22

def exist?
  File.exist?(file_path)
end

#getObject

HTTP GET request.

Write the content of the resource to the response.body.



94
95
96
97
98
99
100
101
102
103
104
# File 'lib/rack_dav/file_resource.rb', line 94

def get
  if stat.directory?
    content = ""
    Rack::Directory.new(root).call(@request.env)[2].each { |line| content << line }
    @response.body = [content]
    @response['Content-Length'] = (content.respond_to?(:bytesize) ? content.bytesize : content.size).to_s
  else
    file = File.open(file_path)
    @response.body = file
  end
end

#get_custom_property(name) ⇒ Object

Raises:

  • (HTTPStatus::NotFound)


81
82
83
84
85
# File 'lib/rack_dav/file_resource.rb', line 81

def get_custom_property(name)
  value = xattr["rack_dav:#{name}"]
  raise HTTPStatus::NotFound if value.nil?
  value
end

#last_modifiedObject

Return the time of last modification.



32
33
34
# File 'lib/rack_dav/file_resource.rb', line 32

def last_modified
  stat.mtime
end

#last_modified=(time) ⇒ Object

Set the time of last modification.



37
38
39
# File 'lib/rack_dav/file_resource.rb', line 37

def last_modified=(time)
  File.utime(Time.now, time, file_path)
end

#list_custom_propertiesObject



87
88
89
# File 'lib/rack_dav/file_resource.rb', line 87

def list_custom_properties
  xattr.list.select { |a| a.start_with?('rack_dav') }.map { |a| a.sub(/^rack_dav:/, '') }
end

#make_collectionObject

HTTP MKCOL request.

Create this resource as collection.



163
164
165
# File 'lib/rack_dav/file_resource.rb', line 163

def make_collection
  Dir.mkdir(file_path)
end

#move(dest) ⇒ Object

HTTP MOVE request.

Move this resource to given destination resource.



155
156
157
158
# File 'lib/rack_dav/file_resource.rb', line 155

def move(dest)
  copy(dest)
  delete
end

#postObject

HTTP POST request.

Usually forbidden.

Raises:

  • (HTTPStatus::Forbidden)


120
121
122
# File 'lib/rack_dav/file_resource.rb', line 120

def post
  raise HTTPStatus::Forbidden
end

#putObject

HTTP PUT request.

Save the content of the request.body.



109
110
111
112
113
114
115
# File 'lib/rack_dav/file_resource.rb', line 109

def put
  if @request.env['HTTP_CONTENT_MD5']
    content_md5_pass?(@request.env) or raise HTTPStatus::BadRequest.new('Content-MD5 mismatch')
  end

  write(@request.body)
end

#resource_typeObject

Return the resource type.

If this is a collection, return a collection element



49
50
51
52
53
# File 'lib/rack_dav/file_resource.rb', line 49

def resource_type
  if collection?
    Nokogiri::XML::fragment('<D:collection xmlns:D="DAV:"/>').children.first
  end
end

#set_custom_property(name, value) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
# File 'lib/rack_dav/file_resource.rb', line 69

def set_custom_property(name, value)
  if value.nil? || value.empty?
    begin
      xattr.remove("rack_dav:#{name}")
    rescue Errno::ENOATTR
      # If the attribute being deleted doesn't exist, just do nothing
    end
  else
    xattr["rack_dav:#{name}"] = value
  end
end

#write(io) ⇒ Object

Write to this resource from given IO.



168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/rack_dav/file_resource.rb', line 168

def write(io)
  tempfile = "#{file_path}.#{Process.pid}.#{object_id}"

  open(tempfile, "wb") do |file|
    while part = io.read(8192)
      file << part
    end
  end

  File.rename(tempfile, file_path)
ensure
  File.unlink(tempfile) rescue nil
end