mirror of https://github.com/sipwise/jitsi.git
- Support for thumbnails in Jabber file transfer. - Fixed some issues with the calculated file transfer speed and estimated transfer time. - Shows open and open folder links also on the sender side when the transfer is completed.cusax-fix
parent
425a1abaf8
commit
c98f98655f
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.protocol.jabber;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import net.java.sip.communicator.service.protocol.*;
|
||||
|
||||
/**
|
||||
* The <tt>OperationSetThumbnailedFileFactory</tt> is meant to be used by
|
||||
* bundles interested in making files with thumbnails. For example the user
|
||||
* interface can be interested in sending files with thumbnails through the
|
||||
* <tt>OperationSetFileTransfer</tt>.
|
||||
*
|
||||
* @author Yana Stamcheva
|
||||
*/
|
||||
public class OperationSetThumbnailedFileFactoryImpl
|
||||
implements OperationSetThumbnailedFileFactory
|
||||
{
|
||||
/**
|
||||
* Creates a file, by attaching the thumbnail, given by the details, to it.
|
||||
*
|
||||
* @param file the base file
|
||||
* @param thumbnailWidth the width of the thumbnail
|
||||
* @param thumbnailHeight the height of the thumbnail
|
||||
* @param thumbnailMimeType the mime type of the thumbnail
|
||||
* @param thumbnail the thumbnail data
|
||||
* @return a file with a thumbnail
|
||||
*/
|
||||
public File createFileWithThumbnail(File file,
|
||||
int thumbnailWidth,
|
||||
int thumbnailHeight,
|
||||
String thumbnailMimeType,
|
||||
byte[] thumbnail)
|
||||
{
|
||||
return new ThumbnailedFile(
|
||||
file, thumbnailWidth, thumbnailHeight,
|
||||
thumbnailMimeType, thumbnail);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.protocol.jabber;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* A <tt>ThumbnailedFile</tt> is a file with a thumbnail.
|
||||
*
|
||||
* @author Yana Stamcheva
|
||||
*/
|
||||
public class ThumbnailedFile
|
||||
extends File
|
||||
{
|
||||
private final int thumbnailWidth;
|
||||
|
||||
private final int thumbnailHeight;
|
||||
|
||||
private final String thumbnailMimeType;
|
||||
|
||||
private final byte[] thumbnail;
|
||||
|
||||
/**
|
||||
* Creates a <tt>ThumbnailedFile</tt>, by specifying the base <tt>file</tt>,
|
||||
* the <tt>thumbnailWidth</tt> and <tt>thumbnailHeight</tt>, the
|
||||
* <tt>thumbnailMimeType</tt> and the <tt>thumbnail</tt> itself.
|
||||
* @param file the base file
|
||||
* @param thumbnailWidth the width of the thumbnail
|
||||
* @param thumbnailHeight the height of the thumbnail
|
||||
* @param thumbnailMimeType the mime type
|
||||
* @param thumbnail the thumbnail
|
||||
*/
|
||||
public ThumbnailedFile( File file,
|
||||
int thumbnailWidth,
|
||||
int thumbnailHeight,
|
||||
String thumbnailMimeType,
|
||||
byte[] thumbnail)
|
||||
{
|
||||
super(file.getPath());
|
||||
|
||||
this.thumbnailWidth = thumbnailWidth;
|
||||
this.thumbnailHeight = thumbnailHeight;
|
||||
this.thumbnailMimeType = thumbnailMimeType;
|
||||
this.thumbnail = thumbnail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the thumbnail of this file.
|
||||
* @return the thumbnail of this file
|
||||
*/
|
||||
public byte[] getThumbnailData()
|
||||
{
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the thumbnail width.
|
||||
* @return the thumbnail width
|
||||
*/
|
||||
public int getThumbnailWidth()
|
||||
{
|
||||
return thumbnailWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the thumbnail height.
|
||||
* @return the thumbnail height
|
||||
*/
|
||||
public int getThumbnailHeight()
|
||||
{
|
||||
return thumbnailHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the thumbnail mime type.
|
||||
* @return the thumbnail mime type
|
||||
*/
|
||||
public String getThumbnailMimeType()
|
||||
{
|
||||
return thumbnailMimeType;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,269 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.protocol.jabber.extensions.thumbnail;
|
||||
|
||||
import org.jivesoftware.smack.packet.*;
|
||||
import org.jivesoftware.smack.provider.*;
|
||||
import org.jivesoftware.smack.util.*;
|
||||
import org.jivesoftware.smackx.packet.*;
|
||||
import org.jivesoftware.smackx.packet.StreamInitiation.*;
|
||||
import org.jivesoftware.smackx.provider.*;
|
||||
import org.xmlpull.v1.*;
|
||||
|
||||
/**
|
||||
* The <tt>FileElement</tt> extends the smackx <tt>StreamInitiation.File</tt>
|
||||
* in order to provide a file that supports thumbnails.
|
||||
*
|
||||
* @author Yana Stamcheva
|
||||
*/
|
||||
public class FileElement
|
||||
extends File
|
||||
implements IQProvider
|
||||
{
|
||||
private ThumbnailElement thumbnail;
|
||||
|
||||
/**
|
||||
* The element name of this <tt>IQProvider</tt>.
|
||||
*/
|
||||
public static final String ELEMENT_NAME = "si";
|
||||
|
||||
/**
|
||||
* The namespace of this <tt>IQProvider</tt>.
|
||||
*/
|
||||
public static final String NAMESPACE = "http://jabber.org/protocol/si";
|
||||
|
||||
/**
|
||||
* An empty constructor used to initialize this class as an
|
||||
* <tt>IQProvider</tt>.
|
||||
*/
|
||||
public FileElement()
|
||||
{
|
||||
this("", 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <tt>FileElement</tt> by specifying a base file and a thumbnail
|
||||
* to extend it with.
|
||||
*
|
||||
* @param baseFile the file used as a base
|
||||
* @param thumbnail the thumbnail to add
|
||||
*/
|
||||
public FileElement(File baseFile, ThumbnailElement thumbnail)
|
||||
{
|
||||
this(baseFile.getName(), baseFile.getSize());
|
||||
|
||||
this.thumbnail = thumbnail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <tt>FileElement</tt> by specifying the name and the size of the
|
||||
* file.
|
||||
*
|
||||
* @param name the name of the file
|
||||
* @param size the size of the file
|
||||
*/
|
||||
public FileElement(String name, long size)
|
||||
{
|
||||
super(name, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents this <tt>FileElement</tt> in an XML.
|
||||
*
|
||||
* @see File#toXML()
|
||||
*/
|
||||
public String toXML()
|
||||
{
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
|
||||
buffer.append("<").append(getElementName()).append(" xmlns=\"")
|
||||
.append(getNamespace()).append("\" ");
|
||||
|
||||
if (getName() != null)
|
||||
{
|
||||
buffer.append("name=\"").append(
|
||||
StringUtils.escapeForXML(getName())).append("\" ");
|
||||
}
|
||||
|
||||
if (getSize() > 0)
|
||||
{
|
||||
buffer.append("size=\"").append(getSize()).append("\" ");
|
||||
}
|
||||
|
||||
if (getDate() != null)
|
||||
{
|
||||
buffer.append("date=\"").append(
|
||||
DelayInformation.UTC_FORMAT
|
||||
.format(this.getDate())).append("\" ");
|
||||
}
|
||||
|
||||
if (getHash() != null)
|
||||
{
|
||||
buffer.append("hash=\"").append(getHash()).append("\" ");
|
||||
}
|
||||
|
||||
if ((this.getDesc() != null && getDesc().length() > 0)
|
||||
|| isRanged()
|
||||
|| thumbnail != null)
|
||||
{
|
||||
buffer.append(">");
|
||||
|
||||
if (getDesc() != null && getDesc().length() > 0)
|
||||
{
|
||||
buffer.append("<desc>").append(
|
||||
StringUtils.escapeForXML(getDesc())).append("</desc>");
|
||||
}
|
||||
|
||||
if (isRanged())
|
||||
{
|
||||
buffer.append("<range/>");
|
||||
}
|
||||
|
||||
if (thumbnail != null)
|
||||
{
|
||||
buffer.append(thumbnail.toXML());
|
||||
}
|
||||
|
||||
buffer.append("</").append(getElementName()).append(">");
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer.append("/>");
|
||||
}
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <tt>ThumbnailElement</tt> contained in this
|
||||
* <tt>FileElement</tt>.
|
||||
* @return the <tt>ThumbnailElement</tt> contained in this
|
||||
* <tt>FileElement</tt>
|
||||
*/
|
||||
public ThumbnailElement getThumbnailElement()
|
||||
{
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given <tt>thumbnail</tt> to this <tt>FileElement</tt>.
|
||||
* @param thumbnail the <tt>ThumbnailElement</tt> to set
|
||||
*/
|
||||
public void setThumbnailElement(ThumbnailElement thumbnail)
|
||||
{
|
||||
this.thumbnail = thumbnail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the given <tt>parser</tt> in order to create a
|
||||
* <tt>FileElement</tt> from it.
|
||||
* @param parser the parser to parse
|
||||
* @see IQProvider#parseIQ(XmlPullParser)
|
||||
*/
|
||||
public IQ parseIQ(final XmlPullParser parser)
|
||||
throws Exception
|
||||
{
|
||||
boolean done = false;
|
||||
|
||||
// si
|
||||
String id = parser.getAttributeValue("", "id");
|
||||
String mimeType = parser.getAttributeValue("", "mime-type");
|
||||
StreamInitiation initiation = new StreamInitiation();
|
||||
|
||||
// file
|
||||
String name = null;
|
||||
String size = null;
|
||||
String hash = null;
|
||||
String date = null;
|
||||
String desc = null;
|
||||
ThumbnailElement thumbnail = null;
|
||||
boolean isRanged = false;
|
||||
|
||||
// feature
|
||||
DataForm form = null;
|
||||
DataFormProvider dataFormProvider = new DataFormProvider();
|
||||
|
||||
int eventType;
|
||||
String elementName;
|
||||
String namespace;
|
||||
|
||||
while (!done)
|
||||
{
|
||||
eventType = parser.next();
|
||||
elementName = parser.getName();
|
||||
namespace = parser.getNamespace();
|
||||
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
if (elementName.equals("file"))
|
||||
{
|
||||
name = parser.getAttributeValue("", "name");
|
||||
size = parser.getAttributeValue("", "size");
|
||||
hash = parser.getAttributeValue("", "hash");
|
||||
date = parser.getAttributeValue("", "date");
|
||||
}
|
||||
else if (elementName.equals("desc"))
|
||||
{
|
||||
desc = parser.nextText();
|
||||
}
|
||||
else if (elementName.equals("range"))
|
||||
{
|
||||
isRanged = true;
|
||||
}
|
||||
else if (elementName.equals("x")
|
||||
&& namespace.equals("jabber:x:data"))
|
||||
{
|
||||
form = (DataForm) dataFormProvider.parseExtension(parser);
|
||||
}
|
||||
else if (elementName.equals("thumbnail"))
|
||||
{
|
||||
thumbnail = new ThumbnailElement(parser.getText());
|
||||
}
|
||||
}
|
||||
else if (eventType == XmlPullParser.END_TAG)
|
||||
{
|
||||
if (elementName.equals("si"))
|
||||
done = true;
|
||||
else if (elementName.equals("file"))
|
||||
{
|
||||
long fileSize = 0;
|
||||
|
||||
if(size != null && size.trim().length() !=0)
|
||||
{
|
||||
try
|
||||
{
|
||||
fileSize = Long.parseLong(size);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
FileElement file = new FileElement(name, fileSize);
|
||||
file.setHash(hash);
|
||||
|
||||
if (date != null)
|
||||
file.setDate(DelayInformation.UTC_FORMAT.parse(date));
|
||||
|
||||
if (thumbnail != null)
|
||||
file.setThumbnailElement(thumbnail);
|
||||
|
||||
file.setDesc(desc);
|
||||
file.setRanged(isRanged);
|
||||
initiation.setFile(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
initiation.setSesssionID(id);
|
||||
initiation.setMimeType(mimeType);
|
||||
initiation.setFeatureNegotiationForm(form);
|
||||
|
||||
return initiation;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,298 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.protocol.jabber.extensions.thumbnail;
|
||||
|
||||
import java.io.*;
|
||||
import java.security.*;
|
||||
|
||||
import javax.xml.parsers.*;
|
||||
|
||||
import org.w3c.dom.*;
|
||||
|
||||
import net.java.sip.communicator.util.*;
|
||||
|
||||
/**
|
||||
* The <tt>ThumbnailElement</tt> represents a "thumbnail" XML element, that is
|
||||
* contained in the file element, we're sending to notify for a file transfer.
|
||||
* The <tt>ThumbnailElement</tt>'s role is to advertise a thumbnail.
|
||||
*
|
||||
* @author Yana Stamcheva
|
||||
*/
|
||||
public class ThumbnailElement
|
||||
{
|
||||
private static final Logger logger
|
||||
= Logger.getLogger(ThumbnailElement.class);
|
||||
|
||||
/**
|
||||
* The name of the XML element used for transport of thumbnail parameters.
|
||||
*/
|
||||
public static final String ELEMENT_NAME = "thumbnail";
|
||||
|
||||
/**
|
||||
* The names XMPP space that the thumbnail elements belong to.
|
||||
*/
|
||||
public static final String NAMESPACE = "urn:xmpp:thumbs:0";
|
||||
|
||||
/**
|
||||
* The name of the thumbnail attribute "cid".
|
||||
*/
|
||||
public final static String CID = "cid";
|
||||
|
||||
/**
|
||||
* The name of the thumbnail attribute "mime-type".
|
||||
*/
|
||||
public final static String MIME_TYPE = "mime-type";
|
||||
|
||||
/**
|
||||
* The name of the thumbnail attribute "width".
|
||||
*/
|
||||
public final static String WIDTH = "width";
|
||||
|
||||
/**
|
||||
* The name of the thumbnail attribute "height".
|
||||
*/
|
||||
public final static String HEIGHT = "height";
|
||||
|
||||
private String cid;
|
||||
|
||||
private String mimeType;
|
||||
|
||||
private int width;
|
||||
|
||||
private int height;
|
||||
|
||||
/**
|
||||
* Creates a <tt>ThumbnailPacketExtension</tt> by specifying all extension
|
||||
* attributes.
|
||||
*
|
||||
* @param serverAddress the Jabber address of the destination contact
|
||||
* @param thumbnailData the byte array containing the thumbnail data
|
||||
* @param mimeType the mime type attribute
|
||||
* @param width the width of the thumbnail
|
||||
* @param height the height of the thumbnail
|
||||
*/
|
||||
public ThumbnailElement(String serverAddress,
|
||||
byte[] thumbnailData,
|
||||
String mimeType,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
this.cid = createCid(serverAddress, thumbnailData);
|
||||
this.mimeType = mimeType;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <tt>ThumbnailElement</tt> by parsing the given <tt>xml</tt>.
|
||||
*
|
||||
* @param xml the XML from which we obtain the needed information to create
|
||||
* this <tt>ThumbnailElement</tt>
|
||||
*/
|
||||
public ThumbnailElement(String xml)
|
||||
{
|
||||
DocumentBuilderFactory factory =
|
||||
DocumentBuilderFactory.newInstance();
|
||||
|
||||
DocumentBuilder builder;
|
||||
try
|
||||
{
|
||||
builder = factory.newDocumentBuilder();
|
||||
InputStream in = new ByteArrayInputStream (xml.getBytes());
|
||||
Document doc = builder.parse(in);
|
||||
|
||||
Element e = doc.getDocumentElement();
|
||||
String elementName = e.getNodeName();
|
||||
|
||||
if (elementName.equals (ELEMENT_NAME))
|
||||
{
|
||||
this.setCid(e.getAttribute (CID));
|
||||
this.setMimeType(e.getAttribute(MIME_TYPE));
|
||||
this.setHeight(Integer.parseInt(e.getAttribute(HEIGHT)));
|
||||
this.setHeight(Integer.parseInt(e.getAttribute(WIDTH)));
|
||||
}
|
||||
else
|
||||
logger.debug ("Element name unknown!");
|
||||
}
|
||||
catch (ParserConfigurationException ex)
|
||||
{
|
||||
logger.debug ("Problem parsing Thumbnail Element : " + xml, ex);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.debug ("Problem parsing Thumbnail Element : " + xml, ex);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.debug ("Problem parsing Thumbnail Element : " + xml, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the XML representation of this PacketExtension.
|
||||
*
|
||||
* @return the packet extension as XML.
|
||||
*/
|
||||
public String toXML()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
|
||||
// open element
|
||||
buf.append("<").append(ELEMENT_NAME).
|
||||
append(" xmlns=\"").append(NAMESPACE).append("\"");
|
||||
|
||||
// adding thumbnail parameters
|
||||
buf = addXmlAttribute(buf, CID, this.getCid());
|
||||
buf = addXmlAttribute(buf, MIME_TYPE, this.getMimeType());
|
||||
buf = addXmlIntAttribute(buf, WIDTH, this.getWidth());
|
||||
buf = addXmlIntAttribute(buf, HEIGHT, this.getWidth());
|
||||
|
||||
// close element
|
||||
buf.append("/>");
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Content-ID, corresponding to this <tt>ThumbnailElement</tt>.
|
||||
* @return the Content-ID, corresponding to this <tt>ThumbnailElement</tt>
|
||||
*/
|
||||
public String getCid()
|
||||
{
|
||||
return cid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mime type of this <tt>ThumbnailElement</tt>.
|
||||
* @return the mime type of this <tt>ThumbnailElement</tt>
|
||||
*/
|
||||
public String getMimeType()
|
||||
{
|
||||
return mimeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the width of this <tt>ThumbnailElement</tt>.
|
||||
* @return the width of this <tt>ThumbnailElement</tt>
|
||||
*/
|
||||
public int getWidth()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the height of this <tt>ThumbnailElement</tt>.
|
||||
* @return the height of this <tt>ThumbnailElement</tt>
|
||||
*/
|
||||
public int getHeight()
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the content-ID of this <tt>ThumbnailElement</tt>.
|
||||
* @param cid the content-ID to set
|
||||
*/
|
||||
public void setCid(String cid)
|
||||
{
|
||||
this.cid = cid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the mime type of the thumbnail.
|
||||
* @param mimeType the mime type of the thumbnail
|
||||
*/
|
||||
public void setMimeType(String mimeType)
|
||||
{
|
||||
this.mimeType = mimeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the width of the thumbnail
|
||||
* @param width the width of the thumbnail
|
||||
*/
|
||||
public void setWidth(int width)
|
||||
{
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the height of the thumbnail
|
||||
* @param height the height of the thumbnail
|
||||
*/
|
||||
public void setHeight(int height)
|
||||
{
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the XML <tt>String</tt> corresponding to the specified attribute
|
||||
* and value and adds them to the <tt>buff</tt> StringBuffer.
|
||||
*
|
||||
* @param buff the <tt>StringBuffer</tt> to add the attribute and value to.
|
||||
* @param attrName the name of the thumbnail attribute that we're adding.
|
||||
* @param attrValue the value of the attribute we're adding to the XML
|
||||
* buffer.
|
||||
* @return the <tt>StringBuffer</tt> that we've added the attribute and its
|
||||
* value to.
|
||||
*/
|
||||
private StringBuffer addXmlAttribute( StringBuffer buff,
|
||||
String attrName,
|
||||
String attrValue)
|
||||
{
|
||||
buff.append(" " + attrName + "=\"").append(attrValue).append("\"");
|
||||
|
||||
return buff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the XML <tt>String</tt> corresponding to the specified attribute
|
||||
* and value and adds them to the <tt>buff</tt> StringBuffer.
|
||||
*
|
||||
* @param buff the <tt>StringBuffer</tt> to add the attribute and value to.
|
||||
* @param attrName the name of the thumbnail attribute that we're adding.
|
||||
* @param attrValue the value of the attribute we're adding to the XML
|
||||
* buffer.
|
||||
* @return the <tt>StringBuffer</tt> that we've added the attribute and its
|
||||
* value to.
|
||||
*/
|
||||
private StringBuffer addXmlIntAttribute(StringBuffer buff,
|
||||
String attrName,
|
||||
int attrValue)
|
||||
{
|
||||
|
||||
return addXmlAttribute(buff, attrName, String.valueOf(attrValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the cid attrubte value for the given <tt>contactJabberAddress</tt>
|
||||
* and <tt>thumbnailData</tt>.
|
||||
*
|
||||
* @param serverAddress the Jabber server address
|
||||
* @param thumbnailData the byte array containing the data
|
||||
* @return the cid attrubte value for the thumbnail extension
|
||||
*/
|
||||
private String createCid( String serverAddress,
|
||||
byte[] thumbnailData)
|
||||
{
|
||||
try
|
||||
{
|
||||
return "sha1+" + Sha1Crypto.encode(thumbnailData)
|
||||
+ "@" + serverAddress;
|
||||
}
|
||||
catch (NoSuchAlgorithmException e)
|
||||
{
|
||||
logger.debug("Failed to encode the thumbnail in SHA-1.", e);
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
{
|
||||
logger.debug("Failed to encode the thumbnail in SHA-1.", e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.protocol.jabber.extensions.thumbnail;
|
||||
|
||||
import net.java.sip.communicator.util.*;
|
||||
|
||||
import org.jivesoftware.smack.packet.*;
|
||||
import org.jivesoftware.smack.provider.*;
|
||||
import org.xmlpull.v1.*;
|
||||
|
||||
/**
|
||||
* The <tt>ThumbnailIQ</tt> is an IQ packet that is meant to be used for
|
||||
* thumbnail requests and responses.
|
||||
*
|
||||
* @author Yana Stamcheva
|
||||
*/
|
||||
public class ThumbnailIQ
|
||||
extends IQ
|
||||
implements IQProvider
|
||||
{
|
||||
/**
|
||||
* The names XMPP space that the thumbnail elements belong to.
|
||||
*/
|
||||
public static final String NAMESPACE = "urn:xmpp:bob";
|
||||
|
||||
/**
|
||||
* The name of the "data" element.
|
||||
*/
|
||||
public static final String ELEMENT_NAME = "data";
|
||||
|
||||
/**
|
||||
* The name of the thumbnail attribute "cid".
|
||||
*/
|
||||
public final static String CID = "cid";
|
||||
|
||||
/**
|
||||
* The name of the thumbnail attribute "mime-type".
|
||||
*/
|
||||
public final static String TYPE = "type";
|
||||
|
||||
private String cid;
|
||||
|
||||
private String mimeType;
|
||||
|
||||
private byte[] data;
|
||||
|
||||
/**
|
||||
* An empty constructor used to initialize this class as an
|
||||
* <tt>IQProvier</tt>.
|
||||
*/
|
||||
public ThumbnailIQ() {}
|
||||
|
||||
/**
|
||||
* Creates a <tt>ThumbnailIQ</tt> packet, by specifying the source, the
|
||||
* destination, the content-ID and the type of this packet. The type could
|
||||
* be one of the types defined in <tt>IQ.Type</tt>.
|
||||
*
|
||||
* @param from the source of the packet
|
||||
* @param to the destination of the packet
|
||||
* @param cid the content-ID used to identify this packet in the destination
|
||||
* @param type the of the packet, which could be one of the types defined
|
||||
* in <tt>IQ.Type</tt>
|
||||
*/
|
||||
public ThumbnailIQ(String from, String to, String cid, Type type)
|
||||
{
|
||||
this.cid = cid;
|
||||
|
||||
this.setFrom(from);
|
||||
this.setTo(to);
|
||||
this.setType(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <tt>ThumbnailIQ</tt> packet, by specifying the source, the
|
||||
* destination, the content-ID, the type of data and the data of the
|
||||
* thumbnail. We also precise the type of the packet to create.
|
||||
*
|
||||
* @param from the source of the packet
|
||||
* @param to the destination of the packet
|
||||
* @param cid the content-ID used to identify this packet in the destination
|
||||
* @param mimeType the type of the data passed
|
||||
* @param data the data of the thumbnail
|
||||
* @param type the of the packet, which could be one of the types defined
|
||||
* in <tt>IQ.Type</tt>
|
||||
*/
|
||||
public ThumbnailIQ( String from, String to, String cid,
|
||||
String mimeType, byte[] data, Type type)
|
||||
{
|
||||
this(from, to, cid, type);
|
||||
|
||||
this.data = data;
|
||||
this.mimeType = mimeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the given <tt>XmlPullParser</tt> into a ThumbnailIQ packet and
|
||||
* returns it.
|
||||
* @see IQProvider#parseIQ(XmlPullParser)
|
||||
*/
|
||||
public IQ parseIQ(XmlPullParser parser) throws Exception
|
||||
{
|
||||
String elementName = parser.getName();
|
||||
String namespace = parser.getNamespace();
|
||||
|
||||
if (elementName.equals(ELEMENT_NAME)
|
||||
&& namespace.equals(NAMESPACE))
|
||||
{
|
||||
this.cid = parser.getAttributeValue("", CID);
|
||||
this.mimeType = parser.getAttributeValue("", TYPE);
|
||||
}
|
||||
|
||||
int eventType = parser.next();
|
||||
|
||||
if (eventType == XmlPullParser.TEXT)
|
||||
{
|
||||
this.data = Base64.decode(parser.getText());
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the xml representing the data element in this <tt>IQ</tt> packet.
|
||||
*/
|
||||
public String getChildElementXML()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
|
||||
// open extension
|
||||
buf.append("<").append(ELEMENT_NAME)
|
||||
.append(" xmlns=\"").append(NAMESPACE).append("\"")
|
||||
.append(" " + CID).append("=\"").append(cid).append("\"");
|
||||
|
||||
if (mimeType != null)
|
||||
buf.append(" " + TYPE).append("=\"").append(mimeType).append("\">");
|
||||
else
|
||||
buf.append(">");
|
||||
|
||||
if (data != null)
|
||||
{
|
||||
byte[] encodedData = Base64.encode(data);
|
||||
buf.append(new String(encodedData));
|
||||
}
|
||||
|
||||
buf.append("</data>");
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the content-ID of this thumbnail packet.
|
||||
* @return the content-ID of this thumbnail packet
|
||||
*/
|
||||
public String getCid()
|
||||
{
|
||||
return cid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data of the thumbnail.
|
||||
* @return the data of the thumbnail
|
||||
*/
|
||||
public byte[] getData()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.service.protocol;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* The <tt>OperationSetThumbnailedFileFactory</tt> is meant to be used by
|
||||
* bundles interested in making files with thumbnails. For example the user
|
||||
* interface can be interested in sending files with thumbnails through the
|
||||
* <tt>OperationSetFileTransfer</tt>.
|
||||
*
|
||||
* @author Yana Stamcheva
|
||||
*/
|
||||
public interface OperationSetThumbnailedFileFactory
|
||||
extends OperationSet
|
||||
{
|
||||
/**
|
||||
* Creates a file, by attaching the thumbnail, given by the details, to it.
|
||||
*
|
||||
* @param file the base file
|
||||
* @param thumbnailWidth the width of the thumbnail
|
||||
* @param thumbnailHeight the height of the thumbnail
|
||||
* @param thumbnailMimeType the mime type of the thumbnail
|
||||
* @param thumbnail the thumbnail data
|
||||
* @return a file with a thumbnail
|
||||
*/
|
||||
public File createFileWithThumbnail(File file,
|
||||
int thumbnailWidth,
|
||||
int thumbnailHeight,
|
||||
String thumbnailMimeType,
|
||||
byte[] thumbnail);
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
package net.java.sip.communicator.util;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
public class Sha1Crypto
|
||||
{
|
||||
/**
|
||||
* Encodes the given text with the SHA-1 algorithm.
|
||||
*
|
||||
* @param text the text to encode
|
||||
* @return the encoded text
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws UnsupportedEncodingException
|
||||
*/
|
||||
public static String encode(String text)
|
||||
throws NoSuchAlgorithmException,
|
||||
UnsupportedEncodingException
|
||||
{
|
||||
MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
|
||||
|
||||
byte[] sha1hash;
|
||||
messageDigest.update(text.getBytes("iso-8859-1"), 0, text.length());
|
||||
sha1hash = messageDigest.digest();
|
||||
|
||||
return convertToHex(sha1hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the given text with the SHA-1 algorithm.
|
||||
*
|
||||
* @param byteArreay the byte array to encode
|
||||
* @return the encoded text
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws UnsupportedEncodingException
|
||||
*/
|
||||
public static String encode(byte[] byteArray)
|
||||
throws NoSuchAlgorithmException,
|
||||
UnsupportedEncodingException
|
||||
{
|
||||
MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
|
||||
|
||||
byte[] sha1hash;
|
||||
messageDigest.update(byteArray);
|
||||
sha1hash = messageDigest.digest();
|
||||
|
||||
return convertToHex(sha1hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given byte data into Hex string.
|
||||
*
|
||||
* @param data the byte array to convert
|
||||
* @return the Hex string representation of the given byte array
|
||||
*/
|
||||
private static String convertToHex(byte[] data)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (int i = 0; i < data.length; i++)
|
||||
{
|
||||
int halfbyte = (data[i] >>> 4) & 0x0F;
|
||||
int two_halfs = 0;
|
||||
do
|
||||
{
|
||||
if ((0 <= halfbyte) && (halfbyte <= 9))
|
||||
buf.append((char) ('0' + halfbyte));
|
||||
else
|
||||
buf.append((char) ('a' + (halfbyte - 10)));
|
||||
halfbyte = data[i] & 0x0F;
|
||||
}
|
||||
while(two_halfs++ < 1);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue