diff options
author | DRC <dcommander@users.sourceforge.net> | 2011-10-07 05:38:00 +0000 |
---|---|---|
committer | DRC <dcommander@users.sourceforge.net> | 2011-10-07 05:38:00 +0000 |
commit | c19ab9ec7f3ac4823802388ac953e9494c613575 (patch) | |
tree | 63513ffd7ce0b3ab3de2d9b619cc4e5b892eea31 /java/com/tigervnc/rfb | |
parent | bba54b0b14fded1d457f426cdc8843a34d6c9dc5 (diff) | |
download | tigervnc-c19ab9ec7f3ac4823802388ac953e9494c613575.tar.gz tigervnc-c19ab9ec7f3ac4823802388ac953e9494c613575.zip |
Move Java source up one level and allow Java viewer to be built as a standalone project (per community request)
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4715 3789f03b-4d11-0410-bbf8-ca57d06f2519
Diffstat (limited to 'java/com/tigervnc/rfb')
54 files changed, 5984 insertions, 0 deletions
diff --git a/java/com/tigervnc/rfb/AliasParameter.java b/java/com/tigervnc/rfb/AliasParameter.java new file mode 100644 index 00000000..2570b877 --- /dev/null +++ b/java/com/tigervnc/rfb/AliasParameter.java @@ -0,0 +1,35 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +public class AliasParameter extends VoidParameter { + public AliasParameter(String name_, String desc_, VoidParameter v) { + super(name_, desc_); + param = v; + } + + public boolean setParam(String v) { return param.setParam(v); } + public boolean setParam() { return param.setParam(); } + + public String getDefaultStr() { return param.getDefaultStr(); } + public String getValueStr() { return param.getValueStr(); } + public boolean isBool() { return param.isBool(); } + + protected VoidParameter param; +} diff --git a/java/com/tigervnc/rfb/AuthFailureException.java b/java/com/tigervnc/rfb/AuthFailureException.java new file mode 100644 index 00000000..35fabef0 --- /dev/null +++ b/java/com/tigervnc/rfb/AuthFailureException.java @@ -0,0 +1,23 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +public class AuthFailureException extends Exception { + public AuthFailureException(String s) { super(s); } +} diff --git a/java/com/tigervnc/rfb/BoolParameter.java b/java/com/tigervnc/rfb/BoolParameter.java new file mode 100644 index 00000000..06c6ed79 --- /dev/null +++ b/java/com/tigervnc/rfb/BoolParameter.java @@ -0,0 +1,51 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +public class BoolParameter extends VoidParameter { + public BoolParameter(String name_, String desc_, boolean v) { + super(name_, desc_); + value = v; + defValue = v; + } + + public boolean setParam(String v) { + if (v.equals("1") || v.equalsIgnoreCase("on") || + v.equalsIgnoreCase("true") || v.equalsIgnoreCase("yes")) + value = true; + else if (v.equals("0") || v.equalsIgnoreCase("off") || + v.equalsIgnoreCase("false") || v.equalsIgnoreCase("no")) + value = false; + else + return false; + return true; + } + + public boolean setParam() { setParam(true); return true; } + public void setParam(boolean b) { value = b; } + + public String getDefaultStr() { return defValue ? "1" : "0"; } + public String getValueStr() { return value ? "1" : "0"; } + public boolean isBool() { return true; } + + final public boolean getValue() { return value; } + + protected boolean value; + protected boolean defValue; +} diff --git a/java/com/tigervnc/rfb/CConnection.java b/java/com/tigervnc/rfb/CConnection.java new file mode 100644 index 00000000..15e19896 --- /dev/null +++ b/java/com/tigervnc/rfb/CConnection.java @@ -0,0 +1,356 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +import java.util.*; + +import com.tigervnc.rdr.*; + +abstract public class CConnection extends CMsgHandler { + + public CConnection() { + security = new SecurityClient(); + } + + // setStreams() sets the streams to be used for the connection. These must + // be set before initialiseProtocol() and processMsg() are called. The + // CSecurity object may call setStreams() again to provide alternative + // streams over which the RFB protocol is sent (i.e. encrypting/decrypting + // streams). Ownership of the streams remains with the caller + // (i.e. SConnection will not delete them). + public void setStreams(InStream is_, OutStream os_) { + is = is_; + os = os_; + } + + // initialiseProtocol() should be called once the streams and security + // types are set. Subsequently, processMsg() should be called whenever + // there is data to read on the InStream. + public void initialiseProtocol() { + state_ = RFBSTATE_PROTOCOL_VERSION; + } + + // processMsg() should be called whenever there is data to read on the + // InStream. You must have called initialiseProtocol() first. + public void processMsg() { + switch (state_) { + + case RFBSTATE_PROTOCOL_VERSION: processVersionMsg(); break; + case RFBSTATE_SECURITY_TYPES: processSecurityTypesMsg(); break; + case RFBSTATE_SECURITY: processSecurityMsg(); break; + case RFBSTATE_SECURITY_RESULT: processSecurityResultMsg(); break; + case RFBSTATE_INITIALISATION: processInitMsg(); break; + case RFBSTATE_NORMAL: reader_.readMsg(); break; + case RFBSTATE_UNINITIALISED: + throw new Exception("CConnection.processMsg: not initialised yet?"); + default: + throw new Exception("CConnection.processMsg: invalid state"); + } + } + + private void processVersionMsg() { + vlog.debug("reading protocol version"); + Boolean done = new Boolean(true); + if (!cp.readVersion(is, done)) { + state_ = RFBSTATE_INVALID; + throw new Exception("reading version failed: not an RFB server?"); + } + if (!done.booleanValue()) return; + + vlog.info("Server supports RFB protocol version "+cp.majorVersion+"."+ + cp.minorVersion); + + // The only official RFB protocol versions are currently 3.3, 3.7 and 3.8 + if (cp.beforeVersion(3,3)) { + String msg = ("Server gave unsupported RFB protocol version "+ + cp.majorVersion+"."+cp.minorVersion); + vlog.error(msg); + state_ = RFBSTATE_INVALID; + throw new Exception(msg); + } else if (useProtocol3_3 || cp.beforeVersion(3,7)) { + cp.setVersion(3,3); + } else if (cp.afterVersion(3,8)) { + cp.setVersion(3,8); + } + + cp.writeVersion(os); + state_ = RFBSTATE_SECURITY_TYPES; + + vlog.info("Using RFB protocol version "+ + cp.majorVersion+"."+cp.minorVersion); + } + + private void processSecurityTypesMsg() { + vlog.info("processing security types message"); + + int secType = Security.secTypeInvalid; + + List<Integer> secTypes = new ArrayList<Integer>(); + secTypes = security.GetEnabledSecTypes(); + //for (Iterator i = secTypes.iterator(); i.hasNext(); ) + // vlog.info(((Integer)i.next()).toString()); + + if (cp.isVersion(3,3)) { + + // legacy 3.3 server may only offer "vnc authentication" or "none" + + secType = is.readU32(); + if (secType == Security.secTypeInvalid) { + throwConnFailedException(); + + } else if (secType == Security.secTypeNone || secType == Security.secTypeVncAuth) { + Iterator i; + for (i = secTypes.iterator(); i.hasNext(); ) { + int refType = (Integer)i.next(); + if (refType == secType) { + secType = refType; + break; + } + if (!i.hasNext()) + secType = Security.secTypeInvalid; + } + + } else { + vlog.error("Unknown 3.3 security type "+secType); + throw new Exception("Unknown 3.3 security type"); + } + + } else { + + // 3.7 server will offer us a list + + int nServerSecTypes = is.readU8(); + if (nServerSecTypes == 0) + throwConnFailedException(); + + for (int i = 0; i < nServerSecTypes; i++) { + int serverSecType = is.readU8(); + vlog.info("Server offers security type "+ + Security.secTypeName(serverSecType)+"("+serverSecType+")"); + + /* + * Use the first type sent by server which matches client's type. + * It means server's order specifies priority. + */ + if (secType == Security.secTypeInvalid) { + for (Iterator j = secTypes.iterator(); j.hasNext(); ) { + int refType = (Integer)j.next(); + if (refType == serverSecType) { + secType = refType; + break; + } + } + } + } + + // Inform the server of our decision + if (secType != Security.secTypeInvalid) { + os.writeU8(secType); + os.flush(); + vlog.info("Choosing security type "+Security.secTypeName(secType)+ + "("+secType+")"); + } + } + + if (secType == Security.secTypeInvalid) { + state_ = RFBSTATE_INVALID; + vlog.error("No matching security types"); + throw new Exception("No matching security types"); + } + + state_ = RFBSTATE_SECURITY; + csecurity = security.GetCSecurity(secType); + processSecurityMsg(); + } + + private void processSecurityMsg() { + vlog.debug("processing security message"); + if (csecurity.processMsg(this)) { + state_ = RFBSTATE_SECURITY_RESULT; + processSecurityResultMsg(); + } + } + + private void processSecurityResultMsg() { + vlog.debug("processing security result message"); + int result; + if (cp.beforeVersion(3,8) && csecurity.getType() == Security.secTypeNone) { + result = Security.secResultOK; + } else { + if (!is.checkNoWait(1)) return; + result = is.readU32(); + } + switch (result) { + case Security.secResultOK: + securityCompleted(); + return; + case Security.secResultFailed: + vlog.debug("auth failed"); + break; + case Security.secResultTooMany: + vlog.debug("auth failed - too many tries"); + break; + default: + throw new Exception("Unknown security result from server"); + } + String reason; + if (cp.beforeVersion(3,8)) + reason = "Authentication failure"; + else + reason = is.readString(); + state_ = RFBSTATE_INVALID; + throw new AuthFailureException(reason); + } + + private void processInitMsg() { + vlog.debug("reading server initialisation"); + reader_.readServerInit(); + } + + private void throwConnFailedException() { + state_ = RFBSTATE_INVALID; + String reason; + reason = is.readString(); + throw new ConnFailedException(reason); + } + + private void securityCompleted() { + state_ = RFBSTATE_INITIALISATION; + reader_ = new CMsgReaderV3(this, is); + writer_ = new CMsgWriterV3(cp, os); + vlog.debug("Authentication success!"); + authSuccess(); + writer_.writeClientInit(shared); + } + + // Methods to initialise the connection + + // setServerName() is used to provide a unique(ish) name for the server to + // which we are connected. This might be the result of getPeerEndpoint on + // a TcpSocket, for example, or a host specified by DNS name & port. + // The serverName is used when verifying the Identity of a host (see RA2). + public void setServerName(String name) { + serverName = name; + } + + public void setServerPort(int port) { + serverPort = port; + } + + public void initSecTypes() { + nSecTypes = 0; + } + + // setShared sets the value of the shared flag which will be sent to the + // server upon initialisation. + public void setShared(boolean s) { shared = s; } + + // setProtocol3_3 configures whether or not the CConnection should + // only ever support protocol version 3.3 + public void setProtocol3_3(boolean s) { useProtocol3_3 = s; } + + // Methods to be overridden in a derived class + + // getCSecurity() gets the CSecurity object for the given type. The type + // is guaranteed to be one of the secTypes passed in to addSecType(). The + // CSecurity object's destroy() method will be called by the CConnection + // from its destructor. + //abstract public CSecurity getCSecurity(int secType); + + // getCurrentCSecurity() gets the CSecurity instance used for this + // connection. + //public CSecurity getCurrentCSecurity() { return security; } + + // setClientSecTypeOrder() determines whether the client should obey the + // server's security type preference, by picking the first server security + // type that the client supports, or whether it should pick the first type + // that the server supports, from the client-supported list of types. + public void setClientSecTypeOrder( boolean csto ) { + clientSecTypeOrder = csto; + } + + // authSuccess() is called when authentication has succeeded. + public void authSuccess() {} + + // serverInit() is called when the ServerInit message is received. The + // derived class must call on to CConnection::serverInit(). + public void serverInit() { + state_ = RFBSTATE_NORMAL; + vlog.debug("initialisation done"); + } + + // Other methods + + public CMsgReaderV3 reader() { return reader_; } + public CMsgWriterV3 writer() { return writer_; } + + public InStream getInStream() { return is; } + public OutStream getOutStream() { return os; } + + public String getServerName() { return serverName; } + public int getServerPort() { return serverPort; } + + public static final int RFBSTATE_UNINITIALISED = 0; + public static final int RFBSTATE_PROTOCOL_VERSION = 1; + public static final int RFBSTATE_SECURITY_TYPES = 2; + public static final int RFBSTATE_SECURITY = 3; + public static final int RFBSTATE_SECURITY_RESULT = 4; + public static final int RFBSTATE_INITIALISATION = 5; + public static final int RFBSTATE_NORMAL = 6; + public static final int RFBSTATE_INVALID = 7; + + public int state() { return state_; } + + protected void setState(int s) { state_ = s; } + + private void throwAuthFailureException() { + String reason; + vlog.debug("state="+state()+", ver="+cp.majorVersion+"."+cp.minorVersion); + if (state() == RFBSTATE_SECURITY_RESULT && !cp.beforeVersion(3,8)) { + reason = is.readString(); + } else { + reason = "Authentication failure"; + } + state_ = RFBSTATE_INVALID; + vlog.error(reason); + throw new AuthFailureException(reason); + } + + InStream is = null; + OutStream os = null; + CMsgReaderV3 reader_ = null; + CMsgWriterV3 writer_ = null; + boolean shared = false; + public CSecurity csecurity; + public SecurityClient security; + public static final int maxSecTypes = 8; + int nSecTypes; + int[] secTypes; + int state_ = RFBSTATE_UNINITIALISED; + String serverName; + int serverPort; + boolean useProtocol3_3 = false; + boolean clientSecTypeOrder; + public static java.net.Socket sock; + + public static java.net.Socket getSocket() { return sock; } + public static void setSocket(java.net.Socket sock_) { sock = sock_; } + + static LogWriter vlog = new LogWriter("CConnection"); +} diff --git a/java/com/tigervnc/rfb/CMsgHandler.java b/java/com/tigervnc/rfb/CMsgHandler.java new file mode 100644 index 00000000..81fd2a1b --- /dev/null +++ b/java/com/tigervnc/rfb/CMsgHandler.java @@ -0,0 +1,88 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// CMsgHandler +// + +package com.tigervnc.rfb; + +public class CMsgHandler { + + public CMsgHandler() { + cp = new ConnParams(); + } + + public void setDesktopSize(int width, int height) + { + cp.width = width; + cp.height = height; + } + + public void setExtendedDesktopSize(int reason, int result, + int width, int height, + ScreenSet layout) + { + cp.supportsSetDesktopSize = true; + + if ((reason == screenTypes.reasonClient) && (result != screenTypes.resultSuccess)) + return; + + if (!layout.validate(width, height)) + vlog.error("Server sent us an invalid screen layout"); + + cp.width = width; + cp.height = height; + cp.screenLayout = layout; + } + + public void setPixelFormat(PixelFormat pf) + { + cp.setPF(pf); + } + + public void setName(String name) + { + cp.setName(name); + } + + public void clientRedirect(int port, String host, + String x509subject) {} + + public void setCursor(int width, int height, Point hotspot, + int[] data, byte[] mask) {} + public void serverInit() {} + + public void framebufferUpdateStart() {} + public void framebufferUpdateEnd() {} + public void beginRect(Rect r, int encoding) {} + public void endRect(Rect r, int encoding) {} + + public void setColourMapEntries(int firstColour, int nColours, + int[] rgbs) { } + public void bell() {} + public void serverCutText(String str, int len) {} + + public void fillRect(Rect r, int pix) {} + public void imageRect(Rect r, int[] pixels) {} + public void copyRect(Rect r, int srcX, int srcY) {} + + public ConnParams cp; + + static LogWriter vlog = new LogWriter("CMsgHandler"); +} diff --git a/java/com/tigervnc/rfb/CMsgReader.java b/java/com/tigervnc/rfb/CMsgReader.java new file mode 100644 index 00000000..41230560 --- /dev/null +++ b/java/com/tigervnc/rfb/CMsgReader.java @@ -0,0 +1,179 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// CMsgReader - class for reading RFB messages on the client side +// (i.e. messages from server to client). +// + +package com.tigervnc.rfb; + +import com.tigervnc.rdr.*; + +abstract public class CMsgReader { + + protected CMsgReader(CMsgHandler handler_, InStream is_) + { + imageBufIdealSize = 0; + handler = handler_; + is = is_; + imageBuf = null; + imageBufSize = 0; + decoders = new Decoder[Encodings.encodingMax+1]; + } + + protected void readSetColourMapEntries() + { + is.skip(1); + int firstColour = is.readU16(); + int nColours = is.readU16(); + int[] rgbs = new int[nColours * 3]; + for (int i = 0; i < nColours * 3; i++) + rgbs[i] = is.readU16(); + handler.setColourMapEntries(firstColour, nColours, rgbs); + } + + protected void readBell() + { + handler.bell(); + } + + protected void readServerCutText() + { + is.skip(3); + int len = is.readU32(); + if (len > 256*1024) { + is.skip(len); + vlog.error("cut text too long ("+len+" bytes) - ignoring"); + return; + } + byte[] buf = new byte[len]; + is.readBytes(buf, 0, len); + String str = new String(); + try { + str = new String(buf,"UTF8"); + } catch(java.io.UnsupportedEncodingException e) { + e.printStackTrace(); + } + handler.serverCutText(str, len); + } + + protected void readFramebufferUpdateStart() + { + handler.framebufferUpdateStart(); + } + + protected void readFramebufferUpdateEnd() + { + handler.framebufferUpdateEnd(); + } + + protected void readRect(Rect r, int encoding) + { + if ((r.br.x > handler.cp.width) || (r.br.y > handler.cp.height)) { + vlog.error("Rect too big: "+r.width()+"x"+r.height()+" at "+ + r.tl.x+","+r.tl.y+" exceeds "+handler.cp.width+"x"+ + handler.cp.height); + throw new Exception("Rect too big"); + } + + if (r.is_empty()) + vlog.error("Ignoring zero size rect"); + + handler.beginRect(r, encoding); + + if (encoding == Encodings.encodingCopyRect) { + readCopyRect(r); + } else { + + if (decoders[encoding] == null) { + decoders[encoding] = Decoder.createDecoder(encoding, this); + if (decoders[encoding] == null) { + vlog.error("Unknown rect encoding "+encoding); + throw new Exception("Unknown rect encoding"); + } + } + decoders[encoding].readRect(r, handler); + } + + handler.endRect(r, encoding); + } + + protected void readCopyRect(Rect r) + { + int srcX = is.readU16(); + int srcY = is.readU16(); + handler.copyRect(r, srcX, srcY); + } + + protected void readSetCursor(int width, int height, Point hotspot) + { + int data_len = width * height; + int mask_len = ((width+7)/8) * height; + int[] data = new int[data_len]; + byte[] mask = new byte[mask_len]; + + is.readPixels(data, data_len, (handler.cp.pf().bpp/8), handler.cp.pf().bigEndian); + is.readBytes(mask, 0, mask_len); + + handler.setCursor(width, height, hotspot, data, mask); + } + + public int[] getImageBuf(int required) { return getImageBuf(required, 0, 0); } + + public int[] getImageBuf(int required, int requested, int nPixels) + { + int requiredBytes = required * (handler.cp.pf().bpp / 8); + int requestedBytes = requested * (handler.cp.pf().bpp / 8); + int size = requestedBytes; + if (size > imageBufIdealSize) size = imageBufIdealSize; + + if (size < requiredBytes) + size = requiredBytes; + + if (imageBufSize < size) { + imageBufSize = size; + imageBuf = new int[imageBufSize]; + } + if (nPixels != 0) + nPixels = imageBufSize / (handler.cp.pf().bpp / 8); + return imageBuf; + } + + public final int bpp() + { + return handler.cp.pf().bpp; + } + + abstract public void readServerInit(); + + // readMsg() reads a message, calling the handler as appropriate. + abstract public void readMsg(); + + public InStream getInStream() { return is; } + + public int imageBufIdealSize; + + protected CMsgHandler handler; + protected InStream is; + protected Decoder[] decoders; + protected int[] imageBuf; + protected int imageBufSize; + + static LogWriter vlog = new LogWriter("CMsgReader"); +} diff --git a/java/com/tigervnc/rfb/CMsgReaderV3.java b/java/com/tigervnc/rfb/CMsgReaderV3.java new file mode 100644 index 00000000..6d9e254b --- /dev/null +++ b/java/com/tigervnc/rfb/CMsgReaderV3.java @@ -0,0 +1,155 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +import com.tigervnc.rdr.*; + +public class CMsgReaderV3 extends CMsgReader { + + public CMsgReaderV3(CMsgHandler handler_, InStream is_) + { + super(handler_, is_); + nUpdateRectsLeft = 0; + } + + public void readServerInit() + { + int width = is.readU16(); + int height = is.readU16(); + handler.setDesktopSize(width, height); + PixelFormat pf = new PixelFormat(); + pf.read(is); + handler.setPixelFormat(pf); + String name = is.readString(); + handler.setName(name); + handler.serverInit(); + } + + public void readMsg() + { + if (nUpdateRectsLeft == 0) { + + int type = is.readU8(); + switch (type) { + case MsgTypes.msgTypeFramebufferUpdate: readFramebufferUpdate(); break; + case MsgTypes.msgTypeSetColourMapEntries: readSetColourMapEntries(); break; + case MsgTypes.msgTypeBell: readBell(); break; + case MsgTypes.msgTypeServerCutText: readServerCutText(); break; + default: + vlog.error("unknown message type "+type); + throw new Exception("unknown message type"); + } + + } else { + + int x = is.readU16(); + int y = is.readU16(); + int w = is.readU16(); + int h = is.readU16(); + int encoding = is.readS32(); + + switch (encoding) { + case Encodings.pseudoEncodingDesktopSize: + handler.setDesktopSize(w, h); + break; + case Encodings.pseudoEncodingExtendedDesktopSize: + readExtendedDesktopSize(x, y, w, h); + break; + case Encodings.pseudoEncodingDesktopName: + readSetDesktopName(x, y, w, h); + break; + case Encodings.pseudoEncodingCursor: + readSetCursor(w, h, new Point(x,y)); + break; + case Encodings.pseudoEncodingLastRect: + nUpdateRectsLeft = 1; // this rectangle is the last one + break; + case Encodings.pseudoEncodingClientRedirect: + readClientRedirect(x, y, w, h); + break; + default: + readRect(new Rect(x, y, x+w, y+h), encoding); + break; + } + + nUpdateRectsLeft--; + if (nUpdateRectsLeft == 0) handler.framebufferUpdateEnd(); + } + } + + void readFramebufferUpdate() + { + is.skip(1); + nUpdateRectsLeft = is.readU16(); + handler.framebufferUpdateStart(); + } + + void readSetDesktopName(int x, int y, int w, int h) + { + String name = is.readString(); + + if (x != 0 || y != 0 || w != 0 || h != 0) { + vlog.error("Ignoring DesktopName rect with non-zero position/size"); + } else { + handler.setName(name); + } + + } + + void readExtendedDesktopSize(int x, int y, int w, int h) + { + int screens, i; + int id, flags; + int sx, sy, sw, sh; + ScreenSet layout = new ScreenSet(); + + screens = is.readU8(); + is.skip(3); + + for (i = 0;i < screens;i++) { + id = is.readU32(); + sx = is.readU16(); + sy = is.readU16(); + sw = is.readU16(); + sh = is.readU16(); + flags = is.readU32(); + + layout.add_screen(new Screen(id, sx, sy, sw, sh, flags)); + } + + handler.setExtendedDesktopSize(x, y, w, h, layout); + } + + void readClientRedirect(int x, int y, int w, int h) + { + int port = is.readU16(); + String host = is.readString(); + String x509subject = is.readString(); + + if (x != 0 || y != 0 || w != 0 || h != 0) { + vlog.error("Ignoring ClientRedirect rect with non-zero position/size"); + } else { + handler.clientRedirect(port, host, x509subject); + } + } + + int nUpdateRectsLeft; + + static LogWriter vlog = new LogWriter("CMsgReaderV3"); +} diff --git a/java/com/tigervnc/rfb/CMsgWriter.java b/java/com/tigervnc/rfb/CMsgWriter.java new file mode 100644 index 00000000..7cafddde --- /dev/null +++ b/java/com/tigervnc/rfb/CMsgWriter.java @@ -0,0 +1,171 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +import com.tigervnc.rdr.*; + +abstract public class CMsgWriter { + + abstract public void writeClientInit(boolean shared); + + public void writeSetPixelFormat(PixelFormat pf) + { + startMsg(MsgTypes.msgTypeSetPixelFormat); + os.pad(3); + pf.write(os); + endMsg(); + } + + public void writeSetEncodings(int nEncodings, int[] encodings) + { + startMsg(MsgTypes.msgTypeSetEncodings); + os.skip(1); + os.writeU16(nEncodings); + for (int i = 0; i < nEncodings; i++) + os.writeU32(encodings[i]); + endMsg(); + } + + // Ask for encodings based on which decoders are supported. Assumes higher + // encoding numbers are more desirable. + + public void writeSetEncodings(int preferredEncoding, boolean useCopyRect) + { + int nEncodings = 0; + int[] encodings = new int[Encodings.encodingMax+3]; + if (cp.supportsLocalCursor) + encodings[nEncodings++] = Encodings.pseudoEncodingCursor; + if (cp.supportsDesktopResize) + encodings[nEncodings++] = Encodings.pseudoEncodingDesktopSize; + if (cp.supportsExtendedDesktopSize) + encodings[nEncodings++] = Encodings.pseudoEncodingExtendedDesktopSize; + if (cp.supportsDesktopRename) + encodings[nEncodings++] = Encodings.pseudoEncodingDesktopName; + if (cp.supportsClientRedirect) + encodings[nEncodings++] = Encodings.pseudoEncodingClientRedirect; + if (Decoder.supported(preferredEncoding)) { + encodings[nEncodings++] = preferredEncoding; + } + if (useCopyRect) { + encodings[nEncodings++] = Encodings.encodingCopyRect; + } + + /* + * Prefer encodings in this order: + * + * Tight, ZRLE, Hextile, * + */ + + if ((preferredEncoding != Encodings.encodingTight) && + Decoder.supported(Encodings.encodingTight)) + encodings[nEncodings++] = Encodings.encodingTight; + + if ((preferredEncoding != Encodings.encodingZRLE) && + Decoder.supported(Encodings.encodingZRLE)) + encodings[nEncodings++] = Encodings.encodingZRLE; + + if ((preferredEncoding != Encodings.encodingHextile) && + Decoder.supported(Encodings.encodingHextile)) + encodings[nEncodings++] = Encodings.encodingHextile; + + // Remaining encodings + for (int i = Encodings.encodingMax; i >= 0; i--) { + switch (i) { + case Encodings.encodingTight: + case Encodings.encodingZRLE: + case Encodings.encodingHextile: + break; + default: + if ((i != preferredEncoding) && Decoder.supported(i)) + encodings[nEncodings++] = i; + } + } + + encodings[nEncodings++] = Encodings.pseudoEncodingLastRect; + if (cp.customCompressLevel && cp.compressLevel >= 0 && cp.compressLevel <= 9) + encodings[nEncodings++] = Encodings.pseudoEncodingCompressLevel0 + cp.compressLevel; + if (!cp.noJpeg && cp.qualityLevel >= 0 && cp.qualityLevel <= 9) + encodings[nEncodings++] = Encodings.pseudoEncodingQualityLevel0 + cp.qualityLevel; + + writeSetEncodings(nEncodings, encodings); + } + + public void writeFramebufferUpdateRequest(Rect r, boolean incremental) + { + startMsg(MsgTypes.msgTypeFramebufferUpdateRequest); + os.writeU8(incremental?1:0); + os.writeU16(r.tl.x); + os.writeU16(r.tl.y); + os.writeU16(r.width()); + os.writeU16(r.height()); + endMsg(); + } + + public void writeKeyEvent(int key, boolean down) + { + startMsg(MsgTypes.msgTypeKeyEvent); + os.writeU8(down?1:0); + os.pad(2); + os.writeU32(key); + endMsg(); + } + + public void writePointerEvent(Point pos, int buttonMask) + { + Point p = new Point(pos.x,pos.y); + if (p.x < 0) p.x = 0; + if (p.y < 0) p.y = 0; + if (p.x >= cp.width) p.x = cp.width - 1; + if (p.y >= cp.height) p.y = cp.height - 1; + + startMsg(MsgTypes.msgTypePointerEvent); + os.writeU8(buttonMask); + os.writeU16(p.x); + os.writeU16(p.y); + endMsg(); + } + + public void writeClientCutText(String str, int len) + { + startMsg(MsgTypes.msgTypeClientCutText); + os.pad(3); + os.writeU32(len); + try { + byte[] utf8str = str.getBytes("UTF8"); + os.writeBytes(utf8str, 0, len); + } catch(java.io.UnsupportedEncodingException e) { + e.printStackTrace(); + } + endMsg(); + } + + abstract public void startMsg(int type); + abstract public void endMsg(); + + public void setOutStream(OutStream os_) { os = os_; } + + ConnParams getConnParams() { return cp; } + OutStream getOutStream() { return os; } + + protected CMsgWriter(ConnParams cp_, OutStream os_) {cp = cp_; os = os_;} + + ConnParams cp; + OutStream os; + static LogWriter vlog = new LogWriter("CMsgWriter"); +} diff --git a/java/com/tigervnc/rfb/CMsgWriterV3.java b/java/com/tigervnc/rfb/CMsgWriterV3.java new file mode 100644 index 00000000..ec30a826 --- /dev/null +++ b/java/com/tigervnc/rfb/CMsgWriterV3.java @@ -0,0 +1,68 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +import com.tigervnc.rdr.*; +import java.util.*; + +public class CMsgWriterV3 extends CMsgWriter { + + public CMsgWriterV3(ConnParams cp_, OutStream os_) { super(cp_, os_); } + + public void writeClientInit(boolean shared) { + os.writeU8(shared?1:0); + endMsg(); + } + + public void startMsg(int type) { + os.writeU8(type); + } + + public void endMsg() { + os.flush(); + } + + public void writeSetDesktopSize(int width, int height, + ScreenSet layout) + { + if (!cp.supportsSetDesktopSize) + throw new Exception("Server does not support SetDesktopSize"); + + startMsg(MsgTypes.msgTypeSetDesktopSize); + os.pad(1); + + os.writeU16(width); + os.writeU16(height); + + os.writeU8(layout.num_screens()); + os.pad(1); + + for (Iterator iter = layout.screens.iterator(); iter.hasNext(); ) { + Screen refScreen = (Screen)iter.next(); + os.writeU32(refScreen.id); + os.writeU16(refScreen.dimensions.tl.x); + os.writeU16(refScreen.dimensions.tl.y); + os.writeU16(refScreen.dimensions.width()); + os.writeU16(refScreen.dimensions.height()); + os.writeU32(refScreen.flags); + } + + endMsg(); + } +} diff --git a/java/com/tigervnc/rfb/CSecurity.java b/java/com/tigervnc/rfb/CSecurity.java new file mode 100644 index 00000000..e5b300f6 --- /dev/null +++ b/java/com/tigervnc/rfb/CSecurity.java @@ -0,0 +1,46 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// CSecurity - class on the client side for handling security handshaking. A +// derived class for a particular security type overrides the processMsg() +// method. processMsg() is called first when the security type has been +// decided on, and will keep being called whenever there is data to read from +// the server until either it returns 0, indicating authentication/security +// failure, or it returns 1, to indicate success. A return value of 2 +// (actually anything other than 0 or 1) indicates that it should be called +// back when there is more data to read. +// +// Note that the first time processMsg() is called, there is no guarantee that +// there is any data to read from the CConnection's InStream, but subsequent +// calls guarantee there is at least one byte which can be read without +// blocking. + +package com.tigervnc.rfb; + +abstract public class CSecurity { + abstract public boolean processMsg(CConnection cc); + abstract public int getType(); + abstract public String description(); + + /* + * Use variable directly instead of dumb get/set methods. + * It MUST be set by viewer. + */ + static UserPasswdGetter upg; +} diff --git a/java/com/tigervnc/rfb/CSecurityIdent.java b/java/com/tigervnc/rfb/CSecurityIdent.java new file mode 100644 index 00000000..6523e411 --- /dev/null +++ b/java/com/tigervnc/rfb/CSecurityIdent.java @@ -0,0 +1,58 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +import java.io.IOException; + +import com.tigervnc.rdr.*; +import com.tigervnc.vncviewer.*; + +public class CSecurityIdent extends CSecurity { + + public CSecurityIdent() { } + + public boolean processMsg(CConnection cc) { + InStream is = cc.getInStream(); + OutStream os = cc.getOutStream(); + + StringBuffer username = new StringBuffer(); + + CConn.upg.getUserPasswd(username, null); + + // Return the response to the server + os.writeU32(username.length()); + try { + byte[] utf8str = username.toString().getBytes("UTF8"); + os.writeBytes(utf8str, 0, username.length()); + } catch(java.io.UnsupportedEncodingException e) { + e.printStackTrace(); + } + os.flush(); + return true; + } + + public int getType() { return Security.secTypeIdent; } + + java.net.Socket sock; + UserPasswdGetter upg; + + static LogWriter vlog = new LogWriter("Ident"); + public String description() { return "No Encryption"; } + +} diff --git a/java/com/tigervnc/rfb/CSecurityManaged.java b/java/com/tigervnc/rfb/CSecurityManaged.java new file mode 100644 index 00000000..2461682d --- /dev/null +++ b/java/com/tigervnc/rfb/CSecurityManaged.java @@ -0,0 +1,76 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +import java.io.IOException; + +import com.tigervnc.rdr.*; +import com.tigervnc.vncviewer.*; + +public class CSecurityManaged extends CSecurity { + + public CSecurityManaged() { } + + public boolean processMsg(CConnection cc) { + InStream is = cc.getInStream(); + OutStream os = cc.getOutStream(); + + StringBuffer username = new StringBuffer(); + + CConn.upg.getUserPasswd(username, null); + + // Return the response to the server + os.writeU8(username.length()); + try { + byte[] utf8str = username.toString().getBytes("UTF8"); + os.writeBytes(utf8str, 0, username.length()); + } catch(java.io.UnsupportedEncodingException e) { + e.printStackTrace(); + } + os.flush(); + int serverPort = is.readU16(); + //if (serverPort==0) { return true; }; + String serverName = cc.getServerName(); + vlog.debug("Redirected to "+serverName+" port "+serverPort); + try { + CConn.getSocket().close(); + cc.setServerPort(serverPort); + sock = new java.net.Socket(serverName, serverPort); + sock.setTcpNoDelay(true); + sock.setTrafficClass(0x10); + CConn.setSocket(sock); + vlog.debug("connected to host "+serverName+" port "+serverPort); + cc.setStreams(new JavaInStream(sock.getInputStream()), + new JavaOutStream(sock.getOutputStream())); + cc.initialiseProtocol(); + } catch (java.io.IOException e) { + e.printStackTrace(); + } + return false; + } + + public int getType() { return Security.secTypeManaged; } + + java.net.Socket sock; + UserPasswdGetter upg; + + static LogWriter vlog = new LogWriter("Managed"); + public String description() { return "No Encryption"; } + +} diff --git a/java/com/tigervnc/rfb/CSecurityNone.java b/java/com/tigervnc/rfb/CSecurityNone.java new file mode 100644 index 00000000..e31056da --- /dev/null +++ b/java/com/tigervnc/rfb/CSecurityNone.java @@ -0,0 +1,27 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +public class CSecurityNone extends CSecurity { + + public boolean processMsg(CConnection cc) { return true; } + public int getType() { return Security.secTypeNone; } + public String description() { return "No Encryption"; } + static LogWriter vlog = new LogWriter("CSecurityNone"); +} diff --git a/java/com/tigervnc/rfb/CSecurityPlain.java b/java/com/tigervnc/rfb/CSecurityPlain.java new file mode 100644 index 00000000..707915cc --- /dev/null +++ b/java/com/tigervnc/rfb/CSecurityPlain.java @@ -0,0 +1,57 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +import com.tigervnc.rdr.*; +import com.tigervnc.vncviewer.*; + +public class CSecurityPlain extends CSecurity { + + public CSecurityPlain() { } + + public boolean processMsg(CConnection cc) + { + OutStream os = cc.getOutStream(); + + StringBuffer username = new StringBuffer(); + StringBuffer password = new StringBuffer(); + + CConn.upg.getUserPasswd(username, password); + + // Return the response to the server + os.writeU32(username.length()); + os.writeU32(password.length()); + byte[] utf8str; + try { + utf8str = username.toString().getBytes("UTF8"); + os.writeBytes(utf8str, 0, username.length()); + utf8str = password.toString().getBytes("UTF8"); + os.writeBytes(utf8str, 0, password.length()); + } catch(java.io.UnsupportedEncodingException e) { + e.printStackTrace(); + } + os.flush(); + return true; + } + + public int getType() { return Security.secTypePlain; } + public String description() { return "ask for username and password"; } + + static LogWriter vlog = new LogWriter("Plain"); +} diff --git a/java/com/tigervnc/rfb/CSecurityStack.java b/java/com/tigervnc/rfb/CSecurityStack.java new file mode 100644 index 00000000..5886268e --- /dev/null +++ b/java/com/tigervnc/rfb/CSecurityStack.java @@ -0,0 +1,69 @@ +/* Copyright (C) 2005 Martin Koegler + * Copyright (C) 2010 TigerVNC Team + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +public class CSecurityStack extends CSecurity { + + public CSecurityStack(int Type, String Name, CSecurity s0, + CSecurity s1) + { + name = Name; + type = Type; + state = 0; + state0 = s0; + state1 = s1; + } + + public boolean processMsg(CConnection cc) + { + boolean res = true; + if (state == 0) { + if (state0 != null) + res = state0.processMsg(cc); + + if (!res) + return res; + + state++; + } + + if (state == 1) { + if(state1 != null) + res = state1.processMsg(cc); + + if(!res) + return res; + + state++; + } + + return res; + } + + public final int getType() { return type; } + public final String description() { return name; } + + private int state; + private CSecurity state0; + private CSecurity state1; + private String name; + private int type; + +} diff --git a/java/com/tigervnc/rfb/CSecurityTLS.java b/java/com/tigervnc/rfb/CSecurityTLS.java new file mode 100644 index 00000000..73eb6199 --- /dev/null +++ b/java/com/tigervnc/rfb/CSecurityTLS.java @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2003 Sun Microsystems, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +import javax.net.ssl.*; +import java.security.*; +import java.security.cert.*; +import java.security.KeyStore; +import java.io.File; +import java.io.InputStream; +import java.io.FileInputStream; +import java.util.ArrayList; +import java.util.Collection; +import javax.swing.JOptionPane; + +import com.tigervnc.vncviewer.UserPrefs; +import com.tigervnc.rdr.*; + +public class CSecurityTLS extends CSecurity { + + public static StringParameter x509ca + = new StringParameter("x509ca", + "X509 CA certificate", ""); + public static StringParameter x509crl + = new StringParameter("x509crl", + "X509 CRL file", ""); + + private void initGlobal() + { + try { + SSLSocketFactory sslfactory; + SSLContext ctx = SSLContext.getInstance("TLS"); + if (anon) { + ctx.init(null, null, null); + } else { + TrustManager[] myTM = new TrustManager[] { + new MyX509TrustManager() + }; + ctx.init (null, myTM, null); + } + sslfactory = ctx.getSocketFactory(); + try { + ssl = (SSLSocket)sslfactory.createSocket(cc.sock, + cc.sock.getInetAddress().getHostName(), + cc.sock.getPort(), true); + } catch (java.io.IOException e) { + throw new Exception(e.toString()); + } + + if (anon) { + String[] supported; + ArrayList<String> enabled = new ArrayList<String>(); + + supported = ssl.getSupportedCipherSuites(); + + for (int i = 0; i < supported.length; i++) + if (supported[i].matches("TLS_DH_anon.*")) + enabled.add(supported[i]); + + ssl.setEnabledCipherSuites(enabled.toArray(new String[0])); + } else { + ssl.setEnabledCipherSuites(ssl.getSupportedCipherSuites()); + } + + ssl.setEnabledProtocols(new String[]{"SSLv3","TLSv1"}); + ssl.addHandshakeCompletedListener(new MyHandshakeListener()); + } + catch (java.security.GeneralSecurityException e) + { + vlog.error ("TLS handshake failed " + e.toString ()); + return; + } + } + + public CSecurityTLS(boolean _anon) + { + anon = _anon; + setDefaults(); + cafile = x509ca.getData(); + crlfile = x509crl.getData(); + } + + public static void setDefaults() + { + String homeDir = null; + + if ((homeDir=UserPrefs.getHomeDir()) == null) { + vlog.error("Could not obtain VNC home directory path"); + return; + } + + String vnchomedir = homeDir+UserPrefs.getFileSeparator()+".vnc"+ + UserPrefs.getFileSeparator(); + String caDefault = new String(vnchomedir+"x509_ca.pem"); + String crlDefault = new String(vnchomedir+"x509_crl.pem"); + + if (new File(caDefault).exists()) + x509ca.setDefaultStr(caDefault); + if (new File(crlDefault).exists()) + x509crl.setDefaultStr(crlDefault); + } + + public boolean processMsg(CConnection cc) { + is = cc.getInStream(); + os = cc.getOutStream(); + + initGlobal(); + + if (!is.checkNoWait(1)) + return false; + + if (is.readU8() == 0) { + int result = is.readU32(); + String reason; + if (result == Security.secResultFailed || + result == Security.secResultTooMany) + reason = is.readString(); + else + reason = new String("Authentication failure (protocol error)"); + throw new AuthFailureException(reason); + } + + // SSLSocket.getSession blocks until the handshake is complete + session = ssl.getSession(); + if (!session.isValid()) + throw new Exception("TLS Handshake failed!"); + + try { + cc.setStreams(new JavaInStream(ssl.getInputStream()), + new JavaOutStream(ssl.getOutputStream())); + } catch (java.io.IOException e) { + throw new Exception("Failed to set streams"); + } + + return true; + } + + class MyHandshakeListener implements HandshakeCompletedListener { + public void handshakeCompleted(HandshakeCompletedEvent e) { + vlog.info("Handshake succesful!"); + vlog.info("Using cipher suite: " + e.getCipherSuite()); + } + } + + class MyX509TrustManager implements X509TrustManager + { + + X509TrustManager tm; + + MyX509TrustManager() throws java.security.GeneralSecurityException + { + TrustManagerFactory tmf = + TrustManagerFactory.getInstance("PKIX"); + KeyStore ks = KeyStore.getInstance("JKS"); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + try { + ks.load(null, null); + File cacert = new File(cafile); + if (!cacert.exists() || !cacert.canRead()) + return; + InputStream caStream = new FileInputStream(cafile); + X509Certificate ca = (X509Certificate)cf.generateCertificate(caStream); + ks.setCertificateEntry("CA", ca); + PKIXBuilderParameters params = new PKIXBuilderParameters(ks, new X509CertSelector()); + File crlcert = new File(crlfile); + if (!crlcert.exists() || !crlcert.canRead()) { + params.setRevocationEnabled(false); + } else { + InputStream crlStream = new FileInputStream(crlfile); + Collection<? extends CRL> crls = cf.generateCRLs(crlStream); + CertStoreParameters csp = new CollectionCertStoreParameters(crls); + CertStore store = CertStore.getInstance("Collection", csp); + params.addCertStore(store); + params.setRevocationEnabled(true); + } + tmf.init(new CertPathTrustManagerParameters(params)); + } catch (java.io.FileNotFoundException e) { + vlog.error(e.toString()); + } catch (java.io.IOException e) { + vlog.error(e.toString()); + } + tm = (X509TrustManager)tmf.getTrustManagers()[0]; + } + + public void checkClientTrusted(X509Certificate[] chain, String authType) + throws CertificateException + { + tm.checkClientTrusted(chain, authType); + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) + throws CertificateException + { + try { + tm.checkServerTrusted(chain, authType); + } catch (CertificateException e) { + Object[] answer = {"Proceed", "Exit"}; + int ret = JOptionPane.showOptionDialog(null, + e.getCause().getLocalizedMessage()+"\n"+ + "Continue connecting to this host?", + "Confirm certificate exception?", + JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, + null, answer, answer[0]); + if (ret == JOptionPane.NO_OPTION) + System.exit(1); + } catch (java.lang.Exception e) { + throw new Exception(e.toString()); + } + } + + public X509Certificate[] getAcceptedIssuers () + { + return tm.getAcceptedIssuers(); + } + } + + public final int getType() { return anon ? Security.secTypeTLSNone : Security.secTypeX509None; } + public final String description() + { return anon ? "TLS Encryption without VncAuth" : "X509 Encryption without VncAuth"; } + + + //protected void setParam(); + //protected void checkSession(); + protected CConnection cc; + + private boolean anon; + private SSLSession session; + private String cafile, crlfile; + private InStream is; + private OutStream os; + private SSLSocket ssl; + + static LogWriter vlog = new LogWriter("CSecurityTLS"); +} diff --git a/java/com/tigervnc/rfb/CSecurityVeNCrypt.java b/java/com/tigervnc/rfb/CSecurityVeNCrypt.java new file mode 100644 index 00000000..ae758e7f --- /dev/null +++ b/java/com/tigervnc/rfb/CSecurityVeNCrypt.java @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2003 Sun Microsystems, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +import java.util.*; + +import com.tigervnc.rdr.*; + +public class CSecurityVeNCrypt extends CSecurity { + + public CSecurityVeNCrypt(SecurityClient sec) + { + haveRecvdMajorVersion = false; + haveRecvdMinorVersion = false; + haveSentVersion = false; + haveAgreedVersion = false; + haveListOfTypes = false; + haveNumberOfTypes = false; + haveChosenType = false; + majorVersion = 0; + minorVersion = 0; + chosenType = Security.secTypeVeNCrypt; + nAvailableTypes = 0; + availableTypes = null; + iAvailableType = 0; + security = sec; + } + + public boolean processMsg(CConnection cc) { + InStream is = cc.getInStream(); + OutStream os = cc.getOutStream(); + + /* get major, minor versions, send what we can support (or 0.0 for can't support it) */ + if (!haveRecvdMinorVersion) { + minorVersion = is.readU8(); + haveRecvdMinorVersion = true; + + return false; + } + + if (!haveRecvdMajorVersion) { + majorVersion = is.readU8(); + haveRecvdMajorVersion = true; + } + + /* major version in upper 8 bits and minor version in lower 8 bits */ + int Version = (majorVersion << 8) | minorVersion; + + if (!haveSentVersion) { + /* Currently we don't support former VeNCrypt 0.1 */ + if (Version >= 0x0002) { + majorVersion = 0; + minorVersion = 2; + os.writeU8(majorVersion); + os.writeU8(minorVersion); + os.flush(); + } else { + /* Send 0.0 to indicate no support */ + majorVersion = 0; + minorVersion = 0; + os.writeU8(majorVersion); + os.writeU8(minorVersion); + os.flush(); + throw new Exception("Server reported an unsupported VeNCrypt version"); + } + + haveSentVersion = true; + return false; + } + + /* Check that the server is OK */ + if (!haveAgreedVersion) { + if (is.readU8() != 0) + throw new Exception("Server reported it could not support the VeNCrypt version"); + + haveAgreedVersion = true; + return false; + } + + /* get a number of types */ + if (!haveNumberOfTypes) { + nAvailableTypes = is.readU8(); + iAvailableType = 0; + + if (nAvailableTypes <= 0) + throw new Exception("The server reported no VeNCrypt sub-types"); + + availableTypes = new int[nAvailableTypes]; + haveNumberOfTypes = true; + return false; + } + + if (nAvailableTypes > 0) { + /* read in the types possible */ + if (!haveListOfTypes) { + if (is.checkNoWait(4)) { + availableTypes[iAvailableType++] = is.readU32(); + haveListOfTypes = (iAvailableType >= nAvailableTypes); + vlog.debug("Server offers security type "+ + Security.secTypeName(availableTypes[iAvailableType - 1])+" ("+ + availableTypes[iAvailableType - 1]+")"); + + if (!haveListOfTypes) + return false; + + } else + return false; + } + + /* make a choice and send it to the server, meanwhile set up the stack */ + if (!haveChosenType) { + chosenType = Security.secTypeInvalid; + int i; + Iterator j; + List<Integer> secTypes = new ArrayList<Integer>(); + + secTypes = security.GetEnabledExtSecTypes(); + + /* Honor server's security type order */ + for (i = 0; i < nAvailableTypes; i++) { + for (j = secTypes.iterator(); j.hasNext(); ) { + int refType = (Integer)j.next(); + if (refType == availableTypes[i]) { + chosenType = refType; + break; + } + } + + if (chosenType != Security.secTypeInvalid) + break; + } + + vlog.debug("Choosing security type "+Security.secTypeName(chosenType)+ + " ("+chosenType+")"); + + /* Set up the stack according to the chosen type: */ + if (chosenType == Security.secTypeInvalid || chosenType == Security.secTypeVeNCrypt) + throw new AuthFailureException("No valid VeNCrypt sub-type"); + + csecurity = security.GetCSecurity(chosenType); + + /* send chosen type to server */ + os.writeU32(chosenType); + os.flush(); + + haveChosenType = true; + } + } else { + /* + * Server told us that there are 0 types it can support - this should not + * happen, since if the server supports 0 sub-types, it doesn't support + * this security type + */ + throw new AuthFailureException("The server reported 0 VeNCrypt sub-types"); + } + + return csecurity.processMsg(cc); + } + + public final int getType() { return chosenType; } + public final String description() { return Security.secTypeName(chosenType); } + + public static StringParameter secTypesStr; + + private CSecurity csecurity; + SecurityClient security; + private boolean haveRecvdMajorVersion; + private boolean haveRecvdMinorVersion; + private boolean haveSentVersion; + private boolean haveAgreedVersion; + private boolean haveListOfTypes; + private boolean haveNumberOfTypes; + private boolean haveChosenType; + private int majorVersion, minorVersion; + private int chosenType; + private int nAvailableTypes; + private int[] availableTypes; + private int iAvailableType; + //private final String desc; + + static LogWriter vlog = new LogWriter("CSecurityVeNCrypt"); +} diff --git a/java/com/tigervnc/rfb/CSecurityVncAuth.java b/java/com/tigervnc/rfb/CSecurityVncAuth.java new file mode 100644 index 00000000..405e79fa --- /dev/null +++ b/java/com/tigervnc/rfb/CSecurityVncAuth.java @@ -0,0 +1,66 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +import com.tigervnc.rdr.*; +import com.tigervnc.vncviewer.*; + +public class CSecurityVncAuth extends CSecurity { + + public CSecurityVncAuth() { } + + private static final int vncAuthChallengeSize = 16; + + public boolean processMsg(CConnection cc) + { + InStream is = cc.getInStream(); + OutStream os = cc.getOutStream(); + + // Read the challenge & obtain the user's password + byte[] challenge = new byte[vncAuthChallengeSize]; + is.readBytes(challenge, 0, vncAuthChallengeSize); + StringBuffer passwd = new StringBuffer(); + CConn.upg.getUserPasswd(null, passwd); + + // Calculate the correct response + byte[] key = new byte[8]; + int pwdLen = passwd.length(); + byte[] utf8str = new byte[pwdLen]; + try { + utf8str = passwd.toString().getBytes("UTF8"); + } catch(java.io.UnsupportedEncodingException e) { + e.printStackTrace(); + } + for (int i=0; i<8; i++) + key[i] = i<pwdLen ? utf8str[i] : 0; + DesCipher des = new DesCipher(key); + for (int j = 0; j < vncAuthChallengeSize; j += 8) + des.encrypt(challenge,j,challenge,j); + + // Return the response to the server + os.writeBytes(challenge, 0, vncAuthChallengeSize); + os.flush(); + return true; + } + + public int getType() { return Security.secTypeVncAuth; } + public String description() { return "No Encryption"; } + + static LogWriter vlog = new LogWriter("VncAuth"); +} diff --git a/java/com/tigervnc/rfb/Configuration.java b/java/com/tigervnc/rfb/Configuration.java new file mode 100644 index 00000000..bc676087 --- /dev/null +++ b/java/com/tigervnc/rfb/Configuration.java @@ -0,0 +1,91 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// Configuration - class for dealing with configuration parameters. +// + +package com.tigervnc.rfb; + +public class Configuration { + + // - Set named parameter to value + public static boolean setParam(String name, String value) { + VoidParameter param = getParam(name); + if (param == null) return false; + return param.setParam(value); + } + + // - Set parameter to value (separated by "=") + public static boolean setParam(String config) { + boolean hyphen = false; + if (config.charAt(0) == '-') { + hyphen = true; + if (config.charAt(1) == '-') + config = config.substring(2); // allow gnu-style --<option> + else + config = config.substring(1); + } + int equal = config.indexOf('='); + if (equal != -1) { + return setParam(config.substring(0, equal), config.substring(equal+1)); + } else if (hyphen) { + VoidParameter param = getParam(config); + if (param == null) return false; + return param.setParam(); + } + return false; + } + + // - Get named parameter + public static VoidParameter getParam(String name) { + VoidParameter current = head; + while (current != null) { + if (name.equalsIgnoreCase(current.getName())) + return current; + current = current.next; + } + return null; + } + + public static String listParams() { + StringBuffer s = new StringBuffer(); + + VoidParameter current = head; + while (current != null) { + String def_str = current.getDefaultStr(); + String desc = current.getDescription(); + s.append(" "+current.getName()+" - "+desc+" (default="+def_str+")\n"); + current = current.next; + } + + return s.toString(); + } + + public static void readAppletParams(java.applet.Applet applet) { + VoidParameter current = head; + while (current != null) { + String str = applet.getParameter(current.getName()); + if (str != null) + current.setParam(str); + current = current.next; + } + } + + public static VoidParameter head; +} diff --git a/java/com/tigervnc/rfb/ConnFailedException.java b/java/com/tigervnc/rfb/ConnFailedException.java new file mode 100644 index 00000000..d1ddcb4e --- /dev/null +++ b/java/com/tigervnc/rfb/ConnFailedException.java @@ -0,0 +1,23 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +public class ConnFailedException extends Exception { + public ConnFailedException(String s) { super(s); } +} diff --git a/java/com/tigervnc/rfb/ConnParams.java b/java/com/tigervnc/rfb/ConnParams.java new file mode 100644 index 00000000..70d6114f --- /dev/null +++ b/java/com/tigervnc/rfb/ConnParams.java @@ -0,0 +1,171 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +import com.tigervnc.rdr.*; + +public class ConnParams { + static LogWriter vlog = new LogWriter("ConnParams"); + + public ConnParams() { + majorVersion = 0; minorVersion = 0; + width = 0; height = 0; useCopyRect = false; + supportsLocalCursor = false; supportsLocalXCursor = false; + supportsDesktopResize = false; supportsExtendedDesktopSize = false; + supportsDesktopRename = false; supportsLastRect = false; + supportsSetDesktopSize = false; supportsClientRedirect = false; + customCompressLevel = false; compressLevel = 6; + noJpeg = false; qualityLevel = -1; + name_ = null; nEncodings_ = 0; encodings_ = null; + currentEncoding_ = Encodings.encodingRaw; verStrPos = 0; + screenLayout = new ScreenSet(); + + setName(""); + } + + public boolean readVersion(InStream is, Boolean done) + { + if (verStrPos >= 12) return false; + verStr = new StringBuilder(13); + while (verStrPos < 12 && is.checkNoWait(1)) { + verStr.insert(verStrPos++,(char)is.readU8()); + } + + if (verStrPos < 12) { + done = Boolean.valueOf(false); + return true; + } + done = Boolean.valueOf(true); + verStr.insert(12,'0'); + verStrPos = 0; + if (verStr.toString().matches("RFB \\d{3}\\.\\d{3}\\n0")) { + majorVersion = Integer.parseInt(verStr.substring(4,7)); + minorVersion = Integer.parseInt(verStr.substring(8,11)); + return true; + } + return false; + } + + public void writeVersion(OutStream os) { + String str = String.format("RFB %03d.%03d\n", majorVersion, minorVersion); + os.writeBytes(str.getBytes(), 0, 12); + os.flush(); + } + + public int majorVersion; + public int minorVersion; + + public void setVersion(int major, int minor) { + majorVersion = major; minorVersion = minor; + } + public boolean isVersion(int major, int minor) { + return majorVersion == major && minorVersion == minor; + } + public boolean beforeVersion(int major, int minor) { + return (majorVersion < major || + (majorVersion == major && minorVersion < minor)); + } + public boolean afterVersion(int major, int minor) { + return !beforeVersion(major,minor+1); + } + + public int width; + public int height; + public ScreenSet screenLayout; + + public PixelFormat pf() { return pf_; } + public void setPF(PixelFormat pf) { + pf_ = pf; + if (pf.bpp != 8 && pf.bpp != 16 && pf.bpp != 32) { + throw new Exception("setPF: not 8, 16 or 32 bpp?"); + } + } + + public String name() { return name_; } + public void setName(String name) + { + name_ = name; + } + + public int currentEncoding() { return currentEncoding_; } + public int nEncodings() { return nEncodings_; } + public int[] encodings() { return encodings_; } + public void setEncodings(int nEncodings, int[] encodings) + { + if (nEncodings > nEncodings_) { + encodings_ = new int[nEncodings]; + } + nEncodings_ = nEncodings; + useCopyRect = false; + supportsLocalCursor = false; + supportsDesktopResize = false; + customCompressLevel = false; + compressLevel = -1; + noJpeg = true; + qualityLevel = -1; + currentEncoding_ = Encodings.encodingRaw; + + for (int i = nEncodings-1; i >= 0; i--) { + encodings_[i] = encodings[i]; + if (encodings[i] == Encodings.encodingCopyRect) + useCopyRect = true; + else if (encodings[i] == Encodings.pseudoEncodingCursor) + supportsLocalCursor = true; + else if (encodings[i] == Encodings.pseudoEncodingDesktopSize) + supportsDesktopResize = true; + else if (encodings[i] == Encodings.pseudoEncodingClientRedirect) + supportsClientRedirect = true; + else if (encodings[i] >= Encodings.pseudoEncodingCompressLevel0 && + encodings[i] <= Encodings.pseudoEncodingCompressLevel9) { + customCompressLevel = true; + compressLevel = encodings[i] - Encodings.pseudoEncodingCompressLevel0; + } else if (encodings[i] >= Encodings.pseudoEncodingQualityLevel0 && + encodings[i] <= Encodings.pseudoEncodingQualityLevel9) { + noJpeg = false; + qualityLevel = encodings[i] - Encodings.pseudoEncodingQualityLevel0; + } else if (encodings[i] <= Encodings.encodingMax && + Encoder.supported(encodings[i])) + currentEncoding_ = encodings[i]; + } + } + public boolean useCopyRect; + + public boolean supportsLocalCursor; + public boolean supportsLocalXCursor; + public boolean supportsDesktopResize; + public boolean supportsExtendedDesktopSize; + public boolean supportsDesktopRename; + public boolean supportsClientRedirect; + public boolean supportsLastRect; + + public boolean supportsSetDesktopSize; + + public boolean customCompressLevel; + public int compressLevel; + public boolean noJpeg; + public int qualityLevel; + + private PixelFormat pf_; + private String name_; + private int nEncodings_; + private int[] encodings_; + private int currentEncoding_; + private StringBuilder verStr; + private int verStrPos; +} diff --git a/java/com/tigervnc/rfb/Cursor.java b/java/com/tigervnc/rfb/Cursor.java new file mode 100644 index 00000000..420eb82a --- /dev/null +++ b/java/com/tigervnc/rfb/Cursor.java @@ -0,0 +1,34 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +import java.awt.*; + +public class Cursor extends ManagedPixelBuffer { + + public void setSize(int w, int h) { + super.setSize(w, h); + if (mask == null || mask.length < maskLen()) + mask = new byte[maskLen()]; + } + public int maskLen() { return (width() + 7) / 8 * height(); } + + public Point hotspot; + public byte[] mask; +} diff --git a/java/com/tigervnc/rfb/Decoder.java b/java/com/tigervnc/rfb/Decoder.java new file mode 100644 index 00000000..8d42ea5e --- /dev/null +++ b/java/com/tigervnc/rfb/Decoder.java @@ -0,0 +1,51 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +abstract public class Decoder { + + abstract public void readRect(Rect r, CMsgHandler handler); + + static public boolean supported(int encoding) + { +/* + return encoding <= Encodings.encodingMax && createFns[encoding]; +*/ + return (encoding == Encodings.encodingRaw || + encoding == Encodings.encodingRRE || + encoding == Encodings.encodingHextile || + encoding == Encodings.encodingTight || + encoding == Encodings.encodingZRLE); + } + static public Decoder createDecoder(int encoding, CMsgReader reader) { +/* + if (encoding <= Encodings.encodingMax && createFns[encoding]) + return (createFns[encoding])(reader); + return 0; +*/ + switch(encoding) { + case Encodings.encodingRaw: return new RawDecoder(reader); + case Encodings.encodingRRE: return new RREDecoder(reader); + case Encodings.encodingHextile: return new HextileDecoder(reader); + case Encodings.encodingTight: return new TightDecoder(reader); + case Encodings.encodingZRLE: return new ZRLEDecoder(reader); + } + return null; + } +} diff --git a/java/com/tigervnc/rfb/DesCipher.java b/java/com/tigervnc/rfb/DesCipher.java new file mode 100644 index 00000000..f7ae9db9 --- /dev/null +++ b/java/com/tigervnc/rfb/DesCipher.java @@ -0,0 +1,496 @@ +// +// This DES class has been extracted from package Acme.Crypto for use in VNC. +// The bytebit[] array has been reversed so that the most significant bit +// in each byte of the key is ignored, not the least significant. Also the +// unnecessary odd parity code has been removed. +// +// These changes are: +// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. +// +// 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. +// + +// DesCipher - the DES encryption method +// +// The meat of this code is by Dave Zimmerman <dzimm@widget.com>, and is: +// +// Copyright (c) 1996 Widget Workshop, Inc. All Rights Reserved. +// +// Permission to use, copy, modify, and distribute this software +// and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and +// without fee is hereby granted, provided that this copyright notice is kept +// intact. +// +// WIDGET WORKSHOP MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY +// OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE, OR NON-INFRINGEMENT. WIDGET WORKSHOP SHALL NOT BE LIABLE +// FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +// DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. +// +// THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE +// CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE +// PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT +// NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE +// SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE +// SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE +// PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). WIDGET WORKSHOP +// SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR +// HIGH RISK ACTIVITIES. +// +// +// The rest is: +// +// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +// SUCH DAMAGE. +// +// Visit the ACME Labs Java page for up-to-date versions of this and other +// fine Java utilities: http://www.acme.com/java/ + + +/// The DES encryption method. +// <P> +// This is surprisingly fast, for pure Java. On a SPARC 20, wrapped +// in Acme.Crypto.EncryptedOutputStream or Acme.Crypto.EncryptedInputStream, +// it does around 7000 bytes/second. +// <P> +// Most of this code is by Dave Zimmerman <dzimm@widget.com>, and is +// Copyright (c) 1996 Widget Workshop, Inc. See the source file for details. +// <P> +// <A HREF="/resources/classes/Acme/Crypto/DesCipher.java">Fetch the software.</A><BR> +// <A HREF="/resources/classes/Acme.tar.Z">Fetch the entire Acme package.</A> +// <P> +// @see Des3Cipher +// @see EncryptedOutputStream +// @see EncryptedInputStream + +package com.tigervnc.rfb; + +public class DesCipher + { + + // Constructor, byte-array key. + public DesCipher( byte[] key ) + { + setKey( key ); + } + + // Key routines. + + private int[] encryptKeys = new int[32]; + private int[] decryptKeys = new int[32]; + + /// Set the key. + public void setKey( byte[] key ) + { + deskey( key, true, encryptKeys ); + deskey( key, false, decryptKeys ); + } + + // Turn an 8-byte key into internal keys. + private void deskey( byte[] keyBlock, boolean encrypting, int[] KnL ) + { + int i, j, l, m, n; + int[] pc1m = new int[56]; + int[] pcr = new int[56]; + int[] kn = new int[32]; + + for ( j = 0; j < 56; ++j ) + { + l = pc1[j]; + m = l & 07; + pc1m[j] = ( (keyBlock[l >>> 3] & bytebit[m]) != 0 )? 1: 0; + } + + for ( i = 0; i < 16; ++i ) + { + if ( encrypting ) + m = i << 1; + else + m = (15-i) << 1; + n = m+1; + kn[m] = kn[n] = 0; + for ( j = 0; j < 28; ++j ) + { + l = j+totrot[i]; + if ( l < 28 ) + pcr[j] = pc1m[l]; + else + pcr[j] = pc1m[l-28]; + } + for ( j=28; j < 56; ++j ) + { + l = j+totrot[i]; + if ( l < 56 ) + pcr[j] = pc1m[l]; + else + pcr[j] = pc1m[l-28]; + } + for ( j = 0; j < 24; ++j ) + { + if ( pcr[pc2[j]] != 0 ) + kn[m] |= bigbyte[j]; + if ( pcr[pc2[j+24]] != 0 ) + kn[n] |= bigbyte[j]; + } + } + cookey( kn, KnL ); + } + + private void cookey( int[] raw, int KnL[] ) + { + int raw0, raw1; + int rawi, KnLi; + int i; + + for ( i = 0, rawi = 0, KnLi = 0; i < 16; ++i ) + { + raw0 = raw[rawi++]; + raw1 = raw[rawi++]; + KnL[KnLi] = (raw0 & 0x00fc0000) << 6; + KnL[KnLi] |= (raw0 & 0x00000fc0) << 10; + KnL[KnLi] |= (raw1 & 0x00fc0000) >>> 10; + KnL[KnLi] |= (raw1 & 0x00000fc0) >>> 6; + ++KnLi; + KnL[KnLi] = (raw0 & 0x0003f000) << 12; + KnL[KnLi] |= (raw0 & 0x0000003f) << 16; + KnL[KnLi] |= (raw1 & 0x0003f000) >>> 4; + KnL[KnLi] |= (raw1 & 0x0000003f); + ++KnLi; + } + } + + + // Block encryption routines. + + private int[] tempInts = new int[2]; + + /// Encrypt a block of eight bytes. + public void encrypt( byte[] clearText, int clearOff, byte[] cipherText, int cipherOff ) + { + squashBytesToInts( clearText, clearOff, tempInts, 0, 2 ); + des( tempInts, tempInts, encryptKeys ); + spreadIntsToBytes( tempInts, 0, cipherText, cipherOff, 2 ); + } + + /// Decrypt a block of eight bytes. + public void decrypt( byte[] cipherText, int cipherOff, byte[] clearText, int clearOff ) + { + squashBytesToInts( cipherText, cipherOff, tempInts, 0, 2 ); + des( tempInts, tempInts, decryptKeys ); + spreadIntsToBytes( tempInts, 0, clearText, clearOff, 2 ); + } + + // The DES function. + private void des( int[] inInts, int[] outInts, int[] keys ) + { + int fval, work, right, leftt; + int round; + int keysi = 0; + + leftt = inInts[0]; + right = inInts[1]; + + work = ((leftt >>> 4) ^ right) & 0x0f0f0f0f; + right ^= work; + leftt ^= (work << 4); + + work = ((leftt >>> 16) ^ right) & 0x0000ffff; + right ^= work; + leftt ^= (work << 16); + + work = ((right >>> 2) ^ leftt) & 0x33333333; + leftt ^= work; + right ^= (work << 2); + + work = ((right >>> 8) ^ leftt) & 0x00ff00ff; + leftt ^= work; + right ^= (work << 8); + right = (right << 1) | ((right >>> 31) & 1); + + work = (leftt ^ right) & 0xaaaaaaaa; + leftt ^= work; + right ^= work; + leftt = (leftt << 1) | ((leftt >>> 31) & 1); + + for ( round = 0; round < 8; ++round ) + { + work = (right << 28) | (right >>> 4); + work ^= keys[keysi++]; + fval = SP7[ work & 0x0000003f ]; + fval |= SP5[(work >>> 8) & 0x0000003f ]; + fval |= SP3[(work >>> 16) & 0x0000003f ]; + fval |= SP1[(work >>> 24) & 0x0000003f ]; + work = right ^ keys[keysi++]; + fval |= SP8[ work & 0x0000003f ]; + fval |= SP6[(work >>> 8) & 0x0000003f ]; + fval |= SP4[(work >>> 16) & 0x0000003f ]; + fval |= SP2[(work >>> 24) & 0x0000003f ]; + leftt ^= fval; + work = (leftt << 28) | (leftt >>> 4); + work ^= keys[keysi++]; + fval = SP7[ work & 0x0000003f ]; + fval |= SP5[(work >>> 8) & 0x0000003f ]; + fval |= SP3[(work >>> 16) & 0x0000003f ]; + fval |= SP1[(work >>> 24) & 0x0000003f ]; + work = leftt ^ keys[keysi++]; + fval |= SP8[ work & 0x0000003f ]; + fval |= SP6[(work >>> 8) & 0x0000003f ]; + fval |= SP4[(work >>> 16) & 0x0000003f ]; + fval |= SP2[(work >>> 24) & 0x0000003f ]; + right ^= fval; + } + + right = (right << 31) | (right >>> 1); + work = (leftt ^ right) & 0xaaaaaaaa; + leftt ^= work; + right ^= work; + leftt = (leftt << 31) | (leftt >>> 1); + work = ((leftt >>> 8) ^ right) & 0x00ff00ff; + right ^= work; + leftt ^= (work << 8); + work = ((leftt >>> 2) ^ right) & 0x33333333; + right ^= work; + leftt ^= (work << 2); + work = ((right >>> 16) ^ leftt) & 0x0000ffff; + leftt ^= work; + right ^= (work << 16); + work = ((right >>> 4) ^ leftt) & 0x0f0f0f0f; + leftt ^= work; + right ^= (work << 4); + outInts[0] = right; + outInts[1] = leftt; + } + + + // Tables, permutations, S-boxes, etc. + + private static byte[] bytebit = { + (byte)0x01, (byte)0x02, (byte)0x04, (byte)0x08, + (byte)0x10, (byte)0x20, (byte)0x40, (byte)0x80 + }; + private static int[] bigbyte = { + 0x800000, 0x400000, 0x200000, 0x100000, + 0x080000, 0x040000, 0x020000, 0x010000, + 0x008000, 0x004000, 0x002000, 0x001000, + 0x000800, 0x000400, 0x000200, 0x000100, + 0x000080, 0x000040, 0x000020, 0x000010, + 0x000008, 0x000004, 0x000002, 0x000001 + }; + private static byte[] pc1 = { + (byte)56, (byte)48, (byte)40, (byte)32, (byte)24, (byte)16, (byte) 8, + (byte) 0, (byte)57, (byte)49, (byte)41, (byte)33, (byte)25, (byte)17, + (byte) 9, (byte) 1, (byte)58, (byte)50, (byte)42, (byte)34, (byte)26, + (byte)18, (byte)10, (byte) 2, (byte)59, (byte)51, (byte)43, (byte)35, + (byte)62, (byte)54, (byte)46, (byte)38, (byte)30, (byte)22, (byte)14, + (byte) 6, (byte)61, (byte)53, (byte)45, (byte)37, (byte)29, (byte)21, + (byte)13, (byte) 5, (byte)60, (byte)52, (byte)44, (byte)36, (byte)28, + (byte)20, (byte)12, (byte) 4, (byte)27, (byte)19, (byte)11, (byte)3 + }; + private static int[] totrot = { + 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 + }; + + private static byte[] pc2 = { + (byte)13, (byte)16, (byte)10, (byte)23, (byte) 0, (byte) 4, + (byte) 2, (byte)27, (byte)14, (byte) 5, (byte)20, (byte) 9, + (byte)22, (byte)18, (byte)11, (byte)3 , (byte)25, (byte) 7, + (byte)15, (byte) 6, (byte)26, (byte)19, (byte)12, (byte) 1, + (byte)40, (byte)51, (byte)30, (byte)36, (byte)46, (byte)54, + (byte)29, (byte)39, (byte)50, (byte)44, (byte)32, (byte)47, + (byte)43, (byte)48, (byte)38, (byte)55, (byte)33, (byte)52, + (byte)45, (byte)41, (byte)49, (byte)35, (byte)28, (byte)31, + }; + + private static int[] SP1 = { + 0x01010400, 0x00000000, 0x00010000, 0x01010404, + 0x01010004, 0x00010404, 0x00000004, 0x00010000, + 0x00000400, 0x01010400, 0x01010404, 0x00000400, + 0x01000404, 0x01010004, 0x01000000, 0x00000004, + 0x00000404, 0x01000400, 0x01000400, 0x00010400, + 0x00010400, 0x01010000, 0x01010000, 0x01000404, + 0x00010004, 0x01000004, 0x01000004, 0x00010004, + 0x00000000, 0x00000404, 0x00010404, 0x01000000, + 0x00010000, 0x01010404, 0x00000004, 0x01010000, + 0x01010400, 0x01000000, 0x01000000, 0x00000400, + 0x01010004, 0x00010000, 0x00010400, 0x01000004, + 0x00000400, 0x00000004, 0x01000404, 0x00010404, + 0x01010404, 0x00010004, 0x01010000, 0x01000404, + 0x01000004, 0x00000404, 0x00010404, 0x01010400, + 0x00000404, 0x01000400, 0x01000400, 0x00000000, + 0x00010004, 0x00010400, 0x00000000, 0x01010004 + }; + private static int[] SP2 = { + 0x80108020, 0x80008000, 0x00008000, 0x00108020, + 0x00100000, 0x00000020, 0x80100020, 0x80008020, + 0x80000020, 0x80108020, 0x80108000, 0x80000000, + 0x80008000, 0x00100000, 0x00000020, 0x80100020, + 0x00108000, 0x00100020, 0x80008020, 0x00000000, + 0x80000000, 0x00008000, 0x00108020, 0x80100000, + 0x00100020, 0x80000020, 0x00000000, 0x00108000, + 0x00008020, 0x80108000, 0x80100000, 0x00008020, + 0x00000000, 0x00108020, 0x80100020, 0x00100000, + 0x80008020, 0x80100000, 0x80108000, 0x00008000, + 0x80100000, 0x80008000, 0x00000020, 0x80108020, + 0x00108020, 0x00000020, 0x00008000, 0x80000000, + 0x00008020, 0x80108000, 0x00100000, 0x80000020, + 0x00100020, 0x80008020, 0x80000020, 0x00100020, + 0x00108000, 0x00000000, 0x80008000, 0x00008020, + 0x80000000, 0x80100020, 0x80108020, 0x00108000 + }; + private static int[] SP3 = { + 0x00000208, 0x08020200, 0x00000000, 0x08020008, + 0x08000200, 0x00000000, 0x00020208, 0x08000200, + 0x00020008, 0x08000008, 0x08000008, 0x00020000, + 0x08020208, 0x00020008, 0x08020000, 0x00000208, + 0x08000000, 0x00000008, 0x08020200, 0x00000200, + 0x00020200, 0x08020000, 0x08020008, 0x00020208, + 0x08000208, 0x00020200, 0x00020000, 0x08000208, + 0x00000008, 0x08020208, 0x00000200, 0x08000000, + 0x08020200, 0x08000000, 0x00020008, 0x00000208, + 0x00020000, 0x08020200, 0x08000200, 0x00000000, + 0x00000200, 0x00020008, 0x08020208, 0x08000200, + 0x08000008, 0x00000200, 0x00000000, 0x08020008, + 0x08000208, 0x00020000, 0x08000000, 0x08020208, + 0x00000008, 0x00020208, 0x00020200, 0x08000008, + 0x08020000, 0x08000208, 0x00000208, 0x08020000, + 0x00020208, 0x00000008, 0x08020008, 0x00020200 + }; + private static int[] SP4 = { + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802080, 0x00800081, 0x00800001, 0x00002001, + 0x00000000, 0x00802000, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00800080, 0x00800001, + 0x00000001, 0x00002000, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002001, 0x00002080, + 0x00800081, 0x00000001, 0x00002080, 0x00800080, + 0x00002000, 0x00802080, 0x00802081, 0x00000081, + 0x00800080, 0x00800001, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00000000, 0x00802000, + 0x00002080, 0x00800080, 0x00800081, 0x00000001, + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802081, 0x00000081, 0x00000001, 0x00002000, + 0x00800001, 0x00002001, 0x00802080, 0x00800081, + 0x00002001, 0x00002080, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002000, 0x00802080 + }; + private static int[] SP5 = { + 0x00000100, 0x02080100, 0x02080000, 0x42000100, + 0x00080000, 0x00000100, 0x40000000, 0x02080000, + 0x40080100, 0x00080000, 0x02000100, 0x40080100, + 0x42000100, 0x42080000, 0x00080100, 0x40000000, + 0x02000000, 0x40080000, 0x40080000, 0x00000000, + 0x40000100, 0x42080100, 0x42080100, 0x02000100, + 0x42080000, 0x40000100, 0x00000000, 0x42000000, + 0x02080100, 0x02000000, 0x42000000, 0x00080100, + 0x00080000, 0x42000100, 0x00000100, 0x02000000, + 0x40000000, 0x02080000, 0x42000100, 0x40080100, + 0x02000100, 0x40000000, 0x42080000, 0x02080100, + 0x40080100, 0x00000100, 0x02000000, 0x42080000, + 0x42080100, 0x00080100, 0x42000000, 0x42080100, + 0x02080000, 0x00000000, 0x40080000, 0x42000000, + 0x00080100, 0x02000100, 0x40000100, 0x00080000, + 0x00000000, 0x40080000, 0x02080100, 0x40000100 + }; + private static int[] SP6 = { + 0x20000010, 0x20400000, 0x00004000, 0x20404010, + 0x20400000, 0x00000010, 0x20404010, 0x00400000, + 0x20004000, 0x00404010, 0x00400000, 0x20000010, + 0x00400010, 0x20004000, 0x20000000, 0x00004010, + 0x00000000, 0x00400010, 0x20004010, 0x00004000, + 0x00404000, 0x20004010, 0x00000010, 0x20400010, + 0x20400010, 0x00000000, 0x00404010, 0x20404000, + 0x00004010, 0x00404000, 0x20404000, 0x20000000, + 0x20004000, 0x00000010, 0x20400010, 0x00404000, + 0x20404010, 0x00400000, 0x00004010, 0x20000010, + 0x00400000, 0x20004000, 0x20000000, 0x00004010, + 0x20000010, 0x20404010, 0x00404000, 0x20400000, + 0x00404010, 0x20404000, 0x00000000, 0x20400010, + 0x00000010, 0x00004000, 0x20400000, 0x00404010, + 0x00004000, 0x00400010, 0x20004010, 0x00000000, + 0x20404000, 0x20000000, 0x00400010, 0x20004010 + }; + private static int[] SP7 = { + 0x00200000, 0x04200002, 0x04000802, 0x00000000, + 0x00000800, 0x04000802, 0x00200802, 0x04200800, + 0x04200802, 0x00200000, 0x00000000, 0x04000002, + 0x00000002, 0x04000000, 0x04200002, 0x00000802, + 0x04000800, 0x00200802, 0x00200002, 0x04000800, + 0x04000002, 0x04200000, 0x04200800, 0x00200002, + 0x04200000, 0x00000800, 0x00000802, 0x04200802, + 0x00200800, 0x00000002, 0x04000000, 0x00200800, + 0x04000000, 0x00200800, 0x00200000, 0x04000802, + 0x04000802, 0x04200002, 0x04200002, 0x00000002, + 0x00200002, 0x04000000, 0x04000800, 0x00200000, + 0x04200800, 0x00000802, 0x00200802, 0x04200800, + 0x00000802, 0x04000002, 0x04200802, 0x04200000, + 0x00200800, 0x00000000, 0x00000002, 0x04200802, + 0x00000000, 0x00200802, 0x04200000, 0x00000800, + 0x04000002, 0x04000800, 0x00000800, 0x00200002 + }; + private static int[] SP8 = { + 0x10001040, 0x00001000, 0x00040000, 0x10041040, + 0x10000000, 0x10001040, 0x00000040, 0x10000000, + 0x00040040, 0x10040000, 0x10041040, 0x00041000, + 0x10041000, 0x00041040, 0x00001000, 0x00000040, + 0x10040000, 0x10000040, 0x10001000, 0x00001040, + 0x00041000, 0x00040040, 0x10040040, 0x10041000, + 0x00001040, 0x00000000, 0x00000000, 0x10040040, + 0x10000040, 0x10001000, 0x00041040, 0x00040000, + 0x00041040, 0x00040000, 0x10041000, 0x00001000, + 0x00000040, 0x10040040, 0x00001000, 0x00041040, + 0x10001000, 0x00000040, 0x10000040, 0x10040000, + 0x10040040, 0x10000000, 0x00040000, 0x10001040, + 0x00000000, 0x10041040, 0x00040040, 0x10000040, + 0x10040000, 0x10001000, 0x10001040, 0x00000000, + 0x10041040, 0x00041000, 0x00041000, 0x00001040, + 0x00001040, 0x00040040, 0x10000000, 0x10041000 + }; + + // Routines taken from other parts of the Acme utilities. + + /// Squash bytes down to ints. + public static void squashBytesToInts( byte[] inBytes, int inOff, int[] outInts, int outOff, int intLen ) + { + for ( int i = 0; i < intLen; ++i ) + outInts[outOff + i] = + ( ( inBytes[inOff + i * 4 ] & 0xff ) << 24 ) | + ( ( inBytes[inOff + i * 4 + 1] & 0xff ) << 16 ) | + ( ( inBytes[inOff + i * 4 + 2] & 0xff ) << 8 ) | + ( inBytes[inOff + i * 4 + 3] & 0xff ); + } + + /// Spread ints into bytes. + public static void spreadIntsToBytes( int[] inInts, int inOff, byte[] outBytes, int outOff, int intLen ) + { + for ( int i = 0; i < intLen; ++i ) + { + outBytes[outOff + i * 4 ] = (byte) ( inInts[inOff + i] >>> 24 ); + outBytes[outOff + i * 4 + 1] = (byte) ( inInts[inOff + i] >>> 16 ); + outBytes[outOff + i * 4 + 2] = (byte) ( inInts[inOff + i] >>> 8 ); + outBytes[outOff + i * 4 + 3] = (byte) inInts[inOff + i]; + } + } + } diff --git a/java/com/tigervnc/rfb/Encoder.java b/java/com/tigervnc/rfb/Encoder.java new file mode 100644 index 00000000..0964f88e --- /dev/null +++ b/java/com/tigervnc/rfb/Encoder.java @@ -0,0 +1,25 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +public class Encoder { + static public boolean supported(int encoding) { + return false; + } +} diff --git a/java/com/tigervnc/rfb/Encodings.java b/java/com/tigervnc/rfb/Encodings.java new file mode 100644 index 00000000..493d5488 --- /dev/null +++ b/java/com/tigervnc/rfb/Encodings.java @@ -0,0 +1,70 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +public class Encodings { + + public static final int encodingRaw = 0; + public static final int encodingCopyRect = 1; + public static final int encodingRRE = 2; + public static final int encodingCoRRE = 4; + public static final int encodingHextile = 5; + public static final int encodingTight = 7; + public static final int encodingZRLE = 16; + + public static final int encodingMax = 255; + + public static final int pseudoEncodingXCursor = -240; + public static final int pseudoEncodingCursor = -239; + public static final int pseudoEncodingDesktopSize = -223; + public static final int pseudoEncodingExtendedDesktopSize = -308; + public static final int pseudoEncodingDesktopName = -307; + public static final int pseudoEncodingClientRedirect = -311; + + // TightVNC-specific + public static final int pseudoEncodingLastRect = -224; + public static final int pseudoEncodingQualityLevel0 = -32; + public static final int pseudoEncodingQualityLevel9 = -23; + public static final int pseudoEncodingCompressLevel0 = -256; + public static final int pseudoEncodingCompressLevel9 = -247; + + public static int encodingNum(String name) { + if (name.equalsIgnoreCase("raw")) return encodingRaw; + if (name.equalsIgnoreCase("copyRect")) return encodingCopyRect; + if (name.equalsIgnoreCase("RRE")) return encodingRRE; + if (name.equalsIgnoreCase("coRRE")) return encodingCoRRE; + if (name.equalsIgnoreCase("hextile")) return encodingHextile; + if (name.equalsIgnoreCase("Tight")) return encodingTight; + if (name.equalsIgnoreCase("ZRLE")) return encodingZRLE; + return -1; + } + + public static String encodingName(int num) { + switch (num) { + case encodingRaw: return "raw"; + case encodingCopyRect: return "copyRect"; + case encodingRRE: return "RRE"; + case encodingCoRRE: return "CoRRE"; + case encodingHextile: return "hextile"; + case encodingTight: return "Tight"; + case encodingZRLE: return "ZRLE"; + default: return "[unknown encoding]"; + } + } +} diff --git a/java/com/tigervnc/rfb/Exception.java b/java/com/tigervnc/rfb/Exception.java new file mode 100644 index 00000000..26ac355b --- /dev/null +++ b/java/com/tigervnc/rfb/Exception.java @@ -0,0 +1,23 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +public class Exception extends com.tigervnc.rdr.Exception { + public Exception(String s) { super(s); } +} diff --git a/java/com/tigervnc/rfb/Hextile.java b/java/com/tigervnc/rfb/Hextile.java new file mode 100644 index 00000000..9c05b729 --- /dev/null +++ b/java/com/tigervnc/rfb/Hextile.java @@ -0,0 +1,27 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +public class Hextile { + public static final int raw = (1 << 0); + public static final int bgSpecified = (1 << 1); + public static final int fgSpecified = (1 << 2); + public static final int anySubrects = (1 << 3); + public static final int subrectsColoured = (1 << 4); +} diff --git a/java/com/tigervnc/rfb/HextileDecoder.java b/java/com/tigervnc/rfb/HextileDecoder.java new file mode 100644 index 00000000..4c32b52c --- /dev/null +++ b/java/com/tigervnc/rfb/HextileDecoder.java @@ -0,0 +1,101 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +import com.tigervnc.rdr.*; + +public class HextileDecoder extends Decoder { + + public HextileDecoder(CMsgReader reader_) { reader = reader_; } + + public void readRect(Rect r, CMsgHandler handler) { + InStream is = reader.getInStream(); + int bytesPerPixel = handler.cp.pf().bpp / 8; + boolean bigEndian = handler.cp.pf().bigEndian; + + int[] buf = reader.getImageBuf(16 * 16 * 4); + + Rect t = new Rect(); + int bg = 0; + int fg = 0; + + for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 16) { + + t.br.y = Math.min(r.br.y, t.tl.y + 16); + + for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 16) { + + t.br.x = Math.min(r.br.x, t.tl.x + 16); + + int tileType = is.readU8(); + + if ((tileType & Hextile.raw) != 0) { + is.readPixels(buf, t.area(), bytesPerPixel, bigEndian); + handler.imageRect(t, buf); + continue; + } + + if ((tileType & Hextile.bgSpecified) != 0) + bg = is.readPixel(bytesPerPixel, bigEndian); + + int len = t.area(); + int ptr = 0; + while (len-- > 0) buf[ptr++] = bg; + + if ((tileType & Hextile.fgSpecified) != 0) + fg = is.readPixel(bytesPerPixel, bigEndian); + + if ((tileType & Hextile.anySubrects) != 0) { + int nSubrects = is.readU8(); + + for (int i = 0; i < nSubrects; i++) { + + if ((tileType & Hextile.subrectsColoured) != 0) + fg = is.readPixel(bytesPerPixel, bigEndian); + + int xy = is.readU8(); + int wh = is.readU8(); + +/* + Rect s = new Rect(); + s.tl.x = t.tl.x + ((xy >> 4) & 15); + s.tl.y = t.tl.y + (xy & 15); + s.br.x = s.tl.x + ((wh >> 4) & 15) + 1; + s.br.y = s.tl.y + (wh & 15) + 1; +*/ + int x = ((xy >> 4) & 15); + int y = (xy & 15); + int w = ((wh >> 4) & 15) + 1; + int h = (wh & 15) + 1; + ptr = y * t.width() + x; + int rowAdd = t.width() - w; + while (h-- > 0) { + len = w; + while (len-- > 0) buf[ptr++] = fg; + ptr += rowAdd; + } + } + } + handler.imageRect(t, buf); + } + } + } + + CMsgReader reader; +} diff --git a/java/com/tigervnc/rfb/Hostname.java b/java/com/tigervnc/rfb/Hostname.java new file mode 100644 index 00000000..42fda537 --- /dev/null +++ b/java/com/tigervnc/rfb/Hostname.java @@ -0,0 +1,41 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +public class Hostname { + + public static String getHost(String vncServerName) { + int colonPos = vncServerName.indexOf(':'); + if (colonPos == 0) + return "localhost"; + if (colonPos == -1) + colonPos = vncServerName.length(); + return vncServerName.substring(0, colonPos); + } + + public static int getPort(String vncServerName) { + int colonPos = vncServerName.indexOf(':'); + if (colonPos == -1 || colonPos == vncServerName.length()-1) + return 5900; + if (vncServerName.charAt(colonPos+1) == ':') { + return Integer.parseInt(vncServerName.substring(colonPos+2)); + } + return Integer.parseInt(vncServerName.substring(colonPos+1)) + 5900; + } +} diff --git a/java/com/tigervnc/rfb/IntParameter.java b/java/com/tigervnc/rfb/IntParameter.java new file mode 100644 index 00000000..877063e7 --- /dev/null +++ b/java/com/tigervnc/rfb/IntParameter.java @@ -0,0 +1,44 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +public class IntParameter extends VoidParameter { + public IntParameter(String name_, String desc_, int v) { + super(name_, desc_); + value = v; + defValue = v; + } + + public boolean setParam(String v) { + try { + value = Integer.parseInt(v); + } catch (NumberFormatException e) { + return false; + } + return true; + } + + public String getDefaultStr() { return Integer.toString(defValue); } + public String getValueStr() { return Integer.toString(value); } + + public int getValue() { return value; } + + protected int value; + protected int defValue; +} diff --git a/java/com/tigervnc/rfb/Keysyms.java b/java/com/tigervnc/rfb/Keysyms.java new file mode 100644 index 00000000..6bfafeaf --- /dev/null +++ b/java/com/tigervnc/rfb/Keysyms.java @@ -0,0 +1,88 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// Keysyms - defines X keysyms for non-character keys. All keysyms +// corresponding to characters should be generated by calling +// UnicodeToKeysym.translate(). +// + +package com.tigervnc.rfb; + +public class Keysyms { + + public static final int BackSpace = 0xFF08; + public static final int Tab = 0xFF09; + public static final int Linefeed = 0xFF0A; + public static final int Clear = 0xFF0B; + public static final int Return = 0xFF0D; + public static final int Pause = 0xFF13; + public static final int Scroll_Lock = 0xFF14; + public static final int Sys_Req = 0xFF15; + public static final int Escape = 0xFF1B; + public static final int Delete = 0xFFFF; + + public static final int Home = 0xFF50; + public static final int Left = 0xFF51; + public static final int Up = 0xFF52; + public static final int Right = 0xFF53; + public static final int Down = 0xFF54; + public static final int Prior = 0xFF55; + public static final int Page_Up = 0xFF55; + public static final int Next = 0xFF56; + public static final int Page_Down = 0xFF56; + public static final int End = 0xFF57; + public static final int Begin = 0xFF58; + + public static final int Select = 0xFF60; + public static final int Print = 0xFF61; + public static final int Execute = 0xFF62; + public static final int Insert = 0xFF63; + public static final int Undo = 0xFF65; + public static final int Redo = 0xFF66; + public static final int Menu = 0xFF67; + public static final int Find = 0xFF68; + public static final int Cancel = 0xFF69; + public static final int Help = 0xFF6A; + public static final int Break = 0xFF6B; + public static final int Mode_switch = 0xFF7E; + public static final int script_switch = 0xFF7E; + public static final int Num_Lock = 0xFF7F; + + public static final int F1 = 0xFFBE; + public static final int F2 = 0xFFBF; + public static final int F3 = 0xFFC0; + public static final int F4 = 0xFFC1; + public static final int F5 = 0xFFC2; + public static final int F6 = 0xFFC3; + public static final int F7 = 0xFFC4; + public static final int F8 = 0xFFC5; + public static final int F9 = 0xFFC6; + public static final int F10 = 0xFFC7; + public static final int F11 = 0xFFC8; + public static final int F12 = 0xFFC9; + + public static final int Shift_L = 0xFFE1; + public static final int Shift_R = 0xFFE2; + public static final int Control_L = 0xFFE3; + public static final int Control_R = 0xFFE4; + public static final int Meta_L = 0xFFE7; + public static final int Meta_R = 0xFFE8; + public static final int Alt_L = 0xFFE9; + public static final int Alt_R = 0xFFEA; +} diff --git a/java/com/tigervnc/rfb/LogWriter.java b/java/com/tigervnc/rfb/LogWriter.java new file mode 100644 index 00000000..c5730531 --- /dev/null +++ b/java/com/tigervnc/rfb/LogWriter.java @@ -0,0 +1,99 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +public class LogWriter { + + public LogWriter(String name_) { + name = name_; + level = globalLogLevel; + next = log_writers; + log_writers = this; + } + + public void setLevel(int level_) { level = level_; } + + public void write(int level, String str) { + if (level <= this.level) { + System.err.println(name+": "+str); + } + } + + public void error(String str) { write(0, str); } + public void status(String str) { write(10, str); } + public void info(String str) { write(30, str); } + public void debug(String str) { write(100, str); } + + public static boolean setLogParams(String params) { + globalLogLevel = Integer.parseInt(params); + LogWriter current = log_writers; + while (current != null) { + current.setLevel(globalLogLevel); + current = current.next; + } + return true; +// int colon = params.indexOf(':'); +// String logwriter_name = params.substring(0, colon); +// params = params.substring(colon+1); +// colon = params.indexOf(':'); +// String logger_name = params.substring(0, colon); +// params = params.substring(colon+1); +// int level = Integer.parseInt(params); +// // XXX ignore logger name for the moment + +// System.err.println("setting level to "+level); +// System.err.println("logwriters is "+log_writers); +// if (logwriter_name.equals("*")) { +// LogWriter current = log_writers; +// while (current != null) { +// //current.setLog(logger); +// System.err.println("setting level of "+current.name+" to "+level); +// current.setLevel(level); +// current = current.next; +// } +// return true; +// } + +// LogWriter logwriter = getLogWriter(logwriter_name); +// if (logwriter == null) { +// System.err.println("no logwriter found: "+logwriter_name); +// return false; +// } + +// //logwriter.setLog(logger); +// logwriter.setLevel(level); +// return true; + } + + + static LogWriter getLogWriter(String name) { + LogWriter current = log_writers; + while (current != null) { + if (name.equalsIgnoreCase(current.name)) return current; + current = current.next; + } + return null; + } + + String name; + int level; + LogWriter next; + static LogWriter log_writers; + static int globalLogLevel = 30; +} diff --git a/java/com/tigervnc/rfb/ManagedPixelBuffer.java b/java/com/tigervnc/rfb/ManagedPixelBuffer.java new file mode 100644 index 00000000..46b5acf7 --- /dev/null +++ b/java/com/tigervnc/rfb/ManagedPixelBuffer.java @@ -0,0 +1,38 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +public class ManagedPixelBuffer extends PixelBuffer { + public void setSize(int w, int h) { + width_ = w; + height_ = h; + checkDataSize(); + } + public void setPF(PixelFormat pf) { + super.setPF(pf); + checkDataSize(); + } + + public int dataLen() { return area(); } + + final void checkDataSize() { + if (data == null || data.length < dataLen()) + data = new int[dataLen()]; + } +} diff --git a/java/com/tigervnc/rfb/MsgTypes.java b/java/com/tigervnc/rfb/MsgTypes.java new file mode 100644 index 00000000..a009b396 --- /dev/null +++ b/java/com/tigervnc/rfb/MsgTypes.java @@ -0,0 +1,40 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +public class MsgTypes { + // server to client + + public static final int msgTypeFramebufferUpdate = 0; + public static final int msgTypeSetColourMapEntries = 1; + public static final int msgTypeBell = 2; + public static final int msgTypeServerCutText = 3; + + // client to server + + public static final int msgTypeSetPixelFormat = 0; + public static final int msgTypeFixColourMapEntries = 1; + public static final int msgTypeSetEncodings = 2; + public static final int msgTypeFramebufferUpdateRequest = 3; + public static final int msgTypeKeyEvent = 4; + public static final int msgTypePointerEvent = 5; + public static final int msgTypeClientCutText = 6; + + public static final int msgTypeSetDesktopSize = 251; +} diff --git a/java/com/tigervnc/rfb/PixelBuffer.java b/java/com/tigervnc/rfb/PixelBuffer.java new file mode 100644 index 00000000..f87fead8 --- /dev/null +++ b/java/com/tigervnc/rfb/PixelBuffer.java @@ -0,0 +1,116 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// PixelBuffer - note that this code is only written for the 8, 16, and 32 bpp cases at the +// moment. +// + +package com.tigervnc.rfb; + +import java.awt.image.*; + +public class PixelBuffer { + + public PixelBuffer() { + setPF(new PixelFormat()); + } + + public void setPF(PixelFormat pf) { + if (!(pf.bpp == 32) && !(pf.bpp == 16) && !(pf.bpp == 8)) + throw new Exception("Internal error: bpp must be 8, 16, or 32 in PixelBuffer ("+pf.bpp+")"); + format = pf; + switch (pf.depth) { + case 8: + //cm = new IndexColorModel(8, 256, new byte[256], new byte[256], new byte[256]); + cm = new DirectColorModel(8, 7, (7 << 3), (3 << 6)); + break; + case 16: + cm = new DirectColorModel(32, 0xF800, 0x07C0, 0x003E, (0xff << 24)); + break; + case 24: + cm = new DirectColorModel(32, (0xff << 16), (0xff << 8), 0xff, (0xff << 24)); + break; + } + } + public PixelFormat getPF() { return format; } + + public final int width() { return width_; } + public final int height() { return height_; } + public final int area() { return width_ * height_; } + + public void fillRect(int x, int y, int w, int h, int pix) { + for (int ry = y; ry < y + h; ry++) + for (int rx = x; rx < x + w; rx++) + data[ry * width_ + rx] = pix; + } + + public void imageRect(int x, int y, int w, int h, int[] pix) { + for (int j = 0; j < h; j++) + System.arraycopy(pix, (w * j), data, width_ * (y + j) + x, w); + } + + public void copyRect(int x, int y, int w, int h, int srcX, int srcY) { + int dest = (width_ * y) + x; + int src = (width_ * srcY) + srcX; + int inc = width_; + + if (y > srcY) { + src += (h-1) * inc; + dest += (h-1) * inc; + inc = -inc; + } + int destEnd = dest + h * inc; + + while (dest != destEnd) { + System.arraycopy(data, src, data, dest, w); + src += inc; + dest += inc; + } + } + + public void maskRect(int x, int y, int w, int h, int[] pix, byte[] mask) { + int maskBytesPerRow = (w + 7) / 8; + + for (int j = 0; j < h; j++) { + int cy = y + j; + + if (cy < 0 || cy >= height_) + continue; + + for (int i = 0; i < w; i++) { + int cx = x + i; + + if (cx < 0 || cx >= width_) + continue; + + int byte_ = j * maskBytesPerRow + i / 8; + int bit = 7 - i % 8; + + if ((mask[byte_] & (1 << bit)) != 0) + data[cy * width_ + cx] = pix[j * w + i]; + } + } + } + + public int[] data; + public ColorModel cm; + + protected PixelFormat format; + protected int width_, height_; +} diff --git a/java/com/tigervnc/rfb/PixelFormat.java b/java/com/tigervnc/rfb/PixelFormat.java new file mode 100644 index 00000000..a8ab5f11 --- /dev/null +++ b/java/com/tigervnc/rfb/PixelFormat.java @@ -0,0 +1,163 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// PixelFormat +// + +package com.tigervnc.rfb; + +import com.tigervnc.rdr.*; + +public class PixelFormat { + + public PixelFormat(int b, int d, boolean e, boolean t) { + bpp = b; + depth = d; + bigEndian = e; + trueColour = t; + } + public PixelFormat(int b, int d, boolean e, boolean t, + int rm, int gm, int bm, int rs, int gs, int bs) { + this(b, d, e, t); + redMax = rm; + greenMax = gm; + blueMax = bm; + redShift = rs; + greenShift = gs; + blueShift = bs; + } + public PixelFormat() { this(8,8,false,true,7,7,3,0,3,6); } + + public boolean equal(PixelFormat x) { + return (bpp == x.bpp && + depth == x.depth && + (bigEndian == x.bigEndian || bpp == 8) && + trueColour == x.trueColour && + (!trueColour || (redMax == x.redMax && + greenMax == x.greenMax && + blueMax == x.blueMax && + redShift == x.redShift && + greenShift == x.greenShift && + blueShift == x.blueShift))); + } + + public void read(InStream is) { + bpp = is.readU8(); + depth = is.readU8(); + bigEndian = is.readU8()!=0; + trueColour = is.readU8()!=0; + redMax = is.readU16(); + greenMax = is.readU16(); + blueMax = is.readU16(); + redShift = is.readU8(); + greenShift = is.readU8(); + blueShift = is.readU8(); + is.skip(3); + } + + public void write(OutStream os) { + os.writeU8(bpp); + os.writeU8(depth); + os.writeU8(bigEndian?1:0); + os.writeU8(trueColour?1:0); + os.writeU16(redMax); + os.writeU16(greenMax); + os.writeU16(blueMax); + os.writeU8(redShift); + os.writeU8(greenShift); + os.writeU8(blueShift); + os.pad(3); + } + + public final boolean is888() { + if(!trueColour) + return false; + if(bpp != 32) + return false; + if(depth != 24) + return false; + if(redMax != 255) + return false; + if(greenMax != 255) + return false; + if(blueMax != 255) + return false; + + return true; + } + + public void bufferFromRGB(int dst, byte[] src) { + if (bigEndian) { + dst = + (src[0] & 0xFF) << 16 | (src[1] & 0xFF) << 8 | (src[2] & 0xFF) | 0xFF << 24; + } else { + dst = + (src[2] & 0xFF) << 16 | (src[1] & 0xFF) << 8 | (src[0] & 0xFF) | 0xFF << 24; + } + } + + public String print() { + StringBuffer s = new StringBuffer(); + s.append("depth "+depth+" ("+bpp+"bpp)"); + if (bpp != 8) { + if (bigEndian) + s.append(" big-endian"); + else + s.append(" little-endian"); + } + + if (!trueColour) { + s.append(" colour-map"); + return s.toString(); + } + + if (blueShift == 0 && greenShift > blueShift && redShift > greenShift && + blueMax == (1 << greenShift) - 1 && + greenMax == (1 << (redShift-greenShift)) - 1 && + redMax == (1 << (depth-redShift)) - 1) + { + s.append(" rgb"+(depth-redShift)+(redShift-greenShift)+greenShift); + return s.toString(); + } + + if (redShift == 0 && greenShift > redShift && blueShift > greenShift && + redMax == (1 << greenShift) - 1 && + greenMax == (1 << (blueShift-greenShift)) - 1 && + blueMax == (1 << (depth-blueShift)) - 1) + { + s.append(" bgr"+(depth-blueShift)+(blueShift-greenShift)+greenShift); + return s.toString(); + } + + s.append(" rgb max "+redMax+","+greenMax+","+blueMax+" shift "+redShift+ + ","+greenShift+","+blueShift); + return s.toString(); + } + + public int bpp; + public int depth; + public boolean bigEndian; + public boolean trueColour; + public int redMax; + public int greenMax; + public int blueMax; + public int redShift; + public int greenShift; + public int blueShift; +} diff --git a/java/com/tigervnc/rfb/Point.java b/java/com/tigervnc/rfb/Point.java new file mode 100644 index 00000000..25de8c20 --- /dev/null +++ b/java/com/tigervnc/rfb/Point.java @@ -0,0 +1,40 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +public class Point { + + // Point + // + // Represents a point in 2D space, by X and Y coordinates. + // Can also be used to represent a delta, or offset, between + // two Points. + // Functions are provided to allow Points to be compared for + // equality and translated by a supplied offset. + // Functions are also provided to negate offset Points. + + public Point() {x=0; y=0;} + public Point(int x_, int y_) { x=x_; y=y_;} + public final Point negate() {return new Point(-x, -y);} + public final boolean equals(Point p) {return (x==p.x && y==p.y);} + public final Point translate(Point p) {return new Point(x+p.x, y+p.y);} + public final Point subtract(Point p) {return new Point(x-p.x, y-p.y);} + public int x, y; + +} diff --git a/java/com/tigervnc/rfb/RREDecoder.java b/java/com/tigervnc/rfb/RREDecoder.java new file mode 100644 index 00000000..e0ff5cfe --- /dev/null +++ b/java/com/tigervnc/rfb/RREDecoder.java @@ -0,0 +1,46 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +import com.tigervnc.rdr.*; + +public class RREDecoder extends Decoder { + + public RREDecoder(CMsgReader reader_) { reader = reader_; } + + public void readRect(Rect r, CMsgHandler handler) { + InStream is = reader.getInStream(); + int bytesPerPixel = handler.cp.pf().bpp / 8; + boolean bigEndian = handler.cp.pf().bigEndian; + int nSubrects = is.readU32(); + int bg = is.readPixel(bytesPerPixel, bigEndian); + handler.fillRect(r, bg); + + for (int i = 0; i < nSubrects; i++) { + int pix = is.readPixel(bytesPerPixel, bigEndian); + int x = is.readU16(); + int y = is.readU16(); + int w = is.readU16(); + int h = is.readU16(); + handler.fillRect(new Rect(r.tl.x+x, r.tl.y+y, r.tl.x+x+w, r.tl.y+y+h), pix); + } + } + + CMsgReader reader; +} diff --git a/java/com/tigervnc/rfb/RawDecoder.java b/java/com/tigervnc/rfb/RawDecoder.java new file mode 100644 index 00000000..79db8260 --- /dev/null +++ b/java/com/tigervnc/rfb/RawDecoder.java @@ -0,0 +1,45 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +public class RawDecoder extends Decoder { + + public RawDecoder(CMsgReader reader_) { reader = reader_; } + + public void readRect(Rect r, CMsgHandler handler) { + int x = r.tl.x; + int y = r.tl.y; + int w = r.width(); + int h = r.height(); + int[] imageBuf = reader.getImageBuf(w * h); + int nPixels = imageBuf.length / (reader.bpp() / 8); + int bytesPerRow = w * (reader.bpp() / 8); + while (h > 0) { + int nRows = nPixels / w; + if (nRows > h) nRows = h; + reader.is.readPixels(imageBuf, w * h, (reader.bpp() / 8), handler.cp.pf().bigEndian); + handler.imageRect(new Rect(x, y, x+w, y+nRows), imageBuf); + h -= nRows; + y += nRows; + } + } + + CMsgReader reader; + static LogWriter vlog = new LogWriter("RawDecoder"); +} diff --git a/java/com/tigervnc/rfb/Rect.java b/java/com/tigervnc/rfb/Rect.java new file mode 100644 index 00000000..fab4f5dd --- /dev/null +++ b/java/com/tigervnc/rfb/Rect.java @@ -0,0 +1,89 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +public class Rect { + + // Rect + // + // Represents a rectangular region defined by its top-left (tl) + // and bottom-right (br) Points. + // Rects may be compared for equality, checked to determine whether + // or not they are empty, cleared (made empty), or intersected with + // one another. The bounding rectangle of two existing Rects + // may be calculated, as may the area of a Rect. + // Rects may also be translated, in the same way as Points, by + // an offset specified in a Point structure. + + public Rect() { + tl=new Point(0,0); + br=new Point(0,0); + } + public Rect(Point tl_, Point br_) { + tl=new Point(tl_.x, tl_.y); + br=new Point(br_.x,br_.y); + } + public Rect(int x1, int y1, int x2, int y2) { + tl=new Point(x1, y1); + br=new Point(x2, y2); + } + public final void setXYWH(int x, int y, int w, int h) { + tl.x = x; tl.y = y; br.x = x+w; br.y = y+h; + } + public final Rect intersect(Rect r) { + Rect result = new Rect(); + result.tl.x = Math.max(tl.x, r.tl.x); + result.tl.y = Math.max(tl.y, r.tl.y); + result.br.x = Math.max(Math.min(br.x, r.br.x), result.tl.x); + result.br.y = Math.max(Math.min(br.y, r.br.y), result.tl.y); + return result; + } + public final Rect union_boundary(Rect r) { + if (r.is_empty()) return this; + if (is_empty()) return r; + Rect result = new Rect(); + result.tl.x = Math.min(tl.x, r.tl.x); + result.tl.y = Math.min(tl.y, r.tl.y); + result.br.x = Math.max(br.x, r.br.x); + result.br.y = Math.max(br.y, r.br.y); + return result; + } + public final Rect translate(Point p) { + return new Rect(tl.translate(p), br.translate(p)); + } + public final boolean equals(Rect r) {return r.tl.equals(tl) && r.br.equals(br);} + public final boolean is_empty() {return (tl.x >= br.x) || (tl.y >= br.y);} + public final void clear() {tl = new Point(); br = new Point();} + public final boolean enclosed_by(Rect r) { + return (tl.x>=r.tl.x) && (tl.y>=r.tl.y) && (br.x<=r.br.x) && (br.y<=r.br.y); + } + public final boolean overlaps(Rect r) { + return tl.x < r.br.x && tl.y < r.br.y && br.x > r.tl.x && br.y > r.tl.y; + } + public final int area() {return is_empty() ? 0 : (br.x-tl.x)*(br.y-tl.y);} + public final Point dimensions() {return new Point(width(), height());} + public final int width() {return br.x-tl.x;} + public final int height() {return br.y-tl.y;} + public final boolean contains(Point p) { + return (tl.x<=p.x) && (tl.y<=p.y) && (br.x>p.x) && (br.y>p.y); + } + public Point tl; + public Point br; + +} diff --git a/java/com/tigervnc/rfb/Screen.java b/java/com/tigervnc/rfb/Screen.java new file mode 100644 index 00000000..90b22b6d --- /dev/null +++ b/java/com/tigervnc/rfb/Screen.java @@ -0,0 +1,48 @@ +/* Copyright 2009 Pierre Ossman for Cendio AB + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// Represents a single RFB virtual screen, which includes +// coordinates, an id and flags. + +package com.tigervnc.rfb; + +public class Screen { + + public Screen() { id=0; flags=0; dimensions = new Rect(); } + + public Screen(int id_, int x_, int y_, int w_, int h_, int flags_) { + id = id_; + dimensions = new Rect(x_, y_, x_+w_, y_+h_); + flags = flags_; + } + + public final static boolean operator(Screen r) { + if (id != r.id) + return false; + if (!dimensions.equals(r.dimensions)) + return false; + if (flags != r.flags) + return false; + return true; + } + + public static int id; + public static Rect dimensions; + public static int flags; + +} diff --git a/java/com/tigervnc/rfb/ScreenSet.java b/java/com/tigervnc/rfb/ScreenSet.java new file mode 100644 index 00000000..071282ff --- /dev/null +++ b/java/com/tigervnc/rfb/ScreenSet.java @@ -0,0 +1,89 @@ +/* Copyright 2009 Pierre Ossman for Cendio AB + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// Management class for the RFB virtual screens + +package com.tigervnc.rfb; + +import java.util.*; + +public class ScreenSet { + + // Represents a complete screen configuration, excluding framebuffer + // dimensions. + + public ScreenSet() { + screens = new ArrayList<Screen>(); + } + + public static final int num_screens() { return screens.size(); } + + public static final void add_screen(Screen screen) { screens.add(screen); } + public static final void remove_screen(int id) { + for (Iterator iter = screens.iterator(); iter.hasNext(); ) { + Screen refScreen = (Screen)iter.next(); + if (refScreen.id == id) + iter.remove(); + } + } + + public static final boolean validate(int fb_width, int fb_height) { + List<Integer> seen_ids = new ArrayList<Integer>(); + Rect fb_rect = new Rect(); + + if (screens.isEmpty()) + return false; + if (num_screens() > 255) + return false; + + fb_rect.setXYWH(0, 0, fb_width, fb_height); + + for (Iterator iter = screens.iterator(); iter.hasNext(); ) { + Screen refScreen = (Screen)iter.next(); + if (refScreen.dimensions.is_empty()) + return false; + if (!refScreen.dimensions.enclosed_by(fb_rect)) + return false; + //if (seen_ids.lastIndexOf(refScreen.id) != seen_ids.get(-1)) + // return false; + seen_ids.add(refScreen.id); + } + + return true; + } + + public final void debug_print() { + for (Iterator iter = screens.iterator(); iter.hasNext(); ) { + Screen refScreen = (Screen)iter.next(); + vlog.error(" "+refScreen.id+" (0x"+refScreen.id+"): "+ + refScreen.dimensions.width()+"x"+refScreen.dimensions.height()+ + "+"+refScreen.dimensions.tl.x+"+"+refScreen.dimensions.tl.y+ + " (flags 0x"+refScreen.flags+")"); + } + } + + // FIXME: List order shouldn't matter + //inline bool operator(const ScreenSet& r) const { return screens == r.screens; } + //inline bool operator(const ScreenSet& r) const { return screens != r.screens; } + + public static List<Screen> screens; + + static LogWriter vlog = new LogWriter("ScreenSet"); + +} + diff --git a/java/com/tigervnc/rfb/Security.java b/java/com/tigervnc/rfb/Security.java new file mode 100644 index 00000000..379851d8 --- /dev/null +++ b/java/com/tigervnc/rfb/Security.java @@ -0,0 +1,195 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// SecTypes.java - constants for the various security types. +// + +package com.tigervnc.rfb; +import java.util.*; + +public class Security { + + public static final int secTypeInvalid = 0; + public static final int secTypeNone = 1; + public static final int secTypeVncAuth = 2; + + public static final int secTypeRA2 = 5; + public static final int secTypeRA2ne = 6; + + public static final int secTypeSSPI = 7; + public static final int secTypeSSPIne = 8; + + public static final int secTypeTight = 16; + public static final int secTypeUltra = 17; + public static final int secTypeTLS = 18; + public static final int secTypeVeNCrypt = 19; + + /* VeNCrypt subtypes */ + public static final int secTypePlain = 256; + public static final int secTypeTLSNone = 257; + public static final int secTypeTLSVnc = 258; + public static final int secTypeTLSPlain = 259; + public static final int secTypeX509None = 260; + public static final int secTypeX509Vnc = 261; + public static final int secTypeX509Plain = 262; + public static final int secTypeIdent = 265; + public static final int secTypeTLSIdent = 266; + public static final int secTypeX509Ident = 267; + + // result types + + public static final int secResultOK = 0; + public static final int secResultFailed = 1; + public static final int secResultTooMany = 2; // deprecated + + public Security(StringParameter secTypes) + { + String secTypesStr; + + secTypesStr = secTypes.getData(); + enabledSecTypes = parseSecTypes(secTypesStr); + + secTypesStr = null; + } + + public static List<Integer> enabledSecTypes = new ArrayList<Integer>(); + + public static final List<Integer> GetEnabledSecTypes() + { + List<Integer> result = new ArrayList<Integer>(); + + result.add(secTypeVeNCrypt); + for (Iterator i = enabledSecTypes.iterator(); i.hasNext(); ) { + int refType = (Integer)i.next(); + if (refType < 0x100) + result.add(refType); + } + + return (result); + } + + public static final List<Integer> GetEnabledExtSecTypes() + { + List<Integer> result = new ArrayList<Integer>(); + + for (Iterator i = enabledSecTypes.iterator(); i.hasNext(); ) { + int refType = (Integer)i.next(); + if (refType != secTypeVeNCrypt) /* Do not include VeNCrypt to avoid loops */ + result.add(refType); + } + + return (result); + } + + public static final void EnableSecType(int secType) + { + + for (Iterator i = enabledSecTypes.iterator(); i.hasNext(); ) + if ((Integer)i.next() == secType) + return; + + enabledSecTypes.add(secType); + } + + public boolean IsSupported(int secType) + { + Iterator i; + + for (i = enabledSecTypes.iterator(); i.hasNext(); ) + if ((Integer)i.next() == secType) + return true; + if (secType == secTypeVeNCrypt) + return true; + + return false; + } + + public static void DisableSecType(int secType) { enabledSecTypes.remove((Object)secType); } + + public static int secTypeNum(String name) { + if (name.equalsIgnoreCase("None")) return secTypeNone; + if (name.equalsIgnoreCase("VncAuth")) return secTypeVncAuth; + if (name.equalsIgnoreCase("Tight")) return secTypeTight; + if (name.equalsIgnoreCase("RA2")) return secTypeRA2; + if (name.equalsIgnoreCase("RA2ne")) return secTypeRA2ne; + if (name.equalsIgnoreCase("SSPI")) return secTypeSSPI; + if (name.equalsIgnoreCase("SSPIne")) return secTypeSSPIne; + //if (name.equalsIgnoreCase("ultra")) return secTypeUltra; + //if (name.equalsIgnoreCase("TLS")) return secTypeTLS; + if (name.equalsIgnoreCase("VeNCrypt")) return secTypeVeNCrypt; + + /* VeNCrypt subtypes */ + if (name.equalsIgnoreCase("Plain")) return secTypePlain; + if (name.equalsIgnoreCase("Ident")) return secTypeIdent; + if (name.equalsIgnoreCase("TLSNone")) return secTypeTLSNone; + if (name.equalsIgnoreCase("TLSVnc")) return secTypeTLSVnc; + if (name.equalsIgnoreCase("TLSPlain")) return secTypeTLSPlain; + if (name.equalsIgnoreCase("TLSIdent")) return secTypeTLSIdent; + if (name.equalsIgnoreCase("X509None")) return secTypeX509None; + if (name.equalsIgnoreCase("X509Vnc")) return secTypeX509Vnc; + if (name.equalsIgnoreCase("X509Plain")) return secTypeX509Plain; + if (name.equalsIgnoreCase("X509Ident")) return secTypeX509Ident; + + return secTypeInvalid; + } + + public static String secTypeName(int num) { + switch (num) { + case secTypeNone: return "None"; + case secTypeVncAuth: return "VncAuth"; + case secTypeTight: return "Tight"; + case secTypeRA2: return "RA2"; + case secTypeRA2ne: return "RA2ne"; + case secTypeSSPI: return "SSPI"; + case secTypeSSPIne: return "SSPIne"; + //case secTypeUltra: return "Ultra"; + //case secTypeTLS: return "TLS"; + case secTypeVeNCrypt: return "VeNCrypt"; + + /* VeNCrypt subtypes */ + case secTypePlain: return "Plain"; + case secTypeIdent: return "Ident"; + case secTypeTLSNone: return "TLSNone"; + case secTypeTLSVnc: return "TLSVnc"; + case secTypeTLSPlain: return "TLSPlain"; + case secTypeTLSIdent: return "TLSIdent"; + case secTypeX509None: return "X509None"; + case secTypeX509Vnc: return "X509Vnc"; + case secTypeX509Plain: return "X509Plain"; + case secTypeX509Ident: return "X509Ident"; + default: return "[unknown secType]"; + } + } + + public final static List<Integer> parseSecTypes(String types_) + { + List<Integer> result = new ArrayList<Integer>(); + String[] types = types_.split(","); + for (int i = 0; i < types.length; i++) { + int typeNum = secTypeNum(types[i]); + if (typeNum != secTypeInvalid) + result.add(typeNum); + } + return (result); + } + + public final void SetSecTypes(List<Integer> secTypes) { enabledSecTypes = secTypes; } + + static LogWriter vlog = new LogWriter("Security"); +} diff --git a/java/com/tigervnc/rfb/SecurityClient.java b/java/com/tigervnc/rfb/SecurityClient.java new file mode 100644 index 00000000..a8abd9e1 --- /dev/null +++ b/java/com/tigervnc/rfb/SecurityClient.java @@ -0,0 +1,85 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright (C) 2010 TigerVNC Team + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +import com.tigervnc.vncviewer.CConn; + +public class SecurityClient extends Security { + + public SecurityClient() { super(secTypes); } + + public CSecurity GetCSecurity(int secType) + { + assert (CConn.upg != null); /* (upg == null) means bug in the viewer */ + assert (msg != null); + + if (!IsSupported(secType)) + throw new Exception("Security type not supported"); + + switch (secType) { + case Security.secTypeNone: return (new CSecurityNone()); + case Security.secTypeVncAuth: return (new CSecurityVncAuth()); + case Security.secTypeVeNCrypt: return (new CSecurityVeNCrypt(this)); + case Security.secTypePlain: return (new CSecurityPlain()); + case Security.secTypeIdent: return (new CSecurityIdent()); + case Security.secTypeTLSNone: + return (new CSecurityStack(secTypeTLSNone, "TLS with no password", + new CSecurityTLS(true), null)); + case Security.secTypeTLSVnc: + return (new CSecurityStack(secTypeTLSVnc, "TLS with VNCAuth", + new CSecurityTLS(true), new CSecurityVncAuth())); + case Security.secTypeTLSPlain: + return (new CSecurityStack(secTypeTLSPlain, "TLS with Username/Password", + new CSecurityTLS(true), new CSecurityPlain())); + case Security.secTypeTLSIdent: + return (new CSecurityStack(secTypeTLSIdent, "TLS with username only", + new CSecurityTLS(true), new CSecurityIdent())); + case Security.secTypeX509None: + return (new CSecurityStack(secTypeX509None, "X509 with no password", + new CSecurityTLS(false), null)); + case Security.secTypeX509Vnc: + return (new CSecurityStack(secTypeX509Vnc, "X509 with VNCAuth", + new CSecurityTLS(false), new CSecurityVncAuth())); + case Security.secTypeX509Plain: + return (new CSecurityStack(secTypeX509Plain, "X509 with Username/Password", + new CSecurityTLS(false), new CSecurityPlain())); + case Security.secTypeX509Ident: + return (new CSecurityStack(secTypeX509Ident, "X509 with username only", + new CSecurityTLS(false), new CSecurityIdent())); + default: + throw new Exception("Security type not supported"); + } + + } + + public static void setDefaults() + { + CSecurityTLS.setDefaults(); + } + + //UserPasswdGetter upg = null; + String msg = null; + + static StringParameter secTypes + = new StringParameter("SecurityTypes", + "Specify which security scheme to use (None, VncAuth)", + "Ident,TLSIdent,X509Ident,X509Plain,TLSPlain,X509Vnc,TLSVnc,X509None,TLSNone,VncAuth,None"); + +} diff --git a/java/com/tigervnc/rfb/StringParameter.java b/java/com/tigervnc/rfb/StringParameter.java new file mode 100644 index 00000000..d7fd1a51 --- /dev/null +++ b/java/com/tigervnc/rfb/StringParameter.java @@ -0,0 +1,46 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +public class StringParameter extends VoidParameter { + public StringParameter(String name_, String desc_, String v) { + super(name_, desc_); + value = v; + defValue = v; + } + + public boolean setParam(String v) { + value = v; + return value != null; + } + + public boolean setDefaultStr(String v) { + value = defValue = v; + return defValue != null; + } + + public String getDefaultStr() { return defValue; } + public String getValueStr() { return value; } + + public String getValue() { return value; } + public String getData() { return value; } + + protected String value; + protected String defValue; +} diff --git a/java/com/tigervnc/rfb/TightDecoder.java b/java/com/tigervnc/rfb/TightDecoder.java new file mode 100644 index 00000000..5cce3a93 --- /dev/null +++ b/java/com/tigervnc/rfb/TightDecoder.java @@ -0,0 +1,426 @@ +/* Copyright (C) 2000-2003 Constantin Kaplinsky. All Rights Reserved. + * Copyright 2004-2005 Cendio AB. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +import com.tigervnc.rdr.InStream; +import com.tigervnc.rdr.ZlibInStream; +import java.awt.image.PixelGrabber; +import java.awt.Image; +import java.util.ArrayList; + +public class TightDecoder extends Decoder { + + final static int TIGHT_MAX_WIDTH = 2048; + + // Compression control + final static int rfbTightExplicitFilter = 0x04; + final static int rfbTightFill = 0x08; + final static int rfbTightJpeg = 0x09; + final static int rfbTightMaxSubencoding = 0x09; + + // Filters to improve compression efficiency + final static int rfbTightFilterCopy = 0x00; + final static int rfbTightFilterPalette = 0x01; + final static int rfbTightFilterGradient = 0x02; + final static int rfbTightMinToCompress = 12; + + public TightDecoder(CMsgReader reader_) { + reader = reader_; + zis = new ZlibInStream[4]; + for (int i = 0; i < 4; i++) + zis[i] = new ZlibInStream(); + } + + public void readRect(Rect r, CMsgHandler handler) + { + InStream is = reader.getInStream(); + int[] buf = reader.getImageBuf(r.width() * r.height()); + boolean cutZeros = false; + PixelFormat myFormat = handler.cp.pf(); + int bpp = handler.cp.pf().bpp; + if (bpp == 32) { + if (myFormat.is888()) { + cutZeros = true; + } + } + + int comp_ctl = is.readU8(); + + int bytesPerPixel = handler.cp.pf().bpp / 8; + boolean bigEndian = handler.cp.pf().bigEndian; + + // Flush zlib streams if we are told by the server to do so. + for (int i = 0; i < 4; i++) { + if ((comp_ctl & 1) != 0) { + zis[i].reset(); + } + comp_ctl >>= 1; + } + + // "Fill" compression type. + if (comp_ctl == rfbTightFill) { + int pix; + if (cutZeros) { + byte[] elem = new byte[3]; + is.readBytes(elem, 0, 3); + if (bigEndian) { + pix = + (elem[2] & 0xFF) << 16 | (elem[1] & 0xFF) << 8 | (elem[0] & 0xFF) | 0xFF << 24; + } else { + pix = + (elem[0] & 0xFF) << 16 | (elem[1] & 0xFF) << 8 | (elem[2] & 0xFF) | 0xFF << 24; + } + } else { + pix = (bpp == 8) ? is.readOpaque8() : is.readOpaque24B(); + } + handler.fillRect(r, pix); + return; + } + + // "JPEG" compression type. + if (comp_ctl == rfbTightJpeg) { + // Read length + int compressedLen = is.readCompactLength(); + if (compressedLen <= 0) + vlog.info("Incorrect data received from the server."); + + // Allocate netbuf and read in data + byte[] netbuf = new byte[compressedLen]; + is.readBytes(netbuf, 0, compressedLen); + + // Create an Image object from the JPEG data. + Image jpeg = java.awt.Toolkit.getDefaultToolkit().createImage(netbuf); + PixelGrabber pg = new PixelGrabber(jpeg, 0, 0, r.width(), r.height(), true); + try { + boolean ret = pg.grabPixels(); + if (!ret) + vlog.info("failed to grab pixels"); + } catch (InterruptedException e) { + e.printStackTrace(); + } + Object pixels = pg.getPixels(); + buf = (pixels instanceof byte[]) ? + convertByteArrayToIntArray((byte[])pixels) : (int[])pixels; + handler.imageRect(r, buf); + return; + } + + // Quit on unsupported compression type. + if (comp_ctl > rfbTightMaxSubencoding) { + throw new Exception("TightDecoder: bad subencoding value received"); + } + + // "Basic" compression type. + int palSize = 0; + int[] palette = new int[256]; + boolean useGradient = false; + + if ((comp_ctl & rfbTightExplicitFilter) != 0) { + int filterId = is.readU8(); + + switch (filterId) { + case rfbTightFilterPalette: + palSize = is.readU8() + 1; + if (cutZeros) { + byte[] elem = new byte[3]; + for (int i = 0; i < palSize; i++) { + is.readBytes(elem, 0, 3); + if (bigEndian) { + palette[i] = + (elem[2] & 0xFF) << 16 | (elem[1] & 0xFF) << 8 | (elem[0] & 0xFF) | 0xFF << 24; + } else { + palette[i] = + (elem[0] & 0xFF) << 16 | (elem[1] & 0xFF) << 8 | (elem[2] & 0xFF) | 0xFF << 24; + } + } + } else { + for (int i = 0; i < palSize; i++) { + palette[i] = (bpp == 8) ? is.readOpaque8() : is.readOpaque24B(); + } + } + break; + case rfbTightFilterGradient: + useGradient = true; + break; + case rfbTightFilterCopy: + break; + default: + throw new Exception("TightDecoder: unknown filter code recieved"); + } + } + + int bppp = bpp; + if (palSize != 0) { + bppp = (palSize <= 2) ? 1 : 8; + } else if (cutZeros) { + bppp = 24; + } + + // Determine if the data should be decompressed or just copied. + int rowSize = (r.width() * bppp + 7) / 8; + int dataSize = r.height() * rowSize; + int streamId = -1; + InStream input; + if (dataSize < rfbTightMinToCompress) { + input = is; + } else { + int length = is.readCompactLength(); + streamId = comp_ctl & 0x03; + zis[streamId].setUnderlying(is, length); + input = (ZlibInStream)zis[streamId]; + } + + if (palSize == 0) { + // Truecolor data. + if (useGradient) { + vlog.info("useGradient"); + if (bpp == 32 && cutZeros) { + vlog.info("FilterGradient24"); + FilterGradient24(r, input, dataSize, buf, handler); + } else { + vlog.info("FilterGradient"); + FilterGradient(r, input, dataSize, buf, handler); + } + } else { + if (cutZeros) { + byte[] elem = new byte[3]; + for (int i = 0; i < r.area(); i++) { + input.readBytes(elem, 0, 3); + if (bigEndian) { + buf[i] = + (elem[2] & 0xFF) << 16 | (elem[1] & 0xFF) << 8 | (elem[0] & 0xFF) | 0xFF << 24; + } else { + buf[i] = + (elem[0] & 0xFF) << 16 | (elem[1] & 0xFF) << 8 | (elem[2] & 0xFF) | 0xFF << 24; + } + } + } else { + for (int ptr=0; ptr < dataSize; ptr++) + buf[ptr] = input.readU8(); + } + } + } else { + int x, y, b; + int ptr = 0; + int bits; + if (palSize <= 2) { + // 2-color palette + for (y = 0; y < r.height(); y++) { + for (x = 0; x < r.width() / 8; x++) { + bits = input.readU8(); + for(b = 7; b >= 0; b--) { + buf[ptr++] = palette[bits >> b & 1]; + } + } + if (r.width() % 8 != 0) { + bits = input.readU8(); + for (b = 7; b >= 8 - r.width() % 8; b--) { + buf[ptr++] = palette[bits >> b & 1]; + } + } + } + } else { + // 256-color palette + for (y = 0; y < r.height(); y++) { + for (x = 0; x < r.width(); x++) { + buf[ptr++] = palette[input.readU8()]; + } + } + } + } + + handler.imageRect(r, buf); + + if (streamId != -1) { + zis[streamId].reset(); + } + } + + private CMsgReader reader; + private ZlibInStream[] zis; + static LogWriter vlog = new LogWriter("TightDecoder"); + + private static int convertByteArrayToInt(byte[] bytes) { + return (bytes[0] << 32) | (bytes[1] << 24) | (bytes[2] << 16) | (bytes[3] << 8) | bytes[4]; + } + + private static byte[] convertIntToByteArray(int integer) { + byte[] bytes = new byte[4]; + bytes[0] =(byte)( integer >> 24 ); + bytes[1] =(byte)( (integer << 8) >> 24 ); + bytes[2] =(byte)( (integer << 16) >> 24 ); + bytes[3] =(byte)( (integer << 24) >> 24 ); + return bytes; + } + private static int[] convertByteArrayToIntArray(byte[] bytes) { + vlog.info("convertByteArrayToIntArray"); + ArrayList<Integer> integers = new ArrayList<Integer>(); + for (int index = 0; index < bytes.length; index += 4) { + byte[] fourBytes = new byte[4]; + fourBytes[0] = bytes[index]; + fourBytes[1] = bytes[index+1]; + fourBytes[2] = bytes[index+2]; + fourBytes[3] = bytes[index+3]; + int integer = convertByteArrayToInt(fourBytes); + integers.add(new Integer(integer)); + } + int[] ints = new int[bytes.length/4]; + for (int index = 0; index < integers.size() ; index++) { + ints[index] = (integers.get(index)).intValue(); + } + return ints; + } + + private static byte[] convertIntArrayToByteArray(int[] integers) { + byte[] bytes = new byte[integers.length*4]; + for (int index = 0; index < integers.length; index++) { + byte[] integerBytes = convertIntToByteArray(integers[index]); + bytes[index*4] = integerBytes[0]; + bytes[1 + (index*4)] = integerBytes[1]; + bytes[2 + (index*4)] = integerBytes[2]; + bytes[3 + (index*4)] = integerBytes[3]; + } + return bytes; + } + + // + // Decode data processed with the "Gradient" filter. + // + + final private void FilterGradient24(Rect r, InStream is, int dataSize, int[] buf, CMsgHandler handler) { + + int x, y, c; + int[] prevRow = new int[TIGHT_MAX_WIDTH * 3]; + int[] thisRow = new int[TIGHT_MAX_WIDTH * 3]; + int[] pix = new int[3]; + int[] est = new int[3]; + + // Allocate netbuf and read in data + int[] netbuf = new int[dataSize]; + for (int i = 0; i < dataSize; i++) + netbuf[i] = is.readU8(); + //is.readBytes(netbuf, 0, dataSize); + + PixelFormat myFormat = handler.cp.pf(); + int rectHeight = r.height(); + int rectWidth = r.width(); + + for (y = 0; y < rectHeight; y++) { + /* First pixel in a row */ + for (c = 0; c < 3; c++) { + pix[c] = netbuf[y*rectWidth*3+c] + prevRow[c]; + thisRow[c] = pix[c]; + } + if (myFormat.bigEndian) { + buf[y*rectWidth] = + (pix[0] & 0xFF) << 16 | (pix[1] & 0xFF) << 8 | (pix[2] & 0xFF) | 0xFF << 24; + } else { + buf[y*rectWidth] = + (pix[2] & 0xFF) << 16 | (pix[1] & 0xFF) << 8 | (pix[0] & 0xFF) | 0xFF << 24; + } + + /* Remaining pixels of a row */ + for (x = 1; x < rectWidth; x++) { + for (c = 0; c < 3; c++) { + est[c] = prevRow[x*3+c] + pix[c] - prevRow[(x-1)*3+c]; + if (est[c] > 0xFF) { + est[c] = 0xFF; + } else if (est[c] < 0) { + est[c] = 0; + } + pix[c] = netbuf[(y*rectWidth+x)*3+c] + est[c]; + thisRow[x*3+c] = pix[c]; + } + if (myFormat.bigEndian) { + buf[y*rectWidth] = + (pix[2] & 0xFF) << 16 | (pix[1] & 0xFF) << 8 | (pix[0] & 0xFF) | 0xFF << 24; + } else { + buf[y*rectWidth] = + (pix[0] & 0xFF) << 16 | (pix[1] & 0xFF) << 8 | (pix[2] & 0xFF) | 0xFF << 24; + } + } + + System.arraycopy(thisRow, 0, prevRow, 0, prevRow.length); + } + } + + final private void FilterGradient(Rect r, InStream is, int dataSize, int[] buf, CMsgHandler handler) { + + int x, y, c; + int[] prevRow = new int[TIGHT_MAX_WIDTH]; + int[] thisRow = new int[TIGHT_MAX_WIDTH]; + int[] pix = new int[3]; + int[] est = new int[3]; + + // Allocate netbuf and read in data + int[] netbuf = new int[dataSize]; + for (int i = 0; i < dataSize; i++) + netbuf[i] = is.readU8(); + //is.readBytes(netbuf, 0, dataSize); + + PixelFormat myFormat = handler.cp.pf(); + int rectHeight = r.height(); + int rectWidth = r.width(); + + for (y = 0; y < rectHeight; y++) { + /* First pixel in a row */ + if (myFormat.bigEndian) { + buf[y*rectWidth] = + (pix[2] & 0xFF) << 16 | (pix[1] & 0xFF) << 8 | (pix[0] & 0xFF) | 0xFF << 24; + } else { + buf[y*rectWidth] = + (pix[0] & 0xFF) << 16 | (pix[1] & 0xFF) << 8 | (pix[2] & 0xFF) | 0xFF << 24; + } + for (c = 0; c < 3; c++) + pix[c] += prevRow[c]; + + /* Remaining pixels of a row */ + for (x = 1; x < rectWidth; x++) { + for (c = 0; c < 3; c++) { + est[c] = prevRow[x*3+c] + pix[c] - prevRow[(x-1)*3+c]; + if (est[c] > 255) { + est[c] = 255; + } else if (est[c] < 0) { + est[c] = 0; + } + } + + // FIXME? + System.arraycopy(pix, 0, netbuf, 0, netbuf.length); + for (c = 0; c < 3; c++) + pix[c] += est[c]; + + System.arraycopy(thisRow, x*3, pix, 0, pix.length); + + if (myFormat.bigEndian) { + buf[y*rectWidth+x] = + (pix[2] & 0xFF) << 16 | (pix[1] & 0xFF) << 8 | (pix[0] & 0xFF) | 0xFF << 24; + } else { + buf[y*rectWidth+x] = + (pix[0] & 0xFF) << 16 | (pix[1] & 0xFF) << 8 | (pix[2] & 0xFF) | 0xFF << 24; + } + + } + + System.arraycopy(thisRow, 0, prevRow, 0, prevRow.length); + } + } + +} diff --git a/java/com/tigervnc/rfb/UnicodeToKeysym.java b/java/com/tigervnc/rfb/UnicodeToKeysym.java new file mode 100644 index 00000000..44f61ba6 --- /dev/null +++ b/java/com/tigervnc/rfb/UnicodeToKeysym.java @@ -0,0 +1,795 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// UnicodeToKeysym - provides a translate() method to convert from unicode +// characters to the equivalent X keysym. +// + +package com.tigervnc.rfb; + +public class UnicodeToKeysym { + + public static short[][] table = { + { 0x03c0, 0x0100 }, + { 0x03e0, 0x0101 }, + { 0x01c3, 0x0102 }, + { 0x01e3, 0x0103 }, + { 0x01a1, 0x0104 }, + { 0x01b1, 0x0105 }, + { 0x01c6, 0x0106 }, + { 0x01e6, 0x0107 }, + { 0x02c6, 0x0108 }, + { 0x02e6, 0x0109 }, + { 0x02c5, 0x010a }, + { 0x02e5, 0x010b }, + { 0x01c8, 0x010c }, + { 0x01e8, 0x010d }, + { 0x01cf, 0x010e }, + { 0x01ef, 0x010f }, + { 0x01d0, 0x0110 }, + { 0x01f0, 0x0111 }, + { 0x03aa, 0x0112 }, + { 0x03ba, 0x0113 }, + { 0x03cc, 0x0116 }, + { 0x03ec, 0x0117 }, + { 0x01ca, 0x0118 }, + { 0x01ea, 0x0119 }, + { 0x01cc, 0x011a }, + { 0x01ec, 0x011b }, + { 0x02d8, 0x011c }, + { 0x02f8, 0x011d }, + { 0x02ab, 0x011e }, + { 0x02bb, 0x011f }, + { 0x02d5, 0x0120 }, + { 0x02f5, 0x0121 }, + { 0x03ab, 0x0122 }, + { 0x03bb, 0x0123 }, + { 0x02a6, 0x0124 }, + { 0x02b6, 0x0125 }, + { 0x02a1, 0x0126 }, + { 0x02b1, 0x0127 }, + { 0x03a5, 0x0128 }, + { 0x03b5, 0x0129 }, + { 0x03cf, 0x012a }, + { 0x03ef, 0x012b }, + { 0x03c7, 0x012e }, + { 0x03e7, 0x012f }, + { 0x02a9, 0x0130 }, + { 0x02b9, 0x0131 }, + { 0x02ac, 0x0134 }, + { 0x02bc, 0x0135 }, + { 0x03d3, 0x0136 }, + { 0x03f3, 0x0137 }, + { 0x03a2, 0x0138 }, + { 0x01c5, 0x0139 }, + { 0x01e5, 0x013a }, + { 0x03a6, 0x013b }, + { 0x03b6, 0x013c }, + { 0x01a5, 0x013d }, + { 0x01b5, 0x013e }, + { 0x01a3, 0x0141 }, + { 0x01b3, 0x0142 }, + { 0x01d1, 0x0143 }, + { 0x01f1, 0x0144 }, + { 0x03d1, 0x0145 }, + { 0x03f1, 0x0146 }, + { 0x01d2, 0x0147 }, + { 0x01f2, 0x0148 }, + { 0x03bd, 0x014a }, + { 0x03bf, 0x014b }, + { 0x03d2, 0x014c }, + { 0x03f2, 0x014d }, + { 0x01d5, 0x0150 }, + { 0x01f5, 0x0151 }, + { 0x13bc, 0x0152 }, + { 0x13bd, 0x0153 }, + { 0x01c0, 0x0154 }, + { 0x01e0, 0x0155 }, + { 0x03a3, 0x0156 }, + { 0x03b3, 0x0157 }, + { 0x01d8, 0x0158 }, + { 0x01f8, 0x0159 }, + { 0x01a6, 0x015a }, + { 0x01b6, 0x015b }, + { 0x02de, 0x015c }, + { 0x02fe, 0x015d }, + { 0x01aa, 0x015e }, + { 0x01ba, 0x015f }, + { 0x01a9, 0x0160 }, + { 0x01b9, 0x0161 }, + { 0x01de, 0x0162 }, + { 0x01fe, 0x0163 }, + { 0x01ab, 0x0164 }, + { 0x01bb, 0x0165 }, + { 0x03ac, 0x0166 }, + { 0x03bc, 0x0167 }, + { 0x03dd, 0x0168 }, + { 0x03fd, 0x0169 }, + { 0x03de, 0x016a }, + { 0x03fe, 0x016b }, + { 0x02dd, 0x016c }, + { 0x02fd, 0x016d }, + { 0x01d9, 0x016e }, + { 0x01f9, 0x016f }, + { 0x01db, 0x0170 }, + { 0x01fb, 0x0171 }, + { 0x03d9, 0x0172 }, + { 0x03f9, 0x0173 }, + { 0x13be, 0x0178 }, + { 0x01ac, 0x0179 }, + { 0x01bc, 0x017a }, + { 0x01af, 0x017b }, + { 0x01bf, 0x017c }, + { 0x01ae, 0x017d }, + { 0x01be, 0x017e }, + { 0x08f6, 0x0192 }, + { 0x01b7, 0x02c7 }, + { 0x01a2, 0x02d8 }, + { 0x01ff, 0x02d9 }, + { 0x01b2, 0x02db }, + { 0x01bd, 0x02dd }, + { 0x07ae, 0x0385 }, + { 0x07a1, 0x0386 }, + { 0x07a2, 0x0388 }, + { 0x07a3, 0x0389 }, + { 0x07a4, 0x038a }, + { 0x07a7, 0x038c }, + { 0x07a8, 0x038e }, + { 0x07ab, 0x038f }, + { 0x07b6, 0x0390 }, + { 0x07c1, 0x0391 }, + { 0x07c2, 0x0392 }, + { 0x07c3, 0x0393 }, + { 0x07c4, 0x0394 }, + { 0x07c5, 0x0395 }, + { 0x07c6, 0x0396 }, + { 0x07c7, 0x0397 }, + { 0x07c8, 0x0398 }, + { 0x07c9, 0x0399 }, + { 0x07ca, 0x039a }, + { 0x07cb, 0x039b }, + { 0x07cc, 0x039c }, + { 0x07cd, 0x039d }, + { 0x07ce, 0x039e }, + { 0x07cf, 0x039f }, + { 0x07d0, 0x03a0 }, + { 0x07d1, 0x03a1 }, + { 0x07d2, 0x03a3 }, + { 0x07d4, 0x03a4 }, + { 0x07d5, 0x03a5 }, + { 0x07d6, 0x03a6 }, + { 0x07d7, 0x03a7 }, + { 0x07d8, 0x03a8 }, + { 0x07d9, 0x03a9 }, + { 0x07a5, 0x03aa }, + { 0x07a9, 0x03ab }, + { 0x07b1, 0x03ac }, + { 0x07b2, 0x03ad }, + { 0x07b3, 0x03ae }, + { 0x07b4, 0x03af }, + { 0x07ba, 0x03b0 }, + { 0x07e1, 0x03b1 }, + { 0x07e2, 0x03b2 }, + { 0x07e3, 0x03b3 }, + { 0x07e4, 0x03b4 }, + { 0x07e5, 0x03b5 }, + { 0x07e6, 0x03b6 }, + { 0x07e7, 0x03b7 }, + { 0x07e8, 0x03b8 }, + { 0x07e9, 0x03b9 }, + { 0x07ea, 0x03ba }, + { 0x07eb, 0x03bb }, + { 0x07ec, 0x03bc }, + { 0x07ed, 0x03bd }, + { 0x07ee, 0x03be }, + { 0x07ef, 0x03bf }, + { 0x07f0, 0x03c0 }, + { 0x07f1, 0x03c1 }, + { 0x07f3, 0x03c2 }, + { 0x07f2, 0x03c3 }, + { 0x07f4, 0x03c4 }, + { 0x07f5, 0x03c5 }, + { 0x07f6, 0x03c6 }, + { 0x07f7, 0x03c7 }, + { 0x07f8, 0x03c8 }, + { 0x07f9, 0x03c9 }, + { 0x07b5, 0x03ca }, + { 0x07b9, 0x03cb }, + { 0x07b7, 0x03cc }, + { 0x07b8, 0x03cd }, + { 0x07bb, 0x03ce }, + { 0x06b3, 0x0401 }, + { 0x06b1, 0x0402 }, + { 0x06b2, 0x0403 }, + { 0x06b4, 0x0404 }, + { 0x06b5, 0x0405 }, + { 0x06b6, 0x0406 }, + { 0x06b7, 0x0407 }, + { 0x06b8, 0x0408 }, + { 0x06b9, 0x0409 }, + { 0x06ba, 0x040a }, + { 0x06bb, 0x040b }, + { 0x06bc, 0x040c }, + { 0x06be, 0x040e }, + { 0x06bf, 0x040f }, + { 0x06e1, 0x0410 }, + { 0x06e2, 0x0411 }, + { 0x06f7, 0x0412 }, + { 0x06e7, 0x0413 }, + { 0x06e4, 0x0414 }, + { 0x06e5, 0x0415 }, + { 0x06f6, 0x0416 }, + { 0x06fa, 0x0417 }, + { 0x06e9, 0x0418 }, + { 0x06ea, 0x0419 }, + { 0x06eb, 0x041a }, + { 0x06ec, 0x041b }, + { 0x06ed, 0x041c }, + { 0x06ee, 0x041d }, + { 0x06ef, 0x041e }, + { 0x06f0, 0x041f }, + { 0x06f2, 0x0420 }, + { 0x06f3, 0x0421 }, + { 0x06f4, 0x0422 }, + { 0x06f5, 0x0423 }, + { 0x06e6, 0x0424 }, + { 0x06e8, 0x0425 }, + { 0x06e3, 0x0426 }, + { 0x06fe, 0x0427 }, + { 0x06fb, 0x0428 }, + { 0x06fd, 0x0429 }, + { 0x06ff, 0x042a }, + { 0x06f9, 0x042b }, + { 0x06f8, 0x042c }, + { 0x06fc, 0x042d }, + { 0x06e0, 0x042e }, + { 0x06f1, 0x042f }, + { 0x06c1, 0x0430 }, + { 0x06c2, 0x0431 }, + { 0x06d7, 0x0432 }, + { 0x06c7, 0x0433 }, + { 0x06c4, 0x0434 }, + { 0x06c5, 0x0435 }, + { 0x06d6, 0x0436 }, + { 0x06da, 0x0437 }, + { 0x06c9, 0x0438 }, + { 0x06ca, 0x0439 }, + { 0x06cb, 0x043a }, + { 0x06cc, 0x043b }, + { 0x06cd, 0x043c }, + { 0x06ce, 0x043d }, + { 0x06cf, 0x043e }, + { 0x06d0, 0x043f }, + { 0x06d2, 0x0440 }, + { 0x06d3, 0x0441 }, + { 0x06d4, 0x0442 }, + { 0x06d5, 0x0443 }, + { 0x06c6, 0x0444 }, + { 0x06c8, 0x0445 }, + { 0x06c3, 0x0446 }, + { 0x06de, 0x0447 }, + { 0x06db, 0x0448 }, + { 0x06dd, 0x0449 }, + { 0x06df, 0x044a }, + { 0x06d9, 0x044b }, + { 0x06d8, 0x044c }, + { 0x06dc, 0x044d }, + { 0x06c0, 0x044e }, + { 0x06d1, 0x044f }, + { 0x06a3, 0x0451 }, + { 0x06a1, 0x0452 }, + { 0x06a2, 0x0453 }, + { 0x06a4, 0x0454 }, + { 0x06a5, 0x0455 }, + { 0x06a6, 0x0456 }, + { 0x06a7, 0x0457 }, + { 0x06a8, 0x0458 }, + { 0x06a9, 0x0459 }, + { 0x06aa, 0x045a }, + { 0x06ab, 0x045b }, + { 0x06ac, 0x045c }, + { 0x06ae, 0x045e }, + { 0x06af, 0x045f }, + { 0x0ce0, 0x05d0 }, + { 0x0ce1, 0x05d1 }, + { 0x0ce2, 0x05d2 }, + { 0x0ce3, 0x05d3 }, + { 0x0ce4, 0x05d4 }, + { 0x0ce5, 0x05d5 }, + { 0x0ce6, 0x05d6 }, + { 0x0ce7, 0x05d7 }, + { 0x0ce8, 0x05d8 }, + { 0x0ce9, 0x05d9 }, + { 0x0cea, 0x05da }, + { 0x0ceb, 0x05db }, + { 0x0cec, 0x05dc }, + { 0x0ced, 0x05dd }, + { 0x0cee, 0x05de }, + { 0x0cef, 0x05df }, + { 0x0cf0, 0x05e0 }, + { 0x0cf1, 0x05e1 }, + { 0x0cf2, 0x05e2 }, + { 0x0cf3, 0x05e3 }, + { 0x0cf4, 0x05e4 }, + { 0x0cf5, 0x05e5 }, + { 0x0cf6, 0x05e6 }, + { 0x0cf7, 0x05e7 }, + { 0x0cf8, 0x05e8 }, + { 0x0cf9, 0x05e9 }, + { 0x0cfa, 0x05ea }, + { 0x05ac, 0x060c }, + { 0x05bb, 0x061b }, + { 0x05bf, 0x061f }, + { 0x05c1, 0x0621 }, + { 0x05c2, 0x0622 }, + { 0x05c3, 0x0623 }, + { 0x05c4, 0x0624 }, + { 0x05c5, 0x0625 }, + { 0x05c6, 0x0626 }, + { 0x05c7, 0x0627 }, + { 0x05c8, 0x0628 }, + { 0x05c9, 0x0629 }, + { 0x05ca, 0x062a }, + { 0x05cb, 0x062b }, + { 0x05cc, 0x062c }, + { 0x05cd, 0x062d }, + { 0x05ce, 0x062e }, + { 0x05cf, 0x062f }, + { 0x05d0, 0x0630 }, + { 0x05d1, 0x0631 }, + { 0x05d2, 0x0632 }, + { 0x05d3, 0x0633 }, + { 0x05d4, 0x0634 }, + { 0x05d5, 0x0635 }, + { 0x05d6, 0x0636 }, + { 0x05d7, 0x0637 }, + { 0x05d8, 0x0638 }, + { 0x05d9, 0x0639 }, + { 0x05da, 0x063a }, + { 0x05e0, 0x0640 }, + { 0x05e1, 0x0641 }, + { 0x05e2, 0x0642 }, + { 0x05e3, 0x0643 }, + { 0x05e4, 0x0644 }, + { 0x05e5, 0x0645 }, + { 0x05e6, 0x0646 }, + { 0x05e7, 0x0647 }, + { 0x05e8, 0x0648 }, + { 0x05e9, 0x0649 }, + { 0x05ea, 0x064a }, + { 0x05eb, 0x064b }, + { 0x05ec, 0x064c }, + { 0x05ed, 0x064d }, + { 0x05ee, 0x064e }, + { 0x05ef, 0x064f }, + { 0x05f0, 0x0650 }, + { 0x05f1, 0x0651 }, + { 0x05f2, 0x0652 }, + { 0x0da1, 0x0e01 }, + { 0x0da2, 0x0e02 }, + { 0x0da3, 0x0e03 }, + { 0x0da4, 0x0e04 }, + { 0x0da5, 0x0e05 }, + { 0x0da6, 0x0e06 }, + { 0x0da7, 0x0e07 }, + { 0x0da8, 0x0e08 }, + { 0x0da9, 0x0e09 }, + { 0x0daa, 0x0e0a }, + { 0x0dab, 0x0e0b }, + { 0x0dac, 0x0e0c }, + { 0x0dad, 0x0e0d }, + { 0x0dae, 0x0e0e }, + { 0x0daf, 0x0e0f }, + { 0x0db0, 0x0e10 }, + { 0x0db1, 0x0e11 }, + { 0x0db2, 0x0e12 }, + { 0x0db3, 0x0e13 }, + { 0x0db4, 0x0e14 }, + { 0x0db5, 0x0e15 }, + { 0x0db6, 0x0e16 }, + { 0x0db7, 0x0e17 }, + { 0x0db8, 0x0e18 }, + { 0x0db9, 0x0e19 }, + { 0x0dba, 0x0e1a }, + { 0x0dbb, 0x0e1b }, + { 0x0dbc, 0x0e1c }, + { 0x0dbd, 0x0e1d }, + { 0x0dbe, 0x0e1e }, + { 0x0dbf, 0x0e1f }, + { 0x0dc0, 0x0e20 }, + { 0x0dc1, 0x0e21 }, + { 0x0dc2, 0x0e22 }, + { 0x0dc3, 0x0e23 }, + { 0x0dc4, 0x0e24 }, + { 0x0dc5, 0x0e25 }, + { 0x0dc6, 0x0e26 }, + { 0x0dc7, 0x0e27 }, + { 0x0dc8, 0x0e28 }, + { 0x0dc9, 0x0e29 }, + { 0x0dca, 0x0e2a }, + { 0x0dcb, 0x0e2b }, + { 0x0dcc, 0x0e2c }, + { 0x0dcd, 0x0e2d }, + { 0x0dce, 0x0e2e }, + { 0x0dcf, 0x0e2f }, + { 0x0dd0, 0x0e30 }, + { 0x0dd1, 0x0e31 }, + { 0x0dd2, 0x0e32 }, + { 0x0dd3, 0x0e33 }, + { 0x0dd4, 0x0e34 }, + { 0x0dd5, 0x0e35 }, + { 0x0dd6, 0x0e36 }, + { 0x0dd7, 0x0e37 }, + { 0x0dd8, 0x0e38 }, + { 0x0dd9, 0x0e39 }, + { 0x0dda, 0x0e3a }, + { 0x0ddf, 0x0e3f }, + { 0x0de0, 0x0e40 }, + { 0x0de1, 0x0e41 }, + { 0x0de2, 0x0e42 }, + { 0x0de3, 0x0e43 }, + { 0x0de4, 0x0e44 }, + { 0x0de5, 0x0e45 }, + { 0x0de6, 0x0e46 }, + { 0x0de7, 0x0e47 }, + { 0x0de8, 0x0e48 }, + { 0x0de9, 0x0e49 }, + { 0x0dea, 0x0e4a }, + { 0x0deb, 0x0e4b }, + { 0x0dec, 0x0e4c }, + { 0x0ded, 0x0e4d }, + { 0x0df0, 0x0e50 }, + { 0x0df1, 0x0e51 }, + { 0x0df2, 0x0e52 }, + { 0x0df3, 0x0e53 }, + { 0x0df4, 0x0e54 }, + { 0x0df5, 0x0e55 }, + { 0x0df6, 0x0e56 }, + { 0x0df7, 0x0e57 }, + { 0x0df8, 0x0e58 }, + { 0x0df9, 0x0e59 }, + { 0x0ed4, 0x11a8 }, + { 0x0ed5, 0x11a9 }, + { 0x0ed6, 0x11aa }, + { 0x0ed7, 0x11ab }, + { 0x0ed8, 0x11ac }, + { 0x0ed9, 0x11ad }, + { 0x0eda, 0x11ae }, + { 0x0edb, 0x11af }, + { 0x0edc, 0x11b0 }, + { 0x0edd, 0x11b1 }, + { 0x0ede, 0x11b2 }, + { 0x0edf, 0x11b3 }, + { 0x0ee0, 0x11b4 }, + { 0x0ee1, 0x11b5 }, + { 0x0ee2, 0x11b6 }, + { 0x0ee3, 0x11b7 }, + { 0x0ee4, 0x11b8 }, + { 0x0ee5, 0x11b9 }, + { 0x0ee6, 0x11ba }, + { 0x0ee7, 0x11bb }, + { 0x0ee8, 0x11bc }, + { 0x0ee9, 0x11bd }, + { 0x0eea, 0x11be }, + { 0x0eeb, 0x11bf }, + { 0x0eec, 0x11c0 }, + { 0x0eed, 0x11c1 }, + { 0x0eee, 0x11c2 }, + { 0x0ef8, 0x11eb }, + { 0x0ef9, 0x11f0 }, + { 0x0efa, 0x11f9 }, + { 0x0aa2, 0x2002 }, + { 0x0aa1, 0x2003 }, + { 0x0aa3, 0x2004 }, + { 0x0aa4, 0x2005 }, + { 0x0aa5, 0x2007 }, + { 0x0aa6, 0x2008 }, + { 0x0aa7, 0x2009 }, + { 0x0aa8, 0x200a }, + { 0x0abb, 0x2012 }, + { 0x0aaa, 0x2013 }, + { 0x0aa9, 0x2014 }, + { 0x07af, 0x2015 }, + { 0x0cdf, 0x2017 }, + { 0x0ad0, 0x2018 }, + { 0x0ad1, 0x2019 }, + { 0x0afd, 0x201a }, + { 0x0ad2, 0x201c }, + { 0x0ad3, 0x201d }, + { 0x0afe, 0x201e }, + { 0x0af1, 0x2020 }, + { 0x0af2, 0x2021 }, + { 0x0ae6, 0x2022 }, + { 0x0aaf, 0x2025 }, + { 0x0aae, 0x2026 }, + { 0x0ad6, 0x2032 }, + { 0x0ad7, 0x2033 }, + { 0x0afc, 0x2038 }, + { 0x047e, 0x203e }, + { 0x0eff, 0x20a9 }, + { 0x20ac, 0x20ac }, + { 0x0ab8, 0x2105 }, + { 0x06b0, 0x2116 }, + { 0x0afb, 0x2117 }, + { 0x0ad4, 0x211e }, + { 0x0ac9, 0x2122 }, + { 0x0ab0, 0x2153 }, + { 0x0ab1, 0x2154 }, + { 0x0ab2, 0x2155 }, + { 0x0ab3, 0x2156 }, + { 0x0ab4, 0x2157 }, + { 0x0ab5, 0x2158 }, + { 0x0ab6, 0x2159 }, + { 0x0ab7, 0x215a }, + { 0x0ac3, 0x215b }, + { 0x0ac4, 0x215c }, + { 0x0ac5, 0x215d }, + { 0x0ac6, 0x215e }, + { 0x08fb, 0x2190 }, + { 0x08fc, 0x2191 }, + { 0x08fd, 0x2192 }, + { 0x08fe, 0x2193 }, + { 0x08ce, 0x21d2 }, + { 0x08cd, 0x21d4 }, + { 0x08ef, 0x2202 }, + { 0x08c5, 0x2207 }, + { 0x0bca, 0x2218 }, + { 0x08d6, 0x221a }, + { 0x08c1, 0x221d }, + { 0x08c2, 0x221e }, + { 0x08de, 0x2227 }, + { 0x08df, 0x2228 }, + { 0x08dc, 0x2229 }, + { 0x08dd, 0x222a }, + { 0x08bf, 0x222b }, + { 0x08c0, 0x2234 }, + { 0x08c8, 0x223c }, + { 0x08c9, 0x2243 }, + { 0x08bd, 0x2260 }, + { 0x08cf, 0x2261 }, + { 0x08bc, 0x2264 }, + { 0x08be, 0x2265 }, + { 0x08da, 0x2282 }, + { 0x08db, 0x2283 }, + { 0x0bfc, 0x22a2 }, + { 0x0bdc, 0x22a3 }, + { 0x0bce, 0x22a4 }, + { 0x0bc2, 0x22a5 }, + { 0x0bd3, 0x2308 }, + { 0x0bc4, 0x230a }, + { 0x0afa, 0x2315 }, + { 0x08a4, 0x2320 }, + { 0x08a5, 0x2321 }, + { 0x0abc, 0x2329 }, + { 0x0abe, 0x232a }, + { 0x0bcc, 0x2395 }, + { 0x08ab, 0x239b }, + { 0x08ac, 0x239d }, + { 0x08ad, 0x239e }, + { 0x08ae, 0x23a0 }, + { 0x08a7, 0x23a1 }, + { 0x08a8, 0x23a3 }, + { 0x08a9, 0x23a4 }, + { 0x08aa, 0x23a6 }, + { 0x08af, 0x23a8 }, + { 0x08b0, 0x23ac }, + { 0x08a1, 0x23b7 }, + { 0x09ef, 0x23ba }, + { 0x09f0, 0x23bb }, + { 0x09f2, 0x23bc }, + { 0x09f3, 0x23bd }, + { 0x09e2, 0x2409 }, + { 0x09e5, 0x240a }, + { 0x09e9, 0x240b }, + { 0x09e3, 0x240c }, + { 0x09e4, 0x240d }, + { 0x09e8, 0x2424 }, + { 0x09f1, 0x2500 }, + { 0x09f8, 0x2502 }, + { 0x09ec, 0x250c }, + { 0x09eb, 0x2510 }, + { 0x09ed, 0x2514 }, + { 0x09ea, 0x2518 }, + { 0x09f4, 0x251c }, + { 0x09f5, 0x2524 }, + { 0x09f7, 0x252c }, + { 0x09f6, 0x2534 }, + { 0x09ee, 0x253c }, + { 0x09e1, 0x2592 }, + { 0x0ae7, 0x25aa }, + { 0x0ae1, 0x25ab }, + { 0x0adb, 0x25ac }, + { 0x0ae2, 0x25ad }, + { 0x0adf, 0x25ae }, + { 0x0acf, 0x25af }, + { 0x0ae8, 0x25b2 }, + { 0x0ae3, 0x25b3 }, + { 0x0add, 0x25b6 }, + { 0x0acd, 0x25b7 }, + { 0x0ae9, 0x25bc }, + { 0x0ae4, 0x25bd }, + { 0x0adc, 0x25c0 }, + { 0x0acc, 0x25c1 }, + { 0x09e0, 0x25c6 }, + { 0x0ace, 0x25cb }, + { 0x0ade, 0x25cf }, + { 0x0ae0, 0x25e6 }, + { 0x0ae5, 0x2606 }, + { 0x0af9, 0x260e }, + { 0x0aca, 0x2613 }, + { 0x0aea, 0x261c }, + { 0x0aeb, 0x261e }, + { 0x0af8, 0x2640 }, + { 0x0af7, 0x2642 }, + { 0x0aec, 0x2663 }, + { 0x0aee, 0x2665 }, + { 0x0aed, 0x2666 }, + { 0x0af6, 0x266d }, + { 0x0af5, 0x266f }, + { 0x0af3, 0x2713 }, + { 0x0af4, 0x2717 }, + { 0x0ad9, 0x271d }, + { 0x0af0, 0x2720 }, + { 0x04a4, 0x3001 }, + { 0x04a1, 0x3002 }, + { 0x04a2, 0x300c }, + { 0x04a3, 0x300d }, + { 0x04de, 0x309b }, + { 0x04df, 0x309c }, + { 0x04a7, 0x30a1 }, + { 0x04b1, 0x30a2 }, + { 0x04a8, 0x30a3 }, + { 0x04b2, 0x30a4 }, + { 0x04a9, 0x30a5 }, + { 0x04b3, 0x30a6 }, + { 0x04aa, 0x30a7 }, + { 0x04b4, 0x30a8 }, + { 0x04ab, 0x30a9 }, + { 0x04b5, 0x30aa }, + { 0x04b6, 0x30ab }, + { 0x04b7, 0x30ad }, + { 0x04b8, 0x30af }, + { 0x04b9, 0x30b1 }, + { 0x04ba, 0x30b3 }, + { 0x04bb, 0x30b5 }, + { 0x04bc, 0x30b7 }, + { 0x04bd, 0x30b9 }, + { 0x04be, 0x30bb }, + { 0x04bf, 0x30bd }, + { 0x04c0, 0x30bf }, + { 0x04c1, 0x30c1 }, + { 0x04af, 0x30c3 }, + { 0x04c2, 0x30c4 }, + { 0x04c3, 0x30c6 }, + { 0x04c4, 0x30c8 }, + { 0x04c5, 0x30ca }, + { 0x04c6, 0x30cb }, + { 0x04c7, 0x30cc }, + { 0x04c8, 0x30cd }, + { 0x04c9, 0x30ce }, + { 0x04ca, 0x30cf }, + { 0x04cb, 0x30d2 }, + { 0x04cc, 0x30d5 }, + { 0x04cd, 0x30d8 }, + { 0x04ce, 0x30db }, + { 0x04cf, 0x30de }, + { 0x04d0, 0x30df }, + { 0x04d1, 0x30e0 }, + { 0x04d2, 0x30e1 }, + { 0x04d3, 0x30e2 }, + { 0x04ac, 0x30e3 }, + { 0x04d4, 0x30e4 }, + { 0x04ad, 0x30e5 }, + { 0x04d5, 0x30e6 }, + { 0x04ae, 0x30e7 }, + { 0x04d6, 0x30e8 }, + { 0x04d7, 0x30e9 }, + { 0x04d8, 0x30ea }, + { 0x04d9, 0x30eb }, + { 0x04da, 0x30ec }, + { 0x04db, 0x30ed }, + { 0x04dc, 0x30ef }, + { 0x04a6, 0x30f2 }, + { 0x04dd, 0x30f3 }, + { 0x04a5, 0x30fb }, + { 0x04b0, 0x30fc }, + { 0x0ea1, 0x3131 }, + { 0x0ea2, 0x3132 }, + { 0x0ea3, 0x3133 }, + { 0x0ea4, 0x3134 }, + { 0x0ea5, 0x3135 }, + { 0x0ea6, 0x3136 }, + { 0x0ea7, 0x3137 }, + { 0x0ea8, 0x3138 }, + { 0x0ea9, 0x3139 }, + { 0x0eaa, 0x313a }, + { 0x0eab, 0x313b }, + { 0x0eac, 0x313c }, + { 0x0ead, 0x313d }, + { 0x0eae, 0x313e }, + { 0x0eaf, 0x313f }, + { 0x0eb0, 0x3140 }, + { 0x0eb1, 0x3141 }, + { 0x0eb2, 0x3142 }, + { 0x0eb3, 0x3143 }, + { 0x0eb4, 0x3144 }, + { 0x0eb5, 0x3145 }, + { 0x0eb6, 0x3146 }, + { 0x0eb7, 0x3147 }, + { 0x0eb8, 0x3148 }, + { 0x0eb9, 0x3149 }, + { 0x0eba, 0x314a }, + { 0x0ebb, 0x314b }, + { 0x0ebc, 0x314c }, + { 0x0ebd, 0x314d }, + { 0x0ebe, 0x314e }, + { 0x0ebf, 0x314f }, + { 0x0ec0, 0x3150 }, + { 0x0ec1, 0x3151 }, + { 0x0ec2, 0x3152 }, + { 0x0ec3, 0x3153 }, + { 0x0ec4, 0x3154 }, + { 0x0ec5, 0x3155 }, + { 0x0ec6, 0x3156 }, + { 0x0ec7, 0x3157 }, + { 0x0ec8, 0x3158 }, + { 0x0ec9, 0x3159 }, + { 0x0eca, 0x315a }, + { 0x0ecb, 0x315b }, + { 0x0ecc, 0x315c }, + { 0x0ecd, 0x315d }, + { 0x0ece, 0x315e }, + { 0x0ecf, 0x315f }, + { 0x0ed0, 0x3160 }, + { 0x0ed1, 0x3161 }, + { 0x0ed2, 0x3162 }, + { 0x0ed3, 0x3163 }, + { 0x0eef, 0x316d }, + { 0x0ef0, 0x3171 }, + { 0x0ef1, 0x3178 }, + { 0x0ef2, 0x317f }, + { 0x0ef3, 0x3181 }, + { 0x0ef4, 0x3184 }, + { 0x0ef5, 0x3186 }, + { 0x0ef6, 0x318d }, + { 0x0ef7, 0x318e } + }; + + public static int translate(int unicode) { + if ((unicode >= 0x20 && unicode <= 0x7e) || + (unicode >= 0xa0 && unicode <= 0xff)) + return unicode; + + int min = 0; + int max = table.length - 1; + int mid; + + while (max >= min) { + mid = (min + max) / 2; + if (table[mid][1] < unicode) + min = mid + 1; + else if (table[mid][1] > unicode) + max = mid - 1; + else + return table[mid][0]; + } + + /* no matching Unicode value found */ + return -1; + } +} diff --git a/java/com/tigervnc/rfb/UserMsgBox.java b/java/com/tigervnc/rfb/UserMsgBox.java new file mode 100644 index 00000000..e83d9956 --- /dev/null +++ b/java/com/tigervnc/rfb/UserMsgBox.java @@ -0,0 +1,27 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// getUserPasswd() gets the username and password. This might involve a +// dialog, getpass(), etc. The user buffer pointer can be null, in which case +// no user name will be retrieved. + +package com.tigervnc.rfb; + +public interface UserMsgBox { + public boolean showMsgBox(int flags,String title, String text); +} diff --git a/java/com/tigervnc/rfb/UserPasswdGetter.java b/java/com/tigervnc/rfb/UserPasswdGetter.java new file mode 100644 index 00000000..9796b66f --- /dev/null +++ b/java/com/tigervnc/rfb/UserPasswdGetter.java @@ -0,0 +1,27 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// getUserPasswd() gets the username and password. This might involve a +// dialog, getpass(), etc. The user buffer pointer can be null, in which case +// no user name will be retrieved. + +package com.tigervnc.rfb; + +public interface UserPasswdGetter { + public boolean getUserPasswd(StringBuffer user, StringBuffer password); +} diff --git a/java/com/tigervnc/rfb/VncAuth.java b/java/com/tigervnc/rfb/VncAuth.java new file mode 100644 index 00000000..cce8d81c --- /dev/null +++ b/java/com/tigervnc/rfb/VncAuth.java @@ -0,0 +1,67 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +public class VncAuth { + + public static final int ok = 0; + public static final int failed = 1; + public static final int tooMany = 2; // deprecated + + public static final int challengeSize = 16; + + public static void encryptChallenge(byte[] challenge, String passwd) { + byte[] key = new byte[8]; + for (int i = 0; i < 8 && i < passwd.length(); i++) { + key[i] = (byte)passwd.charAt(i); + } + + DesCipher des = new DesCipher(key); + + for (int j = 0; j < challengeSize; j += 8) + des.encrypt(challenge,j,challenge,j); + } + + void obfuscatePasswd(String passwd, byte[] obfuscated) { + for (int i = 0; i < 8; i++) { + if (i < passwd.length()) + obfuscated[i] = (byte)passwd.charAt(i); + else + obfuscated[i] = 0; + } + DesCipher des = new DesCipher(obfuscationKey); + des.encrypt(obfuscated,0,obfuscated,0); + } + + String unobfuscatePasswd(byte[] obfuscated) { + DesCipher des = new DesCipher(obfuscationKey); + des.decrypt(obfuscated,0,obfuscated,0); + int len; + for (len = 0; len < 8; len++) { + if (obfuscated[len] == 0) break; + } + char[] plain = new char[len]; + for (int i = 0; i < len; i++) { + plain[i] = (char)obfuscated[i]; + } + return new String(plain); + } + + static byte[] obfuscationKey = {23,82,107,6,35,78,88,7}; +} diff --git a/java/com/tigervnc/rfb/VoidParameter.java b/java/com/tigervnc/rfb/VoidParameter.java new file mode 100644 index 00000000..f41f4c84 --- /dev/null +++ b/java/com/tigervnc/rfb/VoidParameter.java @@ -0,0 +1,41 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +abstract public class VoidParameter { + public VoidParameter(String name_, String desc_) { + name = name_; + description = desc_; + next = Configuration.head; + Configuration.head = this; + } + + final public String getName() { return name; } + final public String getDescription() { return description; } + + abstract public boolean setParam(String value); + public boolean setParam() { return false; } + abstract public String getDefaultStr(); + abstract public String getValueStr(); + public boolean isBool() { return false; } + + VoidParameter next; + protected String name; + protected String description; +} diff --git a/java/com/tigervnc/rfb/ZRLEDecoder.java b/java/com/tigervnc/rfb/ZRLEDecoder.java new file mode 100644 index 00000000..4f740f9d --- /dev/null +++ b/java/com/tigervnc/rfb/ZRLEDecoder.java @@ -0,0 +1,166 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +import com.tigervnc.rdr.*; + +public class ZRLEDecoder extends Decoder { + + public ZRLEDecoder(CMsgReader reader_) { + reader = reader_; + zis = new ZlibInStream(); + } + + public void readRect(Rect r, CMsgHandler handler) { + InStream is = reader.getInStream(); + int[] buf = reader.getImageBuf(64 * 64 * 4); + int bytesPerPixel = handler.cp.pf().bpp / 8; + boolean bigEndian = handler.cp.pf().bigEndian; + + int length = is.readU32(); + zis.setUnderlying(is, length); + Rect t = new Rect(); + + for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 64) { + + t.br.y = Math.min(r.br.y, t.tl.y + 64); + + for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 64) { + + t.br.x = Math.min(r.br.x, t.tl.x + 64); + + int mode = zis.readU8(); + boolean rle = (mode & 128) != 0; + int palSize = mode & 127; + int[] palette = new int[128]; + + if (bytesPerPixel > 1) { + zis.readPixels(palette, palSize, 3, bigEndian); + } else { + for (int i = 0; i < palSize; i++) { + palette[i] = zis.readPixel(bytesPerPixel, bigEndian); + } + } + + if (palSize == 1) { + int pix = palette[0]; + handler.fillRect(t, pix); + continue; + } + + if (!rle) { + if (palSize == 0) { + + // raw + + if (bytesPerPixel > 1) { + zis.readPixels(buf, t.area(), 3, bigEndian); + } else { + zis.readPixels(buf, t.area(), bytesPerPixel, bigEndian); + } + + } else { + + // packed pixels + int bppp = ((palSize > 16) ? 8 : + ((palSize > 4) ? 4 : ((palSize > 2) ? 2 : 1))); + + int ptr = 0; + + for (int i = 0; i < t.height(); i++) { + int eol = ptr + t.width(); + int b = 0; + int nbits = 0; + + while (ptr < eol) { + if (nbits == 0) { + b = zis.readU8(); + nbits = 8; + } + nbits -= bppp; + int index = (b >> nbits) & ((1 << bppp) - 1) & 127; + buf[ptr++] = palette[index]; + } + } + } + + } else { + + if (palSize == 0) { + + // plain RLE + + int ptr = 0; + int end = ptr + t.area(); + while (ptr < end) { + int pix = (bytesPerPixel > 1 ? zis.readPixel(3, bigEndian) : + zis.readPixel(bytesPerPixel, bigEndian)); + int len = 1; + int b; + do { + b = zis.readU8(); + len += b; + } while (b == 255); + + if (!(len <= end - ptr)) + throw new Exception("ZRLEDecoder: assertion (len <= end - ptr)" + +" failed"); + + while (len-- > 0) buf[ptr++] = pix; + } + } else { + + // palette RLE + + int ptr = 0; + int end = ptr + t.area(); + while (ptr < end) { + int index = zis.readU8(); + int len = 1; + if ((index & 128) != 0) { + int b; + do { + b = zis.readU8(); + len += b; + } while (b == 255); + + if (!(len <= end - ptr)) + throw new Exception("ZRLEDecoder: assertion " + +"(len <= end - ptr) failed"); + } + + index &= 127; + + int pix = palette[index]; + + while (len-- > 0) buf[ptr++] = pix; + } + } + } + + handler.imageRect(t, buf); + } + } + + zis.reset(); + } + + CMsgReader reader; + ZlibInStream zis; +} diff --git a/java/com/tigervnc/rfb/screenTypes.java b/java/com/tigervnc/rfb/screenTypes.java new file mode 100644 index 00000000..d46741c6 --- /dev/null +++ b/java/com/tigervnc/rfb/screenTypes.java @@ -0,0 +1,36 @@ +/* Copyright 2009 Pierre Ossman for Cendio AB + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package com.tigervnc.rfb; + +public class screenTypes { + + // Reasons + public static final int reasonServer = 0; + public static final int reasonClient = 1; + public static final int reasonOtherClient = 2; + + // Result codes + public static final int resultSuccess = 0; + public static final int resultProhibited = 1; + public static final int resultNoResources = 2; + public static final int resultInvalid = 3; + + public static final int resultUnsolicited = 0xffff; // internal code used for server changes + +} |