diff options
author | Emil Ivov <emcho@jitsi.org> | 2012-08-07 18:32:13 +0000 |
---|---|---|
committer | Emil Ivov <emcho@jitsi.org> | 2012-08-07 18:32:13 +0000 |
commit | ab1a357d8cb3e05d205a26c5bfe8a7e3fbd11978 (patch) | |
tree | 1fb81e9b39745bc1bd66b0178d155f622139caf2 /src | |
parent | 20a28fa8c210a665f6a5fc4ef37ab12fe70a1ba8 (diff) | |
download | jitsi-ab1a357d8cb3e05d205a26c5bfe8a7e3fbd11978.zip jitsi-ab1a357d8cb3e05d205a26c5bfe8a7e3fbd11978.tar.gz jitsi-ab1a357d8cb3e05d205a26c5bfe8a7e3fbd11978.tar.bz2 |
Adds password modification from within Jitsi for XMPP accounts that allow it. Contributed by Boris Grozev.
Diffstat (limited to 'src')
6 files changed, 458 insertions, 2 deletions
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetChangePasswordJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetChangePasswordJabberImpl.java new file mode 100644 index 0000000..82b89d5 --- /dev/null +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetChangePasswordJabberImpl.java @@ -0,0 +1,73 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.protocol.jabber; + +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.util.*; +import org.jivesoftware.smack.*; + +/** + * A jabber implementation of the password change operation set. + * + * @author Boris Grozev + */ +public class OperationSetChangePasswordJabberImpl + implements OperationSetChangePassword +{ + /** + * The <tt>ProtocolProviderService</tt> whose password we'll change. + */ + private ProtocolProviderServiceJabberImpl protocolProvider; + + /** + * The logger used by <tt>OperationSetChangePasswordJabberImpl</tt>. + */ + private static final Logger logger = + Logger.getLogger(OperationSetChangePasswordJabberImpl.class); + + /** + * Sets the object protocolProvider to the one given. + * @param protocolProvider the protocolProvider to use. + */ + OperationSetChangePasswordJabberImpl ( + ProtocolProviderServiceJabberImpl protocolProvider) + { + this.protocolProvider = protocolProvider; + } + + /** + * Changes the jabber account password of protocolProvider to newPass. + * @param newPass the new password. + * @throws IllegalStateException if the account is not registered. + * @throws OperationFailedException if the server does not support password + * changes. + */ + public void changePassword(String newPass) + throws IllegalStateException, OperationFailedException + { + org.jivesoftware.smack.AccountManager accountManager + = new org.jivesoftware.smack.AccountManager( + protocolProvider.getConnection()); + + try + { + accountManager.changePassword(newPass); + } + catch (XMPPException e) + { + if(logger.isInfoEnabled()) + { + logger.info("Tried to change jabber password, but the server " + + "does not support inband password changes", e); + } + + throw new OperationFailedException("In-band password changes not" + + " supported", + OperationFailedException.NOT_SUPPORTED_OPERATION, + e); + } + } +} diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java index d6947d7..c2d0865 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java @@ -1794,6 +1794,11 @@ public class ProtocolProviderServiceJabberImpl supportedFeatures.add(MessageCorrectionExtension.NAMESPACE); addSupportedOperationSet(OperationSetMessageCorrection.class, basicInstantMessaging); + + OperationSetChangePassword opsetChangePassword + = new OperationSetChangePasswordJabberImpl(this); + addSupportedOperationSet(OperationSetChangePassword.class, + opsetChangePassword); isInitialized = true; } diff --git a/src/net/java/sip/communicator/plugin/jabberaccregwizz/AccountPanel.java b/src/net/java/sip/communicator/plugin/jabberaccregwizz/AccountPanel.java index 264e875..0bcac3a 100644 --- a/src/net/java/sip/communicator/plugin/jabberaccregwizz/AccountPanel.java +++ b/src/net/java/sip/communicator/plugin/jabberaccregwizz/AccountPanel.java @@ -14,6 +14,7 @@ import javax.swing.event.*; import net.java.sip.communicator.util.*; import net.java.sip.communicator.util.swing.*; +import net.java.sip.communicator.service.protocol.*; /** * @author Yana Stamcheva */ @@ -48,6 +49,18 @@ public class AccountPanel private final JCheckBox rememberPassBox = new SIPCommCheckBox(Resources .getString("service.gui.REMEMBER_PASSWORD")); + /** + * Panel to hold the "change password" button + */ + private final JPanel changePasswordPanel = new TransparentPanel(); + + /** + * "Change password" button + */ + private final JButton changePasswordButton + = new JButton(Resources.getString( + "plugin.jabberaccregwizz.CHANGE_PASSWORD")); + private final JabberAccountRegistrationForm parentForm; private final JRadioButton existingAccountButton; @@ -128,8 +141,19 @@ public class AccountPanel userIDPassPanel.add(southPanel, BorderLayout.SOUTH); this.add(mainPanel, BorderLayout.NORTH); + + changePasswordButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + ChangePasswordDialog changePasswordDialog + = new ChangePasswordDialog(); + } + }); + changePasswordPanel.add(changePasswordButton, BorderLayout.CENTER); + //show it only if needed (when modifying an account) + changePasswordPanel.setVisible(false); + this.add(changePasswordPanel); + } - /** * Creates a register choice panel. * @return the created component @@ -473,4 +497,300 @@ public class AccountPanel return registerButton; } + /** + * Shows or hides the "change password" button + */ + public void showChangePasswordButton() + { + changePasswordPanel.setVisible(true); + } + + /** + * A "change password" dialog. + */ + private class ChangePasswordDialog extends SIPCommDialog + { + /** + * The main panel + */ + private final JPanel mainPanel = new JPanel(new BorderLayout()); + + /** + * A pane for showing messages (info or errors) + */ + private final JEditorPane messagePane = new JEditorPane(); + + /** + * Panel for the text fields + */ + TransparentPanel valuesPanel + = new TransparentPanel(new GridLayout(0, 1)); + + /** + * The password field + */ + private final JPasswordField passField1 = new JPasswordField(); + + /** + * The confirm password field + */ + private final JPasswordField passField2 = new JPasswordField(); + + /** + * Panel for the "ok" and "cancel" buttons + */ + private final TransparentPanel buttonsPanel + = new TransparentPanel(new FlowLayout(FlowLayout.RIGHT)); + + /** + * The "OK" button + */ + private final JButton okButton + = new JButton(Resources.getString("service.gui.OK")); + + /** + * The "cancel" button + */ + private final JButton cancelButton + = new JButton(Resources.getString("service.gui.CANCEL")); + + /** + * Panel for the labels + */ + private final TransparentPanel labelsPanel + = new TransparentPanel(new GridLayout(0, 1)); + + /** + * The "new password" label + */ + private final JLabel passLabel1 = new JLabel(Resources. + getString("plugin.jabberaccregwizz.NEW_PASSWORD")); + + /** + * The "confirm password" label + */ + private final JLabel passLabel2 = new JLabel(Resources. + getString("plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM")); + + + /** + * Creates a full dialog (sets all the fields and buttons) + */ + public ChangePasswordDialog() + { + //don't save size and location + super(false); + + setTitle(Resources. + getString("plugin.jabberaccregwizz.CHANGE_PASSWORD")); + + messagePane.setOpaque(false); + messagePane.setForeground(Color.RED); + messagePane.setBorder(BorderFactory.createEmptyBorder(0, 0, 15, 0)); + messagePane.setEditable(false); + mainPanel.add(messagePane, BorderLayout.NORTH); + loadMessage(Resources.getString( + "plugin.jabberaccregwizz.ENTER_NEW_PASSWORD")); + + labelsPanel.add(passLabel1); + labelsPanel.add(passLabel2); + + passField1.setColumns(15); + passField2.setColumns(15); + valuesPanel.add(passField1); + valuesPanel.add(passField2); + + okButton.addActionListener(okButtonListener); + cancelButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e){ + dispose(); + } + }); + + buttonsPanel.add(okButton); + buttonsPanel.add(cancelButton); + getRootPane().setDefaultButton(okButton); + + mainPanel.add(labelsPanel, BorderLayout.WEST); + mainPanel.add(valuesPanel, BorderLayout.CENTER); + mainPanel.add(buttonsPanel, BorderLayout.SOUTH); + + mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); + getContentPane().add(mainPanel, BorderLayout.NORTH); + setModal(true); + setVisible(true); + pack(); + } + + /** + * This is the ActionListener for the "ok" button. + */ + private final ActionListener okButtonListener = new ActionListener(){ + /** + * Action for the "ok" button. This contains most of the logic for + * the dialog: + * It checks the fields, whether the account is logged in, tries to + * change the password and displays messages in the message pane + */ + public void actionPerformed(ActionEvent e) { + String newPass1 = new String(passField1.getPassword()); + String newPass2 = new String(passField2.getPassword()); + + ProtocolProviderService protocolProvider = + parentForm.getWizard().getProtocolProvider(); + + if (protocolProvider == null) { + //we shouldn't get here, because this dialog only shows + //when editing an existing account + logger.warn("protocolProvider is null in change" + + " password dialog"); + loadMessage("Could not change password"); + hideCancelAndFields(); + okButton.removeActionListener(okButtonListener); + okButton.addActionListener(new ActionListener(){ + public void actionPerformed(ActionEvent e) + { + dispose(); + } + }); + } + else if (!protocolProvider.isRegistered()) { + //editing an account, which is not logged in + loadMessage(Resources.getString( + "plugin.jabberaccregwizz.HAS_TO_BE_LOGGED_IN")); + } + else if (!newPass1.equals(newPass2)) { + loadMessage(Resources.getString( + "plugin.jabberaccregwizz.NOT_SAME_PASSWORD")); + } + else if (newPass1.length() <= 0) { + loadMessage(Resources.getString( + "plugin.jabberaccregwizz.PASSWORD_EMPTY")); + } + else if (protocolProvider.getTransportProtocol() + != TransportProtocol.TLS) { + //XEP-077 advices agains changing password unless + //the underlying stream is encrypted + loadMessage(Resources.getString( + "plugin.jabberaccregwizz.TLS_REQUIRED")); + } + else //try to change + { + if (logger.isInfoEnabled()) { + logger.info("Trying to change password for jabber" + + " account " + + protocolProvider. + getAccountID().getAccountAddress()); + } + + OperationSetChangePassword opset = + protocolProvider.getOperationSet( + OperationSetChangePassword.class); + try { + opset.changePassword(newPass1); + loadMessage(Resources.getString( + "plugin.jabberaccregwizz.PASSWORD_CHANGED")); + + /** + * If the old password was stored, update it with the + * new one. If the old password was not stored, leave it + * like it is. + */ + if (isRememberPassword()) + { + try + { + if(logger.isInfoEnabled()) + logger.info("Storing new password for" + + " account " + protocolProvider. + getAccountID().getAccountAddress()); + + storeNewPassword(newPass1); + } + catch (IllegalArgumentException ex) + { + //If we get here its a bug, and showing a + //message like this might be unappropriate. But + //the user would want to know about it! + logger.warn("Failed to store password for" + + " account " + protocolProvider. + getAccountID().getAccountAddress(), + ex); + loadMessage(Resources.getString( + "plugin.jabberaccregwizz." + + "PASSWORD_NOT_STORED")); + } + + //now update the password field in AccountPanel, + //because it still has the old pass and if the user + //completes the wizard it will store it. + passField.setText(newPass1); + } + + hideCancelAndFields(); + okButton.removeActionListener(this); + okButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + dispose(); + } + }); + } + catch (IllegalStateException ex) { + //we already checked for this, but if the connection + //has since been lost smack will throw this + loadMessage(Resources.getString( + "plugin.jabberaccregwizz.HAS_TO_BE_LOGGED_IN")); + } + catch (OperationFailedException ex) { + loadMessage(Resources.getString( + "plugin.jabberaccregwizz." + + "SERVER_NOT_SUPPORT_PASSWORD_CHANGE")); + } + } + } + }; + + + /** + * Loads the given message into the message pane. + * @param message The message to load + */ + private void loadMessage(String message) + { + messagePane.setText(message); + mainPanel.revalidate(); + mainPanel.repaint(); + pack(); + } + + /** + * Leaves only the message pane and the "ok" button visible + * XXX: a more appropriate name? + */ + public void hideCancelAndFields() + { + cancelButton.setVisible(false); + passField1.setVisible(false); + passField2.setVisible(false); + passLabel1.setVisible(false); + passLabel2.setVisible(false); + pack(); + } + + /** + * Stores the new password in the account configuration + * @param newPass The new password + * @throws IllegalArgumentException on failure (from + * ProtocolProviderFactory.storePassword) + */ + void storeNewPassword(String newPass) throws IllegalArgumentException + { + AccountID accountID = parentForm.getWizard().getProtocolProvider(). + getAccountID(); + ProtocolProviderFactory protocolProviderFactory = + JabberAccRegWizzActivator.getJabberProtocolProviderFactory(); + + protocolProviderFactory.storePassword(accountID, newPass); + } + } } diff --git a/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountRegistrationForm.java b/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountRegistrationForm.java index 9baba50..6008dc8 100644 --- a/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountRegistrationForm.java +++ b/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountRegistrationForm.java @@ -365,10 +365,21 @@ public class JabberAccountRegistrationForm accountPanel.setPassword(password); accountPanel.setRememberPassword(true); } - + String serverAddress = accountProperties.get(ProtocolProviderFactory.SERVER_ADDRESS); + //The idea here is to not show the "change password" button for + //GTalk and Facebook acounts, or accounts in gmail, since we know + //they don't support inband password changes. + //This is probably a bad way to achieve it... + if ( !serverAddress.equals("gmail.com") + && !serverAddress.equals("talk.google.com") + && !serverAddress.equals("chat.facebook.com")) + { + accountPanel.showChangePasswordButton(); + } + connectionPanel.setServerAddress(serverAddress); String serverPort @@ -699,4 +710,13 @@ public class JabberAccountRegistrationForm return password; } + + /** + * Returns the wizard that created the form + * @return The form wizard + */ + public JabberAccountRegistrationWizard getWizard() + { + return wizard; + } } diff --git a/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountRegistrationWizard.java b/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountRegistrationWizard.java index 4126865..093b361 100644 --- a/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountRegistrationWizard.java +++ b/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountRegistrationWizard.java @@ -749,4 +749,16 @@ public class JabberAccountRegistrationWizard { return null; } + + /** + * Return the wizard's protocolProvider, if the wizard modifies an + * account, null if it creates a new one + * @return the wizard's protocolProvider + */ + public ProtocolProviderService getProtocolProvider() + { + if(isModification()) + return protocolProvider; + return null; + } } diff --git a/src/net/java/sip/communicator/service/protocol/OperationSetChangePassword.java b/src/net/java/sip/communicator/service/protocol/OperationSetChangePassword.java new file mode 100644 index 0000000..0efda6a --- /dev/null +++ b/src/net/java/sip/communicator/service/protocol/OperationSetChangePassword.java @@ -0,0 +1,26 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.service.protocol; + +/** + * An operation set that allows "inband" change of the account password + * + * @author Boris Grozev + */ +public interface OperationSetChangePassword + extends OperationSet +{ + /** + * Changes the account password to newPass + * + * @param newPass the new password. + * @throws IllegalStateException if the account is not registered. + * @throws OperationFailedException if the change failed for another reason. + */ + public void changePassword(String newPass) + throws IllegalStateException, OperationFailedException; +} |