bool index_sort_list_next(struct mail_search_sort_program *program, struct mail *mail) { const uint32_t *seqp; if (program->iter_idx == array_count(&program->seqs)) return FALSE; seqp = array_idx(&program->seqs, program->iter_idx++); mail_set_seq(mail, *seqp); return TRUE; }
static void index_sort_set_seq(struct mail_search_sort_program *program, struct mail *mail, uint32_t seq) { if ((mail->mail_stream_opened || mail->mail_metadata_accessed) && program->slow_mails_left > 0) program->slow_mails_left--; mail_set_seq(mail, seq); if (program->slow_mails_left == 0) { /* too many slow lookups - just return the rest of the results in whatever order. */ mail->lookup_abort = MAIL_LOOKUP_ABORT_NOT_IN_CACHE; } }
static struct mail_raw *mail_raw_create (struct mail_user *ruser, struct istream *input, const char *mailfile, const char *sender, time_t mtime) { struct mail_raw *mailr; struct mailbox_header_lookup_ctx *headers_ctx; const char *envelope_sender; int ret; if ( mailfile != NULL && *mailfile != '/' ) mailfile = t_abspath(mailfile); mailr = i_new(struct mail_raw, 1); envelope_sender = sender != NULL ? sender : DEFAULT_ENVELOPE_SENDER; if ( mailfile == NULL ) { ret = raw_mailbox_alloc_stream(ruser, input, mtime, envelope_sender, &mailr->box); } else { ret = raw_mailbox_alloc_path(ruser, mailfile, (time_t)-1, envelope_sender, &mailr->box); } if ( ret < 0 ) { if ( mailfile == NULL ) { i_fatal("Can't open delivery mail as raw: %s", mailbox_get_last_error(mailr->box, NULL)); } else { i_fatal("Can't open delivery mail as raw (file=%s): %s", mailfile, mailbox_get_last_error(mailr->box, NULL)); } } mailr->trans = mailbox_transaction_begin(mailr->box, 0); headers_ctx = mailbox_header_lookup_init(mailr->box, wanted_headers); mailr->mail = mail_alloc(mailr->trans, 0, headers_ctx); mailbox_header_lookup_unref(&headers_ctx); mail_set_seq(mailr->mail, 1); return mailr; }
int index_sort_header_get(struct mail *mail, uint32_t seq, enum mail_sort_type sort_type, string_t *dest) { const char *str; int ret; bool reply_or_fw; mail_set_seq(mail, seq); str_truncate(dest, 0); switch (sort_type & MAIL_SORT_MASK) { case MAIL_SORT_SUBJECT: if ((ret = mail_get_first_header(mail, "Subject", &str)) <= 0) return ret; str = imap_get_base_subject_cased(pool_datastack_create(), str, &reply_or_fw); str_append(dest, str); return 0; case MAIL_SORT_CC: ret = get_first_mailbox(mail, "Cc", &str); break; case MAIL_SORT_FROM: ret = get_first_mailbox(mail, "From", &str); break; case MAIL_SORT_TO: ret = get_first_mailbox(mail, "To", &str); break; case MAIL_SORT_DISPLAYFROM: ret = get_display_name(mail, "From", &str); break; case MAIL_SORT_DISPLAYTO: ret = get_display_name(mail, "To", &str); break; default: i_unreached(); } (void)uni_utf8_to_decomposed_titlecase(str, strlen(str), dest); return ret; }
static int index_mailbox_get_first_save_date(struct mailbox *box, struct mailbox_metadata *metadata_r) { const struct mail_index_header *hdr; struct mailbox_transaction_context *t; struct mail *mail; uint32_t seq; int ret = -1; hdr = mail_index_get_header(box->view); if (hdr->messages_count == 0) { metadata_r->first_save_date = (time_t)-1; return 0; } t = mailbox_transaction_begin(box, 0, __func__); mail = mail_alloc(t, 0, NULL); for (seq = 1; seq <= hdr->messages_count; seq++) { mail_set_seq(mail, seq); if (mail_get_save_date(mail, &metadata_r->first_save_date) == 0) { ret = 0; break; } if (mailbox_get_last_mail_error(box) != MAIL_ERROR_EXPUNGED) { /* failed */ break; } } mail_free(&mail); (void)mailbox_transaction_commit(&t); if (seq > hdr->messages_count) { /* all messages were expunged after all */ metadata_r->first_save_date = (time_t)-1; return 0; } 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 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; }