a764a6d96c99433fb3e0b0f6baa59348fd36f2e6
[odoo/odoo.git] / addons / document_webdav / DAV / utils.py
1 #!/usr/bin/env python
2
3 """
4
5 UTILITIES
6
7 - parse a propfind request body into a list of props
8
9 """
10
11 from xml.dom import ext
12 from xml.dom.Document import Document
13 from xml.dom.ext.reader import PyExpat
14 from xml.dom import Node
15 from xml.dom import NodeIterator, NodeFilter
16
17 from string import lower, split, atoi, joinfields
18 import urlparse
19 from StringIO import StringIO
20
21 from constants import RT_ALLPROP, RT_PROPNAME, RT_PROP
22 from status import STATUS_CODES
23
24 VERSION = '0.6'
25 AUTHOR  = 'Simon Pamies <s.pamies@banality.de>'
26
27
28 def gen_estring(ecode):
29     """ generate an error string from the given code """
30     ec=atoi(str(ecode))
31     if STATUS_CODES.has_key(ec):
32         return "HTTP/1.1 %s %s" %(ec,STATUS_CODES[ec])
33     else:
34         return "HTTP/1.1 %s" %(ec)
35
36 def parse_propfind(xml_doc):
37     """ parse an propfind xml file and return a list of props
38
39     returns:
40
41         request_type            -- ALLPROP, PROPNAME, PROP
42         proplist            -- list of properties found
43         namespaces            -- list of namespaces found
44
45     """
46     doc = PyExpat.Reader().fromString(xml_doc)
47     snit = doc.createNodeIterator(doc, NodeFilter.NodeFilter.SHOW_ELEMENT, None, None)
48
49     request_type=None
50     props={}
51     namespaces=[]
52
53     while 1:
54         curr_elem = snit.nextNode()
55         if not curr_elem: break
56         ename=fname=lower(curr_elem.nodeName)
57         if ":" in fname:
58             ename=split(fname,":")[1]
59         if ename=="prop": request_type=RT_PROP; continue
60         if ename=="propfind": continue
61         if ename=="allprop": request_type=RT_ALLPROP; continue
62         if ename=="propname": request_type=RT_PROPNAME; continue
63
64         # rest should be names of attributes
65
66         ns = curr_elem.namespaceURI
67         if props.has_key(ns):
68             props[ns].append(ename)
69         else:
70             props[ns]=[ename]
71             namespaces.append(ns)
72
73     return request_type,props,namespaces
74
75
76 def create_treelist(dataclass,uri):
77     """ create a list of resources out of a tree
78
79     This function is used for the COPY, MOVE and DELETE methods
80
81     uri - the root of the subtree to flatten
82
83     It will return the flattened tree as list
84
85     """
86     queue=[uri]
87     list=[uri]
88     while len(queue):
89         element=queue[-1]
90         if dataclass.is_collection(element):
91             childs=dataclass.get_childs(element)
92         else:
93             childs=[]
94         if len(childs):
95             list=list+childs
96         # update queue
97         del queue[-1]
98         if len(childs):
99             queue=queue+childs
100     return list
101
102 def is_prefix(uri1,uri2):
103     """ returns 1 of uri1 is a prefix of uri2 """
104     if uri2[:len(uri1)]==uri1:
105         return 1
106     else:
107         return None
108
109 def quote_uri(uri):
110     """ quote an URL but not the protocol part """
111     import urlparse
112     import urllib
113
114     up=urlparse.urlparse(uri)
115     np=urllib.quote(up[2])
116     return urlparse.urlunparse((up[0],up[1],np,up[3],up[4],up[5]))
117
118 def get_uriparentpath(uri):
119     """ extract the uri path and remove the last element """
120     up=urlparse.urlparse(uri)
121     return joinfields(split(up[2],"/")[:-1],"/")
122
123 def get_urifilename(uri):
124     """ extract the uri path and return the last element """
125     up=urlparse.urlparse(uri)
126     return split(up[2],"/")[-1]
127
128 def get_parenturi(uri):
129     """ return the parent of the given resource"""
130     up=urlparse.urlparse(uri)
131     np=joinfields(split(up[2],"/")[:-1],"/")
132     return urlparse.urlunparse((up[0],up[1],np,up[3],up[4],up[5]))
133
134 ### XML utilities
135
136 def make_xmlresponse(result):
137     """ construct a response from a dict of uri:error_code elements """
138     doc = Document.Document(None)
139     ms=doc.createElement("D:multistatus")
140     ms.setAttribute("xmlns:D","DAV:")
141     doc.appendChild(ms)
142
143     for el,ec in result.items():
144         re=doc.createElement("D:response")
145         hr=doc.createElement("D:href")
146         st=doc.createElement("D:status")
147         huri=doc.createTextNode(quote_uri(el))
148         t=doc.createTextNode(gen_estring(ec))
149         st.appendChild(t)
150         hr.appendChild(huri)
151         re.appendChild(hr)
152         re.appendChild(st)
153         ms.appendChild(re)
154
155     sfile=StringIO()
156     ext.PrettyPrint(doc,stream=sfile)
157     s=sfile.getvalue()
158     sfile.close()
159     return s
160