diff --git a/addons/.bzrignore b/addons/.bzrignore new file mode 100644 index 00000000000..8d98f9debde --- /dev/null +++ b/addons/.bzrignore @@ -0,0 +1 @@ +.* diff --git a/addons/account_invoice_layout/.project b/addons/account_invoice_layout/.project deleted file mode 100644 index 9fcfcc5ebf0..00000000000 --- a/addons/account_invoice_layout/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - account_invoice_layout - - - - - - org.python.pydev.PyDevBuilder - - - - - - org.python.pydev.pythonNature - - diff --git a/addons/account_invoice_layout/.pydevproject b/addons/account_invoice_layout/.pydevproject deleted file mode 100644 index b4c1448c08b..00000000000 --- a/addons/account_invoice_layout/.pydevproject +++ /dev/null @@ -1,6 +0,0 @@ - - - - -python 2.4 - diff --git a/addons/document/document.py b/addons/document/document.py index 5613cc55958..824607fa2e8 100644 --- a/addons/document/document.py +++ b/addons/document/document.py @@ -36,26 +36,27 @@ import tools from tools.translate import _ import nodes +DMS_ROOT_PATH = tools.config.get('document_path', os.path.join(tools.config['root_path'], 'filestore')) class document_file(osv.osv): _inherit = 'ir.attachment' _rec_name = 'datas_fname' def _get_filestore(self, cr): - return os.path.join(tools.config['root_path'], 'filestore', cr.dbname) + return os.path.join(DMS_ROOT_PATH, cr.dbname) def _data_get(self, cr, uid, ids, name, arg, context): - fbrl = self.browse(cr,uid,ids,context=context) - nctx = nodes.get_node_context(cr,uid,context) + fbrl = self.browse(cr, uid, ids, context=context) + nctx = nodes.get_node_context(cr, uid, context) result = {} bin_size = context.get('bin_size', False) for fbro in fbrl: - fnode = nodes.node_file(None,None,nctx,fbro) + fnode = nodes.node_file(None, None, nctx, fbro) if not bin_size: - data = fnode.get_data(cr,fbro) + data = fnode.get_data(cr, fbro) result[fbro.id] = base64.encodestring(data or '') else: - result[fbro.id] = fnode.get_data_len(cr,fbro) - + result[fbro.id] = fnode.get_data_len(cr, fbro) + return result # @@ -64,10 +65,10 @@ class document_file(osv.osv): def _data_set(self, cr, uid, id, name, value, arg, context): if not value: return True - fbro = self.browse(cr,uid,id,context=context) - nctx = nodes.get_node_context(cr,uid,context) - fnode = nodes.node_file(None,None,nctx,fbro) - res = fnode.set_data(cr,base64.decodestring(value),fbro) + fbro = self.browse(cr, uid, id, context=context) + nctx = nodes.get_node_context(cr, uid, context) + fnode = nodes.node_file(None, None, nctx, fbro) + res = fnode.set_data(cr, base64.decodestring(value), fbro) return res _columns = { @@ -79,138 +80,138 @@ class document_file(osv.osv): 'file_type': fields.char('Content Type', size=32), # If ir.attachment contained any data before document is installed, preserve # the data, don't drop the column! - 'db_datas': fields.binary('Data',oldname='datas'), + 'db_datas': fields.binary('Data', oldname='datas'), 'index_content': fields.text('Indexed Content'), 'write_date': fields.datetime('Date Modified', readonly=True), 'write_uid': fields.many2one('res.users', 'Last Modification User', readonly=True), 'create_date': fields.datetime('Date Created', readonly=True), 'create_uid': fields.many2one('res.users', 'Creator', readonly=True), - 'store_method': fields.selection([('db','Database'),('fs','Filesystem'),('link','Link')], "Storing Method"), - 'datas': fields.function(_data_get,method=True,fnct_inv=_data_set,string='File Content',type="binary", nodrop=True), + 'store_method': fields.selection([('db', 'Database'), ('fs', 'Filesystem'), ('link', 'Link')], "Storing Method"), + 'datas': fields.function(_data_get, method=True, fnct_inv=_data_set, string='File Content', type="binary", nodrop=True), 'store_fname': fields.char('Stored Filename', size=200), 'res_model': fields.char('Attached Model', size=64), #res_model 'res_id': fields.integer('Attached ID'), #res_id 'partner_id':fields.many2one('res.partner', 'Partner', select=1), - 'title': fields.char('Resource Title',size=64), + 'title': fields.char('Resource Title', size=64), } - def __get_def_directory(self,cr,uid, context = None): + def __get_def_directory(self, cr, uid, context=None): dirobj = self.pool.get('document.directory') - return dirobj._get_root_directory(cr,uid,context) + return dirobj._get_root_directory(cr, uid, context) _defaults = { - 'user_id': lambda self,cr,uid,ctx:uid, - 'file_size': lambda self,cr,uid,ctx:0, + 'user_id': lambda self, cr, uid, ctx:uid, + 'file_size': lambda self, cr, uid, ctx:0, 'store_method': lambda *args: 'db', 'parent_id': __get_def_directory } _sql_constraints = [ ('filename_uniq', 'unique (name,parent_id,res_id,res_model)', 'The file name must be unique !') ] - def _check_duplication(self, cr, uid,vals,ids=[],op='create'): - name=vals.get('name',False) - parent_id=vals.get('parent_id',False) - res_model=vals.get('res_model',False) - res_id=vals.get('res_id',0) - if op=='write': - for file in self.browse(cr,uid,ids): + def _check_duplication(self, cr, uid, vals, ids=[], op='create'): + name = vals.get('name', False) + parent_id = vals.get('parent_id', False) + res_model = vals.get('res_model', False) + res_id = vals.get('res_id', 0) + if op == 'write': + for file in self.browse(cr, uid, ids): if not name: - name=file.name + name = file.name if not parent_id: - parent_id=file.parent_id and file.parent_id.id or False + parent_id = file.parent_id and file.parent_id.id or False if not res_model: - res_model=file.res_model and file.res_model or False + res_model = file.res_model and file.res_model or False if not res_id: - res_id=file.res_id and file.res_id or 0 - res=self.search(cr,uid,[('id','<>',file.id),('name','=',name),('parent_id','=',parent_id),('res_model','=',res_model),('res_id','=',res_id)]) + res_id = file.res_id and file.res_id or 0 + res = self.search(cr, uid, [('id', '<>', file.id), ('name', '=', name), ('parent_id', '=', parent_id), ('res_model', '=', res_model), ('res_id', '=', res_id)]) if len(res): return False - if op=='create': - res=self.search(cr,uid,[('name','=',name),('parent_id','=',parent_id),('res_id','=',res_id),('res_model','=',res_model)]) + if op == 'create': + res = self.search(cr, uid, [('name', '=', name), ('parent_id', '=', parent_id), ('res_id', '=', res_id), ('res_model', '=', res_model)]) if len(res): return False return True def copy(self, cr, uid, id, default=None, context=None): if not default: - default ={} + default = {} if 'name' not in default: name = self.read(cr, uid, [id])[0]['name'] - default.update({'name': name+ " (copy)"}) - return super(document_file,self).copy(cr,uid,id,default,context) + default.update({'name': name + " (copy)"}) + return super(document_file, self).copy(cr, uid, id, default, context) def write(self, cr, uid, ids, vals, context=None): - res=self.search(cr,uid,[('id','in',ids)]) + res = self.search(cr, uid, [('id', 'in', ids)]) if not len(res): return False - if not self._check_duplication(cr,uid,vals,ids,'write'): + if not self._check_duplication(cr, uid, vals, ids, 'write'): raise osv.except_osv(_('ValidateError'), _('File name must be unique!')) - result = super(document_file,self).write(cr,uid,ids,vals,context=context) + result = super(document_file, self).write(cr, uid, ids, vals, context=context) cr.commit() return result def create(self, cr, uid, vals, context=None): if not context: context = {} - vals['title']=vals['name'] - vals['parent_id'] = context.get('parent_id',False) or vals.get('parent_id',False) - if not vals.get('res_id', False) and context.get('default_res_id',False): - vals['res_id']=context.get('default_res_id',False) - if not vals.get('res_model', False) and context.get('default_res_model',False): - vals['res_model']=context.get('default_res_model',False) - if vals.get('res_id', False) and vals.get('res_model',False): - obj_model=self.pool.get(vals['res_model']) + vals['title'] = vals['name'] + vals['parent_id'] = context.get('parent_id', False) or vals.get('parent_id', False) + if not vals.get('res_id', False) and context.get('default_res_id', False): + vals['res_id'] = context.get('default_res_id', False) + if not vals.get('res_model', False) and context.get('default_res_model', False): + vals['res_model'] = context.get('default_res_model', False) + if vals.get('res_id', False) and vals.get('res_model', False): + obj_model = self.pool.get(vals['res_model']) result = obj_model.read(cr, uid, [vals['res_id']], context=context) if len(result): - obj=result[0] - if obj.get('name',False): - vals['title'] = (obj.get('name',''))[:60] - if obj_model._name=='res.partner': - vals['partner_id']=obj['id'] - elif obj.get('address_id',False): - if isinstance(obj['address_id'],tuple) or isinstance(obj['address_id'],list): - address_id=obj['address_id'][0] + obj = result[0] + if obj.get('name', False): + vals['title'] = (obj.get('name', ''))[:60] + if obj_model._name == 'res.partner': + vals['partner_id'] = obj['id'] + elif obj.get('address_id', False): + if isinstance(obj['address_id'], tuple) or isinstance(obj['address_id'], list): + address_id = obj['address_id'][0] else: - address_id=obj['address_id'] - address=self.pool.get('res.partner.address').read(cr,uid,[address_id],context=context) + address_id = obj['address_id'] + address = self.pool.get('res.partner.address').read(cr, uid, [address_id], context=context) if len(address): - vals['partner_id']=address[0]['partner_id'][0] or False - elif obj.get('partner_id',False): - if isinstance(obj['partner_id'],tuple) or isinstance(obj['partner_id'],list): - vals['partner_id']=obj['partner_id'][0] + vals['partner_id'] = address[0]['partner_id'][0] or False + elif obj.get('partner_id', False): + if isinstance(obj['partner_id'], tuple) or isinstance(obj['partner_id'], list): + vals['partner_id'] = obj['partner_id'][0] else: - vals['partner_id']=obj['partner_id'] + vals['partner_id'] = obj['partner_id'] - datas=None - if vals.get('link',False) : + datas = None + if vals.get('link', False) : import urllib - datas=base64.encodestring(urllib.urlopen(vals['link']).read()) + datas = base64.encodestring(urllib.urlopen(vals['link']).read()) else: - datas = vals.get('datas',False) + datas = vals.get('datas', False) - vals['file_size']= datas and len(datas) or 0 - if not self._check_duplication(cr,uid,vals): + vals['file_size'] = datas and len(datas) or 0 + if not self._check_duplication(cr, uid, vals): raise osv.except_osv(_('ValidateError'), _('File name must be unique!')) - result = super(document_file,self).create(cr, uid, vals, context) + result = super(document_file, self).create(cr, uid, vals, context) cr.commit() return result - def unlink(self,cr, uid, ids, context={}): + def unlink(self, cr, uid, ids, context={}): stor = self.pool.get('document.storage') - unres= [] + unres = [] # We have to do the unlink in 2 stages: prepare a list of actual # files to be unlinked, update the db (safer to do first, can be # rolled back) and then unlink the files. The list wouldn't exist # after we discard the objects - + for f in self.browse(cr, uid, ids, context): # TODO: update the node cache - r = stor.prepare_unlink(cr,uid,f.parent_id.storage_id, f) + r = stor.prepare_unlink(cr, uid, f.parent_id.storage_id, f) if r: unres.append(r) res = super(document_file, self).unlink(cr, uid, ids, context) - stor.do_unlink(cr,uid,unres) + stor.do_unlink(cr, uid, unres) return res - + document_file() diff --git a/addons/document/document_storage.py b/addons/document/document_storage.py index d09bc62d325..2b50e7a27c9 100644 --- a/addons/document/document_storage.py +++ b/addons/document/document_storage.py @@ -34,6 +34,8 @@ import string import netsvc from content_index import cntIndex +DMS_ROOT_PATH = tools.config.get('document_path', os.path.join(tools.config.get('root_path'), 'filestore')) + """ The algorithm of data storage @@ -71,12 +73,12 @@ def random_name(): name = "".join(d) return name -INVALID_CHARS={'*':str(hash('*')), '|':str(hash('|')) , "\\":str(hash("\\")), '/':'__', ':':str(hash(':')), '"':str(hash('"')), '<':str(hash('<')) , '>':str(hash('>')) , '?':str(hash('?'))} +INVALID_CHARS = {'*':str(hash('*')), '|':str(hash('|')) , "\\":str(hash("\\")), '/':'__', ':':str(hash(':')), '"':str(hash('"')), '<':str(hash('<')) , '>':str(hash('>')) , '?':str(hash('?'))} def create_directory(path): dir_name = random_name() - path = os.path.join(path,dir_name) + path = os.path.join(path, dir_name) os.makedirs(path) return dir_name @@ -103,19 +105,18 @@ class document_storage(osv.osv): 'user_id': fields.many2one('res.users', 'Owner'), 'group_ids': fields.many2many('res.groups', 'document_directory_group_rel', 'item_id', 'group_id', 'Groups'), 'dir_ids': fields.one2many('document.directory', 'parent_id', 'Directories'), - 'type': fields.selection([('db','Database'),('filestore','Internal File storage'), - ('realstore','External file storage'), ('virtual','Virtual storage')], 'Type', required=True), - 'path': fields.char('Path',size=250,select=1,help="For file storage, the root path of the storage"), - 'online': fields.boolean('Online',help="If not checked, media is currently offline and its contents not available", required=True), + 'type': fields.selection([('db', 'Database'), ('filestore', 'Internal File storage'), + ('realstore', 'External file storage'), ('virtual', 'Virtual storage')], 'Type', required=True), + 'path': fields.char('Path', size=250, select=1, help="For file storage, the root path of the storage"), + 'online': fields.boolean('Online', help="If not checked, media is currently offline and its contents not available", required=True), 'readonly': fields.boolean('Read Only', help="If set, media is for reading only"), } - def _get_rootpath(self,cr,uid,context=None): - from tools import config - return os.path.join(tools.config['root_path'], 'filestore', cr.dbname) + def _get_rootpath(self, cr, uid, context=None): + return os.path.join(DMS_ROOT_PATH, cr.dbname) _defaults = { - 'user_id': lambda self,cr,uid,ctx: uid, + 'user_id': lambda self, cr, uid, ctx: uid, 'online': lambda *args: True, 'readonly': lambda *args: False, # Note: the defaults below should only be used ONCE for the default @@ -127,22 +128,22 @@ class document_storage(osv.osv): # SQL note: a path = NULL doesn't have to be unique. ('path_uniq', 'UNIQUE(type,path)', "The storage path must be unique!") ] - - def get_data(self, cr,uid, id, file_node,context = None, fil_obj = None): + + def get_data(self, cr, uid, id, file_node, context=None, fil_obj=None): """ retrieve the contents of some file_node having storage_id = id optionally, fil_obj could point to the browse object of the file (ir.attachment) """ if not context: context = {} - boo = self.browse(cr,uid,id,context) + boo = self.browse(cr, uid, id, context) if fil_obj: ira = fil_obj else: - ira = self.pool.get('ir.attachment').browse(cr,uid, file_node.file_id, context=context) - return self.__get_data_3(cr,uid,boo, ira, context) - - def __get_data_3(self,cr,uid, boo, ira, context): + ira = self.pool.get('ir.attachment').browse(cr, uid, file_node.file_id, context=context) + return self.__get_data_3(cr, uid, boo, ira, context) + + def __get_data_3(self, cr, uid, boo, ira, context): if not boo.online: raise RuntimeError('media offline') if boo.type == 'filestore': @@ -150,17 +151,17 @@ class document_storage(osv.osv): # On a migrated db, some files may have the wrong storage type # try to fix their directory. if ira.file_size: - netsvc.Logger().notifyChannel('document',netsvc.LOG_WARNING,"ir.attachment #%d does not have a filename, but is at filestore, fix it!" %ira.id) + netsvc.Logger().notifyChannel('document', netsvc.LOG_WARNING, "ir.attachment #%d does not have a filename, but is at filestore, fix it!" % ira.id) return None - fpath = os.path.join(boo.path,ira.store_fname) - print "Trying to read \"%s\".."% fpath - return file(fpath,'rb').read() + fpath = os.path.join(boo.path, ira.store_fname) + print "Trying to read \"%s\".." % fpath + return file(fpath, 'rb').read() elif boo.type == 'db': # TODO: we need a better api for large files if ira.db_datas: - out=base64.decodestring(ira.db_datas) + out = base64.decodestring(ira.db_datas) else: - out='' + out = '' return out elif boo.type == 'realstore': # fpath = os.path.join(boo.path, @@ -168,23 +169,23 @@ class document_storage(osv.osv): else: raise TypeError("No %s storage" % boo.type) - def set_data(self, cr,uid, id, file_node, data, context = None, fil_obj = None): + def set_data(self, cr, uid, id, file_node, data, context=None, fil_obj=None): """ store the data. This function MUST be used from an ir.attachment. It wouldn't make sense to store things persistently for other types (dynamic). """ if not context: context = {} - boo = self.browse(cr,uid,id,context) + boo = self.browse(cr, uid, id, context) logger = netsvc.Logger() if fil_obj: ira = fil_obj else: - ira = self.pool.get('ir.attachment').browse(cr,uid, file_node.file_id, context=context) - + ira = self.pool.get('ir.attachment').browse(cr, uid, file_node.file_id, context=context) + if not boo.online: raise RuntimeError('media offline') - logger.notifyChannel('document',netsvc.LOG_DEBUG,"Store data for ir.attachment #%d" %ira.id) + logger.notifyChannel('document', netsvc.LOG_DEBUG, "Store data for ir.attachment #%d" % ira.id) store_fname = None fname = None if boo.type == 'filestore': @@ -192,32 +193,32 @@ class document_storage(osv.osv): try: flag = None # This can be improved - if os.path.isdir(path): + if os.path.isdir(path): for dirs in os.listdir(path): - if os.path.isdir(os.path.join(path,dirs)) and len(os.listdir(os.path.join(path,dirs)))<4000: + if os.path.isdir(os.path.join(path, dirs)) and len(os.listdir(os.path.join(path, dirs))) < 4000: flag = dirs break flag = flag or create_directory(path) filename = random_name() fname = os.path.join(path, flag, filename) - fp = file(fname,'wb') + fp = file(fname, 'wb') fp.write(data) fp.close() - logger.notifyChannel('document',netsvc.LOG_DEBUG,"Saved data to %s" % fname) + logger.notifyChannel('document', netsvc.LOG_DEBUG, "Saved data to %s" % fname) filesize = len(data) # os.stat(fname).st_size - store_fname = os.path.join(flag,filename) - + store_fname = os.path.join(flag, filename) + # TODO Here, an old file would be left hanging. - except Exception,e : - netsvc.Logger().notifyChannel('document',netsvc.LOG_WARNING,"Couldn't save data: %s" %str(e)) + except Exception, e : + netsvc.Logger().notifyChannel('document', netsvc.LOG_WARNING, "Couldn't save data: %s" % str(e)) raise except_orm(_('Error!'), str(e)) elif boo.type == 'db': filesize = len(data) # will that work for huge data? TODO - out=base64.encodestring(data) + out = base64.encodestring(data) cr.execute('UPDATE ir_attachment SET db_datas = %s WHERE id = %s', - ( out, file_node.file_id )) + (out, file_node.file_id)) else: raise TypeError("No %s storage" % boo.type) @@ -226,9 +227,9 @@ class document_storage(osv.osv): icont = '' mime = ira.file_type try: - mime,icont = cntIndex.doIndex(data, ira.datas_fname, - ira.file_type or None,fname) - except Exception,e: + mime, icont = cntIndex.doIndex(data, ira.datas_fname, + ira.file_type or None, fname) + except Exception, e: logger.notifyChannel('document', netsvc.LOG_DEBUG, 'Cannot index file: %s' % str(e)) pass @@ -236,46 +237,46 @@ class document_storage(osv.osv): # to write the fname and size, and update them in the db concurrently. # We cannot use a write() here, because we are already in one. cr.execute('UPDATE ir_attachment SET store_fname = %s, file_size = %s, index_content = %s, file_type = %s WHERE id = %s', - (store_fname, filesize, ustr(icont), mime, file_node.file_id )) + (store_fname, filesize, ustr(icont), mime, file_node.file_id)) file_node.content_length = filesize file_node.content_type = mime return True - except Exception,e : - netsvc.Logger().notifyChannel('document',netsvc.LOG_WARNING,"Couldn't save data: %s" %str(e)) + except Exception, e : + netsvc.Logger().notifyChannel('document', netsvc.LOG_WARNING, "Couldn't save data: %s" % str(e)) # should we really rollback once we have written the actual data? # at the db case (only), that rollback would be safe raise except_orm(_('Error at doc write!'), str(e)) - def prepare_unlink(self,cr,uid,storage_bo, fil_bo): + def prepare_unlink(self, cr, uid, storage_bo, fil_bo): """ Before we unlink a file (fil_boo), prepare the list of real files that have to be removed, too. """ - + if not storage_bo.online: raise RuntimeError('media offline') - + if storage_bo.type == 'filestore': fname = fil_bo.store_fname if not fname: return None path = storage_bo.path - return ( storage_bo.id, 'file', os.path.join(path,fname)) + return (storage_bo.id, 'file', os.path.join(path, fname)) elif storage_bo.type == 'db': return None else: raise TypeError("No %s storage" % boo.type) - def do_unlink(self, cr,uid,unres): + def do_unlink(self, cr, uid, unres): for id, ktype, fname in unres: if ktype == 'file': try: os.unlink(fname) - except Exception,e: - netsvc.Logger().notifyChannel('document',netsvc.LOG_WARNING,"Could not remove file %s, please remove manually." % fname) + except Exception, e: + netsvc.Logger().notifyChannel('document', netsvc.LOG_WARNING, "Could not remove file %s, please remove manually." % fname) else: - netsvc.Logger().notifyChannel('document',netsvc.LOG_WARNING,"Unknown unlink key %s" % ktype) - + netsvc.Logger().notifyChannel('document', netsvc.LOG_WARNING, "Unknown unlink key %s" % ktype) + return True - + document_storage() diff --git a/addons/document_ftp/ftpserver/__init__.py b/addons/document_ftp/ftpserver/__init__.py index 056782e7c1a..481274add93 100644 --- a/addons/document_ftp/ftpserver/__init__.py +++ b/addons/document_ftp/ftpserver/__init__.py @@ -24,11 +24,15 @@ import ftpserver import authorizer import abstracted_fs import netsvc - from tools import config from tools.misc import detect_ip_addr -HOST = '' -PORT = 8021 + +if detect_ip_addr: + HOST = config.get('ftp_server_host', detect_ip_addr()) +else: + HOST = config.get('ftp_server_host', '127.0.0.1') + +PORT = int(config.get('ftp_server_port', '8021')) PASSIVE_PORTS = None pps = config.get('ftp_server_passive_ports', '').split(':') if len(pps) == 2: @@ -52,14 +56,15 @@ class ftp_server(threading.Thread): ftpserver.logline = lambda msg: None ftpserver.logerror = lambda msg: self.log(netsvc.LOG_ERROR, msg) - HOST = config.get('ftp_server_address', detect_ip_addr()) - PORT = int(config.get('ftp_server_port', '8021')) - address = (HOST, PORT) - ftpd = ftpserver.FTPServer(address, ftpserver.FTPHandler) + ftpd = ftpserver.FTPServer((HOST, PORT), ftpserver.FTPHandler) ftpd.serve_forever() -ds = ftp_server() -ds.start() +if HOST.lower() == 'none': + netsvc.Logger().notifyChannel("FTP", netsvc.LOG_INFO, "\n Server FTP Not Started\n") +else: + netsvc.Logger().notifyChannel("FTP", netsvc.LOG_INFO, "\n Serving FTP on %s:%s\n" % (HOST, PORT)) + ds = ftp_server() + ds.start() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: