KIMAP

rfccodecs.cpp
Go to the documentation of this file.
1/**********************************************************************
2 *
3 * rfccodecs.cpp - handler for various rfc/mime encodings
4 * SPDX-FileCopyrightText: 2000 s .carstens@gmx.de
5 *
6 * SPDX-License-Identifier: LGPL-2.0-or-later
7 *
8 *********************************************************************/
9/**
10 * @file
11 * This file is part of the IMAP support library and defines the
12 * RfcCodecs class.
13 *
14 * @brief
15 * Defines the RfcCodecs class.
16 *
17 * @author Sven Carstens
18 */
19
20#include "rfccodecs.h"
21
22#include <ctype.h>
23#include <sys/types.h>
24
25#include <stdio.h>
26#include <stdlib.h>
27
28#include <QByteArray>
29#include <QLatin1Char>
30
31using namespace KIMAP;
32
33// This part taken from rfc 2192 IMAP URL Scheme. C. Newman. September 1997.
34// adapted to QT-Toolkit by Sven Carstens <s.carstens@gmx.de> 2000
35
36//@cond PRIVATE
37static const unsigned char base64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
38#define UNDEFINED 64
39#define MAXLINE 76
40static const char especials[17] = "()<>@,;:\"/[]?.= ";
41
42/* UTF16 definitions */
43#define UTF16MASK 0x03FFUL
44#define UTF16SHIFT 10
45#define UTF16BASE 0x10000UL
46#define UTF16HIGHSTART 0xD800UL
47#define UTF16HIGHEND 0xDBFFUL
48#define UTF16LOSTART 0xDC00UL
49#define UTF16LOEND 0xDFFFUL
50//@endcond
51
52//-----------------------------------------------------------------------------
54{
55 unsigned char c;
56 unsigned char i;
57 unsigned char bitcount;
58 unsigned long ucs4;
59 unsigned long utf16;
60 unsigned long bitbuf;
61 unsigned char base64[256];
62 unsigned char utf8[6];
63 unsigned int srcPtr = 0;
64 QByteArray dst;
65 QByteArray src = inSrc;
66 uint srcLen = inSrc.length();
67
68 /* initialize modified base64 decoding table */
69 memset(base64, UNDEFINED, sizeof(base64));
70 for (i = 0; i < sizeof(base64chars); ++i) {
71 base64[(int)base64chars[i]] = i;
72 }
73
74 /* loop until end of string */
75 while (srcPtr < srcLen) {
76 c = src[srcPtr++];
77 /* deal with literal characters and &- */
78 if (c != '&' || src[srcPtr] == '-') {
79 /* encode literally */
80 dst += c;
81 /* skip over the '-' if this is an &- sequence */
82 if (c == '&') {
83 srcPtr++;
84 }
85 } else {
86 /* convert modified UTF-7 -> UTF-16 -> UCS-4 -> UTF-8 -> HEX */
87 bitbuf = 0;
88 bitcount = 0;
89 ucs4 = 0;
90 while ((c = base64[(unsigned char)src[srcPtr]]) != UNDEFINED) {
91 ++srcPtr;
92 bitbuf = (bitbuf << 6) | c;
93 bitcount += 6;
94 /* enough bits for a UTF-16 character? */
95 if (bitcount >= 16) {
96 bitcount -= 16;
97 utf16 = (bitcount ? bitbuf >> bitcount : bitbuf) & 0xffff;
98 /* convert UTF16 to UCS4 */
99 if (utf16 >= UTF16HIGHSTART && utf16 <= UTF16HIGHEND) {
100 ucs4 = (utf16 - UTF16HIGHSTART) << UTF16SHIFT;
101 continue;
102 } else if (utf16 >= UTF16LOSTART && utf16 <= UTF16LOEND) {
103 ucs4 += utf16 - UTF16LOSTART + UTF16BASE;
104 } else {
105 ucs4 = utf16;
106 }
107 /* convert UTF-16 range of UCS4 to UTF-8 */
108 if (ucs4 <= 0x7fUL) {
109 utf8[0] = ucs4;
110 i = 1;
111 } else if (ucs4 <= 0x7ffUL) {
112 utf8[0] = 0xc0 | (ucs4 >> 6);
113 utf8[1] = 0x80 | (ucs4 & 0x3f);
114 i = 2;
115 } else if (ucs4 <= 0xffffUL) {
116 utf8[0] = 0xe0 | (ucs4 >> 12);
117 utf8[1] = 0x80 | ((ucs4 >> 6) & 0x3f);
118 utf8[2] = 0x80 | (ucs4 & 0x3f);
119 i = 3;
120 } else {
121 utf8[0] = 0xf0 | (ucs4 >> 18);
122 utf8[1] = 0x80 | ((ucs4 >> 12) & 0x3f);
123 utf8[2] = 0x80 | ((ucs4 >> 6) & 0x3f);
124 utf8[3] = 0x80 | (ucs4 & 0x3f);
125 i = 4;
126 }
127 /* copy it */
128 for (c = 0; c < i; ++c) {
129 dst += utf8[c];
130 }
131 }
132 }
133 /* skip over trailing '-' in modified UTF-7 encoding */
134 if (src[srcPtr] == '-') {
135 ++srcPtr;
136 }
137 }
138 }
139 return dst;
140}
141
146
147//-----------------------------------------------------------------------------
148
150{
151 int len = src.length();
152 QByteArray result;
153 result.reserve(2 * len);
154 for (int i = 0; i < len; i++) {
155 if (src[i] == '"' || src[i] == '\\') {
156 result += '\\';
157 }
158 result += src[i];
159 }
160 result.squeeze();
161 return result;
162}
163
165{
166 uint len = src.length();
167 QString result;
168 result.reserve(2 * len);
169 for (unsigned int i = 0; i < len; i++) {
170 if (src[i] == QLatin1Char('"') || src[i] == QLatin1Char('\\')) {
171 result += QLatin1Char('\\');
172 }
173 result += src[i];
174 }
175 // result.squeeze(); - unnecessary and slow
176 return result;
177}
178
179//-----------------------------------------------------------------------------
184
186{
187 unsigned int utf8pos;
188 unsigned int utf8total;
189 unsigned int c;
190 unsigned int utf7mode;
191 unsigned int bitstogo;
192 unsigned int utf16flag;
193 unsigned int ucs4;
194 unsigned int bitbuf;
195 QByteArray src = inSrc;
196 QByteArray dst;
197
198 int srcPtr = 0;
199 utf7mode = 0;
200 utf8total = 0;
201 bitstogo = 0;
202 utf8pos = 0;
203 bitbuf = 0;
204 ucs4 = 0;
205 while (srcPtr < src.length()) {
206 c = (unsigned char)src[srcPtr++];
207 /* normal character? */
208 if (c >= ' ' && c <= '~') {
209 /* switch out of UTF-7 mode */
210 if (utf7mode) {
211 if (bitstogo) {
212 dst += base64chars[(bitbuf << (6 - bitstogo)) & 0x3F];
213 bitstogo = 0;
214 }
215 dst += '-';
216 utf7mode = 0;
217 }
218 dst += c;
219 /* encode '&' as '&-' */
220 if (c == '&') {
221 dst += '-';
222 }
223 continue;
224 }
225 /* switch to UTF-7 mode */
226 if (!utf7mode) {
227 dst += '&';
228 utf7mode = 1;
229 }
230 /* Encode US-ASCII characters as themselves */
231 if (c < 0x80) {
232 ucs4 = c;
233 utf8total = 1;
234 } else if (utf8total) {
235 /* save UTF8 bits into UCS4 */
236 ucs4 = (ucs4 << 6) | (c & 0x3FUL);
237 if (++utf8pos < utf8total) {
238 continue;
239 }
240 } else {
241 utf8pos = 1;
242 if (c < 0xE0) {
243 utf8total = 2;
244 ucs4 = c & 0x1F;
245 } else if (c < 0xF0) {
246 utf8total = 3;
247 ucs4 = c & 0x0F;
248 } else {
249 /* NOTE: can't convert UTF8 sequences longer than 4 */
250 utf8total = 4;
251 ucs4 = c & 0x03;
252 }
253 continue;
254 }
255 /* loop to split ucs4 into two utf16 chars if necessary */
256 utf8total = 0;
257 do {
258 if (ucs4 >= UTF16BASE) {
259 ucs4 -= UTF16BASE;
260 bitbuf = (bitbuf << 16) | ((ucs4 >> UTF16SHIFT) + UTF16HIGHSTART);
261 ucs4 = (ucs4 & UTF16MASK) + UTF16LOSTART;
262 utf16flag = 1;
263 } else {
264 bitbuf = (bitbuf << 16) | ucs4;
265 utf16flag = 0;
266 }
267 bitstogo += 16;
268 /* spew out base64 */
269 while (bitstogo >= 6) {
270 bitstogo -= 6;
271 dst += base64chars[(bitstogo ? (bitbuf >> bitstogo) : bitbuf) & 0x3F];
272 }
273 } while (utf16flag);
274 }
275 /* if in UTF-7 mode, finish in ASCII */
276 if (utf7mode) {
277 if (bitstogo) {
278 dst += base64chars[(bitbuf << (6 - bitstogo)) & 0x3F];
279 }
280 dst += '-';
281 }
282 return quoteIMAP(dst);
283}
const char * constData() const const
qsizetype length() const const
void reserve(qsizetype size)
void squeeze()
QString fromUtf8(QByteArrayView str)
qsizetype length() const const
void reserve(qsizetype size)
QByteArray toUtf8() const const
This file is part of the IMAP support library and defines the RfcCodecs class.
KIMAP_EXPORT QString quoteIMAP(const QString &src)
Replaces " with \" and \ with \\ " and \ characters.
KIMAP_EXPORT QByteArray decodeImapFolderName(const QByteArray &inSrc)
Converts an UTF-7 encoded IMAP mailbox to a QByteArray.
Definition rfccodecs.cpp:53
KIMAP_EXPORT QByteArray encodeImapFolderName(const QByteArray &src)
Converts an Unicode IMAP mailbox to a QByteArray which can be used in IMAP communication.
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:14:37 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.