[Commits] imap.c 1.179.2.268 1.179.2.269

colin at claws-mail.org colin at claws-mail.org
Wed Nov 28 10:39:39 CET 2012


Update of /home/claws-mail/claws/src
In directory srv:/tmp/cvs-serv12270/src

Modified Files:
      Tag: gtk2
	imap.c 
Log Message:
2012-11-28 [colin]	3.9.0cvs26

	* src/imap.c
	* src/etpan/imap-thread.c
	* src/etpan/imap-thread.h
		Try locale's charset and UTF-7 on server-side
		searches when UTF-8 fails. Also, don't even
		mention a charset if searching for an ASCII
		string.

Index: imap.c
===================================================================
RCS file: /home/claws-mail/claws/src/imap.c,v
retrieving revision 1.179.2.268
retrieving revision 1.179.2.269
diff -u -d -r1.179.2.268 -r1.179.2.269
--- imap.c	12 Oct 2012 15:13:16 -0000	1.179.2.268
+++ imap.c	28 Nov 2012 09:39:37 -0000	1.179.2.269
@@ -95,6 +95,8 @@
 	gchar last_seen_separator;
 	guint refcnt;
 	guint max_set_size;
+	const gchar *search_charset;
+	gboolean search_charset_supported;
 };
 
 struct _IMAPSession
@@ -749,6 +751,8 @@
 {
 	folder_remote_folder_init((Folder *)folder, name, path);
 	IMAP_FOLDER(folder)->max_set_size = IMAP_SET_MAX_COUNT;
+	IMAP_FOLDER(folder)->search_charset_supported = TRUE;
+	IMAP_FOLDER(folder)->search_charset = "UTF-8";
 }
 
 static FolderItem *imap_folder_item_new(Folder *folder)
@@ -1957,6 +1961,32 @@
 	return ret;
 }
 
+static gboolean imap_matcher_type_is_local(gint matchertype)
+{
+	switch (matchertype) {
+	case MATCHCRITERIA_FROM:
+	case MATCHCRITERIA_TO:
+	case MATCHCRITERIA_CC:
+	case MATCHCRITERIA_TO_OR_CC:
+	case MATCHCRITERIA_SUBJECT:
+	case MATCHCRITERIA_REFERENCES:
+	case MATCHCRITERIA_INREPLYTO:
+	case MATCHCRITERIA_AGE_GREATER:
+	case MATCHCRITERIA_AGE_LOWER:
+	case MATCHCRITERIA_FORWARDED:
+	case MATCHCRITERIA_SPAM:
+	case MATCHCRITERIA_UNREAD:
+	case MATCHCRITERIA_NEW:
+	case MATCHCRITERIA_MARKED:
+	case MATCHCRITERIA_REPLIED:
+	case MATCHCRITERIA_DELETED:
+	case MATCHCRITERIA_SIZE_GREATER:
+	case MATCHCRITERIA_SIZE_SMALLER:
+	case MATCHCRITERIA_SIZE_EQUAL:
+		return TRUE;
+	}
+	return FALSE;
+}
 
 static IMAPSearchKey* search_make_key(MatcherProp* match, gboolean* is_all)
 {
@@ -1994,28 +2024,8 @@
 		 * has proven faster than IMAP search plus network roundtrips. once this changes,
 		 * consider removing these exceptions.
 		 */
-		switch (matchertype) {
-		case MATCHCRITERIA_FROM:
-		case MATCHCRITERIA_TO:
-		case MATCHCRITERIA_CC:
-		case MATCHCRITERIA_TO_OR_CC:
-		case MATCHCRITERIA_SUBJECT:
-		case MATCHCRITERIA_REFERENCES:
-		case MATCHCRITERIA_INREPLYTO:
-		case MATCHCRITERIA_AGE_GREATER:
-		case MATCHCRITERIA_AGE_LOWER:
-		case MATCHCRITERIA_FORWARDED:
-		case MATCHCRITERIA_SPAM:
-		case MATCHCRITERIA_UNREAD:
-		case MATCHCRITERIA_NEW:
-		case MATCHCRITERIA_MARKED:
-		case MATCHCRITERIA_REPLIED:
-		case MATCHCRITERIA_DELETED:
-		case MATCHCRITERIA_SIZE_GREATER:
-		case MATCHCRITERIA_SIZE_SMALLER:
-		case MATCHCRITERIA_SIZE_EQUAL:
+		if (imap_matcher_type_is_local(matchertype))
 			return NULL;
-		}
 
 		/* the Message-ID header is also cached */
 		if (matchertype == MATCHCRITERIA_HEADER && g_strcmp0("Message-ID", match->header) == 0) {
@@ -2157,6 +2167,70 @@
 	return NULL;
 }
 
+static void imap_change_search_charset(IMAPFolder *folder)
+{
+	/* If server supports charset in searches, but the last used one failed,
+	 * changed to the next preferred charset. If none are still available,
+	 * disable charset searches.
+	 * Charsets are tried in the following order: 
+	 * UTF-8, locale's charset, UTF-7.
+	 */
+
+	if (folder->search_charset_supported) {
+		if (folder->search_charset && !strcmp(folder->search_charset, "UTF-8"))
+			folder->search_charset = conv_get_locale_charset_str_no_utf8();
+		else if (folder->search_charset && !strcmp(folder->search_charset, conv_get_locale_charset_str_no_utf8()))
+			folder->search_charset = "UTF-7";
+		else {
+			folder->search_charset = NULL;
+			folder->search_charset_supported = FALSE;
+		}
+	}
+}
+
+static MatcherProp *imap_matcher_prop_set_charset(IMAPFolder *folder,
+						  MatcherProp *utf8_prop,
+						  gchar **charset)
+{
+	/* If the match is going to be done locally, or the criteria is on
+	 * tag (special-cased to modified-UTF-7), or the expression searched
+	 * is ASCII, don't bother converting.
+	 */
+	if (imap_matcher_type_is_local(utf8_prop->criteria)
+	 || utf8_prop->criteria == MATCHCRITERIA_TAG
+	 || utf8_prop->criteria == MATCHCRITERIA_NOT_TAG
+	 || is_ascii_str(utf8_prop->expr))
+		return matcherprop_new(utf8_prop->criteria,
+			       utf8_prop->header,
+			       utf8_prop->matchtype,
+			       utf8_prop->expr,
+			       utf8_prop->value);
+	else {
+		gchar *conv_expr = NULL;
+
+		/* If the search is server-side and the server doesn't support
+		 * searching with the charsets we handle, bail out.
+		 */
+		if (folder->search_charset_supported == FALSE)
+			return NULL;
+
+		/* Else, convert. */
+		if (*charset == NULL)
+			*charset = g_strdup(folder->search_charset);
+
+		conv_expr = conv_codeset_strdup(utf8_prop->expr, CS_UTF_8, *charset);
+
+		if (conv_expr == NULL)
+			conv_expr = g_strdup(utf8_prop->expr);
+
+		return matcherprop_new(utf8_prop->criteria,
+			       utf8_prop->header,
+			       utf8_prop->matchtype,
+			       conv_expr,
+			       utf8_prop->value);
+	}
+}
+
 static gint	search_msgs		(Folder			*folder,
 					 FolderItem		*container,
 					 MsgNumberList		**msgs,
@@ -2171,6 +2245,7 @@
 	clist* uidlist = NULL;
 	gboolean server_filtering_useless = FALSE;
         IMAPSession *session;
+	gchar *charset_to_use = NULL;
 
 	if (on_server == NULL || !*on_server) {
 		return folder_item_search_msgs_local(folder, container, msgs, on_server,
@@ -2181,8 +2256,17 @@
 		IMAPSearchKey* matcherPart = NULL;
 		MatcherProp* prop = (MatcherProp*) cur->data;
 		gboolean is_all;
+		MatcherProp *imap_prop = imap_matcher_prop_set_charset(IMAP_FOLDER(folder), prop, &charset_to_use);
 
-		matcherPart = search_make_key(prop, &is_all);
+		if (imap_prop == NULL) {
+			/* Couldn't convert matcherprop to IMAP - probably not ascii
+			 * and server doesn't support the charsets we do. */
+			 return -1;
+		}
+
+		matcherPart = search_make_key(imap_prop, &is_all);
+
+		matcherprop_free(imap_prop);
 
 		if (on_server) {
 			*on_server &= matcherPart != NULL && prop->matchtype == MATCHTYPE_MATCHCASE;
@@ -2235,7 +2319,7 @@
 
 	if (progress_cb)
 		progress_cb(progress_data, TRUE, 0, 0, container->total_msgs);
-	result = imap_threaded_search(folder, IMAP_SEARCH_TYPE_KEYED, key, NULL, &uidlist);
+	result = imap_threaded_search(folder, IMAP_SEARCH_TYPE_KEYED, key, charset_to_use, NULL, &uidlist);
 	if (progress_cb)
 		progress_cb(progress_data, TRUE, container->total_msgs, 0, container->total_msgs);
 
@@ -2243,9 +2327,25 @@
 		gint result = 0;
 
 		*msgs = imap_uid_list_from_lep(uidlist, &result);
+
 		mailimap_search_result_free(uidlist);
 
+		if (charset_to_use != NULL)
+			g_free(charset_to_use);
+
 		return result;
+	} else if (charset_to_use != NULL) {
+		/* If search failed and was on an 8-bit string, try the next
+		 * available charset to search if there still are some.
+		 */
+		g_free(charset_to_use);
+		
+		imap_change_search_charset(IMAP_FOLDER(folder));
+		if (IMAP_FOLDER(folder)->search_charset_supported)
+			return search_msgs(folder, container, msgs, on_server, predicate,
+				   progress_cb, progress_data);
+		else
+			return -1;
 	} else {
 		return -1;
 	}
@@ -4278,7 +4378,7 @@
 	
 	if (folder->account && folder->account->low_bandwidth) {
 		r = imap_threaded_search(folder, IMAP_SEARCH_TYPE_SIMPLE,
-				NULL, NULL, &lep_uidlist);
+				NULL, NULL, NULL, &lep_uidlist);
 	}
 	
 	if (r == MAILIMAP_NO_ERROR) {
@@ -4913,12 +5013,12 @@
 			imapset = cur->data;
 			if (reverse_seen) {
 				r = imap_threaded_search(folder, IMAP_SEARCH_TYPE_SEEN, NULL,
-							 full_search ? NULL:imapset, &lep_uidlist);
+							 NULL, full_search ? NULL:imapset, &lep_uidlist);
 			}
 			else {
 				r = imap_threaded_search(folder,
 							 IMAP_SEARCH_TYPE_UNSEEN, NULL,
-							 full_search ? NULL:imapset, &lep_uidlist);
+							 NULL, full_search ? NULL:imapset, &lep_uidlist);
 			}
 			if (r == MAILIMAP_NO_ERROR) {
 				GSList * uidlist;
@@ -4933,7 +5033,7 @@
 			}
 
 			r = imap_threaded_search(folder, IMAP_SEARCH_TYPE_FLAGGED, NULL,
-						 full_search ? NULL:imapset, &lep_uidlist);
+						 NULL, full_search ? NULL:imapset, &lep_uidlist);
 			if (r == MAILIMAP_NO_ERROR) {
 				GSList * uidlist;
 
@@ -4948,7 +5048,7 @@
 
 			if (fitem->opened || fitem->processing_pending || fitem == folder->inbox) {
 				r = imap_threaded_search(folder, IMAP_SEARCH_TYPE_ANSWERED, NULL,
-							 full_search ? NULL:imapset, &lep_uidlist);
+							 NULL, full_search ? NULL:imapset, &lep_uidlist);
 				if (r == MAILIMAP_NO_ERROR) {
 					GSList * uidlist;
 
@@ -4963,7 +5063,7 @@
 
 				if (flag_ok(IMAP_FOLDER_ITEM(fitem), IMAP_FLAG_FORWARDED)) {
 					r = imap_threaded_search(folder, IMAP_SEARCH_TYPE_FORWARDED, NULL,
-								 full_search ? NULL:imapset, &lep_uidlist);
+								 NULL, full_search ? NULL:imapset, &lep_uidlist);
 					if (r == MAILIMAP_NO_ERROR) {
 						GSList * uidlist;
 
@@ -4979,7 +5079,7 @@
 
 				if (flag_ok(IMAP_FOLDER_ITEM(fitem), IMAP_FLAG_SPAM)) {
 					r = imap_threaded_search(folder, IMAP_SEARCH_TYPE_SPAM, NULL,
-								 full_search ? NULL:imapset, &lep_uidlist);
+								 NULL, full_search ? NULL:imapset, &lep_uidlist);
 					if (r == MAILIMAP_NO_ERROR) {
 						GSList * uidlist;
 
@@ -4994,7 +5094,7 @@
 				}
 
 				r = imap_threaded_search(folder, IMAP_SEARCH_TYPE_DELETED, NULL,
-							 full_search ? NULL:imapset, &lep_uidlist);
+							 NULL, full_search ? NULL:imapset, &lep_uidlist);
 				if (r == MAILIMAP_NO_ERROR) {
 					GSList * uidlist;
 



More information about the Commits mailing list