Ejemplo n.º 1
0
def _process_text(self, txt):
        """Translate ``txt`` according to the language in the local context,
           replace dynamic ``[[expr]]`` with their real value, then escape
           the result for XML.

           :param str txt: original text to translate (must NOT be XML-escaped)
           :return: translated text, with dynamic expressions evaluated and
                    with special XML characters escaped (``&,<,>``).
        """
        if not self.localcontext:
            return str2xml(txt)
        if not txt:
            return ''
        result = ''
        sps = _regex.split(txt)
        while sps:
            # This is a simple text to translate
            to_translate = tools.ustr(sps.pop(0))
            result += tools.ustr(self.localcontext.get('translate', lambda x:x)(to_translate))
            if sps:
                txt = None
                try:
                    expr = sps.pop(0)
                    txt = eval(expr, self.localcontext)
                    if txt and isinstance(txt, basestring):
                        txt = tools.ustr(txt)
                except Exception:
                    _logger.info("Failed to evaluate expression [[ %s ]] with context %r while rendering report, ignored.", expr, self.localcontext)
                if isinstance(txt, basestring):
                    result += txt
                elif txt and (txt is not None) and (txt is not False):
                    result += ustr(txt)
        return str2xml(result)
Ejemplo n.º 2
0
    def get_record_data(self, values):
        """ Returns a defaults-like dict with initial values for the composition
        wizard when sending an email related a previous email (parent_id) or
        a document (model, res_id). This is based on previously computed default
        values. """
        result, subject = {}, False
        if values.get('parent_id'):
            parent = self.env['mail.message'].browse(values.get('parent_id'))
            result['record_name'] = parent.record_name,
            subject = tools.ustr(parent.subject or parent.record_name or '')
            if not values.get('model'):
                result['model'] = parent.model
            if not values.get('res_id'):
                result['res_id'] = parent.res_id
            partner_ids = values.get('partner_ids', list()) + [(4, id) for id in parent.partner_ids.ids]
            if self._context.get('is_private') and parent.author_id:  # check message is private then add author also in partner list.
                partner_ids += [(4, parent.author_id.id)]
            result['partner_ids'] = partner_ids
        elif values.get('model') and values.get('res_id'):
            doc_name_get = self.env[values.get('model')].browse(values.get('res_id')).name_get()
            result['record_name'] = doc_name_get and doc_name_get[0][1] or ''
            subject = tools.ustr(result['record_name'])

        re_prefix = _('Re:')
        if subject and not (subject.startswith('Re:') or subject.startswith(re_prefix)):
            subject = "%s %s" % (re_prefix, subject)
        result['subject'] = subject

        return result
Ejemplo n.º 3
0
 def from_data(self, uid, fields, rows, company_name):
     pageSize=[210.0,297.0]
     new_doc = etree.Element("report")
     config = etree.SubElement(new_doc, 'config')
     def _append_node(name, text):
         n = etree.SubElement(config, name)
         n.text = text
     _append_node('date', time.strftime(str(locale.nl_langinfo(locale.D_FMT).replace('%y', '%Y'))))
     _append_node('PageSize', '%.2fmm,%.2fmm' % tuple(pageSize))
     _append_node('PageWidth', '%.2f' % (pageSize[0] * 2.8346,))
     _append_node('PageHeight', '%.2f' %(pageSize[1] * 2.8346,))
     _append_node('PageFormat', 'a4')
     _append_node('header-date', time.strftime(str(locale.nl_langinfo(locale.D_FMT).replace('%y', '%Y'))))
     _append_node('company', company_name)
     l = []
     t = 0
     temp = []
     tsum = []
     skip_index = []
     header = etree.SubElement(new_doc, 'header')
     i = 0
     for f in fields:
         if f.get('header_data_id', False):
             value = f.get('header_name', "")
             field = etree.SubElement(header, 'field')
             field.text = tools.ustr(value)
         else:
             skip_index.append(i)
         i += 1
     lines = etree.SubElement(new_doc, 'lines')
     for row_lines in rows:
         node_line = etree.SubElement(lines, 'row')
         j = 0
         for row in row_lines:
             if not j in skip_index:
                 para = "yes"
                 tree = "no"
                 value = row.get('data', '')
                 if row.get('bold', False):
                     para = "group"
                 if row.get('number', False):
                     tree = "float"
                 col = etree.SubElement(node_line, 'col', para=para, tree=tree)
                 col.text = tools.ustr(value)
             j += 1
     transform = etree.XSLT(
         etree.parse(os.path.join(tools.config['root_path'],
                                  'addons/base/report/custom_new.xsl')))
     rml = etree.tostring(transform(new_doc))
     self.obj = trml2pdf.parseNode(rml, title='Printscreen')
     return self.obj
Ejemplo n.º 4
0
def initialize_sys_path():
    """
    Setup an import-hook to be able to import YuanCloud addons from the different
    addons paths.

    This ensures something like ``import crm`` (or even
    ``import yuancloud.addons.crm``) works even if the addons are not in the
    PYTHONPATH.
    """
    global ad_paths
    global hooked

    dd = tools.config.addons_data_dir
    if dd not in ad_paths:
        ad_paths.append(dd)

    for ad in tools.config['addons_path'].split(','):
        ad = os.path.abspath(tools.ustr(ad.strip()))
        if ad not in ad_paths:
            ad_paths.append(ad)

    # add base module path
    base_path = os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'addons'))
    if base_path not in ad_paths:
        ad_paths.append(base_path)

    if not hooked:
        sys.meta_path.append(AddonsImportHook())
        hooked = True
Ejemplo n.º 5
0
def exp_render_report(db, uid, object, ids, datas=None, context=None):
    if not datas:
        datas={}
    if not context:
        context={}

    self_id_protect.acquire()
    global self_id
    self_id += 1
    id = self_id
    self_id_protect.release()

    self_reports[id] = {'uid': uid, 'result': False, 'state': False, 'exception': None}

    cr = yuancloud.registry(db).cursor()
    try:
        result, format = yuancloud.report.render_report(cr, uid, ids, object, datas, context)
        if not result:
            tb = sys.exc_info()
            self_reports[id]['exception'] = yuancloud.exceptions.DeferredException('RML is not available at specified location or not enough data to print!', tb)
        self_reports[id]['result'] = result
        self_reports[id]['format'] = format
        self_reports[id]['state'] = True
    except Exception, exception:

        _logger.exception('Exception: %s\n', exception)
        if hasattr(exception, 'name') and hasattr(exception, 'value'):
            self_reports[id]['exception'] = yuancloud.exceptions.DeferredException(tools.ustr(exception.name), tools.ustr(exception.value))
        else:
            tb = sys.exc_info()
            self_reports[id]['exception'] = yuancloud.exceptions.DeferredException(tools.exception_to_unicode(exception), tb)
        self_reports[id]['state'] = True
Ejemplo n.º 6
0
def remove_accents(input_str):
    """Suboptimal-but-better-than-nothing way to replace accented
    latin letters by an ASCII equivalent. Will obviously change the
    meaning of input_str and work only for some cases"""
    input_str = ustr(input_str)
    nkfd_form = unicodedata.normalize('NFKD', input_str)
    return u''.join([c for c in nkfd_form if not unicodedata.combining(c)])
Ejemplo n.º 7
0
    def from_html(self, cr, uid, model, field, element, context=None):
        record = self.browse(cr, uid, [], context=context)
        value = element.text_content().strip()
        selection = field.get_description(record.env)['selection']
        for k, v in selection:
            if isinstance(v, str):
                v = ustr(v)
            if value == v:
                return k

        raise ValueError(u"No value found for label %s in selection %s" % (
                         value, selection))
Ejemplo n.º 8
0
def geo_query_address(street=None,
                      zip=None,
                      city=None,
                      state=None,
                      country=None):
    if country and ',' in country and (country.endswith(' of')
                                       or country.endswith(' of the')):
        # put country qualifier in front, otherwise GMap gives wrong results,
        # e.g. 'Congo, Democratic Republic of the' => 'Democratic Republic of the Congo'
        country = '{1} {0}'.format(*country.split(',', 1))
    return tools.ustr(', '.join(
        filter(None, [
            street, ("%s %s" % (zip or '', city or '')).strip(), state, country
        ])))
Ejemplo n.º 9
0
 def button_confirm_login(self, cr, uid, ids, context=None):
     if context is None:
         context = {}
     for server in self.browse(cr, uid, ids, context=context):
         try:
             connection = server.connect()
             server.write({'state': 'done'})
         except Exception, e:
             _logger.info("Failed to connect to %s server %s.",
                          server.type,
                          server.name,
                          exc_info=True)
             raise UserError(
                 _("Connection test failed: %s") % tools.ustr(e))
         finally:
Ejemplo n.º 10
0
    def change_product_qty(self, cr, uid, ids, context=None):
        """ Changes the Product Quantity by making a Physical Inventory. """
        if context is None:
            context = {}

        inventory_obj = self.pool.get('stock.inventory')
        inventory_line_obj = self.pool.get('stock.inventory.line')

        for data in self.browse(cr, uid, ids, context=context):
            if data.new_quantity < 0:
                raise UserError(_('Quantity cannot be negative.'))
            ctx = context.copy()
            ctx['location'] = data.location_id.id
            ctx['lot_id'] = data.lot_id.id
            if data.product_id.id and data.lot_id.id:
                filter = 'none'
            elif data.product_id.id:
                filter = 'product'
            else:
                filter = 'none'
            inventory_id = inventory_obj.create(
                cr,
                uid, {
                    'name': _('INV: %s') % tools.ustr(data.product_id.name),
                    'filter': filter,
                    'product_id': data.product_id.id,
                    'location_id': data.location_id.id,
                    'lot_id': data.lot_id.id
                },
                context=context)
            product = data.product_id.with_context(
                location=data.location_id.id, lot_id=data.lot_id.id)
            th_qty = product.qty_available
            line_data = {
                'inventory_id': inventory_id,
                'product_qty': data.new_quantity,
                'location_id': data.location_id.id,
                'product_id': data.product_id.id,
                'product_uom_id': data.product_id.uom_id.id,
                'theoretical_qty': th_qty,
                'prod_lot_id': data.lot_id.id
            }
            inventory_line_obj.create(cr, uid, line_data, context=context)
            inventory_obj.action_done(cr, uid, [inventory_id], context=context)
        return {}
Ejemplo n.º 11
0
def attr_get(node, attrs, dict=None):
    if dict is None:
        dict = {}
    res = {}
    for name in attrs:
        if node.get(name):
            res[name] = unit_get(node.get(name))
    for key in dict:
        if node.get(key):
            if dict[key]=='str':
                res[key] = tools.ustr(node.get(key))
            elif dict[key]=='bool':
                res[key] = bool_get(node.get(key))
            elif dict[key]=='int':
                res[key] = int(node.get(key))
            elif dict[key]=='unit':
                res[key] = unit_get(node.get(key))
            elif dict[key] == 'float' :
                res[key] = float(node.get(key))
    return res
Ejemplo n.º 12
0
 def save_as_template(self):
     """ hit save as template button: current form value will be a new
         template attached to the current document. """
     for record in self:
         models = self.env['ir.model'].search([('model', '=', record.model or 'mail.message')])
         model_name = ''
         if models:
             model_name = models.name
         template_name = "%s: %s" % (model_name, tools.ustr(record.subject))
         values = {
             'name': template_name,
             'subject': record.subject or False,
             'body_html': record.body or False,
             'model_id': models.id or False,
             'attachment_ids': [(6, 0, [att.id for att in record.attachment_ids])],
         }
         template = self.env['mail.template'].create(values)
         # generate the saved template
         record.write({'template_id': template.id})
         record.onchange_template_id_wrapper()
         return _reopen(self, record.id, record.model)
Ejemplo n.º 13
0
    def create(self, cr, uid, ids, datas, context):
        registry = yuancloud.registry(cr.dbname)
        xml = self.create_xml(cr, uid, ids, datas, context)
        xml = tools.ustr(xml).encode('utf8')
        report_type = datas.get('report_type', 'pdf')
        if report_type == 'raw':
            return xml, report_type

        registry['res.font'].font_scan(cr,
                                       SUPERUSER_ID,
                                       lazy=True,
                                       context=context)

        rml = self.create_rml(cr, xml, uid, context)
        ir_actions_report_xml_obj = registry['ir.actions.report.xml']
        report_xml_ids = ir_actions_report_xml_obj.search(
            cr, uid, [('report_name', '=', self.name[7:])], context=context)
        self.title = report_xml_ids and ir_actions_report_xml_obj.browse(
            cr, uid, report_xml_ids)[0].name or 'YuanCloud Report'
        create_doc = self.generators[report_type]
        pdf = create_doc(rml, title=self.title)
        return pdf, report_type
Ejemplo n.º 14
0
    def _create_table(self, uid, ids, fields, fields_order, results, context, title=''):
        pageSize=[297.0, 210.0]

        new_doc = etree.Element("report")
        config = etree.SubElement(new_doc, 'config')

        def _append_node(name, text):
            n = etree.SubElement(config, name)
            n.text = text

        #_append_node('date', time.strftime('%d/%m/%Y'))
        _append_node('date', time.strftime(str(locale.nl_langinfo(locale.D_FMT).replace('%y', '%Y'))))
        _append_node('PageSize', '%.2fmm,%.2fmm' % tuple(pageSize))
        _append_node('PageWidth', '%.2f' % (pageSize[0] * 2.8346,))
        _append_node('PageHeight', '%.2f' %(pageSize[1] * 2.8346,))
        _append_node('report-header', title)

        registry = yuancloud.registry(self.cr.dbname)
        _append_node('company', registry['res.users'].browse(self.cr,uid,uid).company_id.name)
        rpt_obj = registry['res.users']
        rml_obj=report_sxw.rml_parse(self.cr, uid, rpt_obj._name,context)
        _append_node('header-date', str(rml_obj.formatLang(time.strftime("%Y-%m-%d"),date=True))+' ' + str(time.strftime("%H:%M")))
        l = []
        t = 0
        strmax = (pageSize[0]-40) * 2.8346
        temp = []
        tsum = []
        for i in range(0, len(fields_order)):
            temp.append(0)
            tsum.append(0)
        ince = -1
        for f in fields_order:
            s = 0
            ince += 1
            if fields[f]['type'] in ('date','time','datetime','float','integer'):
                s = 60
                strmax -= s
                if fields[f]['type'] in ('float','integer'):
                    temp[ince] = 1
            else:
                t += fields[f].get('size', 80) / 28 + 1

            l.append(s)
        for pos in range(len(l)):
            if not l[pos]:
                s = fields[fields_order[pos]].get('size', 80) / 28 + 1
                l[pos] = strmax * s / t

        _append_node('tableSize', ','.join(map(str,l)) )

        header = etree.SubElement(new_doc, 'header')
        for f in fields_order:
            field = etree.SubElement(header, 'field')
            field.text = tools.ustr(fields[f]['string'] or '')

        lines = etree.SubElement(new_doc, 'lines')
        for line in results:
            node_line = etree.SubElement(lines, 'row')
            count = -1
            for f in fields_order:
                float_flag = 0
                count += 1
                if fields[f]['type']=='many2one' and line[f]:
                    if not line.get('__group'):
                        line[f] = line[f][1]
                if fields[f]['type']=='selection' and line[f]:
                    for key, value in fields[f]['selection']:
                        if key == line[f]:
                            line[f] = value
                            break
                if fields[f]['type'] in ('one2many','many2many') and line[f]:
                    line[f] = '( '+tools.ustr(len(line[f])) + ' )'
                if fields[f]['type'] == 'float' and line[f]:
                    precision=(('digits' in fields[f]) and fields[f]['digits'][1]) or 2
                    prec ='%.' + str(precision) +'f'
                    line[f]=prec%(line[f])
                    float_flag = 1

                if fields[f]['type'] == 'date' and line[f]:
                    new_d1 = line[f]
                    if not line.get('__group'):
                        format = str(locale.nl_langinfo(locale.D_FMT).replace('%y', '%Y'))
                        d1 = datetime.strptime(line[f],'%Y-%m-%d')
                        new_d1 = d1.strftime(format)
                    line[f] = new_d1

                if fields[f]['type'] == 'time' and line[f]:
                    new_d1 = line[f]
                    if not line.get('__group'):
                        format = str(locale.nl_langinfo(locale.T_FMT))
                        d1 = datetime.strptime(line[f], '%H:%M:%S')
                        new_d1 = d1.strftime(format)
                    line[f] = new_d1

                if fields[f]['type'] == 'datetime' and line[f]:
                    new_d1 = line[f]
                    if not line.get('__group'):
                        format = str(locale.nl_langinfo(locale.D_FMT).replace('%y', '%Y'))+' '+str(locale.nl_langinfo(locale.T_FMT))
                        d1 = datetime.strptime(line[f], '%Y-%m-%d %H:%M:%S')
                        new_d1 = d1.strftime(format)
                    line[f] = new_d1


                if line.get('__group'):
                    col = etree.SubElement(node_line, 'col', para='group', tree='no')
                else:
                    col = etree.SubElement(node_line, 'col', para='yes', tree='no')

                # Prevent empty labels in groups
                if f == line.get('__grouped_by') and line.get('__group') and not line[f] and not float_flag and not temp[count]:
                    col.text = line[f] = 'Undefined'
                    col.set('tree', 'undefined')

                if line[f] is not None:
                    col.text = tools.ustr(line[f] or '')
                    if float_flag:
                        col.set('tree','float')
                    if line.get('__no_leaf') and temp[count] == 1 and f != 'id' and not line['__context']['group_by']:
                        tsum[count] = float(tsum[count]) + float(line[f])
                    if not line.get('__group') and f != 'id' and temp[count] == 1:
                        tsum[count] = float(tsum[count])  + float(line[f])
                else:
                    col.text = '/'

        node_line = etree.SubElement(lines, 'row')
        for f in range(0, len(fields_order)):
            col = etree.SubElement(node_line, 'col', para='group', tree='no')
            col.set('tree', 'float')
            if tsum[f] is not None:
                if tsum[f] != 0.0:
                    digits = fields[fields_order[f]].get('digits', (16, 2))
                    prec = '%%.%sf' % (digits[1], )
                    total = prec % (tsum[f], )
                    txt = str(total or '')
                else:
                    txt = str(tsum[f] or '')
            else:
                txt = '/'
            if f == 0:
                txt ='Total'
                col.set('tree','no')
            col.text = tools.ustr(txt or '')

        transform = etree.XSLT(
            etree.parse(os.path.join(tools.config['root_path'],
                                     'addons/base/report/custom_new.xsl')))
        rml = etree.tostring(transform(new_doc))
        self.obj = render.rml(rml, title=self.title)
        self.obj.render()
        return True
Ejemplo n.º 15
0
    def schedule_backup(self, cr, user, context={}):
        conf_ids = self.search(cr, user, [])
        confs = self.browse(cr, user, conf_ids)
        for rec in confs:
            db_list = self.get_db_list(cr, user, [], rec.host, rec.port)
            if rec.name in db_list:
                try:
                    if not os.path.isdir(rec.bkp_dir):
                        os.makedirs(rec.bkp_dir)
                except:
                    raise
                # Create name for dumpfile.
                bkp_file = '%s_%s.%s' % (time.strftime('%d_%m_%Y_%H_%M_%S'),
                                         rec.name, rec.backup_type)
                file_path = os.path.join(rec.bkp_dir, bkp_file)
                uri = 'http://' + rec.host + ':' + rec.port
                conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/db')
                bkp = ''
                try:
                    bkp = execute(conn, 'dump', tools.config['admin_passwd'],
                                  rec.name, rec.backup_type)
                except:
                    _logger.debug(
                        "Couldn't backup database %s. Bad database administrator password for server running at http://%s:%s"
                        % (rec.name, rec.host, rec.port))
                    continue
                bkp = base64.decodestring(bkp)
                fp = open(file_path, 'wb')
                fp.write(bkp)
                fp.close()
            else:
                _logger.debug("database %s doesn't exist on http://%s:%s" %
                              (rec.name, rec.host, rec.port))

            # Check if user wants to write to SFTP or not.
            if rec.sftpwrite is True:
                try:
                    # Store all values in variables
                    dir = rec.bkp_dir
                    pathToWriteTo = rec.sftppath
                    ipHost = rec.sftpip
                    portHost = rec.sftpport
                    usernameLogin = rec.sftpusername
                    passwordLogin = rec.sftppassword
                    # Connect with external server over SFTP
                    srv = pysftp.Connection(host=ipHost,
                                            username=usernameLogin,
                                            password=passwordLogin,
                                            port=portHost)
                    # set keepalive to prevent socket closed / connection dropped error
                    srv._transport.set_keepalive(30)
                    # Move to the correct directory on external server. If the user made a typo in his path with multiple slashes (/yuancloud//backups/) it will be fixed by this regex.
                    pathToWriteTo = re.sub('([/]{2,5})+', '/', pathToWriteTo)
                    _logger.debug('sftp remote path: %s' % pathToWriteTo)
                    try:
                        srv.chdir(pathToWriteTo)
                    except IOError:
                        # Create directory and subdirs if they do not exist.
                        currentDir = ''
                        for dirElement in pathToWriteTo.split('/'):
                            currentDir += dirElement + '/'
                            try:
                                srv.chdir(currentDir)
                            except:
                                _logger.info(
                                    '(Part of the) path didn\'t exist. Creating it now at '
                                    + currentDir)
                                # Make directory and then navigate into it
                                srv.mkdir(currentDir, mode=777)
                                srv.chdir(currentDir)
                                pass
                    srv.chdir(pathToWriteTo)
                    # Loop over all files in the directory.
                    for f in os.listdir(dir):
                        fullpath = os.path.join(dir, f)
                        if os.path.isfile(fullpath):
                            if not srv.exists(f):
                                _logger.info(
                                    'The file %s is not yet on the remote FTP Server ------ Copying file'
                                    % fullpath)
                                srv.put(fullpath)
                                _logger.info('Copying File % s------ success' %
                                             fullpath)
                            else:
                                _logger.debug(
                                    'File %s already exists on the remote FTP Server ------ skipped'
                                    % fullpath)

                    # Navigate in to the correct folder.
                    srv.chdir(pathToWriteTo)

                    # Loop over all files in the directory from the back-ups.
                    # We will check the creation date of every back-up.
                    for file in srv.listdir(pathToWriteTo):
                        # Get the full path
                        fullpath = os.path.join(pathToWriteTo, file)
                        # Get the timestamp from the file on the external server
                        timestamp = srv.stat(fullpath).st_atime
                        createtime = datetime.datetime.fromtimestamp(timestamp)
                        now = datetime.datetime.now()
                        delta = now - createtime
                        # If the file is older than the daystokeepsftp (the days to keep that the user filled in on the YuanCloud form it will be removed.
                        if delta.days >= rec.daystokeepsftp:
                            # Only delete files, no directories!
                            if srv.isfile(fullpath) and ".dump" in file:
                                _logger.info(
                                    "Delete too old file from SFTP servers: " +
                                    file)
                                srv.unlink(file)
                    # Close the SFTP session.
                    srv.close()
                except Exception, e:
                    _logger.debug(
                        'Exception! We couldn\'t back up to the FTP server..')
                    # At this point the SFTP backup failed. We will now check if the user wants
                    # an e-mail notification about this.
                    if rec.sendmailsftpfail:
                        try:
                            ir_mail_server = self.pool.get('ir.mail_server')
                            message = "Dear,\n\nThe backup for the server " + rec.host + " (IP: " + rec.sftpip + ") failed.Please check the following details:\n\nIP address SFTP server: " + rec.sftpip + "\nUsername: "******"\nPassword: "******"\n\nError details: " + tools.ustr(
                                e) + "\n\nWith kind regards"
                            msg = ir_mail_server.build_email(
                                "auto_backup@" + rec.name + ".com",
                                [rec.emailtonotify], "Backup from " +
                                rec.host + "(" + rec.sftpip + ") failed",
                                message)
                            ir_mail_server.send_email(cr, user, msg)
                        except Exception:
                            pass
            """Remove all old files (on local server) in case this is configured..
            This is done after the SFTP writing to prevent unusual behaviour:
            If the user would set local back-ups to be kept 0 days and the SFTP
            to keep backups xx days there wouldn't be any new back-ups added to the
            SFTP.
            If we'd remove the dump files before they're writen to the SFTP there willbe nothing to write. Meaning that if an user doesn't want to keep back-ups locally and only wants them on the SFTP (NAS for example) there wouldn't be any writing to the remote server if this if statement was before the SFTP write method right above this comment.
            """
            if rec.autoremove is True:
                dir = rec.bkp_dir
                # Loop over all files in the directory.
                for f in os.listdir(dir):
                    fullpath = os.path.join(dir, f)
                    timestamp = os.stat(fullpath).st_ctime
                    createtime = datetime.datetime.fromtimestamp(timestamp)
                    now = datetime.datetime.now()
                    delta = now - createtime
                    if delta.days >= rec.daystokeep:
                        # Only delete files (which are .dump), no directories.
                        if os.path.isfile(fullpath) and (".dump" in f
                                                         or ".zip" in f):
                            _logger.info("Delete local out-of-date file: " +
                                         fullpath)
                            os.remove(fullpath)
Ejemplo n.º 16
0
def toxml(value):
    unicode_value = tools.ustr(value)
    return unicode_value.replace('&',
                                 '&amp;').replace('<',
                                                  '&lt;').replace('>', '&gt;')
Ejemplo n.º 17
0
class db_backup(osv.Model):
    _name = 'db.backup'

    def get_db_list(self, cr, user, ids, host, port, context={}):
        _logger.debug("Host: " + host)
        _logger.debug("Port: " + port)
        uri = 'http://' + host + ':' + port
        conn = xmlrpclib.ServerProxy(uri + '/xmlrpc/db')
        db_list = execute(conn, 'list')
        return db_list

    def _get_db_name(self, cr, uid, vals, context=None):
        attach_pool = self.pool.get("ir.logging")
        dbName = cr.dbname
        return dbName

    _columns = {
        # Columns local server
        'host':
        fields.char('Host', size=100, required='True'),
        'port':
        fields.char('Port', size=10, required='True'),
        'name':
        fields.char('Database',
                    size=100,
                    required='True',
                    help='Database you want to schedule backups for'),
        'bkp_dir':
        fields.char('Backup Directory',
                    size=100,
                    help='Absolute path for storing the backups',
                    required='True'),
        'backup_type':
        fields.selection([('zip', 'Zip'), ('dump', 'Dump')],
                         'Backup Type',
                         required=True),
        'autoremove':
        fields.boolean(
            'Auto. Remove Backups',
            help=
            "If you check this option you can choose to automaticly remove the backup after xx days"
        ),
        'daystokeep':
        fields.integer(
            'Remove after x days',
            help=
            "Choose after how many days the backup should be deleted. For example:\nIf you fill in 5 the backups will be removed after 5 days.",
            required=True),
        # Columns for external server (SFTP)
        'sftpwrite':
        fields.boolean(
            'Write to external server with sftp',
            help=
            "If you check this option you can specify the details needed to write to a remote server with SFTP."
        ),
        'sftppath':
        fields.char(
            'Path external server',
            help=
            "The location to the folder where the dumps should be written to. For example /yuancloud/backups/.\nFiles will then be written to /yuancloud/backups/ on your remote server."
        ),
        'sftpip':
        fields.char(
            'IP Address SFTP Server',
            help=
            "The IP address from your remote server. For example 192.168.0.1"),
        'sftpport':
        fields.integer(
            "SFTP Port",
            help="The port on the FTP server that accepts SSH/SFTP calls."),
        'sftpusername':
        fields.char(
            'Username SFTP Server',
            help=
            "The username where the SFTP connection should be made with. This is the user on the external server."
        ),
        'sftppassword':
        fields.char(
            'Password User SFTP Server',
            help=
            "The password from the user where the SFTP connection should be made with. This is the password from the user on the external server."
        ),
        'daystokeepsftp':
        fields.integer(
            'Remove SFTP after x days',
            help=
            "Choose after how many days the backup should be deleted from the FTP server. For example:\nIf you fill in 5 the backups will be removed after 5 days from the FTP server."
        ),
        'sendmailsftpfail':
        fields.boolean(
            'Auto. E-mail on backup fail',
            help=
            "If you check this option you can choose to automaticly get e-mailed when the backup to the external server failed."
        ),
        'emailtonotify':
        fields.char(
            'E-mail to notify',
            help=
            "Fill in the e-mail where you want to be notified that the backup failed on the FTP."
        ),
    }

    _defaults = {
        # 'bkp_dir' : lambda *a : addons_path,
        'bkp_dir': '/yuancloud/backups',
        'backup_type': 'zip',
        'host': lambda *a: 'localhost',
        'port': lambda *a: '8080',
        'name': _get_db_name,
        'daystokeepsftp': 30,
        'sftpport': 22,
    }

    def _check_db_exist(self, cr, user, ids):
        for rec in self.browse(cr, user, ids):
            db_list = self.get_db_list(cr, user, ids, rec.host, rec.port)
            if rec.name in db_list:
                return True
        return False

    _constraints = [(_check_db_exist, _('Error ! No such database exists!'),
                     [])]

    def test_sftp_connection(self, cr, uid, ids, context=None):
        conf_ids = self.search(cr, uid, [])
        confs = self.browse(cr, uid, conf_ids)
        # Check if there is a success or fail and write messages
        messageTitle = ""
        messageContent = ""
        for rec in confs:
            db_list = self.get_db_list(cr, uid, [], rec.host, rec.port)
            try:
                pathToWriteTo = rec.sftppath
                ipHost = rec.sftpip
                portHost = rec.sftpport
                usernameLogin = rec.sftpusername
                passwordLogin = rec.sftppassword
                # Connect with external server over SFTP, so we know sure that everything works.
                srv = pysftp.Connection(host=ipHost,
                                        username=usernameLogin,
                                        password=passwordLogin,
                                        port=portHost)
                srv.close()
                # We have a success.
                messageTitle = "Connection Test Succeeded!"
                messageContent = "Everything seems properly set up for FTP back-ups!"
            except Exception, e:
                messageTitle = "Connection Test Failed!"
                if len(rec.sftpip) < 8:
                    messageContent += "\nYour IP address seems to be too short.\n"
                messageContent += "Here is what we got instead:\n"
        if "Failed" in messageTitle:
            raise osv.except_osv(_(messageTitle),
                                 _(messageContent + "%s") % tools.ustr(e))
        else:
            raise osv.except_osv(_(messageTitle), _(messageContent))
Ejemplo n.º 18
0
             _logger.info(msg, exc_info=True)
             raise UserError(msg)
 else:
     try:
         html = body_mako_tpl.render(dict(parser_instance.localcontext))
         htmls.append(html)
     except Exception, e:
         msg = u"%s" % e
         _logger.info(msg, exc_info=True)
         raise UserError(msg)
 head_mako_tpl = mako_template(header)
 try:
     head = head_mako_tpl.render(
         dict(parser_instance.localcontext, _debug=False))
 except Exception, e:
     raise UserError(tools.ustr(e))
 foot = False
 if footer:
     foot_mako_tpl = mako_template(footer)
     try:
         foot = foot_mako_tpl.render(dict(parser_instance.localcontext))
     except Exception, e:
         msg = u"%s" % e
         _logger.info(msg, exc_info=True)
         raise UserError(msg)
 if report_xml.webkit_debug:
     try:
         deb = head_mako_tpl.render(
             dict(parser_instance.localcontext,
                  _debug=tools.ustr("\n".join(htmls))))
     except Exception, e:
Ejemplo n.º 19
0
def try_report(cr,
               uid,
               rname,
               ids,
               data=None,
               context=None,
               our_module=None,
               report_type=None):
    """ Try to render a report <rname> with contents of ids
    
        This function should also check for common pitfalls of reports.
    """
    if data is None:
        data = {}
    if context is None:
        context = {}
    if rname.startswith('report.'):
        rname_s = rname[7:]
    else:
        rname_s = rname
    _test_logger.info("  - Trying %s.create(%r)", rname, ids)
    res = yuancloud.report.render_report(cr, uid, ids, rname_s, data, context)
    if not isinstance(res, tuple):
        raise RuntimeError("Result of %s.create() should be a (data,format) tuple, now it is a %s" % \
                                (rname, type(res)))
    (res_data, res_format) = res

    if not res_data:
        raise ValueError("Report %s produced an empty result!" % rname)

    if tools.config['test_report_directory']:
        file(
            os.path.join(tools.config['test_report_directory'],
                         rname + '.' + res_format), 'wb+').write(res_data)

    _logger.debug("Have a %s report for %s, will examine it", res_format,
                  rname)
    if res_format == 'pdf':
        if res_data[:5] != '%PDF-':
            raise ValueError("Report %s produced a non-pdf header, %r" %
                             (rname, res_data[:10]))

        res_text = False
        try:
            fd, rfname = tempfile.mkstemp(suffix=res_format)
            os.write(fd, res_data)
            os.close(fd)

            proc = Popen(
                ['pdftotext', '-enc', 'UTF-8', '-nopgbrk', rfname, '-'],
                shell=False,
                stdout=PIPE)
            stdout, stderr = proc.communicate()
            res_text = tools.ustr(stdout)
            os.unlink(rfname)
        except Exception:
            _logger.debug(
                "Unable to parse PDF report: install pdftotext to perform automated tests."
            )

        if res_text is not False:
            for line in res_text.split('\n'):
                if ('[[' in line) or ('[ [' in line):
                    _logger.error(
                        "Report %s may have bad expression near: \"%s\".",
                        rname, line[80:])
            # TODO more checks, what else can be a sign of a faulty report?
    elif res_format == 'html':
        pass
    else:
        _logger.warning("Report %s produced a \"%s\" chunk, cannot examine it",
                        rname, res_format)
        return False

    _test_logger.info("  + Report %s produced correctly.", rname)
    return True
Ejemplo n.º 20
0
    def send(self, auto_commit=False, raise_exception=False):
        """ Sends the selected emails immediately, ignoring their current
            state (mails that have already been sent should not be passed
            unless they should actually be re-sent).
            Emails successfully delivered are marked as 'sent', and those
            that fail to be deliver are marked as 'exception', and the
            corresponding error mail is output in the server logs.

            :param bool auto_commit: whether to force a commit of the mail status
                after sending each mail (meant only for scheduler processing);
                should never be True during normal transactions (default: False)
            :param bool raise_exception: whether to raise an exception if the
                email sending process has failed
            :return: True
        """
        IrMailServer = self.env['ir.mail_server']

        for mail in self:
            try:
                # TDE note: remove me when model_id field is present on mail.message - done here to avoid doing it multiple times in the sub method
                if mail.model:
                    model = self.env['ir.model'].sudo().search([
                        ('model', '=', mail.model)
                    ])[0]
                else:
                    model = None
                if model:
                    mail = mail.with_context(model_name=model.name)

                # load attachment binary data with a separate read(), as prefetching all
                # `datas` (binary field) could bloat the browse cache, triggerring
                # soft/hard mem limits with temporary data.
                attachments = [(a['datas_fname'], base64.b64decode(a['datas']))
                               for a in mail.attachment_ids.sudo().read(
                                   ['datas_fname', 'datas'])]

                # specific behavior to customize the send email for notified partners
                email_list = []
                if mail.email_to:
                    email_list.append(mail.send_get_email_dict())
                for partner in mail.recipient_ids:
                    email_list.append(
                        mail.send_get_email_dict(partner=partner))

                # headers
                headers = {}
                bounce_alias = self.env['ir.config_parameter'].get_param(
                    "mail.bounce.alias")
                catchall_domain = self.env['ir.config_parameter'].get_param(
                    "mail.catchall.domain")
                if bounce_alias and catchall_domain:
                    if mail.model and mail.res_id:
                        headers['Return-Path'] = '%s-%d-%s-%d@%s' % (
                            bounce_alias, mail.id, mail.model, mail.res_id,
                            catchall_domain)
                    else:
                        headers['Return-Path'] = '%s-%d@%s' % (
                            bounce_alias, mail.id, catchall_domain)
                if mail.headers:
                    try:
                        headers.update(eval(mail.headers))
                    except Exception:
                        pass

                # Writing on the mail object may fail (e.g. lock on user) which
                # would trigger a rollback *after* actually sending the email.
                # To avoid sending twice the same email, provoke the failure earlier
                mail.write({
                    'state':
                    'exception',
                    'failure_reason':
                    _('Error without exception. Probably due do sending an email without computed recipients.'
                      ),
                })
                mail_sent = False

                # build an RFC2822 email.message.Message object and send it without queuing
                res = None
                for email in email_list:
                    msg = IrMailServer.build_email(
                        email_from=mail.email_from,
                        email_to=email.get('email_to'),
                        subject=mail.subject,
                        body=email.get('body'),
                        body_alternative=email.get('body_alternative'),
                        email_cc=tools.email_split(mail.email_cc),
                        reply_to=mail.reply_to,
                        attachments=attachments,
                        message_id=mail.message_id,
                        references=mail.references,
                        object_id=mail.res_id
                        and ('%s-%s' % (mail.res_id, mail.model)),
                        subtype='html',
                        subtype_alternative='plain',
                        headers=headers)
                    try:
                        res = IrMailServer.send_email(
                            msg, mail_server_id=mail.mail_server_id.id)
                    except AssertionError as error:
                        if error.message == IrMailServer.NO_VALID_RECIPIENT:
                            # No valid recipient found for this particular
                            # mail item -> ignore error to avoid blocking
                            # delivery to next recipients, if any. If this is
                            # the only recipient, the mail will show as failed.
                            _logger.info(
                                "Ignoring invalid recipients for mail.mail %s: %s",
                                mail.message_id, email.get('email_to'))
                        else:
                            raise
                if res:
                    mail.write({
                        'state': 'sent',
                        'message_id': res,
                        'failure_reason': False
                    })
                    mail_sent = True

                # /!\ can't use mail.state here, as mail.refresh() will cause an error
                # see revid:[email protected] in 6.1
                if mail_sent:
                    _logger.info(
                        'Mail with ID %r and Message-Id %r successfully sent',
                        mail.id, mail.message_id)
                mail._postprocess_sent_message_v9(mail_sent=mail_sent)
            except MemoryError:
                # prevent catching transient MemoryErrors, bubble up to notify user or abort cron job
                # instead of marking the mail as failed
                _logger.exception(
                    'MemoryError while processing mail with ID %r and Msg-Id %r. Consider raising the --limit-memory-hard startup option',
                    mail.id, mail.message_id)
                raise
            except psycopg2.Error:
                # If an error with the database occurs, chances are that the cursor is unusable.
                # This will lead to an `psycopg2.InternalError` being raised when trying to write
                # `state`, shadowing the original exception and forbid a retry on concurrent
                # update. Let's bubble it.
                raise
            except Exception as e:
                failure_reason = tools.ustr(e)
                _logger.exception('failed sending mail (id: %s) due to %s',
                                  mail.id, failure_reason)
                mail.write({
                    'state': 'exception',
                    'failure_reason': failure_reason
                })
                mail._postprocess_sent_message_v9(mail_sent=False)
                if raise_exception:
                    if isinstance(e, AssertionError):
                        # get the args of the original error, wrap into a value and throw a MailDeliveryException
                        # that is an except_orm, with name and value as arguments
                        value = '. '.join(e.args)
                        raise MailDeliveryException(_("Mail Delivery Failed"),
                                                    value)
                    raise

            if auto_commit is True:
                self._cr.commit()
        return True
Ejemplo n.º 21
0
    def render_template(self,
                        template_txt,
                        model,
                        res_ids,
                        post_process=False):
        """ Render the given template text, replace mako expressions ``${expr}``
        with the result of evaluating these expressions with an evaluation
        context containing:

         - ``user``: browse_record of the current user
         - ``object``: record of the document record this mail is related to
         - ``context``: the context passed to the mail composition wizard

        :param str template_txt: the template text to render
        :param str model: model name of the document record this mail is related to.
        :param int res_ids: list of ids of document records those mails are related to.
        """
        multi_mode = True
        if isinstance(res_ids, (int, long)):
            multi_mode = False
            res_ids = [res_ids]

        results = dict.fromkeys(res_ids, u"")

        # try to load the template
        try:
            mako_env = mako_safe_template_env if self.env.context.get(
                'safe') else mako_template_env
            template = mako_env.from_string(tools.ustr(template_txt))
        except Exception:
            _logger.info("Failed to load template %r",
                         template_txt,
                         exc_info=True)
            return multi_mode and results or results[res_ids[0]]

        # prepare template variables
        records = self.env[model].browse(filter(
            None, res_ids))  # filter to avoid browsing [None]
        res_to_rec = dict.fromkeys(res_ids, None)
        for record in records:
            res_to_rec[record.id] = record
        variables = {
            'format_tz':
            lambda dt, tz=False, format=False, context=self._context:
            format_tz(self.pool, self._cr, self._uid, dt, tz, format, context),
            'user':
            self.env.user,
            'ctx':
            self._context,  # context kw would clash with mako internals
        }
        for res_id, record in res_to_rec.iteritems():
            variables['object'] = record
            try:
                render_result = template.render(variables)
            except Exception:
                _logger.info("Failed to render template %r using values %r" %
                             (template, variables),
                             exc_info=True)
                raise UserError(
                    _("Failed to render template %r using values %r") %
                    (template, variables))
                render_result = u""
            if render_result == u"False":
                render_result = u""
            results[res_id] = render_result

        if post_process:
            for res_id, result in results.iteritems():
                results[res_id] = self.render_post_process(result)

        return multi_mode and results or results[res_ids[0]]
Ejemplo n.º 22
0
    def _create_table(self,
                      uid,
                      ids,
                      fields,
                      fields_order,
                      results,
                      context,
                      title=''):
        pageSize = [297.0, 210.0]

        new_doc = etree.Element("report")
        config = etree.SubElement(new_doc, 'config')

        # build header
        def _append_node(name, text):
            n = etree.SubElement(config, name)
            n.text = text

        _append_node('date', time.strftime('%d/%m/%Y'))
        _append_node('PageSize', '%.2fmm,%.2fmm' % tuple(pageSize))
        _append_node('PageWidth', '%.2f' % (pageSize[0] * 2.8346, ))
        _append_node('PageHeight', '%.2f' % (pageSize[1] * 2.8346, ))
        _append_node('report-header', title)

        l = []
        t = 0
        strmax = (pageSize[0] - 40) * 2.8346
        for f in fields_order:
            s = 0
            if fields[f]['type'] in ('date', 'time', 'float', 'integer'):
                s = 60
                strmax -= s
            else:
                t += fields[f].get('size', 56) / 28 + 1
            l.append(s)
        for pos in range(len(l)):
            if not l[pos]:
                s = fields[fields_order[pos]].get('size', 56) / 28 + 1
                l[pos] = strmax * s / t
        _append_node('tableSize', ','.join(map(str, l)))

        header = etree.SubElement(new_doc, 'header')
        for f in fields_order:
            field = etree.SubElement(header, 'field')
            field.text = fields[f]['string'] or ''

        lines = etree.SubElement(new_doc, 'lines')
        for line in results:
            node_line = etree.SubElement(lines, 'row')
            for f in fields_order:
                if fields[f]['type'] == 'many2one' and line[f]:
                    line[f] = line[f][1]
                if fields[f]['type'] in ('one2many', 'many2many') and line[f]:
                    line[f] = '( ' + str(len(line[f])) + ' )'
                if fields[f]['type'] == 'float':
                    precision = (('digits' in fields[f])
                                 and fields[f]['digits'][1]) or 2
                    line[f] = round(line[f], precision)
                col = etree.SubElement(node_line, 'col', tree='no')
                if line[f] is not None:
                    col.text = tools.ustr(line[f] or '')
                else:
                    col.text = '/'

        transform = etree.XSLT(
            etree.parse(
                os.path.join(tools.config['root_path'],
                             'addons/base/report/custom_new.xsl')))
        rml = etree.tostring(transform(new_doc))

        self.obj = render.rml(rml, self.title)
        self.obj.render()
        return True
Ejemplo n.º 23
0
 def go(id, uid, ids, datas, context):
     with yuancloud.api.Environment.manage():
         cr = yuancloud.registry(db).cursor()
         try:
             result, format = yuancloud.report.render_report(cr, uid, ids, object, datas, context)
             if not result:
                 tb = sys.exc_info()
                 self_reports[id]['exception'] = yuancloud.exceptions.DeferredException('RML is not available at specified location or not enough data to print!', tb)
             self_reports[id]['result'] = result
             self_reports[id]['format'] = format
             self_reports[id]['state'] = True
         except Exception, exception:
             _logger.exception('Exception: %s\n', exception)
             if hasattr(exception, 'name') and hasattr(exception, 'value'):
                 self_reports[id]['exception'] = yuancloud.exceptions.DeferredException(tools.ustr(exception.name), tools.ustr(exception.value))
             else:
                 tb = sys.exc_info()
                 self_reports[id]['exception'] = yuancloud.exceptions.DeferredException(tools.exception_to_unicode(exception), tb)
             self_reports[id]['state'] = True
         cr.commit()
         cr.close()
Ejemplo n.º 24
0
class SaasPortalConfigWizard(models.TransientModel):
    _inherit = 'saas_server.config.settings'

    sftp_server = fields.Char(string='SFTP Server Address',
                              help='IP address of your remote server. For example 192.168.0.1')
    sftp_username = fields.Char(string='Username on SFTP Server',
                                help="The username where the SFTP connection should be made with. This is the user on the external server.")
    sftp_password = fields.Char(string='Password User SFTP Server',
                                help="The password from the user where the SFTP connection should be made with. This is the password from the user on the external server.")
    sftp_path = fields.Char(string='Path external server',
                            help="The location to the folder where the dumps should be written to. For example /yuancloud/backups/.\nFiles will then be written to /yuancloud/backups/ on your remote server.")
    sftp_daystokeep = fields.Integer('Remove SFTP after x days', default=30,
                                     help="Choose after how many days the backup should be deleted from the FTP server. For example:\nIf you fill in 5 the backups will be removed after 5 days from the FTP server.")

    # sftp_server
    def get_default_sftp_server(self, cr, uid, ids, context=None):
        sftp_server = self.pool.get("ir.config_parameter").get_param(cr, uid, "saas_server.sftp_server", default=None,
                                                                     context=context)
        return {'sftp_server': sftp_server or False}

    def set_sftp_server(self, cr, uid, ids, context=None):
        config_parameters = self.pool.get("ir.config_parameter")
        for record in self.browse(cr, uid, ids, context=context):
            config_parameters.set_param(cr, uid, "saas_server.sftp_server", record.sftp_server or '', context=context)

    # sftp_username
    def get_default_sftp_username(self, cr, uid, ids, context=None):
        sftp_username = self.pool.get("ir.config_parameter").get_param(cr, uid, "saas_server.sftp_username",
                                                                       default=None, context=context)
        return {'sftp_username': sftp_username or False}

    def set_sftp_username(self, cr, uid, ids, context=None):
        config_parameters = self.pool.get("ir.config_parameter")
        for record in self.browse(cr, uid, ids, context=context):
            config_parameters.set_param(cr, uid, "saas_server.sftp_username", record.sftp_username or '',
                                        context=context)

    # sftp_password
    def get_default_sftp_password(self, cr, uid, ids, context=None):
        sftp_password = self.pool.get("ir.config_parameter").get_param(cr, uid, "saas_server.sftp_password",
                                                                       default=None, context=context)
        return {'sftp_password': sftp_password or False}

    def set_sftp_password(self, cr, uid, ids, context=None):
        config_parameters = self.pool.get("ir.config_parameter")
        for record in self.browse(cr, uid, ids, context=context):
            config_parameters.set_param(cr, uid, "saas_server.sftp_password", record.sftp_password or '',
                                        context=context)

    # sftp_path
    def get_default_sftp_path(self, cr, uid, ids, context=None):
        sftp_path = self.pool.get("ir.config_parameter").get_param(cr, uid, "saas_server.sftp_path", default=None,
                                                                   context=context)
        return {'sftp_path': sftp_path or False}

    def set_sftp_path(self, cr, uid, ids, context=None):
        config_parameters = self.pool.get("ir.config_parameter")
        for record in self.browse(cr, uid, ids, context=context):
            config_parameters.set_param(cr, uid, "saas_server.sftp_path", record.sftp_path or '', context=context)

    def get_default_sftp_daystokeep(self, cr, uid, ids, context=None):
        sftp_daystokeep = self.pool.get("ir.config_parameter").get_param(cr, uid, "saas_server.sftp_daystokeep",
                                                                         default=None,
                                                                         context=context)
        return {'sftp_daystokeep': sftp_daystokeep and int(sftp_daystokeep) or False}

    def set_sftp_daystokeep(self, cr, uid, ids, context=None):
        config_parameters = self.pool.get("ir.config_parameter")
        for record in self.browse(cr, uid, ids, context=context):
            config_parameters.set_param(cr, uid, "saas_server.sftp_daystokeep", record.sftp_daystokeep or '',
                                        context=context)

    def test_sftp_connection(self, cr, uid, ids, context=None):
        server = self.pool.get("ir.config_parameter").get_param(cr, uid, "saas_server.sftp_server", default=None,
                                                                context=context)
        username = self.pool.get("ir.config_parameter").get_param(cr, uid, "saas_server.sftp_username", default=None,
                                                                  context=context)
        password = self.pool.get("ir.config_parameter").get_param(cr, uid, "saas_server.sftp_password", default=None,
                                                                  context=context)
        path = self.pool.get("ir.config_parameter").get_param(cr, uid, "saas_server.sftp_path", default=None,
                                                              context=context)

        messageTitle = ""
        messageContent = ""

        try:
            # Connect with external server over SFTP, so we know sure that everything works.
            srv = pysftp.Connection(host=server, username=username, password=password)
            srv.close()
            # We have a success.
            messageTitle = "Connection Test Succeeded!"
            messageContent = "Everything seems properly set up for FTP back-ups!"
        except Exception, e:
            messageTitle = "Connection Test Failed!"
            messageContent += "Here is what we got instead:\n"
        if "Failed" in messageTitle:
            raise osv.except_osv(_(messageTitle), _(messageContent + "%s") % tools.ustr(e))
        else:
            raise osv.except_osv(_(messageTitle), _(messageContent))