~ubuntu-branches/ubuntu/quantal/psi/quantal

« back to all changes in this revision

Viewing changes to third-party/qca/qca/src/qca_textfilter.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2008-04-14 18:57:30 UTC
  • mfrom: (2.1.9 hardy)
  • Revision ID: james.westby@ubuntu.com-20080414185730-528re3zp0m2hdlhi
Tags: 0.11-8
* added CONFIG -= link_prl to .pro files and removed dependencies
  which are made unnecessary by this change
* Fix segfault when closing last chat tab with qt4.4
  (This is from upstream svn, rev. 1101) (Closes: Bug#476122)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2003-2005  Justin Karneges <justin@affinix.com>
 
3
 * Copyright (C) 2004,2005  Brad Hards <bradh@frogmouth.net>
 
4
 *
 
5
 * This library is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU Lesser General Public
 
7
 * License as published by the Free Software Foundation; either
 
8
 * version 2.1 of the License, or (at your option) any later version.
 
9
 *
 
10
 * This library is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * Lesser General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Lesser General Public
 
16
 * License along with this library; if not, write to the Free Software
 
17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 
18
 *
 
19
 */
 
20
 
 
21
#include "qca_textfilter.h"
 
22
 
 
23
namespace QCA {
 
24
 
 
25
//----------------------------------------------------------------------------
 
26
// TextFilter
 
27
//----------------------------------------------------------------------------
 
28
TextFilter::TextFilter(Direction dir)
 
29
{
 
30
        setup(dir);
 
31
}
 
32
 
 
33
void TextFilter::setup(Direction dir)
 
34
{
 
35
        _dir = dir;
 
36
}
 
37
 
 
38
Direction TextFilter::direction() const
 
39
{
 
40
        return _dir;
 
41
}
 
42
 
 
43
MemoryRegion TextFilter::encode(const MemoryRegion &a)
 
44
{
 
45
        setup(Encode);
 
46
        return process(a);
 
47
}
 
48
 
 
49
MemoryRegion TextFilter::decode(const MemoryRegion &a)
 
50
{
 
51
        setup(Decode);
 
52
        return process(a);
 
53
}
 
54
 
 
55
QString TextFilter::arrayToString(const MemoryRegion &a)
 
56
{
 
57
        return QString::fromLatin1(encode(a).toByteArray());
 
58
}
 
59
 
 
60
MemoryRegion TextFilter::stringToArray(const QString &s)
 
61
{
 
62
        if(s.isEmpty())
 
63
                return MemoryRegion();
 
64
        return decode(s.toLatin1());
 
65
}
 
66
 
 
67
QString TextFilter::encodeString(const QString &s)
 
68
{
 
69
        return arrayToString(s.toUtf8());
 
70
}
 
71
 
 
72
QString TextFilter::decodeString(const QString &s)
 
73
{
 
74
        return QString::fromUtf8(stringToArray(s).toByteArray());
 
75
}
 
76
 
 
77
//----------------------------------------------------------------------------
 
78
// Hex
 
79
//----------------------------------------------------------------------------
 
80
static int enhex(uchar c)
 
81
{
 
82
        if(c < 10)
 
83
                return c + '0';
 
84
        else if(c < 16)
 
85
                return c - 10 + 'a';
 
86
        else
 
87
                return -1;
 
88
}
 
89
 
 
90
static int dehex(char c)
 
91
{
 
92
        if(c >= 'a' && c <= 'f')
 
93
                return c - 'a' + 10;
 
94
        else if(c >= 'A' && c <= 'F')
 
95
                return c - 'A' + 10;
 
96
        else if(c >= '0' && c <= '9')
 
97
                return c - '0';
 
98
        else
 
99
                return -1;
 
100
}
 
101
 
 
102
Hex::Hex(Direction dir)
 
103
:TextFilter(dir)
 
104
{
 
105
        clear();
 
106
}
 
107
 
 
108
void Hex::clear()
 
109
{
 
110
        partial = false;
 
111
        _ok = true;
 
112
}
 
113
 
 
114
MemoryRegion Hex::update(const MemoryRegion &m)
 
115
{
 
116
        QByteArray a = m.toByteArray();
 
117
        if(_dir == Encode)
 
118
        {
 
119
                QByteArray out(a.size() * 2, 0);
 
120
                int at = 0;
 
121
                int c;
 
122
                for(int n = 0; n < (int)a.size(); ++n)
 
123
                {
 
124
                        uchar lo = (uchar)a[n] & 0x0f;
 
125
                        uchar hi = (uchar)a[n] >> 4;
 
126
                        c = enhex(hi);
 
127
                        if(c == -1)
 
128
                        {
 
129
                                _ok = false;
 
130
                                break;
 
131
                        }
 
132
                        out[at++] = (char)c;
 
133
                        c = enhex(lo);
 
134
                        if(c == -1)
 
135
                        {
 
136
                                _ok = false;
 
137
                                break;
 
138
                        }
 
139
                        out[at++] = (char)c;
 
140
                }
 
141
                if(!_ok)
 
142
                        return MemoryRegion();
 
143
 
 
144
                return out;
 
145
        }
 
146
        else
 
147
        {
 
148
                uchar lo = 0;
 
149
                uchar hi = 0;
 
150
                bool flag = false;
 
151
                if(partial)
 
152
                {
 
153
                        hi = val;
 
154
                        flag = true;
 
155
                }
 
156
 
 
157
                QByteArray out(a.size() / 2, 0);
 
158
                int at = 0;
 
159
                int c;
 
160
                for(int n = 0; n < (int)a.size(); ++n)
 
161
                {
 
162
                        c = dehex((char)a[n]);
 
163
                        if(c == -1)
 
164
                        {
 
165
                                _ok = false;
 
166
                                break;
 
167
                        }
 
168
                        if(flag)
 
169
                        {
 
170
                                lo = (uchar)c;
 
171
                                uchar full = ((hi & 0x0f) << 4) + (lo & 0x0f);
 
172
                                out[at++] = full;
 
173
                                flag = false;
 
174
                        }
 
175
                        else
 
176
                        {
 
177
                                hi = (uchar)c;
 
178
                                flag = true;
 
179
                        }
 
180
                }
 
181
                if(!_ok)
 
182
                        return MemoryRegion();
 
183
 
 
184
                if(flag)
 
185
                {
 
186
                        val = hi;
 
187
                        partial = true;
 
188
                }
 
189
                return out;
 
190
        }
 
191
}
 
192
 
 
193
MemoryRegion Hex::final()
 
194
{
 
195
        if(partial)
 
196
                _ok = false;
 
197
        return MemoryRegion();
 
198
}
 
199
 
 
200
bool Hex::ok() const
 
201
{
 
202
        return _ok;
 
203
}
 
204
 
 
205
//----------------------------------------------------------------------------
 
206
// Base64
 
207
//----------------------------------------------------------------------------
 
208
Base64::Base64(Direction dir)
 
209
:TextFilter(dir)
 
210
{
 
211
        _lb_enabled = false;
 
212
        _lb_column = 76;
 
213
}
 
214
 
 
215
void Base64::clear()
 
216
{
 
217
        partial.resize(0);
 
218
        _ok = true;
 
219
        col = 0;
 
220
}
 
221
 
 
222
bool Base64::lineBreaksEnabled() const
 
223
{
 
224
        return _lb_enabled;
 
225
}
 
226
 
 
227
int Base64::lineBreaksColumn() const
 
228
{
 
229
        return _lb_column;
 
230
}
 
231
 
 
232
void Base64::setLineBreaksEnabled(bool b)
 
233
{
 
234
        _lb_enabled = b;
 
235
}
 
236
 
 
237
void Base64::setLineBreaksColumn(int column)
 
238
{
 
239
        if(column > 0)
 
240
                _lb_column = column;
 
241
        else
 
242
                _lb_column = 76;
 
243
}
 
244
 
 
245
static QByteArray b64encode(const QByteArray &s)
 
246
{
 
247
        int i;
 
248
        int len = s.size();
 
249
        static char tbl[] =
 
250
                "ABCDEFGH"
 
251
                "IJKLMNOP"
 
252
                "QRSTUVWX"
 
253
                "YZabcdef"
 
254
                "ghijklmn"
 
255
                "opqrstuv"
 
256
                "wxyz0123"
 
257
                "456789+/"
 
258
                "=";
 
259
        int a, b, c;
 
260
 
 
261
        QByteArray p((len + 2) / 3 * 4, 0);
 
262
        int at = 0;
 
263
        for(i = 0; i < len; i += 3)
 
264
        {
 
265
                a = ((unsigned char)s[i] & 3) << 4;
 
266
                if(i + 1 < len)
 
267
                {
 
268
                        a += (unsigned char)s[i + 1] >> 4;
 
269
                        b = ((unsigned char)s[i + 1] & 0xf) << 2;
 
270
                        if(i + 2 < len)
 
271
                        {
 
272
                                b += (unsigned char)s[i + 2] >> 6;
 
273
                                c = (unsigned char)s[i + 2] & 0x3f;
 
274
                        }
 
275
                        else
 
276
                                c = 64;
 
277
                }
 
278
                else
 
279
                        b = c = 64;
 
280
 
 
281
                p[at++] = tbl[(unsigned char)s[i] >> 2];
 
282
                p[at++] = tbl[a];
 
283
                p[at++] = tbl[b];
 
284
                p[at++] = tbl[c];
 
285
        }
 
286
        return p;
 
287
}
 
288
 
 
289
static QByteArray b64decode(const QByteArray &s, bool *ok)
 
290
{
 
291
        // -1 specifies invalid
 
292
        // 64 specifies eof
 
293
        // everything else specifies data
 
294
 
 
295
        static char tbl[] =
 
296
        {
 
297
                -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
 
298
                -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
 
299
                -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63,
 
300
                52,53,54,55,56,57,58,59,60,61,-1,-1,-1,64,-1,-1,
 
301
                -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
 
302
                15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,
 
303
                -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
 
304
                41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1,
 
305
                -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
 
306
                -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
 
307
                -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
 
308
                -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
 
309
                -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
 
310
                -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
 
311
                -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
 
312
                -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
 
313
        };
 
314
 
 
315
        // return value
 
316
        QByteArray p;
 
317
        *ok = true;
 
318
 
 
319
        // this should be a multiple of 4
 
320
        int len = s.size();
 
321
        if(len % 4)
 
322
        {
 
323
                *ok = false;
 
324
                return p;
 
325
        }
 
326
 
 
327
        p.resize(len / 4 * 3);
 
328
 
 
329
        int i;
 
330
        int at = 0;
 
331
 
 
332
        int a, b, c, d;
 
333
        c = d = 0;
 
334
 
 
335
        for(i = 0; i < len; i += 4)
 
336
        {
 
337
                a = tbl[(int)s[i]];
 
338
                b = tbl[(int)s[i + 1]];
 
339
                c = tbl[(int)s[i + 2]];
 
340
                d = tbl[(int)s[i + 3]];
 
341
                if((a == 64 || b == 64) || (a < 0 || b < 0 || c < 0 || d < 0))
 
342
                {
 
343
                        p.resize(0);
 
344
                        *ok = false;
 
345
                        return p;
 
346
                }
 
347
                p[at++] = ((a & 0x3F) << 2) | ((b >> 4) & 0x03);
 
348
                p[at++] = ((b & 0x0F) << 4) | ((c >> 2) & 0x0F);
 
349
                p[at++] = ((c & 0x03) << 6) | ((d >> 0) & 0x3F);
 
350
        }
 
351
 
 
352
        if(c & 64)
 
353
                p.resize(at - 2);
 
354
        else if(d & 64)
 
355
                p.resize(at - 1);
 
356
 
 
357
        return p;
 
358
}
 
359
 
 
360
static int findLF(const QByteArray &in, int offset)
 
361
{
 
362
        for(int n = offset; n < in.size(); ++n)
 
363
        {
 
364
                if(in[n] == '\n')
 
365
                        return n;
 
366
        }
 
367
        return -1;
 
368
}
 
369
 
 
370
static QByteArray insert_linebreaks(const QByteArray &s, int *col, int lfAt)
 
371
{
 
372
        QByteArray out = s;
 
373
 
 
374
        int needed = (out.size() + *col) / lfAt;   // how many newlines needed?
 
375
        if(needed > 0)
 
376
        {
 
377
                int firstlen = lfAt - *col;                // length of first chunk
 
378
                int at = firstlen + (lfAt * (needed - 1)); // position of last newline
 
379
                int lastlen = out.size() - at;             // length of last chunk
 
380
 
 
381
                //printf("size=%d,needed=%d,firstlen=%d,at=%d,lastlen=%d\n", out.size(), needed, firstlen, at, lastlen);
 
382
 
 
383
                // make room
 
384
                out.resize(out.size() + needed);
 
385
 
 
386
                // move backwards
 
387
                for(int n = 0; n < needed; ++n)
 
388
                {
 
389
                        char *p = out.data() + at;
 
390
                        int len;
 
391
                        if(n == 0)
 
392
                                len = lastlen;
 
393
                        else
 
394
                                len = lfAt;
 
395
                        memmove(p + needed - n, p, len);
 
396
                        p[needed - n - 1] = '\n';
 
397
                        at -= lfAt;
 
398
                }
 
399
 
 
400
                *col = lastlen;
 
401
        }
 
402
        else
 
403
                *col += out.size();
 
404
 
 
405
        return out;
 
406
}
 
407
 
 
408
static QByteArray remove_linebreaks(const QByteArray &s)
 
409
{
 
410
        QByteArray out = s;
 
411
 
 
412
        int removed = 0;
 
413
        int at = findLF(out, 0);
 
414
        while(at != -1)
 
415
        {
 
416
                int next = findLF(out, at + 1);
 
417
                int len;
 
418
                if(next != -1)
 
419
                        len = next - at;
 
420
                else
 
421
                        len = out.size() - at;
 
422
 
 
423
                if(len > 1)
 
424
                {
 
425
                        char *p = out.data() + at;
 
426
                        memmove(p - removed, p + 1, len - 1);
 
427
                }
 
428
                ++removed;
 
429
                at = next;
 
430
        }
 
431
        out.resize(out.size() - removed);
 
432
 
 
433
        return out;
 
434
}
 
435
 
 
436
static void appendArray(QByteArray *a, const QByteArray &b)
 
437
{
 
438
        a->append(b);
 
439
}
 
440
 
 
441
MemoryRegion Base64::update(const MemoryRegion &m)
 
442
{
 
443
        QByteArray in;
 
444
        if(_dir == Decode && _lb_enabled)
 
445
                in = remove_linebreaks(m.toByteArray());
 
446
        else
 
447
                in = m.toByteArray();
 
448
 
 
449
        if(in.isEmpty())
 
450
                return MemoryRegion();
 
451
 
 
452
        int chunk;
 
453
        if(_dir == Encode)
 
454
                chunk = 3;
 
455
        else
 
456
                chunk = 4;
 
457
 
 
458
        int size = partial.size() + in.size();
 
459
        if(size < chunk)
 
460
        {
 
461
                appendArray(&partial, in);
 
462
                return MemoryRegion();
 
463
        }
 
464
 
 
465
        int eat = size % chunk;
 
466
 
 
467
        // s = partial + a - eat
 
468
        QByteArray s(partial.size() + in.size() - eat, 0);
 
469
        memcpy(s.data(), partial.data(), partial.size());
 
470
        memcpy(s.data() + partial.size(), in.data(), in.size() - eat);
 
471
 
 
472
        partial.resize(eat);
 
473
        memcpy(partial.data(), in.data() + in.size() - eat, eat);
 
474
 
 
475
        if(_dir == Encode)
 
476
        {
 
477
                if(_lb_enabled)
 
478
                        return insert_linebreaks(b64encode(s), &col, _lb_column);
 
479
                else
 
480
                        return b64encode(s);
 
481
        }
 
482
        else
 
483
        {
 
484
                bool ok;
 
485
                QByteArray out = b64decode(s, &ok);
 
486
                if(!ok)
 
487
                        _ok = false;
 
488
                return out;
 
489
        }
 
490
}
 
491
 
 
492
MemoryRegion Base64::final()
 
493
{
 
494
        if(_dir == Encode)
 
495
        {
 
496
                if(_lb_enabled)
 
497
                        return insert_linebreaks(b64encode(partial), &col, _lb_column);
 
498
                else
 
499
                        return b64encode(partial);
 
500
        }
 
501
        else
 
502
        {
 
503
                bool ok;
 
504
                QByteArray out = b64decode(partial, &ok);
 
505
                if(!ok)
 
506
                        _ok = false;
 
507
                return out;
 
508
        }
 
509
}
 
510
 
 
511
bool Base64::ok() const
 
512
{
 
513
        return _ok;
 
514
}
 
515
 
 
516
}