You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by ng...@apache.org on 2011/01/16 22:24:45 UTC
svn commit: r1059682 - in /mina/vysper/trunk/server/core/src:
main/java/org/apache/vysper/xmpp/modules/extension/xep007_inbandreg/
main/java/org/apache/vysper/xmpp/protocol/
main/java/org/apache/vysper/xmpp/protocol/worker/
main/java/org/apache/vysper/...
Author: ngn
Date: Sun Jan 16 21:24:44 2011
New Revision: 1059682
URL: http://svn.apache.org/viewvc?rev=1059682&view=rev
Log:
Add support for in-band registration (XEP-0077). Supports adding account and changing password (VYSPER-264)
Added:
mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/modules/extension/xep007_inbandreg/
mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/modules/extension/xep007_inbandreg/InBandRegistrationHandler.java
mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/modules/extension/xep007_inbandreg/InBandRegistrationModule.java
mina/vysper/trunk/server/core/src/test/java/org/apache/vysper/xmpp/modules/extension/xep007_inbandreg/
mina/vysper/trunk/server/core/src/test/java/org/apache/vysper/xmpp/modules/extension/xep007_inbandreg/InBandRegistrationHandlerTestCase.java
Modified:
mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/NamespaceURIs.java
mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/ProtocolWorker.java
mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/worker/EncryptedProtocolWorker.java
mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/worker/StartedProtocolWorker.java
mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/server/ServerMain.java
mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/server/response/ServerErrorResponses.java
Added: mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/modules/extension/xep007_inbandreg/InBandRegistrationHandler.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/modules/extension/xep007_inbandreg/InBandRegistrationHandler.java?rev=1059682&view=auto
==============================================================================
--- mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/modules/extension/xep007_inbandreg/InBandRegistrationHandler.java (added)
+++ mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/modules/extension/xep007_inbandreg/InBandRegistrationHandler.java Sun Jan 16 21:24:44 2011
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.vysper.xmpp.modules.extension.xep007_inbandreg;
+
+import org.apache.vysper.compliance.SpecCompliant;
+import org.apache.vysper.xml.fragment.XMLElement;
+import org.apache.vysper.xml.fragment.XMLSemanticError;
+import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.addressing.EntityFormatException;
+import org.apache.vysper.xmpp.addressing.EntityImpl;
+import org.apache.vysper.xmpp.authorization.AccountCreationException;
+import org.apache.vysper.xmpp.authorization.AccountManagement;
+import org.apache.vysper.xmpp.modules.core.base.handler.DefaultIQHandler;
+import org.apache.vysper.xmpp.protocol.NamespaceURIs;
+import org.apache.vysper.xmpp.server.ServerRuntimeContext;
+import org.apache.vysper.xmpp.server.SessionContext;
+import org.apache.vysper.xmpp.server.SessionState;
+import org.apache.vysper.xmpp.server.response.ServerErrorResponses;
+import org.apache.vysper.xmpp.stanza.IQStanza;
+import org.apache.vysper.xmpp.stanza.IQStanzaType;
+import org.apache.vysper.xmpp.stanza.Stanza;
+import org.apache.vysper.xmpp.stanza.StanzaBuilder;
+import org.apache.vysper.xmpp.stanza.StanzaErrorCondition;
+import org.apache.vysper.xmpp.stanza.StanzaErrorType;
+
+/**
+ * Implementation of <a href="http://xmpp.org/extensions/xep-0077.html">XEP-0077 In-Band Registration</a>.
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+@SpecCompliant(spec = "xep-0077", status = SpecCompliant.ComplianceStatus.IN_PROGRESS, coverage = SpecCompliant.ComplianceCoverage.PARTIAL)
+public class InBandRegistrationHandler extends DefaultIQHandler {
+
+ public InBandRegistrationHandler() {
+ }
+
+ @Override
+ protected boolean verifyNamespace(Stanza stanza) {
+ return verifyInnerNamespace(stanza, NamespaceURIs.JABBER_IQ_REGISTER);
+ }
+
+ @Override
+ public boolean isSessionRequired() {
+ return false;
+ }
+
+ @Override
+ protected Stanza handleGet(IQStanza stanza, ServerRuntimeContext serverRuntimeContext, SessionContext sessionContext) {
+ // <iq type='result' id='reg1'>
+ // <query xmlns='jabber:iq:register'>
+ // <instructions>
+ // Choose a username and password for use with this service.
+ // Please also provide your email address.
+ // </instructions>
+ // <username/>
+ // <password/>
+ // <email/>
+ // </query>
+ // </iq>
+
+ if(sessionContext.getState().equals(SessionState.STARTED)
+ || sessionContext.getState().equals(SessionState.ENCRYPTED)
+ || sessionContext.getState().equals(SessionState.AUTHENTICATED)) {
+ StanzaBuilder stanzaBuilder = StanzaBuilder.createIQStanza(stanza.getTo(), stanza.getFrom(),
+ IQStanzaType.RESULT, stanza.getID());
+ stanzaBuilder.startInnerElement("query", NamespaceURIs.JABBER_IQ_REGISTER)
+ .startInnerElement("instructions", NamespaceURIs.JABBER_IQ_REGISTER)
+ .addText("Choose a username and password for use with this service.")
+ .endInnerElement();
+ if(sessionContext.getState().equals(SessionState.AUTHENTICATED)) {
+ stanzaBuilder.startInnerElement("registered", NamespaceURIs.JABBER_IQ_REGISTER).endInnerElement()
+ .startInnerElement("username", NamespaceURIs.JABBER_IQ_REGISTER)
+ .addText(sessionContext.getInitiatingEntity().getNode())
+ .endInnerElement();
+ } else {
+ stanzaBuilder.startInnerElement("username", NamespaceURIs.JABBER_IQ_REGISTER).endInnerElement()
+ .startInnerElement("password", NamespaceURIs.JABBER_IQ_REGISTER).endInnerElement();
+ }
+ return stanzaBuilder.build();
+ } else {
+ return ServerErrorResponses.getStanzaError(StanzaErrorCondition.SERVICE_UNAVAILABLE, stanza, StanzaErrorType.CANCEL, null, null, null);
+ }
+ }
+
+ @Override
+ protected Stanza handleSet(IQStanza stanza, ServerRuntimeContext serverRuntimeContext, SessionContext sessionContext) {
+ // <iq type='set' id='reg2'>
+ // <query xmlns='jabber:iq:register'>
+ // <username>bill</username>
+ // <password>Calliope</password>
+ // <email>bard@shakespeare.lit</email>
+ // </query>
+ // </iq>
+
+ if(sessionContext.getState().equals(SessionState.STARTED)
+ || sessionContext.getState().equals(SessionState.ENCRYPTED)
+ || sessionContext.getState().equals(SessionState.AUTHENTICATED)) {
+
+ try {
+ XMLElement query = stanza.getSingleInnerElementsNamed("query", NamespaceURIs.JABBER_IQ_REGISTER);
+ XMLElement usernameElm = query.getSingleInnerElementsNamed("username", NamespaceURIs.JABBER_IQ_REGISTER);
+ if(usernameElm == null || usernameElm.getInnerText() == null) throw new XMLSemanticError("Invalid or missing username");
+ String username = usernameElm.getInnerText().getText();
+
+ XMLElement passwordElm = query.getSingleInnerElementsNamed("password", NamespaceURIs.JABBER_IQ_REGISTER);
+ if(passwordElm == null || passwordElm.getInnerText() == null) throw new XMLSemanticError("Invalid or missing password");
+ String password = passwordElm.getInnerText().getText();
+ if(password.trim().length() == 0) throw new XMLSemanticError("Invalid password");
+
+ AccountManagement accountManagement = (AccountManagement) serverRuntimeContext.getStorageProvider(AccountManagement.class);
+ Entity user;
+ if(username.contains("@")) {
+ user = EntityImpl.parse(username);
+ if(!serverRuntimeContext.getServerEnitity().getDomain().equals(user.getDomain())) {
+ throw new XMLSemanticError("Username must be in the same domain as the server");
+ }
+ } else {
+ user = EntityImpl.parse(username + "@" + serverRuntimeContext.getServerEnitity());
+ }
+
+ if(sessionContext.getState().equals(SessionState.AUTHENTICATED)) {
+ if(accountManagement.verifyAccountExists(user)) {
+ // account exists
+ accountManagement.changePassword(user, password);
+ } else {
+ throw new AccountCreationException("Account does not exist");
+ }
+ } else {
+ if(accountManagement.verifyAccountExists(user)) {
+ // account exists
+ throw new AccountCreationException("Account already exists");
+ } else {
+ accountManagement.addUser(user, password);
+ }
+ }
+ return StanzaBuilder.createDirectReply(stanza, true, IQStanzaType.RESULT).build();
+
+ } catch (XMLSemanticError e) {
+ // <iq type='error' id='reg2'>
+ // <query xmlns='jabber:iq:register'>
+ // <username>bill</username>
+ // <password>Calliope</password>
+ // </query>
+ // <error code='406' type='modify'>
+ // <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
+ // </error>
+ // </iq>
+ return ServerErrorResponses.getStanzaError(StanzaErrorCondition.NOT_ACCEPTABLE, stanza, StanzaErrorType.MODIFY, 406, null, null, null);
+ } catch (EntityFormatException e) {
+ return ServerErrorResponses.getStanzaError(StanzaErrorCondition.NOT_ACCEPTABLE, stanza, StanzaErrorType.MODIFY, 406, null, null, null);
+ } catch (AccountCreationException e) {
+ return ServerErrorResponses.getStanzaError(StanzaErrorCondition.CONFLICT, stanza, StanzaErrorType.CANCEL, 409, e.getMessage(), null, null);
+ }
+ } else {
+ return ServerErrorResponses.getStanzaError(StanzaErrorCondition.SERVICE_UNAVAILABLE, stanza, StanzaErrorType.CANCEL, null, null, null);
+ }
+ }
+
+
+}
Added: mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/modules/extension/xep007_inbandreg/InBandRegistrationModule.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/modules/extension/xep007_inbandreg/InBandRegistrationModule.java?rev=1059682&view=auto
==============================================================================
--- mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/modules/extension/xep007_inbandreg/InBandRegistrationModule.java (added)
+++ mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/modules/extension/xep007_inbandreg/InBandRegistrationModule.java Sun Jan 16 21:24:44 2011
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.vysper.xmpp.modules.extension.xep007_inbandreg;
+
+import java.util.List;
+
+import org.apache.vysper.xmpp.modules.DefaultModule;
+import org.apache.vysper.xmpp.protocol.DefaultHandlerDictionary;
+import org.apache.vysper.xmpp.protocol.HandlerDictionary;
+
+/**
+ * A module for <a href="http://xmpp.org/extensions/xep-0077.html">XEP-0077 In-Band Registration</a>.
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class InBandRegistrationModule extends DefaultModule {
+
+ private InBandRegistrationHandler handler = new InBandRegistrationHandler();
+
+ @Override
+ public String getName() {
+ return "XEP-0077 In-Band Registration";
+ }
+
+ @Override
+ public String getVersion() {
+ return "2.3";
+ }
+
+ @Override
+ protected void addHandlerDictionaries(List<HandlerDictionary> dictionary) {
+ dictionary.add(new DefaultHandlerDictionary(handler));
+ }
+}
Modified: mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/NamespaceURIs.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/NamespaceURIs.java?rev=1059682&r1=1059681&r2=1059682&view=diff
==============================================================================
--- mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/NamespaceURIs.java (original)
+++ mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/NamespaceURIs.java Sun Jan 16 21:24:44 2011
@@ -48,6 +48,8 @@ public class NamespaceURIs {
public static final String JABBER_SERVER_DIALBACK = "jabber:server:dialback";
+ public static final String JABBER_IQ_REGISTER = "jabber:iq:register";
+
public static final String JABBER_IQ_ROSTER = "jabber:iq:roster";
// compatibility namespaces
Modified: mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/ProtocolWorker.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/ProtocolWorker.java?rev=1059682&r1=1059681&r2=1059682&view=diff
==============================================================================
--- mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/ProtocolWorker.java (original)
+++ mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/ProtocolWorker.java Sun Jan 16 21:24:44 2011
@@ -24,6 +24,7 @@ import java.util.List;
import java.util.Map;
import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.modules.extension.xep007_inbandreg.InBandRegistrationHandler;
import org.apache.vysper.xmpp.protocol.exception.TLSException;
import org.apache.vysper.xmpp.protocol.worker.AuthenticatedProtocolWorker;
import org.apache.vysper.xmpp.protocol.worker.EncryptedProtocolWorker;
@@ -105,7 +106,8 @@ public class ProtocolWorker implements S
// check as of RFC3920/4.3:
if (sessionStateHolder.getState() != SessionState.AUTHENTICATED) {
// is not authenticated...
- if (XMPPCoreStanza.getWrapper(stanza) != null) {
+ if (XMPPCoreStanza.getWrapper(stanza) != null
+ && !(stanzaHandler instanceof InBandRegistrationHandler)) {
// ... and is a IQ/PRESENCE/MESSAGE stanza!
responseWriter.handleNotAuthorized(sessionContext, stanza);
return;
Modified: mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/worker/EncryptedProtocolWorker.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/worker/EncryptedProtocolWorker.java?rev=1059682&r1=1059681&r2=1059682&view=diff
==============================================================================
--- mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/worker/EncryptedProtocolWorker.java (original)
+++ mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/worker/EncryptedProtocolWorker.java Sun Jan 16 21:24:44 2011
@@ -22,6 +22,7 @@ package org.apache.vysper.xmpp.protocol.
import org.apache.vysper.xmpp.modules.core.base.handler.StreamStartHandler;
import org.apache.vysper.xmpp.modules.core.base.handler.XMLPrologHandler;
import org.apache.vysper.xmpp.modules.core.sasl.handler.AbstractSASLHandler;
+import org.apache.vysper.xmpp.modules.extension.xep007_inbandreg.InBandRegistrationHandler;
import org.apache.vysper.xmpp.modules.extension.xep0220_server_dailback.DbResultHandler;
import org.apache.vysper.xmpp.modules.extension.xep0220_server_dailback.DbVerifyHandler;
import org.apache.vysper.xmpp.protocol.ResponseWriter;
@@ -45,17 +46,20 @@ public class EncryptedProtocolWorker ext
@Override
protected boolean checkState(SessionContext sessionContext, SessionStateHolder sessionStateHolder, Stanza stanza,
StanzaHandler stanzaHandler) {
-
- if (stanzaHandler instanceof StreamStartHandler)
+
+ if (stanzaHandler instanceof StreamStartHandler) {
return true;
- if (stanzaHandler instanceof AbstractSASLHandler)
+ } else if (stanzaHandler instanceof AbstractSASLHandler) {
return true;
- if (stanzaHandler instanceof XMLPrologHandler)
+ } else if (stanzaHandler instanceof XMLPrologHandler) {
return true; // PSI client sends that.
- if (sessionContext.isServerToServer() && stanzaHandler instanceof DbResultHandler)
+ } else if (stanzaHandler instanceof InBandRegistrationHandler) {
+ return true;
+ } else if (sessionContext.isServerToServer() && stanzaHandler instanceof DbResultHandler) {
return true;
- if (sessionContext.isServerToServer() && stanzaHandler instanceof DbVerifyHandler)
+ } else if (sessionContext.isServerToServer() && stanzaHandler instanceof DbVerifyHandler) {
return true;
+ }
ResponseWriter.writeUnsupportedStanzaError(sessionContext);
return false;
}
Modified: mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/worker/StartedProtocolWorker.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/worker/StartedProtocolWorker.java?rev=1059682&r1=1059681&r2=1059682&view=diff
==============================================================================
--- mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/worker/StartedProtocolWorker.java (original)
+++ mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/worker/StartedProtocolWorker.java Sun Jan 16 21:24:44 2011
@@ -20,6 +20,7 @@
package org.apache.vysper.xmpp.protocol.worker;
import org.apache.vysper.xmpp.modules.core.starttls.handler.StartTLSHandler;
+import org.apache.vysper.xmpp.modules.extension.xep007_inbandreg.InBandRegistrationHandler;
import org.apache.vysper.xmpp.modules.extension.xep0220_server_dailback.DbResultHandler;
import org.apache.vysper.xmpp.modules.extension.xep0220_server_dailback.DbVerifyHandler;
import org.apache.vysper.xmpp.protocol.ResponseWriter;
@@ -44,12 +45,15 @@ public class StartedProtocolWorker exten
protected boolean checkState(SessionContext sessionContext, SessionStateHolder sessionStateHolder, Stanza stanza,
StanzaHandler stanzaHandler) {
- if (stanzaHandler instanceof StartTLSHandler)
+ if (stanzaHandler instanceof StartTLSHandler) {
return true;
- if (sessionContext.isServerToServer() && stanzaHandler instanceof DbVerifyHandler)
+ } else if (stanzaHandler instanceof InBandRegistrationHandler) {
return true;
- if (sessionContext.isServerToServer() && stanzaHandler instanceof DbResultHandler)
+ } else if (sessionContext.isServerToServer() && stanzaHandler instanceof DbVerifyHandler) {
return true;
+ } else if (sessionContext.isServerToServer() && stanzaHandler instanceof DbResultHandler) {
+ return true;
+ }
ResponseWriter.writeUnsupportedStanzaError(sessionContext);
return false;
}
Modified: mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/server/ServerMain.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/server/ServerMain.java?rev=1059682&r1=1059681&r2=1059682&view=diff
==============================================================================
--- mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/server/ServerMain.java (original)
+++ mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/server/ServerMain.java Sun Jan 16 21:24:44 2011
@@ -19,12 +19,16 @@
*/
package org.apache.vysper.xmpp.server;
-import org.apache.commons.lang.RandomStringUtils;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
import org.apache.vysper.mina.TCPEndpoint;
import org.apache.vysper.storage.StorageProviderRegistry;
import org.apache.vysper.storage.inmemory.MemoryStorageProviderRegistry;
import org.apache.vysper.xmpp.addressing.Entity;
-import org.apache.vysper.xmpp.addressing.EntityFormatException;
import org.apache.vysper.xmpp.addressing.EntityImpl;
import org.apache.vysper.xmpp.authorization.AccountCreationException;
import org.apache.vysper.xmpp.authorization.AccountManagement;
@@ -32,17 +36,12 @@ import org.apache.vysper.xmpp.modules.Mo
import org.apache.vysper.xmpp.modules.extension.xep0049_privatedata.PrivateDataModule;
import org.apache.vysper.xmpp.modules.extension.xep0050_adhoc_commands.AdhocCommandsModule;
import org.apache.vysper.xmpp.modules.extension.xep0054_vcardtemp.VcardTempModule;
+import org.apache.vysper.xmpp.modules.extension.xep007_inbandreg.InBandRegistrationModule;
import org.apache.vysper.xmpp.modules.extension.xep0092_software_version.SoftwareVersionModule;
import org.apache.vysper.xmpp.modules.extension.xep0119_xmppping.XmppPingModule;
import org.apache.vysper.xmpp.modules.extension.xep0133_service_administration.ServiceAdministrationModule;
import org.apache.vysper.xmpp.modules.extension.xep0202_entity_time.EntityTimeModule;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
/**
* starts the server as a standalone application
*
@@ -102,6 +101,7 @@ public class ServerMain {
server.addModule(new VcardTempModule());
server.addModule(new XmppPingModule());
server.addModule(new PrivateDataModule());
+ server.addModule(new InBandRegistrationModule());
server.addModule(new AdhocCommandsModule());
final ServiceAdministrationModule serviceAdministrationModule = new ServiceAdministrationModule();
// unless admin user account with a secure password is added, this will be not become effective
Modified: mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/server/response/ServerErrorResponses.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/server/response/ServerErrorResponses.java?rev=1059682&r1=1059681&r2=1059682&view=diff
==============================================================================
--- mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/server/response/ServerErrorResponses.java (original)
+++ mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/server/response/ServerErrorResponses.java Sun Jan 16 21:24:44 2011
@@ -93,13 +93,28 @@ public class ServerErrorResponses {
StanzaBuilder responseBuilder = StanzaBuilder.createDirectReply(stanza, true, "error");
- fillErrorStanza(stanza, type, errorCondition, errorText, errorLang, errorConditionElement, responseBuilder);
+ fillErrorStanza(stanza, type, errorCondition, -1, errorText, errorLang, errorConditionElement, responseBuilder);
return responseBuilder.build();
}
+ public static Stanza getStanzaError(StanzaErrorCondition errorCondition, XMPPCoreStanza stanza, StanzaErrorType type, int code,
+ String errorText, String errorLang, XMLElement errorConditionElement) {
+
+ if (stanza != null && "error".equals(stanza.getType())) {
+ return ServerErrorResponses.getStreamError(StreamErrorCondition.UNSUPPORTED_STANZA_TYPE,
+ errorLang, "cannot respond to IQ stanza of type error with the same", null);
+ }
+
+ StanzaBuilder responseBuilder = StanzaBuilder.createDirectReply(stanza, true, "error");
+
+ fillErrorStanza(stanza, type, errorCondition, code, errorText, errorLang, errorConditionElement, responseBuilder);
+
+ return responseBuilder.build();
+ }
+
private static void fillErrorStanza(XMPPCoreStanza stanza, StanzaErrorType type, StanzaErrorCondition errorCondition,
- String errorText, String errorLang, XMLElement errorConditionElement, StanzaBuilder responseBuilder) {
+ int code, String errorText, String errorLang, XMLElement errorConditionElement, StanzaBuilder responseBuilder) {
// inline incoming stanza as of RFC 3920 9.3.1
for (XMLElement innerElement : stanza.getInnerElements()) {
responseBuilder.addPreparedElement(innerElement);
@@ -107,7 +122,9 @@ public class ServerErrorResponses {
// error element
responseBuilder.startInnerElement("error", NamespaceURIs.JABBER_CLIENT).addAttribute("type", type.value());
-
+ if(code != -1) responseBuilder.addAttribute("code", Integer.toString(code));
+
+
// insert defined error condition relating to the stanza error type
responseBuilder.startInnerElement(errorCondition.value(), NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_STANZAS);
responseBuilder.endInnerElement();
Added: mina/vysper/trunk/server/core/src/test/java/org/apache/vysper/xmpp/modules/extension/xep007_inbandreg/InBandRegistrationHandlerTestCase.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/server/core/src/test/java/org/apache/vysper/xmpp/modules/extension/xep007_inbandreg/InBandRegistrationHandlerTestCase.java?rev=1059682&view=auto
==============================================================================
--- mina/vysper/trunk/server/core/src/test/java/org/apache/vysper/xmpp/modules/extension/xep007_inbandreg/InBandRegistrationHandlerTestCase.java (added)
+++ mina/vysper/trunk/server/core/src/test/java/org/apache/vysper/xmpp/modules/extension/xep007_inbandreg/InBandRegistrationHandlerTestCase.java Sun Jan 16 21:24:44 2011
@@ -0,0 +1,305 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.vysper.xmpp.modules.extension.xep007_inbandreg;
+
+import org.apache.vysper.xml.fragment.XMLElement;
+import org.apache.vysper.xml.fragment.XMLSemanticError;
+import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.addressing.EntityImpl;
+import org.apache.vysper.xmpp.authorization.AccountCreationException;
+import org.apache.vysper.xmpp.authorization.AccountManagement;
+import org.apache.vysper.xmpp.protocol.NamespaceURIs;
+import org.apache.vysper.xmpp.protocol.SessionStateHolder;
+import org.apache.vysper.xmpp.server.ServerRuntimeContext;
+import org.apache.vysper.xmpp.server.SessionContext;
+import org.apache.vysper.xmpp.server.SessionState;
+import org.apache.vysper.xmpp.stanza.IQStanzaType;
+import org.apache.vysper.xmpp.stanza.Stanza;
+import org.apache.vysper.xmpp.stanza.StanzaBuilder;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+/**
+ */
+public class InBandRegistrationHandlerTestCase {
+
+ private static final String IQ_ID = "id1";
+
+ private AccountManagement accountManagement = Mockito.mock(AccountManagement.class);
+ private SessionContext sessionContext = Mockito.mock(SessionContext.class);
+ private ServerRuntimeContext serverRuntimeContext = Mockito.mock(ServerRuntimeContext.class);
+ private SessionStateHolder sessionStateHolder = Mockito.mock(SessionStateHolder.class);
+
+ private static final Entity FROM = EntityImpl.parseUnchecked("from@vysper.org");
+ private static final Entity SERVER = EntityImpl.parseUnchecked("vysper.org");
+ private static final Entity EXISTING = EntityImpl.parseUnchecked("existing@vysper.org");
+
+ protected InBandRegistrationHandler handler = new InBandRegistrationHandler();
+
+ @Before
+ public void before() {
+ Mockito.when(serverRuntimeContext.getStorageProvider(AccountManagement.class)).thenReturn(accountManagement);
+ Mockito.when(serverRuntimeContext.getServerEnitity()).thenReturn(SERVER);
+ Mockito.when(accountManagement.verifyAccountExists(EXISTING)).thenReturn(true);
+ Mockito.when(sessionContext.getState()).thenReturn(SessionState.STARTED);
+ }
+
+
+ @Test
+ public void testGetUnauthenticated() throws XMLSemanticError {
+ // <iq type='get' id='reg1'>
+ // <query xmlns='jabber:iq:register'/>
+ // </iq>
+ Stanza get = StanzaBuilder.createIQStanza(FROM, SERVER, IQStanzaType.GET, IQ_ID)
+ .startInnerElement("query", NamespaceURIs.JABBER_IQ_REGISTER).build();
+
+ Stanza response = handler.execute(get, serverRuntimeContext, true, sessionContext, sessionStateHolder).getResponseStanza();
+
+ // <iq type='result' id='reg1'>
+ // <query xmlns='jabber:iq:register'>
+ // <instructions>
+ // Choose a username and password for use with this service.
+ // Please also provide your email address.
+ // </instructions>
+ // <username/>
+ // <password/>
+ // <email/>
+ // </query>
+ // </iq>
+ Assert.assertNotNull(response);
+ Assert.assertEquals("iq", response.getName());
+ Assert.assertEquals(NamespaceURIs.JABBER_CLIENT, response.getNamespaceURI());
+ Assert.assertEquals(IQ_ID, response.getAttributeValue("id"));
+ Assert.assertEquals(SERVER.getFullQualifiedName(), response.getAttributeValue("from"));
+ Assert.assertEquals(FROM.getFullQualifiedName(), response.getAttributeValue("to"));
+
+ XMLElement query = response.getSingleInnerElementsNamed("query", NamespaceURIs.JABBER_IQ_REGISTER);
+ Assert.assertNotNull(query.getSingleInnerElementsNamed("instructions", NamespaceURIs.JABBER_IQ_REGISTER));
+ Assert.assertNotNull(query.getSingleInnerElementsNamed("username", NamespaceURIs.JABBER_IQ_REGISTER));
+ Assert.assertNotNull(query.getSingleInnerElementsNamed("password", NamespaceURIs.JABBER_IQ_REGISTER));
+ }
+
+ @Test
+ public void testGetAuthenticated() throws XMLSemanticError {
+ // <iq type='get' id='reg1'>
+ // <query xmlns='jabber:iq:register'/>
+ // </iq>
+ Stanza get = StanzaBuilder.createIQStanza(EXISTING, SERVER, IQStanzaType.GET, IQ_ID)
+ .startInnerElement("query", NamespaceURIs.JABBER_IQ_REGISTER).build();
+
+ Mockito.when(sessionContext.getState()).thenReturn(SessionState.AUTHENTICATED);
+ Mockito.when(sessionContext.getInitiatingEntity()).thenReturn(EXISTING);
+
+ Stanza response = handler.execute(get, serverRuntimeContext, true, sessionContext, sessionStateHolder).getResponseStanza();
+
+ // <iq type='result' id='reg1'>
+ // <query xmlns='jabber:iq:register'>
+ // <registered/>
+ // <username>juliet</username>
+ // <password>R0m30</password>
+ // <email>juliet@capulet.com</email>
+ // </query>
+ // </iq>
+ Assert.assertNotNull(response);
+ Assert.assertEquals("iq", response.getName());
+ Assert.assertEquals(NamespaceURIs.JABBER_CLIENT, response.getNamespaceURI());
+ Assert.assertEquals(IQ_ID, response.getAttributeValue("id"));
+ Assert.assertEquals("result", response.getAttributeValue("type"));
+ Assert.assertEquals(SERVER.getFullQualifiedName(), response.getAttributeValue("from"));
+ Assert.assertEquals(EXISTING.getFullQualifiedName(), response.getAttributeValue("to"));
+
+ XMLElement query = response.getSingleInnerElementsNamed("query", NamespaceURIs.JABBER_IQ_REGISTER);
+ Assert.assertNotNull(query.getSingleInnerElementsNamed("registered", NamespaceURIs.JABBER_IQ_REGISTER));
+ assertInnerText(EXISTING.getNode(), "username", query);
+ }
+
+ @Test
+ public void testSet() throws XMLSemanticError, AccountCreationException {
+ // <iq type='set' id='reg2'>
+ // <query xmlns='jabber:iq:register'>
+ // <username>bill</username>
+ // <password>Calliope</password>
+ // <email>bard@shakespeare.lit</email>
+ // </query>
+ // </iq>
+ Stanza set = StanzaBuilder.createIQStanza(FROM, SERVER, IQStanzaType.SET, IQ_ID)
+ .startInnerElement("query", NamespaceURIs.JABBER_IQ_REGISTER)
+ .startInnerElement("username", NamespaceURIs.JABBER_IQ_REGISTER).addText(FROM.getNode()).endInnerElement()
+ .startInnerElement("password", NamespaceURIs.JABBER_IQ_REGISTER).addText("password").endInnerElement()
+ .endInnerElement()
+ .build();
+
+ Stanza response = handler.execute(set, serverRuntimeContext, true, sessionContext, sessionStateHolder).getResponseStanza();
+
+ // <iq type='result' id='reg2'/>
+ Assert.assertNotNull(response);
+ Assert.assertEquals("iq", response.getName());
+ Assert.assertEquals(NamespaceURIs.JABBER_CLIENT, response.getNamespaceURI());
+ Assert.assertEquals(IQ_ID, response.getAttributeValue("id"));
+ Assert.assertEquals("result", response.getAttributeValue("type"));
+ Assert.assertEquals(SERVER.getFullQualifiedName(), response.getAttributeValue("from"));
+ Assert.assertEquals(FROM.getFullQualifiedName(), response.getAttributeValue("to"));
+ Assert.assertEquals(0, response.getInnerElements().size());
+
+ Mockito.verify(accountManagement).addUser(FROM, "password");
+ }
+
+ @Test
+ public void testSetExisting() throws XMLSemanticError, AccountCreationException {
+ // <iq type='set' id='reg2'>
+ // <query xmlns='jabber:iq:register'>
+ // <username>bill</username>
+ // <password>Calliope</password>
+ // <email>bard@shakespeare.lit</email>
+ // </query>
+ // </iq>
+ Stanza set = StanzaBuilder.createIQStanza(EXISTING, SERVER, IQStanzaType.SET, IQ_ID)
+ .startInnerElement("query", NamespaceURIs.JABBER_IQ_REGISTER)
+ .startInnerElement("username", NamespaceURIs.JABBER_IQ_REGISTER).addText(EXISTING.getNode()).endInnerElement()
+ .startInnerElement("password", NamespaceURIs.JABBER_IQ_REGISTER).addText("password").endInnerElement()
+ .endInnerElement()
+ .build();
+
+ Stanza response = handler.execute(set, serverRuntimeContext, true, sessionContext, sessionStateHolder).getResponseStanza();
+
+ // <iq type='error' id='reg2'>
+ // <query xmlns='jabber:iq:register'>
+ // <username>bill</username>
+ // <password>m1cro$oft</password>
+ // <email>billg@bigcompany.com</email>
+ // </query>
+ // <error code='409' type='cancel'>
+ // <conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
+ // </error>
+ // </iq>
+ Assert.assertNotNull(response);
+ Assert.assertEquals("iq", response.getName());
+ Assert.assertEquals(NamespaceURIs.JABBER_CLIENT, response.getNamespaceURI());
+ Assert.assertEquals(IQ_ID, response.getAttributeValue("id"));
+ Assert.assertEquals("error", response.getAttributeValue("type"));
+ Assert.assertEquals(SERVER.getFullQualifiedName(), response.getAttributeValue("from"));
+ Assert.assertEquals(EXISTING.getFullQualifiedName(), response.getAttributeValue("to"));
+
+ XMLElement query = response.getSingleInnerElementsNamed("query", NamespaceURIs.JABBER_IQ_REGISTER);
+ assertInnerText(EXISTING.getNode(), "username", query);
+ assertInnerText("password", "password", query);
+
+ XMLElement error = response.getSingleInnerElementsNamed("error", NamespaceURIs.JABBER_CLIENT);
+ Assert.assertEquals("409", error.getAttributeValue("code"));
+ Assert.assertEquals("cancel", error.getAttributeValue("type"));
+ Assert.assertNotNull(error.getSingleInnerElementsNamed("conflict", NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_STANZAS));
+
+ Mockito.verify(accountManagement, Mockito.never()).addUser(EXISTING, "password");
+ }
+
+ @Test
+ public void testSetMissingPassword() throws XMLSemanticError, AccountCreationException {
+ // <iq type='set' id='reg2'>
+ // <query xmlns='jabber:iq:register'>
+ // <username>bill</username>
+ // <password>Calliope</password>
+ // <email>bard@shakespeare.lit</email>
+ // </query>
+ // </iq>
+ Stanza set = StanzaBuilder.createIQStanza(FROM, SERVER, IQStanzaType.SET, IQ_ID)
+ .startInnerElement("query", NamespaceURIs.JABBER_IQ_REGISTER)
+ .startInnerElement("username", NamespaceURIs.JABBER_IQ_REGISTER).addText(FROM.getNode()).endInnerElement()
+ .endInnerElement()
+ .build();
+
+ Stanza response = handler.execute(set, serverRuntimeContext, true, sessionContext, sessionStateHolder).getResponseStanza();
+
+ // <iq type='error' id='reg2'>
+ // <query xmlns='jabber:iq:register'>
+ // <username>bill</username>
+ // <password>Calliope</password>
+ // </query>
+ // <error code='406' type='modify'>
+ // <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
+ // </error>
+ // </iq>
+ Assert.assertNotNull(response);
+ Assert.assertEquals("iq", response.getName());
+ Assert.assertEquals(NamespaceURIs.JABBER_CLIENT, response.getNamespaceURI());
+ Assert.assertEquals(IQ_ID, response.getAttributeValue("id"));
+ Assert.assertEquals("error", response.getAttributeValue("type"));
+ Assert.assertEquals(SERVER.getFullQualifiedName(), response.getAttributeValue("from"));
+ Assert.assertEquals(FROM.getFullQualifiedName(), response.getAttributeValue("to"));
+
+ XMLElement query = response.getSingleInnerElementsNamed("query", NamespaceURIs.JABBER_IQ_REGISTER);
+ assertInnerText(FROM.getNode(), "username", query);
+
+ XMLElement error = response.getSingleInnerElementsNamed("error", NamespaceURIs.JABBER_CLIENT);
+ Assert.assertEquals("406", error.getAttributeValue("code"));
+ Assert.assertEquals("modify", error.getAttributeValue("type"));
+ Assert.assertNotNull(error.getSingleInnerElementsNamed("not-acceptable", NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_STANZAS));
+
+ Mockito.verify(accountManagement, Mockito.never()).addUser(EXISTING, "password");
+ }
+
+ @Test
+ public void testSetChangePassword() throws XMLSemanticError, AccountCreationException {
+ // <iq type='set' id='reg2'>
+ // <query xmlns='jabber:iq:register'>
+ // <username>bill</username>
+ // <password>Calliope</password>
+ // <email>bard@shakespeare.lit</email>
+ // </query>
+ // </iq>
+ Stanza set = StanzaBuilder.createIQStanza(EXISTING, SERVER, IQStanzaType.SET, IQ_ID)
+ .startInnerElement("query", NamespaceURIs.JABBER_IQ_REGISTER)
+ .startInnerElement("username", NamespaceURIs.JABBER_IQ_REGISTER).addText(EXISTING.getNode()).endInnerElement()
+ .startInnerElement("password", NamespaceURIs.JABBER_IQ_REGISTER).addText("password").endInnerElement()
+ .endInnerElement()
+ .build();
+
+ Mockito.when(sessionContext.getState()).thenReturn(SessionState.AUTHENTICATED);
+ Mockito.when(sessionContext.getInitiatingEntity()).thenReturn(EXISTING);
+
+ Stanza response = handler.execute(set, serverRuntimeContext, true, sessionContext, sessionStateHolder)
+ .getResponseStanza();
+
+ // <iq type='result' id='reg2'/>
+ Assert.assertNotNull(response);
+ Assert.assertEquals("iq", response.getName());
+ Assert.assertEquals(NamespaceURIs.JABBER_CLIENT, response.getNamespaceURI());
+ Assert.assertEquals(IQ_ID, response.getAttributeValue("id"));
+ Assert.assertEquals("result", response.getAttributeValue("type"));
+ Assert.assertEquals(SERVER.getFullQualifiedName(), response.getAttributeValue("from"));
+ Assert.assertEquals(EXISTING.getFullQualifiedName(), response.getAttributeValue("to"));
+ Assert.assertEquals(0, response.getInnerElements().size());
+
+ Mockito.verify(accountManagement).changePassword(EXISTING, "password");
+ }
+
+
+ private void assertInnerText(String expected, String name, XMLElement parent) {
+ try {
+ Assert.assertEquals(expected,
+ parent.getSingleInnerElementsNamed(name, NamespaceURIs.JABBER_IQ_REGISTER).getInnerText().getText());
+ } catch (XMLSemanticError e) {
+ Assert.fail("Incorrect number of elements: " + e.getMessage());
+ }
+
+ }
+
+}