mirror of
				https://github.com/jlu5/PyLink.git
				synced 2025-11-04 00:47:21 +01:00 
			
		
		
		
	relay: cleanup, consistently include the function in log.debug calls
This commit is contained in:
		
							parent
							
								
									a740163cbe
								
							
						
					
					
						commit
						34ca973047
					
				
							
								
								
									
										228
									
								
								plugins/relay.py
									
									
									
									
									
								
							
							
						
						
									
										228
									
								
								plugins/relay.py
									
									
									
									
									
								
							@ -30,12 +30,17 @@ dbname = utils.getDatabaseName('pylinkrelay')
 | 
			
		||||
 | 
			
		||||
def initializeAll(irc):
 | 
			
		||||
    """Initializes all relay channels for the given IRC object."""
 | 
			
		||||
    # Wait for all IRC objects to initialize first. This prevents
 | 
			
		||||
 | 
			
		||||
    # Wait for all IRC objects to be created first. This prevents
 | 
			
		||||
    # relay servers from being spawned too early (before server authentication),
 | 
			
		||||
    # which would break connections.
 | 
			
		||||
    world.started.wait(2)
 | 
			
		||||
 | 
			
		||||
    for chanpair, entrydata in db.items():
 | 
			
		||||
        # Iterate over all the channels stored in our relay links DB.
 | 
			
		||||
        network, channel = chanpair
 | 
			
		||||
 | 
			
		||||
        # Initialize each relay channel on their home network, and on every linked one too.
 | 
			
		||||
        initializeChannel(irc, channel)
 | 
			
		||||
        for link in entrydata['links']:
 | 
			
		||||
            network, channel = link
 | 
			
		||||
@ -90,7 +95,7 @@ def normalizeNick(irc, netname, nick, separator=None, uid=''):
 | 
			
		||||
    """Creates a normalized nickname for the given nick suitable for
 | 
			
		||||
    introduction to a remote network (as a relay client)."""
 | 
			
		||||
    separator = separator or irc.serverdata.get('separator') or "/"
 | 
			
		||||
    log.debug('(%s) normalizeNick: using %r as separator.', irc.name, separator)
 | 
			
		||||
    log.debug('(%s) relay.normalizeNick: using %r as separator.', irc.name, separator)
 | 
			
		||||
    orig_nick = nick
 | 
			
		||||
    protoname = irc.protoname
 | 
			
		||||
    maxnicklen = irc.maxnicklen
 | 
			
		||||
@ -129,7 +134,7 @@ def normalizeNick(irc, netname, nick, separator=None, uid=''):
 | 
			
		||||
    # the same client.
 | 
			
		||||
    while irc.nickToUid(nick) and irc.nickToUid(nick) != uid:
 | 
			
		||||
        new_sep = separator + separator[-1]
 | 
			
		||||
        log.debug('(%s) normalizeNick: nick %r is in use; using %r as new_sep.', irc.name, nick, new_sep)
 | 
			
		||||
        log.debug('(%s) relay.normalizeNick: nick %r is in use; using %r as new_sep.', irc.name, nick, new_sep)
 | 
			
		||||
        nick = normalizeNick(irc, netname, orig_nick, separator=new_sep)
 | 
			
		||||
    finalLength = len(nick)
 | 
			
		||||
    assert finalLength <= maxnicklen, "Normalized nick %r went over max " \
 | 
			
		||||
@ -185,15 +190,22 @@ def getPrefixModes(irc, remoteirc, channel, user, mlist=None):
 | 
			
		||||
    remote IRC network given.
 | 
			
		||||
 | 
			
		||||
    Optionally, an mlist argument can be given to look at an earlier state of
 | 
			
		||||
    the channel, e.g. for checking the op  status of a mode setter before their
 | 
			
		||||
    the channel, e.g. for checking the op status of a mode setter before their
 | 
			
		||||
    modes are processed and added to the channel state.
 | 
			
		||||
    """
 | 
			
		||||
    modes = ''
 | 
			
		||||
 | 
			
		||||
    # Get the mapping of all the channel's prefix modes
 | 
			
		||||
    mlist = mlist or irc.channels[channel].prefixmodes
 | 
			
		||||
 | 
			
		||||
    # Iterate over the the supported prefix modes for relay
 | 
			
		||||
    for pmode in ('owner', 'admin', 'op', 'halfop', 'voice'):
 | 
			
		||||
        if pmode in remoteirc.cmodes:  # Mode supported by IRCd
 | 
			
		||||
        if pmode in remoteirc.cmodes:  # If the mode supported by IRCd
 | 
			
		||||
            # Check if the caller is in the prefix modes list for that
 | 
			
		||||
            # prefix.prefixmodes mapping looks like:
 | 
			
		||||
            #     {'ops': ['user1', 'user2'], 'voices': ['user3', 'user4'], ...}
 | 
			
		||||
            userlist = mlist[pmode+'s']
 | 
			
		||||
            log.debug('(%s) getPrefixModes: checking if %r is in %s list: %r',
 | 
			
		||||
            log.debug('(%s) relay.getPrefixModes: checking if %r is in %s list: %r',
 | 
			
		||||
                      irc.name, user, pmode, userlist)
 | 
			
		||||
            if user in userlist:
 | 
			
		||||
                modes += remoteirc.cmodes[pmode]
 | 
			
		||||
@ -321,7 +333,7 @@ def getOrigUser(irc, user, targetirc=None):
 | 
			
		||||
        remoteuser = irc.users[user].remote
 | 
			
		||||
    except (AttributeError, KeyError):
 | 
			
		||||
        remoteuser = None
 | 
			
		||||
    log.debug('(%s) getOrigUser: remoteuser set to %r (looking up %s/%s).',
 | 
			
		||||
    log.debug('(%s) relay.getOrigUser: remoteuser set to %r (looking up %s/%s).',
 | 
			
		||||
              irc.name, remoteuser, user, irc.name)
 | 
			
		||||
    if remoteuser:
 | 
			
		||||
        # If targetirc is given, we'll return simply the UID of the user on the
 | 
			
		||||
@ -336,7 +348,7 @@ def getOrigUser(irc, user, targetirc=None):
 | 
			
		||||
            # Otherwise, use getRemoteUser to find our UID.
 | 
			
		||||
            res = getRemoteUser(sourceobj, targetirc, remoteuser[1],
 | 
			
		||||
                                spawnIfMissing=False)
 | 
			
		||||
            log.debug('(%s) getOrigUser: targetirc found, getting %r as '
 | 
			
		||||
            log.debug('(%s) relay.getOrigUser: targetirc found, getting %r as '
 | 
			
		||||
                      'remoteuser for %r (looking up %s/%s).', irc.name, res,
 | 
			
		||||
                      remoteuser[1], user, irc.name)
 | 
			
		||||
            return res
 | 
			
		||||
@ -373,33 +385,41 @@ def initializeChannel(irc, channel):
 | 
			
		||||
    # We're initializing a relay that already exists. This can be done at
 | 
			
		||||
    # ENDBURST, or on the LINK command.
 | 
			
		||||
    relay = getRelay((irc.name, channel))
 | 
			
		||||
    log.debug('(%s) initializeChannel being called on %s', irc.name, channel)
 | 
			
		||||
    log.debug('(%s) initializeChannel: relay pair found to be %s', irc.name, relay)
 | 
			
		||||
    log.debug('(%s) relay.initializeChannel being called on %s', irc.name, channel)
 | 
			
		||||
    log.debug('(%s) relay.initializeChannel: relay pair found to be %s', irc.name, relay)
 | 
			
		||||
    queued_users = []
 | 
			
		||||
    if relay:
 | 
			
		||||
        all_links = db[relay]['links'].copy()
 | 
			
		||||
        all_links.update((relay,))
 | 
			
		||||
        log.debug('(%s) initializeChannel: all_links: %s', irc.name, all_links)
 | 
			
		||||
        log.debug('(%s) relay.initializeChannel: all_links: %s', irc.name, all_links)
 | 
			
		||||
 | 
			
		||||
        # Iterate over all the remote channels linked in this relay.
 | 
			
		||||
        for link in all_links:
 | 
			
		||||
            remotenet, remotechan = link
 | 
			
		||||
            if remotenet == irc.name:
 | 
			
		||||
            if remotenet == irc.name:  # If the network is us, skip.
 | 
			
		||||
                continue
 | 
			
		||||
            remoteirc = world.networkobjects.get(remotenet)
 | 
			
		||||
 | 
			
		||||
            if remoteirc is None:
 | 
			
		||||
                # Remote network doesn't have an IRC object; e.g. it was removed
 | 
			
		||||
                # from the config. Skip this.
 | 
			
		||||
                continue
 | 
			
		||||
            rc = remoteirc.channels[remotechan]
 | 
			
		||||
 | 
			
		||||
            if not (remoteirc.connected.is_set() and getRemoteChan(remoteirc, irc, remotechan)):
 | 
			
		||||
                continue  # They aren't connected, don't bother!
 | 
			
		||||
                continue  # Remote network isn't connected.
 | 
			
		||||
 | 
			
		||||
            # Join their (remote) users and set their modes.
 | 
			
		||||
            relayJoins(remoteirc, remotechan, rc.users, rc.ts)
 | 
			
		||||
            topic = remoteirc.channels[remotechan].topic
 | 
			
		||||
 | 
			
		||||
            # Only update the topic if it's different from what we already have,
 | 
			
		||||
            # and topic bursting is complete.
 | 
			
		||||
            if remoteirc.channels[remotechan].topicset and topic != irc.channels[channel].topic:
 | 
			
		||||
                irc.proto.topicBurst(getRemoteSid(irc, remoteirc), channel, topic)
 | 
			
		||||
 | 
			
		||||
        # Send our users and channel modes to the other nets
 | 
			
		||||
        log.debug('(%s) initializeChannel: joining our (%s) users: %s', irc.name, remotenet, irc.channels[channel].users)
 | 
			
		||||
        log.debug('(%s) relay.initializeChannel: joining our (%s) users: %s', irc.name, remotenet, irc.channels[channel].users)
 | 
			
		||||
        relayJoins(irc, channel, irc.channels[channel].users, irc.channels[channel].ts)
 | 
			
		||||
        if irc.pseudoclient.uid not in irc.channels[channel].users:
 | 
			
		||||
            irc.proto.join(irc.pseudoclient.uid, channel)
 | 
			
		||||
@ -457,27 +477,42 @@ def getSupportedUmodes(irc, remoteirc, modes):
 | 
			
		||||
    """Given a list of user modes, filters out all of those not supported by the
 | 
			
		||||
    remote network."""
 | 
			
		||||
    supported_modes = []
 | 
			
		||||
 | 
			
		||||
    # Iterate over all mode pairs.
 | 
			
		||||
    for modepair in modes:
 | 
			
		||||
        try:
 | 
			
		||||
            # Get the prefix and the actual mode character (the prefix being + or -, or
 | 
			
		||||
            # whether we're setting or unsetting a mode)
 | 
			
		||||
            prefix, modechar = modepair[0]
 | 
			
		||||
        except ValueError:
 | 
			
		||||
            # If the prefix is missing, assume we're adding a mode.
 | 
			
		||||
            modechar = modepair[0]
 | 
			
		||||
            prefix = '+'
 | 
			
		||||
 | 
			
		||||
        # Get the mode argument.
 | 
			
		||||
        arg = modepair[1]
 | 
			
		||||
 | 
			
		||||
        # Iterate over all supported user modes for the current network.
 | 
			
		||||
        for name, m in irc.umodes.items():
 | 
			
		||||
            supported_char = None
 | 
			
		||||
 | 
			
		||||
            # Mode character matches one in our list, so set that named mode
 | 
			
		||||
            # as the one we're trying to set. Then, look up that named mode
 | 
			
		||||
            # in the supported modes list for the TARGET network, and set that
 | 
			
		||||
            # mode character as the one we're setting, if it exists.
 | 
			
		||||
            if modechar == m:
 | 
			
		||||
                if name not in whitelisted_umodes:
 | 
			
		||||
                    log.debug("(%s) getSupportedUmodes: skipping mode (%r, %r) because "
 | 
			
		||||
                    log.debug("(%s) relay.getSupportedUmodes: skipping mode (%r, %r) because "
 | 
			
		||||
                              "it isn't a whitelisted (safe) mode for relay.",
 | 
			
		||||
                              irc.name, modechar, arg)
 | 
			
		||||
                    break
 | 
			
		||||
                supported_char = remoteirc.umodes.get(name)
 | 
			
		||||
 | 
			
		||||
            if supported_char:
 | 
			
		||||
                supported_modes.append((prefix+supported_char, arg))
 | 
			
		||||
                break
 | 
			
		||||
        else:
 | 
			
		||||
            log.debug("(%s) getSupportedUmodes: skipping mode (%r, %r) because "
 | 
			
		||||
            log.debug("(%s) relay.getSupportedUmodes: skipping mode (%r, %r) because "
 | 
			
		||||
                      "the remote network (%s)'s IRCd (%s) doesn't support it.",
 | 
			
		||||
                      irc.name, modechar, arg, remoteirc.name,
 | 
			
		||||
                      remoteirc.protoname)
 | 
			
		||||
@ -499,59 +534,83 @@ def isRelayClient(irc, user):
 | 
			
		||||
### EVENT HANDLER INTERNALS
 | 
			
		||||
 | 
			
		||||
def relayJoins(irc, channel, users, ts, burst=True):
 | 
			
		||||
    """
 | 
			
		||||
    Relays one or more users' joins from a channel to its relay links.
 | 
			
		||||
    """
 | 
			
		||||
    for name, remoteirc in world.networkobjects.copy().items():
 | 
			
		||||
        queued_users = []
 | 
			
		||||
        if name == irc.name or not remoteirc.connected.is_set():
 | 
			
		||||
            # Don't relay things to their source network...
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        remotechan = getRemoteChan(irc, remoteirc, channel)
 | 
			
		||||
        if remotechan is None:
 | 
			
		||||
            # If there is no link on our network for the user, don't
 | 
			
		||||
            # bother spawning it.
 | 
			
		||||
            # If there is no link on the current network for the channel in question,
 | 
			
		||||
            # just skip it
 | 
			
		||||
            continue
 | 
			
		||||
        log.debug('(%s) relayJoins: got %r for users', irc.name, users)
 | 
			
		||||
 | 
			
		||||
        log.debug('(%s) relay.relayJoins: got %r for users', irc.name, users)
 | 
			
		||||
 | 
			
		||||
        for user in users.copy():
 | 
			
		||||
            if isRelayClient(irc, user):
 | 
			
		||||
                # Don't clone relay clients; that'll cause some bad, bad
 | 
			
		||||
                # things to happen.
 | 
			
		||||
                # Don't clone relay clients; that'll cause bad infinite loops.
 | 
			
		||||
                continue
 | 
			
		||||
            log.debug('Okay, spawning %s/%s everywhere', user, irc.name)
 | 
			
		||||
            assert user in irc.users, "(%s) How is this possible? %r isn't in our user database." % (irc.name, user)
 | 
			
		||||
 | 
			
		||||
            assert user in irc.users, "(%s) relay.relayJoins: How is this possible? %r isn't in our user database." % (irc.name, user)
 | 
			
		||||
            u = getRemoteUser(irc, remoteirc, user)
 | 
			
		||||
            # Only join users if they aren't already joined. This prevents op floods
 | 
			
		||||
            # on charybdis from all the SJOINing.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            if u not in remoteirc.channels[remotechan].users:
 | 
			
		||||
                # Note: only join users if they aren't already joined. This prevents op floods
 | 
			
		||||
                # on charybdis from repeated SJOINs sent for one user.
 | 
			
		||||
 | 
			
		||||
                # Fetch the known channel TS and all the prefix modes for each user. This ensures
 | 
			
		||||
                # the different sides of the relay are merged properly.
 | 
			
		||||
                ts = irc.channels[channel].ts
 | 
			
		||||
                prefixes = getPrefixModes(irc, remoteirc, channel, user)
 | 
			
		||||
 | 
			
		||||
                # proto.sjoin() takes its users as a list of (prefix mode characters, UID) pairs.
 | 
			
		||||
                userpair = (prefixes, u)
 | 
			
		||||
                queued_users.append(userpair)
 | 
			
		||||
                log.debug('(%s) relayJoins: joining %s to %s%s', irc.name, userpair, remoteirc.name, remotechan)
 | 
			
		||||
            else:
 | 
			
		||||
                log.debug('(%s) relayJoins: not joining %s to %s%s; they\'re already there!', irc.name,
 | 
			
		||||
                          u, remoteirc.name, remotechan)
 | 
			
		||||
 | 
			
		||||
        if queued_users:
 | 
			
		||||
            # Burst was explicitly given, or we're trying to join multiple
 | 
			
		||||
            # users/someone with a prefix.
 | 
			
		||||
            # Look at whether we should relay this join as a regular JOIN, or a SJOIN.
 | 
			
		||||
            # SJOIN will be used if either the amount of users to join is > 1, or there are modes
 | 
			
		||||
            # to be set on the joining user.
 | 
			
		||||
            if burst or len(queued_users) > 1 or queued_users[0][0]:
 | 
			
		||||
                # Send the SJOIN from the relay subserver on the target network.
 | 
			
		||||
                rsid = getRemoteSid(remoteirc, irc)
 | 
			
		||||
                remoteirc.proto.sjoin(rsid, remotechan, queued_users, ts=ts)
 | 
			
		||||
                relayModes(irc, remoteirc, getRemoteSid(irc, remoteirc), channel, irc.channels[channel].modes)
 | 
			
		||||
            else:
 | 
			
		||||
                # A regular JOIN only needs the user and the channel. TS, source SID, etc., can all be omitted.
 | 
			
		||||
                remoteirc.proto.join(queued_users[0][1], remotechan)
 | 
			
		||||
 | 
			
		||||
def relayPart(irc, channel, user):
 | 
			
		||||
    """
 | 
			
		||||
    Relays a user part from a channel to its relay links, as part of a channel delink.
 | 
			
		||||
    """
 | 
			
		||||
    for name, remoteirc in world.networkobjects.items():
 | 
			
		||||
        if name == irc.name or not remoteirc.connected.is_set():
 | 
			
		||||
            # Don't relay things to their source network...
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        remotechan = getRemoteChan(irc, remoteirc, channel)
 | 
			
		||||
        log.debug('(%s) relayPart: looking for %s/%s on %s', irc.name, user, irc.name, remoteirc.name)
 | 
			
		||||
        log.debug('(%s) relayPart: remotechan found as %s', irc.name, remotechan)
 | 
			
		||||
        log.debug('(%s) relay.relayPart: looking for %s/%s on %s', irc.name, user, irc.name, remoteirc.name)
 | 
			
		||||
        log.debug('(%s) relay.relayPart: remotechan found as %s', irc.name, remotechan)
 | 
			
		||||
 | 
			
		||||
        remoteuser = getRemoteUser(irc, remoteirc, user, spawnIfMissing=False)
 | 
			
		||||
        log.debug('(%s) relayPart: remoteuser for %s/%s found as %s', irc.name, user, irc.name, remoteuser)
 | 
			
		||||
        log.debug('(%s) relay.relayPart: remoteuser for %s/%s found as %s', irc.name, user, irc.name, remoteuser)
 | 
			
		||||
 | 
			
		||||
        if remotechan is None or remoteuser is None:
 | 
			
		||||
            # If there is no relay channel on the target network, or the relay
 | 
			
		||||
            # user doesn't exist, just do nothing.
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        # Part the relay client with the channel delinked message.
 | 
			
		||||
        remoteirc.proto.part(remoteuser, remotechan, 'Channel delinked.')
 | 
			
		||||
 | 
			
		||||
        # If the relay client no longer has any channels, quit them to prevent inflating /lusers.
 | 
			
		||||
        if isRelayClient(remoteirc, remoteuser) and not remoteirc.users[remoteuser].channels:
 | 
			
		||||
            remoteirc.proto.quit(remoteuser, 'Left all shared channels.')
 | 
			
		||||
            del relayusers[(irc.name, user)][remoteirc.name]
 | 
			
		||||
@ -568,15 +627,21 @@ whitelisted_umodes = {'bot', 'hidechans', 'hideoper', 'invisible', 'oper',
 | 
			
		||||
                      'regdeaf', 'u_stripcolor', 'u_noctcp', 'wallops',
 | 
			
		||||
                      'hideidle'}
 | 
			
		||||
def relayModes(irc, remoteirc, sender, channel, modes=None):
 | 
			
		||||
    """
 | 
			
		||||
    Relays a mode change on a channel to its relay links.
 | 
			
		||||
    """
 | 
			
		||||
    remotechan = getRemoteChan(irc, remoteirc, channel)
 | 
			
		||||
    log.debug('(%s) Relay mode: remotechan for %s on %s is %s', irc.name, channel, irc.name, remotechan)
 | 
			
		||||
    log.debug('(%s) relay.relayModes: remotechan for %s on %s is %s', irc.name, channel, irc.name, remotechan)
 | 
			
		||||
 | 
			
		||||
    if remotechan is None:
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    if modes is None:
 | 
			
		||||
        modes = irc.channels[channel].modes
 | 
			
		||||
        log.debug('(%s) Relay mode: channel data for %s%s: %s', irc.name, remoteirc.name, remotechan, remoteirc.channels[remotechan])
 | 
			
		||||
        log.debug('(%s) relay.relayModes: channel data for %s%s: %s', irc.name, remoteirc.name, remotechan, remoteirc.channels[remotechan])
 | 
			
		||||
    supported_modes = []
 | 
			
		||||
    log.debug('(%s) Relay mode: initial modelist for %s is %s', irc.name, channel, modes)
 | 
			
		||||
    log.debug('(%s) relay.relayModes: initial modelist for %s is %s', irc.name, channel, modes)
 | 
			
		||||
 | 
			
		||||
    for modepair in modes:
 | 
			
		||||
        try:
 | 
			
		||||
            prefix, modechar = modepair[0]
 | 
			
		||||
@ -584,56 +649,72 @@ def relayModes(irc, remoteirc, sender, channel, modes=None):
 | 
			
		||||
            modechar = modepair[0]
 | 
			
		||||
            prefix = '+'
 | 
			
		||||
        arg = modepair[1]
 | 
			
		||||
 | 
			
		||||
        # Iterate over every mode see whether the remote IRCd supports
 | 
			
		||||
        # this mode, and what its mode char for it is (if it is different).
 | 
			
		||||
        for name, m in irc.cmodes.items():
 | 
			
		||||
            supported_char = None
 | 
			
		||||
            if modechar == m:
 | 
			
		||||
                supported_char = remoteirc.cmodes.get(name)
 | 
			
		||||
 | 
			
		||||
                if supported_char is None:
 | 
			
		||||
                    break
 | 
			
		||||
 | 
			
		||||
                if name not in whitelisted_cmodes:
 | 
			
		||||
                    log.debug("(%s) Relay mode: skipping mode (%r, %r) because "
 | 
			
		||||
                    log.debug("(%s) relay.relayModes: skipping mode (%r, %r) because "
 | 
			
		||||
                              "it isn't a whitelisted (safe) mode for relay.",
 | 
			
		||||
                              irc.name, modechar, arg)
 | 
			
		||||
                    break
 | 
			
		||||
 | 
			
		||||
                if modechar in irc.prefixmodes:
 | 
			
		||||
                    # This is a prefix mode (e.g. +o). We must coerse the argument
 | 
			
		||||
                    # so that the target exists on the remote relay network.
 | 
			
		||||
                    log.debug("(%s) Relay mode: coersing argument of (%r, %r) "
 | 
			
		||||
                    log.debug("(%s) relay.relayModes: coersing argument of (%r, %r) "
 | 
			
		||||
                              "for network %r.",
 | 
			
		||||
                              irc.name, modechar, arg, remoteirc.name)
 | 
			
		||||
 | 
			
		||||
                    # If the target is a remote user, get the real target
 | 
			
		||||
                    # (original user).
 | 
			
		||||
                    arg = getOrigUser(irc, arg, targetirc=remoteirc) or \
 | 
			
		||||
                        getRemoteUser(irc, remoteirc, arg, spawnIfMissing=False)
 | 
			
		||||
                    log.debug("(%s) Relay mode: argument found as (%r, %r) "
 | 
			
		||||
 | 
			
		||||
                    log.debug("(%s) relay.relayModes: argument found as (%r, %r) "
 | 
			
		||||
                              "for network %r.",
 | 
			
		||||
                              irc.name, modechar, arg, remoteirc.name)
 | 
			
		||||
                    oplist = remoteirc.channels[remotechan].prefixmodes[name+'s']
 | 
			
		||||
                    log.debug("(%s) Relay mode: list of %ss on %r is: %s",
 | 
			
		||||
 | 
			
		||||
                    log.debug("(%s) relay.relayModes: list of %ss on %r is: %s",
 | 
			
		||||
                              irc.name, name, remotechan, oplist)
 | 
			
		||||
 | 
			
		||||
                    if prefix == '+' and arg in oplist:
 | 
			
		||||
 | 
			
		||||
                        # Don't set prefix modes that are already set.
 | 
			
		||||
                        log.debug("(%s) Relay mode: skipping setting %s on %s/%s because it appears to be already set.",
 | 
			
		||||
                        log.debug("(%s) relay.relayModes: skipping setting %s on %s/%s because it appears to be already set.",
 | 
			
		||||
                                  irc.name, name, arg, remoteirc.name)
 | 
			
		||||
                        break
 | 
			
		||||
 | 
			
		||||
                supported_char = remoteirc.cmodes.get(name)
 | 
			
		||||
 | 
			
		||||
            if supported_char:
 | 
			
		||||
                final_modepair = (prefix+supported_char, arg)
 | 
			
		||||
                if name in ('ban', 'banexception', 'invex') and not utils.isHostmask(arg):
 | 
			
		||||
 | 
			
		||||
                    # Don't add bans that don't match n!u@h syntax!
 | 
			
		||||
                    log.debug("(%s) Relay mode: skipping mode (%r, %r) because it doesn't match nick!user@host syntax.",
 | 
			
		||||
                    log.debug("(%s) relay.relayModes: skipping mode (%r, %r) because it doesn't match nick!user@host syntax.",
 | 
			
		||||
                              irc.name, modechar, arg)
 | 
			
		||||
                    break
 | 
			
		||||
 | 
			
		||||
                # Don't set modes that are already set, to prevent floods on TS6
 | 
			
		||||
                # where the same mode can be set infinite times.
 | 
			
		||||
                if prefix == '+' and final_modepair in remoteirc.channels[remotechan].modes:
 | 
			
		||||
                    log.debug("(%s) Relay mode: skipping setting mode (%r, %r) on %s%s because it appears to be already set.",
 | 
			
		||||
                    log.debug("(%s) relay.relayModes: skipping setting mode (%r, %r) on %s%s because it appears to be already set.",
 | 
			
		||||
                              irc.name, supported_char, arg, remoteirc.name, remotechan)
 | 
			
		||||
                    break
 | 
			
		||||
 | 
			
		||||
                supported_modes.append(final_modepair)
 | 
			
		||||
    log.debug('(%s) Relay mode: final modelist (sending to %s%s) is %s', irc.name, remoteirc.name, remotechan, supported_modes)
 | 
			
		||||
 | 
			
		||||
    log.debug('(%s) relay.relayModes: final modelist (sending to %s%s) is %s', irc.name, remoteirc.name, remotechan, supported_modes)
 | 
			
		||||
 | 
			
		||||
    # Don't send anything if there are no supported modes left after filtering.
 | 
			
		||||
    if supported_modes:
 | 
			
		||||
        # Check if the sender is a user; remember servers are allowed to set modes too.
 | 
			
		||||
@ -645,6 +726,9 @@ def relayModes(irc, remoteirc, sender, channel, modes=None):
 | 
			
		||||
            remoteirc.proto.mode(rsid, remotechan, supported_modes)
 | 
			
		||||
 | 
			
		||||
def relayWhoisHandler(irc, target):
 | 
			
		||||
    """
 | 
			
		||||
    WHOIS handler for the relay plugin.
 | 
			
		||||
    """
 | 
			
		||||
    user = irc.users[target]
 | 
			
		||||
    orig = getOrigUser(irc, target)
 | 
			
		||||
    if orig:
 | 
			
		||||
@ -700,7 +784,7 @@ def handle_squit(irc, numeric, command, args):
 | 
			
		||||
        # Some other netsplit happened on the network, we'll have to fake
 | 
			
		||||
        # some *.net *.split quits for that.
 | 
			
		||||
        for user in users:
 | 
			
		||||
            log.debug('(%s) relay handle_squit: sending handle_quit on %s', irc.name, user)
 | 
			
		||||
            log.debug('(%s) relay.handle_squit: sending handle_quit on %s', irc.name, user)
 | 
			
		||||
            handle_quit(irc, user, command, {'text': '*.net *.split'})
 | 
			
		||||
utils.add_hook(handle_squit, 'SQUIT')
 | 
			
		||||
 | 
			
		||||
@ -748,7 +832,7 @@ def handle_messages(irc, numeric, command, args):
 | 
			
		||||
 | 
			
		||||
    elif numeric not in irc.users:
 | 
			
		||||
        # Sender didn't pass the check above, AND isn't a user.
 | 
			
		||||
        log.debug('(%s) relay: Unknown message sender %s.', irc.name, numeric)
 | 
			
		||||
        log.debug('(%s) relay.handle_messages: Unknown message sender %s.', irc.name, numeric)
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    relay = getRelay((irc.name, target))
 | 
			
		||||
@ -762,7 +846,7 @@ def handle_messages(irc, numeric, command, args):
 | 
			
		||||
    else:
 | 
			
		||||
        target = '#' + target
 | 
			
		||||
 | 
			
		||||
    log.debug('(%s) relay privmsg: prefix is %r, target is %r', irc.name, prefix, target)
 | 
			
		||||
    log.debug('(%s) relay.handle_messages: prefix is %r, target is %r', irc.name, prefix, target)
 | 
			
		||||
    if utils.isChannel(target) and relay and numeric not in irc.channels[target].users:
 | 
			
		||||
        # The sender must be in the target channel to send messages over the relay;
 | 
			
		||||
        # it's the only way we can make sure they have a spawned client on ALL
 | 
			
		||||
@ -784,7 +868,7 @@ def handle_messages(irc, numeric, command, args):
 | 
			
		||||
 | 
			
		||||
            user = getRemoteUser(irc, remoteirc, numeric, spawnIfMissing=False)
 | 
			
		||||
            real_target = prefix + real_target
 | 
			
		||||
            log.debug('(%s) relay: sending message to %s from %s on behalf of %s',
 | 
			
		||||
            log.debug('(%s) relay.handle_messages: sending message to %s from %s on behalf of %s',
 | 
			
		||||
                      irc.name, real_target, user, numeric)
 | 
			
		||||
            if notice:
 | 
			
		||||
                remoteirc.proto.notice(user, real_target, text)
 | 
			
		||||
@ -832,24 +916,24 @@ def handle_kick(irc, source, command, args):
 | 
			
		||||
        if irc.name == name or not remoteirc.connected.is_set():
 | 
			
		||||
            continue
 | 
			
		||||
        remotechan = getRemoteChan(irc, remoteirc, channel)
 | 
			
		||||
        log.debug('(%s) Relay kick: remotechan for %s on %s is %s', irc.name, channel, name, remotechan)
 | 
			
		||||
        log.debug('(%s) relay.handle_kick: remotechan for %s on %s is %s', irc.name, channel, name, remotechan)
 | 
			
		||||
        if remotechan is None:
 | 
			
		||||
            continue
 | 
			
		||||
        real_kicker = getRemoteUser(irc, remoteirc, kicker, spawnIfMissing=False)
 | 
			
		||||
        log.debug('(%s) Relay kick: real kicker for %s on %s is %s', irc.name, kicker, name, real_kicker)
 | 
			
		||||
        log.debug('(%s) relay.handle_kick: real kicker for %s on %s is %s', irc.name, kicker, name, real_kicker)
 | 
			
		||||
        if not isRelayClient(irc, target):
 | 
			
		||||
            log.debug('(%s) Relay kick: target %s is NOT an internal client', irc.name, target)
 | 
			
		||||
            log.debug('(%s) relay.handle_kick: target %s is NOT an internal client', irc.name, target)
 | 
			
		||||
            # Both the target and kicker are external clients; i.e.
 | 
			
		||||
            # they originate from the same network. We won't have
 | 
			
		||||
            # to filter this; the uplink IRCd will handle it appropriately,
 | 
			
		||||
            # and we'll just follow.
 | 
			
		||||
            real_target = getRemoteUser(irc, remoteirc, target, spawnIfMissing=False)
 | 
			
		||||
            log.debug('(%s) Relay kick: real target for %s is %s', irc.name, target, real_target)
 | 
			
		||||
            log.debug('(%s) relay.handle_kick: real target for %s is %s', irc.name, target, real_target)
 | 
			
		||||
        else:
 | 
			
		||||
            log.debug('(%s) Relay kick: target %s is an internal client, going to look up the real user', irc.name, target)
 | 
			
		||||
            log.debug('(%s) relay.handle_kick: target %s is an internal client, going to look up the real user', irc.name, target)
 | 
			
		||||
            real_target = getOrigUser(irc, target, targetirc=remoteirc)
 | 
			
		||||
            if not checkClaim(irc, channel, kicker):
 | 
			
		||||
                log.debug('(%s) Relay kick: kicker %s is not opped... We should rejoin the target user %s', irc.name, kicker, real_target)
 | 
			
		||||
                log.debug('(%s) relay.handle_kick: kicker %s is not opped... We should rejoin the target user %s', irc.name, kicker, real_target)
 | 
			
		||||
                # Home network is not in the channel's claim AND the kicker is not
 | 
			
		||||
                # opped. We won't propograte the kick then.
 | 
			
		||||
                # TODO: make the check slightly more advanced: i.e. halfops can't
 | 
			
		||||
@ -858,14 +942,14 @@ def handle_kick(irc, source, command, args):
 | 
			
		||||
                # Join the kicked client back with its respective modes.
 | 
			
		||||
                irc.proto.sjoin(irc.sid, channel, [(modes, target)])
 | 
			
		||||
                if kicker in irc.users:
 | 
			
		||||
                    log.info('(%s) Relay claim: Blocked KICK (reason %r) from %s to relay client %s on %s.',
 | 
			
		||||
                    log.info('(%s) relay.handle_kick: Blocked KICK (reason %r) from %s to relay client %s on %s.',
 | 
			
		||||
                             irc.name, args['text'], irc.users[source].nick,
 | 
			
		||||
                             remoteirc.users[real_target].nick, channel)
 | 
			
		||||
                    irc.msg(kicker, "This channel is claimed; your kick to "
 | 
			
		||||
                                    "%s has been blocked because you are not "
 | 
			
		||||
                                    "(half)opped." % channel, notice=True)
 | 
			
		||||
                else:
 | 
			
		||||
                    log.info('(%s) Relay claim: Blocked KICK (reason %r) from server %s to relay client %s/%s on %s.',
 | 
			
		||||
                    log.info('(%s) relay.handle_kick: Blocked KICK (reason %r) from server %s to relay client %s/%s on %s.',
 | 
			
		||||
                             irc.name, args['text'], irc.servers[source].name,
 | 
			
		||||
                             remoteirc.users[real_target].nick, remoteirc.name, channel)
 | 
			
		||||
                return
 | 
			
		||||
@ -874,13 +958,13 @@ def handle_kick(irc, source, command, args):
 | 
			
		||||
            continue
 | 
			
		||||
        # Propogate the kick!
 | 
			
		||||
        if real_kicker:
 | 
			
		||||
            log.debug('(%s) Relay kick: Kicking %s from channel %s via %s on behalf of %s/%s', irc.name, real_target, remotechan,real_kicker, kicker, irc.name)
 | 
			
		||||
            log.debug('(%s) relay.handle_kick: Kicking %s from channel %s via %s on behalf of %s/%s', irc.name, real_target, remotechan,real_kicker, kicker, irc.name)
 | 
			
		||||
            remoteirc.proto.kick(real_kicker, remotechan, real_target, args['text'])
 | 
			
		||||
        else:
 | 
			
		||||
            # Kick originated from a server, or the kicker isn't in any
 | 
			
		||||
            # common channels with the target relay network.
 | 
			
		||||
            rsid = getRemoteSid(remoteirc, irc)
 | 
			
		||||
            log.debug('(%s) Relay kick: Kicking %s from channel %s via %s on behalf of %s/%s', irc.name, real_target, remotechan, rsid, kicker, irc.name)
 | 
			
		||||
            log.debug('(%s) relay.handle_kick: Kicking %s from channel %s via %s on behalf of %s/%s', irc.name, real_target, remotechan, rsid, kicker, irc.name)
 | 
			
		||||
            try:
 | 
			
		||||
                if kicker in irc.servers:
 | 
			
		||||
                    kname = irc.servers[kicker].name
 | 
			
		||||
@ -921,7 +1005,7 @@ def handle_chgclient(irc, source, command, args):
 | 
			
		||||
                    text = normalizeHost(remoteirc, text)
 | 
			
		||||
                remoteirc.proto.updateClient(user, field, text)
 | 
			
		||||
            except NotImplementedError:  # IRCd doesn't support changing the field we want
 | 
			
		||||
                log.debug('(%s) Ignoring changing field %r of %s on %s (for %s/%s);'
 | 
			
		||||
                log.debug('(%s) relay.handle_chgclient: Ignoring changing field %r of %s on %s (for %s/%s);'
 | 
			
		||||
                          ' remote IRCd doesn\'t support it', irc.name, field,
 | 
			
		||||
                          user, netname, target, irc.name)
 | 
			
		||||
                continue
 | 
			
		||||
@ -935,27 +1019,33 @@ def handle_mode(irc, numeric, command, args):
 | 
			
		||||
    for name, remoteirc in world.networkobjects.items():
 | 
			
		||||
        if irc.name == name or not remoteirc.connected.is_set():
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        if utils.isChannel(target):
 | 
			
		||||
            oldchan = args.get('oldchan')
 | 
			
		||||
 | 
			
		||||
            if checkClaim(irc, target, numeric, chanobj=oldchan):
 | 
			
		||||
                relayModes(irc, remoteirc, numeric, target, modes)
 | 
			
		||||
            else:  # Mode change blocked by CLAIM.
 | 
			
		||||
                reversed_modes = utils.reverseModes(irc, target, modes, oldobj=oldchan)
 | 
			
		||||
                log.debug('(%s) Reversing mode changes of %r with %r (CLAIM).',
 | 
			
		||||
                log.debug('(%s) relay.handle_mode: Reversing mode changes of %r with %r (CLAIM).',
 | 
			
		||||
                          irc.name, modes, reversed_modes)
 | 
			
		||||
                irc.proto.mode(irc.pseudoclient.uid, target, reversed_modes)
 | 
			
		||||
                break
 | 
			
		||||
 | 
			
		||||
        else:
 | 
			
		||||
            # Set hideoper on remote opers, to prevent inflating
 | 
			
		||||
            # /lusers and various /stats
 | 
			
		||||
            hideoper_mode = remoteirc.umodes.get('hideoper')
 | 
			
		||||
            modes = getSupportedUmodes(irc, remoteirc, modes)
 | 
			
		||||
 | 
			
		||||
            if hideoper_mode:
 | 
			
		||||
                if ('+o', None) in modes:
 | 
			
		||||
                    modes.append(('+%s' % hideoper_mode, None))
 | 
			
		||||
                elif ('-o', None) in modes:
 | 
			
		||||
                    modes.append(('-%s' % hideoper_mode, None))
 | 
			
		||||
 | 
			
		||||
            remoteuser = getRemoteUser(irc, remoteirc, target, spawnIfMissing=False)
 | 
			
		||||
 | 
			
		||||
            if remoteuser and modes:
 | 
			
		||||
                remoteirc.proto.mode(remoteuser, remoteuser, modes)
 | 
			
		||||
 | 
			
		||||
@ -990,7 +1080,7 @@ def handle_kill(irc, numeric, command, args):
 | 
			
		||||
    target = args['target']
 | 
			
		||||
    userdata = args['userdata']
 | 
			
		||||
    realuser = getOrigUser(irc, target) or userdata.__dict__.get('remote')
 | 
			
		||||
    log.debug('(%s) relay handle_kill: realuser is %r', irc.name, realuser)
 | 
			
		||||
    log.debug('(%s) relay.handle_kill: realuser is %r', irc.name, realuser)
 | 
			
		||||
    # Target user was remote:
 | 
			
		||||
    if realuser and realuser[0] != irc.name:
 | 
			
		||||
        # We don't allow killing over the relay, so we must respawn the affected
 | 
			
		||||
@ -1002,11 +1092,11 @@ def handle_kill(irc, numeric, command, args):
 | 
			
		||||
                localchan = getRemoteChan(remoteirc, irc, remotechan)
 | 
			
		||||
                if localchan:
 | 
			
		||||
                    modes = getPrefixModes(remoteirc, irc, remotechan, realuser[1])
 | 
			
		||||
                    log.debug('(%s) relay handle_kill: userpair: %s, %s', irc.name, modes, realuser)
 | 
			
		||||
                    log.debug('(%s) relay.handle_kill: userpair: %s, %s', irc.name, modes, realuser)
 | 
			
		||||
                    client = getRemoteUser(remoteirc, irc, realuser[1])
 | 
			
		||||
                    irc.proto.sjoin(getRemoteSid(irc, remoteirc), localchan, [(modes, client)])
 | 
			
		||||
            if userdata and numeric in irc.users:
 | 
			
		||||
                log.info('(%s) Relay claim: Blocked KILL (reason %r) from %s to relay client %s/%s.',
 | 
			
		||||
                log.info('(%s) relay.handle_kill: Blocked KILL (reason %r) from %s to relay client %s/%s.',
 | 
			
		||||
                         irc.name, args['text'], irc.users[numeric].nick,
 | 
			
		||||
                         remoteirc.users[realuser[1]].nick, realuser[0])
 | 
			
		||||
                irc.msg(numeric, "Your kill to %s has been blocked "
 | 
			
		||||
@ -1014,11 +1104,11 @@ def handle_kill(irc, numeric, command, args):
 | 
			
		||||
                                 " users over the relay at this time." % \
 | 
			
		||||
                                 userdata.nick, notice=True)
 | 
			
		||||
            else:
 | 
			
		||||
                log.info('(%s) Relay claim: Blocked KILL (reason %r) from server %s to relay client %s/%s.',
 | 
			
		||||
                log.info('(%s) relay.handle_kill: Blocked KILL (reason %r) from server %s to relay client %s/%s.',
 | 
			
		||||
                         irc.name, args['text'], irc.servers[numeric].name,
 | 
			
		||||
                         remoteirc.users[realuser[1]].nick, realuser[0])
 | 
			
		||||
        else:
 | 
			
		||||
            log.error('(%s) Too many kills received for target %s, aborting!',
 | 
			
		||||
            log.error('(%s) relay.handle_kill: Too many kills received for target %s, aborting!',
 | 
			
		||||
                      irc.name, userdata.nick)
 | 
			
		||||
            irc.disconnect()
 | 
			
		||||
        killcache[irc.name] += 1
 | 
			
		||||
@ -1108,7 +1198,7 @@ utils.add_hook(handle_disconnect, "PYLINK_DISCONNECT")
 | 
			
		||||
def handle_save(irc, numeric, command, args):
 | 
			
		||||
    target = args['target']
 | 
			
		||||
    realuser = getOrigUser(irc, target)
 | 
			
		||||
    log.debug('(%s) relay handle_save: %r got in a nick collision! Real user: %r',
 | 
			
		||||
    log.debug('(%s) relay.handle_save: %r got in a nick collision! Real user: %r',
 | 
			
		||||
                  irc.name, target, realuser)
 | 
			
		||||
    if isRelayClient(irc, target) and realuser:
 | 
			
		||||
        # Nick collision!
 | 
			
		||||
@ -1121,11 +1211,11 @@ def handle_save(irc, numeric, command, args):
 | 
			
		||||
        # floods and such.
 | 
			
		||||
        if savecache.setdefault(irc.name, 0) <= 5:
 | 
			
		||||
            newnick = normalizeNick(irc, remotenet, nick)
 | 
			
		||||
            log.info('(%s) SAVE received for relay client %r (%s), fixing nick to %s',
 | 
			
		||||
            log.info('(%s) relay.handle_save: SAVE received for relay client %r (%s), fixing nick to %s',
 | 
			
		||||
                      irc.name, target, nick, newnick)
 | 
			
		||||
            irc.proto.nick(target, newnick)
 | 
			
		||||
        else:
 | 
			
		||||
            log.warning('(%s) SAVE received for relay client %r (%s), not '
 | 
			
		||||
            log.warning('(%s) relay.handle_save: SAVE received for relay client %r (%s), not '
 | 
			
		||||
                        'fixing nick again due to 5 failed attempts in '
 | 
			
		||||
                        'the last 10 seconds!', irc.name, target, nick)
 | 
			
		||||
        savecache[irc.name] += 1
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user