1 diff -Naur JavaViewer.orig/ButtonPanel.java JavaViewer/ButtonPanel.java 2 --- JavaViewer.orig/ButtonPanel.java 2004-12-12 20:51:02.000000000 -0500 3 +++ JavaViewer/ButtonPanel.java 2007-05-31 15:40:45.000000000 -0400 4 @@ -43,30 +43,36 @@ 5 viewer = v; 6 7 setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); 8 - disconnectButton = new Button("Disconnect"); 9 + if (v.ftpOnly) { 10 + disconnectButton = new Button("Quit"); 11 + } else { 12 + disconnectButton = new Button("Close"); 13 + } 14 disconnectButton.setEnabled(false); 15 add(disconnectButton); 16 disconnectButton.addActionListener(this); 17 - optionsButton = new Button("Options"); 18 - add(optionsButton); 19 - optionsButton.addActionListener(this); 20 - clipboardButton = new Button("Clipboard"); 21 - clipboardButton.setEnabled(false); 22 - add(clipboardButton); 23 - clipboardButton.addActionListener(this); 24 - if (viewer.rec != null) { 25 - recordButton = new Button("Record"); 26 - add(recordButton); 27 - recordButton.addActionListener(this); 28 - } 29 - ctrlAltDelButton = new Button("Send Ctrl-Alt-Del"); 30 - ctrlAltDelButton.setEnabled(false); 31 - add(ctrlAltDelButton); 32 - ctrlAltDelButton.addActionListener(this); 33 - refreshButton = new Button("Refresh"); 34 - refreshButton.setEnabled(false); 35 - add(refreshButton); 36 - refreshButton.addActionListener(this); 37 + if (!v.ftpOnly) { 38 + optionsButton = new Button("Options"); 39 + add(optionsButton); 40 + optionsButton.addActionListener(this); 41 + clipboardButton = new Button("Clipboard"); 42 + clipboardButton.setEnabled(false); 43 + add(clipboardButton); 44 + clipboardButton.addActionListener(this); 45 + if (viewer.rec != null) { 46 + recordButton = new Button("Record"); 47 + add(recordButton); 48 + recordButton.addActionListener(this); 49 + } 50 + ctrlAltDelButton = new Button("Send Ctrl-Alt-Del"); 51 + ctrlAltDelButton.setEnabled(false); 52 + add(ctrlAltDelButton); 53 + ctrlAltDelButton.addActionListener(this); 54 + refreshButton = new Button("Refresh"); 55 + refreshButton.setEnabled(false); 56 + add(refreshButton); 57 + refreshButton.addActionListener(this); 58 + } 59 ftpButton = new Button("File Transfer"); 60 ftpButton.setEnabled(false); 61 add(ftpButton); 62 @@ -79,9 +85,10 @@ 63 64 public void enableButtons() { 65 disconnectButton.setEnabled(true); 66 + ftpButton.setEnabled(true); 67 + if (viewer.ftpOnly) {return;} 68 clipboardButton.setEnabled(true); 69 refreshButton.setEnabled(true); 70 - ftpButton.setEnabled(true); 71 } 72 73 // 74 @@ -89,6 +96,9 @@ 75 // 76 77 public void disableButtonsOnDisconnect() { 78 + ftpButton.setEnabled(false); 79 + if (viewer.ftpOnly) {return;} 80 + 81 remove(disconnectButton); 82 disconnectButton = new Button("Hide desktop"); 83 disconnectButton.setEnabled(true); 84 @@ -99,7 +109,6 @@ 85 clipboardButton.setEnabled(false); 86 ctrlAltDelButton.setEnabled(false); 87 refreshButton.setEnabled(false); 88 - ftpButton.setEnabled(false); 89 90 validate(); 91 } 92 @@ -110,6 +119,7 @@ 93 // 94 95 public void enableRemoteAccessControls(boolean enable) { 96 + if (viewer.ftpOnly) {return;} 97 ctrlAltDelButton.setEnabled(enable); 98 } 99 100 @@ -163,9 +173,19 @@ 101 } 102 else if (evt.getSource() == ftpButton) 103 { 104 - viewer.ftp.setVisible(!viewer.ftp.isVisible()); 105 +// begin runge/x11vnc 106 + if (viewer.ftpOnly) { 107 + viewer.vncFrame.setVisible(false); 108 + } 109 + viewer.ftp.setSavedLocations(); 110 + if (viewer.ftp.isVisible()) { 111 + viewer.ftp.doClose(); 112 + } else { 113 + viewer.ftp.doOpen(); 114 + } 115 +// end runge/x11vnc 116 viewer.rfb.readServerDriveList(); 117 - 118 + 119 } 120 } 121 } 122 diff -Naur JavaViewer.orig/FTPFrame.java JavaViewer/FTPFrame.java 123 --- JavaViewer.orig/FTPFrame.java 2005-03-15 23:53:14.000000000 -0500 124 +++ JavaViewer/FTPFrame.java 2009-01-13 09:48:30.000000000 -0500 125 @@ -24,8 +24,17 @@ 126 import java.io.*; 127 import java.util.ArrayList; 128 import java.util.Vector; 129 +import java.util.Date; 130 import javax.swing.*; 131 132 +import java.nio.ByteBuffer; 133 +import java.nio.CharBuffer; 134 +import java.nio.charset.*; 135 + 136 +// begin runge/x11vnc 137 +import java.util.Arrays; 138 +// end runge/x11vnc 139 + 140 141 /* 142 * Created on Feb 25, 2004 143 @@ -74,12 +83,31 @@ 144 public javax.swing.JTextField connectionStatus = null; 145 public boolean updateDriveList; 146 private Vector remoteList = null; 147 + private Vector remoteListInfo = null; 148 private Vector localList = null; 149 + private Vector localListInfo = null; 150 private File currentLocalDirectory = null; // Holds the current local Directory 151 private File currentRemoteDirectory = null; // Holds the current remote Directory 152 private File localSelection = null; // Holds the currently selected local file 153 private String remoteSelection = null; // Holds the currently selected remote file 154 public String selectedTable = null; 155 + 156 +// begin runge/x11vnc 157 + private javax.swing.JButton viewButton = null; 158 + private javax.swing.JButton refreshButton = null; 159 + public File saveLocalDirectory = null; 160 + public long saveLocalDirectoryTime = 0; 161 + public int saveLocalDirectoryCount = 0; 162 + public String saveRemoteDirectory = null; 163 + public long saveRemoteDirectoryTime = 0; 164 + public int saveRemoteDirectoryCount = 0; 165 + private boolean localCurrentIsDir = true; 166 + private int lastRemoteIndex = -1; 167 + private int lastLocalIndex = -1; 168 + private boolean doingShortcutDir = false; 169 + private boolean gotShortcutDir = false; 170 + private boolean ignore_events = false; 171 +// end runge/x11vnc 172 173 // sf@2004 - Separate directories and files for better lisibility 174 private ArrayList DirsList; 175 @@ -125,11 +153,61 @@ 176 177 void refreshRemoteLocation() 178 { 179 + 180 +//System.out.println("refreshRemoteLocation1"); 181 remoteList.clear(); 182 + remoteListInfo.clear(); 183 remoteFileTable.setListData(remoteList); 184 +System.out.println("refreshRemoteLocation '" + remoteLocation.getText() + "'"); // runge/x11vnc 185 viewer.rfb.readServerDirectory(remoteLocation.getText()); 186 } 187 188 +// begin runge/x11vnc 189 + public void setSavedLocations() { 190 + saveLocalDirectory = currentLocalDirectory; 191 + saveLocalDirectoryTime = System.currentTimeMillis(); 192 + saveLocalDirectoryCount = 0; 193 + 194 + if (remoteLocation != null) { 195 + saveRemoteDirectory = remoteLocation.getText(); 196 +System.out.println("RemoteSave '" + saveRemoteDirectory + "'"); 197 + } 198 + saveRemoteDirectoryTime = System.currentTimeMillis(); 199 + saveRemoteDirectoryCount = 0; 200 + } 201 + 202 + private File saveLocalHack(File dir) { 203 + saveLocalDirectoryCount++; 204 +//System.out.println("L " + saveLocalDirectoryCount + " dt: " + (System.currentTimeMillis() - saveLocalDirectoryTime) + " - " + saveLocalDirectory); 205 + if (System.currentTimeMillis() > saveLocalDirectoryTime + 2000 || saveLocalDirectoryCount > 2) { 206 + saveLocalDirectory = null; 207 + } 208 + if (saveLocalDirectory != null) { 209 + currentLocalDirectory = saveLocalDirectory; 210 + localLocation.setText(saveLocalDirectory.toString()); 211 + return saveLocalDirectory; 212 + } else { 213 + return dir; 214 + } 215 + } 216 + 217 + private String saveRemoteHack(String indrive) { 218 + saveRemoteDirectoryCount++; 219 +//System.out.println("R " + saveRemoteDirectoryCount + " - " + saveRemoteDirectory); 220 + if (saveRemoteDirectory != null && saveRemoteDirectoryCount > 1) { 221 + saveRemoteDirectory = null; 222 + } 223 + if (saveRemoteDirectory != null) { 224 + if (! saveRemoteDirectory.equals("")) { 225 +System.out.println("saveRemoteHack setText + refreshRemoteLocation '" + saveRemoteDirectory + "'"); 226 + return saveRemoteDirectory; 227 + } 228 + } 229 + return indrive; 230 + } 231 +// end runge/x11vnc 232 + 233 + 234 /* 235 * Prints the list of drives on the remote directory and returns a String[]. 236 * str takes as string like A:fC:lD:lE:lF:lG:cH:c 237 @@ -143,6 +221,9 @@ 238 int size = str.length(); 239 String driveType = null; 240 String[] drive = new String[str.length() / 3]; 241 + int idx = 0, C_drive = -1, O_drive = -1; 242 + 243 +System.out.println("ComboBox: Str '" + str + "'"); 244 245 // Loop through the string to create a String[] 246 for (int i = 0; i < size; i = i + 3) { 247 @@ -150,26 +231,68 @@ 248 driveType = str.substring(i + 2, i + 3); 249 if (driveType.compareTo("f") == 0) 250 drive[i / 3] += "\\ Floppy"; 251 - if (driveType.compareTo("l") == 0) 252 + if (driveType.compareTo("l") == 0) { 253 drive[i / 3] += "\\ Local Disk"; 254 + if (drive[i/3].substring(0,1).toUpperCase().equals("C")) { 255 + C_drive = idx; 256 + } else if (O_drive < 0) { 257 + O_drive = idx; 258 + } 259 + } 260 if (driveType.compareTo("c") == 0) 261 drive[i / 3] += "\\ CD-ROM"; 262 if (driveType.compareTo("n") == 0) 263 drive[i / 3] += "\\ Network"; 264 265 remoteDrivesComboBox.addItem(drive[i / 3]); 266 +System.out.println("ComboBox: Add " + idx + " '" + drive[i/3] + "'"); 267 + idx++; 268 + } 269 + 270 + // runge 271 + if (viewer.ftpDropDown != null) { 272 + String[] dd = viewer.ftpDropDown.split("\\."); 273 + for (int i=0; i < dd.length; i++) { 274 + if (!dd[i].equals("")) { 275 + String s = dd[i]; 276 + if (s.startsWith("TOP_")) { 277 + s = s.substring(4); 278 + remoteDrivesComboBox.insertItemAt(" [" + s + "]", 0); 279 + } else { 280 + remoteDrivesComboBox.addItem(" [" + s + "]"); 281 + } 282 + } 283 + } 284 + } else { 285 + remoteDrivesComboBox.addItem(" [My Documents]"); 286 + remoteDrivesComboBox.addItem(" [Desktop]"); 287 + remoteDrivesComboBox.addItem(" [Home]"); 288 } 289 + 290 //sf@ - Select Drive C:as default if possible 291 boolean bFound = false; 292 - for(int i = 0; i < remoteDrivesComboBox.getItemCount() ; i++) 293 - { 294 - if(remoteDrivesComboBox.getItemAt(i).toString().substring(0,1).toUpperCase().equals("C")) 295 - { 296 - remoteDrivesComboBox.setSelectedIndex(i); 297 + 298 + if (false) { 299 + for(int i = 0; i < remoteDrivesComboBox.getItemCount() ; i++) { 300 + if(remoteDrivesComboBox.getItemAt(i).toString().substring(0,1).toUpperCase().equals("C")) { 301 + remoteDrivesComboBox.setSelectedIndex(i); 302 + bFound = true; 303 + } 304 + } 305 + } else { 306 + if (C_drive >= 0) { 307 + remoteDrivesComboBox.setSelectedIndex(C_drive); 308 + bFound = true; 309 +System.out.println("ComboBox: C_drive index: " + C_drive); 310 + } else if (O_drive >= 0) { 311 + remoteDrivesComboBox.setSelectedIndex(O_drive); 312 bFound = true; 313 +System.out.println("ComboBox: Other_drive index: " + O_drive); 314 } 315 } 316 + 317 if (!bFound) remoteDrivesComboBox.setSelectedIndex(0); 318 + 319 updateDriveList = false; 320 return drive; 321 } 322 @@ -185,6 +308,8 @@ 323 stopButton.setVisible(true); 324 stopButton.setEnabled(true); 325 receiveButton.setEnabled(false); 326 + viewButton.setEnabled(false); // runge/x11vnc 327 + refreshButton.setEnabled(false); 328 remoteTopButton.setEnabled(false); 329 sendButton.setEnabled(false); 330 remoteFileTable.setEnabled(false); 331 @@ -207,6 +332,8 @@ 332 stopButton.setVisible(false); 333 stopButton.setEnabled(false); 334 receiveButton.setEnabled(true); 335 + viewButton.setEnabled(true); // runge/x11vnc 336 + refreshButton.setEnabled(true); 337 remoteTopButton.setEnabled(true); 338 sendButton.setEnabled(true); 339 remoteFileTable.setEnabled(true); 340 @@ -221,10 +348,11 @@ 341 /* 342 * Print Directory prints out all the contents of a directory 343 */ 344 - void printDirectory(ArrayList a) { 345 + void printDirectory(ArrayList a, ArrayList b) { 346 347 for (int i = 0; i < a.size(); i++) { 348 remoteList.addElement(a.get(i)); 349 + remoteListInfo.addElement(b.get(i)); 350 } 351 remoteFileTable.setListData(remoteList); 352 } 353 @@ -235,10 +363,12 @@ 354 * @return void 355 */ 356 private void initialize() { 357 + ignore_events = true; 358 this.setSize(794, 500); 359 this.setContentPane(getJContentPane()); 360 + ignore_events = false; 361 updateDriveList = true; 362 - } 363 + } 364 /** 365 * This method initializes jContentPane. This is the main content pane 366 * 367 @@ -253,6 +383,33 @@ 368 jContentPane.add(getRemotePanel(), java.awt.BorderLayout.EAST); 369 jContentPane.add(getLocalPanel(), java.awt.BorderLayout.WEST); 370 jContentPane.add(getButtonPanel(), java.awt.BorderLayout.CENTER); 371 + 372 + KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); 373 + AbstractAction escapeAction = new AbstractAction() { 374 + public void actionPerformed(ActionEvent actionEvent) { 375 + System.out.println("Escape Pressed"); 376 + if (viewer.ftpOnly) { 377 + System.out.println("exiting..."); 378 + System.exit(0); 379 + } else { 380 + doClose(); 381 + } 382 + } 383 + }; 384 + jContentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(stroke, "escapeAction"); 385 + jContentPane.getInputMap().put(stroke, "escapeAction"); 386 + jContentPane.getActionMap().put("escapeAction", escapeAction); 387 + 388 + stroke = KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_MASK); 389 + AbstractAction resetAction = new AbstractAction() { 390 + public void actionPerformed(ActionEvent actionEvent) { 391 + System.out.println("Ctrl-R Pressed"); 392 + doReset(); 393 + } 394 + }; 395 + jContentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(stroke, "resetAction"); 396 + jContentPane.getInputMap().put(stroke, "resetAction"); 397 + jContentPane.getActionMap().put("resetAction", resetAction); 398 } 399 return jContentPane; 400 } 401 @@ -270,6 +427,7 @@ 402 topPanelLocal.add(getLocalMachineLabel(), java.awt.BorderLayout.CENTER); 403 topPanelLocal.add(getLocalTopButton(), java.awt.BorderLayout.EAST); 404 topPanelLocal.setBackground(java.awt.Color.lightGray); 405 +//System.out.println("getTopPanelLocal"); 406 } 407 return topPanelLocal; 408 } 409 @@ -288,6 +446,7 @@ 410 topPanelRemote.add(getRemoteMachineLabel(), java.awt.BorderLayout.CENTER); 411 topPanelRemote.add(getRemoteTopButton(), java.awt.BorderLayout.EAST); 412 topPanelRemote.setBackground(java.awt.Color.lightGray); 413 +//System.out.println("getTopPanelRemote"); 414 } 415 return topPanelRemote; 416 } 417 @@ -301,6 +460,7 @@ 418 if (topPanelCenter == null) { 419 topPanelCenter = new javax.swing.JPanel(); 420 topPanelCenter.add(getDummyButton(), null); 421 +//System.out.println("getTopPanelCenter"); 422 } 423 return topPanelCenter; 424 } 425 @@ -328,6 +488,7 @@ 426 topPanel.add(getRemoteTopButton(), null); 427 topPanel.setBackground(java.awt.Color.lightGray); 428 */ 429 +//System.out.println("getTopPanel"); 430 } 431 return topPanel; 432 } 433 @@ -348,6 +509,7 @@ 434 statusPanel.add(getJProgressBar(), null); 435 statusPanel.add(getConnectionStatus(), null); 436 statusPanel.setBackground(java.awt.Color.lightGray); 437 +//System.out.println("getStatusPanel"); 438 439 } 440 return statusPanel; 441 @@ -368,6 +530,7 @@ 442 remotePanel.add(getRemoteScrollPane(), null); 443 remotePanel.add(getRemoteStatus(), null); 444 remotePanel.setBackground(java.awt.Color.lightGray); 445 +//System.out.println("getRemotePanel"); 446 } 447 return remotePanel; 448 } 449 @@ -390,6 +553,7 @@ 450 localPanel.setComponentOrientation( 451 java.awt.ComponentOrientation.UNKNOWN); 452 localPanel.setName("localPanel"); 453 +//System.out.println("getLocalPanel"); 454 } 455 return localPanel; 456 } 457 @@ -405,12 +569,15 @@ 458 buttonPanel = new javax.swing.JPanel(); 459 buttonPanel.setLayout(null); 460 buttonPanel.add(getReceiveButton(), null); 461 + buttonPanel.add(getRefreshButton(), null); // runge/x11vnc 462 + buttonPanel.add(getViewButton(), null); // runge/x11vnc 463 buttonPanel.add(getNewFolderButton(), null); 464 buttonPanel.add(getCloseButton(), null); 465 buttonPanel.add(getDeleteButton(), null); 466 buttonPanel.add(getSendButton(), null); 467 buttonPanel.add(getStopButton(), null); 468 buttonPanel.setBackground(java.awt.Color.lightGray); 469 +//System.out.println("getButtonPanel"); 470 } 471 return buttonPanel; 472 } 473 @@ -422,10 +589,11 @@ 474 private javax.swing.JButton getSendButton() { 475 if (sendButton == null) { 476 sendButton = new javax.swing.JButton(); 477 - sendButton.setBounds(20, 30, 97, 25); 478 + sendButton.setBounds(15, 30, 107, 25); // runge/x11vnc 479 sendButton.setText("Send >>"); 480 sendButton.setName("sendButton"); 481 sendButton.addActionListener(this); 482 +//System.out.println("getSendButton"); 483 484 } 485 return sendButton; 486 @@ -438,7 +606,7 @@ 487 private javax.swing.JButton getReceiveButton() { 488 if (receiveButton == null) { 489 receiveButton = new javax.swing.JButton(); 490 - receiveButton.setBounds(20, 60, 97, 25); 491 + receiveButton.setBounds(15, 60, 107, 25); // runge/x11vnc 492 receiveButton.setText("<< Receive"); 493 receiveButton.setName("receiveButton"); 494 receiveButton.addActionListener(this); 495 @@ -453,7 +621,7 @@ 496 private javax.swing.JButton getDeleteButton() { 497 if (deleteButton == null) { 498 deleteButton = new javax.swing.JButton(); 499 - deleteButton.setBounds(20, 110, 97, 25); 500 + deleteButton.setBounds(15, 110, 107, 25); // runge/x11vnc 501 deleteButton.setText("Delete File"); 502 deleteButton.setName("deleteButton"); 503 deleteButton.addActionListener(this); 504 @@ -468,7 +636,7 @@ 505 private javax.swing.JButton getNewFolderButton() { 506 if (newFolderButton == null) { 507 newFolderButton = new javax.swing.JButton(); 508 - newFolderButton.setBounds(20, 140, 97, 25); 509 + newFolderButton.setBounds(15, 140, 107, 25); // runge/x11vnc 510 newFolderButton.setText("New Folder"); 511 newFolderButton.setName("newFolderButton"); 512 newFolderButton.addActionListener(this); 513 @@ -476,6 +644,39 @@ 514 return newFolderButton; 515 } 516 517 +// begin runge/x11vnc 518 + /** 519 + * This method initializes refreshButton 520 + * 521 + * @return javax.swing.JButton 522 + */ 523 + private javax.swing.JButton getRefreshButton() { 524 + if (refreshButton == null) { 525 + refreshButton = new javax.swing.JButton(); 526 + refreshButton.setBounds(15, 170, 107, 25); 527 + refreshButton.setText("Refresh"); 528 + refreshButton.setName("refreshButton"); 529 + refreshButton.addActionListener(this); 530 + } 531 + return refreshButton; 532 + } 533 + /** 534 + * This method initializes viewButton 535 + * 536 + * @return javax.swing.JButton 537 + */ 538 + private javax.swing.JButton getViewButton() { 539 + if (viewButton == null) { 540 + viewButton = new javax.swing.JButton(); 541 + viewButton.setBounds(15, 200, 107, 25); 542 + viewButton.setText("View File"); 543 + viewButton.setName("viewButton"); 544 + viewButton.addActionListener(this); 545 + } 546 + return viewButton; 547 + } 548 +// end runge/x11vnc 549 + 550 /** 551 * This method initializes stopButton 552 * 553 @@ -486,7 +687,7 @@ 554 if (stopButton == null) 555 { 556 stopButton = new javax.swing.JButton(); 557 - stopButton.setBounds(20, 200, 97, 25); 558 + stopButton.setBounds(15, 230, 107, 25); // runge/x11vnc 559 stopButton.setText("Stop"); 560 stopButton.setName("stopButton"); 561 stopButton.addActionListener(this); 562 @@ -503,8 +704,12 @@ 563 private javax.swing.JButton getCloseButton() { 564 if (closeButton == null) { 565 closeButton = new javax.swing.JButton(); 566 - closeButton.setBounds(20, 325, 97, 25); 567 - closeButton.setText("Close"); 568 + closeButton.setBounds(15, 325, 107, 25); // runge/x11vnc 569 + if (viewer.ftpOnly) { 570 + closeButton.setText("Quit"); 571 + } else { 572 + closeButton.setText("Close"); 573 + } 574 closeButton.setName("closeButton"); 575 closeButton.addActionListener(this); 576 } 577 @@ -551,6 +756,7 @@ 578 //Select the second entry (e.g. C:\) 579 // localDrivesComboBox.setSelectedIndex(1); 580 localDrivesComboBox.addActionListener(this); 581 +//System.out.println("getLocalDrivesComboBox"); 582 } 583 updateDriveList = false; 584 return localDrivesComboBox; 585 @@ -567,6 +773,7 @@ 586 remoteDrivesComboBox.setFont( 587 new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); 588 remoteDrivesComboBox.addActionListener(this); 589 +//System.out.println("getRemoteDrivesComboBox"); 590 591 } 592 return remoteDrivesComboBox; 593 @@ -587,6 +794,7 @@ 594 localMachineLabel.setFont( 595 new java.awt.Font("Dialog", java.awt.Font.BOLD, 11)); 596 localMachineLabel.setEditable(false); 597 +//System.out.println("getLocalMachineLabel"); 598 } 599 return localMachineLabel; 600 } 601 @@ -622,6 +830,7 @@ 602 localTopButton.setFont( 603 new java.awt.Font("Dialog", java.awt.Font.BOLD, 10)); 604 localTopButton.addActionListener(this); 605 +//System.out.println("getLocalTopButton"); 606 } 607 return localTopButton; 608 } 609 @@ -638,6 +847,7 @@ 610 remoteTopButton.setFont( 611 new java.awt.Font("Dialog", java.awt.Font.BOLD, 10)); 612 remoteTopButton.addActionListener(this); 613 +//System.out.println("getRemoteTopButton"); 614 } 615 return remoteTopButton; 616 } 617 @@ -650,9 +860,24 @@ 618 private javax.swing.JList getLocalFileTable() { 619 if (localFileTable == null) { 620 localList = new Vector(0); 621 + localListInfo = new Vector(0); 622 localFileTable = new JList(localList); 623 + MouseMotionListener mlisten = new MouseMotionAdapter() { 624 + public void mouseMoved(MouseEvent e) { 625 + int index = localFileTable.locationToIndex(e.getPoint()); 626 + if (index == lastLocalIndex) { 627 + return; 628 + } else if (index < 0) { 629 + return; 630 + } 631 + lastLocalIndex = index; 632 + connectionStatus.setText((String) localListInfo.get(index)); 633 + } 634 + }; 635 localFileTable.addMouseListener(this); 636 + localFileTable.addMouseMotionListener(mlisten); 637 localFileTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 638 +//System.out.println("getLocalFileTable"); 639 } 640 return localFileTable; 641 } 642 @@ -669,6 +894,7 @@ 643 localScrollPane.setFont( 644 new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); 645 localScrollPane.setName("localFileList"); 646 +//System.out.println("getLocalScrollPane"); 647 } 648 return localScrollPane; 649 } 650 @@ -680,10 +906,25 @@ 651 private javax.swing.JList getRemoteFileTable() { 652 if (remoteFileTable == null) { 653 remoteList = new Vector(0); 654 + remoteListInfo = new Vector(0); 655 remoteFileTable = new JList(remoteList); 656 + MouseMotionListener mlisten = new MouseMotionAdapter() { 657 + public void mouseMoved(MouseEvent e) { 658 + int index = remoteFileTable.locationToIndex(e.getPoint()); 659 + if (index == lastRemoteIndex) { 660 + return; 661 + } else if (index < 0) { 662 + return; 663 + } 664 + lastRemoteIndex = index; 665 + connectionStatus.setText((String) remoteListInfo.get(index)); 666 + } 667 + }; 668 remoteFileTable.addMouseListener(this); 669 + remoteFileTable.addMouseMotionListener(mlisten); 670 remoteFileTable.setSelectedValue("C:\\", false); 671 remoteFileTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 672 +//System.out.println("getRemoteFileTable"); 673 674 } 675 return remoteFileTable; 676 @@ -698,6 +939,7 @@ 677 remoteScrollPane = new javax.swing.JScrollPane(); 678 remoteScrollPane.setViewportView(getRemoteFileTable()); 679 remoteScrollPane.setPreferredSize(new java.awt.Dimension(325, 418)); 680 +//System.out.println("getRemoteScrollPane"); 681 } 682 return remoteScrollPane; 683 } 684 @@ -716,6 +958,7 @@ 685 remoteLocation.setBackground(new Color(255,255,238)); 686 remoteLocation.setFont( 687 new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); 688 +//System.out.println("getRemoteLocation"); 689 } 690 return remoteLocation; 691 } 692 @@ -732,6 +975,7 @@ 693 localLocation.setBackground( new Color(255,255,238)); 694 localLocation.setFont( 695 new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); 696 +//System.out.println("getLocalLocation"); 697 } 698 return localLocation; 699 } 700 @@ -748,6 +992,7 @@ 701 localStatus.setFont( 702 new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); 703 localStatus.setEditable(false); 704 +//System.out.println("getLocalStatus"); 705 } 706 return localStatus; 707 } 708 @@ -764,6 +1009,7 @@ 709 remoteStatus.setFont( 710 new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); 711 remoteStatus.setEditable(false); 712 +//System.out.println("getRemoteStatus"); 713 } 714 return remoteStatus; 715 } 716 @@ -777,9 +1023,10 @@ 717 historyComboBox = new javax.swing.JComboBox(); 718 historyComboBox.setFont( 719 new java.awt.Font("Dialog", java.awt.Font.BOLD, 10)); 720 - historyComboBox.insertItemAt(new String("Pulldown to view history ..."),0); 721 + historyComboBox.insertItemAt(new String("Pulldown to view history; Press Escape to Close/Quit; Press Ctrl-R to Reset Panel."),0); 722 historyComboBox.setSelectedIndex(0); 723 historyComboBox.addActionListener(this); 724 +//System.out.println("getHistoryComboBox"); 725 } 726 return historyComboBox; 727 } 728 @@ -791,6 +1038,7 @@ 729 private javax.swing.JProgressBar getJProgressBar() { 730 if (jProgressBar == null) { 731 jProgressBar = new javax.swing.JProgressBar(); 732 +//System.out.println("getJProgressBar"); 733 } 734 return jProgressBar; 735 } 736 @@ -806,6 +1054,7 @@ 737 connectionStatus.setBackground(java.awt.Color.lightGray); 738 connectionStatus.setFont( 739 new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); 740 +//System.out.println("getConnectionStatus"); 741 } 742 connectionStatus.setEditable(false); 743 return connectionStatus; 744 @@ -815,7 +1064,12 @@ 745 * Implements Action listener. 746 */ 747 public void actionPerformed(ActionEvent evt) { 748 - System.out.println(evt.getSource()); 749 +// System.out.println(evt.getSource()); 750 + 751 + if (ignore_events) { 752 + System.out.println("ignore_events: " + evt.getSource()); 753 + return; 754 + } 755 756 if (evt.getSource() == closeButton) 757 { // Close Button 758 @@ -829,15 +1083,27 @@ 759 { 760 doReceive(); 761 } 762 +// begin runge/x11vnc 763 + else if (evt.getSource() == viewButton) 764 + { 765 + doView(); 766 + } 767 +// end runge/x11vnc 768 else if (evt.getSource() == localDrivesComboBox) 769 { 770 changeLocalDrive(); 771 } 772 else if (evt.getSource() == remoteDrivesComboBox) 773 { 774 +//System.out.println("remoteDrivesComboBox"); // runge/x11vnc 775 changeRemoteDrive(); 776 - remoteList.clear(); 777 - remoteFileTable.setListData(remoteList); 778 + 779 + // are these really needed? changeRemoteDrive() does them at the end. 780 + if (false) { 781 + remoteList.clear(); 782 + remoteListInfo.clear(); 783 + remoteFileTable.setListData(remoteList); 784 + } 785 } 786 else if (evt.getSource() == localTopButton) 787 { 788 @@ -845,12 +1111,17 @@ 789 } 790 else if (evt.getSource() == remoteTopButton) 791 { 792 +//System.out.println("remoteTopButton"); // runge/x11vnc 793 changeRemoteDrive(); 794 } 795 else if(evt.getSource() == deleteButton) 796 { 797 doDelete(); 798 } 799 + else if(evt.getSource() == refreshButton) 800 + { 801 + doRefresh(); 802 + } 803 else if(evt.getSource()==newFolderButton) 804 { 805 doNewFolder(); 806 @@ -864,7 +1135,7 @@ 807 808 private void doNewFolder() 809 { 810 - String name = JOptionPane.showInputDialog(null,"Enter new directory name", "Create New Directory", JOptionPane.QUESTION_MESSAGE); 811 + String name = JOptionPane.showInputDialog(jContentPane,"Enter new directory name", "Create New Directory", JOptionPane.QUESTION_MESSAGE); 812 if(selectedTable.equals("remote")) 813 { 814 name = remoteLocation.getText()+name; 815 @@ -880,34 +1151,106 @@ 816 historyComboBox.setSelectedIndex(0); 817 } 818 } 819 - private void doClose() 820 + public void doClose() 821 { 822 + if (viewer.ftpOnly) { 823 + viewer.disconnect(); 824 + return; 825 + } 826 try { 827 this.setVisible(false); 828 - viewer.rfb.writeFramebufferUpdateRequest( 829 - 0, 830 - 0, 831 - viewer.rfb.framebufferWidth, 832 - viewer.rfb.framebufferHeight, 833 - true); 834 + viewer.rfb.writeFramebufferUpdateRequest(0, 0, viewer.rfb.framebufferWidth, 835 + viewer.rfb.framebufferHeight, true); 836 + 837 + if (false) { 838 + this.dispose(); 839 + jContentPane = null; 840 + } 841 } catch (IOException e) { 842 // TODO Auto-generated catch block 843 e.printStackTrace(); 844 } 845 } 846 + private void unSwing() { 847 + jContentPane = null; 848 + topPanel = null; 849 + topPanelLocal = null; 850 + topPanelRemote = null; 851 + topPanelCenter = null; 852 + statusPanel = null; 853 + remotePanel = null; 854 + localPanel = null; 855 + buttonPanel = null; 856 + sendButton = null; 857 + receiveButton = null; 858 + deleteButton = null; 859 + newFolderButton = null; 860 + stopButton = null; 861 + closeButton = null; 862 + dummyButton = null; 863 + localDrivesComboBox = null; 864 + remoteDrivesComboBox = null; 865 + localMachineLabel = null; 866 + remoteMachineLabel = null; 867 + localTopButton = null; 868 + remoteTopButton = null; 869 + localScrollPane = null; 870 + localFileTable = null; 871 + remoteScrollPane = null; 872 + remoteFileTable = null; 873 + remoteLocation = null; 874 + localLocation = null; 875 + localStatus = null; 876 + remoteStatus = null; 877 + historyComboBox = null; 878 + jProgressBar = null; 879 + connectionStatus = null; 880 + viewButton = null; 881 + refreshButton = null; 882 + } 883 + 884 + public void doReset() 885 + { 886 + try { 887 + this.setVisible(false); 888 + this.dispose(); 889 + jContentPane = null; 890 + try {Thread.sleep(500);} catch (InterruptedException e) {} 891 + viewer.ftp_init(); 892 + } catch (Exception e) { 893 + // TODO Auto-generated catch block 894 + e.printStackTrace(); 895 + } 896 + } 897 898 + public void doOpen() 899 + { 900 + try { 901 + this.setVisible(true); 902 + if (false) { 903 + this.initialize(); 904 + } 905 + } catch (Exception e) { 906 + // TODO Auto-generated catch block 907 + e.printStackTrace(); 908 + } 909 + } 910 private void doDelete() 911 { 912 - System.out.println("Delete Button Pressed"); 913 +// System.out.println("Delete Button Pressed"); 914 //Call this method to delete a file at server 915 if(selectedTable.equals("remote")) 916 { 917 - String sFileName = ((String) this.remoteFileTable.getSelectedValue()); 918 + Object selected = this.remoteFileTable.getSelectedValue(); 919 + if (selected == null) { 920 + return; 921 + } 922 + String sFileName = ((String) selected); 923 924 // sf@2004 - Directory can't be deleted 925 if (sFileName.substring(0, 2).equals(" [") && sFileName.substring((sFileName.length() - 1), sFileName.length()).equals("]")) 926 { 927 - JOptionPane.showMessageDialog(null, (String)"Directory Deletion is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); 928 + JOptionPane.showMessageDialog(jContentPane, (String)"Directory Deletion is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); 929 return; 930 } 931 932 @@ -916,7 +1259,7 @@ 933 // sf@2004 - Delete prompt 934 if (remoteList.contains(sFileName)) 935 { 936 - int r = JOptionPane.showConfirmDialog(null, "Are you sure you want to delete the file \n< " + sFileName + " >\n on Remote Machine ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); 937 + int r = JOptionPane.showConfirmDialog(jContentPane, "Are you sure you want to delete the file \n< " + sFileName + " >\n on Remote Machine ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); 938 if (r == JOptionPane.NO_OPTION) 939 return; 940 } 941 @@ -926,18 +1269,22 @@ 942 } 943 else 944 { 945 - String sFileName = ((String) this.localFileTable.getSelectedValue()); 946 + Object selected = this.localFileTable.getSelectedValue(); 947 + if (selected == null) { 948 + return; 949 + } 950 + String sFileName = ((String) selected); 951 952 // sf@2004 - Directory can't be deleted 953 if (sFileName.substring(0, 2).equals(" [") && sFileName.substring((sFileName.length() - 1), sFileName.length()).equals("]")) 954 { 955 - JOptionPane.showMessageDialog(null, (String)"Directory Deletion is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); 956 + JOptionPane.showMessageDialog(jContentPane, (String)"Directory Deletion is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); 957 return; 958 } 959 // sf@2004 - Delete prompt 960 if (localList.contains(sFileName)) 961 { 962 - int r = JOptionPane.showConfirmDialog(null, "Are you sure you want to delete the file \n< " + sFileName + " >\n on Local Machine ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); 963 + int r = JOptionPane.showConfirmDialog(jContentPane, "Are you sure you want to delete the file \n< " + sFileName + " >\n on Local Machine ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); 964 if (r == JOptionPane.NO_OPTION) 965 return; 966 } 967 @@ -952,21 +1299,25 @@ 968 969 private void doReceive() 970 { 971 - System.out.println("Received Button Pressed"); 972 +// System.out.println("Received Button Pressed"); 973 974 - String sFileName = ((String) this.remoteFileTable.getSelectedValue()); 975 + Object selected = this.remoteFileTable.getSelectedValue(); 976 + if (selected == null) { 977 + return; 978 + } 979 + String sFileName = ((String) selected); 980 981 // sf@2004 - Directory can't be transfered 982 if (sFileName.substring(0, 2).equals(" [") && sFileName.substring((sFileName.length() - 1), sFileName.length()).equals("]")) 983 { 984 - JOptionPane.showMessageDialog(null, (String)"Directory Transfer is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); 985 + JOptionPane.showMessageDialog(jContentPane, (String)"Directory Transfer is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); 986 return; 987 } 988 989 // sf@2004 - Overwrite prompt 990 if (localList.contains(sFileName)) 991 { 992 - int r = JOptionPane.showConfirmDialog(null, "The file < " + sFileName + " >\n already exists on Local Machine\n Are you sure you want to overwrite it ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); 993 + int r = JOptionPane.showConfirmDialog(jContentPane, "The file < " + sFileName + " >\n already exists on Local Machine\n Are you sure you want to overwrite it ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); 994 if (r == JOptionPane.NO_OPTION) 995 return; 996 } 997 @@ -979,23 +1330,101 @@ 998 viewer.rfb.requestRemoteFile(remoteFileName,localDestinationPath); 999 } 1000 1001 +// begin runge/x11vnc 1002 + private void doRefresh() 1003 + { 1004 + System.out.println("Refreshing Local and Remote."); 1005 + refreshLocalLocation(); 1006 + refreshRemoteLocation(); 1007 + } 1008 + 1009 + private void doView() 1010 + { 1011 +// System.out.println("View Button Pressed"); 1012 + 1013 + if (selectedTable == null) { 1014 + return; 1015 + } 1016 + if (selectedTable.equals("remote")) { 1017 + viewRemote(); 1018 + } else if (selectedTable.equals("local")) { 1019 + viewLocal(); 1020 + } 1021 + } 1022 + 1023 + private File doReceiveTmp() 1024 + { 1025 + 1026 + if (remoteFileTable == null) { 1027 + return null; 1028 + } 1029 + Object selected = this.remoteFileTable.getSelectedValue(); 1030 + if (selected == null) { 1031 + return null; 1032 + } 1033 + String sFileName = ((String) selected); 1034 + 1035 + if (sFileName == null) { 1036 + return null; 1037 + } 1038 + 1039 + // sf@2004 - Directory can't be transfered 1040 + if (sFileName.substring(0, 2).equals(" [") && sFileName.substring((sFileName.length() - 1), sFileName.length()).equals("]")) 1041 + { 1042 + return null; 1043 + } 1044 + 1045 + File tmp = null; 1046 + try { 1047 + tmp = File.createTempFile("ULTRAFTP", ".txt"); 1048 + } catch (Exception e) { 1049 + return null; 1050 + } 1051 + 1052 + //updateHistory("Downloaded " + localSelection.toString()); 1053 + String remoteFileName = this.remoteLocation.getText(); 1054 + remoteFileName+= ((String) this.remoteFileTable.getSelectedValue()).substring(1); 1055 + System.out.println("remoteFileName: " + remoteFileName); 1056 +if (false) { 1057 + char[] b = remoteFileName.toCharArray(); 1058 + for (int n = 0; n < b.length; n++) { 1059 + System.out.print(Integer.toHexString(b[n]) + " "); 1060 + } 1061 + System.out.println(""); 1062 + for (int n = 0; n < b.length; n++) { 1063 + System.out.print(b[n]); 1064 + } 1065 + System.out.println(""); 1066 +} 1067 + 1068 + String localDestinationPath = tmp.getAbsolutePath(); 1069 + viewer.rfb.requestRemoteFile(remoteFileName,localDestinationPath); 1070 + System.out.println("ReceiveTmp: " + localDestinationPath); 1071 + return tmp; 1072 + } 1073 +// end runge/x11vnc 1074 + 1075 private void doSend() 1076 { 1077 - System.out.println("Send Button Pressed"); 1078 +// System.out.println("Send Button Pressed"); 1079 1080 - String sFileName = ((String) this.localFileTable.getSelectedValue()); 1081 + Object selected = this.localFileTable.getSelectedValue(); 1082 + if (selected == null) { 1083 + return; 1084 + } 1085 + String sFileName = ((String) selected); 1086 1087 // sf@2004 - Directory can't be transfered 1088 if (sFileName.substring(0, 2).equals(" [") && sFileName.substring((sFileName.length() - 1), sFileName.length()).equals("]")) 1089 { 1090 - JOptionPane.showMessageDialog(null, (String)"Directory Transfer is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); 1091 + JOptionPane.showMessageDialog(jContentPane, (String)"Directory Transfer is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); 1092 return; 1093 } 1094 1095 // sf@2004 - Overwrite prompt 1096 if (remoteList.contains(sFileName)) 1097 { 1098 - int r = JOptionPane.showConfirmDialog(null, "The file < " + sFileName + " >\n already exists on Remote Machine\n Are you sure you want to overwrite it ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); 1099 + int r = JOptionPane.showConfirmDialog(jContentPane, "The file < " + sFileName + " >\n already exists on Remote Machine\n Are you sure you want to overwrite it ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); 1100 if (r == JOptionPane.NO_OPTION) 1101 return; 1102 } 1103 @@ -1013,6 +1442,7 @@ 1104 // 1105 private void doStop() 1106 { 1107 + System.out.println("** Current Transfer Aborted **"); 1108 viewer.rfb.fAbort = true; 1109 } 1110 /** 1111 @@ -1024,6 +1454,14 @@ 1112 System.out.println("History: " + message); 1113 historyComboBox.insertItemAt(new String(message), 0); 1114 } 1115 + 1116 + public void receivedRemoteDirectoryName(String str) { 1117 + if (doingShortcutDir) { 1118 + if (str.length() > 1) { 1119 + remoteLocation.setText(str); 1120 + } 1121 + } 1122 + } 1123 1124 /** 1125 * This method updates the file table to the current selection of the remoteComboBox 1126 @@ -1034,11 +1472,44 @@ 1127 remoteSelection = null; 1128 1129 if (!updateDriveList) { 1130 - String drive = remoteDrivesComboBox.getSelectedItem().toString().substring(0,1)+ ":\\"; 1131 - viewer.rfb.readServerDirectory(drive); 1132 - remoteLocation.setText(drive); 1133 +//System.out.println("changeRemoteDrive-A " + drive); // begin runge/x11vnc 1134 + Object selected = remoteDrivesComboBox.getSelectedItem(); 1135 + if (selected != null) { 1136 + String instr = selected.toString(); 1137 + if (instr != null) { 1138 +System.out.println("changeRemoteDrive: instr='" + instr + "'"); 1139 + String drive = instr.substring(0,1)+ ":\\"; 1140 + if (instr.startsWith(" [")) { 1141 + int idx = instr.lastIndexOf(']'); 1142 + if (idx > 2) { 1143 + drive = instr.substring(2, idx); 1144 + } else { 1145 + drive = instr.substring(2); 1146 + } 1147 + if (drive.equals("Home")) { 1148 + drive = ""; 1149 + } 1150 + drive += "\\"; 1151 + doingShortcutDir = true; 1152 + } else { 1153 + doingShortcutDir = false; 1154 + drive = saveRemoteHack(drive); 1155 + } 1156 + gotShortcutDir = false; 1157 + viewer.rfb.readServerDirectory(drive); 1158 + if (!gotShortcutDir) { 1159 + remoteLocation.setText(drive); 1160 + } 1161 + } else { 1162 +System.out.println("changeRemoteDrive: instr null"); 1163 + } 1164 + } else { 1165 +System.out.println("changeRemoteDrive: selection null"); 1166 + } 1167 +//System.out.println("changeRemoteDrive-B " + drive); // end runge/x11vnc 1168 } 1169 remoteList.clear(); 1170 + remoteListInfo.clear(); 1171 remoteFileTable.setListData(remoteList); 1172 } 1173 /** 1174 @@ -1048,6 +1519,7 @@ 1175 private void changeLocalDrive() 1176 { 1177 File currentDrive = new File(localDrivesComboBox.getSelectedItem().toString()); 1178 +System.out.println("changeLocalDrive " + currentDrive.toString()); // runge/x11vnc 1179 if(currentDrive.canRead()) 1180 { 1181 localSelection = null; 1182 @@ -1057,9 +1529,11 @@ 1183 else 1184 { 1185 localList.clear(); 1186 + localListInfo.clear(); 1187 localStatus.setText("WARNING: Drive " + localDrivesComboBox.getSelectedItem().toString()); 1188 connectionStatus.setText(" > WARNING - Local Drive unavailable (possibly restricted access or media not present)"); 1189 } 1190 + 1191 } 1192 /** 1193 * Determines which FileTable was double-clicked and updates the table 1194 @@ -1098,10 +1572,18 @@ 1195 selectedTable = "remote"; 1196 localFileTable.setBackground(new Color(238, 238, 238)); 1197 remoteFileTable.setBackground(new Color(255, 255, 255)); 1198 - String name = (remoteFileTable.getSelectedValue().toString()).substring(1); 1199 + Object selected = remoteFileTable.getSelectedValue(); 1200 + if (selected == null) { 1201 + return; 1202 + } 1203 + String selstr = selected.toString(); 1204 + if (selstr == null) { 1205 + return; 1206 + } 1207 + String name = selstr.substring(1); 1208 if( !name.substring(0, 2).equals(" [")) 1209 remoteSelection = remoteLocation.getText() + name.substring(0, name.length()); 1210 - 1211 + 1212 } 1213 1214 /* 1215 @@ -1115,10 +1597,38 @@ 1216 localFileTable.setBackground(new Color(255, 255, 255)); 1217 File currentSelection = new File(currentLocalDirectory, getTrimmedSelection()); 1218 1219 - if(currentSelection.isFile()) 1220 +// begin runge/x11vnc 1221 + // localSelection = currentSelection.getAbsoluteFile(); 1222 + if(currentSelection.isFile()) { 1223 localSelection = currentSelection.getAbsoluteFile(); 1224 + localCurrentIsDir = false; 1225 + } else { 1226 + localCurrentIsDir = true; 1227 + } 1228 +// end runge/x11vnc 1229 1230 } 1231 + 1232 +// begin runge/x11vnc 1233 + private void viewRemote() { 1234 + File tmp = doReceiveTmp(); 1235 + if (tmp == null) { 1236 + return; 1237 + } 1238 + TextViewer tv = new TextViewer("Remote: " + remoteSelection, tmp, true); 1239 + } 1240 + private void viewLocal() { 1241 + if (localSelection == null) { 1242 + return; 1243 + } 1244 + if (localCurrentIsDir) { 1245 + return; 1246 + } 1247 + File loc = new File(localSelection.toString()); 1248 + TextViewer tv = new TextViewer("Local: " + localSelection.toString(), loc, false); 1249 + } 1250 +// end runge/x11vnc 1251 + 1252 /** 1253 * Updates the Remote File Table based on selection. Called from mouseClicked handler 1254 */ 1255 @@ -1126,20 +1636,29 @@ 1256 String name = null; 1257 String action = null; 1258 String drive = null; 1259 - name = (remoteFileTable.getSelectedValue().toString()).substring(1); 1260 + Object selected = remoteFileTable.getSelectedValue(); 1261 + if (selected == null) { 1262 + return; 1263 + } 1264 + String sname = selected.toString(); 1265 + if (sname == null) { 1266 + return; 1267 + } 1268 + name = sname.substring(1); 1269 1270 if (name.equals("[..]")) 1271 { 1272 action = "up"; 1273 remoteSelection = null; 1274 drive = remoteLocation.getText().substring(0, remoteLocation.getText().length() - 1); 1275 - // JOptionPane.showMessageDialog(null, (String)drive, "FileTransfer DEBUG", JOptionPane.INFORMATION_MESSAGE); 1276 + // JOptionPane.showMessageDialog(jContentPane, (String)drive, "FileTransfer DEBUG", JOptionPane.INFORMATION_MESSAGE); 1277 int index = drive.lastIndexOf("\\"); 1278 drive = drive.substring(0, index + 1); 1279 1280 remoteLocation.setText(drive); 1281 viewer.rfb.readServerDirectory(drive); 1282 remoteList.clear(); 1283 + remoteListInfo.clear(); 1284 remoteFileTable.setListData(remoteList); 1285 } 1286 else if (!name.substring(0, 2).equals(" [") && !name.substring((name.length() - 1), name.length()).equals("]")) 1287 @@ -1149,6 +1668,7 @@ 1288 remoteSelection = remoteLocation.getText() + name.substring(0, name.length()); 1289 drive = remoteLocation.getText(); 1290 // ?? 1291 + viewRemote(); // runge/x11vnc 1292 } 1293 else 1294 { 1295 @@ -1159,10 +1679,12 @@ 1296 remoteLocation.setText(drive); 1297 viewer.rfb.readServerDirectory(drive); 1298 remoteList.clear(); 1299 + remoteListInfo.clear(); 1300 remoteFileTable.setListData(remoteList); 1301 } 1302 //remoteLocation.setText(drive); 1303 } 1304 + 1305 /** 1306 * Updates the Local File Table based on selection. Called from MouseClicked handler 1307 */ 1308 @@ -1188,6 +1710,7 @@ 1309 else if (currentSelection.isFile()) 1310 { 1311 localSelection = currentSelection.getAbsoluteFile(); 1312 + viewLocal(); // runge/x11vnc 1313 } 1314 else if (currentSelection.isDirectory()) 1315 { 1316 @@ -1201,13 +1724,22 @@ 1317 * 1318 */ 1319 private String getTrimmedSelection(){ 1320 - String currentSelection = (localFileTable.getSelectedValue().toString()).substring(1); 1321 - if(currentSelection.substring(0,1).equals("[") && 1322 - currentSelection.substring(currentSelection.length()-1,currentSelection.length()).equals("]")){ 1323 - return currentSelection.substring(1,currentSelection.length()-1); 1324 - } else { 1325 - return currentSelection; 1326 - } 1327 + String currentSelection = ""; 1328 + Object selected = localFileTable.getSelectedValue(); 1329 + if (selected == null) { 1330 + return currentSelection; 1331 + } 1332 + String selstr = selected.toString(); 1333 + if (selstr == null) { 1334 + return currentSelection; 1335 + } 1336 + currentSelection = selstr.substring(1); 1337 + if(currentSelection.substring(0,1).equals("[") && 1338 + currentSelection.substring(currentSelection.length()-1,currentSelection.length()).equals("]")){ 1339 + return currentSelection.substring(1,currentSelection.length()-1); 1340 + } else { 1341 + return currentSelection; 1342 + } 1343 } 1344 1345 /* 1346 @@ -1241,36 +1773,148 @@ 1347 return null; 1348 } 1349 1350 + String timeStr(long t) { 1351 + Date date = new Date(t); 1352 + return date.toString(); 1353 + } 1354 + String dotPast(double f, int n) { 1355 + String fs = "" + f; 1356 + int i = fs.lastIndexOf(".") + n; 1357 + if (i >= 0) { 1358 + int len = fs.length(); 1359 + if (i >= len) { 1360 + i = len-1; 1361 + } 1362 + fs = fs.substring(0, i); 1363 + } 1364 + return fs; 1365 + } 1366 + String sizeStr(int s) { 1367 + if (s < 0) { 1368 + return s + "? B"; 1369 + } else if (s < 1024) { 1370 + return s + " B"; 1371 + } else if (s < 1024 * 1024) { 1372 + double k = s / 1024.0; 1373 + String ks = dotPast(k, 3); 1374 + 1375 + return s + " (" + ks + " KB)"; 1376 + } else { 1377 + double m = s / (1024.0*1024.0); 1378 + String ms = dotPast(m, 3); 1379 + return s + " (" + ms + " MB)"; 1380 + } 1381 + } 1382 + 1383 + int max_char(String text) { 1384 + int maxc = 0; 1385 + char chars[] = text.toCharArray(); 1386 + for (int n = 0; n < chars.length; n++) { 1387 + if ((int) chars[n] > maxc) { 1388 + maxc = (int) chars[n]; 1389 + } 1390 + } 1391 + return maxc; 1392 + } 1393 1394 /* 1395 * Navigates the local file structure up or down one directory 1396 */ 1397 public void changeLocalDirectory(File dir) 1398 { 1399 - currentLocalDirectory = dir; // Updates Global 1400 + dir = saveLocalHack(dir); // runge/x11vnc 1401 + 1402 + if (dir == null) { 1403 + connectionStatus.setText("Error changing local directory."); 1404 + historyComboBox.insertItemAt(new String("> Error changing local directory."), 0); 1405 + historyComboBox.setSelectedIndex(0); 1406 + return; 1407 + } 1408 + 1409 File allFiles[] = dir.listFiles(); // Reads files 1410 String[] contents = dir.list(); 1411 1412 + if (contents == null || allFiles == null) { 1413 + connectionStatus.setText("Error changing local directory."); 1414 + historyComboBox.insertItemAt(new String("> Error changing local directory."), 0); 1415 + historyComboBox.setSelectedIndex(0); 1416 + return; 1417 + } 1418 + 1419 + currentLocalDirectory = dir; // Updates Global 1420 +// begin runge/x11vnc 1421 +System.out.println("changeLocalDirectory: " + dir.toString()); 1422 + if (contents != null) { 1423 + java.util.Arrays.sort(contents, String.CASE_INSENSITIVE_ORDER); 1424 + for (int i = 0; i < contents.length; i++) { 1425 + allFiles[i] = new File(dir, contents[i]); 1426 + } 1427 + } else { 1428 + return; 1429 + } 1430 +// end runge/x11vnc 1431 + 1432 localList.clear(); 1433 + localListInfo.clear(); 1434 localList.addElement(" [..]"); 1435 + localListInfo.addElement(" [..]"); 1436 + 1437 + ArrayList DirInfo = new ArrayList(); 1438 + ArrayList FilInfo = new ArrayList(); 1439 + 1440 + Charset charset = Charset.forName("ISO-8859-1"); 1441 + CharsetDecoder decoder = charset.newDecoder(); 1442 + CharsetEncoder encoder = charset.newEncoder(); 1443 1444 // Populate the Lists 1445 for (int i = 0; i < contents.length; i++) 1446 { 1447 - if (allFiles[i].isDirectory()) 1448 + String f1 = contents[i]; 1449 + 1450 +if (false) { 1451 + 1452 +System.out.println("max_char: " + max_char(f1) + " " + f1); 1453 + if (max_char(f1) > 255) { 1454 + try { 1455 +System.out.println("bbuf1"); 1456 + ByteBuffer bbuf = encoder.encode(CharBuffer.wrap(f1.toCharArray())); 1457 +System.out.println("bbuf2"); 1458 + CharBuffer cbuf = decoder.decode(bbuf); 1459 +System.out.println("bbuf3"); 1460 + f1 = cbuf.toString(); 1461 +System.out.println("did bbuf: " + f1); 1462 + } catch (Exception e) { 1463 + ; 1464 + } 1465 + } 1466 +} 1467 + 1468 + String f2 = f1; 1469 + if (f2.length() < 24) { 1470 + for (int ik = f2.length(); ik < 24; ik++) { 1471 + f2 = f2 + " "; 1472 + } 1473 + } 1474 + String s = f2 + " \tLastmod: " + timeStr(allFiles[i].lastModified()) + " \t\tSize: " + sizeStr((int) allFiles[i].length()); 1475 + if (allFiles[i].isDirectory()) { 1476 // localList.addElement("[" + contents[i] + "]"); 1477 - DirsList.add(" [" + contents[i] + "]"); // sf@2004 1478 - else 1479 - { 1480 + DirsList.add(" [" + f1 + "]"); // sf@2004 1481 + DirInfo.add(s); 1482 + } else { 1483 // localList.addElement(contents[i]); 1484 - FilesList.add(" " + contents[i]); // sf@2004 1485 + FilesList.add(" " + f1); // sf@2004 1486 + FilInfo.add(s); 1487 } 1488 } 1489 // sf@2004 1490 - for (int i = 0; i < DirsList.size(); i++) 1491 + for (int i = 0; i < DirsList.size(); i++) { 1492 localList.addElement(DirsList.get(i)); 1493 - for (int i = 0; i < FilesList.size(); i++) 1494 + localListInfo.addElement(DirInfo.get(i)); 1495 + } 1496 + for (int i = 0; i < FilesList.size(); i++) { 1497 localList.addElement(FilesList.get(i)); 1498 + localListInfo.addElement(FilInfo.get(i)); 1499 + } 1500 1501 FilesList.clear(); 1502 DirsList.clear(); 1503 @@ -1296,3 +1940,147 @@ 1504 } 1505 1506 } // @jve:visual-info decl-index=0 visual-constraint="10,10" 1507 + 1508 +// begin runge/x11vnc 1509 +class TextViewer extends JFrame implements ActionListener { 1510 + 1511 + JTextArea textArea = new JTextArea(35, 80); 1512 + File file = null; 1513 + JButton refreshButton; 1514 + JButton dismissButton; 1515 + Timer tim = null; 1516 + int rcnt = 0; 1517 + int tms = 250; 1518 + boolean delete_it = false; 1519 + TextViewer me; 1520 + 1521 + public TextViewer(String s, File f, boolean d) { 1522 + 1523 + delete_it = d; 1524 + file = f; 1525 + me = this; 1526 + 1527 + JScrollPane scrollPane = new JScrollPane(textArea, 1528 + JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 1529 + JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); 1530 + 1531 + textArea.setEditable(false); 1532 + textArea.setFont(new Font("Monospaced", Font.PLAIN, 12)); 1533 + 1534 + KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, InputEvent.SHIFT_MASK); 1535 + AbstractAction escapeAction = new AbstractAction() { 1536 + public void actionPerformed(ActionEvent actionEvent) { 1537 + cleanse(); 1538 + me.dispose(); 1539 + } 1540 + }; 1541 + textArea.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(stroke, "escapeAction"); 1542 + textArea.getInputMap().put(stroke, "escapeAction"); 1543 + textArea.getActionMap().put("escapeAction", escapeAction); 1544 + 1545 + refreshButton = new JButton(); 1546 + refreshButton.setText("Reload"); 1547 + refreshButton.setName("refreshButton"); 1548 + refreshButton.addActionListener(this); 1549 + 1550 + dismissButton = new JButton(); 1551 + dismissButton.setText("Dismiss"); 1552 + dismissButton.setName("dismissButton"); 1553 + dismissButton.addActionListener(this); 1554 + 1555 + JPanel buttons = new JPanel(); 1556 + buttons.setLayout(new BorderLayout()); 1557 + buttons.add(refreshButton, BorderLayout.WEST); 1558 + buttons.add(dismissButton, BorderLayout.EAST); 1559 + 1560 + JPanel content = new JPanel(); 1561 + content.setLayout(new BorderLayout()); 1562 + content.add(scrollPane, BorderLayout.CENTER); 1563 + content.add(buttons, BorderLayout.SOUTH); 1564 + 1565 + ActionListener tsk = new ActionListener() { 1566 + public void actionPerformed(ActionEvent evt) { 1567 + // System.out.println("tsk"); 1568 + refresh(); 1569 + } 1570 + }; 1571 + tim = new Timer(tms, tsk); 1572 + tim.start(); 1573 + 1574 + this.setContentPane(content); 1575 + this.setTitle("TextViewer - " + s); 1576 + this.pack(); 1577 + this.setVisible(true); 1578 + } 1579 + 1580 + private void refresh() { 1581 + 1582 + rcnt++; 1583 + if (rcnt * tms > 3000 && tim != null) { 1584 + tim.stop(); 1585 + tim = null; 1586 + } 1587 + BufferedReader input = null; 1588 + StringBuffer contents = new StringBuffer(); 1589 + try { 1590 + if (input == null) { 1591 + input = new BufferedReader(new FileReader(file)); 1592 + } 1593 + String line = null; 1594 + int i = 0; 1595 + while (( line = input.readLine()) != null) { 1596 + if (i == 0) { 1597 + // System.out.println("read"); 1598 + } 1599 + i++; 1600 + contents.append(line); 1601 + contents.append(System.getProperty("line.separator")); 1602 + } 1603 + } catch (Exception e) { 1604 + ; 1605 + } finally { 1606 + try { 1607 + if (input != null) { 1608 + input.close(); 1609 + input = null; 1610 + } 1611 + } catch (Exception e) { 1612 + ; 1613 + } 1614 + } 1615 + 1616 + textArea.setText(contents.toString()); 1617 + textArea.setCaretPosition(0); 1618 + } 1619 + 1620 + public void actionPerformed(ActionEvent evt) { 1621 + 1622 + if (evt.getSource() == refreshButton) { 1623 + refresh(); 1624 + } 1625 + if (evt.getSource() == dismissButton) { 1626 + cleanse(); 1627 + this.dispose(); 1628 + } 1629 + } 1630 + 1631 + private void cleanse() { 1632 + if (delete_it && file != null) { 1633 + try { 1634 + file.delete(); 1635 + file = null; 1636 + } catch (Exception e) { 1637 + ; 1638 + } 1639 + } 1640 + } 1641 + 1642 + protected void finalize() throws Throwable { 1643 + try { 1644 + cleanse(); 1645 + } finally { 1646 + super.finalize(); 1647 + } 1648 + } 1649 +} 1650 +// end runge/x11vnc 1651 diff -Naur JavaViewer.orig/Makefile JavaViewer/Makefile 1652 --- JavaViewer.orig/Makefile 2006-05-29 09:06:32.000000000 -0400 1653 +++ JavaViewer/Makefile 2010-05-18 20:53:32.000000000 -0400 1654 @@ -4,6 +4,7 @@ 1655 1656 CP = cp 1657 JC = javac 1658 +JC_ARGS = -target 1.4 -source 1.4 1659 JAR = jar 1660 ARCHIVE = VncViewer.jar 1661 PAGES = index.vnc shared.vnc noshared.vnc hextile.vnc zlib.vnc tight.vnc 1662 @@ -20,7 +21,7 @@ 1663 all: $(CLASSES) $(ARCHIVE) 1664 1665 $(CLASSES): $(SOURCES) 1666 - $(JC) -O $(SOURCES) 1667 + $(JC) $(JC_ARGS) -O $(SOURCES) 1668 1669 $(ARCHIVE): $(CLASSES) 1670 $(JAR) cf $(ARCHIVE) $(CLASSES) 1671 diff -Naur JavaViewer.orig/OptionsFrame.java JavaViewer/OptionsFrame.java 1672 --- JavaViewer.orig/OptionsFrame.java 2005-11-21 18:50:16.000000000 -0500 1673 +++ JavaViewer/OptionsFrame.java 2007-05-13 22:18:30.000000000 -0400 1674 @@ -144,7 +144,10 @@ 1675 choices[jpegQualityIndex].select("6"); 1676 choices[cursorUpdatesIndex].select("Enable"); 1677 choices[useCopyRectIndex].select("Yes"); 1678 - choices[eightBitColorsIndex].select("64"); 1679 +// begin runge/x11vnc 1680 +// choices[eightBitColorsIndex].select("64"); 1681 + choices[eightBitColorsIndex].select("Full"); 1682 +// end runge/x11vnc 1683 choices[mouseButtonIndex].select("Normal"); 1684 choices[viewOnlyIndex].select("No"); 1685 choices[shareDesktopIndex].select("Yes"); 1686 diff -Naur JavaViewer.orig/RfbProto.java JavaViewer/RfbProto.java 1687 --- JavaViewer.orig/RfbProto.java 2006-05-24 15:14:40.000000000 -0400 1688 +++ JavaViewer/RfbProto.java 2010-11-30 22:13:58.000000000 -0500 1689 @@ -31,6 +31,7 @@ 1690 import java.net.Socket; 1691 import java.util.*; 1692 import java.util.zip.*; 1693 +import java.text.DateFormat; 1694 1695 1696 class RfbProto { 1697 @@ -86,8 +87,11 @@ 1698 1699 // sf@2004 - FileTransfer part 1700 ArrayList remoteDirsList; 1701 + ArrayList remoteDirsListInfo; 1702 ArrayList remoteFilesList; 1703 + ArrayList remoteFilesListInfo; 1704 ArrayList a; 1705 + ArrayList b; 1706 boolean fFTInit = true; // sf@2004 1707 boolean fFTAllowed = true; 1708 boolean fAbort = false; 1709 @@ -199,6 +203,10 @@ 1710 // playback. 1711 int numUpdatesInSession; 1712 1713 +// begin runge/x11vnc 1714 + int readServerDriveListCnt = -1; 1715 + long readServerDriveListTime = 0; 1716 +// end runge/x11vnc 1717 // 1718 // Constructor. Make TCP connection to RFB server. 1719 // 1720 @@ -207,7 +215,27 @@ 1721 viewer = v; 1722 host = h; 1723 port = p; 1724 - sock = new Socket(host, port); 1725 +// begin runge/x11vnc 1726 +// sock = new Socket(host, port); 1727 + if (! viewer.disableSSL) { 1728 + System.out.println("new SSLSocketToMe"); 1729 + SSLSocketToMe ssl; 1730 + try { 1731 + ssl = new SSLSocketToMe(host, port, v); 1732 + } catch (Exception e) { 1733 + throw new IOException(e.getMessage()); 1734 + } 1735 + 1736 + try { 1737 + sock = ssl.connectSock(); 1738 + } catch (Exception es) { 1739 + throw new IOException(es.getMessage()); 1740 + } 1741 + } else { 1742 + sock = new Socket(host, port); 1743 + } 1744 +// end runge/x11vnc 1745 + 1746 is = 1747 new DataInputStream( 1748 new BufferedInputStream(sock.getInputStream(), 16384)); 1749 @@ -215,9 +243,12 @@ 1750 osw = new OutputStreamWriter(sock.getOutputStream()); 1751 inDirectory2 = false; 1752 a = new ArrayList(); 1753 + b = new ArrayList(); 1754 // sf@2004 1755 remoteDirsList = new ArrayList(); 1756 + remoteDirsListInfo = new ArrayList(); 1757 remoteFilesList = new ArrayList(); 1758 + remoteFilesListInfo = new ArrayList(); 1759 1760 sendFileSource = ""; 1761 } 1762 @@ -420,7 +451,13 @@ 1763 // 1764 1765 int readServerMessageType() throws IOException { 1766 - int msgType = is.readUnsignedByte(); 1767 + int msgType; 1768 + try { 1769 + msgType = is.readUnsignedByte(); 1770 + } catch (Exception e) { 1771 + viewer.disconnect(); 1772 + return -1; 1773 + } 1774 1775 // If the session is being recorded: 1776 if (rec != null) { 1777 @@ -600,6 +637,7 @@ 1778 contentParamT = is.readUnsignedByte(); 1779 contentParamT = contentParamT << 8; 1780 contentParam = contentParam | contentParamT; 1781 +//System.out.println("FTM: contentType " + contentType + " contentParam " + contentParam); 1782 if (contentType == rfbRDrivesList || contentType == rfbDirPacket) 1783 { 1784 readDriveOrDirectory(contentParam); 1785 @@ -610,7 +648,7 @@ 1786 } 1787 else if (contentType == rfbFilePacket) 1788 { 1789 - receiveFileChunk(); 1790 + receiveFileChunk(); 1791 } 1792 else if (contentType == rfbEndOfFile) 1793 { 1794 @@ -618,6 +656,10 @@ 1795 } 1796 else if (contentType == rfbAbortFileTransfer) 1797 { 1798 + System.out.println("rfbAbortFileTransfer: fFileReceptionRunning=" 1799 + + fFileReceptionRunning + " fAbort=" 1800 + + fAbort + " fFileReceptionError=" 1801 + + fFileReceptionError); 1802 if (fFileReceptionRunning) 1803 { 1804 endOfReceiveFile(false); // Error 1805 @@ -626,6 +668,11 @@ 1806 { 1807 // sf@2004 - Todo: Add TestPermission 1808 // System.out.println("File Transfer Aborted!"); 1809 + 1810 + // runge: seems like we must at least read the remaining 1811 + // 8 bytes of the header, right? 1812 + int size = is.readInt(); 1813 + int length = is.readInt(); 1814 } 1815 1816 } 1817 @@ -645,6 +692,7 @@ 1818 { 1819 System.out.println("ContentType: " + contentType); 1820 } 1821 +//System.out.println("FTM: done"); 1822 } 1823 1824 //Refactored from readRfbFileTransferMsg() 1825 @@ -662,6 +710,7 @@ 1826 1827 //Refactored from readRfbFileTransferMsg() 1828 public void readDriveOrDirectory(int contentParam) throws IOException { 1829 +//System.out.println("RDOD: " + contentParam + " " + inDirectory2); 1830 if (contentParam == rfbADrivesList) 1831 { 1832 readFTPMsgDriveList(); 1833 @@ -688,13 +737,21 @@ 1834 1835 // Internally used. Write an Rfb message to the server 1836 void writeRfbFileTransferMsg( 1837 - int contentType, 1838 - int contentParam, 1839 - long size, // 0 : compression not supported - 1 : compression supported 1840 - long length, 1841 - String text) throws IOException 1842 + int contentType, 1843 + int contentParam, 1844 + long size, // 0 : compression not supported - 1 : compression supported 1845 + long length, 1846 + String text) throws IOException 1847 { 1848 byte b[] = new byte[12]; 1849 + byte byteArray[]; 1850 + 1851 + if (viewer.dsmActive) { 1852 + // need to send the rfbFileTransfer msg type twice for the plugin... 1853 + byte b2[] = new byte[1]; 1854 + b2[0] = (byte) rfbFileTransfer; 1855 + os.write(b2); 1856 + } 1857 1858 b[0] = (byte) rfbFileTransfer; 1859 b[1] = (byte) contentType; 1860 @@ -702,7 +759,7 @@ 1861 1862 byte by = 0; 1863 long c = 0; 1864 - length++; 1865 + 1866 c = size & 0xFF000000; 1867 by = (byte) (c >>> 24); 1868 b[4] = by; 1869 @@ -716,6 +773,32 @@ 1870 by = (byte) c; 1871 b[7] = by; 1872 1873 + if (text != null) { 1874 + byte byteArray0[] = text.getBytes(); 1875 + int maxc = max_char(text); 1876 + if (maxc > 255) { 1877 + System.out.println("writeRfbFileTransferMsg: using getBytes(\"UTF-8\")"); 1878 + byteArray0 = text.getBytes("UTF-8"); 1879 + } else if (maxc > 127) { 1880 + System.out.println("writeRfbFileTransferMsg: using getBytes(\"ISO-8859-1\")"); 1881 + byteArray0 = text.getBytes("ISO-8859-1"); 1882 + } 1883 + byteArray = new byte[byteArray0.length + 1]; 1884 + for (int i = 0; i < byteArray0.length; i++) { 1885 + byteArray[i] = byteArray0[i]; 1886 + } 1887 + byteArray[byteArray.length - 1] = 0; 1888 +System.out.println("writeRfbFileTransferMsg: length: " + length + " -> byteArray.length: " + byteArray.length); 1889 + 1890 + // will equal length for ascii, ISO-8859-1, more for UTF-8 1891 + length = byteArray.length; 1892 + 1893 + //length++; // used to not include null byte at end. 1894 + } else { 1895 + String moo = "moo"; 1896 + byteArray = moo.getBytes(); 1897 + } 1898 + 1899 c = length & 0xFF000000; 1900 by = (byte) (c >>> 24); 1901 b[8] = by; 1902 @@ -729,29 +812,91 @@ 1903 by = (byte) c; 1904 b[11] = by; 1905 os.write(b); 1906 + 1907 +//System.out.println("size: " + size + " length: " + length + " text: " + text); 1908 1909 1910 if (text != null) 1911 { 1912 - byte byteArray[] = text.getBytes(); 1913 - byte byteArray2[] = new byte[byteArray.length + 1]; 1914 - for (int i = 0; i < byteArray.length; i++) { 1915 - byteArray2[i] = byteArray[i]; 1916 + os.write(byteArray); 1917 + } 1918 + } 1919 + 1920 + int max_char(String text) { 1921 + int maxc = 0; 1922 + char chars[] = text.toCharArray(); 1923 + for (int n = 0; n < chars.length; n++) { 1924 + if ((int) chars[n] > maxc) { 1925 + maxc = (int) chars[n]; 1926 } 1927 - byteArray2[byteArray2.length - 1] = 0; 1928 - os.write(byteArray2); 1929 } 1930 - 1931 + return maxc; 1932 } 1933 1934 + String guess_encoding(char[] chars) { 1935 + boolean saw_high_char = false; 1936 + 1937 + for (int i = 0; i < chars.length; i++) { 1938 + if (chars[i] == '\0') { 1939 + break; 1940 + } 1941 + if (chars[i] >= 128) { 1942 + saw_high_char = true; 1943 + break; 1944 + } 1945 + } 1946 + if (!saw_high_char) { 1947 + return "ASCII"; 1948 + } 1949 + char prev = 1; 1950 + boolean valid_utf8 = true; 1951 + int n = 0; 1952 + for (int i = 0; i < chars.length; i++) { 1953 + if (chars[i] == '\0') { 1954 + break; 1955 + } 1956 + char c = chars[i]; 1957 + if (prev < 128 && c >= 128) { 1958 + if (c >> 5 == 0x6) { 1959 + n = 1; 1960 + } else if (c >> 4 == 0xe) { 1961 + n = 2; 1962 + } else if (c >> 3 == 0x1e) { 1963 + n = 3; 1964 + } else if (c >> 2 == 0x3e) { 1965 + n = 4; 1966 + } else { 1967 + valid_utf8 = false; 1968 + break; 1969 + } 1970 + } else { 1971 + if (n > 0) { 1972 + if (c < 128) { 1973 + valid_utf8 = false; 1974 + break; 1975 + } 1976 + n--; 1977 + } 1978 + } 1979 + 1980 + prev = c; 1981 + } 1982 + if (valid_utf8) { 1983 + return "UTF-8"; 1984 + } else { 1985 + return "ISO-8859-1"; 1986 + } 1987 + } 1988 + 1989 + 1990 //Internally used. Write an rfb message to the server for sending files ONLY 1991 int writeRfbFileTransferMsgForSendFile( 1992 - int contentType, 1993 - int contentParam, 1994 - long size, 1995 - long length, 1996 - String source 1997 - ) throws IOException 1998 + int contentType, 1999 + int contentParam, 2000 + long size, 2001 + long length, 2002 + String source 2003 + ) throws IOException 2004 { 2005 File f = new File(source); 2006 fis = new FileInputStream(f); 2007 @@ -768,50 +913,47 @@ 2008 2009 while (bytesRead!=-1) 2010 { 2011 - counter += bytesRead; 2012 - myDeflater.setInput(byteBuffer, 0, bytesRead); 2013 - myDeflater.finish(); 2014 - compressedSize = myDeflater.deflate(CompressionBuffer); 2015 - myDeflater.reset(); 2016 - // If the compressed data is larger than the original one, we're dealing with 2017 - // already compressed data 2018 - if (compressedSize > bytesRead) 2019 - fCompress = false; 2020 - this.writeRfbFileTransferMsg( 2021 - contentType, 2022 - contentParam, 2023 - (fCompress ? 1 : 0), 2024 - (fCompress ? compressedSize-1 : bytesRead-1), 2025 - null 2026 - ); 2027 - // Todo: Test write error ! 2028 - os.write( 2029 - fCompress ? CompressionBuffer : byteBuffer, 2030 - 0, 2031 - fCompress ? compressedSize : bytesRead 2032 - ); 2033 - 2034 - // Todo: test read error ! 2035 - bytesRead = fis.read(byteBuffer); 2036 - 2037 - // viewer.ftp.connectionStatus.setText("Sent: "+ counter + " bytes of "+ f.length() + " bytes"); 2038 - viewer.ftp.jProgressBar.setValue((int)((counter * 100) / f.length())); 2039 - viewer.ftp.connectionStatus.setText(">>> Sending File: " + source + " - Size: " + f.length() + " bytes - Progress: " + ((counter * 100) / f.length()) + "%"); 2040 - 2041 - if (fAbort == true) 2042 - { 2043 - fAbort = false; 2044 - fError = true; 2045 - break; 2046 - } 2047 - try 2048 - { 2049 - Thread.sleep(5); 2050 - } 2051 - catch(InterruptedException e) 2052 - { 2053 - System.err.println("Interrupted"); 2054 - } 2055 + counter += bytesRead; 2056 + myDeflater.setInput(byteBuffer, 0, bytesRead); 2057 + myDeflater.finish(); 2058 + compressedSize = myDeflater.deflate(CompressionBuffer); 2059 + myDeflater.reset(); 2060 + // If the compressed data is larger than the original one, we're dealing with 2061 + // already compressed data 2062 + if (compressedSize > bytesRead) 2063 + fCompress = false; 2064 + this.writeRfbFileTransferMsg( 2065 + contentType, 2066 + contentParam, 2067 + (fCompress ? 1 : 0), 2068 +// RUNGE (fCompress ? compressedSize-1 : bytesRead-1), 2069 + (fCompress ? compressedSize : bytesRead), 2070 + null 2071 + ); 2072 + // Todo: Test write error ! 2073 + os.write(fCompress ? CompressionBuffer : byteBuffer, 0, fCompress ? compressedSize : bytesRead); 2074 + 2075 + // Todo: test read error ! 2076 + bytesRead = fis.read(byteBuffer); 2077 + 2078 + // viewer.ftp.connectionStatus.setText("Sent: "+ counter + " bytes of "+ f.length() + " bytes"); 2079 + viewer.ftp.jProgressBar.setValue((int)((counter * 100) / f.length())); 2080 + viewer.ftp.connectionStatus.setText(">>> Sending File: " + source + " - Size: " + f.length() + " bytes - Progress: " + ((counter * 100) / f.length()) + "%"); 2081 + 2082 + if (fAbort == true) 2083 + { 2084 + fAbort = false; 2085 + fError = true; 2086 + break; 2087 + } 2088 + try 2089 + { 2090 + Thread.sleep(5); 2091 + } 2092 + catch(InterruptedException e) 2093 + { 2094 + System.err.println("Interrupted"); 2095 + } 2096 } 2097 2098 writeRfbFileTransferMsg(fError ? rfbAbortFileTransfer : rfbEndOfFile, 0, 0, 0, null); 2099 @@ -831,24 +973,30 @@ 2100 { 2101 System.out.print((char) is.readUnsignedByte()); 2102 } 2103 + System.out.println(""); 2104 + 2105 + if (size == rfbRErrorCmd || size == -1) { 2106 + viewer.ftp.enableButtons(); 2107 + viewer.ftp.connectionStatus.setText("Remote file not available for writing."); 2108 + viewer.ftp.historyComboBox.insertItemAt(new String(" > Error - Remote file not available for writing."), 0); 2109 + viewer.ftp.historyComboBox.setSelectedIndex(0); 2110 + return; 2111 + } 2112 2113 - int ret = writeRfbFileTransferMsgForSendFile( 2114 - rfbFilePacket, 2115 - 0, 2116 - 0, 2117 - 0, 2118 - sendFileSource); 2119 + int ret = writeRfbFileTransferMsgForSendFile(rfbFilePacket, 0, 0, 0, sendFileSource); 2120 2121 viewer.ftp.refreshRemoteLocation(); 2122 if (ret != 1) 2123 { 2124 viewer.ftp.connectionStatus.setText(" > Error - File NOT sent"); 2125 - viewer.ftp.historyComboBox.insertItemAt(new String(" > Error - File: <" + sendFileSource) + "> was not correctly sent (aborted by user or error)",0); 2126 + viewer.ftp.historyComboBox.insertItemAt(new String(" > Error - File: <" + sendFileSource) 2127 + + "> was not correctly sent (aborted or error). Data may still be buffered/in transit. Wait for remote listing...",0); 2128 } 2129 else 2130 { 2131 viewer.ftp.connectionStatus.setText(" > File sent"); 2132 - viewer.ftp.historyComboBox.insertItemAt(new String(" > File: <" + sendFileSource) + "> was sent to Remote Machine",0); 2133 + viewer.ftp.historyComboBox.insertItemAt(new String(" > File: <" + sendFileSource) 2134 + + "> was sent to Remote Machine. Note: data may still be buffered/in transit. Wait for remote listing...",0); 2135 } 2136 viewer.ftp.historyComboBox.setSelectedIndex(0); 2137 viewer.ftp.enableButtons(); 2138 @@ -907,7 +1055,7 @@ 2139 //Handles acknowledgement that the file has been deleted on the server 2140 void deleteRemoteFileFeedback() throws IOException 2141 { 2142 - is.readInt(); 2143 + int ret = is.readInt(); 2144 int length = is.readInt(); 2145 String f = ""; 2146 for (int i = 0; i < length; i++) 2147 @@ -916,7 +1064,11 @@ 2148 } 2149 2150 viewer.ftp.refreshRemoteLocation(); 2151 - viewer.ftp.historyComboBox.insertItemAt(new String(" > Deleted File On Remote Machine: " + f.substring(0, f.length()-1)),0); 2152 + if (ret == -1) { 2153 + viewer.ftp.historyComboBox.insertItemAt(new String(" > ERROR Could not Delete File On Remote Machine: "),0); 2154 + } else { 2155 + viewer.ftp.historyComboBox.insertItemAt(new String(" > Deleted File On Remote Machine: " + f.substring(0, f.length()-1)),0); 2156 + } 2157 viewer.ftp.historyComboBox.setSelectedIndex(0); 2158 } 2159 2160 @@ -926,12 +1078,7 @@ 2161 try 2162 { 2163 String temp = text; 2164 - writeRfbFileTransferMsg( 2165 - rfbCommand, 2166 - rfbCFileDelete, 2167 - 0, 2168 - temp.length(), 2169 - temp); 2170 + writeRfbFileTransferMsg(rfbCommand, rfbCFileDelete, 0, temp.length(), temp); 2171 } 2172 catch (IOException e) 2173 { 2174 @@ -943,7 +1090,7 @@ 2175 // Handles acknowledgement that the directory has been created on the server 2176 void createRemoteDirectoryFeedback() throws IOException 2177 { 2178 - is.readInt(); 2179 + int ret = is.readInt(); 2180 int length = is.readInt(); 2181 String f=""; 2182 for (int i = 0; i < length; i++) 2183 @@ -951,7 +1098,11 @@ 2184 f += (char)is.readUnsignedByte(); 2185 } 2186 viewer.ftp.refreshRemoteLocation(); 2187 - viewer.ftp.historyComboBox.insertItemAt(new String(" > Created Directory on Remote Machine: " + f.substring(0, f.length()-1)),0); 2188 + if (ret == -1) { 2189 + viewer.ftp.historyComboBox.insertItemAt(new String(" > ERROR Could not Create Directory on Remote Machine."),0); 2190 + } else { 2191 + viewer.ftp.historyComboBox.insertItemAt(new String(" > Created Directory on Remote Machine: " + f.substring(0, f.length()-1)),0); 2192 + } 2193 viewer.ftp.historyComboBox.setSelectedIndex(0); 2194 } 2195 2196 @@ -961,12 +1112,7 @@ 2197 try 2198 { 2199 String temp = text; 2200 - writeRfbFileTransferMsg( 2201 - rfbCommand, 2202 - rfbCDirCreate, 2203 - 0, 2204 - temp.length(), 2205 - temp); 2206 + writeRfbFileTransferMsg(rfbCommand, rfbCDirCreate, 0, temp.length(), temp); 2207 } 2208 catch (IOException e) 2209 { 2210 @@ -979,15 +1125,13 @@ 2211 { 2212 try 2213 { 2214 +//System.out.println("requestRemoteFile text: " + text); 2215 +//System.out.println("requestRemoteFile leng: " + text.length()); 2216 String temp = text; 2217 receivePath = localPath; 2218 2219 - writeRfbFileTransferMsg( 2220 - rfbFileTransferRequest, 2221 - 0, 2222 - 1, // 0 : compression not supported - 1 : compression supported 2223 - temp.length(), 2224 - temp); 2225 + // 0 : compression not supported - 1 : compression supported 2226 + writeRfbFileTransferMsg(rfbFileTransferRequest, 0, 1, temp.length(), temp); 2227 } 2228 catch (IOException e) 2229 { 2230 @@ -1004,6 +1148,9 @@ 2231 viewer.ftp.disableButtons(); 2232 int size = is.readInt(); 2233 int length = is.readInt(); 2234 + 2235 +//System.out.println("receiveFileHeader size: " + size); 2236 +//System.out.println("receiveFileHeader leng: " + length); 2237 2238 String tempName = ""; 2239 for (int i = 0; i < length; i++) 2240 @@ -1011,6 +1158,15 @@ 2241 tempName += (char) is.readUnsignedByte(); 2242 } 2243 2244 + if (size == rfbRErrorCmd || size == -1) { 2245 + fFileReceptionRunning = false; 2246 + viewer.ftp.enableButtons(); 2247 + viewer.ftp.connectionStatus.setText("Remote file not available for reading."); 2248 + viewer.ftp.historyComboBox.insertItemAt(new String(" > Error - Remote file not available for reading."), 0); 2249 + viewer.ftp.historyComboBox.setSelectedIndex(0); 2250 + return; 2251 + } 2252 + 2253 // sf@2004 - Read the high part of file size (not yet in rfbFileTransferMsg for 2254 // backward compatibility reasons...) 2255 int sizeH = is.readInt(); 2256 @@ -1021,7 +1177,16 @@ 2257 fileSize=0; 2258 fileChunkCounter = 0; 2259 String fileName = receivePath; 2260 - fos = new FileOutputStream(fileName); 2261 + try { 2262 + fos = new FileOutputStream(fileName); 2263 + } catch (Exception e) { 2264 + fFileReceptionRunning = false; 2265 + writeRfbFileTransferMsg(rfbAbortFileTransfer, 0, 0, 0, null); 2266 + viewer.ftp.historyComboBox.insertItemAt(new String(" > ERROR opening Local File: <" + fileName ),0); 2267 + viewer.ftp.historyComboBox.setSelectedIndex(0); 2268 + viewer.ftp.enableButtons(); 2269 + return; 2270 + } 2271 writeRfbFileTransferMsg(rfbFileHeader, 0, 0, 0, null); 2272 } 2273 2274 @@ -1085,7 +1250,13 @@ 2275 fAbort = false; 2276 fFileReceptionError = true; 2277 writeRfbFileTransferMsg(rfbAbortFileTransfer, 0, 0, 0, null); 2278 - 2279 + 2280 + //runge for use with x11vnc/libvncserver, no rfbAbortFileTransfer reply sent. 2281 + try {Thread.sleep(500);} catch (InterruptedException e) {} 2282 + viewer.ftp.enableButtons(); 2283 + viewer.ftp.refreshLocalLocation(); 2284 + viewer.ftp.connectionStatus.setText(" > Error - File NOT received"); 2285 + viewer.ftp.historyComboBox.insertItemAt(new String(" > Error - File: <" + receivePath + "> not correctly received from Remote Machine (aborted by user or error)") ,0); 2286 } 2287 // sf@2004 - For old FT protocole only 2288 /* 2289 @@ -1104,7 +1275,7 @@ 2290 int length = is.readInt(); 2291 fileSize=0; 2292 fos.close(); 2293 - 2294 + 2295 viewer.ftp.refreshLocalLocation(); 2296 if (fReceptionOk && !fFileReceptionError) 2297 { 2298 @@ -1132,12 +1303,7 @@ 2299 try 2300 { 2301 String temp = text; 2302 - writeRfbFileTransferMsg( 2303 - rfbDirContentRequest, 2304 - rfbRDirContent, 2305 - 0, 2306 - temp.length(), 2307 - temp); 2308 + writeRfbFileTransferMsg(rfbDirContentRequest, rfbRDirContent, 0, temp.length(), temp); 2309 } 2310 catch (IOException e) 2311 { 2312 @@ -1197,11 +1363,80 @@ 2313 str += temp; 2314 } 2315 } 2316 + // runge 2317 + viewer.ftp.receivedRemoteDirectoryName(str); 2318 // viewer.ftp.changeRemoteDirectory(str); 2319 2320 } 2321 } 2322 2323 + int zogswap(int n) { 2324 + long l = n; 2325 + if (l < 0) { 2326 + l += 0x100000000L; 2327 + } 2328 + l = l & 0xFFFFFFFF; 2329 + l = (l >> 24) | ((l & 0x00ff0000) >> 8) | ((l & 0x0000ff00) << 8) | (l << 24); 2330 + return (int) l; 2331 + } 2332 + 2333 + int windozeToUnix(int L, int H) { 2334 + long L2 = zogswap(L); 2335 + long H2 = zogswap(H); 2336 + long unix = (H2 << 32) + L2; 2337 + unix -= 11644473600L * 10000000L; 2338 + unix /= 10000000L; 2339 + //System.out.println("unix time: " + unix + " H2: " + H2 + " L2: " + L2); 2340 + return (int) unix; 2341 + } 2342 + 2343 + String timeStr(int t, int h) { 2344 + if (h == 0) { 2345 + // x11vnc/libvncserver unix 2346 + t = zogswap(t); 2347 + } else { 2348 + // ultra (except if h==0 by chance) 2349 + t = windozeToUnix(t, h); 2350 + } 2351 + long tl = (long) t; 2352 + Date date = new Date(tl * 1000); 2353 + if (true) { 2354 + return date.toString(); 2355 + } else { 2356 + return DateFormat.getDateTimeInstance().format(date); 2357 + } 2358 + } 2359 + 2360 + String dotPast(double f, int n) { 2361 + String fs = "" + f; 2362 + int i = fs.lastIndexOf(".") + n; 2363 + if (i >= 0) { 2364 + int len = fs.length(); 2365 + if (i >= len) { 2366 + i = len-1; 2367 + } 2368 + fs = fs.substring(0, i); 2369 + } 2370 + return fs; 2371 + } 2372 + String sizeStr(int s) { 2373 + s = zogswap(s); 2374 + if (s < 0) { 2375 + return s + "? B"; 2376 + } else if (s < 1024) { 2377 + return s + " B"; 2378 + } else if (s < 1024 * 1024) { 2379 + double k = s / 1024.0; 2380 + String ks = dotPast(k, 3); 2381 + 2382 + return s + " (" + ks + " KB)"; 2383 + } else { 2384 + double m = s / (1024.0*1024.0); 2385 + String ms = dotPast(m, 3); 2386 + return s + " (" + ms + " MB)"; 2387 + } 2388 + } 2389 + 2390 //Internally used to receive directory content from server 2391 //Here, the server sends one file/directory with it's attributes 2392 void readFTPMsgDirectoryListContent() throws IOException 2393 @@ -1217,17 +1452,32 @@ 2394 dwReserved0, 2395 dwReserved1; 2396 long ftCreationTime, ftLastAccessTime, ftLastWriteTime; 2397 + int ftCreationTimeL, ftLastAccessTimeL, ftLastWriteTimeL; 2398 + int ftCreationTimeH, ftLastAccessTimeH, ftLastWriteTimeH; 2399 char cFileName, cAlternateFileName; 2400 int length = 0; 2401 is.readInt(); 2402 length = is.readInt(); 2403 + 2404 + char[] chars = new char[4*length]; 2405 + int char_cnt = 0; 2406 + for (int i = 0; i < chars.length; i++) { 2407 + chars[i] = '\0'; 2408 + } 2409 + 2410 dwFileAttributes = is.readInt(); 2411 length -= 4; 2412 - ftCreationTime = is.readLong(); 2413 + //ftCreationTime = is.readLong(); 2414 + ftCreationTimeL = is.readInt(); 2415 + ftCreationTimeH = is.readInt(); 2416 length -= 8; 2417 - ftLastAccessTime = is.readLong(); 2418 + //ftLastAccessTime = is.readLong(); 2419 + ftLastAccessTimeL = is.readInt(); 2420 + ftLastAccessTimeH = is.readInt(); 2421 length -= 8; 2422 - ftLastWriteTime = is.readLong(); 2423 + //ftLastWriteTime = is.readLong(); 2424 + ftLastWriteTimeL = is.readInt(); 2425 + ftLastWriteTimeH = is.readInt(); 2426 length -= 8; 2427 nFileSizeHigh = is.readInt(); 2428 length -= 4; 2429 @@ -1239,10 +1489,12 @@ 2430 length -= 4; 2431 cFileName = (char) is.readUnsignedByte(); 2432 length--; 2433 + chars[char_cnt++] = cFileName; 2434 while (cFileName != '\0') 2435 { 2436 fileName += cFileName; 2437 cFileName = (char) is.readUnsignedByte(); 2438 + chars[char_cnt++] = cFileName; 2439 length--; 2440 } 2441 cAlternateFileName = (char) is.readByte(); 2442 @@ -1253,7 +1505,28 @@ 2443 cAlternateFileName = (char) is.readUnsignedByte(); 2444 length--; 2445 } 2446 - if (dwFileAttributes == 268435456 2447 + String guessed = guess_encoding(chars); 2448 + if (!guessed.equals("ASCII")) { 2449 + System.out.println("guess: " + guessed + "\t" + fileName); 2450 + } 2451 + if (guessed.equals("UTF-8")) { 2452 + try { 2453 + byte[] bytes = new byte[char_cnt-1]; 2454 + for (int i=0; i < char_cnt-1; i++) { 2455 + bytes[i] = (byte) chars[i]; 2456 + } 2457 + String newstr = new String(bytes, "UTF-8"); 2458 + fileName = newstr; 2459 + } catch (Exception e) { 2460 + System.out.println("failed to convert bytes to UTF-8 based string"); 2461 + } 2462 + } 2463 + for (int i = 0; i < char_cnt; i++) { 2464 + //System.out.println("char[" + i + "]\t" + (int) chars[i]); 2465 + } 2466 + if (fileName.length() <= 0) { 2467 + ; 2468 + } else if (dwFileAttributes == 268435456 2469 || dwFileAttributes == 369098752 2470 || dwFileAttributes == 285212672 2471 || dwFileAttributes == 271056896 2472 @@ -1263,11 +1536,74 @@ 2473 || dwFileAttributes == 369623040) 2474 { 2475 fileName = " [" + fileName + "]"; 2476 - remoteDirsList.add(fileName); // sf@2004 2477 - } 2478 - else 2479 - { 2480 - remoteFilesList.add(" " + fileName); // sf@2004 2481 +// begin runge/x11vnc 2482 +// remoteDirsList.add(fileName); // sf@2004 2483 + int i = -1; 2484 + String t1 = fileName.toLowerCase(); 2485 + for (int j = 0; j < remoteDirsList.size(); j++) { 2486 + String t = (String) remoteDirsList.get(j); 2487 + String t2 = t.toLowerCase(); 2488 + if (t1.compareTo(t2) < 0) { 2489 + i = j; 2490 + break; 2491 + } 2492 + } 2493 + //String s = "Lastmod: " + timeStr(ftLastWriteTimeL, ftLastWriteTimeH) + " " + fileName; 2494 + String f2 = fileName; 2495 + if (f2.length() < 24) { 2496 + for (int ik = f2.length(); ik < 24; ik++) { 2497 + f2 = f2 + " "; 2498 + } 2499 + } 2500 + String s = f2 + " \tLastmod: " + timeStr(ftLastWriteTimeL, ftLastWriteTimeH) + " \t\tSize: " + sizeStr(nFileSizeLow); 2501 + //s = fileName + " Lastmod: " + zogswap(ftLastWriteTimeL); 2502 + if (i >= 0) { 2503 + remoteDirsList.add(i, fileName); 2504 + remoteDirsListInfo.add(i, s); 2505 + } else { 2506 + remoteDirsList.add(fileName); 2507 + remoteDirsListInfo.add(s); 2508 + } 2509 +// end runge/x11vnc 2510 + } else { 2511 +// begin runge/x11vnc 2512 +// remoteFilesList.add(" " + fileName); // sf@2004 2513 + 2514 + fileName = " " + fileName; 2515 + int i = -1; 2516 + String t1 = fileName.toLowerCase(); 2517 + for (int j = 0; j < remoteFilesList.size(); j++) { 2518 + String t = (String) remoteFilesList.get(j); 2519 + String t2 = t.toLowerCase(); 2520 + if (t1.compareTo(t2) < 0) { 2521 + i = j; 2522 + break; 2523 + } 2524 + } 2525 + String f2 = fileName; 2526 + if (f2.length() < 24) { 2527 + for (int ik = f2.length(); ik < 24; ik++) { 2528 + f2 = f2 + " "; 2529 + } 2530 + } 2531 + 2532 +if (false) { 2533 +System.out.println("fileName: " + f2); 2534 +System.out.println("ftLastWriteTimeL: " + ftLastWriteTimeL); 2535 +System.out.println("ftLastWriteTimeH: " + ftLastWriteTimeH); 2536 +System.out.println("nFileSizeLow: " + nFileSizeLow); 2537 +} 2538 + 2539 + String s = f2 + " \tLastmod: " + timeStr(ftLastWriteTimeL, ftLastWriteTimeH) + " \t\tSize: " + sizeStr(nFileSizeLow); 2540 + //s = fileName + " Lastmod: " + ftLastWriteTimeL + "/" + zogswap(ftLastWriteTimeL) + " Size: " + nFileSizeLow + "/" + zogswap(nFileSizeLow); 2541 + if (i >= 0) { 2542 + remoteFilesList.add(i, fileName); 2543 + remoteFilesListInfo.add(i, s); 2544 + } else { 2545 + remoteFilesList.add(fileName); 2546 + remoteFilesListInfo.add(s); 2547 + } 2548 +// end runge/x11vnc 2549 } 2550 2551 // a.add(fileName); 2552 @@ -1282,14 +1618,32 @@ 2553 2554 // sf@2004 2555 a.clear(); 2556 - for (int i = 0; i < remoteDirsList.size(); i++) 2557 + b.clear(); 2558 + for (int i = 0; i < remoteDirsList.size(); i++) { 2559 a.add(remoteDirsList.get(i)); 2560 - for (int i = 0; i < remoteFilesList.size(); i++) 2561 + b.add(remoteDirsListInfo.get(i)); 2562 + } 2563 + for (int i = 0; i < remoteFilesList.size(); i++) { 2564 a.add(remoteFilesList.get(i)); 2565 + 2566 + b.add(remoteFilesListInfo.get(i)); 2567 + } 2568 remoteDirsList.clear(); 2569 + remoteDirsListInfo.clear(); 2570 remoteFilesList.clear(); 2571 + remoteFilesListInfo.clear(); 2572 2573 - viewer.ftp.printDirectory(a); 2574 +// begin runge/x11vnc 2575 + // Hack for double listing at startup... probably libvncserver bug.. 2576 + readServerDriveListCnt++; 2577 + if (readServerDriveListCnt == 2) { 2578 + if (System.currentTimeMillis() - readServerDriveListTime < 2000) { 2579 +//System.out.println("readServerDriveListCnt skip " + readServerDriveListCnt); 2580 + return; 2581 + } 2582 + } 2583 +// end runge/x11vnc 2584 + viewer.ftp.printDirectory(a, b); 2585 } 2586 2587 //Internally used to signify the drive requested is not ready 2588 @@ -1299,6 +1653,8 @@ 2589 System.out.println("Remote Drive unavailable"); 2590 viewer.ftp.connectionStatus.setText(" > WARNING - Remote Drive unavailable (possibly restricted access or media not present)"); 2591 viewer.ftp.remoteStatus.setText("WARNING: Remote Drive unavailable"); 2592 + viewer.ftp.historyComboBox.insertItemAt(new String(" > WARNING: Remote Drive unavailable."), 0); 2593 + viewer.ftp.historyComboBox.setSelectedIndex(0); 2594 } 2595 2596 //Call this method to request the list of drives on the server. 2597 @@ -1306,12 +1662,11 @@ 2598 { 2599 try 2600 { 2601 - viewer.rfb.writeRfbFileTransferMsg( 2602 - RfbProto.rfbDirContentRequest, 2603 - RfbProto.rfbRDrivesList, 2604 - 0, 2605 - 0, 2606 - null); 2607 + viewer.rfb.writeRfbFileTransferMsg(RfbProto.rfbDirContentRequest, RfbProto.rfbRDrivesList, 0, 0, null); 2608 +// begin runge/x11vnc 2609 + readServerDriveListCnt = 0; 2610 + readServerDriveListTime = System.currentTimeMillis(); 2611 +// end runge/x11vnc 2612 } 2613 catch (IOException e) 2614 { 2615 @@ -1355,21 +1710,21 @@ 2616 int h, 2617 boolean incremental) 2618 throws IOException { 2619 - if (!viewer.ftp.isVisible()) { 2620 - byte[] b = new byte[10]; 2621 + if (!viewer.ftp.isVisible()) { 2622 + byte[] b = new byte[10]; 2623 2624 - b[0] = (byte) FramebufferUpdateRequest; 2625 - b[1] = (byte) (incremental ? 1 : 0); 2626 - b[2] = (byte) ((x >> 8) & 0xff); 2627 - b[3] = (byte) (x & 0xff); 2628 - b[4] = (byte) ((y >> 8) & 0xff); 2629 - b[5] = (byte) (y & 0xff); 2630 - b[6] = (byte) ((w >> 8) & 0xff); 2631 - b[7] = (byte) (w & 0xff); 2632 - b[8] = (byte) ((h >> 8) & 0xff); 2633 - b[9] = (byte) (h & 0xff); 2634 + b[0] = (byte) FramebufferUpdateRequest; 2635 + b[1] = (byte) (incremental ? 1 : 0); 2636 + b[2] = (byte) ((x >> 8) & 0xff); 2637 + b[3] = (byte) (x & 0xff); 2638 + b[4] = (byte) ((y >> 8) & 0xff); 2639 + b[5] = (byte) (y & 0xff); 2640 + b[6] = (byte) ((w >> 8) & 0xff); 2641 + b[7] = (byte) (w & 0xff); 2642 + b[8] = (byte) ((h >> 8) & 0xff); 2643 + b[9] = (byte) (h & 0xff); 2644 2645 - os.write(b); 2646 + os.write(b); 2647 } 2648 } 2649 2650 @@ -1482,7 +1837,13 @@ 2651 b[6] = (byte) ((text.length() >> 8) & 0xff); 2652 b[7] = (byte) (text.length() & 0xff); 2653 2654 - System.arraycopy(text.getBytes(), 0, b, 8, text.length()); 2655 + if (false && max_char(text) > 255) { 2656 + System.arraycopy(text.getBytes("UTF-8"), 0, b, 8, text.length()); 2657 + } else if (max_char(text) > 127) { 2658 + System.arraycopy(text.getBytes("ISO-8859-1"), 0, b, 8, text.length()); 2659 + } else { 2660 + System.arraycopy(text.getBytes(), 0, b, 8, text.length()); 2661 + } 2662 2663 os.write(b); 2664 // } 2665 @@ -1506,6 +1867,37 @@ 2666 final static int META_MASK = InputEvent.META_MASK; 2667 final static int ALT_MASK = InputEvent.ALT_MASK; 2668 2669 + void writeWheelEvent(MouseWheelEvent evt) throws IOException { 2670 + eventBufLen = 0; 2671 + 2672 + int x = evt.getX(); 2673 + int y = evt.getY(); 2674 + 2675 + if (x < 0) x = 0; 2676 + if (y < 0) y = 0; 2677 + 2678 + int ptrmask; 2679 + 2680 + int clicks = evt.getWheelRotation(); 2681 + System.out.println("writeWheelEvent: clicks: " + clicks); 2682 + if (clicks > 0) { 2683 + ptrmask = 16; 2684 + } else if (clicks < 0) { 2685 + ptrmask = 8; 2686 + } else { 2687 + return; 2688 + } 2689 + 2690 + eventBuf[eventBufLen++] = (byte) PointerEvent; 2691 + eventBuf[eventBufLen++] = (byte) ptrmask; 2692 + eventBuf[eventBufLen++] = (byte) ((x >> 8) & 0xff); 2693 + eventBuf[eventBufLen++] = (byte) (x & 0xff); 2694 + eventBuf[eventBufLen++] = (byte) ((y >> 8) & 0xff); 2695 + eventBuf[eventBufLen++] = (byte) (y & 0xff); 2696 + 2697 + os.write(eventBuf, 0, eventBufLen); 2698 + } 2699 + 2700 // 2701 // Write a pointer event message. We may need to send modifier key events 2702 // around it to set the correct modifier state. 2703 @@ -1610,6 +2002,21 @@ 2704 2705 boolean down = (evt.getID() == KeyEvent.KEY_PRESSED); 2706 2707 + if (viewer.debugKeyboard) { 2708 + System.out.println("----------------------------------------"); 2709 + System.out.println("evt.getKeyChar: " + evt.getKeyChar()); 2710 + System.out.println("getKeyText: " + KeyEvent.getKeyText(evt.getKeyCode())); 2711 + System.out.println("evt.getKeyCode: " + evt.getKeyCode()); 2712 + System.out.println("evt.getID: " + evt.getID()); 2713 + System.out.println("evt.getKeyLocation: " + evt.getKeyLocation()); 2714 + System.out.println("evt.isActionKey: " + evt.isActionKey()); 2715 + System.out.println("evt.isControlDown: " + evt.isControlDown()); 2716 + System.out.println("evt.getModifiers: " + evt.getModifiers()); 2717 + System.out.println("getKeyModifiersText: " + KeyEvent.getKeyModifiersText(evt.getModifiers())); 2718 + System.out.println("evt.paramString: " + evt.paramString()); 2719 + } 2720 + 2721 + 2722 int key; 2723 if (evt.isActionKey()) { 2724 2725 @@ -1685,6 +2092,9 @@ 2726 default : 2727 return; 2728 } 2729 + if (key == 0xffc2 && viewer.mapF5_to_atsign) { 2730 + key = 0x40; 2731 + } 2732 2733 } else { 2734 2735 @@ -1794,6 +2204,16 @@ 2736 int oldModifiers = 0; 2737 2738 void writeModifierKeyEvents(int newModifiers) { 2739 + if(viewer.forbid_Ctrl_Alt) { 2740 + if ((newModifiers & CTRL_MASK) != 0 && (newModifiers & ALT_MASK) != 0) { 2741 + int orig = newModifiers; 2742 + newModifiers &= ~ALT_MASK; 2743 + newModifiers &= ~CTRL_MASK; 2744 + if (viewer.debugKeyboard) { 2745 + System.out.println("Ctrl+Alt modifiers: " + orig + " -> " + newModifiers); 2746 + } 2747 + } 2748 + } 2749 if ((newModifiers & CTRL_MASK) != (oldModifiers & CTRL_MASK)) 2750 writeKeyEvent(0xffe3, (newModifiers & CTRL_MASK) != 0); 2751 2752 diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java 2753 --- JavaViewer.orig/SSLSocketToMe.java 1969-12-31 19:00:00.000000000 -0500 2754 +++ JavaViewer/SSLSocketToMe.java 2010-07-10 19:18:06.000000000 -0400 2755 @@ -0,0 +1,2067 @@ 2756 +/* 2757 + * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer. 2758 + * 2759 + * Copyright (c) 2006 Karl J. Runge <runge (a] karlrunge.com> 2760 + * All rights reserved. 2761 + * 2762 + * This is free software; you can redistribute it and/or modify 2763 + * it under the terms of the GNU General Public License as published by 2764 + * the Free Software Foundation; version 2 of the License, or 2765 + * (at your option) any later version. 2766 + * 2767 + * This software is distributed in the hope that it will be useful, 2768 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 2769 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 2770 + * GNU General Public License for more details. 2771 + * 2772 + * You should have received a copy of the GNU General Public License 2773 + * along with this software; if not, write to the Free Software 2774 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 2775 + * USA. 2776 + * 2777 + */ 2778 + 2779 +import java.net.*; 2780 +import java.io.*; 2781 +import javax.net.ssl.*; 2782 +import java.util.*; 2783 + 2784 +import java.security.*; 2785 +import java.security.cert.*; 2786 +import java.security.spec.*; 2787 +import java.security.cert.Certificate; 2788 +import java.security.cert.CertificateFactory; 2789 + 2790 +import java.awt.*; 2791 +import java.awt.event.*; 2792 + 2793 +public class SSLSocketToMe { 2794 + 2795 + /* basic member data: */ 2796 + String host; 2797 + int port; 2798 + VncViewer viewer; 2799 + 2800 + boolean debug = true; 2801 + boolean debug_certs = false; 2802 + 2803 + /* sockets */ 2804 + SSLSocket socket = null; 2805 + SSLSocketFactory factory; 2806 + 2807 + /* fallback for Proxy connection */ 2808 + boolean proxy_in_use = false; 2809 + boolean proxy_failure = false; 2810 + public DataInputStream is = null; 2811 + public OutputStream os = null; 2812 + 2813 + /* strings from user WRT proxy: */ 2814 + String proxy_auth_string = null; 2815 + String proxy_dialog_host = null; 2816 + int proxy_dialog_port = 0; 2817 + 2818 + Socket proxySock; 2819 + DataInputStream proxy_is; 2820 + OutputStream proxy_os; 2821 + 2822 + /* trust contexts */ 2823 + SSLContext trustloc_ctx; 2824 + SSLContext trustall_ctx; 2825 + SSLContext trustsrv_ctx; 2826 + SSLContext trusturl_ctx; 2827 + SSLContext trustone_ctx; 2828 + 2829 + /* corresponding trust managers */ 2830 + TrustManager[] trustAllCerts; 2831 + TrustManager[] trustSrvCert; 2832 + TrustManager[] trustUrlCert; 2833 + TrustManager[] trustOneCert; 2834 + 2835 + /* client-side SSL auth key (oneTimeKey=...) */ 2836 + KeyManager[] mykey = null; 2837 + 2838 + boolean user_wants_to_see_cert = true; 2839 + String cert_fail = null; 2840 + 2841 + /* cert(s) we retrieve from Web server, VNC server, or serverCert param: */ 2842 + java.security.cert.Certificate[] trustallCerts = null; 2843 + java.security.cert.Certificate[] trustsrvCerts = null; 2844 + java.security.cert.Certificate[] trusturlCerts = null; 2845 + 2846 + /* utility to decode hex oneTimeKey=... and serverCert=... */ 2847 + byte[] hex2bytes(String s) { 2848 + byte[] bytes = new byte[s.length()/2]; 2849 + for (int i=0; i<s.length()/2; i++) { 2850 + int j = 2*i; 2851 + try { 2852 + int val = Integer.parseInt(s.substring(j, j+2), 16); 2853 + if (val > 127) { 2854 + val -= 256; 2855 + } 2856 + Integer I = new Integer(val); 2857 + bytes[i] = Byte.decode(I.toString()).byteValue(); 2858 + 2859 + } catch (Exception e) { 2860 + ; 2861 + } 2862 + } 2863 + return bytes; 2864 + } 2865 + 2866 + SSLSocketToMe(String h, int p, VncViewer v) throws Exception { 2867 + host = h; 2868 + port = p; 2869 + viewer = v; 2870 + 2871 + debug_certs = v.debugCerts; 2872 + 2873 + /* we will first try default factory for certification: */ 2874 + 2875 + factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); 2876 + 2877 + dbg("SSL startup: " + host + " " + port); 2878 + 2879 + 2880 + /* create trust managers to be used if initial handshake fails: */ 2881 + 2882 + trustAllCerts = new TrustManager[] { 2883 + /* 2884 + * this one accepts everything. Only used if user 2885 + * has disabled checking (trustAllVncCerts=yes) 2886 + * or when we grab the cert to show it to them in 2887 + * a dialog and ask them to manually verify/accept it. 2888 + */ 2889 + new X509TrustManager() { 2890 + public java.security.cert.X509Certificate[] 2891 + getAcceptedIssuers() { 2892 + return null; 2893 + } 2894 + public void checkClientTrusted( 2895 + java.security.cert.X509Certificate[] certs, 2896 + String authType) { 2897 + /* empty */ 2898 + } 2899 + public void checkServerTrusted( 2900 + java.security.cert.X509Certificate[] certs, 2901 + String authType) { 2902 + /* empty */ 2903 + dbg("ALL: an untrusted connect to grab cert."); 2904 + } 2905 + } 2906 + }; 2907 + 2908 + trustUrlCert = new TrustManager[] { 2909 + /* 2910 + * this one accepts only the retrieved server 2911 + * cert by SSLSocket by this applet and stored in 2912 + * trusturlCerts. 2913 + */ 2914 + new X509TrustManager() { 2915 + public java.security.cert.X509Certificate[] 2916 + getAcceptedIssuers() { 2917 + return null; 2918 + } 2919 + public void checkClientTrusted( 2920 + java.security.cert.X509Certificate[] certs, 2921 + String authType) throws CertificateException { 2922 + throw new CertificateException("No Clients (URL)"); 2923 + } 2924 + public void checkServerTrusted( 2925 + java.security.cert.X509Certificate[] certs, 2926 + String authType) throws CertificateException { 2927 + /* we want to check 'certs' against 'trusturlCerts' */ 2928 + if (trusturlCerts == null) { 2929 + throw new CertificateException( 2930 + "No Trust url Certs array."); 2931 + } 2932 + if (trusturlCerts.length < 1) { 2933 + throw new CertificateException( 2934 + "No Trust url Certs."); 2935 + } 2936 + if (certs == null) { 2937 + throw new CertificateException( 2938 + "No this-certs array."); 2939 + } 2940 + if (certs.length < 1) { 2941 + throw new CertificateException( 2942 + "No this-certs Certs."); 2943 + } 2944 + if (certs.length != trusturlCerts.length) { 2945 + throw new CertificateException( 2946 + "certs.length != trusturlCerts.length " + certs.length + " " + trusturlCerts.length); 2947 + } 2948 + boolean ok = true; 2949 + for (int i = 0; i < certs.length; i++) { 2950 + if (! trusturlCerts[i].equals(certs[i])) { 2951 + ok = false; 2952 + dbg("URL: cert mismatch at i=" + i); 2953 + dbg("URL: cert mismatch cert" + certs[i]); 2954 + dbg("URL: cert mismatch url" + trusturlCerts[i]); 2955 + if (cert_fail == null) { 2956 + cert_fail = "cert-mismatch"; 2957 + } 2958 + } 2959 + if (debug_certs) { 2960 + dbg("\n***********************************************"); 2961 + dbg("URL: cert info at i=" + i); 2962 + dbg("URL: cert info cert" + certs[i]); 2963 + dbg("==============================================="); 2964 + dbg("URL: cert info url" + trusturlCerts[i]); 2965 + dbg("***********************************************"); 2966 + } 2967 + } 2968 + if (!ok) { 2969 + throw new CertificateException( 2970 + "Server Cert Chain != URL Cert Chain."); 2971 + } 2972 + dbg("URL: trusturlCerts[i] matches certs[i] i=0:" + (certs.length-1)); 2973 + } 2974 + } 2975 + }; 2976 + 2977 + trustSrvCert = new TrustManager[] { 2978 + /* 2979 + * this one accepts cert given to us in the serverCert 2980 + * Applet Parameter we were started with. It is 2981 + * currently a fatal error if the VNC Server's cert 2982 + * doesn't match it. 2983 + */ 2984 + new X509TrustManager() { 2985 + public java.security.cert.X509Certificate[] 2986 + getAcceptedIssuers() { 2987 + return null; 2988 + } 2989 + public void checkClientTrusted( 2990 + java.security.cert.X509Certificate[] certs, 2991 + String authType) throws CertificateException { 2992 + throw new CertificateException("No Clients (SRV)"); 2993 + } 2994 + public void checkServerTrusted( 2995 + java.security.cert.X509Certificate[] certs, 2996 + String authType) throws CertificateException { 2997 + /* we want to check 'certs' against 'trustsrvCerts' */ 2998 + if (trustsrvCerts == null) { 2999 + throw new CertificateException( 3000 + "No Trust srv Certs array."); 3001 + } 3002 + if (trustsrvCerts.length < 1) { 3003 + throw new CertificateException( 3004 + "No Trust srv Certs."); 3005 + } 3006 + if (certs == null) { 3007 + throw new CertificateException( 3008 + "No this-certs array."); 3009 + } 3010 + if (certs.length < 1) { 3011 + throw new CertificateException( 3012 + "No this-certs Certs."); 3013 + } 3014 + if (certs.length != trustsrvCerts.length) { 3015 + throw new CertificateException( 3016 + "certs.length != trustsrvCerts.length " + certs.length + " " + trustsrvCerts.length); 3017 + } 3018 + boolean ok = true; 3019 + for (int i = 0; i < certs.length; i++) { 3020 + if (! trustsrvCerts[i].equals(certs[i])) { 3021 + ok = false; 3022 + dbg("SRV: cert mismatch at i=" + i); 3023 + dbg("SRV: cert mismatch cert" + certs[i]); 3024 + dbg("SRV: cert mismatch srv" + trustsrvCerts[i]); 3025 + if (cert_fail == null) { 3026 + cert_fail = "server-cert-mismatch"; 3027 + } 3028 + } 3029 + if (debug_certs) { 3030 + dbg("\n***********************************************"); 3031 + dbg("SRV: cert info at i=" + i); 3032 + dbg("SRV: cert info cert" + certs[i]); 3033 + dbg("==============================================="); 3034 + dbg("SRV: cert info srv" + trustsrvCerts[i]); 3035 + dbg("***********************************************"); 3036 + } 3037 + } 3038 + if (!ok) { 3039 + throw new CertificateException( 3040 + "Server Cert Chain != serverCert Applet Parameter Cert Chain."); 3041 + } 3042 + dbg("SRV: trustsrvCerts[i] matches certs[i] i=0:" + (certs.length-1)); 3043 + } 3044 + } 3045 + }; 3046 + 3047 + trustOneCert = new TrustManager[] { 3048 + /* 3049 + * this one accepts only the retrieved server 3050 + * cert by SSLSocket by this applet we stored in 3051 + * trustallCerts that user has accepted or applet 3052 + * parameter trustAllVncCerts=yes is set. This is 3053 + * for when we reconnect after the user has manually 3054 + * accepted the trustall cert in the dialog (or set 3055 + * trustAllVncCerts=yes applet param.) 3056 + */ 3057 + new X509TrustManager() { 3058 + public java.security.cert.X509Certificate[] 3059 + getAcceptedIssuers() { 3060 + return null; 3061 + } 3062 + public void checkClientTrusted( 3063 + java.security.cert.X509Certificate[] certs, 3064 + String authType) throws CertificateException { 3065 + throw new CertificateException("No Clients (ONE)"); 3066 + } 3067 + public void checkServerTrusted( 3068 + java.security.cert.X509Certificate[] certs, 3069 + String authType) throws CertificateException { 3070 + /* we want to check 'certs' against 'trustallCerts' */ 3071 + if (trustallCerts == null) { 3072 + throw new CertificateException( 3073 + "No Trust All Server Certs array."); 3074 + } 3075 + if (trustallCerts.length < 1) { 3076 + throw new CertificateException( 3077 + "No Trust All Server Certs."); 3078 + } 3079 + if (certs == null) { 3080 + throw new CertificateException( 3081 + "No this-certs array."); 3082 + } 3083 + if (certs.length < 1) { 3084 + throw new CertificateException( 3085 + "No this-certs Certs."); 3086 + } 3087 + if (certs.length != trustallCerts.length) { 3088 + throw new CertificateException( 3089 + "certs.length != trustallCerts.length " + certs.length + " " + trustallCerts.length); 3090 + } 3091 + boolean ok = true; 3092 + for (int i = 0; i < certs.length; i++) { 3093 + if (! trustallCerts[i].equals(certs[i])) { 3094 + ok = false; 3095 + dbg("ONE: cert mismatch at i=" + i); 3096 + dbg("ONE: cert mismatch cert" + certs[i]); 3097 + dbg("ONE: cert mismatch all" + trustallCerts[i]); 3098 + } 3099 + if (debug_certs) { 3100 + dbg("\n***********************************************"); 3101 + dbg("ONE: cert info at i=" + i); 3102 + dbg("ONE: cert info cert" + certs[i]); 3103 + dbg("==============================================="); 3104 + dbg("ONE: cert info all" + trustallCerts[i]); 3105 + dbg("***********************************************"); 3106 + } 3107 + } 3108 + if (!ok) { 3109 + throw new CertificateException( 3110 + "Server Cert Chain != TRUSTALL Cert Chain."); 3111 + } 3112 + dbg("ONE: trustallCerts[i] matches certs[i] i=0:" + (certs.length-1)); 3113 + } 3114 + } 3115 + }; 3116 + 3117 + /* 3118 + * The above TrustManagers are used: 3119 + * 3120 + * 1) to retrieve the server cert in case of failure to 3121 + * display it to the user in a dialog. 3122 + * 2) to subsequently connect to the server if user agrees. 3123 + */ 3124 + 3125 + /* 3126 + * build oneTimeKey cert+key if supplied in applet parameter: 3127 + */ 3128 + if (viewer.oneTimeKey != null && viewer.oneTimeKey.equals("PROMPT")) { 3129 + ClientCertDialog d = new ClientCertDialog(); 3130 + viewer.oneTimeKey = d.queryUser(); 3131 + } 3132 + if (viewer.oneTimeKey != null && viewer.oneTimeKey.indexOf(",") > 0) { 3133 + int idx = viewer.oneTimeKey.indexOf(","); 3134 + 3135 + String onetimekey = viewer.oneTimeKey.substring(0, idx); 3136 + byte[] key = hex2bytes(onetimekey); 3137 + String onetimecert = viewer.oneTimeKey.substring(idx+1); 3138 + byte[] cert = hex2bytes(onetimecert); 3139 + 3140 + KeyFactory kf = KeyFactory.getInstance("RSA"); 3141 + PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec ( key ); 3142 + PrivateKey ff = kf.generatePrivate (keysp); 3143 + if (debug_certs) { 3144 + dbg("one time key " + ff); 3145 + } 3146 + 3147 + CertificateFactory cf = CertificateFactory.getInstance("X.509"); 3148 + Collection c = cf.generateCertificates(new ByteArrayInputStream(cert)); 3149 + Certificate[] certs = new Certificate[c.toArray().length]; 3150 + if (c.size() == 1) { 3151 + Certificate tmpcert = cf.generateCertificate(new ByteArrayInputStream(cert)); 3152 + if (debug_certs) { 3153 + dbg("one time cert" + tmpcert); 3154 + } 3155 + certs[0] = tmpcert; 3156 + } else { 3157 + certs = (Certificate[]) c.toArray(); 3158 + } 3159 + 3160 + KeyStore ks = KeyStore.getInstance("JKS"); 3161 + ks.load(null, null); 3162 + ks.setKeyEntry("onetimekey", ff, "".toCharArray(), certs); 3163 + String da = KeyManagerFactory.getDefaultAlgorithm(); 3164 + KeyManagerFactory kmf = KeyManagerFactory.getInstance(da); 3165 + kmf.init(ks, "".toCharArray()); 3166 + 3167 + mykey = kmf.getKeyManagers(); 3168 + } 3169 + 3170 + /* 3171 + * build serverCert cert if supplied in applet parameter: 3172 + */ 3173 + if (viewer.serverCert != null) { 3174 + CertificateFactory cf = CertificateFactory.getInstance("X.509"); 3175 + byte[] cert = hex2bytes(viewer.serverCert); 3176 + Collection c = cf.generateCertificates(new ByteArrayInputStream(cert)); 3177 + trustsrvCerts = new Certificate[c.toArray().length]; 3178 + if (c.size() == 1) { 3179 + Certificate tmpcert = cf.generateCertificate(new ByteArrayInputStream(cert)); 3180 + trustsrvCerts[0] = tmpcert; 3181 + } else { 3182 + trustsrvCerts = (Certificate[]) c.toArray(); 3183 + } 3184 + } 3185 + 3186 + /* the trust loc certs context: */ 3187 + try { 3188 + trustloc_ctx = SSLContext.getInstance("SSL"); 3189 + 3190 + /* 3191 + * below is a failed attempt to get jvm's default 3192 + * trust manager using null (below) makes it so 3193 + * for HttpsURLConnection the server cannot be 3194 + * verified (no prompting.) 3195 + */ 3196 + if (false) { 3197 + boolean didit = false; 3198 + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 3199 + tmf.init((KeyStore) null); 3200 + TrustManager [] tml = tmf.getTrustManagers(); 3201 + for (int i = 0; i < tml.length; i++) { 3202 + TrustManager tm = tml[i]; 3203 + if (tm instanceof X509TrustManager) { 3204 + TrustManager tm1[] = new TrustManager[1]; 3205 + tm1[0] = tm; 3206 + trustloc_ctx.init(mykey, tm1, null); 3207 + didit = true; 3208 + break; 3209 + } 3210 + } 3211 + if (!didit) { 3212 + trustloc_ctx.init(mykey, null, null); 3213 + } 3214 + } else { 3215 + /* we have to set trust manager to null */ 3216 + trustloc_ctx.init(mykey, null, null); 3217 + } 3218 + 3219 + } catch (Exception e) { 3220 + String msg = "SSL trustloc_ctx FAILED."; 3221 + dbg(msg); 3222 + throw new Exception(msg); 3223 + } 3224 + 3225 + /* the trust all certs context: */ 3226 + try { 3227 + trustall_ctx = SSLContext.getInstance("SSL"); 3228 + trustall_ctx.init(mykey, trustAllCerts, new 3229 + java.security.SecureRandom()); 3230 + 3231 + } catch (Exception e) { 3232 + String msg = "SSL trustall_ctx FAILED."; 3233 + dbg(msg); 3234 + throw new Exception(msg); 3235 + } 3236 + 3237 + /* the trust url certs context: */ 3238 + try { 3239 + trusturl_ctx = SSLContext.getInstance("SSL"); 3240 + trusturl_ctx.init(mykey, trustUrlCert, new 3241 + java.security.SecureRandom()); 3242 + 3243 + } catch (Exception e) { 3244 + String msg = "SSL trusturl_ctx FAILED."; 3245 + dbg(msg); 3246 + throw new Exception(msg); 3247 + } 3248 + 3249 + /* the trust srv certs context: */ 3250 + try { 3251 + trustsrv_ctx = SSLContext.getInstance("SSL"); 3252 + trustsrv_ctx.init(mykey, trustSrvCert, new 3253 + java.security.SecureRandom()); 3254 + 3255 + } catch (Exception e) { 3256 + String msg = "SSL trustsrv_ctx FAILED."; 3257 + dbg(msg); 3258 + throw new Exception(msg); 3259 + } 3260 + 3261 + /* the trust the one cert from server context: */ 3262 + try { 3263 + trustone_ctx = SSLContext.getInstance("SSL"); 3264 + trustone_ctx.init(mykey, trustOneCert, new 3265 + java.security.SecureRandom()); 3266 + 3267 + } catch (Exception e) { 3268 + String msg = "SSL trustone_ctx FAILED."; 3269 + dbg(msg); 3270 + throw new Exception(msg); 3271 + } 3272 + } 3273 + 3274 + /* 3275 + * we call this early on to 1) check for a proxy, 2) grab 3276 + * Browser/JVM accepted HTTPS cert. 3277 + */ 3278 + public void check_for_proxy_and_grab_vnc_server_cert() { 3279 + 3280 + trusturlCerts = null; 3281 + proxy_in_use = false; 3282 + 3283 + if (viewer.ignoreProxy) { 3284 + /* applet param says skip it. */ 3285 + /* the downside is we do not set trusturlCerts for comparison later... */ 3286 + /* nor do we autodetect x11vnc for GET=1. */ 3287 + return; 3288 + } 3289 + 3290 + dbg("------------------------------------------------"); 3291 + dbg("Into check_for_proxy_and_grab_vnc_server_cert():"); 3292 + 3293 + dbg("TRYING HTTPS:"); 3294 + String ustr = "https://" + host + ":"; 3295 + if (viewer.httpsPort != null) { 3296 + ustr += viewer.httpsPort; 3297 + } else { 3298 + ustr += port; 3299 + } 3300 + ustr += viewer.urlPrefix + "/check.https.proxy.connection"; 3301 + dbg("ustr is: " + ustr); 3302 + 3303 + try { 3304 + /* prepare for an HTTPS URL connection to host:port */ 3305 + URL url = new URL(ustr); 3306 + HttpsURLConnection https = (HttpsURLConnection) url.openConnection(); 3307 + 3308 + if (mykey != null) { 3309 + /* with oneTimeKey (mykey) we can't use the default SSL context */ 3310 + if (trustsrvCerts != null) { 3311 + dbg("passing trustsrv_ctx to HttpsURLConnection to provide client cert."); 3312 + https.setSSLSocketFactory(trustsrv_ctx.getSocketFactory()); 3313 + } else if (trustloc_ctx != null) { 3314 + dbg("passing trustloc_ctx to HttpsURLConnection to provide client cert."); 3315 + https.setSSLSocketFactory(trustloc_ctx.getSocketFactory()); 3316 + } 3317 + } 3318 + 3319 + https.setUseCaches(false); 3320 + https.setRequestMethod("GET"); 3321 + https.setRequestProperty("Pragma", "No-Cache"); 3322 + https.setRequestProperty("Proxy-Connection", "Keep-Alive"); 3323 + https.setDoInput(true); 3324 + 3325 + dbg("trying https.connect()"); 3326 + https.connect(); 3327 + 3328 + dbg("trying https.getServerCertificates()"); 3329 + trusturlCerts = https.getServerCertificates(); 3330 + 3331 + if (trusturlCerts == null) { 3332 + dbg("set trusturlCerts to null!"); 3333 + } else { 3334 + dbg("set trusturlCerts to non-null"); 3335 + } 3336 + 3337 + if (https.usingProxy()) { 3338 + proxy_in_use = true; 3339 + dbg("An HTTPS proxy is in use. There may be connection problems."); 3340 + } 3341 + 3342 + dbg("trying https.getContent()"); 3343 + Object output = https.getContent(); 3344 + dbg("trying https.disconnect()"); 3345 + https.disconnect(); 3346 + if (! viewer.GET) { 3347 + String header = https.getHeaderField("VNC-Server"); 3348 + if (header != null && header.startsWith("x11vnc")) { 3349 + dbg("detected x11vnc server (1), setting GET=1"); 3350 + viewer.GET = true; 3351 + } 3352 + } 3353 + 3354 + } catch(Exception e) { 3355 + dbg("HttpsURLConnection: " + e.getMessage()); 3356 + } 3357 + 3358 + if (proxy_in_use) { 3359 + dbg("exit check_for_proxy_and_grab_vnc_server_cert():"); 3360 + dbg("------------------------------------------------"); 3361 + return; 3362 + } else if (trusturlCerts != null && !viewer.forceProxy) { 3363 + /* Allow user to require HTTP check? use forceProxy for now. */ 3364 + dbg("SKIPPING HTTP PROXY CHECK: got trusturlCerts, assuming proxy info is correct."); 3365 + dbg("exit check_for_proxy_and_grab_vnc_server_cert():"); 3366 + dbg("------------------------------------------------"); 3367 + return; 3368 + } 3369 + 3370 + /* 3371 + * XXX need to remember scenario where this extra check 3372 + * gives useful info. User's Browser proxy settings? 3373 + */ 3374 + dbg("TRYING HTTP:"); 3375 + ustr = "http://" + host + ":" + port; 3376 + ustr += viewer.urlPrefix + "/index.vnc"; 3377 + dbg("ustr is: " + ustr); 3378 + 3379 + try { 3380 + /* prepare for an HTTP URL connection to the same host:port (but not httpsPort) */ 3381 + URL url = new URL(ustr); 3382 + HttpURLConnection http = (HttpURLConnection) 3383 + url.openConnection(); 3384 + 3385 + http.setUseCaches(false); 3386 + http.setRequestMethod("GET"); 3387 + http.setRequestProperty("Pragma", "No-Cache"); 3388 + http.setRequestProperty("Proxy-Connection", "Keep-Alive"); 3389 + http.setDoInput(true); 3390 + 3391 + dbg("trying http.connect()"); 3392 + http.connect(); 3393 + 3394 + if (http.usingProxy()) { 3395 + proxy_in_use = true; 3396 + dbg("An HTTP proxy is in use. There may be connection problems."); 3397 + } 3398 + dbg("trying http.getContent()"); 3399 + Object output = http.getContent(); 3400 + dbg("trying http.disconnect()"); 3401 + http.disconnect(); 3402 + if (! viewer.GET) { 3403 + String header = http.getHeaderField("VNC-Server"); 3404 + if (header != null && header.startsWith("x11vnc")) { 3405 + dbg("detected x11vnc server (2), setting GET=1"); 3406 + viewer.GET = true; 3407 + } 3408 + } 3409 + } catch(Exception e) { 3410 + dbg("HttpURLConnection: " + e.getMessage()); 3411 + } 3412 + dbg("exit check_for_proxy_and_grab_vnc_server_cert():"); 3413 + dbg("------------------------------------------------"); 3414 + } 3415 + 3416 + public Socket connectSock() throws IOException { 3417 + /* 3418 + * first try a https connection to detect a proxy, and 3419 + * grab the VNC server cert at the same time: 3420 + */ 3421 + check_for_proxy_and_grab_vnc_server_cert(); 3422 + 3423 + boolean srv_cert = false; 3424 + 3425 + if (trustsrvCerts != null) { 3426 + /* applet parameter suppled serverCert */ 3427 + dbg("viewer.trustSrvCert-0 using trustsrv_ctx"); 3428 + factory = trustsrv_ctx.getSocketFactory(); 3429 + srv_cert = true; 3430 + } else if (viewer.trustAllVncCerts) { 3431 + /* trust all certs (no checking) */ 3432 + dbg("viewer.trustAllVncCerts-0 using trustall_ctx"); 3433 + factory = trustall_ctx.getSocketFactory(); 3434 + } else if (trusturlCerts != null) { 3435 + /* trust certs the Browser/JVM accepted in check_for_proxy... */ 3436 + dbg("using trusturl_ctx"); 3437 + factory = trusturl_ctx.getSocketFactory(); 3438 + } else { 3439 + /* trust the local defaults */ 3440 + dbg("using trustloc_ctx"); 3441 + factory = trustloc_ctx.getSocketFactory(); 3442 + } 3443 + 3444 + socket = null; 3445 + 3446 + try { 3447 + if (proxy_in_use && viewer.forceProxy) { 3448 + throw new Exception("forcing proxy (forceProxy)"); 3449 + } else if (viewer.CONNECT != null) { 3450 + throw new Exception("forcing CONNECT"); 3451 + } 3452 + 3453 + int timeout = 6; 3454 + if (timeout > 0) { 3455 + socket = (SSLSocket) factory.createSocket(); 3456 + InetSocketAddress inetaddr = new InetSocketAddress(host, port); 3457 + dbg("Using timeout of " + timeout + " secs to: " + host + ":" + port); 3458 + socket.connect(inetaddr, timeout * 1000); 3459 + } else { 3460 + socket = (SSLSocket) factory.createSocket(host, port); 3461 + } 3462 + 3463 + } catch (Exception esock) { 3464 + dbg("socket error: " + esock.getMessage()); 3465 + if (proxy_in_use || viewer.CONNECT != null) { 3466 + proxy_failure = true; 3467 + if (proxy_in_use) { 3468 + dbg("HTTPS proxy in use. Trying to go with it."); 3469 + } else { 3470 + dbg("viewer.CONNECT reverse proxy in use. Trying to go with it."); 3471 + } 3472 + try { 3473 + socket = proxy_socket(factory); 3474 + } catch (Exception e) { 3475 + dbg("proxy_socket error: " + e.getMessage()); 3476 + } 3477 + } else { 3478 + /* n.b. socket is left in error state to cause ex. below. */ 3479 + } 3480 + } 3481 + 3482 + try { 3483 + socket.startHandshake(); 3484 + 3485 + dbg("The Server Connection Verified OK on 1st try."); 3486 + 3487 + java.security.cert.Certificate[] currentTrustedCerts; 3488 + BrowserCertsDialog bcd; 3489 + 3490 + SSLSession sess = socket.getSession(); 3491 + currentTrustedCerts = sess.getPeerCertificates(); 3492 + 3493 + if (viewer.trustAllVncCerts) { 3494 + dbg("viewer.trustAllVncCerts-1 keeping socket."); 3495 + } else if (currentTrustedCerts == null || currentTrustedCerts.length < 1) { 3496 + try { 3497 + socket.close(); 3498 + } catch (Exception e) { 3499 + dbg("socket is grumpy."); 3500 + } 3501 + socket = null; 3502 + throw new SSLHandshakeException("no current certs"); 3503 + } 3504 + 3505 + String serv = ""; 3506 + try { 3507 + CertInfo ci = new CertInfo(currentTrustedCerts[0]); 3508 + serv = ci.get_certinfo("CN"); 3509 + } catch (Exception e) { 3510 + ; 3511 + } 3512 + 3513 + if (viewer.trustAllVncCerts) { 3514 + dbg("viewer.trustAllVncCerts-2 skipping browser certs dialog"); 3515 + user_wants_to_see_cert = false; 3516 + } else if (viewer.serverCert != null && trustsrvCerts != null) { 3517 + dbg("viewer.serverCert-1 skipping browser certs dialog"); 3518 + user_wants_to_see_cert = false; 3519 + } else if (viewer.trustUrlVncCert) { 3520 + dbg("viewer.trustUrlVncCert-1 skipping browser certs dialog"); 3521 + user_wants_to_see_cert = false; 3522 + } else { 3523 + /* have a dialog with the user: */ 3524 + bcd = new BrowserCertsDialog(serv, host + ":" + port); 3525 + dbg("browser certs dialog begin."); 3526 + bcd.queryUser(); 3527 + dbg("browser certs dialog finished."); 3528 + 3529 + if (bcd.showCertDialog) { 3530 + String msg = "user wants to see cert"; 3531 + dbg(msg); 3532 + user_wants_to_see_cert = true; 3533 + if (cert_fail == null) { 3534 + cert_fail = "user-view"; 3535 + } 3536 + throw new SSLHandshakeException(msg); 3537 + } else { 3538 + user_wants_to_see_cert = false; 3539 + dbg("browser certs dialog: user said yes, accept it"); 3540 + } 3541 + } 3542 + 3543 + } catch (SSLHandshakeException eh) { 3544 + dbg("SSLHandshakeException: could not automatically verify Server."); 3545 + dbg("msg: " + eh.getMessage()); 3546 + 3547 + 3548 + /* send a cleanup string just in case: */ 3549 + String getoutstr = "GET /index.vnc HTTP/1.0\r\nConnection: close\r\n\r\n"; 3550 + 3551 + try { 3552 + OutputStream os = socket.getOutputStream(); 3553 + os.write(getoutstr.getBytes()); 3554 + socket.close(); 3555 + } catch (Exception e) { 3556 + dbg("socket is grumpy!"); 3557 + } 3558 + 3559 + /* reload */ 3560 + 3561 + socket = null; 3562 + 3563 + String reason = null; 3564 + 3565 + if (srv_cert) { 3566 + /* for serverCert usage we make this a fatal error. */ 3567 + throw new IOException("Fatal: VNC Server's Cert does not match Applet Parameter 'serverCert=...'"); 3568 + /* see below in TrustDialog were we describe this case to user anyway */ 3569 + } 3570 + 3571 + /* 3572 + * Reconnect, trusting any cert, so we can grab 3573 + * the cert to show it to the user in a dialog 3574 + * for him to manually accept. This connection 3575 + * is not used for anything else. 3576 + */ 3577 + factory = trustall_ctx.getSocketFactory(); 3578 + if (proxy_failure) { 3579 + socket = proxy_socket(factory); 3580 + } else { 3581 + socket = (SSLSocket) factory.createSocket(host, port); 3582 + } 3583 + 3584 + if (debug_certs) { 3585 + dbg("trusturlCerts: " + trusturlCerts); 3586 + dbg("trustsrvCerts: " + trustsrvCerts); 3587 + } 3588 + if (trusturlCerts == null && cert_fail == null) { 3589 + cert_fail = "missing-certs"; 3590 + } 3591 + 3592 + try { 3593 + socket.startHandshake(); 3594 + 3595 + dbg("The TrustAll Server Cert-grab Connection (trivially) Verified OK."); 3596 + 3597 + /* grab the cert: */ 3598 + try { 3599 + SSLSession sess = socket.getSession(); 3600 + trustallCerts = sess.getPeerCertificates(); 3601 + } catch (Exception e) { 3602 + throw new Exception("Could not get " + 3603 + "Peer Certificate"); 3604 + } 3605 + if (debug_certs) { 3606 + dbg("trustallCerts: " + trustallCerts); 3607 + } 3608 + 3609 + if (viewer.trustAllVncCerts) { 3610 + dbg("viewer.trustAllVncCerts-3. skipping dialog, trusting everything."); 3611 + } else if (! browser_cert_match()) { 3612 + /* 3613 + * close socket now, we will reopen after 3614 + * dialog if user agrees to use the cert. 3615 + */ 3616 + try { 3617 + OutputStream os = socket.getOutputStream(); 3618 + os.write(getoutstr.getBytes()); 3619 + socket.close(); 3620 + } catch (Exception e) { 3621 + dbg("socket is grumpy!!"); 3622 + } 3623 + socket = null; 3624 + 3625 + /* dialog with user to accept cert or not: */ 3626 + 3627 + TrustDialog td= new TrustDialog(host, port, 3628 + trustallCerts); 3629 + 3630 + if (cert_fail == null) { 3631 + ; 3632 + } else if (cert_fail.equals("user-view")) { 3633 + reason = "Reason for this Dialog:\n\n" 3634 + + " You Asked to View the Certificate."; 3635 + } else if (cert_fail.equals("server-cert-mismatch")) { 3636 + /* this is now fatal error, see above. */ 3637 + reason = "Reason for this Dialog:\n\n" 3638 + + " The VNC Server's Certificate does not match the Certificate\n" 3639 + + " specified in the supplied 'serverCert' Applet Parameter."; 3640 + } else if (cert_fail.equals("cert-mismatch")) { 3641 + reason = "Reason for this Dialog:\n\n" 3642 + + " The VNC Server's Certificate does not match the Website's\n" 3643 + + " HTTPS Certificate (that you previously accepted; either\n" 3644 + + " manually or automatically via Certificate Authority.)"; 3645 + } else if (cert_fail.equals("missing-certs")) { 3646 + reason = "Reason for this Dialog:\n\n" 3647 + + " Not all Certificates could be obtained to check."; 3648 + } 3649 + 3650 + if (! td.queryUser(reason)) { 3651 + String msg = "User decided against it."; 3652 + dbg(msg); 3653 + throw new IOException(msg); 3654 + } 3655 + } 3656 + 3657 + } catch (Exception ehand2) { 3658 + dbg("** Could not TrustAll Verify Server!"); 3659 + 3660 + throw new IOException(ehand2.getMessage()); 3661 + } 3662 + 3663 + /* reload again: */ 3664 + 3665 + if (socket != null) { 3666 + try { 3667 + socket.close(); 3668 + } catch (Exception e) { 3669 + dbg("socket is grumpy!!!"); 3670 + } 3671 + socket = null; 3672 + } 3673 + 3674 + /* 3675 + * Now connect a 3rd time, using the cert 3676 + * retrieved during connection 2 (sadly, that 3677 + * the user likely blindly agreed to...) 3678 + */ 3679 + 3680 + factory = trustone_ctx.getSocketFactory(); 3681 + if (proxy_failure) { 3682 + socket = proxy_socket(factory); 3683 + } else { 3684 + socket = (SSLSocket) factory.createSocket(host, port); 3685 + } 3686 + 3687 + try { 3688 + socket.startHandshake(); 3689 + dbg("TrustAll/TrustOne Server Connection Verified #3."); 3690 + 3691 + } catch (Exception ehand3) { 3692 + dbg("** Could not TrustAll/TrustOne Verify Server #3."); 3693 + 3694 + throw new IOException(ehand3.getMessage()); 3695 + } 3696 + } 3697 + 3698 + /* we have socket (possibly null) at this point, so proceed: */ 3699 + 3700 + /* handle x11vnc GET=1, if applicable: */ 3701 + if (socket != null && viewer.GET) { 3702 + String str = "GET "; 3703 + str += viewer.urlPrefix; 3704 + str += "/request.https.vnc.connection"; 3705 + str += " HTTP/1.0\r\n"; 3706 + str += "Pragma: No-Cache\r\n"; 3707 + str += "\r\n"; 3708 + 3709 + System.out.println("sending: " + str); 3710 + OutputStream os = socket.getOutputStream(); 3711 + String type = "os"; 3712 + 3713 + if (type == "os") { 3714 + os.write(str.getBytes()); 3715 + os.flush(); 3716 + System.out.println("used OutputStream"); 3717 + } else if (type == "bs") { 3718 + BufferedOutputStream bs = new BufferedOutputStream(os); 3719 + bs.write(str.getBytes()); 3720 + bs.flush(); 3721 + System.out.println("used BufferedOutputStream"); 3722 + } else if (type == "ds") { 3723 + DataOutputStream ds = new DataOutputStream(os); 3724 + ds.write(str.getBytes()); 3725 + ds.flush(); 3726 + System.out.println("used DataOutputStream"); 3727 + } 3728 + if (false) { 3729 + String rep = ""; 3730 + DataInputStream is = new DataInputStream( 3731 + new BufferedInputStream(socket.getInputStream(), 16384)); 3732 + while (true) { 3733 + rep += readline(is); 3734 + if (rep.indexOf("\r\n\r\n") >= 0) { 3735 + break; 3736 + } 3737 + } 3738 + System.out.println("rep: " + rep); 3739 + } 3740 + } 3741 + 3742 + dbg("SSL returning socket to caller."); 3743 + dbg(""); 3744 + 3745 + /* could be null, let caller handle that. */ 3746 + return (Socket) socket; 3747 + } 3748 + 3749 + boolean browser_cert_match() { 3750 + String msg = "Browser URL accept previously accepted cert"; 3751 + 3752 + if (user_wants_to_see_cert) { 3753 + return false; 3754 + } 3755 + 3756 + if (viewer.serverCert != null || trustsrvCerts != null) { 3757 + if (cert_fail == null) { 3758 + cert_fail = "server-cert-mismatch"; 3759 + } 3760 + } 3761 + if (trustallCerts != null && trusturlCerts != null) { 3762 + if (trustallCerts.length == trusturlCerts.length) { 3763 + boolean ok = true; 3764 + /* check toath trustallCerts (socket) equals trusturlCerts (browser) */ 3765 + for (int i = 0; i < trusturlCerts.length; i++) { 3766 + if (! trustallCerts[i].equals(trusturlCerts[i])) { 3767 + dbg("BCM: cert mismatch at i=" + i); 3768 + dbg("BCM: cert mismatch url" + trusturlCerts[i]); 3769 + dbg("BCM: cert mismatch all" + trustallCerts[i]); 3770 + ok = false; 3771 + } 3772 + } 3773 + if (ok) { 3774 + System.out.println(msg); 3775 + if (cert_fail == null) { 3776 + cert_fail = "did-not-fail"; 3777 + } 3778 + return true; 3779 + } else { 3780 + if (cert_fail == null) { 3781 + cert_fail = "cert-mismatch"; 3782 + } 3783 + return false; 3784 + } 3785 + } 3786 + } 3787 + if (cert_fail == null) { 3788 + cert_fail = "missing-certs"; 3789 + } 3790 + return false; 3791 + } 3792 + 3793 + private void dbg(String s) { 3794 + if (debug) { 3795 + System.out.println(s); 3796 + } 3797 + } 3798 + 3799 + private int gint(String s) { 3800 + int n = -1; 3801 + try { 3802 + Integer I = new Integer(s); 3803 + n = I.intValue(); 3804 + } catch (Exception ex) { 3805 + return -1; 3806 + } 3807 + return n; 3808 + } 3809 + 3810 + /* this will do the proxy CONNECT negotiation and hook us up. */ 3811 + 3812 + private void proxy_helper(String proxyHost, int proxyPort) { 3813 + 3814 + boolean proxy_auth = false; 3815 + String proxy_auth_basic_realm = ""; 3816 + String hp = host + ":" + port; 3817 + dbg("proxy_helper: " + proxyHost + ":" + proxyPort + " hp: " + hp); 3818 + 3819 + /* we loop here a few times trying for the password case */ 3820 + for (int k=0; k < 2; k++) { 3821 + dbg("proxy_in_use psocket: " + k); 3822 + 3823 + if (proxySock != null) { 3824 + try { 3825 + proxySock.close(); 3826 + } catch (Exception e) { 3827 + dbg("proxy socket is grumpy."); 3828 + } 3829 + } 3830 + 3831 + proxySock = psocket(proxyHost, proxyPort); 3832 + if (proxySock == null) { 3833 + dbg("1-a sadly, returning a null socket"); 3834 + return; 3835 + } 3836 + 3837 + String req1 = "CONNECT " + hp + " HTTP/1.1\r\n" 3838 + + "Host: " + hp + "\r\n"; 3839 + 3840 + dbg("requesting via proxy: " + req1); 3841 + 3842 + if (proxy_auth) { 3843 + if (proxy_auth_string == null) { 3844 + ProxyPasswdDialog pp = new ProxyPasswdDialog(proxyHost, proxyPort, proxy_auth_basic_realm); 3845 + pp.queryUser(); 3846 + proxy_auth_string = pp.getAuth(); 3847 + } 3848 + //dbg("auth1: " + proxy_auth_string); 3849 + 3850 + String auth2 = Base64Coder.encodeString(proxy_auth_string); 3851 + //dbg("auth2: " + auth2); 3852 + 3853 + req1 += "Proxy-Authorization: Basic " + auth2 + "\r\n"; 3854 + //dbg("req1: " + req1); 3855 + 3856 + dbg("added Proxy-Authorization: Basic ... to request"); 3857 + } 3858 + req1 += "\r\n"; 3859 + 3860 + try { 3861 + proxy_os.write(req1.getBytes()); 3862 + String reply = readline(proxy_is); 3863 + 3864 + dbg("proxy replied: " + reply.trim()); 3865 + 3866 + if (reply.indexOf("HTTP/1.") == 0 && reply.indexOf(" 407 ") > 0) { 3867 + proxy_auth = true; 3868 + proxySock.close(); 3869 + } else if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) { 3870 + proxySock.close(); 3871 + proxySock = psocket(proxyHost, proxyPort); 3872 + if (proxySock == null) { 3873 + dbg("2-a sadly, returning a null socket"); 3874 + return; 3875 + } 3876 + } 3877 + } catch(Exception e) { 3878 + dbg("some proxy socket problem: " + e.getMessage()); 3879 + } 3880 + 3881 + /* read the rest of the HTTP headers */ 3882 + while (true) { 3883 + String line = readline(proxy_is); 3884 + dbg("proxy line: " + line.trim()); 3885 + if (proxy_auth) { 3886 + String uc = line.toLowerCase(); 3887 + if (uc.indexOf("proxy-authenticate:") == 0) { 3888 + if (uc.indexOf(" basic ") >= 0) { 3889 + int idx = uc.indexOf(" realm"); 3890 + if (idx >= 0) { 3891 + proxy_auth_basic_realm = uc.substring(idx+1); 3892 + } 3893 + } 3894 + } 3895 + } 3896 + if (line.equals("\r\n") || line.equals("\n")) { 3897 + break; 3898 + } 3899 + } 3900 + if (!proxy_auth || proxy_auth_basic_realm.equals("")) { 3901 + /* we only try once for the non-password case: */ 3902 + break; 3903 + } 3904 + } 3905 + } 3906 + 3907 + public SSLSocket proxy_socket(SSLSocketFactory factory) { 3908 + Properties props = null; 3909 + String proxyHost = null; 3910 + int proxyPort = 0; 3911 + String proxyHost_nossl = null; 3912 + int proxyPort_nossl = 0; 3913 + String str; 3914 + 3915 + /* see if we can guess the proxy info from Properties: */ 3916 + try { 3917 + props = System.getProperties(); 3918 + } catch (Exception e) { 3919 + /* sandboxed applet might not be able to read it. */ 3920 + dbg("props failed: " + e.getMessage()); 3921 + } 3922 + if (viewer.proxyHost != null) { 3923 + dbg("Using supplied proxy " + viewer.proxyHost + " " + viewer.proxyPort + " applet parameters."); 3924 + proxyHost = viewer.proxyHost; 3925 + if (viewer.proxyPort != null) { 3926 + proxyPort = gint(viewer.proxyPort); 3927 + } else { 3928 + proxyPort = 8080; 3929 + } 3930 + 3931 + } else if (props != null) { 3932 + dbg("\n---------------\nAll props:"); 3933 + props.list(System.out); 3934 + dbg("\n---------------\n\n"); 3935 + 3936 + /* scrape throught properties looking for proxy info: */ 3937 + 3938 + for (Enumeration e = props.propertyNames(); e.hasMoreElements(); ) { 3939 + String s = (String) e.nextElement(); 3940 + String v = System.getProperty(s); 3941 + String s2 = s.toLowerCase(); 3942 + String v2 = v.toLowerCase(); 3943 + 3944 + if (s2.indexOf("proxy.https.host") >= 0) { 3945 + proxyHost = v2; 3946 + continue; 3947 + } 3948 + if (s2.indexOf("proxy.https.port") >= 0) { 3949 + proxyPort = gint(v2); 3950 + continue; 3951 + } 3952 + if (s2.indexOf("proxy.http.host") >= 0) { 3953 + proxyHost_nossl = v2; 3954 + continue; 3955 + } 3956 + if (s2.indexOf("proxy.http.port") >= 0) { 3957 + proxyPort_nossl = gint(v2); 3958 + continue; 3959 + } 3960 + } 3961 + 3962 + for (Enumeration e = props.propertyNames(); e.hasMoreElements(); ) { 3963 + String s = (String) e.nextElement(); 3964 + String v = System.getProperty(s); 3965 + String s2 = s.toLowerCase(); 3966 + String v2 = v.toLowerCase(); 3967 + 3968 + if (proxyHost != null && proxyPort > 0) { 3969 + break; 3970 + } 3971 + 3972 + // look for something like: javaplugin.proxy.config.list = http=10.0.2.1:8082 3973 + if (s2.indexOf("proxy") < 0 && v2.indexOf("proxy") < 0) { 3974 + continue; 3975 + } 3976 + if (v2.indexOf("http") < 0) { 3977 + continue; 3978 + } 3979 + 3980 + String[] pieces = v.split("[,;]"); 3981 + for (int i = 0; i < pieces.length; i++) { 3982 + String p = pieces[i]; 3983 + int j = p.indexOf("https"); 3984 + if (j < 0) { 3985 + j = p.indexOf("http"); 3986 + if (j < 0) { 3987 + continue; 3988 + } 3989 + } 3990 + j = p.indexOf("=", j); 3991 + if (j < 0) { 3992 + continue; 3993 + } 3994 + p = p.substring(j+1); 3995 + String [] hp = p.split(":"); 3996 + if (hp.length != 2) { 3997 + continue; 3998 + } 3999 + if (hp[0].length() > 1 && hp[1].length() > 1) { 4000 + 4001 + proxyPort = gint(hp[1]); 4002 + if (proxyPort < 0) { 4003 + continue; 4004 + } 4005 + proxyHost = new String(hp[0]); 4006 + break; 4007 + } 4008 + } 4009 + } 4010 + } 4011 + if (proxyHost != null) { 4012 + if (proxyHost_nossl != null && proxyPort_nossl > 0) { 4013 + dbg("Using http proxy info instead of https."); 4014 + proxyHost = proxyHost_nossl; 4015 + proxyPort = proxyPort_nossl; 4016 + } 4017 + } 4018 + 4019 + if (proxy_in_use) { 4020 + if (proxy_dialog_host != null && proxy_dialog_port > 0) { 4021 + proxyHost = proxy_dialog_host; 4022 + proxyPort = proxy_dialog_port; 4023 + } 4024 + if (proxyHost != null) { 4025 + dbg("Lucky us! we figured out the Proxy parameters: " + proxyHost + " " + proxyPort); 4026 + } else { 4027 + /* ask user to help us: */ 4028 + ProxyDialog pd = new ProxyDialog(proxyHost, proxyPort); 4029 + pd.queryUser(); 4030 + proxyHost = pd.getHost(); 4031 + proxyPort = pd.getPort(); 4032 + proxy_dialog_host = new String(proxyHost); 4033 + proxy_dialog_port = proxyPort; 4034 + dbg("User said host: " + pd.getHost() + " port: " + pd.getPort()); 4035 + } 4036 + 4037 + proxy_helper(proxyHost, proxyPort); 4038 + if (proxySock == null) { 4039 + return null; 4040 + } 4041 + } else if (viewer.CONNECT != null) { 4042 + dbg("viewer.CONNECT psocket:"); 4043 + proxySock = psocket(host, port); 4044 + if (proxySock == null) { 4045 + dbg("1-b sadly, returning a null socket"); 4046 + return null; 4047 + } 4048 + } 4049 + 4050 + if (viewer.CONNECT != null) { 4051 + String hp = viewer.CONNECT; 4052 + String req2 = "CONNECT " + hp + " HTTP/1.1\r\n" 4053 + + "Host: " + hp + "\r\n\r\n"; 4054 + 4055 + dbg("requesting2: " + req2); 4056 + 4057 + try { 4058 + proxy_os.write(req2.getBytes()); 4059 + String reply = readline(proxy_is); 4060 + 4061 + dbg("proxy replied2: " + reply.trim()); 4062 + 4063 + if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) { 4064 + proxySock.close(); 4065 + proxySock = psocket(proxyHost, proxyPort); 4066 + if (proxySock == null) { 4067 + dbg("2-b sadly, returning a null socket"); 4068 + return null; 4069 + } 4070 + } 4071 + } catch(Exception e) { 4072 + dbg("proxy socket problem-2: " + e.getMessage()); 4073 + } 4074 + 4075 + while (true) { 4076 + String line = readline(proxy_is); 4077 + dbg("proxy line2: " + line.trim()); 4078 + if (line.equals("\r\n") || line.equals("\n")) { 4079 + break; 4080 + } 4081 + } 4082 + } 4083 + 4084 + Socket sslsock = null; 4085 + try { 4086 + sslsock = factory.createSocket(proxySock, host, port, true); 4087 + } catch(Exception e) { 4088 + dbg("sslsock prob: " + e.getMessage()); 4089 + dbg("3 sadly, returning a null socket"); 4090 + } 4091 + 4092 + return (SSLSocket) sslsock; 4093 + } 4094 + 4095 + Socket psocket(String h, int p) { 4096 + Socket psock = null; 4097 + try { 4098 + psock = new Socket(h, p); 4099 + proxy_is = new DataInputStream(new BufferedInputStream( 4100 + psock.getInputStream(), 16384)); 4101 + proxy_os = psock.getOutputStream(); 4102 + } catch(Exception e) { 4103 + dbg("psocket prob: " + e.getMessage()); 4104 + return null; 4105 + } 4106 + 4107 + return psock; 4108 + } 4109 + 4110 + String readline(DataInputStream i) { 4111 + byte[] ba = new byte[1]; 4112 + String s = new String(""); 4113 + ba[0] = 0; 4114 + try { 4115 + while (ba[0] != 0xa) { 4116 + ba[0] = (byte) i.readUnsignedByte(); 4117 + s += new String(ba); 4118 + } 4119 + } catch (Exception e) { 4120 + ; 4121 + } 4122 + return s; 4123 + } 4124 +} 4125 + 4126 +class TrustDialog implements ActionListener { 4127 + String msg, host, text; 4128 + int port; 4129 + java.security.cert.Certificate[] trustallCerts = null; 4130 + boolean viewing_cert = false; 4131 + boolean trust_this_session = false; 4132 + 4133 + /* 4134 + * this is the gui to show the user the cert and info and ask 4135 + * them if they want to continue using this cert. 4136 + */ 4137 + 4138 + Button ok, cancel, viewcert; 4139 + TextArea textarea; 4140 + Checkbox accept, deny; 4141 + Dialog dialog; 4142 + 4143 + String s1 = "Accept this certificate temporarily for this session"; 4144 + String s2 = "Do not accept this certificate and do not connect to" 4145 + + " this VNC server"; 4146 + String ln = "\n---------------------------------------------------\n\n"; 4147 + 4148 + TrustDialog (String h, int p, java.security.cert.Certificate[] s) { 4149 + host = h; 4150 + port = p; 4151 + trustallCerts = s; 4152 + 4153 + msg = "VNC Server " + host + ":" + port + " Not Verified"; 4154 + } 4155 + 4156 + public boolean queryUser(String reason) { 4157 + 4158 + /* create and display the dialog for unverified cert. */ 4159 + 4160 + Frame frame = new Frame(msg); 4161 + 4162 + dialog = new Dialog(frame, true); 4163 + 4164 + String infostr = ""; 4165 + if (trustallCerts.length == 1) { 4166 + CertInfo ci = new CertInfo(trustallCerts[0]); 4167 + infostr = ci.get_certinfo("all"); 4168 + } 4169 + if (reason != null) { 4170 + reason += "\n\n"; 4171 + } 4172 + 4173 + text = "\n" 4174 ++ "Unable to verify the identity of\n" 4175 ++ "\n" 4176 ++ " " + host + ":" + port + "\n" 4177 ++ "\n" 4178 ++ infostr 4179 ++ "\n" 4180 ++ "as a trusted VNC server.\n" 4181 ++ "\n" 4182 ++ reason 4183 ++ "In General not being able to verify the VNC Server and/or your seeing this Dialog\n" 4184 ++ "is due to one of the following:\n" 4185 ++ "\n" 4186 ++ " - Your requesting to View the Certificate before accepting.\n" 4187 ++ "\n" 4188 ++ " - The VNC server is using a Self-Signed Certificate or a Certificate\n" 4189 ++ " Authority not recognized by your Web Browser or Java Plugin runtime.\n" 4190 ++ "\n" 4191 ++ " - The use of an Apache SSL portal scheme employing CONNECT proxying AND\n" 4192 ++ " the Apache Web server has a certificate *different* from the VNC server's.\n" 4193 ++ "\n" 4194 ++ " - No previously accepted Certificate (via Web Broswer/Java Plugin) could be\n" 4195 ++ " obtained by this applet to compare the VNC Server Certificate against.\n" 4196 ++ "\n" 4197 ++ " - The VNC Server's Certificate does not match the one specified in the\n" 4198 ++ " supplied 'serverCert' Java Applet Parameter.\n" 4199 ++ "\n" 4200 ++ " - A Man-In-The-Middle attack impersonating as the VNC server that you wish\n" 4201 ++ " to connect to. (Wouldn't that be exciting!!)\n" 4202 ++ "\n" 4203 ++ "By safely copying the VNC server's Certificate (or using a common Certificate\n" 4204 ++ "Authority certificate) you can configure your Web Browser and Java Plugin to\n" 4205 ++ "automatically authenticate this VNC Server.\n" 4206 ++ "\n" 4207 ++ "If you do so, then you will only have to click \"Yes\" when this VNC Viewer\n" 4208 ++ "applet asks you whether to trust your Browser/Java Plugin's acceptance of the\n" 4209 ++ "certificate (except for the Apache portal case above where they don't match.)\n" 4210 ++ "\n" 4211 ++ "You can also set the applet parameter 'trustUrlVncCert=yes' to automatically\n" 4212 ++ "accept certificates already accepted/trusted by your Web Browser/Java Plugin,\n" 4213 ++ "and thereby see no dialog from this VNC Viewer applet.\n" 4214 +; 4215 + 4216 + /* the accept / do-not-accept radio buttons: */ 4217 + CheckboxGroup checkbox = new CheckboxGroup(); 4218 + accept = new Checkbox(s1, true, checkbox); 4219 + deny = new Checkbox(s2, false, checkbox); 4220 + 4221 + /* put the checkboxes in a panel: */ 4222 + Panel check = new Panel(); 4223 + check.setLayout(new GridLayout(2, 1)); 4224 + 4225 + check.add(accept); 4226 + check.add(deny); 4227 + 4228 + /* make the 3 buttons: */ 4229 + ok = new Button("OK"); 4230 + cancel = new Button("Cancel"); 4231 + viewcert = new Button("View Certificate"); 4232 + 4233 + ok.addActionListener(this); 4234 + cancel.addActionListener(this); 4235 + viewcert.addActionListener(this); 4236 + 4237 + /* put the buttons in their own panel: */ 4238 + Panel buttonrow = new Panel(); 4239 + buttonrow.setLayout(new FlowLayout(FlowLayout.LEFT)); 4240 + buttonrow.add(viewcert); 4241 + buttonrow.add(ok); 4242 + buttonrow.add(cancel); 4243 + 4244 + /* label at the top: */ 4245 + Label label = new Label(msg, Label.CENTER); 4246 + label.setFont(new Font("Helvetica", Font.BOLD, 16)); 4247 + 4248 + /* textarea in the middle */ 4249 + textarea = new TextArea(text, 38, 64, 4250 + TextArea.SCROLLBARS_VERTICAL_ONLY); 4251 + textarea.setEditable(false); 4252 + 4253 + /* put the two panels in their own panel at bottom: */ 4254 + Panel bot = new Panel(); 4255 + bot.setLayout(new GridLayout(2, 1)); 4256 + bot.add(check); 4257 + bot.add(buttonrow); 4258 + 4259 + /* now arrange things inside the dialog: */ 4260 + dialog.setLayout(new BorderLayout()); 4261 + 4262 + dialog.add("North", label); 4263 + dialog.add("South", bot); 4264 + dialog.add("Center", textarea); 4265 + 4266 + dialog.pack(); 4267 + dialog.resize(dialog.preferredSize()); 4268 + 4269 + dialog.show(); /* block here til OK or Cancel pressed. */ 4270 + 4271 + return trust_this_session; 4272 + } 4273 + 4274 + public synchronized void actionPerformed(ActionEvent evt) { 4275 + 4276 + if (evt.getSource() == viewcert) { 4277 + /* View Certificate button clicked */ 4278 + if (viewing_cert) { 4279 + /* show the original info text: */ 4280 + textarea.setText(text); 4281 + viewcert.setLabel("View Certificate"); 4282 + viewing_cert = false; 4283 + } else { 4284 + int i; 4285 + /* show all (likely just one) certs: */ 4286 + textarea.setText(""); 4287 + for (i=0; i < trustallCerts.length; i++) { 4288 + int j = i + 1; 4289 + textarea.append("Certificate[" + 4290 + j + "]\n\n"); 4291 + textarea.append( 4292 + trustallCerts[i].toString()); 4293 + textarea.append(ln); 4294 + } 4295 + viewcert.setLabel("View Info"); 4296 + viewing_cert = true; 4297 + 4298 + textarea.setCaretPosition(0); 4299 + } 4300 + 4301 + } else if (evt.getSource() == ok) { 4302 + /* OK button clicked */ 4303 + if (accept.getState()) { 4304 + trust_this_session = true; 4305 + } else { 4306 + trust_this_session = false; 4307 + } 4308 + //dialog.dispose(); 4309 + dialog.hide(); 4310 + 4311 + } else if (evt.getSource() == cancel) { 4312 + /* Cancel button clicked */ 4313 + trust_this_session = false; 4314 + 4315 + //dialog.dispose(); 4316 + dialog.hide(); 4317 + } 4318 + } 4319 + 4320 + String get_certinfo() { 4321 + String all = ""; 4322 + String fields[] = {"CN", "OU", "O", "L", "C"}; 4323 + int i; 4324 + if (trustallCerts.length < 1) { 4325 + all = ""; 4326 + return all; 4327 + } 4328 + String cert = trustallCerts[0].toString(); 4329 + 4330 + /* 4331 + * For now we simply scrape the cert string, there must 4332 + * be an API for this... perhaps optionValue? 4333 + */ 4334 + 4335 + for (i=0; i < fields.length; i++) { 4336 + int f, t, t1, t2; 4337 + String sub, mat = fields[i] + "="; 4338 + 4339 + f = cert.indexOf(mat, 0); 4340 + if (f > 0) { 4341 + t1 = cert.indexOf(", ", f); 4342 + t2 = cert.indexOf("\n", f); 4343 + if (t1 < 0 && t2 < 0) { 4344 + continue; 4345 + } else if (t1 < 0) { 4346 + t = t2; 4347 + } else if (t2 < 0) { 4348 + t = t1; 4349 + } else if (t1 < t2) { 4350 + t = t1; 4351 + } else { 4352 + t = t2; 4353 + } 4354 + if (t > f) { 4355 + sub = cert.substring(f, t); 4356 + all = all + " " + sub + "\n"; 4357 + } 4358 + } 4359 + } 4360 + return all; 4361 + } 4362 +} 4363 + 4364 +class ProxyDialog implements ActionListener { 4365 + String guessedHost = null; 4366 + String guessedPort = null; 4367 + /* 4368 + * this is the gui to show the user the cert and info and ask 4369 + * them if they want to continue using this cert. 4370 + */ 4371 + 4372 + Button ok; 4373 + Dialog dialog; 4374 + TextField entry; 4375 + String reply = ""; 4376 + 4377 + ProxyDialog (String h, int p) { 4378 + guessedHost = h; 4379 + try { 4380 + guessedPort = Integer.toString(p); 4381 + } catch (Exception e) { 4382 + guessedPort = "8080"; 4383 + } 4384 + } 4385 + 4386 + public void queryUser() { 4387 + 4388 + /* create and display the dialog for unverified cert. */ 4389 + 4390 + Frame frame = new Frame("Need Proxy host:port"); 4391 + 4392 + dialog = new Dialog(frame, true); 4393 + 4394 + 4395 + Label label = new Label("Please Enter your https Proxy info as host:port", Label.CENTER); 4396 + //label.setFont(new Font("Helvetica", Font.BOLD, 16)); 4397 + entry = new TextField(30); 4398 + ok = new Button("OK"); 4399 + ok.addActionListener(this); 4400 + 4401 + String guess = ""; 4402 + if (guessedHost != null) { 4403 + guess = guessedHost + ":" + guessedPort; 4404 + } 4405 + entry.setText(guess); 4406 + 4407 + dialog.setLayout(new BorderLayout()); 4408 + dialog.add("North", label); 4409 + dialog.add("Center", entry); 4410 + dialog.add("South", ok); 4411 + dialog.pack(); 4412 + dialog.resize(dialog.preferredSize()); 4413 + 4414 + dialog.show(); /* block here til OK or Cancel pressed. */ 4415 + return; 4416 + } 4417 + 4418 + public String getHost() { 4419 + int i = reply.indexOf(":"); 4420 + if (i < 0) { 4421 + return "unknown"; 4422 + } 4423 + String h = reply.substring(0, i); 4424 + return h; 4425 + } 4426 + 4427 + public int getPort() { 4428 + int i = reply.indexOf(":"); 4429 + int p = 8080; 4430 + if (i < 0) { 4431 + return p; 4432 + } 4433 + i++; 4434 + String ps = reply.substring(i); 4435 + try { 4436 + Integer I = new Integer(ps); 4437 + p = I.intValue(); 4438 + } catch (Exception e) { 4439 + ; 4440 + } 4441 + return p; 4442 + } 4443 + 4444 + public synchronized void actionPerformed(ActionEvent evt) { 4445 + System.out.println(evt.getActionCommand()); 4446 + if (evt.getSource() == ok) { 4447 + reply = entry.getText(); 4448 + //dialog.dispose(); 4449 + dialog.hide(); 4450 + } 4451 + } 4452 +} 4453 + 4454 +class ProxyPasswdDialog implements ActionListener { 4455 + String guessedHost = null; 4456 + String guessedPort = null; 4457 + String guessedUser = null; 4458 + String guessedPasswd = null; 4459 + String realm = null; 4460 + /* 4461 + * this is the gui to show the user the cert and info and ask 4462 + * them if they want to continue using this cert. 4463 + */ 4464 + 4465 + Button ok; 4466 + Dialog dialog; 4467 + TextField entry1; 4468 + TextField entry2; 4469 + String reply1 = ""; 4470 + String reply2 = ""; 4471 + 4472 + ProxyPasswdDialog (String h, int p, String realm) { 4473 + guessedHost = h; 4474 + try { 4475 + guessedPort = Integer.toString(p); 4476 + } catch (Exception e) { 4477 + guessedPort = "8080"; 4478 + } 4479 + this.realm = realm; 4480 + } 4481 + 4482 + public void queryUser() { 4483 + 4484 + /* create and display the dialog for unverified cert. */ 4485 + 4486 + Frame frame = new Frame("Proxy Requires Username and Password"); 4487 + 4488 + dialog = new Dialog(frame, true); 4489 + 4490 + //Label label = new Label("Please Enter your Web Proxy Username in the top Entry and Password in the bottom Entry", Label.CENTER); 4491 + TextArea label = new TextArea("Please Enter your Web Proxy\nUsername in the Top Entry and\nPassword in the Bottom Entry,\nand then press OK.", 4, 20, TextArea.SCROLLBARS_NONE); 4492 + entry1 = new TextField(30); 4493 + entry2 = new TextField(30); 4494 + entry2.setEchoChar('*'); 4495 + ok = new Button("OK"); 4496 + ok.addActionListener(this); 4497 + 4498 + dialog.setLayout(new BorderLayout()); 4499 + dialog.add("North", label); 4500 + dialog.add("Center", entry1); 4501 + dialog.add("South", entry2); 4502 + dialog.add("East", ok); 4503 + dialog.pack(); 4504 + dialog.resize(dialog.preferredSize()); 4505 + 4506 + dialog.show(); /* block here til OK or Cancel pressed. */ 4507 + return; 4508 + } 4509 + 4510 + public String getAuth() { 4511 + return reply1 + ":" + reply2; 4512 + } 4513 + 4514 + public synchronized void actionPerformed(ActionEvent evt) { 4515 + System.out.println(evt.getActionCommand()); 4516 + if (evt.getSource() == ok) { 4517 + reply1 = entry1.getText(); 4518 + reply2 = entry2.getText(); 4519 + //dialog.dispose(); 4520 + dialog.hide(); 4521 + } 4522 + } 4523 +} 4524 + 4525 +class ClientCertDialog implements ActionListener { 4526 + 4527 + Button ok; 4528 + Dialog dialog; 4529 + TextField entry; 4530 + String reply = ""; 4531 + 4532 + ClientCertDialog() { 4533 + ; 4534 + } 4535 + 4536 + public String queryUser() { 4537 + 4538 + /* create and display the dialog for unverified cert. */ 4539 + 4540 + Frame frame = new Frame("Enter SSL Client Cert+Key String"); 4541 + 4542 + dialog = new Dialog(frame, true); 4543 + 4544 + 4545 + Label label = new Label("Please Enter the SSL Client Cert+Key String 308204c0...,...522d2d0a", Label.CENTER); 4546 + entry = new TextField(30); 4547 + ok = new Button("OK"); 4548 + ok.addActionListener(this); 4549 + 4550 + dialog.setLayout(new BorderLayout()); 4551 + dialog.add("North", label); 4552 + dialog.add("Center", entry); 4553 + dialog.add("South", ok); 4554 + dialog.pack(); 4555 + dialog.resize(dialog.preferredSize()); 4556 + 4557 + dialog.show(); /* block here til OK or Cancel pressed. */ 4558 + return reply; 4559 + } 4560 + 4561 + public synchronized void actionPerformed(ActionEvent evt) { 4562 + System.out.println(evt.getActionCommand()); 4563 + if (evt.getSource() == ok) { 4564 + reply = entry.getText(); 4565 + //dialog.dispose(); 4566 + dialog.hide(); 4567 + } 4568 + } 4569 +} 4570 + 4571 +class BrowserCertsDialog implements ActionListener { 4572 + Button yes, no; 4573 + Dialog dialog; 4574 + String vncServer; 4575 + String hostport; 4576 + public boolean showCertDialog = true; 4577 + 4578 + BrowserCertsDialog(String serv, String hp) { 4579 + vncServer = serv; 4580 + hostport = hp; 4581 + } 4582 + 4583 + public void queryUser() { 4584 + 4585 + /* create and display the dialog for unverified cert. */ 4586 + 4587 + Frame frame = new Frame("Use Browser/JVM Certs?"); 4588 + 4589 + dialog = new Dialog(frame, true); 4590 + 4591 + String m = ""; 4592 +m += "\n"; 4593 +m += "This VNC Viewer applet does not have its own keystore to track\n"; 4594 +m += "SSL certificates, and so cannot authenticate the certificate\n"; 4595 +m += "of the VNC Server:\n"; 4596 +m += "\n"; 4597 +m += " " + hostport + "\n\n " + vncServer + "\n"; 4598 +m += "\n"; 4599 +m += "on its own.\n"; 4600 +m += "\n"; 4601 +m += "However, it has noticed that your Web Browser and/or Java VM Plugin\n"; 4602 +m += "has previously accepted the same certificate. You may have set\n"; 4603 +m += "this up permanently or just for this session, or the server\n"; 4604 +m += "certificate was signed by a CA cert that your Web Browser or\n"; 4605 +m += "Java VM Plugin has.\n"; 4606 +m += "\n"; 4607 +m += "If the VNC Server connection times out while you are reading this\n"; 4608 +m += "dialog, then restart the connection and try again.\n"; 4609 +m += "\n"; 4610 +m += "Should this VNC Viewer applet now connect to the above VNC server?\n"; 4611 +m += "\n"; 4612 + 4613 + TextArea textarea = new TextArea(m, 22, 64, 4614 + TextArea.SCROLLBARS_VERTICAL_ONLY); 4615 + textarea.setEditable(false); 4616 + yes = new Button("Yes"); 4617 + yes.addActionListener(this); 4618 + no = new Button("No, Let Me See the Certificate."); 4619 + no.addActionListener(this); 4620 + 4621 + dialog.setLayout(new BorderLayout()); 4622 + dialog.add("North", textarea); 4623 + dialog.add("Center", yes); 4624 + dialog.add("South", no); 4625 + dialog.pack(); 4626 + dialog.resize(dialog.preferredSize()); 4627 + 4628 + dialog.show(); /* block here til Yes or No pressed. */ 4629 + System.out.println("done show()"); 4630 + return; 4631 + } 4632 + 4633 + public synchronized void actionPerformed(ActionEvent evt) { 4634 + System.out.println(evt.getActionCommand()); 4635 + if (evt.getSource() == yes) { 4636 + showCertDialog = false; 4637 + //dialog.dispose(); 4638 + dialog.hide(); 4639 + } else if (evt.getSource() == no) { 4640 + showCertDialog = true; 4641 + //dialog.dispose(); 4642 + dialog.hide(); 4643 + } 4644 + System.out.println("done actionPerformed()"); 4645 + } 4646 +} 4647 + 4648 +class CertInfo { 4649 + String fields[] = {"CN", "OU", "O", "L", "C"}; 4650 + java.security.cert.Certificate cert; 4651 + String certString = ""; 4652 + 4653 + CertInfo(java.security.cert.Certificate c) { 4654 + cert = c; 4655 + certString = cert.toString(); 4656 + } 4657 + 4658 + String get_certinfo(String which) { 4659 + int i; 4660 + String cs = new String(certString); 4661 + String all = ""; 4662 + 4663 + /* 4664 + * For now we simply scrape the cert string, there must 4665 + * be an API for this... perhaps optionValue? 4666 + */ 4667 + for (i=0; i < fields.length; i++) { 4668 + int f, t, t1, t2; 4669 + String sub, mat = fields[i] + "="; 4670 + 4671 + f = cs.indexOf(mat, 0); 4672 + if (f > 0) { 4673 + t1 = cs.indexOf(", ", f); 4674 + t2 = cs.indexOf("\n", f); 4675 + if (t1 < 0 && t2 < 0) { 4676 + continue; 4677 + } else if (t1 < 0) { 4678 + t = t2; 4679 + } else if (t2 < 0) { 4680 + t = t1; 4681 + } else if (t1 < t2) { 4682 + t = t1; 4683 + } else { 4684 + t = t2; 4685 + } 4686 + if (t > f) { 4687 + sub = cs.substring(f, t); 4688 + all = all + " " + sub + "\n"; 4689 + if (which.equals(fields[i])) { 4690 + return sub; 4691 + } 4692 + } 4693 + } 4694 + } 4695 + if (which.equals("all")) { 4696 + return all; 4697 + } else { 4698 + return ""; 4699 + } 4700 + } 4701 +} 4702 + 4703 +class Base64Coder { 4704 + 4705 + // Mapping table from 6-bit nibbles to Base64 characters. 4706 + private static char[] map1 = new char[64]; 4707 + static { 4708 + int i=0; 4709 + for (char c='A'; c<='Z'; c++) map1[i++] = c; 4710 + for (char c='a'; c<='z'; c++) map1[i++] = c; 4711 + for (char c='0'; c<='9'; c++) map1[i++] = c; 4712 + map1[i++] = '+'; map1[i++] = '/'; } 4713 + 4714 + // Mapping table from Base64 characters to 6-bit nibbles. 4715 + private static byte[] map2 = new byte[128]; 4716 + static { 4717 + for (int i=0; i<map2.length; i++) map2[i] = -1; 4718 + for (int i=0; i<64; i++) map2[map1[i]] = (byte)i; } 4719 + 4720 + /** 4721 + * Encodes a string into Base64 format. 4722 + * No blanks or line breaks are inserted. 4723 + * @param s a String to be encoded. 4724 + * @return A String with the Base64 encoded data. 4725 + */ 4726 + public static String encodeString (String s) { 4727 + return new String(encode(s.getBytes())); } 4728 + 4729 + /** 4730 + * Encodes a byte array into Base64 format. 4731 + * No blanks or line breaks are inserted. 4732 + * @param in an array containing the data bytes to be encoded. 4733 + * @return A character array with the Base64 encoded data. 4734 + */ 4735 + public static char[] encode (byte[] in) { 4736 + return encode(in,in.length); } 4737 + 4738 + /** 4739 + * Encodes a byte array into Base64 format. 4740 + * No blanks or line breaks are inserted. 4741 + * @param in an array containing the data bytes to be encoded. 4742 + * @param iLen number of bytes to process in <code>in</code>. 4743 + * @return A character array with the Base64 encoded data. 4744 + */ 4745 + public static char[] encode (byte[] in, int iLen) { 4746 + int oDataLen = (iLen*4+2)/3; // output length without padding 4747 + int oLen = ((iLen+2)/3)*4; // output length including padding 4748 + char[] out = new char[oLen]; 4749 + int ip = 0; 4750 + int op = 0; 4751 + while (ip < iLen) { 4752 + int i0 = in[ip++] & 0xff; 4753 + int i1 = ip < iLen ? in[ip++] & 0xff : 0; 4754 + int i2 = ip < iLen ? in[ip++] & 0xff : 0; 4755 + int o0 = i0 >>> 2; 4756 + int o1 = ((i0 & 3) << 4) | (i1 >>> 4); 4757 + int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); 4758 + int o3 = i2 & 0x3F; 4759 + out[op++] = map1[o0]; 4760 + out[op++] = map1[o1]; 4761 + out[op] = op < oDataLen ? map1[o2] : '='; op++; 4762 + out[op] = op < oDataLen ? map1[o3] : '='; op++; } 4763 + return out; } 4764 + 4765 + /** 4766 + * Decodes a string from Base64 format. 4767 + * @param s a Base64 String to be decoded. 4768 + * @return A String containing the decoded data. 4769 + * @throws IllegalArgumentException if the input is not valid Base64 encoded data. 4770 + */ 4771 + public static String decodeString (String s) { 4772 + return new String(decode(s)); } 4773 + 4774 + /** 4775 + * Decodes a byte array from Base64 format. 4776 + * @param s a Base64 String to be decoded. 4777 + * @return An array containing the decoded data bytes. 4778 + * @throws IllegalArgumentException if the input is not valid Base64 encoded data. 4779 + */ 4780 + public static byte[] decode (String s) { 4781 + return decode(s.toCharArray()); } 4782 + 4783 + /** 4784 + * Decodes a byte array from Base64 format. 4785 + * No blanks or line breaks are allowed within the Base64 encoded data. 4786 + * @param in a character array containing the Base64 encoded data. 4787 + * @return An array containing the decoded data bytes. 4788 + * @throws IllegalArgumentException if the input is not valid Base64 encoded data. 4789 + */ 4790 + public static byte[] decode (char[] in) { 4791 + int iLen = in.length; 4792 + if (iLen%4 != 0) throw new IllegalArgumentException ("Length of Base64 encoded input string is not a multiple of 4."); 4793 + while (iLen > 0 && in[iLen-1] == '=') iLen--; 4794 + int oLen = (iLen*3) / 4; 4795 + byte[] out = new byte[oLen]; 4796 + int ip = 0; 4797 + int op = 0; 4798 + while (ip < iLen) { 4799 + int i0 = in[ip++]; 4800 + int i1 = in[ip++]; 4801 + int i2 = ip < iLen ? in[ip++] : 'A'; 4802 + int i3 = ip < iLen ? in[ip++] : 'A'; 4803 + if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) 4804 + throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); 4805 + int b0 = map2[i0]; 4806 + int b1 = map2[i1]; 4807 + int b2 = map2[i2]; 4808 + int b3 = map2[i3]; 4809 + if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) 4810 + throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); 4811 + int o0 = ( b0 <<2) | (b1>>>4); 4812 + int o1 = ((b1 & 0xf)<<4) | (b2>>>2); 4813 + int o2 = ((b2 & 3)<<6) | b3; 4814 + out[op++] = (byte)o0; 4815 + if (op<oLen) out[op++] = (byte)o1; 4816 + if (op<oLen) out[op++] = (byte)o2; } 4817 + return out; } 4818 + 4819 + // Dummy constructor. 4820 + private Base64Coder() {} 4821 + 4822 +} 4823 diff -Naur JavaViewer.orig/VncCanvas.java JavaViewer/VncCanvas.java 4824 --- JavaViewer.orig/VncCanvas.java 2005-11-21 18:50:18.000000000 -0500 4825 +++ JavaViewer/VncCanvas.java 2010-11-30 22:57:50.000000000 -0500 4826 @@ -27,6 +27,13 @@ 4827 import java.lang.*; 4828 import java.util.zip.*; 4829 4830 +// begin runge/x11vnc 4831 +import java.util.Collections; 4832 +// end runge/x11vnc 4833 + 4834 +// begin runge/x11vnc 4835 +// all the MouseWheel stuff below. 4836 +// end runge/x11vnc 4837 4838 // 4839 // VncCanvas is a subclass of Canvas which draws a VNC desktop on it. 4840 @@ -34,7 +41,7 @@ 4841 4842 class VncCanvas 4843 extends Canvas 4844 - implements KeyListener, MouseListener, MouseMotionListener { 4845 + implements KeyListener, MouseListener, MouseMotionListener, MouseWheelListener { 4846 4847 VncViewer viewer; 4848 RfbProto rfb; 4849 @@ -85,6 +92,22 @@ 4850 4851 cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF); 4852 4853 +// begin runge/x11vnc 4854 +// kludge to not show any Java cursor in the canvas since we are 4855 +// showing the soft cursor (should be a user setting...) 4856 +Cursor dot = Toolkit.getDefaultToolkit().createCustomCursor( 4857 + Toolkit.getDefaultToolkit().createImage(new byte[4]), new Point(0,0), 4858 + "dot"); 4859 +this.setCursor(dot); 4860 + 4861 +// while we are at it... get rid of the keyboard traversals that 4862 +// make it so we can't type a Tab character: 4863 +this.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 4864 + Collections.EMPTY_SET); 4865 +this.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, 4866 + Collections.EMPTY_SET); 4867 +// end runge/x11vnc 4868 + 4869 colors = new Color[256]; 4870 // sf@2005 - Now Default 4871 for (int i = 0; i < 256; i++) 4872 @@ -186,6 +209,7 @@ 4873 inputEnabled = true; 4874 addMouseListener(this); 4875 addMouseMotionListener(this); 4876 + addMouseWheelListener(this); 4877 if (viewer.showControls) { 4878 viewer.buttonPanel.enableRemoteAccessControls(true); 4879 } 4880 @@ -193,6 +217,7 @@ 4881 inputEnabled = false; 4882 removeMouseListener(this); 4883 removeMouseMotionListener(this); 4884 + removeMouseWheelListener(this); 4885 if (viewer.showControls) { 4886 viewer.buttonPanel.enableRemoteAccessControls(false); 4887 } 4888 @@ -202,6 +227,9 @@ 4889 4890 public void setPixelFormat() throws IOException { 4891 // sf@2005 - Adding more color modes 4892 + if (viewer.graftFtp) { 4893 + return; 4894 + } 4895 if (viewer.options.eightBitColors > 0) 4896 { 4897 viewer.options.oldEightBitColors = viewer.options.eightBitColors; 4898 @@ -237,6 +265,9 @@ 4899 } 4900 else 4901 { 4902 +// begin runge/x11vnc 4903 + viewer.options.oldEightBitColors = viewer.options.eightBitColors; 4904 +// end runge/x11vnc 4905 rfb.writeSetPixelFormat( 4906 32, 4907 24, 4908 @@ -376,12 +407,14 @@ 4909 // Start/stop session recording if necessary. 4910 viewer.checkRecordingStatus(); 4911 4912 - rfb.writeFramebufferUpdateRequest( 4913 - 0, 4914 - 0, 4915 - rfb.framebufferWidth, 4916 - rfb.framebufferHeight, 4917 - false); 4918 + if (!viewer.graftFtp) { 4919 + rfb.writeFramebufferUpdateRequest( 4920 + 0, 4921 + 0, 4922 + rfb.framebufferWidth, 4923 + rfb.framebufferHeight, 4924 + false); 4925 + } 4926 4927 // 4928 // main dispatch loop 4929 @@ -390,6 +423,9 @@ 4930 while (true) { 4931 // Read message type from the server. 4932 int msgType = rfb.readServerMessageType(); 4933 + if (viewer.ftpOnly && msgType != RfbProto.rfbFileTransfer) { 4934 + System.out.println("msgType:" + msgType); 4935 + } 4936 4937 // Process the message depending on its type. 4938 switch (msgType) { 4939 @@ -1332,6 +1368,9 @@ 4940 public void mouseDragged(MouseEvent evt) { 4941 processLocalMouseEvent(evt, true); 4942 } 4943 + public void mouseWheelMoved(MouseWheelEvent evt) { 4944 + processLocalMouseWheelEvent(evt); 4945 + } 4946 4947 public void processLocalKeyEvent(KeyEvent evt) { 4948 if (viewer.rfb != null && rfb.inNormalProtocol) { 4949 @@ -1367,6 +1406,19 @@ 4950 evt.consume(); 4951 } 4952 4953 + public void processLocalMouseWheelEvent(MouseWheelEvent evt) { 4954 + if (viewer.rfb != null && rfb.inNormalProtocol) { 4955 + synchronized(rfb) { 4956 + try { 4957 + rfb.writeWheelEvent(evt); 4958 + } catch (Exception e) { 4959 + e.printStackTrace(); 4960 + } 4961 + rfb.notify(); 4962 + } 4963 + } 4964 + } 4965 + 4966 public void processLocalMouseEvent(MouseEvent evt, boolean moved) { 4967 if (viewer.rfb != null && rfb.inNormalProtocol) { 4968 if (moved) { 4969 @@ -1532,9 +1584,14 @@ 4970 else 4971 { 4972 result = 4973 - 0xFF000000 | (pixBuf[i * 4 + 1] & 0xFF) 4974 - << 16 | (pixBuf[i * 4 + 2] & 0xFF) 4975 - << 8 | (pixBuf[i * 4 + 3] & 0xFF); 4976 +// begin runge/x11vnc 4977 +// 0xFF000000 | (pixBuf[i * 4 + 1] & 0xFF) 4978 +// << 16 | (pixBuf[i * 4 + 2] & 0xFF) 4979 +// << 8 | (pixBuf[i * 4 + 3] & 0xFF); 4980 + 0xFF000000 | (pixBuf[i * 4 + 2] & 0xFF) 4981 + << 16 | (pixBuf[i * 4 + 1] & 0xFF) 4982 + << 8 | (pixBuf[i * 4 + 0] & 0xFF); 4983 +// end runge/x11vnc 4984 } 4985 } else { 4986 result = 0; // Transparent pixel 4987 @@ -1565,9 +1622,14 @@ 4988 else 4989 { 4990 result = 4991 - 0xFF000000 | (pixBuf[i * 4 + 1] & 0xFF) 4992 - << 16 | (pixBuf[i * 4 + 2] & 0xFF) 4993 - << 8 | (pixBuf[i * 4 + 3] & 0xFF); 4994 +// begin runge/x11vnc 4995 +// 0xFF000000 | (pixBuf[i * 4 + 1] & 0xFF) 4996 +// << 16 | (pixBuf[i * 4 + 2] & 0xFF) 4997 +// << 8 | (pixBuf[i * 4 + 3] & 0xFF); 4998 + 0xFF000000 | (pixBuf[i * 4 + 2] & 0xFF) 4999 + << 16 | (pixBuf[i * 4 + 1] & 0xFF) 5000 + << 8 | (pixBuf[i * 4 + 0] & 0xFF); 5001 +// end runge/x11vnc 5002 } 5003 } else { 5004 result = 0; // Transparent pixel 5005 diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java 5006 --- JavaViewer.orig/VncViewer.java 2006-05-24 15:14:40.000000000 -0400 5007 +++ JavaViewer/VncViewer.java 2010-03-27 18:00:28.000000000 -0400 5008 @@ -41,6 +41,7 @@ 5009 import java.io.*; 5010 import java.net.*; 5011 import javax.swing.*; 5012 +import java.util.Date; 5013 5014 public class VncViewer extends java.applet.Applet 5015 implements java.lang.Runnable, WindowListener { 5016 @@ -80,11 +81,11 @@ 5017 GridBagLayout gridbag; 5018 ButtonPanel buttonPanel; 5019 AuthPanel authenticator; 5020 - VncCanvas vc; 5021 + VncCanvas vc = null; 5022 OptionsFrame options; 5023 ClipboardFrame clipboard; 5024 RecordingFrame rec; 5025 - FTPFrame ftp; // KMC: FTP Frame declaration 5026 + FTPFrame ftp = null; // KMC: FTP Frame declaration 5027 5028 // Control session recording. 5029 Object recordingSync; 5030 @@ -96,7 +97,7 @@ 5031 5032 // Variables read from parameter values. 5033 String host; 5034 - int port; 5035 + int port, vncserverport; 5036 String passwordParam; 5037 String encPasswordParam; 5038 boolean showControls; 5039 @@ -115,28 +116,75 @@ 5040 int i; 5041 // mslogon support 2 end 5042 5043 +// begin runge/x11vnc 5044 +boolean disableSSL; 5045 +boolean GET; 5046 +String CONNECT; 5047 +String urlPrefix; 5048 +String httpsPort; 5049 +String oneTimeKey; 5050 +String serverCert; 5051 +String ftpDropDown; 5052 +String proxyHost; 5053 +String proxyPort; 5054 +boolean forceProxy; 5055 +boolean ignoreProxy; 5056 +boolean trustAllVncCerts; 5057 +boolean trustUrlVncCert; 5058 +boolean debugCerts; 5059 +boolean debugKeyboard; 5060 +boolean mapF5_to_atsign; 5061 +boolean forbid_Ctrl_Alt; 5062 + 5063 +boolean ignoreMSLogonCheck; 5064 +boolean delayAuthPanel; 5065 +boolean ftpOnly; 5066 +boolean graftFtp; 5067 +boolean dsmActive; 5068 + 5069 +boolean gotAuth; 5070 +int authGot; 5071 +// end runge/x11vnc 5072 + 5073 + 5074 // 5075 // init() 5076 // 5077 5078 +public void ftp_init() { 5079 + boolean show = false; 5080 + if (ftp != null) { 5081 + show = true; 5082 + } 5083 + ftp = null; 5084 + 5085 + ftp = new FTPFrame(this); // KMC: FTPFrame creation 5086 + 5087 + if (show) { 5088 + ftp.doOpen(); 5089 + rfb.readServerDriveList(); 5090 + } 5091 +} 5092 + 5093 public void init() { 5094 5095 readParameters(); 5096 5097 if (inSeparateFrame) { 5098 - vncFrame = new Frame("Ultr@VNC"); 5099 - if (!inAnApplet) { 5100 - vncFrame.add("Center", this); 5101 - } 5102 - vncContainer = vncFrame; 5103 + vncFrame = new Frame("Ultr@VNC"); 5104 + if (!inAnApplet) { 5105 + vncFrame.add("Center", this); 5106 + } 5107 + vncContainer = vncFrame; 5108 } else { 5109 - vncContainer = this; 5110 + vncContainer = this; 5111 } 5112 5113 recordingSync = new Object(); 5114 5115 options = new OptionsFrame(this); 5116 clipboard = new ClipboardFrame(this); 5117 + 5118 // authenticator = new AuthPanel(false); // mslogon support : go to connectAndAuthenticate() 5119 if (RecordingFrame.checkSecurity()) 5120 rec = new RecordingFrame(this); 5121 @@ -147,10 +195,11 @@ 5122 cursorUpdatesDef = null; 5123 eightBitColorsDef = null; 5124 5125 - if (inSeparateFrame) 5126 + if (inSeparateFrame && vncFrame != null) 5127 vncFrame.addWindowListener(this); 5128 5129 - ftp = new FTPFrame(this); // KMC: FTPFrame creation 5130 + ftp_init(); 5131 + 5132 rfbThread = new Thread(this); 5133 rfbThread.start(); 5134 } 5135 @@ -186,6 +235,30 @@ 5136 gbc.weightx = 1.0; 5137 gbc.weighty = 1.0; 5138 5139 + if (ftpOnly) { 5140 + if (showControls) { 5141 + buttonPanel.enableButtons(); 5142 + } 5143 + ActionListener taskPerformer = new ActionListener() { 5144 + public void actionPerformed(ActionEvent evt) { 5145 + vncFrame.setVisible(false); 5146 + ftp.setSavedLocations(); 5147 + if (ftp.isVisible()) { 5148 + ftp.doClose(); 5149 + } else { 5150 + ftp.doOpen(); 5151 + } 5152 + rfb.readServerDriveList(); 5153 + } 5154 + }; 5155 + Timer t = new Timer(300, taskPerformer); 5156 + t.setRepeats(false); 5157 + t.start(); 5158 + 5159 + vc.processNormalProtocol(); 5160 + return; 5161 + } 5162 + 5163 // Add ScrollPanel to applet mode 5164 5165 // Create a panel which itself is resizeable and can hold 5166 @@ -286,6 +359,24 @@ 5167 5168 void connectAndAuthenticate() throws Exception { 5169 5170 + if (graftFtp) { 5171 + rfb = new RfbProto(host, port, this); 5172 + rfb.desktopName = "ftponly"; 5173 + rfb.framebufferWidth = 12; 5174 + rfb.framebufferHeight = 12; 5175 + rfb.bitsPerPixel = 32; 5176 + rfb.depth = 24; 5177 + rfb.trueColour = true; 5178 + rfb.redMax = 255; 5179 + rfb.greenMax = 255; 5180 + rfb.blueMax = 255; 5181 + rfb.redShift = 16; 5182 + rfb.greenShift = 8; 5183 + rfb.blueShift = 0; 5184 + rfb.inNormalProtocol = true; 5185 + return; 5186 + } 5187 + 5188 // If "ENCPASSWORD" parameter is set, decrypt the password into 5189 // the passwordParam string. 5190 5191 @@ -336,7 +427,22 @@ 5192 // 5193 5194 5195 - prologueDetectAuthProtocol() ; 5196 +// begin runge/x11vnc 5197 + gotAuth = false; 5198 + if (delayAuthPanel) { 5199 + if (tryAuthenticate(null, null)) { 5200 + if (inSeparateFrame) { 5201 + vncFrame.pack(); 5202 + vncFrame.show(); 5203 + } 5204 + return; 5205 + } 5206 + } 5207 +// prologueDetectAuthProtocol() ; 5208 + if (ignoreMSLogonCheck == false) { 5209 + prologueDetectAuthProtocol() ; 5210 + } 5211 +// end runge/x11vnc 5212 5213 authenticator = new AuthPanel(mslogon); 5214 5215 @@ -371,6 +477,7 @@ 5216 //mslogon support end 5217 } 5218 5219 + int tries = 0; 5220 while (true) { 5221 // Wait for user entering a password, or a username and a password 5222 synchronized(authenticator) { 5223 @@ -390,6 +497,13 @@ 5224 break; 5225 //mslogon support end 5226 5227 +// begin runge/x11vnc 5228 + gotAuth = false; 5229 + if (++tries > 2) { 5230 + throw new Exception("Incorrect password entered " + tries + " times."); 5231 + } 5232 +// end runge/x11vnc 5233 + 5234 // Retry on authentication failure. 5235 authenticator.retry(); 5236 } 5237 @@ -405,9 +519,11 @@ 5238 5239 void prologueDetectAuthProtocol() throws Exception { 5240 5241 - rfb = new RfbProto(host, port, this); 5242 + if (!gotAuth) { 5243 + rfb = new RfbProto(host, port, this); 5244 5245 - rfb.readVersionMsg(); 5246 + rfb.readVersionMsg(); 5247 + } 5248 5249 System.out.println("RFB server supports protocol version " + 5250 rfb.serverMajor + "." + rfb.serverMinor); 5251 @@ -431,16 +547,36 @@ 5252 5253 boolean tryAuthenticate(String us, String pw) throws Exception { 5254 5255 - rfb = new RfbProto(host, port, this); 5256 + int authScheme; 5257 5258 - rfb.readVersionMsg(); 5259 + if (!gotAuth) { 5260 + rfb = new RfbProto(host, port, this); 5261 5262 - System.out.println("RFB server supports protocol version " + 5263 - rfb.serverMajor + "." + rfb.serverMinor); 5264 + rfb.readVersionMsg(); 5265 5266 - rfb.writeVersionMsg(); 5267 + System.out.println("RFB server supports protocol version: " + 5268 + rfb.serverMajor + "." + rfb.serverMinor); 5269 5270 - int authScheme = rfb.readAuthScheme(); 5271 + rfb.writeVersionMsg(); 5272 + 5273 + authScheme = rfb.readAuthScheme(); 5274 + 5275 + gotAuth = true; 5276 + authGot = authScheme; 5277 + } else { 5278 + authScheme = authGot; 5279 + } 5280 +// begin runge/x11vnc 5281 + if (delayAuthPanel && pw == null) { 5282 + if (authScheme == RfbProto.NoAuth) { 5283 + System.out.println("No authentication needed"); 5284 + return true; 5285 + } else { 5286 + return false; 5287 + } 5288 + } 5289 +System.out.println("as: " + authScheme); 5290 +// end runge/x11vnc 5291 5292 switch (authScheme) { 5293 5294 @@ -629,6 +765,10 @@ 5295 5296 void doProtocolInitialisation() throws IOException { 5297 5298 + if (graftFtp) { 5299 + return; 5300 + } 5301 + 5302 rfb.writeClientInit(); 5303 5304 rfb.readServerInit(); 5305 @@ -774,9 +914,28 @@ 5306 fatalError("HOST parameter not specified"); 5307 } 5308 } 5309 + Date d = new Date(); 5310 + System.out.println("-\nSSL VNC Java Applet starting. " + d); 5311 5312 - String str = readParameter("PORT", true); 5313 - port = Integer.parseInt(str); 5314 + port = 0; 5315 + String str = readParameter("PORT", false); 5316 + if (str != null) { 5317 + port = Integer.parseInt(str); 5318 + } 5319 + // When there is a proxy VNCSERVERPORT may be inaccessible (inside firewall). 5320 + vncserverport = 0; 5321 + str = readParameter("VNCSERVERPORT", false); 5322 + if (str != null) { 5323 + vncserverport = Integer.parseInt(str); 5324 + } 5325 + if (port == 0 && vncserverport == 0) { 5326 + fatalError("Neither PORT nor VNCSERVERPORT parameters specified"); 5327 + } 5328 + if (port == 0) { 5329 + // Nevertheless, fall back to vncserverport if we have to. 5330 + System.out.println("using vncserverport: '" + vncserverport + "' for PORT."); 5331 + port = vncserverport; 5332 + } 5333 5334 if (inAnApplet) { 5335 str = readParameter("Open New Window", false); 5336 @@ -804,6 +963,158 @@ 5337 deferScreenUpdates = readIntParameter("Defer screen updates", 20); 5338 deferCursorUpdates = readIntParameter("Defer cursor updates", 10); 5339 deferUpdateRequests = readIntParameter("Defer update requests", 50); 5340 + 5341 +// begin runge/x11vnc 5342 + // SSL 5343 + disableSSL = false; 5344 + str = readParameter("DisableSSL", false); 5345 + if (str != null && str.equalsIgnoreCase("Yes")) 5346 + disableSSL = true; 5347 + 5348 + httpsPort = readParameter("httpsPort", false); 5349 + 5350 + // Extra GET, CONNECT string: 5351 + CONNECT = readParameter("CONNECT", false); 5352 + if (CONNECT != null) { 5353 + CONNECT = CONNECT.replaceAll(" ", ":"); 5354 + } 5355 + 5356 + GET = false; 5357 + str = readParameter("GET", false); 5358 + if (str != null && str.equalsIgnoreCase("Yes")) { 5359 + GET = true; 5360 + } 5361 + if (str != null && str.equalsIgnoreCase("1")) { 5362 + GET = true; 5363 + } 5364 + 5365 + urlPrefix = readParameter("urlPrefix", false); 5366 + if (urlPrefix != null) { 5367 + urlPrefix = urlPrefix.replaceAll("%2F", "/"); 5368 + urlPrefix = urlPrefix.replaceAll("%2f", "/"); 5369 + urlPrefix = urlPrefix.replaceAll("_2F_", "/"); 5370 + if (urlPrefix.indexOf("/") != 0) { 5371 + urlPrefix = "/" + urlPrefix; 5372 + } 5373 + } else { 5374 + urlPrefix = ""; 5375 + } 5376 + System.out.println("urlPrefix: '" + urlPrefix + "'"); 5377 + 5378 + ftpDropDown = readParameter("ftpDropDown", false); 5379 + if (ftpDropDown != null) { 5380 + ftpDropDown = ftpDropDown.replaceAll("%2F", "/"); 5381 + ftpDropDown = ftpDropDown.replaceAll("%2f", "/"); 5382 + ftpDropDown = ftpDropDown.replaceAll("_2F_", "/"); 5383 + ftpDropDown = ftpDropDown.replaceAll("%20", " "); 5384 + System.out.println("ftpDropDown: '" + ftpDropDown + "'"); 5385 + } 5386 + 5387 + 5388 + oneTimeKey = readParameter("oneTimeKey", false); 5389 + if (oneTimeKey != null) { 5390 + System.out.println("oneTimeKey is set."); 5391 + } 5392 + 5393 + serverCert = readParameter("serverCert", false); 5394 + if (serverCert != null) { 5395 + System.out.println("serverCert is set."); 5396 + } 5397 + 5398 + forceProxy = false; 5399 + proxyHost = null; 5400 + proxyPort = null; 5401 + str = readParameter("forceProxy", false); 5402 + if (str != null) { 5403 + if (str.equalsIgnoreCase("Yes")) { 5404 + forceProxy = true; 5405 + } else if (str.equalsIgnoreCase("No")) { 5406 + forceProxy = false; 5407 + } else { 5408 + forceProxy = true; 5409 + String[] pieces = str.split(" "); 5410 + proxyHost = new String(pieces[0]); 5411 + if (pieces.length >= 2) { 5412 + proxyPort = new String(pieces[1]); 5413 + } else { 5414 + proxyPort = new String("8080"); 5415 + } 5416 + } 5417 + } 5418 + str = readParameter("proxyHost", false); 5419 + if (str != null) { 5420 + proxyHost = new String(str); 5421 + } 5422 + str = readParameter("proxyPort", false); 5423 + if (str != null) { 5424 + proxyPort = new String(str); 5425 + } 5426 + if (proxyHost != null && proxyPort == null) { 5427 + proxyPort = new String("8080"); 5428 + } 5429 + 5430 + ignoreProxy = false; 5431 + str = readParameter("ignoreProxy", false); 5432 + if (str != null && str.equalsIgnoreCase("Yes")) { 5433 + ignoreProxy = true; 5434 + } 5435 + 5436 + trustAllVncCerts = false; 5437 + str = readParameter("trustAllVncCerts", false); 5438 + if (str != null && str.equalsIgnoreCase("Yes")) { 5439 + trustAllVncCerts = true; 5440 + } 5441 + trustUrlVncCert = false; 5442 + str = readParameter("trustUrlVncCert", false); 5443 + if (str != null && str.equalsIgnoreCase("Yes")) { 5444 + trustUrlVncCert = true; 5445 + } 5446 + debugCerts = false; 5447 + str = readParameter("debugCerts", false); 5448 + if (str != null && str.equalsIgnoreCase("Yes")) { 5449 + debugCerts = true; 5450 + } 5451 + debugKeyboard = false; 5452 + str = readParameter("debugKeyboard", false); 5453 + if (str != null && str.equalsIgnoreCase("Yes")) { 5454 + debugKeyboard = true; 5455 + } 5456 + mapF5_to_atsign = false; 5457 + str = readParameter("mapF5_to_atsign", false); 5458 + if (str != null && str.equalsIgnoreCase("Yes")) { 5459 + mapF5_to_atsign = true; 5460 + } 5461 + forbid_Ctrl_Alt = false; 5462 + str = readParameter("forbid_Ctrl_Alt", false); 5463 + if (str != null && str.equalsIgnoreCase("Yes")) { 5464 + forbid_Ctrl_Alt = true; 5465 + } 5466 + ignoreMSLogonCheck = false; 5467 + str = readParameter("ignoreMSLogonCheck", false); 5468 + if (str != null && str.equalsIgnoreCase("Yes")) { 5469 + ignoreMSLogonCheck = true; 5470 + } 5471 + ftpOnly = false; 5472 + str = readParameter("ftpOnly", false); 5473 + if (str != null && str.equalsIgnoreCase("Yes")) { 5474 + ftpOnly = true; 5475 + } 5476 + graftFtp = false; 5477 + str = readParameter("graftFtp", false); 5478 + if (str != null && str.equalsIgnoreCase("Yes")) { 5479 + graftFtp = true; 5480 + } 5481 + dsmActive = false; 5482 + str = readParameter("dsmActive", false); 5483 + if (str != null && str.equalsIgnoreCase("Yes")) { 5484 + dsmActive = true; 5485 + } 5486 + delayAuthPanel = false; 5487 + str = readParameter("delayAuthPanel", false); 5488 + if (str != null && str.equalsIgnoreCase("Yes")) { 5489 + delayAuthPanel = true; 5490 + } 5491 +// end runge/x11vnc 5492 } 5493 5494 public String readParameter(String name, boolean required) { 5495