diff --git a/document_ftp/README.rst b/document_ftp/README.rst new file mode 100644 index 00000000..da59afbf --- /dev/null +++ b/document_ftp/README.rst @@ -0,0 +1,6 @@ +This is a support FTP Interface with document management system. +================================================================ + +With this module you would not only be able to access documents through OpenERP +but you would also be able to connect with them through the file system using the +FTP client. diff --git a/document_ftp/__init__.py b/document_ftp/__init__.py new file mode 100644 index 00000000..098e6cb7 --- /dev/null +++ b/document_ftp/__init__.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). +# +# ThinkOpen Solutions Brasil (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from . import ftpserver +from . import wizard +from . import res_config + +post_load = ftpserver.start_server + diff --git a/document_ftp/__openerp__.py b/document_ftp/__openerp__.py new file mode 100644 index 00000000..1bb322da --- /dev/null +++ b/document_ftp/__openerp__.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). + +# ThinkOpen Solutions Brasil (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + + +{ + 'name': 'Shared Repositories (FTP)', + 'version': '8.0.0.0.1', + 'category': 'Knowledge Management', + 'author': 'OpenERP SA', + 'website': 'http://www.openerp.com', + 'depends': ['base', 'document'], + 'data': [ + 'wizard/ftp_configuration_view.xml', + 'wizard/ftp_browse_view.xml', + 'security/ir.model.access.csv', + 'res_config_view.xml', + ], + 'demo': [], + 'test': [ + 'test/document_ftp_test2.yml', + 'test/document_ftp_test4.yml', + ], + 'installable': True, + 'auto_install': False, + 'images': ['images/1_configure_ftp.jpeg', 'images/2_document_browse.jpeg', 'images/3_document_ftp.jpeg'], + 'post_load': 'post_load', +} + diff --git a/document_ftp/ftpserver/__init__.py b/document_ftp/ftpserver/__init__.py new file mode 100644 index 00000000..2d55be57 --- /dev/null +++ b/document_ftp/ftpserver/__init__.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). + +# ThinkOpen Solutions Brasil (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +import threading +import logging + +import authorizer +import abstracted_fs +import ftpserver + +import openerp +from openerp.tools import config +_logger = logging.getLogger(__name__) +import socket + +def start_server(): + if openerp.multi_process: + _logger.info("FTP disabled in multiprocess mode") + return + ip_address = ([(s.connect(('8.8.8.8', 80)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]) + if not ip_address: + ip_address = '127.0.0.1' + HOST = config.get('ftp_server_host', str(ip_address)) + PORT = int(config.get('ftp_server_port', '8021')) + PASSIVE_PORTS = None + pps = config.get('ftp_server_passive_ports', '').split(':') + if len(pps) == 2: + PASSIVE_PORTS = int(pps[0]), int(pps[1]) + + class ftp_server(threading.Thread): + + def run(self): + autho = authorizer.authorizer() + ftpserver.FTPHandler.authorizer = autho + ftpserver.max_cons = 300 + ftpserver.max_cons_per_ip = 50 + ftpserver.FTPHandler.abstracted_fs = abstracted_fs.abstracted_fs + if PASSIVE_PORTS: + ftpserver.FTPHandler.passive_ports = PASSIVE_PORTS + + ftpserver.log = lambda msg: _logger.info(msg) + ftpserver.logline = lambda msg: None + ftpserver.logerror = lambda msg: _logger.error(msg) + + ftpd = ftpserver.FTPServer((HOST, PORT), ftpserver.FTPHandler) + ftpd.serve_forever() + + if HOST.lower() == 'none': + _logger.info("\n Server FTP Not Started\n") + else: + _logger.info("\n Serving FTP on %s:%s\n" % (HOST, PORT)) + ds = ftp_server() + ds.daemon = True + ds.start() diff --git a/document_ftp/ftpserver/abstracted_fs.py b/document_ftp/ftpserver/abstracted_fs.py new file mode 100644 index 00000000..9d611f85 --- /dev/null +++ b/document_ftp/ftpserver/abstracted_fs.py @@ -0,0 +1,665 @@ +# -*- encoding: utf-8 -*- + +import os +import time +from tarfile import filemode +import logging +import errno +import openerp +import glob +import fnmatch + +from openerp import pooler, netsvc, sql_db +from openerp.service import security +from openerp.osv import osv + +from openerp.addons.document.document import get_node_context + +def _get_month_name(month): + month = int(month) + if month == 1:return 'Jan' + elif month == 2:return 'Feb' + elif month == 3:return 'Mar' + elif month == 4:return 'Apr' + elif month == 5:return 'May' + elif month == 6:return 'Jun' + elif month == 7:return 'Jul' + elif month == 8:return 'Aug' + elif month == 9:return 'Sep' + elif month == 10:return 'Oct' + elif month == 11:return 'Nov' + elif month == 12:return 'Dec' + +from ftpserver import _to_decode, _to_unicode + + +class abstracted_fs(object): + """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. + + Instance attributes: + - (str) root: the user home directory. + - (str) cwd: the current working directory. + - (str) rnfr: source file to be renamed. + + """ + + def __init__(self): + self.root = None + self.cwd = '/' + self.cwd_node = None + self.rnfr = None + self._log = logging.getLogger(__name__) + + # Ok + def db_list(self): + """Get the list of available databases, with FTPd support + """ + #======================================================================= + # s = netsvc.ExportService.getService('db') + # result = s.exp_list(document=True) + #======================================================================= + result = openerp.service.db.exp_list(True) + # yogesh + self.db_name_list = [] + for db_name in result: + db, cr = None, None + try: + try: + db = sql_db.db_connect(db_name) + cr = db.cursor() + cr.execute("SELECT 1 FROM pg_class WHERE relkind = 'r' AND relname = 'ir_module_module'") + if not cr.fetchone(): + continue + + cr.execute("SELECT id FROM ir_module_module WHERE name = 'document_ftp' AND state IN ('installed', 'to install', 'to upgrade') ") + res = cr.fetchone() + if res and len(res): + self.db_name_list.append(db_name) + cr.commit() + except Exception: + self._log.warning('Cannot use db "%s".', db_name) + finally: + if cr is not None: + cr.close() + return self.db_name_list + + def ftpnorm(self, ftppath): + """Normalize a "virtual" ftp pathname (tipically the raw string + coming from client). + + Pathname returned is relative!. + """ + p = os.path.normpath(ftppath) + # normalize string in a standard web-path notation having '/' + # as separator. xrg: is that really in the spec? + 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:] + if p == '.': + return '' + return p + + def get_cwd(self): + """ return the cwd, decoded in utf""" + return _to_decode(self.cwd) + + def ftp2fs(self, path_orig, data): + raise DeprecationWarning() + + def fs2ftp(self, node): + """ Return the string path of a node, in ftp form + """ + res = '/' + if node: + paths = node.full_path() + res = '/' + node.context.dbname + '/' + \ + _to_decode(os.path.join(*paths)) + + return res + + def validpath(self, path): + """Check whether the path belongs to user's home directory. + Expected argument is a datacr tuple + """ + # TODO: are we called for "/" ? + return isinstance(path, tuple) and path[1] and True or False + + # --- Wrapper methods around open() and tempfile.mkstemp + + def create(self, datacr, objname, mode): + """ Create a children file-node under node, open it + @return open node_descriptor of the created node + """ + objname = _to_unicode(objname) + cr , node, rem = datacr + try: + child = node.child(cr, objname) + if child: + if child.type not in ('file', 'content'): + raise OSError(1, 'Operation is not permitted.') + + ret = child.open_data(cr, mode) + cr.commit() + assert ret, "Cannot create descriptor for %r: %r." % (child, ret) + return ret + except EnvironmentError: + raise + except Exception: + self._log.exception('Cannot locate item %s at node %s.', objname, repr(node)) + pass + + try: + child = node.create_child(cr, objname, data=None) + ret = child.open_data(cr, mode) + assert ret, "Cannot create descriptor for %r." % child + cr.commit() + return ret + except EnvironmentError: + raise + except Exception: + self._log.exception('Cannot create item %s at node %s.', objname, repr(node)) + raise OSError(1, 'Operation is not permitted.') + + def open(self, datacr, mode): + if not (datacr and datacr[1]): + raise OSError(1, 'Operation is not permitted.') + # Reading operation + cr, node, rem = datacr + try: + res = node.open_data(cr, mode) + cr.commit() + except TypeError: + raise IOError(errno.EINVAL, "No data.") + return res + + # 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 NotImplementedError # TODO + + 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(node.context.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] + return self.create(dir, suffix + prefix, text) + + + + # Ok + def chdir(self, datacr): + if (not datacr) or datacr == (None, None, None): + self.cwd = '/' + self.cwd_node = None + return None + if not datacr[1]: + raise OSError(1, 'Operation is not permitted.') + if datacr[1].type not in ('collection', 'database'): + raise OSError(2, 'Path is not a directory.') + self.cwd = '/' + datacr[1].context.dbname + '/' + self.cwd += '/'.join(datacr[1].full_path()) + self.cwd_node = datacr[1] + + # Ok + def mkdir(self, datacr, basename): + """Create the specified directory.""" + cr, node, rem = datacr or (None, None, None) + if not node: + raise OSError(1, 'Operation is not permitted.') + + try: + basename = _to_unicode(basename) + cdir = node.create_child_collection(cr, basename) + self._log.debug("Created child dir: %r", cdir) + cr.commit() + except Exception: + self._log.exception('Cannot create dir "%s" at node %s.', basename, repr(node)) + raise OSError(1, 'Operation is not permitted.') + + def close_cr(self, data): + if data and data[0]: + data[0].close() + return True + + def get_cr(self, pathname): + raise DeprecationWarning() + + def get_crdata(self, line, mode='file'): + """ Get database cursor, node and remainder data, for commands + + This is the helper function that will prepare the arguments for + any of the subsequent commands. + It returns a tuple in the form of: + @code ( cr, node, rem_path=None ) + + @param line An absolute or relative ftp path, as passed to the cmd. + @param mode A word describing the mode of operation, so that this + function behaves properly in the different commands. + """ + path = self.ftpnorm(line) + if self.cwd_node is None: + if not os.path.isabs(path): + path = os.path.join(self.root, path) + + if path == '/' and mode in ('list', 'cwd'): + return (None, None, None) + + if path == '..': path = self.cwd + '/..' + path = _to_unicode(os.path.normpath(path)) # again, for '/db/../ss' + if path == '.': path = '' + + if os.path.isabs(path) and self.cwd_node is not None \ + and path.startswith(self.cwd): + # make relative, so that cwd_node is used again + path = path[len(self.cwd):] + if path.startswith('/'): + path = path[1:] + + p_parts = path.split(os.sep) + + assert '..' not in p_parts + + rem_path = None + if mode in ('create',): + rem_path = p_parts[-1] + p_parts = p_parts[:-1] + + if os.path.isabs(path): + # we have to start from root, again + while p_parts and p_parts[0] == '': + p_parts = p_parts[1:] + # self._log.debug("Path parts: %r ", p_parts) + if not p_parts: + raise IOError(errno.EPERM, 'Cannot perform operation at root directory.') + dbname = p_parts[0] + if dbname not in self.db_list(): + raise IOError(errno.ENOENT, 'Invalid database path: %s.' % dbname) + try: + db = pooler.get_db(dbname) + except Exception: + raise OSError(1, 'Database cannot be used.') + cr = db.cursor() + try: + uid = security.login(dbname, self.username, self.password) + except Exception: + cr.close() + raise + if not uid: + cr.close() + raise OSError(2, 'Authentification required.') + n = get_node_context(cr, uid, {}) + node = n.get_uri(cr, p_parts[1:]) + return (cr, node, rem_path) + else: + # we never reach here if cwd_node is not set + if p_parts and p_parts[-1] == '': + p_parts = p_parts[:-1] + cr, uid = self.get_node_cr_uid(self.cwd_node) + if p_parts: + node = self.cwd_node.get_uri(cr, p_parts) + else: + node = self.cwd_node + if node is False and mode not in ('???'): + cr.close() + raise IOError(errno.ENOENT, 'Path does not exist.') + return (cr, node, rem_path) + + def get_node_cr_uid(self, node): + """ Get cr, uid, pool from a node + """ + assert node + db = pooler.get_db(node.context.dbname) + return db.cursor(), node.context.uid + + def get_node_cr(self, node): + """ Get the cursor for the database of a node + + The cursor is the only thing that a node will not store + persistenly, so we have to obtain a new one for each call. + """ + return self.get_node_cr_uid(node)[0] + + def listdir(self, datacr): + """List the content of a directory.""" + class false_node(object): + write_date = 0.0 + create_date = 0.0 + unixperms = 040550 + content_length = 0L + uuser = 'root' + ugroup = 'root' + type = 'database' + + def __init__(self, db): + self.path = db + + if datacr[1] is None: + result = [] + for db in self.db_list(): + try: + result.append(false_node(db)) + except osv.except_osv: + pass + return result + cr, node, rem = datacr + res = node.children(cr) + return res + + def rmdir(self, datacr): + """Remove the specified directory.""" + cr, node, rem = datacr + assert node + node.rmcol(cr) + cr.commit() + + def remove(self, datacr): + assert datacr[1] + if datacr[1].type == 'collection': + return self.rmdir(datacr) + elif datacr[1].type == 'file': + return self.rmfile(datacr) + raise OSError(1, 'Operation is not permitted.') + + def rmfile(self, datacr): + """Remove the specified file.""" + assert datacr[1] + cr = datacr[0] + datacr[1].rm(cr) + cr.commit() + + def rename(self, src, datacr): + """ Renaming operation, the effect depends on the src: + * A file: read, create and remove + * A directory: change the parent and reassign children to ressource + """ + cr = datacr[0] + try: + nname = _to_unicode(datacr[2]) + ret = src.move_to(cr, datacr[1], new_name=nname) + # API shouldn't wait for us to write the object + assert (ret is True) or (ret is False) + cr.commit() + except EnvironmentError: + raise + except Exception: + self._log.exception('Cannot rename "%s" to "%s" at "%s".', src, datacr[2], datacr[1]) + raise OSError(1, 'Operation is not permitted.') + + def stat(self, node): + raise NotImplementedError() + + # --- Wrapper methods around os.path.* + + # Ok + def isfile(self, node): + if node and (node.type in ('file', 'content')): + return True + return False + + # Ok + def islink(self, path): + """Return True if path is a symbolic link.""" + return False + + 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 + + def getsize(self, datacr): + """Return the size of the specified file in bytes.""" + if not (datacr and datacr[1]): + raise IOError(errno.ENOENT, "No such file or directory.") + if datacr[1].type in ('file', 'content'): + return datacr[1].get_data_len(datacr[0]) or 0L + return 0L + + # Ok + def getmtime(self, datacr): + """Return the last modified time as a number of seconds since + the epoch.""" + + node = datacr[1] + if node.write_date or node.create_date: + dt = (node.write_date or node.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 lexists(self, path): + """Return True if path refers to an existing path, including + a broken or circular symbolic link. + """ + raise DeprecationWarning() + 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. + + 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 + + # note: the following operations are no more blocking + + def get_list_dir(self, datacr): + """"Return an iterator object that yields a directory listing + in a form suitable for LIST command. + """ + if not datacr: + return None + elif self.isdir(datacr[1]): + listing = self.listdir(datacr) + return self.format_list(datacr[0], datacr[1], listing) + # if path is a file or a symlink we return information about it + elif self.isfile(datacr[1]): + par = datacr[1].parent + return self.format_list(datacr[0], par, [datacr[1]]) + + 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) + + def format_list(self, cr, parent_node, 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 parent directory node. Can be None + - (list) listing: a list of nodes + - (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. + + 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 node in listing: + perms = filemode(node.unixperms) # permissions + nlinks = 1 + size = node.content_length or 0L + uname = _to_decode(node.uuser) + gname = _to_decode(node.ugroup) + # stat.st_mtime could fail (-1) if last mtime is too old + # in which case we return the local time as last mtime + try: + st_mtime = node.write_date or 0.0 + if isinstance(st_mtime, basestring): + st_mtime = time.strptime(st_mtime, '%Y-%m-%d %H:%M:%S') + elif isinstance(st_mtime, float): + st_mtime = time.localtime(st_mtime) + mname = _get_month_name(time.strftime("%m", st_mtime)) + mtime = mname + ' ' + time.strftime("%d %H:%M", st_mtime) + except ValueError: + mname = _get_month_name(time.strftime("%m")) + mtime = mname + ' ' + time.strftime("%d %H:%M") + fpath = node.path + if isinstance(fpath, (list, tuple)): + fpath = fpath[-1] + # formatting is matched with proftpd ls output + path = _to_decode(fpath) + yield "%s %3s %-8s %-8s %8s %s %s\r\n" % (perms, nlinks, uname, gname, + size, mtime, path) + + # Ok + def format_mlsx(self, cr, 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. + + - (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. + + 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 node in listing: + # type + perm + if self.isdir(node): + if 'type' in facts: + 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;' % (node.content_length or 0L) + # last modification time + if 'modify' in facts: + try: + st_mtime = node.write_date or 0.0 + if isinstance(st_mtime, basestring): + st_mtime = time.strptime(st_mtime, '%Y-%m-%d %H:%M:%S') + elif isinstance(st_mtime, float): + st_mtime = time.localtime(st_mtime) + modify = 'modify=%s;' % time.strftime("%Y%m%d%H%M%S", 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: + st_ctime = node.create_date or 0.0 + if isinstance(st_ctime, basestring): + st_ctime = time.strptime(st_ctime, '%Y-%m-%d %H:%M:%S') + elif isinstance(st_mtime, float): + st_ctime = time.localtime(st_ctime) + create = 'create=%s;' % time.strftime("%Y%m%d%H%M%S", st_ctime) + except ValueError: + create = "" + # UNIX only + if 'unix.mode' in facts: + mode = 'unix.mode=%s;' % oct(node.unixperms & 0777) + if 'unix.uid' in facts: + uid = 'unix.uid=%s;' % _to_decode(node.uuser) + if 'unix.gid' in facts: + gid = 'unix.gid=%s;' % _to_decode(node.ugroup) + # 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: todo + # unique = "unique=%x%x;" %(st.st_dev, st.st_ino) + path = node.path + if isinstance (path, (list, tuple)): + path = path[-1] + path = _to_decode(path) + yield "%s%s%s%s%s%s%s%s%s %s\r\n" % (type, size, perm, modify, create, + mode, uid, gid, unique, path) + diff --git a/document_ftp/ftpserver/authorizer.py b/document_ftp/ftpserver/authorizer.py new file mode 100644 index 00000000..5bcb21b6 --- /dev/null +++ b/document_ftp/ftpserver/authorizer.py @@ -0,0 +1,70 @@ +# -*- encoding: utf-8 -*- + +class authorizer: + read_perms = "elr" + write_perms = "adfmw" + + def __init__(self): + self.password = '' + + def validate_authentication(self, username, password): + """Return True if the supplied username and password match the + stored credentials.""" + self.password = password + return True + + def impersonate_user(self, username, password): + """Impersonate another user (noop). + + It is always called before accessing the filesystem. + By default it does nothing. The subclass overriding this + method is expected to provide a mechanism to change the + current user. + """ + + def terminate_impersonation(self): + """Terminate impersonation (noop). + + It is always called after having accessed the filesystem. + By default it does nothing. The subclass overriding this + method is expected to provide a mechanism to switch back + to the original user. + """ + + def has_user(self, username): + """Whether the username exists in the virtual users table.""" + if username == 'anonymous': + return False + return True + + def has_perm(self, username, perm, path=None): + """Whether the user has permission over path (an absolute + pathname of a file or a directory). + + Expected perm argument is one of the following letters: + "elradfmw". + """ + paths = path.split('/') + if not len(paths) > 2: + return True + db_name = paths[1] + db, pool = pooler.get_db_and_pool(db_name) + res = security.login(db_name, username, self.password) + return bool(res) + + def get_perms(self, username): + """Return current user permissions.""" + return 'elr' + + def get_home_dir(self, username): + """Return the user's home directory.""" + return '/' + + def get_msg_login(self, username): + """Return the user's login message.""" + return 'Welcome on OpenERP document management system.' + + def get_msg_quit(self, username): + """Return the user's quitting message.""" + return 'Bye.' + diff --git a/document_ftp/ftpserver/ftpserver.py b/document_ftp/ftpserver/ftpserver.py new file mode 100755 index 00000000..99d2e50a --- /dev/null +++ b/document_ftp/ftpserver/ftpserver.py @@ -0,0 +1,3046 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- +# ftpserver.py +# +# pyftpdlib is released under the MIT license, reproduced below: +# ====================================================================== +# Copyright (C) 2007 Giampaolo Rodola' +# Hacked by Fabien Pinckaers (C) 2008 +# +# All Rights Reserved +# +# Permission to use, copy, modify, and distribute this software and +# its documentation for any purpose and without fee is hereby +# granted, provided that the above copyright notice appear in all +# copies and that both that copyright notice and this permission +# notice appear in supporting documentation, and that the name of +# Giampaolo Rodola' not be used in advertising or publicity pertaining to +# distribution of the software without specific, written prior +# permission. +# +# Giampaolo Rodola' DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN +# NO EVENT Giampaolo Rodola' BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# ====================================================================== + + +"""pyftpdlib: RFC-959 asynchronous FTP server. + +pyftpdlib implements a fully functioning asynchronous FTP server as +defined in RFC-959. A hierarchy of classes outlined below implement +the backend functionality for the FTPd: + + [FTPServer] - the base class for the backend. + + [FTPHandler] - a class representing the server-protocol-interpreter + (server-PI, see RFC-959). Each time a new connection occurs + FTPServer will create a new FTPHandler instance to handle the + current PI session. + + [ActiveDTP], [PassiveDTP] - base classes for active/passive-DTP + backends. + + [DTPHandler] - this class handles processing of data transfer + operations (server-DTP, see RFC-959). + + [DummyAuthorizer] - an "authorizer" is a class handling FTPd + authentications and permissions. It is used inside FTPHandler class + to verify user passwords, to get user's home directory and to get + permissions when a filesystem read/write occurs. "DummyAuthorizer" + is the base authorizer class providing a platform independent + interface for managing virtual users. + + [AbstractedFS] - class used to interact with the file system, + providing a high level, cross-platform interface compatible + with both Windows and UNIX style filesystems. + + [AuthorizerError] - base class for authorizers exceptions. + + +pyftpdlib also provides 3 different logging streams through 3 functions +which can be overridden to allow for custom logging. + + [log] - the main logger that logs the most important messages for + the end user regarding the FTPd. + + [logline] - this function is used to log commands and responses + passing through the control FTP channel. + + [logerror] - log traceback outputs occurring in case of errors. + + +Usage example: + +>>> from pyftpdlib import ftpserver +>>> authorizer = ftpserver.DummyAuthorizer() +>>> authorizer.add_user('user', 'password', '/home/user', perm='elradfmw') +>>> authorizer.add_anonymous('/home/nobody') +>>> ftp_handler = ftpserver.FTPHandler +>>> ftp_handler.authorizer = authorizer +>>> address = ("127.0.0.1", 21) +>>> ftpd = ftpserver.FTPServer(address, ftp_handler) +>>> ftpd.serve_forever() +Serving FTP on 127.0.0.1:21 +[]127.0.0.1:2503 connected. +127.0.0.1:2503 ==> 220 Ready. +127.0.0.1:2503 <== USER anonymous +127.0.0.1:2503 ==> 331 Username ok, send password. +127.0.0.1:2503 <== PASS ****** +127.0.0.1:2503 ==> 230 Login successful. +[anonymous]@127.0.0.1:2503 User anonymous logged in. +127.0.0.1:2503 <== TYPE A +127.0.0.1:2503 ==> 200 Type set to: ASCII. +127.0.0.1:2503 <== PASV +127.0.0.1:2503 ==> 227 Entering passive mode (127,0,0,1,9,201). +127.0.0.1:2503 <== LIST +127.0.0.1:2503 ==> 150 File status okay. About to open data connection. +[anonymous]@127.0.0.1:2503 OK LIST "/". Transfer starting. +127.0.0.1:2503 ==> 226 Transfer complete. +[anonymous]@127.0.0.1:2503 Transfer complete. 706 bytes transmitted. +127.0.0.1:2503 <== QUIT +127.0.0.1:2503 ==> 221 Goodbye. +[anonymous]@127.0.0.1:2503 Disconnected. +""" + + +import asyncore +import asynchat +import socket +import os +import sys +import traceback +import errno +import time +import glob +import fnmatch +import tempfile +import warnings +import random +import stat +from collections import deque +from tarfile import filemode + +LOG_ACTIVE = True + +__all__ = ['proto_cmds', 'Error', 'log', 'logline', 'logerror', 'DummyAuthorizer', + 'FTPHandler', 'FTPServer', 'PassiveDTP', 'ActiveDTP', 'DTPHandler', + 'FileProducer', 'IteratorProducer', 'BufferedIteratorProducer', + 'AbstractedFS', ] + + +__pname__ = 'Python FTP server library (pyftpdlib)' +__ver__ = '0.4.0' +__date__ = '2008-05-16' +__author__ = "Giampaolo Rodola' " +__web__ = 'http://code.google.com/p/pyftpdlib/' + + +proto_cmds = { + 'ABOR': 'Syntax: ABOR (abort transfer).', + 'ALLO': 'Syntax: ALLO bytes (obsolete; allocate storage).', + 'APPE': 'Syntax: APPE file-name (append data to an existent file).', + 'CDUP': 'Syntax: CDUP (go to parent directory).', + 'CWD' : 'Syntax: CWD dir-name (change current working directory).', + 'DELE': 'Syntax: DELE file-name (delete file).', + 'EPRT': 'Syntax: EPRT |proto|ip|port| (set server in extended active mode).', + 'EPSV': 'Syntax: EPSV [ proto/"ALL"] (set server in extended passive mode).', + 'FEAT': 'Syntax: FEAT (list all new features supported).', + 'HELP': 'Syntax: HELP [ cmd] (show help).', + 'LIST': 'Syntax: LIST [ path-name] (list files).', + 'MDTM': 'Syntax: MDTM file-name (get last modification time).', + 'MLSD': 'Syntax: MLSD [ dir-name] (list files in a machine-processable form)', + 'MLST': 'Syntax: MLST [ path-name] (show a path in a machine-processable form)', + 'MODE': 'Syntax: MODE mode (obsolete; set data transfer mode).', + 'MKD' : 'Syntax: MDK dir-name (create directory).', + 'NLST': 'Syntax: NLST [ path-name] (list files in a compact form).', + 'NOOP': 'Syntax: NOOP (just do nothing).', + 'OPTS': 'Syntax: OPTS ftp-command [ option] (specify options for FTP commands)', + 'PASS': 'Syntax: PASS user-name (set user password).', + 'PASV': 'Syntax: PASV (set server in passive mode).', + 'PORT': 'Syntax: PORT h1,h2,h3,h4,p1,p2 (set server in active mode).', + 'PWD' : 'Syntax: PWD (get current working directory).', + 'QUIT': 'Syntax: QUIT (quit current session).', + 'REIN': 'Syntax: REIN (reinitialize / flush account).', + 'REST': 'Syntax: REST marker (restart file position).', + 'RETR': 'Syntax: RETR file-name (retrieve a file).', + 'RMD' : 'Syntax: RMD dir-name (remove directory).', + 'RNFR': 'Syntax: RNFR file-name (file renaming (source name)).', + 'RNTO': 'Syntax: RNTO file-name (file renaming (destination name)).', + 'SIZE': 'Syntax: HELP file-name (get file size).', + 'STAT': 'Syntax: STAT [ path name] (status information [list files]).', + 'STOR': 'Syntax: STOR file-name (store a file).', + 'STOU': 'Syntax: STOU [ file-name] (store a file with a unique name).', + 'STRU': 'Syntax: STRU type (obsolete; set file structure).', + 'SYST': 'Syntax: SYST (get operating system type).', + 'TYPE': 'Syntax: TYPE [A | I] (set transfer type).', + 'USER': 'Syntax: USER user-name (set username).', + 'XCUP': 'Syntax: XCUP (obsolete; go to parent directory).', + 'XCWD': 'Syntax: XCWD dir-name (obsolete; change current directory).', + 'XMKD': 'Syntax: XMDK dir-name (obsolete; create directory).', + 'XPWD': 'Syntax: XPWD (obsolete; get current dir).', + 'XRMD': 'Syntax: XRMD dir-name (obsolete; remove directory).', + } + + +def _strerror(err): + """A wrap around os.strerror() which may be not available on all + platforms (e.g. pythonCE). + + - (instance) err: an EnvironmentError or derived class instance. + """ + if hasattr(os, 'strerror'): + return os.strerror(err.errno) + else: + return err.strerror + +def _to_unicode(s): + try: + return s.decode('utf-8') + except UnicodeError: + pass + try: + return s.decode('latin') + except UnicodeError: + pass + try: + return s.encode('ascii') + except UnicodeError: + return s + +def _to_decode(s): + try: + return s.encode('utf-8') + except UnicodeError: + pass + try: + return s.encode('latin') + except UnicodeError: + pass + try: + return s.decode('ascii') + except UnicodeError: + return s + +# --- library defined exceptions + +class Error(Exception): + """Base class for module exceptions.""" + +class AuthorizerError(Error): + """Base class for authorizer exceptions.""" + + +# --- loggers + +def log(msg): + """Log messages intended for the end user.""" + if LOG_ACTIVE: + print msg + +def logline(msg): + """Log commands and responses passing through the command channel.""" + if LOG_ACTIVE: + print msg + +def logerror(msg): + """Log traceback outputs occurring in case of errors.""" + sys.stderr.write(str(msg) + '\n') + sys.stderr.flush() + + +# --- authorizers + +class DummyAuthorizer: + """Basic "dummy" authorizer class, suitable for subclassing to + create your own custom authorizers. + + An "authorizer" is a class handling authentications and permissions + of the FTP server. It is used inside FTPHandler class for verifying + user's password, getting users home directory, checking user + permissions when a file read/write event occurs and changing user + before accessing the filesystem. + + DummyAuthorizer is the base authorizer, providing a platform + independent interface for managing "virtual" FTP users. System + dependent authorizers can by written by subclassing this base + class and overriding appropriate methods as necessary. + """ + + read_perms = "elr" + write_perms = "adfmw" + + def __init__(self): + self.user_table = {} + + def add_user(self, username, password, homedir, perm='elr', + msg_login="Login successful.", msg_quit="Goodbye."): + """Add a user to the virtual users table. + + AuthorizerError exceptions raised on error conditions such as + invalid permissions, missing home directory or duplicate usernames. + + Optional perm argument is a string referencing the user's + permissions explained below: + + Read permissions: + - "e" = change directory (CWD command) + - "l" = list files (LIST, NLST, MLSD commands) + - "r" = retrieve file from the server (RETR command) + + Write permissions: + - "a" = append data to an existing file (APPE command) + - "d" = delete file or directory (DELE, RMD commands) + - "f" = rename file or directory (RNFR, RNTO commands) + - "m" = create directory (MKD command) + - "w" = store a file to the server (STOR, STOU commands) + + Optional msg_login and msg_quit arguments can be specified to + provide customized response strings when user log-in and quit. + """ + if self.has_user(username): + raise AuthorizerError('User "%s" already exists.' % username) + homedir = os.path.realpath(homedir) + if not os.path.isdir(homedir): + raise AuthorizerError('No such directory: "%s".' % homedir) + for p in perm: + if p not in 'elradfmw': + raise AuthorizerError('No such permission: "%s".' % p) + for p in perm: + if (p in self.write_perms) and (username == 'anonymous'): + warnings.warn("Write permissions are assigned to anonymous user.", + RuntimeWarning) + break + dic = {'pwd': str(password), + 'home': homedir, + 'perm': perm, + 'msg_login': str(msg_login), + 'msg_quit': str(msg_quit) + } + self.user_table[username] = dic + + def add_anonymous(self, homedir, **kwargs): + """Add an anonymous user to the virtual users table. + + AuthorizerError exception raised on error conditions such as + invalid permissions, missing home directory, or duplicate + anonymous users. + + The keyword arguments in kwargs are the same expected by + add_user method: "perm", "msg_login" and "msg_quit". + + The optional "perm" keyword argument is a string defaulting to + "elr" referencing "read-only" anonymous user's permissions. + + Using write permission values ("adfmw") results in a + RuntimeWarning. + """ + DummyAuthorizer.add_user(self, 'anonymous', '', homedir, **kwargs) + + def remove_user(self, username): + """Remove a user from the virtual users table.""" + del self.user_table[username] + + def validate_authentication(self, username, password): + """Return True if the supplied username and password match the + stored credentials.""" + return self.user_table[username]['pwd'] == password + + def impersonate_user(self, username, password): + """Impersonate another user (noop). + + It is always called before accessing the filesystem. + By default it does nothing. The subclass overriding this + method is expected to provide a mechanism to change the + current user. + """ + + def terminate_impersonation(self): + """Terminate impersonation (noop). + + It is always called after having accessed the filesystem. + By default it does nothing. The subclass overriding this + method is expected to provide a mechanism to switch back + to the original user. + """ + + def has_user(self, username): + """Whether the username exists in the virtual users table.""" + return username in self.user_table + + def has_perm(self, username, perm, path=None): + """Whether the user has permission over path (an absolute + pathname of a file or a directory). + + Expected perm argument is one of the following letters: + "elradfmw". + """ + return perm in self.user_table[username]['perm'] + + def get_perms(self, username): + """Return current user permissions.""" + return self.user_table[username]['perm'] + + def get_home_dir(self, username): + """Return the user's home directory.""" + return self.user_table[username]['home'] + + def get_msg_login(self, username): + """Return the user's login message.""" + return self.user_table[username]['msg_login'] + + def get_msg_quit(self, username): + """Return the user's quitting message.""" + return self.user_table[username]['msg_quit'] + + +# --- DTP classes + +class PassiveDTP(asyncore.dispatcher): + """This class is an asyncore.disptacher subclass. It creates a + socket listening on a local port, dispatching the resultant + connection to DTPHandler. + """ + + def __init__(self, cmd_channel, extmode=False): + """Initialize the passive data server. + + - (instance) cmd_channel: the command channel class instance. + - (bool) extmode: wheter use extended passive mode response type. + """ + asyncore.dispatcher.__init__(self) + self.cmd_channel = cmd_channel + + ip = self.cmd_channel.getsockname()[0] + self.create_socket(self.cmd_channel.af, socket.SOCK_STREAM) + + if not self.cmd_channel.passive_ports: + # By using 0 as port number value we let kernel choose a free + # unprivileged random port. + self.bind((ip, 0)) + else: + ports = list(self.cmd_channel.passive_ports) + while ports: + port = ports.pop(random.randint(0, len(ports) - 1)) + try: + self.bind((ip, port)) + except socket.error, why: + if why[0] == errno.EADDRINUSE: # port already in use + if ports: + continue + # If cannot use one of the ports in the configured + # range we'll use a kernel-assigned port, and log + # a message reporting the issue. + # By using 0 as port number value we let kernel + # choose a free unprivileged random port. + else: + self.bind((ip, 0)) + self.cmd_channel.log( + "Can't find a valid passive port in the " + "configured range. A random kernel-assigned " + "port will be used." + ) + else: + raise + else: + break + self.listen(5) + port = self.socket.getsockname()[1] + if not extmode: + if self.cmd_channel.masquerade_address: + ip = self.cmd_channel.masquerade_address + # The format of 227 response in not standardized. + # This is the most expected: + self.cmd_channel.respond('227 Entering passive mode (%s,%d,%d).' % ( + ip.replace('.', ','), port / 256, port % 256)) + else: + self.cmd_channel.respond('229 Entering extended passive mode ' + '(|||%d|).' % port) + + # --- connection / overridden + + def handle_accept(self): + """Called when remote client initiates a connection.""" + sock, addr = self.accept() + + # Check the origin of data connection. If not expressively + # configured we drop the incoming data connection if remote + # IP address does not match the client's IP address. + if (self.cmd_channel.remote_ip != addr[0]): + if not self.cmd_channel.permit_foreign_addresses: + try: + sock.close() + except socket.error: + pass + msg = 'Rejected data connection from foreign address %s:%s.' \ + % (addr[0], addr[1]) + self.cmd_channel.respond("425 %s" % msg) + self.cmd_channel.log(msg) + # do not close listening socket: it couldn't be client's blame + return + else: + # site-to-site FTP allowed + msg = 'Established data connection with foreign address %s:%s.'\ + % (addr[0], addr[1]) + self.cmd_channel.log(msg) + # Immediately close the current channel (we accept only one + # connection at time) and avoid running out of max connections + # limit. + self.close() + # delegate such connection to DTP handler + handler = self.cmd_channel.dtp_handler(sock, self.cmd_channel) + self.cmd_channel.data_channel = handler + self.cmd_channel.on_dtp_connection() + + def writable(self): + return 0 + + def handle_error(self): + """Called to handle any uncaught exceptions.""" + try: + raise + except (KeyboardInterrupt, SystemExit, asyncore.ExitNow): + raise + logerror(traceback.format_exc()) + self.close() + + def handle_close(self): + """Called on closing the data connection.""" + self.close() + + +class ActiveDTP(asyncore.dispatcher): + """This class is an asyncore.disptacher subclass. It creates a + socket resulting from the connection to a remote user-port, + dispatching it to DTPHandler. + """ + + def __init__(self, ip, port, cmd_channel): + """Initialize the active data channel attemping to connect + to remote data socket. + + - (str) ip: the remote IP address. + - (int) port: the remote port. + - (instance) cmd_channel: the command channel class instance. + """ + asyncore.dispatcher.__init__(self) + self.cmd_channel = cmd_channel + self.create_socket(self.cmd_channel.af, socket.SOCK_STREAM) + try: + self.connect((ip, port)) + except socket.gaierror: + self.cmd_channel.respond("425 Cannot connect to specified address.") + self.close() + + # --- connection / overridden + + def handle_write(self): + """NOOP, must be overridden to prevent unhandled write event.""" + + def handle_connect(self): + """Called when connection is established.""" + self.cmd_channel.respond('200 Active data connection has been established.') + # delegate such connection to DTP handler + handler = self.cmd_channel.dtp_handler(self.socket, self.cmd_channel) + self.cmd_channel.data_channel = handler + self.cmd_channel.on_dtp_connection() + + def handle_expt(self): + self.cmd_channel.respond("425 Cannot connect to specified address.") + self.close() + + def handle_error(self): + """Called to handle any uncaught exceptions.""" + try: + raise + except (KeyboardInterrupt, SystemExit, asyncore.ExitNow): + raise + except socket.error: + pass + except: + logerror(traceback.format_exc()) + self.cmd_channel.respond("425 Cannot connect to specified address.") + self.close() + +class DTPHandler(asyncore.dispatcher): + """Class handling server-data-transfer-process (server-DTP, see + RFC-959) managing data-transfer operations involving sending + and receiving data. + + Instance attributes defined in this class, initialized when + channel is opened: + + - (instance) cmd_channel: the command channel class instance. + - (file) file_obj: the file transferred (if any). + - (bool) receive: True if channel is used for receiving data. + - (bool) transfer_finished: True if transfer completed successfully. + - (int) tot_bytes_sent: the total bytes sent. + - (int) tot_bytes_received: the total bytes received. + + DTPHandler implementation note: + + When a producer is consumed and close_when_done() has been called + previously, refill_buffer() erroneously calls close() instead of + handle_close() - (see: http://bugs.python.org/issue1740572) + + To avoid this problem DTPHandler is implemented as a subclass of + asyncore.dispatcher instead of asynchat.async_chat. + This implementation follows the same approach that asynchat module + should use in Python 2.6. + + The most important change in the implementation is related to + producer_fifo, which is a pure deque object instead of a + producer_fifo instance. + + Since we don't want to break backward compatibily with older python + versions (deque has been introduced in Python 2.4), if deque is not + available we use a list instead. + """ + + ac_in_buffer_size = 8192 + ac_out_buffer_size = 8192 + + def __init__(self, sock_obj, cmd_channel): + """Initialize the command channel. + + - (instance) sock_obj: the socket object instance of the newly + established connection. + - (instance) cmd_channel: the command channel class instance. + """ + asyncore.dispatcher.__init__(self, sock_obj) + # we toss the use of the asynchat's "simple producer" and + # replace it with a pure deque, which the original fifo + # was a wrapping of + self.producer_fifo = deque() + + self.cmd_channel = cmd_channel + self.file_obj = None + self.receive = False + self.transfer_finished = False + self.tot_bytes_sent = 0 + self.tot_bytes_received = 0 + self.data_wrapper = lambda x: x + + # --- utility methods + + def enable_receiving(self, type): + """Enable receiving of data over the channel. Depending on the + TYPE currently in use it creates an appropriate wrapper for the + incoming data. + + - (str) type: current transfer type, 'a' (ASCII) or 'i' (binary). + """ + if type == 'a': + self.data_wrapper = lambda x: x.replace('\r\n', os.linesep) + elif type == 'i': + self.data_wrapper = lambda x: x + else: + raise TypeError, "Unsupported type." + self.receive = True + + def get_transmitted_bytes(self): + "Return the number of transmitted bytes." + return self.tot_bytes_sent + self.tot_bytes_received + + def transfer_in_progress(self): + "Return True if a transfer is in progress, else False." + return self.get_transmitted_bytes() != 0 + + # --- connection + + def handle_read(self): + """Called when there is data waiting to be read.""" + try: + chunk = self.recv(self.ac_in_buffer_size) + except socket.error: + self.handle_error() + else: + self.tot_bytes_received += len(chunk) + if not chunk: + self.transfer_finished = True + # self.close() # <-- asyncore.recv() already do that... + return + # while we're writing on the file an exception could occur + # in case that filesystem gets full; if this happens we + # let handle_error() method handle this exception, providing + # a detailed error message. + self.file_obj.write(self.data_wrapper(chunk)) + + def handle_write(self): + """Called when data is ready to be written, initiates send.""" + self.initiate_send() + + def push(self, data): + """Push data onto the deque and initiate send.""" + sabs = self.ac_out_buffer_size + if len(data) > sabs: + for i in xrange(0, len(data), sabs): + self.producer_fifo.append(data[i:i + sabs]) + else: + self.producer_fifo.append(data) + self.initiate_send() + + def push_with_producer(self, producer): + """Push data using a producer and initiate send.""" + self.producer_fifo.append(producer) + self.initiate_send() + + def readable(self): + """Predicate for inclusion in the readable for select().""" + return self.receive + + def writable(self): + """Predicate for inclusion in the writable for select().""" + return self.producer_fifo or (not self.connected) + + def close_when_done(self): + """Automatically close this channel once the outgoing queue is empty.""" + self.producer_fifo.append(None) + + def initiate_send(self): + """Attempt to send data in fifo order.""" + while self.producer_fifo and self.connected: + first = self.producer_fifo[0] + # handle empty string/buffer or None entry + if not first: + del self.producer_fifo[0] + if first is None: + self.transfer_finished = True + self.handle_close() + return + + # handle classic producer behavior + obs = self.ac_out_buffer_size + try: + data = buffer(first, 0, obs) + except TypeError: + data = first.more() + if data: + self.producer_fifo.appendleft(data) + else: + del self.producer_fifo[0] + continue + + # send the data + try: + num_sent = self.send(data) + except socket.error: + self.handle_error() + return + + if num_sent: + self.tot_bytes_sent += num_sent + if num_sent < len(data) or obs < len(first): + self.producer_fifo[0] = first[num_sent:] + else: + del self.producer_fifo[0] + # we tried to send some actual data + return + + def handle_expt(self): + """Called on "exceptional" data events.""" + self.cmd_channel.respond("426 Connection error; transfer aborted.") + self.close() + + def handle_error(self): + """Called when an exception is raised and not otherwise handled.""" + try: + raise + except (KeyboardInterrupt, SystemExit, asyncore.ExitNow): + raise + except socket.error, err: + # fix around asyncore bug (http://bugs.python.org/issue1736101) + if err[0] in (errno.ECONNRESET, errno.ENOTCONN, errno.ESHUTDOWN, \ + errno.ECONNABORTED): + self.handle_close() + return + else: + error = str(err[1]) + # an error could occur in case we fail reading / writing + # from / to file (e.g. file system gets full) + except EnvironmentError, err: + error = _strerror(err) + except: + # some other exception occurred; we don't want to provide + # confidential error messages + logerror(traceback.format_exc()) + error = "Internal error." + self.cmd_channel.respond("426 %s; transfer aborted." % error) + self.close() + + def handle_close(self): + """Called when the socket is closed.""" + # If we used channel for receiving we assume that transfer is + # finished when client close connection , if we used channel + # for sending we have to check that all data has been sent + # (responding with 226) or not (responding with 426). + if self.receive: + self.transfer_finished = True + action = 'received' + else: + action = 'sent' + if self.transfer_finished: + self.cmd_channel.respond("226 Transfer complete.") + if self.file_obj: + fname = self.file_obj.name + self.cmd_channel.log('"%s" %s.' % (fname, action)) + else: + tot_bytes = self.get_transmitted_bytes() + msg = "Transfer aborted; %d bytes transmitted." % tot_bytes + self.cmd_channel.respond("426 " + msg) + self.cmd_channel.log(msg) + self.close() + + def close(self): + """Close the data channel, first attempting to close any remaining + file handles.""" + if self.file_obj and not self.file_obj.closed: + self.file_obj.close() + asyncore.dispatcher.close(self) + self.cmd_channel.on_dtp_close() + + +# --- producers + +class FileProducer: + """Producer wrapper for file[-like] objects.""" + + buffer_size = 65536 + + def __init__(self, file, type): + """Initialize the producer with a data_wrapper appropriate to TYPE. + + - (file) file: the file[-like] object. + - (str) type: the current TYPE, 'a' (ASCII) or 'i' (binary). + """ + self.done = False + self.file = file + if type == 'a': + self.data_wrapper = lambda x: x.replace(os.linesep, '\r\n') + elif type == 'i': + self.data_wrapper = lambda x: x + else: + raise TypeError, "Unsupported type." + + def more(self): + """Attempt a chunk of data of size self.buffer_size.""" + if self.done: + return '' + data = self.data_wrapper(self.file.read(self.buffer_size)) + if not data: + self.done = True + if not self.file.closed: + self.file.close() + return data + + +class IteratorProducer: + """Producer for iterator objects.""" + + def __init__(self, iterator): + self.iterator = iterator + + def more(self): + """Attempt a chunk of data from iterator by calling its next() + method. + """ + try: + return self.iterator.next() + except StopIteration: + return '' + + +class BufferedIteratorProducer: + """Producer for iterator objects with buffer capabilities.""" + # how many times iterator.next() will be called before + # returning some data + loops = 20 + + def __init__(self, iterator): + self.iterator = iterator + + def more(self): + """Attempt a chunk of data from iterator by calling + its next() method different times. + """ + buffer = [] + for x in xrange(self.loops): + try: + buffer.append(self.iterator.next()) + except StopIteration: + break + return ''.join(buffer) + + +# --- filesystem + +class AbstractedFS: + """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. + + Instance attributes: + - (str) root: the user home directory. + - (str) cwd: the current working directory. + - (str) rnfr: source file to be renamed. + """ + + def __init__(self): + self.root = None + self.cwd = '/' + self.rnfr = None + + # --- Pathname / conversion utilities + + 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' + + 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 + + def ftp2fs(self, ftppath): + """Translate a "virtual" ftp pathname (tipically the raw string + coming from client) into equivalent absolute "real" filesystem + pathname. + + Example (having "/home/user" as root directory): + 'x' -> '/home/user/x' + + Note: directory separators are system dependent. + """ + # as far as I know, it should always be path traversal safe... + if os.path.normpath(self.root) == os.sep: + return os.path.normpath(self.ftpnorm(ftppath)) + else: + p = self.ftpnorm(ftppath)[1:] + return os.path.normpath(os.path.join(self.root, p)) + + def fs2ftp(self, fspath): + """Translate a "real" filesystem pathname into equivalent + absolute "virtual" ftp pathname depending on the user's + root directory. + + Example (having "/home/user" as root directory): + '/home/user/x' -> '/x' + + As for ftpnorm, directory separators are system independent + ("/") and pathname returned is always absolutized. + + On invalid pathnames escaping from user's root directory + (e.g. "/home" when root is "/home/user") always return "/". + """ + if os.path.isabs(fspath): + p = os.path.normpath(fspath) + else: + p = os.path.normpath(os.path.join(self.root, fspath)) + if not self.validpath(p): + return '/' + p = p.replace(os.sep, "/") + p = p[len(self.root):] + if not p.startswith('/'): + p = '/' + p + return p + + # alias for backward compatibility with 0.2.0 + normalize = ftpnorm + translate = ftp2fs + + 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. + + Pathnames escaping from user's root directory are considered + not valid. + """ + root = self.realpath(self.root) + path = self.realpath(path) + if not self.root.endswith(os.sep): + root = self.root + os.sep + if not path.endswith(os.sep): + path = path + os.sep + if path[0:len(root)] == root: + return True + return False + + # --- Wrapper methods around open() and tempfile.mkstemp + + def open(self, filename, mode): + """Open a file returning its handler.""" + return open(filename, mode) + + 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. + """ + 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) + + # --- Wrapper methods around os.* + + def chdir(self, path): + """Change the current directory.""" + # temporarily join the specified directory to see if we have + # permissions to do so + basedir = os.getcwd() + try: + os.chdir(path) + except os.error: + raise + else: + os.chdir(basedir) + self.cwd = self.fs2ftp(path) + + def mkdir(self, path, basename): + """Create the specified directory.""" + os.mkdir(os.path.join(path, basename)) + + def listdir(self, path): + """List the content of a directory.""" + return os.listdir(path) + + def rmdir(self, path): + """Remove the specified directory.""" + os.rmdir(path) + + def remove(self, path): + """Remove the specified file.""" + os.remove(path) + + def rename(self, src, dst): + """Rename the specified src file to the dst filename.""" + os.rename(src, dst) + + def stat(self, path): + """Perform a stat() system call on the given path.""" + return os.stat(path) + + def lstat(self, path): + """Like stat but does not follow symbolic links.""" + return os.lstat(path) + + if not hasattr(os, 'lstat'): + lstat = stat + + # --- Wrapper methods around os.path.* + + def isfile(self, path): + """Return True if path is a file.""" + return os.path.isfile(path) + + def islink(self, path): + """Return True if path is a symbolic link.""" + return os.path.islink(path) + + def isdir(self, path): + """Return True if path is a directory.""" + return os.path.isdir(path) + + def getsize(self, path): + """Return the size of the specified file in bytes.""" + return os.path.getsize(path) + + def getmtime(self, path): + """Return the last modified time as a number of seconds since + the epoch.""" + return os.path.getmtime(path) + + 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 os.path.realpath(path) + + def lexists(self, path): + """Return True if path refers to an existing path, including + a broken or circular symbolic link. + """ + if hasattr(os.path, 'lexists'): + return os.path.lexists(path) + # grant backward compatibility with python 2.3 + elif hasattr(os, 'lstat'): + try: + os.lstat(path) + except os.error: + return False + return True + # fallback + else: + return os.path.exists(path) + + exists = lexists # alias for backward compatibility with 0.2.0 + + 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[0] != '.', names) + return fnmatch.filter(names, pattern) + + # --- Listing utilities + + # note: the following operations are no more blocking + + def get_list_dir(self, datacr): + """"Return an iterator object that yields a directory listing + in a form suitable for LIST command. + """ + raise DeprecationWarning() + + def get_stat_dir(self, rawline): + """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)) + 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) + listing = self.glob1(basedir, basename) + if listing: + listing.sort() + return self.format_list(basedir, listing) + + 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. + + 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: + + -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 basename in listing: + file = os.path.join(basedir, basename) + 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 = st.st_uid or "owner" + gname = st.st_gid or "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") + # if the file is a symlink, resolve it, e.g. "symlink -> realfile" + if stat.S_ISLNK(st.st_mode): + basename = basename + " -> " + os.readlink(file) + + # formatting is matched with proftpd ls output + yield "%s %3s %-8s %-8s %8s %s %s\r\n" % (perms, nlinks, uname, gname, + size, mtime, basename) + + 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. + + - (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. + + 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) + + yield "%s%s%s%s%s%s%s%s%s %s\r\n" % (type, size, perm, modify, create, + mode, uid, gid, unique, basename) + + +# --- FTP + +class FTPExceptionSent(Exception): + """An FTP exception that FTPHandler has processed + """ + pass + +class FTPHandler(asynchat.async_chat): + """Implements the FTP server Protocol Interpreter (see RFC-959), + handling commands received from the client on the control channel. + + All relevant session information is stored in class attributes + reproduced below and can be modified before instantiating this + class. + + - (str) banner: the string sent when client connects. + + - (int) max_login_attempts: + the maximum number of wrong authentications before disconnecting + the client (default 3). + + - (bool)permit_foreign_addresses: + FTP site-to-site transfer feature: also referenced as "FXP" it + permits for transferring a file between two remote FTP servers + without the transfer going through the client's host (not + recommended for security reasons as described in RFC-2577). + Having this attribute set to False means that all data + connections from/to remote IP addresses which do not match the + client's IP address will be dropped (defualt False). + + - (bool) permit_privileged_ports: + set to True if you want to permit active data connections (PORT) + over privileged ports (not recommended, defaulting to False). + + - (str) masquerade_address: + the "masqueraded" IP address to provide along PASV reply when + pyftpdlib is running behind a NAT or other types of gateways. + When configured pyftpdlib will hide its local address and + instead use the public address of your NAT (default None). + + - (list) passive_ports: + what ports ftpd will use for its passive data transfers. + Value expected is a list of integers (e.g. range(60000, 65535)). + When configured pyftpdlib will no longer use kernel-assigned + random ports (default None). + + + All relevant instance attributes initialized when client connects + are reproduced below. You may be interested in them in case you + want to subclass the original FTPHandler. + + - (bool) authenticated: True if client authenticated himself. + - (str) username: the name of the connected user (if any). + - (int) attempted_logins: number of currently attempted logins. + - (str) current_type: the current transfer type (default "a") + - (int) af: the address family (IPv4/IPv6) + - (instance) server: the FTPServer class instance. + - (instance) data_server: the data server instance (if any). + - (instance) data_channel: the data channel instance (if any). + """ + # these are overridable defaults + + # default classes + authorizer = DummyAuthorizer() + active_dtp = ActiveDTP + passive_dtp = PassiveDTP + dtp_handler = DTPHandler + abstracted_fs = AbstractedFS + + # session attributes (explained in the docstring) + banner = "pyftpdlib %s ready." % __ver__ + max_login_attempts = 3 + permit_foreign_addresses = False + permit_privileged_ports = False + masquerade_address = None + passive_ports = None + + def __init__(self, conn, server): + """Initialize the command channel. + + - (instance) conn: the socket object instance of the newly + established connection. + - (instance) server: the ftp server class instance. + """ + try: + asynchat.async_chat.__init__(self, conn=conn) # python2.5 + except TypeError: + asynchat.async_chat.__init__(self, sock=conn) # python2.6 + self.server = server + self.remote_ip, self.remote_port = self.socket.getpeername()[:2] + self.in_buffer = [] + self.in_buffer_len = 0 + self.set_terminator("\r\n") + + # session attributes + self.fs = self.abstracted_fs() + self.authenticated = False + self.username = "" + self.password = "" + self.attempted_logins = 0 + self.current_type = 'a' + self.restart_position = 0 + self.quit_pending = False + self._epsvall = False + self.__in_dtp_queue = None + self.__out_dtp_queue = None + + self.__errno_responses = { + errno.EPERM: 553, + errno.EINVAL: 504, + errno.ENOENT: 550, + errno.EREMOTE: 450, + errno.EEXIST: 521, + } + + # mlsx facts attributes + self.current_facts = ['type', 'perm', 'size', 'modify'] + self.current_facts.append('unique') + self.available_facts = self.current_facts[:] + self.available_facts += ['unix.mode', 'unix.uid', 'unix.gid'] + self.available_facts.append('create') + + # dtp attributes + self.data_server = None + self.data_channel = None + + if hasattr(self.socket, 'family'): + self.af = self.socket.family + else: # python < 2.5 + ip, port = self.socket.getsockname()[:2] + self.af = socket.getaddrinfo(ip, port, socket.AF_UNSPEC, + socket.SOCK_STREAM)[0][0] + + def handle(self): + """Return a 220 'Ready' response to the client over the command + channel. + """ + if len(self.banner) <= 75: + self.respond("220 %s" % str(self.banner)) + else: + self.push('220-%s\r\n' % str(self.banner)) + self.respond('220 ') + + def handle_max_cons(self): + """Called when limit for maximum number of connections is reached.""" + msg = "Too many connections. Service temporary unavailable." + self.respond("421 %s" % msg) + self.log(msg) + # If self.push is used, data could not be sent immediately in + # which case a new "loop" will occur exposing us to the risk of + # accepting new connections. Since this could cause asyncore to + # run out of fds (...and exposes the server to DoS attacks), we + # immediately close the channel by using close() instead of + # close_when_done(). If data has not been sent yet client will + # be silently disconnected. + self.close() + + def handle_max_cons_per_ip(self): + """Called when too many clients are connected from the same IP.""" + msg = "Too many connections from the same IP address." + self.respond("421 %s" % msg) + self.log(msg) + self.close_when_done() + + # --- asyncore / asynchat overridden methods + + def readable(self): + # if there's a quit pending we stop reading data from socket + return not self.quit_pending + + def collect_incoming_data(self, data): + """Read incoming data and append to the input buffer.""" + self.in_buffer.append(data) + self.in_buffer_len += len(data) + # Flush buffer if it gets too long (possible DoS attacks). + # RFC-959 specifies that a 500 response could be given in + # such cases + buflimit = 2048 + if self.in_buffer_len > buflimit: + self.respond('500 Command too long.') + self.log('Command has been received exceeds buffer limit of %s.' % (buflimit)) + self.in_buffer = [] + self.in_buffer_len = 0 + + # commands accepted before authentication + unauth_cmds = ('FEAT', 'HELP', 'NOOP', 'PASS', 'QUIT', 'STAT', 'SYST', 'USER') + + # commands needing an argument + arg_cmds = ('ALLO', 'APPE', 'DELE', 'EPRT', 'MDTM', 'MODE', 'MKD', 'OPTS', 'PORT', + 'REST', 'RETR', 'RMD', 'RNFR', 'RNTO', 'SIZE', 'STOR', 'STRU', + 'TYPE', 'USER', 'XMKD', 'XRMD') + + # commands needing no argument + unarg_cmds = ('ABOR', 'CDUP', 'FEAT', 'NOOP', 'PASV', 'PWD', 'QUIT', 'REIN', + 'SYST', 'XCUP', 'XPWD') + + def found_terminator(self): + r"""Called when the incoming data stream matches the \r\n + terminator. + + Depending on the command received it calls the command's + corresponding method (e.g. for received command "MKD pathname", + ftp_MKD() method is called with "pathname" as the argument). + """ + line = ''.join(self.in_buffer) + self.in_buffer = [] + self.in_buffer_len = 0 + + cmd = line.split(' ')[0].upper() + space = line.find(' ') + if space != -1: + arg = line[space + 1:] + else: + arg = "" + + if cmd != 'PASS': + self.logline("<== %s" % line) + else: + self.logline("<== %s %s" % (line.split(' ')[0], '*' * 6)) + + # let's check if user provided an argument for those commands + # needing one + if not arg and cmd in self.arg_cmds: + self.respond("501 Syntax error! Command needs an argument.") + return + + # let's do the same for those commands requiring no argument. + elif arg and cmd in self.unarg_cmds: + self.respond("501 Syntax error! Command does not accept arguments.") + return + + # provide a limited set of commands if user isn't + # authenticated yet + if (not self.authenticated): + if cmd in self.unauth_cmds: + # we permit STAT during this phase but we don't want + # STAT to return a directory LISTing if the user is + # not authenticated yet (this could happen if STAT + # is used with an argument) + if (cmd == 'STAT') and arg: + self.respond("530 Log in with USER and PASS first.") + else: + method = getattr(self, 'ftp_' + cmd) + method(arg) # call the proper ftp_* method + elif cmd in proto_cmds: + self.respond("530 Log in with USER and PASS first.") + else: + self.respond('500 Command "%s" not understood.' % line) + + # provide full command set + elif (self.authenticated) and (cmd in proto_cmds): + if not (self.__check_path(arg, arg)): # and self.__check_perm(cmd, arg)): + return + method = getattr(self, 'ftp_' + cmd) + method(arg) # call the proper ftp_* method + + else: + # recognize those commands having "special semantics" + if 'ABOR' in cmd: + self.ftp_ABOR("") + elif 'STAT' in cmd: + self.ftp_STAT("") + # unknown command + else: + self.respond('500 Command "%s" not understood.' % line) + + def __check_path(self, cmd, line): + """Check whether a path is valid.""" + + # Always true, we will only check later, once we have a cursor + return True + + def __check_perm(self, cmd, line, datacr): + """Check permissions depending on issued command.""" + map = {'CWD':'e', 'XCWD':'e', 'CDUP':'e', 'XCUP':'e', + 'LIST':'l', 'NLST':'l', 'MLSD':'l', 'STAT':'l', + 'RETR':'r', + 'APPE':'a', + 'DELE':'d', 'RMD':'d', 'XRMD':'d', + 'RNFR':'f', + 'MKD':'m', 'XMKD':'m', + 'STOR':'w'} + raise NotImplementedError + if cmd in map: + if cmd == 'STAT' and not line: + return True + perm = map[cmd] + if not line and (cmd in ('LIST', 'NLST', 'MLSD')): + path = self.fs.ftp2fs(self.fs.cwd, datacr) + else: + path = self.fs.ftp2fs(line, datacr) + if not self.authorizer.has_perm(self.username, perm, path): + self.log('FAIL %s "%s". Not enough privileges.' \ + % (cmd, self.fs.ftpnorm(line))) + self.respond("550 Can't %s. Not enough privileges." % cmd) + return False + return True + + def handle_expt(self): + """Called when there is out of band (OOB) data for the socket + connection. This could happen in case of such commands needing + "special action" (typically STAT and ABOR) in which case we + append OOB data to incoming buffer. + """ + if hasattr(socket, 'MSG_OOB'): + try: + data = self.socket.recv(1024, socket.MSG_OOB) + except socket.error: + pass + else: + self.in_buffer.append(data) + return + self.log("Cannot handle OOB data.") + self.close() + + def handle_error(self): + try: + raise + except (KeyboardInterrupt, SystemExit, asyncore.ExitNow): + raise + except socket.error, err: + # fix around asyncore bug (http://bugs.python.org/issue1736101) + if err[0] in (errno.ECONNRESET, errno.ENOTCONN, errno.ESHUTDOWN, \ + errno.ECONNABORTED): + self.handle_close() + return + else: + logerror(traceback.format_exc()) + except: + logerror(traceback.format_exc()) + self.close() + + def handle_close(self): + self.close() + + _closed = False + def close(self): + """Close the current channel disconnecting the client.""" + if not self._closed: + self._closed = True + if self.data_server: + self.data_server.close() + del self.data_server + + if self.data_channel: + self.data_channel.close() + del self.data_channel + + del self.__out_dtp_queue + del self.__in_dtp_queue + + # remove client IP address from ip map + self.server.ip_map.remove(self.remote_ip) + asynchat.async_chat.close(self) + self.log("Disconnected.") + + # --- callbacks + + def on_dtp_connection(self): + """Called every time data channel connects (either active or + passive). + + Incoming and outgoing queues are checked for pending data. + If outbound data is pending, it is pushed into the data channel. + If awaiting inbound data, the data channel is enabled for + receiving. + """ + if self.data_server: + self.data_server.close() + self.data_server = None + + # check for data to send + if self.__out_dtp_queue: + data, isproducer, file = self.__out_dtp_queue + if file: + self.data_channel.file_obj = file + if not isproducer: + self.data_channel.push(data) + else: + self.data_channel.push_with_producer(data) + if self.data_channel: + self.data_channel.close_when_done() + self.__out_dtp_queue = None + + # check for data to receive + elif self.__in_dtp_queue: + self.data_channel.file_obj = self.__in_dtp_queue + self.data_channel.enable_receiving(self.current_type) + self.__in_dtp_queue = None + + def on_dtp_close(self): + """Called every time the data channel is closed.""" + self.data_channel = None + if self.quit_pending: + self.close_when_done() + + # --- utility + + def respond(self, resp): + """Send a response to the client using the command channel.""" + self.push(resp + '\r\n') + self.logline('==> %s' % resp) + + def push_dtp_data(self, data, isproducer=False, file=None): + """Pushes data into the data channel. + + It is usually called for those commands requiring some data to + be sent over the data channel (e.g. RETR). + If data channel does not exist yet, it queues the data to send + later; data will then be pushed into data channel when + on_dtp_connection() will be called. + + - (str/classobj) data: the data to send which may be a string + or a producer object). + - (bool) isproducer: whether treat data as a producer. + - (file) file: the file[-like] object to send (if any). + """ + if self.data_channel: + self.respond("125 Data connection already open. Transfer starting.") + if file: + self.data_channel.file_obj = file + if not isproducer: + self.data_channel.push(data) + else: + self.data_channel.push_with_producer(data) + if self.data_channel: + self.data_channel.close_when_done() + else: + self.respond("150 File status okay. About to open data connection.") + self.__out_dtp_queue = (data, isproducer, file) + + def log(self, msg): + """Log a message, including additional identifying session data.""" + log("[%s]@%s:%s %s" % (self.username, self.remote_ip, + self.remote_port, msg)) + + def logline(self, msg): + """Log a line including additional indentifying session data.""" + logline("%s:%s %s" % (self.remote_ip, self.remote_port, msg)) + + def flush_account(self): + """Flush account information by clearing attributes that need + to be reset on a REIN or new USER command. + """ + if self.data_channel: + if not self.data_channel.transfer_in_progress(): + self.data_channel.close() + self.data_channel = None + if self.data_server: + self.data_server.close() + self.data_server = None + + self.fs.rnfr = None + self.authenticated = False + self.username = "" + self.password = "" + self.attempted_logins = 0 + self.current_type = 'a' + self.restart_position = 0 + self.quit_pending = False + self.__in_dtp_queue = None + self.__out_dtp_queue = None + + def run_as_current_user(self, function, *args, **kwargs): + """Execute a function impersonating the current logged-in user.""" + self.authorizer.impersonate_user(self.username, self.password) + try: + return function(*args, **kwargs) + finally: + self.authorizer.terminate_impersonation() + + # --- connection + + def try_as_current_user(self, function, args=None, kwargs=None, line=None, errno_resp=None): + """run function as current user, auto-respond in exceptions + @param args,kwargs the arguments, in list and dict respectively + @param errno_resp a dictionary of responses to IOError, OSError + """ + if errno_resp: + eresp = self.__errno_responses.copy() + eresp.update(errno_resp) + else: + eresp = self.__errno_responses + + uline = '' + if line: + uline = ' "%s"' % _to_unicode(line) + try: + if args is None: + args = () + if kwargs is None: + kwargs = {} + return self.run_as_current_user(function, *args, **kwargs) + except NotImplementedError, err: + cmdname = function.__name__ + why = err.args[0] or 'Not implemented' + self.log('FAIL %s() is not implemented: %s.' % (cmdname, why)) + self.respond('502 %s.' % why) + raise FTPExceptionSent(why) + except EnvironmentError, err: + cmdname = function.__name__ + try: + logline(traceback.format_exc()) + except Exception: + pass + ret_code = eresp.get(err.errno, '451') + why = (err.strerror) or 'Error in command.' + self.log('FAIL %s() %s errno=%s: %s.' % (cmdname, uline, err.errno, why)) + self.respond('%s %s.' % (str(ret_code), why)) + + raise FTPExceptionSent(why) + except Exception, err: + cmdname = function.__name__ + try: + logerror(traceback.format_exc()) + except Exception: + pass + why = (err.args and err.args[0]) or 'Exception' + self.log('FAIL %s() %s Exception: %s.' % (cmdname, uline, why)) + self.respond('451 %s.' % why) + raise FTPExceptionSent(why) + + def get_crdata2(self, *args, **kwargs): + return self.try_as_current_user(self.fs.get_crdata, args, kwargs, line=args[0]) + + def _make_eport(self, ip, port): + """Establish an active data channel with remote client which + issued a PORT or EPRT command. + """ + # FTP bounce attacks protection: according to RFC-2577 it's + # recommended to reject PORT if IP address specified in it + # does not match client IP address. + if not self.permit_foreign_addresses: + if ip != self.remote_ip: + self.log("Rejected data connection to foreign address %s:%s." + % (ip, port)) + self.respond("501 Cannot connect to a foreign address.") + return + + # ...another RFC-2577 recommendation is rejecting connections + # to privileged ports (< 1024) for security reasons. + if not self.permit_privileged_ports: + if port < 1024: + self.log('PORT against the privileged port "%s" has been refused.' % port) + self.respond("501 Cannot connect over a privileged port.") + return + + # close existent DTP-server instance, if any. + if self.data_server: + self.data_server.close() + self.data_server = None + if self.data_channel: + self.data_channel.close() + self.data_channel = None + + # make sure we are not hitting the max connections limit + if self.server.max_cons: + if len(self._map) >= self.server.max_cons: + msg = "Too many connections. Can't open data channel." + self.respond("425 %s" % msg) + self.log(msg) + return + + # open data channel + self.active_dtp(ip, port, self) + + def _make_epasv(self, extmode=False): + """Initialize a passive data channel with remote client which + issued a PASV or EPSV command. + If extmode argument is False we assume that client issued EPSV in + which case extended passive mode will be used (see RFC-2428). + """ + # close existing DTP-server instance, if any + if self.data_server: + self.data_server.close() + self.data_server = None + + if self.data_channel: + self.data_channel.close() + self.data_channel = None + + # make sure we are not hitting the max connections limit + if self.server.max_cons: + if len(self._map) >= self.server.max_cons: + msg = "Too many connections. Cannot open data channel." + self.respond("425 %s" % msg) + self.log(msg) + return + + # open data channel + self.data_server = self.passive_dtp(self, extmode) + + def ftp_PORT(self, line): + """Start an active data channel by using IPv4.""" + if self._epsvall: + self.respond("501 PORT not allowed after EPSV ALL.") + return + if self.af != socket.AF_INET: + self.respond("425 You cannot use PORT on IPv6 connections. " + "Use EPRT instead.") + return + # Parse PORT request for getting IP and PORT. + # Request comes in as: + # > h1,h2,h3,h4,p1,p2 + # ...where the client's IP address is h1.h2.h3.h4 and the TCP + # port number is (p1 * 256) + p2. + try: + addr = map(int, line.split(',')) + assert len(addr) == 6 + for x in addr[:4]: + assert 0 <= x <= 255 + ip = '%d.%d.%d.%d' % tuple(addr[:4]) + port = (addr[4] * 256) + addr[5] + assert 0 <= port <= 65535 + except (AssertionError, ValueError, OverflowError): + self.respond("501 Invalid PORT format.") + return + self._make_eport(ip, port) + + def ftp_EPRT(self, line): + """Start an active data channel by choosing the network protocol + to use (IPv4/IPv6) as defined in RFC-2428. + """ + if self._epsvall: + self.respond("501 EPRT not allowed after EPSV ALL.") + return + # Parse EPRT request for getting protocol, IP and PORT. + # Request comes in as: + # # protoipport + # ...where is an arbitrary delimiter character (usually "|") and + # is the network protocol to use (1 for IPv4, 2 for IPv6). + try: + af, ip, port = line.split(line[0])[1:-1] + port = int(port) + assert 0 <= port <= 65535 + except (AssertionError, ValueError, IndexError, OverflowError): + self.respond("501 Invalid EPRT format.") + return + + if af == "1": + if self.af != socket.AF_INET: + self.respond('522 Network protocol not supported (use 2).') + else: + try: + octs = map(int, ip.split('.')) + assert len(octs) == 4 + for x in octs: + assert 0 <= x <= 255 + except (AssertionError, ValueError, OverflowError): + self.respond("501 Invalid EPRT format.") + else: + self._make_eport(ip, port) + elif af == "2": + if self.af == socket.AF_INET: + self.respond('522 Network protocol not supported (use 1).') + else: + self._make_eport(ip, port) + else: + if self.af == socket.AF_INET: + self.respond('501 Unknown network protocol (use 1).') + else: + self.respond('501 Unknown network protocol (use 2).') + + def ftp_PASV(self, line): + """Start a passive data channel by using IPv4.""" + if self._epsvall: + self.respond("501 PASV not allowed after EPSV ALL.") + return + if self.af != socket.AF_INET: + self.respond("425 You cannot use PASV on IPv6 connections. " + "Use EPSV instead.") + else: + self._make_epasv(extmode=False) + + def ftp_EPSV(self, line): + """Start a passive data channel by using IPv4 or IPv6 as defined + in RFC-2428. + """ + # RFC-2428 specifies that if an optional parameter is given, + # we have to determine the address family from that otherwise + # use the same address family used on the control connection. + # In such a scenario a client may use IPv4 on the control channel + # and choose to use IPv6 for the data channel. + # But how could we use IPv6 on the data channel without knowing + # which IPv6 address to use for binding the socket? + # Unfortunately RFC-2428 does not provide satisfing information + # on how to do that. The assumption is that we don't have any way + # to know which address to use, hence we just use the same address + # family used on the control connection. + if not line: + self._make_epasv(extmode=True) + elif line == "1": + if self.af != socket.AF_INET: + self.respond('522 Network protocol not supported (use 2).') + else: + self._make_epasv(extmode=True) + elif line == "2": + if self.af == socket.AF_INET: + self.respond('522 Network protocol not supported (use 1).') + else: + self._make_epasv(extmode=True) + elif line.lower() == 'all': + self._epsvall = True + self.respond('220 Other commands other than EPSV are now disabled.') + else: + if self.af == socket.AF_INET: + self.respond('501 Unknown network protocol (use 1).') + else: + self.respond('501 Unknown network protocol (use 2).') + + def ftp_QUIT(self, line): + """Quit the current session.""" + # From RFC-959: + # This command terminates a USER and if file transfer is not + # in progress, the server closes the control connection. + # If file transfer is in progress, the connection will remain + # open for result response and the server will then close it. + if self.authenticated: + msg_quit = self.authorizer.get_msg_quit(self.username) + else: + msg_quit = "Goodbye." + if len(msg_quit) <= 75: + self.respond("221 %s" % msg_quit) + else: + self.push("221-%s\r\n" % msg_quit) + self.respond("221 ") + + if not self.data_channel: + self.close_when_done() + else: + # tell the cmd channel to stop responding to commands. + self.quit_pending = True + + + # --- data transferring + + def ftp_LIST(self, line): + """Return a list of files in the specified directory to the + client. + """ + # - If no argument, fall back on cwd as default. + # - Some older FTP clients erroneously issue /bin/ls-like LIST + # formats in which case we fall back on cwd as default. + if not line or line.lower() in ('-a', '-l', '-al', '-la'): + line = '' + datacr = None + try: + datacr = self.get_crdata2(line, mode='list') + iterator = self.try_as_current_user(self.fs.get_list_dir, (datacr,)) + except FTPExceptionSent: + self.fs.close_cr(datacr) + return + + try: + self.log('OK LIST "%s". Transfer starting.' % line) + producer = BufferedIteratorProducer(iterator) + self.push_dtp_data(producer, isproducer=True) + finally: + self.fs.close_cr(datacr) + + + def ftp_NLST(self, line): + """Return a list of files in the specified directory in a + compact form to the client. + """ + if not line: + line = '' + + datacr = None + try: + datacr = self.get_crdata2(line, mode='list') + if not datacr: + datacr = (None, None, None) + if self.fs.isdir(datacr[1]): + nodelist = self.try_as_current_user(self.fs.listdir, (datacr,)) + else: + # if path is a file we just list its name + nodelist = [datacr[1], ] + + listing = [] + for nl in nodelist: + if isinstance(nl.path, (list, tuple)): + listing.append(nl.path[-1]) + else: + listing.append(nl.path) # assume string + except FTPExceptionSent: + self.fs.close_cr(datacr) + return + + self.fs.close_cr(datacr) + data = '' + if listing: + listing.sort() + data = ''.join([ _to_decode(x) + '\r\n' for x in listing ]) + self.log('OK NLST "%s". Transfer starting.' % line) + self.push_dtp_data(data) + + # --- MLST and MLSD commands + + # The MLST and MLSD commands are intended to standardize the file and + # directory information returned by the server-FTP process. These + # commands differ from the LIST command in that the format of the + # replies is strictly defined although extensible. + + def ftp_MLST(self, line): + """Return information about a pathname in a machine-processable + form as defined in RFC-3659. + """ + # if no argument, fall back on cwd as default + if not line: + line = '' + datacr = None + try: + datacr = self.get_crdata2(line, mode='list') + perms = self.authorizer.get_perms(self.username) + iterator = self.try_as_current_user(self.fs.format_mlsx, (datacr[0], datacr[1].parent, + [datacr[1], ], perms, self.current_facts), {'ignore_err':False}) + data = ''.join(iterator) + except FTPExceptionSent: + self.fs.close_cr(datacr) + return + else: + self.fs.close_cr(datacr) + # since TVFS is supported (see RFC-3659 chapter 6), a fully + # qualified pathname should be returned + data = data.split(' ')[0] + ' %s\r\n' % line + # response is expected on the command channel + self.push('250-Listing "%s":\r\n' % line) + # the fact set must be preceded by a space + self.push(' ' + data) + self.respond('250 End MLST.') + + def ftp_MLSD(self, line): + """Return contents of a directory in a machine-processable form + as defined in RFC-3659. + """ + # if no argument, fall back on cwd as default + if not line: + line = '' + + datacr = None + try: + datacr = self.get_crdata2(line, mode='list') + # RFC-3659 requires 501 response code if path is not a directory + if not self.fs.isdir(datacr[1]): + err = 'No such directory.' + self.log('FAIL MLSD "%s". %s.' % (line, err)) + self.respond("501 %s." % err) + return + listing = self.try_as_current_user(self.fs.listdir, (datacr,)) + except FTPExceptionSent: + self.fs.close_cr(datacr) + return + else: + self.fs.close_cr(datacr) + perms = self.authorizer.get_perms(self.username) + iterator = self.fs.format_mlsx(datacr[0], datacr[1], listing, perms, + self.current_facts) + producer = BufferedIteratorProducer(iterator) + self.log('OK MLSD "%s". Transfer starting.' % line) + self.push_dtp_data(producer, isproducer=True) + + def ftp_RETR(self, line): + """Retrieve the specified file (transfer from the server to the + client) + """ + datacr = None + try: + datacr = self.get_crdata2(line, mode='file') + fd = self.try_as_current_user(self.fs.open, (datacr, 'rb')) + except FTPExceptionSent: + self.fs.close_cr(datacr) + return + + if self.restart_position: + # Make sure that the requested offset is valid (within the + # size of the file being resumed). + # According to RFC-1123 a 554 reply may result in case that + # the existing file cannot be repositioned as specified in + # the REST. + ok = 0 + try: + assert not self.restart_position > self.fs.getsize(datacr) + fd.seek(self.restart_position) + ok = 1 + except AssertionError: + why = "Invalid REST parameter." + except IOError, err: + why = _strerror(err) + self.restart_position = 0 + if not ok: + self.respond('554 %s' % why) + self.log('FAIL RETR "%s". %s.' % (line, why)) + self.fs.close_cr(datacr) + return + self.log('OK RETR "%s". Download starting.' % line) + producer = FileProducer(fd, self.current_type) + self.push_dtp_data(producer, isproducer=True, file=fd) + self.fs.close_cr(datacr) + + def ftp_STOR(self, line, mode='w'): + """Store a file (transfer from the client to the server).""" + # A resume could occur in case of APPE or REST commands. + # In that case we have to open file object in different ways: + # STOR: mode = 'w' + # APPE: mode = 'a' + # REST: mode = 'r+' (to permit seeking on file object) + if 'a' in mode: + cmd = 'APPE' + else: + cmd = 'STOR' + + datacr = None + try: + datacr = self.get_crdata2(line, mode='create') + if self.restart_position: + mode = 'r+' + fd = self.try_as_current_user(self.fs.create, (datacr, datacr[2], mode + 'b')) + assert fd + except FTPExceptionSent: + self.fs.close_cr(datacr) + return + + if self.restart_position: + # Make sure that the requested offset is valid (within the + # size of the file being resumed). + # According to RFC-1123 a 554 reply may result in case + # that the existing file cannot be repositioned as + # specified in the REST. + ok = 0 + try: + assert not self.restart_position > self.fs.getsize(datacr) + fd.seek(self.restart_position) + ok = 1 + except AssertionError: + why = "Invalid REST parameter." + except IOError, err: + why = _strerror(err) + self.restart_position = 0 + if not ok: + self.fs.close_cr(datacr) + self.respond('554 %s' % why) + self.log('FAIL %s "%s". %s.' % (cmd, line, why)) + return + + self.log('OK %s "%s". Upload starting.' % (cmd, line)) + if self.data_channel: + self.respond("125 Data connection already open. Transfer starting.") + self.data_channel.file_obj = fd + self.data_channel.enable_receiving(self.current_type) + else: + self.respond("150 File status okay. About to open data connection.") + self.__in_dtp_queue = fd + self.fs.close_cr(datacr) + + + def ftp_STOU(self, line): + """Store a file on the server with a unique name.""" + # Note 1: RFC-959 prohibited STOU parameters, but this + # prohibition is obsolete. + # Note 2: 250 response wanted by RFC-959 has been declared + # incorrect in RFC-1123 that wants 125/150 instead. + # Note 3: RFC-1123 also provided an exact output format + # defined to be as follow: + # > 125 FILE: pppp + # ...where pppp represents the unique path name of the + # file that will be written. + + # watch for STOU preceded by REST, which makes no sense. + if self.restart_position: + self.respond("450 Cannot STOU while REST request is pending.") + return + + + if line: + datacr = self.get_crdata2(line, mode='create') + # TODO + else: + # TODO + basedir = self.fs.ftp2fs(self.fs.cwd, datacr) + prefix = 'ftpd.' + try: + fd = self.try_as_current_user(self.fs.mkstemp, kwargs={'prefix':prefix, + 'dir': basedir}, line=line) + except FTPExceptionSent: + self.fs.close_cr(datacr) + return + except IOError, err: # TODO + # hitted the max number of tries to find out file with + # unique name + if err.errno == errno.EEXIST: + why = 'No usable unique file name found.' + # something else happened + else: + why = _strerror(err) + self.respond("450 %s." % why) + self.log('FAIL STOU "%s". %s.' % (self.fs.ftpnorm(line), why)) + self.fs.close_cr(datacr) + return + + filename = line + if not self.authorizer.has_perm(self.username, 'w', filename): + self.log('FAIL STOU "%s". Not enough privileges.' + % self.fs.ftpnorm(line)) + self.respond("550 Cannot STOU: not enough privileges.") + self.fs.close_cr(datacr) + return + + # now just acts like STOR except that restarting isn't allowed + self.log('OK STOU "%s". Upload starting.' % filename) + if self.data_channel: + self.respond("125 FILE: %s" % filename) + self.data_channel.file_obj = fd + self.data_channel.enable_receiving(self.current_type) + else: + self.respond("150 FILE: %s" % filename) + self.__in_dtp_queue = fd + self.fs.close_cr(datacr) + + + def ftp_APPE(self, line): + """Append data to an existing file on the server.""" + # watch for APPE preceded by REST, which makes no sense. + if self.restart_position: + self.respond("550 Cannot APPE while REST request is pending.") + else: + self.ftp_STOR(line, mode='a') + + def ftp_REST(self, line): + """Restart a file transfer from a previous mark.""" + try: + marker = int(line) + if marker < 0: + raise ValueError + except (ValueError, OverflowError): + self.respond("501 Invalid parameter.") + else: + self.respond("350 Restarting at position %s. " \ + "Now use RETR/STOR for resuming." % marker) + self.log("OK REST %s." % marker) + self.restart_position = marker + + def ftp_ABOR(self, line): + """Abort the current data transfer.""" + + # ABOR received while no data channel exists + if (self.data_server is None) and (self.data_channel is None): + resp = "225 No transfer to abort." + else: + # a PASV was received but connection wasn't made yet + if self.data_server: + self.data_server.close() + self.data_server = None + resp = "225 ABOR command successful; data channel closed." + + # If a data transfer is in progress the server must first + # close the data connection, returning a 426 reply to + # indicate that the transfer terminated abnormally, then it + # must send a 226 reply, indicating that the abort command + # was successfully processed. + # If no data has been transmitted we just respond with 225 + # indicating that no transfer was in progress. + if self.data_channel: + if self.data_channel.transfer_in_progress(): + self.data_channel.close() + self.data_channel = None + self.respond("426 Connection closed; transfer aborted.") + self.log("OK ABOR. Transfer aborted, data channel closed.") + resp = "226 ABOR command successful." + else: + self.data_channel.close() + self.data_channel = None + self.log("OK ABOR. Data channel closed.") + resp = "225 ABOR command successful; data channel closed." + self.respond(resp) + + + # --- authentication + + def ftp_USER(self, line): + """Set the username for the current session.""" + # we always treat anonymous user as lower-case string. + if line.lower() == "anonymous": + line = "anonymous" + + # RFC-959 specifies a 530 response to the USER command if the + # username is not valid. If the username is valid is required + # ftpd returns a 331 response instead. In order to prevent a + # malicious client from determining valid usernames on a server, + # it is suggested by RFC-2577 that a server always return 331 to + # the USER command and then reject the combination of username + # and password for an invalid username when PASS is provided later. + if not self.authenticated: + self.respond('331 Username ok, send password.') + else: + # a new USER command could be entered at any point in order + # to change the access control flushing any user, password, + # and account information already supplied and beginning the + # login sequence again. + self.flush_account() + msg = 'Previous account information is flushed.' + self.log('OK USER "%s". %s.' % (line, msg)) + self.respond('331 %s, send password.' % msg) + self.username = line + + def ftp_PASS(self, line): + """Check username's password against the authorizer.""" + + if self.authenticated: + self.respond("503 User already authenticated.") + return + if not self.username: + self.respond("503 Login with USER first.") + return + + # username ok + if self.authorizer.has_user(self.username): + if self.username == 'anonymous' \ + or self.authorizer.validate_authentication(self.username, line): + msg_login = self.authorizer.get_msg_login(self.username) + if len(msg_login) <= 75: + self.respond('230 %s' % msg_login) + else: + self.push("230-%s\r\n" % msg_login) + self.respond("230 ") + + self.authenticated = True + self.password = line + self.attempted_logins = 0 + self.fs.root = self.authorizer.get_home_dir(self.username) + self.fs.username = self.username + self.fs.password = line + self.log("User %s logged in." % self.username) + else: + self.attempted_logins += 1 + if self.attempted_logins >= self.max_login_attempts: + self.respond("530 Maximum login attempts. Disconnecting.") + self.close() + else: + self.respond("530 Authentication failed.") + self.log('Authentication failed (user: "%s").' % self.username) + self.username = "" + + # wrong username + else: + self.attempted_logins += 1 + if self.attempted_logins >= self.max_login_attempts: + self.log('Authentication failed: unknown username "%s".' + % self.username) + self.respond("530 Maximum login attempts. Disconnecting.") + self.close() + elif self.username.lower() == 'anonymous': + self.respond("530 Anonymous access not allowed.") + self.log('Authentication failed: anonymous access not allowed.') + else: + self.respond("530 Authentication failed.") + self.log('Authentication failed: unknown username "%s".' + % self.username) + self.username = "" + + def ftp_REIN(self, line): + """Reinitialize user's current session.""" + # From RFC-959: + # REIN command terminates a USER, flushing all I/O and account + # information, except to allow any transfer in progress to be + # completed. All parameters are reset to the default settings + # and the control connection is left open. This is identical + # to the state in which a user finds himself immediately after + # the control connection is opened. + self.log("OK REIN. Flushing account information.") + self.flush_account() + # Note: RFC-959 erroneously mention "220" as the correct response + # code to be given in this case, but this is wrong... + self.respond("230 Ready for new user.") + + + # --- filesystem operations + + def ftp_PWD(self, line): + """Return the name of the current working directory to the client.""" + cwd = self.fs.get_cwd() + self.respond('257 "%s" is the current directory.' % cwd) + + def ftp_CWD(self, line): + """Change the current working directory.""" + # check: a lot of FTP servers go back to root directory if no + # arg is provided but this is not specified in RFC-959. + # Search for official references about this behaviour. + datacr = None + try: + datacr = self.get_crdata2(line, 'cwd') + self.try_as_current_user(self.fs.chdir, (datacr,), line=line, errno_resp={2: 530}) + cwd = self.fs.get_cwd() + self.log('OK CWD "%s".' % cwd) + self.respond('250 "%s" is the current directory.' % cwd) + except FTPExceptionSent: + return + finally: + self.fs.close_cr(datacr) + + def ftp_CDUP(self, line): + """Change into the parent directory.""" + # Note: RFC-959 says that code 200 is required but it also says + # that CDUP uses the same codes as CWD. + self.ftp_CWD('..') + + def ftp_SIZE(self, line): + """Return size of file in a format suitable for using with + RESTart as defined in RFC-3659. + + Implementation note: + properly handling the SIZE command when TYPE ASCII is used would + require to scan the entire file to perform the ASCII translation + logic (file.read().replace(os.linesep, '\r\n')) and then + calculating the len of such data which may be different than + the actual size of the file on the server. Considering that + calculating such result could be very resource-intensive it + could be easy for a malicious client to try a DoS attack, thus + we do not perform the ASCII translation. + + However, clients in general should not be resuming downloads in + ASCII mode. Resuming downloads in binary mode is the recommended + way as specified in RFC-3659. + """ + datacr = None + try: + datacr = self.get_crdata2(line, mode='file') + size = self.try_as_current_user(self.fs.getsize, (datacr,), line=line) + except FTPExceptionSent: + self.fs.close_cr(datacr) + return + else: + self.respond("213 %s" % size) + self.log('OK SIZE "%s".' % line) + self.fs.close_cr(datacr) + + def ftp_MDTM(self, line): + """Return last modification time of file to the client as an ISO + 3307 style timestamp (YYYYMMDDHHMMSS) as defined in RFC-3659. + """ + datacr = None + + try: + if line.find('/', 1) < 0: + # root or db, just return local + lmt = None + else: + datacr = self.get_crdata2(line) + if not datacr: + raise IOError(errno.ENOENT, "%s is not retrievable." % line) + + lmt = self.try_as_current_user(self.fs.getmtime, (datacr,), line=line) + lmt = time.strftime("%Y%m%d%H%M%S", time.localtime(lmt)) + self.respond("213 %s" % lmt) + self.log('OK MDTM "%s".' % line) + except FTPExceptionSent: + return + finally: + self.fs.close_cr(datacr) + + def ftp_MKD(self, line): + """Create the specified directory.""" + try: + datacr = self.get_crdata2(line, mode='create') + self.try_as_current_user(self.fs.mkdir, (datacr, datacr[2]), line=line) + except FTPExceptionSent: + self.fs.close_cr(datacr) + return + else: + self.log('OK MKD "%s".' % line) + self.respond("257 Directory created.") + self.fs.close_cr(datacr) + + def ftp_RMD(self, line): + """Remove the specified directory.""" + datacr = None + try: + datacr = self.get_crdata2(line, mode='delete') + if not datacr[1]: + msg = "Cannot remove root directory." + self.respond("553 %s" % msg) + self.log('FAIL MKD "/". %s' % msg) + self.fs.close_cr(datacr) + return + self.try_as_current_user(self.fs.rmdir, (datacr,), line=line) + self.log('OK RMD "%s".' % line) + self.respond("250 Directory removed.") + except FTPExceptionSent: + pass + self.fs.close_cr(datacr) + + def ftp_DELE(self, line): + """Delete the specified file.""" + datacr = None + try: + datacr = self.get_crdata2(line, mode='delete') + self.try_as_current_user(self.fs.remove, (datacr,), line=line) + self.log('OK DELE "%s".' % line) + self.respond("250 File removed.") + except FTPExceptionSent: + pass + self.fs.close_cr(datacr) + + def ftp_RNFR(self, line): + """Rename the specified (only the source name is specified + here, see RNTO command)""" + datacr = None + try: + datacr = self.get_crdata2(line, mode='rfnr') + if not datacr[1]: + self.respond("550 No such file or directory.") + elif not datacr[1]: + self.respond("553 Cannot rename the home directory.") + else: + self.fs.rnfr = datacr[1] + self.respond("350 Ready for destination name.") + except FTPExceptionSent: + pass + self.fs.close_cr(datacr) + + def ftp_RNTO(self, line): + """Rename file (destination name only, source is specified with + RNFR). + """ + if not self.fs.rnfr: + self.respond("503 Bad sequence of commands: use RNFR first.") + return + datacr = None + try: + datacr = self.get_crdata2(line, 'create') + oldname = self.fs.rnfr.path + if isinstance(oldname, (list, tuple)): + oldname = '/'.join(oldname) + self.try_as_current_user(self.fs.rename, (self.fs.rnfr, datacr), line=line) + self.fs.rnfr = None + self.log('OK RNFR/RNTO "%s ==> %s".' % \ + (_to_unicode(oldname), _to_unicode(line))) + self.respond("250 Renaming ok.") + except FTPExceptionSent: + pass + finally: + self.fs.rnfr = None + self.fs.close_cr(datacr) + + + # --- others + + def ftp_TYPE(self, line): + """Set current type data type to binary/ascii""" + line = line.upper() + if line in ("A", "AN", "A N"): + self.respond("200 Type set to: ASCII.") + self.current_type = 'a' + elif line in ("I", "L8", "L 8"): + self.respond("200 Type set to: Binary.") + self.current_type = 'i' + else: + self.respond('504 Unsupported type "%s".' % line) + + def ftp_STRU(self, line): + """Set file structure (obsolete).""" + # obsolete (backward compatibility with older ftp clients) + if line in ('f', 'F'): + self.respond('200 File transfer structure set to: F.') + else: + self.respond('504 Unimplemented STRU type.') + + def ftp_MODE(self, line): + """Set data transfer mode (obsolete)""" + # obsolete (backward compatibility with older ftp clients) + if line in ('s', 'S'): + self.respond('200 Transfer mode set to: S') + else: + self.respond('504 Unimplemented MODE type.') + + def ftp_STAT(self, line): + """Return statistics about current ftp session. If an argument + is provided return directory listing over command channel. + + Implementation note: + + RFC-959 do not explicitly mention globbing; this means that FTP + servers are not required to support globbing in order to be + compliant. However, many FTP servers do support globbing as a + measure of convenience for FTP clients and users. + + In order to search for and match the given globbing expression, + the code has to search (possibly) many directories, examine + each contained filename, and build a list of matching files in + memory. Since this operation can be quite intensive, both CPU- + and memory-wise, we limit the search to only one directory + non-recursively, as LIST does. + """ + # return STATus information about ftpd + if not line: + s = [] + s.append('Connected to: %s:%s' % self.socket.getsockname()[:2]) + if self.authenticated: + s.append('Logged in as: %s' % self.username) + else: + if not self.username: + s.append("Waiting for username.") + else: + s.append("Waiting for password.") + if self.current_type == 'a': + type = 'ASCII' + else: + type = 'Binary' + s.append("TYPE: %s; STRUcture: File; MODE: Stream" % type) + if self.data_server: + s.append('Passive data channel waiting for connection.') + elif self.data_channel: + bytes_sent = self.data_channel.tot_bytes_sent + bytes_recv = self.data_channel.tot_bytes_received + s.append('Data connection open:') + s.append('Total bytes sent: %s' % bytes_sent) + s.append('Total bytes received: %s' % bytes_recv) + else: + s.append('Data connection closed.') + + self.push('211-FTP server status:\r\n') + self.push(''.join([' %s\r\n' % item for item in s])) + self.respond('211 End of status.') + # return directory LISTing over the command channel + else: + datacr = None + try: + datacr = self.fs.get_cr(line) + iterator = self.try_as_current_user(self.fs.get_stat_dir, (line, datacr), line=line) + except FTPExceptionSent: + pass + else: + self.push('213-Status of "%s":\r\n' % self.fs.ftpnorm(line)) + self.push_with_producer(BufferedIteratorProducer(iterator)) + self.respond('213 End of status.') + self.fs.close_cr(datacr) + + def ftp_FEAT(self, line): + """List all new features supported as defined in RFC-2398.""" + features = ['EPRT', 'EPSV', 'MDTM', 'MLSD', 'REST STREAM', 'SIZE', 'TVFS'] + s = '' + for fact in self.available_facts: + if fact in self.current_facts: + s += fact + '*;' + else: + s += fact + ';' + features.append('MLST ' + s) + features.sort() + self.push("211-Features supported:\r\n") + self.push("".join([" %s\r\n" % x for x in features])) + self.respond('211 End FEAT.') + + def ftp_OPTS(self, line): + """Specify options for FTP commands as specified in RFC-2389.""" + try: + assert (not line.count(' ') > 1), 'Invalid number of arguments.' + if ' ' in line: + cmd, arg = line.split(' ') + assert (';' in arg), 'Invalid argument!' + else: + cmd, arg = line, '' + # actually the only command able to accept options is MLST + assert (cmd.upper() == 'MLST'), 'Unsupported command "%s".' % cmd + except AssertionError, err: + self.respond('501 %s.' % err) + else: + facts = [x.lower() for x in arg.split(';')] + self.current_facts = [x for x in facts if x in self.available_facts] + f = ''.join([x + ';' for x in self.current_facts]) + self.respond('200 MLST OPTS ' + f) + + def ftp_NOOP(self, line): + """Do nothing.""" + self.respond("200 I successfully done nothin'.") + + def ftp_SYST(self, line): + """Return system type (always returns UNIX type: L8).""" + # This command is used to find out the type of operating system + # at the server. The reply shall have as its first word one of + # the system names listed in RFC-943. + # Since that we always return a "/bin/ls -lA"-like output on + # LIST we prefer to respond as if we would on Unix in any case. + self.respond("215 UNIX Type: L8") + + def ftp_ALLO(self, line): + """Allocate bytes for storage (obsolete).""" + # obsolete (always respond with 202) + self.respond("202 No storage allocation necessary.") + + def ftp_HELP(self, line): + """Return help text to the client.""" + if line: + if line.upper() in proto_cmds: + self.respond("214 %s" % proto_cmds[line.upper()]) + else: + self.respond("501 Unrecognized command.") + else: + # provide a compact list of recognized commands + def formatted_help(): + cmds = [] + keys = proto_cmds.keys() + keys.sort() + while keys: + elems = tuple((keys[0:8])) + cmds.append(' %-6s' * len(elems) % elems + '\r\n') + del keys[0:8] + return ''.join(cmds) + + self.push("214-The following commands are recognized:\r\n") + self.push(formatted_help()) + self.respond("214 Help command successful.") + + + # --- support for deprecated cmds + + # RFC-1123 requires that the server treat XCUP, XCWD, XMKD, XPWD + # and XRMD commands as synonyms for CDUP, CWD, MKD, LIST and RMD. + # Such commands are obsoleted but some ftp clients (e.g. Windows + # ftp.exe) still use them. + + def ftp_XCUP(self, line): + """Change to the parent directory. Synonym for CDUP. Deprecated.""" + self.ftp_CDUP(line) + + def ftp_XCWD(self, line): + """Change the current working directory. Synonym for CWD. Deprecated.""" + self.ftp_CWD(line) + + def ftp_XMKD(self, line): + """Create the specified directory. Synonym for MKD. Deprecated.""" + self.ftp_MKD(line) + + def ftp_XPWD(self, line): + """Return the current working directory. Synonym for PWD. Deprecated.""" + self.ftp_PWD(line) + + def ftp_XRMD(self, line): + """Remove the specified directory. Synonym for RMD. Deprecated.""" + self.ftp_RMD(line) + + +class FTPServer(asyncore.dispatcher): + """This class is an asyncore.disptacher subclass. It creates a FTP + socket listening on
, dispatching the requests to a + (typically FTPHandler class). + + Depending on the type of address specified IPv4 or IPv6 connections + (or both, depending from the underlying system) will be accepted. + + All relevant session information is stored in class attributes + described below. + Overriding them is strongly recommended to avoid running out of + file descriptors (DoS)! + + - (int) max_cons: + number of maximum simultaneous connections accepted (defaults + to 0 == unlimited). + + - (int) max_cons_per_ip: + number of maximum connections accepted for the same IP address + (defaults to 0 == unlimited). + """ + + max_cons = 0 + max_cons_per_ip = 0 + + def __init__(self, address, handler): + """Initiate the FTP server opening listening on address. + + - (tuple) address: the host:port pair on which the command + channel will listen. + + - (classobj) handler: the handler class to use. + """ + asyncore.dispatcher.__init__(self) + self.handler = handler + self.ip_map = [] + host, port = address + + # AF_INET or AF_INET6 socket + # Get the correct address family for our host (allows IPv6 addresses) + try: + info = socket.getaddrinfo(host, port, socket.AF_UNSPEC, + socket.SOCK_STREAM, 0, socket.AI_PASSIVE) + except socket.gaierror: + # Probably a DNS issue. Assume IPv4. + self.create_socket(socket.AF_INET, socket.SOCK_STREAM) + self.set_reuse_addr() + self.bind((host, port)) + else: + for res in info: + af, socktype, proto, canonname, sa = res + try: + self.create_socket(af, socktype) + self.set_reuse_addr() + self.bind(sa) + except socket.error, msg: + if self.socket: + self.socket.close() + self.socket = None + continue + break + if not self.socket: + raise socket.error, msg + self.listen(5) + + def set_reuse_addr(self): + # Overridden for convenience. Avoid to reuse address on Windows. + if (os.name in ('nt', 'ce')) or (sys.platform == 'cygwin'): + return + asyncore.dispatcher.set_reuse_addr(self) + + def serve_forever(self, **kwargs): + """A wrap around asyncore.loop(); starts the asyncore polling + loop. + + The keyword arguments in kwargs are the same expected by + asyncore.loop() function: timeout, use_poll, map and count. + """ + if not 'count' in kwargs: + log("Serving FTP on %s:%s" % self.socket.getsockname()[:2]) + + # backward compatibility for python < 2.4 + if not hasattr(self, '_map'): + if not 'map' in kwargs: + map = asyncore.socket_map + else: + map = kwargs['map'] + self._map = self.handler._map = map + + try: + # FIX #16, #26 + # use_poll specifies whether to use select module's poll() + # with asyncore or whether to use asyncore's own poll() + # method Python versions < 2.4 need use_poll set to False + # This breaks on OS X systems if use_poll is set to True. + # All systems seem to work fine with it set to False + # (tested on Linux, Windows, and OS X platforms) + if kwargs: + asyncore.loop(**kwargs) + else: + asyncore.loop(timeout=1.0, use_poll=False) + except (KeyboardInterrupt, SystemExit, asyncore.ExitNow): + log("Shutting down FTPd.") + self.close_all() + + def handle_accept(self): + """Called when remote client initiates a connection.""" + sock_obj, addr = self.accept() + log("[]%s:%s Connected." % addr[:2]) + + handler = self.handler(sock_obj, self) + ip = addr[0] + self.ip_map.append(ip) + + # For performance and security reasons we should always set a + # limit for the number of file descriptors that socket_map + # should contain. When we're running out of such limit we'll + # use the last available channel for sending a 421 response + # to the client before disconnecting it. + if self.max_cons: + if len(self._map) > self.max_cons: + handler.handle_max_cons() + return + + # accept only a limited number of connections from the same + # source address. + if self.max_cons_per_ip: + if self.ip_map.count(ip) > self.max_cons_per_ip: + handler.handle_max_cons_per_ip() + return + + handler.handle() + + def writable(self): + return 0 + + def handle_error(self): + """Called to handle any uncaught exceptions.""" + try: + raise + except (KeyboardInterrupt, SystemExit, asyncore.ExitNow): + raise + logerror(traceback.format_exc()) + self.close() + + def close_all(self, map=None, ignore_all=False): + """Stop serving; close all existent connections disconnecting + clients. + + - (dict) map: + A dictionary whose items are the channels to close. + If map is omitted, the default asyncore.socket_map is used. + + - (bool) ignore_all: + having it set to False results in raising exception in case + of unexpected errors. + + Implementation note: + + Instead of using the current asyncore.close_all() function + which only close sockets, we iterate over all existent channels + calling close() method for each one of them, avoiding memory + leaks. + + This is how asyncore.close_all() function should work in + Python 2.6. + """ + if map is None: + map = self._map + for x in map.values(): + try: + x.close() + except OSError, x: + if x[0] == errno.EBADF: + pass + elif not ignore_all: + raise + except (asyncore.ExitNow, KeyboardInterrupt, SystemExit): + raise + except: + if not ignore_all: + raise + map.clear() + + +def test(): + # cmd line usage (provide a read-only anonymous ftp server): + # python -m pyftpdlib.FTPServer + authorizer = DummyAuthorizer() + authorizer.add_anonymous(os.getcwd(), perm='elradfmw') + FTPHandler.authorizer = authorizer + address = ('', 8021) + ftpd = FTPServer(address, FTPHandler) + ftpd.serve_forever() + +if __name__ == '__main__': + test() + diff --git a/document_ftp/i18n/ar.po b/document_ftp/i18n/ar.po new file mode 100644 index 00000000..580fe183 --- /dev/null +++ b/document_ftp/i18n/ar.po @@ -0,0 +1,130 @@ +# Arabic translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2013-11-26 18:27+0000\n" +"Last-Translator: kifcaliph \n" +"Language-Team: Arabic \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-27 05:39+0000\n" +"X-Generator: Launchpad (build 16845)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "قم بضبط الخادم FTP" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "التهيئة التلقائية للمسار" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"يشير عنوان الشبكة التي لديك على الخادم OpenERP ينبغي أن تكون قابلة للوصول " +"للمستخدمين النهائيين. هذا يعتمد على هيكل الشبكة الخاصة بك والتكوين، وسوف " +"تؤثر فقط على الروابط المعروضة للمستخدمين. والشكل هو مضيف: منفذ والمضيف " +"الافتراضي (المضيف المحلي) وهي مناسبة فقط للوصول من جهاز الخادم نفسه .." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "knowledge.config.settings" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "استعراض الملفات" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "اضغط على الرابط لتصفح المستندات" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "خادم FTP" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "ضبط خدمة FTP" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "تصفح المستندات" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_تصفح" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"عنوان الخادم أو الملكية الفكرية والمنفذ الذي يجب على المستخدمين الاتصال به " +"للحصول DMS" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "مستودع مشترك (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "العنوان" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "إلغاء" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "تصفح وثيقة FTP" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "الاعدادات لنظام أدارة الوثائق" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "متصفح الوثيقة" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "أو" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "تصفح الوثيقة" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contents" diff --git a/document_ftp/i18n/bg.po b/document_ftp/i18n/bg.po new file mode 100644 index 00000000..3596c259 --- /dev/null +++ b/document_ftp/i18n/bg.po @@ -0,0 +1,131 @@ +# Bulgarian translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2012-12-21 23:00+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Bulgarian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Настройване на FTP сървър" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Автоматично настройване на категория" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Показва мрежовия адрес, на който вашият OpenErp сървър следва да бъде " +"достъпен за крайни потребители. Зависи от топологията на вашата мрежа и " +"настройки, и ще влияе само на връзките показвани на потребителите. Форматът " +"е HOST:PORT и по подразбиране (localhost) единствено е подходящ за достъп " +"от самия сървър." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Преглед на файловете" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "FTP сървър" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "Настройки на FTP сървър" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Разглеждане" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Адрес на сървъра или IP и порта, към който потребителите трябва да се свърже " +"за DMS за достъп" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Споделено храниилище (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Адрес" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Преглед на FTP документи" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Настройки на приложение ЗНАНИЯ" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Преглед на документ" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Преглед на Документ" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contents" diff --git a/document_ftp/i18n/ca.po b/document_ftp/i18n/ca.po new file mode 100644 index 00000000..7e6e202c --- /dev/null +++ b/document_ftp/i18n/ca.po @@ -0,0 +1,131 @@ +# Catalan translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2012-12-21 23:00+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Catalan \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Configura servidor FTP" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Configuració automàtica de directoris" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Indiqueu l'adreça de xarxa en la que el vostre servidor d'OpenERP hauria " +"d'estar accessible per als usuaris finals. Això depèn de la vostra topologia " +"de xarxa i configuració, i només afectara als enllaços mostrats als usuaris. " +"El formato és SERVIDOR:PORT i el servidor per defecte (localhost) només és " +"adequat per a l'accés des de la pròpia màquina del servidor." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Navega pels fitxers" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "Servidor FTP" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "Configuració del servidor FTP" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Navega" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Adreça del servidor o IP i el port per accedir al sistema de gestió de " +"documents." + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Directorio compartido de documentos (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Adreça" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Navega pels documents per FTP" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Configuració aplicació del coneixement" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Navega pels documents" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Navega pels documents" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_continguts" diff --git a/document_ftp/i18n/cs.po b/document_ftp/i18n/cs.po new file mode 100644 index 00000000..1af83c60 --- /dev/null +++ b/document_ftp/i18n/cs.po @@ -0,0 +1,130 @@ +# Czech translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2012-12-21 23:00+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Konfigurovat FTP server" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Automatická konfigurace adresářů" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Značí adresu sítě, na které by měl být pro koncové uživatel dostupný váš " +"OpenERP server. To závisí na vaší síťové topologii a nastavení a ovlivní to " +"pouze odkazy zobrazené uživatelům. Formát je POĆÍTAČ:PORT a výchozí počítač " +"(localhost) je vhodný pouze pro přístup ze samotného serveru." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Procházet soubory" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "FTP server" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "Konfigurace FTP serveru" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Procházet" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Adresa serveru nebo IP a port, ke kterému by se měli uživatelé připojit pro " +"přístup DMS" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Sdílené úložiště (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Adresa" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Procházení FTP dokumentů" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Nastavení aplikace znalostí" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Procházení dokumentů" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Procházet dokument" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contents" diff --git a/document_ftp/i18n/da.po b/document_ftp/i18n/da.po new file mode 100644 index 00000000..53ee5596 --- /dev/null +++ b/document_ftp/i18n/da.po @@ -0,0 +1,124 @@ +# Danish translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2012-12-21 23:00+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Danish \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "" diff --git a/document_ftp/i18n/de.po b/document_ftp/i18n/de.po new file mode 100644 index 00000000..b584a975 --- /dev/null +++ b/document_ftp/i18n/de.po @@ -0,0 +1,131 @@ +# German translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2014-01-27 18:34+0000\n" +"Last-Translator: Ralf Hilgenstock \n" +"Language-Team: German \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2014-01-28 07:02+0000\n" +"X-Generator: Launchpad (build 16914)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "FTP Server konfigurieren" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Auto Konfigurator Verzeichnisse" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Zeigt die Netzwerk IP Adresse über die der OpenERP Server für Endbenutzer " +"erreicht werden kann. Diese Adresse hängt ab von der Architektur des " +"Netzwerks und wird lediglich einen Einfluss auf die Anzeige der Adresse beim " +"Benutzer haben. Das Format der Adresse ist HOST:PORT, wobei der Standard " +"Host (localhost) lediglich gültig ist für einen direkten Zugriff vom Server " +"selbst." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "Wissensdatenbank.Konfiguration.Einstellungen" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Dateien durchsuchen" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "URL klicken, um die Dokumente anzuzeigen" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "FTP-Server" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "Konfiguration FTP-Server" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "Dokumente anzeigen" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "Suchen" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Servername oder IP und Port über den Benutzer per FTP auf Dokumente zugreifen" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Adresse" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "Abbrechen" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Suche per FTP-Dokument" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Knowledge-Anwendung konfigurieren" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Dokument suchen" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "oder" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Dokument suchen" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contents" diff --git a/document_ftp/i18n/document_ftp.pot b/document_ftp/i18n/document_ftp.pot new file mode 100644 index 00000000..8c842c35 --- /dev/null +++ b/document_ftp/i18n/document_ftp.pot @@ -0,0 +1,117 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * document_ftp +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2013-06-07 19:36+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Indicate the network address on which your OpenERP server should be reachable for end-users. This depends on your network topology and configuration, and will only affect the links displayed to the users. The format is HOST:PORT and the default host (localhost) is only suitable for access from the server machine itself.." +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "Server address or IP and port to which users should connect to for DMS access" +msgstr "" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "" + diff --git a/document_ftp/i18n/el.po b/document_ftp/i18n/el.po new file mode 100644 index 00000000..5f684b7f --- /dev/null +++ b/document_ftp/i18n/el.po @@ -0,0 +1,124 @@ +# Greek translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2012-12-21 23:00+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Greek \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Περιήγηση στα Αρχεία" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "Εξυπηρετητής FTP" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "Παραμετροποίηση Διακομιστή FTP" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Περιήγηση" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Διεύθυνση" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "" diff --git a/document_ftp/i18n/en_GB.po b/document_ftp/i18n/en_GB.po new file mode 100644 index 00000000..2460f119 --- /dev/null +++ b/document_ftp/i18n/en_GB.po @@ -0,0 +1,130 @@ +# English (United Kingdom) translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2013-02-07 17:09+0000\n" +"Last-Translator: mrx5682 \n" +"Language-Team: English (United Kingdom) \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Configure FTP Server" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Auto Directory Configuration" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "knowledge.config.settings" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Browse Files" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "Click the url to browse the documents" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "FTP Server" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "FTP Server Configuration" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "Browse Documents" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Browse" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Server address or IP and port to which users should connect to for DMS access" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Shared Repository (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Address" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "Cancel" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Document FTP Browse" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Knowledge Application Configuration" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Document Browse" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "or" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Browse Document" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contents" diff --git a/document_ftp/i18n/es.po b/document_ftp/i18n/es.po new file mode 100644 index 00000000..0ae47486 --- /dev/null +++ b/document_ftp/i18n/es.po @@ -0,0 +1,131 @@ +# Spanish translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2012-12-21 23:00+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Spanish \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Configurar servidor FTP" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Configuración automática de directorios" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Indique la dirección de red en la cual su servidor de OpenERP debería estar " +"accesible para los usuarios finales. Esto depende de su topología de red y " +"configuración, y sólo afectará a los enlaces mostrados a los usuarios. El " +"formato es SERVIDOR:PUERTO y el servidor por defecto (localhost) sólo es " +"adecuado para el acceso desde la propia máquina del servidor." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "Parámetros de configuración de la base de conocimiento" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Navegar por los archivos" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "Pulse sobre el enlace para acceder a los documentos" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "Servidor FTP" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "Configuración del servidor FTP" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "Navegue por los documentos" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Navegar" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Dirección del servidor o IP y el puerto para acceder al sistema de gestión " +"de documentos." + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Directorio compartido de documentos (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Dirección" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "Cancelar" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Navegar por los documentos por FTP" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Configuración aplicación del conocimiento" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Navegar por los documentos" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "o" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Navegar por los documentos" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contenidos" diff --git a/document_ftp/i18n/es_CR.po b/document_ftp/i18n/es_CR.po new file mode 100644 index 00000000..f524eccb --- /dev/null +++ b/document_ftp/i18n/es_CR.po @@ -0,0 +1,131 @@ +# Spanish (Costa Rica) translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2012-12-21 23:00+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Spanish (Costa Rica) \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Configurar servidor FTP" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Configuración automática de directorios" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Indique la dirección de red en la cual su servidor de OpenERP debería estar " +"accesible para los usuarios finales. Esto depende de su topología de red y " +"configuración, y sólo afectará a los enlaces mostrados a los usuarios. El " +"formato es SERVIDOR:PUERTO y el servidor por defecto (localhost) sólo es " +"adecuado para el acceso desde la propia máquina del servidor." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Navegar por los archivos" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "Servidor FTP" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "Configuración del servidor FTP" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Navegar" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Dirección del servidor o IP y el puerto para acceder al sistema de gestión " +"de documentos." + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Directorio compartido de documentos (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Dirección" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Navegar por los documentos por FTP" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Configuración aplicación del conocimiento" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Navegar por los documentos" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Navegar por los documentos" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contenidos" diff --git a/document_ftp/i18n/es_EC.po b/document_ftp/i18n/es_EC.po new file mode 100644 index 00000000..929a63c7 --- /dev/null +++ b/document_ftp/i18n/es_EC.po @@ -0,0 +1,129 @@ +# Spanish (Ecuador) translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2012-12-21 23:00+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Spanish (Ecuador) \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Configurar servidor FTP" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Configuración automática de directorios" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Indique la dirección de red en la cual su servidor de OpenERP debería estar " +"disponible para los usuarios finales. Esto depende de su topología de red y " +"configuración, y sólo afectará a los enlaces mostrados a los usuarios. El " +"formato es ANFITRIÓN:PUERTO y el anfitrión por defecto (localhost) sólo es " +"adecuado para acceso desde la propia máquina del servidor." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Examinar archivos" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "Servidor FTP" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "Configuración de Servidor FTP" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Examinar" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "Dirección del servidor o IP y el puerto para acceder al DMS." + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Biblioteca compartida de módulos (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Dirección" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Examinar documento por FTP" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Configuración aplicación del conocimiento" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Examinar documento" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Examinar documento" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "Configurar Contenidos" diff --git a/document_ftp/i18n/es_MX.po b/document_ftp/i18n/es_MX.po new file mode 100644 index 00000000..4c568d45 --- /dev/null +++ b/document_ftp/i18n/es_MX.po @@ -0,0 +1,148 @@ +# Spanish translation for openobject-addons +# Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2011-01-11 11:15+0000\n" +"PO-Revision-Date: 2011-01-13 22:59+0000\n" +"Last-Translator: Jordi Esteve (www.zikzakmedia.com) " +"\n" +"Language-Team: Spanish \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2011-09-05 05:55+0000\n" +"X-Generator: Launchpad (build 13830)\n" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Configuración automática de directorios" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Indique la dirección de red en la cual su servidor de OpenERP debería estar " +"accesible para los usuarios finales. Esto depende de su topología de red y " +"configuración, y sólo afectará a los enlaces mostrados a los usuarios. El " +"formato es SERVIDOR:PUERTO y el servidor por defecto (localhost) sólo es " +"adecuado para el acceso desde la propia máquina del servidor." + +#. module: document_ftp +#: field:document.ftp.configuration,progress:0 +msgid "Configuration Progress" +msgstr "Progreso de la configuración" + +#. module: document_ftp +#: model:ir.actions.url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Navegar por los archivos" + +#. module: document_ftp +#: field:document.ftp.configuration,config_logo:0 +msgid "Image" +msgstr "Imagen" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Dirección" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "Servidor FTP" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "Configuración del servidor FTP" + +#. module: document_ftp +#: model:ir.module.module,description:document_ftp.module_meta_information +msgid "" +"This is a support FTP Interface with document management system.\n" +" With this module you would not only be able to access documents through " +"OpenERP\n" +" but you would also be able to connect with them through the file system " +"using the\n" +" FTP client.\n" +msgstr "" +"Proporciona un interfaz FTP para el sistema de gestión de documentos.\n" +" Además del acceso a los documentos a través de OpenERP, este módulo\n" +" permite acceder a los mismos a través del sistema de archivos " +"utilizando un\n" +" cliente FTP.\n" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Navegar" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Dirección del servidor o IP y el puerto para acceder al sistema de gestión " +"de documentos." + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Directorio compartido de documentos (FTP)" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Cancel" +msgstr "_Cancelar" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Configurar servidor FTP" + +#. module: document_ftp +#: model:ir.module.module,shortdesc:document_ftp.module_meta_information +msgid "Integrated FTP Server with Document Management System" +msgstr "Servidor FTP integrado al sistema de gestión de documentos" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "title" +msgstr "título" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Navegar por los documentos por FTP" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Configuración aplicación del conocimiento" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Navegar por los documentos" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Navegar por los documentos" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contenidos" diff --git a/document_ftp/i18n/es_PY.po b/document_ftp/i18n/es_PY.po new file mode 100644 index 00000000..1ee94005 --- /dev/null +++ b/document_ftp/i18n/es_PY.po @@ -0,0 +1,126 @@ +# Spanish (Paraguay) translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2012-12-21 23:00+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Spanish (Paraguay) \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Configurar servidor FTP" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Configuración automática de carpetas" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Navegar por los archivos" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "Servidor FTP" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "Configuración del servidor FTP" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Navegar" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Dirección del servidor o IP y el puerto para acceder al sistema de gestión " +"de documentos." + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Directorio compartido de documentos (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Dirección" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Navegar por los documentos por FTP" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Configuración de la aplicación de conocimiento" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Navegar por los documentos" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Navegar por los documentos" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contenidos" diff --git a/document_ftp/i18n/es_VE.po b/document_ftp/i18n/es_VE.po new file mode 100644 index 00000000..4c568d45 --- /dev/null +++ b/document_ftp/i18n/es_VE.po @@ -0,0 +1,148 @@ +# Spanish translation for openobject-addons +# Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2011-01-11 11:15+0000\n" +"PO-Revision-Date: 2011-01-13 22:59+0000\n" +"Last-Translator: Jordi Esteve (www.zikzakmedia.com) " +"\n" +"Language-Team: Spanish \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2011-09-05 05:55+0000\n" +"X-Generator: Launchpad (build 13830)\n" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Configuración automática de directorios" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Indique la dirección de red en la cual su servidor de OpenERP debería estar " +"accesible para los usuarios finales. Esto depende de su topología de red y " +"configuración, y sólo afectará a los enlaces mostrados a los usuarios. El " +"formato es SERVIDOR:PUERTO y el servidor por defecto (localhost) sólo es " +"adecuado para el acceso desde la propia máquina del servidor." + +#. module: document_ftp +#: field:document.ftp.configuration,progress:0 +msgid "Configuration Progress" +msgstr "Progreso de la configuración" + +#. module: document_ftp +#: model:ir.actions.url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Navegar por los archivos" + +#. module: document_ftp +#: field:document.ftp.configuration,config_logo:0 +msgid "Image" +msgstr "Imagen" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Dirección" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "Servidor FTP" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "Configuración del servidor FTP" + +#. module: document_ftp +#: model:ir.module.module,description:document_ftp.module_meta_information +msgid "" +"This is a support FTP Interface with document management system.\n" +" With this module you would not only be able to access documents through " +"OpenERP\n" +" but you would also be able to connect with them through the file system " +"using the\n" +" FTP client.\n" +msgstr "" +"Proporciona un interfaz FTP para el sistema de gestión de documentos.\n" +" Además del acceso a los documentos a través de OpenERP, este módulo\n" +" permite acceder a los mismos a través del sistema de archivos " +"utilizando un\n" +" cliente FTP.\n" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Navegar" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Dirección del servidor o IP y el puerto para acceder al sistema de gestión " +"de documentos." + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Directorio compartido de documentos (FTP)" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Cancel" +msgstr "_Cancelar" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Configurar servidor FTP" + +#. module: document_ftp +#: model:ir.module.module,shortdesc:document_ftp.module_meta_information +msgid "Integrated FTP Server with Document Management System" +msgstr "Servidor FTP integrado al sistema de gestión de documentos" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "title" +msgstr "título" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Navegar por los documentos por FTP" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Configuración aplicación del conocimiento" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Navegar por los documentos" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Navegar por los documentos" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contenidos" diff --git a/document_ftp/i18n/et.po b/document_ftp/i18n/et.po new file mode 100644 index 00000000..a0d22c5c --- /dev/null +++ b/document_ftp/i18n/et.po @@ -0,0 +1,124 @@ +# Estonian translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2012-12-21 23:00+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Estonian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Failide sirvimine" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "FTP server" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "FTP serveri konfiguratsioon" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Sirvi" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Aadress" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "" diff --git a/document_ftp/i18n/fi.po b/document_ftp/i18n/fi.po new file mode 100644 index 00000000..2a1684c2 --- /dev/null +++ b/document_ftp/i18n/fi.po @@ -0,0 +1,126 @@ +# Finnish translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2012-12-21 23:00+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Finnish \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Konfiguroi FTP palvelin" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Automaattinen hakemistojen konfigurointi" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Selaa tiedostoja" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "FTP-palvelin" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "FTP palvelimen konfiguraatio" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "Selaa" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Palvelimen osoite tai IP ja portti mihin käyttäjien tulisi ottaa yhteyttä " +"DMS:n käyttöä varten" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Jaettu tietolähde (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Osoite" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Dokumenttien FTP selailu" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Tiedonhallintaohjelmiston konfiguraatio" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Dokumenttien selailu" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Selaa dokumenttia" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "" diff --git a/document_ftp/i18n/fr.po b/document_ftp/i18n/fr.po new file mode 100644 index 00000000..655e01ce --- /dev/null +++ b/document_ftp/i18n/fr.po @@ -0,0 +1,132 @@ +# French translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2013-01-03 13:59+0000\n" +"Last-Translator: Florian Hatat \n" +"Language-Team: French \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Configurer le serveur FTP" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Configuration automatique des répertoires" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Indiquez l'adresse réseau sur laquelle votre serveur OpenERP doit être " +"accessible pour les utilisateurs finaux. Ceci dépend de la topologie de " +"votre réseau et de votre configuration, et il affectera seulement les liens " +"affiché aux utilisateurs. Le format est HÔTE:PORT et l'hôte par défaut " +"(localhost) est seulement approprié pour des accès depuis la machine du " +"serveur." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "knowledge.config.settings" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Parcourir les fichiers" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "Cliquer sur l'url pour parcourir les documents" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "Serveur FTP" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "Configuration du serveur FTP" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "Parcourir les documents" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Parcourir" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Adresse du serveur ou adresse IP et port auquel les utilisateurs devraient " +"se connecter pour l'accès au GED." + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Répertoire partagé (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Adresse" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "Annuler" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Parcourir les documents FTP" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Configuration de l'application de gestion des connaissances" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Parcourez le document" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "ou" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Parcourir le document" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contents" diff --git a/document_ftp/i18n/gl.po b/document_ftp/i18n/gl.po new file mode 100644 index 00000000..d27e5656 --- /dev/null +++ b/document_ftp/i18n/gl.po @@ -0,0 +1,131 @@ +# Galician translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2012-12-21 23:00+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Galician \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Configurar servidor FTP" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Configuración automática de directorios" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Indique a dirección de rede na que o seu servidor de OpenERP debería estar " +"dispoñible para os usuarios finais. Isto depende da topoloxía de rede e da " +"configuración, e só afectará aos enlaces mostrados aos usuarios. O formato é " +"ANFITRIÓN:PORTO e o anfitrión por defecto (localhost) só é adecuado para " +"acceso desde a propia máquina do servidor." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Procurar arquivos" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "Servidor FTP" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "Configuración de servidor FTP" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Explorar" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Dirección do servidor ou IP e porto para que os usuarios podan conectar ao " +"acceso DMS." + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Repositorio compartido (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Enderezo" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Examinar documento por FTP" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Configuración da aplicación do coñecemento" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Examinar documento" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Examinar documento" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contents" diff --git a/document_ftp/i18n/hr.po b/document_ftp/i18n/hr.po new file mode 100644 index 00000000..6bab7ef4 --- /dev/null +++ b/document_ftp/i18n/hr.po @@ -0,0 +1,131 @@ +# Croatian translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2013-02-09 15:43+0000\n" +"Last-Translator: Davor Bojkić \n" +"Language-Team: Croatian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Postavke FTP poslužitelja" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Automatska postava mapa" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Predstavlja adresu na mreži, na kojoj bi OpenERP trebao biti dostupan " +"krajnjim korisnicima. Ona ovisi o Vašoj topologiji mreže kao i postavkama, i " +"utječe jedino na linkove prikazane krajnjim korisnicima. Format zapisa je " +"HOST:PORT a zadani host (localhost) korisi se jedino za pristup sa samog " +"poslužitelja." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Pretraži datoteke" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "Kliknite na poveznicu za pregled dokumenata" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "FTP poslužitelj" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "Postave FTP poslužitelja" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "Pregled dokumenata" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Pregledaj" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"IP adresa i port na koji se korisnici spajaju na DMS (sustav upravljana " +"dokumentima)" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Dijeljeni repozitorij (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "IP adresa" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "Odustani" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Pregled dokumenata na FTP" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Pregled dokumenta" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "ili" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Pregled dokumenta" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "" diff --git a/document_ftp/i18n/hu.po b/document_ftp/i18n/hu.po new file mode 100644 index 00000000..9262c452 --- /dev/null +++ b/document_ftp/i18n/hu.po @@ -0,0 +1,131 @@ +# Hungarian translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2013-03-02 10:23+0000\n" +"Last-Translator: krnkris \n" +"Language-Team: Hungarian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "FTP szerver beállítása" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Automatikus könyvtárbeállítás" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Hálózati címek megjelenítése melyen az OpenERP szervere elérhető a vég-" +"felhasználók részére. Ez a hálózati beállítások topológiájától függ, és csak " +"a felhasználóknak megjelenített elérési utakkat befolyásolja. A HOST:PORT " +"forma és az alapértelmezett host (localhost) csak akkor megfelelő, ha a " +"szerver maga az alapgép." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "knowledge.config.settings" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Fájlok böngészése" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "Kattintson az URL elérési útra a dokumentum böngészéséhez" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "FTP szerver" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "FTP szerver konfiguráció" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "Dokumantumok böngészése" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Böngészés" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Szerver cím vagy IP és port amelyen a felhasználónak kapcsolódnia kell a DMS " +"eléréshez" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Megosztott (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Cím" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "Mégsem" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Documentum FTP böngészése" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Tudáskezelő programok beállítása" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Dokumentum böngészése" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "vagy" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Dokumentum böngészése" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contents" diff --git a/document_ftp/i18n/it.po b/document_ftp/i18n/it.po new file mode 100644 index 00000000..72df7ccc --- /dev/null +++ b/document_ftp/i18n/it.po @@ -0,0 +1,131 @@ +# Italian translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2012-12-21 23:00+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Italian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Configura FTP server" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Configurazione automatica Directory" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Indica l'indirizzo di rete su cui i vostri server OpenERP possono essere " +"disponibili all'utente finale. Questo dipende dalla topologia di rete e " +"dalla configurazione, e interessa solamente i link visualizzati dagli " +"utenti. Il formato è HOST:PORTA e il default host (localhost) è adatto " +"solamente per l'accesso dal server su se stesso.." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "knowledge.config.settings" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Sfoglia files" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "Cliccare l'url per sfogliare i documenti" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "Server FTP" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "Configurazione server FTP" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "Sfoglia Documenti" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Sfoglia" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Indirizzo Server o IP e porta a cui gli utenti dovrebbero connettersi per " +"l'accesso al DMS" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Deposito condiviso (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Indirizzo" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "Annulla" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Browse FTP documenti" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Configurazione applicazione know how" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Sfoglia documento" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "o" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Sfoglia documento" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contents" diff --git a/document_ftp/i18n/ja.po b/document_ftp/i18n/ja.po new file mode 100644 index 00000000..8e5e6335 --- /dev/null +++ b/document_ftp/i18n/ja.po @@ -0,0 +1,127 @@ +# Japanese translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2012-12-21 23:00+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Japanese \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "FTPサーバを設定する" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "自動ディレクトの設定" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"ユーザがアクセスするOpenERPサーバのネットワークアドレスを指定して下さい。それはネットワークトポロジとその設定によって決まり、ユーザに表示されるリン" +"クになります。\r\n" +"指定の形式は HOST:PORT であり、デフォルトのホスト(ローカルホスト)がサーバからのアクセスに最も適しています。" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "ファイルをブラウズする" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "FTPサーバ" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "FTPサーバの設定" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_ブラウズ(_B)" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "サーバアドレスあるいはDMSアクセスのために接続するIPとポート" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "共有リプジトリ(FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "住所" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "FTP文書をブラウズする" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "知識アプリケーションの設定" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "文書をブラウズする" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "文書をブラウズする" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contents" diff --git a/document_ftp/i18n/mk.po b/document_ftp/i18n/mk.po new file mode 100644 index 00000000..25251bc8 --- /dev/null +++ b/document_ftp/i18n/mk.po @@ -0,0 +1,131 @@ +# Macedonian translation for openobject-addons +# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2013. +# Sofce Dimitrijeva , 2013. +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2013-03-28 22:42+0000\n" +"Last-Translator: Sofce Dimitrijeva \n" +"Language-Team: ESKON-INZENERING\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" +"Language: mk\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Конфигурирај FTP сервер" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Автоматска конфигурација на директориум" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Ја покажува адресата на која OpenERP ќе биде достапен за крајните корисници. " +"Ова зависи од мрежната топологија и конфигурација и има влијание само врз " +"линковите прикажани на корисниците. Форматот е HOST:PORT и стандардниот хост " +"(localhost) е за пристап само преку самиот сервер.." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "knowledge.config.settings" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Прелистување фајлови" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "Кликни на url-то за прелистување на документите" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "FTP сервер" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "Конфигурација на FTP серверот" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "Прелистување документи" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Прегледај" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Адреса на серверот или IP и порт на кои корисниците се поврзуваат за пристап " +"до DMS" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Заеднички магацин (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Адреса" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "Откажи" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Прелистување на документи преку FTP" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Конфигурација за апликација Знаење" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Прелистување на документи" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "или" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Прелистај документ" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contents" diff --git a/document_ftp/i18n/mn.po b/document_ftp/i18n/mn.po new file mode 100644 index 00000000..d74026b0 --- /dev/null +++ b/document_ftp/i18n/mn.po @@ -0,0 +1,129 @@ +# Mongolian translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2012-12-21 23:00+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Mongolian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "FTP Сервэр тохируулах" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Автомат Директорын Тохиргоо" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Эцсийн хэрэглэгчидийн OpenERP-руу хандаж чадах сүлжээний хаягийг илэрхийлнэ. " +"Энэ танай сүлжээний бүтэц, тохиргооноос хамаарах бөгөөд зөвхөн хэрэглэгчдэд " +"харагдах холбоост л нөлөөтэй. Формат нь HOST:PORT гэсэн загвартай бөгөөд " +"анхын host нь (localhost) гэж байдаг нь зөвхөн сервер машин дээрээс хандахад " +"л тохирно." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Файлуудыг тольдох" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "FTP Сервер" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "FTP Серверийн тохиргоо" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Тольдох" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "DMS хандалтаар хандах серверийн хаяг эсвэл IP болон порт." + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Агуулахыг хуваалцах (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Хаяг" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "FTP-ээр баримт оруулах" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Мэдлэгийн Програмын Тохиргоо" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Баримт оруулах" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Оруулах баримт" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contents" diff --git a/document_ftp/i18n/nb.po b/document_ftp/i18n/nb.po new file mode 100644 index 00000000..0e8eec6e --- /dev/null +++ b/document_ftp/i18n/nb.po @@ -0,0 +1,131 @@ +# Norwegian Bokmal translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2012-12-21 23:00+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Norwegian Bokmal \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Konfigurer FTP serveren" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Automatisk Katalog Konfigurasjon." + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Indikere nettverksadressen som din OpenERP server bør være tilgjengelige for " +"sluttbrukerne. Dette avhenger av nettverkstopologi og konfigurasjon, og vil " +"bare påvirke lenker som vises til brukerne. Formatet er HOST: PORT og " +"standard verten (lokalhost) er bare egnet for tilgang fra serveren maskinen " +"selv .." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Bla i filer" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "FTP-tjener" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "FTP Serverkonfigurasjon" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Bla gjennom" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Server adresse eller IP og port til hvilke brukere som skal koble seg til " +"for DMS tilgang" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Wikimedia Commons (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Adresse" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Document FTP Bla i." + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Kunnskap Programkonfigurasjon" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Dokument Bla i." + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Bla igjennom dokument" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_konfig_innhold" diff --git a/document_ftp/i18n/nl.po b/document_ftp/i18n/nl.po new file mode 100644 index 00000000..00ab719e --- /dev/null +++ b/document_ftp/i18n/nl.po @@ -0,0 +1,131 @@ +# Dutch translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2012-12-21 23:00+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Dutch \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "FTP Server configureren" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Auto map configuratie" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Geeft het netwerkadres aan waarop uw OpenERP server te vinden zou moeten " +"zijn voor eindgebruikers. Dit hangt af van netwerk topologie en configuratie " +"en zal alleen de link beïnvloeden die wordt getoond aan de gebruikers. Het " +"formaat HOST:PORT en standaard host (localhost) zijn allen geschikt voor " +"toegang vanaf de server machine zelf." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "knowledge.config.settings" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Bestanden bladeren" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "Klik op de url om door de documenten te bladeren" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "FTP server" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "FTP server configuratie" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "Blader door documenten" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Bladeren" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Server adres of IP en poort waarmee gebruikers moeten verbinden voor DMS " +"toegang" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Gedeelde repository (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Adres" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "Annuleren" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Document FTP bladeren" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Kennis applicatie configuratie" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Document bladeren" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "of" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Document bladeren" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contents" diff --git a/document_ftp/i18n/pl.po b/document_ftp/i18n/pl.po new file mode 100644 index 00000000..03b319a0 --- /dev/null +++ b/document_ftp/i18n/pl.po @@ -0,0 +1,130 @@ +# Polish translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2013-11-20 18:01+0000\n" +"Last-Translator: Mirosław Bojanowicz \n" +"Language-Team: Polish \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Konfiguruj Serwer FTP" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Autokonfiguracja katalogu" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Wskazuje adres sieciowy na którym twój serwer OpenERP powinien być dostępny " +"dla użytkowników końcowych. To zależy od topologii sieci i ustawień i ma " +"efekt tylko w odniesieniu do linków wyświetlanych użytkownikom. Format to " +"HOST:PORT i domyślny (localhost) jest do użytku tylko z poziomu serwera." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "knowledge.config.settings" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Przeglądaj pliki" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "Kliknij adres url żeby przeglądać dokumenty" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "Serwer FTP" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "Konfiguracja serwera FTP" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "Przeglądaj Dokumenty" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Przeglądaj" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Adres serwera lub IP i port do którego użytkownik powinien się podłączyć dla " +"dostępu do DMS (System Zarządzania Dokumentami)." + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Współdzielone repozytorium (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Adresy" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "Anuluj" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "FTP Przeglądaj dokument" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Konfiguracja aplikacji wiedzy" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Przeglądanie dokumentów" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "lub" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Przeglądaj dokumenty" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contents" diff --git a/document_ftp/i18n/pt.po b/document_ftp/i18n/pt.po new file mode 100644 index 00000000..13a8a060 --- /dev/null +++ b/document_ftp/i18n/pt.po @@ -0,0 +1,131 @@ +# Portuguese translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2013-01-18 10:48+0000\n" +"Last-Translator: Rui Franco (multibase.pt) \n" +"Language-Team: Portuguese \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Configurar servidor de FTP" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Configuração automática de diretórios" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Indicar o endereço de rede em que o servidor OpenERP deve ser acedido por " +"utilizadores finais. Isso depende da topologia da rede e configuração, e só " +"vai afectar os links exibidos aos utilizadores. O formato é HOST:PORT e o " +"host padrão (localhost) só é adequado para o acesso da máquina do servidor " +"em si.." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "knowledge.config.settings" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Procurar Ficheiros" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "Carregue no URL para percorrer os documentos" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "Servidor FTP" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "Configuração do servidor FTP" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "Percorrer os documentos" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Procurar" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Endereço do servidor ou IP e a porta à qual os utilizadores devem se conetar " +"para acesso DMS" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Repositório Partilhado (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Endereço" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "Cancelar" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Procurar Documento FTP" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Configuração da Aplicação do conhecimento" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Pesquisar Documento" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "ou" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Procurar Documento" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contents" diff --git a/document_ftp/i18n/pt_BR.po b/document_ftp/i18n/pt_BR.po new file mode 100644 index 00000000..0298141f --- /dev/null +++ b/document_ftp/i18n/pt_BR.po @@ -0,0 +1,130 @@ +# Brazilian Portuguese translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2012-12-21 23:00+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Brazilian Portuguese \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Configurar Servidor de FTP" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Configuração Automática de Diretório" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Indique o endereço em que seu servidor OpenERP deve ser acessível para os " +"usuários finais. Isso depende da sua topologia de rede e configuração. O " +"formato é HOST:PORT e o host padrão (localhost) é adequado apenas para " +"acesso a partir da máquina própria maquina.." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "knowledge.config.settings" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Navegar pelos Arquivos" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "Clique na url para navegar pelos documentos" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "Servidor FTP" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "Configuração do Servidor FTP" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "Navegar pelos Documentos" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "(_B) Navegar" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"O endereço do servidor ou IP e porta que o usuário deve conectar para acesso " +"DMS." + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Repositório Compartilhado (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Endereço" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "Cancelar" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Navegador FTP de Documentos" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Configuração da Aplicação de Conhecimento" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Navegador de Documentos" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "ou" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Navegar por Documentos" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contents" diff --git a/document_ftp/i18n/ro.po b/document_ftp/i18n/ro.po new file mode 100644 index 00000000..97a1f7f9 --- /dev/null +++ b/document_ftp/i18n/ro.po @@ -0,0 +1,131 @@ +# Romanian translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2013-01-23 20:42+0000\n" +"Last-Translator: ERPSystems.ro \n" +"Language-Team: Romanian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Configureaza Serverul FTP" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Configurare Director Automata" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Indica adresa retelei la care serverul OpenERP ar trebui sa fie accesibil " +"utilizatorilor finali. Aceasta depinde de topologia si configurarea retelei " +"dumneavoastra, si va afecta doar link-urile afisate utilizatorilor. Formatul " +"este HOST:PORT, iar gazda predenifinta (localhost) (gazda locala) este " +"potrivita doar pentru accesul de la server.." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "cunostinte.config.setari" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Rasfoieste fisiere" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "Faceti click pe url pentru a cauta documentele" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "Server FTP" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "Configurare Server FTP" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "Cautare Documente" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Rasfoieste" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Adresa serverului sau IP-ul si portul la care utilizatorii ar trebui sa se " +"conecteze pentru acces DMS" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Depozit comun (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Adresa" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "Anuleaza" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Rasfoieste Documentul FTP" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Configurare Aplicare Cunostinte" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Rasfoire document" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "sau" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Rasfoieste Documentul" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_continuturi" diff --git a/document_ftp/i18n/ru.po b/document_ftp/i18n/ru.po new file mode 100644 index 00000000..ce93a7c1 --- /dev/null +++ b/document_ftp/i18n/ru.po @@ -0,0 +1,130 @@ +# Russian translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2012-12-21 23:00+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Russian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Настройка FTP сервера" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Автоматическая настройка каталога" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Указывает сетевой адрес, на котором сервер OpenERP должен быть доступен для " +"конечных пользователей. Это зависит от конфигурации и топологии сети и " +"влияет только на отображение ссылок. Формат АДРЕС:ПОРТ и адрес по умолчанию " +"(localhost) подходит только для доступа с самого сервера." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "knowledge.config.settings" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Просмотр файлов" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "Щелкните URL-адрес для просмотра документов" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "FTP Сервер" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "Настройка FTP сервера" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "Просмотр документов" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Обзор" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Адрес сервера или IP и порт для соединения пользователя и доступа к " +"документам" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Общее хранилище (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Адрес" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "Отмена" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Просмотр документа через FTP" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Настройка приложения Знания" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Просмотр документа" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "или" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Просмотр документа" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contents" diff --git a/document_ftp/i18n/sk.po b/document_ftp/i18n/sk.po new file mode 100644 index 00000000..6567b51c --- /dev/null +++ b/document_ftp/i18n/sk.po @@ -0,0 +1,124 @@ +# Slovak translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2012-12-21 23:00+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Slovak \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Prehľadávať súbory" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "FTP Server" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "Nastavenia FTP Servera" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Adresa" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "" diff --git a/document_ftp/i18n/sl.po b/document_ftp/i18n/sl.po new file mode 100644 index 00000000..622c5754 --- /dev/null +++ b/document_ftp/i18n/sl.po @@ -0,0 +1,130 @@ +# Slovenian translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2013-11-09 10:27+0000\n" +"Last-Translator: Darja Zorman \n" +"Language-Team: Slovenian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Konfiguriraj FTP strežnik" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Avto konfiguracija map" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Določa omrežni naslov, na katerem bo dosegljiv vaš OpenERP server za končne " +"uporabnike. To je odvisno od topologije in nastavitev vašega omrežja. Vpliva " +"samo na povezavo, ki se izpiše uporabniku. Format je HOST:PORT in privzeti " +"strežnik (localhost) je primeren samo za dostop iz serverja samega." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "knowledge.config.settings" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Brskanje Datoteke" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "Potrdite url za brskanje po dokumentih" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "Strežnik FTP" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "Konfiguracija FTP strežnika" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "brskanje po dokumentih" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Prebrskaj" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Naslov strežnika ali IP in vrata, na katerega se bodo uporabniki povezali za " +"DMS dostop" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Deljeni repozitorij (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Naslov" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "Preklic" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "FTP brskanje po dokumentih" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Nastavitev aplikacije znanja" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Brskanje po dokumentih" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "ali" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Brskanje po dokumentu" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contents" diff --git a/document_ftp/i18n/sr.po b/document_ftp/i18n/sr.po new file mode 100644 index 00000000..2af0fc6c --- /dev/null +++ b/document_ftp/i18n/sr.po @@ -0,0 +1,126 @@ +# Serbian translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2012-12-21 23:00+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Serbian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Auto Podesavanje dIrektorijuma" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Pretrazi fajlove" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "FTP Server" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "KOnfiguracija FTP Servera" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Browse" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Adresa Servera ili IP i Port na koji bi korisnik trebalo da se konektuje za " +"DMS pristup" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Deljeno skladiste (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "FTP pretrazi Dokumente" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Pretrazi Dokumente" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Pretrazi Dokument" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contents" diff --git a/document_ftp/i18n/sr@latin.po b/document_ftp/i18n/sr@latin.po new file mode 100644 index 00000000..08f95389 --- /dev/null +++ b/document_ftp/i18n/sr@latin.po @@ -0,0 +1,131 @@ +# Serbian Latin translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2012-12-21 23:00+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Serbian Latin \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Podesi FTP server" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Auto-podešavanje direktorijuma" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Odredite adresu mreže na koju bi Vaši OpenERP server trebalo da bude " +"dostupan za konačne korisnike. Ovo zavisi od Vaše mrežne toplogije i " +"podešavanja, i neće imati uticaja na linkove prikazane korisnicima. Format " +"je HOST:PORT i domaćin po defaultu (localhost) je jedino prikladan za " +"pristup na server sa same mašine." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Pretraži datoteke" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "FTP Server" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "Podešavanje FTP servera" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Pretraži" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Adresa Servera ili IP i Port na koji bi korisnik trebalo da se konektuje za " +"DMS pristup" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Deljeno skladište" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Adresa" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Pretraži FTP dokumente" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Podešavanje aplikacije znanja" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Pretrazi Dokumente" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Pretraži dokumenta" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contents" diff --git a/document_ftp/i18n/sv.po b/document_ftp/i18n/sv.po new file mode 100644 index 00000000..dc2e1d31 --- /dev/null +++ b/document_ftp/i18n/sv.po @@ -0,0 +1,131 @@ +# Swedish translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2014-03-27 12:39+0000\n" +"Last-Translator: Anders Wallenquist \n" +"Language-Team: Swedish \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2014-03-28 06:44+0000\n" +"X-Generator: Launchpad (build 16967)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "Konfigurera FTP-servern" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Automatisk katalogkonfiguration" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"Ange nätverksadressen som din OpenERP servern ska vara nåbar på för " +"slutanvändare. Det beror på ditt nätverk topologi och konfiguration, och " +"kommer endast att påverka hur länkarna visas för användarna. Formatet är " +"värd: PORT och förvald värd (localhost) är endast lämplig för åtkomst från " +"servern själva maskinen .." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "knowledge.config.settings" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Bläddra bland filer" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "Klicka på url-en för att bläddra bland dokumenten" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "FTP-server" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "FTP-serverkonfiguration" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "Dokumentbläddring" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Bläddra" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"Serveradress eller IP och den port som användarna ska ansluta till för DMS-" +"tillgång" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Delat arkiv (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Adress" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "Avbryt" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "Bläddra bland dokumenten via FTP" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Konfiguration av kunskapshanteringsapplikationen" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Dokumentbläddring" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "eller" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Bläddra bland dokument" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contents" diff --git a/document_ftp/i18n/tr.po b/document_ftp/i18n/tr.po new file mode 100644 index 00000000..ff71f253 --- /dev/null +++ b/document_ftp/i18n/tr.po @@ -0,0 +1,130 @@ +# Turkish translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2013-02-06 22:28+0000\n" +"Last-Translator: Ahmet Altınışık \n" +"Language-Team: Turkish \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "FTP Sunucusunu Yapılandır" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "Otomatik Klasör Yapılandırması" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"OpenERP sunucusunda son kullanıcıların erişebileceği ağ adresini belirtir. " +"Bu, ağ yapınıza ve yapılandırmasına bağlıdır ve yalnızca kullanıcılara " +"gösterilen ağları etkiler. Formatı HOST:PORT şeklindedir ve varsayılan " +"sunucu (localhost) yalnızca sunucu cihazından erişim için uygundur." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "knowledge.config.settings" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "Dosyalara Gözat" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "Dökümanları incelemek için adrese tıklayın" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "FTP Sunucusu" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "FTP Sunucusu Yapılandırması" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "Dökümanları İncele" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "_Gözat" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" +"DMS erişimi için kullanıcıların bağlanacağı sunucu adresi ya da IP ve " +"bağlantı noktasıdır." + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "Paylaşılan Havuz (FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "Adres" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "İptal" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "FTP BelgeTaraması" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "Bilgi Birikimi Uygulama Ayarları" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "Belge Tarama" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "ya da" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "Belge Tara" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contents" diff --git a/document_ftp/i18n/vi.po b/document_ftp/i18n/vi.po new file mode 100644 index 00000000..66585e99 --- /dev/null +++ b/document_ftp/i18n/vi.po @@ -0,0 +1,124 @@ +# Vietnamese translation for openobject-addons +# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2013-01-17 09:02+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Vietnamese \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "" diff --git a/document_ftp/i18n/zh_CN.po b/document_ftp/i18n/zh_CN.po new file mode 100644 index 00000000..6a5b2fa1 --- /dev/null +++ b/document_ftp/i18n/zh_CN.po @@ -0,0 +1,126 @@ +# Chinese (Simplified) translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2013-07-19 16:04+0000\n" +"Last-Translator: 盈通 ccdos \n" +"Language-Team: Chinese (Simplified) \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "配置 FTP 服务器" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "自动目录设置" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"输入你的最终用户用于连接你OpenERP服务器的网址。基于你的网络配置,会影响客户端显示的链接。格式是:主机:端口。注意localhost只是在服务器本机" +"才有用的。" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "knowledge.config.settings" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "浏览文件" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "点击 urk 来浏览文档" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "FTP 服务器" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "FTP 服务器设置" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "浏览文档" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "浏览(_B)" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "服务器地址或IP地址,以及端口。用于用户连接文档管理系统。" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "共享仓库(FTP)" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "地址" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "取消" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "文档 FTP 浏览" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "知识管理应用设置" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "文档浏览" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "或" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "浏览文档" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contents" diff --git a/document_ftp/i18n/zh_TW.po b/document_ftp/i18n/zh_TW.po new file mode 100644 index 00000000..3c7461f7 --- /dev/null +++ b/document_ftp/i18n/zh_TW.po @@ -0,0 +1,126 @@ +# Chinese (Traditional) translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-06-07 19:36+0000\n" +"PO-Revision-Date: 2012-12-21 23:00+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Chinese (Traditional) \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-11-21 06:07+0000\n" +"X-Generator: Launchpad (build 16831)\n" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Configure FTP Server" +msgstr "設置FTP 伺服器" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_configuration +msgid "Auto Directory Configuration" +msgstr "自動目錄配置" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "" +"Indicate the network address on which your OpenERP server should be " +"reachable for end-users. This depends on your network topology and " +"configuration, and will only affect the links displayed to the users. The " +"format is HOST:PORT and the default host (localhost) is only suitable for " +"access from the server machine itself.." +msgstr "" +"說明OpenERP的服務器上的網絡地址應該為最終用戶訪問。這取決於您的網絡拓撲和配置,而且只會影響顯示給用戶的鏈接。的格式為HOST:PORT和預設的主機" +"(localhost)的訪問從服務器本身只適合.." + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_knowledge_config_settings +msgid "knowledge.config.settings" +msgstr "" + +#. module: document_ftp +#: model:ir.actions.act_url,name:document_ftp.action_document_browse +msgid "Browse Files" +msgstr "瀏覽檔案" + +#. module: document_ftp +#: help:knowledge.config.settings,document_ftp_url:0 +msgid "Click the url to browse the documents" +msgstr "" + +#. module: document_ftp +#: field:document.ftp.browse,url:0 +msgid "FTP Server" +msgstr "FTP 伺服器" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory +msgid "FTP Server Configuration" +msgstr "FTP Server Configuration" + +#. module: document_ftp +#: field:knowledge.config.settings,document_ftp_url:0 +msgid "Browse Documents" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "_Browse" +msgstr "瀏覽(_B)" + +#. module: document_ftp +#: help:document.ftp.configuration,host:0 +msgid "" +"Server address or IP and port to which users should connect to for DMS access" +msgstr "服務器地址或IP地址和端口,用戶應該連接到DMS訪問" + +#. module: document_ftp +#: model:ir.ui.menu,name:document_ftp.menu_document_browse +msgid "Shared Repository (FTP)" +msgstr "供享的儲存庫" + +#. module: document_ftp +#: field:document.ftp.configuration,host:0 +msgid "Address" +msgstr "地址" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Cancel" +msgstr "" + +#. module: document_ftp +#: model:ir.model,name:document_ftp.model_document_ftp_browse +msgid "Document FTP Browse" +msgstr "瀏覽FTP文件" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "Knowledge Application Configuration" +msgstr "知識應用配置" + +#. module: document_ftp +#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse +msgid "Document Browse" +msgstr "文件瀏覽" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "or" +msgstr "" + +#. module: document_ftp +#: view:document.ftp.browse:0 +msgid "Browse Document" +msgstr "瀏覽文件" + +#. module: document_ftp +#: view:document.ftp.configuration:0 +msgid "res_config_contents" +msgstr "res_config_contents" diff --git a/document_ftp/images/1_configure_ftp.jpeg b/document_ftp/images/1_configure_ftp.jpeg new file mode 100644 index 00000000..3a14d433 Binary files /dev/null and b/document_ftp/images/1_configure_ftp.jpeg differ diff --git a/document_ftp/images/2_document_browse.jpeg b/document_ftp/images/2_document_browse.jpeg new file mode 100644 index 00000000..865e531e Binary files /dev/null and b/document_ftp/images/2_document_browse.jpeg differ diff --git a/document_ftp/images/3_document_ftp.jpeg b/document_ftp/images/3_document_ftp.jpeg new file mode 100644 index 00000000..ef1ea46c Binary files /dev/null and b/document_ftp/images/3_document_ftp.jpeg differ diff --git a/document_ftp/res_config.py b/document_ftp/res_config.py new file mode 100644 index 00000000..cb17bf0e --- /dev/null +++ b/document_ftp/res_config.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Business Applications +# Copyright (C) 2004-2012 OpenERP S.A. (). + +# ThinkOpen Solutions Brasil (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.osv import fields, osv +from openerp.tools import config + +class documnet_ftp_setting(osv.osv_memory): + _name = 'knowledge.config.settings' + _inherit = 'knowledge.config.settings' + _columns = { + 'ftp_server_host' : fields.char(string='Host'), + 'ftp_server_port' : fields.char(string='Port'), + 'document_ftp_url': fields.char('Browse Documents', size=128, + help="""Click the url to browse the documents""", readonly=True), + } + + def get_default_ftp_config(self, cr, uid, fields, context=None): + action = self.pool.get('ir.model.data').get_object(cr, uid, 'document_ftp', 'action_document_browse') + return {'document_ftp_url': action.url} + diff --git a/document_ftp/res_config_view.xml b/document_ftp/res_config_view.xml new file mode 100644 index 00000000..3ba0b549 --- /dev/null +++ b/document_ftp/res_config_view.xml @@ -0,0 +1,17 @@ + + + + + Knowledge Application + knowledge.config.settings + + + + + + + + + + + diff --git a/document_ftp/security/ir.model.access.csv b/document_ftp/security/ir.model.access.csv new file mode 100644 index 00000000..4a08a4aa --- /dev/null +++ b/document_ftp/security/ir.model.access.csv @@ -0,0 +1 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink diff --git a/document_ftp/test/document_ftp_test.yml b/document_ftp/test/document_ftp_test.yml new file mode 100644 index 00000000..b3ff2a89 --- /dev/null +++ b/document_ftp/test/document_ftp_test.yml @@ -0,0 +1,87 @@ +- | + In order to test the document_ftp module in OpenERP, I will try different operations on the FTP interface and check their impacts on OpenERP's documents and vice-versa. +- + In order to test the behaviour of resource Directory, I will make one resource Directory "Labels" in OpenERP having type "Other Resources" and Directory mapped to object "Partner" +- + !record {model: 'document.directory', id: dir_label}: + name : "Labels" + storage_id : document.storage_default + type : ressource + content_ids: + - name: "Label" + report_id : base.res_partner_address_report +- + Assign "res.partner" object to ressource_type_id. +- + !python {model: document.directory}: | + ids = self.pool.get('ir.model').search(cr, uid, [('model','=','res.partner')]) + id = self.write(cr, uid, [ref("dir_label")], {'ressource_type_id' : ids[0]}, context) +- + In order to check static directory in OpenERP which is the real directory just like system's local folders, + First I create a directory in OpenERP named "Directory 1" with storage as "Default File storage" and type as "Static Directory" +- + !record {model: 'document.directory', id: directory_file}: + name : "File" + storage_id : document.storage_default + type : directory +- + I am create one Document name "Document" and select "File" as its Directory, +- + When I am creating the record, "Resource Title" is filled automatic with "Document". +- + !record {model: 'ir.attachment', id: document_1}: + name : "Document" + parent_id : directory_file +- + In order to connect FTP server and set "File" path, + I create one directory "New" in "File" directory from FTP and check its effect in OpenERP. +- + Also Rename the directory name "New" to "New Directory". +- + Remove directory "New Directory" and remove file "Document". +- + !python {model: ir.attachment}: | + from ftplib import FTP + from tools.misc import detect_ip_addr + from tools import config + ftp = FTP() + 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 = config.get('ftp_server_port','8021') + ftp.connect(host,port) + user = self.pool.get('res.users').read(cr, uid, uid, context) + ftp.login(user.get('login',''),user.get('password','')) + ftp.cwd("/" + cr.dbname+"/Documents/File/") + ftp.mkd("New") + ftp.rename('New','New Directory') + ftp.cwd("/" + cr.dbname+"/Documents/File/") + ftp.rmd('New Directory') + ftp.delete('Document') + ftp.quit() +- + In order to check directory created from FTP is working perfectly +- + Now I will test the same for Resource directory which is mapped with OpenERP object. + When you open this directory from FTP clients, it displays each record of mapped resource object as directory. +- + Now I test FTP client and Open the "Labels" Directory to check Resource Directory in FTP. + I can see that all Labels of OpenERP are shown as children of "Labels" in FTP client as Directories. +- + !python {model: ir.attachment}: | + from ftplib import FTP + from tools.misc import detect_ip_addr + from tools import config + ftp = FTP() + 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 = config.get('ftp_server_port','8021') + ftp.connect(host,port) + user = self.pool.get('res.users').read(cr, uid, uid, context) + ftp.login(user.get('login',''),user.get('password','')) + ftp.cwd("/" + cr.dbname+"/Documents/Labels/") +- + I make sure that I Open Labels Directory successfully. diff --git a/document_ftp/test/document_ftp_test2.yml b/document_ftp/test/document_ftp_test2.yml new file mode 100644 index 00000000..ce8e2590 --- /dev/null +++ b/document_ftp/test/document_ftp_test2.yml @@ -0,0 +1,289 @@ +- + In order to test the document_ftp functionality +- + I open the 8021 port and see for ftp presence there +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + ftp = te.get_plain_ftp(timeout=2.0) + assert ftp.sock and (ftp.lastresp == '220'), ftp.lastresp + ftp.close() +- + I read the list of databases at port 8021 and confirm our db is + there +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + ftp = te.get_ftp_login(cr, uid, self) + assert cr.dbname in ftp.nlst("/") + ftp.close() +- + I try to locate the default "Documents" folder in the db. +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + ftp = te.get_ftp_login(cr, uid, self) + ftp.cwd('Documents') + ftp.close() +- + I create a "test.txt" file at the server (directly). The file + should have the "abcd" content +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + from cStringIO import StringIO + ftp = te.get_ftp_folder(cr, uid, self, 'Documents') + fdata = StringIO('abcd') + ftp.storbinary('STOR test.txt', fdata) + ftp.close() +- + I look for the "test.txt" file at the server +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + ftp = te.get_ftp_folder(cr, uid, self, 'Documents') + assert ftp.nlst("test.txt") == ['test.txt'] + ftp.close() +- + I check that the content of "test.txt" is "abcd" +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + from cStringIO import StringIO + ftp = te.get_ftp_folder(cr, uid, self, 'Documents') + gotdata = te.get_ftp_fulldata(ftp, "test.txt") + ftp.close() + assert gotdata == 'abcd', 'Data: %r' % gotdata +- + I append the string 'defgh' to "test.txt" +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + from cStringIO import StringIO + ftp = te.get_ftp_folder(cr, uid, self, 'Documents') + fdata = StringIO('defgh') + ftp.storbinary('APPE test.txt', fdata) + ftp.close() +- + I check that the content of "text.txt" is 'abcddefgh' +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + from cStringIO import StringIO + ftp = te.get_ftp_folder(cr, uid, self, 'Documents') + gotdata = te.get_ftp_fulldata(ftp, "test.txt") + ftp.close() + assert gotdata == 'abcddefgh', 'Data: %r' % gotdata +- + I try to cd into an non-existing folder 'Not-This' +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + import ftplib + ftp = te.get_ftp_login(cr, uid, self) + try: + ftp.cwd('/Not-This') + assert False, "We should't be able to change here" + except ftplib.error_perm: + pass + except OSError, err: + ftp.close() + assert err.errno == 2, err.errno + ftp.close() +- + I create a "test2.txt" file through FTP. +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + from cStringIO import StringIO + ftp = te.get_ftp_folder(cr, uid, self, 'Documents') + fdata = StringIO('abcd') + ftp.storbinary('STOR test2.txt', fdata) + ftp.close() +- + I look for the "test2.txt" file at the server +- + !python {model: ir.attachment }: | + cr.rollback() # restart transaction to see changes (FTP-FS uses its own cursor) + ids = self.search(cr, uid, [('name', '=', 'test2.txt')]) + assert ids, "No test2.txt file found." +- + I delete the "test2.txt" file using FTP. +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + from cStringIO import StringIO + ftp = te.get_ftp_folder(cr, uid, self, 'Documents') + ftp.delete('test2.txt') + ftp.close() +- + I check at the server that test2.txt is deleted +- + !python {model: ir.attachment }: | + cr.rollback() # restart transaction to see changes (FTP-FS uses its own cursor) + ids = self.search(cr, uid, [('name', '=', 'test2.txt')]) + assert not ids, "test2.txt file can still be found." +- + I create a test2.txt file again. +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + from cStringIO import StringIO + ftp = te.get_ftp_folder(cr, uid, self, 'Documents') + fdata = StringIO('abcd') + ftp.storbinary('STOR test2.txt', fdata) + ftp.close() + cr.rollback() # restart transaction to see changes (FTP-FS uses its own cursor) +- + I delete the test2.txt from the server (RPC). +- + !delete { model: ir.attachment, id:, search: "[('name','=','test2.txt')]" } +- + I also commit, because ftp would run in a different transaction. +- + !python {model: ir.attachment}: | + cr.commit() +- + I check through FTP that test2.txt does not appear. +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + import ftplib + ftp = te.get_ftp_folder(cr, uid, self, 'Documents') + try: + nlst_result = ftp.nlst("test2.txt") + except ftplib.error_perm: # 550 error: 'path not exists' + nlst_result = [] + assert "test2.txt" not in nlst_result, "Files: %r" % nlst_result + ftp.close() +- + I create a "test-name.txt" file +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + from cStringIO import StringIO + ftp = te.get_ftp_folder(cr, uid, self, 'Documents') + fdata = StringIO('abcd') + ftp.storbinary('STOR test-name.txt', fdata) + ftp.close() +- + I rename the "test-name.txt" file through ftp. +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + ftp = te.get_ftp_folder(cr, uid, self, 'Documents') + ftp.rename("test-name.txt", "test-renamed.txt") + ftp.close() +- + I check that test-name.txt has been renamed. +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + from ftplib import error_perm + ftp = te.get_ftp_folder(cr, uid, self, 'Documents') + try: + res = ftp.nlst("test-name.txt") + assert res == [], "File has not been renamed!" + except error_perm, e: + pass + assert ftp.nlst("test-renamed.txt") == ['test-renamed.txt'] + ftp.close() +- + I create a new folder 'Test-Folder2' through FTP +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + ftp = te.get_ftp_folder(cr, uid, self, 'Documents') + ftp.mkd("Test-Folder2") + ftp.close() +- + I create a file 'test3.txt' at the 'Test-Folder2' +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + from cStringIO import StringIO + ftp = te.get_ftp_folder(cr, uid, self, 'Documents/Test-Folder2') + fdata = StringIO('abcd') + ftp.storbinary('STOR test3.txt', fdata) + ftp.close() +- + I try to retrieve test3.txt +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + ftp = te.get_ftp_folder(cr, uid, self, 'Documents/Test-Folder2') + assert ftp.nlst("test3.txt") == ['test3.txt'], "File test3.txt is not there!" + ftp.close() +- + I create a new folder, 'Test-Folder3', through FTP + I try to move test3.txt to 'Test-Folder3' +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + ftp = te.get_ftp_folder(cr, uid, self, 'Documents') + ftp.mkd("Test-Folder3") + ftp.close() + # TODO move +- + I remove the 'Test-Folder3' +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + ftp = te.get_ftp_folder(cr, uid, self, 'Documents') + ftp.rmd("Test-Folder3") + ftp.close() +- + I check that test3.txt is removed. +- + I create 5 files through FTP +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + from cStringIO import StringIO + ftp = te.get_ftp_folder(cr, uid, self, 'Documents/Test-Folder2') + fdata = StringIO('abcd') + for i in range(0, 5): + fdata.seek(0) + ftp.storbinary('STOR test-name%s.txt' %i, fdata) + ftp.close() +- + I list the 5 files, check speed +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + ftp = te.get_ftp_folder(cr, uid, self, 'Documents/Test-Folder2') + assert len(ftp.nlst()) >= 5, "We haven't managed to store 5 files!" +- + I read the 5 files, check speed +- + I move the 5 files to 'Test-Folder2' +- + I delete the 5 files +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + from cStringIO import StringIO + ftp = te.get_ftp_folder(cr, uid, self, 'Documents/Test-Folder2') + ftp.delete('test3.txt') + for i in range(0, 5): + ftp.delete('test-name%s.txt' %i) + ftp.close() + +- + I delete the "test.txt" and "test-renamed.txt" file +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + from cStringIO import StringIO + ftp = te.get_ftp_folder(cr, uid, self, 'Documents') + ftp.delete('test.txt') + ftp.delete('test-renamed.txt') + ftp.close() +- + I remove the 'Test-Folder2' +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + ftp = te.get_ftp_folder(cr, uid, self, 'Documents') + ftp.rmd("Test-Folder2") + ftp.close() diff --git a/document_ftp/test/document_ftp_test3.yml b/document_ftp/test/document_ftp_test3.yml new file mode 100644 index 00000000..a51f259f --- /dev/null +++ b/document_ftp/test/document_ftp_test3.yml @@ -0,0 +1,92 @@ +- + In order to check international character functionality +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + ftp = te.get_plain_ftp(timeout=1.0) +- + I create in the server a folder called ' ' +- + !record {model: document.directory, id: dir_itests }: + name: ' ' + parent_id: document.dir_root +- + And then I create another folder, under it, through FTP +- + !python {model: ir.attachment}: | + cr.commit() + from document_ftp import test_easyftp as te + ftp = te.get_ftp_folder(cr, uid, self, 'Documents/ ') + ftp.mkd(" ") +- + I check that this folder exists at the server +- + !assert {model: document.directory, id: , search: "[('name','=',' ')]" }: + - parent_id != False +- + I login with FTP and check that ' ' is there +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + ftp = te.get_ftp_folder(cr, uid, self, 'Documents/ / ') +- + I create a file named '' into that folder +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + from cStringIO import StringIO + ftp = te.get_ftp_folder(cr, uid, self, 'Documents/ / ') + fdata = StringIO(' utf-8') + ftp.storbinary('STOR .txt', fdata) +- + I remove the '.txt' file +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + from cStringIO import StringIO + ftp = te.get_ftp_folder(cr, uid, self, 'Documents/ / ') + ftp.delete('.txt') +- + I rename ' ' into '' +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + ftp = te.get_ftp_folder(cr, uid, self, 'Documents/ ') + ftp.rename(" ", "") +- + I place a file 'file 3' in '' +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + from cStringIO import StringIO + ftp = te.get_ftp_folder(cr, uid, self, 'Documents/ /') + fdata = StringIO(' ') + ftp.storbinary('STOR file 3.txt', fdata) +- + I rename the file into file+range(1..200) (large filename) +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + from cStringIO import StringIO + ftp = te.get_ftp_folder(cr, uid, self, 'Documents/ /') + vuvuzela = 'b'+''.join('z' * 200)+'!' + ftp.rename("file 3.txt", vuvuzela) +- + I delete the file with the large name +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + from cStringIO import StringIO + ftp = te.get_ftp_folder(cr, uid, self, 'Documents/ /') + vuvuzela = 'b'+''.join('z' * 200)+'!' + ftp.delete(vuvuzela) + +- + I delete the testing folders +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + from cStringIO import StringIO + ftp = te.get_ftp_folder(cr, uid, self, 'Documents') + ftp.rmd(' /') + ftp.rmd(' ') diff --git a/document_ftp/test/document_ftp_test4.yml b/document_ftp/test/document_ftp_test4.yml new file mode 100644 index 00000000..9b311f64 --- /dev/null +++ b/document_ftp/test/document_ftp_test4.yml @@ -0,0 +1,187 @@ +- + In order to check dynamic folder functionality of document + FTP +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + ftp = te.get_plain_ftp(timeout=1.0) +- | + I create two partners 'Partner1' and 'Partner2'. + I create three partner categories: 'none', 'pat1' and 'all' + I attach Partner1 to pat1, Partner1+Partner2 to 'all' +- + !record {model: res.partner.category, id: tpat_categ_none }: + name: 'No partners' +- + !record {model: res.partner.category, id: tpat_categ_pat1 }: + name: 'Pat 1' +- + !record {model: res.partner.category, id: tpat_categ_all }: + name: 'All Partner1+2' +- + !record {model: res.partner, id: tpartner1 }: + name: Partner 1 + category_id: + - tpat_categ_pat1 + - tpat_categ_all +- + !record {model: res.partner, id: tpartner_2 }: + name: 'Partner 2' + category_id: + - tpat_categ_all +- + I create a resource folder of partners, by the (none, pat1, all) + categories. +- + !record {model: document.directory, id: dir_tests2 }: + name: Partners Testing + parent_id: document.dir_root + type: ressource + ressource_type_id: base.model_res_partner_category + domain: [] # TODO +- + I commit (because FTP operations are on different transaction) +- + !python {model: document.directory, id: }: | + cr.commit() +- + I browse through ftp in the resource folder, checking that three + categories are there. +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + ftp = te.get_ftp_folder(cr, uid, self, 'Documents/Partners Testing') + dirs = ftp.nlst() + for dir in [ 'All Partner1+2', 'No partners', 'Pat 1' ]: + assert dir in dirs, "Dir %s not in folder" % dir +- + I create a 'partners' folder by the first resource one. +- + !record {model: document.directory, id: dir_respart1 }: + name: Partners of Test + parent_id: dir_tests2 + type: ressource + ressource_type_id: base.model_res_partner + domain: "[('category_id','in',[active_id])]" + ressource_parent_type_id : base.model_res_partner_category +- + I commit (because FTP operations are on different transaction) +- + !python {model: document.directory, id: }: | + cr.commit() +- + I check through FTP that the correct partners are listed at each + 'partners' folder. +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + ftp = te.get_ftp_folder(cr, uid, self, 'Documents/Partners Testing') + correct = { 'All Partner1+2': [ 'Partner 1', 'Partner 2' ], + 'No partners': [], + 'Pat 1': ['Partner 1',] } + for dir in correct: + res = ftp.nlst(dir+'/Partners of Test') + assert res == correct[dir], "Dir %s falsely contains %s" %(dir, res) +- + I create an ir.attachment, attached (not related) to Partner1 +- + !record {model: ir.attachment, id: file_test1}: + name: File of pat1 + res_model: res.partner + res_id: !eval ref("tpartner1") +- + I commit (because FTP operations are on different transaction) +- + !python {model: document.directory, id: }: | + cr.commit() +- + I check that pat1/Partner1 folder has the file. + I check that all/Partner1 folder has the file +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + ftp = te.get_ftp_folder(cr, uid, self, 'Documents/Partners Testing') + dirs = [ 'All Partner1+2', 'Pat 1' ] + for dir in dirs: + res = ftp.nlst(dir+'/Partners of Test/Partner 1') + assert 'File of pat1' in res, "Dir %s contains only %s" %(dir, res) +- + I place a file at the 'pat1'/Partner1 folder, through FTP +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + from cStringIO import StringIO + ftp = te.get_ftp_folder(cr, uid, self, 'Documents/Partners Testing/Pat 1/Partners of Test/Partner 1') + fdata = StringIO('abcd') + ftp.storbinary('STOR pat1-dynamic.txt', fdata) + cr.rollback() # restart transaction to see changes (FTP-FS uses its own cursor) +- + I check at the server that the file is attached to Partner1 +- + !assert {model: ir.attachment, id: , search: "[('name','=','pat1-dynamic.txt')]" }: + - parent_id.name == 'Documents' + - res_model == 'res.partner' + - res_id != False +- + I try to create a file directly under the Partners Testing folder +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + import ftplib + from cStringIO import StringIO + ftp = te.get_ftp_folder(cr, uid, self, 'Documents/Partners Testing') + fdata = StringIO('abcd') + try: + ftp.storbinary('STOR stray.txt', fdata) + assert False, "We should't be able to create files here" + except ftplib.error_perm: + # That's what should happen + pass +- + I try to create a folder directly under the Partners Testing folder +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + import ftplib + from cStringIO import StringIO + ftp = te.get_ftp_folder(cr, uid, self, 'Documents/Partners Testing') + try: + ftp.mkd('Weird folder') + assert False, "We should't be able to create folders here" + except ftplib.error_perm: + # That's what should happen + pass +- + I check that all/Partner1 also has the file +- | + Bonus Piste: + I create a 'Partner3' under 'all' + +- + I delete "pat1-dynamic.txt" File. +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + from cStringIO import StringIO + ftp = te.get_ftp_folder(cr, uid, self, 'Documents/Partners Testing/Pat 1/Partners of Test/Partner 1') + ftp.delete('pat1-dynamic.txt') + ftp.close() + cr.rollback() # restart transaction to see changes (FTP-FS uses its own cursor) + +- + I delete the Partners Testing folder, "File of pat1" file, Partner and Partner category. +- + !python {model: document.directory}: | + attach_pool = self.pool.get('ir.attachment') + partner_categ_pool = self.pool.get('res.partner.category') + partner_pool = self.pool.get('res.partner') + + self.unlink(cr, uid, [ref('dir_tests2')]) + self.unlink(cr, uid, [ref('dir_respart1')]) + attach_pool.unlink(cr, uid, [ref('file_test1')]) + partner_categ_pool.unlink(cr, uid, [ref('tpat_categ_none')]) + partner_categ_pool.unlink(cr, uid, [ref('tpat_categ_pat1')]) + partner_categ_pool.unlink(cr, uid, [ref('tpat_categ_all')]) + partner_pool.unlink(cr, uid, [ref('tpartner1')]) + partner_pool.unlink(cr, uid, [ref('tpartner_2')]) + cr.commit() #required because all the operations via FTP were committed + diff --git a/document_ftp/test/document_ftp_test5.yml b/document_ftp/test/document_ftp_test5.yml new file mode 100644 index 00000000..a66f4099 --- /dev/null +++ b/document_ftp/test/document_ftp_test5.yml @@ -0,0 +1,30 @@ +- + In order to check the permissions setup and functionality of the + document module: +- + I create a testing user for the documents +- + I assign some ... group to the testing user +- + I create a "group testing" user, which also belongs to the same ... group +- + I create a "blocked" user. +- + I create (as root) a testing folder in the document hierarchy, and + assign ownership to the testing user, groups to the ... group. +- + I create a "private" folder inside the testing folder. +- + I try to read the testing folder as the testing user +- + I try to read the folder as the group user, it should fail. +- + I try to read the folder as the blocked user. +- + I create a "group" folder, with the ... group. +- + I try to read the "group" folder as the testing user +- + I try to read the "group" folder as the group user +- + I try to read the "group" folder as the blocked user diff --git a/document_ftp/test_easyftp.py b/document_ftp/test_easyftp.py new file mode 100644 index 00000000..407bb912 --- /dev/null +++ b/document_ftp/test_easyftp.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). + +# ThinkOpen Solutions Brasil (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +""" This is a testing module, which exports some functions for the YAML tests. + Instead of repeating the same FTP code all over, we prefer to have + it in this file +""" + +from ftplib import FTP +from openerp.tools import config + +def get_plain_ftp(timeout=10.0): + ftp = FTP() + host = config.get('ftp_server_host', '177.134.67.3') + port = config.get('ftp_server_port', '8021') + ftp.connect(host, port, timeout) + return ftp + +def get_ftp_login(cr, uid, ormobj): + ftp = get_plain_ftp() + user = ormobj.pool.get('res.users').browse(cr, uid, uid) + passwd = user.password or '' + if passwd.startswith("$1$"): + # md5 by base crypt. We cannot decode, wild guess + # that passwd = login + passwd = user.login + ftp.login(user.login, passwd) + ftp.cwd("/" + cr.dbname) + return ftp + +def get_ftp_anonymous(cr): + ftp = get_plain_ftp() + ftp.login('anonymous', 'the-test') + ftp.cwd("/") + return ftp + +def get_ftp_folder(cr, uid, ormobj, foldername): + ftp = get_ftp_login(cr, uid, ormobj) + ftp.cwd("/" + cr.dbname + "/" + foldername) + return ftp + +def get_ftp_fulldata(ftp, fname, limit=8192): + from functools import partial + data = [] + def ffp(data, ndata): + if len(data) + len(ndata) > limit: + raise IndexError('Data over the limit.') + data.append(ndata) + ftp.retrbinary('RETR %s' % fname, partial(ffp, data)) + return ''.join(data) + diff --git a/document_ftp/wizard/__init__.py b/document_ftp/wizard/__init__.py new file mode 100644 index 00000000..ba533caf --- /dev/null +++ b/document_ftp/wizard/__init__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). + +# ThinkOpen Solutions Brasil (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from . import ftp_browse +from . import ftp_configuration + diff --git a/document_ftp/wizard/ftp_browse.py b/document_ftp/wizard/ftp_browse.py new file mode 100644 index 00000000..d65fd92b --- /dev/null +++ b/document_ftp/wizard/ftp_browse.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). + +# ThinkOpen Solutions Brasil (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.osv import fields, osv +from .. import ftpserver + +class document_ftp_browse(osv.osv_memory): + _name = 'document.ftp.browse' + _description = 'Document FTP Browse' + + _columns = { + 'url' : fields.char('FTP Server', size=64, required=True), + } + + def default_get(self, cr, uid, fields, context=None): + res = {} + if 'url' in fields: + user_pool = self.pool.get('res.users') + current_user = user_pool.browse(cr, uid, uid, context=context) + data_pool = self.pool.get('ir.model.data') + aid = data_pool._get_id(cr, uid, 'document_ftp', 'action_document_browse') + aid = data_pool.browse(cr, uid, aid, context=context).res_id + ftp_url = self.pool.get('ir.actions.act_url').browse(cr, uid, aid, context=context) + url = ftp_url.url and ftp_url.url.split('ftp://') or [] + if url: + url = url[1] + if url[-1] == '/': + url = url[:-1] + else: + url = '%s:%s' % (ftpserver.HOST, ftpserver.PORT) + res['url'] = 'ftp://%s@%s' % (current_user.login, url) + return res + + def browse_ftp(self, cr, uid, ids, context=None): + data_id = ids and ids[0] or False + data = self.browse(cr, uid, data_id, context=context) + final_url = data.url + return { + 'type': 'ir.actions.act_url', + 'url':final_url, + 'target': 'new' + } + +document_ftp_browse() + diff --git a/document_ftp/wizard/ftp_browse_view.xml b/document_ftp/wizard/ftp_browse_view.xml new file mode 100644 index 00000000..7ccc7897 --- /dev/null +++ b/document_ftp/wizard/ftp_browse_view.xml @@ -0,0 +1,39 @@ + + + + + Document FTP Browse + document.ftp.browse + +
+ + + +
+
+
+
+
+ + + Document Browse + ir.actions.act_window + document.ftp.browse + + form + form + new + + + + +
+
diff --git a/document_ftp/wizard/ftp_configuration.py b/document_ftp/wizard/ftp_configuration.py new file mode 100644 index 00000000..64ee369e --- /dev/null +++ b/document_ftp/wizard/ftp_configuration.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). + +# ThinkOpen Solutions Brasil (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see +# +############################################################################## + +from openerp.osv import fields, osv +from openerp.tools import config + +class document_ftp_configuration(osv.osv_memory): + + _name = 'document.ftp.configuration' + _description = 'Auto Directory Configuration' + _inherit = 'res.config' + _rec_name = 'host' + _columns = { + 'host': fields.char('Address', size=64, + help="Server address or IP and port to which users should connect to for DMS access", + required=True), + } + + _defaults = { + 'host': config.get('ftp_server_host', 'localhost') + ':' + config.get('ftp_server_port', '8021'), + } + + def execute(self, cr, uid, ids, context=None): + conf = self.browse(cr, uid, ids[0], context=context) + data_pool = self.pool.get('ir.model.data') + # Update the action for FTP browse. + aid = data_pool._get_id(cr, uid, 'document_ftp', 'action_document_browse') + aid = data_pool.browse(cr, uid, aid, context=context).res_id + self.pool.get('ir.actions.act_url').write(cr, uid, [aid], + {'url': 'ftp://' + (conf.host or 'localhost:8021') + '/' + cr.dbname + '/'}) + +document_ftp_configuration() + diff --git a/document_ftp/wizard/ftp_configuration_view.xml b/document_ftp/wizard/ftp_configuration_view.xml new file mode 100644 index 00000000..7cb4d25c --- /dev/null +++ b/document_ftp/wizard/ftp_configuration_view.xml @@ -0,0 +1,44 @@ + + + + + Browse Files + ftp://localhost:8021/ + + + + FTP Server Configuration + document.ftp.configuration + + + +
+ Knowledge Application + Configuration +
+ + + +
+
+
+ + + FTP Server Configuration + ir.actions.act_window + document.ftp.configuration + + form + form + new + + + + + automatic + +
+