diff options
author | Leonid Lisovskiy <lly.dev@gmail.com> | 2011-10-28 13:59:04 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-10-28 13:59:55 +0200 |
commit | 328f27fe447761f355104e7f524dc1115f16ca44 (patch) | |
tree | 1a8280c4cbc4458b89dda72c4d0c8f7402661355 | |
parent | ec447c7f01acb0e3abd9daa52a1b616be3f39484 (diff) | |
download | busybox-w32-328f27fe447761f355104e7f524dc1115f16ca44.tar.gz busybox-w32-328f27fe447761f355104e7f524dc1115f16ca44.tar.bz2 busybox-w32-328f27fe447761f355104e7f524dc1115f16ca44.zip |
libbb: split decode_base64 off read_base64
function old new delta
decode_base64 - 182 +182
read_base64 378 255 -123
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 0/1 up/down: 182/-123) Total: 59 bytes
Signed-off-by: Leonid Lisovskiy <lly.dev@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | include/libbb.h | 3 | ||||
-rw-r--r-- | libbb/uuencode.c | 125 | ||||
-rwxr-xr-x | testsuite/uuencode.tests | 101 |
3 files changed, 200 insertions, 29 deletions
diff --git a/include/libbb.h b/include/libbb.h index d248781c3..791cdd94e 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -1591,7 +1591,8 @@ enum { | |||
1591 | /* Sign-extends to a value which never matches fgetc result: */ | 1591 | /* Sign-extends to a value which never matches fgetc result: */ |
1592 | BASE64_FLAG_NO_STOP_CHAR = 0x80, | 1592 | BASE64_FLAG_NO_STOP_CHAR = 0x80, |
1593 | }; | 1593 | }; |
1594 | void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags); | 1594 | const char *decode_base64(char **pp_dst, const char *src) FAST_FUNC; |
1595 | void read_base64(FILE *src_stream, FILE *dst_stream, int flags) FAST_FUNC; | ||
1595 | 1596 | ||
1596 | typedef struct md5_ctx_t { | 1597 | typedef struct md5_ctx_t { |
1597 | uint8_t wbuffer[64]; /* always correctly aligned for uint64_t */ | 1598 | uint8_t wbuffer[64]; /* always correctly aligned for uint64_t */ |
diff --git a/libbb/uuencode.c b/libbb/uuencode.c index 03e708fd5..23e2123bc 100644 --- a/libbb/uuencode.c +++ b/libbb/uuencode.c | |||
@@ -73,23 +73,23 @@ void FAST_FUNC bb_uuencode(char *p, const void *src, int length, const char *tbl | |||
73 | } | 73 | } |
74 | 74 | ||
75 | /* | 75 | /* |
76 | * Decode base64 encoded stream. | 76 | * Decode base64 encoded string. Stops on '\0'. |
77 | * Can stop on EOF, specified char, or on uuencode-style "====" line: | 77 | * |
78 | * flags argument controls it. | 78 | * Returns: pointer to the undecoded part of source. |
79 | * If points to '\0', then the source was fully decoded. | ||
80 | * (*dst): advanced past the last written byte. | ||
79 | */ | 81 | */ |
80 | void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags) | 82 | const char* FAST_FUNC decode_base64(char **pp_dst, const char *src) |
81 | { | 83 | { |
82 | /* Note that EOF _can_ be passed as exit_char too */ | 84 | char *dst = *pp_dst; |
83 | #define exit_char ((int)(signed char)flags) | 85 | const char *src_tail; |
84 | #define uu_style_end (flags & BASE64_FLAG_UU_STOP) | ||
85 | |||
86 | int term_count = 0; | ||
87 | 86 | ||
88 | while (1) { | 87 | while (1) { |
89 | unsigned char translated[4]; | 88 | unsigned char translated[4]; |
90 | int count = 0; | 89 | int count = 0; |
91 | 90 | ||
92 | /* Process one group of 4 chars */ | 91 | /* Process one group of 4 chars */ |
92 | src_tail = src; | ||
93 | while (count < 4) { | 93 | while (count < 4) { |
94 | char *table_ptr; | 94 | char *table_ptr; |
95 | int ch; | 95 | int ch; |
@@ -101,11 +101,20 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags) | |||
101 | * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n" | 101 | * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n" |
102 | */ | 102 | */ |
103 | do { | 103 | do { |
104 | ch = fgetc(src_stream); | 104 | ch = *src; |
105 | if (ch == exit_char && count == 0) | 105 | if (ch == '\0') { |
106 | return; | 106 | if (count == 0) { |
107 | if (ch == EOF) | 107 | /* Example: |
108 | bb_error_msg_and_die("truncated base64 input"); | 108 | * If we decode "QUJD <NUL>", we want |
109 | * to return ptr to NUL, not to ' ', | ||
110 | * because we did fully decode | ||
111 | * the string (to "ABC"). | ||
112 | */ | ||
113 | src_tail = src; | ||
114 | } | ||
115 | goto ret; | ||
116 | } | ||
117 | src++; | ||
109 | table_ptr = strchr(bb_uuenc_tbl_base64, ch); | 118 | table_ptr = strchr(bb_uuenc_tbl_base64, ch); |
110 | //TODO: add BASE64_FLAG_foo to die on bad char? | 119 | //TODO: add BASE64_FLAG_foo to die on bad char? |
111 | //Note that then we may need to still allow '\r' (for mail processing) | 120 | //Note that then we may need to still allow '\r' (for mail processing) |
@@ -114,21 +123,15 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags) | |||
114 | /* Convert encoded character to decimal */ | 123 | /* Convert encoded character to decimal */ |
115 | ch = table_ptr - bb_uuenc_tbl_base64; | 124 | ch = table_ptr - bb_uuenc_tbl_base64; |
116 | 125 | ||
117 | if (ch == 65 /* '\n' */) { | 126 | if (ch == 65) { /* '\n' */ |
118 | /* Terminating "====" line? */ | ||
119 | if (uu_style_end && term_count == 4) | ||
120 | return; /* yes */ | ||
121 | term_count = 0; | ||
122 | continue; | 127 | continue; |
123 | } | 128 | } |
124 | /* ch is 64 if char was '=', otherwise 0..63 */ | 129 | /* ch is 64 if char was '=', otherwise 0..63 */ |
125 | translated[count] = ch & 63; /* 64 -> 0 */ | 130 | translated[count] = ch & 63; /* 64 -> 0 */ |
126 | if (ch == 64) { | 131 | if (ch == 64) { /* '=' */ |
127 | term_count++; | ||
128 | break; | 132 | break; |
129 | } | 133 | } |
130 | count++; | 134 | count++; |
131 | term_count = 0; | ||
132 | } | 135 | } |
133 | 136 | ||
134 | /* Merge 6 bit chars to 8 bit. | 137 | /* Merge 6 bit chars to 8 bit. |
@@ -136,10 +139,82 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags) | |||
136 | * "eQ==" -> "y", not "y NUL NUL" | 139 | * "eQ==" -> "y", not "y NUL NUL" |
137 | */ | 140 | */ |
138 | if (count > 1) | 141 | if (count > 1) |
139 | fputc(translated[0] << 2 | translated[1] >> 4, dst_stream); | 142 | *dst++ = translated[0] << 2 | translated[1] >> 4; |
140 | if (count > 2) | 143 | if (count > 2) |
141 | fputc(translated[1] << 4 | translated[2] >> 2, dst_stream); | 144 | *dst++ = translated[1] << 4 | translated[2] >> 2; |
142 | if (count > 3) | 145 | if (count > 3) |
143 | fputc(translated[2] << 6 | translated[3], dst_stream); | 146 | *dst++ = translated[2] << 6 | translated[3]; |
144 | } /* while (1) */ | 147 | } /* while (1) */ |
148 | ret: | ||
149 | *pp_dst = dst; | ||
150 | return src_tail; | ||
151 | } | ||
152 | |||
153 | /* | ||
154 | * Decode base64 encoded stream. | ||
155 | * Can stop on EOF, specified char, or on uuencode-style "====" line: | ||
156 | * flags argument controls it. | ||
157 | */ | ||
158 | void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags) | ||
159 | { | ||
160 | /* Note that EOF _can_ be passed as exit_char too */ | ||
161 | #define exit_char ((int)(signed char)flags) | ||
162 | #define uu_style_end (flags & BASE64_FLAG_UU_STOP) | ||
163 | |||
164 | /* uuencoded files have 61 byte lines. Use 64 byte buffer | ||
165 | * to process line at a time. | ||
166 | */ | ||
167 | enum { BUFFER_SIZE = 64 }; | ||
168 | |||
169 | char in_buf[BUFFER_SIZE + 2]; | ||
170 | char out_buf[BUFFER_SIZE / 4 * 3 + 2]; | ||
171 | char *out_tail; | ||
172 | const char *in_tail; | ||
173 | int term_seen = 0; | ||
174 | int in_count = 0; | ||
175 | |||
176 | while (1) { | ||
177 | while (in_count < BUFFER_SIZE) { | ||
178 | int ch = fgetc(src_stream); | ||
179 | if (ch == exit_char) { | ||
180 | if (in_count == 0) | ||
181 | return; | ||
182 | term_seen = 1; | ||
183 | break; | ||
184 | } | ||
185 | if (ch == EOF) { | ||
186 | term_seen = 1; | ||
187 | break; | ||
188 | } | ||
189 | /* Prevent "====" line to be split: stop if we see '\n'. | ||
190 | * We can also skip other whitespace and skirt the problem | ||
191 | * of files with NULs by stopping on any control char or space: | ||
192 | */ | ||
193 | if (ch <= ' ') | ||
194 | break; | ||
195 | in_buf[in_count++] = ch; | ||
196 | } | ||
197 | in_buf[in_count] = '\0'; | ||
198 | |||
199 | /* Did we encounter "====" line? */ | ||
200 | if (uu_style_end && strcmp(in_buf, "====") == 0) | ||
201 | return; | ||
202 | |||
203 | out_tail = out_buf; | ||
204 | in_tail = decode_base64(&out_tail, in_buf); | ||
205 | |||
206 | fwrite(out_buf, (out_tail - out_buf), 1, dst_stream); | ||
207 | |||
208 | if (term_seen) { | ||
209 | /* Did we consume ALL characters? */ | ||
210 | if (*in_tail == '\0') | ||
211 | return; | ||
212 | /* No */ | ||
213 | bb_error_msg_and_die("truncated base64 input"); | ||
214 | } | ||
215 | |||
216 | /* It was partial decode */ | ||
217 | in_count = strlen(in_tail); | ||
218 | memmove(in_buf, in_tail, in_count); | ||
219 | } | ||
145 | } | 220 | } |
diff --git a/testsuite/uuencode.tests b/testsuite/uuencode.tests index cd6191b1b..6ce70f747 100755 --- a/testsuite/uuencode.tests +++ b/testsuite/uuencode.tests | |||
@@ -8,9 +8,9 @@ | |||
8 | 8 | ||
9 | . ./testing.sh | 9 | . ./testing.sh |
10 | 10 | ||
11 | # testing "test name" "options" "expected result" "file input" "stdin" | 11 | # testing "test name" "command(s)" "expected result" "file input" "stdin" |
12 | # file input will be file called "input" | 12 | # file input will be file called "input" |
13 | # test can create a file "actual" instead of writing to stdout | 13 | # test can create a file "actual" instead of writing to stdout |
14 | 14 | ||
15 | # Test setup of standard input | 15 | # Test setup of standard input |
16 | umask 0 | 16 | umask 0 |
@@ -24,4 +24,99 @@ testing "uuencode correct encoding" "uuencode bb_uuenc_test.out" \ | |||
24 | testing "uuencode correct base64 encoding" "uuencode -m bb_uuenc_test.out" \ | 24 | testing "uuencode correct base64 encoding" "uuencode -m bb_uuenc_test.out" \ |
25 | "begin-base64 644 bb_uuenc_test.out\nVGhlIGZhc3QgZ3JleSBmb3gganVtcGVkIG92ZXIgdGhlIGxhenkgYnJvd24g\nZG9nLgo=\n====\n" \ | 25 | "begin-base64 644 bb_uuenc_test.out\nVGhlIGZhc3QgZ3JleSBmb3gganVtcGVkIG92ZXIgdGhlIGxhenkgYnJvd24g\nZG9nLgo=\n====\n" \ |
26 | "" "The fast grey fox jumped over the lazy brown dog.\n" | 26 | "" "The fast grey fox jumped over the lazy brown dog.\n" |
27 | |||
28 | testing "uuencode empty file" 'r=`uuencode FILE`; echo "$r"; echo "$r" | uudecode -o -;' \ | ||
29 | 'begin 644 FILE | ||
30 | ` | ||
31 | end | ||
32 | ' "" "" | ||
33 | testing "uuencode -m empty file" 'r=`uuencode -m FILE`; echo "$r"; echo "$r" | uudecode -o -;' \ | ||
34 | 'begin-base64 644 FILE | ||
35 | ==== | ||
36 | ' "" "" | ||
37 | |||
38 | testing "uuencode file 'A'" 'r=`uuencode FILE`; echo "$r"; echo "$r" | uudecode -o -;' \ | ||
39 | 'begin 644 FILE | ||
40 | !00`` | ||
41 | ` | ||
42 | end | ||
43 | A' "" "A" | ||
44 | testing "uuencode -m file 'A'" 'r=`uuencode -m FILE`; echo "$r"; echo "$r" | uudecode -o -;' \ | ||
45 | 'begin-base64 644 FILE | ||
46 | QQ== | ||
47 | ==== | ||
48 | A' "" "A" | ||
49 | |||
50 | testing "uuencode file 'AB'" 'r=`uuencode FILE`; echo "$r"; echo "$r" | uudecode -o -;' \ | ||
51 | 'begin 644 FILE | ||
52 | "04(` | ||
53 | ` | ||
54 | end | ||
55 | AB' "" "AB" | ||
56 | testing "uuencode -m file 'AB'" 'r=`uuencode -m FILE`; echo "$r"; echo "$r" | uudecode -o -;' \ | ||
57 | 'begin-base64 644 FILE | ||
58 | QUI= | ||
59 | ==== | ||
60 | AB' "" "AB" | ||
61 | |||
62 | testing "uuencode file 'ABC'" 'r=`uuencode FILE`; echo "$r"; echo "$r" | uudecode -o -;' \ | ||
63 | 'begin 644 FILE | ||
64 | #04)# | ||
65 | ` | ||
66 | end | ||
67 | ABC' "" "ABC" | ||
68 | testing "uuencode -m file 'ABC'" 'r=`uuencode -m FILE`; echo "$r"; echo "$r" | uudecode -o -;' \ | ||
69 | 'begin-base64 644 FILE | ||
70 | QUJD | ||
71 | ==== | ||
72 | ABC' "" "ABC" | ||
73 | |||
74 | testing "uuencode file 'ABCD'" 'r=`uuencode FILE`; echo "$r"; echo "$r" | uudecode -o -;' \ | ||
75 | 'begin 644 FILE | ||
76 | $04)#1``` | ||
77 | ` | ||
78 | end | ||
79 | ABCD' "" "ABCD" | ||
80 | testing "uuencode -m file 'ABCD'" 'r=`uuencode -m FILE`; echo "$r"; echo "$r" | uudecode -o -;' \ | ||
81 | 'begin-base64 644 FILE | ||
82 | QUJDRA== | ||
83 | ==== | ||
84 | ABCD' "" "ABCD" | ||
85 | |||
86 | testing "uuencode file 'ABCDE'" 'r=`uuencode FILE`; echo "$r"; echo "$r" | uudecode -o -;' \ | ||
87 | 'begin 644 FILE | ||
88 | %04)#1$4` | ||
89 | ` | ||
90 | end | ||
91 | ABCDE' "" "ABCDE" | ||
92 | testing "uuencode -m file 'ABCDE'" 'r=`uuencode -m FILE`; echo "$r"; echo "$r" | uudecode -o -;' \ | ||
93 | 'begin-base64 644 FILE | ||
94 | QUJDREU= | ||
95 | ==== | ||
96 | ABCDE' "" "ABCDE" | ||
97 | |||
98 | testing "uuencode file 'ABCDEF'" 'r=`uuencode FILE`; echo "$r"; echo "$r" | uudecode -o -;' \ | ||
99 | 'begin 644 FILE | ||
100 | &04)#1$5& | ||
101 | ` | ||
102 | end | ||
103 | ABCDEF' "" "ABCDEF" | ||
104 | testing "uuencode -m file 'ABCDEF'" 'r=`uuencode -m FILE`; echo "$r"; echo "$r" | uudecode -o -;' \ | ||
105 | 'begin-base64 644 FILE | ||
106 | QUJDREVG | ||
107 | ==== | ||
108 | ABCDEF' "" "ABCDEF" | ||
109 | |||
110 | testing "uuencode file 'A<NUL><0xff>Z'" 'r=`uuencode FILE`; echo "$r"; echo "$r" | uudecode -o -;' \ | ||
111 | 'begin 644 FILE | ||
112 | $00#_6@`` | ||
113 | ` | ||
114 | end | ||
115 | A\x0\xffZ' "" "A\x0\xffZ" | ||
116 | testing "uuencode -m file 'A<NUL><0xff>Z'" 'r=`uuencode -m FILE`; echo "$r"; echo "$r" | uudecode -o -;' \ | ||
117 | 'begin-base64 644 FILE | ||
118 | QQD/Wg== | ||
119 | ==== | ||
120 | A\x0\xffZ' "" "A\x0\xffZ" | ||
121 | |||
27 | exit $FAILCOUNT | 122 | exit $FAILCOUNT |