'Perform next SASL auth step. Used internally.'

def SASLHandler(self, conn, challenge):

    if (challenge.getNamespace() != NS_SASL):
        return
    if (challenge.getName() == 'failure'):
        self.startsasl = 'failure'
        try:
            reason = challenge.getChildren()[0]
        except:
            reason = challenge
        self.DEBUG(('Failed    SASL    authentification:    %s' % reason), 'error')
        raise NodeProcessed
    elif (challenge.getName() == 'success'):
        self.startsasl = 'success'
        self.DEBUG('Successfully    authenticated    with    remote    server.', 'ok')
        handlers = self._owner.Dispatcher.dumpHandlers()
        self._owner.Dispatcher.PlugOut()
        dispatcher.Dispatcher().PlugIn(self._owner)
        self._owner.Dispatcher.restoreHandlers(handlers)
        self._owner.User = self.username
        raise NodeProcessed
    incoming_data = challenge.getData()
    chal = {}
    data = base64.decodestring(incoming_data)
    self.DEBUG(('Got    challenge:' + data), 'ok')
    for pair in re.findall('(\\w+\\s*=\\s*(?:(?:"[^"]+")|(?:[^,]+)))', data):
        (key, value) = [x.strip() for x in pair.split('=', 1)]
        if ((value[:1] == '"') and (value[(-1):] == '"')):
            value = value[1:(-1)]
        chal[key] = value
    if (chal.has_key('qop') and ('auth' in [x.strip() for x in chal['qop'].split(',')])):
        resp = {}
        resp['username'] = self.username
        resp['realm'] = self._owner.Server
        resp['nonce'] = chal['nonce']
        cnonce = ''
        for i in range(7):
            cnonce += hex(int(((random.random() * 65536) * 4096)))[2:]
        resp['cnonce'] = cnonce
        resp['nc'] = '00000001'
        resp['qop'] = 'auth'
        resp['digest-uri'] = ('xmpp/' + self._owner.Server)
        A1 = C([H(C([resp['username'], resp['realm'], self.password])), resp['nonce'], resp['cnonce']])
        A2 = C(['AUTHENTICATE', resp['digest-uri']])
        response = HH(C([HH(A1), resp['nonce'], resp['nc'], resp['cnonce'], resp['qop'], HH(A2)]))
        resp['response'] = response
        resp['charset'] = 'utf-8'
        sasl_data = ''
        for key in ['charset', 'username', 'realm', 'nonce', 'nc', 'cnonce', 'digest-uri', 'response', 'qop']:
            if (key in ['nc', 'qop', 'response', 'charset']):
                sasl_data += ('%s=%s,' % (key, resp[key]))
            else:
                sasl_data += ('%s="%s",' % (key, resp[key]))
        node = Node('response', attrs={'xmlns': NS_SASL}, payload=[base64.encodestring(sasl_data[:(-1)]).replace('\r', '').replace('\n', '')])
        self._owner.send(node.__str__())
    elif chal.has_key('rspauth'):
        self._owner.send(Node('response', attrs={'xmlns': NS_SASL}).__str__())
    else:
        self.startsasl = 'failure'
        self.DEBUG('Failed    SASL    authentification:    unknown    challenge', 'error')
    raise NodeProcessed
