package de.uni_passau.fim.pkjab.model.xmpp; import java.io.IOException; import java.util.Collections; import java.util.Set; import java.util.TreeSet; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import de.uni_passau.fim.pkjab.model.RestartStreamException; import de.uni_passau.fim.pkjab.model.ConnectionCallback; import de.uni_passau.fim.pkjab.model.tags.AbstractXMLTag; import de.uni_passau.fim.pkjab.model.tags.XMLTag; import de.uni_passau.fim.pkjab.util.Base64; import de.uni_passau.fim.pkjab.util.Stack; public class XMPPReaderLogin extends XMPPReaderTopLevel { //private static final String XMPP_TLS_URI = "urn:ietf:params:xml:ns:xmpp-tls"; private static final String XMPP_SASL_URI = "urn:ietf:params:xml:ns:xmpp-sasl"; private static final XMLTag SASL_MECHANISMS_TAG = new XMLTag("mechanisms", XMPP_SASL_URI); private XMPPAuthHandler auth = null; private Set saslMechanisms = null; // <String> public XMPPReaderLogin(final ConnectionCallback connection) { super(connection); } protected boolean startChild(Stack xmlStack, AbstractXMLTag thisTag, Attributes atts) throws SAXException { boolean result = super.startChild(xmlStack, thisTag, atts); if (thisTag.uri.equals(XMPP_SASL_URI)) { // ignore SASL challenge (challenge, aborted, failure, success) // they are handled in endElement() return true; } else if (thisTag.equals(STREAM_ERROR_TAG)) { /* TODO: handle non-recoverable stream errors (RFC 3920 4.7.3) */ XMPPReaderAdapter newHandler = new XMPPReaderIgnore(this, null); connection.setXMPPReader(newHandler); return newHandler.startElement(xmlStack, thisTag, null, atts); } return result; } protected boolean startGrandchild(Stack xmlStack, AbstractXMLTag thisTag, Attributes atts) throws SAXException { boolean result = super.startGrandchild(xmlStack, thisTag, atts); if (xmlStack.get(1).equals(FEATURES_TAG) && thisTag.equals(SASL_MECHANISMS_TAG)) { saslMechanisms = new TreeSet(); return true; } return result; } protected boolean startFurtherChild(Stack xmlStack, AbstractXMLTag thisTag, AbstractXMLTag lastTag, Attributes atts) throws SAXException { boolean result = super.startFurtherChild(xmlStack, thisTag, lastTag, atts); if (lastTag.equals(SASL_MECHANISMS_TAG)) { // ignore, mechanisms are handled in endElement() return true; } return result; } protected boolean endChild(Stack xmlStack, AbstractXMLTag thisTag, String content) throws IOException, SAXException { //boolean result = super.endChild(xmlStack, thisTag, content); if (thisTag.equals(FEATURES_TAG)) { auth = connection.firstInitWasSuccessful(getFeatures(), saslMechanisms); return true; } else if (thisTag.uri.equals(XMPP_SASL_URI) && (auth != null)) { // handle SASL tags if (thisTag.getName().equals("challenge")) { auth.challenge( content != null ? Base64.decode(content) : null); return true; } else if (thisTag.getName().equals("success")) { auth.successful( content != null ? Base64.decode(content) : null); throw new RestartStreamException(); } // TODO: aborted, failure } return false; } protected boolean endGrandchild(Stack xmlStack, AbstractXMLTag thisTag, String content) throws IOException, SAXException { boolean result = super.endGrandchild(xmlStack, thisTag, content); if (xmlStack.get(1).equals(FEATURES_TAG) && thisTag.equals(SASL_MECHANISMS_TAG)) { saslMechanisms = Collections.unmodifiableSet(saslMechanisms); return true; } return result; } protected boolean endFurtherChild(Stack xmlStack, AbstractXMLTag thisTag, AbstractXMLTag lastTag, String content) throws IOException, SAXException { boolean result = super.endFurtherChild(xmlStack, thisTag, lastTag, content); if (lastTag.uri.equals(XMPP_SASL_URI)) { if (thisTag.getName().equals("mechanism")) { if (content != null) { saslMechanisms.add(content); } else { // this is not fatal, just log System.err.println("Empty SASL mechanism tag"); } return true; } } return result; } }