fix bug 4773, 'remove obsolescent AC_C_CONST'
[claws.git] / src / common / quoted-printable.c
blobea223613b8cfaf678f16aa7aa1decfba7c5f5907
1 /*
2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2012 Hiroyuki Yamamoto and the Claws Mail team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
10 * This program 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
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "config.h"
22 #include <glib.h>
23 #include <ctype.h>
25 #include "utils.h"
27 #define MAX_LINELEN 76
29 #define IS_LBREAK(p) \
30 (*(p) == '\0' || *(p) == '\n' || (*(p) == '\r' && *((p) + 1) == '\n'))
32 #define SOFT_LBREAK_IF_REQUIRED(n) \
33 if (len + (n) > MAX_LINELEN || \
34 (len + (n) == MAX_LINELEN && (!IS_LBREAK(inp + 1)))) { \
35 *outp++ = '='; \
36 *outp++ = '\n'; \
37 len = 0; \
40 void qp_encode_line(gchar *out, const guchar *in)
42 const guchar *inp = in;
43 gchar *outp = out;
44 guchar ch;
45 gint len = 0;
47 while (*inp != '\0') {
48 ch = *inp;
50 if (IS_LBREAK(inp)) {
51 *outp++ = '\n';
52 len = 0;
53 if (*inp == '\r')
54 inp++;
55 inp++;
56 } else if (ch == '\t' || ch == ' ') {
57 if (IS_LBREAK(inp + 1)) {
58 SOFT_LBREAK_IF_REQUIRED(3);
59 *outp++ = '=';
60 get_hex_str(outp, ch);
61 outp += 2;
62 len += 3;
63 inp++;
64 } else {
65 SOFT_LBREAK_IF_REQUIRED(1);
66 *outp++ = *inp++;
67 len++;
69 } else if ((ch >= 33 && ch <= 60) || (ch >= 62 && ch <= 126)) {
70 SOFT_LBREAK_IF_REQUIRED(1);
71 *outp++ = *inp++;
72 len++;
73 } else {
74 SOFT_LBREAK_IF_REQUIRED(3);
75 *outp++ = '=';
76 get_hex_str(outp, ch);
77 outp += 2;
78 len += 3;
79 inp++;
83 if (len > 0)
84 *outp++ = '\n';
86 *outp = '\0';
89 gint qp_decode_line(gchar *str)
91 gchar *inp = str, *outp = str;
93 while (*inp != '\0') {
94 if (*inp == '=') {
95 if (inp[1] && inp[2] &&
96 get_hex_value((guchar *)outp, inp[1], inp[2])
97 == TRUE) {
98 inp += 3;
99 } else if (inp[1] == '\0' || g_ascii_isspace(inp[1])) {
100 /* soft line break */
101 break;
102 } else {
103 /* broken QP string */
104 *outp = *inp++;
106 } else {
107 *outp = *inp++;
109 outp++;
112 *outp = '\0';
114 return outp - str;
117 gint qp_decode_const(gchar *out, gint avail, const gchar *str)
119 const gchar *inp = str;
120 gchar *outp = out;
122 while (*inp != '\0' && avail > 0) {
123 if (*inp == '=') {
124 if (inp[1] && inp[2] &&
125 get_hex_value((guchar *)outp, inp[1], inp[2])
126 == TRUE) {
127 inp += 3;
128 } else if (inp[1] == '\0' || g_ascii_isspace(inp[1])) {
129 /* soft line break */
130 break;
131 } else {
132 /* broken QP string */
133 *outp = *inp++;
135 } else {
136 *outp = *inp++;
138 outp++;
139 avail--;
142 *outp = '\0';
144 return outp - out;
147 gint qp_decode_q_encoding(guchar *out, const gchar *in, gint inlen)
149 const gchar *inp = in;
150 guchar *outp = out;
152 if (inlen < 0)
153 inlen = G_MAXINT;
155 while (inp - in < inlen && *inp != '\0') {
156 if (*inp == '=' && inp + 3 - in <= inlen) {
157 if (get_hex_value(outp, inp[1], inp[2]) == TRUE) {
158 inp += 3;
159 } else {
160 *outp = *inp++;
162 } else if (*inp == '_') {
163 *outp = ' ';
164 inp++;
165 } else {
166 *outp = *inp++;
168 outp++;
171 *outp = '\0';
173 return outp - out;
176 gint qp_get_q_encoding_len(const guchar *str)
178 const guchar *inp = str;
179 gint len = 0;
181 while (*inp != '\0') {
182 if (*inp == 0x20)
183 len++;
184 else if (*inp == '=' || *inp == '?' || *inp == '_' ||
185 *inp < 32 || *inp > 127 || g_ascii_isspace(*inp))
186 len += 3;
187 else
188 len++;
190 inp++;
193 return len;
196 void qp_q_encode(gchar *out, const guchar *in)
198 const guchar *inp = in;
199 gchar *outp = out;
201 while (*inp != '\0') {
202 if (*inp == 0x20)
203 *outp++ = '_';
204 else if (*inp == '=' || *inp == '?' || *inp == '_' ||
205 *inp < 32 || *inp > 127 || g_ascii_isspace(*inp)) {
206 *outp++ = '=';
207 get_hex_str(outp, *inp);
208 outp += 2;
209 } else
210 *outp++ = *inp;
212 inp++;
215 *outp = '\0';