From: David ‘Bombe’ Roden Date: Thu, 20 Sep 2012 15:13:30 +0000 (+0200) Subject: Merge branch 'keys-from-wot' into next X-Git-Tag: 0.11^2~10 X-Git-Url: https://git.pterodactylus.net/?p=jSite.git;a=commitdiff_plain;h=e00f3d069490144830f5eaa3c0d6d755e2517855;hp=e06fc7d961d51a38917737d86804b7608bd7a711 Merge branch 'keys-from-wot' into next This resolves #285. --- diff --git a/.gitignore b/.gitignore index 7dbcc35..71c5144 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ bin build/ dist/ +target/ diff --git a/src/main/java/de/todesbaum/jsite/application/KeyDialog.java b/src/main/java/de/todesbaum/jsite/application/KeyDialog.java deleted file mode 100644 index cd628e7..0000000 --- a/src/main/java/de/todesbaum/jsite/application/KeyDialog.java +++ /dev/null @@ -1,322 +0,0 @@ -/* - * jSite - KeyDialog.java - Copyright © 2010–2012 David Roden - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -package de.todesbaum.jsite.application; - -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.Toolkit; -import java.awt.event.ActionEvent; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.IOException; -import java.text.MessageFormat; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JSeparator; -import javax.swing.JTextField; -import javax.swing.KeyStroke; -import javax.swing.SwingConstants; - -import de.todesbaum.jsite.i18n.I18n; -import de.todesbaum.jsite.i18n.I18nContainer; - -/** - * A dialog that lets the user edit the private and public key for a project. - * - * @author David ‘Bombe’ Roden <bombe@freenetproject.org> - */ -public class KeyDialog extends JDialog { - - /** Interface to the freenet node. */ - private final Freenet7Interface freenetInterface; - - /** The public key. */ - private String publicKey; - - /** The private key. */ - private String privateKey; - - /** The “OK” button’s action. */ - private Action okAction; - - /** The “Cancel” button’s action. */ - private Action cancelAction; - - /** The “Regenerate” button’s action. */ - private Action generateAction; - - /** The text field for the private key. */ - private JTextField privateKeyTextField; - - /** The text field for the public key. */ - private JTextField publicKeyTextField; - - /** Whether the dialog was cancelled. */ - private boolean cancelled; - - /** - * Creates a new key dialog. - * - * @param freenetInterface - * Interface to the freenet node - * @param parent - * The parent frame - */ - public KeyDialog(Freenet7Interface freenetInterface, JFrame parent) { - super(parent, I18n.getMessage("jsite.key-dialog.title"), true); - this.freenetInterface = freenetInterface; - addWindowListener(new WindowAdapter() { - - @Override - @SuppressWarnings("synthetic-access") - public void windowClosing(WindowEvent windowEvent) { - actionCancel(); - } - }); - initDialog(); - } - - // - // ACCESSORS - // - - /** - * Returns whether the dialog was cancelled. - * - * @return {@code true} if the dialog was cancelled, {@code false} otherwise - */ - public boolean wasCancelled() { - return cancelled; - } - - /** - * Returns the public key. - * - * @return The public key - */ - public String getPublicKey() { - return publicKey; - } - - /** - * Sets the public key. - * - * @param publicKey - * The public key - */ - public void setPublicKey(String publicKey) { - this.publicKey = publicKey; - publicKeyTextField.setText(publicKey); - pack(); - } - - /** - * Returns the private key. - * - * @return The private key - */ - public String getPrivateKey() { - return privateKey; - } - - /** - * Sets the private key. - * - * @param privateKey - * The private key - */ - public void setPrivateKey(String privateKey) { - this.privateKey = privateKey; - privateKeyTextField.setText(privateKey); - pack(); - } - - // - // ACTIONS - // - - /** - * {@inheritDoc} - */ - @Override - public void pack() { - super.pack(); - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - setLocation((screenSize.width - getWidth()) / 2, (screenSize.height - getHeight()) / 2); - } - - // - // PRIVATE METHODS - // - - /** - * Creates all necessary actions. - */ - private void createActions() { - okAction = new AbstractAction(I18n.getMessage("jsite.general.ok")) { - - @Override - @SuppressWarnings("synthetic-access") - public void actionPerformed(ActionEvent actionEvent) { - actionOk(); - } - }; - okAction.putValue(Action.SHORT_DESCRIPTION, I18n.getMessage("jsite.key-dialog.button.ok.tooltip")); - okAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_ENTER); - - cancelAction = new AbstractAction(I18n.getMessage("jsite.general.cancel")) { - - @Override - @SuppressWarnings("synthetic-access") - public void actionPerformed(ActionEvent actionEvent) { - actionCancel(); - } - }; - cancelAction.putValue(Action.SHORT_DESCRIPTION, I18n.getMessage("jsite.key-dialog.button.cancel.tooltip")); - cancelAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_ESCAPE); - - generateAction = new AbstractAction(I18n.getMessage("jsite.key-dialog.button.generate")) { - - @Override - @SuppressWarnings("synthetic-access") - public void actionPerformed(ActionEvent actionEvent) { - actionGenerate(); - } - }; - generateAction.putValue(Action.SHORT_DESCRIPTION, I18n.getMessage("jsite.key-dialog.button.generate.tooltip")); - generateAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_DOWN_MASK)); - } - - /** - * Initializes the dialog and all its components. - */ - private void initDialog() { - createActions(); - JPanel dialogPanel = new JPanel(new BorderLayout(12, 12)); - dialogPanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12)); - - JPanel contentPanel = new JPanel(new GridBagLayout()); - dialogPanel.add(contentPanel, BorderLayout.CENTER); - - final JLabel keysLabel = new JLabel(I18n.getMessage("jsite.key-dialog.label.keys")); - contentPanel.add(keysLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); - - final JLabel privateKeyLabel = new JLabel(I18n.getMessage("jsite.key-dialog.label.private-key")); - contentPanel.add(privateKeyLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(12, 18, 0, 0), 0, 0)); - - privateKeyTextField = new JTextField(); - contentPanel.add(privateKeyTextField, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(6, 12, 0, 0), 0, 0)); - - final JLabel publicKeyLabel = new JLabel(I18n.getMessage("jsite.key-dialog.label.public-key")); - contentPanel.add(publicKeyLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(6, 18, 0, 0), 0, 0)); - - publicKeyTextField = new JTextField(); - contentPanel.add(publicKeyTextField, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(6, 12, 0, 0), 0, 0)); - - final JLabel actionsLabel = new JLabel(I18n.getMessage("jsite.key-dialog.label.actions")); - contentPanel.add(actionsLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(12, 0, 0, 0), 0, 0)); - - JPanel actionButtonPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 12, 12)); - actionButtonPanel.setBorder(BorderFactory.createEmptyBorder(-12, -12, -12, -12)); - contentPanel.add(actionButtonPanel, new GridBagConstraints(0, 4, 2, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(12, 18, 0, 0), 0, 0)); - - actionButtonPanel.add(new JButton(generateAction)); - - JPanel separatorPanel = new JPanel(new BorderLayout(12, 12)); - dialogPanel.add(separatorPanel, BorderLayout.PAGE_END); - separatorPanel.add(new JSeparator(SwingConstants.HORIZONTAL), BorderLayout.PAGE_START); - - JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING, 12, 12)); - buttonPanel.setBorder(BorderFactory.createEmptyBorder(-12, -12, -12, -12)); - separatorPanel.add(buttonPanel, BorderLayout.CENTER); - buttonPanel.add(new JButton(okAction)); - buttonPanel.add(new JButton(cancelAction)); - - I18nContainer.getInstance().registerRunnable(new Runnable() { - - @Override - public void run() { - keysLabel.setText(I18n.getMessage("jsite.key-dialog.label.keys")); - privateKeyLabel.setText(I18n.getMessage("jsite.key-dialog.label.private-key")); - publicKeyLabel.setText(I18n.getMessage("jsite.key-dialog.label.public-key")); - actionsLabel.setText(I18n.getMessage("jsite.key-dialog.label.actions")); - } - }); - - getContentPane().add(dialogPanel, BorderLayout.CENTER); - pack(); - setResizable(false); - } - - // - // PRIVATE ACTIONS - // - - /** - * Quits the dialog, accepting all changes. - */ - private void actionOk() { - publicKey = publicKeyTextField.getText(); - privateKey = privateKeyTextField.getText(); - cancelled = false; - setVisible(false); - } - - /** - * Quits the dialog, discarding all changes. - */ - private void actionCancel() { - cancelled = true; - setVisible(false); - } - - /** - * Generates a new key pair. - */ - private void actionGenerate() { - if (JOptionPane.showConfirmDialog(this, I18n.getMessage("jsite.project.warning.generate-new-key"), null, JOptionPane.OK_CANCEL_OPTION) == JOptionPane.CANCEL_OPTION) { - return; - } - String[] keyPair = null; - try { - keyPair = freenetInterface.generateKeyPair(); - } catch (IOException ioe1) { - JOptionPane.showMessageDialog(this, MessageFormat.format(I18n.getMessage("jsite.project.keygen.io-error"), ioe1.getMessage()), null, JOptionPane.ERROR_MESSAGE); - return; - } - publicKeyTextField.setText(keyPair[1].substring(keyPair[1].indexOf('@') + 1, keyPair[1].lastIndexOf('/'))); - privateKeyTextField.setText(keyPair[0].substring(keyPair[0].indexOf('@') + 1, keyPair[0].lastIndexOf('/'))); - pack(); - } - -} diff --git a/src/main/java/de/todesbaum/jsite/application/WebOfTrustInterface.java b/src/main/java/de/todesbaum/jsite/application/WebOfTrustInterface.java new file mode 100644 index 0000000..ea5c6b3 --- /dev/null +++ b/src/main/java/de/todesbaum/jsite/application/WebOfTrustInterface.java @@ -0,0 +1,236 @@ +/* + * jSite - WebOfTrustInterface.java - Copyright © 2012 David Roden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +package de.todesbaum.jsite.application; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; +import java.util.logging.Level; +import java.util.logging.Logger; + +import net.pterodactylus.util.logging.Logging; +import de.todesbaum.util.freenet.fcp2.Client; +import de.todesbaum.util.freenet.fcp2.Connection; +import de.todesbaum.util.freenet.fcp2.FcpPluginMessage; +import de.todesbaum.util.freenet.fcp2.Message; +import de.todesbaum.util.freenet.fcp2.wot.DefaultOwnIdentity; +import de.todesbaum.util.freenet.fcp2.wot.OwnIdentity; + +/** + * FCP interface to the node’s web of trust. + * + * @author David ‘Bombe’ Roden <bombe@freenetproject.org> + */ +public class WebOfTrustInterface implements Runnable { + + /** The logger. */ + private static final Logger logger = Logging.getLogger(WebOfTrustInterface.class); + + /** Unique ID for the command identifier. */ + private static final AtomicLong commandCounter = new AtomicLong(System.nanoTime()); + + /** Object used for synchronization. */ + private final Object syncObject = new Object(); + + /** The freenet interface. */ + private final Freenet7Interface freenetInterface; + + /** Whether the interface should stop. */ + private boolean shouldStop; + + /** The own identities. */ + private final List ownIdentities = new ArrayList(); + + /** + * Creates a new web of trust interface. + * + * @param freenetInterface + * The freenet interface + */ + public WebOfTrustInterface(Freenet7Interface freenetInterface) { + this.freenetInterface = freenetInterface; + } + + // + // ACCESSORS + // + + /** + * Returns a list of own identities. If the identities have not yet been + * retrieved, an empty list is returned. + * + * @return The list of own identities + */ + public List getOwnIdentities() { + synchronized (ownIdentities) { + return new ArrayList(ownIdentities); + } + } + + // + // ACTIONS + // + + /** + * Starts the web of trust interface. + */ + public void start() { + Thread webOfTrustThread = new Thread(this, "WebOfTrust Interface"); + webOfTrustThread.start(); + } + + /** + * Stops the web of trust interface + */ + public void stop() { + synchronized (syncObject) { + shouldStop = true; + syncObject.notifyAll(); + } + } + + // + // PRIVATE METHODS + // + + /** + * Returns whether the web of trust interface should stop. + * + * @return {@code true} if the web of trust interface should stop, + * {@code false} otherwise + */ + private boolean shouldStop() { + synchronized (syncObject) { + return shouldStop; + } + } + + /** + * Returns the essential parts of an URI, consisting of only the + * private/public key, decryption key, and the flags. + * + * @param uri + * The URI to shorten + * @return The shortened URI + */ + private static String shortenUri(String uri) { + String shortenedUri = uri; + if (shortenedUri.charAt(3) == '@') { + shortenedUri = shortenedUri.substring(4); + } + if (shortenedUri.indexOf('/') > -1) { + shortenedUri = shortenedUri.substring(0, shortenedUri.indexOf('/')); + } + return shortenedUri; + } + + // + // RUNNABLE METHODS + // + + /** + * {@inheritDoc} + */ + @Override + public void run() { + boolean waitBeforeReconnect = false; + while (!shouldStop()) { + + /* wait a minute before reconnecting for another try. */ + if (waitBeforeReconnect) { + logger.log(Level.FINE, "Waiting 60 seconds before reconnecting."); + synchronized (syncObject) { + try { + syncObject.wait(60 * 1000); + } catch (InterruptedException ie1) { + /* ignore. */ + } + } + if (shouldStop()) { + continue; + } + } else { + waitBeforeReconnect = true; + } + + try { + + /* connect. */ + Connection connection = freenetInterface.getConnection("jSite-WoT-Connector"); + logger.log(Level.INFO, String.format("Trying to connect to node at %s...", freenetInterface.getNode())); + if (!connection.connect()) { + logger.log(Level.WARNING, "Connection failed."); + continue; + } + Client client = new Client(connection); + + /* send FCP command to WebOfTrust plugin. */ + String messageIdentifier = "jSite-WoT-Command-" + commandCounter.getAndIncrement(); + FcpPluginMessage pluginMessage = new FcpPluginMessage(messageIdentifier); + pluginMessage.setPluginName("plugins.WebOfTrust.WebOfTrust"); + pluginMessage.setParameter("Message", "GetOwnIdentities"); + client.execute(pluginMessage); + + /* read a message. */ + Message message = null; + while (!client.isDisconnected() && !shouldStop() && (message == null)) { + message = client.readMessage(1000); + } + if (message == null) { + continue; + } + + /* evaluate message. */ + if (message.getName().equals("FCPPluginReply")) { + logger.log(Level.FINE, "Got matching Reply from WebOfTrust."); + /* parse identities. */ + List ownIdentities = new ArrayList(); + int identityCounter = -1; + while (message.get("Replies.Identity" + ++identityCounter) != null) { + String id = message.get("Replies.Identity" + identityCounter); + String nickname = message.get("Replies.Nickname" + identityCounter); + String requestUri = shortenUri(message.get("Replies.RequestURI" + identityCounter)); + String insertUri = shortenUri(message.get("Replies.InsertURI" + identityCounter)); + DefaultOwnIdentity ownIdentity = new DefaultOwnIdentity(id, nickname, requestUri, insertUri); + logger.log(Level.FINE, String.format("Parsed Own Identity %s.", ownIdentity)); + ownIdentities.add(ownIdentity); + } + logger.log(Level.INFO, String.format("Parsed %d Own Identities.", ownIdentities.size())); + + synchronized (this.ownIdentities) { + this.ownIdentities.clear(); + this.ownIdentities.addAll(ownIdentities); + } + } else if ("ProtocolError".equals(message.getName())) { + logger.log(Level.WARNING, "WebOfTrust Plugin not found!"); + } + + /* disconnect. */ + logger.log(Level.INFO, "Disconnecting from Node."); + connection.disconnect(); + + } catch (IOException ioe1) { + logger.log(Level.WARNING, String.format("Communication with node at %s failed.", freenetInterface.getNode()), ioe1); + } + + } + } + +} diff --git a/src/main/java/de/todesbaum/jsite/gui/KeyDialog.java b/src/main/java/de/todesbaum/jsite/gui/KeyDialog.java new file mode 100644 index 0000000..732bb6e --- /dev/null +++ b/src/main/java/de/todesbaum/jsite/gui/KeyDialog.java @@ -0,0 +1,432 @@ +/* + * jSite - KeyDialog.java - Copyright © 2010–2012 David Roden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +package de.todesbaum.jsite.gui; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.IOException; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.DefaultListCellRenderer; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JSeparator; +import javax.swing.JTextField; +import javax.swing.KeyStroke; +import javax.swing.SwingConstants; + +import net.pterodactylus.util.swing.ComboBoxModelList; +import de.todesbaum.jsite.application.Freenet7Interface; +import de.todesbaum.jsite.i18n.I18n; +import de.todesbaum.jsite.i18n.I18nContainer; +import de.todesbaum.util.freenet.fcp2.wot.OwnIdentity; + +/** + * A dialog that lets the user edit the private and public key for a project. + * + * @author David ‘Bombe’ Roden <bombe@freenetproject.org> + */ +public class KeyDialog extends JDialog { + + /** Interface to the freenet node. */ + private final Freenet7Interface freenetInterface; + + /** The public key. */ + private String publicKey; + + /** The private key. */ + private String privateKey; + + /** The “OK” button’s action. */ + private Action okAction; + + /** The “Cancel” button’s action. */ + private Action cancelAction; + + /** The “Regenerate” button’s action. */ + private Action generateAction; + + /** The “Copy from Identity” action. */ + private Action copyFromIdentityAction; + + /** The text field for the private key. */ + private JTextField privateKeyTextField; + + /** The text field for the public key. */ + private JTextField publicKeyTextField; + + /** The select box for the own identities. */ + private JComboBox ownIdentitiesComboBox; + + /** Whether the dialog was cancelled. */ + private boolean cancelled; + + /** The list of own identities. */ + private final List ownIdentities = new ArrayList(); + + /** + * Creates a new key dialog. + * + * @param freenetInterface + * Interface to the freenet node + * @param parent + * The parent frame + */ + public KeyDialog(Freenet7Interface freenetInterface, JFrame parent) { + super(parent, I18n.getMessage("jsite.key-dialog.title"), true); + this.freenetInterface = freenetInterface; + addWindowListener(new WindowAdapter() { + + @Override + @SuppressWarnings("synthetic-access") + public void windowClosing(WindowEvent windowEvent) { + actionCancel(); + } + }); + initDialog(); + } + + // + // ACCESSORS + // + + /** + * Returns whether the dialog was cancelled. + * + * @return {@code true} if the dialog was cancelled, {@code false} otherwise + */ + public boolean wasCancelled() { + return cancelled; + } + + /** + * Returns the public key. + * + * @return The public key + */ + public String getPublicKey() { + return publicKey; + } + + /** + * Sets the public key. + * + * @param publicKey + * The public key + */ + public void setPublicKey(String publicKey) { + this.publicKey = publicKey; + publicKeyTextField.setText(publicKey); + pack(); + } + + /** + * Returns the private key. + * + * @return The private key + */ + public String getPrivateKey() { + return privateKey; + } + + /** + * Sets the private key. + * + * @param privateKey + * The private key + */ + public void setPrivateKey(String privateKey) { + this.privateKey = privateKey; + privateKeyTextField.setText(privateKey); + pack(); + } + + /** + * Sets the own identities to display and copy URIs from. + * + * @param ownIdentities + * The list of own identities + */ + public void setOwnIdentities(Collection ownIdentities) { + synchronized (this.ownIdentities) { + this.ownIdentities.clear(); + this.ownIdentities.addAll(ownIdentities); + Collections.sort(this.ownIdentities, new Comparator() { + + @Override + public int compare(OwnIdentity leftOwnIdentity, OwnIdentity rightOwnIdentity) { + return leftOwnIdentity.getNickname().compareToIgnoreCase(rightOwnIdentity.getNickname()); + } + }); + } + int selectedIndex = -1; + int index = 0; + for (OwnIdentity ownIdentity : this.ownIdentities) { + if (ownIdentity.getInsertUri().equals(privateKey) && ownIdentity.getRequestUri().equals(publicKey)) { + selectedIndex = index; + } + index++; + } + ownIdentitiesComboBox.setSelectedIndex(selectedIndex); + } + + // + // ACTIONS + // + + /** + * {@inheritDoc} + */ + @Override + public void pack() { + super.pack(); + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + setLocation((screenSize.width - getWidth()) / 2, (screenSize.height - getHeight()) / 2); + } + + // + // PRIVATE METHODS + // + + /** + * Creates all necessary actions. + */ + private void createActions() { + okAction = new AbstractAction(I18n.getMessage("jsite.general.ok")) { + + @Override + @SuppressWarnings("synthetic-access") + public void actionPerformed(ActionEvent actionEvent) { + actionOk(); + } + }; + okAction.putValue(Action.SHORT_DESCRIPTION, I18n.getMessage("jsite.key-dialog.button.ok.tooltip")); + okAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_ENTER); + + cancelAction = new AbstractAction(I18n.getMessage("jsite.general.cancel")) { + + @Override + @SuppressWarnings("synthetic-access") + public void actionPerformed(ActionEvent actionEvent) { + actionCancel(); + } + }; + cancelAction.putValue(Action.SHORT_DESCRIPTION, I18n.getMessage("jsite.key-dialog.button.cancel.tooltip")); + cancelAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_ESCAPE); + + copyFromIdentityAction = new AbstractAction(I18n.getMessage("jsite.key-dialog.button.copy-from-identity")) { + + @Override + @SuppressWarnings("synthetic-access") + public void actionPerformed(ActionEvent actionevent) { + actionCopyFromIdentity(); + } + }; + copyFromIdentityAction.putValue(Action.SHORT_DESCRIPTION, I18n.getMessage("jsite.key-dialog.button.copy-from-identity.tooltip")); + copyFromIdentityAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK)); + + generateAction = new AbstractAction(I18n.getMessage("jsite.key-dialog.button.generate")) { + + @Override + @SuppressWarnings("synthetic-access") + public void actionPerformed(ActionEvent actionEvent) { + actionGenerate(); + } + }; + generateAction.putValue(Action.SHORT_DESCRIPTION, I18n.getMessage("jsite.key-dialog.button.generate.tooltip")); + generateAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_DOWN_MASK)); + } + + /** + * Initializes the dialog and all its components. + */ + private void initDialog() { + createActions(); + JPanel dialogPanel = new JPanel(new BorderLayout(12, 12)); + dialogPanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12)); + + JPanel contentPanel = new JPanel(new GridBagLayout()); + dialogPanel.add(contentPanel, BorderLayout.CENTER); + + final JLabel keysLabel = new JLabel(I18n.getMessage("jsite.key-dialog.label.keys")); + contentPanel.add(keysLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); + + final JLabel privateKeyLabel = new JLabel(I18n.getMessage("jsite.key-dialog.label.private-key")); + contentPanel.add(privateKeyLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(12, 18, 0, 0), 0, 0)); + + privateKeyTextField = new JTextField(); + contentPanel.add(privateKeyTextField, new GridBagConstraints(1, 1, 2, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(6, 12, 0, 0), 0, 0)); + + final JLabel publicKeyLabel = new JLabel(I18n.getMessage("jsite.key-dialog.label.public-key")); + contentPanel.add(publicKeyLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(6, 18, 0, 0), 0, 0)); + + publicKeyTextField = new JTextField(); + contentPanel.add(publicKeyTextField, new GridBagConstraints(1, 2, 2, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(6, 12, 0, 0), 0, 0)); + + final JLabel identitiesLabel = new JLabel(I18n.getMessage("jsite.key-dialog.label.identities")); + contentPanel.add(identitiesLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(12, 0, 0, 0), 0, 0)); + + final JLabel identityLabel = new JLabel(I18n.getMessage("jsite.key-dialog.label.identity")); + contentPanel.add(identityLabel, new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(12, 18, 0, 0), 0, 0)); + + ownIdentitiesComboBox = new JComboBox(new ComboBoxModelList(ownIdentities)); + ownIdentitiesComboBox.addActionListener(new ActionListener() { + + @Override + @SuppressWarnings("synthetic-access") + public void actionPerformed(ActionEvent actionevent) { + copyFromIdentityAction.setEnabled(ownIdentitiesComboBox.getSelectedIndex() > -1); + } + }); + ownIdentitiesComboBox.setRenderer(new DefaultListCellRenderer() { + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (value == null) { + setText(""); + } else { + OwnIdentity ownIdentity = (OwnIdentity) value; + setText(String.format("%s (%s)", ownIdentity.getNickname(), ownIdentity.getRequestUri().substring(0, ownIdentity.getRequestUri().indexOf(',')))); + } + return this; + } + }); + contentPanel.add(ownIdentitiesComboBox, new GridBagConstraints(1, 4, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(6, 12, 0, 0), 0, 0)); + + JButton copyFromIdentityButton = new JButton(copyFromIdentityAction); + contentPanel.add(copyFromIdentityButton, new GridBagConstraints(2, 4, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_END, GridBagConstraints.NONE, new Insets(6, 12, 0, 0), 0, 0)); + + final JLabel actionsLabel = new JLabel(I18n.getMessage("jsite.key-dialog.label.actions")); + contentPanel.add(actionsLabel, new GridBagConstraints(0, 5, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(12, 0, 0, 0), 0, 0)); + + JPanel actionButtonPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 12, 12)); + actionButtonPanel.setBorder(BorderFactory.createEmptyBorder(-12, -12, -12, -12)); + contentPanel.add(actionButtonPanel, new GridBagConstraints(0, 6, 3, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(12, 18, 0, 0), 0, 0)); + + actionButtonPanel.add(new JButton(generateAction)); + + JPanel separatorPanel = new JPanel(new BorderLayout(12, 12)); + dialogPanel.add(separatorPanel, BorderLayout.PAGE_END); + separatorPanel.add(new JSeparator(SwingConstants.HORIZONTAL), BorderLayout.PAGE_START); + + JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING, 12, 12)); + buttonPanel.setBorder(BorderFactory.createEmptyBorder(-12, -12, -12, -12)); + separatorPanel.add(buttonPanel, BorderLayout.CENTER); + buttonPanel.add(new JButton(okAction)); + buttonPanel.add(new JButton(cancelAction)); + + I18nContainer.getInstance().registerRunnable(new Runnable() { + + @Override + public void run() { + keysLabel.setText(I18n.getMessage("jsite.key-dialog.label.keys")); + privateKeyLabel.setText(I18n.getMessage("jsite.key-dialog.label.private-key")); + publicKeyLabel.setText(I18n.getMessage("jsite.key-dialog.label.public-key")); + identitiesLabel.setText(I18n.getMessage("jsite.key-dialog.label.identities")); + identityLabel.setText(I18n.getMessage("jsite.key-dialog.label.identity")); + actionsLabel.setText(I18n.getMessage("jsite.key-dialog.label.actions")); + } + }); + + getContentPane().add(dialogPanel, BorderLayout.CENTER); + pack(); + setResizable(false); + } + + // + // PRIVATE ACTIONS + // + + /** + * Quits the dialog, accepting all changes. + */ + private void actionOk() { + publicKey = publicKeyTextField.getText(); + privateKey = privateKeyTextField.getText(); + cancelled = false; + setVisible(false); + } + + /** + * Quits the dialog, discarding all changes. + */ + private void actionCancel() { + cancelled = true; + setVisible(false); + } + + /** + * Copies the public and private key from the selected identity. + */ + private void actionCopyFromIdentity() { + OwnIdentity ownIdentity = (OwnIdentity) ownIdentitiesComboBox.getSelectedItem(); + if (ownIdentity == null) { + return; + } + setPublicKey(ownIdentity.getRequestUri()); + setPrivateKey(ownIdentity.getInsertUri()); + } + + /** + * Generates a new key pair. + */ + private void actionGenerate() { + if (JOptionPane.showConfirmDialog(this, I18n.getMessage("jsite.project.warning.generate-new-key"), null, JOptionPane.OK_CANCEL_OPTION) == JOptionPane.CANCEL_OPTION) { + return; + } + String[] keyPair = null; + try { + keyPair = freenetInterface.generateKeyPair(); + } catch (IOException ioe1) { + JOptionPane.showMessageDialog(this, MessageFormat.format(I18n.getMessage("jsite.project.keygen.io-error"), ioe1.getMessage()), null, JOptionPane.ERROR_MESSAGE); + return; + } + publicKeyTextField.setText(keyPair[1].substring(keyPair[1].indexOf('@') + 1, keyPair[1].lastIndexOf('/'))); + privateKeyTextField.setText(keyPair[0].substring(keyPair[0].indexOf('@') + 1, keyPair[0].lastIndexOf('/'))); + pack(); + } + +} diff --git a/src/main/java/de/todesbaum/jsite/gui/ProjectPage.java b/src/main/java/de/todesbaum/jsite/gui/ProjectPage.java index a072423..2fc5716 100644 --- a/src/main/java/de/todesbaum/jsite/gui/ProjectPage.java +++ b/src/main/java/de/todesbaum/jsite/gui/ProjectPage.java @@ -59,8 +59,8 @@ import javax.swing.text.DocumentFilter; import net.pterodactylus.util.swing.SortedListModel; import de.todesbaum.jsite.application.Freenet7Interface; -import de.todesbaum.jsite.application.KeyDialog; import de.todesbaum.jsite.application.Project; +import de.todesbaum.jsite.application.WebOfTrustInterface; import de.todesbaum.jsite.i18n.I18n; import de.todesbaum.jsite.i18n.I18nContainer; import de.todesbaum.util.swing.TLabel; @@ -77,6 +77,9 @@ public class ProjectPage extends TWizardPage implements ListSelectionListener, D /** The freenet interface. */ private Freenet7Interface freenetInterface; + /** The web of trust interface. */ + private WebOfTrustInterface webOfTrustInterface; + /** The “browse” action. */ private Action projectLocalPathBrowseAction; @@ -464,6 +467,16 @@ public class ProjectPage extends TWizardPage implements ListSelectionListener, D } /** + * Sets the web of trust interface to use. + * + * @param webOfTrustInterface + * The web of trust interface to use + */ + public void setWebOfTrustInterface(WebOfTrustInterface webOfTrustInterface) { + this.webOfTrustInterface = webOfTrustInterface; + } + + /** * Returns the currently selected project. * * @return The currently selected project @@ -616,6 +629,7 @@ public class ProjectPage extends TWizardPage implements ListSelectionListener, D KeyDialog keyDialog = new KeyDialog(freenetInterface, wizard); keyDialog.setPrivateKey(selectedProject.getInsertURI()); keyDialog.setPublicKey(selectedProject.getRequestURI()); + keyDialog.setOwnIdentities(webOfTrustInterface.getOwnIdentities()); keyDialog.setVisible(true); if (!keyDialog.wasCancelled()) { String originalPublicKey = selectedProject.getRequestURI(); diff --git a/src/main/java/de/todesbaum/jsite/main/Main.java b/src/main/java/de/todesbaum/jsite/main/Main.java index 6621931..f91cfd6 100644 --- a/src/main/java/de/todesbaum/jsite/main/Main.java +++ b/src/main/java/de/todesbaum/jsite/main/Main.java @@ -55,6 +55,7 @@ import de.todesbaum.jsite.application.ProjectInserter.CheckReport; import de.todesbaum.jsite.application.ProjectInserter.Issue; import de.todesbaum.jsite.application.UpdateChecker; import de.todesbaum.jsite.application.UpdateListener; +import de.todesbaum.jsite.application.WebOfTrustInterface; import de.todesbaum.jsite.gui.NodeManagerListener; import de.todesbaum.jsite.gui.NodeManagerPage; import de.todesbaum.jsite.gui.PreferencesPage; @@ -90,6 +91,9 @@ public class Main implements ActionListener, ListSelectionListener, WizardListen /** The update checker. */ private final UpdateChecker updateChecker; + /** The web of trust interface. */ + private final WebOfTrustInterface webOfTrustInterface; + /** The jSite icon. */ private Icon jSiteIcon; @@ -190,6 +194,9 @@ public class Main implements ActionListener, ListSelectionListener, WizardListen updateChecker.addUpdateListener(this); updateChecker.start(); + webOfTrustInterface = new WebOfTrustInterface(freenetInterface); + webOfTrustInterface.start(); + initPages(); showPage(PageType.PAGE_PROJECTS); } @@ -334,6 +341,7 @@ public class Main implements ActionListener, ListSelectionListener, WizardListen projectPage.setName("page.project"); projectPage.setProjects(configuration.getProjects()); projectPage.setFreenetInterface(freenetInterface); + projectPage.setWebOfTrustInterface(webOfTrustInterface); projectPage.addListSelectionListener(this); pages.put(PageType.PAGE_PROJECTS, projectPage); @@ -493,6 +501,15 @@ public class Main implements ActionListener, ListSelectionListener, WizardListen } } + /** + * Quits jSite, stopping all background services. + */ + private void quit() { + updateChecker.stop(); + webOfTrustInterface.stop(); + System.exit(0); + } + // // INTERFACE ListSelectionListener // @@ -620,21 +637,21 @@ public class Main implements ActionListener, ListSelectionListener, WizardListen int overwriteConfigurationAnswer = JOptionPane.showConfirmDialog(wizard, MessageFormat.format(I18n.getMessage("jsite.quit.overwrite-configuration"), configuration.getConfigurationLocator().getFile(configuration.getConfigurationDirectory())), I18n.getMessage("jsite.quit.overwrite-configuration.title"), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE); if (overwriteConfigurationAnswer == JOptionPane.YES_OPTION) { if (saveConfiguration()) { - System.exit(0); + quit(); } } else if (overwriteConfigurationAnswer == JOptionPane.CANCEL_OPTION) { return; } if (overwriteConfigurationAnswer == JOptionPane.NO_OPTION) { - System.exit(0); + quit(); } } else { if (saveConfiguration()) { - System.exit(0); + quit(); } } if (JOptionPane.showConfirmDialog(wizard, I18n.getMessage("jsite.quit.config-not-saved"), null, JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.OK_OPTION) { - System.exit(0); + quit(); } } } diff --git a/src/main/java/de/todesbaum/util/freenet/fcp2/FcpPluginMessage.java b/src/main/java/de/todesbaum/util/freenet/fcp2/FcpPluginMessage.java new file mode 100644 index 0000000..11bbf1d --- /dev/null +++ b/src/main/java/de/todesbaum/util/freenet/fcp2/FcpPluginMessage.java @@ -0,0 +1,99 @@ +/* + * jSite - FcpPluginMessage.java - Copyright © 2012 David Roden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +package de.todesbaum.util.freenet.fcp2; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Writer; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +/** + * Implementation of the FCPPluginMessage command. + *

+ * TODO: Implement passing of data as an {@link InputStream}. + * + * @author David ‘Bombe’ Roden <bombe@freenetproject.org> + */ +public class FcpPluginMessage extends Command { + + /** The name of the plugin to talk to. */ + private String pluginName; + + /** The parameters to send to the plugin. */ + private final Map parameters = new HashMap(); + + /** + * Creates a new FCPPluginMessage command. + * + * @param identifier + * The identifier of the command + */ + public FcpPluginMessage(String identifier) { + super("FCPPluginMessage", identifier); + } + + // + // ACCESSORS + // + + /** + * Sets the name of the plugin to talk to. + * + * @param pluginName + * The name of the plugin to talk to + * @return This command + */ + public FcpPluginMessage setPluginName(String pluginName) { + this.pluginName = pluginName; + return this; + } + + /** + * Sets a parameter to send to the plugin. + * + * @param name + * The name of the parameter + * @param value + * The value of the parameter + * @return This command + */ + public FcpPluginMessage setParameter(String name, String value) { + parameters.put(name, value); + return this; + } + + // + // COMMAND METHODS + // + + /** + * {@inheritDoc} + */ + @Override + protected void write(Writer writer) throws IOException { + super.write(writer); + writer.write("PluginName=" + pluginName + LINEFEED); + for (Entry parameter : parameters.entrySet()) { + writer.write(String.format("Param.%s=%s%s", parameter.getKey(), parameter.getValue(), LINEFEED)); + } + } + +} diff --git a/src/main/java/de/todesbaum/util/freenet/fcp2/Node.java b/src/main/java/de/todesbaum/util/freenet/fcp2/Node.java index 71c2a6e..4347d30 100644 --- a/src/main/java/de/todesbaum/util/freenet/fcp2/Node.java +++ b/src/main/java/de/todesbaum/util/freenet/fcp2/Node.java @@ -87,7 +87,7 @@ public class Node { */ @Override public String toString() { - return String.format("%s[hostname=%s,port=%d]", getClass().getName(), getHostname(), getPort()); + return String.format("%s:%d", getHostname(), getPort()); } } diff --git a/src/main/java/de/todesbaum/util/freenet/fcp2/wot/DefaultIdentity.java b/src/main/java/de/todesbaum/util/freenet/fcp2/wot/DefaultIdentity.java new file mode 100644 index 0000000..a9b4cb3 --- /dev/null +++ b/src/main/java/de/todesbaum/util/freenet/fcp2/wot/DefaultIdentity.java @@ -0,0 +1,234 @@ +/* + * Sone - DefaultIdentity.java - Copyright © 2010–2012 David Roden + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.todesbaum.util.freenet.fcp2.wot; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * A Web of Trust identity. + * + * @author David ‘Bombe’ Roden + */ +public class DefaultIdentity implements Identity { + + /** The ID of the identity. */ + private final String id; + + /** The nickname of the identity. */ + private final String nickname; + + /** The request URI of the identity. */ + private final String requestUri; + + /** The contexts of the identity. */ + private final Set contexts = Collections.synchronizedSet(new HashSet()); + + /** The properties of the identity. */ + private final Map properties = Collections.synchronizedMap(new HashMap()); + + /** Cached trust. */ + private final Map trustCache = Collections.synchronizedMap(new HashMap()); + + /** + * Creates a new identity. + * + * @param id + * The ID of the identity + * @param nickname + * The nickname of the identity + * @param requestUri + * The request URI of the identity + */ + public DefaultIdentity(String id, String nickname, String requestUri) { + this.id = id; + this.nickname = nickname; + this.requestUri = requestUri; + } + + // + // ACCESSORS + // + + /** + * {@inheritDoc} + */ + @Override + public String getId() { + return id; + } + + /** + * {@inheritDoc} + */ + @Override + public String getNickname() { + return nickname; + } + + /** + * {@inheritDoc} + */ + @Override + public String getRequestUri() { + return requestUri; + } + + /** + * {@inheritDoc} + */ + @Override + public Set getContexts() { + return Collections.unmodifiableSet(contexts); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean hasContext(String context) { + return contexts.contains(context); + } + + /** + * {@inheritDoc} + */ + @Override + public void setContexts(Collection contexts) { + this.contexts.clear(); + this.contexts.addAll(contexts); + } + + /** + * {@inheritDoc} + */ + @Override + public void addContext(String context) { + contexts.add(context); + } + + /** + * {@inheritDoc} + */ + @Override + public void removeContext(String context) { + contexts.remove(context); + } + + /** + * {@inheritDoc} + */ + @Override + public Map getProperties() { + return Collections.unmodifiableMap(properties); + } + + /** + * {@inheritDoc} + */ + @Override + public void setProperties(Map properties) { + this.properties.clear(); + this.properties.putAll(properties); + } + + /** + * {@inheritDoc} + */ + @Override + public String getProperty(String name) { + return properties.get(name); + } + + /** + * {@inheritDoc} + */ + @Override + public void setProperty(String name, String value) { + properties.put(name, value); + } + + /** + * {@inheritDoc} + */ + @Override + public void removeProperty(String name) { + properties.remove(name); + } + + /** + * {@inheritDoc} + */ + @Override + public Trust getTrust(OwnIdentity ownIdentity) { + return trustCache.get(ownIdentity); + } + + /** + * {@inheritDoc} + */ + @Override + public void setTrust(OwnIdentity ownIdentity, Trust trust) { + trustCache.put(ownIdentity, trust); + } + + /** + * {@inheritDoc} + */ + @Override + public void removeTrust(OwnIdentity ownIdentity) { + trustCache.remove(ownIdentity); + } + + // + // OBJECT METHODS + // + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + return id.hashCode(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object object) { + if (!(object instanceof DefaultIdentity)) { + return false; + } + DefaultIdentity identity = (DefaultIdentity) object; + return identity.id.equals(id); + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return getClass().getSimpleName() + "[id=" + id + ",nickname=" + nickname + ",contexts=" + contexts + ",properties=" + properties + "]"; + } + +} diff --git a/src/main/java/de/todesbaum/util/freenet/fcp2/wot/DefaultOwnIdentity.java b/src/main/java/de/todesbaum/util/freenet/fcp2/wot/DefaultOwnIdentity.java new file mode 100644 index 0000000..058116e --- /dev/null +++ b/src/main/java/de/todesbaum/util/freenet/fcp2/wot/DefaultOwnIdentity.java @@ -0,0 +1,73 @@ +/* + * Sone - DefaultOwnIdentity.java - Copyright © 2010–2012 David Roden + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.todesbaum.util.freenet.fcp2.wot; + +/** + * An own identity is an identity that the owner of the node has full control + * over. + * + * @author David ‘Bombe’ Roden + */ +public class DefaultOwnIdentity extends DefaultIdentity implements OwnIdentity { + + /** The insert URI of the identity. */ + private final String insertUri; + + /** + * Creates a new own identity. + * + * @param id + * The ID of the identity + * @param nickname + * The nickname of the identity + * @param requestUri + * The request URI of the identity + * @param insertUri + * The insert URI of the identity + */ + public DefaultOwnIdentity(String id, String nickname, String requestUri, String insertUri) { + super(id, nickname, requestUri); + this.insertUri = insertUri; + } + + /** + * Copy constructor for an own identity. + * + * @param ownIdentity + * The own identity to copy + */ + public DefaultOwnIdentity(OwnIdentity ownIdentity) { + super(ownIdentity.getId(), ownIdentity.getNickname(), ownIdentity.getRequestUri()); + this.insertUri = ownIdentity.getInsertUri(); + setContexts(ownIdentity.getContexts()); + setProperties(ownIdentity.getProperties()); + } + + // + // ACCESSORS + // + + /** + * {@inheritDoc} + */ + @Override + public String getInsertUri() { + return insertUri; + } + +} diff --git a/src/main/java/de/todesbaum/util/freenet/fcp2/wot/Identity.java b/src/main/java/de/todesbaum/util/freenet/fcp2/wot/Identity.java new file mode 100644 index 0000000..19a3cdb --- /dev/null +++ b/src/main/java/de/todesbaum/util/freenet/fcp2/wot/Identity.java @@ -0,0 +1,169 @@ +/* + * Sone - Identity.java - Copyright © 2010–2012 David Roden + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.todesbaum.util.freenet.fcp2.wot; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +/** + * Interface for web of trust identities, defining all functions that can be + * performed on an identity. An identity is only a container for identity data + * and will not perform any updating in the WebOfTrust plugin itself. + * + * @author David ‘Bombe’ Roden + */ +public interface Identity { + + /** + * Returns the ID of the identity. + * + * @return The ID of the identity + */ + public String getId(); + + /** + * Returns the nickname of the identity. + * + * @return The nickname of the identity + */ + public String getNickname(); + + /** + * Returns the request URI of the identity. + * + * @return The request URI of the identity + */ + public String getRequestUri(); + + /** + * Returns all contexts of this identity. + * + * @return All contexts of this identity + */ + public Set getContexts(); + + /** + * Returns whether this identity has the given context. + * + * @param context + * The context to check for + * @return {@code true} if this identity has the given context, + * {@code false} otherwise + */ + public boolean hasContext(String context); + + /** + * Adds the given context to this identity. + * + * @param context + * The context to add + */ + public void addContext(String context); + + /** + * Sets all contexts of this identity. + * + * @param contexts + * All contexts of the identity + */ + public void setContexts(Collection contexts); + + /** + * Removes the given context from this identity. + * + * @param context + * The context to remove + */ + public void removeContext(String context); + + /** + * Returns all properties of this identity. + * + * @return All properties of this identity + */ + public Map getProperties(); + + /** + * Returns the value of the property with the given name. + * + * @param name + * The name of the property + * @return The value of the property + */ + public String getProperty(String name); + + /** + * Sets the property with the given name to the given value. + * + * @param name + * The name of the property + * @param value + * The value of the property + */ + public void setProperty(String name, String value); + + /** + * Sets all properties of this identity. + * + * @param properties + * The new properties of this identity + */ + public void setProperties(Map properties); + + /** + * Removes the property with the given name. + * + * @param name + * The name of the property to remove + */ + public void removeProperty(String name); + + /** + * Retrieves the trust that this identity receives from the given own + * identity. If this identity is not in the own identity’s trust tree, a + * {@link Trust} is returned that has all its elements set to {@code null}. + * If the trust can not be retrieved, {@code null} is returned. + * + * @param ownIdentity + * The own identity to get the trust for + * @return The trust assigned to this identity, or {@code null} if the trust + * could not be retrieved + */ + public Trust getTrust(OwnIdentity ownIdentity); + + /** + * Sets the trust given by an own identity to this identity. + * + * @param ownIdentity + * The own identity that gave trust to this identity + * @param trust + * The trust given by the given own identity + */ + public void setTrust(OwnIdentity ownIdentity, Trust trust); + + /** + * Removes trust assignment from the given own identity for this identity. + * + * @param ownIdentity + * The own identity that removed the trust assignment for this + * identity + */ + public void removeTrust(OwnIdentity ownIdentity); + +} diff --git a/src/main/java/de/todesbaum/util/freenet/fcp2/wot/OwnIdentity.java b/src/main/java/de/todesbaum/util/freenet/fcp2/wot/OwnIdentity.java new file mode 100644 index 0000000..74256af --- /dev/null +++ b/src/main/java/de/todesbaum/util/freenet/fcp2/wot/OwnIdentity.java @@ -0,0 +1,35 @@ +/* + * Sone - OwnIdentity.java - Copyright © 2010–2012 David Roden + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.todesbaum.util.freenet.fcp2.wot; + + +/** + * Defines a local identity, an own identity. + * + * @author David ‘Bombe’ Roden + */ +public interface OwnIdentity extends Identity { + + /** + * Returns the insert URI of the identity. + * + * @return The insert URI of the identity + */ + public String getInsertUri(); + +} diff --git a/src/main/java/de/todesbaum/util/freenet/fcp2/wot/Trust.java b/src/main/java/de/todesbaum/util/freenet/fcp2/wot/Trust.java new file mode 100644 index 0000000..4297ac3 --- /dev/null +++ b/src/main/java/de/todesbaum/util/freenet/fcp2/wot/Trust.java @@ -0,0 +1,90 @@ +/* + * Sone - Trust.java - Copyright © 2010–2012 David Roden + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.todesbaum.util.freenet.fcp2.wot; + +/** + * Container class for trust in the web of trust. + * + * @author David ‘Bombe’ Roden + */ +public class Trust { + + /** Explicitely assigned trust. */ + private final Integer explicit; + + /** Implicitely calculated trust. */ + private final Integer implicit; + + /** The distance from the owner of the trust tree. */ + private final Integer distance; + + /** + * Creates a new trust container. + * + * @param explicit + * The explicit trust + * @param implicit + * The implicit trust + * @param distance + * The distance + */ + public Trust(Integer explicit, Integer implicit, Integer distance) { + this.explicit = explicit; + this.implicit = implicit; + this.distance = distance; + } + + /** + * Returns the trust explicitely assigned to an identity. + * + * @return The explicitely assigned trust, or {@code null} if the identity + * is not in the own identity’s trust tree + */ + public Integer getExplicit() { + return explicit; + } + + /** + * Returns the implicitely assigned trust, or the calculated trust. + * + * @return The calculated trust, or {@code null} if the identity is not in + * the own identity’s trust tree + */ + public Integer getImplicit() { + return implicit; + } + + /** + * Returns the distance of the trusted identity from the trusting identity. + * + * @return The distance from the own identity, or {@code null} if the + * identity is not in the own identity’s trust tree + */ + public Integer getDistance() { + return distance; + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return getClass().getName() + "[explicit=" + explicit + ",implicit=" + implicit + ",distance=" + distance + "]"; + } + +} diff --git a/src/main/resources/de/todesbaum/jsite/i18n/jSite.properties b/src/main/resources/de/todesbaum/jsite/i18n/jSite.properties index 942692d..81bfc89 100644 --- a/src/main/resources/de/todesbaum/jsite/i18n/jSite.properties +++ b/src/main/resources/de/todesbaum/jsite/i18n/jSite.properties @@ -175,11 +175,15 @@ jsite.update-checker.latest-version.okay.message=You are currently running jsite.key-dialog.title=Manage Project Keys jsite.key-dialog.button.ok.tooltip=Accepts the changes jsite.key-dialog.button.cancel.tooltip=Discards the changes +jsite.key-dialog.button.copy-from-identity=Copy from Identity +jsite.key-dialog.button.copy-from-identity.tooltip=Copies the public and private keys from the selected identity jsite.key-dialog.button.generate=Regenerate Keys jsite.key-dialog.button.generate.tooltip=Create a new key pair jsite.key-dialog.label.keys=Keys jsite.key-dialog.label.private-key=Private Key jsite.key-dialog.label.public-key=Public Key +jsite.key-dialog.label.identities=Identities +jsite.key-dialog.label.identity=Identity jsite.key-dialog.label.actions=Actions jsite.warning.empty-index=No default file

You did not specify a default file for this project.
While it is possible to insert a project without a default
file you should specify one to ease browsing. diff --git a/src/main/resources/de/todesbaum/jsite/i18n/jSite_de.properties b/src/main/resources/de/todesbaum/jsite/i18n/jSite_de.properties index dd04f6f..7e34e0e 100644 --- a/src/main/resources/de/todesbaum/jsite/i18n/jSite_de.properties +++ b/src/main/resources/de/todesbaum/jsite/i18n/jSite_de.properties @@ -175,11 +175,15 @@ jsite.update-checker.latest-version.okay.message=Es l\u00e4uft momentan Ve jsite.key-dialog.title=Projektschl\u00fcsselverwaltung jsite.key-dialog.button.ok.tooltip=\u00c4nderungen akzeptieren jsite.key-dialog.button.cancel.tooltip=\u00c4nderungen verwerfen +jsite.key-dialog.button.copy-from-identity=Von Identit\u00e4t kopieren +jsite.key-dialog.button.copy-from-identity.tooltip=Kopiert das Schl\u00fcsselpaar der ausgew\u00e4hlten Identit\u00e4t jsite.key-dialog.button.generate=Schl\u00fcssel neu generieren jsite.key-dialog.button.generate.tooltip=Generiert ein neues Schl\u00fcsselpaar jsite.key-dialog.label.keys=Schl\u00fcssel jsite.key-dialog.label.private-key=Privater Schl\u00fcssel jsite.key-dialog.label.public-key=\u00d6ffentlicher Schl\u00fcssel +jsite.key-dialog.label.identities=Identit\u00e4ten +jsite.key-dialog.label.identity=Identit\u00e4t jsite.key-dialog.label.actions=Aktionen jsite.warning.empty-index=Keine Index-Datei gew\u00e4hlt

Sie haben keine Index-Datei f\u00fcr das Projekt angegeben.
Obwohl es m\u00f6glich ist, das zu machen, sollten Sie doch
eine Index-Datei angeben, um das Browsen zu erleichtern. diff --git a/src/main/resources/de/todesbaum/jsite/i18n/jSite_fr.properties b/src/main/resources/de/todesbaum/jsite/i18n/jSite_fr.properties index 0f40e0f..21691b6 100644 --- a/src/main/resources/de/todesbaum/jsite/i18n/jSite_fr.properties +++ b/src/main/resources/de/todesbaum/jsite/i18n/jSite_fr.properties @@ -175,15 +175,20 @@ jsite.update-checker.latest-version.okay.message=Vous utilisez la version jsite.key-dialog.title=G\u00e9rer les cl\u00e9s des projets jsite.key-dialog.button.ok.tooltip=Accepter les changements jsite.key-dialog.button.cancel.tooltip=Annuler les changements +jsite.key-dialog.button.copy-from-identity=Copy from Identity +jsite.key-dialog.button.copy-from-identity.tooltip=Copies the public and private keys from the selected identity jsite.key-dialog.button.generate=Reg\u00e9n\u00e9rer les cl\u00e9s jsite.key-dialog.button.generate.tooltip=Cr\u00e9er une nouvelle paire de cl\u00e9s jsite.key-dialog.label.keys=Cl\u00e9s jsite.key-dialog.label.private-key=Cl\u00e9 priv\u00e9e jsite.key-dialog.label.public-key=Cl\u00e9 publique +jsite.key-dialog.label.identities=Identities +jsite.key-dialog.label.identity=Identity jsite.key-dialog.label.actions=Actions jsite.warning.empty-index=Pas de fichier par d\u00e9faut

Avez vous sp\u00e9cifi\u00e9 un fichier par d\u00e9faut pour le projet?
M\u00eame s'il est possible de ne pas en sp\u00e9cifier, c'est g\u00e9n\u00e9ralement une mauvaise id\u00e9e. jsite.warning.index-not-html=Le fichier principal n'est pas un fichier HTML!

Votre fichier par d\u00e9faut n'est pas du type MIME "text/html"!
Chargez ce type de fichiers dans un navigateur peut \u00eatre dangereux. +jsite.warning.site-larger-than-2-mib=Site is larger than 2 MiB!

Your site contains more than 2 megabytes of data.
Due to bugs in Freenet it will probably not load correctly.
Try to reduce the size of your site, or continue at your own peril. jsite.error.no-node-selected=Pas de noeud s\u00e9lectionn\u00e9

S\u00e9lectionnez un noeud dans le menu! jsite.error.no-node-running=Ce noeud n'est pas actif!

Vous ne pouvez pas utiliser jSite sans noeud actif.
Veuillez d\u00e9marrer votre noeud et r\u00e9essayer. @@ -194,5 +199,4 @@ jsite.error.index-not-inserted=Fichier par d\u00e9faut non ins\u00e9r\u jsite.error.no-custom-key=Pas de clef existante sp\u00e9cifi\u00e9e pour ce fichier

Vous avez sp\u00e9cifier de ne pas ins\u00e9rer {0}
mais n'avez pas sp\u00e9cifier de clef ou rediriger! jsite.error.no-files-to-insert=Aucun fichier \u00e0 ins\u00e9rer

Vous n'avez s\u00e9lectionn\u00e9 aucun fichier pour l'insertion !
Veuillez s\u00e9lectionner au moins un fichier \u00e0 ins\u00e9rer. jsite.error.duplicate-file=Fichier dupliqu\u00e9

Le fichier {0} est ins\u00e9r\u00e9 deux fois !
Veuillez v\u00e9rifier les noms de fichier et les redirections. - -# to update: jsite.project-files.scanning \ No newline at end of file +# to update: 178, 179, 185-187, 191 \ No newline at end of file