1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-06-16 08:34:50 +02:00
Smack/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/store/filebased/FileBasedOpenPgpMetadataStore.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

151 lines
5.5 KiB
Java

/**
*
* Copyright 2018 Paul Schaub.
*
* 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.store.filebased;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.util.CloseableUtil;
import org.jivesoftware.smack.util.FileUtils;
import org.jivesoftware.smackx.ox.store.abstr.AbstractOpenPgpMetadataStore;
import org.jivesoftware.smackx.ox.store.definition.OpenPgpMetadataStore;
import org.jivesoftware.smackx.ox.util.Util;
import org.jxmpp.jid.BareJid;
import org.jxmpp.util.XmppDateTime;
import org.pgpainless.key.OpenPgpV4Fingerprint;
/**
* Implementation of the {@link OpenPgpMetadataStore}, which stores metadata information in a file structure.
* The information is stored in the following directory structure:
*
* <pre>
* {@code
* <basePath>/
* <userjid@server.tld>/
* announced.list // list of the users announced key fingerprints and modification dates
* }
* </pre>
*/
public class FileBasedOpenPgpMetadataStore extends AbstractOpenPgpMetadataStore {
public static final String ANNOUNCED = "announced.list";
private static final Logger LOGGER = Logger.getLogger(FileBasedOpenPgpMetadataStore.class.getName());
private final File basePath;
public FileBasedOpenPgpMetadataStore(File basePath) {
this.basePath = basePath;
}
@Override
public Map<OpenPgpV4Fingerprint, Date> readAnnouncedFingerprintsOf(BareJid contact) throws IOException {
return readFingerprintsAndDates(getAnnouncedFingerprintsPath(contact));
}
@Override
public void writeAnnouncedFingerprintsOf(BareJid contact, Map<OpenPgpV4Fingerprint, Date> metadata)
throws IOException {
File destination = getAnnouncedFingerprintsPath(contact);
writeFingerprintsAndDates(metadata, destination);
}
static Map<OpenPgpV4Fingerprint, Date> readFingerprintsAndDates(File source) throws IOException {
// TODO: Why do we not throw a FileNotFoundException here?
if (!source.exists() || source.isDirectory()) {
return new HashMap<>();
}
BufferedReader reader = null;
try {
InputStream inputStream = FileUtils.prepareFileInputStream(source);
InputStreamReader isr = new InputStreamReader(inputStream, Util.UTF8);
reader = new BufferedReader(isr);
Map<OpenPgpV4Fingerprint, Date> fingerprintDateMap = new HashMap<>();
String line; int lineNr = 0;
while ((line = reader.readLine()) != null) {
lineNr++;
line = line.trim();
String[] split = line.split(" ");
if (split.length != 2) {
LOGGER.log(Level.FINE, "Skipping invalid line " + lineNr + " in file " + source.getAbsolutePath());
continue;
}
try {
OpenPgpV4Fingerprint fingerprint = new OpenPgpV4Fingerprint(split[0]);
Date date = XmppDateTime.parseXEP0082Date(split[1]);
fingerprintDateMap.put(fingerprint, date);
} catch (IllegalArgumentException | ParseException e) {
LOGGER.log(Level.WARNING, "Error parsing fingerprint/date touple in line " + lineNr +
" of file " + source.getAbsolutePath(), e);
}
}
return fingerprintDateMap;
} finally {
CloseableUtil.maybeClose(reader, LOGGER);
}
}
static void writeFingerprintsAndDates(Map<OpenPgpV4Fingerprint, Date> data, File destination)
throws IOException {
if (data == null || data.isEmpty()) {
FileUtils.maybeDeleteFileOrThrow(destination);
return;
}
FileUtils.maybeCreateFileWithParentDirectories(destination);
BufferedWriter writer = null;
try {
OutputStream outputStream = FileUtils.prepareFileOutputStream(destination);
OutputStreamWriter osw = new OutputStreamWriter(outputStream, Util.UTF8);
writer = new BufferedWriter(osw);
for (OpenPgpV4Fingerprint fingerprint : data.keySet()) {
Date date = data.get(fingerprint);
String line = fingerprint.toString() + " " +
(date != null ? XmppDateTime.formatXEP0082Date(date) : XmppDateTime.formatXEP0082Date(new Date()));
writer.write(line);
writer.newLine();
}
} finally {
CloseableUtil.maybeClose(writer, LOGGER);
}
}
private File getAnnouncedFingerprintsPath(BareJid contact) {
return new File(FileBasedOpenPgpStore.getContactsPath(basePath, contact), ANNOUNCED);
}
}