static void index_sort_list_add_date(struct mail_search_sort_program *program, struct mail *mail) { ARRAY_TYPE(mail_sort_node_date) *nodes = program->context; struct mail_sort_node_date *node; node = array_append_space(nodes); node->seq = mail->seq; if (mail_get_date(mail, &node->date, NULL) < 0) node->date = 0; else if (node->date == 0) { if (mail_get_received_date(mail, &node->date) < 0) node->date = 0; } }
static int virtual_mail_get_date(struct mail *mail, time_t *date_r, int *timezone_r) { struct virtual_mail *vmail = (struct virtual_mail *)mail; int tz; if (timezone_r == NULL) timezone_r = &tz; if (virtual_mail_handle_lost(vmail) < 0) return -1; if (mail_get_date(vmail->backend_mail, date_r, timezone_r) < 0) { virtual_box_copy_error(mail->box, vmail->backend_mail->box); return -1; } return 0; }
int index_sort_node_cmp_type(struct mail *mail, const enum mail_sort_type *sort_program, uint32_t seq1, uint32_t seq2) { enum mail_sort_type sort_type; time_t time1, time2; uoff_t size1, size2; float float1, float2; int tz, ret = 0; sort_type = *sort_program & MAIL_SORT_MASK; switch (sort_type) { case MAIL_SORT_CC: case MAIL_SORT_FROM: case MAIL_SORT_TO: case MAIL_SORT_SUBJECT: case MAIL_SORT_DISPLAYFROM: case MAIL_SORT_DISPLAYTO: T_BEGIN { string_t *str1, *str2; str1 = t_str_new(256); str2 = t_str_new(256); (void)index_sort_header_get(mail, seq1, sort_type, str1); (void)index_sort_header_get(mail, seq2, sort_type, str2); ret = strcmp(str_c(str1), str_c(str2)); } T_END; break; case MAIL_SORT_ARRIVAL: mail_set_seq(mail, seq1); if (mail_get_received_date(mail, &time1) < 0) time1 = 0; mail_set_seq(mail, seq2); if (mail_get_received_date(mail, &time2) < 0) time1 = 0; ret = time1 < time2 ? -1 : (time1 > time2 ? 1 : 0); break; case MAIL_SORT_DATE: mail_set_seq(mail, seq1); if (mail_get_date(mail, &time1, &tz) < 0) time1 = 0; else if (time1 == 0) { if (mail_get_received_date(mail, &time1) < 0) time1 = 0; } mail_set_seq(mail, seq2); if (mail_get_date(mail, &time2, &tz) < 0) time2 = 0; else if (time2 == 0) { if (mail_get_received_date(mail, &time2) < 0) time2 = 0; } ret = time1 < time2 ? -1 : (time1 > time2 ? 1 : 0); break; case MAIL_SORT_SIZE: mail_set_seq(mail, seq1); if (mail_get_virtual_size(mail, &size1) < 0) size1 = 0; mail_set_seq(mail, seq2); if (mail_get_virtual_size(mail, &size2) < 0) size2 = 0; ret = size1 < size2 ? -1 : (size1 > size2 ? 1 : 0); break; case MAIL_SORT_RELEVANCY: mail_set_seq(mail, seq1); float1 = index_sort_get_relevancy(mail); mail_set_seq(mail, seq2); float2 = index_sort_get_relevancy(mail); /* NOTE: higher relevancy is returned first, unlike with all other number based sort keys */ ret = float1 < float2 ? 1 : (float1 > float2 ? -1 : 0); break; case MAIL_SORT_POP3_ORDER: /* 32bit numbers would be enough, but since there is already existing code for uoff_t in sizes, just use them. */ mail_set_seq(mail, seq1); size1 = index_sort_get_pop3_order(mail); mail_set_seq(mail, seq2); size2 = index_sort_get_pop3_order(mail); ret = size1 < size2 ? -1 : (size1 > size2 ? 1 : 0); break; case MAIL_SORT_END: return seq1 < seq2 ? -1 : (seq1 > seq2 ? 1 : 0); case MAIL_SORT_MASK: case MAIL_SORT_FLAG_REVERSE: i_unreached(); } if (ret == 0) { return index_sort_node_cmp_type(mail, sort_program+1, seq1, seq2); } if ((*sort_program & MAIL_SORT_FLAG_REVERSE) != 0) ret = ret < 0 ? 1 : -1; return ret; }
int index_sort_node_cmp_type(struct mail *mail, const enum mail_sort_type *sort_program, uint32_t seq1, uint32_t seq2) { enum mail_sort_type sort_type; time_t time1, time2; uoff_t size1, size2; float float1, float2; int ret = 0; sort_type = *sort_program & MAIL_SORT_MASK; switch (sort_type) { case MAIL_SORT_CC: case MAIL_SORT_FROM: case MAIL_SORT_TO: case MAIL_SORT_SUBJECT: case MAIL_SORT_DISPLAYFROM: case MAIL_SORT_DISPLAYTO: T_BEGIN { string_t *str1, *str2; str1 = t_str_new(256); str2 = t_str_new(256); index_sort_header_get(mail, seq1, sort_type, str1); index_sort_header_get(mail, seq2, sort_type, str2); ret = strcmp(str_c(str1), str_c(str2)); } T_END; break; case MAIL_SORT_ARRIVAL: mail_set_seq(mail, seq1); if (mail_get_received_date(mail, &time1) < 0) time1 = 0; mail_set_seq(mail, seq2); if (mail_get_received_date(mail, &time2) < 0) time1 = 0; ret = time1 < time2 ? -1 : (time1 > time2 ? 1 : 0); break; case MAIL_SORT_DATE: mail_set_seq(mail, seq1); if (mail_get_date(mail, &time1, NULL) < 0) time1 = 0; else if (time1 == 0) { if (mail_get_received_date(mail, &time1) < 0) time1 = 0; } mail_set_seq(mail, seq2); if (mail_get_date(mail, &time2, NULL) < 0) time2 = 0; else if (time2 == 0) { if (mail_get_received_date(mail, &time2) < 0) time2 = 0; } ret = time1 < time2 ? -1 : (time1 > time2 ? 1 : 0); break; case MAIL_SORT_SIZE: mail_set_seq(mail, seq1); if (mail_get_virtual_size(mail, &size1) < 0) size1 = 0; mail_set_seq(mail, seq2); if (mail_get_virtual_size(mail, &size2) < 0) size2 = 0; ret = size1 < size2 ? -1 : (size1 > size2 ? 1 : 0); break; case MAIL_SORT_SEARCH_SCORE: mail_set_seq(mail, seq1); float1 = index_sort_get_score(mail); mail_set_seq(mail, seq2); float2 = index_sort_get_score(mail); ret = float1 < float2 ? -1 : (float1 > float2 ? 1 : 0); break; case MAIL_SORT_END: return seq1 < seq2 ? -1 : (seq1 > seq2 ? 1 : 0); case MAIL_SORT_MASK: case MAIL_SORT_FLAG_REVERSE: i_unreached(); } if (ret == 0) { return index_sort_node_cmp_type(mail, sort_program+1, seq1, seq2); } if ((*sort_program & MAIL_SORT_FLAG_REVERSE) != 0) ret = ret < 0 ? 1 : -1; return ret; }
/* Returns >0 = matched, 0 = not matched, -1 = unknown */ static int search_arg_match_cached(struct index_search_context *ctx, struct mail_search_arg *arg) { const char *str; struct tm *tm; uoff_t virtual_size; time_t date; int tz_offset; bool have_tz_offset; switch (arg->type) { /* internal dates */ case SEARCH_BEFORE: case SEARCH_ON: case SEARCH_SINCE: have_tz_offset = FALSE; tz_offset = 0; date = (time_t)-1; switch (arg->value.date_type) { case MAIL_SEARCH_DATE_TYPE_SENT: if (mail_get_date(ctx->mail, &date, &tz_offset) < 0) return -1; have_tz_offset = TRUE; break; case MAIL_SEARCH_DATE_TYPE_RECEIVED: if (mail_get_received_date(ctx->mail, &date) < 0) return -1; break; case MAIL_SEARCH_DATE_TYPE_SAVED: if (mail_get_save_date(ctx->mail, &date) < 0) return -1; break; } if ((arg->value.search_flags & MAIL_SEARCH_ARG_FLAG_USE_TZ) == 0) { if (!have_tz_offset) { tm = localtime(&date); tz_offset = utc_offset(tm, date); } date += tz_offset * 60; } switch (arg->type) { case SEARCH_BEFORE: return date < arg->value.time; case SEARCH_ON: return date >= arg->value.time && date < arg->value.time + 3600*24; case SEARCH_SINCE: return date >= arg->value.time; default: /* unreachable */ break; } /* sizes */ case SEARCH_SMALLER: case SEARCH_LARGER: if (mail_get_virtual_size(ctx->mail, &virtual_size) < 0) return -1; if (arg->type == SEARCH_SMALLER) return virtual_size < arg->value.size; else return virtual_size > arg->value.size; case SEARCH_GUID: if (mail_get_special(ctx->mail, MAIL_FETCH_GUID, &str) < 0) return -1; return strcmp(str, arg->value.str) == 0; default: return -1; } }