diff --git a/src/mu-cmd-find.c b/src/mu-cmd-find.c index 6b8f2aa5..c166e8e0 100644 --- a/src/mu-cmd-find.c +++ b/src/mu-cmd-find.c @@ -294,6 +294,35 @@ resolve_bookmark (MuConfig *opts, GError **err) } + +gchar* +str_quoted_from_strv (const gchar **params) +{ + GString *str; + int i; + + g_return_val_if_fail (params, NULL); + + if (!params[0]) + return g_strdup (""); + + str = g_string_sized_new (64); /* just a guess */ + + for (i = 0; params[i]; ++i) { + + if (i > 0) + g_string_append_c (str, ' '); + + g_string_append_c (str, '"'); + g_string_append (str, params[i]); + g_string_append_c (str, '"'); + } + + return g_string_free (str, FALSE); +} + + + static gchar* get_query (MuConfig *opts, GError **err) { @@ -313,7 +342,7 @@ get_query (MuConfig *opts, GError **err) return NULL; } - query = mu_util_str_from_strv ((const gchar**)&opts->params[1]); + query = str_quoted_from_strv ((const gchar**)&opts->params[1]); if (bookmarkval) { gchar *tmp; tmp = g_strdup_printf ("%s %s", bookmarkval, query); diff --git a/src/mu-query.cc b/src/mu-query.cc index 2f45a54e..c5d27505 100644 --- a/src/mu-query.cc +++ b/src/mu-query.cc @@ -203,7 +203,8 @@ get_query (MuQuery *mqx, const char* searchexpr, GError **err) Xapian::QueryParser::FLAG_PURE_NOT | Xapian::QueryParser::FLAG_WILDCARD | Xapian::QueryParser::FLAG_AUTO_SYNONYMS | - Xapian::QueryParser::FLAG_BOOLEAN_ANY_CASE); + Xapian::QueryParser::FLAG_BOOLEAN_ANY_CASE + ); g_free (preprocessed); return query; @@ -275,22 +276,32 @@ mu_query_destroy (MuQuery *self) } -/* preprocess a query to make them a bit more permissive */ +/* preprocess a query to make them a bit more promiscuous */ char* mu_query_preprocess (const char *query) { - gchar *my_query; + GSList *parts, *cur; + gchar *myquery; g_return_val_if_fail (query, NULL); - my_query = g_strdup (query); - /* remove accents and turn to lower-case */ - mu_str_normalize_in_place (my_query, TRUE); - /* escape '@', single '_' and ':' if it's not following a - * xapian-pfx with '_' */ - mu_str_ascii_xapian_escape_in_place (my_query); + /* convert the query to a list of query terms, and escape them + * separately */ + parts = mu_str_esc_to_list (query); - return my_query; + for (cur = parts; cur; cur = g_slist_next(cur)) { + /* remove accents and turn to lower-case */ + cur->data = mu_str_normalize_in_place ((gchar*)cur->data, TRUE); + /* escape '@', single '_' and ':' if it's not following a + * xapian-pfx with '_' */ + cur->data = mu_str_ascii_xapian_escape_in_place + ((gchar*)cur->data, TRUE /*escape spaces too*/); + } + + myquery = mu_str_from_list (parts, ' '); + mu_str_free_list (parts); + + return myquery; } diff --git a/src/mu-str.c b/src/mu-str.c index d746861f..d88e9647 100644 --- a/src/mu-str.c +++ b/src/mu-str.c @@ -432,7 +432,7 @@ mu_str_subject_normalize (const gchar* str) * specially; function below is an ugly hack to make it DWIM in most * cases...*/ char* -mu_str_ascii_xapian_escape_in_place (char *query) +mu_str_ascii_xapian_escape_in_place (char *query, gboolean esc_space) { gchar *cur; const char escchar = '_'; @@ -444,10 +444,14 @@ mu_str_ascii_xapian_escape_in_place (char *query) *cur = tolower(*cur); switch (*cur) { + case ' ': + if (!esc_space) + break; case '@': case '-': case '/': - case '.': { + case '.': + { /* don't replace a final special char */ if (cur[1]== ' ' || cur[1]=='\t' || cur[1]== '.') ++cur; @@ -472,11 +476,11 @@ mu_str_ascii_xapian_escape_in_place (char *query) } char* -mu_str_ascii_xapian_escape (const char *query) +mu_str_ascii_xapian_escape (const char *query, gboolean esc_space) { g_return_val_if_fail (query, NULL); - return mu_str_ascii_xapian_escape_in_place (g_strdup(query)); + return mu_str_ascii_xapian_escape_in_place (g_strdup(query), esc_space); } diff --git a/src/mu-str.h b/src/mu-str.h index a5598195..e0c30bdc 100644 --- a/src/mu-str.h +++ b/src/mu-str.h @@ -1,22 +1,22 @@ /* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ -/* +/* ** Copyright (C) 2008-2010 Dirk-Jan C. Binnema ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 3 of the License, or ** (at your option) any later version. -** +** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. -** +** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software Foundation, -** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -** +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** */ #ifndef __MU_STR_H__ @@ -43,9 +43,9 @@ G_BEGIN_DECLS * buffer (ie, non-reentrant), while mu_str_display_contact * returns a newly allocated string that you must free with g_free * when done with it. - * + * * @param str a 'contact str' (ie., what is in the To/Cc/Bcc/From fields), or NULL - * + * * @return a newly allocated string with a display contact */ const char* mu_str_display_contact_s (const char *str); @@ -56,13 +56,13 @@ char *mu_str_display_contact (const char *str); * get a display size for a given size_t; uses M for sizes > * 1000*1000, k for smaller sizes. Note: this function use the * 10-based SI units, _not_ the powers-of-2 based ones. - * + * * mu_str_size_s returns a ptr to a static buffer, * while mu_str_size returns dynamically allocated * memory that must be freed after use. * * @param t the size as an size_t - * + * * @return a string representation of the size; see above * for what to do with it */ @@ -70,17 +70,17 @@ const char* mu_str_size_s (size_t s) G_GNUC_CONST; char* mu_str_size (size_t s) G_GNUC_WARN_UNUSED_RESULT; /** - * get a display string for a given set of flags, OR'ed in + * get a display string for a given set of flags, OR'ed in * @param flags; one character per flag: - * D=draft,F=flagged,N=new,P=passed,R=replied,S=seen,T=trashed + * D=draft,F=flagged,N=new,P=passed,R=replied,S=seen,T=trashed * a=has-attachment,s=signed, x=encrypted - * + * * mu_str_file_flags_s returns a ptr to a static buffer, * while mu_str_file_flags returns dynamically allocated * memory that must be freed after use. * * @param flags file flags - * + * * @return a string representation of the flags; see above * for what to do with it */ @@ -91,10 +91,10 @@ char* mu_str_flags (MuFlags flags) /** * get a 'summary' of the string, ie. the first /n/ lines of the * strings, with all newlines removed, replaced by single spaces - * + * * @param str the source string * @param max_lines the maximum number of lines to include in the summary - * + * * @return a newly allocated string with the summary. use g_free to free it. */ char* mu_str_summarize (const char* str, size_t max_lines) @@ -106,8 +106,8 @@ char* mu_str_summarize (const char* str, size_t max_lines) * 'Latin-1 Supplement' and 'Latin Extended-A' * * @param str a valid utf8 string or NULL - * @param downcase if TRUE, convert the string to lowercase - * + * @param downcase if TRUE, convert the string to lowercase + * * @return the normalize string, or NULL in case of error or str was NULL */ char* mu_str_normalize (const char *str, gboolean downcase) @@ -120,10 +120,10 @@ char* mu_str_normalize (const char *str, gboolean downcase) * optionally, downcase it. this happen by changing the string; if * that is not desired, use mu_str_normalize. Works for accented chars * in Unicode Blocks 'Latin-1 Supplement' and 'Latin Extended-A' - * + * * @param str a valid utf8 string or NULL * @param downcase if TRUE, convert the string to lowercase - * + * * @return the normalized string, or NULL in case of error or str was * NULL */ @@ -139,12 +139,13 @@ char* mu_str_normalize_in_place (char *str, gboolean downcase); * case, the string will be downcased. * * works for ascii strings, like e-mail addresses and message-id. - * + * * @param query a query string - * + * @param esc_space escape space characters as well + * * @return the escaped string or NULL in case of error */ -char* mu_str_ascii_xapian_escape_in_place (char *query); +char* mu_str_ascii_xapian_escape_in_place (char *query, gboolean esc_space); /** * escape the string for use with xapian matching. in practice, if the @@ -153,12 +154,13 @@ char* mu_str_ascii_xapian_escape_in_place (char *query); * as 'subject:', 't:' etc, as defined in mu-msg-fields.[ch]). * * works for ascii strings, like e-mail addresses and message-id. - * + * * @param query a query string - * + * @param esc_space escape space characters as well + * * @return the escaped string (free with g_free) or NULL in case of error */ -char* mu_str_ascii_xapian_escape (const char *query) +char* mu_str_ascii_xapian_escape (const char *query, gboolean esc_space) G_GNUC_WARN_UNUSED_RESULT; @@ -174,9 +176,9 @@ char* mu_str_ascii_xapian_escape (const char *query) * practical sizes for email messages are in terms of Mb; even in * extreme cases it should be under 100 Mb. Function return * GUINT64_MAX if there a parsing error - * + * * @param str a string with a size, such a "100", "100Kb", "1Mb" - * + * * @return the corresponding size in bytes, or -1 in case of error */ gint64 mu_str_size_parse_bkm (const char* str); @@ -184,10 +186,10 @@ gint64 mu_str_size_parse_bkm (const char* str); /** * create a full path from a path + a filename. function is _not_ * reentrant. - * + * * @param path a path (!= NULL) * @param name a name (may be NULL) - * + * * @return the path as a statically allocated buffer. don't free. */ const char* mu_str_fullpath_s (const char* path, const char* name); @@ -196,10 +198,10 @@ const char* mu_str_fullpath_s (const char* path, const char* name); /** * escape a string like a string literal in C; ie. replace \ with \\, * and " with \" - * + * * @param str a non-NULL str * @param in_quotes whether the result should be enclosed in "" - * + * * @return the escaped string, newly allocated (free with g_free) */ char* mu_str_escape_c_literal (const gchar* str, gboolean in_quotes) @@ -210,9 +212,9 @@ char* mu_str_escape_c_literal (const gchar* str, gboolean in_quotes) /** * turn a string into plain ascii by replacing each non-ascii * character with a dot ('.'). replacement is done in-place. - * + * * @param buf a buffer to asciify - * + * * @return the buf ptr (as to allow for function composition) */ char* mu_str_asciify_in_place (char *buf); @@ -220,10 +222,10 @@ char* mu_str_asciify_in_place (char *buf); /** * convert a string in a certain charset into utf8 - * + * * @param buffer a buffer to convert * @param charset source character set. - * + * * @return a UTF8 string (which you need to g_free when done with it), * or NULL in case of error */ @@ -234,9 +236,9 @@ gchar* mu_str_convert_to_utf8 (const char* buffer, const char *charset); /** * macro to check whether the string is empty, ie. if it's NULL or * it's length is 0 - * + * * @param S a string - * + * * @return TRUE if the string is empty, FALSE otherwise */ #define mu_str_is_empty(S) ((!(S)||!(*S))?TRUE:FALSE) @@ -244,10 +246,10 @@ gchar* mu_str_convert_to_utf8 (const char* buffer, const char *charset); /** * convert a GSList of strings to a #sepa-separated list - * + * * @param lst a GSList * @param the separator character - * + * * @return a newly allocated string */ char* mu_str_from_list (const GSList *lst, char sepa); @@ -255,7 +257,7 @@ char* mu_str_from_list (const GSList *lst, char sepa); /** * convert a #sepa-separated list of strings in to a GSList - * + * * @param str a #sepa-separated list of strings * @param the separator character * @param remove leading/trailing whitespace from the string @@ -270,9 +272,9 @@ GSList* mu_str_to_list (const char *str, char sepa, gboolean strip); * separated by one or more spaces. list items can be quoted (using * '"'), and '"', ' ' and '\' use their special meaning when prefixed * with \. - * + * * @param str a string - * + * * @return a list of elements or NULL in case of error */ GSList* mu_str_esc_to_list (const char *str); @@ -280,7 +282,7 @@ GSList* mu_str_esc_to_list (const char *str); /** * free a GSList consisting of allocated strings - * + * * @param lst a GSList */ void mu_str_free_list (GSList *lst); @@ -289,9 +291,9 @@ void mu_str_free_list (GSList *lst); /** * strip the subject of Re:, Fwd: etc. - * + * * @param str a subject string - * + * * @return a new string -- this is pointing somewhere inside the @str; * no copy is made, don't free */ @@ -303,9 +305,9 @@ const gchar* mu_str_subject_normalize (const gchar* str); * first name, last name, the nick will be first name + the first char * of the last name. otherwise, it's just the first name. clearly, * this is just a rough guess for setting an initial value for nicks. - * + * * @param name a name - * + * * @return the guessed nick, as a newly allocated string (free with g_free) */ gchar* mu_str_guess_nick (const char* name) @@ -315,9 +317,9 @@ gchar* mu_str_guess_nick (const char* name) /** * guess the first name for the given name; clearly, * this is just a rough guess for setting an initial value. - * + * * @param name a name - * + * * @return the first name, as a newly allocated string (free with * g_free) */ @@ -329,9 +331,9 @@ gchar* mu_str_guess_first_name (const char* name) /** * guess the last name for the given name; clearly, * this is just a rough guess for setting an initial value. - * + * * @param name a name - * + * * @return the last name, as a newly allocated string (free with * g_free) */ diff --git a/src/mu-util.c b/src/mu-util.c index 496950c1..5a6a4698 100644 --- a/src/mu-util.c +++ b/src/mu-util.c @@ -284,7 +284,7 @@ mu_util_str_from_strv (const gchar **params) for (i = 0; params[i]; ++i) { - if (i>0) + if (i > 0) g_string_append_c (str, ' '); g_string_append (str, params[i]); @@ -293,6 +293,11 @@ mu_util_str_from_strv (const gchar **params) return g_string_free (str, FALSE); } + + + + + int mu_util_create_writeable_fd (const char* path, mode_t mode, gboolean overwrite) @@ -482,5 +487,3 @@ mu_util_printerr_encoded (const char *frm, ...) return rv; } - -