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_uuencode.h"
36 :
37 : const mbfl_encoding mbfl_encoding_uuencode = {
38 : mbfl_no_encoding_uuencode,
39 : "UUENCODE",
40 : "x-uuencode",
41 : NULL,
42 : NULL,
43 : MBFL_ENCTYPE_SBCS
44 : };
45 :
46 : const struct mbfl_convert_vtbl vtbl_uuencode_8bit = {
47 : mbfl_no_encoding_uuencode,
48 : mbfl_no_encoding_8bit,
49 : mbfl_filt_conv_common_ctor,
50 : mbfl_filt_conv_common_dtor,
51 : mbfl_filt_conv_uudec,
52 : mbfl_filt_conv_common_flush
53 : };
54 :
55 : #define CK(statement) do { if ((statement) < 0) return (-1); } while (0)
56 :
57 : /* uuencode => any */
58 : #define UUDEC(c) (char)(((c)-' ')&077)
59 : static const char * uuenc_begin_text = "begin ";
60 : enum { uudec_state_ground=0, uudec_state_inbegin,
61 : uudec_state_until_newline,
62 : uudec_state_size, uudec_state_a, uudec_state_b, uudec_state_c, uudec_state_d,
63 : uudec_state_skip_newline};
64 :
65 : int mbfl_filt_conv_uudec(int c, mbfl_convert_filter * filter)
66 0 : {
67 : int n;
68 :
69 0 : switch(filter->status) {
70 : case uudec_state_ground:
71 : /* looking for "begin 0666 filename\n" line */
72 0 : if (filter->cache == 0 && c == 'b')
73 : {
74 0 : filter->status = uudec_state_inbegin;
75 0 : filter->cache = 1; /* move to 'e' */
76 : }
77 0 : else if (c == '\n')
78 0 : filter->cache = 0;
79 : else
80 0 : filter->cache++;
81 0 : break;
82 : case uudec_state_inbegin:
83 0 : if (uuenc_begin_text[filter->cache++] != c) {
84 : /* doesn't match pattern */
85 0 : filter->status = uudec_state_ground;
86 0 : break;
87 : }
88 0 : if (filter->cache == 5)
89 : {
90 : /* thats good enough - wait for a newline */
91 0 : filter->status = uudec_state_until_newline;
92 0 : filter->cache = 0;
93 : }
94 0 : break;
95 : case uudec_state_until_newline:
96 0 : if (c == '\n')
97 0 : filter->status = uudec_state_size;
98 0 : break;
99 : case uudec_state_size:
100 : /* get "size" byte */
101 0 : n = UUDEC(c);
102 0 : filter->cache = n << 24;
103 0 : filter->status = uudec_state_a;
104 0 : break;
105 : case uudec_state_a:
106 : /* get "a" byte */
107 0 : n = UUDEC(c);
108 0 : filter->cache |= (n << 16);
109 0 : filter->status = uudec_state_b;
110 0 : break;
111 : case uudec_state_b:
112 : /* get "b" byte */
113 0 : n = UUDEC(c);
114 0 : filter->cache |= (n << 8);
115 0 : filter->status = uudec_state_c;
116 0 : break;
117 : case uudec_state_c:
118 : /* get "c" byte */
119 0 : n = UUDEC(c);
120 0 : filter->cache |= n;
121 0 : filter->status = uudec_state_d;
122 0 : break;
123 : case uudec_state_d:
124 : /* get "d" byte */
125 : {
126 0 : int A, B, C, D = UUDEC(c);
127 0 : A = (filter->cache >> 16) & 0xff;
128 0 : B = (filter->cache >> 8) & 0xff;
129 0 : C = (filter->cache) & 0xff;
130 0 : n = (filter->cache >> 24) & 0xff;
131 0 : if (n-- > 0)
132 0 : CK((*filter->output_function)( (A << 2) | (B >> 4), filter->data));
133 0 : if (n-- > 0)
134 0 : CK((*filter->output_function)( (B << 4) | (C >> 2), filter->data));
135 0 : if (n-- > 0)
136 0 : CK((*filter->output_function)( (C << 6) | D, filter->data));
137 0 : filter->cache = n << 24;
138 :
139 0 : if (n == 0)
140 0 : filter->status = uudec_state_skip_newline; /* skip next byte (newline) */
141 : else
142 0 : filter->status = uudec_state_a; /* go back to fetch "A" byte */
143 : }
144 0 : break;
145 : case uudec_state_skip_newline:
146 : /* skip newline */
147 0 : filter->status = uudec_state_size;
148 : }
149 0 : return c;
150 : }
151 :
152 :
|