Skip to content

Commit ff062cb

Browse files
author
Martin Larralde
committed
Make sure WebDAVFS.validatepath is called in every public method
1 parent b1ef3dc commit ff062cb

File tree

1 file changed

+76
-84
lines changed

1 file changed

+76
-84
lines changed

webdavfs/webdavfs.py

Lines changed: 76 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from contextlib import closing
1+
# coding: utf-8
2+
23
import io
34
import os
45
import six
@@ -35,21 +36,24 @@ def __init__(self, wdfs, path, mode):
3536
self.path = path
3637
self.res = self.fs.get_resource(self.path)
3738
self.mode = mode
38-
self._mode = Mode(mode)
3939
self._lock = threading.RLock()
4040
self.data = self._get_file_data()
4141

4242
self.pos = 0
4343

44-
if 'a' in mode:
45-
self.pos = self._get_data_size()
44+
if self.mode.appending:
45+
self.pos = self.__length_hint__()
46+
if self.mode.writing:
47+
self.write(b'')
48+
if self.mode.reading:
49+
self.read(0)
4650

4751
def _get_file_data(self):
4852
with self._lock:
4953
data = io.BytesIO()
5054
try:
5155
self.res.write_to(data)
52-
if 'a' not in self.mode:
56+
if not self.mode.appending:
5357
data.seek(io.SEEK_SET)
5458
except we.RemoteResourceNotFound:
5559
data.write(b'')
@@ -65,7 +69,7 @@ def __length_hint__(self):
6569

6670
def __repr__(self):
6771
_repr = "WebDAVFile({!r}, {!r}, {!r})"
68-
return _repr.format(self.fs, self.path, self.mode)
72+
return _repr.format(self.fs, self.path, self.mode.to_platform_bin())
6973

7074
def close(self):
7175
if not self.closed:
@@ -75,7 +79,7 @@ def close(self):
7579
self.data.close()
7680

7781
def flush(self):
78-
if self._mode.writing:
82+
if self.mode.writing:
7983
log.debug("flush")
8084
self.data.seek(io.SEEK_SET)
8185
self.res.read_from(self.data)
@@ -84,10 +88,10 @@ def readline(self, size=-1):
8488
return next(line_iterator(self, None if size==-1 else size))
8589

8690
def readable(self):
87-
return self._mode.reading
91+
return self.mode.reading
8892

8993
def read(self, size=-1):
90-
if not self._mode.reading:
94+
if not self.mode.reading:
9195
raise IOError("File is not in read mode")
9296
self.pos = self.pos + size if size != -1 else self.__length_hint__()
9397
return self.data.read(size)
@@ -123,10 +127,10 @@ def truncate(self, size=None):
123127
return size or data_size
124128

125129
def writable(self):
126-
return self._mode.writing
130+
return self.mode.writing
127131

128132
def write(self, data):
129-
if not self._mode.writing:
133+
if not self.mode.writing:
130134
raise IOError("File is not in write mode")
131135
bytes_written = self.data.write(data)
132136
self.seek(bytes_written, Seek.current)
@@ -192,44 +196,46 @@ def _create_info_dict(info):
192196

193197
return info_dict
194198

195-
def isdir(self, path):
196-
try:
197-
return self.client.is_dir(path)
198-
except we.RemoteResourceNotFound:
199-
return False
199+
def create(self, path, wipe=False):
200+
with self._lock:
201+
if not wipe and self.exists(path):
202+
return False
203+
with self.openbin(path, 'wb') as new_file:
204+
new_file.truncate(0)
205+
return True
200206

201207
def exists(self, path):
202-
return self.client.check(path)
208+
_path = self.validatepath(path)
209+
return self.client.check(_path)
203210

204211
def getinfo(self, path, namespaces=None):
205212
_path = self.validatepath(path)
206213
namespaces = namespaces or ()
207214

208215
if _path in '/':
209-
return Info({
210-
"basic":
211-
{
216+
info_dict = {
217+
"basic": {
212218
"name": "",
213219
"is_dir": True
214220
},
215-
"details":
216-
{
217-
"type": int(ResourceType.directory)
221+
"details": {
222+
"type": ResourceType.directory
218223
}
219-
})
220-
221-
try:
222-
info = self.client.info(path)
223-
info_dict = self._create_info_dict(info)
224-
if self.isdir(path):
225-
info_dict['basic']['is_dir'] = True
226-
info_dict['details']['type'] = ResourceType.directory
227-
return Info(info_dict)
228-
except we.RemoteResourceNotFound as exc:
229-
raise errors.ResourceNotFound(path, exc=exc)
224+
}
225+
226+
else:
227+
try:
228+
info = self.client.info(_path)
229+
info_dict = self._create_info_dict(info)
230+
if self.client.is_dir(_path):
231+
info_dict['basic']['is_dir'] = True
232+
info_dict['details']['type'] = ResourceType.directory
233+
except we.RemoteResourceNotFound as exc:
234+
raise errors.ResourceNotFound(path, exc=exc)
235+
236+
return Info(info_dict)
230237

231238
def listdir(self, path):
232-
self.check()
233239
_path = self.validatepath(path)
234240

235241
if not self.getinfo(_path).is_dir:
@@ -239,10 +245,9 @@ def listdir(self, path):
239245
return map(six.u, dir_list) if six.PY2 else dir_list
240246

241247
def makedir(self, path, permissions=None, recreate=False):
242-
self.validatepath(path)
243-
_path = abspath(normpath(path))
248+
_path = self.validatepath(path)
244249

245-
if _path == '/':
250+
if _path in '/':
246251
if not recreate:
247252
raise errors.DirectoryExists(path)
248253

@@ -259,90 +264,77 @@ def makedir(self, path, permissions=None, recreate=False):
259264
def openbin(self, path, mode='r', buffering=-1, **options):
260265
_mode = Mode(mode)
261266
_mode.validate_bin()
262-
self.validatepath(path)
267+
_path = self.validatepath(path)
263268

264269
log.debug("openbin: %s, %s", path, mode)
265270
with self._lock:
266271
try:
267-
info = self.getinfo(path)
272+
info = self.getinfo(_path)
268273
log.debug("Info: %s", info)
269274
except errors.ResourceNotFound:
270-
if _mode.reading:
275+
if not _mode.create:
271276
raise errors.ResourceNotFound(path)
272277
else:
273278
if info.is_dir:
274279
raise errors.FileExpected(path)
275280
if _mode.exclusive:
276281
raise errors.FileExists(path)
277-
wdfile = WebDAVFile(self, abspath(normpath(path)), mode)
278-
return wdfile
282+
return WebDAVFile(self, _path, _mode)
279283

280284
def remove(self, path):
281-
if not self.exists(path):
282-
raise errors.ResourceNotFound(path)
283-
285+
_path = self.validatepath(path)
284286
if self.getinfo(path).is_dir:
285287
raise errors.FileExpected(path)
286-
287-
self.client.clean(path)
288+
self.client.clean(_path)
288289

289290
def removedir(self, path):
290-
if path == '/':
291-
raise errors.RemoveRootError
292-
293-
if not self.exists(path):
294-
raise errors.ResourceNotFound(path)
295-
296-
if not self.isdir(path):
291+
_path = self.validatepath(path)
292+
if path in '/':
293+
raise errors.RemoveRootError()
294+
if not self.getinfo(path).is_dir:
297295
raise errors.DirectoryExpected(path)
298-
299-
checklist = self.client.list(path)
300-
if checklist:
296+
if not self.isempty(_path):
301297
raise errors.DirectoryNotEmpty(path)
302-
303-
self.client.clean(path)
298+
self.client.clean(_path)
304299

305300
def setbytes(self, path, contents):
306301
if not isinstance(contents, bytes):
307302
raise ValueError('contents must be bytes')
308-
_path = abspath(normpath(path))
309-
self.validatepath(path)
303+
_path = self.validatepath(path)
310304
bin_file = io.BytesIO(contents)
311305
with self._lock:
312306
resource = self._create_resource(_path)
313307
resource.read_from(bin_file)
314308

315309
def setinfo(self, path, info):
316-
if not self.exists(path):
310+
_path = self.validatepath(path)
311+
if not self.exists(_path):
317312
raise errors.ResourceNotFound(path)
318313

319-
def create(self, path, wipe=False):
320-
with self._lock:
321-
if not wipe and self.exists(path):
322-
return False
323-
with self.open(path, 'wb') as new_file:
324-
# log.debug("CREATE %s", new_file)
325-
new_file.truncate(0)
326-
return True
327-
328314
def copy(self, src_path, dst_path, overwrite=False):
315+
_src_path = self.validatepath(src_path)
316+
_dst_path = self.validatepath(dst_path)
317+
329318
with self._lock:
330-
if not overwrite and self.exists(dst_path):
319+
if not overwrite and self.exists(_dst_path):
331320
raise errors.DestinationExists(dst_path)
332321
try:
333-
self.client.copy(src_path, dst_path)
334-
except we.RemoteResourceNotFound:
335-
raise errors.ResourceNotFound(src_path)
336-
except we.RemoteParentNotFound:
337-
raise errors.ResourceNotFound(dst_path)
322+
self.client.copy(_src_path, _dst_path)
323+
except we.RemoteResourceNotFound as exc:
324+
raise errors.ResourceNotFound(src_path, exc=exc)
325+
except we.RemoteParentNotFound as exc:
326+
raise errors.ResourceNotFound(dst_path, exc=exc)
338327

339328
def move(self, src_path, dst_path, overwrite=False):
340-
if not overwrite and self.exists(dst_path):
329+
_src_path = self.validatepath(src_path)
330+
_dst_path = self.validatepath(dst_path)
331+
332+
if not overwrite and self.exists(_dst_path):
341333
raise errors.DestinationExists(dst_path)
342334
with self._lock:
343335
try:
344-
self.client.move(src_path, dst_path, overwrite=overwrite)
345-
except we.RemoteResourceNotFound:
346-
raise errors.ResourceNotFound(src_path)
347-
except we.RemoteParentNotFound:
348-
raise errors.ResourceNotFound(dst_path)
336+
self.client.move(_src_path, _dst_path, overwrite=overwrite)
337+
except we.RemoteResourceNotFound as exc:
338+
raise errors.ResourceNotFound(src_path, exc=exc)
339+
except we.RemoteParentNotFound as exc:
340+
raise errors.ResourceNotFound(dst_path, exc=exc)

0 commit comments

Comments
 (0)