123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448 |
- /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
- * Copyright (C) 2011-2013 D. R. Commander. All Rights Reserved.
- * Copyright (C) 2011-2019 Brian P. Hinz
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
- //
- // VncViewer - the VNC viewer. It behaves as much as possible like the native
- // viewers.
- //
- // Unfortunately, because of the way Java classes are loaded on demand, only
- // configuration parameters defined in this file can be set from the command
- // line.
-
- package com.tigervnc.vncviewer;
-
- import java.awt.*;
- import java.awt.event.*;
- import java.awt.Color;
- import java.awt.Graphics;
- import java.awt.Image;
- import java.io.BufferedReader;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.io.IOException;
- import java.io.File;
- import java.lang.Character;
- import java.lang.reflect.*;
- import java.net.URL;
- import java.nio.CharBuffer;
- import java.util.*;
- import java.util.jar.Attributes;
- import java.util.jar.Manifest;
- import javax.swing.*;
- import javax.swing.border.*;
- import javax.swing.plaf.FontUIResource;
- import javax.swing.SwingUtilities;
- import javax.swing.UIManager.*;
-
- import com.tigervnc.rdr.*;
- import com.tigervnc.rfb.*;
- import com.tigervnc.network.*;
-
- import static com.tigervnc.vncviewer.Parameters.*;
-
- public class VncViewer implements Runnable {
-
- public static final String aboutText =
- new String("TigerVNC Java Viewer v%s (%s)%n"+
- "Built on %s at %s%n"+
- "Copyright (C) 1999-2021 TigerVNC Team and many others (see README.rst)%n"+
- "See https://www.tigervnc.org for information on TigerVNC.");
-
- public static String version = null;
- public static String build = null;
- public static String buildDate = null;
- public static String buildTime = null;
- static ImageIcon frameIconSrc =
- new ImageIcon(VncViewer.class.getResource("tigervnc.ico"));
- public static final Image frameIcon = frameIconSrc.getImage();
- public static final ImageIcon logoIcon =
- new ImageIcon(VncViewer.class.getResource("tigervnc.png"));
- public static final Image logoImage = logoIcon.getImage();
- public static final InputStream timestamp =
- VncViewer.class.getResourceAsStream("timestamp");
- public static final String os =
- System.getProperty("os.name").toLowerCase(Locale.ENGLISH);
-
- private String defaultServerName;
- int VNCSERVERNAMELEN = 256;
- CharBuffer vncServerName = CharBuffer.allocate(VNCSERVERNAMELEN);
-
- public static void setLookAndFeel() {
- try {
- if (os.startsWith("mac os x")) {
- Class appClass = Class.forName("com.apple.eawt.Application");
- Method getApplication =
- appClass.getMethod("getApplication", (Class[])null);
- Object app = getApplication.invoke(appClass);
- Class paramTypes[] = new Class[1];
- paramTypes[0] = Image.class;
- Method setDockIconImage =
- appClass.getMethod("setDockIconImage", paramTypes);
- setDockIconImage.invoke(app, VncViewer.logoImage);
- }
- // Use Nimbus LookAndFeel if it's available, otherwise fallback
- // to the native laf, or Metal if no native laf is available.
- String laf = System.getProperty("swing.defaultlaf");
- if (laf == null) {
- LookAndFeelInfo[] installedLafs = UIManager.getInstalledLookAndFeels();
- for (int i = 0; i < installedLafs.length; i++) {
- if (installedLafs[i].getName().equals("Nimbus"))
- laf = installedLafs[i].getClassName();
- }
- if (laf == null)
- UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
- }
- UIManager.setLookAndFeel(laf);
- if (UIManager.getLookAndFeel().getName().equals("Metal")) {
- UIManager.put("swing.boldMetal", Boolean.FALSE);
- Enumeration<Object> keys = UIManager.getDefaults().keys();
- while (keys.hasMoreElements()) {
- Object key = keys.nextElement();
- Object value = UIManager.get(key);
- if (value instanceof FontUIResource) {
- String name = ((FontUIResource)value).getName();
- int style = ((FontUIResource)value).getStyle();
- int size = ((FontUIResource)value).getSize()-1;
- FontUIResource f = new FontUIResource(name, style, size);
- UIManager.put(key, f);
- }
- }
- } else if (UIManager.getLookAndFeel().getName().equals("Nimbus")) {
- Font f = UIManager.getFont("TitledBorder.font");
- String name = f.getName();
- int style = f.getStyle();
- int size = f.getSize()-2;
- FontUIResource r = new FontUIResource(name, style, size);
- UIManager.put("TitledBorder.font", r);
- }
- } catch (java.lang.Exception e) {
- vlog.info(e.toString());
- }
- }
-
- public static void main(String[] argv) {
- setLookAndFeel();
- VncViewer viewer = new VncViewer(argv);
- viewer.start();
- }
-
- public VncViewer(String[] argv) {
-
- SecurityClient.setDefaults();
-
- // Write about text to console, still using normal locale codeset
- getTimestamp();
- System.err.format("%n");
- System.err.format(aboutText, version, build, buildDate, buildTime);
- System.err.format("%n");
-
- Configuration.enableViewerParams();
-
- /* Load the default parameter settings */
- try {
- defaultServerName = loadViewerParameters(null);
- } catch (com.tigervnc.rfb.Exception e) {
- defaultServerName = "";
- vlog.info(e.getMessage());
- }
-
- // Override defaults with command-line options
- int i = 0;
- for (; i < argv.length; i++) {
- if (argv[i].length() == 0)
- continue;
-
- if (argv[i].equalsIgnoreCase("-config")) {
- if (++i >= argv.length)
- usage();
- defaultServerName = loadViewerParameters(argv[i]);
- continue;
- }
-
- if (argv[i].equalsIgnoreCase("-log")) {
- if (++i >= argv.length) usage();
- System.err.println("Log setting: "+argv[i]);
- LogWriter.setLogParams(argv[i]);
- continue;
- }
-
- if (argv[i].charAt(0) == '-') {
- if (i+1 < argv.length) {
- if (Configuration.setParam(argv[i].substring(1), argv[i+1])) {
- i++;
- continue;
- }
- }
- if (Configuration.setParam(argv[i]))
- continue;
-
- usage();
- }
-
- vncServerName.put(argv[i].toCharArray()).flip();
- }
-
- // Check if the server name in reality is a configuration file
- potentiallyLoadConfigurationFile(vncServerName);
- }
-
- public static void usage() {
- String usage = ("\nusage: vncviewer [options/parameters] "+
- "[host:displayNum]\n"+
- " vncviewer [options/parameters] -listen [port] "+
- "[options/parameters]\n"+
- " vncviewer [options/parameters] [.tigervnc file]\n"+
- "\n"+
- "Options:\n"+
- " -log <level> configure logging level\n"+
- "\n"+
- "Parameters can be turned on with -<param> or off with "+
- "-<param>=0\n"+
- "Parameters which take a value can be specified as "+
- "-<param> <value>\n"+
- "Other valid forms are <param>=<value> -<param>=<value> "+
- "--<param>=<value>\n"+
- "Parameter names are case-insensitive. The parameters "+
- "are:\n"+
- "\n");
- System.err.print(usage);
-
- Configuration.listParams(79, 14);
- String propertiesString = ("\n"+
- "System Properties (adapted from the TurboVNC vncviewer man page)\n"+
- " When started with the -via option, vncviewer reads the VNC_VIA_CMD\n"+
- " System property, expands patterns beginning with the \"%\" character,\n"+
- " and uses the resulting command line to establish the secure tunnel\n"+
- " to the VNC gateway. If VNC_VIA_CMD is not set, this command line\n"+
- " defaults to \"/usr/bin/ssh -f -L %L:%H:%R %G sleep 20\".\n"+
- "\n"+
- " The following patterns are recognized in the VNC_VIA_CMD property\n"+
- " (note that all of the patterns %G, %H, %L and %R must be present in \n"+
- " the command template):\n"+
- "\n"+
- " \t%% A literal \"%\";\n"+
- "\n"+
- " \t%G gateway machine name;\n"+
- "\n"+
- " \t%H remote VNC machine name, (as known to the gateway);\n"+
- "\n"+
- " \t%L local TCP port number;\n"+
- "\n"+
- " \t%R remote TCP port number.\n"+
- "\n"+
- " When started with the -tunnel option, vncviewer reads the VNC_TUNNEL_CMD\n"+
- " System property, expands patterns beginning with the \"%\" character, and\n"+
- " uses the resulting command line to establish the secure tunnel to the\n"+
- " VNC server. If VNC_TUNNEL_CMD is not set, this command line defaults\n"+
- " to \"/usr/bin/ssh -f -L %L:localhost:%R %H sleep 20\".\n"+
- "\n"+
- " The following patterns are recognized in the VNC_TUNNEL_CMD property\n"+
- " (note that all of the patterns %H, %L and %R must be present in \n"+
- " the command template):\n"+
- "\n"+
- " \t%% A literal \"%\";\n"+
- "\n"+
- " \t%H remote VNC machine name (as known to the client);\n"+
- "\n"+
- " \t%L local TCP port number;\n"+
- "\n"+
- " \t%R remote TCP port number.\n"+
- "\n");
- System.err.print(propertiesString);
- // Technically, we shouldn't use System.exit here but if there is a parameter
- // error then the problem is in the index/html file anyway.
- System.exit(1);
- }
-
- public static void potentiallyLoadConfigurationFile(CharBuffer vncServerName) {
- String serverName = vncServerName.toString();
- boolean hasPathSeparator = (serverName.indexOf('/') != -1 ||
- (serverName.indexOf('\\')) != -1);
-
- if (hasPathSeparator) {
- try {
- serverName = loadViewerParameters(vncServerName.toString());
- if (serverName == "") {
- vlog.info("Unable to load the server name from given file");
- System.exit(1);
- }
- vncServerName.clear();
- vncServerName.put(serverName).flip();
- } catch (com.tigervnc.rfb.Exception e) {
- vlog.info(e.getMessage());
- System.exit(1);
- }
- }
- }
-
- public static void newViewer() {
- String cmd = "java -jar ";
- try {
- URL url =
- VncViewer.class.getProtectionDomain().getCodeSource().getLocation();
- File f = new File(url.toURI());
- if (!f.exists() || !f.canRead()) {
- String msg = new String("The jar file "+f.getAbsolutePath()+
- " does not exist or cannot be read.");
- JOptionPane.showMessageDialog(null, msg, "ERROR",
- JOptionPane.ERROR_MESSAGE);
- return;
- }
- cmd = cmd.concat(f.getAbsolutePath());
- Thread t = new Thread(new ExtProcess(cmd, vlog));
- t.start();
- } catch (java.net.URISyntaxException e) {
- vlog.info(e.getMessage());
- } catch (java.lang.Exception e) {
- vlog.info(e.getMessage());
- }
- }
-
- private static void getTimestamp() {
- if (version == null || build == null) {
- try {
- Manifest manifest = new Manifest(timestamp);
- Attributes attributes = manifest.getMainAttributes();
- version = attributes.getValue("Version");
- build = attributes.getValue("Build");
- buildDate = attributes.getValue("Package-Date");
- buildTime = attributes.getValue("Package-Time");
- } catch (java.lang.Exception e) { }
- }
- }
-
- public static void about_vncviewer(Container parent) {
- String pkgDate = "";
- String pkgTime = "";
- try {
- Manifest manifest = new Manifest(VncViewer.timestamp);
- Attributes attributes = manifest.getMainAttributes();
- pkgDate = attributes.getValue("Package-Date");
- pkgTime = attributes.getValue("Package-Time");
- } catch (java.lang.Exception e) { }
-
- Window fullScreenWindow = DesktopWindow.getFullScreenWindow();
- if (fullScreenWindow != null)
- DesktopWindow.setFullScreenWindow(null);
- String msg =
- String.format(VncViewer.aboutText, VncViewer.version, VncViewer.build,
- VncViewer.buildDate, VncViewer.buildTime);
- Object[] options = {"Close \u21B5"};
- JOptionPane op =
- new JOptionPane(msg, JOptionPane.INFORMATION_MESSAGE,
- JOptionPane.DEFAULT_OPTION, VncViewer.logoIcon, options);
- JDialog dlg = op.createDialog(parent, "About TigerVNC Viewer for Java");
- dlg.setIconImage(VncViewer.frameIcon);
- dlg.setAlwaysOnTop(true);
- dlg.setVisible(true);
- if (fullScreenWindow != null)
- DesktopWindow.setFullScreenWindow(fullScreenWindow);
- }
-
- public void start() {
- (new Thread(this, "VncViewer Thread")).start();
- }
-
- public void exit(int n) {
- System.exit(n);
- }
-
- void reportException(java.lang.Exception e) {
- String title, msg = e.getMessage();
- int msgType = JOptionPane.ERROR_MESSAGE;
- title = "TigerVNC Viewer : Error";
- e.printStackTrace();
- JOptionPane.showMessageDialog(null, msg, title, msgType);
- }
-
- public void run() {
- cc = null;
- UserDialog dlg = new UserDialog();
- CSecurity.upg = dlg;
- CSecurityTLS.msg = dlg;
- Socket sock = null;
-
- /* Specifying -via and -listen together is nonsense */
- if (listenMode.getValue() && !via.getValueStr().isEmpty()) {
- vlog.error("Parameters -listen and -via are incompatible");
- String msg =
- new String("Parameters -listen and -via are incompatible");
- JOptionPane.showMessageDialog(null, msg, "ERROR",
- JOptionPane.ERROR_MESSAGE);
- exit(1);
- }
-
- if (listenMode.getValue()) {
- int port = 5500;
-
- if (vncServerName.charAt(0) != 0 &&
- Character.isDigit(vncServerName.charAt(0)))
- port = Integer.parseInt(vncServerName.toString());
-
- TcpListener listener = null;
- try {
- listener = new TcpListener(null, port);
- } catch (java.lang.Exception e) {
- reportException(e);
- exit(1);
- }
-
- vlog.info("Listening on port "+port);
-
- while (sock == null)
- sock = listener.accept();
- } else {
- if (vncServerName.charAt(0) == 0) {
- try {
- SwingUtilities.invokeAndWait(
- new ServerDialog(defaultServerName, vncServerName));
- } catch (InvocationTargetException e) {
- reportException(e);
- } catch (InterruptedException e) {
- reportException(e);
- }
- if (vncServerName.charAt(0) == 0)
- exit(0);
- }
- }
-
- try {
- cc = new CConn(vncServerName.toString(), sock);
- while (!cc.shuttingDown)
- cc.processMsg();
- exit(0);
- } catch (java.lang.Exception e) {
- if (cc == null || !cc.shuttingDown) {
- reportException(e);
- if (cc != null)
- cc.close();
- }
- exit(1);
- }
- }
-
- public static CConn cc;
- public static StringParameter config
- = new StringParameter("Config",
- "Specifies a configuration file to load.", null);
-
- static LogWriter vlog = new LogWriter("VncViewer");
- }
|