• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • KDE Support
  • Sitemap
  • Contact Us
 

qca

qca_textfilter.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2003-2005  Justin Karneges <justin@affinix.com>
00003  * Copyright (C) 2004,2005  Brad Hards <bradh@frogmouth.net>
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00018  * 02110-1301  USA
00019  *
00020  */
00021 
00022 #include "qca_textfilter.h"
00023 
00024 namespace QCA {
00025 
00026 //----------------------------------------------------------------------------
00027 // TextFilter
00028 //----------------------------------------------------------------------------
00029 TextFilter::TextFilter(Direction dir)
00030 {
00031     setup(dir);
00032 }
00033 
00034 void TextFilter::setup(Direction dir)
00035 {
00036     _dir = dir;
00037 }
00038 
00039 Direction TextFilter::direction() const
00040 {
00041     return _dir;
00042 }
00043 
00044 MemoryRegion TextFilter::encode(const MemoryRegion &a)
00045 {
00046     setup(Encode);
00047     return process(a);
00048 }
00049 
00050 MemoryRegion TextFilter::decode(const MemoryRegion &a)
00051 {
00052     setup(Decode);
00053     return process(a);
00054 }
00055 
00056 QString TextFilter::arrayToString(const MemoryRegion &a)
00057 {
00058     return QString::fromLatin1(encode(a).toByteArray());
00059 }
00060 
00061 MemoryRegion TextFilter::stringToArray(const QString &s)
00062 {
00063     if(s.isEmpty())
00064         return MemoryRegion();
00065     return decode(s.toLatin1());
00066 }
00067 
00068 QString TextFilter::encodeString(const QString &s)
00069 {
00070     return arrayToString(s.toUtf8());
00071 }
00072 
00073 QString TextFilter::decodeString(const QString &s)
00074 {
00075     return QString::fromUtf8(stringToArray(s).toByteArray());
00076 }
00077 
00078 //----------------------------------------------------------------------------
00079 // Hex
00080 //----------------------------------------------------------------------------
00081 static int enhex(uchar c)
00082 {
00083     if(c < 10)
00084         return c + '0';
00085     else if(c < 16)
00086         return c - 10 + 'a';
00087     else
00088         return -1;
00089 }
00090 
00091 static int dehex(char c)
00092 {
00093     if(c >= 'a' && c <= 'f')
00094         return c - 'a' + 10;
00095     else if(c >= 'A' && c <= 'F')
00096         return c - 'A' + 10;
00097     else if(c >= '0' && c <= '9')
00098         return c - '0';
00099     else
00100         return -1;
00101 }
00102 
00103 Hex::Hex(Direction dir)
00104 :TextFilter(dir)
00105 {
00106     clear();
00107 }
00108 
00109 void Hex::clear()
00110 {
00111     partial = false;
00112     _ok = true;
00113 }
00114 
00115 MemoryRegion Hex::update(const MemoryRegion &m)
00116 {
00117     QByteArray a = m.toByteArray();
00118     if(_dir == Encode)
00119     {
00120         QByteArray out(a.size() * 2, 0);
00121         int at = 0;
00122         int c;
00123         for(int n = 0; n < (int)a.size(); ++n)
00124         {
00125             uchar lo = (uchar)a[n] & 0x0f;
00126             uchar hi = (uchar)a[n] >> 4;
00127             c = enhex(hi);
00128             if(c == -1)
00129             {
00130                 _ok = false;
00131                 break;
00132             }
00133             out[at++] = (char)c;
00134             c = enhex(lo);
00135             if(c == -1)
00136             {
00137                 _ok = false;
00138                 break;
00139             }
00140             out[at++] = (char)c;
00141         }
00142         if(!_ok)
00143             return MemoryRegion();
00144 
00145         return out;
00146     }
00147     else
00148     {
00149         uchar lo = 0;
00150         uchar hi = 0;
00151         bool flag = false;
00152         if(partial)
00153         {
00154             hi = val;
00155             flag = true;
00156         }
00157 
00158         QByteArray out(a.size() / 2, 0);
00159         int at = 0;
00160         int c;
00161         for(int n = 0; n < (int)a.size(); ++n)
00162         {
00163             c = dehex((char)a[n]);
00164             if(c == -1)
00165             {
00166                 _ok = false;
00167                 break;
00168             }
00169             if(flag)
00170             {
00171                 lo = (uchar)c;
00172                 uchar full = ((hi & 0x0f) << 4) + (lo & 0x0f);
00173                 out[at++] = full;
00174                 flag = false;
00175             }
00176             else
00177             {
00178                 hi = (uchar)c;
00179                 flag = true;
00180             }
00181         }
00182         if(!_ok)
00183             return MemoryRegion();
00184 
00185         if(flag)
00186         {
00187             val = hi;
00188             partial = true;
00189         }
00190         return out;
00191     }
00192 }
00193 
00194 MemoryRegion Hex::final()
00195 {
00196     if(partial)
00197         _ok = false;
00198     return MemoryRegion();
00199 }
00200 
00201 bool Hex::ok() const
00202 {
00203     return _ok;
00204 }
00205 
00206 //----------------------------------------------------------------------------
00207 // Base64
00208 //----------------------------------------------------------------------------
00209 Base64::Base64(Direction dir)
00210 :TextFilter(dir)
00211 {
00212     _lb_enabled = false;
00213     _lb_column = 76;
00214 }
00215 
00216 void Base64::clear()
00217 {
00218     partial.resize(0);
00219     _ok = true;
00220     col = 0;
00221 }
00222 
00223 bool Base64::lineBreaksEnabled() const
00224 {
00225     return _lb_enabled;
00226 }
00227 
00228 int Base64::lineBreaksColumn() const
00229 {
00230     return _lb_column;
00231 }
00232 
00233 void Base64::setLineBreaksEnabled(bool b)
00234 {
00235     _lb_enabled = b;
00236 }
00237 
00238 void Base64::setLineBreaksColumn(int column)
00239 {
00240     if(column > 0)
00241         _lb_column = column;
00242     else
00243         _lb_column = 76;
00244 }
00245 
00246 static QByteArray b64encode(const QByteArray &s)
00247 {
00248     int i;
00249     int len = s.size();
00250     static char tbl[] =
00251         "ABCDEFGH"
00252         "IJKLMNOP"
00253         "QRSTUVWX"
00254         "YZabcdef"
00255         "ghijklmn"
00256         "opqrstuv"
00257         "wxyz0123"
00258         "456789+/"
00259         "=";
00260     int a, b, c;
00261 
00262     QByteArray p((len + 2) / 3 * 4, 0);
00263     int at = 0;
00264     for(i = 0; i < len; i += 3)
00265     {
00266         a = ((unsigned char)s[i] & 3) << 4;
00267         if(i + 1 < len)
00268         {
00269             a += (unsigned char)s[i + 1] >> 4;
00270             b = ((unsigned char)s[i + 1] & 0xf) << 2;
00271             if(i + 2 < len)
00272             {
00273                 b += (unsigned char)s[i + 2] >> 6;
00274                 c = (unsigned char)s[i + 2] & 0x3f;
00275             }
00276             else
00277                 c = 64;
00278         }
00279         else
00280             b = c = 64;
00281 
00282         p[at++] = tbl[(unsigned char)s[i] >> 2];
00283         p[at++] = tbl[a];
00284         p[at++] = tbl[b];
00285         p[at++] = tbl[c];
00286     }
00287     return p;
00288 }
00289 
00290 static QByteArray b64decode(const QByteArray &s, bool *ok)
00291 {
00292     // -1 specifies invalid
00293     // 64 specifies eof
00294     // everything else specifies data
00295 
00296     static char tbl[] =
00297     {
00298         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00299         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00300         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63,
00301         52,53,54,55,56,57,58,59,60,61,-1,-1,-1,64,-1,-1,
00302         -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
00303         15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,
00304         -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
00305         41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1,
00306         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00307         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00308         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00309         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00310         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00311         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00312         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00313         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00314     };
00315 
00316     // return value
00317     QByteArray p;
00318     *ok = true;
00319 
00320     // this should be a multiple of 4
00321     int len = s.size();
00322     if(len % 4)
00323     {
00324         *ok = false;
00325         return p;
00326     }
00327 
00328     p.resize(len / 4 * 3);
00329 
00330     int i;
00331     int at = 0;
00332 
00333     int a, b, c, d;
00334     c = d = 0;
00335 
00336     for(i = 0; i < len; i += 4)
00337     {
00338         a = tbl[(int)s[i]];
00339         b = tbl[(int)s[i + 1]];
00340         c = tbl[(int)s[i + 2]];
00341         d = tbl[(int)s[i + 3]];
00342         if((a == 64 || b == 64) || (a < 0 || b < 0 || c < 0 || d < 0))
00343         {
00344             p.resize(0);
00345             *ok = false;
00346             return p;
00347         }
00348         p[at++] = ((a & 0x3F) << 2) | ((b >> 4) & 0x03);
00349         p[at++] = ((b & 0x0F) << 4) | ((c >> 2) & 0x0F);
00350         p[at++] = ((c & 0x03) << 6) | ((d >> 0) & 0x3F);
00351     }
00352 
00353     if(c & 64)
00354         p.resize(at - 2);
00355     else if(d & 64)
00356         p.resize(at - 1);
00357 
00358     return p;
00359 }
00360 
00361 static int findLF(const QByteArray &in, int offset)
00362 {
00363     for(int n = offset; n < in.size(); ++n)
00364     {
00365         if(in[n] == '\n')
00366             return n;
00367     }
00368     return -1;
00369 }
00370 
00371 static QByteArray insert_linebreaks(const QByteArray &s, int *col, int lfAt)
00372 {
00373     QByteArray out = s;
00374 
00375     int needed = (out.size() + *col) / lfAt;   // how many newlines needed?
00376     if(needed > 0)
00377     {
00378         int firstlen = lfAt - *col;                // length of first chunk
00379         int at = firstlen + (lfAt * (needed - 1)); // position of last newline
00380         int lastlen = out.size() - at;             // length of last chunk
00381 
00382         //printf("size=%d,needed=%d,firstlen=%d,at=%d,lastlen=%d\n", out.size(), needed, firstlen, at, lastlen);
00383 
00384         // make room
00385         out.resize(out.size() + needed);
00386 
00387         // move backwards
00388         for(int n = 0; n < needed; ++n)
00389         {
00390             char *p = out.data() + at;
00391             int len;
00392             if(n == 0)
00393                 len = lastlen;
00394             else
00395                 len = lfAt;
00396             memmove(p + needed - n, p, len);
00397             p[needed - n - 1] = '\n';
00398             at -= lfAt;
00399         }
00400 
00401         *col = lastlen;
00402     }
00403     else
00404         *col += out.size();
00405 
00406     return out;
00407 }
00408 
00409 static QByteArray remove_linebreaks(const QByteArray &s)
00410 {
00411     QByteArray out = s;
00412 
00413     int removed = 0;
00414     int at = findLF(out, 0);
00415     while(at != -1)
00416     {
00417         int next = findLF(out, at + 1);
00418         int len;
00419         if(next != -1)
00420             len = next - at;
00421         else
00422             len = out.size() - at;
00423 
00424         if(len > 1)
00425         {
00426             char *p = out.data() + at;
00427             memmove(p - removed, p + 1, len - 1);
00428         }
00429         ++removed;
00430         at = next;
00431     }
00432     out.resize(out.size() - removed);
00433 
00434     return out;
00435 }
00436 
00437 static void appendArray(QByteArray *a, const QByteArray &b)
00438 {
00439     a->append(b);
00440 }
00441 
00442 MemoryRegion Base64::update(const MemoryRegion &m)
00443 {
00444     QByteArray in;
00445     if(_dir == Decode && _lb_enabled)
00446         in = remove_linebreaks(m.toByteArray());
00447     else
00448         in = m.toByteArray();
00449 
00450     if(in.isEmpty())
00451         return MemoryRegion();
00452 
00453     int chunk;
00454     if(_dir == Encode)
00455         chunk = 3;
00456     else
00457         chunk = 4;
00458 
00459     int size = partial.size() + in.size();
00460     if(size < chunk)
00461     {
00462         appendArray(&partial, in);
00463         return MemoryRegion();
00464     }
00465 
00466     int eat = size % chunk;
00467 
00468     // s = partial + a - eat
00469     QByteArray s(partial.size() + in.size() - eat, 0);
00470     memcpy(s.data(), partial.data(), partial.size());
00471     memcpy(s.data() + partial.size(), in.data(), in.size() - eat);
00472 
00473     partial.resize(eat);
00474     memcpy(partial.data(), in.data() + in.size() - eat, eat);
00475 
00476     if(_dir == Encode)
00477     {
00478         if(_lb_enabled)
00479             return insert_linebreaks(b64encode(s), &col, _lb_column);
00480         else
00481             return b64encode(s);
00482     }
00483     else
00484     {
00485         bool ok;
00486         QByteArray out = b64decode(s, &ok);
00487         if(!ok)
00488             _ok = false;
00489         return out;
00490     }
00491 }
00492 
00493 MemoryRegion Base64::final()
00494 {
00495     if(_dir == Encode)
00496     {
00497         if(_lb_enabled)
00498             return insert_linebreaks(b64encode(partial), &col, _lb_column);
00499         else
00500             return b64encode(partial);
00501     }
00502     else
00503     {
00504         bool ok;
00505         QByteArray out = b64decode(partial, &ok);
00506         if(!ok)
00507             _ok = false;
00508         return out;
00509     }
00510 }
00511 
00512 bool Base64::ok() const
00513 {
00514     return _ok;
00515 }
00516 
00517 }

qca

Skip menu "qca"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

KDE Support

Skip menu "KDE Support"
  • akonadi
  • Decibel
  • grantlee
  • kdewin
  • phonon
  •     Backend
  • polkit-qt
  • qca
  • qimageblitz
  • soprano
  • strigi
  •     searchclient
  •     streamanalyzer
  •     streams
Generated for KDE Support by doxygen 1.5.9-20090814
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal