1 # -*- coding: utf-8 -*-
2 ##############################################################################
4 # OpenERP, Open Source Management Solution
5 # Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
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.
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.
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/>.
20 ##############################################################################
24 from osv import osv, fields
25 from osv.orm import except_orm
28 from tools.safe_eval import safe_eval
34 # An object that represent an uri
35 # path: the uri of the object
36 # content: the Content it belongs to (_print.pdf)
37 # type: content or collection
38 # content: objct = res.partner
39 # collection: object = directory, object2 = res.partner
40 # file: objct = ir.attachement
41 # root: if we are at the first directory of a ressource
44 def get_node_context(cr, uid, context):
45 return node_context(cr,uid,context)
47 class node_context(object):
48 """ This is the root node, representing access to some particular
52 def __init__(self, cr, uid, context=None):
53 self.dbname = cr.dbname
55 self.context = context
56 self._dirobj = pooler.get_pool(cr.dbname).get('document.directory')
58 self.rootdir = False #self._dirobj._get_root_directory(cr,uid,context)
60 def get_uri(self, cr, uri):
61 """ Although this fn passes back to doc.dir, it is needed since
62 it is a potential caching point """
63 (ndir, duri) = self._dirobj._locate_child(cr,self.uid, self.rootdir,uri, None, self)
65 ndir = ndir.child(cr, duri[0])
72 class node_database():
73 """ A node representing the database directory
76 def __init__(self,ncontext):
82 class node_class(object):
83 """ this is a superclass for our inodes
84 It is an API for all code that wants to access the document files.
85 Nodes have attributes which contain usual file properties
87 our_type = 'baseclass'
88 def __init__(self, path, parent, context):
89 assert isinstance(context,node_context)
90 assert (not parent ) or isinstance(parent,node_class)
92 self.context = context
93 self.type=self.our_type
95 self.mimetype = 'application/octet-stream'
96 self.create_date = None
97 self.write_date = None
98 self.content_length = 0
102 self.dctx = parent.dctx.copy()
103 self.displayname = 'Object'
106 """ Return the components of the full path for some
108 The returned list only contains the names of nodes.
111 s = self.parent.full_path()
114 if isinstance(self.path,list):
118 return s #map(lambda x: '/' +x, s)
120 def children(self, cr):
121 print "node_class.children()"
124 def child(self,cr, name):
125 print "node_class.child()"
129 print "node_class.path_get()"
132 def get_data(self,cr):
133 raise TypeError('no data for %s'% self.type)
135 def _get_storage(self,cr):
136 raise RuntimeError("no storage for base class")
138 def get_etag(self,cr):
139 """ Get a tag, unique per object + modification.
141 see. http://tools.ietf.org/html/rfc2616#section-13.3.3 """
142 return self._get_ttag(cr) + ':' + self._get_wtag(cr)
144 def _get_wtag(self,cr):
145 """ Return the modification time as a unique, compact string """
147 wtime = time.mktime(time.strptime(self.write_date,'%Y-%m-%d %H:%M:%S'))
148 else: wtime = time.time()
151 def _get_ttag(self,cr):
152 """ Get a unique tag for this type/id of object.
153 Must be overriden, so that each node is uniquely identified.
155 print "node_class.get_ttag()",self
156 raise RuntimeError("get_etag stub()")
158 def get_dav_props(self, cr):
159 """ If this class has special behaviour for GroupDAV etc, export
163 def get_dav_eprop(self,cr,ns,prop):
166 class node_dir(node_class):
167 our_type = 'collection'
168 def __init__(self,path, parent, context, dirr, dctx=None):
169 super(node_dir,self).__init__(path, parent,context)
170 self.dir_id = dirr and dirr.id or False
171 #todo: more info from dirr
172 self.mimetype = 'application/x-directory'
173 # 'httpd/unix-directory'
174 self.create_date = dirr and dirr.create_date or False
175 self.domain = dirr and dirr.domain or []
176 self.res_model = dirr and dirr.ressource_type_id and dirr.ressource_type_id.model or False
177 # TODO: the write date should be MAX(file.write)..
178 self.write_date = dirr and (dirr.write_date or dirr.create_date) or False
179 self.content_length = 0
181 self.dctx.update(dctx)
182 dc2 = self.context.context
183 dc2.update(self.dctx)
184 dc2['dir_id'] = self.dir_id
185 self.displayname = dirr and dirr.name or False
186 if dirr and dirr.dctx_ids:
187 for dfld in dirr.dctx_ids:
189 self.dctx['dctx_' + dfld.field] = safe_eval(dfld.expr,dc2)
191 print "Cannot eval %s" % dfld.expr
195 def children(self,cr):
196 return self._child_get(cr) + self._file_get(cr)
198 def child(self,cr, name):
199 res = self._child_get(cr,name)
202 res = self._file_get(cr,name)
207 def _file_get(self,cr, nodename=False):
209 cntobj = self.context._dirobj.pool.get('document.directory.content')
210 uid = self.context.uid
211 ctx = self.context.context.copy()
212 ctx.update(self.dctx)
213 where = [('directory_id','=',self.dir_id) ]
214 ids = cntobj.search(cr, uid, where, context=ctx)
215 for content in cntobj.browse(cr, uid, ids, context=ctx):
216 res3 = cntobj._file_get(cr, self, nodename, content)
222 def get_dav_props(self, cr):
224 cntobj = self.context._dirobj.pool.get('document.directory.content')
225 uid = self.context.uid
226 ctx = self.context.context.copy()
227 ctx.update(self.dctx)
228 where = [('directory_id','=',self.dir_id) ]
229 ids = cntobj.search(cr,uid,where,context=ctx)
230 for content in cntobj.browse(cr,uid,ids,context=ctx):
231 if content.extension == '.ics': # FIXME: call the content class!
232 res['http://groupdav.org/'] = ('resourcetype',)
236 def get_dav_eprop(self,cr,ns,prop):
237 if ns != 'http://groupdav.org/' or prop != 'resourcetype':
238 print "Who asked for %s:%s?" % (ns,prop)
241 cntobj = self.context._dirobj.pool.get('document.directory.content')
242 uid = self.context.uid
243 ctx = self.context.context.copy()
244 ctx.update(self.dctx)
245 where = [('directory_id','=',self.dir_id) ]
246 ids = cntobj.search(cr,uid,where,context=ctx)
247 for content in cntobj.browse(cr,uid,ids,context=ctx):
248 if content.extension == '.ics': # FIXME: call the content class!
249 return ('vevent-collection','http://groupdav.org/')
252 def _child_get(self,cr,name = None):
253 dirobj = self.context._dirobj
254 uid = self.context.uid
255 ctx = self.context.context.copy()
256 ctx.update(self.dctx)
257 where = [('parent_id','=',self.dir_id) ]
259 where.append(('name','=',name))
261 ids = dirobj.search(cr, uid, where + [('ressource_parent_type_id','=',False)],context=ctx)
264 for dirr in dirobj.browse(cr,uid,ids,context=ctx):
265 if dirr.type == 'directory':
266 res.append(node_dir(dirr.name,self,self.context,dirr))
267 elif dirr.type == 'ressource':
268 res.append(node_res_dir(dirr.name,self,self.context,dirr))
270 fil_obj=dirobj.pool.get('ir.attachment')
271 #where2 = where # + [('res_model', '=', None)]
272 ids = fil_obj.search(cr,uid,where,context=ctx)
274 for fil in fil_obj.browse(cr,uid,ids,context=ctx):
275 res.append(node_file(fil.name,self,self.context,fil))
279 def create_child(self,cr,path,data):
280 """ API function to create a child file object and node
281 Return the node_* created
283 dirobj = self.context._dirobj
284 uid = self.context.uid
285 ctx = self.context.context.copy()
286 ctx.update(self.dctx)
287 fil_obj=dirobj.pool.get('ir.attachment')
291 'parent_id': self.dir_id,
292 # Datas are not set here
295 fil_id = fil_obj.create(cr,uid, val, context=ctx)
296 fil = fil_obj.browse(cr,uid,fil_id,context=ctx)
297 fnode = node_file(path,self,self.context,fil)
298 fnode.set_data(cr,data,fil)
301 def _get_ttag(self,cr):
302 return 'dir-%d' % self.dir_id
304 class node_res_dir(node_class):
305 """ A special sibling to node_dir, which does only contain dynamically
306 created folders foreach resource in the foreign model.
307 All folders should be of type node_res_obj and merely behave like
308 node_dirs (with limited domain).
310 our_type = 'collection'
311 def __init__(self,path, parent, context, dirr, dctx=None ):
312 super(node_res_dir,self).__init__(path, parent,context)
313 self.dir_id = dirr.id
314 #todo: more info from dirr
315 self.mimetype = 'application/x-directory'
316 # 'httpd/unix-directory'
317 self.create_date = dirr.create_date
318 # TODO: the write date should be MAX(file.write)..
319 self.write_date = dirr.write_date or dirr.create_date
320 self.content_length = 0
321 self.res_model = dirr.ressource_type_id and dirr.ressource_type_id.model or False
322 self.resm_id = dirr.ressource_id
323 self.namefield = dirr.resource_field or 'name'
324 self.displayname = dirr.name
325 # Important: the domain is evaluated using the *parent* dctx!
326 self.domain = dirr.domain
327 self.ressource_tree = dirr.ressource_tree
328 # and then, we add our own vars in the dctx:
330 self.dctx.update(dctx)
332 # and then, we prepare a dctx dict, for deferred evaluation:
334 for dfld in dirr.dctx_ids:
335 self.dctx_dict['dctx_' + dfld.field] = dfld.expr
337 def children(self,cr):
338 return self._child_get(cr)
340 def child(self,cr, name):
341 res = self._child_get(cr,name)
346 def _child_get(self,cr,name = None):
347 """ return virtual children of resource, based on the
350 Note that many objects use NULL for a name, so we should
351 better call the name_search(),name_get() set of methods
353 obj = self.context._dirobj.pool.get(self.res_model)
355 print "couldn't find model", self.res_model
357 dirobj = self.context._dirobj
358 uid = self.context.uid
359 ctx = self.context.context.copy()
360 ctx.update(self.dctx)
363 where += safe_eval(self.domain, self.dctx)
365 where.append(('id','=',self.resm_id))
368 where.append((self.namefield,'=',name))
370 # print "Where clause for %s" % self.res_model, where
371 if self.ressource_tree:
374 object2 = dirobj.pool.get(self.res_model).browse(cr, uid, self.resm_id) or False
375 if obj._parent_name in obj.fields_get(cr, uid):
376 where.append((obj._parent_name,'=',object2 and object2.id or False))
378 resids = obj.search(cr,uid, where, context=ctx)
380 for bo in obj.browse(cr,uid,resids,context=ctx):
383 name = getattr(bo,self.namefield)
386 # Yes! we can't do better but skip nameless records.
388 res.append(node_res_obj(name, self.dir_id, self, self.context, self.res_model, bo))
391 def _get_ttag(self,cr):
392 return 'rdir-%d' % self.dir_id
394 class node_res_obj(node_class):
395 """ A special sibling to node_dir, which does only contain dynamically
396 created folders foreach resource in the foreign model.
397 All folders should be of type node_res_obj and merely behave like
398 node_dirs (with limited domain).
400 our_type = 'collection'
401 def __init__(self, path, dir_id, parent, context, res_model, res_bo, res_id = None):
402 super(node_res_obj,self).__init__(path, parent,context)
404 #todo: more info from dirr
406 self.mimetype = 'application/x-directory'
407 # 'httpd/unix-directory'
408 self.create_date = parent.create_date
409 # TODO: the write date should be MAX(file.write)..
410 self.write_date = parent.write_date
411 self.content_length = 0
412 self.res_model = res_model
413 self.domain = parent.domain
414 self.displayname = path
415 self.dctx_dict = parent.dctx_dict
417 self.res_id = res_bo.id
418 dc2 = self.context.context
419 dc2.update(self.dctx)
420 dc2['res_model'] = res_model
421 dc2['res_id'] = res_bo.id
423 for fld,expr in self.dctx_dict.items():
425 self.dctx[fld] = safe_eval(expr,dc2)
427 print "Cannot eval %s for %s" % (expr, fld)
433 def children(self,cr):
434 return self._child_get(cr) + self._file_get(cr)
436 def child(self,cr, name):
437 res = self._child_get(cr,name)
440 res = self._file_get(cr,name)
445 def _file_get(self,cr, nodename=False):
447 cntobj = self.context._dirobj.pool.get('document.directory.content')
448 uid = self.context.uid
449 ctx = self.context.context.copy()
450 ctx.update(self.dctx)
451 where = [('directory_id','=',self.dir_id) ]
453 # where.extend(self.domain)
454 # print "res_obj file_get clause", where
455 ids = cntobj.search(cr,uid,where,context=ctx)
456 for content in cntobj.browse(cr,uid,ids,context=ctx):
457 res3 = cntobj._file_get(cr,self,nodename,content, context=ctx)
463 def get_dav_props(self, cr):
465 cntobj = self.context._dirobj.pool.get('document.directory.content')
466 uid = self.context.uid
467 ctx = self.context.context.copy()
468 ctx.update(self.dctx)
469 where = [('directory_id','=',self.dir_id) ]
470 ids = cntobj.search(cr,uid,where,context=ctx)
471 for content in cntobj.browse(cr,uid,ids,context=ctx):
472 if content.extension == '.ics': # FIXME: call the content class!
473 res['http://groupdav.org/'] = ('resourcetype',)
476 def get_dav_eprop(self,cr,ns,prop):
477 if ns != 'http://groupdav.org/' or prop != 'resourcetype':
478 print "Who asked for %s:%s?" % (ns,prop)
481 cntobj = self.context._dirobj.pool.get('document.directory.content')
482 uid = self.context.uid
483 ctx = self.context.context.copy()
484 ctx.update(self.dctx)
485 where = [('directory_id','=',self.dir_id) ]
486 ids = cntobj.search(cr,uid,where,context=ctx)
487 for content in cntobj.browse(cr,uid,ids,context=ctx):
488 if content.extension == '.ics': # FIXME: call the content class!
489 return ('vevent-collection','http://groupdav.org/')
492 def _child_get(self,cr,name = None):
493 dirobj = self.context._dirobj
494 uid = self.context.uid
495 ctx = self.context.context.copy()
496 ctx.update(self.dctx)
497 directory = dirobj.browse(cr, uid, self.dir_id)
498 obj = dirobj.pool.get(self.res_model)
502 where.append(('name','=',name))
504 # Directory Structure display in tree structure
505 if self.res_id and directory.ressource_tree:
507 if obj._parent_name in obj.fields_get(cr, uid):
508 where1 = where + [(obj._parent_name, '=', self.res_id)]
509 resids = obj.search(cr,uid, where1, context=ctx)
510 for bo in obj.browse(cr,uid,resids,context=ctx):
511 namefield = directory.resource_field or 'name'
514 res_name = getattr(bo, namefield)
517 res.append(node_res_obj(res_name, self.dir_id, self, self.context, self.res_model, res_bo = bo))
520 where2 = where + [('parent_id','=',self.dir_id) ]
521 ids = dirobj.search(cr, uid, where2, context=ctx)
522 for dirr in dirobj.browse(cr, uid, ids, context=ctx):
523 if dirr.type == 'directory':
524 res.append(node_res_obj(dirr.name, dirr.id, self, self.context, self.res_model, res_bo = None, res_id = self.res_id))
525 elif dirr.type == 'ressource':
526 # child resources can be controlled by properly set dctx
527 res.append(node_res_dir(dirr.name,self,self.context, dirr, {'active_id': self.res_id}))
532 fil_obj = dirobj.pool.get('ir.attachment')
533 where3 = where2 + [('res_model', '=', self.res_model), ('res_id','=',self.res_id)]
534 # print "where clause for dir_obj", where2
535 ids = fil_obj.search(cr, uid, where3, context=ctx)
537 for fil in fil_obj.browse(cr, uid, ids, context=ctx):
538 res.append(node_file(fil.name, self, self.context, fil))
541 # Get Child Ressource Directories
542 if directory.ressource_type_id and directory.ressource_type_id.id:
543 where4 = where + [('ressource_parent_type_id','=',directory.ressource_type_id.id)]
544 where5 = where4 + [('ressource_id','=',0)]
545 dirids = dirobj.search(cr,uid, where5)
546 where5 = where4 + [('ressource_id','=',self.res_id)]
547 dirids = dirids + dirobj.search(cr,uid, where5)
548 for dirr in dirobj.browse(cr, uid, dirids, context=ctx):
549 if dirr.type == 'directory' and not dirr.parent_id:
550 res.append(node_res_obj(dirr.name, dirr.id, self, self.context, self.res_model, res_bo = None, res_id = self.res_id))
551 if dirr.type == 'ressource':
552 res.append(node_res_dir(dirr.name, self, self.context, dirr, {'active_id': self.res_id}))
555 def create_child(self,cr,path,data):
556 """ API function to create a child file object and node
557 Return the node_* created
559 dirobj = self.context._dirobj
560 uid = self.context.uid
561 ctx = self.context.context.copy()
562 ctx.update(self.dctx)
563 fil_obj=dirobj.pool.get('ir.attachment')
567 'parent_id': self.dir_id,
568 'res_model': self.res_model,
569 'res_id': self.res_id,
570 # Datas are not set here
573 fil_id = fil_obj.create(cr,uid, val, context=ctx)
574 fil = fil_obj.browse(cr,uid,fil_id,context=ctx)
575 fnode = node_file(path,self,self.context,fil)
576 fnode.set_data(cr,data,fil)
579 def _get_ttag(self,cr):
580 return 'rodir-%d-%d' % (self.dir_id,self.res_id)
582 class node_file(node_class):
584 def __init__(self,path, parent, context, fil):
585 super(node_file,self).__init__(path, parent,context)
586 self.file_id = fil.id
587 #todo: more info from ir_attachment
588 if fil.file_type and '/' in fil.file_type:
589 self.mimetype = fil.file_type
590 self.create_date = fil.create_date
591 self.write_date = fil.write_date or fil.create_date
592 self.content_length = fil.file_size
593 self.displayname = fil.name
595 # This only propagates the problem to get_data. Better
596 # fix those files to point to the root dir.
598 self.storage_id = fil.parent_id.storage_id.id
600 self.storage_id = None
603 def get_data(self, cr, fil_obj = None):
604 """ Retrieve the data for some file.
605 fil_obj may optionally be specified, and should be a browse object
606 for the file. This is useful when the caller has already initiated
607 the browse object. """
608 # this is where storage kicks in..
609 stor = self.storage_id
611 data_obj = self.context._dirobj.pool.get('ir.model.data')
612 data_id = data_obj._get_id(cr, self.context.uid, 'document', 'storage_db')
614 stor = data_obj.browse(cr, self.context.uid, data_id, context=self.context.context).res_id
616 stobj = self.context._dirobj.pool.get('document.storage')
617 return stobj.get_data(cr,self.context.uid,stor, self,self.context.context, fil_obj)
619 def get_data_len(self, cr, fil_obj = None):
620 # TODO: verify with the storage object!
621 bin_size = self.context.context.get('bin_size', False)
622 if bin_size and not self.content_length:
623 self.content_length = fil_obj.db_datas
624 return self.content_length
626 def set_data(self, cr, data, fil_obj = None):
627 """ Store data at some file.
628 fil_obj may optionally be specified, and should be a browse object
629 for the file. This is useful when the caller has already initiated
630 the browse object. """
631 # this is where storage kicks in..
632 stor = self.storage_id
634 stobj = self.context._dirobj.pool.get('document.storage')
635 return stobj.set_data(cr,self.context.uid,stor, self, data, self.context.context, fil_obj)
637 def _get_ttag(self,cr):
638 return 'file-%d' % self.file_id
640 class node_content(node_class):
642 def __init__(self,path, parent, context, cnt, dctx = None, act_id=None):
643 super(node_content,self).__init__(path, parent,context)
645 self.create_date = False
646 self.write_date = False
647 self.content_length = False
648 self.extension = cnt.extension
649 self.report_id = cnt.report_id and cnt.report_id.id
650 #self.mimetype = cnt.extension.
651 self.displayname = path
653 self.dctx.update(dctx)
656 def fill_fields(self,cr,dctx = None):
657 """ Try to read the object and fill missing fields, like mimetype,
659 This function must be different from the constructor, because
660 it uses the db cursor.
663 cr.execute('SELECT DISTINCT mimetype FROM document_directory_content_type WHERE active AND code = %s;',
666 if res and res[0][0]:
667 self.mimetype = res[0][0]
670 def get_data(self, cr, fil_obj = None):
671 cntobj = self.context._dirobj.pool.get('document.directory.content')
672 ctx = self.context.context.copy()
673 ctx.update(self.dctx)
674 data = cntobj.process_read(cr,self.context.uid,self,ctx)
676 self.content_length = len(data)
679 def get_data_len(self, cr, fil_obj = None):
680 if not self.content_length:
681 self.get_data(cr,fil_obj)
682 return self.content_length
684 def set_data(self, cr, data, fil_obj = None):
685 cntobj = self.context._dirobj.pool.get('document.directory.content')
686 ctx = self.context.context.copy()
687 ctx.update(self.dctx)
688 return cntobj.process_write(cr,self.context.uid,self, data,ctx)
690 def _get_ttag(self,cr):
691 return 'cnt-%d%s' % (self.cnt_id,(self.act_id and ('-' + str(self.act_id))) or '')
694 # the old code, remove..
695 def __init__(self, cr, uid, path, object, object2=False, context={}, content=False, type='collection', root=False):
697 def _file_get(self, nodename=False):
700 pool = pooler.get_pool(self.cr.dbname)
701 fobj = pool.get('ir.attachment')
705 where.append( ('res_model','=',self.object2._name) )
706 where.append( ('res_id','=',self.object2.id) )
708 where.append( ('parent_id','=',self.object.id) )
709 where.append( ('res_id','=',False) )
711 where.append( (fobj._rec_name,'=',nodename) )
712 for content in self.object.content_ids:
713 res3 = content._table._file_get(self,nodename,content)
717 ids = fobj.search(self.cr, self.uid, where+[ ('parent_id','=',self.object and self.object.id or False) ])
718 if self.object and self.root and (self.object.type=='ressource'):
719 ids += fobj.search(self.cr, self.uid, where+[ ('parent_id','=',False) ])
720 res = fobj.browse(self.cr, self.uid, ids, context=self.context)
721 return map(lambda x: node_class(self.cr, self.uid, self.path+'/'+eval('x.'+fobj._rec_name), x, False, context=self.context, type='file', root=False), res) + res2
723 def get_translation(self,value,lang):
724 # Must go, it works on arbitrary models and could be ambiguous.
726 pool = pooler.get_pool(self.cr.dbname)
727 translation_ids = pool.get('ir.translation').search(self.cr, self.uid, [('value','=',value),('lang','=',lang),('type','=','model')])
728 if len(translation_ids):
729 tran_id = translation_ids[0]
730 translation = pool.get('ir.translation').read(self.cr, self.uid, tran_id, ['res_id','name'])
731 res_model,field_name = tuple(translation['name'].split(','))
732 res_id = translation['res_id']
733 res = pool.get(res_model).read(self.cr, self.uid, res_id, [field_name])
735 result = res[field_name]
738 def directory_list_for_child(self,nodename,parent=False):
739 pool = pooler.get_pool(self.cr.dbname)
742 nodename = self.get_translation(nodename, self.context['lang'])
743 where.append(('name','=',nodename))
744 if (self.object and self.object.type=='directory') or not self.object2:
745 where.append(('parent_id','=',self.object and self.object.id or False))
747 where.append(('parent_id','=',False))
749 where.append(('ressource_parent_type_id','=',self.object.ressource_type_id.id))
751 where.append(('ressource_parent_type_id','=',False))
753 ids = pool.get('document.directory').search(self.cr, self.uid, where+[('ressource_id','=',0)])
755 ids += pool.get('document.directory').search(self.cr, self.uid, where+[('ressource_id','=',self.object2.id)])
756 res = pool.get('document.directory').browse(self.cr, self.uid, ids, self.context)
759 def _child_get(self, nodename=False):
760 if self.type not in ('collection','database'):
762 res = self.directory_list_for_child(nodename)
763 result= map(lambda x: node_class(self.cr, self.uid, self.path+'/'+x.name, x, x.type=='directory' and self.object2 or False, context=self.context, root=self.root), res)
764 if self.type=='database':
765 pool = pooler.get_pool(self.cr.dbname)
766 fobj = pool.get('ir.attachment')
767 vargs = [('parent_id','=',False),('res_id','=',False)]
769 vargs.append((fobj._rec_name,'=',nodename))
770 file_ids=fobj.search(self.cr,self.uid,vargs)
772 res = fobj.browse(self.cr, self.uid, file_ids, context=self.context)
773 result +=map(lambda x: node_class(self.cr, self.uid, self.path+'/'+eval('x.'+fobj._rec_name), x, False, context=self.context, type='file', root=self.root), res)
774 if self.type=='collection' and self.object.type=="ressource":
775 where = self.object.domain and eval(self.object.domain, {'active_id':self.root, 'uid':self.uid}) or []
776 pool = pooler.get_pool(self.cr.dbname)
777 obj = pool.get(self.object.ressource_type_id.model)
778 _dirname_field = obj._rec_name
779 if len(obj.fields_get(self.cr, self.uid, ['dirname'])):
780 _dirname_field = 'dirname'
782 name_for = obj._name.split('.')[-1]
783 if nodename and nodename.find(name_for) == 0 :
784 id = int(nodename.replace(name_for,''))
785 where.append(('id','=',id))
787 if nodename.find('__') :
788 nodename=nodename.replace('__','/')
789 for invalid in INVALID_CHARS:
790 if nodename.find(INVALID_CHARS[invalid]) :
791 nodename=nodename.replace(INVALID_CHARS[invalid],invalid)
792 nodename = self.get_translation(nodename, self.context['lang'])
793 where.append((_dirname_field,'=',nodename))
795 if self.object.ressource_tree:
796 if obj._parent_name in obj.fields_get(self.cr,self.uid):
797 where.append((obj._parent_name,'=',self.object2 and self.object2.id or False))
798 ids = obj.search(self.cr, self.uid, where)
799 res = obj.browse(self.cr, self.uid, ids,self.context)
800 result+= map(lambda x: node_class(self.cr, self.uid, self.path+'/'+x.name.replace('/','__'), self.object, x, context=self.context, root=x.id), res)
810 ids = obj.search(self.cr, self.uid, where)
811 res = obj.browse(self.cr, self.uid, ids,self.context)
813 if len(obj.fields_get(self.cr, self.uid, [_dirname_field])):
814 r.name = eval('r.'+_dirname_field)
818 r.name = name_for + '%d'%r.id
819 for invalid in INVALID_CHARS:
820 if r.name.find(invalid) :
821 r.name = r.name.replace(invalid,INVALID_CHARS[invalid])
822 result2 = map(lambda x: node_class(self.cr, self.uid, self.path+'/'+x.name.replace('/','__'), self.object, x, context=self.context, root=x.id), res)
824 if self.object.ressource_tree:
833 if self.path[0]=='/':