Пример #1
0
class State:
    loginid: str = None
    ip: str = None
    host: str = None
    tls: bool = False
    nick: str = None
    group: str = None
    authenticated: bool = False
    signon: datetime = dateutils.now()
    t_recv: Timer = None
    t_alive: Timer = None
    t_ping: Timer = None
    beep: BeepMode = BeepMode.ON
    echo: EchoMode = EchoMode.OFF
    away: str = None
    t_away: Timer = None
    hushlist: Hushlist = None
    notifylist: Notifylist = None

    def __init__(self, **kwargs):
        for k, v in kwargs.items():
            setattr(self, k, v)

    @property
    def loggedin(self):
        return self.nick and self.group

    @property
    def address(self):
        return "%s@%s" % (self.loginid, self.host)
Пример #2
0
    def __get_today__(self, scope):
        now = dateutils.now()

        if not self.__date or (self.__date.year != now.year
                               or self.__date.month != now.month
                               or self.__date.day != now.day):
            self.__date = now
            self.__stats = None

        if not self.__stats:
            cur = scope.get_handle()

            cur.execute(
                "select * from Stats where Year=? and Month=? and Day=?",
                (self.__date.year, self.__date.month, self.__date.day))

            row = cur.fetchone()

            if row:
                self.__stats = self.__create_stats__(row)
            else:
                cur.execute(
                    "insert into Stats (Year, Month, Day) values (?, ?, ?) ",
                    (self.__date.year, self.__date.month, self.__date.day))

                self.__stats = statsdb.Stats()

        return self.__stats
Пример #3
0
    def set_signoff(self, scope, nick, timestamp=None):
        cur = scope.get_handle()

        if not timestamp:
            timestamp = dateutils.now()

        cur.execute("update Nick set Signoff=? where Name=?",
                    (int(timestamp.timestamp()), nick))
Пример #4
0
    def year(self, scope):
        now = dateutils.now()

        cur = scope.get_handle()

        cur.execute(self.__build_accumulate_query__("where Year=%d" %
                                                    now.year))

        return self.__create_stats__(cur.fetchone())
Пример #5
0
    def mark_registered(self, session_id):
        with self.nickdb_connection.enter_scope() as scope:
            state = self.session.get(session_id)

            self.nickdb.set_lastlogin(scope, state.nick, state.loginid, state.host)

            now = dateutils.now()

            self.nickdb.set_signon(scope, state.nick, now)

            self.session.update(session_id, signon=now, authenticated=True)

            self.broker.deliver(session_id, ltd.encode_status_msg("Register", "Nick registered."))

            self.reputation.good(session_id)

            scope.complete()
Пример #6
0
async def run_services(opts):
    data_dir = opts.get("data_dir")

    mapping = config.json.load(opts["config"])
    preferences = config.from_mapping(mapping)

    logger = log.new_logger("icbd", preferences.logging_verbosity)

    registry = log.Registry()

    registry.register(logger)

    logger.info("Starting server process with pid %d.", os.getpid())

    container = di.default_container

    connection = sqlite.Connection(preferences.database_filename)

    ipfilter_storage = ipfilter.sqlite.Storage()
    ipfilter_cached = ipfilter.cache.Storage(ipfilter_storage)

    container.register(logging.Logger, logger)
    container.register(log.Registry, registry)
    container.register(config.Config, preferences)
    container.register(ipc.Broadcast, ipc.Broadcast())
    container.register(shutdown.Shutdown, shutdown.Shutdown())
    container.register(ipfilter.Connection, connection)
    container.register(ipfilter.Storage, ipfilter_cached)
    container.register(broker.Broker, broker.memory.Broker())
    container.register(session.Store, session.memory.Store())
    container.register(session.AwayTimeoutTable, timer.TimeoutTable())
    container.register(session.NotificationTimeoutTable, timer.TimeoutTable())
    container.register(reputation.Reputation, reputation.memory.Reputation())
    container.register(group.Store, group.memory.Store())
    container.register(nickdb.Connection, connection)
    container.register(nickdb.NickDb, nickdb.sqlite.NickDb())
    container.register(statsdb.Connection, connection)
    container.register(statsdb.StatsDb, statsdb.sqlite.StatsDb())
    container.register(confirmation.Connection, connection)
    container.register(confirmation.Confirmation,
                       confirmation.sqlite.Confirmation())
    container.register(passwordreset.Connection, connection)
    container.register(passwordreset.PasswordReset,
                       passwordreset.sqlite.PasswordReset())
    container.register(motd.Motd,
                       motd.plaintext.Motd(os.path.join(data_dir, "motd")))
    container.register(manual.Manual,
                       manual.plaintext.Manual(os.path.join(data_dir, "help")))
    container.register(news.News,
                       news.plaintext.News(os.path.join(data_dir, "news")))
    container.register(
        template.Template,
        template.plaintext.Template(os.path.join(data_dir, "templates")))
    container.register(mail.Connection, connection)
    container.register(mail.Sink, mail.sqlite.Sink())
    container.register(avatar.Connection, connection)
    container.register(avatar.Reader, avatar.sqlite.Reader())
    container.register(
        avatar.Writer,
        avatar.sqlite.Writer(preferences.avatar_reload_timeout,
                             preferences.avatar_retry_timeout,
                             preferences.avatar_max_errors,
                             preferences.avatar_error_timeout))
    if avatar.is_available():
        container.register(
            avatar.Storage,
            avatar.fs.AsciiFiles(preferences.avatar_directory,
                                 preferences.avatar_ascii_width,
                                 preferences.avatar_ascii_height))
    else:
        logger.info("Avatar preview not available.")

        container.register(avatar.Storage, avatar.void.Storage())

    with connection.enter_scope() as scope:
        container.resolve(ipfilter.Storage).setup(scope)
        container.resolve(nickdb.NickDb).setup(scope)
        container.resolve(statsdb.StatsDb).setup(scope)
        container.resolve(confirmation.Confirmation).setup(scope)
        container.resolve(mail.Sink).setup(scope)
        container.resolve(avatar.Reader).setup(scope)
        container.resolve(avatar.Writer).setup(scope)
        container.resolve(passwordreset.PasswordReset).setup(scope)

        scope.complete()

    container.resolve(avatar.Storage).setup()

    bus = ipc.Bus()

    await bus.start()

    if os.name == "posix":
        loop = asyncio.get_event_loop()

        loop.add_signal_handler(signal.SIGINT, lambda: server.close())
        loop.add_signal_handler(signal.SIGTERM, lambda: server.close())

    processes = [MailProcess()]

    if avatar.is_available():
        processes.append(AvatarProcess())

    asyncio.gather(*[p.spawn(opts) for p in processes])

    failed = False

    try:
        server = network.Server()

        await server.run()
    except asyncio.CancelledError:
        pass
    except:
        logger.warning(traceback.format_exc())

        failed = True

    await bus.close()

    for p in processes:
        p.exit()

    logger.info("Server stopped.")

    with container.resolve(nickdb.Connection).enter_scope() as scope:
        container.resolve(nickdb.NickDb).set_signoff(scope, core.NICKSERV,
                                                     dateutils.now())

        scope.complete()

    sys.exit(server.exit_code if not failed else core.EXIT_FAILURE)
Пример #7
0
def message_admins(*args, **kwargs):
    """ Asynchronously send messages to all administrators.

    :param preference: if set, the corresponding preference of each admin
        user is checked to see if he/she wants to receive the message or not.
    :type preference: str, unicode or None (default)

    :param timestamping: if ``True``, a timestamp is prepended to the message.
        The timestamp will be translated in the user langage and timezone.
    :type timestamping: bool (default: ``True``)

    """

    timestamping = kwargs.pop('timestamping', True)
    preference = kwargs.pop('preference', None)

    admins = User.objects.filter(is_active=True).filter(
        Q(is_superuser=True) | Q(is_staff=True)).filter(
        preferences__staff__super_powers_enabled=True)

    if preference is not None:
        query_kwargs = {'preference__staff__{}'.format(preference): True}
        admins.filter(**query_kwargs)

    if timestamping:
        args = list(args)

        # This is an UTC datetime.
        dtnow = now()

        initial_lang = translation.get_language()
        prev_lang = initial_lang

        for admin in admins:
            uargs = args[:]

            # default datetime is UTC.
            udtnow = dtnow

            try:
                if admin.account.timezone:
                    udtnow = dtnow.astimezone(pytz.timezone(
                                              admin.account.timezone))

                if admin.account.language:
                    if prev_lang != admin.account.language:
                        translation.activate(admin.account.language)
                        prev_lang = admin.account.language

                    uargs[0] = _(u'{}: {}').format(
                        formats.date_format(udtnow, 'SHORT_DATETIME_FORMAT'),
                        uargs[0])

            except ObjectDoesNotExist:
                # Mostly "user has no account"
                LOGGER.warning('Admin %s has no account ?', admin)

            message_user(admin, *uargs, **kwargs)

        if initial_lang is not None:
            translation.activate(initial_lang)

    else:
        message_users(admins, *args, **kwargs)
Пример #8
0
    def login(self,
              session_id,
              loginid,
              nick,
              password,
              group_name,
              status="",
              remote_address=""):
        self.log.debug("User login: loginid=%s, nick=%s, password=%s", loginid,
                       nick, hide_chars(password))

        if not validate.is_valid_loginid(loginid):
            raise LtdErrorException(
                "loginid must consist of at least %d and at most %d alphabetic characters."
                % (validate.LOGINID_MIN, validate.LOGINID_MAX))

        if not validate.is_valid_nick(nick):
            raise LtdErrorException(
                "Nickname must consist of at least %d and at most %d alphanumeric characters."
                % (validate.NICK_MIN, validate.NICK_MAX))

        self.__resolve_bridged_user__(session_id, loginid, remote_address)

        self.broker.deliver(session_id, ltd.encode_empty_cmd("a"))

        if nick == core.NICKSERV:
            raise LtdStatusException("Register", "Nick already in use.")

        ACTION(Motd).receive(session_id)

        registered = self.config.server_unsecure_login and self.__try_login_unsecure__(
            session_id, loginid, nick)

        if not registered:
            if not password:
                self.__login_no_password__(session_id, loginid, nick)
            else:
                registered = self.__login_password__(session_id, loginid, nick,
                                                     password)

        self.session.update(session_id, signon=dateutils.now())

        registration = ACTION(Registration)

        if registered:
            registration.mark_registered(session_id)

        self.__test_connection_limit__(session_id)
        self.__test_ip__(session_id)

        registration.notify_messagebox(session_id)

        if not group_name:
            group_name = core.DEFAULT_GROUP

        self.join(session_id, group_name, status)

        ACTION(Notify).notify_signon(session_id)

        s = self.resolve(shutdown.Shutdown)
        request = s.pending_request

        if request != shutdown.PendingRequest.NONE:
            msg = "Server is %s in %s." % (
                "restarting" if request == shutdown.PendingRequest.RESTART else
                "shutting down", s.time_left_str)

            self.broker.deliver(session_id,
                                ltd.encode_status_msg("Shutdown", msg))

        with self.statsdb_connection.enter_scope() as scope:
            self.statsdb.add_signon(scope)
            self.statsdb.set_max_logins(scope, self.session.count_logins())

            scope.complete()
Пример #9
0
    def rename(self, session_id, nick):
        if not validate.is_valid_nick(nick):
            raise LtdErrorException("Nickname is invalid.")

        state = self.session.get(session_id)

        old_nick = state.nick
        was_authenticated = False

        if old_nick:
            self.log.debug("Renaming %s to %s.", old_nick, nick)

            was_authenticated = state.authenticated

            if self.session.find_nick(nick):
                self.reputation.warning(session_id)

                raise LtdErrorException("Nick already in use.")

            if state.group:
                self.log.debug("Renaming %s to %s in channel %s.", old_nick,
                               nick, state.group)

                self.broker.to_channel(
                    state.group,
                    ltd.encode_status_msg(
                        "Name",
                        "%s changed nickname to %s." % (old_nick, nick)))

                if self.groups.get(state.group).moderator == session_id:
                    self.broker.to_channel(
                        state.group,
                        ltd.encode_status_msg("Pass", "%s is now mod." % nick))

            self.session.update(session_id, nick=nick, authenticated=False)

            registered = False
            is_admin = False

            with self.nickdb_connection.enter_scope() as scope:
                if was_authenticated and self.nickdb.exists(scope, old_nick):
                    self.nickdb.set_signoff(scope, old_nick)

                if self.nickdb.exists(scope, nick):
                    is_admin = self.nickdb.is_admin(scope, nick)

                    if self.nickdb.is_secure(scope, nick):
                        self.broker.deliver(
                            session_id,
                            ltd.encode_status_msg(
                                "Register",
                                "Send password to authenticate your nickname.")
                        )
                    else:
                        self.log.debug(
                            "Nick not secure, trying to register automatically."
                        )

                        lastlogin = self.nickdb.get_lastlogin(scope, nick)

                        if lastlogin:
                            self.log.debug("Last login: %s@%s", lastlogin[0],
                                           lastlogin[1])

                            registered = (lastlogin[0] == state.loginid
                                          and lastlogin[1] == state.host)
                else:
                    self.broker.deliver(
                        session_id,
                        ltd.encode_status_msg(
                            "No-Pass",
                            "To register your nickname type /m server p password."
                        ))

            registration = ACTION(Registration)

            if registered:
                registration.mark_registered(session_id)
            elif is_admin:
                self.broker.deliver(
                    session_id,
                    ltd.encode_str(
                        "e",
                        "Registration failed, administrative account requires a password."
                    ))

                self.reputation.fatal(session_id)

                self.__auto_rename__(session_id)
            else:
                registration.notify_messagebox(session_id)
                self.session.update(session_id, signon=dateutils.now())