mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2025-09-10 18:59:41 +02:00
SMACK-361 Added support for Entity Capabilities.
git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@13558 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
parent
1167523c4f
commit
9123578ea5
33 changed files with 2395 additions and 88 deletions
|
@ -204,6 +204,11 @@ public abstract class Connection {
|
|||
*/
|
||||
protected final ConnectionConfiguration config;
|
||||
|
||||
/**
|
||||
* Holds the Caps Node information for the used XMPP service (i.e. the XMPP server)
|
||||
*/
|
||||
private String serviceCapsNode;
|
||||
|
||||
protected XMPPInputOutputStream compressionHandler;
|
||||
|
||||
/**
|
||||
|
@ -795,7 +800,29 @@ public abstract class Connection {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the servers Entity Caps node
|
||||
*
|
||||
* Connection holds this information in order to avoid a dependency to
|
||||
* smackx where EntityCapsManager lives from smack.
|
||||
*
|
||||
* @param node
|
||||
*/
|
||||
protected void setServiceCapsNode(String node) {
|
||||
serviceCapsNode = node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the servers Entity Caps node
|
||||
*
|
||||
* Connection holds this information in order to avoid a dependency to
|
||||
* smackx where EntityCapsManager lives from smack.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getServiceCapsNode() {
|
||||
return serviceCapsNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* A wrapper class to associate a packet filter with a listener.
|
||||
|
|
|
@ -393,6 +393,19 @@ class PacketReader {
|
|||
// The server requires the client to bind a resource to the stream
|
||||
connection.getSASLAuthentication().bindingRequired();
|
||||
}
|
||||
// Set the entity caps node for the server if one is send
|
||||
// See http://xmpp.org/extensions/xep-0115.html#stream
|
||||
else if (parser.getName().equals("c")) {
|
||||
String node = parser.getAttributeValue(null, "node");
|
||||
String ver = parser.getAttributeValue(null, "ver");
|
||||
if (ver != null && node != null) {
|
||||
String capsNode = node + "#" + ver;
|
||||
// In order to avoid a dependency from smack to smackx
|
||||
// we have to set the services caps node in the connection
|
||||
// and not directly in the EntityCapsManager
|
||||
connection.setServiceCapsNode(capsNode);
|
||||
}
|
||||
}
|
||||
else if (parser.getName().equals("session")) {
|
||||
// The server supports sessions
|
||||
connection.getSASLAuthentication().sessionsSupported();
|
||||
|
|
|
@ -63,6 +63,11 @@ public final class SmackConfiguration {
|
|||
*/
|
||||
private static int defaultPingInterval = 1800; // 30 min (30*60)
|
||||
|
||||
/**
|
||||
* This automatically enables EntityCaps for new connections if it is set to true
|
||||
*/
|
||||
private static boolean autoEnableEntityCaps = false;
|
||||
|
||||
private SmackConfiguration() {
|
||||
}
|
||||
|
||||
|
@ -115,6 +120,9 @@ public final class SmackConfiguration {
|
|||
else if (parser.getName().equals("defaultPingInterval")) {
|
||||
defaultPingInterval = parseIntProperty(parser, defaultPingInterval);
|
||||
}
|
||||
else if (parser.getName().equals("autoEnableEntityCaps")) {
|
||||
autoEnableEntityCaps = Boolean.parseBoolean(parser.nextText());
|
||||
}
|
||||
}
|
||||
eventType = parser.next();
|
||||
}
|
||||
|
@ -329,6 +337,23 @@ public final class SmackConfiguration {
|
|||
SmackConfiguration.defaultPingInterval = defaultPingInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if Entity Caps are enabled as default for every new connection
|
||||
* @return
|
||||
*/
|
||||
public static boolean autoEnableEntityCaps() {
|
||||
return autoEnableEntityCaps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if Entity Caps are enabled or disabled for every new connection
|
||||
*
|
||||
* @param true if Entity Caps should be auto enabled, false if not
|
||||
*/
|
||||
public static void setAutoEnableEntityCaps(boolean b) {
|
||||
autoEnableEntityCaps = b;
|
||||
}
|
||||
|
||||
private static void parseClassToLoad(XmlPullParser parser) throws Exception {
|
||||
String className = parser.nextText();
|
||||
// Attempt to load the class so that the class can get initialized
|
||||
|
|
|
@ -43,6 +43,14 @@ public abstract class IQ extends Packet {
|
|||
|
||||
private Type type = Type.GET;
|
||||
|
||||
public IQ() {
|
||||
super();
|
||||
}
|
||||
|
||||
public IQ(IQ iq) {
|
||||
super(iq);
|
||||
type = iq.getType();
|
||||
}
|
||||
/**
|
||||
* Returns the type of the IQ packet.
|
||||
*
|
||||
|
|
|
@ -90,6 +90,22 @@ public abstract class Packet {
|
|||
private final Map<String,Object> properties = new HashMap<String, Object>();
|
||||
private XMPPError error = null;
|
||||
|
||||
public Packet() {
|
||||
}
|
||||
|
||||
public Packet(Packet p) {
|
||||
packetID = p.getPacketID();
|
||||
to = p.getTo();
|
||||
from = p.getFrom();
|
||||
xmlns = p.xmlns;
|
||||
error = p.error;
|
||||
|
||||
// Copy extensions
|
||||
for (PacketExtension pe : p.getExtensions()) {
|
||||
addExtension(pe);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique ID of the packet. The returned value could be <tt>null</tt> when
|
||||
* ID_NOT_AVAILABLE was set as the packet's id.
|
||||
|
@ -247,14 +263,25 @@ public abstract class Packet {
|
|||
}
|
||||
|
||||
/**
|
||||
* Adds a packet extension to the packet.
|
||||
* Adds a packet extension to the packet. Does nothing if extension is null.
|
||||
*
|
||||
* @param extension a packet extension.
|
||||
*/
|
||||
public void addExtension(PacketExtension extension) {
|
||||
if (extension == null) return;
|
||||
packetExtensions.add(extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a collection of packet extensions to the packet. Does nothing if extensions is null.
|
||||
*
|
||||
* @param extensions a collection of packet extensions
|
||||
*/
|
||||
public void addExtensions(Collection<PacketExtension> extensions) {
|
||||
if (extensions == null) return;
|
||||
packetExtensions.addAll(extensions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a packet extension from the packet.
|
||||
*
|
||||
|
@ -266,7 +293,7 @@ public abstract class Packet {
|
|||
|
||||
/**
|
||||
* Returns the packet property with the specified name or <tt>null</tt> if the
|
||||
* property doesn't exist. Property values that were orginally primitives will
|
||||
* property doesn't exist. Property values that were originally primitives will
|
||||
* be returned as their object equivalent. For example, an int property will be
|
||||
* returned as an Integer, a double as a Double, etc.
|
||||
*
|
||||
|
@ -456,4 +483,4 @@ public abstract class Packet {
|
|||
result = 31 * result + (error != null ? error.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
187
source/org/jivesoftware/smack/util/Base32Encoder.java
Normal file
187
source/org/jivesoftware/smack/util/Base32Encoder.java
Normal file
|
@ -0,0 +1,187 @@
|
|||
/**
|
||||
* 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.smack.util;
|
||||
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Base32 string encoding is useful for when filenames case-insensitive filesystems are encoded.
|
||||
* Base32 representation takes roughly 20% more space then Base64.
|
||||
*
|
||||
* @author Florian Schmaus
|
||||
* Based on code by Brian Wellington (bwelling@xbill.org)
|
||||
* @see <a href="http://en.wikipedia.org/wiki/Base32">Base32 Wikipedia entry<a>
|
||||
*
|
||||
*/
|
||||
public class Base32Encoder implements StringEncoder {
|
||||
|
||||
private static Base32Encoder instance;
|
||||
private static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ2345678";
|
||||
|
||||
private Base32Encoder() {
|
||||
// Use getInstance()
|
||||
}
|
||||
|
||||
public static Base32Encoder getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new Base32Encoder();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String decode(String str) {
|
||||
ByteArrayOutputStream bs = new ByteArrayOutputStream();
|
||||
byte[] raw = str.getBytes();
|
||||
for (int i = 0; i < raw.length; i++) {
|
||||
char c = (char) raw[i];
|
||||
if (!Character.isWhitespace(c)) {
|
||||
c = Character.toUpperCase(c);
|
||||
bs.write((byte) c);
|
||||
}
|
||||
}
|
||||
|
||||
while (bs.size() % 8 != 0)
|
||||
bs.write('8');
|
||||
|
||||
byte[] in = bs.toByteArray();
|
||||
|
||||
bs.reset();
|
||||
DataOutputStream ds = new DataOutputStream(bs);
|
||||
|
||||
for (int i = 0; i < in.length / 8; i++) {
|
||||
short[] s = new short[8];
|
||||
int[] t = new int[5];
|
||||
|
||||
int padlen = 8;
|
||||
for (int j = 0; j < 8; j++) {
|
||||
char c = (char) in[i * 8 + j];
|
||||
if (c == '8')
|
||||
break;
|
||||
s[j] = (short) ALPHABET.indexOf(in[i * 8 + j]);
|
||||
if (s[j] < 0)
|
||||
return null;
|
||||
padlen--;
|
||||
}
|
||||
int blocklen = paddingToLen(padlen);
|
||||
if (blocklen < 0)
|
||||
return null;
|
||||
|
||||
// all 5 bits of 1st, high 3 (of 5) of 2nd
|
||||
t[0] = (s[0] << 3) | s[1] >> 2;
|
||||
// lower 2 of 2nd, all 5 of 3rd, high 1 of 4th
|
||||
t[1] = ((s[1] & 0x03) << 6) | (s[2] << 1) | (s[3] >> 4);
|
||||
// lower 4 of 4th, high 4 of 5th
|
||||
t[2] = ((s[3] & 0x0F) << 4) | ((s[4] >> 1) & 0x0F);
|
||||
// lower 1 of 5th, all 5 of 6th, high 2 of 7th
|
||||
t[3] = (s[4] << 7) | (s[5] << 2) | (s[6] >> 3);
|
||||
// lower 3 of 7th, all of 8th
|
||||
t[4] = ((s[6] & 0x07) << 5) | s[7];
|
||||
|
||||
try {
|
||||
for (int j = 0; j < blocklen; j++)
|
||||
ds.writeByte((byte) (t[j] & 0xFF));
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
|
||||
return new String(bs.toByteArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encode(String str) {
|
||||
byte[] b = str.getBytes();
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
|
||||
for (int i = 0; i < (b.length + 4) / 5; i++) {
|
||||
short s[] = new short[5];
|
||||
int t[] = new int[8];
|
||||
|
||||
int blocklen = 5;
|
||||
for (int j = 0; j < 5; j++) {
|
||||
if ((i * 5 + j) < b.length)
|
||||
s[j] = (short) (b[i * 5 + j] & 0xFF);
|
||||
else {
|
||||
s[j] = 0;
|
||||
blocklen--;
|
||||
}
|
||||
}
|
||||
int padlen = lenToPadding(blocklen);
|
||||
|
||||
// convert the 5 byte block into 8 characters (values 0-31).
|
||||
|
||||
// upper 5 bits from first byte
|
||||
t[0] = (byte) ((s[0] >> 3) & 0x1F);
|
||||
// lower 3 bits from 1st byte, upper 2 bits from 2nd.
|
||||
t[1] = (byte) (((s[0] & 0x07) << 2) | ((s[1] >> 6) & 0x03));
|
||||
// bits 5-1 from 2nd.
|
||||
t[2] = (byte) ((s[1] >> 1) & 0x1F);
|
||||
// lower 1 bit from 2nd, upper 4 from 3rd
|
||||
t[3] = (byte) (((s[1] & 0x01) << 4) | ((s[2] >> 4) & 0x0F));
|
||||
// lower 4 from 3rd, upper 1 from 4th.
|
||||
t[4] = (byte) (((s[2] & 0x0F) << 1) | ((s[3] >> 7) & 0x01));
|
||||
// bits 6-2 from 4th
|
||||
t[5] = (byte) ((s[3] >> 2) & 0x1F);
|
||||
// lower 2 from 4th, upper 3 from 5th;
|
||||
t[6] = (byte) (((s[3] & 0x03) << 3) | ((s[4] >> 5) & 0x07));
|
||||
// lower 5 from 5th;
|
||||
t[7] = (byte) (s[4] & 0x1F);
|
||||
|
||||
// write out the actual characters.
|
||||
for (int j = 0; j < t.length - padlen; j++) {
|
||||
char c = ALPHABET.charAt(t[j]);
|
||||
os.write(c);
|
||||
}
|
||||
}
|
||||
return new String(os.toByteArray());
|
||||
}
|
||||
|
||||
private static int lenToPadding(int blocklen) {
|
||||
switch (blocklen) {
|
||||
case 1:
|
||||
return 6;
|
||||
case 2:
|
||||
return 4;
|
||||
case 3:
|
||||
return 3;
|
||||
case 4:
|
||||
return 1;
|
||||
case 5:
|
||||
return 0;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private static int paddingToLen(int padlen) {
|
||||
switch (padlen) {
|
||||
case 6:
|
||||
return 1;
|
||||
case 4:
|
||||
return 2;
|
||||
case 3:
|
||||
return 3;
|
||||
case 1:
|
||||
return 4;
|
||||
case 0:
|
||||
return 5;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
44
source/org/jivesoftware/smack/util/Base64Encoder.java
Normal file
44
source/org/jivesoftware/smack/util/Base64Encoder.java
Normal file
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* 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.smack.util;
|
||||
|
||||
|
||||
/**
|
||||
* @author Florian Schmaus
|
||||
*/
|
||||
public class Base64Encoder implements StringEncoder {
|
||||
|
||||
private static Base64Encoder instance;
|
||||
|
||||
private Base64Encoder() {
|
||||
// Use getInstance()
|
||||
}
|
||||
|
||||
public static Base64Encoder getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new Base64Encoder();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public String encode(String s) {
|
||||
return Base64.encodeBytes(s.getBytes());
|
||||
}
|
||||
|
||||
public String decode(String s) {
|
||||
return new String(Base64.decode(s));
|
||||
}
|
||||
|
||||
}
|
38
source/org/jivesoftware/smack/util/StringEncoder.java
Normal file
38
source/org/jivesoftware/smack/util/StringEncoder.java
Normal file
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author Florian Schmaus
|
||||
*/
|
||||
package org.jivesoftware.smack.util;
|
||||
|
||||
// TODO move StringEncoder, Base64Encoder and Base32Encoder to smack.util
|
||||
|
||||
public interface StringEncoder {
|
||||
/**
|
||||
* Encodes an string to another representation
|
||||
*
|
||||
* @param string
|
||||
* @return
|
||||
*/
|
||||
public String encode(String string);
|
||||
|
||||
/**
|
||||
* Decodes an string back to it's initial representation
|
||||
*
|
||||
* @param string
|
||||
* @return
|
||||
*/
|
||||
public String decode(String string);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue