[FIX] caldav: remove unneccassry import packages
[odoo/odoo.git] / addons / caldav / caldav_fs.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #    
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU Affero General Public License for more details.
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.     
19 #
20 ##############################################################################
21
22 import pooler
23
24 import base64
25 import sys
26 import os
27 import time
28 from string import joinfields, split, lower
29
30 from service import security
31
32 import netsvc
33 import urlparse
34
35 from DAV.constants import COLLECTION, OBJECT
36 from DAV.errors import *
37 from DAV.iface import *
38 import urllib
39
40 from DAV.davcmd import copyone, copytree, moveone, movetree, delone, deltree
41 from caldav_cache import memoize
42 from tools import misc
43 CACHE_SIZE=20000
44
45
46 class tinydav_handler(dav_interface):
47     """
48     This class models a Tiny ERP interface for the DAV server
49     """
50     PROPS={'DAV:': dav_interface.PROPS['DAV:'], }
51
52     M_NS={ "DAV:" : dav_interface.M_NS['DAV:'], }
53
54     def __init__(self,  parent, verbose=False):
55         self.db_name = False        
56         self.parent = parent
57         self.baseuri = parent.baseuri
58
59     def get_propnames(self, uri):
60         props = self.PROPS
61         self.parent.log_message('get propnames: %s' % uri)
62         if uri[-1]=='/':uri=uri[:-1]
63         cr, uid, pool, dbname, uri2 = self.get_cr(uri)
64         if not dbname:
65             cr.close()
66             return props
67         node = self.uri2object(cr,uid,pool, uri2)
68         if node:
69             props.update(node.get_dav_props(cr))
70         cr.close()
71         return props
72
73     def get_prop(self,uri,ns,propname):
74         """ return the value of a given property
75
76             uri        -- uri of the object to get the property of
77             ns        -- namespace of the property
78             pname        -- name of the property
79          """
80         if self.M_NS.has_key(ns):
81            return dav_interface.get_prop(self,uri,ns,propname)
82
83         if uri[-1]=='/':uri=uri[:-1]
84         cr, uid, pool, dbname, uri2 = self.get_cr(uri)
85         if not dbname:
86             cr.close()
87             raise DAV_NotFound
88         node = self.uri2object(cr,uid,pool, uri2)
89         if not node:
90             cr.close()
91             raise DAV_NotFound
92         res = node.get_dav_eprop(cr,ns,propname)
93         cr.close()
94         return res
95
96     def urijoin(self,*ajoin):
97         """ Return the base URI of this request, or even join it with the
98             ajoin path elements
99         """
100         return self.baseuri+ '/'.join(ajoin)        
101
102     def uri2local(self, uri):
103         uparts=urlparse.urlparse(uri)
104         reluri=uparts[2]
105         if reluri and reluri[-1]=="/":
106             reluri=reluri[:-1]
107         return reluri
108
109     #
110     # pos: -1 to get the parent of the uri
111     #
112     def get_cr(self, uri):        
113         pdb = self.parent.auth_proxy.last_auth
114         reluri = self.uri2local(uri)        
115         try:
116             dbname = reluri.split('/')[2]
117         except:
118             dbname = False
119         if not dbname:
120             return None, None, None, False, None
121         if not pdb and dbname:
122             # if dbname was in our uri, we should have authenticated
123             # against that.
124             raise Exception("Programming error")        
125         assert pdb == dbname, " %s != %s" %(pdb, dbname)
126         user, passwd, dbn2, uid = self.parent.auth_proxy.auth_creds[pdb]
127         db,pool = pooler.get_db_and_pool(dbname)
128         cr = db.cursor()
129         uri2 = reluri.split('/')[3:]
130         return cr, uid, pool, dbname, uri2
131
132     def uri2object(self, cr, uid, pool, uri):
133         if not uid:
134             return None
135         return pool.get('basic.calendar').get_calendar_object(cr, uid, uri)
136
137     def get_data(self,uri):
138         self.parent.log_message('GET: %s' % uri)
139         if uri[-1]=='/':uri=uri[:-1]
140         cr, uid, pool, dbname, uri2 = self.get_cr(uri)
141         try:
142             if not dbname:
143                 raise DAV_Error, 409
144             node = self.uri2object(cr,uid,pool, uri2)
145             if not node:
146                 raise DAV_NotFound(uri2)
147             try:                
148                 datas = node.get_data(cr, uid)
149             except TypeError,e:
150                 import traceback
151                 self.parent.log_error("GET typeError: %s", str(e))
152                 self.parent.log_message("Exc: %s",traceback.format_exc())
153                 raise DAV_Forbidden
154             except IndexError,e :
155                 self.parent.log_error("GET IndexError: %s", str(e))
156                 raise DAV_NotFound(uri2)
157             except Exception,e:
158                 import traceback
159                 self.parent.log_error("GET exception: %s",str(e))
160                 self.parent.log_message("Exc: %s", traceback.format_exc())
161                 raise DAV_Error, 409
162             return datas
163         finally:
164             cr.close()
165
166     @memoize(CACHE_SIZE)
167     def _get_dav_resourcetype(self,uri):
168         """ return type of object """
169         self.parent.log_message('get RT: %s' % uri)
170         if uri[-1]=='/':uri=uri[:-1]
171         cr, uid, pool, dbname, uri2 = self.get_cr(uri)
172         try:
173             if not dbname:
174                 return COLLECTION
175             node = self.uri2object(cr,uid,pool, uri2)
176             if not node:
177                 raise DAV_NotFound(uri2)            
178             return OBJECT
179         finally:
180             cr.close()
181
182     def _get_dav_displayname(self,uri):
183         self.parent.log_message('get DN: %s' % uri)
184         if uri[-1]=='/':uri=uri[:-1]
185         cr, uid, pool, dbname, uri2 = self.get_cr(uri)
186         if not dbname:
187             cr.close()
188             return COLLECTION
189         node = self.uri2object(cr,uid,pool, uri2)
190         if not node:
191             cr.close()
192             raise DAV_NotFound(uri2)
193         cr.close()
194         return node.displayname
195
196     @memoize(CACHE_SIZE)
197     def _get_dav_getcontentlength(self,uri):
198         """ return the content length of an object """
199         self.parent.log_message('get length: %s' % uri)
200         if uri[-1]=='/':uri=uri[:-1]
201         result = 0
202         cr, uid, pool, dbname, uri2 = self.get_cr(uri)
203         if not dbname:
204             cr.close()
205             return '0'
206         node = self.uri2object(cr, uid, pool, uri2)
207         if not node:
208             cr.close()
209             raise DAV_NotFound(uri2)
210         result = node.content_length or 0
211         cr.close()
212         return str(result)
213
214     @memoize(CACHE_SIZE)
215     def _get_dav_getetag(self,uri):
216         """ return the ETag of an object """
217         self.parent.log_message('get etag: %s' % uri)
218         if uri[-1]=='/':uri=uri[:-1]
219         result = 0
220         cr, uid, pool, dbname, uri2 = self.get_cr(uri)
221         if not dbname:
222             cr.close()
223             return '0'
224         node = self.uri2object(cr, uid, pool, uri2)
225         if not node:
226             cr.close()
227             raise DAV_NotFound(uri2)
228         result = node.get_etag(cr)
229         cr.close()
230         return str(result)
231
232     @memoize(CACHE_SIZE)
233     def get_lastmodified(self,uri):
234         """ return the last modified date of the object """
235         if uri[-1]=='/':uri=uri[:-1]
236         today = time.time()
237         cr, uid, pool, dbname, uri2 = self.get_cr(uri)
238         try:
239             if not dbname:
240                 return today
241             node = self.uri2object(cr,uid,pool, uri2)
242             if not node:
243                 raise DAV_NotFound(uri2)
244             if node.write_date:
245                 return time.mktime(time.strptime(node.write_date,'%Y-%m-%d %H:%M:%S'))
246             else:
247                 return today
248         finally:
249             cr.close()
250
251     @memoize(CACHE_SIZE)
252     def get_creationdate(self,uri):
253         """ return the last modified date of the object """
254
255         if uri[-1]=='/':uri=uri[:-1]
256         cr, uid, pool, dbname, uri2 = self.get_cr(uri)
257         try:
258             if not dbname:
259                 raise DAV_Error, 409
260             node = self.uri2object(cr,uid,pool, uri2)
261             if not node:
262                 raise DAV_NotFound(uri2)
263             if node.create_date:
264                 result = time.strptime(node.create_date,'%Y-%m-%d %H:%M:%S')
265             else:
266                 result = time.gmtime()
267             return result
268         finally:
269             cr.close()
270
271     @memoize(CACHE_SIZE)
272     def _get_dav_getcontenttype(self,uri):
273         self.parent.log_message('get contenttype: %s' % uri)
274         if uri[-1]=='/':uri=uri[:-1]
275         cr, uid, pool, dbname, uri2 = self.get_cr(uri)
276         try:
277             if not dbname:
278                 return 'httpd/unix-directory'
279             node = self.uri2object(cr,uid,pool, uri2)
280             if not node:
281                 raise DAV_NotFound(uri2)
282             result = node.mimetype
283             return result
284             #raise DAV_NotFound, 'Could not find %s' % path
285         finally:
286             cr.close()
287
288     
289
290     def put(self, uri, data, content_type=None):
291         """ put the object into the filesystem """
292         self.parent.log_message('Putting %s (%d), %s'%( misc.ustr(uri), len(data), content_type))
293         parent='/'.join(uri.split('/')[:-1])
294         cr, uid, pool,dbname, uri2 = self.get_cr(uri)        
295         if not dbname:
296             raise DAV_Forbidden
297         try:
298             node = self.uri2object(cr,uid,pool, uri2[:])
299         except:
300             node = False        
301
302         if not node:
303             raise DAV_Forbidden
304         else:
305             try:
306                 node.set_data(cr, uid, data)                
307             except Exception,e:
308                 import traceback                
309                 self.parent.log_error("Cannot save :%s", str(e))
310                 self.parent.log_message("Exc: %s",traceback.format_exc())
311                 raise DAV_Forbidden
312             
313         cr.commit()
314         cr.close()
315         return 201
316
317     
318
319
320     def exists(self,uri):
321         """ test if a resource exists """
322         result = False
323         cr, uid, pool,dbname, uri2 = self.get_cr(uri)
324         if not dbname:
325             cr.close()
326             return True
327         try:
328             node = self.uri2object(cr,uid,pool, uri2)
329             if node:
330                 result = True
331         except:
332             pass
333         cr.close()
334         return result