| /******************************************************************************* |
| * Copyright (c) 2007, 2008 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jsch.ui; |
| |
| import org.eclipse.core.runtime.OperationCanceledException; |
| import org.eclipse.jface.dialogs.IDialogConstants; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jsch.core.IJSchService; |
| import org.eclipse.jsch.internal.ui.KeyboardInteractiveDialog; |
| import org.eclipse.jsch.internal.ui.Messages; |
| import org.eclipse.jsch.internal.ui.UserValidationDialog; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Shell; |
| |
| import com.jcraft.jsch.Session; |
| import com.jcraft.jsch.UIKeyboardInteractive; |
| import com.jcraft.jsch.UserInfo; |
| |
| /** |
| * A {@link UserInfo} prompter implementation that can be used when connecting a |
| * {@link Session}. |
| * <p> |
| * Clients may instantiate or subclass this class. |
| * |
| * @since 1.0 |
| * @see IJSchService#createSession(String, int, String) |
| * @see IJSchService#connect(Session, int, |
| * org.eclipse.core.runtime.IProgressMonitor) |
| */ |
| public class UserInfoPrompter implements UserInfo, UIKeyboardInteractive{ |
| |
| private String passphrase; |
| private String password; |
| private final Session session; |
| private int attemptCount; |
| |
| /** |
| * Create a prompter for the given session. This constructor will associate |
| * this prompter with the session using {@link Session#setUserInfo(UserInfo)}. |
| * |
| * @param session |
| * the session |
| */ |
| public UserInfoPrompter(Session session){ |
| super(); |
| this.session=session; |
| session.setUserInfo(this); |
| } |
| |
| /** |
| * Return the session to which this prompter is assigned. |
| * |
| * @return the session to which this prompter is assigned |
| */ |
| public Session getSession(){ |
| return session; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see com.jcraft.jsch.UserInfo#getPassphrase() |
| */ |
| @Override |
| public String getPassphrase(){ |
| return passphrase; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see com.jcraft.jsch.UserInfo#getPassword() |
| */ |
| @Override |
| public String getPassword(){ |
| return password; |
| } |
| |
| /** |
| * Set the pass phrase to be used when connecting the session. Return |
| * <code>null</code> if the pass phrase is not known. |
| * |
| * @param passphrase |
| * the pass phrase to be used when connecting the session or |
| * <code>null</code> |
| */ |
| public void setPassphrase(String passphrase){ |
| this.passphrase=passphrase; |
| } |
| |
| /** |
| * Set the password to be used when connecting the session. Return |
| * <code>null</code> if the password is not known. |
| * |
| * @param password |
| * the password to be used when connecting the session or |
| * <code>null</code> |
| */ |
| public void setPassword(String password){ |
| this.password=password; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see com.jcraft.jsch.UserInfo#promptPassphrase(java.lang.String) |
| */ |
| @Override |
| public boolean promptPassphrase(String message){ |
| String _passphrase=promptSecret(message); |
| if(_passphrase!=null){ |
| setPassphrase(_passphrase); |
| } |
| return _passphrase!=null; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see com.jcraft.jsch.UserInfo#promptPassword(java.lang.String) |
| */ |
| @Override |
| public boolean promptPassword(String message){ |
| String _password=promptSecret(message); |
| if(_password!=null){ |
| setPassword(_password); |
| } |
| return _password!=null; |
| } |
| |
| private String promptSecret(final String message){ |
| // ask the user for a password |
| final String[] result=new String[1]; |
| Display display=Display.getCurrent(); |
| if(display!=null){ |
| result[0]=promptForPassword(message); |
| } |
| else{ |
| // sync exec in default thread |
| Display.getDefault().syncExec(() -> result[0] = promptForPassword(message)); |
| } |
| |
| if(result[0]==null){ |
| throw new OperationCanceledException(); |
| } |
| return result[0]; |
| } |
| |
| /* package */String promptForPassword(final String message){ |
| String username=getSession().getUserName(); |
| UserValidationDialog dialog=new UserValidationDialog(null, null, |
| (username==null) ? "" : username, message); //$NON-NLS-1$ |
| dialog.setUsernameMutable(false); |
| dialog.open(); |
| return dialog.getPassword(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see com.jcraft.jsch.UIKeyboardInteractive#promptKeyboardInteractive(java.lang.String, |
| * java.lang.String, java.lang.String, java.lang.String[], boolean[]) |
| */ |
| @Override |
| public String[] promptKeyboardInteractive(String destination, String name, |
| String instruction, String[] prompt, boolean[] echo){ |
| if(prompt.length==0){ |
| // No need to prompt, just return an empty String array |
| return new String[0]; |
| } |
| try{ |
| if(attemptCount==0&&password!=null&&prompt.length==1 |
| &&prompt[0].trim().equalsIgnoreCase("password:")){ //$NON-NLS-1$ |
| // Return the provided password the first time but always prompt on |
| // subsequent tries |
| attemptCount++; |
| return new String[] {password}; |
| } |
| String[] result=promptForKeyboradInteractiveInUI(destination, name, |
| instruction, prompt, echo); |
| if(result==null) |
| return null; // canceled |
| if(result.length==1&&prompt.length==1 |
| &&prompt[0].trim().equalsIgnoreCase("password:")){ //$NON-NLS-1$ |
| password=result[0]; |
| } |
| attemptCount++; |
| return result; |
| } |
| catch(OperationCanceledException e){ |
| return null; |
| } |
| } |
| |
| private String[] promptForKeyboradInteractiveInUI(final String destination, |
| final String name, final String instruction, final String[] prompt, |
| final boolean[] echo){ |
| final String[][] result=new String[1][]; |
| Display display=Display.getCurrent(); |
| if(display!=null){ |
| result[0]=internalPromptForUserInteractive(destination, name, |
| instruction, prompt, echo); |
| } |
| else{ |
| // sync exec in default thread |
| Display.getDefault().syncExec( |
| () -> result[0] = internalPromptForUserInteractive(destination, name, instruction, prompt, echo)); |
| } |
| return result[0]; |
| } |
| |
| /* package */ String[] internalPromptForUserInteractive(String destination, |
| String name, String instruction, String[] prompt, boolean[] echo){ |
| String domain=null; |
| String userName=getSession().getUserName(); |
| KeyboardInteractiveDialog dialog=new KeyboardInteractiveDialog(null, |
| domain, destination, name, userName, instruction, prompt, echo); |
| dialog.open(); |
| String[] _result=dialog.getResult(); |
| return _result; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see com.jcraft.jsch.UserInfo#promptYesNo(java.lang.String) |
| */ |
| @Override |
| public boolean promptYesNo(String question){ |
| int prompt=prompt(MessageDialog.QUESTION, Messages.UserInfoPrompter_0, |
| question, new int[] {IDialogConstants.YES_ID, IDialogConstants.NO_ID}, |
| 0 // yes |
| // the |
| // default |
| ); |
| return prompt==0; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see com.jcraft.jsch.UserInfo#showMessage(java.lang.String) |
| */ |
| @Override |
| public void showMessage(String message){ |
| prompt(MessageDialog.INFORMATION, Messages.UserInfoPrompter_1, message, |
| new int[] {IDialogConstants.OK_ID}, 0); |
| } |
| |
| private int prompt(final int promptType, final String title, |
| final String message, final int[] promptResponses, |
| final int defaultResponse){ |
| final Display display=getStandardDisplay(); |
| final int[] retval=new int[1]; |
| final String[] buttons=new String[promptResponses.length]; |
| for(int i=0; i<promptResponses.length; i++){ |
| int prompt=promptResponses[i]; |
| switch(prompt){ |
| case IDialogConstants.OK_ID: |
| buttons[i]=IDialogConstants.OK_LABEL; |
| break; |
| case IDialogConstants.CANCEL_ID: |
| buttons[i]=IDialogConstants.CANCEL_LABEL; |
| break; |
| case IDialogConstants.NO_ID: |
| buttons[i]=IDialogConstants.NO_LABEL; |
| break; |
| case IDialogConstants.YES_ID: |
| buttons[i]=IDialogConstants.YES_LABEL; |
| break; |
| } |
| } |
| |
| display.syncExec(() -> { |
| final MessageDialog dialog=new MessageDialog(new Shell(display), title, |
| null /* title image */, message, promptType, buttons, |
| defaultResponse); |
| retval[0]=dialog.open(); |
| }); |
| return retval[0]; |
| } |
| |
| private Display getStandardDisplay(){ |
| Display display=Display.getCurrent(); |
| if(display==null){ |
| display=Display.getDefault(); |
| } |
| return display; |
| } |
| |
| } |