diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2019-03-27 13:00:43 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2019-03-27 13:00:43 +0200 |
commit | dc0e689310121619eff2c28432997d85069d2565 (patch) | |
tree | 9ad25af0c3797c553470f1200d144afdc003e04a | |
parent | 9f7eb0a63d0c8e406636c9ad9f0d12aeb5ca077c (diff) | |
download | mailutils-dc0e689310121619eff2c28432997d85069d2565.tar.gz mailutils-dc0e689310121619eff2c28432997d85069d2565.tar.bz2 |
Minor fixes in dot filters.
The DOT decoder accepts input consisting of two characters ".\n"
and decodes it to empty output. When encoding empty input, ".\n"
is produced
Similarly, CRLFDOT handles ".\r\n" the same way.
* libmailutils/filter/crlfdot.c (_crlfdot_encoder): Accept ".\r\n"
as input.
* libmailutils/filter/dot.c: Accept ".\n" as input.
* libmailutils/tests/crlfdot.at: Add new test.
* libmailutils/tests/dot.at: Likewise.
-rw-r--r-- | libmailutils/filter/crlfdot.c | 1 | ||||
-rw-r--r-- | libmailutils/filter/dot.c | 61 | ||||
-rw-r--r-- | libmailutils/tests/crlfdot.at | 9 | ||||
-rw-r--r-- | libmailutils/tests/dot.at | 13 |
4 files changed, 47 insertions, 37 deletions
diff --git a/libmailutils/filter/crlfdot.c b/libmailutils/filter/crlfdot.c index 757437d96..3cc963039 100644 --- a/libmailutils/filter/crlfdot.c +++ b/libmailutils/filter/crlfdot.c | |||
@@ -304,6 +304,7 @@ _crlfdot_encoder (void *xd, | |||
304 | { | 304 | { |
305 | switch (state->at) | 305 | switch (state->at) |
306 | { | 306 | { |
307 | case crlfdot_encode_init: | ||
307 | case crlfdot_encode_lf: | 308 | case crlfdot_encode_lf: |
308 | if (j + 3 > osize) | 309 | if (j + 3 > osize) |
309 | result = mu_filter_again; | 310 | result = mu_filter_again; |
diff --git a/libmailutils/filter/dot.c b/libmailutils/filter/dot.c index d3a3aab34..609d2e8d9 100644 --- a/libmailutils/filter/dot.c +++ b/libmailutils/filter/dot.c | |||
@@ -12,7 +12,7 @@ | |||
12 | Lesser General Public License for more details. | 12 | Lesser General Public License for more details. |
13 | 13 | ||
14 | You should have received a copy of the GNU Lesser General | 14 | You should have received a copy of the GNU Lesser General |
15 | Public License along with this library. If not, see | 15 | Public License along with this library. If not, see |
16 | <http://www.gnu.org/licenses/>. */ | 16 | <http://www.gnu.org/licenses/>. */ |
17 | 17 | ||
18 | /* This file implements a DOT filter, useful for data I/O in | 18 | /* This file implements a DOT filter, useful for data I/O in |
@@ -20,7 +20,7 @@ | |||
20 | "byte-stuffs" the input by outputting an additional '.' in front | 20 | "byte-stuffs" the input by outputting an additional '.' in front |
21 | of any '.' appearing at the beginning of a line. Upon closing the | 21 | of any '.' appearing at the beginning of a line. Upon closing the |
22 | filter in this mode, it outputs additional ".\n". | 22 | filter in this mode, it outputs additional ".\n". |
23 | 23 | ||
24 | When decoding, the reverse is performed: any '.' appearing at the | 24 | When decoding, the reverse is performed: any '.' appearing at the |
25 | beginning of a line is removed. A single dot on a line by itself | 25 | beginning of a line is removed. A single dot on a line by itself |
26 | marks end of the stream. | 26 | marks end of the stream. |
@@ -41,9 +41,8 @@ | |||
41 | 41 | ||
42 | enum dot_decode_state | 42 | enum dot_decode_state |
43 | { | 43 | { |
44 | dot_decode_init, /* initial state */ | 44 | dot_decode_bol, /* beginning of line */ |
45 | dot_decode_char, /* Any character excepting [\r\n.] */ | 45 | dot_decode_char, /* Any character excepting [\n.] */ |
46 | dot_decode_lf, /* prev. char was \n */ | ||
47 | dot_decode_dot, /* 2 prev. chars were \n. */ | 46 | dot_decode_dot, /* 2 prev. chars were \n. */ |
48 | dot_decode_end /* final state, a \n.\n seen. */ | 47 | dot_decode_end /* final state, a \n.\n seen. */ |
49 | }; | 48 | }; |
@@ -53,32 +52,24 @@ new_decode_state (enum dot_decode_state state, int c) | |||
53 | { | 52 | { |
54 | switch (state) | 53 | switch (state) |
55 | { | 54 | { |
56 | case dot_decode_init: | 55 | case dot_decode_bol: |
57 | switch (c) | 56 | switch (c) |
58 | { | 57 | { |
59 | case '.': | 58 | case '.': |
60 | return dot_decode_dot; | 59 | return dot_decode_dot; |
61 | } | ||
62 | break; | ||
63 | |||
64 | case dot_decode_char: | ||
65 | switch (c) | ||
66 | { | ||
67 | case '\n': | 60 | case '\n': |
68 | return dot_decode_lf; | 61 | return dot_decode_bol; |
69 | } | 62 | } |
70 | break; | 63 | break; |
71 | 64 | ||
72 | case dot_decode_lf: | 65 | case dot_decode_char: |
73 | switch (c) | 66 | switch (c) |
74 | { | 67 | { |
75 | case '.': | ||
76 | return dot_decode_dot; | ||
77 | case '\n': | 68 | case '\n': |
78 | return dot_decode_lf; | 69 | return dot_decode_bol; |
79 | } | 70 | } |
80 | break; | 71 | break; |
81 | 72 | ||
82 | case dot_decode_dot: | 73 | case dot_decode_dot: |
83 | switch (c) | 74 | switch (c) |
84 | { | 75 | { |
@@ -93,8 +84,7 @@ new_decode_state (enum dot_decode_state state, int c) | |||
93 | return dot_decode_char; | 84 | return dot_decode_char; |
94 | } | 85 | } |
95 | 86 | ||
96 | /* Move min(isize,osize) bytes from iptr to optr, replacing each \r\n | 87 | /* Move min(isize,osize) bytes from iptr to optr, unstuffing '..' sequences */ |
97 | with \n. */ | ||
98 | static enum mu_filter_result | 88 | static enum mu_filter_result |
99 | _dot_decoder (void *xd, | 89 | _dot_decoder (void *xd, |
100 | enum mu_filter_command cmd, | 90 | enum mu_filter_command cmd, |
@@ -110,16 +100,16 @@ _dot_decoder (void *xd, | |||
110 | switch (cmd) | 100 | switch (cmd) |
111 | { | 101 | { |
112 | case mu_filter_init: | 102 | case mu_filter_init: |
113 | *pstate = dot_decode_init; | 103 | *pstate = dot_decode_bol; |
114 | return mu_filter_ok; | 104 | return mu_filter_ok; |
115 | 105 | ||
116 | case mu_filter_done: | 106 | case mu_filter_done: |
117 | return mu_filter_ok; | 107 | return mu_filter_ok; |
118 | 108 | ||
119 | default: | 109 | default: |
120 | break; | 110 | break; |
121 | } | 111 | } |
122 | 112 | ||
123 | iptr = (const unsigned char *) iobuf->input; | 113 | iptr = (const unsigned char *) iobuf->input; |
124 | isize = iobuf->isize; | 114 | isize = iobuf->isize; |
125 | optr = iobuf->output; | 115 | optr = iobuf->output; |
@@ -129,10 +119,9 @@ _dot_decoder (void *xd, | |||
129 | { | 119 | { |
130 | unsigned char c = *iptr++; | 120 | unsigned char c = *iptr++; |
131 | int curstate = *pstate; | 121 | int curstate = *pstate; |
132 | 122 | ||
133 | *pstate = new_decode_state (curstate, c); | 123 | *pstate = new_decode_state (curstate, c); |
134 | if (c == '.' | 124 | if (c == '.' && curstate == dot_decode_bol) |
135 | && (curstate == dot_decode_init || curstate == dot_decode_lf)) | ||
136 | continue; | 125 | continue; |
137 | if (*pstate == dot_decode_end) | 126 | if (*pstate == dot_decode_end) |
138 | { | 127 | { |
@@ -152,7 +141,7 @@ enum dot_encode_state | |||
152 | dot_encode_init, /* initial state */ | 141 | dot_encode_init, /* initial state */ |
153 | dot_encode_char, /* Any character excepting \n */ | 142 | dot_encode_char, /* Any character excepting \n */ |
154 | dot_encode_lf, /* prev. char was \n */ | 143 | dot_encode_lf, /* prev. char was \n */ |
155 | }; | 144 | }; |
156 | 145 | ||
157 | static enum dot_encode_state | 146 | static enum dot_encode_state |
158 | new_encode_state (int c) | 147 | new_encode_state (int c) |
@@ -165,8 +154,8 @@ new_encode_state (int c) | |||
165 | return dot_encode_char; | 154 | return dot_encode_char; |
166 | } | 155 | } |
167 | 156 | ||
168 | /* Move min(isize,osize) bytes from iptr to optr, replacing each \n | 157 | /* Move min(isize,osize) bytes from iptr to optr, byte-stuffing each |
169 | with \r\n. Any input \r\n sequences remain untouched. */ | 158 | '.' appearing at the beginning of a line */ |
170 | static enum mu_filter_result | 159 | static enum mu_filter_result |
171 | _dot_encoder (void *xd, | 160 | _dot_encoder (void *xd, |
172 | enum mu_filter_command cmd, | 161 | enum mu_filter_command cmd, |
@@ -179,20 +168,20 @@ _dot_encoder (void *xd, | |||
179 | char *optr; | 168 | char *optr; |
180 | size_t osize; | 169 | size_t osize; |
181 | enum dot_encode_state *state = xd; | 170 | enum dot_encode_state *state = xd; |
182 | 171 | ||
183 | switch (cmd) | 172 | switch (cmd) |
184 | { | 173 | { |
185 | case mu_filter_init: | 174 | case mu_filter_init: |
186 | *state = dot_encode_init; | 175 | *state = dot_encode_init; |
187 | return mu_filter_ok; | 176 | return mu_filter_ok; |
188 | 177 | ||
189 | case mu_filter_done: | 178 | case mu_filter_done: |
190 | return mu_filter_ok; | 179 | return mu_filter_ok; |
191 | 180 | ||
192 | default: | 181 | default: |
193 | break; | 182 | break; |
194 | } | 183 | } |
195 | 184 | ||
196 | iptr = (const unsigned char *) iobuf->input; | 185 | iptr = (const unsigned char *) iobuf->input; |
197 | isize = iobuf->isize; | 186 | isize = iobuf->isize; |
198 | optr = iobuf->output; | 187 | optr = iobuf->output; |
@@ -206,7 +195,7 @@ _dot_encoder (void *xd, | |||
206 | if (c == '.' && (curstate == dot_encode_init || | 195 | if (c == '.' && (curstate == dot_encode_init || |
207 | curstate == dot_encode_lf)) | 196 | curstate == dot_encode_lf)) |
208 | { | 197 | { |
209 | if (j + 2 > osize) | 198 | if (j + 2 > osize) |
210 | { | 199 | { |
211 | if (i == 0) | 200 | if (i == 0) |
212 | { | 201 | { |
@@ -234,7 +223,7 @@ _dot_encoder (void *xd, | |||
234 | if (j + 2 > osize) | 223 | if (j + 2 > osize) |
235 | result = mu_filter_again; | 224 | result = mu_filter_again; |
236 | break; | 225 | break; |