/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright (C) 2012,2014 Brian P. Hinz
+ * Copyright (C) 2012-2019 Brian P. Hinz
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
end += n;
}
- if (itemSize * nItems > end - ptr)
- nItems = (end - ptr) / itemSize;
+ int nAvail;
+ nAvail = (end - ptr) / itemSize;
+ if (nAvail < nItems)
+ return nAvail;
return nItems;
}
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2011 Pierre Ossman for Cendio AB
- * Copyright (C) 2012,2014 Brian P. Hinz
+ * Copyright (C) 2012-2019 Brian P. Hinz
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
}
}
- // Can we fit all the items asked for?
- if (itemSize * nItems > end - ptr)
- nItems = (end - ptr) / itemSize;
+ int nAvail;
+ nAvail = (end - ptr) / itemSize;
+ if (nAvail < nItems)
+ return nAvail;
return nItems;
}
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright (C) 2011-2019 Brian P. Hinz
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
// maximum of nItems).
public int check(int itemSize, int nItems, boolean wait) {
- if (ptr + itemSize * nItems > end) {
- if (ptr + itemSize > end)
+ int nAvail;
+
+ if (itemSize > (end - ptr))
return overrun(itemSize, nItems, wait);
- nItems = (end - ptr) / itemSize;
- }
+ nAvail = (end - ptr) / itemSize;
+ if (nAvail < nItems)
+ return nAvail;
+
return nItems;
}
// readBytes() reads an exact number of bytes
public void readBytes(ByteBuffer data, int length) {
- ByteBuffer dataPtr = data;
- int dataEnd = dataPtr.position() + length;
- while (dataPtr.position() < dataEnd) {
- int n = check(1, dataEnd - dataPtr.position());
- dataPtr.put(b, ptr, n);
+ while (length > 0) {
+ int n = check(1, length);
+ data.put(b, ptr, n);
ptr += n;
+ length -= n;
}
}
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright (C) 2011-2019 Brian P. Hinz
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
if (len < end * 2)
len = end * 2;
+ if (len < end)
+ throw new Exception("Overflow in MemOutStream::overrun()");
+
byte[] newBuf = new byte[len];
System.arraycopy(b, 0, newBuf, 0, ptr);
b = newBuf;
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright (C) 2011-2019 Brian P. Hinz
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
// of nItems).
public final int check(int itemSize, int nItems) {
- if (ptr + itemSize * nItems > end) {
- if (ptr + itemSize > end)
- return overrun(itemSize, nItems);
+ int nAvail;
+
+ if (itemSize > (end - ptr))
+ return overrun(itemSize, nItems);
+
+ nAvail = (end - ptr) / itemSize;
+ if (nAvail < nItems)
+ return nAvail;
- nItems = (end - ptr) / itemSize;
- }
return nItems;
}
}
public void writeBytes(ByteBuffer data, int length) {
- ByteBuffer dataPtr = data;
- int dataEnd = dataPtr.position() + length;
- while (dataPtr.position() < dataEnd) {
- int n = check(1, dataEnd - dataPtr.position());
- dataPtr.get(b, ptr, n);
+ while (length > 0) {
+ int n = check(1, length);
+ data.get(b, ptr, n);
ptr += n;
+ length -= n;
}
}
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright (C) 2005 Martin Koegler
* Copyright (C) 2010 TigerVNC Team
- * Copyright (C) 2011 Brian P. Hinz
+ * Copyright (C) 2011-2019 Brian P. Hinz
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
end -= ptr - start;
ptr = start;
- while (end < start + itemSize) {
+ while ((end - start) < itemSize) {
int n = readTLS(b, end, start + bufSize - end, wait);
if (!wait && n == 0)
return 0;
end += n;
}
- if (itemSize * nItems > end - ptr)
- nItems = (end - ptr) / itemSize;
+ int nAvail;
+ nAvail = (end - ptr) / itemSize;
+ if (nAvail < nItems)
+ return nAvail;
return nItems;
}
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright (C) 2005 Martin Koegler
* Copyright (C) 2010 TigerVNC Team
- * Copyright (C) 2011 Brian P. Hinz
+ * Copyright (C) 2011-2019 Brian P. Hinz
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
}
ptr = start;
- //out.flush();
}
protected int overrun(int itemSize, int nItems)
flush();
- if (itemSize * nItems > end - ptr)
- nItems = (end - ptr) / itemSize;
+ int nAvail;
+ nAvail = (end - ptr) / itemSize;
+ if (nAvail < nItems)
+ return nAvail;
return nItems;
}
} catch (java.io.IOException e) {
throw new Exception(e.getMessage());
}
- //if (n == GNUTLS_E_INTERRUPTED || n == GNUTLS_E_AGAIN)
- // return 0;
-
- //if (n < 0)
- // throw new TLSException("writeTLS", n);
return n;
}
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright (C) 2011 Brian P. Hinz
+ * Copyright (C) 2011-2019 Brian P. Hinz
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
return offset + ptr - start;
}
- public void removeUnderlying()
+ public void flushUnderlying()
{
ptr = end = start;
- if (underlying == null) return;
while (bytesIn > 0) {
decompress(true);
end = start; // throw away any data
}
- underlying = null;
+
+ setUnderlying(null, 0);
}
public void reset()
public void deinit()
{
assert(zs != null);
- removeUnderlying();
+ setUnderlying(null, 0);
zs.inflateEnd();
zs = null;
}
{
if (itemSize > bufSize)
throw new Exception("ZlibInStream overrun: max itemSize exceeded");
- if (underlying == null)
- throw new Exception("ZlibInStream overrun: no underlying stream");
if (end - ptr != 0)
System.arraycopy(b, ptr, b, start, end - ptr);
return 0;
}
- if (itemSize * nItems > end - ptr)
- nItems = (end - ptr) / itemSize;
+ int nAvail;
+ nAvail = (end - ptr) / itemSize;
+ if (nAvail < nItems)
+ return nAvail;
return nItems;
}
private boolean decompress(boolean wait)
{
+ if (underlying == null)
+ throw new Exception("ZlibInStream overrun: no underlying stream");
+
zs.next_out = b;
zs.next_out_index = end;
zs.avail_out = start + bufSize - end;
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright 2016-2019 Brian P. Hinz
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
-/* Copyright 2016 Brian P. Hinz
+/* Copyright 2016-2019 Brian P. Hinz
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
if (!drect.enclosed_by(getRect())) {
String msg = "Destination rect %dx%d at %d,%d exceeds framebuffer %dx%d";
vlog.error(String.format(msg, drect.width(), drect.height(),
- drect.tl.x, drect.tl.y, width_, height_));
+ drect.tl.x, drect.tl.y, width(), height()));
drect = drect.intersect(getRect());
}
if (!srect.enclosed_by(getRect())) {
String msg = "Source rect %dx%d at %d,%d exceeds framebuffer %dx%d";
vlog.error(String.format(msg, srect.width(), srect.height(),
- srect.tl.x, srect.tl.y, width_, height_));
+ srect.tl.x, srect.tl.y, width(), height()));
srect = srect.intersect(getRect());
// Need to readjust the destination now that the area has changed
drect = srect.translate(move_by_delta);
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2016 Brian P. Hinz
+ * Copyright 2016-2019 Brian P. Hinz
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
public abstract class PixelBuffer {
+ // We do a lot of byte offset calculations that assume the result fits
+ // inside a signed 32 bit integer. Limit the maximum size of pixel
+ // buffers so that these calculations never overflow.
+
+ static final int maxPixelBufferWidth = 16384;
+ static final int maxPixelBufferHeight = 16384;
+
public PixelBuffer(PixelFormat pf, int w, int h) {
format = pf;
width_ = w;
height_= h;
+ setSize(w, h);
}
protected PixelBuffer() { width_ = 0; height_ = 0; }
// const Rect& r, int stride=0) const;
public Image getImage() { return image; }
+ public void setSize(int width, int height)
+ {
+ if ((width < 0) || (width > maxPixelBufferWidth))
+ throw new Exception("Invalid PixelBuffer width of "+width+" pixels requested");
+ if ((height < 0) || (height > maxPixelBufferHeight))
+ throw new Exception("Invalid PixelBuffer height of "+height+" pixels requested");
+
+ width_ = width;
+ height_ = height;
+ }
+
///////////////////////////////////////////////
// Framebuffer update methods
//
redMax = rm; greenMax = gm; blueMax = bm;
redShift = rs; greenShift = gs; blueShift = bs;
converters = new HashMap<Integer, ColorConvertOp>();
- assert(isSane());
+ if (!isSane())
+ throw new Exception("invalid pixel format");
updateState();
}
return false;
if(blueMax != 255)
return false;
+ if ((redShift & 0x7) != 0)
+ return false;
+ if ((greenShift & 0x7) != 0)
+ return false;
+ if ((blueShift & 0x7) != 0)
+ return false;
return true;
}
return false;
totalBits = bits(redMax) + bits(greenMax) + bits(blueMax);
- if (totalBits > bpp)
+ if (totalBits > depth)
+ return false;
+
+ if ((bits(redMax) + redShift) > bpp)
+ return false;
+ if ((bits(greenMax) + greenShift) > bpp)
+ return false;
+ if ((bits(blueMax) + blueShift) > bpp)
return false;
if (((redMax << redShift) & (greenMax << greenShift)) != 0)
zis[streamId].readBytes(netbuf, dataSize);
- zis[streamId].removeUnderlying();
+ zis[streamId].flushUnderlying();
+ zis[streamId].setUnderlying(null, 0);
ms = null;
bufptr = (ByteBuffer)netbuf.flip();
int rectWidth = r.width();
for (y = 0; y < rectHeight; y++) {
- /* First pixel in a row */
- for (c = 0; c < 3; c++) {
- pix.put(c, (byte)(inbuf.get(y*rectWidth*3+c) + prevRow[c]));
- thisRow[c] = pix.get(c);
- }
- pf.bufferFromRGB((ByteBuffer)outbuf.duplicate().position(y*stride), pix, 1);
+ for (x = 0; x < rectWidth; x++) {
+ /* First pixel in a row */
+ if (x == 0) {
+ for (c = 0; c < 3; c++) {
+ pix.put(c, (byte)(inbuf.get(y*rectWidth*3+c) + prevRow[c]));
+ thisRow[c] = pix.get(c);
+ }
+ pf.bufferFromRGB((ByteBuffer)outbuf.duplicate().position(y*stride), pix, 1);
+ continue;
+ }
- /* Remaining pixels of a row */
- for (x = 1; x < rectWidth; x++) {
for (c = 0; c < 3; c++) {
est[c] = prevRow[x*3+c] + pix.get(c) - prevRow[(x-1)*3+c];
if (est[c] > 0xff) {
int rectWidth = r.width();
for (y = 0; y < rectHeight; y++) {
- /* First pixel in a row */
- pf.rgbFromBuffer(pix.duplicate(), (ByteBuffer)inbuf.position(y*rectWidth), 1);
- for (c = 0; c < 3; c++)
- pix.put(c, (byte)(pix.get(c) + prevRow[c]));
-
- System.arraycopy(pix.array(), 0, thisRow, 0, pix.capacity());
-
- pf.bufferFromRGB((ByteBuffer)outbuf.duplicate().position(y*stride), pix, 1);
+ for (x = 0; x < rectWidth; x++) {
+ /* First pixel in a row */
+ if (x == 0) {
+ pf.rgbFromBuffer(pix.duplicate(), (ByteBuffer)inbuf.position(y*rectWidth), 1);
+ for (c = 0; c < 3; c++)
+ pix.put(c, (byte)(pix.get(c) + prevRow[c]));
+
+ System.arraycopy(pix.array(), 0, thisRow, 0, pix.capacity());
+ pf.bufferFromRGB((ByteBuffer)outbuf.duplicate().position(y*stride), pix, 1);
+ continue;
+ }
- /* Remaining pixels of a row */
- for (x = 1; x < rectWidth; x++) {
for (c = 0; c < 3; c++) {
est[c] = prevRow[x*3+c] + pix.get(c) - prevRow[(x-1)*3+c];
if (est[c] > 0xff) {
}
}
- zis.removeUnderlying();
+ zis.flushUnderlying();
+ zis.setUnderlying(null, 0);
}
private ZlibInStream zis;
public static IntParameter compressLevel
= new IntParameter("CompressLevel",
- "Use specified compression level. 0 = Low, 9 = High",
- 1);
+ "Use specified lossless compression level. 0 = Low, 9 = High. Default is 2.",
+ 2);
public static BoolParameter noJpeg
= new BoolParameter("NoJPEG",