changeset 13114:04716e20f44f

IMAP: Implemented the rest of FUZZY extension.
author Timo Sirainen <tss@iki.fi>
date Tue, 26 Jul 2011 15:09:02 +0300
parents 2e15e70f5f2d
children fa852748e601
files configure.in src/imap/imap-search.c src/imap/imap-search.h
diffstat 3 files changed, 61 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/configure.in	Tue Jul 26 15:04:57 2011 +0300
+++ b/configure.in	Tue Jul 26 15:09:02 2011 +0300
@@ -2624,7 +2624,7 @@
 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) 
 
--- a/src/imap/imap-search.c	Tue Jul 26 15:04:57 2011 +0300
+++ b/src/imap/imap-search.c	Tue Jul 26 15:09:02 2011 +0300
@@ -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 @@
 			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 @@
 	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 @@
 			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 @@
 		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 @@
 	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 @@
 
 	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);
--- a/src/imap/imap-search.h	Tue Jul 26 15:04:57 2011 +0300
+++ b/src/imap/imap-search.h	Tue Jul 26 15:09:02 2011 +0300
@@ -12,7 +12,8 @@
 	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 @@
 	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;