1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - RDP decompression
4 Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 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 3 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, see <http://www.gnu.org/licenses/>.
25 /* mppc decompression */
26 /* http://www.faqs.org/rfcs/rfc2118.html */
30 /* hifn contact mentioned in the faq is */
31 /* Robert Friend rfriend at hifn dot com */
33 /* if you have questions regarding MPPC */
35 /* Guus Dhaeze GDhaeze at hifn dot com */
39 /* decompression is alright as long as we */
40 /* don't compress data */
44 /* as the rfc states the algorithm seems to */
45 /* be LZ77 with a sliding buffer */
46 /* that is empty at init. */
48 /* the algorithm is called LZS and is */
49 /* patented for another couple of years. */
51 /* more information is available in */
52 /* http://www.ietf.org/ietf/IPR/hifn-ipr-draft-friend-tls-lzs-compression.txt */
58 mppc_expand(uint8
* data
, uint32 clen
, uint8 ctype
, uint32
* roff
, uint32
* rlen
)
60 int k
, walker_len
= 0, walker
;
62 int next_offset
, match_off
;
64 int old_offset
, match_bits
;
65 RD_BOOL big
= ctype
& RDP_MPPC_BIG
? True
: False
;
67 uint8
*dict
= g_mppc_dict
.hist
;
69 if ((ctype
& RDP_MPPC_COMPRESSED
) == 0)
76 if ((ctype
& RDP_MPPC_RESET
) != 0)
81 if ((ctype
& RDP_MPPC_FLUSH
) != 0)
83 memset(dict
, 0, RDP_MPPC_DICT_SIZE
);
90 walker
= g_mppc_dict
.roff
;
93 old_offset
= next_offset
;
105 walker
= data
[i
++] << 24;
118 walker
|= (data
[i
++] & 0xff) << (24 - walker_len
);
121 if (next_offset
>= RDP_MPPC_DICT_SIZE
)
123 dict
[next_offset
++] = (((uint32
) walker
) >> ((uint32
) 24));
129 /* fetch next 8-bits */
130 if (--walker_len
== 0)
134 walker
= data
[i
++] << 24;
137 /* literal decoding */
144 walker
|= (data
[i
++] & 0xff) << (24 - walker_len
);
147 if (next_offset
>= RDP_MPPC_DICT_SIZE
)
149 dict
[next_offset
++] = (uint8
) (walker
>> 24 | 0x80);
158 if (--walker_len
< (big
? 3 : 2))
162 walker
|= (data
[i
++] & 0xff) << (24 - walker_len
);
168 /* offset decoding where offset len is:
169 -63: 11111 followed by the lower 6 bits of the value
170 64-319: 11110 followed by the lower 8 bits of the value ( value - 64 )
171 320-2367: 1110 followed by lower 11 bits of the value ( value - 320 )
172 2368-65535: 110 followed by lower 16 bits of the value ( value - 2368 )
174 switch (((uint32
) walker
) >> ((uint32
) 29))
177 for (; walker_len
< 9; walker_len
+= 8)
181 walker
|= (data
[i
++] & 0xff) << (24 - walker_len
);
184 match_off
= ((uint32
) walker
) >> ((uint32
) 26);
189 case 6: /* 64 - 319 */
190 for (; walker_len
< 11; walker_len
+= 8)
194 walker
|= (data
[i
++] & 0xff) << (24 - walker_len
);
198 match_off
= (((uint32
) walker
) >> ((uint32
) 24)) + 64;
204 case 4: /* 320 - 2367 */
205 for (; walker_len
< 13; walker_len
+= 8)
209 walker
|= (data
[i
++] & 0xff) << (24 - walker_len
);
213 match_off
= (((uint32
) walker
) >> ((uint32
) 21)) + 320;
218 default: /* 2368 - 65535 */
219 for (; walker_len
< 17; walker_len
+= 8)
223 walker
|= (data
[i
++] & 0xff) << (24 - walker_len
);
227 match_off
= (((uint32
) walker
) >> ((uint32
) 16)) + 2368;
235 /* offset decoding where offset len is:
236 -63: 1111 followed by the lower 6 bits of the value
237 64-319: 1110 followed by the lower 8 bits of the value ( value - 64 )
238 320-8191: 110 followed by the lower 13 bits of the value ( value - 320 )
240 switch (((uint32
) walker
) >> ((uint32
) 30))
247 walker
|= (data
[i
++] & 0xff) << (24 - walker_len
);
251 match_off
= ((uint32
) walker
) >> ((uint32
) 26);
256 case 2: /* 64 - 319 */
257 for (; walker_len
< 10; walker_len
+= 8)
261 walker
|= (data
[i
++] & 0xff) << (24 - walker_len
);
265 match_off
= (((uint32
) walker
) >> ((uint32
) 24)) + 64;
270 default: /* 320 - 8191 */
271 for (; walker_len
< 14; walker_len
+= 8)
275 walker
|= (data
[i
++] & 0xff) << (24 - walker_len
);
278 match_off
= (walker
>> 18) + 320;
288 walker
= data
[i
++] << 24;
292 /* decode length of match */
295 { /* special case - length of 3 is in bit 0 */
302 /* this is how it works len of:
303 4-7: 10 followed by 2 bits of the value
304 8-15: 110 followed by 3 bits of the value
305 16-31: 1110 followed by 4 bits of the value
306 32-63: .... and so forth
315 i.e. 4097 is encoded as: 111111111110 000000000001
318 match_bits
= big
? 14 : 11; /* 11 or 14 bits of value at most */
322 if (--walker_len
== 0)
326 walker
= data
[i
++] << 24;
331 if (--match_bits
== 0)
337 match_len
= (big
? 16 : 13) - match_bits
;
339 if (--walker_len
< match_len
)
341 for (; walker_len
< match_len
; walker_len
+= 8)
347 walker
|= (data
[i
++] & 0xff) << (24 - walker_len
);
351 match_bits
= match_len
;
353 ((walker
>> (32 - match_bits
)) & (~(-1 << match_bits
))) | (1 <<
355 walker
<<= match_bits
;
356 walker_len
-= match_bits
;
358 if (next_offset
+ match_len
>= RDP_MPPC_DICT_SIZE
)
362 /* memory areas can overlap - meaning we can't use memXXX functions */
363 k
= (next_offset
- match_off
) & (big
? 65535 : 8191);
366 dict
[next_offset
++] = dict
[k
++];
368 while (--match_len
!= 0);
372 /* store history offset */
373 g_mppc_dict
.roff
= next_offset
;
376 *rlen
= next_offset
- old_offset
;