Change setting so that the private key isn't displayed unless except when you enter it.
diff --git a/src/fniki/wiki/ArchiveManager.java b/src/fniki/wiki/ArchiveManager.java --- a/src/fniki/wiki/ArchiveManager.java +++ b/src/fniki/wiki/ArchiveManager.java @@ -75,14 +75,23 @@ public class ArchiveManager { FreenetIO.setDebugOutput(out); } - public void setPrivateSSK(String value) { + private static void validatePrivateSSK(String value) { if (!value.startsWith("SSK@") || !value.endsWith(",AQECAAE/")) { throw new IllegalArgumentException("That doesn't look like a private SSK. " + "Did you forget the trailing '/'?"); } + } + + public void setPrivateSSK(String value) { + validatePrivateSSK(value); mPrivateSSK = value; } + public String invertPrivateSSK(String value, int timeoutMs) throws IOException { + validatePrivateSSK(value); + return (new FreenetIO(mFcpHost, mFcpPort)).invertPrivateSSK(value, timeoutMs); + } + public String getPrivateSSK() { return mPrivateSSK; } public String getParentUri() { return mParentUri; } diff --git a/src/fniki/wiki/WikiApp.java b/src/fniki/wiki/WikiApp.java --- a/src/fniki/wiki/WikiApp.java +++ b/src/fniki/wiki/WikiApp.java @@ -68,9 +68,13 @@ public class WikiApp implements ChildCon ArchiveManager.FMS_GROUP, ArchiveManager.BISS_NAME); + // Time to wait for FCP before giving up on inverting private key. + private final static int INVERT_TIMEOUT_MS = 30 * 1000; + // Delegate to implement link, image and macro handling in wikitext. private final FreenetWikiTextParser.ParserDelegate mParserDelegate; + // ChildContainers for non-modal UI elements. private final ChildContainer mDefaultRedirect; private final ChildContainer mGotoRedirect; private final ChildContainer mQueryError; @@ -100,7 +104,6 @@ public class WikiApp implements ChildCon private String mFormPassword; private int mListenPort = LISTEN_PORT; - // final because it is called from the ctor. private final void resetContentFilter() { mFilter = ContentFilterFactory.create(mFproxyPrefix, containerPrefix()); @@ -295,7 +298,6 @@ public class WikiApp implements ChildCon sb.append("{ERROR PROCESSING TITLEINDEX MACRO}"); return true; } - return true; } @@ -402,7 +404,7 @@ public class WikiApp implements ChildCon // Can return an invalid configuration. e.g. if fms id and private ssk are not set. public Configuration getConfiguration() { // Converts null values to "" - return new Configuration(getInt("listen_port", LISTEN_PORT), //DCI: clean up magic numbers + return new Configuration(getInt("listen_port", LISTEN_PORT), mArchiveManager.getFcpHost(), mArchiveManager.getFcpPort(), getString("fproxy_prefix", FPROXY_PREFIX), @@ -417,6 +419,29 @@ public class WikiApp implements ChildCon public Configuration getDefaultConfiguration() { return DEFAULT_CONFIG; } + public String getPublicFmsId(String fmsId, String privateSSK) { + if (fmsId == null || privateSSK == null || fmsId.indexOf("@") != -1) { + return "???"; + } + try { + try { + String publicKey = mArchiveManager.invertPrivateSSK(privateSSK, INVERT_TIMEOUT_MS); + int pos = publicKey.indexOf(","); + if (pos == -1 || pos < 5) { + return "???"; + } + return fmsId + publicKey.substring("SSK".length(), pos); + + } catch (IllegalArgumentException iae) { + // Was called with an invalid privateSSK value + return "???"; + } + } catch (IOException ioe) { + logError("getPublicFmsId failed", ioe); + return "???"; + } + } + // For setting data from forms and restoring saved settings. // throws unchecked Configuration.ConfigurationException public void setConfiguration(Configuration config) { diff --git a/src/fniki/wiki/WikiContext.java b/src/fniki/wiki/WikiContext.java --- a/src/fniki/wiki/WikiContext.java +++ b/src/fniki/wiki/WikiContext.java @@ -44,6 +44,14 @@ public interface WikiContext extends Req Configuration getConfiguration(); Configuration getDefaultConfiguration(); + // Returns a public fmsId. + // e.g. djk@isFiaD04zgAgnrEC5XJt1i4IE7AkNPqhBG5bONi6Yks + // + // fmsId is the human readable part, can be null + // private SSK is the private SSK for the FMS identity. + // This can return "???" on failure or if the args are null. + String getPublicFmsId(String fmsId, String privateSSK); + // throws unchecked Configuration.ConfigurationException void setConfiguration(Configuration config); diff --git a/src/fniki/wiki/child/SettingConfig.java b/src/fniki/wiki/child/SettingConfig.java --- a/src/fniki/wiki/child/SettingConfig.java +++ b/src/fniki/wiki/child/SettingConfig.java @@ -44,10 +44,13 @@ public class SettingConfig implements Mo private boolean mFinished = false; private Configuration mConfig; + private String mPrivateSSK = ""; + private String mPublicFmsId = "???"; private String mMsg = ""; // Doesn't validate. - private static Configuration parseConfigFromPost(Query query, int listenPort) { + private Configuration parseConfigFromPost(WikiContext context, Query query, + int listenPort, String oldSSK) { boolean allowImages = false; if (query.containsKey("images")) { allowImages = true; @@ -66,6 +69,13 @@ public class SettingConfig implements Mo // NOP } + String newSSK = query.get("fmsssk"); + if (newSSK == null || newSSK.equals("")) { + newSSK = oldSSK; + } else { + mPublicFmsId = context.getPublicFmsId(query.get("fmsid"), mPrivateSSK); + } + Configuration config = new Configuration(listenPort, query.get("fcphost"), fcpPort, @@ -74,7 +84,7 @@ public class SettingConfig implements Mo query.get("fmshost"), fmsPort, query.get("fmsid"), - query.get("fmsssk"), + newSSK, query.get("fmsgroup"), query.get("wikiname")); return config; @@ -87,7 +97,7 @@ public class SettingConfig implements Mo // Pop a save-as dialog for configuration. try { // Save any changes the user made. - mConfig = parseConfigFromPost(query, context.getInt("listen_port", 8083)); + mConfig = parseConfigFromPost(context, query, context.getInt("listen_port", 8083), mPrivateSSK); mConfig.validate(); // Force browser to save the config file to disk. @@ -113,6 +123,8 @@ public class SettingConfig implements Mo Configuration config = Configuration.fromStringRep(query.get("upload")); config.validate(); mConfig = config; + mPrivateSSK = mConfig.mFmsSsk; + mPublicFmsId = context.getPublicFmsId(mConfig.mFmsId, mConfig.mFmsSsk); mMsg = "Imported configuration!"; return; } catch (Configuration.ConfigurationException cfe) { @@ -138,8 +150,8 @@ public class SettingConfig implements Mo return; } - mConfig = parseConfigFromPost(query, context.getInt("listen_port", 8083)); - + mConfig = parseConfigFromPost(context, query, context.getInt("listen_port", 8083), mPrivateSSK); + try { mConfig.validate(); context.setConfiguration(mConfig); @@ -174,8 +186,8 @@ public class SettingConfig implements Mo mConfig.mFproxyPrefix, mConfig.mFmsHost, mConfig.mFmsPort, - mConfig.mFmsSsk, mConfig.mFmsId, + mPublicFmsId, mConfig.mFmsGroup, mConfig.mWikiName, mConfig.mAllowImages ? "checked" : "", @@ -195,6 +207,8 @@ public class SettingConfig implements Mo public void entered(WikiContext context) { mFinished = false; mConfig = context.getConfiguration(); + mPrivateSSK = mConfig.mFmsSsk; + mPublicFmsId = context.getPublicFmsId(mConfig.mFmsId, mConfig.mFmsSsk); mMsg = ""; } @@ -242,13 +256,17 @@ public class SettingConfig implements Mo sb.append(" </tr>\n"); sb.append(" <tr>\n"); sb.append(" <td>FMS Private SSK</td>\n"); - sb.append(" <td><input type=\"text\" name=\"fmsssk\" size=\"128\" value=\"%s\" /> </td>\n"); + sb.append(" <td><input type=\"text\" name=\"fmsssk\" size=\"128\" value=\"\" /> </td>\n"); sb.append(" </tr>\n"); sb.append(" <tr>\n"); - sb.append(" <td>FMS ID</td>\n"); + sb.append(" <td>FMS name</td>\n"); sb.append(" <td><input type=\"text\" name=\"fmsid\" value=\"%s\" /> </td>\n"); sb.append(" </tr>\n"); sb.append(" <tr>\n"); + sb.append(" <td>Full FMS ID</td>\n"); + sb.append(" <td><input type=\"text\" name=\"fmsfull\" size=\"64\" readonly=\"readonly\" value=\"%s\" /> </td>\n"); + sb.append(" </tr>\n"); + sb.append(" <tr>\n"); sb.append(" <td>FMS Group</td>\n"); sb.append(" <td><input type=\"text\" name=\"fmsgroup\" value=\"%s\" /> </td>\n"); sb.append(" </tr>\n");