From 29495c58cec6907db7b710edbc08320b2fdbb4e5 Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Tue, 28 Oct 2008 08:10:13 +0100 Subject: [PATCH] removed_depend bzr revid: fp@tinyerp.com-20081028071013-6e2z8qbccmceq18v --- addons/document/__terp__.py | 39 +- addons/document/document.py | 36 +- addons/document/document_view.xml | 8 +- addons/document/ftpserver/abstracted_fs.py | 1305 +++++++++--------- addons/document/process/document_process.xml | 25 - 5 files changed, 705 insertions(+), 708 deletions(-) delete mode 100644 addons/document/process/document_process.xml diff --git a/addons/document/__terp__.py b/addons/document/__terp__.py index aafdbebdb1a..8c43c21e633 100644 --- a/addons/document/__terp__.py +++ b/addons/document/__terp__.py @@ -2,25 +2,24 @@ # Use the custom module to put your specific code in a separate module. # { - "name" : "Integrated Document Management System", - "version" : "1.0", - "author" : "Tiny", - "category" : "Generic Modules/Others", - "website": "http://www.tinyerp.com", - "description": """This is a complete document management system: - * FTP Interface - * User Authentification - * Document Indexation + "name" : "Integrated Document Management System", + "version" : "1.0", + "author" : "Tiny", + "category" : "Generic Modules/Others", + "website": "http://www.tinyerp.com", + "description": """This is a complete document management system: + * FTP Interface + * User Authentification + * Document Indexation """, - "depends" : ["base", "process", "hr"], - "init_xml" : ["document_data.xml"], - "update_xml" : [ - "document_view.xml", - "security/document_security.xml", - "security/ir.model.access.csv", - "process/document_process.xml" - ], - "demo_xml" : ["document_demo.xml"], - "active": False, - "installable": True + "depends" : ["base"], + "init_xml" : ["document_data.xml"], + "update_xml" : [ + "document_view.xml", + "security/document_security.xml", + "security/ir.model.access.csv", + ], + "demo_xml" : ["document_demo.xml"], + "active": False, + "installable": True } diff --git a/addons/document/document.py b/addons/document/document.py index 9778ec5b316..8637e3bc1db 100644 --- a/addons/document/document.py +++ b/addons/document/document.py @@ -81,7 +81,10 @@ class node_class(object): where.append( ('res_model','=',self.object2._name) ) where.append( ('res_id','=',self.object2.id) ) for content in self.object.content_ids: - test_nodename = self.object2.name + (content.suffix or '') + (content.extension or '') + if content.include_name: + test_nodename = self.object2.name + (content.suffix or '') + (content.extension or '') + else: + test_nodename = (content.suffix or '') + (content.extension or '') if test_nodename.find('/'): test_nodename=test_nodename.replace('/', '_') path = self.path+'/'+test_nodename @@ -384,15 +387,35 @@ class document_directory_content(osv.osv): 'name': fields.char('Content Name', size=64, required=True), 'sequence': fields.integer('Sequence', size=16), 'suffix': fields.char('Suffix', size=16), - 'versioning': fields.boolean('Versioning'), 'report_id': fields.many2one('ir.actions.report.xml', 'Report', required=True), - 'extension': fields.selection([('.pdf','.pdf'),('','None')], 'Extension', required=True), - 'directory_id': fields.many2one('document.directory', 'Directory') + 'extension': fields.selection([('.pdf','PDF Report'),('.ics','ICS Calendar')], 'Report Type', required=True), + 'include_name': fields.boolean('Include Record Name', help="Check if you cant that the name of the file start by the record name."), + 'directory_id': fields.many2one('document.directory', 'Directory'), + 'ics_object_id': fields.many2one('ir.model', 'Object'), + 'ics_domain': fields.char('Domain', size=64) } _defaults = { - 'extension': lambda *args: '', - 'sequence': lambda *args: 1 + 'extension': lambda *args: '.pdf', + 'sequence': lambda *args: 1, + 'include_name': lambda *args: 1, } + def process_read_ics(self, cr, uid, node, context={}): + import vobject + obj_class = self.pool.get(node.ics_object_id.name) + ids = obj_class.search(cr, uid, node.ics_domain, context) + cal = vobject.iCalendar() + for obj in obj_class.browse(cr, uid, ids, context): + cal.add('vevent') + cal.vevent.add('summary').value = "This is a note" + return cal.serialize() + + def process_read_pdf(self, cr, uid, node, context={}): + report = self.pool.get('ir.actions.report.xml').browse(cr, uid, node.report_id.id) + srv = netsvc.LocalService('report.'+report.report_name) + pdf,pdftype = srv.create(cr, uid, [node.object.id], {}, {}) + s = StringIO.StringIO(pdf) + s.name = node + return s document_directory_content() class ir_action_report_xml(osv.osv): @@ -635,6 +658,7 @@ class document_configuration_wizard(osv.osv_memory): if doc_obj.name=='All Sales Order': val={} id=model_obj.search(cr,uid,[('model','=','sale.order')]) + print 'Found', id if id and not len(doc_obj.content_ids): val['name']='Sale Report' val['suffix']='_report' diff --git a/addons/document/document_view.xml b/addons/document/document_view.xml index 6b15382af63..cd7689d4e9a 100644 --- a/addons/document/document_view.xml +++ b/addons/document/document_view.xml @@ -29,14 +29,18 @@ + + + + + - + - diff --git a/addons/document/ftpserver/abstracted_fs.py b/addons/document/ftpserver/abstracted_fs.py index bcd271ddeb3..9741c5a6a25 100644 --- a/addons/document/ftpserver/abstracted_fs.py +++ b/addons/document/ftpserver/abstracted_fs.py @@ -13,739 +13,734 @@ import os from service import security class abstracted_fs: - """A class used to interact with the file system, providing a high - level, cross-platform interface compatible with both Windows and - UNIX style filesystems. + """A class used to interact with the file system, providing a high + level, cross-platform interface compatible with both Windows and + UNIX style filesystems. - It provides some utility methods and some wraps around operations - involved in file creation and file system operations like moving - files or removing directories. + It provides some utility methods and some wraps around operations + involved in file creation and file system operations like moving + files or removing directories. - Instance attributes: - - (str) root: the user home directory. - - (str) cwd: the current working directory. - - (str) rnfr: source file to be renamed. - """ + Instance attributes: + - (str) root: the user home directory. + - (str) cwd: the current working directory. + - (str) rnfr: source file to be renamed. + """ - # Ok - def db_list(self): - s = netsvc.LocalService('db') - result = s.list() - self.db_name_list=[] - for db_name in result: - db = pooler.get_db_only(db_name) - cr = db.cursor() - cr.execute("select id from ir_module_module where name like 'document%' and state='installed' ") - res=cr.fetchone() - if res and len(res): - self.db_name_list.append(db_name) - cr.close() - return self.db_name_list + # Ok + def db_list(self): + s = netsvc.LocalService('db') + result = s.list() + self.db_name_list=[] + for db_name in result: + db = pooler.get_db_only(db_name) + cr = db.cursor() + cr.execute("select id from ir_module_module where name like 'document%' and state='installed' ") + res=cr.fetchone() + if res and len(res): + self.db_name_list.append(db_name) + cr.close() + return self.db_name_list - # Ok - def __init__(self): - self.root = None - self.cwd = '/' - self.rnfr = None + # Ok + def __init__(self): + self.root = None + self.cwd = '/' + self.rnfr = None - # --- Pathname / conversion utilities + # --- Pathname / conversion utilities - # Ok - def ftpnorm(self, ftppath): - """Normalize a "virtual" ftp pathname (tipically the raw string - coming from client) depending on the current working directory. + # Ok + def ftpnorm(self, ftppath): + """Normalize a "virtual" ftp pathname (tipically the raw string + coming from client) depending on the current working directory. - Example (having "/foo" as current working directory): - 'x' -> '/foo/x' + Example (having "/foo" as current working directory): + 'x' -> '/foo/x' - Note: directory separators are system independent ("/"). - Pathname returned is always absolutized. - """ - if os.path.isabs(ftppath): - p = os.path.normpath(ftppath) - else: - p = os.path.normpath(os.path.join(self.cwd, ftppath)) - # normalize string in a standard web-path notation having '/' - # as separator. - p = p.replace("\\", "/") - # os.path.normpath supports UNC paths (e.g. "//a/b/c") but we - # don't need them. In case we get an UNC path we collapse - # redundant separators appearing at the beginning of the string - while p[:2] == '//': - p = p[1:] - # Anti path traversal: don't trust user input, in the event - # that self.cwd is not absolute, return "/" as a safety measure. - # This is for extra protection, maybe not really necessary. - if not os.path.isabs(p): - p = "/" - return p + Note: directory separators are system independent ("/"). + Pathname returned is always absolutized. + """ + if os.path.isabs(ftppath): + p = os.path.normpath(ftppath) + else: + p = os.path.normpath(os.path.join(self.cwd, ftppath)) + # normalize string in a standard web-path notation having '/' + # as separator. + p = p.replace("\\", "/") + # os.path.normpath supports UNC paths (e.g. "//a/b/c") but we + # don't need them. In case we get an UNC path we collapse + # redundant separators appearing at the beginning of the string + while p[:2] == '//': + p = p[1:] + # Anti path traversal: don't trust user input, in the event + # that self.cwd is not absolute, return "/" as a safety measure. + # This is for extra protection, maybe not really necessary. + if not os.path.isabs(p): + p = "/" + return p - # Ok - def ftp2fs(self, path_orig, data): - path = self.ftpnorm(path_orig) - if path and path=='/': - return None - path2 = filter(None,path.split('/'))[1:] - (cr, uid, pool) = data - res = pool.get('document.directory').get_object(cr, uid, path2[:]) - if not res: - raise OSError(2, 'Not such file or directory.') - return res + # Ok + def ftp2fs(self, path_orig, data): + path = self.ftpnorm(path_orig) + if path and path=='/': + return None + path2 = filter(None,path.split('/'))[1:] + (cr, uid, pool) = data + res = pool.get('document.directory').get_object(cr, uid, path2[:]) + if not res: + raise OSError(2, 'Not such file or directory.') + return res - # Ok - def fs2ftp(self, node): - res = node and ('/' + node.cr.dbname + '/' + node.path) or '/' - return res + # Ok + def fs2ftp(self, node): + res = node and ('/' + node.cr.dbname + '/' + node.path) or '/' + return res - # Ok - def validpath(self, path): - """Check whether the path belongs to user's home directory. - Expected argument is a "real" filesystem pathname. + # Ok + def validpath(self, path): + """Check whether the path belongs to user's home directory. + Expected argument is a "real" filesystem pathname. - If path is a symbolic link it is resolved to check its real - destination. + If path is a symbolic link it is resolved to check its real + destination. - Pathnames escaping from user's root directory are considered - not valid. - """ - return path and True or False + Pathnames escaping from user's root directory are considered + not valid. + """ + return path and True or False - # --- Wrapper methods around open() and tempfile.mkstemp + # --- Wrapper methods around open() and tempfile.mkstemp - # Ok - def create(self, node, objname, mode): - try: - class file_wrapper(StringIO.StringIO): - def __init__(self, sstr='', ressource_id=False, dbname=None, uid=1, name=''): - StringIO.StringIO.__init__(self, sstr) - self.ressource_id = ressource_id - self.name = name - self.dbname = dbname - self.uid = uid - def close(self, *args, **kwargs): - db,pool = pooler.get_db_and_pool(self.dbname) - cr = db.cursor() - uid =self.uid - val = self.getvalue() - val2 = { - 'datas': base64.encodestring(val), - 'file_size': len(val), - } - pool.get('ir.attachment').write(cr, uid, [self.ressource_id], val2) - cr.commit() - StringIO.StringIO.close(self, *args, **kwargs) + # Ok + def create(self, node, objname, mode): + try: + class file_wrapper(StringIO.StringIO): + def __init__(self, sstr='', ressource_id=False, dbname=None, uid=1, name=''): + StringIO.StringIO.__init__(self, sstr) + self.ressource_id = ressource_id + self.name = name + self.dbname = dbname + self.uid = uid + def close(self, *args, **kwargs): + db,pool = pooler.get_db_and_pool(self.dbname) + cr = db.cursor() + uid =self.uid + val = self.getvalue() + val2 = { + 'datas': base64.encodestring(val), + 'file_size': len(val), + } + pool.get('ir.attachment').write(cr, uid, [self.ressource_id], val2) + cr.commit() + StringIO.StringIO.close(self, *args, **kwargs) - cr = node.cr - uid = node.uid - pool = pooler.get_pool(cr.dbname) + cr = node.cr + uid = node.uid + pool = pooler.get_pool(cr.dbname) - fobj = pool.get('ir.attachment') - ext = objname.find('.') >0 and objname.split('.')[1] or False + fobj = pool.get('ir.attachment') + ext = objname.find('.') >0 and objname.split('.')[1] or False - # TODO: test if already exist and modify in this case if node.type=file - ### checked already exits - object2=node and node.object2 or False - object=node and node.object or False - cid=False + # TODO: test if already exist and modify in this case if node.type=file + ### checked already exits + object2=node and node.object2 or False + object=node and node.object or False + cid=False - where=[('name','=',objname)] - if object and (object.type in ('directory','ressource')) or object2: - where.append(('parent_id','=',object.id)) - else: - where.append(('parent_id','=',False)) + where=[('name','=',objname)] + if object and (object.type in ('directory','ressource')) or object2: + where.append(('parent_id','=',object.id)) + else: + where.append(('parent_id','=',False)) - if object2: - where +=[('res_id','=',object2.id),('res_model','=',object2._name)] - cids = fobj.search(cr, uid,where) - if len(cids): - cid=cids[0] + if object2: + where +=[('res_id','=',object2.id),('res_model','=',object2._name)] + cids = fobj.search(cr, uid,where) + if len(cids): + cid=cids[0] - if not cid: - val = { - 'name': objname, - 'datas_fname': objname, - 'datas': '', - 'file_size': 0L, - 'file_type': ext, - } - if object and (object.type in ('directory','ressource')) or not object2: - val['parent_id']= object and object.id or False - partner = False - if object2: - if 'partner_id' in object2 and object2.partner_id.id: - partner = object2.partner_id.id - if object2._name == 'res.partner': - partner = object2.id - val.update( { - 'res_model': object2._name, - 'partner_id': partner, - 'res_id': object2.id - }) - cid = fobj.create(cr, uid, val, context={}) - cr.commit() + if not cid: + val = { + 'name': objname, + 'datas_fname': objname, + 'datas': '', + 'file_size': 0L, + 'file_type': ext, + } + if object and (object.type in ('directory','ressource')) or not object2: + val['parent_id']= object and object.id or False + partner = False + if object2: + if 'partner_id' in object2 and object2.partner_id.id: + partner = object2.partner_id.id + if object2._name == 'res.partner': + partner = object2.id + val.update( { + 'res_model': object2._name, + 'partner_id': partner, + 'res_id': object2.id + }) + cid = fobj.create(cr, uid, val, context={}) + cr.commit() - s = file_wrapper('', cid, cr.dbname, uid, ) - return s - except Exception,e: - print e - raise OSError(1, 'Operation not permited.') + s = file_wrapper('', cid, cr.dbname, uid, ) + return s + except Exception,e: + print e + raise OSError(1, 'Operation not permited.') - # Ok - def open(self, node, mode): - if not node: - raise OSError(1, 'Operation not permited.') - # Reading operation - if node.type=='file': - if not self.isfile(node): - raise OSError(1, 'Operation not permited.') - s = StringIO.StringIO(base64.decodestring(node.object.datas or '')) - s.name = node - return s - elif node.type=='content': - cr = node.cr - uid = node.uid - pool = pooler.get_pool(cr.dbname) - report = pool.get('ir.actions.report.xml').browse(cr, uid, node.content['report_id']['id']) - srv = netsvc.LocalService('report.'+report.report_name) - pdf,pdftype = srv.create(cr, uid, [node.object.id], {}, {}) - s = StringIO.StringIO(pdf) - s.name = node - return s - else: - raise OSError(1, 'Operation not permited.') + # Ok + def open(self, node, mode): + if not node: + raise OSError(1, 'Operation not permited.') + # Reading operation + if node.type=='file': + if not self.isfile(node): + raise OSError(1, 'Operation not permited.') + s = StringIO.StringIO(base64.decodestring(node.object.datas or '')) + s.name = node + return s + elif node.type=='content': + cr = node.cr + uid = node.uid + pool = pooler.get_pool(cr.dbname) + return getattr(pool.get('document.directory.content'), 'process_read_'+node.extension[1:])(cr, uid, node) + else: + raise OSError(1, 'Operation not permited.') - # ok, but need test more + # ok, but need test more - def mkstemp(self, suffix='', prefix='', dir=None, mode='wb'): - """A wrap around tempfile.mkstemp creating a file with a unique - name. Unlike mkstemp it returns an object with a file-like - interface. - """ - raise 'Not Yet Implemented' -# class FileWrapper: -# def __init__(self, fd, name): -# self.file = fd -# self.name = name -# def __getattr__(self, attr): -# return getattr(self.file, attr) + def mkstemp(self, suffix='', prefix='', dir=None, mode='wb'): + """A wrap around tempfile.mkstemp creating a file with a unique + name. Unlike mkstemp it returns an object with a file-like + interface. + """ + raise 'Not Yet Implemented' +# class FileWrapper: +# def __init__(self, fd, name): +# self.file = fd +# self.name = name +# def __getattr__(self, attr): +# return getattr(self.file, attr) # -# text = not 'b' in mode -# # max number of tries to find out a unique file name -# tempfile.TMP_MAX = 50 -# fd, name = tempfile.mkstemp(suffix, prefix, dir, text=text) -# file = os.fdopen(fd, mode) -# return FileWrapper(file, name) +# text = not 'b' in mode +# # max number of tries to find out a unique file name +# tempfile.TMP_MAX = 50 +# fd, name = tempfile.mkstemp(suffix, prefix, dir, text=text) +# file = os.fdopen(fd, mode) +# return FileWrapper(file, name) - text = not 'b' in mode - # for unique file , maintain version if duplicate file - if dir: - cr = dir.cr - uid = dir.uid - pool = pooler.get_pool(cr.dbname) - object=dir and dir.object or False - object2=dir and dir.object2 or False - res=pool.get('ir.attachment').search(cr,uid,[('name','like',prefix),('parent_id','=',object and object.type in ('directory','ressource') and object.id or False),('res_id','=',object2 and object2.id or False),('res_model','=',object2 and object2._name or False)]) - if len(res): - pre = prefix.split('.') - prefix=pre[0] + '.v'+str(len(res))+'.'+pre[1] - #prefix = prefix + '.' - return self.create(dir,suffix+prefix,text) + text = not 'b' in mode + # for unique file , maintain version if duplicate file + if dir: + cr = dir.cr + uid = dir.uid + pool = pooler.get_pool(cr.dbname) + object=dir and dir.object or False + object2=dir and dir.object2 or False + res=pool.get('ir.attachment').search(cr,uid,[('name','like',prefix),('parent_id','=',object and object.type in ('directory','ressource') and object.id or False),('res_id','=',object2 and object2.id or False),('res_model','=',object2 and object2._name or False)]) + if len(res): + pre = prefix.split('.') + prefix=pre[0] + '.v'+str(len(res))+'.'+pre[1] + #prefix = prefix + '.' + return self.create(dir,suffix+prefix,text) - # Ok - def chdir(self, path): - if not path: - self.cwd='/' - return None - if path.type in ('collection','database'): - self.cwd = self.fs2ftp(path) - else: - raise OSError(1, 'Operation not permited.') + # Ok + def chdir(self, path): + if not path: + self.cwd='/' + return None + if path.type in ('collection','database'): + self.cwd = self.fs2ftp(path) + else: + raise OSError(1, 'Operation not permited.') - # Ok - def mkdir(self, node, basename): - """Create the specified directory.""" - if not node: - raise OSError(1, 'Operation not permited.') - try: - object2=node and node.object2 or False - object=node and node.object or False - cr = node.cr - uid = node.uid - pool = pooler.get_pool(cr.dbname) - if node.object and (node.object.type=='ressource') and not node.object2: - raise OSError(1, 'Operation not permited.') - val = { - 'name': basename, - 'ressource_parent_type_id': object and object.ressource_type_id.id or False, - 'ressource_id': object2 and object2.id or False - } - if (object and (object.type in ('directory'))) or not object2: - val['parent_id'] = object and object.id or False - # Check if it alreayd exists ! - pool.get('document.directory').create(cr, uid, val) - cr.commit() - except Exception,e: - print e - raise OSError(1, 'Operation not permited.') + # Ok + def mkdir(self, node, basename): + """Create the specified directory.""" + if not node: + raise OSError(1, 'Operation not permited.') + try: + object2=node and node.object2 or False + object=node and node.object or False + cr = node.cr + uid = node.uid + pool = pooler.get_pool(cr.dbname) + if node.object and (node.object.type=='ressource') and not node.object2: + raise OSError(1, 'Operation not permited.') + val = { + 'name': basename, + 'ressource_parent_type_id': object and object.ressource_type_id.id or False, + 'ressource_id': object2 and object2.id or False + } + if (object and (object.type in ('directory'))) or not object2: + val['parent_id'] = object and object.id or False + # Check if it alreayd exists ! + pool.get('document.directory').create(cr, uid, val) + cr.commit() + except Exception,e: + print e + raise OSError(1, 'Operation not permited.') - # Ok - def close_cr(self, data): - if data: - data[0].close() - return True + # Ok + def close_cr(self, data): + if data: + data[0].close() + return True - def get_cr(self, path): - path = self.ftpnorm(path) - if path=='/': - return None - dbname = path.split('/')[1] - try: - db,pool = pooler.get_db_and_pool(dbname) - except: - raise OSError(1, 'Operation not permited.') - cr = db.cursor() - uid = security.login(dbname, self.username, self.password) - if not uid: - raise OSError(1, 'Operation not permited.') - return cr, uid, pool + def get_cr(self, path): + path = self.ftpnorm(path) + if path=='/': + return None + dbname = path.split('/')[1] + try: + db,pool = pooler.get_db_and_pool(dbname) + except: + raise OSError(1, 'Operation not permited.') + cr = db.cursor() + uid = security.login(dbname, self.username, self.password) + if not uid: + raise OSError(1, 'Operation not permited.') + return cr, uid, pool - # Ok - def listdir(self, path): - """List the content of a directory.""" - class false_node: - object = None - type = 'database' - def __init__(self, db): - self.path = '/'+db + # Ok + def listdir(self, path): + """List the content of a directory.""" + class false_node: + object = None + type = 'database' + def __init__(self, db): + self.path = '/'+db - if path is None: - result = [] - for db in self.db_list(): - result.append(false_node(db)) - return result - return path.children() + if path is None: + result = [] + for db in self.db_list(): + result.append(false_node(db)) + return result + return path.children() - # Ok - def rmdir(self, node): - """Remove the specified directory.""" - cr = node.cr - uid = node.uid - pool = pooler.get_pool(cr.dbname) - object2=node and node.object2 or False - object=node and node.object or False - if object._table_name=='document.directory': - if node.children(): - raise OSError(39, 'Directory not empty.') - res = pool.get('document.directory').unlink(cr, uid, [object.id]) - else: - raise OSError(39, 'Directory not empty.') + # Ok + def rmdir(self, node): + """Remove the specified directory.""" + cr = node.cr + uid = node.uid + pool = pooler.get_pool(cr.dbname) + object2=node and node.object2 or False + object=node and node.object or False + if object._table_name=='document.directory': + if node.children(): + raise OSError(39, 'Directory not empty.') + res = pool.get('document.directory').unlink(cr, uid, [object.id]) + else: + raise OSError(39, 'Directory not empty.') - cr.commit() + cr.commit() - # Ok - def remove(self, node): - """Remove the specified file.""" - cr = node.cr - uid = node.uid - pool = pooler.get_pool(cr.dbname) - object2=node and node.object2 or False - object=node and node.object or False - if not object: - raise OSError(2, 'Not such file or directory.') - if object._table_name=='ir.attachment': - res = pool.get('ir.attachment').unlink(cr, uid, [object.id]) - else: - raise OSError(1, 'Operation not permited.') - cr.commit() + # Ok + def remove(self, node): + """Remove the specified file.""" + cr = node.cr + uid = node.uid + pool = pooler.get_pool(cr.dbname) + object2=node and node.object2 or False + object=node and node.object or False + if not object: + raise OSError(2, 'Not such file or directory.') + if object._table_name=='ir.attachment': + res = pool.get('ir.attachment').unlink(cr, uid, [object.id]) + else: + raise OSError(1, 'Operation not permited.') + cr.commit() - # Ok - def rename(self, src, dst_basedir,dst_basename): - """ - Renaming operation, the effect depends on the src: - * A file: read, create and remove - * A directory: change the parent and reassign childs to ressource - """ - try: - if src.type=='collection': - if src.object._table_name <> 'document.directory': - raise OSError(1, 'Operation not permited.') - result = { - 'directory': [], - 'attachment': [] - } - # Compute all childs to set the new ressource ID - child_ids = [src] - while len(child_ids): - node = child_ids.pop(0) - child_ids += node.children() - if node.type =='collection': - result['directory'].append(node.object.id) - if (not node.object.ressource_id) and node.object2: - raise OSError(1, 'Operation not permited.') - elif node.type =='file': - result['attachment'].append(node.object.id) + # Ok + def rename(self, src, dst_basedir,dst_basename): + """ + Renaming operation, the effect depends on the src: + * A file: read, create and remove + * A directory: change the parent and reassign childs to ressource + """ + try: + if src.type=='collection': + if src.object._table_name <> 'document.directory': + raise OSError(1, 'Operation not permited.') + result = { + 'directory': [], + 'attachment': [] + } + # Compute all childs to set the new ressource ID + child_ids = [src] + while len(child_ids): + node = child_ids.pop(0) + child_ids += node.children() + if node.type =='collection': + result['directory'].append(node.object.id) + if (not node.object.ressource_id) and node.object2: + raise OSError(1, 'Operation not permited.') + elif node.type =='file': + result['attachment'].append(node.object.id) - cr = src.cr - uid = src.uid - pool = pooler.get_pool(cr.dbname) - object2=src and src.object2 or False - object=src and src.object or False - if object2 and not object.ressource_id: - raise OSError(1, 'Operation not permited.') - val = { - 'name':dst_basename, - } - if (dst_basedir.object and (dst_basedir.object.type in ('directory'))) or not dst_basedir.object2: - val['parent_id'] = dst_basedir.object and dst_basedir.object.id or False - else: - val['parent_id'] = False - res = pool.get('document.directory').write(cr, uid, [object.id],val) + cr = src.cr + uid = src.uid + pool = pooler.get_pool(cr.dbname) + object2=src and src.object2 or False + object=src and src.object or False + if object2 and not object.ressource_id: + raise OSError(1, 'Operation not permited.') + val = { + 'name':dst_basename, + } + if (dst_basedir.object and (dst_basedir.object.type in ('directory'))) or not dst_basedir.object2: + val['parent_id'] = dst_basedir.object and dst_basedir.object.id or False + else: + val['parent_id'] = False + res = pool.get('document.directory').write(cr, uid, [object.id],val) - if dst_basedir.object2: - ressource_type_id = pool.get('ir.model').search(cr,uid,[('model','=',dst_basedir.object2._name)])[0] - ressource_id = dst_basedir.object2.id - title = dst_basedir.object2.name - ressource_model = dst_basedir.object2._name - if dst_basedir.object2._name=='res.partner': - partner_id=dst_basedir.object2.id - else: - partner_id= dst_basedir.object2.partner_id and dst_basedir.object2.partner_id.id or False - else: - ressource_type_id = False - ressource_id=False - ressource_model = False - partner_id = False - title = False + if dst_basedir.object2: + ressource_type_id = pool.get('ir.model').search(cr,uid,[('model','=',dst_basedir.object2._name)])[0] + ressource_id = dst_basedir.object2.id + title = dst_basedir.object2.name + ressource_model = dst_basedir.object2._name + if dst_basedir.object2._name=='res.partner': + partner_id=dst_basedir.object2.id + else: + partner_id= dst_basedir.object2.partner_id and dst_basedir.object2.partner_id.id or False + else: + ressource_type_id = False + ressource_id=False + ressource_model = False + partner_id = False + title = False - pool.get('document.directory').write(cr, uid, result['directory'], { - 'ressource_id': ressource_id, - 'ressource_parent_type_id': ressource_type_id - }) - val = { - 'res_id': ressource_id, - 'res_model': ressource_model, - 'title': title, - 'partner_id': partner_id - } - pool.get('ir.attachment').write(cr, uid, result['attachment'], val) - if (not val['res_id']) and result['attachment']: - dst_basedir.cr.execute('update ir_attachment set res_id=NULL where id in ('+','.join(map(str,result['attachment']))+')') + pool.get('document.directory').write(cr, uid, result['directory'], { + 'ressource_id': ressource_id, + 'ressource_parent_type_id': ressource_type_id + }) + val = { + 'res_id': ressource_id, + 'res_model': ressource_model, + 'title': title, + 'partner_id': partner_id + } + pool.get('ir.attachment').write(cr, uid, result['attachment'], val) + if (not val['res_id']) and result['attachment']: + dst_basedir.cr.execute('update ir_attachment set res_id=NULL where id in ('+','.join(map(str,result['attachment']))+')') - cr.commit() - elif src.type=='file': - pool = pooler.get_pool(src.cr.dbname) - val = { - 'partner_id':False, - #'res_id': False, - 'res_model': False, - 'name': dst_basename, - 'datas_fname': dst_basename, - 'title': dst_basename, - } + cr.commit() + elif src.type=='file': + pool = pooler.get_pool(src.cr.dbname) + val = { + 'partner_id':False, + #'res_id': False, + 'res_model': False, + 'name': dst_basename, + 'datas_fname': dst_basename, + 'title': dst_basename, + } - if (dst_basedir.object and (dst_basedir.object.type in ('directory','ressource'))) or not dst_basedir.object2: - val['parent_id'] = dst_basedir.object and dst_basedir.object.id or False - else: - val['parent_id'] = False + if (dst_basedir.object and (dst_basedir.object.type in ('directory','ressource'))) or not dst_basedir.object2: + val['parent_id'] = dst_basedir.object and dst_basedir.object.id or False + else: + val['parent_id'] = False - if dst_basedir.object2: - val['res_model'] = dst_basedir.object2._name - val['res_id'] = dst_basedir.object2.id - val['title'] = dst_basedir.object2.name - if dst_basedir.object2._name=='res.partner': - val['partner_id']=dst_basedir.object2.id - else: - val['partner_id']= dst_basedir.object2.partner_id and dst_basedir.object2.partner_id.id or False - elif src.object.res_id: - # I had to do that because writing False to an integer writes 0 instead of NULL - # change if one day we decide to improve osv/fields.py - dst_basedir.cr.execute('update ir_attachment set res_id=NULL where id=%d', (src.object.id,)) + if dst_basedir.object2: + val['res_model'] = dst_basedir.object2._name + val['res_id'] = dst_basedir.object2.id + val['title'] = dst_basedir.object2.name + if dst_basedir.object2._name=='res.partner': + val['partner_id']=dst_basedir.object2.id + else: + val['partner_id']= dst_basedir.object2.partner_id and dst_basedir.object2.partner_id.id or False + elif src.object.res_id: + # I had to do that because writing False to an integer writes 0 instead of NULL + # change if one day we decide to improve osv/fields.py + dst_basedir.cr.execute('update ir_attachment set res_id=NULL where id=%d', (src.object.id,)) - pool.get('ir.attachment').write(src.cr, src.uid, [src.object.id], val) - src.cr.commit() - elif src.type=='content': - src_file=self.open(src,'r') - dst_file=self.create(dst_basedir,dst_basename,'w') - dst_file.write(src_file.getvalue()) - dst_file.close() - src_file.close() - src.cr.commit() - else: - raise OSError(1, 'Operation not permited.') - except Exception,err: - print err - raise OSError(1,'Operation not permited.') + pool.get('ir.attachment').write(src.cr, src.uid, [src.object.id], val) + src.cr.commit() + elif src.type=='content': + src_file=self.open(src,'r') + dst_file=self.create(dst_basedir,dst_basename,'w') + dst_file.write(src_file.getvalue()) + dst_file.close() + src_file.close() + src.cr.commit() + else: + raise OSError(1, 'Operation not permited.') + except Exception,err: + print err + raise OSError(1,'Operation not permited.') - # Nearly Ok - def stat(self, node): - r = list(os.stat('/')) - if self.isfile(node): - r[0] = 33188 - r[6] = self.getsize(node) - r[7] = self.getmtime(node) - r[8] = self.getmtime(node) - r[9] = self.getmtime(node) - return os.stat_result(r) - lstat = stat + # Nearly Ok + def stat(self, node): + r = list(os.stat('/')) + if self.isfile(node): + r[0] = 33188 + r[6] = self.getsize(node) + r[7] = self.getmtime(node) + r[8] = self.getmtime(node) + r[9] = self.getmtime(node) + return os.stat_result(r) + lstat = stat - # --- Wrapper methods around os.path.* + # --- Wrapper methods around os.path.* - # Ok - def isfile(self, node): - if node and (node.type not in ('collection','database')): - return True - return False + # Ok + def isfile(self, node): + if node and (node.type not in ('collection','database')): + return True + return False - # Ok - def islink(self, path): - """Return True if path is a symbolic link.""" - return False + # Ok + def islink(self, path): + """Return True if path is a symbolic link.""" + return False - # Ok - def isdir(self, node): - """Return True if path is a directory.""" - if node is None: - return True - if node and (node.type in ('collection','database')): - return True - return False + # Ok + def isdir(self, node): + """Return True if path is a directory.""" + if node is None: + return True + if node and (node.type in ('collection','database')): + return True + return False - # Ok - def getsize(self, node): - """Return the size of the specified file in bytes.""" - result = 0L - if node.type=='file': - result = node.object.file_size or 0L - return result + # Ok + def getsize(self, node): + """Return the size of the specified file in bytes.""" + result = 0L + if node.type=='file': + result = node.object.file_size or 0L + return result - # Ok - def getmtime(self, node): - """Return the last modified time as a number of seconds since - the epoch.""" - if node.object and node.type<>'content': - dt = (node.object.write_date or node.object.create_date)[:19] - result = time.mktime(time.strptime(dt, '%Y-%m-%d %H:%M:%S')) - else: - result = time.mktime(time.localtime()) - return result + # Ok + def getmtime(self, node): + """Return the last modified time as a number of seconds since + the epoch.""" + if node.object and node.type<>'content': + dt = (node.object.write_date or node.object.create_date)[:19] + result = time.mktime(time.strptime(dt, '%Y-%m-%d %H:%M:%S')) + else: + result = time.mktime(time.localtime()) + return result - # Ok - def realpath(self, path): - """Return the canonical version of path eliminating any - symbolic links encountered in the path (if they are - supported by the operating system). - """ - return path + # Ok + def realpath(self, path): + """Return the canonical version of path eliminating any + symbolic links encountered in the path (if they are + supported by the operating system). + """ + return path - # Ok - def lexists(self, path): - """Return True if path refers to an existing path, including - a broken or circular symbolic link. - """ - return path and True or False - exists = lexists + # Ok + def lexists(self, path): + """Return True if path refers to an existing path, including + a broken or circular symbolic link. + """ + return path and True or False + exists = lexists - # Ok, can be improved - def glob1(self, dirname, pattern): - """Return a list of files matching a dirname pattern - non-recursively. + # Ok, can be improved + def glob1(self, dirname, pattern): + """Return a list of files matching a dirname pattern + non-recursively. - Unlike glob.glob1 raises exception if os.listdir() fails. - """ - names = self.listdir(dirname) - if pattern[0] != '.': - names = filter(lambda x: x.path[0] != '.', names) - return fnmatch.filter(names, pattern) + Unlike glob.glob1 raises exception if os.listdir() fails. + """ + names = self.listdir(dirname) + if pattern[0] != '.': + names = filter(lambda x: x.path[0] != '.', names) + return fnmatch.filter(names, pattern) - # --- Listing utilities + # --- Listing utilities - # note: the following operations are no more blocking + # note: the following operations are no more blocking - # Ok - def get_list_dir(self, path): - """"Return an iterator object that yields a directory listing - in a form suitable for LIST command. - """ - if self.isdir(path): - listing = self.listdir(path) - #listing.sort() - return self.format_list(path and path.path or '/', listing) - # if path is a file or a symlink we return information about it - elif self.isfile(path): - basedir, filename = os.path.split(path.path) - self.lstat(path) # raise exc in case of problems - return self.format_list(basedir, [filename]) + # Ok + def get_list_dir(self, path): + """"Return an iterator object that yields a directory listing + in a form suitable for LIST command. + """ + if self.isdir(path): + listing = self.listdir(path) + #listing.sort() + return self.format_list(path and path.path or '/', listing) + # if path is a file or a symlink we return information about it + elif self.isfile(path): + basedir, filename = os.path.split(path.path) + self.lstat(path) # raise exc in case of problems + return self.format_list(basedir, [filename]) - # Ok - def get_stat_dir(self, rawline, datacr): - """Return an iterator object that yields a list of files - matching a dirname pattern non-recursively in a form - suitable for STAT command. + # Ok + def get_stat_dir(self, rawline, datacr): + """Return an iterator object that yields a list of files + matching a dirname pattern non-recursively in a form + suitable for STAT command. - - (str) rawline: the raw string passed by client as command - argument. - """ - ftppath = self.ftpnorm(rawline) - if not glob.has_magic(ftppath): - return self.get_list_dir(self.ftp2fs(rawline, datacr)) - else: - basedir, basename = os.path.split(ftppath) - if glob.has_magic(basedir): - return iter(['Directory recursion not supported.\r\n']) - else: - basedir = self.ftp2fs(basedir, datacr) - listing = self.glob1(basedir, basename) - if listing: - listing.sort() - return self.format_list(basedir, listing) + - (str) rawline: the raw string passed by client as command + argument. + """ + ftppath = self.ftpnorm(rawline) + if not glob.has_magic(ftppath): + return self.get_list_dir(self.ftp2fs(rawline, datacr)) + else: + basedir, basename = os.path.split(ftppath) + if glob.has_magic(basedir): + return iter(['Directory recursion not supported.\r\n']) + else: + basedir = self.ftp2fs(basedir, datacr) + listing = self.glob1(basedir, basename) + if listing: + listing.sort() + return self.format_list(basedir, listing) - # Ok - def format_list(self, basedir, listing, ignore_err=True): - """Return an iterator object that yields the entries of given - directory emulating the "/bin/ls -lA" UNIX command output. + # Ok + def format_list(self, basedir, listing, ignore_err=True): + """Return an iterator object that yields the entries of given + directory emulating the "/bin/ls -lA" UNIX command output. - - (str) basedir: the absolute dirname. - - (list) listing: the names of the entries in basedir - - (bool) ignore_err: when False raise exception if os.lstat() - call fails. + - (str) basedir: the absolute dirname. + - (list) listing: the names of the entries in basedir + - (bool) ignore_err: when False raise exception if os.lstat() + call fails. - On platforms which do not support the pwd and grp modules (such - as Windows), ownership is printed as "owner" and "group" as a - default, and number of hard links is always "1". On UNIX - systems, the actual owner, group, and number of links are - printed. + On platforms which do not support the pwd and grp modules (such + as Windows), ownership is printed as "owner" and "group" as a + default, and number of hard links is always "1". On UNIX + systems, the actual owner, group, and number of links are + printed. - This is how output appears to client: + This is how output appears to client: - -rw-rw-rw- 1 owner group 7045120 Sep 02 3:47 music.mp3 - drwxrwxrwx 1 owner group 0 Aug 31 18:50 e-books - -rw-rw-rw- 1 owner group 380 Sep 02 3:40 module.py - """ - for file in listing: - try: - st = self.lstat(file) - except os.error: - if ignore_err: - continue - raise - perms = filemode(st.st_mode) # permissions - nlinks = st.st_nlink # number of links to inode - if not nlinks: # non-posix system, let's use a bogus value - nlinks = 1 - size = st.st_size # file size - uname = "owner" - gname = "group" - # stat.st_mtime could fail (-1) if last mtime is too old - # in which case we return the local time as last mtime - try: - mtime = time.strftime("%b %d %H:%M", time.localtime(st.st_mtime)) - except ValueError: - mtime = time.strftime("%b %d %H:%M") + -rw-rw-rw- 1 owner group 7045120 Sep 02 3:47 music.mp3 + drwxrwxrwx 1 owner group 0 Aug 31 18:50 e-books + -rw-rw-rw- 1 owner group 380 Sep 02 3:40 module.py + """ + for file in listing: + try: + st = self.lstat(file) + except os.error: + if ignore_err: + continue + raise + perms = filemode(st.st_mode) # permissions + nlinks = st.st_nlink # number of links to inode + if not nlinks: # non-posix system, let's use a bogus value + nlinks = 1 + size = st.st_size # file size + uname = "owner" + gname = "group" + # stat.st_mtime could fail (-1) if last mtime is too old + # in which case we return the local time as last mtime + try: + mtime = time.strftime("%b %d %H:%M", time.localtime(st.st_mtime)) + except ValueError: + mtime = time.strftime("%b %d %H:%M") - # formatting is matched with proftpd ls output - yield "%s %3s %-8s %-8s %8s %s %s\r\n" %(perms, nlinks, uname, gname, - size, mtime, file.path.split('/')[-1]) + # formatting is matched with proftpd ls output + yield "%s %3s %-8s %-8s %8s %s %s\r\n" %(perms, nlinks, uname, gname, + size, mtime, file.path.split('/')[-1]) - # Ok - def format_mlsx(self, basedir, listing, perms, facts, ignore_err=True): - """Return an iterator object that yields the entries of a given - directory or of a single file in a form suitable with MLSD and - MLST commands. + # Ok + def format_mlsx(self, basedir, listing, perms, facts, ignore_err=True): + """Return an iterator object that yields the entries of a given + directory or of a single file in a form suitable with MLSD and + MLST commands. - Every entry includes a list of "facts" referring the listed - element. See RFC-3659, chapter 7, to see what every single - fact stands for. + Every entry includes a list of "facts" referring the listed + element. See RFC-3659, chapter 7, to see what every single + fact stands for. - - (str) basedir: the absolute dirname. - - (list) listing: the names of the entries in basedir - - (str) perms: the string referencing the user permissions. - - (str) facts: the list of "facts" to be returned. - - (bool) ignore_err: when False raise exception if os.stat() - call fails. + - (str) basedir: the absolute dirname. + - (list) listing: the names of the entries in basedir + - (str) perms: the string referencing the user permissions. + - (str) facts: the list of "facts" to be returned. + - (bool) ignore_err: when False raise exception if os.stat() + call fails. - Note that "facts" returned may change depending on the platform - and on what user specified by using the OPTS command. + Note that "facts" returned may change depending on the platform + and on what user specified by using the OPTS command. - This is how output could appear to the client issuing - a MLSD request: + This is how output could appear to the client issuing + a MLSD request: - type=file;size=156;perm=r;modify=20071029155301;unique=801cd2; music.mp3 - type=dir;size=0;perm=el;modify=20071127230206;unique=801e33; ebooks - type=file;size=211;perm=r;modify=20071103093626;unique=801e32; module.py - """ - permdir = ''.join([x for x in perms if x not in 'arw']) - permfile = ''.join([x for x in perms if x not in 'celmp']) - if ('w' in perms) or ('a' in perms) or ('f' in perms): - permdir += 'c' - if 'd' in perms: - permdir += 'p' - type = size = perm = modify = create = unique = mode = uid = gid = "" - for basename in listing: - file = os.path.join(basedir, basename) - try: - st = self.stat(file) - except OSError: - if ignore_err: - continue - raise - # type + perm - if stat.S_ISDIR(st.st_mode): - if 'type' in facts: - if basename == '.': - type = 'type=cdir;' - elif basename == '..': - type = 'type=pdir;' - else: - type = 'type=dir;' - if 'perm' in facts: - perm = 'perm=%s;' %permdir - else: - if 'type' in facts: - type = 'type=file;' - if 'perm' in facts: - perm = 'perm=%s;' %permfile - if 'size' in facts: - size = 'size=%s;' %st.st_size # file size - # last modification time - if 'modify' in facts: - try: - modify = 'modify=%s;' %time.strftime("%Y%m%d%H%M%S", - time.localtime(st.st_mtime)) - except ValueError: - # stat.st_mtime could fail (-1) if last mtime is too old - modify = "" - if 'create' in facts: - # on Windows we can provide also the creation time - try: - create = 'create=%s;' %time.strftime("%Y%m%d%H%M%S", - time.localtime(st.st_ctime)) - except ValueError: - create = "" - # UNIX only - if 'unix.mode' in facts: - mode = 'unix.mode=%s;' %oct(st.st_mode & 0777) - if 'unix.uid' in facts: - uid = 'unix.uid=%s;' %st.st_uid - if 'unix.gid' in facts: - gid = 'unix.gid=%s;' %st.st_gid - # We provide unique fact (see RFC-3659, chapter 7.5.2) on - # posix platforms only; we get it by mixing st_dev and - # st_ino values which should be enough for granting an - # uniqueness for the file listed. - # The same approach is used by pure-ftpd. - # Implementors who want to provide unique fact on other - # platforms should use some platform-specific method (e.g. - # on Windows NTFS filesystems MTF records could be used). - if 'unique' in facts: - unique = "unique=%x%x;" %(st.st_dev, st.st_ino) + type=file;size=156;perm=r;modify=20071029155301;unique=801cd2; music.mp3 + type=dir;size=0;perm=el;modify=20071127230206;unique=801e33; ebooks + type=file;size=211;perm=r;modify=20071103093626;unique=801e32; module.py + """ + permdir = ''.join([x for x in perms if x not in 'arw']) + permfile = ''.join([x for x in perms if x not in 'celmp']) + if ('w' in perms) or ('a' in perms) or ('f' in perms): + permdir += 'c' + if 'd' in perms: + permdir += 'p' + type = size = perm = modify = create = unique = mode = uid = gid = "" + for basename in listing: + file = os.path.join(basedir, basename) + try: + st = self.stat(file) + except OSError: + if ignore_err: + continue + raise + # type + perm + if stat.S_ISDIR(st.st_mode): + if 'type' in facts: + if basename == '.': + type = 'type=cdir;' + elif basename == '..': + type = 'type=pdir;' + else: + type = 'type=dir;' + if 'perm' in facts: + perm = 'perm=%s;' %permdir + else: + if 'type' in facts: + type = 'type=file;' + if 'perm' in facts: + perm = 'perm=%s;' %permfile + if 'size' in facts: + size = 'size=%s;' %st.st_size # file size + # last modification time + if 'modify' in facts: + try: + modify = 'modify=%s;' %time.strftime("%Y%m%d%H%M%S", + time.localtime(st.st_mtime)) + except ValueError: + # stat.st_mtime could fail (-1) if last mtime is too old + modify = "" + if 'create' in facts: + # on Windows we can provide also the creation time + try: + create = 'create=%s;' %time.strftime("%Y%m%d%H%M%S", + time.localtime(st.st_ctime)) + except ValueError: + create = "" + # UNIX only + if 'unix.mode' in facts: + mode = 'unix.mode=%s;' %oct(st.st_mode & 0777) + if 'unix.uid' in facts: + uid = 'unix.uid=%s;' %st.st_uid + if 'unix.gid' in facts: + gid = 'unix.gid=%s;' %st.st_gid + # We provide unique fact (see RFC-3659, chapter 7.5.2) on + # posix platforms only; we get it by mixing st_dev and + # st_ino values which should be enough for granting an + # uniqueness for the file listed. + # The same approach is used by pure-ftpd. + # Implementors who want to provide unique fact on other + # platforms should use some platform-specific method (e.g. + # on Windows NTFS filesystems MTF records could be used). + if 'unique' in facts: + unique = "unique=%x%x;" %(st.st_dev, st.st_ino) - yield "%s%s%s%s%s%s%s%s%s %s\r\n" %(type, size, perm, modify, create, - mode, uid, gid, unique, basename) + yield "%s%s%s%s%s%s%s%s%s %s\r\n" %(type, size, perm, modify, create, + mode, uid, gid, unique, basename) diff --git a/addons/document/process/document_process.xml b/addons/document/process/document_process.xml deleted file mode 100644 index 3c37c793ab4..00000000000 --- a/addons/document/process/document_process.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file