1
0
Fork 0
mirror of https://codeberg.org/Mercury-IM/Smack synced 2024-09-26 17:59:34 +02:00

1) SMACK-170 - Added JID escaping capabilities to SMACK.

2) Escaping form field values to prevent bad xml.

git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@5363 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
Derek DeMoro 2006-09-14 15:19:39 +00:00 committed by derek
parent 1df8baa6f7
commit 85781a7158
8 changed files with 83 additions and 35 deletions

View file

@ -425,6 +425,7 @@ public class XMPPConnection {
} }
// Do partial version of nameprep on the username. // Do partial version of nameprep on the username.
username = username.toLowerCase().trim(); username = username.toLowerCase().trim();
username = StringUtils.escapeNode(username);
String response; String response;
if (configuration.isSASLAuthenticationEnabled() && if (configuration.isSASLAuthenticationEnabled() &&

View file

@ -112,7 +112,7 @@ public abstract class Packet {
* value has not been set. * value has not been set.
*/ */
public String getTo() { public String getTo() {
return to; return StringUtils.escapeJID(to);
} }
/** /**
@ -134,7 +134,7 @@ public abstract class Packet {
* valud has not been set. * valud has not been set.
*/ */
public String getFrom() { public String getFrom() {
return from; return StringUtils.escapeJID(from);
} }
/** /**

View file

@ -198,7 +198,7 @@ public class RosterPacket extends IQ {
public String toXML() { public String toXML() {
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
buf.append("<item jid=\"").append(user).append("\""); buf.append("<item jid=\"").append(StringUtils.escapeJID(user)).append("\"");
if (name != null) { if (name != null) {
buf.append(" name=\"").append(StringUtils.escapeForXML(name)).append("\""); buf.append(" name=\"").append(StringUtils.escapeForXML(name)).append("\"");
} }

View file

@ -47,7 +47,7 @@ public class StringUtils {
if (XMPPAddress == null) { if (XMPPAddress == null) {
return null; return null;
} }
int atIndex = XMPPAddress.indexOf("@"); int atIndex = XMPPAddress.lastIndexOf("@");
if (atIndex <= 0) { if (atIndex <= 0) {
return ""; return "";
} }
@ -68,7 +68,7 @@ public class StringUtils {
if (XMPPAddress == null) { if (XMPPAddress == null) {
return null; return null;
} }
int atIndex = XMPPAddress.indexOf("@"); int atIndex = XMPPAddress.lastIndexOf("@");
// If the String ends with '@', return the empty string. // If the String ends with '@', return the empty string.
if (atIndex + 1 > XMPPAddress.length()) { if (atIndex + 1 > XMPPAddress.length()) {
return ""; return "";
@ -127,6 +127,8 @@ public class StringUtils {
} }
} }
/** /**
* Escapes the node portion of a JID according to "JID Escaping" (JEP-0106). * Escapes the node portion of a JID according to "JID Escaping" (JEP-0106).
* Escaping replaces characters prohibited by node-prep with escape sequences, * Escaping replaces characters prohibited by node-prep with escape sequences,
@ -166,15 +168,9 @@ public class StringUtils {
for (int i=0, n=node.length(); i<n; i++) { for (int i=0, n=node.length(); i<n; i++) {
char c = node.charAt(i); char c = node.charAt(i);
switch (c) { switch (c) {
case '"': buf.append("\\22"); break;
case '&': buf.append("\\26"); break;
case '\'': buf.append("\\27"); break;
case '/': buf.append("\\2f"); break;
case ':': buf.append("\\3a"); break;
case '<': buf.append("\\3c"); break;
case '>': buf.append("\\3e"); break;
case '@': buf.append("\\40"); break; case '@': buf.append("\\40"); break;
case '\\': buf.append("\\5c"); break;
default: { default: {
if (Character.isWhitespace(c)) { if (Character.isWhitespace(c)) {
buf.append("\\20"); buf.append("\\20");
@ -188,6 +184,43 @@ public class StringUtils {
return buf.toString(); return buf.toString();
} }
/**
* Escapes a complete JID by examing the Node itself and escaping
* when neccessary.
* @param jid the users JID
* @return the escaped JID.
*/
public static String escapeJID(String jid){
if(jid == null){
return null;
}
final StringBuilder builder = new StringBuilder();
String node = parseName(jid);
String restOfJID = jid.substring(node.length());
builder.append(escapeNode(node));
builder.append(restOfJID);
return builder.toString();
}
/**
* Unescapes a complete JID by examing the node itself and unescaping when necessary.
* @param jid the users jid.
* @return the unescaped JID.
*/
public static String unescapeJID(String jid){
if(jid == null){
return null;
}
final StringBuilder builder = new StringBuilder();
String node = parseName(jid);
String restOfJID = jid.substring(node.length());
builder.append(unescapeNode(node));
builder.append(restOfJID);
return builder.toString();
}
/** /**
* Un-escapes the node portion of a JID according to "JID Escaping" (JEP-0106).<p> * Un-escapes the node portion of a JID according to "JID Escaping" (JEP-0106).<p>
* Escaping replaces characters prohibited by node-prep with escape sequences, * Escaping replaces characters prohibited by node-prep with escape sequences,
@ -308,7 +341,7 @@ public class StringUtils {
if (i > last) { if (i > last) {
out.append(input, last, i - last); out.append(input, last, i - last);
} }
// Do nothing if the string is of the form &#235; (unicode value) // Do nothing if the string is of the form &#235; (unicode value)
if (!(len > i + 5 if (!(len > i + 5
&& input[i + 1] == '#' && input[i + 1] == '#'
&& Character.isDigit(input[i + 2]) && Character.isDigit(input[i + 2])

View file

@ -20,6 +20,8 @@
package org.jivesoftware.smackx; package org.jivesoftware.smackx;
import org.jivesoftware.smack.util.StringUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
@ -288,7 +290,7 @@ public class FormField {
} }
// Loop through all the values and append them to the string buffer // Loop through all the values and append them to the string buffer
for (Iterator<String> i = getValues(); i.hasNext();) { for (Iterator<String> i = getValues(); i.hasNext();) {
buf.append("<value>").append(i.next()).append("</value>"); buf.append("<value>").append(StringUtils.escapeForXML(i.next())).append("</value>");
} }
// Loop through all the values and append them to the string buffer // Loop through all the values and append them to the string buffer
for (Iterator i = getOptions(); i.hasNext();) { for (Iterator i = getOptions(); i.hasNext();) {

View file

@ -20,6 +20,8 @@
package org.jivesoftware.smackx; package org.jivesoftware.smackx;
import org.jivesoftware.smack.util.StringUtils;
import java.util.*; import java.util.*;
/** /**
@ -100,7 +102,7 @@ public class RemoteRosterEntry {
public String toXML() { public String toXML() {
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
buf.append("<item jid=\"").append(user).append("\""); buf.append("<item jid=\"").append(StringUtils.escapeJID(user)).append("\"");
if (name != null) { if (name != null) {
buf.append(" name=\"").append(name).append("\""); buf.append(" name=\"").append(name).append("\"");
} }

View file

@ -21,6 +21,7 @@
package org.jivesoftware.smackx.packet; package org.jivesoftware.smackx.packet;
import org.jivesoftware.smack.packet.PacketExtension; import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.util.StringUtils;
/** /**
* Represents extended presence information about roles, affiliations, full JIDs, * Represents extended presence information about roles, affiliations, full JIDs,
@ -130,7 +131,7 @@ public class MUCUser implements PacketExtension {
public Destroy getDestroy() { public Destroy getDestroy() {
return destroy; return destroy;
} }
/** /**
* Sets the invitation for another user to a room. The sender of the invitation * Sets the invitation for another user to a room. The sender of the invitation
* must be an occupant of the room. The invitation will be sent to the room which in turn * must be an occupant of the room. The invitation will be sent to the room which in turn
@ -203,7 +204,7 @@ public class MUCUser implements PacketExtension {
private String reason; private String reason;
private String from; private String from;
private String to; private String to;
/** /**
* Returns the bare JID of the inviter or, optionally, the room JID. (e.g. * Returns the bare JID of the inviter or, optionally, the room JID. (e.g.
* 'crone1@shakespeare.lit/desktop'). * 'crone1@shakespeare.lit/desktop').
@ -288,7 +289,7 @@ public class MUCUser implements PacketExtension {
private String reason; private String reason;
private String from; private String from;
private String to; private String to;
/** /**
* Returns the bare JID of the invitee that rejected the invitation. (e.g. * Returns the bare JID of the invitee that rejected the invitation. (e.g.
* 'crone1@shakespeare.lit/desktop'). * 'crone1@shakespeare.lit/desktop').
@ -375,7 +376,7 @@ public class MUCUser implements PacketExtension {
private String jid; private String jid;
private String nick; private String nick;
private String role; private String role;
/** /**
* Creates a new item child. * Creates a new item child.
* *
@ -386,7 +387,7 @@ public class MUCUser implements PacketExtension {
this.affiliation = affiliation; this.affiliation = affiliation;
this.role = role; this.role = role;
} }
/** /**
* Returns the actor (JID of an occupant in the room) that was kicked or banned. * Returns the actor (JID of an occupant in the room) that was kicked or banned.
* *
@ -496,7 +497,7 @@ public class MUCUser implements PacketExtension {
buf.append(" affiliation=\"").append(getAffiliation()).append("\""); buf.append(" affiliation=\"").append(getAffiliation()).append("\"");
} }
if (getJid() != null) { if (getJid() != null) {
buf.append(" jid=\"").append(getJid()).append("\""); buf.append(" jid=\"").append(StringUtils.escapeJID(getJid())).append("\"");
} }
if (getNick() != null) { if (getNick() != null) {
buf.append(" nick=\"").append(getNick()).append("\""); buf.append(" nick=\"").append(getNick()).append("\"");
@ -513,7 +514,7 @@ public class MUCUser implements PacketExtension {
buf.append("<reason>").append(getReason()).append("</reason>"); buf.append("<reason>").append(getReason()).append("</reason>");
} }
if (getActor() != null) { if (getActor() != null) {
buf.append("<actor jid=\"").append(getActor()).append("\"/>"); buf.append("<actor jid=\"").append(StringUtils.escapeJID(getActor())).append("\"/>");
} }
buf.append("</item>"); buf.append("</item>");
} }
@ -528,7 +529,7 @@ public class MUCUser implements PacketExtension {
* @author Gaston Dombiak * @author Gaston Dombiak
*/ */
public static class Status { public static class Status {
private String code; private String code;
/** /**
* Creates a new instance of Status with the specified code. * Creates a new instance of Status with the specified code.
@ -538,7 +539,7 @@ public class MUCUser implements PacketExtension {
public Status(String code) { public Status(String code) {
this.code = code; this.code = code;
} }
/** /**
* Returns the code that uniquely identifies the reason of the error. The code * Returns the code that uniquely identifies the reason of the error. The code
* assists in presenting notification messages. * assists in presenting notification messages.
@ -566,8 +567,8 @@ public class MUCUser implements PacketExtension {
public static class Destroy { public static class Destroy {
private String reason; private String reason;
private String jid; private String jid;
/** /**
* Returns the JID of an alternate location since the current room is being destroyed. * Returns the JID of an alternate location since the current room is being destroyed.
* *
@ -608,7 +609,7 @@ public class MUCUser implements PacketExtension {
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
buf.append("<destroy"); buf.append("<destroy");
if (getJid() != null) { if (getJid() != null) {
buf.append(" jid=\"").append(getJid()).append("\""); buf.append(" jid=\"").append(StringUtils.escapeJID(getJid())).append("\"");
} }
if (getReason() == null) { if (getReason() == null) {
buf.append("/>"); buf.append("/>");

View file

@ -49,7 +49,7 @@ public class UserSearchManager {
/** /**
* Creates a new UserSearchManager. * Creates a new UserSearchManager.
* *
* @param con the XMPPConnection to use. * @param con the XMPPConnection to use.
*/ */
public UserSearchManager(XMPPConnection con) { public UserSearchManager(XMPPConnection con) {
this.con = con; this.con = con;
@ -71,7 +71,7 @@ public class UserSearchManager {
* Submits a search form to the server and returns the resulting information * Submits a search form to the server and returns the resulting information
* in the form of <code>ReportedData</code> * in the form of <code>ReportedData</code>
* *
* @param searchForm the <code>Form</code> to submit for searching. * @param searchForm the <code>Form</code> to submit for searching.
* @param searchService the name of the search service to use. * @param searchService the name of the search service to use.
* @return the ReportedData returned by the server. * @return the ReportedData returned by the server.
* @throws XMPPException thrown if a server error has occurred. * @throws XMPPException thrown if a server error has occurred.
@ -88,18 +88,27 @@ public class UserSearchManager {
* @throws XMPPException thrown if a server error has occurred. * @throws XMPPException thrown if a server error has occurred.
*/ */
public Collection getSearchServices() throws XMPPException { public Collection getSearchServices() throws XMPPException {
List searchServices = new ArrayList(); final List<String> searchServices = new ArrayList<String>();
ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(con); ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(con);
DiscoverItems items = discoManager.discoverItems(con.getServiceName()); DiscoverItems items = discoManager.discoverItems(con.getServiceName());
for (Iterator it = items.getItems(); it.hasNext();) { Iterator iter = items.getItems();
DiscoverItems.Item item = (DiscoverItems.Item) it.next(); while (iter.hasNext()) {
DiscoverItems.Item item = (DiscoverItems.Item) iter.next();
try { try {
DiscoverInfo info = discoManager.discoverInfo(item.getEntityID()); DiscoverInfo info = null;
try {
info = discoManager.discoverInfo(item.getEntityID());
}
catch (XMPPException e) {
// Ignore Case
continue;
}
if (info.containsFeature("jabber:iq:search")) { if (info.containsFeature("jabber:iq:search")) {
searchServices.add(item.getEntityID()); searchServices.add(item.getEntityID());
} }
} }
catch (XMPPException e) { catch (Exception e) {
// No info found. // No info found.
break; break;
} }