001/** 002 * 003 * Copyright 2018 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.ox.store.filebased; 018 019import java.io.BufferedReader; 020import java.io.BufferedWriter; 021import java.io.File; 022import java.io.FileNotFoundException; 023import java.io.IOException; 024import java.io.InputStream; 025import java.io.InputStreamReader; 026import java.io.OutputStream; 027import java.io.OutputStreamWriter; 028import java.util.logging.Level; 029import java.util.logging.Logger; 030 031import org.jivesoftware.smackx.ox.store.abstr.AbstractOpenPgpTrustStore; 032import org.jivesoftware.smackx.ox.store.definition.OpenPgpTrustStore; 033import org.jivesoftware.smackx.ox.util.FileUtils; 034import org.jivesoftware.smackx.ox.util.Util; 035 036import org.jxmpp.jid.BareJid; 037import org.pgpainless.key.OpenPgpV4Fingerprint; 038 039/** 040 * Implementation of the {@link OpenPgpTrustStore} which stores information in a directory structure. 041 * 042 * <pre> 043 * {@code 044 * <basePath>/ 045 * <userjid@server.tld>/ 046 * <fingerprint>.trust // Trust record for a key 047 * } 048 * </pre> 049 */ 050public class FileBasedOpenPgpTrustStore extends AbstractOpenPgpTrustStore { 051 052 private static final Logger LOGGER = Logger.getLogger(FileBasedOpenPgpTrustStore.class.getName()); 053 054 private final File basePath; 055 056 public static String TRUST_RECORD(OpenPgpV4Fingerprint fingerprint) { 057 return fingerprint.toString() + ".trust"; 058 } 059 060 public FileBasedOpenPgpTrustStore(File basePath) { 061 this.basePath = basePath; 062 } 063 064 @Override 065 protected Trust readTrust(BareJid owner, OpenPgpV4Fingerprint fingerprint) throws IOException { 066 File file = getTrustPath(owner, fingerprint); 067 BufferedReader reader = null; 068 try { 069 InputStream inputStream = FileUtils.prepareFileInputStream(file); 070 InputStreamReader isr = new InputStreamReader(inputStream, Util.UTF8); 071 reader = new BufferedReader(isr); 072 073 Trust trust = null; 074 String line; int lineNr = 0; 075 while ((line = reader.readLine()) != null) { 076 lineNr++; 077 try { 078 trust = Trust.valueOf(line); 079 break; 080 } catch (IllegalArgumentException e) { 081 LOGGER.log(Level.WARNING, "Skipping invalid trust record in line " + lineNr + " of file " + 082 file.getAbsolutePath()); 083 } 084 } 085 reader.close(); 086 return trust != null ? trust : Trust.undecided; 087 } catch (IOException e) { 088 if (reader != null) { 089 try { 090 reader.close(); 091 } catch (IOException ignored) { 092 // Don't care 093 } 094 } 095 096 if (e instanceof FileNotFoundException) { 097 return Trust.undecided; 098 } 099 throw e; 100 } 101 } 102 103 @Override 104 protected void writeTrust(BareJid owner, OpenPgpV4Fingerprint fingerprint, Trust trust) throws IOException { 105 File file = getTrustPath(owner, fingerprint); 106 107 if (trust == null || trust == Trust.undecided) { 108 if (!file.exists()) { 109 return; 110 } 111 if (!file.delete()) { 112 throw new IOException("Could not delete file " + file.getAbsolutePath()); 113 } 114 } 115 116 File parent = file.getParentFile(); 117 if (!parent.exists() && !parent.mkdirs()) { 118 throw new IOException("Cannot create directory " + parent.getAbsolutePath()); 119 } 120 if (!file.exists()) { 121 if (!file.createNewFile()) { 122 throw new IOException("Cannot create file " + file.getAbsolutePath()); 123 } 124 } else { 125 if (file.isDirectory()) { 126 throw new IOException("File " + file.getAbsolutePath() + " is a directory."); 127 } 128 } 129 130 BufferedWriter writer = null; 131 try { 132 OutputStream outputStream = FileUtils.prepareFileOutputStream(file); 133 OutputStreamWriter osw = new OutputStreamWriter(outputStream, Util.UTF8); 134 writer = new BufferedWriter(osw); 135 136 writer.write(trust.toString()); 137 writer.flush(); 138 writer.close(); 139 } catch (IOException e) { 140 if (writer != null) { 141 try { 142 writer.close(); 143 } catch (IOException ignored) { 144 // Don't care 145 } 146 } 147 throw e; 148 } 149 } 150 151 private File getTrustPath(BareJid owner, OpenPgpV4Fingerprint fingerprint) { 152 return new File(FileBasedOpenPgpStore.getContactsPath(basePath, owner), TRUST_RECORD(fingerprint)); 153 } 154}