~ubuntu-branches/ubuntu/raring/freerdp/raring-proposed

« back to all changes in this revision

Viewing changes to libfreerdp/mppc.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt, Jeremy Bicha, Jean-Louis Dupond, Martin Pitt
  • Date: 2012-01-31 10:02:14 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20120131100214-jaok3uwvni7sqxth
Tags: 1.0.0-0git1
Upload current Debian packaging git to get this rolling for precise.

[ Jeremy Bicha ]
* New upstream release. Closes: #647498.
* Updated symbols and bumped soname
* debian/control:
  - Added new build dependencies
  - Bump Standards-Version to 3.9.2
* debian/source/format: Set to 3.0 (quilt)
* debian/rules: Turn on strict symbols checking
* debian/watch: Watch github

[ Jean-Louis Dupond ]
* debian/control: Updated homepage
* debian/copyright: Reflect upstream switch to the Apache license

[ Martin Pitt ]
* debian/libfreerdp0.symbols: Fix version number, should
  be 1.0~beta5, not 1.0-beta5.
* debian/control: Add libavcodec-dev build dependency, upstream build system
  checks for that. Thanks Jean-Louis Dupond!

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- c-basic-offset: 8 -*-
2
 
   rdesktop: A Remote Desktop Protocol client.
3
 
   Protocol services - RDP decompression
4
 
   Copyright (C) Matthew Chapman 1999-2008
5
 
 
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.
10
 
 
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.
15
 
 
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.
19
 
*/
20
 
 
21
 
#include <stdio.h>
22
 
#include <string.h>
23
 
 
24
 
#include "frdp.h"
25
 
#include "rdp.h"
26
 
 
27
 
/* mppc decompression                       */
28
 
/* http://www.faqs.org/rfcs/rfc2118.html    */
29
 
 
30
 
/* Contacts:                                */
31
 
 
32
 
/* hifn contact mentioned in the faq is     */
33
 
/* Robert Friend rfriend at hifn dot com    */
34
 
 
35
 
/* if you have questions regarding MPPC     */
36
 
/* our contact is                           */
37
 
/* Guus Dhaeze  GDhaeze at hifn dot com     */
38
 
 
39
 
/* Licensing:                               */
40
 
 
41
 
/* decompression is alright as long as we   */
42
 
/* don't compress data                      */
43
 
 
44
 
/* Algorithm: */
45
 
 
46
 
/* as the rfc states the algorithm seems to */
47
 
/* be LZ77 with a sliding buffer            */
48
 
/* that is empty at init.                   */
49
 
 
50
 
/* the algorithm is called LZS and is       */
51
 
/* patented for another couple of years.    */
52
 
 
53
 
/* more information is available in         */
54
 
/* http://www.ietf.org/ietf/IPR/hifn-ipr-draft-friend-tls-lzs-compression.txt */
55
 
 
56
 
int
57
 
mppc_expand(rdpRdp * rdp, uint8 * data, uint32 clen, uint8 ctype, uint32 * roff, uint32 * rlen)
58
 
{
59
 
        int k, walker_len = 0, walker;
60
 
        uint32 i = 0;
61
 
        int next_offset, match_off;
62
 
        int match_len;
63
 
        int old_offset, match_bits;
64
 
        RD_BOOL big = ctype & RDP_MPPC_BIG ? True : False;
65
 
 
66
 
        uint8 *dict = rdp->mppc_dict.hist;
67
 
 
68
 
        if ((ctype & RDP_MPPC_COMPRESSED) == 0)
69
 
        {
70
 
                *roff = 0;
71
 
                *rlen = clen;
72
 
                return 0;
73
 
        }
74
 
 
75
 
        if ((ctype & RDP_MPPC_RESET) != 0)
76
 
        {
77
 
                rdp->mppc_dict.roff = 0;
78
 
        }
79
 
 
80
 
        if ((ctype & RDP_MPPC_FLUSH) != 0)
81
 
        {
82
 
                memset(dict, 0, RDP_MPPC_DICT_SIZE);
83
 
                rdp->mppc_dict.roff = 0;
84
 
        }
85
 
 
86
 
        *roff = 0;
87
 
        *rlen = 0;
88
 
 
89
 
        walker = rdp->mppc_dict.roff;
90
 
 
91
 
        next_offset = walker;
92
 
        old_offset = next_offset;
93
 
        *roff = old_offset;
94
 
        if (clen == 0)
95
 
                return 0;
96
 
        clen += i;
97
 
 
98
 
        do
99
 
        {
100
 
                if (walker_len == 0)
101
 
                {
102
 
                        if (i >= clen)
103
 
                                break;
104
 
                        walker = data[i++] << 24;
105
 
                        walker_len = 8;
106
 
                }
107
 
                if (walker >= 0)
108
 
                {
109
 
                        if (walker_len < 8)
110
 
                        {
111
 
                                if (i >= clen)
112
 
                                {
113
 
                                        if (walker != 0)
114
 
                                                return -1;
115
 
                                        break;
116
 
                                }
117
 
                                walker |= (data[i++] & 0xff) << (24 - walker_len);
118
 
                                walker_len += 8;
119
 
                        }
120
 
                        if (next_offset >= RDP_MPPC_DICT_SIZE)
121
 
                                return -1;
122
 
                        dict[next_offset++] = (((uint32) walker) >> ((uint32) 24));
123
 
                        walker <<= 8;
124
 
                        walker_len -= 8;
125
 
                        continue;
126
 
                }
127
 
                walker <<= 1;
128
 
                /* fetch next 8-bits */
129
 
                if (--walker_len == 0)
130
 
                {
131
 
                        if (i >= clen)
132
 
                                return -1;
133
 
                        walker = data[i++] << 24;
134
 
                        walker_len = 8;
135
 
                }
136
 
                /* literal decoding */
137
 
                if (walker >= 0)
138
 
                {
139
 
                        if (walker_len < 8)
140
 
                        {
141
 
                                if (i >= clen)
142
 
                                        return -1;
143
 
                                walker |= (data[i++] & 0xff) << (24 - walker_len);
144
 
                                walker_len += 8;
145
 
                        }
146
 
                        if (next_offset >= RDP_MPPC_DICT_SIZE)
147
 
                                return -1;
148
 
                        dict[next_offset++] = (uint8) (walker >> 24 | 0x80);
149
 
                        walker <<= 8;
150
 
                        walker_len -= 8;
151
 
                        continue;
152
 
                }
153
 
 
154
 
                /* decode offset  */
155
 
                /* length pair    */
156
 
                walker <<= 1;
157
 
                if (--walker_len < (big ? 3 : 2))
158
 
                {
159
 
                        if (i >= clen)
160
 
                                return -1;
161
 
                        walker |= (data[i++] & 0xff) << (24 - walker_len);
162
 
                        walker_len += 8;
163
 
                }
164
 
 
165
 
                if (big)
166
 
                {
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 )
172
 
                         */
173
 
                        switch (((uint32) walker) >> ((uint32) 29))
174
 
                        {
175
 
                                case 7: /* - 63 */
176
 
                                        for (; walker_len < 9; walker_len += 8)
177
 
                                        {
178
 
                                                if (i >= clen)
179
 
                                                        return -1;
180
 
                                                walker |= (data[i++] & 0xff) << (24 - walker_len);
181
 
                                        }
182
 
                                        walker <<= 3;
183
 
                                        match_off = ((uint32) walker) >> ((uint32) 26);
184
 
                                        walker <<= 6;
185
 
                                        walker_len -= 9;
186
 
                                        break;
187
 
 
188
 
                                case 6: /* 64 - 319 */
189
 
                                        for (; walker_len < 11; walker_len += 8)
190
 
                                        {
191
 
                                                if (i >= clen)
192
 
                                                        return -1;
193
 
                                                walker |= (data[i++] & 0xff) << (24 - walker_len);
194
 
                                        }
195
 
 
196
 
                                        walker <<= 3;
197
 
                                        match_off = (((uint32) walker) >> ((uint32) 24)) + 64;
198
 
                                        walker <<= 8;
199
 
                                        walker_len -= 11;
200
 
                                        break;
201
 
 
202
 
                                case 5:
203
 
                                case 4: /* 320 - 2367 */
204
 
                                        for (; walker_len < 13; walker_len += 8)
205
 
                                        {
206
 
                                                if (i >= clen)
207
 
                                                        return -1;
208
 
                                                walker |= (data[i++] & 0xff) << (24 - walker_len);
209
 
                                        }
210
 
 
211
 
                                        walker <<= 2;
212
 
                                        match_off = (((uint32) walker) >> ((uint32) 21)) + 320;
213
 
                                        walker <<= 11;
214
 
                                        walker_len -= 13;
215
 
                                        break;
216
 
 
217
 
                                default:        /* 2368 - 65535 */
218
 
                                        for (; walker_len < 17; walker_len += 8)
219
 
                                        {
220
 
                                                if (i >= clen)
221
 
                                                        return -1;
222
 
                                                walker |= (data[i++] & 0xff) << (24 - walker_len);
223
 
                                        }
224
 
 
225
 
                                        walker <<= 1;
226
 
                                        match_off = (((uint32) walker) >> ((uint32) 16)) + 2368;
227
 
                                        walker <<= 16;
228
 
                                        walker_len -= 17;
229
 
                                        break;
230
 
                        }
231
 
                }
232
 
                else
233
 
                {
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 )
238
 
                         */
239
 
                        switch (((uint32) walker) >> ((uint32) 30))
240
 
                        {
241
 
                                case 3: /* - 63 */
242
 
                                        if (walker_len < 8)
243
 
                                        {
244
 
                                                if (i >= clen)
245
 
                                                        return -1;
246
 
                                                walker |= (data[i++] & 0xff) << (24 - walker_len);
247
 
                                                walker_len += 8;
248
 
                                        }
249
 
                                        walker <<= 2;
250
 
                                        match_off = ((uint32) walker) >> ((uint32) 26);
251
 
                                        walker <<= 6;
252
 
                                        walker_len -= 8;
253
 
                                        break;
254
 
 
255
 
                                case 2: /* 64 - 319 */
256
 
                                        for (; walker_len < 10; walker_len += 8)
257
 
                                        {
258
 
                                                if (i >= clen)
259
 
                                                        return -1;
260
 
                                                walker |= (data[i++] & 0xff) << (24 - walker_len);
261
 
                                        }
262
 
 
263
 
                                        walker <<= 2;
264
 
                                        match_off = (((uint32) walker) >> ((uint32) 24)) + 64;
265
 
                                        walker <<= 8;
266
 
                                        walker_len -= 10;
267
 
                                        break;
268
 
 
269
 
                                default:        /* 320 - 8191 */
270
 
                                        for (; walker_len < 14; walker_len += 8)
271
 
                                        {
272
 
                                                if (i >= clen)
273
 
                                                        return -1;
274
 
                                                walker |= (data[i++] & 0xff) << (24 - walker_len);
275
 
                                        }
276
 
 
277
 
                                        match_off = (walker >> 18) + 320;
278
 
                                        walker <<= 14;
279
 
                                        walker_len -= 14;
280
 
                                        break;
281
 
                        }
282
 
                }
283
 
                if (walker_len == 0)
284
 
                {
285
 
                        if (i >= clen)
286
 
                                return -1;
287
 
                        walker = data[i++] << 24;
288
 
                        walker_len = 8;
289
 
                }
290
 
 
291
 
                /* decode length of match */
292
 
                match_len = 0;
293
 
                if (walker >= 0)
294
 
                {               /* special case - length of 3 is in bit 0 */
295
 
                        match_len = 3;
296
 
                        walker <<= 1;
297
 
                        walker_len--;
298
 
                }
299
 
                else
300
 
                {
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
306
 
                           64-127:
307
 
                           128-255:
308
 
                           256-511:
309
 
                           512-1023:
310
 
                           1024-2047:
311
 
                           2048-4095:
312
 
                           4096-8191:
313
 
 
314
 
                           i.e. 4097 is encoded as: 111111111110 000000000001
315
 
                           meaning 4096 + 1...
316
 
                         */
317
 
                        match_bits = big ? 14 : 11;     /* 11 or 14 bits of value at most */
318
 
                        do
319
 
                        {
320
 
                                walker <<= 1;
321
 
                                if (--walker_len == 0)
322
 
                                {
323
 
                                        if (i >= clen)
324
 
                                                return -1;
325
 
                                        walker = data[i++] << 24;
326
 
                                        walker_len = 8;
327
 
                                }
328
 
                                if (walker >= 0)
329
 
                                        break;
330
 
                                if (--match_bits == 0)
331
 
                                {
332
 
                                        return -1;
333
 
                                }
334
 
                        }
335
 
                        while (1);
336
 
                        match_len = (big ? 16 : 13) - match_bits;
337
 
                        walker <<= 1;
338
 
                        if (--walker_len < match_len)
339
 
                        {
340
 
                                for (; walker_len < match_len; walker_len += 8)
341
 
                                {
342
 
                                        if (i >= clen)
343
 
                                        {
344
 
                                                return -1;
345
 
                                        }
346
 
                                        walker |= (data[i++] & 0xff) << (24 - walker_len);
347
 
                                }
348
 
                        }
349
 
 
350
 
                        match_bits = match_len;
351
 
                        match_len =
352
 
                                ((walker >> (32 - match_bits)) & (~(-1 << match_bits))) | (1 <<
353
 
                                                                                           match_bits);
354
 
                        walker <<= match_bits;
355
 
                        walker_len -= match_bits;
356
 
                }
357
 
                if (next_offset + match_len >= RDP_MPPC_DICT_SIZE)
358
 
                {
359
 
                        return -1;
360
 
                }
361
 
                /* memory areas can overlap - meaning we can't use memXXX functions */
362
 
                k = (next_offset - match_off) & (big ? 65535 : 8191);
363
 
                do
364
 
                {
365
 
                        dict[next_offset++] = dict[k++];
366
 
                }
367
 
                while (--match_len != 0);
368
 
        }
369
 
        while (1);
370
 
 
371
 
        /* store history offset */
372
 
        rdp->mppc_dict.roff = next_offset;
373
 
 
374
 
        *roff = old_offset;
375
 
        *rlen = next_offset - old_offset;
376
 
 
377
 
        return 0;
378
 
}