bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2017-2018 Dovecot authors, see the included COPYING file */
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomiqp_encoder_init(string_t *dest, unsigned int max_len, enum qp_encoder_flag flags)
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomi if ((flags & QP_ENCODER_FLAG_HEADER_FORMAT) != 0 &&
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomi i_panic("qp encoder cannot do header format with binary data");
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomi struct qp_encoder *qp = i_new(struct qp_encoder, 1);
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomi if ((flags & QP_ENCODER_FLAG_HEADER_FORMAT) != 0) {
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomistatic inline void
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomiqp_encode_or_break(struct qp_encoder *qp, unsigned char c)
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomi if ((qp->flags & QP_ENCODER_FLAG_HEADER_FORMAT) != 0) {
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomi if (c == ' ')
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomi else if (c != '\t' &&
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomi (c == '?' || c == '_' || c == '=' || c < 33 || c > 126))
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomi /* Include terminating = as well */
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomi if ((c == ' ' || c == '\t') && qp->line_len + 4 >= qp->max_len) {
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomi str_printfa(qp->dest, "=%02X%s", c, qp->linebreak);
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomi /* Include terminating = as well */
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomivoid qp_encoder_more(struct qp_encoder *qp, const void *_src, size_t src_size)
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomi for(unsigned int i = 0; i < src_size; i++) {
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomi unsigned char c = src[i];
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomi /* if input is not binary data and we encounter newline
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomi convert it as crlf, or if the last byte was CR, preserve
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomi if (c == '\n' &&
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomi ((qp->flags & (QP_ENCODER_FLAG_BINARY_DATA|QP_ENCODER_FLAG_HEADER_FORMAT)) == 0 ||
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomi /* reset line length here */
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomi if (c == '\r') {
869e8af5b722032920698743b27e89e6abd170e7Aki Tuomi if ((qp->flags & QP_ENCODER_FLAG_HEADER_FORMAT) != 0 &&