static void mbox_sync_header_remove_space(struct mbox_sync_mail_context *ctx, size_t start_pos, size_t *size) { const unsigned char *data; size_t data_size, pos, last_line_pos; /* find the end of the LWSP */ data = str_data(ctx->header); data_size = str_len(ctx->header); for (pos = last_line_pos = start_pos; pos < data_size; pos++) { if (data[pos] == '\n') { /* possibly continues in next line */ if (pos+1 == data_size || !IS_LWSP(data[pos+1])) { data_size = pos; break; } last_line_pos = pos+1; } else if (!IS_LWSP(data[pos]) && data[pos] != '\r') { start_pos = last_line_pos = pos+1; } } if (start_pos == data_size) return; /* and remove what we can */ if (ctx->header_first_change > start_pos) ctx->header_first_change = start_pos; ctx->header_last_change = (size_t)-1; if (data_size - start_pos <= *size) { /* remove it all */ mbox_sync_move_buffer(ctx, start_pos, 0, data_size - start_pos); *size -= data_size - start_pos; return; } /* we have more space than needed. since we're removing from the beginning of header instead of end, we don't have to worry about multiline-headers. */ mbox_sync_move_buffer(ctx, start_pos, 0, *size); if (last_line_pos <= start_pos + *size) last_line_pos = start_pos; else last_line_pos -= *size; data_size -= *size; *size = 0; if (ctx->mail.space < (off_t)(data_size - last_line_pos)) { ctx->mail.space = data_size - last_line_pos; ctx->mail.offset = ctx->hdr_offset; if (ctx->mail.space > 0) ctx->mail.offset += last_line_pos; } }
void mbox_sync_headers_add_space(struct mbox_sync_mail_context *ctx, size_t size) { size_t data_size, pos, start_pos; const unsigned char *data; void *p; i_assert(size < SSIZE_T_MAX); if (ctx->mail.pseudo) start_pos = ctx->hdr_pos[MBOX_HDR_X_IMAPBASE]; else if (ctx->mail.space > 0) { /* update the header using the existing offset. otherwise we might chose wrong header and just decrease the available space */ start_pos = ctx->mail.offset - ctx->hdr_offset; } else { /* Append at the end of X-Keywords header, or X-UID if it doesn't exist */ start_pos = ctx->hdr_pos[MBOX_HDR_X_KEYWORDS] != (size_t)-1 ? ctx->hdr_pos[MBOX_HDR_X_KEYWORDS] : ctx->hdr_pos[MBOX_HDR_X_UID]; } data = str_data(ctx->header); data_size = str_len(ctx->header); i_assert(start_pos < data_size); for (pos = start_pos; pos < data_size; pos++) { if (data[pos] == '\n') { /* possibly continues in next line */ if (pos+1 == data_size || !IS_LWSP(data[pos+1])) break; start_pos = pos+1; } else if (!IS_LWSP(data[pos]) && data[pos] != '\r') { start_pos = pos+1; } } /* pos points to end of header now, and start_pos to beginning of whitespace. */ mbox_sync_move_buffer(ctx, pos, size, 0); p = buffer_get_space_unsafe(ctx->header, pos, size); memset(p, ' ', size); if (ctx->header_first_change > pos) ctx->header_first_change = pos; ctx->header_last_change = (size_t)-1; ctx->mail.space = (pos - start_pos) + size; ctx->mail.offset = ctx->hdr_offset; if (ctx->mail.space > 0) ctx->mail.offset += start_pos; }
static void status_flags_replace(struct mbox_sync_mail_context *ctx, size_t pos, const struct mbox_flag_type *flags_list) { unsigned char *data; size_t size; int i, need, have; ctx->mail.flags ^= MBOX_NONRECENT_KLUDGE; if (ctx->header_first_change > pos) ctx->header_first_change = pos; /* how many bytes do we need? */ for (i = 0, need = 0; flags_list[i].chr != 0; i++) { if ((ctx->mail.flags & flags_list[i].flag) != 0) need++; } /* how many bytes do we have now? */ data = buffer_get_modifiable_data(ctx->header, &size); for (have = 0; pos < size; pos++) { if (data[pos] == '\n' || data[pos] == '\r') break; /* see if this is unknown flag for us */ for (i = 0; flags_list[i].chr != 0; i++) { if (flags_list[i].chr == (char)data[pos]) break; } if (flags_list[i].chr != 0) have++; else { /* save this one */ data[pos-have] = data[pos]; } } pos -= have; mbox_sync_move_buffer(ctx, pos, need, have); /* @UNSAFE */ data = buffer_get_space_unsafe(ctx->header, pos, need); for (i = 0; flags_list[i].chr != 0; i++) { if ((ctx->mail.flags & flags_list[i].flag) != 0) *data++ = flags_list[i].chr; } ctx->mail.flags ^= MBOX_NONRECENT_KLUDGE; }