예제 #1
0
def send_message(kind, server, user, target, message):
    message = colon(message)

    if target[0] == '#':
        chan = server.find_chan(target)
        if not chan:
            server.send_reply(user, 'ERR_NOSUCHCHANNEL', target)
            return

        # it's actually ok to send a message across connections if both
        # are authenticated and with the same nick
        user_data = server.chan_nick(chan, user['nick'])
        if not user_data:
            server.send_reply(user, 'ERR_NOTONCHANNEL', target)
            return

        if 'm' in chan['modes']:
            modes = user_data['modes']
            can_talk = is_op(user_data) or 'v' in modes
            if not can_talk:
                server.send_reply(user, 'ERR_CANNOTSENDTOCHAN', chan['name'])
                return

        server.send_chan(user, kind, chan, message, others_only=True)
    else:
        tags = server.find_nick(target)
        if not tags:
            server.send_reply(user, 'ERR_NOSUCHNICK', target)
            return

        server.send_command(tags, user, kind, target, message)
예제 #2
0
def cmd_topic(server, user, chan, topic):
    if not topic:
        send_topic(server, user, chan)
        return

    user_data = server.chan_nick(chan, user['nick'])
    if not is_op(user_data):
        server.send_reply(user, 'ERR_CHANOPRIVSNEEDED', chan['name'])
        return

    chan['topic'] = decolon(topic)
    server.save_chan(chan)
    server.send_chan(user, 'TOPIC', chan, ':%s' % chan['topic'])
예제 #3
0
파일: irc_chan.py 프로젝트: lessandro/ircd
def cmd_topic(server, user, chan, topic):
    if not topic:
        send_topic(server, user, chan)
        return

    user_data = server.chan_nick(chan, user['nick'])
    if not is_op(user_data):
        server.send_reply(user, 'ERR_CHANOPRIVSNEEDED', chan['name'])
        return

    chan['topic'] = decolon(topic)
    server.save_chan(chan)
    server.send_chan(user, 'TOPIC', chan, ':%s' % chan['topic'])
예제 #4
0
def cmd_kick(server, user, chan, target, message):
    user_data = server.chan_nick(chan, user['nick'])
    if not is_op(user_data):
        server.send_reply(user, 'ERR_CHANOPRIVSNEEDED', chan['name'])
        return

    target_data = server.chan_nick(chan, target)
    if not target_data:
        server.send_reply(user, 'ERR_USERNOTINCHANNEL', target, chan['name'])
        return

    # +o can't kick +q
    if 'q' not in user_data['modes'] and 'q' in target_data['modes']:
        server.send_reply(user, 'ERR_CHANOPRIVSNEEDED', chan['name'])
        return

    # ok to kick
    server.send_chan(user, 'KICK', chan, '%s %s' % (target, colon(message)))

    target_user = server.load_user(target_data['tag'])
    server.part_chan(target_user, chan)
예제 #5
0
def mode_chan(server, user, target, args):
    chan = server.find_chan(target)
    if not chan:
        server.send_reply(user, 'ERR_NOSUCHCHANNEL', target)
        return

    # parameterless mode: show current modes
    if not args:
        server.send_reply(user, 'RPL_CHANNELMODEIS',
                          chan['name'], chan['modes'])
        return

    # special case for banlist
    if args == 'b' or args == '+b':
        # users should use ACCESS instead
        server.send_reply(user, 'RPL_ENDOFBANLIST', chan['name'])
        return

    # all modes require op status
    user_data = server.chan_nick(chan, user['nick'])
    if not is_op(user_data):
        server.send_reply(user, 'ERR_CHANOPRIVSNEEDED', chan['name'])
        return

    chars, rest = split(args, 1)
    adding = True

    for c in chars:
        if c in '+-':
            adding = c == '+'

        # op/voice
        elif c in 'qov':
            target, rest = split(rest, 1)

            if not target:
                # no target supplied
                continue

            # only owners are allowed to +q/-q
            if c == 'q' and 'q' not in user_data['modes']:
                continue

            target_data = server.chan_nick(chan, target)
            if target_data is None:
                server.send_reply(
                    user, 'ERR_USERNOTINCHANNEL', target, chan['name'])
                continue

            target_modes = target_data['modes']

            # check if it's necessary to add or remove the mode
            if not ((c in target_modes) ^ adding):
                continue

            if adding:
                target_modes += c
            else:
                target_modes = target_modes.replace(c, '')

            target_data['modes'] = target_modes
            server.set_chan_nick(chan, target, target_data)

            args = '%s%s %s' % ('+' if adding else '-', c, target)
            server.send_chan(user, 'MODE', chan, args)

        elif c in 'm':
            chan_modes = chan['modes']
            if not ((c in chan_modes) ^ adding):
                continue

            if adding:
                chan_modes += c
            else:
                chan_modes = chan_modes.replace(c, '')

            chan['modes'] = chan_modes
            server.save_chan(chan)

            args = '%s%s' % ('+' if adding else '-', c)
            server.send_chan(user, 'MODE', chan, args)

        else:
            server.send_reply(user, 'ERR_UNKNOWNMODE', c)
예제 #6
0
파일: irc_access.py 프로젝트: hcit/ircd
def cmd_access(server, user, chan, action, level, mask, timeout, reason):
    user_data = server.chan_nick(chan, user['nick'])
    if not is_op(user_data):
        server.send_reply(user, 'ERR_CHANOPRIVSNEEDED', chan['name'])
        return

    action = action.upper()
    level = level.upper()

    if level not in levels:
        server.send_reply(user, 'ERR_BADLEVEL', 'ACCESS')
        return

    is_owner_ = is_owner(user_data)

    if action in ['ADD', 'DELETE', 'CLEAR']:
        if level == 'OWNER' and not is_owner_:
            server.send_reply(user, 'ERR_NOACCESS', 'ACCESS')
            return

    if action == 'ADD':
        if not mask:
            server.send_reply(user, 'ERR_NEEDMOREPARAMS', 'ACCESS')
            return

        mask = parse_mask(mask)
        timeout = parse_timeout(timeout)
        reason = decolon(reason)
        server.access_list_add(chan, level, mask, timeout, user, reason)
        timeout = timeout_minutes(timeout)

        server.send_reply(user, 'RPL_ACCESSADD', chan['name'], level, mask,
                          timeout, user['id'], reason)

    elif action == 'DELETE':
        mask = parse_mask(mask)
        server.access_list_del(chan, level, mask)

        server.send_reply(user, 'RPL_ACCESSDELETE', chan['name'], level, mask)

    elif action == 'CLEAR':
        for level_, mask, _, _, _ in get_access_list(server, chan):
            if level and level != level_:
                continue
            if level_ == 'OWNER' and not is_owner_:
                continue

            server.access_list_del(chan, level_, mask)

        server.send_reply(user, 'RPL_ACCESSCLEAR', chan['name'], level)

    elif action == 'LIST':
        server.send_reply(user, 'RPL_ACCESSSTART', chan['name'])

        acl = get_access_list(server, chan)
        for level_, mask, timeout, userid, reason in acl:
            if level and level != level_:
                continue

            timeout = timeout_minutes(timeout)

            server.send_reply(user, 'RPL_ACCESSLIST', chan['name'], level_,
                              mask, timeout, userid, reason)

        server.send_reply(user, 'RPL_ACCESSEND', chan['name'])

    else:
        server.send_reply(user, 'ERR_BADCOMMAND', 'ACCESS')
        return
예제 #7
0
def cmd_access(server, user, chan, action, level, mask, timeout, reason):
    user_data = server.chan_nick(chan, user['nick'])
    if not is_op(user_data):
        server.send_reply(user, 'ERR_CHANOPRIVSNEEDED', chan['name'])
        return

    action = action.upper()
    level = level.upper()

    if level not in levels:
        server.send_reply(user, 'ERR_BADLEVEL', 'ACCESS')
        return

    is_owner_ = is_owner(user_data)

    if action in ['ADD', 'DELETE', 'CLEAR']:
        if level == 'OWNER' and not is_owner_:
            server.send_reply(user, 'ERR_NOACCESS', 'ACCESS')
            return

    if action == 'ADD':
        if not mask:
            server.send_reply(user, 'ERR_NEEDMOREPARAMS', 'ACCESS')
            return

        if server.access_list_count(chan) >= server.config.max_acl_entries:
            server.send_reply(user, 'ERR_TOOMANYACCESSES')
            return

        mask = parse_mask(mask)
        timeout = parse_timeout(timeout)
        reason = decolon(reason)
        server.access_list_add(chan, level, mask, timeout, user, reason)
        timeout = timeout_minutes(timeout)

        server.send_reply(user, 'RPL_ACCESSADD', chan['name'], level, mask,
                          timeout, user['id'], reason)

    elif action == 'DELETE':
        mask = parse_mask(mask)
        server.access_list_del(chan, level, mask)

        server.send_reply(user, 'RPL_ACCESSDELETE', chan['name'], level, mask)

    elif action == 'CLEAR':
        for level_, mask, _, _, _ in get_access_list(server, chan):
            if level and level != level_:
                continue
            if level_ == 'OWNER' and not is_owner_:
                continue

            server.access_list_del(chan, level_, mask)

        server.send_reply(user, 'RPL_ACCESSCLEAR', chan['name'], level)

    elif action == 'LIST':
        server.send_reply(user, 'RPL_ACCESSSTART', chan['name'])

        acl = get_access_list(server, chan)
        for level_, mask, timeout, userid, reason in acl:
            if level and level != level_:
                continue

            timeout = timeout_minutes(timeout)

            server.send_reply(user, 'RPL_ACCESSLIST', chan['name'], level_,
                              mask, timeout, userid, reason)

        server.send_reply(user, 'RPL_ACCESSEND', chan['name'])

    else:
        server.send_reply(user, 'ERR_BADCOMMAND', 'ACCESS')
        return