Lines Matching refs:parser

8 #include "smtp-parser.h"
10 #include "smtp-reply-parser.h"
93 smtp_reply_parser_error(struct smtp_reply_parser *parser,
98 i_free(parser->error);
101 parser->error = i_strdup_vprintf(format, args);
108 struct smtp_reply_parser *parser;
110 parser = i_new(struct smtp_reply_parser, 1);
111 parser->max_reply_size =
113 parser->input = input;
115 parser->strbuf = str_new(default_pool, 128);
116 return parser;
121 struct smtp_reply_parser *parser = *_parser;
125 str_free(&parser->strbuf);
126 pool_unref(&parser->reply_pool);
127 i_stream_unref(&parser->input);
128 i_free(parser->error);
129 i_free(parser);
132 void smtp_reply_parser_set_stream(struct smtp_reply_parser *parser,
135 i_stream_unref(&parser->input);
137 parser->input = input;
138 i_stream_ref(parser->input);
143 smtp_reply_parser_restart(struct smtp_reply_parser *parser)
145 str_truncate(parser->strbuf, 0);
146 pool_unref(&parser->reply_pool);
147 i_zero(&parser->state);
149 parser->reply_pool = pool_alloconly_create("smtp_reply", 256);
150 parser->state.reply = p_new(parser->reply_pool, struct smtp_reply, 1);
151 p_array_init(&parser->state.reply_lines, parser->reply_pool, 8);
156 (struct smtp_reply_parser *parser, unsigned int *code_r)
158 const unsigned char *first = parser->cur;
163 while (parser->cur < parser->end && i_isdigit(*parser->cur))
164 parser->cur++;
166 if (str_len(parser->strbuf) + (parser->cur-first) > 3)
169 str_append_n(parser->strbuf, first, parser->cur - first);
170 if (parser->cur == parser->end)
172 if (str_len(parser->strbuf) != 3)
174 p = str_data(parser->strbuf);
178 str_truncate(parser->strbuf, 0);
182 static int smtp_reply_parse_textstring(struct smtp_reply_parser *parser)
184 const unsigned char *first = parser->cur;
188 while (parser->cur < parser->end && smtp_char_is_textstr(*parser->cur))
189 parser->cur++;
191 if (((parser->cur-first) + parser->state.reply_size +
192 str_len(parser->strbuf)) > parser->max_reply_size) {
193 smtp_reply_parser_error(parser,
198 str_append_n(parser->strbuf, first, parser->cur - first);
199 if (parser->cur == parser->end)
204 static int smtp_reply_parse_ehlo_domain(struct smtp_reply_parser *parser)
206 const unsigned char *first = parser->cur;
210 while (parser->cur < parser->end && *parser->cur != ' ' &&
211 smtp_char_is_textstr(*parser->cur))
212 parser->cur++;
214 if (((parser->cur-first) + parser->state.reply_size +
215 str_len(parser->strbuf)) > parser->max_reply_size) {
216 smtp_reply_parser_error(parser,
220 str_append_n(parser->strbuf, first, parser->cur - first);
221 if (parser->cur == parser->end)
226 static int smtp_reply_parse_ehlo_greet(struct smtp_reply_parser *parser)
228 const unsigned char *first = parser->cur;
235 if (parser->cur == parser->end)
237 if (smtp_char_is_ehlo_greet(*parser->cur)) {
239 while (parser->cur < parser->end &&
240 smtp_char_is_textstr(*parser->cur))
241 parser->cur++;
243 if (((parser->cur-first) + parser->state.reply_size +
244 str_len(parser->strbuf)) >
245 parser->max_reply_size) {
246 smtp_reply_parser_error(parser,
252 str_append_n(parser->strbuf,
253 first, parser->cur - first);
255 if (parser->cur == parser->end)
257 if (!smtp_char_is_ehlo_greet(*parser->cur))
259 str_append_c(parser->strbuf, ' ');
260 parser->cur++;
261 first = parser->cur;
275 smtp_reply_parse_enhanced_code(struct smtp_reply_parser *parser,
280 unsigned int prevx = parser->state.reply->enhanced_code.x,
281 prevy = parser->state.reply->enhanced_code.y,
282 prevz = parser->state.reply->enhanced_code.z;
287 parser->state.reply->enhanced_code.x = 9;
288 parser->state.reply->enhanced_code.y = 0;
289 parser->state.reply->enhanced_code.z = 0;
329 if (x != parser->state.reply->status / 100) {
335 if (parser->state.line > 0 &&
341 parser->state.reply->enhanced_code.x = x;
342 parser->state.reply->enhanced_code.y = y;
343 parser->state.reply->enhanced_code.z = z;
346 static void smtp_reply_parser_finish_line(struct smtp_reply_parser *parser)
348 const char *text = str_c(parser->strbuf);
350 if (parser->enhanced_codes && str_len(parser->strbuf) > 5) {
351 smtp_reply_parse_enhanced_code(parser, &text);
354 parser->state.line++;
355 parser->state.reply_size += str_len(parser->strbuf);
356 text = p_strdup(parser->reply_pool, text);
357 array_append(&parser->state.reply_lines, &text, 1);
358 str_truncate(parser->strbuf, 0);
361 static int smtp_reply_parse_more(struct smtp_reply_parser *parser)
378 switch (parser->state.state) {
380 smtp_reply_parser_restart(parser);
381 parser->state.state = SMTP_REPLY_PARSE_STATE_CODE;
385 if ((ret=smtp_reply_parse_code(parser, &status)) <= 0) {
387 smtp_reply_parser_error(parser,
392 if (parser->state.line == 0) {
393 parser->state.reply->status = status;
394 } else if (status != parser->state.reply->status) {
395 smtp_reply_parser_error(parser,
399 parser->state.state = SMTP_REPLY_PARSE_STATE_SEP;
400 if (parser->cur == parser->end)
405 switch (*parser->cur) {
408 parser->cur++;
409 parser->state.last_line = FALSE;
410 parser->state.state =
415 parser->cur++;
416 parser->state.state =
418 parser->state.last_line = TRUE;
423 parser->state.last_line = TRUE;
424 parser->state.state = SMTP_REPLY_PARSE_STATE_CR;
427 smtp_reply_parser_error(parser,
429 _chr_sanitize(*parser->cur));
432 if (parser->state.state != SMTP_REPLY_PARSE_STATE_TEXT)
437 if (parser->ehlo &&
438 parser->state.reply->status == 250 &&
439 parser->state.line == 0) {
443 if ((ret=smtp_reply_parse_ehlo_domain(parser)) <= 0)
445 parser->state.state =
447 if (parser->cur == parser->end)
451 if ((ret=smtp_reply_parse_textstring(parser)) <= 0)
453 parser->state.state = SMTP_REPLY_PARSE_STATE_CR;
454 if (parser->cur == parser->end)
459 if (*parser->cur == '\r') {
460 parser->cur++;
461 parser->state.state =
464 parser->state.state =
467 if (parser->cur == parser->end)
473 if (*parser->cur != '\n') {
474 if (parser->state.state ==
476 smtp_reply_parser_error(parser,
479 smtp_reply_parser_error(parser,
481 _chr_sanitize(*parser->cur));
485 parser->cur++;
486 smtp_reply_parser_finish_line(parser);
487 if (parser->state.last_line) {
488 parser->state.state =
492 parser->state.state = SMTP_REPLY_PARSE_STATE_CODE;
496 if (*parser->cur != ' ') {
497 parser->state.state = SMTP_REPLY_PARSE_STATE_CR;
500 parser->cur++;
501 str_append_c(parser->strbuf, ' ');
502 parser->state.state = SMTP_REPLY_PARSE_STATE_EHLO_GREET;
503 if (parser->cur == parser->end)
508 if ((ret=smtp_reply_parse_ehlo_greet(parser)) <= 0)
510 parser->state.state = SMTP_REPLY_PARSE_STATE_CR;
511 if (parser->cur == parser->end)
523 static int smtp_reply_parse(struct smtp_reply_parser *parser)
528 while ((ret = i_stream_read_more(parser->input,
529 &parser->begin, &size)) > 0) {
530 parser->cur = parser->begin;
531 parser->end = parser->cur + size;
533 if ((ret = smtp_reply_parse_more(parser)) < 0)
536 i_stream_skip(parser->input, parser->cur - parser->begin);
543 i_assert(parser->input->eof);
544 if (parser->input->stream_errno == 0) {
545 if (parser->state.state == SMTP_REPLY_PARSE_STATE_INIT)
547 smtp_reply_parser_error(parser,
550 smtp_reply_parser_error(parser,
552 i_stream_get_error(parser->input));
558 int smtp_reply_parse_next(struct smtp_reply_parser *parser,
564 i_assert(parser->state.state == SMTP_REPLY_PARSE_STATE_INIT ||
565 (parser->enhanced_codes == enhanced_codes && !parser->ehlo));
567 parser->enhanced_codes = enhanced_codes;
568 parser->ehlo = FALSE;
570 i_free_and_null(parser->error);
580 if ((ret=smtp_reply_parse(parser)) <= 0) {
581 *error_r = parser->error;
585 parser->state.state = SMTP_REPLY_PARSE_STATE_INIT;
586 parser->state.reply->text_lines =
587 array_idx(&parser->state.reply_lines, 0);
588 *reply_r = parser->state.reply;
592 int smtp_reply_parse_ehlo(struct smtp_reply_parser *parser,
597 i_assert(parser->state.state == SMTP_REPLY_PARSE_STATE_INIT ||
598 (!parser->enhanced_codes && parser->ehlo));
600 parser->enhanced_codes = FALSE;
601 parser->ehlo = TRUE;
603 i_free_and_null(parser->error);
621 if ((ret=smtp_reply_parse(parser)) <= 0) {
622 *error_r = parser->error;
626 parser->state.state = SMTP_REPLY_PARSE_STATE_INIT;
627 parser->state.reply->text_lines =
628 array_idx(&parser->state.reply_lines, 0);
629 *reply_r = parser->state.reply;