1
/* -*- c-basic-offset: 8 -*-
2
rdesktop: A Remote Desktop Protocol client.
3
Protocol services - RDP decompression
4
Copyright (C) Matthew Chapman 1999-2008
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27
/* mppc decompression */
28
/* http://www.faqs.org/rfcs/rfc2118.html */
32
/* hifn contact mentioned in the faq is */
33
/* Robert Friend rfriend at hifn dot com */
35
/* if you have questions regarding MPPC */
37
/* Guus Dhaeze GDhaeze at hifn dot com */
41
/* decompression is alright as long as we */
42
/* don't compress data */
46
/* as the rfc states the algorithm seems to */
47
/* be LZ77 with a sliding buffer */
48
/* that is empty at init. */
50
/* the algorithm is called LZS and is */
51
/* patented for another couple of years. */
53
/* more information is available in */
54
/* http://www.ietf.org/ietf/IPR/hifn-ipr-draft-friend-tls-lzs-compression.txt */
57
mppc_expand(rdpRdp * rdp, uint8 * data, uint32 clen, uint8 ctype, uint32 * roff, uint32 * rlen)
59
int k, walker_len = 0, walker;
61
int next_offset, match_off;
63
int old_offset, match_bits;
64
RD_BOOL big = ctype & RDP_MPPC_BIG ? True : False;
66
uint8 *dict = rdp->mppc_dict.hist;
68
if ((ctype & RDP_MPPC_COMPRESSED) == 0)
75
if ((ctype & RDP_MPPC_RESET) != 0)
77
rdp->mppc_dict.roff = 0;
80
if ((ctype & RDP_MPPC_FLUSH) != 0)
82
memset(dict, 0, RDP_MPPC_DICT_SIZE);
83
rdp->mppc_dict.roff = 0;
89
walker = rdp->mppc_dict.roff;
92
old_offset = next_offset;
104
walker = data[i++] << 24;
117
walker |= (data[i++] & 0xff) << (24 - walker_len);
120
if (next_offset >= RDP_MPPC_DICT_SIZE)
122
dict[next_offset++] = (((uint32) walker) >> ((uint32) 24));
128
/* fetch next 8-bits */
129
if (--walker_len == 0)
133
walker = data[i++] << 24;
136
/* literal decoding */
143
walker |= (data[i++] & 0xff) << (24 - walker_len);
146
if (next_offset >= RDP_MPPC_DICT_SIZE)
148
dict[next_offset++] = (uint8) (walker >> 24 | 0x80);
157
if (--walker_len < (big ? 3 : 2))
161
walker |= (data[i++] & 0xff) << (24 - walker_len);
167
/* offset decoding where offset len is:
168
-63: 11111 followed by the lower 6 bits of the value
169
64-319: 11110 followed by the lower 8 bits of the value ( value - 64 )
170
320-2367: 1110 followed by lower 11 bits of the value ( value - 320 )
171
2368-65535: 110 followed by lower 16 bits of the value ( value - 2368 )
173
switch (((uint32) walker) >> ((uint32) 29))
176
for (; walker_len < 9; walker_len += 8)
180
walker |= (data[i++] & 0xff) << (24 - walker_len);
183
match_off = ((uint32) walker) >> ((uint32) 26);
188
case 6: /* 64 - 319 */
189
for (; walker_len < 11; walker_len += 8)
193
walker |= (data[i++] & 0xff) << (24 - walker_len);
197
match_off = (((uint32) walker) >> ((uint32) 24)) + 64;
203
case 4: /* 320 - 2367 */
204
for (; walker_len < 13; walker_len += 8)
208
walker |= (data[i++] & 0xff) << (24 - walker_len);
212
match_off = (((uint32) walker) >> ((uint32) 21)) + 320;
217
default: /* 2368 - 65535 */
218
for (; walker_len < 17; walker_len += 8)
222
walker |= (data[i++] & 0xff) << (24 - walker_len);
226
match_off = (((uint32) walker) >> ((uint32) 16)) + 2368;
234
/* offset decoding where offset len is:
235
-63: 1111 followed by the lower 6 bits of the value
236
64-319: 1110 followed by the lower 8 bits of the value ( value - 64 )
237
320-8191: 110 followed by the lower 13 bits of the value ( value - 320 )
239
switch (((uint32) walker) >> ((uint32) 30))
246
walker |= (data[i++] & 0xff) << (24 - walker_len);
250
match_off = ((uint32) walker) >> ((uint32) 26);
255
case 2: /* 64 - 319 */
256
for (; walker_len < 10; walker_len += 8)
260
walker |= (data[i++] & 0xff) << (24 - walker_len);
264
match_off = (((uint32) walker) >> ((uint32) 24)) + 64;
269
default: /* 320 - 8191 */
270
for (; walker_len < 14; walker_len += 8)
274
walker |= (data[i++] & 0xff) << (24 - walker_len);
277
match_off = (walker >> 18) + 320;
287
walker = data[i++] << 24;
291
/* decode length of match */
294
{ /* special case - length of 3 is in bit 0 */
301
/* this is how it works len of:
302
4-7: 10 followed by 2 bits of the value
303
8-15: 110 followed by 3 bits of the value
304
16-31: 1110 followed by 4 bits of the value
305
32-63: .... and so forth
314
i.e. 4097 is encoded as: 111111111110 000000000001
317
match_bits = big ? 14 : 11; /* 11 or 14 bits of value at most */
321
if (--walker_len == 0)
325
walker = data[i++] << 24;
330
if (--match_bits == 0)
336
match_len = (big ? 16 : 13) - match_bits;
338
if (--walker_len < match_len)
340
for (; walker_len < match_len; walker_len += 8)
346
walker |= (data[i++] & 0xff) << (24 - walker_len);
350
match_bits = match_len;
352
((walker >> (32 - match_bits)) & (~(-1 << match_bits))) | (1 <<
354
walker <<= match_bits;
355
walker_len -= match_bits;
357
if (next_offset + match_len >= RDP_MPPC_DICT_SIZE)
361
/* memory areas can overlap - meaning we can't use memXXX functions */
362
k = (next_offset - match_off) & (big ? 65535 : 8191);
365
dict[next_offset++] = dict[k++];
367
while (--match_len != 0);
371
/* store history offset */
372
rdp->mppc_dict.roff = next_offset;
375
*rlen = next_offset - old_offset;