2022-03-10 16:56:46 +01:00
|
|
|
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
|
|
|
|
//
|
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
2022-03-17 15:27:28 +01:00
|
|
|
package pgp.wkd.discovery;
|
2022-03-10 16:56:46 +01:00
|
|
|
|
|
|
|
import pgp.certificate_store.Certificate;
|
2022-03-21 11:25:03 +01:00
|
|
|
import pgp.wkd.exception.CertNotFetchableException;
|
2022-03-10 16:56:46 +01:00
|
|
|
|
2022-03-17 15:27:28 +01:00
|
|
|
import javax.annotation.Nonnull;
|
2022-03-21 11:25:03 +01:00
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.io.OutputStream;
|
2022-03-10 16:56:46 +01:00
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.List;
|
|
|
|
|
2022-04-05 16:11:06 +02:00
|
|
|
/**
|
|
|
|
* Result of discovering an OpenPGP certificate via WKD.
|
|
|
|
*/
|
2022-03-17 15:27:28 +01:00
|
|
|
public class DiscoveryResult {
|
2022-03-10 16:56:46 +01:00
|
|
|
|
2022-04-05 16:11:06 +02:00
|
|
|
private final List<DiscoveryResponse> items;
|
2022-03-10 16:56:46 +01:00
|
|
|
|
2022-04-05 16:11:06 +02:00
|
|
|
/**
|
|
|
|
* Create a {@link DiscoveryResult} from a list of {@link DiscoveryResponse DiscoveryResponses}.
|
|
|
|
* Usually the list contains one or two responses (one for each {@link DiscoveryMethod}.
|
|
|
|
*
|
|
|
|
* @param items responses
|
|
|
|
*/
|
2022-03-17 15:27:28 +01:00
|
|
|
public DiscoveryResult(@Nonnull List<DiscoveryResponse> items) {
|
2022-03-10 16:56:46 +01:00
|
|
|
this.items = items;
|
|
|
|
}
|
|
|
|
|
2022-04-05 16:11:06 +02:00
|
|
|
/**
|
|
|
|
* Return the list of acceptable certificates that were discovered.
|
|
|
|
*
|
|
|
|
* @return certificates
|
|
|
|
*/
|
2022-03-17 15:27:28 +01:00
|
|
|
@Nonnull
|
2022-03-10 16:56:46 +01:00
|
|
|
public List<Certificate> getCertificates() {
|
|
|
|
List<Certificate> certificates = new ArrayList<>();
|
|
|
|
|
2022-03-17 15:27:28 +01:00
|
|
|
for (DiscoveryResponse item : items) {
|
2022-03-10 16:56:46 +01:00
|
|
|
if (item.isSuccessful()) {
|
|
|
|
certificates.addAll(item.getCertificates());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return certificates;
|
|
|
|
}
|
|
|
|
|
2022-04-05 16:11:06 +02:00
|
|
|
/**
|
|
|
|
* Return true, if at least one {@link DiscoveryResponse} was successful and contained acceptable certificates.
|
|
|
|
*
|
|
|
|
* @return success
|
|
|
|
*/
|
2022-03-10 16:56:46 +01:00
|
|
|
public boolean isSuccessful() {
|
2022-03-17 15:27:28 +01:00
|
|
|
for (DiscoveryResponse item : items) {
|
2022-03-10 16:56:46 +01:00
|
|
|
if (item.isSuccessful() && item.hasCertificates()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-03-21 11:25:03 +01:00
|
|
|
/**
|
|
|
|
* Write out the (successful) result (certificates) to the given {@link OutputStream}.
|
|
|
|
* This method does not close the output stream.
|
|
|
|
*
|
|
|
|
* @param outputStream output stream
|
2022-04-02 18:13:06 +02:00
|
|
|
* @throws IOException in case of an IO error
|
2022-03-21 11:25:03 +01:00
|
|
|
*/
|
2022-03-21 13:11:00 +01:00
|
|
|
public void write(OutputStream outputStream)
|
|
|
|
throws IOException {
|
|
|
|
|
2022-03-21 11:25:03 +01:00
|
|
|
if (!isSuccessful()) {
|
2022-03-21 13:11:00 +01:00
|
|
|
throwCertNotFetchableException();
|
2022-03-21 11:25:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
byte[] buf = new byte[4096];
|
|
|
|
int read;
|
|
|
|
for (Certificate certificate : getCertificates()) {
|
|
|
|
InputStream certIn = certificate.getInputStream();
|
|
|
|
while ((read = certIn.read(buf)) != -1) {
|
|
|
|
outputStream.write(buf, 0, read);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-21 13:11:00 +01:00
|
|
|
private void throwCertNotFetchableException() {
|
|
|
|
Throwable cause = null;
|
2022-04-05 16:11:06 +02:00
|
|
|
for (DiscoveryResponse response : getResponses()) {
|
2022-03-21 13:11:00 +01:00
|
|
|
// Find the most "useful" exception.
|
|
|
|
// Rejections are more useful than fetching failures
|
|
|
|
if (!response.getRejectedCertificates().isEmpty()) {
|
|
|
|
cause = response.getRejectedCertificates().get(0).getReasonForRejection();
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
cause = response.getFetchingFailure();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
throw new CertNotFetchableException("Could not fetch certificates.", cause);
|
|
|
|
}
|
|
|
|
|
2022-04-05 16:11:06 +02:00
|
|
|
/**
|
|
|
|
* Return the list of responses.
|
|
|
|
*
|
|
|
|
* @return responses
|
|
|
|
*/
|
2022-03-17 15:27:28 +01:00
|
|
|
@Nonnull
|
2022-04-05 16:11:06 +02:00
|
|
|
public List<DiscoveryResponse> getResponses() {
|
2022-03-10 16:56:46 +01:00
|
|
|
return items;
|
|
|
|
}
|
|
|
|
}
|