Commit 3b625223 authored by Guus der Kinderen's avatar Guus der Kinderen

Merge remote-tracking branch 'upstream/master' into refactor-connectionmanagement

Conflicts:
	src/java/org/jivesoftware/openfire/XMPPServer.java
	src/java/org/jivesoftware/openfire/net/SASLAuthentication.java
	src/java/org/jivesoftware/openfire/net/ServerStanzaHandler.java
	src/java/org/jivesoftware/openfire/session/LocalClientSession.java
	src/java/org/jivesoftware/util/CertificateManager.java
	src/web/WEB-INF/admin.tld
parents 155bb672 1ca70b61
......@@ -23,8 +23,8 @@
<!-- GLOBAL PROPERTIES -->
<!-- ======================================================================================= -->
<property name="version.major" value="3"/>
<property name="version.minor" value="11"/>
<property name="version.major" value="4"/>
<property name="version.minor" value="0"/>
<property name="version.revision" value="0"/>
<property name="version.extra" value="alpha"/> <!-- For 'beta' or 'alpha' -->
......
......@@ -158,10 +158,6 @@ XEPs that only require client-side support are omitted.</p>
<td><a href="http://www.xmpp.org/extensions/xep-0082.html">XEP-0082</a>: XMPP Date and Time Profiles</td>
</tr><tr>
<td><a href="http://www.xmpp.org/extensions/xep-0086.html">XEP-0086</a>: Error Condition Mappings</td>
</tr><tr>
<td><a href="http://www.xmpp.org/extensions/xep-0090.html">XEP-0090</a>: Legacy Entity Time</td>
</tr><tr>
<td><a href="http://www.xmpp.org/extensions/xep-0091.html">XEP-0091</a>: Legacy Delayed Delivery</td>
</tr><tr>
<td><a href="http://www.xmpp.org/extensions/xep-0092.html">XEP-0092</a>: Software Version</td>
</tr><tr>
......
......@@ -38,7 +38,6 @@
<module interface="org.jivesoftware.openfire.handler.IQPrivateHandler" implementation="org.jivesoftware.openfire.handler.IQPrivateHandler" />
<module interface="org.jivesoftware.openfire.handler.IQRegisterHandler" implementation="org.jivesoftware.openfire.handler.IQRegisterHandler" />
<module interface="org.jivesoftware.openfire.handler.IQRosterHandler" implementation="org.jivesoftware.openfire.handler.IQRosterHandler" />
<module interface="org.jivesoftware.openfire.handler.IQTimeHandler" implementation="org.jivesoftware.openfire.handler.IQTimeHandler" />
<module interface="org.jivesoftware.openfire.handler.IQEntityTimeHandler" implementation="org.jivesoftware.openfire.handler.IQEntityTimeHandler" />
<module interface="org.jivesoftware.openfire.handler.IQvCardHandler" implementation="org.jivesoftware.openfire.handler.IQvCardHandler" />
<module interface="org.jivesoftware.openfire.handler.IQVersionHandler" implementation="org.jivesoftware.openfire.handler.IQVersionHandler" />
......
......@@ -459,25 +459,6 @@ public class DbConnectionManager {
}
}
/**
* Creates a scroll insensitive Statement if the JDBC driver supports it, or a normal
* Statement otherwise.
*
* @param con the database connection.
* @return a Statement
* @throws SQLException if an error occurs.
*/
@Deprecated
public static Statement createScrollableStatement(Connection con) throws SQLException {
if (isScrollResultsSupported()) {
return con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
}
else {
return con.createStatement();
}
}
/**
* Creates a scroll insensitive PreparedStatement if the JDBC driver supports it, or a normal
* PreparedStatement otherwise.
......
......@@ -269,21 +269,6 @@ public interface Connection extends Closeable {
*/
public void setXMPPVersion(int majorVersion, int minorVersion);
/**
* Returns the language code that should be used for this connection
* (e.g. "en").
*
* @return the language code for the connection.
*/
public String getLanguage();
/**
* Sets the language code that should be used for this connection (e.g. "en").
*
* @param language the language code.
*/
public void setLanaguage(String language);
/**
* Returns true if the connection is using compression.
*
......
......@@ -433,6 +433,12 @@ public class IQRouter extends BasicModule {
Log.error("Cannot reply an IQ error to another IQ error: " + originalPacket.toXML());
return;
}
if (originalPacket.getFrom() == null) {
if (Log.isDebugEnabled()) {
Log.debug("Original IQ has no sender for reply; dropped: " + originalPacket.toXML());
}
return;
}
IQ reply = IQ.createResultIQ(originalPacket);
reply.setChildElement(originalPacket.getChildElement().createCopy());
reply.setError(condition);
......
......@@ -222,10 +222,6 @@ public class OfflineMessageStore extends BasicModule implements UserEventListene
Element delay = message.addChildElement("delay", "urn:xmpp:delay");
delay.addAttribute("from", XMPPServer.getInstance().getServerInfo().getXMPPDomain());
delay.addAttribute("stamp", XMPPDateTimeFormat.format(creationDate));
// Add a legacy delayed delivery (XEP-0091) element to the message. XEP is obsolete and support should be dropped in future.
delay = message.addChildElement("x", "jabber:x:delay");
delay.addAttribute("from", XMPPServer.getInstance().getServerInfo().getXMPPDomain());
delay.addAttribute("stamp", XMPPDateTimeFormat.formatOld(creationDate));
}
messages.add(message);
}
......@@ -290,10 +286,6 @@ public class OfflineMessageStore extends BasicModule implements UserEventListene
Element delay = message.addChildElement("delay", "urn:xmpp:delay");
delay.addAttribute("from", XMPPServer.getInstance().getServerInfo().getXMPPDomain());
delay.addAttribute("stamp", XMPPDateTimeFormat.format(creationDate));
// Add a legacy delayed delivery (XEP-0091) element to the message. XEP is obsolete and support should be dropped in future.
delay = message.addChildElement("x", "jabber:x:delay");
delay.addAttribute("from", XMPPServer.getInstance().getServerInfo().getXMPPDomain());
delay.addAttribute("stamp", XMPPDateTimeFormat.formatOld(creationDate));
}
}
catch (Exception e) {
......
......@@ -30,6 +30,7 @@ import java.util.Deque;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
......@@ -331,10 +332,11 @@ public class SessionManager extends BasicModule implements ClusterEventListener/
* stream ID.
*
* @param conn the connection to create the session from.
* @param language The language to use for the new session.
* @return a newly created session.
*/
public LocalClientSession createClientSession(Connection conn) {
return createClientSession(conn, nextStreamID());
public LocalClientSession createClientSession(Connection conn, Locale language) {
return createClientSession(conn, nextStreamID(), language);
}
/**
......@@ -345,10 +347,22 @@ public class SessionManager extends BasicModule implements ClusterEventListener/
* @return a newly created session.
*/
public LocalClientSession createClientSession(Connection conn, StreamID id) {
return createClientSession( conn, id, null);
}
/**
* Creates a new <tt>ClientSession</tt> with the specified streamID.
*
* @param conn the connection to create the session from.
* @param id the streamID to use for the new session.
* @param language The language to use for the new session.
* @return a newly created session.
*/
public LocalClientSession createClientSession(Connection conn, StreamID id, Locale language) {
if (serverName == null) {
throw new IllegalStateException("Server not initialized");
}
LocalClientSession session = new LocalClientSession(serverName, conn, id);
LocalClientSession session = new LocalClientSession(serverName, conn, id, language);
conn.init(session);
// Register to receive close notification on this session so we can
// remove and also send an unavailable presence if it wasn't
......@@ -362,13 +376,20 @@ public class SessionManager extends BasicModule implements ClusterEventListener/
return session;
}
public HttpSession createClientHttpSession(long rid, InetAddress address, StreamID id, HttpConnection connection)
/**
* Creates a new <tt>ClientSession</tt> with the specified streamID.
*
* @param conn the connection to create the session from.
* @param id the streamID to use for the new session.
* @return a newly created session.
*/
public HttpSession createClientHttpSession(long rid, InetAddress address, StreamID id, HttpConnection connection, Locale language)
throws UnauthorizedException {
if (serverName == null) {
throw new UnauthorizedException("Server not initialized");
}
PacketDeliverer backupDeliverer = server.getPacketDeliverer();
HttpSession session = new HttpSession(backupDeliverer, serverName, address, id, rid, connection);
HttpSession session = new HttpSession(backupDeliverer, serverName, address, id, rid, connection, language);
Connection conn = session.getConnection();
conn.init(session);
conn.registerCloseListener(clientSessionListener, session);
......@@ -1257,11 +1278,8 @@ public class SessionManager extends BasicModule implements ClusterEventListener/
if (unacked.packet instanceof Message) {
Message m = (Message)unacked.packet;
Element delayInformation = m.addChildElement("delay", "urn:xmpp:delay");
Element delayInformationOld = m.addChildElement("x", "jabber:x:delay");
delayInformation.addAttribute("stamp", XMPPDateTimeFormat.format(unacked.timestamp));
delayInformationOld.addAttribute("stamp", XMPPDateTimeFormat.formatOld(unacked.timestamp));
delayInformation.addAttribute("from", serverAddress.toBareJID());
delayInformationOld.addAttribute("from", serverAddress.toBareJID());
}
router.route(unacked.packet);
}
......
......@@ -316,7 +316,7 @@ public class XMPPServer {
host = "127.0.0.1";
}
version = new Version(3, 11, 0, Version.ReleaseStatus.Alpha, -1);
version = new Version(4, 0, 0, Version.ReleaseStatus.Alpha, -1);
if ("true".equals(JiveGlobals.getXMLProperty("setup"))) {
setupMode = false;
}
......@@ -483,7 +483,8 @@ public class XMPPServer {
@SuppressWarnings("unchecked")
private void loadModules() {
File modulesXml = new File(JiveGlobals.getHomeDirectory(), "conf/modules.xml");
File modulesXml = new File(JiveGlobals.getHomeDirectory(), "conf/modules.xml");
logger.info("Loading modules from " + modulesXml.getAbsolutePath());
SAXReader xmlReader = new SAXReader();
xmlReader.setEncoding("UTF-8");
......
......@@ -39,33 +39,14 @@ public interface XMPPServerInfo {
*
* @return the version of the server.
*/
public Version getVersion();
/**
* Obtain the server name (IP address or hostname).
*
* @return the server's name as an IP address or host name.
* @deprecated replaced by {@link #getXMPPDomain()}
*/
@Deprecated
public String getName();
/**
* Set the server name (IP address or hostname). The server
* must be restarted for this change to take effect.
*
* @param serverName the server's name as an IP address or host name.
* @deprecated replaced by {@link #setXMPPDomain(String)}
*/
@Deprecated
public void setName(String serverName);
Version getVersion();
/**
* Obtain the host name (IP address or hostname) of this server node.
*
* @return the server's host name as an IP address or host name.
*/
public String getHostname();
String getHostname();
/**
* Obtain the server XMPP domain name. Note that, if unconfigured, the
......@@ -73,7 +54,7 @@ public interface XMPPServerInfo {
*
* @return the name of the XMPP domain that this server is part of.
*/
public String getXMPPDomain();
String getXMPPDomain();
/**
* Set the server XMPP domain name. The server must be
......@@ -82,19 +63,19 @@ public interface XMPPServerInfo {
* @param domainName
* the XMPP domain that this server is part of.
*/
public void setXMPPDomain(String domainName);
void setXMPPDomain(String domainName);
/**
* Obtain the date when the server was last started.
*
* @return the date the server was started or null if server has not been started.
*/
public Date getLastStarted();
Date getLastStarted();
/**
* Obtain the server ports active on this server.
*
* @return an iterator over the server ports for this server.
*/
public Collection<ServerPort> getServerPorts();
Collection<ServerPort> getServerPorts();
}
\ No newline at end of file
/**
* $RCSfile$
* $Revision: 1747 $
* $Date: 2005-08-04 18:36:36 -0300 (Thu, 04 Aug 2005) $
*
* Copyright (C) 2004-2008 Jive Software. All rights reserved.
*
* Licensed 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.jivesoftware.openfire.handler;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.QName;
import org.jivesoftware.openfire.IQHandlerInfo;
import org.jivesoftware.openfire.disco.ServerFeaturesProvider;
import org.jivesoftware.util.XMPPDateTimeFormat;
import org.xmpp.packet.IQ;
import java.text.DateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
/**
* Implements the TYPE_IQ jabber:iq:time protocol (time info) as
* as defined by JEP-0090. Allows Jabber entities to query each
* other's local time. The server will respond with its local time.
* <h2>Assumptions</h2>
* This handler assumes that the time request is addressed to itself.
* An appropriate TYPE_IQ tag matcher should be placed in front of this
* one to route TYPE_IQ time requests not addressed to the server to
* another channel (probably for direct delivery to the recipient).
* <h2>Warning</h2>
* There should be a way of determining whether a session has
* authorization to access this feature. I'm not sure it is a good
* idea to do authorization in each handler. It would be nice if
* the framework could assert authorization policies across channels.
*
* @author Iain Shigeoka
*/
public class IQTimeHandler extends IQHandler implements ServerFeaturesProvider {
// todo: Make display text match the locale of user (xml:lang support)
private static final DateFormat DATE_FORMAT = DateFormat.getDateInstance(DateFormat.MEDIUM);
private static final DateFormat TIME_FORMAT = DateFormat.getTimeInstance(DateFormat.LONG);
private Element responseElement;
private IQHandlerInfo info;
public IQTimeHandler() {
super("XMPP Server Time Handler");
info = new IQHandlerInfo("query", "jabber:iq:time");
responseElement = DocumentHelper.createElement(QName.get("query", "jabber:iq:time"));
responseElement.addElement("utc");
responseElement.addElement("tz").setText(TIME_FORMAT.getTimeZone().getDisplayName());
responseElement.addElement("display");
}
@Override
public IQ handleIQ(IQ packet) {
IQ response = null;
response = IQ.createResultIQ(packet);
response.setChildElement(buildResponse());
return response;
}
/**
* Build the responseElement packet
*/
private Element buildResponse() {
Element response = responseElement.createCopy();
Date current = new Date();
response.element("utc").setText(XMPPDateTimeFormat.formatOld(current));
StringBuilder display = new StringBuilder(DATE_FORMAT.format(current));
display.append(' ');
display.append(TIME_FORMAT.format(current));
response.element("display").setText(display.toString());
return response;
}
@Override
public IQHandlerInfo getInfo() {
return info;
}
@Override
public Iterator<String> getFeatures() {
return Collections.singleton("jabber:iq:time").iterator();
}
}
\ No newline at end of file
......@@ -210,8 +210,17 @@ public class PresenceSubscribeHandler extends BasicModule implements ChannelHand
// Send the presence of the local user to the remote user. The remote user
// subscribed to the presence of the local user and the local user accepted
JID prober = localServer.isLocal(recipientJID) ? recipientJID.asBareJID() : recipientJID;
presenceManager.probePresence(prober, senderJID);
PresenceEventDispatcher.subscribedToPresence(recipientJID, senderJID);
if (presenceManager.canProbePresence(prober, senderJID.toString())){
presenceManager.probePresence(prober, senderJID);
PresenceEventDispatcher.subscribedToPresence(recipientJID, senderJID);
}
else {
Presence nonProbablePresence = new Presence();
nonProbablePresence.setStatus("unavailable");
nonProbablePresence.setFrom(senderJID);
nonProbablePresence.setTo(recipientJID);
presenceManager.handleProbe(nonProbablePresence);
}
}
}
......@@ -525,4 +534,4 @@ public class PresenceSubscribeHandler extends BasicModule implements ChannelHand
rosterManager = server.getRosterManager();
userManager = server.getUserManager();
}
}
\ No newline at end of file
}
......@@ -32,6 +32,7 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
......@@ -132,8 +133,8 @@ public class HttpSession extends LocalClientSession {
};
public HttpSession(PacketDeliverer backupDeliverer, String serverName, InetAddress address,
StreamID streamID, long rid, HttpConnection connection) {
super(serverName, new HttpVirtualConnection(address), streamID);
StreamID streamID, long rid, HttpConnection connection, Locale language) {
super(serverName, new HttpVirtualConnection(address), streamID, language);
this.isClosed = false;
this.lastActivity = System.currentTimeMillis();
this.lastRequestID = rid;
......@@ -250,24 +251,6 @@ public class HttpSession extends LocalClientSession {
return hold;
}
/**
* Sets the language this session is using.
*
* @param language the language this session is using.
*/
public void setLanguage(String language) {
this.language = language;
}
/**
* Returns the language this session is using.
*
* @return the language this session is using.
*/
public String getLanguage() {
return language;
}
/**
* Sets the max interval within which a client can send polling requests. If more than one
* request occurs in the interval the session will be terminated.
......
......@@ -21,6 +21,7 @@ package org.jivesoftware.openfire.http;
import java.io.IOException;
import java.net.InetAddress;
import java.util.Locale;
import java.util.Map;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
......@@ -33,6 +34,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.QName;
import org.jivesoftware.openfire.SessionManager;
import org.jivesoftware.openfire.StreamID;
import org.jivesoftware.openfire.auth.UnauthorizedException;
......@@ -42,6 +44,8 @@ import org.jivesoftware.util.TaskEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.xml.XMLConstants;
/**
* Manages sessions for all users connecting to Openfire using the HTTP binding protocol,
* <a href="http://www.xmpp.org/extensions/xep-0124.html">XEP-0124</a>.
......@@ -168,7 +172,7 @@ public class HttpSessionManager {
// TODO Check if IP address is allowed to connect to the server
// Default language is English ("en").
String language = rootNode.attributeValue("xml:lang");
String language = rootNode.attributeValue(QName.get("lang", XMLConstants.XML_NS_URI));
if (language == null || "".equals(language)) {
language = "en";
}
......@@ -181,7 +185,7 @@ public class HttpSessionManager {
version = "1.5";
}
HttpSession session = createSession(connection.getRequestId(), address, connection);
HttpSession session = createSession(connection.getRequestId(), address, connection, Locale.forLanguageTag(language));
session.setWait(Math.min(wait, getMaxWait()));
session.setHold(hold);
session.setSecure(connection.isSecure());
......@@ -197,9 +201,6 @@ public class HttpSessionManager {
}
session.resetInactivityTimeout();
// Store language and version information in the connection.
session.setLanguage(language);
String [] versionString = version.split("\\.");
session.setMajorVersion(Integer.parseInt(versionString[0]));
session.setMinorVersion(Integer.parseInt(versionString[1]));
......@@ -296,11 +297,11 @@ public class HttpSessionManager {
return JiveGlobals.getIntProperty("xmpp.httpbind.client.idle.polling", 60);
}
private HttpSession createSession(long rid, InetAddress address, HttpConnection connection) throws UnauthorizedException {
private HttpSession createSession(long rid, InetAddress address, HttpConnection connection, Locale language) throws UnauthorizedException {
// Create a ClientSession for this user.
StreamID streamID = SessionManager.getInstance().nextStreamID();
// Send to the server that a new client session has been created
HttpSession session = sessionManager.createClientHttpSession(rid, address, streamID, connection);
HttpSession session = sessionManager.createClientHttpSession(rid, address, streamID, connection, language);
// Register that the new session is associated with the specified stream ID
sessionMap.put(streamID.getID(), session);
session.addSessionCloseListener(sessionListener);
......
......@@ -200,7 +200,7 @@ public class PacketCopier implements PacketInterceptor, ComponentEventListener {
"http://jabber.org/protocol/packet#event");
childElement.addAttribute("incoming", subscription.isIncoming() ? "true" : "false");
childElement.addAttribute("processed", subscription.isProcessed() ? "true" : "false");
childElement.addAttribute("date", XMPPDateTimeFormat.formatOld(interceptedPacket.getCreationDate()));
childElement.addAttribute("date", XMPPDateTimeFormat.format(interceptedPacket.getCreationDate()));
childElement.add(interceptedPacket.getElement().createCopy());
// Send message notification to subscribed component
routingTable.routePacket(message.getTo(), message, true);
......
......@@ -245,19 +245,6 @@ public final class GraphicUtils {
return false;
}
/**
* Returns the first component in the tree of <code>c</code> that can accept
* the focus.
*
* @param c the root of the component hierarchy to search
* @see #focusComponentOrChild
* @deprecated replaced by {@link #getFocusableComponentOrChild(Component, boolean)}
*/
@Deprecated
public static Component getFocusableComponentOrChild(Component c) {
return getFocusableComponentOrChild(c, false);
}
/**
* Returns the first component in the tree of <code>c</code> that can accept
* the focus.
......
......@@ -178,7 +178,7 @@ public class HistoryRequest {
}
if (getSeconds() > -1 || getSince() != null) {
delayInformation = message.getChildElement("x", "jabber:x:delay");
delayInformation = message.getChildElement("delay", "urn:xmpp:delay");
try {
// Get the date when the historic message was sent
Date delayedDate = xmppDateTime.parseString(delayInformation.attributeValue("stamp"));
......
......@@ -325,8 +325,8 @@ public class HistoryStrategy {
private static class MessageComparator implements Comparator<Message> {
@Override
public int compare(Message o1, Message o2) {
String stamp1 = o1.getChildElement("x", "jabber:x:delay").attributeValue("stamp");
String stamp2 = o2.getChildElement("x", "jabber:x:delay").attributeValue("stamp");
String stamp1 = o1.getChildElement("delay", "urn:xmpp:delay").attributeValue("stamp");
String stamp2 = o2.getChildElement("delay", "urn:xmpp:delay").attributeValue("stamp");
return stamp1.compareTo(stamp2);
}
}
......
......@@ -80,7 +80,7 @@ public final class MUCRoomHistory {
// TODO Make this update in a separate thread
for (Iterator<Message> it = getMessageHistory(); it.hasNext();) {
Message message = it.next();
Element delayElement = message.getChildElement("x", "jabber:x:delay");
Element delayElement = message.getChildElement("delay", "urn:xmpp:delay");
if (room.canAnyoneDiscoverJID()) {
// Set the Full JID as the "from" attribute
try {
......@@ -101,16 +101,13 @@ public final class MUCRoomHistory {
// Add the delay information to the message
Element delayInformation = packetToAdd.addChildElement("delay", "urn:xmpp:delay");
Element delayInformationOld = packetToAdd.addChildElement("x", "jabber:x:delay");
Date current = new Date();
delayInformation.addAttribute("stamp", XMPPDateTimeFormat.format(current));
delayInformationOld.addAttribute("stamp", XMPPDateTimeFormat.formatOld(current));
if (room.canAnyoneDiscoverJID()) {
// Set the Full JID as the "from" attribute
try {
MUCRole role = room.getOccupant(packet.getFrom().getResource());
delayInformation.addAttribute("from", role.getUserAddress().toString());
delayInformationOld.addAttribute("from", role.getUserAddress().toString());
}
catch (UserNotFoundException e) {
// Ignore.
......@@ -119,7 +116,6 @@ public final class MUCRoomHistory {
else {
// Set the Room JID as the "from" attribute
delayInformation.addAttribute("from", packet.getFrom().toString());
delayInformationOld.addAttribute("from", packet.getFrom().toString());
}
historyStrategy.addMessage(packetToAdd);
}
......@@ -170,18 +166,14 @@ public final class MUCRoomHistory {
// Add the delay information to the message
Element delayInformation = message.addChildElement("delay", "urn:xmpp:delay");
Element delayInformationOld = message.addChildElement("x", "jabber:x:delay");
delayInformation.addAttribute("stamp", XMPPDateTimeFormat.format(sentDate));
delayInformationOld.addAttribute("stamp", XMPPDateTimeFormat.formatOld(sentDate));
if (room.canAnyoneDiscoverJID()) {
// Set the Full JID as the "from" attribute
delayInformation.addAttribute("from", senderJID);
delayInformationOld.addAttribute("from", senderJID);
}
else {
// Set the Room JID as the "from" attribute
delayInformation.addAttribute("from", room.getRole().getRoleAddress().toString());
delayInformationOld.addAttribute("from", room.getRole().getRoleAddress().toString());
}
historyStrategy.addMessage(message);
}
......
......@@ -390,32 +390,4 @@ public class IQMUCSearchHandler
}
return room.isPublicRoom();
}
/**
* Returns the first value from the FormField, or 'null' if no value has
* been set.
*
* @param formField
* The field from which to return the first value.
* @return String based value, or 'null' if the FormField has no values.
* @deprecated replaced by {@link FormField#getFirstValue()}
*/
@Deprecated
public static String getFirstValue(FormField formField)
{
if (formField == null)
{
throw new IllegalArgumentException(
"The argument 'formField' cannot be null.");
}
List<String> it = formField.getValues();
if (it.isEmpty())
{
return null;
}
return it.get(0);
}
}
......@@ -1458,7 +1458,7 @@ public class MultiUserChatServiceImpl implements Component, MultiUserChatService
final FormField fieldDate = dataForm.addField();
fieldDate.setVariable("x-muc#roominfo_creationdate");
fieldDate.setLabel(LocaleUtils.getLocalizedString("muc.extended.info.creationdate"));
fieldDate.addValue(XMPPDateTimeFormat.formatOld(room.getCreationDate()));
fieldDate.addValue(XMPPDateTimeFormat.format(room.getCreationDate()));
return dataForm;
}
......
......@@ -66,30 +66,6 @@ public class DNSUtil {
}
}
/**
* Returns the host name and port that the specified XMPP server can be
* reached at for server-to-server communication. A DNS lookup for a SRV
* record in the form "_xmpp-server._tcp.example.com" is attempted, according
* to section 14.4 of RFC 3920. If that lookup fails, a lookup in the older form
* of "_jabber._tcp.example.com" is attempted since servers that implement an
* older version of the protocol may be listed using that notation. If that
* lookup fails as well, it's assumed that the XMPP server lives at the
* host resolved by a DNS lookup at the specified domain on the specified default port.<p>
*
* As an example, a lookup for "example.com" may return "im.example.com:5269".
*
* @param domain the domain.
* @param defaultPort default port to return if the DNS look up fails.
* @return a HostAddress, which encompasses the hostname and port that the XMPP
* server can be reached at for the specified domain.
* @deprecated replaced with support for multiple srv records, see
* {@link #resolveXMPPDomain(String, int)}
*/
@Deprecated
public static HostAddress resolveXMPPServerDomain(String domain, int defaultPort) {
return resolveXMPPDomain(domain, defaultPort).get(0);
}
/**
* Returns a sorted list of host names and ports that the specified XMPP domain
* can be reached at for server-to-server communication. A DNS lookup for a SRV
......
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2005-2008 Jive Software. All rights reserved.
*
* Licensed 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.jivesoftware.openfire.net;
import org.jivesoftware.util.JiveGlobals;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* Thread pool to be used for processing incoming packets when using non-blocking
* connections.
*
* // TODO Change thead pool configuration. Would be nice to have something that can be
* // TODO dynamically adjusted to demand and circumstances.
*
* @author Daniele Piras
*/
class IOExecutor {
// SingleTon ...
protected static IOExecutor instance = new IOExecutor();
// Pool obj
protected ThreadPoolExecutor executeMsgPool;
// Internal queue for the pool
protected LinkedBlockingQueue<Runnable> executeQueue;
/*
* Simple constructor that initialize the main executor structure.
*
*/
protected IOExecutor() {
// Read poolsize parameter...
int poolSize = JiveGlobals.getIntProperty("tiscali.pool.size", 15);
// Create queue for executor
executeQueue = new LinkedBlockingQueue<>(10000);
// Create executor
executeMsgPool =
new ThreadPoolExecutor(poolSize, poolSize, 60, TimeUnit.SECONDS, executeQueue);
}
public static void execute(Runnable task) {
instance.executeMsgPool.execute(task);
}
}
......@@ -195,8 +195,8 @@ public class SASLAuthentication {
// Server connections don't follow the same rules as clients
if (session.isSecure()) {
LocalIncomingServerSession svr = (LocalIncomingServerSession)session;
final KeyStore keyStore = svr.getConnection().getConfiguration().getIdentityStore().getStore();
final KeyStore trustStore = svr.getConnection().getConfiguration().getTrustStore().getStore();
final KeyStore keyStore = SSLConfig.getStore( Purpose.SOCKETBASED_IDENTITYSTORE );
final KeyStore trustStore = SSLConfig.getStore( Purpose.SOCKETBASED_S2S_TRUSTSTORE );
final X509Certificate trusted = CertificateManager.getEndEntityCertificate( svr.getConnection().getPeerCertificates(), keyStore, trustStore );
boolean haveTrustedCertificate = trusted != null;
......@@ -574,9 +574,8 @@ public class SASLAuthentication {
return Status.failed;
}
final KeyStore keyStore = connection.getConfiguration().getIdentityStore().getStore();
final KeyStore trustStore = connection.getConfiguration().getTrustStore().getStore();
final KeyStore keyStore = SSLConfig.getStore( Purpose.SOCKETBASED_IDENTITYSTORE );
final KeyStore trustStore = SSLConfig.getStore( Purpose.SOCKETBASED_C2S_TRUSTSTORE );
final X509Certificate trusted = CertificateManager.getEndEntityCertificate( connection.getPeerCertificates(), keyStore, trustStore );
if (trusted == null) {
......@@ -647,14 +646,6 @@ public class SASLAuthentication {
return false;
}
/**
* @deprecated Use {@link #verifyCertificates(Certificate[], String, boolean)} instead.
*/
@Deprecated
public static boolean verifyCertificates(Certificate[] chain, String hostname) {
return verifyCertificates( chain, hostname, true );
}
public static boolean verifyCertificates(Certificate[] chain, String hostname, boolean isS2S) {
final CertificateStoreManager certificateStoreManager = XMPPServer.getInstance().getCertificateStoreManager();
final ConnectionType connectionType = isS2S ? ConnectionType.SOCKET_S2S : ConnectionType.SOCKET_C2S;
......
/**
* $RCSfile$
* $Revision: 128 $
* $Date: 2004-10-25 20:42:00 -0300 (Mon, 25 Oct 2004) $
*
* Copyright (C) 2004-2008 Jive Software. All rights reserved.
*
* Licensed 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.jivesoftware.openfire.net;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import org.jivesoftware.util.LocaleUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.X509TrustManager;
/**
* Trust manager which accepts certificates without any validation
* except date validation.
* <p>
* A skeleton placeholder for developers wishing to implement their own custom
* trust manager. In future revisions we may expand the skeleton code if customers
* request assistance in creating custom trust managers.</p>
* <p>
* You only need a trust manager if your server will require clients
* to authenticated with the server (typically only the server authenticates
* with the client).</p>
*
* @author Iain Shigeoka
*/
public class SSLJiveTrustManager implements X509TrustManager {
private static final Logger Log = LoggerFactory.getLogger(SSLJiveTrustManager.class);
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
public boolean isClientTrusted(X509Certificate[] x509Certificates) {
return true;
}
public boolean isServerTrusted(X509Certificate[] x509Certificates) {
boolean trusted = true;
try {
x509Certificates[0].checkValidity();
}
catch (CertificateExpiredException | CertificateNotYetValidException e) {
Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
trusted = false;
}
return trusted;
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2005-2008 Jive Software. All rights reserved.
*
* Licensed 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.jivesoftware.openfire.net;
import java.io.IOException;
import java.nio.channels.SelectionKey;
/**
* @author Daniele Piras
*/
interface SelectorAction
{
public abstract void read( SelectionKey key ) throws IOException;
public abstract void connect( SelectionKey key ) throws IOException;
}
......@@ -419,21 +419,6 @@ public class SocketConnection implements Connection {
this.minorVersion = minorVersion;
}
@Override
public String getLanguage() {
return language;
}
/**
* Sets the language code that should be used for this connection (e.g. "en").
*
* @param language the language code.
*/
@Override
public void setLanaguage(String language) {
this.language = language;
}
@Override
public boolean isFlashClient() {
return flashClient;
......
......@@ -269,7 +269,7 @@ abstract class SocketReadingMode {
sb.append("\" id=\"");
sb.append(socketReader.session.getStreamID().toString());
sb.append("\" xml:lang=\"");
sb.append(socketReader.connection.getLanguage());
sb.append(socketReader.session.getLanguage());
sb.append("\" version=\"");
sb.append(Session.MAJOR_VERSION).append('.').append(Session.MINOR_VERSION);
sb.append("\">");
......
......@@ -580,7 +580,7 @@ public abstract class StanzaHandler {
sb.append("\" id=\"");
sb.append(session.getStreamID());
sb.append("\" xml:lang=\"");
sb.append(connection.getLanguage());
sb.append(session.getLanguage());
sb.append("\" version=\"");
sb.append(Session.MAJOR_VERSION).append('.').append(Session.MINOR_VERSION);
sb.append("\">");
......
......@@ -56,12 +56,6 @@ public abstract class VirtualConnection implements Connection {
private AtomicReference<State> state = new AtomicReference<State>(State.OPEN);
@Override
public String getLanguage() {
// Information not available. Return any value. This is not actually used.
return null;
}
@Override
public int getMajorXMPPVersion() {
// Information not available. Return any value. This is not actually used.
......@@ -134,11 +128,6 @@ public abstract class VirtualConnection implements Connection {
//Ignore
}
@Override
public void setLanaguage(String language) {
//Ignore
}
@Override
public void setCompressionPolicy(CompressionPolicy compressionPolicy) {
//Ignore
......
......@@ -441,16 +441,6 @@ public class NIOConnection implements Connection {
this.minorVersion = minorVersion;
}
@Override
public String getLanguage() {
return language;
}
@Override
public void setLanaguage(String language) {
this.language = language;
}
@Override
public boolean isCompressed() {
return ioSession.getFilterChain().contains(COMPRESSION_FILTER_NAME);
......
......@@ -37,7 +37,6 @@ import org.jivesoftware.openfire.entitycaps.EntityCapabilities;
import org.jivesoftware.openfire.entitycaps.EntityCapabilitiesManager;
import org.jivesoftware.openfire.pubsub.CollectionNode;
import org.jivesoftware.openfire.pubsub.DefaultNodeConfiguration;
import org.jivesoftware.openfire.pubsub.LeafNode;
import org.jivesoftware.openfire.pubsub.Node;
import org.jivesoftware.openfire.pubsub.NodeSubscription;
import org.jivesoftware.openfire.pubsub.PendingSubscriptionsCommand;
......@@ -331,7 +330,7 @@ public class PEPService implements PubSubService, Cacheable {
message.setFrom(getAddress());
for (JID jid : jids) {
message.setTo(jid);
message.setID(node.getNodeID() + "__" + jid.toBareJID() + "__" + StringUtils.randomString(5));
message.setID(StringUtils.randomString(8));
router.route(message);
}
}
......@@ -340,7 +339,7 @@ public class PEPService implements PubSubService, Cacheable {
public void sendNotification(Node node, Message message, JID recipientJID) {
message.setTo(recipientJID);
message.setFrom(getAddress());
message.setID(node.getNodeID() + "__" + recipientJID.toBareJID() + "__" + StringUtils.randomString(5));
message.setID(StringUtils.randomString(8));
// If the recipient subscribed with a bare JID and this PEPService can retrieve
// presence information for the recipient, collect all of their full JIDs and
......
......@@ -723,8 +723,7 @@ public class PubSubModule extends BasicModule implements ServerItemsProvider, Di
message.setFrom(getAddress());
for (JID jid : jids) {
message.setTo(jid);
message.setID(
node.getNodeID() + "__" + jid.toBareJID() + "__" + StringUtils.randomString(5));
message.setID(StringUtils.randomString(8));
router.route(message);
}
}
......@@ -738,8 +737,7 @@ public class PubSubModule extends BasicModule implements ServerItemsProvider, Di
public void sendNotification(Node node, Message message, JID jid) {
message.setFrom(getAddress());
message.setTo(jid);
message.setID(
node.getNodeID() + "__" + jid.toBareJID() + "__" + StringUtils.randomString(5));
message.setID(StringUtils.randomString(8));
router.route(message);
}
......
......@@ -24,6 +24,7 @@ import java.net.UnknownHostException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.StringTokenizer;
......@@ -210,7 +211,7 @@ public class LocalClientSession extends LocalSession implements ClientSession {
}
// Default language is English ("en").
String language = "en";
Locale language = Locale.forLanguageTag("en");
// Default to a version of "0.0". Clients written before the XMPP 1.0 spec may
// not report a version in which case "0.0" should be assumed (per rfc3920
// section 4.4.1).
......@@ -218,7 +219,7 @@ public class LocalClientSession extends LocalSession implements ClientSession {
int minorVersion = 0;
for (int i = 0; i < xpp.getAttributeCount(); i++) {
if ("lang".equals(xpp.getAttributeName(i))) {
language = xpp.getAttributeValue(i);
language = Locale.forLanguageTag(xpp.getAttributeValue(i));
}
if ("version".equals(xpp.getAttributeName(i))) {
try {
......@@ -247,12 +248,9 @@ public class LocalClientSession extends LocalSession implements ClientSession {
}
}
// Store language and version information in the connection.
connection.setLanaguage(language);
connection.setXMPPVersion(majorVersion, minorVersion);
final ConnectionConfiguration connectionConfiguration = connection.getConfiguration();
// Indicate the TLS policy to use for this connection
if (!connection.isSecure()) {
boolean hasCertificates = false;
......@@ -279,7 +277,7 @@ public class LocalClientSession extends LocalSession implements ClientSession {
connection.setCompressionPolicy( connectionConfiguration.getCompressionPolicy() );
// Create a ClientSession for this user.
LocalClientSession session = SessionManager.getInstance().createClientSession(connection);
LocalClientSession session = SessionManager.getInstance().createClientSession(connection, language);
// Build the start packet response
StringBuilder sb = new StringBuilder(200);
......@@ -413,16 +411,6 @@ public class LocalClientSession extends LocalSession implements ClientSession {
}
}
/**
* Sets whether compression is optional or is disabled for clients.
*
* @param policy whether compression is optional or is disabled.
*/
// TODO Move this to ConnectionConfiguration.
public static void setCompressionPolicy(SocketConnection.CompressionPolicy policy) {
JiveGlobals.setProperty(ConnectionSettings.Client.COMPRESSION_SETTINGS, policy.toString());
}
/**
* Returns the Privacy list that overrides the default privacy list. This list affects
* only this session and only for the duration of the session.
......@@ -503,8 +491,8 @@ public class LocalClientSession extends LocalSession implements ClientSession {
* @param connection The connection we are proxying.
* @param streamID unique identifier of this session.
*/
public LocalClientSession(String serverName, Connection connection, StreamID streamID) {
super(serverName, connection, streamID);
public LocalClientSession(String serverName, Connection connection, StreamID streamID, Locale language) {
super(serverName, connection, streamID, language);
// Set an unavailable initial presence
presence = new Presence();
presence.setType(Presence.Type.unavailable);
......
......@@ -23,6 +23,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.jivesoftware.openfire.Connection;
......@@ -188,7 +189,7 @@ public class LocalComponentSession extends LocalSession implements ComponentSess
}
public LocalComponentSession(String serverName, Connection conn, StreamID id) {
super(serverName, conn, id);
super(serverName, conn, id, Locale.getDefault());
}
@Override
......
......@@ -17,6 +17,7 @@
package org.jivesoftware.openfire.session;
import java.util.Collection;
import java.util.Locale;
import org.dom4j.Element;
import org.jivesoftware.openfire.Connection;
......@@ -185,7 +186,7 @@ public class LocalConnectionMultiplexerSession extends LocalSession implements C
}
public LocalConnectionMultiplexerSession(String serverName, Connection connection, StreamID streamID) {
super(serverName, connection, streamID);
super(serverName, connection, streamID, Locale.getDefault());
}
@Override
......
......@@ -8,6 +8,8 @@ import org.jivesoftware.openfire.StreamID;
import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.xmpp.packet.Packet;
import java.util.Locale;
/**
* @author dwd
*
......@@ -19,7 +21,7 @@ public class LocalServerSession extends LocalSession implements ServerSession {
public LocalServerSession(String serverName, Connection connection,
StreamID streamID) {
super(serverName, connection, streamID);
super(serverName, connection, streamID, Locale.getDefault());
}
/* (non-Javadoc)
......
......@@ -20,6 +20,7 @@ import java.net.UnknownHostException;
import java.security.cert.Certificate;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.net.ssl.SSLSession;
......@@ -100,14 +101,17 @@ public abstract class LocalSession implements Session {
*/
protected final StreamManager streamManager;
private final Locale language;
/**
* Creates a session with an underlying connection and permission protection.
*
* @param serverName domain of the XMPP server where the new session belongs.
* @param connection The connection we are proxying.
* @param streamID unique identifier for this session.
* @param language The language to use for this session.
*/
public LocalSession(String serverName, Connection connection, StreamID streamID) {
public LocalSession(String serverName, Connection connection, StreamID streamID, Locale language) {
if (connection == null) {
throw new IllegalArgumentException("connection must not be null");
}
......@@ -118,6 +122,7 @@ public abstract class LocalSession implements Session {
this.address = new JID(null, serverName, id, true);
this.sessionManager = SessionManager.getInstance();
this.streamManager = new StreamManager(conn);
this.language = language;
}
/**
......@@ -470,4 +475,8 @@ public abstract class LocalSession implements Session {
streamManager.setEnabled(true);
}
@Override
public final Locale getLanguage() {
return language;
}
}
......@@ -28,6 +28,7 @@ import org.xmpp.packet.Packet;
import java.net.UnknownHostException;
import java.security.cert.Certificate;
import java.util.Date;
import java.util.Locale;
/**
* The session represents a connection between the server and a client (c2s) or
......@@ -212,4 +213,11 @@ public interface Session extends RoutableChannelHandler {
* @return cipher suite name.
*/
public String getCipherSuiteName();
/**
* Returns the locale that is used for this session (e.g. {@link Locale#ENGLISH}).
*
* @return The language for the session.
*/
Locale getLanguage();
}
\ No newline at end of file
......@@ -66,18 +66,6 @@ public class XMPPServerInfoImpl implements XMPPServerInfo {
return ver;
}
@Override
@Deprecated
public String getName() {
return getXMPPDomain();
}
@Override
@Deprecated
public void setName(String serverName) {
setXMPPDomain(serverName);
}
@Override
public String getHostname()
{
......
......@@ -150,33 +150,6 @@ public class CertificateManager {
}
}
/**
* @Deprecated Use {@link CertificateStore#delete(String)} instead.
*/
@Deprecated
public static void deleteCertificate(CertificateStore storeConfig, String alias) throws GeneralSecurityException, IOException, CertificateStoreConfigException
{
final KeyStore store = storeConfig.getStore();
if (!store.containsAlias( alias ) )
{
Log.info( "Unable to delete certificate for alias '"+alias+"' from store, as the store does not contain a certificate for that alias." );
return;
}
storeConfig.getStore().deleteEntry( alias );
storeConfig.persist();
// Notify listeners that a new certificate has been removed.
for (CertificateEventListener listener : listeners) {
try {
listener.certificateDeleted(store, alias);
}
catch (Exception e) {
Log.warn( "An exception occurred while notifying CertificateEventListener " + listener, e );
}
}
}
/**
* Decide whether or not to trust the given supplied certificate chain, returning the
* End Entity Certificate in this case where it can, and null otherwise.
......@@ -386,7 +359,7 @@ public class CertificateManager {
* @return true if a certificate with the specified configuration was found in the key store.
* @throws KeyStoreException
*/
private static boolean isCertificate(CertificateStore storeConfig, String domain, String algorithm) throws KeyStoreException {
private static boolean isCertificate(CertificateStoreConfig storeConfig, String domain, String algorithm) throws KeyStoreException {
for (Enumeration<String> aliases = storeConfig.getStore().aliases(); aliases.hasMoreElements();) {
X509Certificate certificate = (X509Certificate) storeConfig.getStore().getCertificate(aliases.nextElement());
......
/**
* $RCSfile$
* $Revision: 3144 $
* $Date: 2005-12-01 14:20:11 -0300 (Thu, 01 Dec 2005) $
*
* Copyright (C) 2004-2008 Jive Software. All rights reserved.
*
* Licensed 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.jivesoftware.util;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.Callable;
/**
* Callable which will read from an input stream and write to an output stream.
*
* @author Alexander Wenckus
*/
public class InputOutputStreamWrapper implements Callable {
private static final int DEFAULT_BUFFER_SIZE = 8000;
private long amountWritten = 0;
private int bufferSize;
private InputStream in;
private OutputStream out;
public InputOutputStreamWrapper(InputStream in, OutputStream out, int bufferSize) {
if(bufferSize <= 0) {
bufferSize = DEFAULT_BUFFER_SIZE;
}
this.bufferSize = bufferSize;
this.in = in;
this.out = out;
}
public InputOutputStreamWrapper(InputStream in, OutputStream out) {
this(in, out, DEFAULT_BUFFER_SIZE);
}
@Override
public Object call() throws Exception {
final byte[] b = new byte[bufferSize];
int count = 0;
amountWritten = 0;
do {
// write to the output stream
out.write(b, 0, count);
amountWritten += count;
// read more bytes from the input stream
count = in.read(b);
} while (count >= 0);
return amountWritten;
}
public long getAmountWritten() {
return amountWritten;
}
}
/**
* $RCSfile$
* $Revision: 3144 $
* $Date: 2005-12-01 14:20:11 -0300 (Thu, 01 Dec 2005) $
*
* Copyright (C) 2004-2008 Jive Software. All rights reserved.
*
* Licensed 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.jivesoftware.util;
/**
* A generic exception for when errors occur in the system.
*/
public class InternalServerErrorException extends RuntimeException {
public InternalServerErrorException(String s, Exception e) {
super(s, e);
}
}
......@@ -68,12 +68,9 @@ public class XMPPDateTimeFormat {
private static final FastDateFormat FAST_FORMAT = FastDateFormat.getInstance(
XMPP_DATETIME_FORMAT, TimeZone.getTimeZone("UTC"));
private static final FastDateFormat FAST_FORMAT_OLD = FastDateFormat.getInstance(
XMPP_DELAY_DATETIME_FORMAT, TimeZone.getTimeZone("UTC"));
private final DateFormat dateTimeFormat = new SimpleDateFormat(XMPP_DATETIME_FORMAT_WO_TIMEZONE + 'Z');
private final DateFormat dateTimeFormatWoMillies = new SimpleDateFormat(XMPP_DATETIME_FORMAT_WO_MILLIS_WO_TIMEZONE + 'Z');
private final DateFormat dateTimeFormatOld = new SimpleDateFormat(XMPP_DELAY_DATETIME_FORMAT);
/**
* Create a new thread-safe instance of this utility class
......@@ -82,7 +79,6 @@ public class XMPPDateTimeFormat {
TimeZone utc = TimeZone.getTimeZone("UTC");
dateTimeFormat.setTimeZone(utc);
dateTimeFormatWoMillies.setTimeZone(utc);
dateTimeFormatOld.setTimeZone(utc);
}
/**
......@@ -129,29 +125,8 @@ public class XMPPDateTimeFormat {
return dateTimeFormat.parse(rfc822Date);
}
}
} else {
// at last try with the legacy format
synchronized (dateTimeFormatOld) {
return dateTimeFormatOld.parse(dateString);
}
}
}
/**
* Tries to convert a given string to a Date object.
* This method only supports the legacy XMPP time format: CCYYMMDDThh:mm:ss
*
* This method either returns a Date instance as result or it will return null or throw a ParseException
* in case the String couldn't be parsed.
*
* @param dateStr
* @return the parsed date or null if the String could not be parsed
* @throws ParseException
*/
public Date parseOldDate(String dateStr) throws ParseException {
synchronized (dateTimeFormatOld) {
return dateTimeFormatOld.parse(dateStr);
}
throw new ParseException("Date String could not be parsed", 0);
}
/**
......@@ -166,16 +141,4 @@ public class XMPPDateTimeFormat {
public static String format(Date date) {
return FAST_FORMAT.format(date);
}
/**
* Formats a Date object to String as defined in legacy XMPP protocols (e.g. XEP-0090)
*
* CCYYMMDDThh:mm:ss
*
* @param date
* @return String
*/
public static String formatOld(Date date) {
return FAST_FORMAT_OLD.format(date);
}
}
......@@ -22,6 +22,7 @@ package org.jivesoftware.openfire.plugin.session;
import java.net.UnknownHostException;
import java.security.cert.Certificate;
import java.util.Date;
import java.util.Locale;
import org.jivesoftware.openfire.SessionManager;
import org.jivesoftware.openfire.StreamID;
......@@ -211,6 +212,11 @@ public abstract class RemoteSession implements Session {
}
}
@Override
public final Locale getLanguage() {
return Locale.getDefault();
}
/**
* Simple implementation of the StreamID interface to hold the stream ID of
* the surrogated session.
......
......@@ -7,7 +7,7 @@
<author>Roman Soldatow</author>
<version>1.2.1</version>
<date>11/24/2015</date>
<minServerVersion>3.10.0</minServerVersion>
<minServerVersion>3.11.0 alpha</minServerVersion>
<adminconsole>
<tab id="tab-server">
<sidebar id="sidebar-server-settings">
......
......@@ -44,6 +44,18 @@
Openfire WebSocket Plugin Changelog
</h1>
<p><b>1.1</b> -- November 24, 2015</p>
<ul>
<li>Pass 'xml:lang' attribute to the session.</li>
</ul>
<p><b>1.0.1</b> -- November 21, 2015</p>
<ul>
<li>"lang" attribute should be "xml:lang" in session creation response.</li>
</ul>
<p><b>1.0</b> -- July 28, 2015</p>
<ul>
......
......@@ -8,8 +8,8 @@
<name>Openfire WebSocket</name>
<description>Provides WebSocket support for Openfire.</description>
<author>Tom Evans</author>
<version>1.0.0</version>
<date>07/28/2015</date>
<version>1.1.0</version>
<date>11/24/2015</date>
<url>https://tools.ietf.org/html/rfc7395</url>
<minServerVersion>3.10.0</minServerVersion>
<minServerVersion>3.11.0</minServerVersion>
</plugin>
\ No newline at end of file
......@@ -17,11 +17,13 @@ package org.jivesoftware.openfire.websocket;
import java.io.IOException;
import java.io.StringReader;
import java.util.Locale;
import java.util.TimerTask;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.QName;
import org.dom4j.io.XMPPPacketReader;
import org.eclipse.jetty.websocket.api.RemoteEndpoint;
import org.eclipse.jetty.websocket.api.Session;
......@@ -47,6 +49,8 @@ import org.slf4j.LoggerFactory;
import org.xmpp.packet.PacketError;
import org.xmpp.packet.StreamError;
import javax.xml.XMLConstants;
/**
* This class handles all WebSocket events for the corresponding connection with a remote peer.
* Specifically the XMPP session is managed concurrently with the WebSocket session, including all
......@@ -211,7 +215,7 @@ public class XmppWebSocket {
saslStatus = SASLAuthentication.handle(xmppSession, stanza);
} else if (STREAM_HEADER.equals(tag)) {
// restart the stream
openStream(stanza.attributeValue("lang", "en"), stanza.attributeValue("from"));
openStream(stanza.attributeValue(QName.get("lang", XMLConstants.XML_NS_URI), "en"), stanza.attributeValue("from"));
configureStream();
} else if (Status.authenticated.equals(saslStatus)) {
if (router == null) {
......@@ -244,7 +248,7 @@ public class XmppWebSocket {
String host = stanza.attributeValue("to");
StreamError streamError = null;
Locale language = Locale.forLanguageTag(stanza.attributeValue(QName.get("lang", XMLConstants.XML_NS_URI), "en"));
if (STREAM_FOOTER.equals(stanza.getName())) {
// an error occurred while setting up the session
closeStream(null);
......@@ -261,12 +265,12 @@ public class XmppWebSocket {
streamError = new StreamError(StreamError.Condition.host_unknown);
Log.warn("Closing session due to incorrect hostname in stream header. Host: " + host);
} else {
xmppSession = SessionManager.getInstance().createClientSession(wsConnection);
xmppSession = SessionManager.getInstance().createClientSession(wsConnection, language);
xmppSession.setSessionData("ws", Boolean.TRUE);
}
if (streamError == null) {
openStream(stanza.attributeValue("lang", "en"), stanza.attributeValue("from"));
openStream(language.toLanguageTag(), stanza.attributeValue("from"));
configureStream();
} else {
closeStream(streamError);
......@@ -317,8 +321,8 @@ public class XmppWebSocket {
sb.append("from='").append(XMPPServer.getInstance().getServerInfo().getXMPPDomain()).append("' ");
sb.append("id='").append(xmppSession.getStreamID().toString()).append("' ");
sb.append("xmlns='").append(FRAMING_NAMESPACE).append("' ");
sb.append("lang='").append(lang).append("' ");
sb.append("version='1.0' />");
sb.append("xml:lang='").append(lang).append("' ");
sb.append("version='1.0'/>");
deliver(sb.toString());
}
......@@ -332,8 +336,8 @@ public class XmppWebSocket {
StringBuilder sb = new StringBuilder(250);
sb.append("<close ");
sb.append("xmlns='").append(FRAMING_NAMESPACE).append("' ");
sb.append(" />");
sb.append("xmlns='").append(FRAMING_NAMESPACE).append("'");
sb.append("/>");
deliver(sb.toString());
closeWebSocket();
}
......
<?xml version="1.0" encoding="UTF-8"?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
<taglib xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
version="2.1">
<tlib-version>1.2</tlib-version>
<short-name>Tag Library for Openfire</short-name>
<description>Tab Library for Openfire Admin Console</description>
<display-name>Admin Console Tags</display-name>
<tlib-version>2.0</tlib-version>
<short-name>admin</short-name>
<uri>admin</uri>
<tag>
<name>tabs</name>
<tag-class>org.jivesoftware.admin.TabsTag</tag-class>
<tag-class>org.jivesoftware.admin.TabsTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>css</name>
......@@ -65,7 +66,7 @@
</tag>
<tag>
<name>sidebar</name>
<tag-class>org.jivesoftware.admin.SidebarTag</tag-class>
<tag-class>org.jivesoftware.admin.SidebarTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>css</name>
......@@ -95,7 +96,7 @@
</tag>
<tag>
<name>subsidebar</name>
<tag-class>org.jivesoftware.admin.SubSidebarTag</tag-class>
<tag-class>org.jivesoftware.admin.SubSidebarTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>css</name>
......
<servlet>
<servlet-name>XMPPBootServlet</servlet-name>
<servlet-class>org.jivesoftware.messenger.XMPPBootServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment