Beispiel #1
0
    def __try_change_control__(self, session_id, moderator, info, flag):
        found = True

        try:
            control = group.Control(ord(flag))

            if info.control == control:
                self.broker.deliver(session_id, ltd.encode_str("e", "Group is already %s." % str(control)))
            else:
                info.control = control

                if control == group.Control.PUBLIC:
                    self.broker.to_channel(str(info), ltd.encode_status_msg("Change", "%s made group public." % moderator))
                else:
                    self.broker.to_channel(str(info), ltd.encode_status_msg("Change", "%s is now %s." % (str(info), str(control))))

                info.clear_talkers()

                if control == group.Control.MODERATED:
                    info.moderator = session_id

                    self.broker.to_channel(info.key, ltd.encode_status_msg("Pass", "%s is now mod." % moderator))

                if control == group.Control.RESTRICTED:
                    self.__make_restricted__(session_id, info)
                else:
                    info.clear_invitations()
        except ValueError:
            found = False

        return found
Beispiel #2
0
    def cancel(self, session_id, invitee, mode="n", quiet=None):
        quiet = bool(quiet)

        info = self.__get_group_if_can_moderate__(session_id)

        if not info.control == group.Control.RESTRICTED:
            raise LtdErrorException("The group isn't restricted.")

        try:
            if mode == "n":
                info.cancel_nick(invitee)

                loggedin_session = self.session.find_nick(invitee)

                if loggedin_session:
                    state = self.session.get(session_id)

                    self.broker.deliver(loggedin_session,
                                        ltd.encode_status_msg("FYI", "Invitation to group %s cancelled by %s." % (state.group, state.nick)))
            else:
                info.cancel_address(invitee)
        except KeyError:
            raise LtdErrorException("%s isn't invited." % invitee)

        if not quiet:
            self.broker.deliver(session_id, ltd.encode_status_msg("FYI", "%s cancelled." % invitee))

        self.groups.update(info)
Beispiel #3
0
    def pass_over(self, session_id, nick):
        info = self.__get_group_if_can_moderate__(session_id)

        loggedin_session = self.session.find_nick(nick)

        if not loggedin_session:
            raise LtdErrorException("%s is not signed on." % nick)

        if info.moderator == loggedin_session:
            raise LtdErrorException("You are already moderator.")

        loggedin_state = self.session.get(loggedin_session)

        if loggedin_state.nick.lower() == core.NICKSERV.lower():
            raise LtdErrorException("Cannot pass to %s." % core.NICKSERV)

        info.moderator = loggedin_session

        self.groups.update(info)

        state = self.session.get(session_id)

        self.broker.deliver(loggedin_session, ltd.encode_status_msg("Pass",
                                                                    "%s just passed moderation of group %s."
                                                                    % (state.nick, info.display_name)))

        if info.volume != group.Volume.QUIET:
            self.broker.to_channel(info.key, ltd.encode_status_msg("Pass",
                                                                   "%s has passed moderation to %s."
                                                                   % (state.nick, loggedin_state.nick)))
Beispiel #4
0
    def __notify__(self, session_id, signed_on):
        state = self.session.get(session_id)

        info = None

        if state.group:
            info = self.groups.get(state.group)

        status_name = "Notify-%s" % ("On" if signed_on else "Off")

        for k, v in self.session:
            if k != session_id and v.nick != core.NICKSERV and not v.notifylist.empty(
            ):
                hidden = not info or info.visibility == group.Visibility.INVISIBLE
                same_group = v.group and v.group.lower() == info.key

                if not hidden or same_group:
                    if v.notifylist.nick_watched(
                            state.nick) and not same_group:
                        self.broker.deliver(
                            k, ltd.encode_status_msg(status_name, state.nick))

                    if v.notifylist.site_watched(
                            state.address) and not same_group:
                        self.broker.deliver(
                            k, ltd.encode_status_msg(status_name,
                                                     state.address))
Beispiel #5
0
    def list(self, session_id):
        state = self.session.get(session_id)

        empty = True

        for nick in state.hushlist.nicks:
            empty = False

            if nick.private:
                self.broker.deliver(session_id, ltd.encode_status_msg("Personal-Nick-Hushed", nick.display_name))

            if nick.public:
                self.broker.deliver(session_id, ltd.encode_status_msg("Open-Nick-Hushed", nick.display_name))

        for site in state.hushlist.sites:
            empty = False

            if site.private:
                self.broker.deliver(session_id, ltd.encode_status_msg("Personal-Site-Hushed", site.display_name))

            if site.public:
                self.broker.deliver(session_id, ltd.encode_status_msg("Open-Site-Hushed", site.display_name))

        if empty:
            self.broker.deliver(session_id, ltd.encode_status_msg("Hush-List", "Empty List."))
Beispiel #6
0
    def __login_no_password__(self, session_id, loginid, nick):
        self.log.debug("No password given, skipping authentication.")

        loggedin_session = self.session.find_nick(nick)

        if loggedin_session:
            self.log.debug("%s already logged in, aborting login.", nick)

            raise LtdStatusException("Register", "Nick already in use.")

        with self.nickdb_connection.enter_scope() as scope:
            if self.nickdb.exists(scope, nick):
                if self.nickdb.is_admin(scope, nick):
                    raise LtdErrorException(
                        "You need a password to login as administrator.")

                self.broker.deliver(
                    session_id,
                    ltd.encode_status_msg(
                        "Register",
                        "Send password to authenticate your nickname."))
            else:
                self.broker.deliver(
                    session_id,
                    ltd.encode_status_msg(
                        "No-Pass", "Your nickname does not have a password."))

                self.broker.deliver(
                    session_id,
                    ltd.encode_status_msg("No-Pass",
                                          "For help type /m server ?"))

        self.session.update(session_id, loginid=loginid, nick=nick)
Beispiel #7
0
    def __make_restricted__(self, session_id, info):
        for sub_id in self.broker.get_subscribers(str(info)):
            sub_state = self.session.get(sub_id)

            try:
                info.invite_nick(sub_state.nick, sub_state.authenticated)

                self.broker.deliver(session_id, ltd.encode_status_msg("FYI", "%s invited." % sub_state.nick))
                self.broker.deliver(sub_id, ltd.encode_status_msg("FYI", "You are invited to group %s by default." % sub_state.group))
            except OverflowError:
                self.broker.deliver(session_id, ltd.encode_str("e", "Invitation list is full."))
    def notify_messagebox(self, session_id):
        with self.nickdb_connection.enter_scope() as scope:
            state = self.session.get(session_id)

            if self.nickdb.exists(scope, state.nick):
                count = self.nickdb.count_messages(scope, state.nick)
                limit = self.nickdb.get_mbox_limit(scope, state.nick)

                if count > 0:
                    self.broker.deliver(session_id,
                                        ltd.encode_status_msg("Message", "You have %d message%s." % (count, "" if count == 1 else "s")))

                if count >= limit:
                    self.broker.deliver(session_id, ltd.encode_status_msg("Message", "User mailbox is full."))
Beispiel #9
0
    def change_password(self, session_id, nick, password):
        state = self.session.get(session_id)

        if state.nick.lower() == nick.lower():
            if not state.authenticated:
                raise LtdErrorException("You must be registered to change your password.")
        else:
            self.__test_admin__(session_id)

        self.log.debug("Changing password of user %s." % nick)

        with self.nickdb_connection.enter_scope() as scope:
            if not self.nickdb.exists(scope, nick):
                raise LtdErrorException("%s not found." % nick)

            self.log.debug("Nick found, changing password.")

            if not validate.is_valid_password(password):
                raise LtdStatusException("Password",
                                         "Password format not valid. Password length must be between %d and %d characters."
                                         % (validate.PASSWORD_MIN, validate.PASSWORD_MAX))

            self.nickdb.set_password(scope, nick, password)

            self.broker.deliver(session_id, ltd.encode_status_msg("Pass", "Password changed."))

            scope.complete()
Beispiel #10
0
    def __deny_login__(self, session_id, argv):
        usage = "Usage: ipfilter deny {filter} {seconds}"

        if not argv or len(argv) > 2:
            raise LtdErrorException(usage)

        filter = None

        try:
            filter = ipfilter.Factory.create(argv[0])
        except:
            raise LtdErrorException("Filter is malformed.")

        ttl = -1

        try:
            if len(argv) == 2:
                ttl = int(argv[1])

                if ttl < 0:
                    raise ValueError
        except:
            raise LtdErrorException(usage)

        with self.__ipfilter_connection.enter_scope() as scope:
            self.__ipfilters.deny(scope, filter, ttl)

            lifetime = "forever"

            if ttl > -1:
                lifetime = dateutils.elapsed_time(ttl)

            self.broker.deliver(session_id, ltd.encode_status_msg("IP-Filter", "%s denied (%s)." % (argv[0], lifetime)))

            scope.complete()
Beispiel #11
0
    def boot(self, session_id, nick):
        info = self.__get_group_if_can_moderate__(session_id)

        loggedin_session = self.session.find_nick(nick)

        if loggedin_session == session_id:
            raise LtdErrorException("You cannot boot yourself.")

        if not loggedin_session:
            raise LtdErrorException("%s is not signed on." % nick)

        state = self.session.get(session_id)
        loggedin_state = self.session.get(loggedin_session)

        if loggedin_state.group.lower() != state.group.lower():
            raise LtdErrorException("%s is not in your group." % nick)

        if loggedin_state.authenticated:
            with self.nickdb_connection.enter_scope() as scope:
                if self.nickdb.is_admin(scope, state.nick):
                    self.broker.deliver(loggedin_session, ltd.encode_status_msg("Boot", "%s tried to boot you." % state.nick))

                    self.reputation.fatal(session_id)

                    raise LtdErrorException("You cannot boot an admin.")

        try:
            info.cancel_nick(loggedin_state.nick)

            self.broker.deliver(session_id, ltd.encode_status_msg("FYI", "%s cancelled." % nick))
        except KeyError: pass

        try:
            info.mute_nick(loggedin_state.nick)

            self.broker.deliver(session_id, ltd.encode_status_msg("FYI", "%s removed from talker list." % nick))
        except KeyError: pass

        self.broker.to_channel(info.key, ltd.encode_status_msg("Boot", "%s was booted." % nick))
        self.broker.deliver(loggedin_session, ltd.encode_status_msg("Boot", "%s booted you." % state.nick))

        ACTION(actions.usersession.UserSession).join(loggedin_session, core.BOOT_GROUP)

        with self.statsdb_connection.enter_scope() as scope:
            self.statsdb.add_boot(scope)

            scope.complete()
Beispiel #12
0
    def drop_moderator(self, session_id, category, message):
        for info in self.groups.get_groups():
            if info.moderator == session_id:
                if info.volume != group.Volume.QUIET:
                    self.broker.to_channel_from(
                        session_id, info.key,
                        ltd.encode_status_msg(category, message))

                new_mod = None
                min_elapsed = -1

                for sub_id in self.broker.get_subscribers(info.key):
                    sub_state = self.session.get(sub_id)
                    elapsed = sub_state.t_recv.elapsed()

                    self.log.debug(
                        "Found subscriber: %s, elapsed milliseconds: %f",
                        sub_state.nick, elapsed)

                    if not sub_state.away and (min_elapsed == -1
                                               or elapsed < min_elapsed):
                        min_elapsed = elapsed
                        new_mod = [sub_id, sub_state.nick]

                if new_mod:
                    self.log.debug("New mod: %s", new_mod[1])

                    self.broker.to_channel(
                        info.key,
                        ltd.encode_status_msg("Pass",
                                              "%s is now mod." % new_mod[1]))

                    info.moderator = new_mod[0]
                else:
                    self.log.debug("No new moderator found.")

                    self.broker.to_channel(
                        str(info),
                        ltd.encode_status_msg("Change",
                                              "Group is now public."))

                    info.control = group.Control.PUBLIC
                    info.moderator = None
                    info.clear_talkers()
                    info.clear_invitations()

                self.groups.update(info)
Beispiel #13
0
    def drop(self, session_id, nicks):
        state = self.session.get(session_id)

        with self.statsdb_connection.enter_scope() as scope:
            for nick in nicks:
                victim_id = self.session.find_nick(nick)

                if victim_id:
                    self.broker.deliver(session_id, ltd.encode_status_msg("Drop", "You have dropped %s." % nick))
                    self.broker.deliver(victim_id, ltd.encode_status_msg("Drop", "You have been disconnected by %s." % state.nick))
                    self.broker.deliver(victim_id, ltd.encode_empty_cmd("g"))

                    self.statsdb.add_drop(scope)
                else:
                    self.broker.deliver(session_id, ltd.encode_str("e", "%s not found." % nick))

                scope.complete()
Beispiel #14
0
    def invite(self, session_id, invitee, mode="n", quiet=None, registered=None):
        quiet = bool(quiet)
        registered = bool(registered)

        info = self.__get_group_if_can_moderate__(session_id)

        if not info.control == group.Control.RESTRICTED:
            raise LtdErrorException("The group isn't restricted.")

        state = self.session.get(session_id)
        loggedin_session = None

        try:
            if mode == "n":
                if registered:
                    with self.nickdb_connection.enter_scope() as scope:
                        if not self.nickdb.exists(scope, invitee):
                            raise LtdErrorException("User not found.")

                loggedin_session = self.session.find_nick(invitee)

                if not registered and not loggedin_session:
                    raise LtdErrorException("%s is not signed on." % invitee)

                info.invite_nick(invitee, registered)

                if loggedin_session:
                    loggedin_state = self.session.get(loggedin_session)

                    if registered and not loggedin_state.authenticated:
                        self.broker.deliver(loggedin_session,
                                            ltd.encode_status_msg("RSVP", "You need to be registered to enter group %s." % str(info)))
                    else:
                        self.broker.deliver(loggedin_session,
                                            ltd.encode_status_msg("RSVP", "You are invited to group %s by %s." % (str(info), state.nick)))
            else:
                info.invite_address(invitee, registered)
        except OverflowError:
            raise LtdErrorException("Invitation list is full.")

        if not quiet:
            self.broker.deliver(session_id,
                                ltd.encode_status_msg("FYI", "%s invited%s." % (invitee, " (registered only)" if registered else "")))

        self.groups.update(info)
Beispiel #15
0
    def noaway(self, session_id):
        state = self.session.get(session_id)

        if not state.away:
            raise LtdStatusException("Away", "No away message set.")

        self.session.update(session_id, away=None, t_away=None)

        self.broker.deliver(
            session_id, ltd.encode_status_msg("Away", "Away message unset."))
Beispiel #16
0
    def relinquish(self, session_id):
        info = self.__get_group_if_can_moderate__(session_id)

        info.moderator = None

        state = self.session.get(session_id)

        if info.volume != group.Volume.QUIET:
            self.broker.to_channel(info.key, ltd.encode_status_msg("Change", "%s just relinquished moderation." % state.nick))

        if info.control != group.Control.PUBLIC:
            info.control = group.Control.PUBLIC
            info.clear_talkers()
            info.clear_invitations()

            if info.volume != group.Volume.QUIET:
                self.broker.to_channel(info.key, ltd.encode_status_msg("Change", "Group is now public."))

        self.groups.update(info)
Beispiel #17
0
    def __flush_ip_filters__(self, session_id, argv):
        if argv:
            raise LtdErrorException("Usage: ipfilter flush")

        with self.__ipfilter_connection.enter_scope() as scope:
            self.__ipfilters.flush(scope)

            scope.complete()

        self.broker.deliver(session_id, ltd.encode_status_msg("IP-Filter", "Flushed."))
Beispiel #18
0
    def __change_idle_mod__(self, moderator, info, minutes):
        old_val = info.idle_mod
        info.idle_mod = minutes

        self.broker.to_channel(info.key, ltd.encode_status_msg("Change", "%s changed idle-mod to %s." % (moderator, info.idle_mod_str)))

        if old_val > minutes and minutes > 0 and info.moderator:
            mod_state = self.session.get(info.moderator)

            if mod_state.t_recv.elapsed() > (minutes * 60):
                ACTION(actions.usersession.UserSession).idle_mod(info.moderator)
Beispiel #19
0
    def list(self, session_id):
        state = self.session.get(session_id)

        empty = True

        for nick in state.notifylist.nicks:
            empty = False

            self.broker.deliver(session_id,
                                ltd.encode_status_msg("Notify-Nickname", nick))

        for site in state.notifylist.sites:
            empty = False

            self.broker.deliver(session_id,
                                ltd.encode_status_msg("Notify-Site", site))

        if empty:
            self.broker.deliver(
                session_id, ltd.encode_status_msg("Notify-List",
                                                  "Empty List."))
Beispiel #20
0
    def __show_ip_filters__(self, session_id, argv):
        if argv:
            raise LtdErrorException("Usage: ipfilter show")

        filters = []

        with self.__ipfilter_connection.enter_scope() as scope:
            for f, l in self.__ipfilters.load_deny_filters(scope):
                lifetime = "forever"

                if l > -1:
                    time_left = max(1, l - dateutils.timestamp())
                    lifetime = dateutils.elapsed_time(time_left)

                filters.append((f.expression, lifetime))

        if filters:
            for entry in sorted(filters, key=lambda e: "@".join(reversed(e[0].split("@", 1))).lower()):
                self.broker.deliver(session_id, ltd.encode_status_msg("IP-Filter", "%s denied (%s)" % entry))
        else:
            self.broker.deliver(session_id, ltd.encode_status_msg("IP-Filter", "List is empty."))
Beispiel #21
0
    def idle_boot(self, session_id):
        self.broker.deliver(
            session_id, ltd.encode_status_msg("Idle-Boot", "You were booted."))

        self.join(session_id, core.BOOT_GROUP)
        self.drop_moderator(session_id, "Idle-Boot",
                            "Your group moderator idled away.")

        with self.statsdb_connection.enter_scope() as scope:
            self.statsdb.add_idleboot(scope)

            scope.complete()
Beispiel #22
0
    def beep(self, session_id, receiver):
        loggedin_session = self.session.find_nick(receiver)

        if not loggedin_session:
            raise LtdErrorException("%s is not signed on." % receiver)

        loggedin_state = self.session.get(loggedin_session)

        state = self.session.get(session_id)

        if state.echo == session.EchoMode.VERBOSE:
            self.broker.deliver(
                session_id,
                ltd.encode_co_output("<*to: %s*> [=Beep=]" % receiver))

        if loggedin_state.beep != session.BeepMode.ON:
            if loggedin_state.beep == session.BeepMode.VERBOSE:
                self.broker.deliver(
                    loggedin_session,
                    ltd.encode_status_msg(
                        "No-Beep",
                        "%s attempted (and failed) to beep you." % state.nick))

            raise LtdStatusException("Beep", "User has nobeep enabled.")

        self.broker.deliver(loggedin_session, ltd.encode_str("k", state.nick))

        if loggedin_state.away:
            if not self.away_table.is_alive(session_id, receiver):
                self.broker.deliver(
                    session_id,
                    ltd.encode_status_msg(
                        "Away", "%s (since %s)." %
                        (loggedin_state.away,
                         loggedin_state.t_away.elapsed_str())))

                self.away_table.set_alive(session_id, receiver,
                                          self.config.timeouts_away_message)
Beispiel #23
0
    def away(self, session_id, text):
        state = self.session.get(session_id)

        if text:
            if len(text) > 64:
                text = "%s..." % text[:61]

            self.session.update(session_id, away=text, t_away=Timer())

            self.broker.deliver(
                session_id,
                ltd.encode_status_msg("Away",
                                      "Away message set to \"%s\"." % text))
        elif state.away:
            self.broker.deliver(
                session_id,
                ltd.encode_status_msg(
                    "Away", "Away message is set to \"%s\" (since %s)." %
                    (state.away, state.t_away.elapsed_str())))
        else:
            self.broker.deliver(
                session_id,
                ltd.encode_status_msg("Away", "Away message is not set."))
Beispiel #24
0
    def set_topic(self, session_id, topic):
        info = self.__get_group_if_can_moderate__(session_id, allow_public=True)

        if not validate.is_valid_topic(topic):
            raise LtdErrorException("Topic must consist of at least %d and at most %d characters."
                                    % (validate.TOPIC_MIN, validate.TOPIC_MAX))

        info.topic = topic

        self.groups.update(info)

        if info.volume != group.Volume.QUIET:
            self.broker.to_channel(str(info), ltd.encode_status_msg("Topic",
                                                                    "%s changed the topic to \"%s\"" % (self.session.get(session_id).nick,
                                                                                                        topic)))
Beispiel #25
0
    def set_mode(self, session_id, mode):
        if not mode in ["on", "off", "verbose"]:
            raise LtdErrorException("Usage: /nobeep on|off|verbose")

        real_mode = session.BeepMode.ON

        if mode == "on":
            real_mode = session.BeepMode.OFF
        elif mode == "verbose":
            real_mode = session.BeepMode.VERBOSE

        self.session.update(session_id, beep=real_mode)

        self.broker.deliver(
            session_id,
            ltd.encode_status_msg("No-Beep", "No-Beep is now %s." % mode))
Beispiel #26
0
    def set_mode(self, session_id, mode):
        if not mode in ["on", "off", "verbose"]:
            raise LtdErrorException("Usage: /echoback on|off|verbose")

        real_mode = session.EchoMode.OFF

        if mode == "on":
            real_mode = session.EchoMode.ON
        elif mode == "verbose":
            real_mode = session.EchoMode.VERBOSE

        self.session.update(session_id, echo=real_mode)

        self.broker.deliver(
            session_id,
            ltd.encode_status_msg("Echo", "Echoback is now %s." % mode))
Beispiel #27
0
    def __try_change_visibility__(self, session_id, nick, info, flag):
        found = True

        try:
            visibility = group.Visibility(ord(flag))

            if info.visibility == visibility:
                self.broker.deliver(session_id, ltd.encode_str("e", "Group is already %s." % str(visibility)))
            else:
                info.visibility = visibility

                self.broker.to_channel(str(info), ltd.encode_status_msg("Change", "%s made group %s." % (nick, str(visibility))))
        except ValueError:
            found = False

        return found
    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()
    def change_password(self, session_id, old_pwd, new_pwd):
        self.log.debug("Changing user password.")

        state = self.session.get(session_id)

        is_reset_code = False

        with self.password_reset_connection.enter_scope() as scope:
            is_reset_code = self.password_reset.has_pending_request(scope, state.nick, old_pwd, self.config.timeouts_password_reset_code)

        with self.nickdb_connection.enter_scope() as scope:
            if not self.nickdb.exists(scope, state.nick):
                raise LtdErrorException("Authorization failure.")

            if not is_reset_code:
                self.log.debug("Validating password.")

                if not state.authenticated:
                    self.reputation.critical(session_id)

                    raise LtdErrorException("You must be registered to change your password.")

                if not self.nickdb.check_password(scope, state.nick, old_pwd):
                    self.reputation.fatal(session_id)

                    raise LtdErrorException("Authorization failure.")
            else:
                self.log.debug("Password reset code found: %s", old_pwd)

            if not validate.is_valid_password(new_pwd):
                raise LtdStatusException("Pass",
                                         "Password format not valid. Password length must be between %d and %d characters."
                                         % (validate.PASSWORD_MIN, validate.PASSWORD_MAX))

            self.nickdb.set_password(scope, state.nick, new_pwd)

            self.broker.deliver(session_id, ltd.encode_status_msg("Pass", "Password changed."))

            scope.complete()

        if is_reset_code:
            with self.password_reset_connection.enter_scope() as scope:
                self.password_reset.delete_requests(scope, state.nick)

                scope.complete()
Beispiel #30
0
    def __change_idle_boot__(self, moderator, info, minutes):
        old_val = info.idle_boot
        info.idle_boot = minutes

        self.broker.to_channel(info.key, ltd.encode_status_msg("Change", "%s changed idle-boot to %s." % (moderator, info.idle_boot_str)))

        if old_val > minutes and minutes > 0:
            boot_ids = []

            for sub_id in self.broker.get_subscribers(str(info)):
                sub_state = self.session.get(sub_id)

                if (not info.moderator or sub_id != info.moderator):
                    if sub_state.t_recv.elapsed() > (info.idle_boot * 60):
                        boot_ids.append(sub_id)

            for sub_id in boot_ids:
                ACTION(actions.usersession.UserSession).idle_boot(sub_id)