git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4574 3789f03b-4d11-0410-bbf8-ca57d06f2519tags/v1.1.90
@@ -1,251 +1,251 @@ | |||
/* | |||
* Copyright (C) 2003 Sun Microsystems, Inc. | |||
* | |||
* This 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 software 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 software; if not, write to the Free Software | |||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||
* USA. | |||
*/ | |||
/* | |||
* Copyright (C) 2003 Sun Microsystems, Inc. | |||
* | |||
* This 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 software 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 software; if not, write to the Free Software | |||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||
* USA. | |||
*/ | |||
package com.tigervnc.rfb; | |||
import javax.net.ssl.*; | |||
import java.security.*; | |||
import java.security.cert.*; | |||
import java.security.KeyStore; | |||
import java.io.File; | |||
import java.io.InputStream; | |||
import java.io.FileInputStream; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import javax.swing.JOptionPane; | |||
import com.tigervnc.vncviewer.UserPrefs; | |||
import com.tigervnc.rdr.*; | |||
public class CSecurityTLS extends CSecurity { | |||
public static StringParameter x509ca | |||
= new StringParameter("x509ca", | |||
"X509 CA certificate", ""); | |||
public static StringParameter x509crl | |||
= new StringParameter("x509crl", | |||
"X509 CRL file", ""); | |||
private void initGlobal() | |||
{ | |||
try { | |||
SSLSocketFactory sslfactory; | |||
SSLContext ctx = SSLContext.getInstance("TLS"); | |||
if (anon) { | |||
ctx.init(null, null, null); | |||
} else { | |||
TrustManager[] myTM = new TrustManager[] { | |||
new MyX509TrustManager() | |||
}; | |||
ctx.init (null, myTM, null); | |||
} | |||
sslfactory = ctx.getSocketFactory(); | |||
try { | |||
ssl = (SSLSocket)sslfactory.createSocket(cc.sock, | |||
cc.sock.getInetAddress().getHostName(), | |||
cc.sock.getPort(), true); | |||
} catch (java.io.IOException e) { | |||
throw new Exception(e.toString()); | |||
} | |||
if (anon) { | |||
String[] supported; | |||
ArrayList enabled = new ArrayList(); | |||
supported = ssl.getSupportedCipherSuites(); | |||
for (int i = 0; i < supported.length; i++) | |||
if (supported[i].matches("TLS_DH_anon.*")) | |||
enabled.add(supported[i]); | |||
ssl.setEnabledCipherSuites((String[])enabled.toArray(new String[0])); | |||
} else { | |||
ssl.setEnabledCipherSuites(ssl.getSupportedCipherSuites()); | |||
} | |||
ssl.setEnabledProtocols(new String[]{"SSLv3","TLSv1"}); | |||
ssl.addHandshakeCompletedListener(new MyHandshakeListener()); | |||
} | |||
catch (java.security.GeneralSecurityException e) | |||
{ | |||
vlog.error ("TLS handshake failed " + e.toString ()); | |||
return; | |||
} | |||
} | |||
public CSecurityTLS(boolean _anon) | |||
{ | |||
anon = _anon; | |||
setDefaults(); | |||
cafile = x509ca.getData(); | |||
crlfile = x509crl.getData(); | |||
} | |||
public static void setDefaults() | |||
{ | |||
String homeDir = null; | |||
if ((homeDir=UserPrefs.getHomeDir()) == null) { | |||
vlog.error("Could not obtain VNC home directory path"); | |||
return; | |||
} | |||
String vnchomedir = homeDir+UserPrefs.getFileSeperator()+".vnc"+ | |||
UserPrefs.getFileSeperator(); | |||
String caDefault = new String(vnchomedir+"x509_ca.pem"); | |||
String crlDefault = new String(vnchomedir+"x509_crl.pem"); | |||
if (new File(caDefault).exists()) | |||
x509ca.setDefaultStr(caDefault); | |||
if (new File(crlDefault).exists()) | |||
x509crl.setDefaultStr(crlDefault); | |||
} | |||
public boolean processMsg(CConnection cc) { | |||
is = cc.getInStream(); | |||
os = cc.getOutStream(); | |||
initGlobal(); | |||
if (!is.checkNoWait(1)) | |||
return false; | |||
if (is.readU8() == 0) { | |||
int result = is.readU32(); | |||
String reason; | |||
if (result == Security.secResultFailed || | |||
result == Security.secResultTooMany) | |||
reason = is.readString(); | |||
else | |||
reason = new String("Authentication failure (protocol error)"); | |||
throw new AuthFailureException(reason); | |||
} | |||
// SSLSocket.getSession blocks until the handshake is complete | |||
session = ssl.getSession(); | |||
if (!session.isValid()) | |||
throw new Exception("TLS Handshake failed!"); | |||
try { | |||
cc.setStreams(new JavaInStream(ssl.getInputStream()), | |||
new JavaOutStream(ssl.getOutputStream())); | |||
} catch (java.io.IOException e) { | |||
throw new Exception("Failed to set streams"); | |||
} | |||
return true; | |||
} | |||
class MyHandshakeListener implements HandshakeCompletedListener { | |||
public void handshakeCompleted(HandshakeCompletedEvent e) { | |||
vlog.info("Handshake succesful!"); | |||
vlog.info("Using cipher suite: " + e.getCipherSuite()); | |||
} | |||
} | |||
class MyX509TrustManager implements X509TrustManager | |||
{ | |||
X509TrustManager tm; | |||
MyX509TrustManager() throws java.security.GeneralSecurityException | |||
{ | |||
TrustManagerFactory tmf = | |||
TrustManagerFactory.getInstance("PKIX"); | |||
KeyStore ks = KeyStore.getInstance("JKS"); | |||
CertificateFactory cf = CertificateFactory.getInstance("X.509"); | |||
try { | |||
ks.load(null, null); | |||
File cacert = new File(cafile); | |||
if (!cacert.exists() || !cacert.canRead()) | |||
return; | |||
InputStream caStream = new FileInputStream(cafile); | |||
X509Certificate ca = (X509Certificate)cf.generateCertificate(caStream); | |||
ks.setCertificateEntry("CA", ca); | |||
PKIXBuilderParameters params = new PKIXBuilderParameters(ks, new X509CertSelector()); | |||
File crlcert = new File(crlfile); | |||
if (!crlcert.exists() || !crlcert.canRead()) { | |||
params.setRevocationEnabled(false); | |||
} else { | |||
InputStream crlStream = new FileInputStream(crlfile); | |||
Collection<? extends CRL> crls = cf.generateCRLs(crlStream); | |||
CertStoreParameters csp = new CollectionCertStoreParameters(crls); | |||
CertStore store = CertStore.getInstance("Collection", csp); | |||
params.addCertStore(store); | |||
params.setRevocationEnabled(true); | |||
} | |||
tmf.init(new CertPathTrustManagerParameters(params)); | |||
} catch (java.io.FileNotFoundException e) { | |||
vlog.error(e.toString()); | |||
} catch (java.io.IOException e) { | |||
vlog.error(e.toString()); | |||
} | |||
tm = (X509TrustManager)tmf.getTrustManagers()[0]; | |||
} | |||
public void checkClientTrusted(X509Certificate[] chain, String authType) | |||
throws CertificateException | |||
{ | |||
tm.checkClientTrusted(chain, authType); | |||
} | |||
public void checkServerTrusted(X509Certificate[] chain, String authType) | |||
throws CertificateException | |||
{ | |||
try { | |||
tm.checkServerTrusted(chain, authType); | |||
} catch (CertificateException e) { | |||
Object[] answer = {"Proceed", "Exit"}; | |||
int ret = JOptionPane.showOptionDialog(null, | |||
e.getCause().getLocalizedMessage()+"\n"+ | |||
"Continue connecting to this host?", | |||
"Confirm certificate exception?", | |||
JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, | |||
null, answer, answer[0]); | |||
if (ret == JOptionPane.NO_OPTION) | |||
System.exit(1); | |||
} catch (java.lang.Exception e) { | |||
throw new Exception(e.toString()); | |||
} | |||
} | |||
public X509Certificate[] getAcceptedIssuers () | |||
{ | |||
return tm.getAcceptedIssuers(); | |||
} | |||
} | |||
public final int getType() { return anon ? Security.secTypeTLSNone : Security.secTypeX509None; } | |||
public final String description() | |||
{ return anon ? "TLS Encryption without VncAuth" : "X509 Encryption without VncAuth"; } | |||
//protected void setParam(); | |||
//protected void checkSession(); | |||
protected CConnection cc; | |||
private boolean anon; | |||
private SSLSession session; | |||
private String cafile, crlfile; | |||
private InStream is; | |||
private OutStream os; | |||
private SSLSocket ssl; | |||
static LogWriter vlog = new LogWriter("CSecurityTLS"); | |||
} | |||
import javax.net.ssl.*; | |||
import java.security.*; | |||
import java.security.cert.*; | |||
import java.security.KeyStore; | |||
import java.io.File; | |||
import java.io.InputStream; | |||
import java.io.FileInputStream; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import javax.swing.JOptionPane; | |||
import com.tigervnc.vncviewer.UserPrefs; | |||
import com.tigervnc.rdr.*; | |||
public class CSecurityTLS extends CSecurity { | |||
public static StringParameter x509ca | |||
= new StringParameter("x509ca", | |||
"X509 CA certificate", ""); | |||
public static StringParameter x509crl | |||
= new StringParameter("x509crl", | |||
"X509 CRL file", ""); | |||
private void initGlobal() | |||
{ | |||
try { | |||
SSLSocketFactory sslfactory; | |||
SSLContext ctx = SSLContext.getInstance("TLS"); | |||
if (anon) { | |||
ctx.init(null, null, null); | |||
} else { | |||
TrustManager[] myTM = new TrustManager[] { | |||
new MyX509TrustManager() | |||
}; | |||
ctx.init (null, myTM, null); | |||
} | |||
sslfactory = ctx.getSocketFactory(); | |||
try { | |||
ssl = (SSLSocket)sslfactory.createSocket(cc.sock, | |||
cc.sock.getInetAddress().getHostName(), | |||
cc.sock.getPort(), true); | |||
} catch (java.io.IOException e) { | |||
throw new Exception(e.toString()); | |||
} | |||
if (anon) { | |||
String[] supported; | |||
ArrayList enabled = new ArrayList(); | |||
supported = ssl.getSupportedCipherSuites(); | |||
for (int i = 0; i < supported.length; i++) | |||
if (supported[i].matches("TLS_DH_anon.*")) | |||
enabled.add(supported[i]); | |||
ssl.setEnabledCipherSuites((String[])enabled.toArray(new String[0])); | |||
} else { | |||
ssl.setEnabledCipherSuites(ssl.getSupportedCipherSuites()); | |||
} | |||
ssl.setEnabledProtocols(new String[]{"SSLv3","TLSv1"}); | |||
ssl.addHandshakeCompletedListener(new MyHandshakeListener()); | |||
} | |||
catch (java.security.GeneralSecurityException e) | |||
{ | |||
vlog.error ("TLS handshake failed " + e.toString ()); | |||
return; | |||
} | |||
} | |||
public CSecurityTLS(boolean _anon) | |||
{ | |||
anon = _anon; | |||
setDefaults(); | |||
cafile = x509ca.getData(); | |||
crlfile = x509crl.getData(); | |||
} | |||
public static void setDefaults() | |||
{ | |||
String homeDir = null; | |||
if ((homeDir=UserPrefs.getHomeDir()) == null) { | |||
vlog.error("Could not obtain VNC home directory path"); | |||
return; | |||
} | |||
String vnchomedir = homeDir+UserPrefs.getFileSeperator()+".vnc"+ | |||
UserPrefs.getFileSeperator(); | |||
String caDefault = new String(vnchomedir+"x509_ca.pem"); | |||
String crlDefault = new String(vnchomedir+"x509_crl.pem"); | |||
if (new File(caDefault).exists()) | |||
x509ca.setDefaultStr(caDefault); | |||
if (new File(crlDefault).exists()) | |||
x509crl.setDefaultStr(crlDefault); | |||
} | |||
public boolean processMsg(CConnection cc) { | |||
is = cc.getInStream(); | |||
os = cc.getOutStream(); | |||
initGlobal(); | |||
if (!is.checkNoWait(1)) | |||
return false; | |||
if (is.readU8() == 0) { | |||
int result = is.readU32(); | |||
String reason; | |||
if (result == Security.secResultFailed || | |||
result == Security.secResultTooMany) | |||
reason = is.readString(); | |||
else | |||
reason = new String("Authentication failure (protocol error)"); | |||
throw new AuthFailureException(reason); | |||
} | |||
// SSLSocket.getSession blocks until the handshake is complete | |||
session = ssl.getSession(); | |||
if (!session.isValid()) | |||
throw new Exception("TLS Handshake failed!"); | |||
try { | |||
cc.setStreams(new JavaInStream(ssl.getInputStream()), | |||
new JavaOutStream(ssl.getOutputStream())); | |||
} catch (java.io.IOException e) { | |||
throw new Exception("Failed to set streams"); | |||
} | |||
return true; | |||
} | |||
class MyHandshakeListener implements HandshakeCompletedListener { | |||
public void handshakeCompleted(HandshakeCompletedEvent e) { | |||
vlog.info("Handshake succesful!"); | |||
vlog.info("Using cipher suite: " + e.getCipherSuite()); | |||
} | |||
} | |||
class MyX509TrustManager implements X509TrustManager | |||
{ | |||
X509TrustManager tm; | |||
MyX509TrustManager() throws java.security.GeneralSecurityException | |||
{ | |||
TrustManagerFactory tmf = | |||
TrustManagerFactory.getInstance("PKIX"); | |||
KeyStore ks = KeyStore.getInstance("JKS"); | |||
CertificateFactory cf = CertificateFactory.getInstance("X.509"); | |||
try { | |||
ks.load(null, null); | |||
File cacert = new File(cafile); | |||
if (!cacert.exists() || !cacert.canRead()) | |||
return; | |||
InputStream caStream = new FileInputStream(cafile); | |||
X509Certificate ca = (X509Certificate)cf.generateCertificate(caStream); | |||
ks.setCertificateEntry("CA", ca); | |||
PKIXBuilderParameters params = new PKIXBuilderParameters(ks, new X509CertSelector()); | |||
File crlcert = new File(crlfile); | |||
if (!crlcert.exists() || !crlcert.canRead()) { | |||
params.setRevocationEnabled(false); | |||
} else { | |||
InputStream crlStream = new FileInputStream(crlfile); | |||
Collection<? extends CRL> crls = cf.generateCRLs(crlStream); | |||
CertStoreParameters csp = new CollectionCertStoreParameters(crls); | |||
CertStore store = CertStore.getInstance("Collection", csp); | |||
params.addCertStore(store); | |||
params.setRevocationEnabled(true); | |||
} | |||
tmf.init(new CertPathTrustManagerParameters(params)); | |||
} catch (java.io.FileNotFoundException e) { | |||
vlog.error(e.toString()); | |||
} catch (java.io.IOException e) { | |||
vlog.error(e.toString()); | |||
} | |||
tm = (X509TrustManager)tmf.getTrustManagers()[0]; | |||
} | |||
public void checkClientTrusted(X509Certificate[] chain, String authType) | |||
throws CertificateException | |||
{ | |||
tm.checkClientTrusted(chain, authType); | |||
} | |||
public void checkServerTrusted(X509Certificate[] chain, String authType) | |||
throws CertificateException | |||
{ | |||
try { | |||
tm.checkServerTrusted(chain, authType); | |||
} catch (CertificateException e) { | |||
Object[] answer = {"Proceed", "Exit"}; | |||
int ret = JOptionPane.showOptionDialog(null, | |||
e.getCause().getLocalizedMessage()+"\n"+ | |||
"Continue connecting to this host?", | |||
"Confirm certificate exception?", | |||
JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, | |||
null, answer, answer[0]); | |||
if (ret == JOptionPane.NO_OPTION) | |||
System.exit(1); | |||
} catch (java.lang.Exception e) { | |||
throw new Exception(e.toString()); | |||
} | |||
} | |||
public X509Certificate[] getAcceptedIssuers () | |||
{ | |||
return tm.getAcceptedIssuers(); | |||
} | |||
} | |||
public final int getType() { return anon ? Security.secTypeTLSNone : Security.secTypeX509None; } | |||
public final String description() | |||
{ return anon ? "TLS Encryption without VncAuth" : "X509 Encryption without VncAuth"; } | |||
//protected void setParam(); | |||
//protected void checkSession(); | |||
protected CConnection cc; | |||
private boolean anon; | |||
private SSLSession session; | |||
private String cafile, crlfile; | |||
private InStream is; | |||
private OutStream os; | |||
private SSLSocket ssl; | |||
static LogWriter vlog = new LogWriter("CSecurityTLS"); | |||
} |
@@ -1,66 +1,66 @@ | |||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. | |||
* | |||
* This 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 software 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 software; if not, write to the Free Software | |||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||
* USA. | |||
*/ | |||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. | |||
* | |||
* This 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 software 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 software; if not, write to the Free Software | |||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||
* USA. | |||
*/ | |||
package com.tigervnc.rfb; | |||
import com.tigervnc.rdr.*; | |||
import com.tigervnc.rdr.*; | |||
import com.tigervnc.vncviewer.*; | |||
public class CSecurityVncAuth extends CSecurity { | |||
public CSecurityVncAuth() { } | |||
private static final int vncAuthChallengeSize = 16; | |||
public boolean processMsg(CConnection cc) | |||
{ | |||
InStream is = cc.getInStream(); | |||
OutStream os = cc.getOutStream(); | |||
// Read the challenge & obtain the user's password | |||
byte[] challenge = new byte[vncAuthChallengeSize]; | |||
is.readBytes(challenge, 0, vncAuthChallengeSize); | |||
StringBuffer passwd = new StringBuffer(); | |||
CConn.upg.getUserPasswd(null, passwd); | |||
// Calculate the correct response | |||
byte[] key = new byte[8]; | |||
int pwdLen = passwd.length(); | |||
public class CSecurityVncAuth extends CSecurity { | |||
public CSecurityVncAuth() { } | |||
private static final int vncAuthChallengeSize = 16; | |||
public boolean processMsg(CConnection cc) | |||
{ | |||
InStream is = cc.getInStream(); | |||
OutStream os = cc.getOutStream(); | |||
// Read the challenge & obtain the user's password | |||
byte[] challenge = new byte[vncAuthChallengeSize]; | |||
is.readBytes(challenge, 0, vncAuthChallengeSize); | |||
StringBuffer passwd = new StringBuffer(); | |||
CConn.upg.getUserPasswd(null, passwd); | |||
// Calculate the correct response | |||
byte[] key = new byte[8]; | |||
int pwdLen = passwd.length(); | |||
byte[] utf8str = new byte[pwdLen]; | |||
try { | |||
utf8str = passwd.toString().getBytes("UTF8"); | |||
} catch(java.io.UnsupportedEncodingException e) { | |||
e.printStackTrace(); | |||
} | |||
for (int i=0; i<8; i++) | |||
key[i] = i<pwdLen ? utf8str[i] : 0; | |||
DesCipher des = new DesCipher(key); | |||
for (int j = 0; j < vncAuthChallengeSize; j += 8) | |||
des.encrypt(challenge,j,challenge,j); | |||
// Return the response to the server | |||
os.writeBytes(challenge, 0, vncAuthChallengeSize); | |||
os.flush(); | |||
return true; | |||
} | |||
public int getType() { return Security.secTypeVncAuth; } | |||
public String description() { return "No Encryption"; } | |||
static LogWriter vlog = new LogWriter("VncAuth"); | |||
} | |||
for (int i=0; i<8; i++) | |||
key[i] = i<pwdLen ? utf8str[i] : 0; | |||
DesCipher des = new DesCipher(key); | |||
for (int j = 0; j < vncAuthChallengeSize; j += 8) | |||
des.encrypt(challenge,j,challenge,j); | |||
// Return the response to the server | |||
os.writeBytes(challenge, 0, vncAuthChallengeSize); | |||
os.flush(); | |||
return true; | |||
} | |||
public int getType() { return Security.secTypeVncAuth; } | |||
public String description() { return "No Encryption"; } | |||
static LogWriter vlog = new LogWriter("VncAuth"); | |||
} |
@@ -1,46 +1,46 @@ | |||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. | |||
* | |||
* This 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 software 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 software; if not, write to the Free Software | |||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||
* USA. | |||
*/ | |||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. | |||
* | |||
* This 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 software 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 software; if not, write to the Free Software | |||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||
* USA. | |||
*/ | |||
package com.tigervnc.rfb; | |||
public class StringParameter extends VoidParameter { | |||
public StringParameter(String name_, String desc_, String v) { | |||
super(name_, desc_); | |||
value = v; | |||
defValue = v; | |||
} | |||
public boolean setParam(String v) { | |||
value = v; | |||
return value != null; | |||
} | |||
public boolean setDefaultStr(String v) { | |||
value = defValue = v; | |||
return defValue != null; | |||
} | |||
public String getDefaultStr() { return defValue; } | |||
public String getValueStr() { return value; } | |||
public String getValue() { return value; } | |||
public String getData() { return value; } | |||
protected String value; | |||
protected String defValue; | |||
} | |||
public class StringParameter extends VoidParameter { | |||
public StringParameter(String name_, String desc_, String v) { | |||
super(name_, desc_); | |||
value = v; | |||
defValue = v; | |||
} | |||
public boolean setParam(String v) { | |||
value = v; | |||
return value != null; | |||
} | |||
public boolean setDefaultStr(String v) { | |||
value = defValue = v; | |||
return defValue != null; | |||
} | |||
public String getDefaultStr() { return defValue; } | |||
public String getValueStr() { return value; } | |||
public String getValue() { return value; } | |||
public String getData() { return value; } | |||
protected String value; | |||
protected String defValue; | |||
} |
@@ -1,485 +1,485 @@ | |||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. | |||
* | |||
* This 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 software 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 software; if not, write to the Free Software | |||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||
* USA. | |||
*/ | |||
// | |||
// DesktopWindow is an AWT Canvas representing a VNC desktop. | |||
// | |||
// Methods on DesktopWindow are called from both the GUI thread and the thread | |||
// which processes incoming RFB messages ("the RFB thread"). This means we | |||
// need to be careful with synchronization here. | |||
// | |||
package com.tigervnc.vncviewer; | |||
import java.awt.*; | |||
import java.awt.event.*; | |||
import java.awt.image.*; | |||
import java.awt.datatransfer.DataFlavor; | |||
import java.awt.datatransfer.Transferable; | |||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. | |||
* | |||
* This 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 software 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 software; if not, write to the Free Software | |||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||
* USA. | |||
*/ | |||
// | |||
// DesktopWindow is an AWT Canvas representing a VNC desktop. | |||
// | |||
// Methods on DesktopWindow are called from both the GUI thread and the thread | |||
// which processes incoming RFB messages ("the RFB thread"). This means we | |||
// need to be careful with synchronization here. | |||
// | |||
package com.tigervnc.vncviewer; | |||
import java.awt.*; | |||
import java.awt.event.*; | |||
import java.awt.image.*; | |||
import java.awt.datatransfer.DataFlavor; | |||
import java.awt.datatransfer.Transferable; | |||
import java.awt.datatransfer.Clipboard; | |||
import javax.swing.*; | |||
import com.tigervnc.rfb.*; | |||
import com.tigervnc.rfb.Cursor; | |||
import com.tigervnc.rfb.Cursor; | |||
import com.tigervnc.rfb.Exception; | |||
import com.tigervnc.rfb.Point; | |||
class DesktopWindow extends JPanel implements | |||
Runnable, | |||
MouseListener, | |||
MouseMotionListener, | |||
MouseWheelListener, | |||
KeyListener | |||
{ | |||
//////////////////////////////////////////////////////////////////// | |||
// The following methods are all called from the RFB thread | |||
public DesktopWindow(int width, int height, PixelFormat serverPF, CConn cc_) { | |||
cc = cc_; | |||
setSize(width, height); | |||
im = new PixelBufferImage(width, height, cc, this); | |||
cursor = new Cursor(); | |||
cursorBacking = new ManagedPixelBuffer(); | |||
addMouseListener(this); | |||
addMouseWheelListener(this); | |||
addMouseMotionListener(this); | |||
addKeyListener(this); | |||
addFocusListener(new FocusAdapter() { | |||
public void focusGained(FocusEvent e) { | |||
checkClipboard(); | |||
} | |||
}); | |||
setFocusTraversalKeysEnabled(false); | |||
setFocusable(true); | |||
setDoubleBuffered(true); | |||
} | |||
public int width() { | |||
return getWidth(); | |||
} | |||
public int height() { | |||
return getHeight(); | |||
} | |||
// initGraphics() is needed because for some reason you can't call | |||
// getGraphics() on a newly-created awt Component. It is called when the | |||
// DesktopWindow has actually been made visible so that getGraphics() ought | |||
// to work. | |||
public void initGraphics() { | |||
cc.viewport.g = cc.viewport.getGraphics(); | |||
graphics = getComponentGraphics(cc.viewport.g); | |||
prepareImage(im.image, -1, -1, this); | |||
} | |||
final public PixelFormat getPF() { return im.getPF(); } | |||
synchronized public void setPF(PixelFormat pf) { | |||
im.setPF(pf); | |||
} | |||
class DesktopWindow extends JPanel implements | |||
Runnable, | |||
MouseListener, | |||
MouseMotionListener, | |||
MouseWheelListener, | |||
KeyListener | |||
{ | |||
//////////////////////////////////////////////////////////////////// | |||
// The following methods are all called from the RFB thread | |||
public DesktopWindow(int width, int height, PixelFormat serverPF, CConn cc_) { | |||
cc = cc_; | |||
setSize(width, height); | |||
im = new PixelBufferImage(width, height, cc, this); | |||
cursor = new Cursor(); | |||
cursorBacking = new ManagedPixelBuffer(); | |||
addMouseListener(this); | |||
addMouseWheelListener(this); | |||
addMouseMotionListener(this); | |||
addKeyListener(this); | |||
addFocusListener(new FocusAdapter() { | |||
public void focusGained(FocusEvent e) { | |||
checkClipboard(); | |||
} | |||
}); | |||
setFocusTraversalKeysEnabled(false); | |||
setFocusable(true); | |||
setDoubleBuffered(true); | |||
} | |||
public int width() { | |||
return getWidth(); | |||
} | |||
public int height() { | |||
return getHeight(); | |||
} | |||
// initGraphics() is needed because for some reason you can't call | |||
// getGraphics() on a newly-created awt Component. It is called when the | |||
// DesktopWindow has actually been made visible so that getGraphics() ought | |||
// to work. | |||
public void initGraphics() { | |||
cc.viewport.g = cc.viewport.getGraphics(); | |||
graphics = getComponentGraphics(cc.viewport.g); | |||
prepareImage(im.image, -1, -1, this); | |||
} | |||
final public PixelFormat getPF() { return im.getPF(); } | |||
synchronized public void setPF(PixelFormat pf) { | |||
im.setPF(pf); | |||
} | |||
public void setViewport(ViewportFrame viewport) | |||
{ | |||
viewport.setChild(this); | |||
} | |||
// Methods called from the RFB thread - these need to be synchronized | |||
// wherever they access data shared with the GUI thread. | |||
public void setCursor(int w, int h, Point hotspot, | |||
int[] data, byte[] mask) { | |||
// strictly we should use a mutex around this test since useLocalCursor | |||
// might be being altered by the GUI thread. However it's only a single | |||
// boolean and it doesn't matter if we get the wrong value anyway. | |||
synchronized(this) { | |||
if (!cc.viewer.useLocalCursor.getValue()) return; | |||
hideLocalCursor(); | |||
cursor.hotspot = hotspot; | |||
Dimension bsc = tk.getBestCursorSize(w, h); | |||
cursor.setSize(((int)bsc.getWidth() > w ? (int)bsc.getWidth() : w), | |||
((int)bsc.getHeight() > h ? (int)bsc.getHeight() : h)); | |||
cursor.setPF(getPF()); | |||
cursorBacking.setSize(cursor.width(), cursor.height()); | |||
cursorBacking.setPF(getPF()); | |||
cursor.data = new int[cursor.width() * cursor.height()]; | |||
cursor.mask = new byte[cursor.maskLen()]; | |||
// set the masked pixels of the cursor transparent by using an extra bit in | |||
// the colormap. We'll OR this into the data based on the values in the mask. | |||
if (cursor.getPF().bpp == 8) { | |||
cursor.cm = new DirectColorModel(9, 7, (7 << 3), (3 << 6), (1 << 8)); | |||
} | |||
int maskBytesPerRow = (w + 7) / 8; | |||
for (int y = 0; y < h; y++) { | |||
for (int x = 0; x < w; x++) { | |||
int byte_ = y * maskBytesPerRow + x / 8; | |||
int bit = 7 - x % 8; | |||
if ((mask[byte_] & (1 << bit)) > 0) { | |||
cursor.data[y * cursor.width() + x] = (cursor.getPF().bpp == 8) ? | |||
data[y * w + x] | (1 << 8) : data[y * w + x]; | |||
} | |||
} | |||
System.arraycopy(mask, y * maskBytesPerRow, cursor.mask, | |||
y * ((cursor.width() + 7) / 8), maskBytesPerRow); | |||
} | |||
MemoryImageSource bitmap = | |||
new MemoryImageSource(cursor.width(), cursor.height(), cursor.cm, | |||
cursor.data, 0, cursor.width()); | |||
softCursor = | |||
tk.createCustomCursor(tk.createImage(bitmap), new java.awt.Point(hotspot.x,hotspot.y), "Cursor"); | |||
} | |||
if (softCursor != null) { | |||
setCursor(softCursor); | |||
cursorAvailable = true; | |||
return; | |||
} | |||
if (!cursorAvailable) { | |||
cursorAvailable = true; | |||
} | |||
showLocalCursor(); | |||
return; | |||
} | |||
// setColourMapEntries() changes some of the entries in the colourmap. | |||
// Unfortunately these messages are often sent one at a time, so we delay the | |||
// settings taking effect unless the whole colourmap has changed. This is | |||
// because getting java to recalculate its internal translation table and | |||
// redraw the screen is expensive. | |||
synchronized public void setColourMapEntries(int firstColour, int nColours, | |||
int[] rgbs) { | |||
im.setColourMapEntries(firstColour, nColours, rgbs); | |||
if (nColours <= 256) { | |||
im.updateColourMap(); | |||
im.put(0, 0, im.width(), im.height(), graphics); | |||
} else { | |||
if (setColourMapEntriesTimerThread == null) { | |||
setColourMapEntriesTimerThread = new Thread(this); | |||
setColourMapEntriesTimerThread.start(); | |||
} | |||
} | |||
} | |||
// Update the actual window with the changed parts of the framebuffer. | |||
public void framebufferUpdateEnd() | |||
{ | |||
drawInvalidRect(); | |||
} | |||
// resize() is called when the desktop has changed size | |||
synchronized public void resize() { | |||
int w = cc.cp.width; | |||
int h = cc.cp.height; | |||
hideLocalCursor(); | |||
setSize(w, h); | |||
im.resize(w, h); | |||
} | |||
final void drawInvalidRect() { | |||
if (!invalidRect) return; | |||
int x = invalidLeft; | |||
int w = invalidRight - x; | |||
int y = invalidTop; | |||
int h = invalidBottom - y; | |||
invalidRect = false; | |||
synchronized (this) { | |||
im.put(x, y, w, h, graphics); | |||
} | |||
} | |||
final void invalidate(int x, int y, int w, int h) { | |||
if (invalidRect) { | |||
if (x < invalidLeft) invalidLeft = x; | |||
if (x + w > invalidRight) invalidRight = x + w; | |||
if (y < invalidTop) invalidTop = y; | |||
if (y + h > invalidBottom) invalidBottom = y + h; | |||
} else { | |||
invalidLeft = x; | |||
invalidRight = x + w; | |||
invalidTop = y; | |||
invalidBottom = y + h; | |||
invalidRect = true; | |||
} | |||
if ((invalidRight - invalidLeft) * (invalidBottom - invalidTop) > 100000) | |||
drawInvalidRect(); | |||
} | |||
public void beginRect(int x, int y, int w, int h, int encoding) { | |||
invalidRect = false; | |||
} | |||
public void endRect(int x, int y, int w, int h, int encoding) { | |||
drawInvalidRect(); | |||
} | |||
synchronized final public void fillRect(int x, int y, int w, int h, int pix) | |||
{ | |||
if (overlapsCursor(x, y, w, h)) hideLocalCursor(); | |||
im.fillRect(x, y, w, h, pix); | |||
invalidate(x, y, w, h); | |||
if (softCursor == null) | |||
showLocalCursor(); | |||
} | |||
synchronized final public void imageRect(int x, int y, int w, int h, | |||
int[] pix) { | |||
if (overlapsCursor(x, y, w, h)) hideLocalCursor(); | |||
im.imageRect(x, y, w, h, pix); | |||
invalidate(x, y, w, h); | |||
if (softCursor == null) | |||
showLocalCursor(); | |||
} | |||
synchronized final public void copyRect(int x, int y, int w, int h, | |||
int srcX, int srcY) { | |||
if (overlapsCursor(x, y, w, h) || overlapsCursor(srcX, srcY, w, h)) | |||
hideLocalCursor(); | |||
im.copyRect(x, y, w, h, srcX, srcY); | |||
if (!cc.viewer.fastCopyRect.getValue()) { | |||
invalidate(x, y, w, h); | |||
} | |||
} | |||
// mutex MUST be held when overlapsCursor() is called | |||
final boolean overlapsCursor(int x, int y, int w, int h) { | |||
return (x < cursorBackingX + cursorBacking.width() && | |||
y < cursorBackingY + cursorBacking.height() && | |||
x+w > cursorBackingX && y+h > cursorBackingY); | |||
} | |||
//////////////////////////////////////////////////////////////////// | |||
// The following methods are all called from the GUI thread | |||
synchronized void resetLocalCursor() { | |||
hideLocalCursor(); | |||
cursorAvailable = false; | |||
} | |||
synchronized public Dimension getPreferredSize() { | |||
return new Dimension(im.width(), im.height()); | |||
} | |||
synchronized public Dimension getMinimumSize() { | |||
return new Dimension(im.width(), im.height()); | |||
} | |||
public void update(Graphics g) { | |||
//repaint(); | |||
} | |||
synchronized public void paintComponent(Graphics g) { | |||
Graphics2D g2 = (Graphics2D) g; | |||
g2.drawImage(im.image, 0, 0, this); | |||
} | |||
String oldContents = ""; | |||
synchronized public void checkClipboard() { | |||
// Methods called from the RFB thread - these need to be synchronized | |||
// wherever they access data shared with the GUI thread. | |||
public void setCursor(int w, int h, Point hotspot, | |||
int[] data, byte[] mask) { | |||
// strictly we should use a mutex around this test since useLocalCursor | |||
// might be being altered by the GUI thread. However it's only a single | |||
// boolean and it doesn't matter if we get the wrong value anyway. | |||
synchronized(this) { | |||
if (!cc.viewer.useLocalCursor.getValue()) return; | |||
hideLocalCursor(); | |||
cursor.hotspot = hotspot; | |||
Dimension bsc = tk.getBestCursorSize(w, h); | |||
cursor.setSize(((int)bsc.getWidth() > w ? (int)bsc.getWidth() : w), | |||
((int)bsc.getHeight() > h ? (int)bsc.getHeight() : h)); | |||
cursor.setPF(getPF()); | |||
cursorBacking.setSize(cursor.width(), cursor.height()); | |||
cursorBacking.setPF(getPF()); | |||
cursor.data = new int[cursor.width() * cursor.height()]; | |||
cursor.mask = new byte[cursor.maskLen()]; | |||
// set the masked pixels of the cursor transparent by using an extra bit in | |||
// the colormap. We'll OR this into the data based on the values in the mask. | |||
if (cursor.getPF().bpp == 8) { | |||
cursor.cm = new DirectColorModel(9, 7, (7 << 3), (3 << 6), (1 << 8)); | |||
} | |||
int maskBytesPerRow = (w + 7) / 8; | |||
for (int y = 0; y < h; y++) { | |||
for (int x = 0; x < w; x++) { | |||
int byte_ = y * maskBytesPerRow + x / 8; | |||
int bit = 7 - x % 8; | |||
if ((mask[byte_] & (1 << bit)) > 0) { | |||
cursor.data[y * cursor.width() + x] = (cursor.getPF().bpp == 8) ? | |||
data[y * w + x] | (1 << 8) : data[y * w + x]; | |||
} | |||
} | |||
System.arraycopy(mask, y * maskBytesPerRow, cursor.mask, | |||
y * ((cursor.width() + 7) / 8), maskBytesPerRow); | |||
} | |||
MemoryImageSource bitmap = | |||
new MemoryImageSource(cursor.width(), cursor.height(), cursor.cm, | |||
cursor.data, 0, cursor.width()); | |||
softCursor = | |||
tk.createCustomCursor(tk.createImage(bitmap), new java.awt.Point(hotspot.x,hotspot.y), "Cursor"); | |||
} | |||
if (softCursor != null) { | |||
setCursor(softCursor); | |||
cursorAvailable = true; | |||
return; | |||
} | |||
if (!cursorAvailable) { | |||
cursorAvailable = true; | |||
} | |||
showLocalCursor(); | |||
return; | |||
} | |||
// setColourMapEntries() changes some of the entries in the colourmap. | |||
// Unfortunately these messages are often sent one at a time, so we delay the | |||
// settings taking effect unless the whole colourmap has changed. This is | |||
// because getting java to recalculate its internal translation table and | |||
// redraw the screen is expensive. | |||
synchronized public void setColourMapEntries(int firstColour, int nColours, | |||
int[] rgbs) { | |||
im.setColourMapEntries(firstColour, nColours, rgbs); | |||
if (nColours <= 256) { | |||
im.updateColourMap(); | |||
im.put(0, 0, im.width(), im.height(), graphics); | |||
} else { | |||
if (setColourMapEntriesTimerThread == null) { | |||
setColourMapEntriesTimerThread = new Thread(this); | |||
setColourMapEntriesTimerThread.start(); | |||
} | |||
} | |||
} | |||
// Update the actual window with the changed parts of the framebuffer. | |||
public void framebufferUpdateEnd() | |||
{ | |||
drawInvalidRect(); | |||
} | |||
// resize() is called when the desktop has changed size | |||
synchronized public void resize() { | |||
int w = cc.cp.width; | |||
int h = cc.cp.height; | |||
hideLocalCursor(); | |||
setSize(w, h); | |||
im.resize(w, h); | |||
} | |||
final void drawInvalidRect() { | |||
if (!invalidRect) return; | |||
int x = invalidLeft; | |||
int w = invalidRight - x; | |||
int y = invalidTop; | |||
int h = invalidBottom - y; | |||
invalidRect = false; | |||
synchronized (this) { | |||
im.put(x, y, w, h, graphics); | |||
} | |||
} | |||
final void invalidate(int x, int y, int w, int h) { | |||
if (invalidRect) { | |||
if (x < invalidLeft) invalidLeft = x; | |||
if (x + w > invalidRight) invalidRight = x + w; | |||
if (y < invalidTop) invalidTop = y; | |||
if (y + h > invalidBottom) invalidBottom = y + h; | |||
} else { | |||
invalidLeft = x; | |||
invalidRight = x + w; | |||
invalidTop = y; | |||
invalidBottom = y + h; | |||
invalidRect = true; | |||
} | |||
if ((invalidRight - invalidLeft) * (invalidBottom - invalidTop) > 100000) | |||
drawInvalidRect(); | |||
} | |||
public void beginRect(int x, int y, int w, int h, int encoding) { | |||
invalidRect = false; | |||
} | |||
public void endRect(int x, int y, int w, int h, int encoding) { | |||
drawInvalidRect(); | |||
} | |||
synchronized final public void fillRect(int x, int y, int w, int h, int pix) | |||
{ | |||
if (overlapsCursor(x, y, w, h)) hideLocalCursor(); | |||
im.fillRect(x, y, w, h, pix); | |||
invalidate(x, y, w, h); | |||
if (softCursor == null) | |||
showLocalCursor(); | |||
} | |||
synchronized final public void imageRect(int x, int y, int w, int h, | |||
int[] pix) { | |||
if (overlapsCursor(x, y, w, h)) hideLocalCursor(); | |||
im.imageRect(x, y, w, h, pix); | |||
invalidate(x, y, w, h); | |||
if (softCursor == null) | |||
showLocalCursor(); | |||
} | |||
synchronized final public void copyRect(int x, int y, int w, int h, | |||
int srcX, int srcY) { | |||
if (overlapsCursor(x, y, w, h) || overlapsCursor(srcX, srcY, w, h)) | |||
hideLocalCursor(); | |||
im.copyRect(x, y, w, h, srcX, srcY); | |||
if (!cc.viewer.fastCopyRect.getValue()) { | |||
invalidate(x, y, w, h); | |||
} | |||
} | |||
// mutex MUST be held when overlapsCursor() is called | |||
final boolean overlapsCursor(int x, int y, int w, int h) { | |||
return (x < cursorBackingX + cursorBacking.width() && | |||
y < cursorBackingY + cursorBacking.height() && | |||
x+w > cursorBackingX && y+h > cursorBackingY); | |||
} | |||
//////////////////////////////////////////////////////////////////// | |||
// The following methods are all called from the GUI thread | |||
synchronized void resetLocalCursor() { | |||
hideLocalCursor(); | |||
cursorAvailable = false; | |||
} | |||
synchronized public Dimension getPreferredSize() { | |||
return new Dimension(im.width(), im.height()); | |||
} | |||
synchronized public Dimension getMinimumSize() { | |||
return new Dimension(im.width(), im.height()); | |||
} | |||
public void update(Graphics g) { | |||
//repaint(); | |||
} | |||
synchronized public void paintComponent(Graphics g) { | |||
Graphics2D g2 = (Graphics2D) g; | |||
g2.drawImage(im.image, 0, 0, this); | |||
} | |||
String oldContents = ""; | |||
synchronized public void checkClipboard() { | |||
Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); | |||
if (cb != null && cc.viewer.sendClipboard.getValue()) { | |||
Transferable t = cb.getContents(null); | |||
if ((t != null) && t.isDataFlavorSupported(DataFlavor.stringFlavor)) { | |||
try { | |||
String newContents = (String)t.getTransferData(DataFlavor.stringFlavor); | |||
if (newContents != null && !newContents.equals(oldContents)) { | |||
cc.writeClientCutText(newContents, newContents.length()); | |||
oldContents = newContents; | |||
cc.clipboardDialog.setContents(newContents); | |||
} | |||
} catch (java.lang.Exception e) { | |||
System.out.println("Exception getting clipboard data: " + e.getMessage()); | |||
} | |||
} | |||
} | |||
} | |||
/** Mouse-Motion callback function */ | |||
private void mouseMotionCB(MouseEvent e) { | |||
if (!cc.viewer.viewOnly.getValue()) | |||
cc.writePointerEvent(e); | |||
// - If local cursor rendering is enabled then use it | |||
synchronized(this) { | |||
if (cursorAvailable) { | |||
// - Render the cursor! | |||
if (e.getX() != cursorPosX || e.getY() != cursorPosY) { | |||
hideLocalCursor(); | |||
if (e.getX() >= 0 && e.getX() < im.width() && | |||
e.getY() >= 0 && e.getY() < im.height()) { | |||
cursorPosX = e.getX(); | |||
cursorPosY = e.getY(); | |||
if (softCursor == null) | |||
showLocalCursor(); | |||
} | |||
} | |||
} | |||
} | |||
lastX = e.getX(); | |||
lastY = e.getY(); | |||
} | |||
public void mouseDragged(MouseEvent e) { mouseMotionCB(e);} | |||
public void mouseMoved(MouseEvent e) { mouseMotionCB(e);} | |||
/** Mouse callback function */ | |||
private void mouseCB(MouseEvent e) { | |||
if (!cc.viewer.viewOnly.getValue()) | |||
cc.writePointerEvent(e); | |||
lastX = e.getX(); | |||
lastY = e.getY(); | |||
} | |||
public void mouseReleased(MouseEvent e){ mouseCB(e);} | |||
public void mousePressed(MouseEvent e) { mouseCB(e);} | |||
public void mouseClicked(MouseEvent e){} | |||
public void mouseEntered(MouseEvent e){} | |||
public void mouseExited(MouseEvent e){} | |||
/** MouseWheel callback function */ | |||
private void mouseWheelCB(MouseWheelEvent e) { | |||
if (!cc.viewer.viewOnly.getValue()) | |||
cc.writeWheelEvent(e); | |||
} | |||
public void mouseWheelMoved(MouseWheelEvent e){ | |||
mouseWheelCB(e); | |||
} | |||
/** Handle the key-typed event. */ | |||
public void keyTyped(KeyEvent e) {} | |||
/** Handle the key-released event. */ | |||
public void keyReleased(KeyEvent e) {} | |||
/** Handle the key-pressed event. */ | |||
public void keyPressed(KeyEvent e) { | |||
if (e.getKeyCode() == | |||
(KeyEvent.VK_F1+cc.menuKey-Keysyms.F1)) { | |||
cc.showMenu(lastX, lastY); | |||
return; | |||
} | |||
if (!cc.viewer.viewOnly.getValue()) | |||
cc.writeKeyEvent(e); | |||
} | |||
//////////////////////////////////////////////////////////////////// | |||
// The following methods are called from both RFB and GUI threads | |||
// Note that mutex MUST be held when hideLocalCursor() and showLocalCursor() | |||
// are called. | |||
private void hideLocalCursor() { | |||
// - Blit the cursor backing store over the cursor | |||
if (cursorVisible) { | |||
cursorVisible = false; | |||
im.imageRect(cursorBackingX, cursorBackingY, cursorBacking.width(), | |||
cursorBacking.height(), cursorBacking.data); | |||
im.put(cursorBackingX, cursorBackingY, cursorBacking.width(), | |||
cursorBacking.height(), graphics); | |||
} | |||
} | |||
private void showLocalCursor() { | |||
if (cursorAvailable && !cursorVisible) { | |||
if (!im.getPF().equal(cursor.getPF()) || | |||
cursor.width() == 0 || cursor.height() == 0) { | |||
vlog.debug("attempting to render invalid local cursor"); | |||
cursorAvailable = false; | |||
return; | |||
} | |||
cursorVisible = true; | |||
if (softCursor != null) return; | |||
int cursorLeft = (int)cursor.hotspot.x; | |||
int cursorTop = (int)cursor.hotspot.y; | |||
int cursorRight = cursorLeft + cursor.width(); | |||
int cursorBottom = cursorTop + cursor.height(); | |||
int x = (cursorLeft >= 0 ? cursorLeft : 0); | |||
int y = (cursorTop >= 0 ? cursorTop : 0); | |||
int w = ((cursorRight < im.width() ? cursorRight : im.width()) - x); | |||
int h = ((cursorBottom < im.height() ? cursorBottom : im.height()) - y); | |||
cursorBackingX = x; | |||
cursorBackingY = y; | |||
cursorBacking.setSize(w, h); | |||
for (int j = 0; j < h; j++) | |||
System.arraycopy(im.data, (y+j) * im.width() + x, | |||
cursorBacking.data, j*w, w); | |||
im.maskRect(cursorLeft, cursorTop, cursor.width(), cursor.height(), | |||
cursor.data, cursor.mask); | |||
im.put(x, y, w, h, graphics); | |||
} | |||
} | |||
// run() is executed by the setColourMapEntriesTimerThread - it sleeps for | |||
// 100ms before actually updating the colourmap. | |||
public void run() { | |||
try { | |||
Thread.sleep(100); | |||
} catch (InterruptedException e) {} | |||
synchronized (this) { | |||
im.updateColourMap(); | |||
im.put(0, 0, im.width(), im.height(), graphics); | |||
setColourMapEntriesTimerThread = null; | |||
} | |||
} | |||
// access to cc by different threads is specified in CConn | |||
CConn cc; | |||
// access to the following must be synchronized: | |||
PixelBufferImage im; | |||
Graphics graphics; | |||
Thread setColourMapEntriesTimerThread; | |||
Cursor cursor; | |||
boolean cursorVisible; // Is cursor currently rendered? | |||
boolean cursorAvailable; // Is cursor available for rendering? | |||
int cursorPosX, cursorPosY; | |||
ManagedPixelBuffer cursorBacking; | |||
int cursorBackingX, cursorBackingY; | |||
java.awt.Cursor softCursor; | |||
static Toolkit tk = Toolkit.getDefaultToolkit(); | |||
// the following are only ever accessed by the RFB thread: | |||
boolean invalidRect; | |||
int invalidLeft, invalidRight, invalidTop, invalidBottom; | |||
// the following are only ever accessed by the GUI thread: | |||
int lastX, lastY; | |||
static LogWriter vlog = new LogWriter("DesktopWindow"); | |||
} | |||
if (cb != null && cc.viewer.sendClipboard.getValue()) { | |||
Transferable t = cb.getContents(null); | |||
if ((t != null) && t.isDataFlavorSupported(DataFlavor.stringFlavor)) { | |||
try { | |||
String newContents = (String)t.getTransferData(DataFlavor.stringFlavor); | |||
if (newContents != null && !newContents.equals(oldContents)) { | |||
cc.writeClientCutText(newContents, newContents.length()); | |||
oldContents = newContents; | |||
cc.clipboardDialog.setContents(newContents); | |||
} | |||
} catch (java.lang.Exception e) { | |||
System.out.println("Exception getting clipboard data: " + e.getMessage()); | |||
} | |||
} | |||
} | |||
} | |||
/** Mouse-Motion callback function */ | |||
private void mouseMotionCB(MouseEvent e) { | |||
if (!cc.viewer.viewOnly.getValue()) | |||
cc.writePointerEvent(e); | |||
// - If local cursor rendering is enabled then use it | |||
synchronized(this) { | |||
if (cursorAvailable) { | |||
// - Render the cursor! | |||
if (e.getX() != cursorPosX || e.getY() != cursorPosY) { | |||
hideLocalCursor(); | |||
if (e.getX() >= 0 && e.getX() < im.width() && | |||
e.getY() >= 0 && e.getY() < im.height()) { | |||
cursorPosX = e.getX(); | |||
cursorPosY = e.getY(); | |||
if (softCursor == null) | |||
showLocalCursor(); | |||
} | |||
} | |||
} | |||
} | |||
lastX = e.getX(); | |||
lastY = e.getY(); | |||
} | |||
public void mouseDragged(MouseEvent e) { mouseMotionCB(e);} | |||
public void mouseMoved(MouseEvent e) { mouseMotionCB(e);} | |||
/** Mouse callback function */ | |||
private void mouseCB(MouseEvent e) { | |||
if (!cc.viewer.viewOnly.getValue()) | |||
cc.writePointerEvent(e); | |||
lastX = e.getX(); | |||
lastY = e.getY(); | |||
} | |||
public void mouseReleased(MouseEvent e){ mouseCB(e);} | |||
public void mousePressed(MouseEvent e) { mouseCB(e);} | |||
public void mouseClicked(MouseEvent e){} | |||
public void mouseEntered(MouseEvent e){} | |||
public void mouseExited(MouseEvent e){} | |||
/** MouseWheel callback function */ | |||
private void mouseWheelCB(MouseWheelEvent e) { | |||
if (!cc.viewer.viewOnly.getValue()) | |||
cc.writeWheelEvent(e); | |||
} | |||
public void mouseWheelMoved(MouseWheelEvent e){ | |||
mouseWheelCB(e); | |||
} | |||
/** Handle the key-typed event. */ | |||
public void keyTyped(KeyEvent e) {} | |||
/** Handle the key-released event. */ | |||
public void keyReleased(KeyEvent e) {} | |||
/** Handle the key-pressed event. */ | |||
public void keyPressed(KeyEvent e) { | |||
if (e.getKeyCode() == | |||
(KeyEvent.VK_F1+cc.menuKey-Keysyms.F1)) { | |||
cc.showMenu(lastX, lastY); | |||
return; | |||
} | |||
if (!cc.viewer.viewOnly.getValue()) | |||
cc.writeKeyEvent(e); | |||
} | |||
//////////////////////////////////////////////////////////////////// | |||
// The following methods are called from both RFB and GUI threads | |||
// Note that mutex MUST be held when hideLocalCursor() and showLocalCursor() | |||
// are called. | |||
private void hideLocalCursor() { | |||
// - Blit the cursor backing store over the cursor | |||
if (cursorVisible) { | |||
cursorVisible = false; | |||
im.imageRect(cursorBackingX, cursorBackingY, cursorBacking.width(), | |||
cursorBacking.height(), cursorBacking.data); | |||
im.put(cursorBackingX, cursorBackingY, cursorBacking.width(), | |||
cursorBacking.height(), graphics); | |||
} | |||
} | |||
private void showLocalCursor() { | |||
if (cursorAvailable && !cursorVisible) { | |||
if (!im.getPF().equal(cursor.getPF()) || | |||
cursor.width() == 0 || cursor.height() == 0) { | |||
vlog.debug("attempting to render invalid local cursor"); | |||
cursorAvailable = false; | |||
return; | |||
} | |||
cursorVisible = true; | |||
if (softCursor != null) return; | |||
int cursorLeft = (int)cursor.hotspot.x; | |||
int cursorTop = (int)cursor.hotspot.y; | |||
int cursorRight = cursorLeft + cursor.width(); | |||
int cursorBottom = cursorTop + cursor.height(); | |||
int x = (cursorLeft >= 0 ? cursorLeft : 0); | |||
int y = (cursorTop >= 0 ? cursorTop : 0); | |||
int w = ((cursorRight < im.width() ? cursorRight : im.width()) - x); | |||
int h = ((cursorBottom < im.height() ? cursorBottom : im.height()) - y); | |||
cursorBackingX = x; | |||
cursorBackingY = y; | |||
cursorBacking.setSize(w, h); | |||
for (int j = 0; j < h; j++) | |||
System.arraycopy(im.data, (y+j) * im.width() + x, | |||
cursorBacking.data, j*w, w); | |||
im.maskRect(cursorLeft, cursorTop, cursor.width(), cursor.height(), | |||
cursor.data, cursor.mask); | |||
im.put(x, y, w, h, graphics); | |||
} | |||
} | |||
// run() is executed by the setColourMapEntriesTimerThread - it sleeps for | |||
// 100ms before actually updating the colourmap. | |||
public void run() { | |||
try { | |||
Thread.sleep(100); | |||
} catch (InterruptedException e) {} | |||
synchronized (this) { | |||
im.updateColourMap(); | |||
im.put(0, 0, im.width(), im.height(), graphics); | |||
setColourMapEntriesTimerThread = null; | |||
} | |||
} | |||
// access to cc by different threads is specified in CConn | |||
CConn cc; | |||
// access to the following must be synchronized: | |||
PixelBufferImage im; | |||
Graphics graphics; | |||
Thread setColourMapEntriesTimerThread; | |||
Cursor cursor; | |||
boolean cursorVisible; // Is cursor currently rendered? | |||
boolean cursorAvailable; // Is cursor available for rendering? | |||
int cursorPosX, cursorPosY; | |||
ManagedPixelBuffer cursorBacking; | |||
int cursorBackingX, cursorBackingY; | |||
java.awt.Cursor softCursor; | |||
static Toolkit tk = Toolkit.getDefaultToolkit(); | |||
// the following are only ever accessed by the RFB thread: | |||
boolean invalidRect; | |||
int invalidLeft, invalidRight, invalidTop, invalidBottom; | |||
// the following are only ever accessed by the GUI thread: | |||
int lastX, lastY; | |||
static LogWriter vlog = new LogWriter("DesktopWindow"); | |||
} |
@@ -1,380 +1,380 @@ | |||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. | |||
* | |||
* This 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 software 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 software; if not, write to the Free Software | |||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||
* USA. | |||
*/ | |||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. | |||
* | |||
* This 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 software 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 software; if not, write to the Free Software | |||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||
* USA. | |||
*/ | |||
package com.tigervnc.vncviewer; | |||
import java.awt.*; | |||
import java.awt.event.*; | |||
import javax.swing.*; | |||
import javax.swing.border.*; | |||
import javax.swing.filechooser.*; | |||
import javax.swing.ImageIcon; | |||
import java.net.URL; | |||
import java.io.IOException; | |||
import java.awt.*; | |||
import java.awt.event.*; | |||
import javax.swing.*; | |||
import javax.swing.border.*; | |||
import javax.swing.filechooser.*; | |||
import javax.swing.ImageIcon; | |||
import java.net.URL; | |||
import java.io.IOException; | |||
import com.tigervnc.rfb.*; | |||
import com.tigervnc.rfb.Exception; | |||
class OptionsDialog extends Dialog implements | |||
ActionListener, | |||
ItemListener | |||
{ | |||
// Constants | |||
// Static variables | |||
static LogWriter vlog = new LogWriter("OptionsDialog"); | |||
OptionsDialogCallback cb; | |||
JPanel FormatPanel, InputsPanel, MiscPanel, DefaultsPanel, SecPanel; | |||
JCheckBox autoSelect, customCompressLevel, noJpeg; | |||
JComboBox menuKey, compressLevel, qualityLevel ; | |||
ButtonGroup encodingGroup, colourGroup; | |||
JRadioButton zrle, hextile, tight, raw; | |||
JRadioButton fullColour, mediumColour, lowColour, veryLowColour; | |||
JCheckBox viewOnly, acceptClipboard, sendClipboard; | |||
JCheckBox fullScreen, shared, useLocalCursor, fastCopyRect; | |||
JCheckBox secVeNCrypt, encNone, encTLS, encX509; | |||
JCheckBox secNone, secVnc, secPlain, secIdent, sendLocalUsername; | |||
JButton okButton, cancelButton; | |||
JButton ca, crl; | |||
JButton defSaveButton; | |||
boolean encryption = true; | |||
UserPrefs defaults; | |||
public OptionsDialog(OptionsDialogCallback cb_) { | |||
super(false); | |||
cb = cb_; | |||
setResizable(false); | |||
setTitle("VNC Viewer Options"); | |||
defaults = new UserPrefs("vncviewer"); | |||
getContentPane().setLayout( | |||
new BoxLayout(getContentPane(), BoxLayout.PAGE_AXIS)); | |||
JTabbedPane tabPane = new JTabbedPane(); | |||
ButtonGroup encodingGroup = new ButtonGroup(); | |||
ButtonGroup colourGroup = new ButtonGroup(); | |||
// Colour & Encoding tab | |||
FormatPanel=new JPanel(new GridBagLayout()); | |||
autoSelect = new JCheckBox("Auto Select"); | |||
autoSelect.addItemListener(this); | |||
JPanel encodingPanel = new JPanel(new GridBagLayout()); | |||
encodingPanel.setBorder(BorderFactory.createTitledBorder("Preferred encoding")); | |||
zrle = addRadioCheckbox("ZRLE", encodingGroup, encodingPanel); | |||
hextile = addRadioCheckbox("Hextile", encodingGroup, encodingPanel); | |||
tight = addRadioCheckbox("Tight", encodingGroup, encodingPanel); | |||
raw = addRadioCheckbox("Raw", encodingGroup, encodingPanel); | |||
JPanel tightPanel = new JPanel(new GridBagLayout()); | |||
customCompressLevel = new JCheckBox("Custom Compression Level"); | |||
customCompressLevel.addItemListener(this); | |||
Object[] compressionLevels = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; | |||
compressLevel = new JComboBox(compressionLevels); | |||
JLabel compressionLabel = new JLabel("Level (1=fast, 9=best)"); | |||
noJpeg = new JCheckBox("Allow JPEG Compression"); | |||
noJpeg.addItemListener(this); | |||
Object[] qualityLevels = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; | |||
qualityLevel = new JComboBox(qualityLevels); | |||
JLabel qualityLabel = new JLabel("Level (1=poor, 9=best)"); | |||
addGBComponent(customCompressLevel, tightPanel, 0, 0, 2, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(0,2,0,0)); | |||
addGBComponent(compressLevel, tightPanel, 0, 1, 1, 1, 2, 2, 0, 0, GridBagConstraints.NONE, GridBagConstraints.FIRST_LINE_START, new Insets(0,20,0,0)); | |||
addGBComponent(compressionLabel, tightPanel, 1, 1, 1, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(0,5,0,0)); | |||
addGBComponent(noJpeg, tightPanel, 0, 2, 2, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(0,2,0,0)); | |||
addGBComponent(qualityLevel, tightPanel, 0, 3, 1, 1, 2, 2, 0, 0, GridBagConstraints.NONE, GridBagConstraints.FIRST_LINE_START, new Insets(0,20,0,0)); | |||
addGBComponent(qualityLabel, tightPanel, 1, 3, 1, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(0,5,0,0)); | |||
JPanel colourPanel = new JPanel(new GridBagLayout()); | |||
colourPanel.setBorder(BorderFactory.createTitledBorder("Colour level")); | |||
fullColour = addRadioCheckbox("Full (all available colours)", colourGroup, colourPanel); | |||
mediumColour = addRadioCheckbox("Medium (256 colours)", colourGroup, colourPanel); | |||
lowColour = addRadioCheckbox("Low (64 colours)", colourGroup, colourPanel); | |||
veryLowColour = addRadioCheckbox("Very low(8 colours)", colourGroup, colourPanel); | |||
addGBComponent(autoSelect,FormatPanel, 0, 0, 2, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(0,2,0,0)); | |||
addGBComponent(encodingPanel,FormatPanel, 0, 1, 1, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(0,2,0,0)); | |||
addGBComponent(colourPanel,FormatPanel, 1, 1, 1, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_END, new Insets(0,2,0,0)); | |||
addGBComponent(tightPanel,FormatPanel, 0, 2, 2, GridBagConstraints.REMAINDER, 2, 2, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(0,2,0,0)); | |||
// Inputs tab | |||
InputsPanel=new JPanel(new GridBagLayout()); | |||
viewOnly = new JCheckBox("View Only (ignore mouse & keyboard)"); | |||
viewOnly.addItemListener(this); | |||
acceptClipboard = new JCheckBox("Accept clipboard from server"); | |||
acceptClipboard.addItemListener(this); | |||
sendClipboard = new JCheckBox("Send clipboard to server"); | |||
sendClipboard.addItemListener(this); | |||
JLabel menuKeyLabel = new JLabel("Menu Key"); | |||
String[] menuKeys = | |||
{ "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12" }; | |||
menuKey = new JComboBox(menuKeys); | |||
menuKey.addItemListener(this); | |||
addGBComponent(viewOnly,InputsPanel, 0, 0, 2, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4)); | |||
addGBComponent(acceptClipboard,InputsPanel, 0, 1, 2, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4)); | |||
addGBComponent(sendClipboard,InputsPanel, 0, 2, 2, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4)); | |||
addGBComponent(menuKeyLabel,InputsPanel, 0, 3, 1, GridBagConstraints.REMAINDER, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(8,10,0,4)); | |||
addGBComponent(menuKey,InputsPanel, 1, 3, 1, GridBagConstraints.REMAINDER, 0, 0, 2, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(4,4,0,125)); | |||
//((javax.swing.plaf.basic.BasicComboBoxRenderer)menuKey.getRenderer()).setBorder(new EmptyBorder(0,3,0,3)); | |||
// Misc tab | |||
MiscPanel=new JPanel(new GridBagLayout()); | |||
fullScreen = new JCheckBox("Full-screen mode"); | |||
fullScreen.addItemListener(this); | |||
shared = new JCheckBox("Shared connection (do not disconnect other viewers)"); | |||
shared.addItemListener(this); | |||
useLocalCursor = new JCheckBox("Render cursor locally"); | |||
useLocalCursor.addItemListener(this); | |||
fastCopyRect = new JCheckBox("Fast CopyRect"); | |||
fastCopyRect.addItemListener(this); | |||
addGBComponent(fullScreen,MiscPanel, 0, 0, 1, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4)); | |||
addGBComponent(shared,MiscPanel, 0, 1, 1, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4)); | |||
addGBComponent(useLocalCursor,MiscPanel, 0, 2, 1, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4)); | |||
addGBComponent(fastCopyRect,MiscPanel, 0, 3, 1, GridBagConstraints.REMAINDER, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(4,4,0,4)); | |||
// load/save tab | |||
DefaultsPanel=new JPanel(new GridBagLayout()); | |||
JPanel configPanel = new JPanel(new GridBagLayout()); | |||
configPanel.setBorder(BorderFactory.createTitledBorder("Configuration File")); | |||
JButton cfReloadButton = new JButton("Reload"); | |||
cfReloadButton.addActionListener(this); | |||
addGBComponent(cfReloadButton,configPanel, 0, 0, 1, 1, 0, 0, 0, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(4,8,4,8)); | |||
JButton cfSaveButton = new JButton("Save"); | |||
cfSaveButton.addActionListener(this); | |||
addGBComponent(cfSaveButton,configPanel, 0, 1, 1, 1, 0, 0, 0, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(4,8,4,8)); | |||
JButton cfSaveAsButton = new JButton("Save As..."); | |||
cfSaveAsButton.addActionListener(this); | |||
addGBComponent(cfSaveAsButton,configPanel, 0, 2, 1, 1, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(4,8,4,8)); | |||
cfReloadButton.setEnabled(false); | |||
cfSaveButton.setEnabled(false); | |||
JPanel defaultsPanel = new JPanel(new GridBagLayout()); | |||
defaultsPanel.setBorder(BorderFactory.createTitledBorder("Defaults")); | |||
JButton defReloadButton = new JButton("Reload"); | |||
defReloadButton.addActionListener(this); | |||
addGBComponent(defReloadButton,defaultsPanel, 0, 0, 1, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(4,8,4,8)); | |||
defSaveButton = new JButton("Save"); | |||
defSaveButton.addActionListener(this); | |||
addGBComponent(defSaveButton,defaultsPanel, 0, 1, 1, 1, 0, 0, 0, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(4,8,4,8)); | |||
addGBComponent(configPanel,DefaultsPanel, 0, 0, 1, GridBagConstraints.REMAINDER, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(4,4,4,4)); | |||
addGBComponent(defaultsPanel,DefaultsPanel, 1, 0, 1, GridBagConstraints.REMAINDER, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(4,4,4,4)); | |||
// security tab | |||
SecPanel=new JPanel(new GridBagLayout()); | |||
JPanel encryptionPanel = new JPanel(new GridBagLayout()); | |||
encryptionPanel.setBorder(BorderFactory.createTitledBorder("Session Encryption")); | |||
encNone = addCheckbox("None", null, encryptionPanel); | |||
encTLS = addCheckbox("Anonymous TLS", null, encryptionPanel); | |||
encX509 = addJCheckBox("TLS with X.509 certificates", null, encryptionPanel, new GridBagConstraints(0,2,1,1,1,1,GridBagConstraints.LINE_START,GridBagConstraints.REMAINDER,new Insets(0,0,0,60),0,0)); | |||
JPanel x509Panel = new JPanel(new GridBagLayout()); | |||
x509Panel.setBorder(BorderFactory.createTitledBorder("X.509 certificates")); | |||
ca = new JButton("Load CA certificate"); | |||
ca.setPreferredSize(new Dimension(145,25)); | |||
ca.addActionListener(this); | |||
crl = new JButton("Load CRL certificate"); | |||
crl.setPreferredSize(new Dimension(145,25)); | |||
crl.addActionListener(this); | |||
addGBComponent(ca, x509Panel, 0, 0, 1, 1, 2, 2, 0, 1, GridBagConstraints.NONE, GridBagConstraints.LINE_START, new Insets(2,2,2,2)); | |||
addGBComponent(crl, x509Panel, 1, 0, 1, 1, 2, 2, 1, 1, GridBagConstraints.NONE, GridBagConstraints.LINE_START, new Insets(2,2,2,2)); | |||
JPanel authPanel = new JPanel(new GridBagLayout()); | |||
authPanel.setBorder(BorderFactory.createTitledBorder("Authentication")); | |||
secNone = addCheckbox("None", null, authPanel); | |||
secVnc = addCheckbox("Standard VNC", null, authPanel); | |||
secPlain = addJCheckBox("Plaintext", null, authPanel, new GridBagConstraints(0,2,1,1,1,1,GridBagConstraints.LINE_START,GridBagConstraints.NONE,new Insets(0,0,0,5),0,0)); | |||
secIdent = addJCheckBox("Ident", null, authPanel, new GridBagConstraints(0,3,1,1,1,1,GridBagConstraints.LINE_START,GridBagConstraints.NONE,new Insets(0,0,0,5),0,0)); | |||
sendLocalUsername = new JCheckBox("Send Local Username"); | |||
sendLocalUsername.addItemListener(this); | |||
addGBComponent(sendLocalUsername, authPanel, 1, 2, 1, 2, 0, 0, 2, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(0,20,0,0)); | |||
secVeNCrypt = new JCheckBox("Extended encryption and authentication methods (VeNCrypt)"); | |||
secVeNCrypt.addItemListener(this); | |||
addGBComponent(secVeNCrypt,SecPanel, 0, 0, 1, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(0,2,0,20)); | |||
addGBComponent(encryptionPanel,SecPanel, 0, 1, 1, 1, 2, 2, 1, 0, GridBagConstraints.NONE, GridBagConstraints.LINE_START, new Insets(0,4,2,4)); | |||
addGBComponent(x509Panel,SecPanel, 0, 2, 1, 1, 2, 2, 1, 0, GridBagConstraints.NONE, GridBagConstraints.LINE_START, new Insets(2,4,2,4)); | |||
addGBComponent(authPanel,SecPanel, 0, 3, 1, 1, 2, 2, 1, 1, GridBagConstraints.NONE, GridBagConstraints.FIRST_LINE_START, new Insets(2,4,2,4)); | |||
tabPane.add(FormatPanel); | |||
tabPane.add(InputsPanel); | |||
tabPane.add(MiscPanel); | |||
tabPane.add(DefaultsPanel); | |||
tabPane.add(SecPanel); | |||
tabPane.addTab("Colour & Encoding", FormatPanel); | |||
tabPane.addTab("Inputs", InputsPanel); | |||
tabPane.addTab("Misc", MiscPanel); | |||
tabPane.addTab("Load / Save", DefaultsPanel); | |||
tabPane.addTab("Security", SecPanel); | |||
tabPane.setBorder(BorderFactory.createEmptyBorder(4,4,0,4)); | |||
okButton = new JButton("OK"); | |||
okButton.setPreferredSize(new Dimension(90,30)); | |||
okButton.addActionListener(this); | |||
cancelButton = new JButton("Cancel"); | |||
cancelButton.setPreferredSize(new Dimension(90,30)); | |||
cancelButton.addActionListener(this); | |||
JPanel buttonPane = new JPanel(); | |||
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS)); | |||
buttonPane.setBorder(BorderFactory.createEmptyBorder(4,0,0,0)); | |||
buttonPane.add(Box.createHorizontalGlue()); | |||
buttonPane.add(okButton); | |||
buttonPane.add(Box.createRigidArea(new Dimension(4,0))); | |||
buttonPane.add(cancelButton); | |||
buttonPane.add(Box.createRigidArea(new Dimension(4,0))); | |||
this.getContentPane().add(tabPane); | |||
this.getContentPane().add(buttonPane); | |||
pack(); | |||
} | |||
public void initDialog() { | |||
if (cb != null) cb.setOptions(); | |||
zrle.setEnabled(!autoSelect.isSelected()); | |||
hextile.setEnabled(!autoSelect.isSelected()); | |||
tight.setEnabled(!autoSelect.isSelected()); | |||
raw.setEnabled(!autoSelect.isSelected()); | |||
fullColour.setEnabled(!autoSelect.isSelected()); | |||
mediumColour.setEnabled(!autoSelect.isSelected()); | |||
lowColour.setEnabled(!autoSelect.isSelected()); | |||
veryLowColour.setEnabled(!autoSelect.isSelected()); | |||
compressLevel.setEnabled(customCompressLevel.isSelected()); | |||
qualityLevel.setEnabled(noJpeg.isSelected()); | |||
sendLocalUsername.setEnabled(secVeNCrypt.isEnabled()&& | |||
(secPlain.isSelected()||secIdent.isSelected())); | |||
} | |||
JRadioButton addRadioCheckbox(String str, ButtonGroup group, JPanel panel) { | |||
JRadioButton c = new JRadioButton(str); | |||
GridBagConstraints gbc = new GridBagConstraints(); | |||
gbc.anchor = GridBagConstraints.LINE_START; | |||
gbc.gridwidth = GridBagConstraints.REMAINDER; | |||
gbc.weightx = 1; | |||
gbc.weighty = 1; | |||
panel.add(c,gbc); | |||
group.add(c); | |||
c.addItemListener(this); | |||
return c; | |||
} | |||
JCheckBox addCheckbox(String str, ButtonGroup group, JPanel panel) { | |||
JCheckBox c = new JCheckBox(str); | |||
GridBagConstraints gbc = new GridBagConstraints(); | |||
gbc.anchor = GridBagConstraints.LINE_START; | |||
gbc.gridwidth = GridBagConstraints.REMAINDER; | |||
gbc.weightx = 1; | |||
gbc.weighty = 1; | |||
panel.add(c,gbc); | |||
if (group != null) | |||
group.add(c); | |||
c.addItemListener(this); | |||
return c; | |||
} | |||
JCheckBox addJCheckBox(String str, ButtonGroup group, JPanel panel, | |||
GridBagConstraints gbc) { | |||
JCheckBox c = new JCheckBox(str); | |||
panel.add(c,gbc); | |||
if (group != null) | |||
group.add(c); | |||
c.addItemListener(this); | |||
return c; | |||
} | |||
public void actionPerformed(ActionEvent e) { | |||
Object s = e.getSource(); | |||
if (s instanceof JButton && (JButton)s == okButton) { | |||
ok = true; | |||
if (cb != null) cb.getOptions(); | |||
endDialog(); | |||
} else if (s instanceof JButton && (JButton)s == cancelButton) { | |||
ok = false; | |||
endDialog(); | |||
} else if (s instanceof JButton && (JButton)s == defSaveButton) { | |||
try { | |||
defaults.Save(); | |||
} catch (java.lang.Exception x) { } | |||
} else if (s instanceof JButton && (JButton)s == ca) { | |||
JFileChooser fc = new JFileChooser(); | |||
fc.setDialogTitle("Path to X509 CA certificate"); | |||
int ret = fc.showOpenDialog(this); | |||
if (ret == JFileChooser.APPROVE_OPTION) | |||
CSecurityTLS.x509ca.setParam(fc.getSelectedFile().toString()); | |||
} else if (s instanceof JButton && (JButton)s == crl) { | |||
JFileChooser fc = new JFileChooser(); | |||
fc.setDialogTitle("Path to X509 CRL file"); | |||
int ret = fc.showOpenDialog(this); | |||
if (ret == JFileChooser.APPROVE_OPTION) | |||
CSecurityTLS.x509crl.setParam(fc.getSelectedFile().toString()); | |||
} | |||
} | |||
public void itemStateChanged(ItemEvent e) { | |||
Object s = e.getSource(); | |||
if (s instanceof JCheckBox && (JCheckBox)s == autoSelect) { | |||
zrle.setEnabled(!autoSelect.isSelected()); | |||
hextile.setEnabled(!autoSelect.isSelected()); | |||
tight.setEnabled(!autoSelect.isSelected()); | |||
raw.setEnabled(!autoSelect.isSelected()); | |||
fullColour.setEnabled(!autoSelect.isSelected()); | |||
mediumColour.setEnabled(!autoSelect.isSelected()); | |||
lowColour.setEnabled(!autoSelect.isSelected()); | |||
veryLowColour.setEnabled(!autoSelect.isSelected()); | |||
defaults.setPref("autoSelect",(autoSelect.isSelected()) ? "on" : "off"); | |||
} | |||
if (s instanceof JCheckBox && (JCheckBox)s == customCompressLevel) { | |||
compressLevel.setEnabled(customCompressLevel.isSelected()); | |||
defaults.setPref("customCompressLevel",(customCompressLevel.isSelected()) ? "on" : "off"); | |||
} | |||
if (s instanceof JCheckBox && (JCheckBox)s == noJpeg) { | |||
qualityLevel.setEnabled(noJpeg.isSelected()); | |||
defaults.setPref("noJpeg",(noJpeg.isSelected()) ? "on" : "off"); | |||
} | |||
if (s instanceof JCheckBox && (JCheckBox)s == sendLocalUsername) { | |||
defaults.setPref("sendLocalUsername",(sendLocalUsername.isSelected()) ? "on" : "off"); | |||
} | |||
if (s instanceof JCheckBox && (JCheckBox)s == secVeNCrypt) { | |||
encNone.setEnabled(secVeNCrypt.isSelected()); | |||
encTLS.setEnabled(secVeNCrypt.isSelected()); | |||
encX509.setEnabled(secVeNCrypt.isSelected()); | |||
ca.setEnabled(secVeNCrypt.isSelected()); | |||
crl.setEnabled(secVeNCrypt.isSelected()); | |||
secIdent.setEnabled(secVeNCrypt.isSelected()); | |||
secNone.setEnabled(secVeNCrypt.isSelected()); | |||
secVnc.setEnabled(secVeNCrypt.isSelected()); | |||
secPlain.setEnabled(secVeNCrypt.isSelected()); | |||
sendLocalUsername.setEnabled(secVeNCrypt.isSelected()); | |||
} | |||
if (s instanceof JCheckBox && (JCheckBox)s == secIdent || | |||
s instanceof JCheckBox && (JCheckBox)s == secPlain) { | |||
sendLocalUsername.setEnabled(secIdent.isSelected()||secPlain.isSelected()); | |||
} | |||
} | |||
} | |||
class OptionsDialog extends Dialog implements | |||
ActionListener, | |||
ItemListener | |||
{ | |||
// Constants | |||
// Static variables | |||
static LogWriter vlog = new LogWriter("OptionsDialog"); | |||
OptionsDialogCallback cb; | |||
JPanel FormatPanel, InputsPanel, MiscPanel, DefaultsPanel, SecPanel; | |||
JCheckBox autoSelect, customCompressLevel, noJpeg; | |||
JComboBox menuKey, compressLevel, qualityLevel ; | |||
ButtonGroup encodingGroup, colourGroup; | |||
JRadioButton zrle, hextile, tight, raw; | |||
JRadioButton fullColour, mediumColour, lowColour, veryLowColour; | |||
JCheckBox viewOnly, acceptClipboard, sendClipboard; | |||
JCheckBox fullScreen, shared, useLocalCursor, fastCopyRect; | |||
JCheckBox secVeNCrypt, encNone, encTLS, encX509; | |||
JCheckBox secNone, secVnc, secPlain, secIdent, sendLocalUsername; | |||
JButton okButton, cancelButton; | |||
JButton ca, crl; | |||
JButton defSaveButton; | |||
boolean encryption = true; | |||
UserPrefs defaults; | |||
public OptionsDialog(OptionsDialogCallback cb_) { | |||
super(false); | |||
cb = cb_; | |||
setResizable(false); | |||
setTitle("VNC Viewer Options"); | |||
defaults = new UserPrefs("vncviewer"); | |||
getContentPane().setLayout( | |||
new BoxLayout(getContentPane(), BoxLayout.PAGE_AXIS)); | |||
JTabbedPane tabPane = new JTabbedPane(); | |||
ButtonGroup encodingGroup = new ButtonGroup(); | |||
ButtonGroup colourGroup = new ButtonGroup(); | |||
// Colour & Encoding tab | |||
FormatPanel=new JPanel(new GridBagLayout()); | |||
autoSelect = new JCheckBox("Auto Select"); | |||
autoSelect.addItemListener(this); | |||
JPanel encodingPanel = new JPanel(new GridBagLayout()); | |||
encodingPanel.setBorder(BorderFactory.createTitledBorder("Preferred encoding")); | |||
zrle = addRadioCheckbox("ZRLE", encodingGroup, encodingPanel); | |||
hextile = addRadioCheckbox("Hextile", encodingGroup, encodingPanel); | |||
tight = addRadioCheckbox("Tight", encodingGroup, encodingPanel); | |||
raw = addRadioCheckbox("Raw", encodingGroup, encodingPanel); | |||
JPanel tightPanel = new JPanel(new GridBagLayout()); | |||
customCompressLevel = new JCheckBox("Custom Compression Level"); | |||
customCompressLevel.addItemListener(this); | |||
Object[] compressionLevels = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; | |||
compressLevel = new JComboBox(compressionLevels); | |||
JLabel compressionLabel = new JLabel("Level (1=fast, 9=best)"); | |||
noJpeg = new JCheckBox("Allow JPEG Compression"); | |||
noJpeg.addItemListener(this); | |||
Object[] qualityLevels = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; | |||
qualityLevel = new JComboBox(qualityLevels); | |||
JLabel qualityLabel = new JLabel("Level (1=poor, 9=best)"); | |||
addGBComponent(customCompressLevel, tightPanel, 0, 0, 2, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(0,2,0,0)); | |||
addGBComponent(compressLevel, tightPanel, 0, 1, 1, 1, 2, 2, 0, 0, GridBagConstraints.NONE, GridBagConstraints.FIRST_LINE_START, new Insets(0,20,0,0)); | |||
addGBComponent(compressionLabel, tightPanel, 1, 1, 1, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(0,5,0,0)); | |||
addGBComponent(noJpeg, tightPanel, 0, 2, 2, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(0,2,0,0)); | |||
addGBComponent(qualityLevel, tightPanel, 0, 3, 1, 1, 2, 2, 0, 0, GridBagConstraints.NONE, GridBagConstraints.FIRST_LINE_START, new Insets(0,20,0,0)); | |||
addGBComponent(qualityLabel, tightPanel, 1, 3, 1, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(0,5,0,0)); | |||
JPanel colourPanel = new JPanel(new GridBagLayout()); | |||
colourPanel.setBorder(BorderFactory.createTitledBorder("Colour level")); | |||
fullColour = addRadioCheckbox("Full (all available colours)", colourGroup, colourPanel); | |||
mediumColour = addRadioCheckbox("Medium (256 colours)", colourGroup, colourPanel); | |||
lowColour = addRadioCheckbox("Low (64 colours)", colourGroup, colourPanel); | |||
veryLowColour = addRadioCheckbox("Very low(8 colours)", colourGroup, colourPanel); | |||
addGBComponent(autoSelect,FormatPanel, 0, 0, 2, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(0,2,0,0)); | |||
addGBComponent(encodingPanel,FormatPanel, 0, 1, 1, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(0,2,0,0)); | |||
addGBComponent(colourPanel,FormatPanel, 1, 1, 1, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_END, new Insets(0,2,0,0)); | |||
addGBComponent(tightPanel,FormatPanel, 0, 2, 2, GridBagConstraints.REMAINDER, 2, 2, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(0,2,0,0)); | |||
// Inputs tab | |||
InputsPanel=new JPanel(new GridBagLayout()); | |||
viewOnly = new JCheckBox("View Only (ignore mouse & keyboard)"); | |||
viewOnly.addItemListener(this); | |||
acceptClipboard = new JCheckBox("Accept clipboard from server"); | |||
acceptClipboard.addItemListener(this); | |||
sendClipboard = new JCheckBox("Send clipboard to server"); | |||
sendClipboard.addItemListener(this); | |||
JLabel menuKeyLabel = new JLabel("Menu Key"); | |||
String[] menuKeys = | |||
{ "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12" }; | |||
menuKey = new JComboBox(menuKeys); | |||
menuKey.addItemListener(this); | |||
addGBComponent(viewOnly,InputsPanel, 0, 0, 2, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4)); | |||
addGBComponent(acceptClipboard,InputsPanel, 0, 1, 2, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4)); | |||
addGBComponent(sendClipboard,InputsPanel, 0, 2, 2, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4)); | |||
addGBComponent(menuKeyLabel,InputsPanel, 0, 3, 1, GridBagConstraints.REMAINDER, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(8,10,0,4)); | |||
addGBComponent(menuKey,InputsPanel, 1, 3, 1, GridBagConstraints.REMAINDER, 0, 0, 2, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(4,4,0,125)); | |||
//((javax.swing.plaf.basic.BasicComboBoxRenderer)menuKey.getRenderer()).setBorder(new EmptyBorder(0,3,0,3)); | |||
// Misc tab | |||
MiscPanel=new JPanel(new GridBagLayout()); | |||
fullScreen = new JCheckBox("Full-screen mode"); | |||
fullScreen.addItemListener(this); | |||
shared = new JCheckBox("Shared connection (do not disconnect other viewers)"); | |||
shared.addItemListener(this); | |||
useLocalCursor = new JCheckBox("Render cursor locally"); | |||
useLocalCursor.addItemListener(this); | |||
fastCopyRect = new JCheckBox("Fast CopyRect"); | |||
fastCopyRect.addItemListener(this); | |||
addGBComponent(fullScreen,MiscPanel, 0, 0, 1, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4)); | |||
addGBComponent(shared,MiscPanel, 0, 1, 1, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4)); | |||
addGBComponent(useLocalCursor,MiscPanel, 0, 2, 1, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4)); | |||
addGBComponent(fastCopyRect,MiscPanel, 0, 3, 1, GridBagConstraints.REMAINDER, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(4,4,0,4)); | |||
// load/save tab | |||
DefaultsPanel=new JPanel(new GridBagLayout()); | |||
JPanel configPanel = new JPanel(new GridBagLayout()); | |||
configPanel.setBorder(BorderFactory.createTitledBorder("Configuration File")); | |||
JButton cfReloadButton = new JButton("Reload"); | |||
cfReloadButton.addActionListener(this); | |||
addGBComponent(cfReloadButton,configPanel, 0, 0, 1, 1, 0, 0, 0, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(4,8,4,8)); | |||
JButton cfSaveButton = new JButton("Save"); | |||
cfSaveButton.addActionListener(this); | |||
addGBComponent(cfSaveButton,configPanel, 0, 1, 1, 1, 0, 0, 0, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(4,8,4,8)); | |||
JButton cfSaveAsButton = new JButton("Save As..."); | |||
cfSaveAsButton.addActionListener(this); | |||
addGBComponent(cfSaveAsButton,configPanel, 0, 2, 1, 1, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(4,8,4,8)); | |||
cfReloadButton.setEnabled(false); | |||
cfSaveButton.setEnabled(false); | |||
JPanel defaultsPanel = new JPanel(new GridBagLayout()); | |||
defaultsPanel.setBorder(BorderFactory.createTitledBorder("Defaults")); | |||
JButton defReloadButton = new JButton("Reload"); | |||
defReloadButton.addActionListener(this); | |||
addGBComponent(defReloadButton,defaultsPanel, 0, 0, 1, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(4,8,4,8)); | |||
defSaveButton = new JButton("Save"); | |||
defSaveButton.addActionListener(this); | |||
addGBComponent(defSaveButton,defaultsPanel, 0, 1, 1, 1, 0, 0, 0, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(4,8,4,8)); | |||
addGBComponent(configPanel,DefaultsPanel, 0, 0, 1, GridBagConstraints.REMAINDER, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(4,4,4,4)); | |||
addGBComponent(defaultsPanel,DefaultsPanel, 1, 0, 1, GridBagConstraints.REMAINDER, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(4,4,4,4)); | |||
// security tab | |||
SecPanel=new JPanel(new GridBagLayout()); | |||
JPanel encryptionPanel = new JPanel(new GridBagLayout()); | |||
encryptionPanel.setBorder(BorderFactory.createTitledBorder("Session Encryption")); | |||
encNone = addCheckbox("None", null, encryptionPanel); | |||
encTLS = addCheckbox("Anonymous TLS", null, encryptionPanel); | |||
encX509 = addJCheckBox("TLS with X.509 certificates", null, encryptionPanel, new GridBagConstraints(0,2,1,1,1,1,GridBagConstraints.LINE_START,GridBagConstraints.REMAINDER,new Insets(0,0,0,60),0,0)); | |||
JPanel x509Panel = new JPanel(new GridBagLayout()); | |||
x509Panel.setBorder(BorderFactory.createTitledBorder("X.509 certificates")); | |||
ca = new JButton("Load CA certificate"); | |||
ca.setPreferredSize(new Dimension(145,25)); | |||
ca.addActionListener(this); | |||
crl = new JButton("Load CRL certificate"); | |||
crl.setPreferredSize(new Dimension(145,25)); | |||
crl.addActionListener(this); | |||
addGBComponent(ca, x509Panel, 0, 0, 1, 1, 2, 2, 0, 1, GridBagConstraints.NONE, GridBagConstraints.LINE_START, new Insets(2,2,2,2)); | |||
addGBComponent(crl, x509Panel, 1, 0, 1, 1, 2, 2, 1, 1, GridBagConstraints.NONE, GridBagConstraints.LINE_START, new Insets(2,2,2,2)); | |||
JPanel authPanel = new JPanel(new GridBagLayout()); | |||
authPanel.setBorder(BorderFactory.createTitledBorder("Authentication")); | |||
secNone = addCheckbox("None", null, authPanel); | |||
secVnc = addCheckbox("Standard VNC", null, authPanel); | |||
secPlain = addJCheckBox("Plaintext", null, authPanel, new GridBagConstraints(0,2,1,1,1,1,GridBagConstraints.LINE_START,GridBagConstraints.NONE,new Insets(0,0,0,5),0,0)); | |||
secIdent = addJCheckBox("Ident", null, authPanel, new GridBagConstraints(0,3,1,1,1,1,GridBagConstraints.LINE_START,GridBagConstraints.NONE,new Insets(0,0,0,5),0,0)); | |||
sendLocalUsername = new JCheckBox("Send Local Username"); | |||
sendLocalUsername.addItemListener(this); | |||
addGBComponent(sendLocalUsername, authPanel, 1, 2, 1, 2, 0, 0, 2, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(0,20,0,0)); | |||
secVeNCrypt = new JCheckBox("Extended encryption and authentication methods (VeNCrypt)"); | |||
secVeNCrypt.addItemListener(this); | |||
addGBComponent(secVeNCrypt,SecPanel, 0, 0, 1, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(0,2,0,20)); | |||
addGBComponent(encryptionPanel,SecPanel, 0, 1, 1, 1, 2, 2, 1, 0, GridBagConstraints.NONE, GridBagConstraints.LINE_START, new Insets(0,4,2,4)); | |||
addGBComponent(x509Panel,SecPanel, 0, 2, 1, 1, 2, 2, 1, 0, GridBagConstraints.NONE, GridBagConstraints.LINE_START, new Insets(2,4,2,4)); | |||
addGBComponent(authPanel,SecPanel, 0, 3, 1, 1, 2, 2, 1, 1, GridBagConstraints.NONE, GridBagConstraints.FIRST_LINE_START, new Insets(2,4,2,4)); | |||
tabPane.add(FormatPanel); | |||
tabPane.add(InputsPanel); | |||
tabPane.add(MiscPanel); | |||
tabPane.add(DefaultsPanel); | |||
tabPane.add(SecPanel); | |||
tabPane.addTab("Colour & Encoding", FormatPanel); | |||
tabPane.addTab("Inputs", InputsPanel); | |||
tabPane.addTab("Misc", MiscPanel); | |||
tabPane.addTab("Load / Save", DefaultsPanel); | |||
tabPane.addTab("Security", SecPanel); | |||
tabPane.setBorder(BorderFactory.createEmptyBorder(4,4,0,4)); | |||
okButton = new JButton("OK"); | |||
okButton.setPreferredSize(new Dimension(90,30)); | |||
okButton.addActionListener(this); | |||
cancelButton = new JButton("Cancel"); | |||
cancelButton.setPreferredSize(new Dimension(90,30)); | |||
cancelButton.addActionListener(this); | |||
JPanel buttonPane = new JPanel(); | |||
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS)); | |||
buttonPane.setBorder(BorderFactory.createEmptyBorder(4,0,0,0)); | |||
buttonPane.add(Box.createHorizontalGlue()); | |||
buttonPane.add(okButton); | |||
buttonPane.add(Box.createRigidArea(new Dimension(4,0))); | |||
buttonPane.add(cancelButton); | |||
buttonPane.add(Box.createRigidArea(new Dimension(4,0))); | |||
this.getContentPane().add(tabPane); | |||
this.getContentPane().add(buttonPane); | |||
pack(); | |||
} | |||
public void initDialog() { | |||
if (cb != null) cb.setOptions(); | |||
zrle.setEnabled(!autoSelect.isSelected()); | |||
hextile.setEnabled(!autoSelect.isSelected()); | |||
tight.setEnabled(!autoSelect.isSelected()); | |||
raw.setEnabled(!autoSelect.isSelected()); | |||
fullColour.setEnabled(!autoSelect.isSelected()); | |||
mediumColour.setEnabled(!autoSelect.isSelected()); | |||
lowColour.setEnabled(!autoSelect.isSelected()); | |||
veryLowColour.setEnabled(!autoSelect.isSelected()); | |||
compressLevel.setEnabled(customCompressLevel.isSelected()); | |||
qualityLevel.setEnabled(noJpeg.isSelected()); | |||
sendLocalUsername.setEnabled(secVeNCrypt.isEnabled()&& | |||
(secPlain.isSelected()||secIdent.isSelected())); | |||
} | |||
JRadioButton addRadioCheckbox(String str, ButtonGroup group, JPanel panel) { | |||
JRadioButton c = new JRadioButton(str); | |||
GridBagConstraints gbc = new GridBagConstraints(); | |||
gbc.anchor = GridBagConstraints.LINE_START; | |||
gbc.gridwidth = GridBagConstraints.REMAINDER; | |||
gbc.weightx = 1; | |||
gbc.weighty = 1; | |||
panel.add(c,gbc); | |||
group.add(c); | |||
c.addItemListener(this); | |||
return c; | |||
} | |||
JCheckBox addCheckbox(String str, ButtonGroup group, JPanel panel) { | |||
JCheckBox c = new JCheckBox(str); | |||
GridBagConstraints gbc = new GridBagConstraints(); | |||
gbc.anchor = GridBagConstraints.LINE_START; | |||
gbc.gridwidth = GridBagConstraints.REMAINDER; | |||
gbc.weightx = 1; | |||
gbc.weighty = 1; | |||
panel.add(c,gbc); | |||
if (group != null) | |||
group.add(c); | |||
c.addItemListener(this); | |||
return c; | |||
} | |||
JCheckBox addJCheckBox(String str, ButtonGroup group, JPanel panel, | |||
GridBagConstraints gbc) { | |||
JCheckBox c = new JCheckBox(str); | |||
panel.add(c,gbc); | |||
if (group != null) | |||
group.add(c); | |||
c.addItemListener(this); | |||
return c; | |||
} | |||
public void actionPerformed(ActionEvent e) { | |||
Object s = e.getSource(); | |||
if (s instanceof JButton && (JButton)s == okButton) { | |||
ok = true; | |||
if (cb != null) cb.getOptions(); | |||
endDialog(); | |||
} else if (s instanceof JButton && (JButton)s == cancelButton) { | |||
ok = false; | |||
endDialog(); | |||
} else if (s instanceof JButton && (JButton)s == defSaveButton) { | |||
try { | |||
defaults.Save(); | |||
} catch (java.lang.Exception x) { } | |||
} else if (s instanceof JButton && (JButton)s == ca) { | |||
JFileChooser fc = new JFileChooser(); | |||
fc.setDialogTitle("Path to X509 CA certificate"); | |||
int ret = fc.showOpenDialog(this); | |||
if (ret == JFileChooser.APPROVE_OPTION) | |||
CSecurityTLS.x509ca.setParam(fc.getSelectedFile().toString()); | |||
} else if (s instanceof JButton && (JButton)s == crl) { | |||
JFileChooser fc = new JFileChooser(); | |||
fc.setDialogTitle("Path to X509 CRL file"); | |||
int ret = fc.showOpenDialog(this); | |||
if (ret == JFileChooser.APPROVE_OPTION) | |||
CSecurityTLS.x509crl.setParam(fc.getSelectedFile().toString()); | |||
} | |||
} | |||
public void itemStateChanged(ItemEvent e) { | |||
Object s = e.getSource(); | |||
if (s instanceof JCheckBox && (JCheckBox)s == autoSelect) { | |||
zrle.setEnabled(!autoSelect.isSelected()); | |||
hextile.setEnabled(!autoSelect.isSelected()); | |||
tight.setEnabled(!autoSelect.isSelected()); | |||
raw.setEnabled(!autoSelect.isSelected()); | |||
fullColour.setEnabled(!autoSelect.isSelected()); | |||
mediumColour.setEnabled(!autoSelect.isSelected()); | |||
lowColour.setEnabled(!autoSelect.isSelected()); | |||
veryLowColour.setEnabled(!autoSelect.isSelected()); | |||
defaults.setPref("autoSelect",(autoSelect.isSelected()) ? "on" : "off"); | |||
} | |||
if (s instanceof JCheckBox && (JCheckBox)s == customCompressLevel) { | |||
compressLevel.setEnabled(customCompressLevel.isSelected()); | |||
defaults.setPref("customCompressLevel",(customCompressLevel.isSelected()) ? "on" : "off"); | |||
} | |||
if (s instanceof JCheckBox && (JCheckBox)s == noJpeg) { | |||
qualityLevel.setEnabled(noJpeg.isSelected()); | |||
defaults.setPref("noJpeg",(noJpeg.isSelected()) ? "on" : "off"); | |||
} | |||
if (s instanceof JCheckBox && (JCheckBox)s == sendLocalUsername) { | |||
defaults.setPref("sendLocalUsername",(sendLocalUsername.isSelected()) ? "on" : "off"); | |||
} | |||
if (s instanceof JCheckBox && (JCheckBox)s == secVeNCrypt) { | |||
encNone.setEnabled(secVeNCrypt.isSelected()); | |||
encTLS.setEnabled(secVeNCrypt.isSelected()); | |||
encX509.setEnabled(secVeNCrypt.isSelected()); | |||
ca.setEnabled(secVeNCrypt.isSelected()); | |||
crl.setEnabled(secVeNCrypt.isSelected()); | |||
secIdent.setEnabled(secVeNCrypt.isSelected()); | |||
secNone.setEnabled(secVeNCrypt.isSelected()); | |||
secVnc.setEnabled(secVeNCrypt.isSelected()); | |||
secPlain.setEnabled(secVeNCrypt.isSelected()); | |||
sendLocalUsername.setEnabled(secVeNCrypt.isSelected()); | |||
} | |||
if (s instanceof JCheckBox && (JCheckBox)s == secIdent || | |||
s instanceof JCheckBox && (JCheckBox)s == secPlain) { | |||
sendLocalUsername.setEnabled(secIdent.isSelected()||secPlain.isSelected()); | |||
} | |||
} | |||
} |
@@ -1,178 +1,178 @@ | |||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. | |||
* | |||
* This 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 software 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 software; if not, write to the Free Software | |||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||
* USA. | |||
*/ | |||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. | |||
* | |||
* This 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 software 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 software; if not, write to the Free Software | |||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||
* USA. | |||
*/ | |||
package com.tigervnc.vncviewer; | |||
import java.awt.*; | |||
import java.awt.image.*; | |||
import java.awt.event.*; | |||
import javax.swing.*; | |||
import javax.swing.border.*; | |||
import java.net.URL; | |||
import java.io.File; | |||
import java.util.*; | |||
import java.awt.*; | |||
import java.awt.image.*; | |||
import java.awt.event.*; | |||
import javax.swing.*; | |||
import javax.swing.border.*; | |||
import java.net.URL; | |||
import java.io.File; | |||
import java.util.*; | |||
import com.tigervnc.rfb.*; | |||
import com.tigervnc.rfb.Exception; | |||
class ServerDialog extends Dialog implements | |||
ActionListener, | |||
ItemListener | |||
{ | |||
public ServerDialog(OptionsDialog options_, | |||
String defaultServerName, CConn cc_) { | |||
super(true); | |||
cc = cc_; | |||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); | |||
setResizable(false); | |||
setSize(new Dimension(340, 135)); | |||
setTitle("VNC Viewer : Connection Details"); | |||
options = options_; | |||
getContentPane().setLayout(new GridBagLayout()); | |||
JLabel serverLabel = new JLabel("Server:", JLabel.RIGHT); | |||
if (options.defaults.getString("server") != null) { | |||
server = new JComboBox(options.defaults.getString("server").split(",")); | |||
} else { | |||
server = new JComboBox(); | |||
} | |||
// Hack to set the left inset on editable JComboBox | |||
if (UIManager.getLookAndFeel().getID() == "Windows") { | |||
server.setBorder(BorderFactory.createCompoundBorder(server.getBorder(), | |||
BorderFactory.createEmptyBorder(0,2,0,0))); | |||
} else { | |||
ComboBoxEditor editor = server.getEditor(); | |||
JTextField jtf = (JTextField)editor.getEditorComponent(); | |||
jtf.setBorder(new CompoundBorder(jtf.getBorder(), new EmptyBorder(0,2,0,0))); | |||
} | |||
server.setEditable(true); | |||
editor = server.getEditor(); | |||
JLabel encryptionLabel = new JLabel("Encryption:"); | |||
encryption = new JComboBox(); | |||
serverLabel.setPreferredSize(encryptionLabel.getPreferredSize()); | |||
JPanel topPanel = new JPanel(new GridBagLayout()); | |||
addGBComponent(new JLabel(cc.logo),topPanel, 0, 0, 1, 1, 0, 0, 0, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(5,5,5,15)); | |||
addGBComponent(serverLabel,topPanel, 1, 0, 1, 1, 0, 0, 0, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_END, new Insets(10,0,5,5)); | |||
addGBComponent(server,topPanel, 2, 0, 1, 1, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(10,0,5,40)); | |||
optionsButton = new JButton("Options..."); | |||
aboutButton = new JButton("About..."); | |||
okButton = new JButton("OK"); | |||
cancelButton = new JButton("Cancel"); | |||
JPanel buttonPanel = new JPanel(new GridBagLayout()); | |||
buttonPanel.setPreferredSize(new Dimension(340, 40)); | |||
addGBComponent(aboutButton,buttonPanel, 0, 3, 1, 1, 0, 0, 0.2, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(0,5,0,5)); | |||
addGBComponent(optionsButton,buttonPanel, 1, 3, 1, 1, 0, 0, 0, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(0,5,0,5)); | |||
addGBComponent(okButton,buttonPanel, 2, 3, 1, 1, 0, 0, 0.8, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(0,5,0,5)); | |||
addGBComponent(cancelButton,buttonPanel, 3, 3, 1, 1, 0, 0, 0.5, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(0,5,0,5)); | |||
GridBagConstraints gbc = new GridBagConstraints(); | |||
gbc.anchor = GridBagConstraints.LINE_START; | |||
gbc.fill = GridBagConstraints.BOTH; | |||
gbc.gridwidth = GridBagConstraints.REMAINDER; | |||
gbc.gridheight = 1; | |||
gbc.insets = new Insets(0,0,0,0); | |||
gbc.ipadx = 0; | |||
gbc.ipady = 0; | |||
gbc.weightx = 1; | |||
gbc.weighty = 1; | |||
getContentPane().add(topPanel,gbc); | |||
getContentPane().add(buttonPanel); | |||
server.addActionListener(this); | |||
optionsButton.addActionListener(this); | |||
aboutButton.addActionListener(this); | |||
okButton.addActionListener(this); | |||
cancelButton.addActionListener(this); | |||
pack(); | |||
} | |||
public void itemStateChanged(ItemEvent e) { | |||
Object s = e.getSource(); | |||
if (s instanceof JComboBox && (JComboBox)s == encryption) { | |||
options.encryption=(encryption.getSelectedIndex()==1) ? false : true; | |||
} | |||
} | |||
public void actionPerformed(ActionEvent e) { | |||
Object s = e.getSource(); | |||
if (s instanceof JButton && (JButton)s == okButton) { | |||
ok = true; | |||
endDialog(); | |||
} else if (s instanceof JButton && (JButton)s == cancelButton) { | |||
ok = false; | |||
endDialog(); | |||
} else if (s instanceof JButton && (JButton)s == optionsButton) { | |||
options.showDialog(); | |||
} else if (s instanceof JButton && (JButton)s == aboutButton) { | |||
cc.showAbout(); | |||
} else if (s instanceof JComboBox && (JComboBox)s == server) { | |||
if (e.getActionCommand().equals("comboBoxEdited")) { | |||
server.insertItemAt(editor.getItem(), 0); | |||
server.setSelectedIndex(0); | |||
ok = true; | |||
endDialog(); | |||
} | |||
} | |||
} | |||
public void endDialog() { | |||
if (ok) { | |||
options.defaults.setPref("encryption",(encryption.getSelectedIndex()==1) ? "off" : "on"); | |||
if (!server.getSelectedItem().toString().equals("")) { | |||
String t = (options.defaults.getString("server")==null) ? "" : options.defaults.getString("server"); | |||
StringTokenizer st = new StringTokenizer(t, ","); | |||
StringBuffer sb = new StringBuffer().append((String)server.getSelectedItem()); | |||
while (st.hasMoreTokens()) { | |||
String s = st.nextToken(); | |||
if (!s.equals((String)server.getSelectedItem()) && !s.equals("")) { | |||
sb.append(','); | |||
sb.append(s); | |||
} | |||
} | |||
options.defaults.setPref("server", sb.toString()); | |||
} | |||
try { | |||
options.defaults.Save(); | |||
} catch (java.lang.Exception x) { } | |||
} | |||
done = true; | |||
if (modal) { | |||
synchronized (this) { | |||
notify(); | |||
} | |||
} | |||
this.dispose(); | |||
} | |||
CConn cc; | |||
JComboBox encryption, server; | |||
ComboBoxEditor editor; | |||
JButton aboutButton, optionsButton, okButton, cancelButton; | |||
OptionsDialog options; | |||
static LogWriter vlog = new LogWriter("ServerDialog"); | |||
} | |||
class ServerDialog extends Dialog implements | |||
ActionListener, | |||
ItemListener | |||
{ | |||
public ServerDialog(OptionsDialog options_, | |||
String defaultServerName, CConn cc_) { | |||
super(true); | |||
cc = cc_; | |||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); | |||
setResizable(false); | |||
setSize(new Dimension(340, 135)); | |||
setTitle("VNC Viewer : Connection Details"); | |||
options = options_; | |||
getContentPane().setLayout(new GridBagLayout()); | |||
JLabel serverLabel = new JLabel("Server:", JLabel.RIGHT); | |||
if (options.defaults.getString("server") != null) { | |||
server = new JComboBox(options.defaults.getString("server").split(",")); | |||
} else { | |||
server = new JComboBox(); | |||
} | |||
// Hack to set the left inset on editable JComboBox | |||
if (UIManager.getLookAndFeel().getID() == "Windows") { | |||
server.setBorder(BorderFactory.createCompoundBorder(server.getBorder(), | |||
BorderFactory.createEmptyBorder(0,2,0,0))); | |||
} else { | |||
ComboBoxEditor editor = server.getEditor(); | |||
JTextField jtf = (JTextField)editor.getEditorComponent(); | |||
jtf.setBorder(new CompoundBorder(jtf.getBorder(), new EmptyBorder(0,2,0,0))); | |||
} | |||
server.setEditable(true); | |||
editor = server.getEditor(); | |||
JLabel encryptionLabel = new JLabel("Encryption:"); | |||
encryption = new JComboBox(); | |||
serverLabel.setPreferredSize(encryptionLabel.getPreferredSize()); | |||
JPanel topPanel = new JPanel(new GridBagLayout()); | |||
addGBComponent(new JLabel(cc.logo),topPanel, 0, 0, 1, 1, 0, 0, 0, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(5,5,5,15)); | |||
addGBComponent(serverLabel,topPanel, 1, 0, 1, 1, 0, 0, 0, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_END, new Insets(10,0,5,5)); | |||
addGBComponent(server,topPanel, 2, 0, 1, 1, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(10,0,5,40)); | |||
optionsButton = new JButton("Options..."); | |||
aboutButton = new JButton("About..."); | |||
okButton = new JButton("OK"); | |||
cancelButton = new JButton("Cancel"); | |||
JPanel buttonPanel = new JPanel(new GridBagLayout()); | |||
buttonPanel.setPreferredSize(new Dimension(340, 40)); | |||
addGBComponent(aboutButton,buttonPanel, 0, 3, 1, 1, 0, 0, 0.2, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(0,5,0,5)); | |||
addGBComponent(optionsButton,buttonPanel, 1, 3, 1, 1, 0, 0, 0, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(0,5,0,5)); | |||
addGBComponent(okButton,buttonPanel, 2, 3, 1, 1, 0, 0, 0.8, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(0,5,0,5)); | |||
addGBComponent(cancelButton,buttonPanel, 3, 3, 1, 1, 0, 0, 0.5, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(0,5,0,5)); | |||
GridBagConstraints gbc = new GridBagConstraints(); | |||
gbc.anchor = GridBagConstraints.LINE_START; | |||
gbc.fill = GridBagConstraints.BOTH; | |||
gbc.gridwidth = GridBagConstraints.REMAINDER; | |||
gbc.gridheight = 1; | |||
gbc.insets = new Insets(0,0,0,0); | |||
gbc.ipadx = 0; | |||
gbc.ipady = 0; | |||
gbc.weightx = 1; | |||
gbc.weighty = 1; | |||
getContentPane().add(topPanel,gbc); | |||
getContentPane().add(buttonPanel); | |||
server.addActionListener(this); | |||
optionsButton.addActionListener(this); | |||
aboutButton.addActionListener(this); | |||
okButton.addActionListener(this); | |||
cancelButton.addActionListener(this); | |||
pack(); | |||
} | |||
public void itemStateChanged(ItemEvent e) { | |||
Object s = e.getSource(); | |||
if (s instanceof JComboBox && (JComboBox)s == encryption) { | |||
options.encryption=(encryption.getSelectedIndex()==1) ? false : true; | |||
} | |||
} | |||
public void actionPerformed(ActionEvent e) { | |||
Object s = e.getSource(); | |||
if (s instanceof JButton && (JButton)s == okButton) { | |||
ok = true; | |||
endDialog(); | |||
} else if (s instanceof JButton && (JButton)s == cancelButton) { | |||
ok = false; | |||
endDialog(); | |||
} else if (s instanceof JButton && (JButton)s == optionsButton) { | |||
options.showDialog(); | |||
} else if (s instanceof JButton && (JButton)s == aboutButton) { | |||
cc.showAbout(); | |||
} else if (s instanceof JComboBox && (JComboBox)s == server) { | |||
if (e.getActionCommand().equals("comboBoxEdited")) { | |||
server.insertItemAt(editor.getItem(), 0); | |||
server.setSelectedIndex(0); | |||
ok = true; | |||
endDialog(); | |||
} | |||
} | |||
} | |||
public void endDialog() { | |||
if (ok) { | |||
options.defaults.setPref("encryption",(encryption.getSelectedIndex()==1) ? "off" : "on"); | |||
if (!server.getSelectedItem().toString().equals("")) { | |||
String t = (options.defaults.getString("server")==null) ? "" : options.defaults.getString("server"); | |||
StringTokenizer st = new StringTokenizer(t, ","); | |||
StringBuffer sb = new StringBuffer().append((String)server.getSelectedItem()); | |||
while (st.hasMoreTokens()) { | |||
String s = st.nextToken(); | |||
if (!s.equals((String)server.getSelectedItem()) && !s.equals("")) { | |||
sb.append(','); | |||
sb.append(s); | |||
} | |||
} | |||
options.defaults.setPref("server", sb.toString()); | |||
} | |||
try { | |||
options.defaults.Save(); | |||
} catch (java.lang.Exception x) { } | |||
} | |||
done = true; | |||
if (modal) { | |||
synchronized (this) { | |||
notify(); | |||
} | |||
} | |||
this.dispose(); | |||
} | |||
CConn cc; | |||
JComboBox encryption, server; | |||
ComboBoxEditor editor; | |||
JButton aboutButton, optionsButton, okButton, cancelButton; | |||
OptionsDialog options; | |||
static LogWriter vlog = new LogWriter("ServerDialog"); | |||
} |