static void
imap_search_send_partial(struct imap_search_context *ctx, string_t *str)
{
- struct seq_range *range;
- uint32_t n, diff;
- unsigned int i, count, delete_count;
-
str_printfa(str, " PARTIAL (%u:%u ", ctx->partial1, ctx->partial2);
- ctx->partial1--;
- ctx->partial2--;
-
- /* we need to be able to handle non-sorted seq ranges (for SORT
- replies), so do this ourself instead of using seq_range_array_*()
- functions. */
- range = array_get_modifiable(&ctx->result, &count);
- /* delete everything up to partial1 */
- delete_count = 0;
- for (i = n = 0; i < count; i++) {
- diff = range[i].seq2 - range[i].seq1;
- if (n + diff >= ctx->partial1) {
- range[i].seq1 += ctx->partial1 - n;
- delete_count = i;
- break;
- }
- n += diff + 1;
- }
- if (i == count) {
- /* partial1 points past the result */
- array_clear(&ctx->result);
- } else {
- /* delete everything after partial2 */
- for (n = ctx->partial1; i < count; i++) {
- diff = range[i].seq2 - range[i].seq1;
- if (n + diff >= ctx->partial2) {
- range[i].seq2 = range[i].seq1 + (ctx->partial2 - n);
- array_delete(&ctx->result, i + 1, count-(i+1));
- break;
- }
- n += diff + 1;
- }
- array_delete(&ctx->result, 0, delete_count);
- }
-
if (array_count(&ctx->result) == 0) {
/* no results (in range) */
str_append(str, "NIL");
ctx->min_id = id;
search_update_mail(ctx, mail);
}
- if (HAS_ANY_BITS(opts, SEARCH_RETURN_ALL))
+ if (HAS_ANY_BITS(opts, SEARCH_RETURN_ALL)) {
+ /* ALL and PARTIAL are mutually exclusive */
+ i_assert(HAS_NO_BITS(opts, SEARCH_RETURN_PARTIAL));
search_add_result_id(ctx, id);
- else if (HAS_ANY_BITS(opts, SEARCH_RETURN_COUNT)) {
+ } else if ((opts & SEARCH_RETURN_PARTIAL) != 0) {
+ /* only update if it's within range */
+ i_assert(HAS_NO_BITS(opts, SEARCH_RETURN_ALL));
+ if (ctx->partial1 <= ctx->result_count &&
+ ctx->partial2 >= ctx->result_count)
+ search_add_result_id(ctx, id);
+ else if (HAS_ALL_BITS(opts, SEARCH_RETURN_COUNT |
+ SEARCH_RETURN_SAVE)) {
+ /* (SAVE COUNT PARTIAL n:m) must include all
+ results in SAVE, but not include mails
+ outside the PARTIAL range in MODSEQ or
+ RELEVANCY */
+ seq_range_array_add(&cmd->client->search_saved_uidset,
+ mail->uid);
+ continue;
+ } else {
+ continue;
+ }
+ } else if (HAS_ANY_BITS(opts, SEARCH_RETURN_COUNT)) {
/* with COUNT don't add it to results, but handle
SAVE and MODSEQ */
} else if (HAS_ANY_BITS(opts, SEARCH_RETURN_MIN |