Addressbook: Add initial support for signatures in subscriptions

More cleanups
SingleFileNamingService: Store signature properties on write
This commit is contained in:
zzz
2016-04-17 20:20:10 +00:00
parent 0ceb9576b9
commit b69677b709
9 changed files with 635 additions and 54 deletions

View File

@ -59,6 +59,10 @@ public class SingleFileNamingService extends NamingService {
private long _lastWrite;
private volatile boolean _isClosed;
private static final String RCVD_PROP_PREFIX = "=";
private static final String PROPS_SEPARATOR = "#!";
private static final char PROP_SEPARATOR = '#';
public SingleFileNamingService(I2PAppContext context, String filename) {
super(context);
File file = new File(filename);
@ -165,7 +169,8 @@ public class SingleFileNamingService extends NamingService {
/**
* @param hostname case-sensitive; caller should convert to lower case
* @param options ignored
* @param options if non-null, any prefixed with '=' will be appended
* in subscription format
*/
@Override
public boolean put(String hostname, Destination d, Properties options) {
@ -196,6 +201,9 @@ public class SingleFileNamingService extends NamingService {
out.write(hostname);
out.write('=');
out.write(d.toBase64());
// subscription options
if (options != null)
writeOptions(options, out);
out.newLine();
out.close();
boolean success = FileUtil.rename(tmp, _file);
@ -215,11 +223,12 @@ public class SingleFileNamingService extends NamingService {
/**
* @param hostname case-sensitive; caller should convert to lower case
* @param options ignored
* @param options if non-null, any prefixed with '=' will be appended
* in subscription format
*/
@Override
public boolean putIfAbsent(String hostname, Destination d, Properties options) {
OutputStream out = null;
BufferedWriter out = null;
if (!getWriteLock())
return false;
try {
@ -236,11 +245,14 @@ public class SingleFileNamingService extends NamingService {
}
// else new file
}
out = new SecureFileOutputStream(_file, true);
out = new BufferedWriter(new OutputStreamWriter(new SecureFileOutputStream(_file, true), "UTF-8"));
// FIXME fails if previous last line didn't have a trailing \n
out.write(hostname.getBytes("UTF-8"));
out.write(hostname);
out.write('=');
out.write(DataHelper.getASCII(d.toBase64()));
out.write(d.toBase64());
// subscription options
if (options != null)
writeOptions(options, out);
out.write('\n');
out.close();
for (NamingServiceListener nsl : _listeners) {
@ -254,6 +266,34 @@ public class SingleFileNamingService extends NamingService {
} finally { releaseWriteLock(); }
}
/**
* Write the subscription options part of the line (after the #!).
* Only options starting with '=' (if any) are written (with the '=' stripped).
* Does not write a newline.
*
* @param options non-null
* @since 0.9.26
*/
private static void writeOptions(Properties options, Writer out) throws IOException {
boolean started = false;
for (Map.Entry<Object, Object> e : options.entrySet()) {
String k = (String) e.getKey();
if (!k.startsWith(RCVD_PROP_PREFIX))
continue;
k = k.substring(1);
String v = (String) e.getValue();
if (started) {
out.write(PROP_SEPARATOR);
} else {
started = true;
out.write(PROPS_SEPARATOR);
}
out.write(k);
out.write('=');
out.write(v);
}
}
/**
* @param hostname case-sensitive; caller should convert to lower case
* @param options ignored