Annotation of embedaddon/php/ext/mbstring/libmbfl/filters/mbfilter_qprint.c, revision 1.1.1.1
1.1 misho 1: /*
2: * "streamable kanji code filter and converter"
3: * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
4: *
5: * LICENSE NOTICES
6: *
7: * This file is part of "streamable kanji code filter and converter",
8: * which is distributed under the terms of GNU Lesser General Public
9: * License (version 2) as published by the Free Software Foundation.
10: *
11: * This software 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 Lesser General Public License for more details.
15: *
16: * You should have received a copy of the GNU Lesser General Public
17: * License along with "streamable kanji code filter and converter";
18: * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
19: * Suite 330, Boston, MA 02111-1307 USA
20: *
21: * The author of this file:
22: *
23: */
24: /*
25: * The source code included in this files was separated from mbfilter.c
26: * by moriyoshi koizumi <moriyoshi@php.net> on 4 dec 2002.
27: *
28: */
29:
30: #ifdef HAVE_CONFIG_H
31: #include "config.h"
32: #endif
33:
34: #include "mbfilter.h"
35: #include "mbfilter_qprint.h"
36: #include "unicode_prop.h"
37:
38: static const char *mbfl_encoding_qprint_aliases[] = {"qprint", NULL};
39:
40: const mbfl_encoding mbfl_encoding_qprint = {
41: mbfl_no_encoding_qprint,
42: "Quoted-Printable",
43: "Quoted-Printable",
44: (const char *(*)[])&mbfl_encoding_qprint_aliases,
45: NULL,
46: MBFL_ENCTYPE_SBCS
47: };
48:
49: const struct mbfl_convert_vtbl vtbl_8bit_qprint = {
50: mbfl_no_encoding_8bit,
51: mbfl_no_encoding_qprint,
52: mbfl_filt_conv_common_ctor,
53: mbfl_filt_conv_common_dtor,
54: mbfl_filt_conv_qprintenc,
55: mbfl_filt_conv_qprintenc_flush };
56:
57: const struct mbfl_convert_vtbl vtbl_qprint_8bit = {
58: mbfl_no_encoding_qprint,
59: mbfl_no_encoding_8bit,
60: mbfl_filt_conv_common_ctor,
61: mbfl_filt_conv_common_dtor,
62: mbfl_filt_conv_qprintdec,
63: mbfl_filt_conv_qprintdec_flush };
64:
65:
66: #define CK(statement) do { if ((statement) < 0) return (-1); } while (0)
67:
68: /*
69: * any => Quoted-Printable
70: */
71:
72: int mbfl_filt_conv_qprintenc(int c, mbfl_convert_filter *filter)
73: {
74: int s, n;
75:
76: switch (filter->status & 0xff) {
77: case 0:
78: filter->cache = c;
79: filter->status++;
80: break;
81: default:
82: s = filter->cache;
83: filter->cache = c;
84: n = (filter->status & 0xff00) >> 8;
85:
86: if (s == 0) { /* null */
87: CK((*filter->output_function)(s, filter->data));
88: filter->status &= ~0xff00;
89: break;
90: }
91:
92: if ((filter->status & MBFL_QPRINT_STS_MIME_HEADER) == 0) {
93: if (s == 0x0a || (s == 0x0d && c != 0x0a)) { /* line feed */
94: CK((*filter->output_function)(0x0d, filter->data)); /* CR */
95: CK((*filter->output_function)(0x0a, filter->data)); /* LF */
96: filter->status &= ~0xff00;
97: break;
98: } else if (s == 0x0d) {
99: break;
100: }
101: }
102:
103: if ((filter->status & MBFL_QPRINT_STS_MIME_HEADER) == 0 && n >= 72) { /* soft line feed */
104: CK((*filter->output_function)(0x3d, filter->data)); /* '=' */
105: CK((*filter->output_function)(0x0d, filter->data)); /* CR */
106: CK((*filter->output_function)(0x0a, filter->data)); /* LF */
107: filter->status &= ~0xff00;
108: }
109:
110: if (s <= 0 || s >= 0x80 || s == 0x3d /* not ASCII or '=' */
111: || ((filter->status & MBFL_QPRINT_STS_MIME_HEADER) != 0 &&
112: (mbfl_charprop_table[s] & MBFL_CHP_MMHQENC) != 0)) {
113: /* hex-octet */
114: CK((*filter->output_function)(0x3d, filter->data)); /* '=' */
115: n = (s >> 4) & 0xf;
116: if (n < 10) {
117: n += 48; /* '0' */
118: } else {
119: n += 55; /* 'A' - 10 */
120: }
121: CK((*filter->output_function)(n, filter->data));
122: n = s & 0xf;
123: if (n < 10) {
124: n += 48;
125: } else {
126: n += 55;
127: }
128: CK((*filter->output_function)(n, filter->data));
129: if ((filter->status & MBFL_QPRINT_STS_MIME_HEADER) == 0) {
130: filter->status += 0x300;
131: }
132: } else {
133: CK((*filter->output_function)(s, filter->data));
134: if ((filter->status & MBFL_QPRINT_STS_MIME_HEADER) == 0) {
135: filter->status += 0x100;
136: }
137: }
138: break;
139: }
140:
141: return c;
142: }
143:
144: int mbfl_filt_conv_qprintenc_flush(mbfl_convert_filter *filter)
145: {
146: /* flush filter cache */
147: (*filter->filter_function)('\0', filter);
148: filter->status &= ~0xffff;
149: filter->cache = 0;
150: return 0;
151: }
152:
153: /*
154: * Quoted-Printable => any
155: */
156: int mbfl_filt_conv_qprintdec(int c, mbfl_convert_filter *filter)
157: {
158: int n, m;
159:
160: static int hex2code_map[] = {
161: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
162: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
163: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
164: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
165: -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
166: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
167: -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
168: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
169: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
170: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
171: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
172: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
173: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
174: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
175: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
176: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
177: };
178:
179: switch (filter->status) {
180: case 1:
181: if (hex2code_map[c & 0xff] >= 0) {
182: filter->cache = c;
183: filter->status = 2;
184: } else if (c == 0x0d) { /* soft line feed */
185: filter->status = 3;
186: } else if (c == 0x0a) { /* soft line feed */
187: filter->status = 0;
188: } else {
189: CK((*filter->output_function)(0x3d, filter->data)); /* '=' */
190: CK((*filter->output_function)(c, filter->data));
191: filter->status = 0;
192: }
193: break;
194: case 2:
195: m = hex2code_map[c & 0xff];
196: if (m < 0) {
197: CK((*filter->output_function)(0x3d, filter->data)); /* '=' */
198: CK((*filter->output_function)(filter->cache, filter->data));
199: n = c;
200: } else {
201: n = hex2code_map[filter->cache] << 4 | m;
202: }
203: CK((*filter->output_function)(n, filter->data));
204: filter->status = 0;
205: break;
206: case 3:
207: if (c != 0x0a) { /* LF */
208: CK((*filter->output_function)(c, filter->data));
209: }
210: filter->status = 0;
211: break;
212: default:
213: if (c == 0x3d) { /* '=' */
214: filter->status = 1;
215: } else {
216: CK((*filter->output_function)(c, filter->data));
217: }
218: break;
219: }
220:
221: return c;
222: }
223:
224: int mbfl_filt_conv_qprintdec_flush(mbfl_convert_filter *filter)
225: {
226: int status, cache;
227:
228: status = filter->status;
229: cache = filter->cache;
230: filter->status = 0;
231: filter->cache = 0;
232: /* flush fragments */
233: if (status == 1) {
234: CK((*filter->output_function)(0x3d, filter->data)); /* '=' */
235: } else if (status == 2) {
236: CK((*filter->output_function)(0x3d, filter->data)); /* '=' */
237: CK((*filter->output_function)(cache, filter->data));
238: }
239:
240: return 0;
241: }
242:
243:
244:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>