]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-smtp: reply: Make parsing enhanced status codes available as a separate function.
authorStephan Bosch <stephan.bosch@dovecot.fi>
Fri, 2 Nov 2018 09:11:35 +0000 (10:11 +0100)
committerVille Savolainen <ville.savolainen@dovecot.fi>
Tue, 12 Feb 2019 13:41:55 +0000 (15:41 +0200)
src/lib-smtp/smtp-reply-parser.c
src/lib-smtp/smtp-reply-parser.h

index d47eab4513b8ddef4912295bf02670f0593ac181..cd35ffb731c62ccef6d9d6e84354f22b4cbea717 100644 (file)
@@ -89,6 +89,59 @@ struct smtp_reply_parser {
        bool ehlo:1;
 };
 
+bool smtp_reply_parse_enhanced_code(const char *text,
+                                   struct smtp_reply_enhanced_code *enh_code_r,
+                                   const char **pos_r)
+{
+       const char *p = text;
+       unsigned int digits, x, y, z;
+
+       i_zero(enh_code_r);
+
+       /* status-code ::= class "." subject "." detail
+          class       ::= "2" / "4" / "5"
+          subject     ::= 1*3digit
+          detail      ::= 1*3digit
+       */
+
+       /* class */
+       if (p[1] != '.' || (p[0] != '2' && p[0] != '4' && p[0] != '5'))
+               return FALSE;
+       x = p[0] - '0';
+       p += 2;
+
+       /* subject */
+       digits = 0;
+       y = 0;
+       while (*p != '\0' && i_isdigit(*p) && digits++ < 3) {
+               y = y*10 + (*p - '0');
+               p++;
+       }
+       if (digits == 0 || *p != '.')
+               return FALSE;
+       p++;
+
+       /* detail */
+       digits = 0;
+       z = 0;
+       while (*p != '\0' && i_isdigit(*p) && digits++ < 3) {
+               z = z*10 + (*p - '0');
+               p++;
+       }
+       if (digits == 0 || (pos_r == NULL && *p != '\0'))
+               return FALSE;
+
+       if (pos_r != NULL) {
+               /* code is syntactically valid; strip code from textstring */
+               *pos_r = p;
+       }
+
+       enh_code_r->x = x;
+       enh_code_r->y = y;
+       enh_code_r->z = z;
+       return TRUE;
+}
+
 static inline void ATTR_FORMAT(2, 3)
 smtp_reply_parser_error(struct smtp_reply_parser *parser,
                        const char *format, ...)
@@ -272,84 +325,51 @@ static inline const char *_chr_sanitize(unsigned char c)
 }
 
 static void
-smtp_reply_parse_enhanced_code(struct smtp_reply_parser *parser,
-       const char **pos)
+smtp_reply_parser_parse_enhanced_code(const char *text,
+                                     struct smtp_reply_parser *parser,
+                                     const char **pos_r)
 {
-       const char *p = *pos;
-       unsigned int digits, x, y, z;
-       unsigned int prevx = parser->state.reply->enhanced_code.x,
-               prevy = parser->state.reply->enhanced_code.y,
-               prevz = parser->state.reply->enhanced_code.z;
+       struct smtp_reply_enhanced_code code;
+       struct smtp_reply_enhanced_code *cur_code =
+               &parser->state.reply->enhanced_code;
 
-       if (prevx == 9)
+       if (cur_code->x == 9)
                return; /* failed on earlier line */
 
-       parser->state.reply->enhanced_code.x = 9;
-       parser->state.reply->enhanced_code.y = 0;
-       parser->state.reply->enhanced_code.z = 0;
-
-       /* status-code ::= class "." subject "." detail
-          class       ::= "2" / "4" / "5"
-          subject     ::= 1*3digit
-          detail      ::= 1*3digit
-       */
-
-       /* class */
-       if (p[1] != '.' || (p[0] != '2' && p[0] != '4' && p[0] != '5'))
+       if (!smtp_reply_parse_enhanced_code(text, &code, pos_r)) {
+               /* failed to parse an enhanced code */
+               i_zero(cur_code);
+               cur_code->x = 9;
                return;
-       x = p[0] - '0';
-       p += 2;
-
-       /* subject */
-       digits = 0;
-       y = 0;
-       while (*p != '\0' && i_isdigit(*p) && digits++ < 3) {
-               y = y*10 + (*p - '0');
-               p++;
        }
-       if (digits == 0 || *p != '.')
-               return;
-       p++;
 
-       /* detail */
-       digits = 0;
-       z = 0;
-       while (*p != '\0' && i_isdigit(*p) && digits++ < 3) {
-               z = z*10 + (*p - '0');
-               p++;
-       }
-       if (digits == 0 || (*p != ' ' && *p != '\r' && *p != '\n'))
+       if (**pos_r != ' ' && **pos_r != '\r' && **pos_r != '\n')
                return;
-       p++;
-
-       /* code is syntactically valid; strip code from textstring */
-       *pos = p;
+       (*pos_r)++;
 
        /* check for match with status */
-       if (x != parser->state.reply->status / 100) {
+       if (code.x != parser->state.reply->status / 100) {
                /* ignore code */
                return;
        }
 
        /* check for code consistency */
        if (parser->state.line > 0 &&
-               (prevx != x || prevy != y || prevz != z)) {
+           (cur_code->x != code.x || cur_code->y != code.y ||
+            cur_code->z != code.z)) {
                /* ignore code */
                return;
        }
 
-       parser->state.reply->enhanced_code.x = x;
-       parser->state.reply->enhanced_code.y = y;
-       parser->state.reply->enhanced_code.z = z;
+       *cur_code = code;
 }
 
 static void smtp_reply_parser_finish_line(struct smtp_reply_parser *parser)
 {
        const char *text = str_c(parser->strbuf);
 
-       if (parser->enhanced_codes && str_len(parser->strbuf) > 5) {
-               smtp_reply_parse_enhanced_code(parser, &text);
-       }
+       if (parser->enhanced_codes && str_len(parser->strbuf) > 5)
+               smtp_reply_parser_parse_enhanced_code(text, parser, &text);
 
        parser->state.line++;
        parser->state.reply_size += str_len(parser->strbuf);
index bbafd7542b4ebeb59054ca50c88fa5a47d59958a..4ffb32af24de875cc0d339e6ab8fb3fc6ae849b1 100644 (file)
@@ -5,6 +5,10 @@
 
 struct smtp_reply_parser;
 
+bool smtp_reply_parse_enhanced_code(const char *text,
+                                   struct smtp_reply_enhanced_code *enh_code_r,
+                                   const char **pos_r) ATTR_NULL(3);
+
 struct smtp_reply_parser *
 smtp_reply_parser_init(struct istream *input, size_t max_reply_size);
 void smtp_reply_parser_deinit(struct smtp_reply_parser **_parser);