Adds password modification from within Jitsi for XMPP accounts that allow it. Contributed by Boris Grozev.

cusax-fix
Emil Ivov 13 years ago
parent 20a28fa8c2
commit ab1a357d8c

@ -943,6 +943,17 @@ plugin.jabberaccregwizz.TELEPHONY_DOMAIN=Telephony domain
plugin.jabberaccregwizz.ALLOW_NON_SECURE=Allow non-secure connections
plugin.jabberaccregwizz.DTMF_AUTO=Auto: Choose automatically between RTP and Inband
plugin.jabberaccregwizz.SERVER_OPTIONS=Server options
plugin.jabberaccregwizz.CHANGE_PASSWORD=Change account password
plugin.jabberaccregwizz.NEW_PASSWORD=New password
plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=Confirm new password
plugin.jabberaccregwizz.PORT_FIELD_INVALID=Please fill a valid port number in order to continue.
plugin.jabberaccregwizz.HAS_TO_BE_LOGGED_IN=The account has to be signed in before changing a password.
plugin.jabberaccregwizz.PASSWORD_EMPTY=The password is empty.
plugin.jabberaccregwizz.TLS_REQUIRED=The connection does not use TLS, will not attempt a password change.
plugin.jabberaccregwizz.PASSWORD_CHANGED=The password has been successfully changed
plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=Your jabber server does not support password changes.
plugin.jabberaccregwizz.PASSWORD_NOT_STORED=The password has been changed on the server, but local configuration was not updated
plugin.jabberaccregwizz.ENTER_NEW_PASSWORD=Please enter your new password in both fields:
# mailbox
plugin.mailbox.OUTGOING=Outgoing Message:

@ -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);
}
}
}

@ -1794,6 +1794,11 @@ protected void initialize(String screenname,
supportedFeatures.add(MessageCorrectionExtension.NAMESPACE);
addSupportedOperationSet(OperationSetMessageCorrection.class,
basicInstantMessaging);
OperationSetChangePassword opsetChangePassword
= new OperationSetChangePasswordJabberImpl(this);
addSupportedOperationSet(OperationSetChangePassword.class,
opsetChangePassword);
isInitialized = true;
}

@ -14,6 +14,7 @@
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 AccountPanel(final JabberAccountRegistrationForm parentForm)
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 void actionPerformed(ActionEvent evt)
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);
}
}
}

@ -365,10 +365,21 @@ public void loadAccount(AccountID accountID)
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 @@ private static String loadStunPassword(AccountID accountID,
return password;
}
/**
* Returns the wizard that created the form
* @return The form wizard
*/
public JabberAccountRegistrationWizard getWizard()
{
return wizard;
}
}

@ -749,4 +749,16 @@ protected String getHomeLinkLabel()
{
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;
}
}

@ -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;
}
Loading…
Cancel
Save