1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * you may not use this file except in compliance with the License.
4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * You may obtain a copy of the License at
5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *     http://www.apache.org/licenses/LICENSE-2.0
7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Unless required by applicable law or agreed to in writing, software
9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * distributed under the License is distributed on an "AS IS" BASIS,
10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * See the License for the specific language governing permissions and
12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * limitations under the License.
13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.jivesoftware.smackx.bytestreams.ibb.packet;
15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.PacketExtension;
17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.util.StringUtils;
18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamManager;
19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Represents a chunk of data of an In-Band Bytestream within an IQ stanza or a
22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * message stanza
23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Henning Staib
25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic class DataPacketExtension implements PacketExtension {
27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * The element name of the data packet extension.
30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public final static String ELEMENT_NAME = "data";
32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /* unique session ID identifying this In-Band Bytestream */
34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private final String sessionID;
35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /* sequence of this packet in regard to the other data packets */
37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private final long seq;
38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /* the data contained in this packet */
40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private final String data;
41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private byte[] decodedData;
43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Creates a new In-Band Bytestream data packet.
46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param sessionID unique session ID identifying this In-Band Bytestream
48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param seq sequence of this packet in regard to the other data packets
49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param data the base64 encoded data contained in this packet
50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public DataPacketExtension(String sessionID, long seq, String data) {
52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (sessionID == null || "".equals(sessionID)) {
53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            throw new IllegalArgumentException("Session ID must not be null or empty");
54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (seq < 0 || seq > 65535) {
56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            throw new IllegalArgumentException("Sequence must not be between 0 and 65535");
57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (data == null) {
59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            throw new IllegalArgumentException("Data must not be null");
60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        this.sessionID = sessionID;
62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        this.seq = seq;
63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        this.data = data;
64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the unique session ID identifying this In-Band Bytestream.
68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the unique session ID identifying this In-Band Bytestream
70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public String getSessionID() {
72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return sessionID;
73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the sequence of this packet in regard to the other data packets.
77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the sequence of this packet in regard to the other data packets.
79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public long getSeq() {
81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return seq;
82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the data contained in this packet.
86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the data contained in this packet.
88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public String getData() {
90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return data;
91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the decoded data or null if data could not be decoded.
95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * <p>
96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * The encoded data is invalid if it contains bad Base64 input characters or
97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * if it contains the pad ('=') character on a position other than the last
98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * character(s) of the data. See <a
99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * href="http://xmpp.org/extensions/xep-0047.html#sec">XEP-0047</a> Section
100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * 6.
101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the decoded data
103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public byte[] getDecodedData() {
105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // return cached decoded data
106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (this.decodedData != null) {
107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            return this.decodedData;
108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // data must not contain the pad (=) other than end of data
111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (data.matches(".*={1,2}+.+")) {
112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            return null;
113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // decodeBase64 will return null if bad characters are included
116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        this.decodedData = StringUtils.decodeBase64(data);
117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return this.decodedData;
118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public String getElementName() {
121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return ELEMENT_NAME;
122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public String getNamespace() {
125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return InBandBytestreamManager.NAMESPACE;
126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public String toXML() {
129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        StringBuilder buf = new StringBuilder();
130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        buf.append("<");
131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        buf.append(getElementName());
132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        buf.append(" ");
133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        buf.append("xmlns=\"");
134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        buf.append(InBandBytestreamManager.NAMESPACE);
135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        buf.append("\" ");
136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        buf.append("seq=\"");
137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        buf.append(seq);
138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        buf.append("\" ");
139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        buf.append("sid=\"");
140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        buf.append(sessionID);
141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        buf.append("\">");
142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        buf.append(data);
143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        buf.append("</");
144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        buf.append(getElementName());
145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        buf.append(">");
146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return buf.toString();
147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
150