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, ...)
}
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);