static int imap_parser_read_atom(struct imap_parser *parser, const unsigned char *data, size_t data_size) { size_t i; /* read until we've found space, CR or LF. */ for (i = parser->cur_pos; i < data_size; i++) { if (data[i] == ' ' || is_linebreak(data[i])) { imap_parser_save_arg(parser, data, i); break; } else if (data[i] == ')') { if (parser->list_arg != NULL || (parser->flags & IMAP_PARSE_FLAG_INSIDE_LIST) != 0) { imap_parser_save_arg(parser, data, i); break; } else if ((parser->flags & IMAP_PARSE_FLAG_ATOM_ALLCHARS) == 0) { parser->error = "Unexpected ')'"; return FALSE; } /* assume it's part of the atom */ } else if (!is_valid_atom_char(parser, data[i])) return FALSE; } parser->cur_pos = i; return parser->cur_type == ARG_PARSE_NONE; }
static bool imap_parser_read_literal_data(struct imap_parser *parser, const unsigned char *data, size_t data_size) { if (parser->literal_skip_crlf) { /* skip \r\n or \n, anything else gives an error */ if (data_size == 0) return FALSE; if (*data == '\r') { parser->line_size++; data++; data_size--; i_stream_skip(parser->input, 1); if (data_size == 0) return FALSE; } if (*data != '\n') { parser->error = IMAP_PARSE_ERROR_BAD_SYNTAX; parser->error_msg = "Missing LF after literal size"; return FALSE; } parser->line_size++; data++; data_size--; i_stream_skip(parser->input, 1); parser->literal_skip_crlf = FALSE; i_assert(parser->cur_pos == 0); } if ((parser->flags & IMAP_PARSE_FLAG_LITERAL_SIZE) == 0 || parser->cur_type == ARG_PARSE_LITERAL_DATA_FORCED) { /* now we just wait until we've read enough data */ if (data_size < parser->literal_size) return FALSE; else { imap_parser_save_arg(parser, data, (size_t)parser->literal_size); parser->cur_pos = (size_t)parser->literal_size; return TRUE; } } else { /* we want to save only literal size, not the literal itself. */ parser->literal_size_return = TRUE; imap_parser_save_arg(parser, uchar_empty_ptr, 0); return FALSE; } }
static bool imap_parser_read_text(struct imap_parser *parser, const unsigned char *data, size_t data_size) { size_t i; /* read until end of line */ for (i = parser->cur_pos; i < data_size; i++) { if (is_linebreak(data[i])) { imap_parser_save_arg(parser, data, i); break; } } parser->cur_pos = i; return parser->cur_type == ARG_PARSE_NONE; }
static bool imap_parser_read_string(struct imap_parser *parser, const unsigned char *data, size_t data_size) { size_t i; /* read until we've found non-escaped ", CR or LF */ for (i = parser->cur_pos; i < data_size; i++) { if (data[i] == '"') { imap_parser_save_arg(parser, data, i); i++; /* skip the trailing '"' too */ break; } if (data[i] == '\\') { if (i+1 == data_size) { /* known data ends with '\' - leave it to next time as well if it happens to be \" */ break; } /* save the first escaped char */ if (parser->str_first_escape < 0) parser->str_first_escape = i; /* skip the escaped char */ i++; } /* check linebreaks here, so escaping CR/LF isn't possible. string always ends with '"', so it's an error if we found a linebreak.. */ if (is_linebreak(data[i]) && (parser->flags & IMAP_PARSE_FLAG_MULTILINE_STR) == 0) { parser->error = IMAP_PARSE_ERROR_BAD_SYNTAX; parser->error_msg = "Missing '\"'"; return FALSE; } } parser->cur_pos = i; return parser->cur_type == ARG_PARSE_NONE; }