1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-06-23 20:04:51 +02:00
Smack/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpMessage.java
Florian Schmaus 4133eb175c Replace XPP3 by XmlPullParser interface wrapping StAX and XPP3
Introducing Smack's own XmlPullParser interface which tries to stay as
compatible as possible to XPP3. The interface is used to either wrap
StAX's XMLStreamReader if Smack is used on Java SE, and XPP3's
XmlPullParser if Smack is used on on Android.

Fixes SMACK-591.

Also introduce JUnit 5 and non-strict javadoc projects.
2019-05-06 22:10:50 +02:00

158 lines
5.9 KiB
Java

/**
*
* Copyright 2017 Florian Schmaus.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.ox;
import java.io.IOException;
import java.nio.charset.Charset;
import org.jivesoftware.smack.util.Objects;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smackx.ox.element.CryptElement;
import org.jivesoftware.smackx.ox.element.OpenPgpContentElement;
import org.jivesoftware.smackx.ox.element.OpenPgpElement;
import org.jivesoftware.smackx.ox.element.SignElement;
import org.jivesoftware.smackx.ox.element.SigncryptElement;
import org.jivesoftware.smackx.ox.provider.OpenPgpContentElementProvider;
import org.pgpainless.decryption_verification.OpenPgpMetadata;
/**
* This class embodies a decrypted and/or verified {@link OpenPgpElement}.
* <br>
* The content can be one of the following three {@link OpenPgpContentElement}s:
* <br><br>
* {@link SignElement}: The content is expected to be signed with the senders key, but unencrypted.<br>
* {@link CryptElement}: The content is expected to be encrypted, but not signed.<br>
* {@link SigncryptElement}: The content is expected to be signed with the senders key and encrypted.<br>
* <br>
* To determine, of which nature the content of the message is, use {@link #getState()}. You should utilize this
* information to cast the return value of {@link #getOpenPgpContentElement()} correctly.
* <br>
* Use {@link #getMetadata()} in order to get information about the messages encryption status, its signatures etc.
*/
public class OpenPgpMessage {
public enum State {
/**
* Represents a {@link SigncryptElement}.
*/
signcrypt,
/**
* Represents a {@link SignElement}.
*/
sign,
/**
* Represents a {@link CryptElement}.
*/
crypt,
;
}
private final String element;
private final State state;
private final OpenPgpMetadata metadata;
private OpenPgpContentElement openPgpContentElement;
/**
* Constructor.
*
* @param content XML representation of the decrypted {@link OpenPgpContentElement}.
* @param state {@link State} of the {@link OpenPgpContentElement}.
* @param metadata Metadata about the encryption.
*/
public OpenPgpMessage(String content, State state, OpenPgpMetadata metadata) {
this.metadata = Objects.requireNonNull(metadata);
this.state = Objects.requireNonNull(state);
this.element = Objects.requireNonNull(content);
}
/**
* Constructor.
*
* @param bytes bytes of the XML representation of the decrypted {@link OpenPgpContentElement}.
* @param state {@link State} of the {@link OpenPgpContentElement}.
* @param metadata metadata about the encryption.
*/
public OpenPgpMessage(byte[] bytes, State state, OpenPgpMetadata metadata) {
this(new String(Objects.requireNonNull(bytes), Charset.forName("UTF-8")), state, metadata);
}
/**
* Return the decrypted {@link OpenPgpContentElement} of this message.
* To determine, whether the element is a {@link SignElement}, {@link CryptElement} or {@link SigncryptElement},
* please consult {@link #getState()}.
*
* @return {@link OpenPgpContentElement}
* @throws XmlPullParserException if the parser encounters an error.
* @throws IOException if the parser encounters an error.
*/
public OpenPgpContentElement getOpenPgpContentElement() throws XmlPullParserException, IOException {
ensureOpenPgpContentElementSet();
return openPgpContentElement;
}
private void ensureOpenPgpContentElementSet() throws XmlPullParserException, IOException {
if (openPgpContentElement != null)
return;
openPgpContentElement = OpenPgpContentElementProvider.parseOpenPgpContentElement(element);
if (openPgpContentElement == null) {
return;
}
// Determine the state of the content element.
if (openPgpContentElement instanceof SigncryptElement) {
if (state != State.signcrypt) {
throw new IllegalStateException("OpenPgpContentElement was signed and encrypted, but is not a SigncryptElement.");
}
} else if (openPgpContentElement instanceof SignElement) {
if (state != State.sign) {
throw new IllegalStateException("OpenPgpContentElement was signed and unencrypted, but is not a SignElement.");
}
} else if (openPgpContentElement instanceof CryptElement) {
if (state != State.crypt) {
throw new IllegalStateException("OpenPgpContentElement was unsigned and encrypted, but is not a CryptElement.");
}
}
}
/**
* Return the state of the message. This value determines, whether the message was a {@link SignElement},
* {@link CryptElement} or {@link SigncryptElement}.
*
* @return state of the content element.
* @throws IOException if the parser encounters an error.
* @throws XmlPullParserException if the parser encounters and error.
*/
public State getState() throws IOException, XmlPullParserException {
ensureOpenPgpContentElementSet();
return state;
}
/**
* Return metadata about the encrypted message.
*
* @return metadata
*/
public OpenPgpMetadata getMetadata() {
return metadata;
}
}