Example #1
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
Example #2
0
    def amount_to_text(self, amount):
        self.ensure_one()

        def _num2words(number, lang):
            try:
                return num2words(number, lang=lang).title()
            except NotImplementedError:
                return num2words(number, lang='en').title()

        if num2words is None:
            logging.getLogger(__name__).warning(
                "The library 'num2words' is missing, cannot render textual amounts."
            )
            return ""

        formatted = "%.{0}f".format(self.decimal_places) % amount
        parts = formatted.partition('.')
        integer_value = int(parts[0])
        fractional_value = int(parts[2] or 0)

        lang_code = self.env.context.get('lang') or self.env.user.lang
        lang = self.env['res.lang'].search([('code', '=', lang_code)])
        amount_words = tools.ustr('{amt_value} {amt_word}').format(
            amt_value=_num2words(integer_value, lang=lang.iso_code),
            amt_word=self.currency_unit_label,
        )
        if not self.is_zero(amount - integer_value):
            amount_words += ' ' + _('and') + tools.ustr(
                ' {amt_value} {amt_word}').format(
                    amt_value=_num2words(fractional_value, lang=lang.iso_code),
                    amt_word=self.currency_subunit_label,
                )
        return amount_words
Example #3
0
 def get_graph_data(self, question, current_filters=None):
     '''Returns formatted data required by graph library on basis of filter'''
     # TODO refactor this terrible method and merge it with prepare_result_dict
     current_filters = current_filters if current_filters else []
     Survey = request.env['survey.survey']
     result = []
     if question.type == 'multiple_choice':
         result.append({
             'key':
             ustr(question.question),
             'values':
             Survey.prepare_result(question, current_filters)['answers']
         })
     if question.type == 'simple_choice':
         result = Survey.prepare_result(question,
                                        current_filters)['answers']
     if question.type == 'matrix':
         data = Survey.prepare_result(question, current_filters)
         for answer in data['answers']:
             values = []
             for row in data['rows']:
                 values.append({
                     'text': data['rows'].get(row),
                     'count': data['result'].get((row, answer))
                 })
             result.append({
                 'key': data['answers'].get(answer),
                 'values': values
             })
     return json.dumps(result)
Example #4
0
 def write(self, vals):
     if 'image' in vals:
         image = ustr(vals['image'] or '').encode('utf-8')
         vals['image_payment_form'] = image_resize_image(image,
                                                         size=(45, 30))
         vals['image'] = image_resize_image(image, size=(64, 64))
     return super(PaymentIcon, self).write(vals)
Example #5
0
    def execute_callback(self):
        res = None
        for transaction in self:
            # limited sudo env, only for checking callback presence, not for running it!
            # manual transactions have no callback, and can pass without being run by admin user
            tx_sudo = transaction.sudo()
            if not (tx_sudo.callback_model_id and tx_sudo.callback_res_id
                    and tx_sudo.callback_method):
                continue

            valid_token = transaction._generate_callback_hash()
            if not consteq(ustr(valid_token), transaction.callback_hash):
                _logger.warning(
                    "Invalid callback signature for transaction %d" %
                    (transaction.id))
                continue

            record = self.env[transaction.callback_model_id.model].browse(
                transaction.callback_res_id).exists()
            if record:
                res = getattr(record, transaction.callback_method)(transaction)
            else:
                _logger.warning(
                    "Did not found record %s.%s for callback of transaction %d"
                    % (transaction.callback_model_id.model,
                       transaction.callback_res_id, transaction.id))
        return res
Example #6
0
    def change_product_qty(self):
        """ Changes the Product Quantity by making a Physical Inventory. """
        Inventory = self.env['stock.inventory']
        for wizard in self:
            product = wizard.product_id.with_context(
                location=wizard.location_id.id, lot_id=wizard.lot_id.id)
            line_data = wizard._action_start_line()

            if wizard.product_id.id and wizard.lot_id.id:
                inventory_filter = 'none'
            elif wizard.product_id.id:
                inventory_filter = 'product'
            else:
                inventory_filter = 'none'
            inventory = Inventory.create({
                'name':
                _('INV: %s') % tools.ustr(wizard.product_id.display_name),
                'filter':
                inventory_filter,
                'product_id':
                wizard.product_id.id,
                'location_id':
                wizard.location_id.id,
                'lot_id':
                wizard.lot_id.id,
                'line_ids': [(0, 0, line_data)],
            })
            inventory.action_done()
        return {'type': 'ir.actions.act_window_close'}
Example #7
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:
         model = self.env['ir.model']._get(record.model or 'mail.message')
         model_name = model.name or ''
         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':
             model.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,
                        context=self._context)
Example #8
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)])
Example #9
0
    def _get_source(self, name, types, lang, source=None, res_id=None):
        """ Return the translation for the given combination of ``name``,
        ``type``, ``language`` and ``source``. All values passed to this method
        should be unicode (not byte strings), especially ``source``.

        :param name: identification of the term to translate, such as field name (optional if source is passed)
        :param types: single string defining type of term to translate (see ``type`` field on ir.translation), or sequence of allowed types (strings)
        :param lang: language code of the desired translation
        :param source: optional source term to translate (should be unicode)
        :param res_id: optional resource id or a list of ids to translate (if used, ``source`` should be set)
        :rtype: unicode
        :return: the request translation, or an empty unicode string if no translation was
                 found and `source` was not passed
        """
        # FIXME: should assert that `source` is unicode and fix all callers to
        # always pass unicode so we can remove the string encoding/decoding.
        if not lang:
            return tools.ustr(source or '')
        if isinstance(types, pycompat.string_types):
            types = (types, )
        if res_id:
            if isinstance(res_id, pycompat.integer_types):
                res_id = (res_id, )
            else:
                res_id = tuple(res_id)
        return self.__get_source(name, types, lang, source, res_id)
Example #10
0
    def write(self, vals):
        if vals.get('user_domain'):
            users = self._get_challenger_users(ustr(vals.get('user_domain')))

            if not vals.get('user_ids'):
                vals['user_ids'] = []
            vals['user_ids'].extend((4, user.id) for user in users)

        write_res = super(Challenge, self).write(vals)

        if vals.get('report_message_frequency', 'never') != 'never':
            # _recompute_challenge_users do not set users for challenges with no reports, subscribing them now
            for challenge in self:
                challenge.message_subscribe(
                    [user.partner_id.id for user in challenge.user_ids])

        if vals.get('state') == 'inprogress':
            self._recompute_challenge_users()
            self._generate_goals_from_challenge()

        elif vals.get('state') == 'done':
            self._check_challenge_reward(force=True)

        elif vals.get('state') == 'draft':
            # resetting progress
            if self.env['gamification.goal'].search(
                [('challenge_id', 'in', self.ids),
                 ('state', '=', 'inprogress')],
                    limit=1):
                raise exceptions.UserError(
                    _("You can not reset a challenge with unfinished goals."))

        return write_res
Example #11
0
    def get_or_create_user(self, conf, login, ldap_entry):
        """
        Retrieve an active resource of model res_users with the specified
        login. Create the user if it is not initially found.

        :param dict conf: LDAP configuration
        :param login: the user's login
        :param tuple ldap_entry: single LDAP result (dn, attrs)
        :return: res_users id
        :rtype: int
        """

        user_id = False
        login = tools.ustr(login.lower().strip())
        self.env.cr.execute(
            "SELECT id, active FROM res_users WHERE lower(login)=%s",
            (login, ))
        res = self.env.cr.fetchone()
        if res:
            if res[1]:
                user_id = res[0]
        elif conf['create_user']:
            _logger.debug("Creating new izi user \"%s\" from LDAP" % login)
            values = self.map_ldap_attributes(conf, login, ldap_entry)
            SudoUser = self.env['res.users'].sudo()
            if conf['user']:
                values['active'] = True
                user_id = SudoUser.browse(
                    conf['user'][0]).copy(default=values).id
            else:
                user_id = SudoUser.create(values).id
        return user_id
Example #12
0
def extract_rfc2822_addresses(text):
    """Returns a list of valid RFC2822 addresses
       that can be found in ``source``, ignoring
       malformed ones and non-ASCII ones.
    """
    if not text:
        return []
    candidates = address_pattern.findall(ustr(text))
    return [c for c in candidates if is_ascii(c)]
Example #13
0
 def _geoip_setup_resolver(cls):
     # Lazy init of GeoIP resolver
     if izi._geoip_resolver is not None:
         return
     geofile = config.get('geoip_database')
     try:
         izi._geoip_resolver = GeoIPResolver.open(geofile) or False
     except Exception as e:
         _logger.warning('Cannot load GeoIP: %s', ustr(e))
Example #14
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``: Model 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, pycompat.integer_types):
            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(it for it in res_ids if it)  # 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_date': lambda date, format=False, context=self._context: format_date(self.env, date, format),
            'format_tz': lambda dt, tz=False, format=False, context=self._context: format_tz(self.env, dt, tz, format),
            'format_amount': lambda amount, currency, context=self._context: format_amount(self.env, amount, currency),
            'user': self.env.user,
            'ctx': self._context,  # context kw would clash with mako internals
        }
        for res_id, record in res_to_rec.items():
            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))
            if render_result == u"False":
                render_result = u""
            results[res_id] = render_result

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

        return multi_mode and results or results[res_ids[0]]
Example #15
0
def schema_valid(arch):
    """ Get RNG validator and validate RNG file."""
    validator = relaxng(arch.tag)
    if validator and not validator.validate(arch):
        result = True
        for error in validator.error_log:
            _logger.error(tools.ustr(error))
            result = False
        return result
    return True
Example #16
0
 def __get_source(self, name, types, lang, source, res_id):
     # res_id is a tuple or None, otherwise ormcache cannot cache it!
     query, params = self._get_source_query(name, types, lang, source,
                                            res_id)
     self._cr.execute(query, params)
     res = self._cr.fetchone()
     trad = res and res[0] or u''
     if source and not trad:
         return tools.ustr(source)
     return trad
Example #17
0
    def from_html(self, model, field, element):
        value = element.text_content().strip()
        selection = field.get_description(self.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))
Example #18
0
    def _get_source_query(self, name, types, lang, source, res_id):
        if source:
            # Note: the extra test on md5(src) is a hint for postgres to use the
            # index ir_translation_src_md5
            query = """SELECT value FROM ir_translation
                       WHERE lang=%s AND type in %s AND src=%s AND md5(src)=md5(%s)"""
            source = tools.ustr(source)
            params = (lang or '', types, source, source)
            if res_id:
                query += " AND res_id in %s"
                params += (res_id, )
            if name:
                query += " AND name=%s"
                params += (tools.ustr(name), )
        else:
            query = """ SELECT value FROM ir_translation
                        WHERE lang=%s AND type in %s AND name=%s """
            params = (lang or '', types, tools.ustr(name))

        return (query, params)
Example #19
0
    def create(self, vals):
        """Overwrite the create method to add the user of groups"""

        if vals.get('user_domain'):
            users = self._get_challenger_users(ustr(vals.get('user_domain')))

            if not vals.get('user_ids'):
                vals['user_ids'] = []
            vals['user_ids'].extend((4, user.id) for user in users)

        return super(Challenge, self).create(vals)
Example #20
0
    def _get_sys_logs(self):
        """
        Utility method to send a publisher warranty get logs messages.
        """
        msg = self._get_message()
        arguments = {'arg0': ustr(msg), "action": "update"}

        url = config.get("publisher_warranty_url")

        r = requests.post(url, data=arguments, timeout=30)
        r.raise_for_status()
        return literal_eval(r.text)
Example #21
0
    def _sync_response(self, limit=GENGO_DEFAULT_LIMIT):
        """
        This method will be called by cron services to get translations from
        Gengo. It will read translated terms and comments from Gengo and will
        update respective ir.translation in izi.
        """
        IrTranslation = self.env['ir.translation']
        flag, gengo = self.gengo_authentication()
        if not flag:
            _logger.warning("%s", gengo)
        else:
            offset = 0
            all_translation_ids = IrTranslation.search([
                ('state', '=', 'inprogress'),
                ('gengo_translation', 'in', ('machine', 'standard', 'pro',
                                             'ultra')),
                ('order_id', "!=", False)
            ])
            while True:
                translation_ids = all_translation_ids[offset:offset + limit]
                offset += limit
                if not translation_ids:
                    break

                terms_progress = {
                    'gengo_order_ids': set(),
                    'ir_translation_ids': set(),
                }
                for term in translation_ids:
                    terms_progress['gengo_order_ids'].add(term.order_id)
                    terms_progress['ir_translation_ids'].add(
                        tools.ustr(term.id))

                for order_id in terms_progress['gengo_order_ids']:
                    order_response = gengo.getTranslationOrderJobs(id=order_id)
                    jobs_approved = order_response.get('response', []).get(
                        'order', []).get('jobs_approved', [])
                    gengo_ids = ','.join(jobs_approved)

                if gengo_ids:  # Need to check, because getTranslationJobBatch don't catch this case and so call the getTranslationJobs because no ids in url
                    try:
                        job_response = gengo.getTranslationJobBatch(
                            id=gengo_ids)
                    except:
                        continue
                    if job_response['opstat'] == 'ok':
                        for job in job_response['response'].get('jobs', []):
                            if job.get('custom_data') in terms_progress[
                                    'ir_translation_ids']:
                                self._update_terms_job(job)
        return True
Example #22
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(
        field for field in
        [street, ("%s %s" % (zip or '', city or '')).strip(), state, country]
        if field))
Example #23
0
    def create(self, values):
        # coming from mail.js that does not have pid in its values
        if self.env.context.get('default_starred'):
            self = self.with_context({'default_starred_partner_ids': [(4, self.env.user.partner_id.id)]})

        if 'email_from' not in values:  # needed to compute reply_to
            values['email_from'] = self._get_default_from()
        if not values.get('message_id'):
            values['message_id'] = self._get_message_id(values)
        if 'reply_to' not in values:
            values['reply_to'] = self._get_reply_to(values)
        if 'record_name' not in values and 'default_record_name' not in self.env.context:
            values['record_name'] = self._get_record_name(values)

        if 'attachment_ids' not in values:
            values.setdefault('attachment_ids', [])

        # extract base64 images
        if 'body' in values:
            Attachments = self.env['ir.attachment']
            data_to_url = {}
            def base64_to_boundary(match):
                key = match.group(2)
                if not data_to_url.get(key):
                    name = 'image%s' % len(data_to_url)
                    attachment = Attachments.create({
                        'name': name,
                        'datas': match.group(2),
                        'datas_fname': name,
                        'res_model': 'mail.message',
                    })
                    attachment.generate_access_token()
                    values['attachment_ids'].append((4, attachment.id))
                    data_to_url[key] = ['/web/image/%s?access_token=%s' % (attachment.id, attachment.access_token), name]
                return '%s%s alt="%s"' % (data_to_url[key][0], match.group(3), data_to_url[key][1])
            values['body'] = _image_dataurl.sub(base64_to_boundary, tools.ustr(values['body']))

        # delegate creation of tracking after the create as sudo to avoid access rights issues
        tracking_values_cmd = values.pop('tracking_value_ids', False)
        message = super(Message, self).create(values)
        if tracking_values_cmd:
            message.sudo().write({'tracking_value_ids': tracking_values_cmd})

        message._invalidate_documents()

        if not self.env.context.get('message_create_from_mail_mail'):
            message._notify(force_send=self.env.context.get('mail_notify_force_send', True),
                            user_signature=self.env.context.get('mail_notify_user_signature', True))
        return message
Example #24
0
    def fields_get(self, fields=None, attributes=None):
        """ If an addon is already installed, set it to readonly as
        res.config.installer doesn't handle uninstallations of already
        installed addons
        """
        fields = super(ResConfigInstaller,
                       self).fields_get(fields, attributes=attributes)

        for name in self.already_installed():
            if name not in fields:
                continue
            fields[name].update(
                readonly=True,
                help=ustr(fields[name].get('help', '')) +
                _('\n\nThis addon is already installed on your system'))
        return fields
Example #25
0
    def onchange_employee(self):

        if (not self.employee_id) or (not self.date_from) or (
                not self.date_to):
            return

        employee = self.employee_id
        date_from = self.date_from
        date_to = self.date_to
        contract_ids = []

        ttyme = datetime.fromtimestamp(
            time.mktime(time.strptime(date_from, "%Y-%m-%d")))
        locale = self.env.context.get('lang') or 'en_US'
        self.name = _('Salary Slip of %s for %s') % (
            employee.name,
            tools.ustr(
                babel.dates.format_date(
                    date=ttyme, format='MMMM-y', locale=locale)))
        self.company_id = employee.company_id

        if not self.env.context.get('contract') or not self.contract_id:
            contract_ids = self.get_contract(employee, date_from, date_to)
            if not contract_ids:
                return
            self.contract_id = self.env['hr.contract'].browse(contract_ids[0])

        if not self.contract_id.struct_id:
            return
        self.struct_id = self.contract_id.struct_id

        #computation of the salary input
        contracts = self.env['hr.contract'].browse(contract_ids)
        worked_days_line_ids = self.get_worked_day_lines(
            contracts, date_from, date_to)
        worked_days_lines = self.worked_days_line_ids.browse([])
        for r in worked_days_line_ids:
            worked_days_lines += worked_days_lines.new(r)
        self.worked_days_line_ids = worked_days_lines

        input_line_ids = self.get_inputs(contracts, date_from, date_to)
        input_lines = self.input_line_ids.browse([])
        for r in input_line_ids:
            input_lines += input_lines.new(r)
        self.input_line_ids = input_lines
        return
Example #26
0
    def update_list(self):
        res = [0, 0]  # [update, add]

        default_version = modules.adapt_version('1.0')
        known_mods = self.with_context(lang=None).search([])
        known_mods_names = {mod.name: mod for mod in known_mods}

        # iterate through detected modules and update/create them in db
        for mod_name in modules.get_modules():
            mod = known_mods_names.get(mod_name)
            terp = self.get_module_info(mod_name)
            values = self.get_values_from_terp(terp)

            if mod:
                updated_values = {}
                for key in values:
                    old = getattr(mod, key)
                    updated = tools.ustr(values[key]) if isinstance(
                        values[key], pycompat.string_types) else values[key]
                    if (old or updated) and updated != old:
                        updated_values[key] = values[key]
                if terp.get('installable',
                            True) and mod.state == 'uninstallable':
                    updated_values['state'] = 'uninstalled'
                if parse_version(terp.get(
                        'version', default_version)) > parse_version(
                            mod.latest_version or default_version):
                    res[0] += 1
                if updated_values:
                    mod.write(updated_values)
            else:
                mod_path = modules.get_module_path(mod_name)
                if not mod_path:
                    continue
                if not terp or not terp.get('installable', True):
                    continue
                mod = self.create(
                    dict(name=mod_name, state='uninstalled', **values))
                res[1] += 1

            mod._update_dependencies(terp.get('depends', []))
            mod._update_exclusions(terp.get('excludes', []))
            mod._update_category(terp.get('category', 'Uncategorized'))

        return res
Example #27
0
 def pack_jobs_request(self, term_ids, context=None):
     ''' prepare the terms that will be requested to gengo and returns them in a dictionary with following format
         {'jobs': {
             'term1.id': {...}
             'term2.id': {...}
             }
         }'''
     base_url = self.env['ir.config_parameter'].sudo().get_param(
         'web.base.url')
     IrTranslation = self.env['ir.translation']
     jobs = {}
     user = self.env.user
     auto_approve = 1 if user.company_id.gengo_auto_approve else 0
     for term in term_ids:
         if re.search(r"\w", term.src or ""):
             comment = user.company_id.gengo_comment or ''
             if term.gengo_comment:
                 comment += '\n' + term.gengo_comment
             jobs[time.strftime('%Y%m%d%H%M%S') + '-' + str(term.id)] = {
                 'type':
                 'text',
                 'slug':
                 'Single :: English to ' + term.lang,
                 'tier':
                 tools.ustr(term.gengo_translation),
                 'custom_data':
                 str(term.id),
                 'body_src':
                 term.src,
                 'lc_src':
                 'en',
                 'lc_tgt':
                 IrTranslation._get_gengo_corresponding_language(term.lang),
                 'auto_approve':
                 auto_approve,
                 'comment':
                 comment,
                 'callback_url':
                 "%s/website/gengo_callback?pgk=%s&db=%s" %
                 (base_url, self.get_gengo_key(), self.env.cr.dbname)
             }
     return {'jobs': jobs, 'as_group': 0}
Example #28
0
def encode_header(header_text):
    """Returns an appropriate representation of the given header value,
       suitable for direct assignment as a header value in an
       email.message.Message. RFC2822 assumes that headers contain
       only 7-bit characters, so we ensure it is the case, using
       RFC2047 encoding when needed.

       :param header_text: unicode or utf-8 encoded string with header value
       :rtype: string | email.header.Header
       :return: if ``header_text`` represents a plain ASCII string,
                return the same 7-bit string, otherwise returns an email.header.Header
                that will perform the appropriate RFC2047 encoding of
                non-ASCII values.
    """
    if not header_text:
        return ""
    header_text = ustr(header_text) # FIXME: require unicode higher up?
    if is_ascii(header_text):
        return pycompat.to_native(header_text)
    return Header(header_text, 'utf-8')
Example #29
0
def encode_header_param(param_text):
    """Returns an appropriate RFC2047 encoded representation of the given
       header parameter value, suitable for direct assignation as the
       param value (e.g. via Message.set_param() or Message.add_header())
       RFC2822 assumes that headers contain only 7-bit characters,
       so we ensure it is the case, using RFC2047 encoding when needed.

       :param param_text: unicode or utf-8 encoded string with header value
       :rtype: string
       :return: if ``param_text`` represents a plain ASCII string,
                return the same 7-bit string, otherwise returns an
                ASCII string containing the RFC2047 encoded text.
    """
    # For details see the encode_header() method that uses the same logic
    if not param_text:
        return ""
    param_text = ustr(param_text) # FIXME: require unicode higher up?
    if is_ascii(param_text):
        return pycompat.to_native(param_text) # TODO: is that actually necessary?
    return Charset("utf-8").header_encode(param_text)
Example #30
0
    def authenticate(self, conf, login, password):
        """
        Authenticate a user against the specified LDAP server.

        In order to prevent an unintended 'unauthenticated authentication',
        which is an anonymous bind with a valid dn and a blank password,
        check for empty passwords explicitely (:rfc:`4513#section-6.3.1`)
        :param dict conf: LDAP configuration
        :param login: username
        :param password: Password for the LDAP user
        :return: LDAP entry of authenticated user or False
        :rtype: dictionary of attributes
        """

        if not password:
            return False

        entry = False
        try:
            filter = filter_format(conf['ldap_filter'], (login, ))
        except TypeError:
            _logger.warning(
                'Could not format LDAP filter. Your filter should contain one \'%s\'.'
            )
            return False
        try:
            results = self.query(conf, tools.ustr(filter))

            # Get rid of (None, attrs) for searchResultReference replies
            results = [i for i in results if i[0]]
            if len(results) == 1:
                dn = results[0][0]
                conn = self.connect(conf)
                conn.simple_bind_s(dn, to_native(password))
                conn.unbind()
                entry = results[0]
        except ldap.INVALID_CREDENTIALS:
            return False
        except ldap.LDAPError as e:
            _logger.error('An LDAP exception occurred: %s', e)
        return entry