<commit_before>from twisted.internet import reactor
from twisted.internet.defer import Deferred
from twisted.internet.interfaces import ISSLTransport
from twisted.internet.task import LoopingCall
from twisted.names import client as dnsClient
from twisted.words.protocols import irc
from txircd import version
from txircd.ircbase import IRCBase
from txircd.utils import CaseInsensitiveDictionary, expandIPv6Address, ipIsV4, isValidMetadataKey, ModeType, now, splitMessage

irc.ERR_ALREADYREGISTERED = "462"

class IRCUser(IRCBase):
	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)
	
	def _startDNSResolving(self, timeout):
		ip = self.ip
		if ipIsV4(ip):
			addr = "{}.in-addr.arpa".format(".".join(reversed(ip.split("."))))
		else:
			addr = reversed(expandIPv6Address(ip).replace(":", ""))
			addr = "{}.ip6.arpa".format(".".join(addr))
		resolveDeferred = dnsClient.lookupPointer(addr, ((timeout/2),))
		resolveDeferred.addCallbacks(callback=self._verifyDNSResolution, callbackArgs=(timeout,), errback=self._cancelDNSResolution)
	
	def _verifyDNSResolution(self, result, timeout):
		name = result[0][0].payload.name.name
		if len(name) > self.ircd.config.get("hostname_length", 64):
			self._cancelDNSResolution()
			return 
		resolveDeferred = dnsClient.getHostByName(name, ((timeout/2),))<commit_msg>Do the extra check that we resolved a valid host, since some DNS servers are completely broken<commit_after>from twisted.internet import reactor
from twisted.internet.defer import Deferred
from twisted.internet.interfaces import ISSLTransport
from twisted.internet.task import LoopingCall
from twisted.names import client as dnsClient
from twisted.words.protocols import irc
from txircd import version
from txircd.ircbase import IRCBase
from txircd.utils import CaseInsensitiveDictionary, expandIPv6Address, ipIsV4, isValidHost, isValidMetadataKey, ModeType, now, splitMessage

irc.ERR_ALREADYREGISTERED = "462"

class IRCUser(IRCBase):
	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)
	
	def _startDNSResolving(self, timeout):
		ip = self.ip
		if ipIsV4(ip):
			addr = "{}.in-addr.arpa".format(".".join(reversed(ip.split("."))))
		else:
			addr = reversed(expandIPv6Address(ip).replace(":", ""))
			addr = "{}.ip6.arpa".format(".".join(addr))
		resolveDeferred = dnsClient.lookupPointer(addr, ((timeout/2),))
		resolveDeferred.addCallbacks(callback=self._verifyDNSResolution, callbackArgs=(timeout,), errback=self._cancelDNSResolution)
	
	def _verifyDNSResolution(self, result, timeout):
		name = result[0][0].payload.name.name
		if len(name) > self.ircd.config.get("hostname_length", 64):
			self._cancelDNSResolution()
			return
		if not isValidHost(name):
			self._cancelDNSResolution()
			return
		resolveDeferred = dnsClient.getHostByName(name, ((timeout/2),))
{'fraction_non_alphanumeric': 0.12316249503377036, 'fraction_numerical': 0.007548669050456893, 'mean_word_length': 4.807381776239907, 'pattern_counts': {'":': 6, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4176148', 'n_tokens_mistral': 1802, 'n_tokens_neox': 1636, 'n_words': 357}