<commit_before>#
# (C) Copyright 2003 <NAME> <<EMAIL>>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License Version
# 2.1 as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#

import libxml2
import sha
import time
from types import UnicodeType

from stream import Stream,StreamError,FatalStreamError,SASLNotAvailable,SASLMechanismNotAvailable
from stream import StreamAuthenticationError
from iq import Iq
from stanza import common_doc
from jid import JID
from utils import to_utf8,from_utf8

class ClientError(RuntimeError):
	pass

class LegacyAuthenticationError(StreamAuthenticationError):
	pass

class ClientStream(Stream):
	def __init__(self,jid,password=<PASSWORD>,server=None,port=5222,
			auth_methods=["sasl:DIGEST-MD5","digest"],
			enable_tls=0,require_tls=0):
		sasl_mechanisms=[]
		for m in auth_methods:
			if not m.startswith("sasl:"):
				continue
			m=m[5:].upper()
			sasl_mechanisms.append(m)
		Stream.__init__(self,"jabber:client",
					sasl_mechanisms=sasl_mechanisms,
					enable_tls=enable_tls,
					require_tls=require_tls)
		if server:
			self.server=server
		else:
			self.server=jid.domain
		self.port=port
		self.jid=jid
		self.password=password
		self.auth_methods=auth_methods
		self.auth_methods_left=[]
		self.available_auth_methods=None
		self.features_timeout=None
		self.auth_stanza=None

	def connect(self,server=None,port=None):
		if not self.jid.node or not self.jid.resource:
			raise ClientError,"Client JID must have username and resource"
		if server:
			self.server=server
		if port:
			self.port=port
		Stream.connect(self,self.server,self.port,self.jid.domain)

	def accept(self,sock):
		Stream.accept(self,sock,self.jid)

	def post_connect(self):
		if self.initiator:
			self.auth_methods_left=self.auth_methods
			self.try_auth()
		else:
			if "plain" in self.auth_methods or "digest" in self.auth_methods:
				self.set_iq_get_handler("query","jabber:iq:auth",
							self.auth_in_stage1,pre_auth=1)
				self.set_iq_set_handler("query","jabber:iq:auth",
							self.auth_in_stage2, pre_auth=1)

	def idle(self):
		Stream.idle(self)
		if self.features_timeout and self.features_timeout<=time.time():
			self.debug("Timout while waiting for <features/>")
			self.features_timeout=None
			if self.auth_methods_left:
				self.auth_methods_left.pop(0)
			self.try_auth()

	def got_features(self):
		self.debug("Got <features/>")
		Stream.got_features(self)
		self.try_auth()

	def try_auth(self):
		if self.authenticated:
			self.debug("try_auth: already authenticated")
			return
		self.features_timeout=None
		self.debug("trying auth: %r" % (self.auth_methods_left,))
		if not self.auth_methods_left:
			raise AuthenticationError,"No allowed authentication methods available"
		method=self.auth_methods_left[0]
		if method.startswith("sasl:"):
			if self.features:
				self.auth_methods_left.pop(0)
				try:
					self.sasl_authenticate(self.jid.node,self.jid.as_unicode(),
								mechanism=method[5:].upper())
				except (SASLMechanismNotAvailable,SASLNotAvailable),e:
					self.debug("Skipping unavailable auth method: %s" % method)
					return self.try_auth()
			else:
				self.features_timeout=time.time()+60
				self.debug("Must wait for <features/>")
				return
		elif method not in ("plain","digest"):
			self.debug("Skipping unknown auth method: %s" % method)
			return try_auth()
		elif self.available_auth_methods is not None:
			if method in self.available_auth_methods:
				self.auth_methods_left.pop(0)
				self.auth_method_used=method
				if method=="digest":
					self.digest_auth_stage2(self.auth_stanza)
				else:
					self.plain_auth_stage2(self.auth_stanza)
				self.auth_stanza=None
				return
			else:
				self.debug("Skipping unavailable auth method: %s" % method)
		else:
			self.auth_stage1()

	def auth_in_stage1(self,stanza):
		if "plain" not in self.auth_methods and "digest" not in self.auth_methods:
			iq=stanza.make_error_reply("access","forbidden")
			self.send(iq)
			return

		iq=stanza.make_result_reply()
		q=iq.new_query("jabber:iq:auth")
		q.newChild(q.ns(),"username",None)
		q.newChild(q.ns(),"resource",None)
		if "plain" in self.auth_methods:
			q.newChild(q.ns(),"password",None)
		if "digest" in self.auth_methods:
			q.newChild(q.ns(),"digest",None)
		self.send(iq)
		iq.free()<commit_msg>- authentication method negotiation fixed<commit_after>#
# (C) Copyright 2003 <NAME> <<EMAIL>>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License Version
# 2.1 as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#

import libxml2
import sha
import time
from types import UnicodeType

from stream import Stream,StreamError,FatalStreamError,SASLNotAvailable,SASLMechanismNotAvailable
from stream import StreamAuthenticationError
from iq import Iq
from stanza import common_doc
from jid import JID
from utils import to_utf8,from_utf8

class ClientError(RuntimeError):
	pass

class LegacyAuthenticationError(StreamAuthenticationError):
	pass

class ClientStream(Stream):
	def __init__(self,jid,password=<PASSWORD>,server=None,port=5222,
			auth_methods=["sasl:DIGEST-MD5","digest"],
			enable_tls=0,require_tls=0):
		sasl_mechanisms=[]
		for m in auth_methods:
			if not m.startswith("sasl:"):
				continue
			m=m[5:].upper()
			sasl_mechanisms.append(m)
		Stream.__init__(self,"jabber:client",
					sasl_mechanisms=sasl_mechanisms,
					enable_tls=enable_tls,
					require_tls=require_tls)
		if server:
			self.server=server
		else:
			self.server=jid.domain
		self.port=port
		self.jid=jid
		self.password=password
		self.auth_methods=auth_methods
		self.auth_methods_left=[]
		self.available_auth_methods=None
		self.features_timeout=None
		self.auth_stanza=None

	def connect(self,server=None,port=None):
		if not self.jid.node or not self.jid.resource:
			raise ClientError,"Client JID must have username and resource"
		if server:
			self.server=server
		if port:
			self.port=port
		Stream.connect(self,self.server,self.port,self.jid.domain)

	def accept(self,sock):
		Stream.accept(self,sock,self.jid)

	def post_connect(self):
		if self.initiator:
			self.auth_methods_left=self.auth_methods
			self.try_auth()
		else:
			if "plain" in self.auth_methods or "digest" in self.auth_methods:
				self.set_iq_get_handler("query","jabber:iq:auth",
							self.auth_in_stage1,pre_auth=1)
				self.set_iq_set_handler("query","jabber:iq:auth",
							self.auth_in_stage2, pre_auth=1)

	def idle(self):
		Stream.idle(self)
		if self.features_timeout and self.features_timeout<=time.time():
			self.debug("Timout while waiting for <features/>")
			self.features_timeout=None
			if self.auth_methods_left:
				self.auth_methods_left.pop(0)
			self.try_auth()

	def got_features(self):
		self.debug("Got <features/>")
		Stream.got_features(self)
		self.try_auth()

	def try_auth(self):
		if self.authenticated:
			self.debug("try_auth: already authenticated")
			return
		self.features_timeout=None
		self.debug("trying auth: %r" % (self.auth_methods_left,))
		if not self.auth_methods_left:
			raise AuthenticationError,"No allowed authentication methods available"
		method=self.auth_methods_left[0]
		if method.startswith("sasl:"):
			if self.features:
				self.auth_methods_left.pop(0)
				try:
					self.sasl_authenticate(self.jid.node,self.jid.as_unicode(),
								mechanism=method[5:].upper())
				except (SASLMechanismNotAvailable,SASLNotAvailable),e:
					self.debug("Skipping unavailable auth method: %s" % (method,) )
					return self.try_auth()
			elif not self.version:
				self.auth_methods_left.pop(0)
				self.debug("Skipping auth method %s as legacy protocol is in use" % (method,) )
				return self.try_auth()
			else:
				self.features_timeout=time.time()+60
				self.debug("Must wait for <features/>")
				return
		elif method not in ("plain","digest"):
			self.debug("Skipping unknown auth method: %s" % method)
			return self.try_auth()
		elif self.available_auth_methods is not None:
			if method in self.available_auth_methods:
				self.auth_methods_left.pop(0)
				self.auth_method_used=method
				if method=="digest":
					self.digest_auth_stage2(self.auth_stanza)
				else:
					self.plain_auth_stage2(self.auth_stanza)
				self.auth_stanza=None
				return
			else:
				self.debug("Skipping unavailable auth method: %s" % method)
		else:
			self.auth_stage1()

	def auth_in_stage1(self,stanza):
		if "plain" not in self.auth_methods and "digest" not in self.auth_methods:
			iq=stanza.make_error_reply("access","forbidden")
			self.send(iq)
			return

		iq=stanza.make_result_reply()
		q=iq.new_query("jabber:iq:auth")
		q.newChild(q.ns(),"username",None)
		q.newChild(q.ns(),"resource",None)
		if "plain" in self.auth_methods:
			q.newChild(q.ns(),"password",None)
		if "digest" in self.auth_methods:
			q.newChild(q.ns(),"digest",None)
		self.send(iq)
		iq.free()
{'fraction_non_alphanumeric': 0.10939091464656753, 'fraction_numerical': 0.008250152780607048, 'mean_word_length': 4.685581933989577, 'pattern_counts': {'":': 2, '<': 19, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, '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': '623703', 'n_tokens_mistral': 3823, 'n_tokens_neox': 3309, 'n_words': 762}