diff --git a/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBook.java b/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBook.java index 96bba3435..aa74445d2 100644 --- a/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBook.java +++ b/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBook.java @@ -119,4 +119,8 @@ public class AddressBook { throw new IOException("Corrupt address book - " + dfe.getMessage()); } } + + public String toString() { + return "Entries: " + _entries.size() + " conflicting: " + _conflictingReferences.size(); + } } diff --git a/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookServiceData.java b/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookServiceData.java index 7639d6169..3bfaa8e74 100644 --- a/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookServiceData.java +++ b/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookServiceData.java @@ -8,6 +8,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; +import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -54,6 +55,8 @@ public class AddressBookServiceData { AddressBook addressBook = new AddressBook(_context); addressBook.read(fis); _addressBook = addressBook; + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Address book: " + addressBook); Properties props = DataHelper.readProperties(fis); Map log = new HashMap(props.size()); for (Iterator iter = props.keySet().iterator(); iter.hasNext(); ) { @@ -65,6 +68,8 @@ public class AddressBookServiceData { while (log.containsKey(new Long(when))) when++; log.put(new Long(when), event); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Activity log: on " + new Date(when) + ": " + event); } catch (NumberFormatException nfe) { if (_log.shouldLog(Log.WARN)) _log.warn("Corrupt activity log entry: when=" + key, nfe); diff --git a/apps/myi2p/java/src/net/i2p/myi2p/address/CreateEntryCLI.java b/apps/myi2p/java/src/net/i2p/myi2p/address/CreateEntryCLI.java new file mode 100644 index 000000000..b90de3c57 --- /dev/null +++ b/apps/myi2p/java/src/net/i2p/myi2p/address/CreateEntryCLI.java @@ -0,0 +1,154 @@ +package net.i2p.myi2p.address; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import net.i2p.I2PAppContext; +import net.i2p.data.Destination; +import net.i2p.util.Log; + +/** + * CreateEntryCLI addressBookFile referenceFile localName subscriptionFrequencyHours [ key=value]* + */ +public class CreateEntryCLI { + private I2PAppContext _context; + private String _args[]; + private String _addressBook; + private String _referenceFile; + private String _localName; + private int _subscriptionFrequencyHours; + private Properties _options; + + public CreateEntryCLI(String args[]) { + _context = new I2PAppContext(); + _args = args; + _options = new Properties(); + } + + public void execute() { + if (parseArgs()) + doExecute(); + else + System.err.println("Usage: CreateEntryCLI addressBookFile referenceFile localName subscriptionFrequencyHours[ key=value]*"); + } + + private boolean parseArgs() { + if ( (_args == null) || (_args.length < 3) ) + return false; + _addressBook = _args[0]; + _referenceFile = _args[1]; + _localName = _args[2]; + try { + _subscriptionFrequencyHours = Integer.parseInt(_args[3]); + } catch (NumberFormatException nfe) { + return false; + } + for (int i = 4; i < _args.length; i++) { + int eq = _args[i].indexOf('='); + if ( (eq <= 0) || (eq >= _args[i].length() - 1) ) + continue; + String key = _args[i].substring(0,eq); + String val = _args[i].substring(eq+1); + _options.setProperty(key, val); + } + return true; + } + + private void doExecute() { + AddressBookServiceData data = new AddressBookServiceData(_context); + File f = new File(_addressBook); + if (f.exists()) { + data.load(f); + if (data.getError() != null) { + if (data.getErrorMessage() != null) + System.err.println(data.getErrorMessage()); + data.getError().printStackTrace(); + return; + } + } else { + data.setAddressBook(new AddressBook(_context)); + data.setActivityLog(new HashMap()); + } + NameReference ref = null; + FileInputStream fis = null; + try { + fis = new FileInputStream(_referenceFile); + ref = new NameReference(_context); + ref.read(fis); + } catch (Exception e) { + System.err.println("Name reference under " + _referenceFile + " is corrupt"); + e.printStackTrace(); + return; + } finally { + if (fis != null) try { fis.close(); } catch (IOException ioe) {} + } + + AddressBook book = data.getAddressBook(); + Map activityLog = data.getActivityLog(); + + AddressBookEntry oldEntry = book.getEntry(_localName); + + AddressBookEntry entry = new AddressBookEntry(_context); + entry.setLocalName(_localName); + entry.setNameReference(ref); + + Subscription sub = new Subscription(_context); + sub.setQueryFrequencyMinutes(60*_subscriptionFrequencyHours); + + entry.setSubscription(sub); + entry.setOptions(_options); + + if (oldEntry == null) { + book.addEntry(entry); + System.out.println("New address book entry added for " + entry.getLocalName()); + activityLog.put(new Long(_context.clock().now()), "New address book entry added for " + entry.getLocalName()); + } else { + Destination oldDest = oldEntry.getNameReference().getDestination(); + if (oldDest.equals(ref.getDestination())) { + if (ref.getSequenceNum() < oldEntry.getNameReference().getSequenceNum()) { + System.err.println("Not updating the address book - newer reference for " + entry.getLocalName() + " exists"); + return; + } else { + // same or newer rev + if (null != entry.getSubscription()) { + if (null != oldEntry.getSubscription()) { + entry.getSubscription().setLastQueryAttempt(oldEntry.getSubscription().getLastQueryAttempt()); + entry.getSubscription().setLastQuerySuccess(oldEntry.getSubscription().getLastQuerySuccess()); + } + } + book.addEntry(entry); + System.err.println("Updating the options and subscription for an existing reference to " + entry.getLocalName()); + activityLog.put(new Long(_context.clock().now()), "Updating options and subscription for " + entry.getLocalName()); + } + } else { + book.addConflictingReference(ref); + System.out.println("Old entry exists for " + _localName + " - adding a conflicting reference"); + System.out.println("Existing entry points to " + oldEntry.getNameReference().getDestination().calculateHash().toBase64()); + System.out.println("New entry points to " + entry.getNameReference().getDestination().calculateHash().toBase64()); + + activityLog.put(new Long(_context.clock().now()), "Adding conflicting reference for " + entry.getLocalName()); + } + } + + data.setAddressBook(book); + data.setActivityLog(activityLog); + + data.store(f); + if (data.getError() != null) { + if (data.getErrorMessage() != null) + System.err.println(data.getErrorMessage()); + data.getError().printStackTrace(); + return; + } + } + + public static void main(String args[]) { + CreateEntryCLI cli = new CreateEntryCLI(args); + cli.execute(); + } +} diff --git a/apps/myi2p/java/src/net/i2p/myi2p/address/CreateNameReferenceCLI.java b/apps/myi2p/java/src/net/i2p/myi2p/address/CreateNameReferenceCLI.java new file mode 100644 index 000000000..f57ede936 --- /dev/null +++ b/apps/myi2p/java/src/net/i2p/myi2p/address/CreateNameReferenceCLI.java @@ -0,0 +1,125 @@ +package net.i2p.myi2p.address; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; + +import java.util.Iterator; +import java.util.Properties; + +import net.i2p.I2PAppContext; +import net.i2p.data.Destination; +import net.i2p.data.PrivateKey; +import net.i2p.data.SigningPrivateKey; +import net.i2p.util.Log; + +/** + * CreateNameReferenceCLI outputFile privateDestFile preferredName sequenceNum serviceType[ key=value]* + */ +public class CreateNameReferenceCLI { + private I2PAppContext _context; + private String _args[]; + private String _outputFile; + private String _destFile; + private String _preferredName; + private long _sequenceNum; + private String _serviceType; + private Properties _options; + + public CreateNameReferenceCLI(String[] args) { + _context = new I2PAppContext(); + _args = args; + _options = new Properties(); + } + + public void execute() { + if (parseArgs()) + doExecute(); + else + System.err.println("Usage: CreateNameReferenceCLI outputFile privateDestFile preferredName sequenceNum serviceType[ key=value]*"); + } + + private boolean parseArgs() { + if ( (_args == null) || (_args.length < 4) ) + return false; + _outputFile = _args[0]; + _destFile = _args[1]; + _preferredName = _args[2]; + try { + _sequenceNum = Long.parseLong(_args[3]); + } catch (NumberFormatException nfe) { + return false; + } + _serviceType = _args[4]; + + for (int i = 5; i < _args.length; i++) { + int eq = _args[i].indexOf('='); + if ( (eq <= 0) || (eq >= _args[i].length() - 1) ) + continue; + String key = _args[i].substring(0,eq); + String val = _args[i].substring(eq+1); + _options.setProperty(key, val); + } + return true; + } + + private void doExecute() { + Destination dest = null; + SigningPrivateKey priv = null; + FileInputStream fis = null; + try { + fis = new FileInputStream(_destFile); + dest = new Destination(); + dest.readBytes(fis); + PrivateKey whocares = new PrivateKey(); + whocares.readBytes(fis); + priv = new SigningPrivateKey(); + priv.readBytes(fis); + } catch (Exception e) { + System.err.println("Destination private keys under " + _destFile + " are corrupt"); + e.printStackTrace(); + return; + } finally { + if (fis != null) try { fis.close(); } catch (IOException ioe) {} + } + + NameReference ref = new NameReference(_context); + ref.setDestination(dest); + ref.setPreferredName(_preferredName); + ref.setSequenceNum(_sequenceNum); + ref.setServiceType(_serviceType); + if (_options != null) { + for (Iterator iter = _options.keySet().iterator(); iter.hasNext(); ) { + String key = (String)iter.next(); + String val = _options.getProperty(key); + ref.setOption(key, val); + } + } + + try { + ref.sign(priv); + } catch (IllegalStateException ise) { + System.err.println("Error signing the new reference"); + ise.printStackTrace(); + } + + FileOutputStream fos = null; + try { + fos = new FileOutputStream(_outputFile); + ref.write(fos); + } catch (IOException ioe) { + System.err.println("Error writing out the new reference"); + ioe.printStackTrace(); + } finally { + if (fos != null) try { fos.close(); } catch (IOException ioe) {} + } + + System.out.println("Reference created at " + _outputFile); + } + + public static void main(String args[]) { + CreateNameReferenceCLI cli = new CreateNameReferenceCLI(args); + cli.execute(); + } +}