001/**
002 *
003 * Copyright © 2017 Paul Schaub
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.jivesoftware.smackx.hashes.element;
018
019import static org.jivesoftware.smack.util.Objects.requireNonNull;
020
021import org.jivesoftware.smack.packet.ExtensionElement;
022import org.jivesoftware.smack.util.XmlStringBuilder;
023import org.jivesoftware.smack.util.stringencoder.Base64;
024
025import org.jivesoftware.smackx.hashes.HashManager;
026
027/**
028 * Represent a hash element.
029 *
030 * @author Paul Schaub
031 */
032public class HashElement implements ExtensionElement {
033
034    public static final String ELEMENT = "hash";
035    public static final String ATTR_ALGO = "algo";
036
037    private final HashManager.ALGORITHM algorithm;
038    private final byte[] hash;
039    private final String hashB64;
040
041    /**
042     * Create a HashElement from pre-calculated values.
043     * @param algorithm The algorithm which was used.
044     * @param hash the checksum as byte array.
045     */
046    public HashElement(HashManager.ALGORITHM algorithm, byte[] hash) {
047        this.algorithm = requireNonNull(algorithm);
048        this.hash = requireNonNull(hash);
049        hashB64 = Base64.encodeToString(hash);
050    }
051
052    /**
053     * Create a HashElement from pre-calculated values.
054     * @param algorithm the algorithm that was used.
055     * @param hashB64 the checksum in base 64.
056     */
057    public HashElement(HashManager.ALGORITHM algorithm, String hashB64) {
058        this.algorithm = algorithm;
059        this.hash = Base64.decode(hashB64);
060        this.hashB64 = hashB64;
061    }
062
063    /**
064     * Return the hash algorithm used in this HashElement.
065     *
066     * @return algorithm the algorithm.
067     */
068    public HashManager.ALGORITHM getAlgorithm() {
069        return algorithm;
070    }
071
072    /**
073     * Return the checksum as a byte array.
074     *
075     * @return the hash.
076     */
077    public byte[] getHash() {
078        return hash;
079    }
080
081    /**
082     * Return the checksum as a base16 (hex) string.
083     *
084     * @return the hash.
085     */
086    public String getHashB64() {
087        return hashB64;
088    }
089
090    @Override
091    public String getElementName() {
092        return ELEMENT;
093    }
094
095    @Override
096    public CharSequence toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
097        XmlStringBuilder sb = new XmlStringBuilder(this);
098        sb.attribute(ATTR_ALGO, algorithm.toString());
099        sb.rightAngleBracket();
100        sb.append(hashB64);
101        sb.closeElement(this);
102        return sb;
103    }
104
105    @Override
106    public String getNamespace() {
107        return HashManager.NAMESPACE.V2.toString();
108    }
109
110    @Override
111    public boolean equals(Object other) {
112        if (other == null || !(other instanceof HashElement)) {
113            return false;
114        }
115
116        HashElement otherHashElement = (HashElement) other;
117        return this.getAlgorithm() == otherHashElement.getAlgorithm() &&
118            this.getHashB64().equals(otherHashElement.getHashB64());
119    }
120
121    @Override
122    public int hashCode() {
123        return toXML().toString().hashCode();
124    }
125}