Class: Calligraphy::FileResource

Inherits:
Resource
  • Object
show all
Includes:
Utils
Defined in:
lib/calligraphy/resource/file_resource.rb

Overview

Resource responsible for writing and deleting directories and files to disk.

Constant Summary collapse

DAV_PROPERTY_METHODS =
%w[
  creationdate displayname getcontentlanguage getcontentlength
  getcontenttype getetag getlastmodified lockdiscovery resourcetype
  supportedlock
].freeze

Constants included from Utils

Utils::FALSE_VALUES, Utils::TRUE_VALUES

Instance Attribute Summary

Attributes inherited from Resource

#client_nonce, #contents, #full_request_path, #mount_point, #request_body, #request_path, #root_dir, #updated_at

Instance Method Summary collapse

Methods included from Utils

#extract_lock_token, #false?, #join_paths, #lockentry_hash, #map_array_of_hashes, #obj_exists_and_is_not_type?, #split_and_pop, #true?

Methods inherited from Resource

#dav_compliance, #readable?

Constructor Details

#initialize(resource: nil, req: nil, mount: nil, root_dir: Dir.pwd) ⇒ FileResource

:nodoc:



17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/calligraphy/resource/file_resource.rb', line 17

def initialize(resource: nil, req: nil, mount: nil, root_dir: Dir.pwd)
  super

  @src_path = join_paths @root_dir, @request_path

  if exists?
    @name = File.basename @src_path
    init_pstore
    set_file_stats
  end

  set_ancestors
end

Instance Method Details

#ancestor_exist?Boolean

Responsible for returning a boolean value indicating if an ancestor exists for the resource.

Used in COPY and MKCOL requests.

Returns:

  • (Boolean)


35
36
37
# File 'lib/calligraphy/resource/file_resource.rb', line 35

def ancestor_exist?
  File.exist? @ancestor_path
end

#collection?Boolean

Responsible for returning a boolean value indicating if the resource is a collection.

Used in DELETE, MKCOL, MOVE, and PUT requests.

Returns:

  • (Boolean)


43
44
45
# File 'lib/calligraphy/resource/file_resource.rb', line 43

def collection?
  File.directory? @src_path
end

#copy(options) ⇒ Object

Responsible for creating a duplicate of the resource in ‘options` (see section 9.8 of RFC4918).

Used in COPY and MOVE (which inherits from COPY) requests.



72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/calligraphy/resource/file_resource.rb', line 72

def copy(options)
  destination = copy_destination options
  to_path = join_paths @root_dir, destination
  to_path_exists = File.exist? to_path

  preserve_existing = false? options[:overwrite]

  copy_resource_to_path to_path, preserve_existing
  copy_pstore_to_path to_path, preserve_existing

  to_path_exists
end

#copy_options(options) ⇒ Object

Responsible for returning a hash with keys indicating if the resource can be copied, if an ancestor exists, or if the copy destinatin is locked.

Return hash should contain ‘can_copy`, `ancestor_exist`, and `locked` keys with boolean values.

Used in COPY and MOVE (which inherits from COPY) requests.



55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/calligraphy/resource/file_resource.rb', line 55

def copy_options(options)
  copy_options = { can_copy: false, ancestor_exist: false, locked: false }

  destination = copy_destination options
  to_path = join_paths @root_dir, destination
  to_path_exists = File.exist? to_path

  copy_options[:ancestor_exist] = File.exist? parent_path destination
  copy_options[:locked] = can_copy_locked_option to_path, to_path_exists
  copy_options = can_copy_option copy_options, options, to_path_exists
  copy_options
end

#create_collectionObject

Responsible for creating a new collection based on the resource (see section 9.3 of RFC4918).

Used in MKCOL requests.



89
90
91
# File 'lib/calligraphy/resource/file_resource.rb', line 89

def create_collection
  Dir.mkdir @src_path
end

#delete_collectionObject

Responsible for deleting a resource collection (see section 9.6 of RFC4918).

Used in DELETE and MOVE requests.



97
98
99
100
# File 'lib/calligraphy/resource/file_resource.rb', line 97

def delete_collection
  FileUtils.rm_r @src_path
  FileUtils.rm_r @store_path if store_exist?
end

#etagObject

Responsible for returning unique identifier used to create an etag.

Used in precondition validation, as well as GET, HEAD, and PROPFIND requests.



106
107
108
# File 'lib/calligraphy/resource/file_resource.rb', line 106

def etag
  [@updated_at.to_i, @stats[:inode], @stats[:size]].join('-').to_s
end

#exists?Boolean

Responsible for indicating if the resource already exists.

Used in DELETE, LOCK, MKCOL, and MOVE requests.

Returns:

  • (Boolean)


113
114
115
# File 'lib/calligraphy/resource/file_resource.rb', line 113

def exists?
  File.exist? @src_path
end

#lock(nodes, depth = 'infinity') ⇒ Object

Responsible for creating a lock on the resource (see section 9.10 of RFC4918).

Used in LOCK requests.



121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/calligraphy/resource/file_resource.rb', line 121

def lock(nodes, depth = 'infinity')
  properties = {}

  nodes.each do |node|
    next unless node.is_a? Nokogiri::XML::Element
    properties[node.name.to_sym] = node
  end

  create_blank_file unless exists?

  create_lock properties, depth
  fetch_lock_info
end

#lock_is_exclusive?Boolean

Responsible for indicating if a resource lock is exclusive.

Used in LOCK requests.

Returns:

  • (Boolean)


138
139
140
# File 'lib/calligraphy/resource/file_resource.rb', line 138

def lock_is_exclusive?
  lockscope == 'exclusive'
end

#locked?Boolean

Responsible for indicating if a resource is current locked.

Used in LOCK requests.

Returns:

  • (Boolean)


145
146
147
148
149
# File 'lib/calligraphy/resource/file_resource.rb', line 145

def locked?
  fetch_lock_info

  obj_exists_and_is_not_type? obj: @lock_info, type: []
end

#locked_to_user?(headers = nil) ⇒ Boolean

Responsible for indicating if a resource is locked to the current user.

Used in DELETE, LOCK, MOVE, PROPPATCH, and PUT requests.

Returns:

  • (Boolean)


154
155
156
157
158
159
160
# File 'lib/calligraphy/resource/file_resource.rb', line 154

def locked_to_user?(headers = nil)
  if locked?
    !can_unlock? headers
  else
    locking_ancestor? @ancestor_path, @ancestors.dup, headers
  end
end

#propfind(nodes) ⇒ Object

Responsible for handling the retrieval of properties defined on the resource (see section 9.1 of RFC4918).

Used in PROPFIND requests.



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

def propfind(nodes)
  properties = { found: [], not_found: [] }

  nodes.each do |node|
    node.children.each do |prop|
      next unless prop.is_a? Nokogiri::XML::Element

      value = get_property prop

      update_found_properties properties, prop, value
    end
  end

  properties
end

#proppatch(nodes) ⇒ Object

Responsible for handling the addition and/or removal of properties defined on the resource through a PROPPATCH request (see section 9.2 of RFC4918).

Used in PROPPATCH requests.



187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/calligraphy/resource/file_resource.rb', line 187

def proppatch(nodes)
  actions = { set: [], remove: [] }

  @store.transaction do
    @store[:properties] = {} unless @store[:properties].is_a? Hash

    add_remove_properties nodes, actions
  end

  get_custom_property nil
  actions
end

#readObject

Responsible for setting and returning the contents of a resource if it is readable (see section 9.4 of RFC4918).

Used in GET requests.



204
205
206
# File 'lib/calligraphy/resource/file_resource.rb', line 204

def read
  @contents ||= File.read @src_path if readable?
end

#refresh_lockObject

Responsible for refreshing locks (see section 9.10.2 of RFC4918).

Used in LOCK requests.



211
212
213
214
215
216
217
218
219
220
221
# File 'lib/calligraphy/resource/file_resource.rb', line 211

def refresh_lock
  if locked?
    @store.transaction do
      @store[:lockdiscovery][-1][:timeout] = timeout_node
    end

    fetch_lock_info
  else
    refresh_ancestor_locks @ancestor_path, @ancestors.dup
  end
end

#unlock(token) ⇒ Object

Responsible for unlocking a resource lock (see section 9.11 of RFC4918).

Used in UNLOCK requests.



226
227
228
229
230
231
232
233
234
235
# File 'lib/calligraphy/resource/file_resource.rb', line 226

def unlock(token)
  if lock_tokens.include? token
    remove_lock token
    @lock_info = nil

    :no_content
  else
    :forbidden
  end
end

#write(contents = @request_body.to_s) ⇒ Object

Responsible for writing contents to a resource (see section 9.7 of RFC4918).

Used in PUT requests.



241
242
243
244
245
246
247
# File 'lib/calligraphy/resource/file_resource.rb', line 241

def write(contents = @request_body.to_s)
  @contents = contents

  File.open(@src_path, 'w') do |file|
    file.write @contents
  end
end