diff --git a/source/org/jivesoftware/smackx/packet/VCard.java b/source/org/jivesoftware/smackx/packet/VCard.java
index 4f1248859..aabeb8ac8 100644
--- a/source/org/jivesoftware/smackx/packet/VCard.java
+++ b/source/org/jivesoftware/smackx/packet/VCard.java
@@ -118,6 +118,9 @@ public class VCard extends IQ {
*/
private Map otherSimpleFields = new HashMap();
+ // fields that, as they are should not be escaped before forwarding to the server
+ private Map otherUnescapableFields = new HashMap();
+
public VCard() {
}
@@ -139,7 +142,24 @@ public class VCard extends IQ {
* @see #getField(String)
*/
public void setField(String field, String value) {
- otherSimpleFields.put(field, value);
+ setField(field, value, false);
+ }
+
+ /**
+ * Set generic, unescapable VCard field. If unescabale is set to true, XML maybe a part of the
+ * value.
+ *
+ * @param value value of field
+ * @param field field to set. See {@link #getField(String)}
+ * @param isUnescapable True if the value should not be escaped, and false if it should.
+ */
+ public void setField(String field, String value, boolean isUnescapable) {
+ if(!isUnescapable) {
+ otherSimpleFields.put(field, value);
+ }
+ else {
+ otherUnescapableFields.put(field, value);
+ }
}
public String getFirstName() {
@@ -310,7 +330,7 @@ public class VCard extends IQ {
String encodedImage = StringUtils.encodeBase64(bytes);
avatar = encodedImage;
- setField("PHOTO", "image/jpeg" + encodedImage + "");
+ setField("PHOTO", "image/jpeg" + encodedImage + "", true);
}
/**
@@ -322,7 +342,7 @@ public class VCard extends IQ {
String encodedImage = StringUtils.encodeBase64(bytes);
avatar = encodedImage;
- setField("PHOTO", "image/jpeg" + encodedImage + "");
+ setField("PHOTO", "image/jpeg" + encodedImage + "", true);
}
/**
@@ -362,10 +382,7 @@ public class VCard extends IQ {
if (avatar == null) {
return null;
}
- if (avatar != null) {
- return StringUtils.decodeBase64(avatar);
- }
- return null;
+ return StringUtils.decodeBase64(avatar);
}
/**
@@ -384,12 +401,21 @@ public class VCard extends IQ {
}
private static byte[] getFileBytes(File file) throws IOException {
- BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
- int bytes = (int) file.length();
- byte[] buffer = new byte[bytes];
- int readBytes = bis.read(buffer);
- bis.close();
- return buffer;
+ BufferedInputStream bis = null;
+ try {
+ bis = new BufferedInputStream(new FileInputStream(file));
+ int bytes = (int) file.length();
+ byte[] buffer = new byte[bytes];
+ int readBytes = bis.read(buffer);
+ if(readBytes != buffer.length) {
+ throw new IOException("Entire file not read");
+ }
+ return buffer;
+ } finally {
+ if(bis != null) {
+ bis.close();
+ }
+ }
}
/**
@@ -403,12 +429,13 @@ public class VCard extends IQ {
return null;
}
- MessageDigest digest = null;
+ MessageDigest digest;
try {
digest = MessageDigest.getInstance("SHA-1");
}
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
+ return null;
}
digest.update(bytes);
@@ -515,13 +542,13 @@ public class VCard extends IQ {
private void checkAuthenticated(XMPPConnection connection) {
if (connection == null) {
- new IllegalArgumentException("No connection was provided");
+ throw new IllegalArgumentException("No connection was provided");
}
if (!connection.isAuthenticated()) {
- new IllegalArgumentException("Connection is not authenticated");
+ throw new IllegalArgumentException("Connection is not authenticated");
}
if (connection.isAnonymous()) {
- new IllegalArgumentException("Connection cannot be anonymous");
+ throw new IllegalArgumentException("Connection cannot be anonymous");
}
}
@@ -590,11 +617,8 @@ public class VCard extends IQ {
if (!workAddr.equals(vCard.workAddr)) {
return false;
}
- if (!workPhones.equals(vCard.workPhones)) {
- return false;
- }
+ return workPhones.equals(vCard.workPhones);
- return true;
}
public int hashCode() {
@@ -662,7 +686,7 @@ public class VCard extends IQ {
appendEmptyTag(type);
appendEmptyTag("INTERNET");
appendEmptyTag("PREF");
- appendTag("USERID", email);
+ appendTag("USERID", StringUtils.escapeForXML(email));
}
});
}
@@ -676,7 +700,7 @@ public class VCard extends IQ {
public void addTagContent() {
appendEmptyTag(entry.getKey());
appendEmptyTag(code);
- appendTag("NUMBER", (String) entry.getValue());
+ appendTag("NUMBER", StringUtils.escapeForXML((String) entry.getValue()));
}
});
}
@@ -691,7 +715,7 @@ public class VCard extends IQ {
Iterator it = addr.entrySet().iterator();
while (it.hasNext()) {
final Map.Entry entry = (Map.Entry) it.next();
- appendTag((String) entry.getKey(), (String) entry.getValue());
+ appendTag((String) entry.getKey(), StringUtils.escapeForXML((String) entry.getValue()));
}
}
});
@@ -704,6 +728,13 @@ public class VCard extends IQ {
private void appendGenericFields() {
Iterator it = otherSimpleFields.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry entry = (Map.Entry) it.next();
+ appendTag(entry.getKey().toString(),
+ StringUtils.escapeForXML((String) entry.getValue()));
+ }
+
+ it = otherUnescapableFields.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
appendTag(entry.getKey().toString(), (String) entry.getValue());
@@ -714,29 +745,24 @@ public class VCard extends IQ {
if (hasOrganizationFields()) {
appendTag("ORG", true, new ContentBuilder() {
public void addTagContent() {
- appendTag("ORGNAME", organization);
- appendTag("ORGUNIT", organizationUnit);
+ appendTag("ORGNAME", StringUtils.escapeForXML(organization));
+ appendTag("ORGUNIT", StringUtils.escapeForXML(organizationUnit));
}
});
}
}
- private void appendField(String tag) {
- String value = (String) otherSimpleFields.get(tag);
- appendTag(tag, value);
- }
-
private void appendFN() {
final ContentBuilder contentBuilder = new ContentBuilder() {
public void addTagContent() {
if (firstName != null) {
- sb.append(firstName + ' ');
+ sb.append(StringUtils.escapeForXML(firstName)).append(' ');
}
if (middleName != null) {
- sb.append(middleName + ' ');
+ sb.append(StringUtils.escapeForXML(middleName)).append(' ');
}
if (lastName != null) {
- sb.append(lastName);
+ sb.append(StringUtils.escapeForXML(lastName));
}
}
};
@@ -746,9 +772,9 @@ public class VCard extends IQ {
private void appendN() {
appendTag("N", true, new ContentBuilder() {
public void addTagContent() {
- appendTag("FAMILY", lastName);
- appendTag("GIVEN", firstName);
- appendTag("MIDDLE", middleName);
+ appendTag("FAMILY", StringUtils.escapeForXML(lastName));
+ appendTag("GIVEN", StringUtils.escapeForXML(firstName));
+ appendTag("MIDDLE", StringUtils.escapeForXML(middleName));
}
});
}
diff --git a/source/org/jivesoftware/smackx/provider/VCardProvider.java b/source/org/jivesoftware/smackx/provider/VCardProvider.java
index af45448b3..681d951de 100644
--- a/source/org/jivesoftware/smackx/provider/VCardProvider.java
+++ b/source/org/jivesoftware/smackx/provider/VCardProvider.java
@@ -22,6 +22,7 @@ package org.jivesoftware.smackx.provider;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
+import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.packet.VCard;
import org.w3c.dom.*;
import org.xmlpull.v1.XmlPullParser;
@@ -35,7 +36,7 @@ import java.util.List;
import java.util.ArrayList;
/**
- * vCard provider.
+ * vCard provider.
*
* @author Gaston Dombiak
*/
@@ -49,7 +50,8 @@ public class VCardProvider implements IQProvider {
while (true) {
switch (event) {
case XmlPullParser.TEXT:
- sb.append(parser.getText());
+ // We must re-escape the xml so that the DOM won't throw an exception
+ sb.append(StringUtils.escapeForXML(parser.getText()));
break;
case XmlPullParser.START_TAG:
sb.append('<').append(parser.getName()).append('>');