1 # -*- coding: utf-8 -*-
2 ##############################################################################
4 # OpenERP, Open Source Management Solution
5 # Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
6 # Copyright (c) 1999 Christian Scholz (ruebe@aachen.heimat.de)
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU Affero General Public License as
10 # published by the Free Software Foundation, either version 3 of the
11 # License, or (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU Affero General Public License for more details.
18 # You should have received a copy of the GNU Affero General Public License
19 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 ##############################################################################
23 import xml.dom.minidom
24 domimpl = xml.dom.minidom.getDOMImplementation()
25 from xml.dom.minicompat import StringTypes
33 from DAV.propfind import PROPFIND
34 from DAV.report import REPORT
36 raise osv.except_osv('PyWebDAV Import Error!','Please install PyWebDAV \
37 from http://code.google.com/p/pywebdav/downloads/detail?name=PyWebDAV-0.9.4.tar.gz&can=2&q=/')
41 class Text2(xml.dom.minidom.Text):
42 def writexml(self, writer, indent="", addindent="", newl=""):
43 data = "%s%s%s" % (indent, self.data, newl)
44 data = data.replace("&", "&").replace("<", "<")
45 data = data.replace(">", ">")
48 def createText2Node(doc, data):
49 if not isinstance(data, StringTypes):
50 raise TypeError, "node contents must be a string"
57 super_mk_prop_response = PROPFIND.mk_prop_response
58 def mk_prop_response(self, uri, good_props, bad_props, doc):
59 """ make a new <prop> result element
61 We differ between the good props and the bad ones for
62 each generating an extra <propstat>-Node (for each error
66 re=doc.createElement("D:response")
67 # append namespaces to response
69 namespaces = self.namespaces[:]
70 if 'DAV:' in namespaces:
71 namespaces.remove('DAV:')
72 for nsname in namespaces:
73 re.setAttribute("xmlns:ns"+str(nsnum),nsname)
76 def _prop_child(xnode, ns, prop, value):
77 """Append a property xml node to xnode, with <prop>value</prop>
79 And a little smarter than that, it will consider namespace and
80 also allow nested properties etc.
82 :param ns the namespace of the <prop/> node
83 :param prop the name of the property
84 :param value the value. Can be:
86 tuple ('elem', 'ns') for empty sub-node <ns:elem />
87 tuple ('elem', 'ns', sub-elems) for sub-node with elements
88 tuple ('elem', 'ns', sub-elems, {attrs}) for sub-node with
89 optional elements and attributes
95 ns_prefix="ns"+str(namespaces.index(ns))+":"
97 pe=doc.createElement(ns_prefix+str(prop))
98 if hasattr(value, '__class__') and value.__class__.__name__ == 'Element':
101 if ns == 'DAV:' and prop=="resourcetype" and isinstance(value, int):
104 ve=doc.createElement("D:collection")
107 _prop_elem_child(pe, ns, value, ns_prefix)
109 xnode.appendChild(pe)
111 def _prop_elem_child(pnode, pns, v, pns_prefix):
113 if isinstance(v, list):
115 _prop_elem_child(pnode, pns, vit, pns_prefix)
116 elif isinstance(v,tuple):
119 ns_prefix = pns_prefix
122 elif v[1] in namespaces:
123 ns_prefix="ns"+str(namespaces.index(v[1]))+":"
125 ns_prefix="ns"+str(nsnum)+":"
128 ve=doc.createElement(ns_prefix+v[0])
130 ve.setAttribute("xmlns:ns"+str(nsnum), v[1])
131 if len(v) > 2 and v[2] is not None:
132 if isinstance(v[2], (list, tuple)):
133 # support nested elements like:
134 # ( 'elem', 'ns:', [('sub-elem1', 'ns1'), ...]
135 _prop_elem_child(ve, v[1], v[2], ns_prefix)
137 vt=createText2Node(doc,tools.ustr(v[2]))
139 if len(v) > 3 and v[3]:
140 assert isinstance(v[3], dict)
141 for ak, av in v[3].items():
142 ve.setAttribute(ak, av)
143 pnode.appendChild(ve)
145 ve=createText2Node(doc, tools.ustr(v))
146 pnode.appendChild(ve)
148 # write href information
149 uparts=urlparse.urlparse(uri)
151 if isinstance(fileloc, unicode):
152 fileloc = fileloc.encode('utf-8')
153 href=doc.createElement("D:href")
154 davpath = self._dataclass.parent.get_davpath()
155 if uparts[0] and uparts[1]:
156 hurl = '%s://%s%s%s' % (uparts[0], uparts[1], davpath, urllib.quote(fileloc))
158 # When the request has been relative, we don't have enough data to
159 # reply with absolute url here.
160 hurl = '%s%s' % (davpath, urllib.quote(fileloc))
161 huri=doc.createTextNode(hurl)
162 href.appendChild(huri)
165 # write good properties
166 ps=doc.createElement("D:propstat")
169 s=doc.createElement("D:status")
170 t=doc.createTextNode("HTTP/1.1 200 OK")
174 gp=doc.createElement("D:prop")
175 for ns in good_props.keys():
179 ns_prefix="ns"+str(namespaces.index(ns))+":"
180 for p,v in good_props[ns].items():
183 _prop_child(gp, ns, p, v)
188 # now write the errors!
189 if len(bad_props.items()):
191 # write a propstat for each error code
192 for ecode in bad_props.keys():
193 ps=doc.createElement("D:propstat")
195 s=doc.createElement("D:status")
196 t=doc.createTextNode(utils.gen_estring(ecode))
199 bp=doc.createElement("D:prop")
202 for ns in bad_props[ecode].keys():
206 ns_prefix="ns"+str(self.namespaces.index(ns))+":"
208 for p in bad_props[ecode][ns]:
209 pe=doc.createElement(ns_prefix+str(p))
214 # return the new response element
218 def mk_propname_response(self,uri,propnames,doc):
219 """ make a new <prop> result element for a PROPNAME request
221 This will simply format the propnames list.
222 propnames should have the format {NS1 : [prop1, prop2, ...], NS2: ...}
225 re=doc.createElement("D:response")
227 # write href information
228 uparts=urlparse.urlparse(uri)
230 if isinstance(fileloc, unicode):
231 fileloc = fileloc.encode('utf-8')
232 href=doc.createElement("D:href")
233 davpath = self._dataclass.parent.get_davpath()
234 if uparts[0] and uparts[1]:
235 hurl = '%s://%s%s%s' % (uparts[0], uparts[1], davpath, urllib.quote(fileloc))
237 # When the request has been relative, we don't have enough data to
238 # reply with absolute url here.
239 hurl = '%s%s' % (davpath, urllib.quote(fileloc))
240 huri=doc.createTextNode(hurl)
241 href.appendChild(huri)
244 ps=doc.createElement("D:propstat")
247 for ns,plist in propnames.items():
249 pr=doc.createElement("D:prop")
254 ps.setAttribute("xmlns:"+nsp,ns)
257 # write propertynames
259 pe=doc.createElement(nsp+":"+p)
268 PROPFIND.mk_prop_response = mk_prop_response
269 PROPFIND.mk_propname_response = mk_propname_response
271 super_create_prop = REPORT.create_prop
273 def create_prop(self):
275 if (self.filter is not None) and self._depth == "0":
276 hrefs = self.filter.getElementsByTagNameNS('DAV:', 'href')
281 return super_create_prop(self)
283 REPORT.create_prop = create_prop