diff --git a/source/org/jivesoftware/smackx/packet/VCard.java b/source/org/jivesoftware/smackx/packet/VCard.java index d6d475348..daf51747c 100644 --- a/source/org/jivesoftware/smackx/packet/VCard.java +++ b/source/org/jivesoftware/smackx/packet/VCard.java @@ -27,9 +27,13 @@ import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.filter.PacketIDFilter; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.XMPPError; +import org.jivesoftware.smack.util.StringUtils; +import java.io.IOException; +import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.Modifier; +import java.net.URL; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -37,19 +41,19 @@ import java.util.Map; /** * A VCard class for use with the * SMACK jabber library.

- * + *

* You should refer to the * JEP-54 documentation.

- * + *

* Please note that this class is incomplete but it does provide the most commonly found * information in vCards. Also remember that VCard transfer is not a standard, and the protocol * may change or be replaced.

- * + *

* Usage: *

- *
+ * 

* // To save VCard: - * + *

* VCard vCard = new VCard(); * vCard.setFirstName("kir"); * vCard.setLastName("max"); @@ -57,16 +61,16 @@ import java.util.Map; * vCard.setJabberId("jabber@id.org"); * vCard.setOrganization("Jetbrains, s.r.o"); * vCard.setNickName("KIR"); - * + *

* vCard.setField("TITLE", "Mr"); * vCard.setAddressFieldHome("STREET", "Some street"); * vCard.setAddressFieldWork("CTRY", "US"); * vCard.setPhoneWork("FAX", "3443233"); - * + *

* vCard.save(connection); - * + *

* // To load VCard: - * + *

* VCard vCard = new VCard(); * vCard.load(conn); // load own VCard * vCard.load(conn, "joe@foo.bar"); // load someone's VCard @@ -102,6 +106,8 @@ public class VCard extends IQ { private String organization; private String organizationUnit; + private String avatar; + /** * Such as DESC ROLE GEO etc.. see JEP-0054 */ @@ -114,7 +120,7 @@ public class VCard extends IQ { * Set generic VCard field. * * @param field value of field. Possible values: NICKNAME, PHOTO, BDAY, JABBERID, MAILER, TZ, - * GEO, TITLE, ROLE, LOGO, NOTE, PRODID, REV, SORT-STRING, SOUND, UID, URL, DESC. + * GEO, TITLE, ROLE, LOGO, NOTE, PRODID, REV, SORT-STRING, SOUND, UID, URL, DESC. */ public String getField(String field) { return (String) otherSimpleFields.get(field); @@ -282,6 +288,95 @@ public class VCard extends IQ { return (String) workPhones.get(phoneType); } + /** + * Set the avatar for the VCard by specifying the url to the image. + * + * @param avatarURL the url to the image(png,jpeg,gif,bmp) + */ + public void setAvatar(URL avatarURL) { + byte[] bytes = new byte[0]; + try { + bytes = getBytes(avatarURL); + } + catch (IOException e) { + e.printStackTrace(); + } + + String encodedImage = StringUtils.encodeBase64(bytes); + + setField("PHOTO", "image/jpeg" + encodedImage + ""); + } + + /** + * Specify the bytes for the avatar to use. + * @param bytes the bytes of the avatar. + */ + public void setAvatar(byte[] bytes) { + String encodedImage = StringUtils.encodeBase64(bytes); + + setField("PHOTO", "image/jpeg" + encodedImage + ""); + } + + /** + * Set the encoded avatar string. This is used by the provider. + * + * @param encodedAvatar the encoded avatar string. + */ + public void setEncodedImage(String encodedAvatar) { + //TODO Move VCard and VCardProvider into a vCard package. + this.avatar = encodedAvatar; + } + + /** + * Return the byte representation of the avatar(if one exists), otherwise returns null if + * no avatar could be found. + * Example 1 + *

+     * // Load Avatar from VCard
+     * byte[] avatarBytes = vCard.getAvatar();
+     * 

+ * // To create an ImageIcon for Swing applications + * ImageIcon icon = new ImageIcon(avatar); + *

+ * // To create just an image object from the bytes + * ByteArrayInputStream bais = new ByteArrayInputStream(avatar); + * try { + * Image image = ImageIO.read(bais); + * } + * catch (IOException e) { + * e.printStackTrace(); + * } + *

+ * + * @return byte representation of avatar. + */ + public byte[] getAvatar() { + if (avatar == null) { + return null; + } + if (avatar != null) { + return StringUtils.decodeBase64(avatar); + } + return null; + } + + /** + * Common code for getting the bytes of a url. + * + * @param url the url to read. + */ + public static byte[] getBytes(URL url) throws IOException { + InputStream in = url.openStream(); + final byte[] buffer = new byte[4096]; + while (true) { + final int bytesRead = in.read(buffer); + if (bytesRead < 0) { + break; + } + } + return buffer; + } + /** * Save this vCard for the user connected by 'connection'. Connection should be authenticated * and not anonymous.

@@ -333,7 +428,8 @@ public class VCard extends IQ { if (result.getError() != null) { throw new XMPPException(result.getError()); } - } catch (ClassCastException e) { + } + catch (ClassCastException e) { System.out.println("No VCard for " + user); } @@ -357,7 +453,8 @@ public class VCard extends IQ { try { field.setAccessible(true); field.set(this, field.get(result)); - } catch (IllegalAccessException e) { + } + catch (IllegalAccessException e) { throw new RuntimeException("This cannot happen:" + field, e); } } @@ -472,6 +569,7 @@ public class VCard extends IQ { //============================================================== private class VCardWriter { + private final StringBuffer sb; VCardWriter(StringBuffer sb) { @@ -604,7 +702,7 @@ public class VCard extends IQ { } private void appendTag(String tag, String attr, String attrValue, boolean hasContent, - ContentBuilder builder) { + ContentBuilder builder) { sb.append('<').append(tag); if (attr != null) { sb.append(' ').append(attr).append('=').append('\'').append(attrValue).append('\''); @@ -614,7 +712,8 @@ public class VCard extends IQ { sb.append('>'); builder.addTagContent(); sb.append("\n"); - } else { + } + else { sb.append("/>\n"); } } @@ -638,6 +737,7 @@ public class VCard extends IQ { //============================================================== private interface ContentBuilder { + void addTagContent(); } diff --git a/source/org/jivesoftware/smackx/provider/VCardProvider.java b/source/org/jivesoftware/smackx/provider/VCardProvider.java index 085832f8a..3caf730db 100644 --- a/source/org/jivesoftware/smackx/provider/VCardProvider.java +++ b/source/org/jivesoftware/smackx/provider/VCardProvider.java @@ -98,6 +98,7 @@ public class VCardProvider implements IQProvider { vCard.setFirstName(getTagContents("GIVEN")); vCard.setLastName(getTagContents("FAMILY")); vCard.setMiddleName(getTagContents("MIDDLE")); + vCard.setEncodedImage(getTagContents("BINVAL")); setupEmails();