Beispiel #1
0
 def __init__(self, ircd, name):
     if not isValidChannelName(name):
         raise InvalidChannelNameError
     self.ircd = ircd
     self.name = name[:self.ircd.config.get("channel_name_length", 64)]
     self.users = WeakKeyDictionary()
     self.modes = {}
     self.existedSince = now()
     self.topic = ""
     self.topicSetter = ""
     self.topicTime = now()
     self._metadata = CaseInsensitiveDictionary()
     self.cache = {}
Beispiel #2
0
 def load(self):
     self.targetIndex = CaseInsensitiveDictionary()
     # We'll run a cleaner every minute. The reason we do this is that, since there can be multiple
     # notified users for a target, the index is implemented as a CaseInsensitiveDictionary pointing
     # to WeakSets as opposed to simply a CaseInsensitiveDictionary(WeakValueDictionary). Because of
     # this, we'll need to check for empty WeakSets on occasion and garbage-collect them to prevent
     # memory getting full.
     self.indexCleaner = LoopingCall(self.cleanIndex)
     self.indexCleaner.start(60, now=False)
     if "unloading-monitor" in self.ircd.dataCache:
         del self.ircd.dataCache["unloading-monitor"]
         return
     if "cap-add" in self.ircd.functionCache:
         self.ircd.functionCache["cap-add"]("metadata-notify")
Beispiel #3
0
    def __init__(self, ircd, ip, uuid=None, host=None):
        self.ircd = ircd
        self.uuid = ircd.createUUID() if uuid is None else uuid

        registrationTimeout = self.ircd.config.get("user_registration_timeout",
                                                   10)

        self.nick = None
        self.ident = None
        if ip[0] == ":":  # Normalize IPv6 address for IRC
            ip = "0{}".format(ip)
        if host is None:
            self.realHost = ip
        else:
            self.realHost = host
        self.ip = ip
        self._hostStack = []
        self._hostsByType = {}
        self.gecos = None
        self._metadata = CaseInsensitiveDictionary()
        self.cache = {}
        self.channels = []
        self.modes = {}
        self.connectedSince = now()
        self.nickSince = now()
        self.idleSince = now()
        self._registerHolds = set(("connection", "dns", "NICK", "USER"))
        self.disconnectedDeferred = Deferred()
        self._messageBatches = {}
        self._errorBatchName = None
        self._errorBatch = []
        self.ircd.users[self.uuid] = self
        self.localOnly = False
        self.secureConnection = False
        self._pinger = LoopingCall(self._ping)
        self._registrationTimeoutTimer = reactor.callLater(
            registrationTimeout, self._timeoutRegistration)
        self._connectHandlerTimer = None
        self._startDNSResolving(registrationTimeout)
Beispiel #4
0
 def __init__(self, config, options = None, sslCert = None):
     reactor.addSystemEventTrigger("before", "shutdown", self.cleanup)
     self.dead = False
     
     self.config = config
     self.version = "txircd-{}".format(__version__)
     self.created = now()
     self.servers = CaseInsensitiveDictionary()
     self.users = CaseInsensitiveDictionary()
     self.userid = {}
     self.channels = CaseInsensitiveDictionary()
     self.peerConnections = {}
     self.ssl_cert = sslCert
     self.client_ports = {}
     self.server_ports = {}
     self.modules = {}
     self.module_abilities = {}
     self.actions = {
         "connect": [],
         "register": [],
         "welcome": [],
         "join": [],
         "joinmessage": [],
         "nick": [],
         "quit": [],
         "topic": [],
         "mode": [],
         "nameslistentry": [],
         "chancreate": [],
         "chandestroy": [],
         "commandextra": [],
         "commandunknown": [],
         "commandpermission": [],
         "metadataupdate": [],
         "recvdata": [],
         "senddata": [],
         "netmerge": [],
         "netsplit": []
     }
     self.commands = {}
     self.channel_modes = [{}, {}, {}, {}]
     self.channel_mode_type = {}
     self.user_modes = [{}, {}, {}, {}]
     self.user_mode_type = {}
     self.prefixes = {}
     self.prefix_symbols = {}
     self.prefix_order = []
     self.server_commands = {}
     self.module_data_cache = {}
     self.server_factory = None
     self.common_modules = set()
     log.msg("Loading module data...")
     try:
         with open("data.yaml", "r") as dataFile:
             self.serialized_data = yaml.safe_load(dataFile)
             if self.serialized_data is None:
                 self.serialized_data = {}
     except IOError:
         self.serialized_data = {}
     self.isupport = {}
     self.usercount = {
         "localmax": 0,
         "globalmax": 0
     }
     log.msg("Loading configuration...")
     self.servconfig = {}
     if not options:
         options = {}
     self.load_options(options)
     self.name = self.servconfig["server_name"]
     log.msg("Loading modules...")
     self.all_module_load()
     self.save_serialized_deferred = None
     self.autoconnect_servers = LoopingCall(self.server_autoconnect)
     self.autoconnect_servers.start(60, now=False) # The server factory isn't added to here yet
     # Fill in the default ISUPPORT dictionary once config and modules are loaded, since some values depend on those
     self.isupport["CASEMAPPING"] = "rfc1459"
     self.isupport["CHANMODES"] = ",".join(["".join(modedict.keys()) for modedict in self.channel_modes])
     self.isupport["CHANNELLEN"] = "64"
     self.isupport["CHANTYPES"] = "#"
     self.isupport["MODES"] = 20
     self.isupport["NETWORK"] = self.servconfig["server_network_name"]
     self.isupport["NICKLEN"] = "32"
     self.isupport["PREFIX"] = "({}){}".format("".join(self.prefix_order), "".join([self.prefixes[mode][0] for mode in self.prefix_order]))
     self.isupport["STATUSMSG"] = "".join([self.prefixes[mode][0] for mode in self.prefix_order])
     self.isupport["TOPICLEN"] = "316"
     self.isupport["USERMODES"] = ",".join(["".join(modedict.keys()) for modedict in self.user_modes])
Beispiel #5
0
 def __init__(self):
     self.banList = CaseInsensitiveDictionary()
Beispiel #6
0
 def __init__(self):
     self.exceptList = CaseInsensitiveDictionary()
Beispiel #7
0
 def __init__(self):
     self.history = CaseInsensitiveDictionary()
Beispiel #8
0
class Logger(Module):
    # This is to help save from excessive disk I/O by holding the log files instead of constantly opening/flushing/closing them
    logfiles = CaseInsensitiveDictionary()

    def timePrefix(self):
        nowtime = now()
        return "[{:02d}:{:02d}:{:02d}]".format(nowtime.hour, nowtime.minute,
                                               nowtime.second)

    def writeLog(self, chan, line):
        line = "{} {}\n".format(self.timePrefix(), line)
        if chan.name not in self.logfiles:
            self.logfiles[chan.name] = DailyLogFile(
                chan.name, self.ircd.servconfig["app_log_dir"])
        logFile = self.logfiles[chan.name]
        if logFile.shouldRotate():
            logFile.rotate()
        logFile.write(line)

    def logMsg(self, cmd, data):
        if cmd in ["PRIVMSG", "NOTICE"]:
            if "targetchan" not in data or not data["targetchan"]:
                return
            user = data["user"]
            message = data["message"]
            if cmd == "PRIVMSG":
                if message[0:7] == "\x01ACTION":
                    message = data["message"][8:]
                    if message[-1] == "\x01":
                        message = message[:-1]
                    for index, chan in enumerate(data["targetchan"]):
                        prefix = self.ircd.prefixes[
                            chan.users[user]
                            [0]][0] if user in chan.users and chan.users[
                                user] else ""
                        if data["chanmod"][index]:
                            self.writeLog(
                                chan, "*({}#) {}{} {}".format(
                                    data["chanmod"][index], prefix,
                                    user.nickname, message))
                        else:
                            self.writeLog(
                                chan,
                                "* {}{} {}".format(prefix, user.nickname,
                                                   message))
                else:
                    for index, chan in enumerate(data["targetchan"]):
                        prefix = self.ircd.prefixes[
                            chan.users[user]
                            [0]][0] if user in chan.users and chan.users[
                                user] else ""
                        if data["chanmod"][index]:
                            self.writeLog(
                                chan,
                                "<{}#:{}{}> {}".format(data["chanmod"][index],
                                                       prefix, user.nickname,
                                                       message))
                        else:
                            self.writeLog(
                                chan,
                                "<{}{}> {}".format(prefix, user.nickname,
                                                   message))
            elif cmd == "NOTICE":
                for index, chan in enumerate(data["targetchan"]):
                    prefix = self.ircd.prefixes[chan.users[user][0]][
                        0] if user in chan.users and chan.users[user] else ""
                    if data["chanmod"][index]:
                        self.writeLog(
                            chan,
                            "-{}#:{}{}- {}".format(data["chanmod"][index],
                                                   prefix, user.nickname,
                                                   message))
                    else:
                        self.writeLog(
                            chan, "-{}{}- {}".format(prefix, user.nickname,
                                                     message))
        elif cmd == "PART":
            if "reason" in data:
                for chan in data["targetchan"]:
                    self.writeLog(
                        chan, "< {} has left the channel: {}".format(
                            data["user"].nickname, data["reason"]))
            else:
                for chan in data["targetchan"]:
                    self.writeLog(
                        chan, "< {} has left the channel".format(
                            data["user"].nickname))
        elif cmd == "KICK":
            self.writeLog(
                data["targetchan"], "< {} was kicked by {} ({})".format(
                    data["targetuser"].nickname, data["user"].nickname,
                    data["reason"]))

    def logJoin(self, user, channel):
        self.writeLog(channel,
                      "> {} has joined the channel".format(user.nickname))

    def logNick(self, user, oldNick):
        for cdata in self.ircd.channels.itervalues():
            if user in cdata.users:
                self.writeLog(
                    cdata,
                    "! {} is now known as {}".format(oldNick, user.nickname))

    def logQuit(self, user, reason):
        for cdata in self.ircd.channels.itervalues():
            if user in cdata.users:
                self.writeLog(
                    cdata, "< {} has quit: {}".format(user.nickname, reason))

    def logTopic(self, channel, topic, setter):
        self.writeLog(
            channel,
            "! {} has set the channel topic: {}".format(setter, topic))

    def logMode(self, channel, source, modeLine, modesChanged):
        # Filter out users so that we only work on channels
        try:
            channel.name
        except AttributeError:
            return
        self.writeLog(channel,
                      "! {} has set modes {}".format(source, modeLine))

    def onDestroy(self, channel):
        if channel.name in self.logfiles:
            self.logfiles[channel.name].close()
            del self.logfiles[channel.name]

    def closeAllFiles(self):
        for logFile in self.logfiles.itervalues():
            logFile.close()
        self.logfiles.clear()