1a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
2a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  Copyright (C) 2005 Johannes E. Schindelin.  All Rights Reserved.
3a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *
4a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  This is free software; you can redistribute it and/or modify
5a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  it under the terms of the GNU General Public License as published by
6a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  the Free Software Foundation; either version 2 of the License, or
7a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  (at your option) any later version.
8a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *
9a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  This software is distributed in the hope that it will be useful,
10a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  GNU General Public License for more details.
13a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *
14a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  You should have received a copy of the GNU General Public License
15a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  along with this software; if not, write to the Free Software
16a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
17a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  USA.
18a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
19a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
20a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBZ
21a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
22a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
23a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * zrle.c - handle zrle encoding.
24a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *
25a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * This file shouldn't be compiled directly.  It is included multiple times by
26a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * rfbproto.c, each time with a different definition of the macro BPP.  For
27a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * each value of BPP, this file defines a function which handles an zrle
28a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * encoded rectangle with BPP bits per pixel.
29a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
30a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
31a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifndef REALBPP
32a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define REALBPP BPP
33a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
34a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
35a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if !defined(UNCOMP) || UNCOMP==0
36a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define HandleZRLE CONCAT2E(HandleZRLE,REALBPP)
37a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define HandleZRLETile CONCAT2E(HandleZRLETile,REALBPP)
38a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#elif UNCOMP>0
39a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define HandleZRLE CONCAT3E(HandleZRLE,REALBPP,Down)
40a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define HandleZRLETile CONCAT3E(HandleZRLETile,REALBPP,Down)
41a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else
42a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define HandleZRLE CONCAT3E(HandleZRLE,REALBPP,Up)
43a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define HandleZRLETile CONCAT3E(HandleZRLETile,REALBPP,Up)
44a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
45a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define CARDBPP CONCAT3E(uint,BPP,_t)
46a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define CARDREALBPP CONCAT3E(uint,REALBPP,_t)
47a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
48a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define ENDIAN_LITTLE 0
49a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define ENDIAN_BIG 1
50a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define ENDIAN_NO 2
51a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define ZYWRLE_ENDIAN ENDIAN_LITTLE
52a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#undef END_FIX
53a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if ZYWRLE_ENDIAN == ENDIAN_LITTLE
54a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#  define END_FIX LE
55a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#elif ZYWRLE_ENDIAN == ENDIAN_BIG
56a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#  define END_FIX BE
57a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else
58a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#  define END_FIX NE
59a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
60a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define __RFB_CONCAT3E(a,b,c) CONCAT3E(a,b,c)
61a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define __RFB_CONCAT2E(a,b) CONCAT2E(a,b)
62a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#undef CPIXEL
63a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if REALBPP != BPP
64a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if UNCOMP == 0
65a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define CPIXEL REALBPP
66a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#elif UNCOMP>0
67a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define CPIXEL CONCAT2E(REALBPP,Down)
68a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else
69a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define CPIXEL CONCAT2E(REALBPP,Up)
70a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
71a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
72a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define PIXEL_T __RFB_CONCAT3E(uint,BPP,_t)
73a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if BPP!=8
74a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define ZYWRLE_DECODE 1
75a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include "zywrletemplate.c"
76a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
77a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#undef CPIXEL
78a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
79a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic int HandleZRLETile(rfbClient* client,
80a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	uint8_t* buffer,size_t buffer_length,
81a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int x,int y,int w,int h);
82a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
83a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic rfbBool
84a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatHandleZRLE (rfbClient* client, int rx, int ry, int rw, int rh)
85a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
86a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbZRLEHeader header;
87a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int remaining;
88a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int inflateResult;
89a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int toRead;
90a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int min_buffer_size = rw * rh * (REALBPP / 8) * 2;
91a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
92a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	/* First make sure we have a large enough raw buffer to hold the
93a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	 * decompressed data.  In practice, with a fixed REALBPP, fixed frame
94a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	 * buffer size and the first update containing the entire frame
95a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	 * buffer, this buffer allocation should only happen once, on the
96a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	 * first update.
97a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	 */
98a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if ( client->raw_buffer_size < min_buffer_size) {
99a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
100a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if ( client->raw_buffer != NULL ) {
101a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
102a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			free( client->raw_buffer );
103a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
104a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
105a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
106a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		client->raw_buffer_size = min_buffer_size;
107a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		client->raw_buffer = (char*) malloc( client->raw_buffer_size );
108a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
109a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
110a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
111a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (!ReadFromRFBServer(client, (char *)&header, sz_rfbZRLEHeader))
112a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return FALSE;
113a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
114a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	remaining = rfbClientSwap32IfLE(header.length);
115a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
116a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	/* Need to initialize the decompressor state. */
117a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	client->decompStream.next_in   = ( Bytef * )client->buffer;
118a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	client->decompStream.avail_in  = 0;
119a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	client->decompStream.next_out  = ( Bytef * )client->raw_buffer;
120a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	client->decompStream.avail_out = client->raw_buffer_size;
121a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	client->decompStream.data_type = Z_BINARY;
122a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
123a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	/* Initialize the decompression stream structures on the first invocation. */
124a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if ( client->decompStreamInited == FALSE ) {
125a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
126a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		inflateResult = inflateInit( &client->decompStream );
127a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
128a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if ( inflateResult != Z_OK ) {
129a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			rfbClientLog(
130a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					"inflateInit returned error: %d, msg: %s\n",
131a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					inflateResult,
132a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					client->decompStream.msg);
133a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			return FALSE;
134a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
135a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
136a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		client->decompStreamInited = TRUE;
137a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
138a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
139a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
140a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	inflateResult = Z_OK;
141a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
142a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	/* Process buffer full of data until no more to process, or
143a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	 * some type of inflater error, or Z_STREAM_END.
144a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	 */
145a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	while (( remaining > 0 ) &&
146a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			( inflateResult == Z_OK )) {
147a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
148a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if ( remaining > RFB_BUFFER_SIZE ) {
149a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			toRead = RFB_BUFFER_SIZE;
150a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
151a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		else {
152a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			toRead = remaining;
153a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
154a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
155a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		/* Fill the buffer, obtaining data from the server. */
156a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (!ReadFromRFBServer(client, client->buffer,toRead))
157a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			return FALSE;
158a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
159a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		client->decompStream.next_in  = ( Bytef * )client->buffer;
160a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		client->decompStream.avail_in = toRead;
161a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
162a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		/* Need to uncompress buffer full. */
163a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		inflateResult = inflate( &client->decompStream, Z_SYNC_FLUSH );
164a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
165a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		/* We never supply a dictionary for compression. */
166a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if ( inflateResult == Z_NEED_DICT ) {
167a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			rfbClientLog("zlib inflate needs a dictionary!\n");
168a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			return FALSE;
169a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
170a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if ( inflateResult < 0 ) {
171a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			rfbClientLog(
172a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					"zlib inflate returned error: %d, msg: %s\n",
173a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					inflateResult,
174a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					client->decompStream.msg);
175a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			return FALSE;
176a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
177a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
178a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		/* Result buffer allocated to be at least large enough.  We should
179a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		 * never run out of space!
180a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		 */
181a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (( client->decompStream.avail_in > 0 ) &&
182a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				( client->decompStream.avail_out <= 0 )) {
183a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			rfbClientLog("zlib inflate ran out of space!\n");
184a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			return FALSE;
185a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
186a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
187a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		remaining -= toRead;
188a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
189a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	} /* while ( remaining > 0 ) */
190a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
191a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if ( inflateResult == Z_OK ) {
192bec50fdbf6ec2d61edda4f69913f8a8331b8b364Greg Hartman		char* buf=client->raw_buffer;
193a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		int i,j;
194a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
195a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		remaining = client->raw_buffer_size-client->decompStream.avail_out;
196a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
197a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		for(j=0; j<rh; j+=rfbZRLETileHeight)
198a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			for(i=0; i<rw; i+=rfbZRLETileWidth) {
199a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				int subWidth=(i+rfbZRLETileWidth>rw)?rw-i:rfbZRLETileWidth;
200a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				int subHeight=(j+rfbZRLETileHeight>rh)?rh-j:rfbZRLETileHeight;
201a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				int result=HandleZRLETile(client,buf,remaining,rx+i,ry+j,subWidth,subHeight);
202a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
203a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				if(result<0) {
204a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					rfbClientLog("ZRLE decoding failed (%d)\n",result);
205a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatreturn TRUE;
206a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					return FALSE;
207a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				}
208a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
209a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				buf+=result;
210a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				remaining-=result;
211a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
212a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
213a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	else {
214a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
215a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		rfbClientLog(
216a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				"zlib inflate returned error: %d, msg: %s\n",
217a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				inflateResult,
218a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				client->decompStream.msg);
219a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return FALSE;
220a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
221a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
222a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
223a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return TRUE;
224a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
225a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
226a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if REALBPP!=BPP && defined(UNCOMP) && UNCOMP!=0
227a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if UNCOMP>0
228a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define UncompressCPixel(pointer) ((*(CARDBPP*)pointer)>>UNCOMP)
229a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else
230a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define UncompressCPixel(pointer) ((*(CARDBPP*)pointer)<<(-(UNCOMP)))
231a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
232a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else
233a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define UncompressCPixel(pointer) (*(CARDBPP*)pointer)
234a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
235a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
236a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic int HandleZRLETile(rfbClient* client,
237a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		uint8_t* buffer,size_t buffer_length,
238a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		int x,int y,int w,int h) {
239a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	uint8_t* buffer_copy = buffer;
240a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	uint8_t* buffer_end = buffer+buffer_length;
241a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	uint8_t type;
242a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if BPP!=8
243a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	uint8_t zywrle_level = (client->appData.qualityLevel & 0x80) ?
244a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		0 : (3 - client->appData.qualityLevel / 3);
245a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
246a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
247a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if(buffer_length<1)
248a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return -2;
249a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
250a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	type = *buffer;
251a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	buffer++;
252a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	{
253a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if( type == 0 ) /* raw */
254a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if BPP!=8
255a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          if( zywrle_level > 0 ){
256a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			CARDBPP* pFrame = (CARDBPP*)client->frameBuffer + y*client->width+x;
257a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			int ret;
258a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			client->appData.qualityLevel |= 0x80;
259a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			ret = HandleZRLETile(client, buffer, buffer_end-buffer, x, y, w, h);
260a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    client->appData.qualityLevel &= 0x7F;
261a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			if( ret < 0 ){
262a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				return ret;
263a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
264a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			ZYWRLE_SYNTHESIZE( pFrame, pFrame, w, h, client->width, zywrle_level, (int*)client->zlib_buffer );
265a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			buffer += ret;
266a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		  }else
267a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
268a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		{
269a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if REALBPP!=BPP
270a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			int i,j;
271a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
272a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			if(1+w*h*REALBPP/8>buffer_length) {
273a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				rfbClientLog("expected %d bytes, got only %d (%dx%d)\n",1+w*h*REALBPP/8,buffer_length,w,h);
274a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				return -3;
275a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
276a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
277a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			for(j=y*client->width; j<(y+h)*client->width; j+=client->width)
278a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				for(i=x; i<x+w; i++,buffer+=REALBPP/8)
279a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					((CARDBPP*)client->frameBuffer)[j+i] = UncompressCPixel(buffer);
280a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else
281a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			CopyRectangle(client, buffer, x, y, w, h);
282a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			buffer+=w*h*REALBPP/8;
283a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
284a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
285a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		else if( type == 1 ) /* solid */
286a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		{
287a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			CARDBPP color = UncompressCPixel(buffer);
288a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
289a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			if(1+REALBPP/8>buffer_length)
290a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				return -4;
291a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
292a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			FillRectangle(client, x, y, w, h, color);
293a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
294a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			buffer+=REALBPP/8;
295a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
296a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
297a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		else if( (type >= 2)&&(type <= 127) ) /* packed Palette */
298a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		{
299a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			CARDBPP palette[16];
300a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			int i,j,shift,
301a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				bpp=(type>4?(type>16?8:4):(type>2?2:1)),
302a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				mask=(1<<bpp)-1,
303a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				divider=(8/bpp);
304a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
305a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			if(1+type*REALBPP/8+((w+divider-1)/divider)*h>buffer_length)
306a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				return -5;
307a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
308a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			/* read palette */
309a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			for(i=0; i<type; i++,buffer+=REALBPP/8)
310a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				palette[i] = UncompressCPixel(buffer);
311a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
312a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			/* read palettized pixels */
313a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			for(j=y*client->width; j<(y+h)*client->width; j+=client->width) {
314a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				for(i=x,shift=8-bpp; i<x+w; i++) {
315a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					((CARDBPP*)client->frameBuffer)[j+i] = palette[((*buffer)>>shift)&mask];
316a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					shift-=bpp;
317a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					if(shift<0) {
318a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						shift=8-bpp;
319a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						buffer++;
320a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					}
321a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				}
322a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				if(shift<8-bpp)
323a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					buffer++;
324a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
325a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
326a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
327a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		/* case 17 ... 127: not used, but valid */
328a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		else if( type == 128 ) /* plain RLE */
329a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		{
330a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			int i=0,j=0;
331a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			while(j<h) {
332a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				int color,length;
333a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				/* read color */
334a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				if(buffer+REALBPP/8+1>buffer_end)
335a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					return -7;
336a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				color = UncompressCPixel(buffer);
337a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				buffer+=REALBPP/8;
338a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				/* read run length */
339a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				length=1;
340a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				while(*buffer==0xff) {
341a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					if(buffer+1>=buffer_end)
342a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						return -8;
343a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					length+=*buffer;
344a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					buffer++;
345a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				}
346a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				length+=*buffer;
347a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				buffer++;
348a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				while(j<h && length>0) {
349a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					((CARDBPP*)client->frameBuffer)[(y+j)*client->width+x+i] = color;
350a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					length--;
351a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					i++;
352a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					if(i>=w) {
353a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						i=0;
354a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						j++;
355a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					}
356a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				}
357a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				if(length>0)
358a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					rfbClientLog("Warning: possible ZRLE corruption\n");
359a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
360a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
361a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
362a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		else if( type == 129 ) /* unused */
363a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		{
364a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			return -8;
365a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
366a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		else if( type >= 130 ) /* palette RLE */
367a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		{
368a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			CARDBPP palette[128];
369a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			int i,j;
370a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
371a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			if(2+(type-128)*REALBPP/8>buffer_length)
372a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				return -9;
373a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
374a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			/* read palette */
375a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			for(i=0; i<type-128; i++,buffer+=REALBPP/8)
376a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				palette[i] = UncompressCPixel(buffer);
377a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			/* read palettized pixels */
378a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			i=j=0;
379a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			while(j<h) {
380a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				int color,length;
381a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				/* read color */
382a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				if(buffer>=buffer_end)
383a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					return -10;
384a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				color = palette[(*buffer)&0x7f];
385a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				length=1;
386a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				if(*buffer&0x80) {
387a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					if(buffer+1>=buffer_end)
388a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						return -11;
389a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					buffer++;
390a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					/* read run length */
391a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					while(*buffer==0xff) {
392a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						if(buffer+1>=buffer_end)
393a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat							return -8;
394a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						length+=*buffer;
395a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						buffer++;
396a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					}
397a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					length+=*buffer;
398a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				}
399a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				buffer++;
400a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				while(j<h && length>0) {
401a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					((CARDBPP*)client->frameBuffer)[(y+j)*client->width+x+i] = color;
402a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					length--;
403a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					i++;
404a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					if(i>=w) {
405a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						i=0;
406a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						j++;
407a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					}
408a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				}
409a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				if(length>0)
410a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					rfbClientLog("Warning: possible ZRLE corruption\n");
411a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
412a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
413a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
414a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
415a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return buffer-buffer_copy;
416a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
417a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
418a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#undef CARDBPP
419a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#undef CARDREALBPP
420a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#undef HandleZRLE
421a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#undef HandleZRLETile
422a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#undef UncompressCPixel
423a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#undef REALBPP
424a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
425a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
426a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
427a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#undef UNCOMP
428