示例#1
0
 def _get_authz_info(self):
     if not self.authz_file:
         self.log.error("The [svn] authz_file configuration option in "
                        "trac.ini is empty or not defined")
         raise ConfigurationError()
     try:
         mtime = os.path.getmtime(self.authz_file)
     except OSError as e:
         self.log.error("Error accessing svn authz permission policy "
                        "file: %s", exception_to_unicode(e))
         raise ConfigurationError()
     if mtime != self._mtime:
         self._mtime = mtime
         rm = RepositoryManager(self.env)
         modules = set(repos.reponame
                       for repos in rm.get_real_repositories())
         if '' in modules and self.authz_module_name:
             modules.add(self.authz_module_name)
         modules.add('')
         self.log.info("Parsing authz file: %s", self.authz_file)
         try:
             self._authz = parse(self.authz_file, modules)
         except ParsingError as e:
             self.log.error("Error parsing svn authz permission policy "
                            "file: %s", exception_to_unicode(e))
             raise ConfigurationError()
         else:
             self._users = {user
                            for paths in self._authz.itervalues()
                            for path in paths.itervalues()
                            for user, result in path.iteritems()
                            if result}
     return self._authz, self._users
示例#2
0
文件: authz_policy.py 项目: t2y/trac
    def parse_authz(self):
        if ConfigObj is None:
            self.log.error('ConfigObj package not found.')
            raise ConfigurationError()
        self.log.debug('Parsing authz security policy %s',
                       self.get_authz_file)
        try:
            self.authz = ConfigObj(self.get_authz_file, encoding='utf8',
                                   raise_errors=True)
        except ConfigObjError as e:
            self.log.error("Error parsing authz permission policy file: %s",
                           to_unicode(e))
            raise ConfigurationError()
        groups = {}
        for group, users in self.authz.get('groups', {}).iteritems():
            if isinstance(users, basestring):
                users = [users]
            groups[group] = map(to_unicode, users)

        self.groups_by_user = {}

        def add_items(group, items):
            for item in items:
                if item.startswith('@'):
                    add_items(group, groups[item[1:]])
                else:
                    self.groups_by_user.setdefault(item, set()).add(group)

        for group, users in groups.iteritems():
            add_items('@' + group, users)

        self.authz_mtime = os.path.getmtime(self.get_authz_file)
示例#3
0
    def parse_authz(self):
        self.log.debug("Parsing authz security policy %s", self.authz_file)

        if not self.authz_file:
            self.log.error("The `[authz_policy] authz_file` configuration "
                           "option in trac.ini is empty or not defined.")
            raise ConfigurationError()
        try:
            authz_mtime = os.path.getmtime(self.authz_file)
        except OSError as e:
            self.log.error("Error parsing authz permission policy file: %s",
                           exception_to_unicode(e))
            raise ConfigurationError()

        self.authz = UnicodeConfigParser(ignorecase_option=False)
        try:
            self.authz.read(self.authz_file)
        except configparser.ParsingError as e:
            self.log.error("Error parsing authz permission policy file: %s",
                           exception_to_unicode(e))
            raise ConfigurationError()
        groups = {}
        if self.authz.has_section('groups'):
            for group, users in self.authz.items('groups'):
                groups[group] = to_list(users)

        self.groups_by_user = {}

        def add_items(group, items):
            for item in items:
                if item.startswith('@'):
                    add_items(group, groups[item[1:]])
                else:
                    self.groups_by_user.setdefault(item, set()).add(group)

        for group, users in groups.items():
            add_items('@' + group, users)

        all_actions = set(PermissionSystem(self.env).get_actions())
        authz_basename = os.path.basename(self.authz_file)
        for section in self.authz.sections():
            if section == 'groups':
                continue
            for user, actions in self.authz.items(section):
                for action in to_list(actions):
                    if action.startswith('!'):
                        action = action[1:]
                    if action not in all_actions:
                        self.log.warning(
                            "The action %s in the [%s] section "
                            "of %s is not a valid action.", action, section,
                            authz_basename)
        self.authz_mtime = authz_mtime
示例#4
0
    def __init__(self):
        if not self.authz_file:
            self.log.error("The `[authz_policy] authz_file` configuration "
                           "option in trac.ini is empty or not defined.")
            raise ConfigurationError()

        try:
            os.stat(self.authz_file)
        except OSError as e:
            self.log.error("Error parsing authz permission policy file: %s",
                           to_unicode(e))
            raise ConfigurationError()
        self.groups_by_user = {}
示例#5
0
    def parse_authz(self):
        self.log.debug("Parsing authz security policy %s", self.authz_file)

        self.authz = UnicodeConfigParser()
        try:
            self.authz.read(self.authz_file)
        except ParsingError as e:
            self.log.error("Error parsing authz permission policy file: %s",
                           to_unicode(e))
            raise ConfigurationError()
        groups = {}
        if self.authz.has_section('groups'):
            for group, users in self.authz.items('groups'):
                groups[group] = to_list(users)

        self.groups_by_user = {}

        def add_items(group, items):
            for item in items:
                if item.startswith('@'):
                    add_items(group, groups[item[1:]])
                else:
                    self.groups_by_user.setdefault(item, set()).add(group)

        for group, users in groups.iteritems():
            add_items('@' + group, users)

        self.authz_mtime = os.path.getmtime(self.authz_file)
示例#6
0
文件: authz_policy.py 项目: t2y/trac
    def get_authz_file(self):
        if not self.authz_file:
            self.log.error('The `[authz_policy] authz_file` configuration '
                           'option in trac.ini is empty or not defined.')
            raise ConfigurationError()

        authz_file = self.authz_file if os.path.isabs(self.authz_file) \
                                     else os.path.join(self.env.path,
                                                       self.authz_file)
        try:
            os.stat(authz_file)
        except OSError as e:
            self.log.error("Error parsing authz permission policy file: %s",
                           to_unicode(e))
            raise ConfigurationError()
        return authz_file
示例#7
0
 def __init__(self):
     solr_url = self.config.get('pysolr_search_backend', 'solr_url', None)
     timeout = self.config.getfloat('pysolr_search_backend', 'timeout', 30)
     if not solr_url:
         raise ConfigurationError(
             'PySolrSearchBackend must be configured in trac.ini')
     self.conn = pysolr.Solr(solr_url, timeout=timeout)
示例#8
0
def create_message_id(env, targetid, from_email, time, more=None):
    """Generate a predictable, but sufficiently unique message ID.

    In case you want to set the "Message ID" header, this convenience
    function will generate one by running a hash algorithm over a number
    of properties.

    :param env: the `Environment`
    :param targetid: a string that identifies the target, like
        `NotificationEvent.target`
    :param from_email: the email address that the message is sent from
    :param time: a Python `datetime`
    :param more: a string that contains additional information that
        makes this message unique
    """
    items = [env.project_url, targetid, to_utimestamp(time)]
    if more is not None:
        items.append(more.encode('ascii', 'ignore'))
    source = b'.'.join(
        item if isinstance(item, bytes) else str(item).encode('utf-8')
        for item in items)
    hash_type = NotificationSystem(env).message_id_hash
    try:
        h = hashlib.new(hash_type)
    except:
        raise ConfigurationError(
            _("Unknown hash type '%(type)s'", type=hash_type))
    h.update(source)
    host = from_email[from_email.find('@') + 1:]
    return '<%03d.%s@%s>' % (len(source), h.hexdigest(), host)
示例#9
0
文件: mail.py 项目: zxfly/trac
    def send(self, from_addr, recipients, message):
        # Use native line endings in message
        message = fix_eol(message, os.linesep)

        self.log.info("Sending notification through sendmail at %s to %s",
                      self.sendmail_path, recipients)
        cmdline = [self.sendmail_path, '-i', '-f', from_addr] + recipients
        self.log.debug("Sendmail command line: %s", cmdline)
        try:
            child = Popen(cmdline,
                          bufsize=-1,
                          stdin=PIPE,
                          stdout=PIPE,
                          stderr=PIPE,
                          close_fds=close_fds)
        except OSError as e:
            raise ConfigurationError(
                tag_(
                    "Sendmail error (%(error)s). Please modify %(option)s "
                    "in your configuration.",
                    error=to_unicode(e),
                    option=tag.code("[notification] sendmail_path")))
        out, err = child.communicate(message)
        if child.returncode or err:
            raise Exception("Sendmail failed with (%s, %s), command: '%s'" %
                            (child.returncode, err.strip(), cmdline))
示例#10
0
文件: api.py 项目: wataash/trac
def _invalid_db_str(db_str):
    return ConfigurationError(
        tag_(
            "Invalid format %(db_str)s for the database connection string. "
            "Please refer to the %(doc)s for help.",
            db_str=tag.code(db_str),
            doc=_doc_db_str()))
示例#11
0
    def __init__(self, path, log=None, params={}):
        if have_pysqlite == 0:
            raise TracError(_("Cannot load Python bindings for SQLite"))
        self.cnx = None
        if path != ':memory:':
            if not os.access(path, os.F_OK):
                raise ConfigurationError(
                    _('Database "%(path)s" not found.', path=path))

            dbdir = os.path.dirname(path)
            if not os.access(path, os.R_OK + os.W_OK) or \
                   not os.access(dbdir, os.R_OK + os.W_OK):
                raise ConfigurationError(
                    tag_(
                        "The user %(user)s requires read _and_ write permissions "
                        "to the database file %(path)s and the directory it is "
                        "located in.",
                        user=tag.tt(getuser()),
                        path=tag.tt(path)))

        self._active_cursors = weakref.WeakKeyDictionary()
        timeout = int(params.get('timeout', 10.0))
        self._eager = params.get('cursor', 'eager') == 'eager'
        # eager is default, can be turned off by specifying ?cursor=
        if isinstance(path, unicode):  # needed with 2.4.0
            path = path.encode('utf-8')
        cnx = sqlite.connect(path,
                             detect_types=sqlite.PARSE_DECLTYPES,
                             isolation_level=None,
                             check_same_thread=sqlite_version < (3, 3, 1),
                             timeout=timeout)
        # load extensions
        extensions = params.get('extensions', [])
        if len(extensions) > 0:
            cnx.enable_load_extension(True)
            for ext in extensions:
                cnx.load_extension(ext)
            cnx.enable_load_extension(False)

        cursor = cnx.cursor()
        _set_journal_mode(cursor, params.get('journal_mode'))
        _set_synchronous(cursor, params.get('synchronous'))
        cursor.close()
        cnx.isolation_level = 'DEFERRED'
        ConnectionWrapper.__init__(self, cnx, log)
示例#12
0
def getfloat(self, name, default=''):
    value = self.get(name, default)
    if not value:
        return 0.
    try:
        return float(value)
    except ValueError:
        raise ConfigurationError(
            '[%(section)s] %(entry)s: expected float, got %(value)s' %
            dict(section=self.name, entry=name, value=repr(value)))
示例#13
0
 def _get_abspath(self, key, value):
     value.rstrip('/')
     if not os.path.isabs(value):
         raise ConfigurationError(
             '[%(section)s] %(entry)s: expected abs path, got %(value)s', {
                 'section': self.section,
                 'entry': key,
                 'value': repr(value)
             })
     return os.path.normcase(value)
示例#14
0
 def _get_directory(self, key, value):
     if '/' in value or '\\' in value or '..' in value:
         raise ConfigurationError(
             '[%(section)s] %(entry)s: expected directory name, '
             'got %(value)s' % {
                 'section': self.section,
                 'entry': key,
                 'value': repr(value)
             })
     return value
示例#15
0
文件: mail.py 项目: zxfly/trac
    def send(self, from_addr, recipients, message):
        global local_hostname
        # Ensure the message complies with RFC2822: use CRLF line endings
        message = fix_eol(message, CRLF)

        self.log.info("Sending notification through SMTP at %s:%d to %s",
                      self.smtp_server, self.smtp_port, recipients)
        try:
            server = smtplib.SMTP(self.smtp_server, self.smtp_port,
                                  local_hostname)
            local_hostname = server.local_hostname
        except smtplib.socket.error as e:
            raise ConfigurationError(
                tag_(
                    "SMTP server connection error (%(error)s). Please "
                    "modify %(option1)s or %(option2)s in your "
                    "configuration.",
                    error=to_unicode(e),
                    option1=tag.code("[notification] smtp_server"),
                    option2=tag.code("[notification] smtp_port")))
        # server.set_debuglevel(True)
        if self.use_tls:
            server.ehlo()
            if 'starttls' not in server.esmtp_features:
                raise TracError(
                    _("TLS enabled but server does not support"
                      " TLS"))
            server.starttls()
            server.ehlo()
        if self.smtp_user:
            server.login(self.smtp_user.encode('utf-8'),
                         self.smtp_password.encode('utf-8'))
        start = time_now()
        server.sendmail(from_addr, recipients, message)
        t = time_now() - start
        if t > 5:
            self.log.warning(
                "Slow mail submission (%.2f s), "
                "check your mail setup", t)
        if self.use_tls:
            # avoid false failure detection when the server closes
            # the SMTP connection with TLS enabled
            import socket
            try:
                server.quit()
            except socket.sslerror:
                pass
        else:
            server.quit()
示例#16
0
文件: mail.py 项目: zxfly/trac
def create_message_id(env, targetid, from_email, time, more=None):
    """Generate a predictable, but sufficiently unique message ID."""
    items = [env.project_url.encode('utf-8'), targetid, to_utimestamp(time)]
    if more is not None:
        items.append(more.encode('ascii', 'ignore'))
    source = '.'.join(str(item) for item in items)
    hash_type = NotificationSystem(env).message_id_hash
    try:
        h = hashlib.new(hash_type)
    except:
        raise ConfigurationError(
            _("Unknown hash type '%(type)s'", type=hash_type))
    h.update(source)
    host = from_email[from_email.find('@') + 1:]
    return '<%03d.%s@%s>' % (len(source), h.hexdigest(), host)
示例#17
0
 def accessor(self, section, name, default=''):
     """Return the value of the specified option as float.
     
     If the specified option can not be converted to a float, a
     `ConfigurationError` exception is raised.
     
     Valid default input is a string or a float. Returns an float.
     """
     value = section.get(name, default)
     if not value:
         return 0.0
     try:
         return float(value)
     except ValueError:
         raise ConfigurationError('expected real number, got %s' % \
                                  repr(value))
示例#18
0
    def __init__(self):
        solr_url = self.config.get(*CONFIG_FIELD['solr_url'])
        timeout = self.config.getfloat(*CONFIG_FIELD['timeout'])
        if not solr_url:
            raise ConfigurationError(
                'PySolrSearchBackend must be configured in trac.ini')
        self.conn = pysolr.Solr(solr_url, timeout=timeout)

        self.async_indexing = self.config.getbool(
            *CONFIG_FIELD['async_indexing'])
        if self.async_indexing:
            maxsize = self.config.getint(*CONFIG_FIELD['async_queue_maxsize'])
            self.indexer = AsyncSolrIndexer(self, maxsize)
            self.indexer.start()
        else:
            self.indexer = SolrIndexer(self)
示例#19
0
    def send(self, from_addr, recipients, message):
        # Use native line endings in message
        message = fix_eol(message, os.linesep)

        self.log.info("Sending notification through sendmail at %s to %s",
                      self.sendmail_path, recipients)
        cmdline = [self.sendmail_path, "-i", "-f", from_addr]
        cmdline.extend(recipients)
        self.log.debug("Sendmail command line: %s", cmdline)
        try:
            child = Popen(cmdline, bufsize=-1, stdin=PIPE, stdout=PIPE,
                          stderr=PIPE, close_fds=close_fds)
        except OSError, e:
            raise ConfigurationError(
                tag_("Sendmail error (%(error)s). Please modify %(option)s "
                     "in your configuration.",
                     error=to_unicode(e),
                     option=tag.tt("[notification] sendmail_path")))
示例#20
0
    def send(self, from_addr, recipients, message):
        global local_hostname
        # Ensure the message complies with RFC2822: use CRLF line endings
        message = fix_eol(message, CRLF)

        self.log.info("Sending notification through SMTP at %s:%d to %s",
                      self.smtp_server, self.smtp_port, recipients)
        try:
            server = smtplib.SMTP(self.smtp_server, self.smtp_port,
                                  local_hostname)
            local_hostname = server.local_hostname
        except smtplib.socket.error, e:
            raise ConfigurationError(
                tag_("SMTP server connection error (%(error)s). Please "
                     "modify %(option1)s or %(option2)s in your "
                     "configuration.",
                     error=to_unicode(e),
                     option1=tag.tt("[notification] smtp_server"),
                     option2=tag.tt("[notification] smtp_port")))
示例#21
0
文件: main.py 项目: wataash/trac
    def _get_valid_default_handler(self, req):
        # Use default_handler from the Session if it is a valid value.
        name = req.session.get('default_handler')
        handler = self._request_handlers.get(name)
        if handler and not is_valid_default_handler(handler):
            handler = None

        if not handler:
            # Use default_handler from project configuration.
            handler = self.default_handler
            if not is_valid_default_handler(handler):
                raise ConfigurationError(
                    tag_("%(handler)s is not a valid default handler. Please "
                         "update %(option)s through the %(page)s page or by "
                         "directly editing trac.ini.",
                         handler=tag.code(handler.__class__.__name__),
                         option=tag.code("[trac] default_handler"),
                         page=tag.a(_("Basic Settings"),
                                    href=req.href.admin('general/basics'))))
        return handler
示例#22
0
 def _get_relative_url(self, key, value):
     value = urlparse(value).path
     if not value:
         raise ConfigurationError(
             '[%(section)s] %(entry)s: expected relative url, '
             'got %(value)s', {
                 'section': self.section,
                 'entry': key,
                 'value': repr(value)
             })
     if value.strip('/') != value:
         conf.log.warning(
             '[%(section)s] %(entry)s: value %(value)s is invalid, '
             'it should not have leading or trailing slashes', {
                 'section': self.section,
                 'entry': key,
                 'value': repr(value)
             })
         value = value.strip('/')
     return value
示例#23
0
 def _raise_value_error(self, option, typestring, value):
     """Helper for Macro*Option classes to raise an appropriate
     value error when a malformed value is supplied for an option."""
     qual = option._qualified_name()
     if qual[0] == 'trac.ini':
         raise ConfigurationError(
             _('trac.ini [%(sec)s] %(opt)s = "%(val)s": invalid %(type)s',
               sec=self.section,
               opt=qual[1],
               type=typestring,
               val=repr(value)))
     if qual[0] == 'macroarg':
         raise ValueError(
             _('macro argument %(opt)s = "%(val)s": invalid %(type)s',
               opt=qual[1],
               type=typestring,
               val=repr(value)))
     if qual[0] == 'default':
         raise TracError(
             _('plugin default %(opt)s = "%(val)s": invalid %(type)s',
               opt=qual[1],
               type=typestring,
               val=repr(value)))
示例#24
0
    def render_ticket_action_control(self, req, ticket, action):

        self.log.debug('render_ticket_action_control: action "%s"', action)

        this_action = self.actions[action]
        status = this_action['newstate']
        operations = this_action['operations']
        ticket_owner = ticket._old.get('owner', ticket['owner'])
        ticket_status = ticket._old.get('status', ticket['status'])
        author = get_reporter_id(req, 'author')
        author_info = partial(Chrome(self.env).authorinfo, req,
                              resource=ticket.resource)
        format_author = partial(Chrome(self.env).format_author, req,
                                resource=ticket.resource)
        formatted_current_owner = author_info(ticket_owner)
        exists = ticket_status is not None

        ticket_system = TicketSystem(self.env)
        control = []  # default to nothing
        hints = []
        if 'reset_workflow' in operations:
            control.append(_("from invalid state"))
            hints.append(_("Current state no longer exists"))
        if 'del_owner' in operations:
            hints.append(_("The ticket will be disowned"))
        if 'set_owner' in operations or 'may_set_owner' in operations:
            owners = self.get_allowed_owners(req, ticket, this_action)

            if 'set_owner' in operations:
                default_owner = author
            elif 'may_set_owner' in operations:
                if not exists:
                    default_owner = ticket_system.default_owner
                else:
                    default_owner = ticket_owner or None
                if owners is not None and default_owner not in owners:
                    owners.insert(0, default_owner)
            else:
                # Protect against future modification for case that another
                # operation is added to the outer conditional
                raise AssertionError(operations)

            id = 'action_%s_reassign_owner' % action

            if not owners:
                owner = req.args.get(id, default_owner)
                control.append(
                    tag_("to %(owner)s",
                         owner=tag.input(type='text', id=id, name=id,
                                         value=owner)))
                if not exists or ticket_owner is None:
                    hints.append(_("The owner will be the specified user"))
                else:
                    hints.append(tag_("The owner will be changed from "
                                      "%(current_owner)s to the specified "
                                      "user",
                                      current_owner=formatted_current_owner))
            elif len(owners) == 1:
                owner = tag.input(type='hidden', id=id, name=id,
                                  value=owners[0])
                formatted_new_owner = author_info(owners[0])
                control.append(tag_("to %(owner)s",
                                    owner=tag(formatted_new_owner, owner)))
                if not exists or ticket_owner is None:
                    hints.append(tag_("The owner will be %(new_owner)s",
                                      new_owner=formatted_new_owner))
                elif ticket['owner'] != owners[0]:
                    hints.append(tag_("The owner will be changed from "
                                      "%(current_owner)s to %(new_owner)s",
                                      current_owner=formatted_current_owner,
                                      new_owner=formatted_new_owner))
            else:
                selected_owner = req.args.get(id, default_owner)
                control.append(tag_("to %(owner)s", owner=tag.select(
                    [tag.option(label, value=value if value is not None else '',
                                selected=(value == selected_owner or None))
                     for label, value in sorted((format_author(owner), owner)
                                                for owner in owners)],
                    id=id, name=id)))
                if not exists or ticket_owner is None:
                    hints.append(_("The owner will be the selected user"))
                else:
                    hints.append(tag_("The owner will be changed from "
                                      "%(current_owner)s to the selected user",
                                      current_owner=formatted_current_owner))
        elif 'set_owner_to_self' in operations:
            formatted_author = author_info(author)
            if not exists or ticket_owner is None:
                hints.append(tag_("The owner will be %(new_owner)s",
                                  new_owner=formatted_author))
            elif ticket_owner != author:
                hints.append(tag_("The owner will be changed from "
                                  "%(current_owner)s to %(new_owner)s",
                                  current_owner=formatted_current_owner,
                                  new_owner=formatted_author))
            elif ticket_status != status:
                hints.append(tag_("The owner will remain %(current_owner)s",
                                  current_owner=formatted_current_owner))
        if 'set_resolution' in operations:
            resolutions = [r.name for r in Resolution.select(self.env)]
            if 'set_resolution' in this_action:
                valid_resolutions = set(resolutions)
                resolutions = this_action['set_resolution']
                if any(x not in valid_resolutions for x in resolutions):
                    raise ConfigurationError(_(
                        "Your workflow attempts to set a resolution but uses "
                        "undefined resolutions (configuration issue, please "
                        "contact your Trac admin)."))
            if not resolutions:
                raise ConfigurationError(_(
                    "Your workflow attempts to set a resolution but none is "
                    "defined (configuration issue, please contact your Trac "
                    "admin)."))
            id = 'action_%s_resolve_resolution' % action
            if len(resolutions) == 1:
                resolution = tag.input(type='hidden', id=id, name=id,
                                       value=resolutions[0])
                control.append(tag_("as %(resolution)s",
                                    resolution=tag(resolutions[0],
                                                   resolution)))
                hints.append(tag_("The resolution will be set to %(name)s",
                                  name=resolutions[0]))
            else:
                selected_option = req.args.get(id,
                                               ticket_system.default_resolution)
                control.append(tag_("as %(resolution)s",
                                    resolution=tag.select(
                    [tag.option(x, value=x,
                                selected=(x == selected_option or None))
                     for x in resolutions],
                    id=id, name=id)))
                hints.append(_("The resolution will be set"))
        if 'del_resolution' in operations:
            hints.append(_("The resolution will be deleted"))
        if 'leave_status' in operations:
            control.append(tag_("as %(status)s", status=ticket_status))
            if len(operations) == 1:
                hints.append(tag_("The owner will remain %(current_owner)s",
                                  current_owner=formatted_current_owner)
                             if ticket_owner else
                             _("The ticket will remain with no owner"))
        elif not operations:
            if status != '*':
                if ticket['status'] is None:
                    hints.append(tag_("The status will be '%(name)s'",
                                      name=status))
                else:
                    hints.append(tag_("Next status will be '%(name)s'",
                                      name=status))
        return (this_action['label'], tag(separated(control, ' ')),
                tag(separated(hints, '. ', '.') if hints else ''))
示例#25
0
 def accessor(self, section, name, default):
     value = section.get(name, default)
     if value not in self.choices:
         raise ConfigurationError('expected a choice among "%s", got %s' % \
                                  (', '.join(self.choices), repr(value)))
     return value
示例#26
0
文件: api.py 项目: wataash/trac
def parse_connection_uri(db_str):
    """Parse the database connection string.

    The database connection string for an environment is specified through
    the `database` option in the `[trac]` section of trac.ini.

    :return: a tuple containing the scheme and a dictionary of attributes:
             `user`, `password`, `host`, `port`, `path`, `params`.
    :since: 1.1.3
    """
    if not db_str:
        section = tag.a("[trac]",
                        title=_("TracIni documentation"),
                        class_='trac-target-new',
                        href='https://trac.edgewall.org/wiki/TracIni'
                        '#trac-section')
        raise ConfigurationError(
            tag_(
                "Database connection string is empty. Set the %(option)s "
                "configuration option in the %(section)s section of "
                "trac.ini. Please refer to the %(doc)s for help.",
                option=tag.code("database"),
                section=section,
                doc=_doc_db_str()))

    try:
        scheme, rest = db_str.split(':', 1)
    except ValueError:
        raise _invalid_db_str(db_str)

    if not rest.startswith('/'):
        if scheme == 'sqlite' and rest:
            # Support for relative and in-memory SQLite connection strings
            host = None
            path = rest
        else:
            raise _invalid_db_str(db_str)
    else:
        if not rest.startswith('//'):
            host = None
            rest = rest[1:]
        elif rest.startswith('///'):
            host = None
            rest = rest[3:]
        else:
            rest = rest[2:]
            if '/' in rest:
                host, rest = rest.split('/', 1)
            else:
                host = rest
                rest = ''
        path = None

    if host and '@' in host:
        user, host = host.split('@', 1)
        if ':' in user:
            user, password = user.split(':', 1)
        else:
            password = None
        if user:
            user = urllib.unquote(user)
        if password:
            password = unicode_passwd(urllib.unquote(password))
    else:
        user = password = None

    if host and ':' in host:
        host, port = host.split(':', 1)
        try:
            port = int(port)
        except ValueError:
            raise _invalid_db_str(db_str)
    else:
        port = None

    if not path:
        path = '/' + rest
    if os.name == 'nt':
        # Support local paths containing drive letters on Win32
        if len(rest) > 1 and rest[1] == '|':
            path = "%s:%s" % (rest[0], rest[2:])

    params = {}
    if '?' in path:
        path, qs = path.split('?', 1)
        qs = qs.split('&')
        for param in qs:
            try:
                name, value = param.split('=', 1)
            except ValueError:
                raise _invalid_db_str(db_str)
            value = urllib.unquote(value)
            params[name] = value

    args = zip(('user', 'password', 'host', 'port', 'path', 'params'),
               (user, password, host, port, path, params))
    return scheme, {key: value for key, value in args if value}
示例#27
0
    def send(self, from_addr, recipients, message):
        # Ensure the message complies with RFC2822: use CRLF line endings
        message = fix_eol(message, CRLF)

        self.log.info("Sending notification through SMTP at %s:%d to %s",
                      self.smtp_server, self.smtp_port, recipients)
        try:
            server = smtplib.SMTP(self.smtp_server, self.smtp_port)
        except smtplib.socket.error as e:
            raise ConfigurationError(
                tag_(
                    "SMTP server connection error (%(error)s). Please "
                    "modify %(option1)s or %(option2)s in your "
                    "configuration.",
                    error=to_unicode(e),
                    option1=tag.code("[notification] smtp_server"),
                    option2=tag.code("[notification] smtp_port")))
        # server.set_debuglevel(True)
        if self.use_tls:
            server.ehlo()
            if 'starttls' not in server.esmtp_features:
                raise TracError(
                    _("TLS enabled but server does not support"
                      " TLS"))
            server.starttls()
            server.ehlo()
        if self.smtp_user:
            server.login(self.smtp_user.encode('utf-8'),
                         self.smtp_password.encode('utf-8'))
        start = time.time()
        resp = sendmail(server, from_addr, recipients, message)
        t = time.time() - start
        if t > 5:
            self.log.warning(
                "Slow mail submission (%.2f s), "
                "check your mail setup", t)
        if self.use_tls:
            # avoid false failure detection when the server closes
            # the SMTP connection with TLS enabled
            import socket
            try:
                server.quit()
            except socket.sslerror:
                pass
        else:
            server.quit()

        msg = email.message_from_string(message)
        ticket_id = int(msg['x-trac-ticket-id'])
        msgid = msg['message-id']
        aws_re = r'^email-smtp\.([a-z0-9-]+)\.amazonaws\.com$'
        m = re.match(aws_re, self.smtp_server)
        if m:
            parts = resp.split()
            if len(parts) == 2 and parts[0] == 'Ok':
                region = m.group(1)
                msgid = '<%s@%s.amazonses.com>' % (parts[1], region)
        with self.env.db_transaction as db:
            cursor = db.cursor()
            cursor.execute(
                """
                INSERT OR IGNORE INTO messageid (ticket,messageid)
                VALUES (%s, %s)
                """, (ticket_id, msgid))
示例#28
0
 def check_config(self):
     if not self.public_key or not self.private_key:
         raise ConfigurationError('public_key and private_key needs ' \
             'to be in the [recaptcha] section of your trac.ini file. ' \
             'Get these keys from http://recaptcha.net/')