ignore XML tags that are not in DAV: namespace
[pandav-og.git] / fsdav.py
blobf28852526e9463e913a7bf25d85cdeeca7ea3747
1 # Copyright (c) 2005.-2006. Ivan Voras <ivoras@gmail.com>
2 # Released under the Artistic License
4 from member import Member
5 from collection import *
6 import os.path, os
7 import md5
8 import dircache
9 from util import *
10 import mimetypes
13 class FileMember(Member):
15 def __init__(self, name, parent):
16 self.name = name
17 self.parent = parent
18 self.name = name
19 self.fsname = parent.fsname + name # e.g. '/var/www/mysite/some.txt'
20 self.virname = parent.virname + name # e.g. '/mysite/some.txt'
21 self.type = Member.M_MEMBER
23 assert(type(self.name) == unicode)
24 assert(type(self.fsname) == unicode)
25 assert(type(self.virname) == unicode)
27 def __str__(self):
28 return "%s -> %s" % (self.virname, self.fsname)
30 def getProperties(self):
31 """Return dictionary with WebDAV properties. Values shold be
32 formatted according to the WebDAV specs."""
33 st = os.stat(self.fsname)
34 p = {}
35 p['creationdate'] = unixdate2iso8601(st.st_ctime)
36 p['getlastmodified'] = unixdate2httpdate(st.st_mtime)
37 if self.type == Member.M_COLLECTION:
38 p['displayname'] = self.name.strip(u"/").split('/')[-1]
39 else:
40 p['displayname'] = self.name
41 p['getetag'] = md5.new(self.fsname.encode("utf-8")).hexdigest()
42 #p['resourcetype'] = None
43 if self.type == Member.M_MEMBER:
44 p['getcontentlength'] = st.st_size
45 p['getcontenttype'], z = mimetypes.guess_type(self.name)
46 p['getcontentlanguage'] = None
47 if self.name[0] == ".":
48 p['ishidden'] = 1
49 if not os.access(self.fsname, os.W_OK):
50 p['isreadonly'] = 1
51 if self.name == '/':
52 p['isroot'] = 1
53 return p
56 def sendData(self, wfile):
57 """Send the file to the client. Literally."""
58 st = os.stat(self.fsname)
59 f = file(self.fsname, 'rb')
60 writ = 0
61 while writ < st.st_size:
62 buf = f.read(65536)
64 if len(buf) == 0: # eof?
65 break
67 writ += len(buf)
68 wfile.write(buf)
69 f.close()
73 class DirCollection(FileMember, Collection):
75 COLLECTION_MIME_TYPE = 'httpd/unix-directory'
77 def __init__(self, fsdir, virdir, parent=None):
78 if not os.path.exists(fsdir):
79 raise "Local directory (fsdir) not found: " + fsdir
80 assert( type(fsdir) == unicode )
81 assert( type(virdir) == unicode )
82 self.fsname = fsdir
83 self.name = virdir
85 if self.fsname[-1] != os.sep:
86 if self.fsname[-1] == '/': # fixup win/dos/mac separators
87 self.fsname = self.fsname[:-1] + os.sep
88 else:
89 self.fsname += os.sep
91 self.virname = virdir
92 if self.virname[-1] != '/':
93 self.virname += '/'
95 self.parent = parent
96 self.type = Member.M_COLLECTION
99 def getProperties(self):
100 p = FileMember.getProperties(self) # inherit file properties
101 p['iscollection'] = 1
102 p['getcontenttype'] = DirCollection.COLLECTION_MIME_TYPE
103 return p
106 def getMembers(self):
107 """Get immediate members of this collection."""
108 dircache.reset() # workaround to make sure we also get very recently created files
109 l = dircache.listdir(self.fsname)[:] # obtain a copy of dirlist
110 dircache.annotate(self.fsname, l)
111 r = []
112 for f in l:
113 if f[-1] != '/':
114 m = FileMember(f, self) # Member is a file
115 else:
116 m = DirCollection(self.fsname + f, self.virname + f, self) # Member is a collection
117 r.append(m)
118 return r
121 def findMember(self, name):
122 """Search for a particular member."""
123 dircache.reset() # workaround to make sure we also get very recently created files
124 l = dircache.listdir(self.fsname)[:] # obtain a copy of dirlist
125 dircache.annotate(self.fsname, l)
126 #print "%s - %s, find %s" % (self.fsname, repr(l), name)
128 if name in l:
129 if name[-1] != '/':
130 return FileMember(name, self)
131 else:
132 return DirCollection(self.fsname + name, self.virname + name, self)
133 elif name[-1] != '/':
134 name += '/'
135 if name in l:
136 return DirCollection(self.fsname + name, self.virname + name, self)
139 def sendData(self, wfile):
140 """Send "file" to the client. Since this is a directory, build some arbitrary HTML."""
141 memb = self.getMembers()
142 data = '<html><head><title>%s</title></head><body>' % self.virname
143 data += '<table><tr><th>Name</th><th>Size</th><th>Timestamp</th></tr>'
144 for m in memb:
145 p = m.getProperties()
146 if 'getcontentlength' in p:
147 p['size'] = int(p['getcontentlength'])
148 p['timestamp'] = p['getlastmodified']
149 else:
150 p['size'] = 0
151 p['timestamp'] = '-DIR-'
152 data += '<tr><td>%s</td><td>%d</td><td>%s</td></tr>' % (p['displayname'], p['size'], p['timestamp'])
153 data += '</table></body></html>'
154 wfile.write(data)
157 def recvMember(self, rfile, name, size, req):
158 """Receive (save) a member file"""
159 fname = os.path.join(self.fsname, name)
160 f = file(fname, 'wb')
161 writ = 0
162 bs = 65536
163 while True:
164 if size != -1 and (bs > size-writ):
165 bs = size-writ
166 buf = rfile.read(bs)
167 if len(buf) == 0:
168 break
169 f.write(buf)
170 writ += len(buf)
171 if size != -1 and writ >= size:
172 break
173 f.close()
175 def createSubCollection (self, name):
176 dname = os.path.join(self.fsname, name)
178 if os.path.exists(dname):
179 raise CollectionExistsError
181 print "creating new folder '%s'" % dname
182 try:
183 os.mkdir(dname)
184 except OSError, e:
185 raise CollectionError, str(e)