imap-search.c revision 5caf685b62a30b1f935b80a3f9f1bdcefb63a38c
/* Copyright (c) 2002-2017 Dovecot authors, see the included COPYING file */
#include "imap-common.h"
#include "ostream.h"
#include "str.h"
#include "seq-range-array.h"
#include "time-util.h"
#include "imap-resp-code.h"
#include "imap-quote.h"
#include "imap-seqset.h"
#include "imap-util.h"
#include "mail-search-build.h"
#include "imap-fetch.h"
#include "imap-commands.h"
#include "imap-search-args.h"
#include "imap-search.h"
static int
{
return -1;
return -1;
}
return 0;
}
static bool
const struct imap_arg *update_args)
{
const char *error;
return FALSE;
}
return TRUE;
}
static bool
{
const struct imap_arg *update_args;
unsigned int idx;
while (!IMAP_ARG_IS_EOL(args)) {
"SEARCH return options contain non-atoms.");
return FALSE;
}
args++;
/* no-op */
"SEARCH return options have duplicate UPDATE.");
return FALSE;
}
return FALSE;
args++;
}
"PARTIAL can be used only once.");
return FALSE;
}
"PARTIAL range missing.");
return FALSE;
}
"PARTIAL range broken.");
return FALSE;
}
args++;
} else {
"Unknown SEARCH return option");
return FALSE;
}
}
return FALSE;
}
return FALSE;
}
if (ctx->return_options == 0)
return TRUE;
}
const struct mail_search_arg *sargs)
{
case SEARCH_SEQSET:
break;
case SEARCH_MODSEQ:
break;
case SEARCH_OR:
case SEARCH_SUB:
break;
default:
break;
}
}
}
{
struct mail_search_result *result;
struct imap_search_update *update;
/* too many updates */
return;
}
}
{
str_truncate(str, 0);
}
}
if (ctx->highest_seen_modseq != 0) {
(unsigned long long)ctx->highest_seen_modseq);
}
}
static void
{
unsigned int i, count, delete_count;
/* 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. */
/* delete everything up to partial1 */
delete_count = 0;
for (i = n = 0; i < count; i++) {
delete_count = i;
break;
}
n += diff + 1;
}
if (i == count) {
/* partial1 points past the result */
} else {
/* delete everything after partial2 */
break;
}
n += diff + 1;
}
}
/* no results (in range) */
} else {
}
}
static void
{
const float *scores;
unsigned int i, count;
float diff, imap_score;
if (count == 0)
return;
/* we'll need to convert float scores to numbers 1..100
FIXME: would be a good idea to try to detect non-linear score
mappings and convert them better.. */
if (diff == 0)
diff = 1.0;
for (i = 0; i < count; i++) {
if (i > 0)
if (imap_score < 1)
else
}
}
{
unsigned int count;
return;
}
if (ctx->return_options ==
/* we only wanted to save the result, don't return
ESEARCH result. */
return;
}
if (count > 0) {
}
}
}
if (ctx->highest_seen_modseq != 0) {
(unsigned long long)ctx->highest_seen_modseq);
}
}
static void
{
}
}
const char *str;
float score;
score = 0;
else
}
}
{
unsigned int count;
/* only append the data. this is especially important when we're
returning a sort result. */
} else {
}
}
{
enum mailbox_sync_flags sync_flags;
unsigned int count;
const char *ok_reply;
(void)imap_search_deinit(ctx);
return TRUE;
}
if (count == 0) {
id_min = 0;
id_max = 0;
} else {
}
(opts & ~(SEARCH_RETURN_NORESULTS |
SEARCH_RETURN_MIN | SEARCH_RETURN_MAX)) == 0;
ctx->result_count++;
if (minmax) {
if ((opts & SEARCH_RETURN_MAX) != 0)
/* return option updates are delayed until
}
continue;
}
if ((opts & ~(SEARCH_RETURN_NORESULTS |
SEARCH_RETURN_COUNT)) == 0) {
/* we only want to count (and get modseqs) */
continue;
}
}
if (tryagain)
return FALSE;
if ((opts & SEARCH_RETURN_MIN) != 0) {
i_unreached();
} else {
}
}
if ((opts & SEARCH_RETURN_MAX) != 0) {
i_unreached();
} else {
}
}
}
if (imap_search_deinit(ctx) < 0) {
return TRUE;
}
}
{
bool finished;
if (!finished)
(void)client_handle_unfinished_cmd(cmd);
else
if (client->disconnected)
else
}
{
return 1;
}
return -1;
}
/* wait if there is another SEARCH SAVE command running. */
return 0;
}
/* make sure the search result gets cleared if SEARCH fails */
else
}
return 1;
}
struct mail_search_args *sargs,
const enum mail_sort_type *sort_program)
{
if (ctx->have_modseqs) {
}
ctx->search_ctx =
else {
}
if (cmd_search_more(cmd))
return TRUE;
/* we may have moved onto syncing by now */
}
return FALSE;
}
{
int ret = 0;
ret = -1;
/* Send the result also after failing. It might have something useful,
even though it didn't fully succeed. The client should be able to
realize that there was some failure because NO is returned. */
/* search failed */
}
return ret;
}
{
}
}
{
}
}