You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2324 lines
62 KiB
2324 lines
62 KiB
diff -Naur JavaViewer.orig/ButtonPanel.java JavaViewer/ButtonPanel.java
|
|
--- JavaViewer.orig/ButtonPanel.java 2004-12-12 20:51:02.000000000 -0500
|
|
+++ JavaViewer/ButtonPanel.java 2007-05-16 15:50:54.000000000 -0400
|
|
@@ -163,9 +163,12 @@
|
|
}
|
|
else if (evt.getSource() == ftpButton)
|
|
{
|
|
+// begin runge/x11vnc
|
|
+ viewer.ftp.setSavedLocations();
|
|
+// end runge/x11vnc
|
|
viewer.ftp.setVisible(!viewer.ftp.isVisible());
|
|
viewer.rfb.readServerDriveList();
|
|
-
|
|
+
|
|
}
|
|
}
|
|
}
|
|
diff -Naur JavaViewer.orig/FTPFrame.java JavaViewer/FTPFrame.java
|
|
--- JavaViewer.orig/FTPFrame.java 2005-03-15 23:53:14.000000000 -0500
|
|
+++ JavaViewer/FTPFrame.java 2007-05-16 16:05:15.000000000 -0400
|
|
@@ -26,6 +26,10 @@
|
|
import java.util.Vector;
|
|
import javax.swing.*;
|
|
|
|
+// begin runge/x11vnc
|
|
+import java.util.Arrays;
|
|
+// end runge/x11vnc
|
|
+
|
|
|
|
/*
|
|
* Created on Feb 25, 2004
|
|
@@ -80,6 +84,17 @@
|
|
private File localSelection = null; // Holds the currently selected local file
|
|
private String remoteSelection = null; // Holds the currently selected remote file
|
|
public String selectedTable = null;
|
|
+
|
|
+// begin runge/x11vnc
|
|
+ private javax.swing.JButton viewButton = null;
|
|
+ public File saveLocalDirectory = null;
|
|
+ public long saveLocalDirectoryTime = 0;
|
|
+ public int saveLocalDirectoryCount = 0;
|
|
+ public String saveRemoteDirectory = null;
|
|
+ public long saveRemoteDirectoryTime = 0;
|
|
+ public int saveRemoteDirectoryCount = 0;
|
|
+ private boolean localCurrentIsDir = true;
|
|
+// end runge/x11vnc
|
|
|
|
// sf@2004 - Separate directories and files for better lisibility
|
|
private ArrayList DirsList;
|
|
@@ -125,11 +140,59 @@
|
|
|
|
void refreshRemoteLocation()
|
|
{
|
|
+
|
|
remoteList.clear();
|
|
remoteFileTable.setListData(remoteList);
|
|
+System.out.println("refreshRemoteLocation '" + remoteLocation.getText() + "'"); // runge/x11vnc
|
|
viewer.rfb.readServerDirectory(remoteLocation.getText());
|
|
}
|
|
|
|
+// begin runge/x11vnc
|
|
+ public void setSavedLocations() {
|
|
+ saveLocalDirectory = currentLocalDirectory;
|
|
+ saveLocalDirectoryTime = System.currentTimeMillis();
|
|
+ saveLocalDirectoryCount = 0;
|
|
+
|
|
+ if (remoteLocation != null) {
|
|
+ saveRemoteDirectory = remoteLocation.getText();
|
|
+System.out.println("RemoteSave '" + saveRemoteDirectory + "'");
|
|
+ }
|
|
+ saveRemoteDirectoryTime = System.currentTimeMillis();
|
|
+ saveRemoteDirectoryCount = 0;
|
|
+ }
|
|
+
|
|
+ private File saveLocalHack(File dir) {
|
|
+ saveLocalDirectoryCount++;
|
|
+System.out.println("L " + saveLocalDirectoryCount + " dt: " + (System.currentTimeMillis() - saveLocalDirectoryTime) + " - " + saveLocalDirectory);
|
|
+ if (System.currentTimeMillis() > saveLocalDirectoryTime + 2000 || saveLocalDirectoryCount > 2) {
|
|
+ saveLocalDirectory = null;
|
|
+ }
|
|
+ if (saveLocalDirectory != null) {
|
|
+ currentLocalDirectory = saveLocalDirectory;
|
|
+ localLocation.setText(saveLocalDirectory.toString());
|
|
+ return saveLocalDirectory;
|
|
+ } else {
|
|
+ return dir;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private String saveRemoteHack(String indrive) {
|
|
+ saveRemoteDirectoryCount++;
|
|
+System.out.println("R " + saveRemoteDirectoryCount + " - " + saveRemoteDirectory);
|
|
+ if (saveRemoteDirectory != null && saveRemoteDirectoryCount > 1) {
|
|
+ saveRemoteDirectory = null;
|
|
+ }
|
|
+ if (saveRemoteDirectory != null) {
|
|
+ if (! saveRemoteDirectory.equals("")) {
|
|
+System.out.println("saveRemoteHack setText + refreshRemoteLocation '" + saveRemoteDirectory + "'");
|
|
+ return saveRemoteDirectory;
|
|
+ }
|
|
+ }
|
|
+ return indrive;
|
|
+ }
|
|
+// end runge/x11vnc
|
|
+
|
|
+
|
|
/*
|
|
* Prints the list of drives on the remote directory and returns a String[].
|
|
* str takes as string like A:fC:lD:lE:lF:lG:cH:c
|
|
@@ -185,6 +248,7 @@
|
|
stopButton.setVisible(true);
|
|
stopButton.setEnabled(true);
|
|
receiveButton.setEnabled(false);
|
|
+ viewButton.setEnabled(false); // runge/x11vnc
|
|
remoteTopButton.setEnabled(false);
|
|
sendButton.setEnabled(false);
|
|
remoteFileTable.setEnabled(false);
|
|
@@ -207,6 +271,7 @@
|
|
stopButton.setVisible(false);
|
|
stopButton.setEnabled(false);
|
|
receiveButton.setEnabled(true);
|
|
+ viewButton.setEnabled(true); // runge/x11vnc
|
|
remoteTopButton.setEnabled(true);
|
|
sendButton.setEnabled(true);
|
|
remoteFileTable.setEnabled(true);
|
|
@@ -405,6 +470,7 @@
|
|
buttonPanel = new javax.swing.JPanel();
|
|
buttonPanel.setLayout(null);
|
|
buttonPanel.add(getReceiveButton(), null);
|
|
+ buttonPanel.add(getViewButton(), null); // runge/x11vnc
|
|
buttonPanel.add(getNewFolderButton(), null);
|
|
buttonPanel.add(getCloseButton(), null);
|
|
buttonPanel.add(getDeleteButton(), null);
|
|
@@ -422,7 +488,7 @@
|
|
private javax.swing.JButton getSendButton() {
|
|
if (sendButton == null) {
|
|
sendButton = new javax.swing.JButton();
|
|
- sendButton.setBounds(20, 30, 97, 25);
|
|
+ sendButton.setBounds(15, 30, 107, 25); // runge/x11vnc
|
|
sendButton.setText("Send >>");
|
|
sendButton.setName("sendButton");
|
|
sendButton.addActionListener(this);
|
|
@@ -438,7 +504,7 @@
|
|
private javax.swing.JButton getReceiveButton() {
|
|
if (receiveButton == null) {
|
|
receiveButton = new javax.swing.JButton();
|
|
- receiveButton.setBounds(20, 60, 97, 25);
|
|
+ receiveButton.setBounds(15, 60, 107, 25); // runge/x11vnc
|
|
receiveButton.setText("<< Receive");
|
|
receiveButton.setName("receiveButton");
|
|
receiveButton.addActionListener(this);
|
|
@@ -453,7 +519,7 @@
|
|
private javax.swing.JButton getDeleteButton() {
|
|
if (deleteButton == null) {
|
|
deleteButton = new javax.swing.JButton();
|
|
- deleteButton.setBounds(20, 110, 97, 25);
|
|
+ deleteButton.setBounds(15, 110, 107, 25); // runge/x11vnc
|
|
deleteButton.setText("Delete File");
|
|
deleteButton.setName("deleteButton");
|
|
deleteButton.addActionListener(this);
|
|
@@ -468,7 +534,7 @@
|
|
private javax.swing.JButton getNewFolderButton() {
|
|
if (newFolderButton == null) {
|
|
newFolderButton = new javax.swing.JButton();
|
|
- newFolderButton.setBounds(20, 140, 97, 25);
|
|
+ newFolderButton.setBounds(15, 140, 107, 25); // runge/x11vnc
|
|
newFolderButton.setText("New Folder");
|
|
newFolderButton.setName("newFolderButton");
|
|
newFolderButton.addActionListener(this);
|
|
@@ -476,6 +542,24 @@
|
|
return newFolderButton;
|
|
}
|
|
|
|
+// begin runge/x11vnc
|
|
+ /**
|
|
+ * This method initializes viewButton
|
|
+ *
|
|
+ * @return javax.swing.JButton
|
|
+ */
|
|
+ private javax.swing.JButton getViewButton() {
|
|
+ if (viewButton == null) {
|
|
+ viewButton = new javax.swing.JButton();
|
|
+ viewButton.setBounds(15, 170, 107, 25);
|
|
+ viewButton.setText("View File");
|
|
+ viewButton.setName("viewButton");
|
|
+ viewButton.addActionListener(this);
|
|
+ }
|
|
+ return viewButton;
|
|
+ }
|
|
+// end runge/x11vnc
|
|
+
|
|
/**
|
|
* This method initializes stopButton
|
|
*
|
|
@@ -486,7 +570,7 @@
|
|
if (stopButton == null)
|
|
{
|
|
stopButton = new javax.swing.JButton();
|
|
- stopButton.setBounds(20, 200, 97, 25);
|
|
+ stopButton.setBounds(15, 200, 107, 25); // runge/x11vnc
|
|
stopButton.setText("Stop");
|
|
stopButton.setName("stopButton");
|
|
stopButton.addActionListener(this);
|
|
@@ -503,7 +587,7 @@
|
|
private javax.swing.JButton getCloseButton() {
|
|
if (closeButton == null) {
|
|
closeButton = new javax.swing.JButton();
|
|
- closeButton.setBounds(20, 325, 97, 25);
|
|
+ closeButton.setBounds(15, 325, 107, 25); // runge/x11vnc
|
|
closeButton.setText("Close");
|
|
closeButton.setName("closeButton");
|
|
closeButton.addActionListener(this);
|
|
@@ -829,12 +913,19 @@
|
|
{
|
|
doReceive();
|
|
}
|
|
+// begin runge/x11vnc
|
|
+ else if (evt.getSource() == viewButton)
|
|
+ {
|
|
+ doView();
|
|
+ }
|
|
+// end runge/x11vnc
|
|
else if (evt.getSource() == localDrivesComboBox)
|
|
{
|
|
changeLocalDrive();
|
|
}
|
|
else if (evt.getSource() == remoteDrivesComboBox)
|
|
{
|
|
+System.out.println("remoteDrivesComboBox"); // runge/x11vnc
|
|
changeRemoteDrive();
|
|
remoteList.clear();
|
|
remoteFileTable.setListData(remoteList);
|
|
@@ -845,6 +936,7 @@
|
|
}
|
|
else if (evt.getSource() == remoteTopButton)
|
|
{
|
|
+System.out.println("remoteTopButton"); // runge/x11vnc
|
|
changeRemoteDrive();
|
|
}
|
|
else if(evt.getSource() == deleteButton)
|
|
@@ -979,6 +1071,56 @@
|
|
viewer.rfb.requestRemoteFile(remoteFileName,localDestinationPath);
|
|
}
|
|
|
|
+// begin runge/x11vnc
|
|
+ private void doView()
|
|
+ {
|
|
+ System.out.println("View Button Pressed");
|
|
+
|
|
+ if (selectedTable == null) {
|
|
+ return;
|
|
+ }
|
|
+ if (selectedTable.equals("remote")) {
|
|
+ viewRemote();
|
|
+ } else if (selectedTable.equals("local")) {
|
|
+ viewLocal();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private File doReceiveTmp()
|
|
+ {
|
|
+
|
|
+ if (remoteFileTable == null) {
|
|
+ return null;
|
|
+ }
|
|
+ String sFileName = ((String) this.remoteFileTable.getSelectedValue());
|
|
+ if (sFileName == null) {
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ // sf@2004 - Directory can't be transfered
|
|
+ if (sFileName.substring(0, 2).equals(" [") && sFileName.substring((sFileName.length() - 1), sFileName.length()).equals("]"))
|
|
+ {
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ File tmp = null;
|
|
+ try {
|
|
+ tmp = File.createTempFile("ULTRAFTP", ".txt");
|
|
+ } catch (Exception e) {
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ //updateHistory("Downloaded " + localSelection.toString());
|
|
+ String remoteFileName = this.remoteLocation.getText();
|
|
+ remoteFileName+= ((String) this.remoteFileTable.getSelectedValue()).substring(1);
|
|
+
|
|
+ String localDestinationPath = tmp.getAbsolutePath();
|
|
+ viewer.rfb.requestRemoteFile(remoteFileName,localDestinationPath);
|
|
+ System.out.println("ReceiveTmp: " + localDestinationPath);
|
|
+ return tmp;
|
|
+ }
|
|
+// end runge/x11vnc
|
|
+
|
|
private void doSend()
|
|
{
|
|
System.out.println("Send Button Pressed");
|
|
@@ -1035,8 +1177,11 @@
|
|
|
|
if (!updateDriveList) {
|
|
String drive = remoteDrivesComboBox.getSelectedItem().toString().substring(0,1)+ ":\\";
|
|
+System.out.println("changeRemoteDrive-A " + drive); // runge/x11vnc
|
|
+ drive = saveRemoteHack(drive);
|
|
viewer.rfb.readServerDirectory(drive);
|
|
remoteLocation.setText(drive);
|
|
+System.out.println("changeRemoteDrive-B " + drive); // runge/x11vnc
|
|
}
|
|
remoteList.clear();
|
|
remoteFileTable.setListData(remoteList);
|
|
@@ -1048,6 +1193,7 @@
|
|
private void changeLocalDrive()
|
|
{
|
|
File currentDrive = new File(localDrivesComboBox.getSelectedItem().toString());
|
|
+System.out.println("changeLocalDrive " + currentDrive.toString()); // runge/x11vnc
|
|
if(currentDrive.canRead())
|
|
{
|
|
localSelection = null;
|
|
@@ -1060,6 +1206,7 @@
|
|
localStatus.setText("WARNING: Drive " + localDrivesComboBox.getSelectedItem().toString());
|
|
connectionStatus.setText(" > WARNING - Local Drive unavailable (possibly restricted access or media not present)");
|
|
}
|
|
+
|
|
}
|
|
/**
|
|
* Determines which FileTable was double-clicked and updates the table
|
|
@@ -1101,7 +1248,7 @@
|
|
String name = (remoteFileTable.getSelectedValue().toString()).substring(1);
|
|
if( !name.substring(0, 2).equals(" ["))
|
|
remoteSelection = remoteLocation.getText() + name.substring(0, name.length());
|
|
-
|
|
+
|
|
}
|
|
|
|
/*
|
|
@@ -1115,10 +1262,38 @@
|
|
localFileTable.setBackground(new Color(255, 255, 255));
|
|
File currentSelection = new File(currentLocalDirectory, getTrimmedSelection());
|
|
|
|
- if(currentSelection.isFile())
|
|
+// begin runge/x11vnc
|
|
+ // localSelection = currentSelection.getAbsoluteFile();
|
|
+ if(currentSelection.isFile()) {
|
|
localSelection = currentSelection.getAbsoluteFile();
|
|
+ localCurrentIsDir = false;
|
|
+ } else {
|
|
+ localCurrentIsDir = true;
|
|
+ }
|
|
+// end runge/x11vnc
|
|
|
|
}
|
|
+
|
|
+// begin runge/x11vnc
|
|
+ private void viewRemote() {
|
|
+ File tmp = doReceiveTmp();
|
|
+ if (tmp == null) {
|
|
+ return;
|
|
+ }
|
|
+ TextViewer tv = new TextViewer("Remote: " + remoteSelection, tmp, true);
|
|
+ }
|
|
+ private void viewLocal() {
|
|
+ if (localSelection == null) {
|
|
+ return;
|
|
+ }
|
|
+ if (localCurrentIsDir) {
|
|
+ return;
|
|
+ }
|
|
+ File loc = new File(localSelection.toString());
|
|
+ TextViewer tv = new TextViewer("Local: " + localSelection.toString(), loc, false);
|
|
+ }
|
|
+// end runge/x11vnc
|
|
+
|
|
/**
|
|
* Updates the Remote File Table based on selection. Called from mouseClicked handler
|
|
*/
|
|
@@ -1149,6 +1324,7 @@
|
|
remoteSelection = remoteLocation.getText() + name.substring(0, name.length());
|
|
drive = remoteLocation.getText();
|
|
// ??
|
|
+ viewRemote(); // runge/x11vnc
|
|
}
|
|
else
|
|
{
|
|
@@ -1163,6 +1339,7 @@
|
|
}
|
|
//remoteLocation.setText(drive);
|
|
}
|
|
+
|
|
/**
|
|
* Updates the Local File Table based on selection. Called from MouseClicked handler
|
|
*/
|
|
@@ -1188,6 +1365,7 @@
|
|
else if (currentSelection.isFile())
|
|
{
|
|
localSelection = currentSelection.getAbsoluteFile();
|
|
+ viewLocal(); // runge/x11vnc
|
|
}
|
|
else if (currentSelection.isDirectory())
|
|
{
|
|
@@ -1247,9 +1425,20 @@
|
|
*/
|
|
public void changeLocalDirectory(File dir)
|
|
{
|
|
+ dir = saveLocalHack(dir); // runge/x11vnc
|
|
+
|
|
currentLocalDirectory = dir; // Updates Global
|
|
File allFiles[] = dir.listFiles(); // Reads files
|
|
String[] contents = dir.list();
|
|
+// begin runge/x11vnc
|
|
+System.out.println("changeLocalDirectory: " + dir.toString());
|
|
+ if (contents != null) {
|
|
+ java.util.Arrays.sort(contents, String.CASE_INSENSITIVE_ORDER);
|
|
+ for (int i = 0; i < contents.length; i++) {
|
|
+ allFiles[i] = new File(dir, contents[i]);
|
|
+ }
|
|
+ }
|
|
+// end runge/x11vnc
|
|
|
|
localList.clear();
|
|
localList.addElement(" [..]");
|
|
@@ -1296,3 +1485,135 @@
|
|
}
|
|
|
|
} // @jve:visual-info decl-index=0 visual-constraint="10,10"
|
|
+
|
|
+// begin runge/x11vnc
|
|
+class TextViewer extends JFrame implements ActionListener {
|
|
+
|
|
+ JTextArea textArea = new JTextArea(35, 80);
|
|
+ File file = null;
|
|
+ JButton refreshButton;
|
|
+ JButton dismissButton;
|
|
+ Timer tim = null;
|
|
+ int rcnt = 0;
|
|
+ int tms = 250;
|
|
+ boolean delete_it = false;
|
|
+
|
|
+ public TextViewer(String s, File f, boolean d) {
|
|
+
|
|
+ delete_it = d;
|
|
+ file = f;
|
|
+
|
|
+ JScrollPane scrollPane = new JScrollPane(textArea,
|
|
+ JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
|
|
+ JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
|
|
+
|
|
+ textArea.setEditable(false);
|
|
+ textArea.setFont(new Font("Monospaced", Font.PLAIN, 12));
|
|
+
|
|
+
|
|
+ refreshButton = new JButton();
|
|
+ refreshButton.setText("Reload");
|
|
+ refreshButton.setName("refreshButton");
|
|
+ refreshButton.addActionListener(this);
|
|
+
|
|
+ dismissButton = new JButton();
|
|
+ dismissButton.setText("Dismiss");
|
|
+ dismissButton.setName("dismissButton");
|
|
+ dismissButton.addActionListener(this);
|
|
+
|
|
+ JPanel buttons = new JPanel();
|
|
+ buttons.setLayout(new BorderLayout());
|
|
+ buttons.add(refreshButton, BorderLayout.WEST);
|
|
+ buttons.add(dismissButton, BorderLayout.EAST);
|
|
+
|
|
+ JPanel content = new JPanel();
|
|
+ content.setLayout(new BorderLayout());
|
|
+ content.add(scrollPane, BorderLayout.CENTER);
|
|
+ content.add(buttons, BorderLayout.SOUTH);
|
|
+
|
|
+ ActionListener tsk = new ActionListener() {
|
|
+ public void actionPerformed(ActionEvent evt) {
|
|
+ // System.out.println("tsk");
|
|
+ refresh();
|
|
+ }
|
|
+ };
|
|
+ tim = new Timer(tms, tsk);
|
|
+ tim.start();
|
|
+
|
|
+ this.setContentPane(content);
|
|
+ this.setTitle("TextViewer - " + s);
|
|
+ this.pack();
|
|
+ this.setVisible(true);
|
|
+ }
|
|
+
|
|
+ private void refresh() {
|
|
+
|
|
+ rcnt++;
|
|
+ if (rcnt * tms > 3000 && tim != null) {
|
|
+ tim.stop();
|
|
+ tim = null;
|
|
+ }
|
|
+ BufferedReader input = null;
|
|
+ StringBuffer contents = new StringBuffer();
|
|
+ try {
|
|
+ if (input == null) {
|
|
+ input = new BufferedReader(new FileReader(file));
|
|
+ }
|
|
+ String line = null;
|
|
+ int i = 0;
|
|
+ while (( line = input.readLine()) != null) {
|
|
+ if (i == 0) {
|
|
+ // System.out.println("read");
|
|
+ }
|
|
+ i++;
|
|
+ contents.append(line);
|
|
+ contents.append(System.getProperty("line.separator"));
|
|
+ }
|
|
+ } catch (Exception e) {
|
|
+ ;
|
|
+ } finally {
|
|
+ try {
|
|
+ if (input != null) {
|
|
+ input.close();
|
|
+ input = null;
|
|
+ }
|
|
+ } catch (Exception e) {
|
|
+ ;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ textArea.setText(contents.toString());
|
|
+ textArea.setCaretPosition(0);
|
|
+ }
|
|
+
|
|
+ public void actionPerformed(ActionEvent evt) {
|
|
+
|
|
+ if (evt.getSource() == refreshButton) {
|
|
+ refresh();
|
|
+ }
|
|
+ if (evt.getSource() == dismissButton) {
|
|
+ cleanse();
|
|
+ this.dispose();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private void cleanse() {
|
|
+ if (delete_it && file != null) {
|
|
+ try {
|
|
+ file.delete();
|
|
+ file = null;
|
|
+ } catch (Exception e) {
|
|
+ ;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ protected void finalize() throws Throwable {
|
|
+ try {
|
|
+ cleanse();
|
|
+ } finally {
|
|
+ super.finalize();
|
|
+ }
|
|
+ }
|
|
+}
|
|
+// end runge/x11vnc
|
|
diff -Naur JavaViewer.orig/OptionsFrame.java JavaViewer/OptionsFrame.java
|
|
--- JavaViewer.orig/OptionsFrame.java 2005-11-21 18:50:16.000000000 -0500
|
|
+++ JavaViewer/OptionsFrame.java 2007-05-13 22:18:30.000000000 -0400
|
|
@@ -144,7 +144,10 @@
|
|
choices[jpegQualityIndex].select("6");
|
|
choices[cursorUpdatesIndex].select("Enable");
|
|
choices[useCopyRectIndex].select("Yes");
|
|
- choices[eightBitColorsIndex].select("64");
|
|
+// begin runge/x11vnc
|
|
+// choices[eightBitColorsIndex].select("64");
|
|
+ choices[eightBitColorsIndex].select("Full");
|
|
+// end runge/x11vnc
|
|
choices[mouseButtonIndex].select("Normal");
|
|
choices[viewOnlyIndex].select("No");
|
|
choices[shareDesktopIndex].select("Yes");
|
|
diff -Naur JavaViewer.orig/RfbProto.java JavaViewer/RfbProto.java
|
|
--- JavaViewer.orig/RfbProto.java 2006-05-24 15:14:40.000000000 -0400
|
|
+++ JavaViewer/RfbProto.java 2007-05-16 15:57:07.000000000 -0400
|
|
@@ -199,6 +199,10 @@
|
|
// playback.
|
|
int numUpdatesInSession;
|
|
|
|
+// begin runge/x11vnc
|
|
+ int readServerDriveListCnt = -1;
|
|
+ long readServerDriveListTime = 0;
|
|
+// end runge/x11vnc
|
|
//
|
|
// Constructor. Make TCP connection to RFB server.
|
|
//
|
|
@@ -207,7 +211,27 @@
|
|
viewer = v;
|
|
host = h;
|
|
port = p;
|
|
- sock = new Socket(host, port);
|
|
+// begin runge/x11vnc
|
|
+// sock = new Socket(host, port);
|
|
+ if (! viewer.disableSSL) {
|
|
+ System.out.println("new SSLSocketToMe");
|
|
+ SSLSocketToMe ssl;
|
|
+ try {
|
|
+ ssl = new SSLSocketToMe(host, port, v);
|
|
+ } catch (Exception e) {
|
|
+ throw new IOException(e.getMessage());
|
|
+ }
|
|
+
|
|
+ try {
|
|
+ sock = ssl.connectSock();
|
|
+ } catch (Exception es) {
|
|
+ throw new IOException(es.getMessage());
|
|
+ }
|
|
+ } else {
|
|
+ sock = new Socket(host, port);
|
|
+ }
|
|
+// end runge/x11vnc
|
|
+
|
|
is =
|
|
new DataInputStream(
|
|
new BufferedInputStream(sock.getInputStream(), 16384));
|
|
@@ -1263,11 +1287,47 @@
|
|
|| dwFileAttributes == 369623040)
|
|
{
|
|
fileName = " [" + fileName + "]";
|
|
- remoteDirsList.add(fileName); // sf@2004
|
|
+// begin runge/x11vnc
|
|
+// remoteDirsList.add(fileName); // sf@2004
|
|
+ int i = -1;
|
|
+ String t1 = fileName.toLowerCase();
|
|
+ for (int j = 0; j < remoteDirsList.size(); j++) {
|
|
+ String t = (String) remoteDirsList.get(j);
|
|
+ String t2 = t.toLowerCase();
|
|
+ if (t1.compareTo(t2) < 0) {
|
|
+ i = j;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (i >= 0) {
|
|
+ remoteDirsList.add(i, fileName);
|
|
+ } else {
|
|
+ remoteDirsList.add(fileName);
|
|
+ }
|
|
+// end runge/x11vnc
|
|
}
|
|
else
|
|
{
|
|
- remoteFilesList.add(" " + fileName); // sf@2004
|
|
+// begin runge/x11vnc
|
|
+// remoteFilesList.add(" " + fileName); // sf@2004
|
|
+
|
|
+ fileName = " " + fileName;
|
|
+ int i = -1;
|
|
+ String t1 = fileName.toLowerCase();
|
|
+ for (int j = 0; j < remoteFilesList.size(); j++) {
|
|
+ String t = (String) remoteFilesList.get(j);
|
|
+ String t2 = t.toLowerCase();
|
|
+ if (t1.compareTo(t2) < 0) {
|
|
+ i = j;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (i >= 0) {
|
|
+ remoteFilesList.add(i, fileName);
|
|
+ } else {
|
|
+ remoteFilesList.add(fileName);
|
|
+ }
|
|
+// end runge/x11vnc
|
|
}
|
|
|
|
// a.add(fileName);
|
|
@@ -1289,6 +1349,16 @@
|
|
remoteDirsList.clear();
|
|
remoteFilesList.clear();
|
|
|
|
+// begin runge/x11vnc
|
|
+ // Hack for double listing at startup... probably libvncserver bug..
|
|
+ readServerDriveListCnt++;
|
|
+ if (readServerDriveListCnt == 2) {
|
|
+ if (System.currentTimeMillis() - readServerDriveListTime < 1500) {
|
|
+System.out.println("readServerDriveListCnt skip " + readServerDriveListCnt);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+// end runge/x11vnc
|
|
viewer.ftp.printDirectory(a);
|
|
}
|
|
|
|
@@ -1312,6 +1382,10 @@
|
|
0,
|
|
0,
|
|
null);
|
|
+// begin runge/x11vnc
|
|
+ readServerDriveListCnt = 0;
|
|
+ readServerDriveListTime = System.currentTimeMillis();
|
|
+// end runge/x11vnc
|
|
}
|
|
catch (IOException e)
|
|
{
|
|
diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java
|
|
--- JavaViewer.orig/SSLSocketToMe.java 1969-12-31 19:00:00.000000000 -0500
|
|
+++ JavaViewer/SSLSocketToMe.java 2007-04-29 20:40:35.000000000 -0400
|
|
@@ -0,0 +1,1421 @@
|
|
+/*
|
|
+ * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer.
|
|
+ *
|
|
+ * Copyright (c) 2006 Karl J. Runge <runge@karlrunge.com>
|
|
+ * 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; version 2 of the License.
|
|
+ *
|
|
+ * 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.
|
|
+ *
|
|
+ */
|
|
+
|
|
+import java.net.*;
|
|
+import java.io.*;
|
|
+import javax.net.ssl.*;
|
|
+import java.util.*;
|
|
+
|
|
+import java.security.*;
|
|
+import java.security.cert.*;
|
|
+import java.security.spec.*;
|
|
+import java.security.cert.Certificate;
|
|
+import java.security.cert.CertificateFactory;
|
|
+
|
|
+import java.awt.*;
|
|
+import java.awt.event.*;
|
|
+
|
|
+public class SSLSocketToMe {
|
|
+
|
|
+ /* basic member data: */
|
|
+ String host;
|
|
+ int port;
|
|
+ VncViewer viewer;
|
|
+ boolean debug = true;
|
|
+
|
|
+ /* sockets */
|
|
+ SSLSocket socket = null;
|
|
+ SSLSocketFactory factory;
|
|
+
|
|
+ /* fallback for Proxy connection */
|
|
+ boolean proxy_in_use = false;
|
|
+ boolean proxy_is_https = false;
|
|
+ boolean proxy_failure = false;
|
|
+ public DataInputStream is = null;
|
|
+ public OutputStream os = null;
|
|
+
|
|
+ String proxy_dialog_host = null;
|
|
+ int proxy_dialog_port = 0;
|
|
+
|
|
+ Socket proxySock;
|
|
+ DataInputStream proxy_is;
|
|
+ OutputStream proxy_os;
|
|
+
|
|
+ /* trust contexts */
|
|
+ SSLContext trustloc_ctx;
|
|
+ SSLContext trustall_ctx;
|
|
+ SSLContext trusturl_ctx;
|
|
+ SSLContext trustone_ctx;
|
|
+
|
|
+ TrustManager[] trustAllCerts;
|
|
+ TrustManager[] trustUrlCert;
|
|
+ TrustManager[] trustOneCert;
|
|
+
|
|
+ boolean use_url_cert_for_auth = true;
|
|
+ boolean user_wants_to_see_cert = true;
|
|
+
|
|
+ /* cert(s) we retrieve from VNC server */
|
|
+ java.security.cert.Certificate[] trustallCerts = null;
|
|
+ java.security.cert.Certificate[] trusturlCerts = null;
|
|
+
|
|
+ byte[] hex2bytes(String s) {
|
|
+ byte[] bytes = new byte[s.length()/2];
|
|
+ for (int i=0; i<s.length()/2; i++) {
|
|
+ int j = 2*i;
|
|
+ try {
|
|
+ int val = Integer.parseInt(s.substring(j, j+2), 16);
|
|
+ if (val > 127) {
|
|
+ val -= 256;
|
|
+ }
|
|
+ Integer I = new Integer(val);
|
|
+ bytes[i] = Byte.decode(I.toString()).byteValue();
|
|
+
|
|
+ } catch (Exception e) {
|
|
+ ;
|
|
+ }
|
|
+ }
|
|
+ return bytes;
|
|
+ }
|
|
+
|
|
+ SSLSocketToMe(String h, int p, VncViewer v) throws Exception {
|
|
+ host = h;
|
|
+ port = p;
|
|
+ viewer = v;
|
|
+
|
|
+ /* we will first try default factory for certification: */
|
|
+
|
|
+ factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
|
|
+
|
|
+ dbg("SSL startup: " + host + " " + port);
|
|
+
|
|
+ /* create trust managers used if initial handshake fails: */
|
|
+
|
|
+ trustAllCerts = new TrustManager[] {
|
|
+ /*
|
|
+ * this one accepts everything.
|
|
+ */
|
|
+ new X509TrustManager() {
|
|
+ public java.security.cert.X509Certificate[]
|
|
+ getAcceptedIssuers() {
|
|
+ return null;
|
|
+ }
|
|
+ public void checkClientTrusted(
|
|
+ java.security.cert.X509Certificate[] certs,
|
|
+ String authType) {
|
|
+ /* empty */
|
|
+ }
|
|
+ public void checkServerTrusted(
|
|
+ java.security.cert.X509Certificate[] certs,
|
|
+ String authType) {
|
|
+ /* empty */
|
|
+ dbg("ALL: an untrusted connect to grab cert.");
|
|
+ }
|
|
+ }
|
|
+ };
|
|
+
|
|
+ trustUrlCert = new TrustManager[] {
|
|
+ /*
|
|
+ * this one accepts only the retrieved server cert
|
|
+ * by SSLSocket by this applet.
|
|
+ */
|
|
+ new X509TrustManager() {
|
|
+ public java.security.cert.X509Certificate[]
|
|
+ getAcceptedIssuers() {
|
|
+ return null;
|
|
+ }
|
|
+ public void checkClientTrusted(
|
|
+ java.security.cert.X509Certificate[] certs,
|
|
+ String authType) throws CertificateException {
|
|
+ throw new CertificateException("No Clients");
|
|
+ }
|
|
+ public void checkServerTrusted(
|
|
+ java.security.cert.X509Certificate[] certs,
|
|
+ String authType) throws CertificateException {
|
|
+ if (trusturlCerts == null) {
|
|
+ throw new CertificateException(
|
|
+ "No Trust url Certs array.");
|
|
+ }
|
|
+ if (trusturlCerts.length < 1) {
|
|
+ throw new CertificateException(
|
|
+ "No Trust url Certs.");
|
|
+ }
|
|
+ if (trusturlCerts.length > 1) {
|
|
+ int i;
|
|
+ boolean ok = true;
|
|
+ for (i = 0; i < trusturlCerts.length - 1; i++) {
|
|
+ if (! trusturlCerts[i].equals(trusturlCerts[i+1])) {
|
|
+ ok = false;
|
|
+ }
|
|
+ }
|
|
+ if (! ok) {
|
|
+ throw new CertificateException(
|
|
+ "Too many Trust url Certs: "
|
|
+ + trusturlCerts.length
|
|
+ );
|
|
+ }
|
|
+ }
|
|
+ if (certs == null) {
|
|
+ throw new CertificateException(
|
|
+ "No this-certs array.");
|
|
+ }
|
|
+ if (certs.length < 1) {
|
|
+ throw new CertificateException(
|
|
+ "No this-certs Certs.");
|
|
+ }
|
|
+ if (certs.length > 1) {
|
|
+ int i;
|
|
+ boolean ok = true;
|
|
+ for (i = 0; i < certs.length - 1; i++) {
|
|
+ if (! certs[i].equals(certs[i+1])) {
|
|
+ ok = false;
|
|
+ }
|
|
+ }
|
|
+ if (! ok) {
|
|
+ throw new CertificateException(
|
|
+ "Too many this-certs: "
|
|
+ + certs.length
|
|
+ );
|
|
+ }
|
|
+ }
|
|
+ if (! trusturlCerts[0].equals(certs[0])) {
|
|
+ throw new CertificateException(
|
|
+ "Server Cert Changed != URL.");
|
|
+ }
|
|
+ dbg("URL: trusturlCerts[0] matches certs[0]");
|
|
+ }
|
|
+ }
|
|
+ };
|
|
+ trustOneCert = new TrustManager[] {
|
|
+ /*
|
|
+ * this one accepts only the retrieved server cert
|
|
+ * by SSLSocket by this applet.
|
|
+ */
|
|
+ new X509TrustManager() {
|
|
+ public java.security.cert.X509Certificate[]
|
|
+ getAcceptedIssuers() {
|
|
+ return null;
|
|
+ }
|
|
+ public void checkClientTrusted(
|
|
+ java.security.cert.X509Certificate[] certs,
|
|
+ String authType) throws CertificateException {
|
|
+ throw new CertificateException("No Clients");
|
|
+ }
|
|
+ public void checkServerTrusted(
|
|
+ java.security.cert.X509Certificate[] certs,
|
|
+ String authType) throws CertificateException {
|
|
+ if (trustallCerts == null) {
|
|
+ throw new CertificateException(
|
|
+ "No Trust All Server Certs array.");
|
|
+ }
|
|
+ if (trustallCerts.length < 1) {
|
|
+ throw new CertificateException(
|
|
+ "No Trust All Server Certs.");
|
|
+ }
|
|
+ if (trustallCerts.length > 1) {
|
|
+ int i;
|
|
+ boolean ok = true;
|
|
+ for (i = 0; i < trustallCerts.length - 1; i++) {
|
|
+ if (! trustallCerts[i].equals(trustallCerts[i+1])) {
|
|
+ ok = false;
|
|
+ }
|
|
+ }
|
|
+ if (! ok) {
|
|
+ throw new CertificateException(
|
|
+ "Too many Trust All Server Certs: "
|
|
+ + trustallCerts.length
|
|
+ );
|
|
+ }
|
|
+ }
|
|
+ if (certs == null) {
|
|
+ throw new CertificateException(
|
|
+ "No this-certs array.");
|
|
+ }
|
|
+ if (certs.length < 1) {
|
|
+ throw new CertificateException(
|
|
+ "No this-certs Certs.");
|
|
+ }
|
|
+ if (certs.length > 1) {
|
|
+ int i;
|
|
+ boolean ok = true;
|
|
+ for (i = 0; i < certs.length - 1; i++) {
|
|
+ if (! certs[i].equals(certs[i+1])) {
|
|
+ ok = false;
|
|
+ }
|
|
+ }
|
|
+ if (! ok) {
|
|
+ throw new CertificateException(
|
|
+ "Too many this-certs: "
|
|
+ + certs.length
|
|
+ );
|
|
+ }
|
|
+ }
|
|
+ if (! trustallCerts[0].equals(certs[0])) {
|
|
+ throw new CertificateException(
|
|
+ "Server Cert Changed != TRUSTALL.");
|
|
+ }
|
|
+ dbg("ONE: trustallCerts[0] matches certs[0]");
|
|
+ }
|
|
+ }
|
|
+ };
|
|
+
|
|
+ /*
|
|
+ * They are used:
|
|
+ *
|
|
+ * 1) to retrieve the server cert in case of failure to
|
|
+ * display it to the user.
|
|
+ * 2) to subsequently connect to the server if user agrees.
|
|
+ */
|
|
+
|
|
+ KeyManager[] mykey = null;
|
|
+
|
|
+ if (viewer.oneTimeKey != null && viewer.oneTimeKey.equals("PROMPT")) {
|
|
+ ClientCertDialog d = new ClientCertDialog();
|
|
+ viewer.oneTimeKey = d.queryUser();
|
|
+ }
|
|
+
|
|
+ if (viewer.oneTimeKey != null && viewer.oneTimeKey.indexOf(",") > 0) {
|
|
+ int idx = viewer.oneTimeKey.indexOf(",");
|
|
+
|
|
+ String onetimekey = viewer.oneTimeKey.substring(0, idx);
|
|
+ byte[] key = hex2bytes(onetimekey);
|
|
+ String onetimecert = viewer.oneTimeKey.substring(idx+1);
|
|
+ byte[] cert = hex2bytes(onetimecert);
|
|
+
|
|
+ KeyFactory kf = KeyFactory.getInstance("RSA");
|
|
+ PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec ( key );
|
|
+ PrivateKey ff = kf.generatePrivate (keysp);
|
|
+ //dbg("ff " + ff);
|
|
+ String cert_str = new String(cert);
|
|
+
|
|
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
|
+ Collection c = cf.generateCertificates(new ByteArrayInputStream(cert));
|
|
+ Certificate[] certs = new Certificate[c.toArray().length];
|
|
+ if (c.size() == 1) {
|
|
+ Certificate tmpcert = cf.generateCertificate(new ByteArrayInputStream(cert));
|
|
+ //dbg("tmpcert" + tmpcert);
|
|
+ certs[0] = tmpcert;
|
|
+ } else {
|
|
+ certs = (Certificate[]) c.toArray();
|
|
+ }
|
|
+
|
|
+ KeyStore ks = KeyStore.getInstance("JKS");
|
|
+ ks.load(null, null);
|
|
+ ks.setKeyEntry("onetimekey", ff, "".toCharArray(), certs);
|
|
+ String da = KeyManagerFactory.getDefaultAlgorithm();
|
|
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(da);
|
|
+ kmf.init(ks, "".toCharArray());
|
|
+
|
|
+ mykey = kmf.getKeyManagers();
|
|
+ }
|
|
+
|
|
+
|
|
+ /* trust loc certs: */
|
|
+ try {
|
|
+ trustloc_ctx = SSLContext.getInstance("SSL");
|
|
+ trustloc_ctx.init(mykey, null, new
|
|
+ java.security.SecureRandom());
|
|
+
|
|
+ } catch (Exception e) {
|
|
+ String msg = "SSL trustloc_ctx FAILED.";
|
|
+ dbg(msg);
|
|
+ throw new Exception(msg);
|
|
+ }
|
|
+
|
|
+ /* trust all certs: */
|
|
+ try {
|
|
+ trustall_ctx = SSLContext.getInstance("SSL");
|
|
+ trustall_ctx.init(mykey, trustAllCerts, new
|
|
+ java.security.SecureRandom());
|
|
+
|
|
+ } catch (Exception e) {
|
|
+ String msg = "SSL trustall_ctx FAILED.";
|
|
+ dbg(msg);
|
|
+ throw new Exception(msg);
|
|
+ }
|
|
+
|
|
+ /* trust url certs: */
|
|
+ try {
|
|
+ trusturl_ctx = SSLContext.getInstance("SSL");
|
|
+ trusturl_ctx.init(mykey, trustUrlCert, new
|
|
+ java.security.SecureRandom());
|
|
+
|
|
+ } catch (Exception e) {
|
|
+ String msg = "SSL trusturl_ctx FAILED.";
|
|
+ dbg(msg);
|
|
+ throw new Exception(msg);
|
|
+ }
|
|
+
|
|
+ /* trust the one cert from server: */
|
|
+ try {
|
|
+ trustone_ctx = SSLContext.getInstance("SSL");
|
|
+ trustone_ctx.init(mykey, trustOneCert, new
|
|
+ java.security.SecureRandom());
|
|
+
|
|
+ } catch (Exception e) {
|
|
+ String msg = "SSL trustone_ctx FAILED.";
|
|
+ dbg(msg);
|
|
+ throw new Exception(msg);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ boolean browser_cert_match() {
|
|
+ String msg = "Browser URL accept previously accepted cert";
|
|
+
|
|
+ if (user_wants_to_see_cert) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (trustallCerts != null && trusturlCerts != null) {
|
|
+ if (trustallCerts.length == 1 && trusturlCerts.length == 1) {
|
|
+ if (trustallCerts[0].equals(trusturlCerts[0])) {
|
|
+ System.out.println(msg);
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ public void check_for_proxy() {
|
|
+
|
|
+ boolean result = false;
|
|
+
|
|
+ trusturlCerts = null;
|
|
+ proxy_in_use = false;
|
|
+ if (viewer.ignoreProxy) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ String ustr = "https://" + host + ":";
|
|
+ if (viewer.httpsPort != null) {
|
|
+ ustr += viewer.httpsPort;
|
|
+ } else {
|
|
+ ustr += port; // hmmm
|
|
+ }
|
|
+ ustr += viewer.urlPrefix + "/check.https.proxy.connection";
|
|
+ dbg("ustr is: " + ustr);
|
|
+
|
|
+
|
|
+ try {
|
|
+ URL url = new URL(ustr);
|
|
+ HttpsURLConnection https = (HttpsURLConnection)
|
|
+ url.openConnection();
|
|
+
|
|
+ https.setUseCaches(false);
|
|
+ https.setRequestMethod("GET");
|
|
+ https.setRequestProperty("Pragma", "No-Cache");
|
|
+ https.setRequestProperty("Proxy-Connection",
|
|
+ "Keep-Alive");
|
|
+ https.setDoInput(true);
|
|
+
|
|
+ https.connect();
|
|
+
|
|
+ trusturlCerts = https.getServerCertificates();
|
|
+ if (trusturlCerts == null) {
|
|
+ dbg("set trusturlCerts to null...");
|
|
+ } else {
|
|
+ dbg("set trusturlCerts to non-null");
|
|
+ }
|
|
+
|
|
+ if (https.usingProxy()) {
|
|
+ proxy_in_use = true;
|
|
+ proxy_is_https = true;
|
|
+ dbg("HTTPS proxy in use. There may be connection problems.");
|
|
+ }
|
|
+ Object output = https.getContent();
|
|
+ https.disconnect();
|
|
+ result = true;
|
|
+
|
|
+ } catch(Exception e) {
|
|
+ dbg("HttpsURLConnection: " + e.getMessage());
|
|
+ }
|
|
+
|
|
+ if (proxy_in_use) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ ustr = "http://" + host + ":" + port;
|
|
+ ustr += viewer.urlPrefix + "/index.vnc";
|
|
+
|
|
+ try {
|
|
+ URL url = new URL(ustr);
|
|
+ HttpURLConnection http = (HttpURLConnection)
|
|
+ url.openConnection();
|
|
+
|
|
+ http.setUseCaches(false);
|
|
+ http.setRequestMethod("GET");
|
|
+ http.setRequestProperty("Pragma", "No-Cache");
|
|
+ http.setRequestProperty("Proxy-Connection",
|
|
+ "Keep-Alive");
|
|
+ http.setDoInput(true);
|
|
+
|
|
+ http.connect();
|
|
+
|
|
+ if (http.usingProxy()) {
|
|
+ proxy_in_use = true;
|
|
+ proxy_is_https = false;
|
|
+ dbg("HTTP proxy in use. There may be connection problems.");
|
|
+ }
|
|
+ Object output = http.getContent();
|
|
+ http.disconnect();
|
|
+
|
|
+ } catch(Exception e) {
|
|
+ dbg("HttpURLConnection: " + e.getMessage());
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public Socket connectSock() throws IOException {
|
|
+
|
|
+ /*
|
|
+ * first try a https connection to detect a proxy, and
|
|
+ * also grab the VNC server cert.
|
|
+ */
|
|
+ check_for_proxy();
|
|
+
|
|
+ if (viewer.trustAllVncCerts) {
|
|
+ dbg("viewer.trustAllVncCerts-0 using trustall_ctx");
|
|
+ factory = trustall_ctx.getSocketFactory();
|
|
+ } else if (use_url_cert_for_auth && trusturlCerts != null) {
|
|
+ dbg("using trusturl_ctx");
|
|
+ factory = trusturl_ctx.getSocketFactory();
|
|
+ } else {
|
|
+ dbg("using trustloc_ctx");
|
|
+ factory = trustloc_ctx.getSocketFactory();
|
|
+ }
|
|
+
|
|
+ socket = null;
|
|
+ try {
|
|
+ if (proxy_in_use && viewer.forceProxy) {
|
|
+ throw new Exception("forcing proxy (forceProxy)");
|
|
+ } else if (viewer.CONNECT != null) {
|
|
+ throw new Exception("forcing CONNECT");
|
|
+ }
|
|
+
|
|
+ socket = (SSLSocket) factory.createSocket(host, port);
|
|
+
|
|
+ } catch (Exception esock) {
|
|
+ dbg("esock: " + esock.getMessage());
|
|
+ if (proxy_in_use || viewer.CONNECT != null) {
|
|
+ proxy_failure = true;
|
|
+ if (proxy_in_use) {
|
|
+ dbg("HTTPS proxy in use. Trying to go with it.");
|
|
+ } else {
|
|
+ dbg("viewer.CONNECT reverse proxy in use. Trying to go with it.");
|
|
+ }
|
|
+ try {
|
|
+ socket = proxy_socket(factory);
|
|
+ } catch (Exception e) {
|
|
+ dbg("err proxy_socket: " + e.getMessage());
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ try {
|
|
+ socket.startHandshake();
|
|
+ dbg("Server Connection Verified on 1st try.");
|
|
+
|
|
+ java.security.cert.Certificate[] currentTrustedCerts;
|
|
+ BrowserCertsDialog bcd;
|
|
+
|
|
+ SSLSession sess = socket.getSession();
|
|
+ currentTrustedCerts = sess.getPeerCertificates();
|
|
+
|
|
+ if (viewer.trustAllVncCerts) {
|
|
+ dbg("viewer.trustAllVncCerts-1");
|
|
+ } else if (currentTrustedCerts == null || currentTrustedCerts.length < 1) {
|
|
+ socket.close();
|
|
+ socket = null;
|
|
+ throw new SSLHandshakeException("no current certs");
|
|
+ }
|
|
+
|
|
+ String serv = "";
|
|
+ try {
|
|
+ CertInfo ci = new CertInfo(currentTrustedCerts[0]);
|
|
+ serv = ci.get_certinfo("CN");
|
|
+ } catch (Exception e) {
|
|
+ ;
|
|
+ }
|
|
+
|
|
+ if (viewer.trustAllVncCerts) {
|
|
+ dbg("viewer.trustAllVncCerts-2");
|
|
+ user_wants_to_see_cert = false;
|
|
+ } else if (viewer.trustUrlVncCert) {
|
|
+ dbg("viewer.trustUrlVncCert-1");
|
|
+ user_wants_to_see_cert = false;
|
|
+ } else {
|
|
+ bcd = new BrowserCertsDialog(serv, host + ":" + port);
|
|
+ bcd.queryUser();
|
|
+ if (bcd.showCertDialog) {
|
|
+ String msg = "user wants to see cert";
|
|
+ dbg(msg);
|
|
+ user_wants_to_see_cert = true;
|
|
+ throw new SSLHandshakeException(msg);
|
|
+ } else {
|
|
+ user_wants_to_see_cert = false;
|
|
+ dbg("bcd: user said yes, accept it");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ } catch (SSLHandshakeException eh) {
|
|
+ dbg("Could not automatically verify Server.");
|
|
+ dbg("msg: " + eh.getMessage());
|
|
+
|
|
+ socket.close();
|
|
+ socket = null;
|
|
+
|
|
+ /*
|
|
+ * Reconnect, trusting any cert, so we can grab
|
|
+ * the cert to show it to the user. The connection
|
|
+ * is not used for anything else.
|
|
+ */
|
|
+ factory = trustall_ctx.getSocketFactory();
|
|
+ if (proxy_failure) {
|
|
+ socket = proxy_socket(factory);
|
|
+ } else {
|
|
+ socket = (SSLSocket) factory.createSocket(host, port);
|
|
+ }
|
|
+
|
|
+ try {
|
|
+ socket.startHandshake();
|
|
+ dbg("TrustAll Server Connection Verified.");
|
|
+
|
|
+ /* grab the cert: */
|
|
+ try {
|
|
+ SSLSession sess = socket.getSession();
|
|
+ trustallCerts = sess.getPeerCertificates();
|
|
+ } catch (Exception e) {
|
|
+ throw new Exception("Could not get " +
|
|
+ "Peer Certificate");
|
|
+ }
|
|
+
|
|
+ if (viewer.trustAllVncCerts) {
|
|
+ dbg("viewer.trustAllVncCerts-3");
|
|
+ } else if (! browser_cert_match()) {
|
|
+ /*
|
|
+ * close socket now, we will reopen after
|
|
+ * dialog if user agrees to use the cert.
|
|
+ */
|
|
+ socket.close();
|
|
+ socket = null;
|
|
+
|
|
+ /* dialog with user to accept cert or not: */
|
|
+
|
|
+ TrustDialog td= new TrustDialog(host, port,
|
|
+ trustallCerts);
|
|
+
|
|
+ if (! td.queryUser()) {
|
|
+ String msg = "User decided against it.";
|
|
+ dbg(msg);
|
|
+ throw new IOException(msg);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ } catch (Exception ehand2) {
|
|
+ dbg("** Could not TrustAll Verify Server.");
|
|
+
|
|
+ throw new IOException(ehand2.getMessage());
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Now connect a 3rd time, using the cert
|
|
+ * retrieved during connection 2 (that the user
|
|
+ * likely blindly agreed to).
|
|
+ */
|
|
+
|
|
+ factory = trustone_ctx.getSocketFactory();
|
|
+ if (proxy_failure) {
|
|
+ socket = proxy_socket(factory);
|
|
+ } else {
|
|
+ socket = (SSLSocket) factory.createSocket(host, port);
|
|
+ }
|
|
+
|
|
+ try {
|
|
+ socket.startHandshake();
|
|
+ dbg("TrustAll Server Connection Verified #3.");
|
|
+
|
|
+ } catch (Exception ehand3) {
|
|
+ dbg("** Could not TrustAll Verify Server #3.");
|
|
+
|
|
+ throw new IOException(ehand3.getMessage());
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (socket != null && viewer.GET) {
|
|
+ String str = "GET ";
|
|
+ str += viewer.urlPrefix;
|
|
+ str += "/request.https.vnc.connection";
|
|
+ str += " HTTP/1.0\r\n";
|
|
+ str += "Pragma: No-Cache\r\n";
|
|
+ str += "\r\n";
|
|
+ System.out.println("sending GET: " + str);
|
|
+ OutputStream os = socket.getOutputStream();
|
|
+ os.write(str.getBytes());
|
|
+ os.flush();
|
|
+ if (false) {
|
|
+ String rep = "";
|
|
+ DataInputStream is = new DataInputStream(
|
|
+ new BufferedInputStream(socket.getInputStream(), 16384));
|
|
+ while (true) {
|
|
+ rep += readline(is);
|
|
+ if (rep.indexOf("\r\n\r\n") >= 0) {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ System.out.println("rep: " + rep);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ dbg("SSL returning socket to caller.");
|
|
+ return (Socket) socket;
|
|
+ }
|
|
+
|
|
+ private void dbg(String s) {
|
|
+ if (debug) {
|
|
+ System.out.println(s);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private int gint(String s) {
|
|
+ int n = -1;
|
|
+ try {
|
|
+ Integer I = new Integer(s);
|
|
+ n = I.intValue();
|
|
+ } catch (Exception ex) {
|
|
+ return -1;
|
|
+ }
|
|
+ return n;
|
|
+ }
|
|
+
|
|
+ public SSLSocket proxy_socket(SSLSocketFactory factory) {
|
|
+ Properties props = null;
|
|
+ String proxyHost = null;
|
|
+ int proxyPort = 0;
|
|
+ String proxyHost_nossl = null;
|
|
+ int proxyPort_nossl = 0;
|
|
+ String str;
|
|
+
|
|
+ /* see if we can guess the proxy info from Properties: */
|
|
+ try {
|
|
+ props = System.getProperties();
|
|
+ } catch (Exception e) {
|
|
+ dbg("props failed: " + e.getMessage());
|
|
+ }
|
|
+ if (props != null) {
|
|
+ dbg("\n---------------\nAll props:");
|
|
+ props.list(System.out);
|
|
+ dbg("\n---------------\n\n");
|
|
+
|
|
+ for (Enumeration e = props.propertyNames(); e.hasMoreElements(); ) {
|
|
+ String s = (String) e.nextElement();
|
|
+ String v = System.getProperty(s);
|
|
+ String s2 = s.toLowerCase();
|
|
+ String v2 = v.toLowerCase();
|
|
+
|
|
+ if (s2.indexOf("proxy") < 0 && v2.indexOf("proxy") < 0) {
|
|
+ continue;
|
|
+ }
|
|
+ if (v2.indexOf("https") < 0) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (s2.indexOf("proxy.https.host") >= 0) {
|
|
+ proxyHost = v2;
|
|
+ continue;
|
|
+ }
|
|
+ if (s2.indexOf("proxy.https.port") >= 0) {
|
|
+ proxyPort = gint(v2);
|
|
+ continue;
|
|
+ }
|
|
+ if (s2.indexOf("proxy.http.host") >= 0) {
|
|
+ proxyHost_nossl = v2;
|
|
+ continue;
|
|
+ }
|
|
+ if (s2.indexOf("proxy.http.port") >= 0) {
|
|
+ proxyPort_nossl = gint(v2);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ String[] pieces = v.split("[,;]");
|
|
+ for (int i = 0; i < pieces.length; i++) {
|
|
+ String p = pieces[i];
|
|
+ int j = p.indexOf("https");
|
|
+ if (j < 0) {
|
|
+ continue;
|
|
+ }
|
|
+ j = p.indexOf("=", j);
|
|
+ if (j < 0) {
|
|
+ continue;
|
|
+ }
|
|
+ p = p.substring(j+1);
|
|
+ String [] hp = p.split(":");
|
|
+ if (hp.length != 2) {
|
|
+ continue;
|
|
+ }
|
|
+ if (hp[0].length() > 1 && hp[1].length() > 1) {
|
|
+
|
|
+ proxyPort = gint(hp[1]);
|
|
+ if (proxyPort < 0) {
|
|
+ continue;
|
|
+ }
|
|
+ proxyHost = new String(hp[0]);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if (proxyHost != null) {
|
|
+ if (proxyHost_nossl != null && proxyPort_nossl > 0) {
|
|
+ dbg("Using http proxy info instead of https.");
|
|
+ proxyHost = proxyHost_nossl;
|
|
+ proxyPort = proxyPort_nossl;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (proxy_in_use) {
|
|
+ if (proxy_dialog_host != null && proxy_dialog_port > 0) {
|
|
+ proxyHost = proxy_dialog_host;
|
|
+ proxyPort = proxy_dialog_port;
|
|
+ }
|
|
+ if (proxyHost != null) {
|
|
+ dbg("Lucky us! we figured out the Proxy parameters: " + proxyHost + " " + proxyPort);
|
|
+ } else {
|
|
+ /* ask user to help us: */
|
|
+ ProxyDialog pd = new ProxyDialog(proxyHost, proxyPort);
|
|
+ pd.queryUser();
|
|
+ proxyHost = pd.getHost();
|
|
+ proxyPort = pd.getPort();
|
|
+ proxy_dialog_host = new String(proxyHost);
|
|
+ proxy_dialog_port = proxyPort;
|
|
+ dbg("User said host: " + pd.getHost() + " port: " + pd.getPort());
|
|
+ }
|
|
+
|
|
+ dbg("proxy_in_use psocket:");
|
|
+ proxySock = psocket(proxyHost, proxyPort);
|
|
+ if (proxySock == null) {
|
|
+ dbg("1-a sadly, returning a null socket");
|
|
+ return null;
|
|
+ }
|
|
+ String hp = host + ":" + port;
|
|
+
|
|
+ String req1 = "CONNECT " + hp + " HTTP/1.1\r\n"
|
|
+ + "Host: " + hp + "\r\n\r\n";
|
|
+
|
|
+ dbg("requesting1: " + req1);
|
|
+
|
|
+ try {
|
|
+ proxy_os.write(req1.getBytes());
|
|
+ String reply = readline(proxy_is);
|
|
+
|
|
+ dbg("proxy replied1: " + reply.trim());
|
|
+
|
|
+ if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) {
|
|
+ proxySock.close();
|
|
+ proxySock = psocket(proxyHost, proxyPort);
|
|
+ if (proxySock == null) {
|
|
+ dbg("2-a sadly, returning a null socket");
|
|
+ return null;
|
|
+ }
|
|
+ }
|
|
+ } catch(Exception e) {
|
|
+ dbg("sock prob1: " + e.getMessage());
|
|
+ }
|
|
+
|
|
+ while (true) {
|
|
+ String line = readline(proxy_is);
|
|
+ dbg("proxy line1: " + line.trim());
|
|
+ if (line.equals("\r\n") || line.equals("\n")) {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ } else if (viewer.CONNECT != null) {
|
|
+ dbg("viewer.CONNECT psocket:");
|
|
+ proxySock = psocket(host, port);
|
|
+ if (proxySock == null) {
|
|
+ dbg("1-b sadly, returning a null socket");
|
|
+ return null;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (viewer.CONNECT != null) {
|
|
+ String hp = viewer.CONNECT;
|
|
+ String req2 = "CONNECT " + hp + " HTTP/1.1\r\n"
|
|
+ + "Host: " + hp + "\r\n\r\n";
|
|
+
|
|
+ dbg("requesting2: " + req2);
|
|
+
|
|
+ try {
|
|
+ proxy_os.write(req2.getBytes());
|
|
+ String reply = readline(proxy_is);
|
|
+
|
|
+ dbg("proxy replied2: " + reply.trim());
|
|
+
|
|
+ if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) {
|
|
+ proxySock.close();
|
|
+ proxySock = psocket(proxyHost, proxyPort);
|
|
+ if (proxySock == null) {
|
|
+ dbg("2-b sadly, returning a null socket");
|
|
+ return null;
|
|
+ }
|
|
+ }
|
|
+ } catch(Exception e) {
|
|
+ dbg("sock prob2: " + e.getMessage());
|
|
+ }
|
|
+
|
|
+ while (true) {
|
|
+ String line = readline(proxy_is);
|
|
+ dbg("proxy line2: " + line.trim());
|
|
+ if (line.equals("\r\n") || line.equals("\n")) {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ }
|
|
+
|
|
+ Socket sslsock = null;
|
|
+ try {
|
|
+ sslsock = factory.createSocket(proxySock, host, port, true);
|
|
+ } catch(Exception e) {
|
|
+ dbg("sslsock prob: " + e.getMessage());
|
|
+ dbg("3 sadly, returning a null socket");
|
|
+ }
|
|
+
|
|
+ return (SSLSocket) sslsock;
|
|
+ }
|
|
+
|
|
+ Socket psocket(String h, int p) {
|
|
+ Socket psock = null;
|
|
+ try {
|
|
+ psock = new Socket(h, p);
|
|
+ proxy_is = new DataInputStream(new BufferedInputStream(
|
|
+ psock.getInputStream(), 16384));
|
|
+ proxy_os = psock.getOutputStream();
|
|
+ } catch(Exception e) {
|
|
+ dbg("psocket prob: " + e.getMessage());
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ return psock;
|
|
+ }
|
|
+
|
|
+ String readline(DataInputStream i) {
|
|
+ byte[] ba = new byte[1];
|
|
+ String s = new String("");
|
|
+ ba[0] = 0;
|
|
+ try {
|
|
+ while (ba[0] != 0xa) {
|
|
+ ba[0] = (byte) i.readUnsignedByte();
|
|
+ s += new String(ba);
|
|
+ }
|
|
+ } catch (Exception e) {
|
|
+ ;
|
|
+ }
|
|
+ return s;
|
|
+ }
|
|
+}
|
|
+
|
|
+class TrustDialog implements ActionListener {
|
|
+ String msg, host, text;
|
|
+ int port;
|
|
+ java.security.cert.Certificate[] trustallCerts = null;
|
|
+ boolean viewing_cert = false;
|
|
+ boolean trust_this_session = false;
|
|
+
|
|
+ /*
|
|
+ * this is the gui to show the user the cert and info and ask
|
|
+ * them if they want to continue using this cert.
|
|
+ */
|
|
+
|
|
+ Button ok, cancel, viewcert;
|
|
+ TextArea textarea;
|
|
+ Checkbox accept, deny;
|
|
+ Dialog dialog;
|
|
+
|
|
+ String s1 = "Accept this certificate temporarily for this session";
|
|
+ String s2 = "Do not accept this certificate and do not connect to"
|
|
+ + " this VNC server";
|
|
+ String ln = "\n---------------------------------------------------\n\n";
|
|
+
|
|
+ TrustDialog (String h, int p, java.security.cert.Certificate[] s) {
|
|
+ host = h;
|
|
+ port = p;
|
|
+ trustallCerts = s;
|
|
+
|
|
+ msg = "VNC Server " + host + ":" + port + " Not Verified";
|
|
+ }
|
|
+
|
|
+ public boolean queryUser() {
|
|
+
|
|
+ /* create and display the dialog for unverified cert. */
|
|
+
|
|
+ Frame frame = new Frame(msg);
|
|
+
|
|
+ dialog = new Dialog(frame, true);
|
|
+
|
|
+ String infostr = "";
|
|
+ if (trustallCerts.length == 1) {
|
|
+ CertInfo ci = new CertInfo(trustallCerts[0]);
|
|
+ infostr = ci.get_certinfo("all");
|
|
+ }
|
|
+
|
|
+ text = "\n"
|
|
++ "Unable to verify the identity of\n"
|
|
++ "\n"
|
|
++ " " + host + ":" + port + "\n"
|
|
++ "\n"
|
|
++ infostr
|
|
++ "\n"
|
|
++ "as a trusted VNC server.\n"
|
|
++ "\n"
|
|
++ "This may be due to:\n"
|
|
++ "\n"
|
|
++ " - Your requesting to View the Certificate before accepting.\n"
|
|
++ "\n"
|
|
++ " - The VNC server using a Self-Signed Certificate.\n"
|
|
++ "\n"
|
|
++ " - The VNC server using a Certificate Authority not recognized by your\n"
|
|
++ " Browser or Java Plugin runtime.\n"
|
|
++ "\n"
|
|
++ " - The use of an Apache SSL portal employing CONNECT proxying and the\n"
|
|
++ " Apache web server has a certificate different from the VNC server's. \n"
|
|
++ "\n"
|
|
++ " - A Man-In-The-Middle attack impersonating as the VNC server you wish\n"
|
|
++ " to connect to. (Wouldn't that be exciting!!)\n"
|
|
++ "\n"
|
|
++ "By safely copying the VNC server's Certificate (or using a common\n"
|
|
++ "Certificate Authority certificate) you can configure your Web Browser or\n"
|
|
++ "Java Plugin to automatically authenticate this Server.\n"
|
|
++ "\n"
|
|
++ "If you do so, then you will only have to click \"Yes\" when this VNC\n"
|
|
++ "Viewer applet asks you whether to trust your Browser/Java Plugin's\n"
|
|
++ "acceptance of the certificate. (except for the Apache portal case above.)\n"
|
|
+;
|
|
+
|
|
+ /* the accept / do-not-accept radio buttons: */
|
|
+ CheckboxGroup checkbox = new CheckboxGroup();
|
|
+ accept = new Checkbox(s1, true, checkbox);
|
|
+ deny = new Checkbox(s2, false, checkbox);
|
|
+
|
|
+ /* put the checkboxes in a panel: */
|
|
+ Panel check = new Panel();
|
|
+ check.setLayout(new GridLayout(2, 1));
|
|
+
|
|
+ check.add(accept);
|
|
+ check.add(deny);
|
|
+
|
|
+ /* make the 3 buttons: */
|
|
+ ok = new Button("OK");
|
|
+ cancel = new Button("Cancel");
|
|
+ viewcert = new Button("View Certificate");
|
|
+
|
|
+ ok.addActionListener(this);
|
|
+ cancel.addActionListener(this);
|
|
+ viewcert.addActionListener(this);
|
|
+
|
|
+ /* put the buttons in their own panel: */
|
|
+ Panel buttonrow = new Panel();
|
|
+ buttonrow.setLayout(new FlowLayout(FlowLayout.LEFT));
|
|
+ buttonrow.add(viewcert);
|
|
+ buttonrow.add(ok);
|
|
+ buttonrow.add(cancel);
|
|
+
|
|
+ /* label at the top: */
|
|
+ Label label = new Label(msg, Label.CENTER);
|
|
+ label.setFont(new Font("Helvetica", Font.BOLD, 16));
|
|
+
|
|
+ /* textarea in the middle */
|
|
+ textarea = new TextArea(text, 36, 64,
|
|
+ TextArea.SCROLLBARS_VERTICAL_ONLY);
|
|
+ textarea.setEditable(false);
|
|
+
|
|
+ /* put the two panels in their own panel at bottom: */
|
|
+ Panel bot = new Panel();
|
|
+ bot.setLayout(new GridLayout(2, 1));
|
|
+ bot.add(check);
|
|
+ bot.add(buttonrow);
|
|
+
|
|
+ /* now arrange things inside the dialog: */
|
|
+ dialog.setLayout(new BorderLayout());
|
|
+
|
|
+ dialog.add("North", label);
|
|
+ dialog.add("South", bot);
|
|
+ dialog.add("Center", textarea);
|
|
+
|
|
+ dialog.pack();
|
|
+ dialog.resize(dialog.preferredSize());
|
|
+
|
|
+ dialog.show(); /* block here til OK or Cancel pressed. */
|
|
+
|
|
+ return trust_this_session;
|
|
+ }
|
|
+
|
|
+ public synchronized void actionPerformed(ActionEvent evt) {
|
|
+
|
|
+ if (evt.getSource() == viewcert) {
|
|
+ /* View Certificate button clicked */
|
|
+ if (viewing_cert) {
|
|
+ /* show the original info text: */
|
|
+ textarea.setText(text);
|
|
+ viewcert.setLabel("View Certificate");
|
|
+ viewing_cert = false;
|
|
+ } else {
|
|
+ int i;
|
|
+ /* show all (likely just one) certs: */
|
|
+ textarea.setText("");
|
|
+ for (i=0; i < trustallCerts.length; i++) {
|
|
+ int j = i + 1;
|
|
+ textarea.append("Certificate[" +
|
|
+ j + "]\n\n");
|
|
+ textarea.append(
|
|
+ trustallCerts[i].toString());
|
|
+ textarea.append(ln);
|
|
+ }
|
|
+ viewcert.setLabel("View Info");
|
|
+ viewing_cert = true;
|
|
+
|
|
+ textarea.setCaretPosition(0);
|
|
+ }
|
|
+
|
|
+ } else if (evt.getSource() == ok) {
|
|
+ /* OK button clicked */
|
|
+ if (accept.getState()) {
|
|
+ trust_this_session = true;
|
|
+ } else {
|
|
+ trust_this_session = false;
|
|
+ }
|
|
+ dialog.dispose();
|
|
+
|
|
+ } else if (evt.getSource() == cancel) {
|
|
+ /* Cancel button clicked */
|
|
+ trust_this_session = false;
|
|
+
|
|
+ dialog.dispose();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ String get_certinfo() {
|
|
+ String all = "";
|
|
+ String fields[] = {"CN", "OU", "O", "L", "C"};
|
|
+ int i;
|
|
+ if (trustallCerts.length < 1) {
|
|
+ all = "";
|
|
+ return all;
|
|
+ }
|
|
+ String cert = trustallCerts[0].toString();
|
|
+
|
|
+ /*
|
|
+ * For now we simply scrape the cert string, there must
|
|
+ * be an API for this... perhaps optionValue?
|
|
+ */
|
|
+
|
|
+ for (i=0; i < fields.length; i++) {
|
|
+ int f, t, t1, t2;
|
|
+ String sub, mat = fields[i] + "=";
|
|
+
|
|
+ f = cert.indexOf(mat, 0);
|
|
+ if (f > 0) {
|
|
+ t1 = cert.indexOf(", ", f);
|
|
+ t2 = cert.indexOf("\n", f);
|
|
+ if (t1 < 0 && t2 < 0) {
|
|
+ continue;
|
|
+ } else if (t1 < 0) {
|
|
+ t = t2;
|
|
+ } else if (t2 < 0) {
|
|
+ t = t1;
|
|
+ } else if (t1 < t2) {
|
|
+ t = t1;
|
|
+ } else {
|
|
+ t = t2;
|
|
+ }
|
|
+ if (t > f) {
|
|
+ sub = cert.substring(f, t);
|
|
+ all = all + " " + sub + "\n";
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return all;
|
|
+ }
|
|
+}
|
|
+
|
|
+class ProxyDialog implements ActionListener {
|
|
+ String guessedHost = null;
|
|
+ String guessedPort = null;
|
|
+ /*
|
|
+ * this is the gui to show the user the cert and info and ask
|
|
+ * them if they want to continue using this cert.
|
|
+ */
|
|
+
|
|
+ Button ok;
|
|
+ Dialog dialog;
|
|
+ TextField entry;
|
|
+ String reply = "";
|
|
+
|
|
+ ProxyDialog (String h, int p) {
|
|
+ guessedHost = h;
|
|
+ try {
|
|
+ guessedPort = Integer.toString(p);
|
|
+ } catch (Exception e) {
|
|
+ guessedPort = "8080";
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public void queryUser() {
|
|
+
|
|
+ /* create and display the dialog for unverified cert. */
|
|
+
|
|
+ Frame frame = new Frame("Need Proxy host:port");
|
|
+
|
|
+ dialog = new Dialog(frame, true);
|
|
+
|
|
+
|
|
+ Label label = new Label("Please Enter your https Proxy info as host:port", Label.CENTER);
|
|
+ //label.setFont(new Font("Helvetica", Font.BOLD, 16));
|
|
+ entry = new TextField(30);
|
|
+ ok = new Button("OK");
|
|
+ ok.addActionListener(this);
|
|
+
|
|
+ String guess = "";
|
|
+ if (guessedHost != null) {
|
|
+ guess = guessedHost + ":" + guessedPort;
|
|
+ }
|
|
+ entry.setText(guess);
|
|
+
|
|
+ dialog.setLayout(new BorderLayout());
|
|
+ dialog.add("North", label);
|
|
+ dialog.add("Center", entry);
|
|
+ dialog.add("South", ok);
|
|
+ dialog.pack();
|
|
+ dialog.resize(dialog.preferredSize());
|
|
+
|
|
+ dialog.show(); /* block here til OK or Cancel pressed. */
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ public String getHost() {
|
|
+ int i = reply.indexOf(":");
|
|
+ if (i < 0) {
|
|
+ return "unknown";
|
|
+ }
|
|
+ String h = reply.substring(0, i);
|
|
+ return h;
|
|
+ }
|
|
+
|
|
+ public int getPort() {
|
|
+ int i = reply.indexOf(":");
|
|
+ int p = 8080;
|
|
+ if (i < 0) {
|
|
+ return p;
|
|
+ }
|
|
+ i++;
|
|
+ String ps = reply.substring(i);
|
|
+ try {
|
|
+ Integer I = new Integer(ps);
|
|
+ p = I.intValue();
|
|
+ } catch (Exception e) {
|
|
+ ;
|
|
+ }
|
|
+ return p;
|
|
+ }
|
|
+
|
|
+ public synchronized void actionPerformed(ActionEvent evt) {
|
|
+ System.out.println(evt.getActionCommand());
|
|
+ if (evt.getSource() == ok) {
|
|
+ reply = entry.getText();
|
|
+ dialog.dispose();
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+class ClientCertDialog implements ActionListener {
|
|
+
|
|
+ Button ok;
|
|
+ Dialog dialog;
|
|
+ TextField entry;
|
|
+ String reply = "";
|
|
+
|
|
+ ClientCertDialog() {
|
|
+ ;
|
|
+ }
|
|
+
|
|
+ public String queryUser() {
|
|
+
|
|
+ /* create and display the dialog for unverified cert. */
|
|
+
|
|
+ Frame frame = new Frame("Enter SSL Client Cert+Key String");
|
|
+
|
|
+ dialog = new Dialog(frame, true);
|
|
+
|
|
+
|
|
+ Label label = new Label("Please Enter the SSL Client Cert+Key String 308204c0...,...522d2d0a", Label.CENTER);
|
|
+ entry = new TextField(30);
|
|
+ ok = new Button("OK");
|
|
+ ok.addActionListener(this);
|
|
+
|
|
+ dialog.setLayout(new BorderLayout());
|
|
+ dialog.add("North", label);
|
|
+ dialog.add("Center", entry);
|
|
+ dialog.add("South", ok);
|
|
+ dialog.pack();
|
|
+ dialog.resize(dialog.preferredSize());
|
|
+
|
|
+ dialog.show(); /* block here til OK or Cancel pressed. */
|
|
+ return reply;
|
|
+ }
|
|
+
|
|
+ public synchronized void actionPerformed(ActionEvent evt) {
|
|
+ System.out.println(evt.getActionCommand());
|
|
+ if (evt.getSource() == ok) {
|
|
+ reply = entry.getText();
|
|
+ dialog.dispose();
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+class BrowserCertsDialog implements ActionListener {
|
|
+ Button yes, no;
|
|
+ Dialog dialog;
|
|
+ String vncServer;
|
|
+ String hostport;
|
|
+ public boolean showCertDialog = true;
|
|
+
|
|
+ BrowserCertsDialog(String serv, String hp) {
|
|
+ vncServer = serv;
|
|
+ hostport = hp;
|
|
+ }
|
|
+
|
|
+ public void queryUser() {
|
|
+
|
|
+ /* create and display the dialog for unverified cert. */
|
|
+
|
|
+ Frame frame = new Frame("Use Browser/JVM Certs?");
|
|
+
|
|
+ dialog = new Dialog(frame, true);
|
|
+
|
|
+ String m = "";
|
|
+m += "\n";
|
|
+m += "This VNC Viewer applet does not have its own keystore to track\n";
|
|
+m += "SSL certificates, and so cannot authenticate the certificate\n";
|
|
+m += "of the VNC Server:\n";
|
|
+m += "\n";
|
|
+m += " " + hostport + "\n\n " + vncServer + "\n";
|
|
+m += "\n";
|
|
+m += "on its own.\n";
|
|
+m += "\n";
|
|
+m += "However, it has noticed that your Web Browser or Java VM Plugin\n";
|
|
+m += "has previously accepted the same certificate. You may have set\n";
|
|
+m += "this up permanently or just for this session, or the server\n";
|
|
+m += "certificate was signed by a CA cert that your Web Browser or\n";
|
|
+m += "Java VM Plugin has.\n";
|
|
+m += "\n";
|
|
+m += "Should this VNC Viewer applet now connect to the above VNC server?\n";
|
|
+m += "\n";
|
|
+
|
|
+// String m = "\nShould this VNC Viewer applet use your Browser/JVM certs to\n";
|
|
+// m += "authenticate the VNC Server:\n";
|
|
+// m += "\n " + hostport + "\n\n " + vncServer + "\n\n";
|
|
+// m += "(NOTE: this *includes* any certs you have Just Now accepted in a\n";
|
|
+// m += "dialog box with your Web Browser or Java Applet Plugin)\n\n";
|
|
+
|
|
+ TextArea textarea = new TextArea(m, 20, 64,
|
|
+ TextArea.SCROLLBARS_VERTICAL_ONLY);
|
|
+ textarea.setEditable(false);
|
|
+ yes = new Button("Yes");
|
|
+ yes.addActionListener(this);
|
|
+ no = new Button("No, Let Me See the Certificate.");
|
|
+ no.addActionListener(this);
|
|
+
|
|
+ dialog.setLayout(new BorderLayout());
|
|
+ dialog.add("North", textarea);
|
|
+ dialog.add("Center", yes);
|
|
+ dialog.add("South", no);
|
|
+ dialog.pack();
|
|
+ dialog.resize(dialog.preferredSize());
|
|
+
|
|
+ dialog.show(); /* block here til Yes or No pressed. */
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ public synchronized void actionPerformed(ActionEvent evt) {
|
|
+ System.out.println(evt.getActionCommand());
|
|
+ if (evt.getSource() == yes) {
|
|
+ showCertDialog = false;
|
|
+ dialog.dispose();
|
|
+ } else if (evt.getSource() == no) {
|
|
+ showCertDialog = true;
|
|
+ dialog.dispose();
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+class CertInfo {
|
|
+ String fields[] = {"CN", "OU", "O", "L", "C"};
|
|
+ java.security.cert.Certificate cert;
|
|
+ String certString = "";
|
|
+
|
|
+ CertInfo(java.security.cert.Certificate c) {
|
|
+ cert = c;
|
|
+ certString = cert.toString();
|
|
+ }
|
|
+
|
|
+ String get_certinfo(String which) {
|
|
+ int i;
|
|
+ String cs = new String(certString);
|
|
+ String all = "";
|
|
+
|
|
+ /*
|
|
+ * For now we simply scrape the cert string, there must
|
|
+ * be an API for this... perhaps optionValue?
|
|
+ */
|
|
+ for (i=0; i < fields.length; i++) {
|
|
+ int f, t, t1, t2;
|
|
+ String sub, mat = fields[i] + "=";
|
|
+
|
|
+ f = cs.indexOf(mat, 0);
|
|
+ if (f > 0) {
|
|
+ t1 = cs.indexOf(", ", f);
|
|
+ t2 = cs.indexOf("\n", f);
|
|
+ if (t1 < 0 && t2 < 0) {
|
|
+ continue;
|
|
+ } else if (t1 < 0) {
|
|
+ t = t2;
|
|
+ } else if (t2 < 0) {
|
|
+ t = t1;
|
|
+ } else if (t1 < t2) {
|
|
+ t = t1;
|
|
+ } else {
|
|
+ t = t2;
|
|
+ }
|
|
+ if (t > f) {
|
|
+ sub = cs.substring(f, t);
|
|
+ all = all + " " + sub + "\n";
|
|
+ if (which.equals(fields[i])) {
|
|
+ return sub;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if (which.equals("all")) {
|
|
+ return all;
|
|
+ } else {
|
|
+ return "";
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff -Naur JavaViewer.orig/VncCanvas.java JavaViewer/VncCanvas.java
|
|
--- JavaViewer.orig/VncCanvas.java 2005-11-21 18:50:18.000000000 -0500
|
|
+++ JavaViewer/VncCanvas.java 2007-05-16 15:57:36.000000000 -0400
|
|
@@ -27,6 +27,9 @@
|
|
import java.lang.*;
|
|
import java.util.zip.*;
|
|
|
|
+// begin runge/x11vnc
|
|
+import java.util.Collections;
|
|
+// end runge/x11vnc
|
|
|
|
//
|
|
// VncCanvas is a subclass of Canvas which draws a VNC desktop on it.
|
|
@@ -85,6 +88,22 @@
|
|
|
|
cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
|
|
|
|
+// begin runge/x11vnc
|
|
+// kludge to not show any Java cursor in the canvas since we are
|
|
+// showing the soft cursor (should be a user setting...)
|
|
+Cursor dot = Toolkit.getDefaultToolkit().createCustomCursor(
|
|
+ Toolkit.getDefaultToolkit().createImage(new byte[4]), new Point(0,0),
|
|
+ "dot");
|
|
+this.setCursor(dot);
|
|
+
|
|
+// while we are at it... get rid of the keyboard traversals that
|
|
+// make it so we can't type a Tab character:
|
|
+this.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
|
|
+ Collections.EMPTY_SET);
|
|
+this.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
|
|
+ Collections.EMPTY_SET);
|
|
+// end runge/x11vnc
|
|
+
|
|
colors = new Color[256];
|
|
// sf@2005 - Now Default
|
|
for (int i = 0; i < 256; i++)
|
|
@@ -237,6 +256,9 @@
|
|
}
|
|
else
|
|
{
|
|
+// begin runge/x11vnc
|
|
+ viewer.options.oldEightBitColors = viewer.options.eightBitColors;
|
|
+// end runge/x11vnc
|
|
rfb.writeSetPixelFormat(
|
|
32,
|
|
24,
|
|
@@ -1532,9 +1554,14 @@
|
|
else
|
|
{
|
|
result =
|
|
- 0xFF000000 | (pixBuf[i * 4 + 1] & 0xFF)
|
|
- << 16 | (pixBuf[i * 4 + 2] & 0xFF)
|
|
- << 8 | (pixBuf[i * 4 + 3] & 0xFF);
|
|
+// begin runge/x11vnc
|
|
+// 0xFF000000 | (pixBuf[i * 4 + 1] & 0xFF)
|
|
+// << 16 | (pixBuf[i * 4 + 2] & 0xFF)
|
|
+// << 8 | (pixBuf[i * 4 + 3] & 0xFF);
|
|
+ 0xFF000000 | (pixBuf[i * 4 + 2] & 0xFF)
|
|
+ << 16 | (pixBuf[i * 4 + 1] & 0xFF)
|
|
+ << 8 | (pixBuf[i * 4 + 0] & 0xFF);
|
|
+// end runge/x11vnc
|
|
}
|
|
} else {
|
|
result = 0; // Transparent pixel
|
|
@@ -1565,9 +1592,14 @@
|
|
else
|
|
{
|
|
result =
|
|
- 0xFF000000 | (pixBuf[i * 4 + 1] & 0xFF)
|
|
- << 16 | (pixBuf[i * 4 + 2] & 0xFF)
|
|
- << 8 | (pixBuf[i * 4 + 3] & 0xFF);
|
|
+// begin runge/x11vnc
|
|
+// 0xFF000000 | (pixBuf[i * 4 + 1] & 0xFF)
|
|
+// << 16 | (pixBuf[i * 4 + 2] & 0xFF)
|
|
+// << 8 | (pixBuf[i * 4 + 3] & 0xFF);
|
|
+ 0xFF000000 | (pixBuf[i * 4 + 2] & 0xFF)
|
|
+ << 16 | (pixBuf[i * 4 + 1] & 0xFF)
|
|
+ << 8 | (pixBuf[i * 4 + 0] & 0xFF);
|
|
+// end runge/x11vnc
|
|
}
|
|
} else {
|
|
result = 0; // Transparent pixel
|
|
diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java
|
|
--- JavaViewer.orig/VncViewer.java 2006-05-24 15:14:40.000000000 -0400
|
|
+++ JavaViewer/VncViewer.java 2007-05-15 15:09:10.000000000 -0400
|
|
@@ -115,6 +115,22 @@
|
|
int i;
|
|
// mslogon support 2 end
|
|
|
|
+// begin runge/x11vnc
|
|
+boolean disableSSL;
|
|
+boolean GET;
|
|
+String CONNECT;
|
|
+String urlPrefix;
|
|
+String httpsPort;
|
|
+String oneTimeKey;
|
|
+boolean forceProxy;
|
|
+boolean ignoreProxy;
|
|
+boolean trustAllVncCerts;
|
|
+boolean trustUrlVncCert;
|
|
+
|
|
+boolean ignoreMSLogonCheck;
|
|
+// end runge/x11vnc
|
|
+
|
|
+
|
|
//
|
|
// init()
|
|
//
|
|
@@ -336,7 +352,12 @@
|
|
//
|
|
|
|
|
|
- prologueDetectAuthProtocol() ;
|
|
+// begin runge/x11vnc
|
|
+// prologueDetectAuthProtocol() ;
|
|
+ if (ignoreMSLogonCheck == false) {
|
|
+ prologueDetectAuthProtocol() ;
|
|
+ }
|
|
+// end runge/x11vnc
|
|
|
|
authenticator = new AuthPanel(mslogon);
|
|
|
|
@@ -435,7 +456,7 @@
|
|
|
|
rfb.readVersionMsg();
|
|
|
|
- System.out.println("RFB server supports protocol version " +
|
|
+ System.out.println("RFB server supports protocol version: " +
|
|
rfb.serverMajor + "." + rfb.serverMinor);
|
|
|
|
rfb.writeVersionMsg();
|
|
@@ -804,6 +825,75 @@
|
|
deferScreenUpdates = readIntParameter("Defer screen updates", 20);
|
|
deferCursorUpdates = readIntParameter("Defer cursor updates", 10);
|
|
deferUpdateRequests = readIntParameter("Defer update requests", 50);
|
|
+
|
|
+// begin runge/x11vnc
|
|
+ // SSL
|
|
+ disableSSL = false;
|
|
+ str = readParameter("DisableSSL", false);
|
|
+ if (str != null && str.equalsIgnoreCase("Yes"))
|
|
+ disableSSL = true;
|
|
+
|
|
+ httpsPort = readParameter("httpsPort", false);
|
|
+
|
|
+ // Extra GET, CONNECT string:
|
|
+ CONNECT = readParameter("CONNECT", false);
|
|
+ if (CONNECT != null) {
|
|
+ CONNECT = CONNECT.replaceAll(" ", ":");
|
|
+ }
|
|
+
|
|
+ GET = false;
|
|
+ str = readParameter("GET", false);
|
|
+ if (str != null && str.equalsIgnoreCase("Yes")) {
|
|
+ GET = true;
|
|
+ }
|
|
+ if (str != null && str.equalsIgnoreCase("1")) {
|
|
+ GET = true;
|
|
+ }
|
|
+
|
|
+ urlPrefix = readParameter("urlPrefix", false);
|
|
+ if (urlPrefix != null) {
|
|
+ urlPrefix = urlPrefix.replaceAll("%2F", "/");
|
|
+ urlPrefix = urlPrefix.replaceAll("%2f", "/");
|
|
+ urlPrefix = urlPrefix.replaceAll("_2F_", "/");
|
|
+ if (urlPrefix.indexOf("/") != 0) {
|
|
+ urlPrefix = "/" + urlPrefix;
|
|
+ }
|
|
+ } else {
|
|
+ urlPrefix = "";
|
|
+ }
|
|
+ System.out.println("urlPrefix: '" + urlPrefix + "'");
|
|
+
|
|
+ oneTimeKey = readParameter("oneTimeKey", false);
|
|
+ if (oneTimeKey != null) {
|
|
+ System.out.println("oneTimeKey: is set");
|
|
+ }
|
|
+
|
|
+ forceProxy = false;
|
|
+ str = readParameter("forceProxy", false);
|
|
+ if (str != null && str.equalsIgnoreCase("Yes")) {
|
|
+ forceProxy = true;
|
|
+ }
|
|
+ ignoreProxy = false;
|
|
+ str = readParameter("ignoreProxy", false);
|
|
+ if (str != null && str.equalsIgnoreCase("Yes")) {
|
|
+ ignoreProxy = true;
|
|
+ }
|
|
+ trustAllVncCerts = false;
|
|
+ str = readParameter("trustAllVncCerts", false);
|
|
+ if (str != null && str.equalsIgnoreCase("Yes")) {
|
|
+ trustAllVncCerts = true;
|
|
+ }
|
|
+ trustUrlVncCert = false;
|
|
+ str = readParameter("trustUrlVncCert", false);
|
|
+ if (str != null && str.equalsIgnoreCase("Yes")) {
|
|
+ trustUrlVncCert = true;
|
|
+ }
|
|
+ ignoreMSLogonCheck = false;
|
|
+ str = readParameter("ignoreMSLogonCheck", false);
|
|
+ if (str != null && str.equalsIgnoreCase("Yes")) {
|
|
+ ignoreMSLogonCheck = true;
|
|
+ }
|
|
+// end runge/x11vnc
|
|
}
|
|
|
|
public String readParameter(String name, boolean required) {
|