]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
IMAP: Implemented the rest of FUZZY extension.
authorTimo Sirainen <tss@iki.fi>
Tue, 26 Jul 2011 12:09:02 +0000 (15:09 +0300)
committerTimo Sirainen <tss@iki.fi>
Tue, 26 Jul 2011 12:09:02 +0000 (15:09 +0300)
configure.in
src/imap/imap-search.c
src/imap/imap-search.h

index f1ddc7495bda2096bb7d01a8efa63d19dd90c5ea..4c67bb500328e602b76e7386d9881b6b8e2763d1 100644 (file)
@@ -2624,7 +2624,7 @@ dnl **
 dnl IDLE doesn't really belong to banner. It's there just to make Blackberries
 dnl happy, because otherwise BIS server disables push email.
 capability_banner="IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE"
-capability="$capability_banner SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS MULTIAPPEND UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS"
+capability="$capability_banner SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS MULTIAPPEND UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS FUZZY"
 AC_DEFINE_UNQUOTED(CAPABILITY_STRING, "$capability", IMAP capabilities)
 AC_DEFINE_UNQUOTED(CAPABILITY_BANNER_STRING, "$capability_banner", IMAP capabilities advertised in banner) 
 
index cafc0d7b246e943846434be46fc20bf4ff9b87ed..83ea0c6773ca0e785bfce8f1a9c18e482b00a2d5 100644 (file)
@@ -14,6 +14,8 @@
 #include "imap-search-args.h"
 #include "imap-search.h"
 
+#include <stdlib.h>
+
 static int imap_search_deinit(struct imap_search_context *ctx);
 
 static int
@@ -67,6 +69,8 @@ search_parse_return_options(struct imap_search_context *ctx,
                        ctx->return_options |= SEARCH_RETURN_SAVE;
                else if (strcmp(name, "UPDATE") == 0)
                        ctx->return_options |= SEARCH_RETURN_UPDATE;
+               else if (strcmp(name, "RELEVANCY") == 0)
+                       ctx->return_options |= SEARCH_RETURN_RELEVANCY;
                else if (strcmp(name, "PARTIAL") == 0) {
                        if (ctx->partial1 != 0) {
                                client_send_command_error(cmd,
@@ -230,6 +234,34 @@ imap_search_send_partial(struct imap_search_context *ctx, string_t *str)
        str_append_c(str, ')');
 }
 
+static void
+imap_search_send_relevancy(struct imap_search_context *ctx, string_t *dest)
+{
+       const float *scores;
+       unsigned int i, count;
+       float diff, imap_score;
+
+       scores = array_get(&ctx->relevancy_scores, &count);
+       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.. */
+       diff = ctx->max_relevancy - ctx->min_relevancy;
+       if (diff == 0)
+               diff = 1.0;
+       for (i = 0; i < count; i++) {
+               if (i > 0)
+                       str_append_c(dest, ' ');
+               imap_score = (scores[i] - ctx->min_relevancy) / diff * 100.0;
+               if (imap_score < 1)
+                       str_append(dest, "1");
+               else
+                       str_printfa(dest, "%u", (unsigned int)imap_score);
+       }
+}
+
 static void imap_search_send_result(struct imap_search_context *ctx)
 {
        struct client *client = ctx->cmd->client;
@@ -268,6 +300,11 @@ static void imap_search_send_result(struct imap_search_context *ctx)
                        imap_write_seq_range(str, &ctx->result);
                }
        }
+       if ((ctx->return_options & SEARCH_RETURN_RELEVANCY) != 0) {
+               str_append(str, " RELEVANCY (");
+               imap_search_send_relevancy(ctx, str);
+               str_append_c(str, ')');
+       }
 
        if ((ctx->return_options & SEARCH_RETURN_PARTIAL) != 0)
                imap_search_send_partial(ctx, str);
@@ -297,6 +334,20 @@ search_update_mail(struct imap_search_context *ctx, struct mail *mail)
                seq_range_array_add(&ctx->cmd->client->search_saved_uidset,
                                    0, mail->uid);
        }
+       if ((ctx->return_options & SEARCH_RETURN_RELEVANCY) != 0) {
+               const char *str;
+               float score;
+
+               if (mail_get_special(mail, MAIL_FETCH_SEARCH_RELEVANCY, &str) < 0)
+                       score = 0;
+               else
+                       score = strtod(str, NULL);
+               array_append(&ctx->relevancy_scores, &score, 1);
+               if (ctx->min_relevancy > score)
+                       ctx->min_relevancy = score;
+               if (ctx->max_relevancy < score)
+                       ctx->max_relevancy = score;
+       }
 }
 
 static void search_add_result_id(struct imap_search_context *ctx, uint32_t id)
@@ -501,6 +552,8 @@ bool imap_search_start(struct imap_search_context *ctx,
        i_array_init(&ctx->result, 128);
        if ((ctx->return_options & SEARCH_RETURN_UPDATE) != 0)
                imap_search_result_save(ctx);
+       if ((ctx->return_options & SEARCH_RETURN_RELEVANCY) != 0)
+               i_array_init(&ctx->relevancy_scores, 128);
 
        cmd->func = cmd_search_more;
        cmd->context = ctx;
@@ -533,6 +586,8 @@ static int imap_search_deinit(struct imap_search_context *ctx)
 
        if (ctx->to != NULL)
                timeout_remove(&ctx->to);
+       if (array_is_created(&ctx->relevancy_scores))
+               array_free(&ctx->relevancy_scores);
        array_free(&ctx->result);
        mail_search_args_deinit(ctx->sargs);
        mail_search_args_unref(&ctx->sargs);
index 359f3a108aee71d6c048103c10fea2bbeaf2fb20..6849574467cfd3cb4e6139d1e7fa5e58720acc1b 100644 (file)
@@ -12,7 +12,8 @@ enum search_return_options {
        SEARCH_RETURN_MODSEQ            = 0x0020,
        SEARCH_RETURN_SAVE              = 0x0040,
        SEARCH_RETURN_UPDATE            = 0x0080,
-       SEARCH_RETURN_PARTIAL           = 0x0100
+       SEARCH_RETURN_PARTIAL           = 0x0100,
+       SEARCH_RETURN_RELEVANCY         = 0x0200
 /* Options that don't return any seq/uid results */
 #define SEARCH_RETURN_NORESULTS \
        (SEARCH_RETURN_ESEARCH | SEARCH_RETURN_MODSEQ | SEARCH_RETURN_SAVE | \
@@ -33,6 +34,9 @@ struct imap_search_context {
        ARRAY_TYPE(seq_range) result;
        unsigned int result_count;
 
+       ARRAY_DEFINE(relevancy_scores, float);
+       float min_relevancy, max_relevancy;
+
        uint64_t highest_seen_modseq;
        struct timeval start_time;