static gint
camel_ustrncasecmp (const gchar *ps1, const gchar *ps2, gsize len)
{
	gunichar u1, u2 = 0;
	const guchar *s1 = (const guchar *)ps1;
	const guchar *s2 = (const guchar *)ps2;

	CAMEL_SEARCH_COMPARE (s1, s2, NULL);

	u1 = camel_utf8_getc (&s1);
	u2 = camel_utf8_getc (&s2);
	while (len > 0 && u1 && u2) {
		u1 = g_unichar_tolower (u1);
		u2 = g_unichar_tolower (u2);
		if (u1 < u2)
			return -1;
		else if (u1 > u2)
			return 1;

		len--;
		u1 = camel_utf8_getc (&s1);
		u2 = camel_utf8_getc (&s2);
	}

	if (len == 0)
		return 0;

	/* end of one of the strings ? */
	CAMEL_SEARCH_COMPARE (u1, u2, 0);

	/* if we have invalid utf8 sequence ?  */
	CAMEL_SEARCH_COMPARE (s1, s2, NULL);

	return 0;
}
static int
camel_ustrcasecmp (const char *ps1, const char *ps2)
{
	gunichar u1, u2 = 0;
	const unsigned char *s1 = (const unsigned char *)ps1;
	const unsigned char *s2 = (const unsigned char *)ps2;

	CAMEL_SEARCH_COMPARE (s1, s2, NULL);

	u1 = camel_utf8_getc(&s1);
	u2 = camel_utf8_getc(&s2);
	while (u1 && u2) {
		u1 = g_unichar_tolower (u1);
		u2 = g_unichar_tolower (u2);
		if (u1 < u2)
			return -1;
		else if (u1 > u2)
			return 1;

		u1 = camel_utf8_getc(&s1);
		u2 = camel_utf8_getc(&s2);
	}

	/* end of one of the strings ? */
	CAMEL_SEARCH_COMPARE (u1, u2, 0);

	/* if we have invalid utf8 sequence ?  */
	CAMEL_SEARCH_COMPARE (s1, s2, NULL);

	return 0;
}
/* value is the match value suitable for exact match if required */
static int
header_match(const char *value, const char *match, camel_search_match_t how)
{
	const unsigned char *p;
	int vlen, mlen;
	gunichar c;

	if (how == CAMEL_SEARCH_MATCH_SOUNDEX)
		return header_soundex (value, match);

	vlen = strlen(value);
	mlen = strlen(match);
	if (vlen < mlen)
		return FALSE;

	/* from dan the man, if we have mixed case, perform a case-sensitive match,
	   otherwise not */
	p = (const unsigned char *)match;

	c = camel_utf8_getc (&p);
	while (c)
	{
		if (g_unichar_isupper(c)) {
			switch (how) {
			case CAMEL_SEARCH_MATCH_EXACT:
				return strcmp(value, match) == 0;
			case CAMEL_SEARCH_MATCH_CONTAINS:
				return strstr(value, match) != NULL;
			case CAMEL_SEARCH_MATCH_STARTS:
				return strncmp(value, match, mlen) == 0;
			case CAMEL_SEARCH_MATCH_ENDS:
				return strcmp(value + vlen - mlen, match) == 0;
			default:
				break;
			}
			return FALSE;
		}
		c = camel_utf8_getc (&p);
	}

	switch (how) {
	case CAMEL_SEARCH_MATCH_EXACT:
		return camel_ustrcasecmp(value, match) == 0;
	case CAMEL_SEARCH_MATCH_CONTAINS:
		return camel_ustrstrcase(value, match) != NULL;
	case CAMEL_SEARCH_MATCH_STARTS:
		return camel_ustrncasecmp(value, match, mlen) == 0;
	case CAMEL_SEARCH_MATCH_ENDS:
		return camel_ustrcasecmp(value + vlen - mlen, match) == 0;
	default:
		break;
	}

	return FALSE;
}
const gchar *
camel_ustrstrcase (const gchar *haystack, const gchar *needle)
{
	gunichar *nuni, *puni;
	gunichar u;
	const guchar *p;

	g_return_val_if_fail (haystack != NULL, NULL);
	g_return_val_if_fail (needle != NULL, NULL);

	if (strlen (needle) == 0)
		return haystack;
	if (strlen (haystack) == 0)
		return NULL;

	puni = nuni = g_alloca (sizeof (gunichar) * strlen (needle));

	p = (const guchar *) needle;
	while ((u = camel_utf8_getc (&p)))
		*puni++ = g_unichar_tolower (u);

	/* NULL means there was illegal utf-8 sequence */
	if (!p)
		return NULL;

	p = (const guchar *)haystack;
	while ((u = camel_utf8_getc (&p))) {
		gunichar c;

		c = g_unichar_tolower (u);
		/* We have valid stripped gchar */
		if (c == nuni[0]) {
			const guchar *q = p;
			gint npos = 1;

			while (nuni + npos < puni) {
				u = camel_utf8_getc (&q);
				if (!q || !u)
					return NULL;

				c = g_unichar_tolower (u);
				if (c != nuni[npos])
					break;

				npos++;
			}

			if (nuni + npos == puni)
				return (const gchar *) p;
		}
	}

	return NULL;
}
struct _camel_search_words *
camel_search_words_split (const guchar *in)
{
	gint type = CAMEL_SEARCH_WORD_SIMPLE, all = 0;
	GString *w;
	struct _camel_search_words *words;
	GPtrArray *list = g_ptr_array_new ();
	guint32 c;
	gint inquote = 0;

	words = g_malloc0 (sizeof (*words));
	w = g_string_new("");

	do {
		c = camel_utf8_getc (&in);

		if (c == 0
		    || (inquote && c == '"')
		    || (!inquote && g_unichar_isspace (c))) {
			output_w (w, list, type);
			all |= type;
			type = CAMEL_SEARCH_WORD_SIMPLE;
			inquote = 0;
		} else {
			if (c == '\\') {
				c = camel_utf8_getc (&in);
				if (c)
					output_c (w, c, &type);
				else {
					output_w (w, list, type);
					all |= type;
				}
			} else if (c == '\"') {
				inquote = 1;
			} else {
				output_c (w, c, &type);
			}
		}
	} while (c);

	g_string_free (w, TRUE);
	words->len = list->len;
	words->words = (struct _camel_search_word **)list->pdata;
	words->type = all;
	g_ptr_array_free (list, FALSE);

	return words;
}
/* takes an existing 'words' list, and converts it to another consisting of
   only simple words, with any punctuation etc stripped */
struct _camel_search_words *
camel_search_words_simple (struct _camel_search_words *wordin)
{
	gint i;
	const guchar *ptr, *start, *last;
	gint type = CAMEL_SEARCH_WORD_SIMPLE, all = 0;
	GPtrArray *list = g_ptr_array_new ();
	struct _camel_search_word *word;
	struct _camel_search_words *words;
	guint32 c;

	words = g_malloc0 (sizeof (*words));

	for (i=0;i<wordin->len;i++) {
		if ((wordin->words[i]->type & CAMEL_SEARCH_WORD_COMPLEX) == 0) {
			word = g_malloc0 (sizeof (*word));
			word->type = wordin->words[i]->type;
			word->word = g_strdup (wordin->words[i]->word);
			g_ptr_array_add (list, word);
		} else {
			ptr = (const guchar *) wordin->words[i]->word;
			start = last = ptr;
			do {
				c = camel_utf8_getc (&ptr);
				if (c == 0 || !g_unichar_isalnum (c)) {
					if (last > start) {
						word = g_malloc0 (sizeof (*word));
						word->word = g_strndup ((gchar *) start, last-start);
						word->type = type;
						g_ptr_array_add (list, word);
						all |= type;
						type = CAMEL_SEARCH_WORD_SIMPLE;
					}
					start = ptr;
				}
				if (c > 0x80)
					type = CAMEL_SEARCH_WORD_8BIT;
				last = ptr;
			} while (c);
		}
	}

	words->len = list->len;
	words->words = (struct _camel_search_word **)list->pdata;
	words->type = all;
	g_ptr_array_free (list, FALSE);

	return words;
}
Example #7
0
/**
 * clean_name code from mail-to-task plugin (gpl)
 **/
static gchar *
clean_name(const guchar *s) {
   GString *out = g_string_new("");
   guint32 c;
   gchar *r;

   while ((c = camel_utf8_getc((const guchar **) & s))) {
      if (!g_unichar_isprint(c) || (c < 0x7f && strchr(" /'\"`&();|<>$%{}!", c)))
         c = '_';
      g_string_append_u(out, c);
   }

   r = g_strdup(out->str);
   g_string_free(out, TRUE);

   return r;
}
char *
camel_nntp_store_summary_path_to_full (CamelNNTPStoreSummary *s, const char *path, char dir_sep)
{
	char *full, *f;
	guint32 c, v = 0;
	const char *p;
	int state=0;
	char *subpath, *last = NULL;
	CamelStoreInfo *si;

	/* check to see if we have a subpath of path already defined */
	subpath = g_alloca (strlen (path) + 1);
	strcpy (subpath, path);
	do {
		si = camel_store_summary_path ((CamelStoreSummary *) s, subpath);
		if (si == NULL) {
			last = strrchr (subpath, '/');
			if (last)
				*last = 0;
		}
	} while (si == NULL && last);

	/* path is already present, use the raw version we have */
	if (si && strlen (subpath) == strlen (path)) {
		f = g_strdup (camel_nntp_store_info_full_name (s, si));
		camel_store_summary_info_free ((CamelStoreSummary *) s, si);
		return f;
	}

	f = full = g_alloca (strlen (path)*2+1);
	if (si)
		p = path + strlen (subpath);
	else
		p = path;

	while ((c = camel_utf8_getc ((const unsigned char **) &p))) {
		switch (state) {
		case 0:
			if (c == '%') {
				state = 1;
			} else {
				if (c == '/')
					c = dir_sep;
				camel_utf8_putc((unsigned char **) &f, c);
			}
			break;
		case 1:
			state = 2;
			v = hexnib (c) << 4;
			break;
		case 2:
			state = 0;
			v |= hexnib (c);
			camel_utf8_putc ((unsigned char **) &f, v);
			break;
		}
	}
	camel_utf8_putc ((unsigned char **) &f, c);

	/* merge old path part if required */
	f = camel_utf8_utf7 (full);
	if (si) {
		full = g_strdup_printf ("%s%s", camel_nntp_store_info_full_name (s, si), f);
		g_free (f);
		camel_store_summary_info_free ((CamelStoreSummary *) s, si);
		f = full;
	}

	return f;
}
/* searhces for match inside value, if match is mixed case, hten use case-sensitive,
   else insensitive */
gboolean
camel_search_header_match (const gchar *value, const gchar *match, camel_search_match_t how, camel_search_t type, const gchar *default_charset)
{
	const gchar *name, *addr;
	const guchar *ptr;
	gint truth = FALSE, i;
	CamelInternetAddress *cia;
	gchar *v, *vdom, *mdom;
	gunichar c;

	ptr = (const guchar *)value;
	while ((c = camel_utf8_getc (&ptr)) && g_unichar_isspace (c))
		value = (const gchar *)ptr;

	switch (type) {
	case CAMEL_SEARCH_TYPE_ENCODED:
		v = camel_header_decode_string (value, default_charset); /* FIXME: Find header charset */
		truth = header_match (v, match, how);
		g_free (v);
		break;
	case CAMEL_SEARCH_TYPE_MLIST:
		/* Special mailing list old-version domain hack
		   If one of the mailing list names doesn't have an @ in it, its old-style, so
		   only match against the pre-domain part, which should be common */

		vdom = strchr (value, '@');
		mdom = strchr (match, '@');
		if (mdom == NULL && vdom != NULL) {
			v = g_alloca (vdom-value+1);
			memcpy (v, value, vdom-value);
			v[vdom-value] = 0;
			value = (gchar *)v;
		} else if (mdom != NULL && vdom == NULL) {
			v = g_alloca (mdom-match+1);
			memcpy (v, match, mdom-match);
			v[mdom-match] = 0;
			match = (gchar *)v;
		}
		/* Falls through */
	case CAMEL_SEARCH_TYPE_ASIS:
		truth = header_match (value, match, how);
		break;
	case CAMEL_SEARCH_TYPE_ADDRESS_ENCODED:
	case CAMEL_SEARCH_TYPE_ADDRESS:
		/* possible simple case to save some work if we can */
		if (header_match (value, match, how))
			return TRUE;

		/* Now we decode any addresses, and try asis matches on name and address parts */
		cia = camel_internet_address_new ();
		if (type == CAMEL_SEARCH_TYPE_ADDRESS_ENCODED)
			camel_address_decode ((CamelAddress *)cia, value);
		else
			camel_address_unformat ((CamelAddress *)cia, value);

		for (i=0; !truth && camel_internet_address_get (cia, i, &name, &addr);i++)
			truth = (name && header_match (name, match, how)) || (addr && header_match (addr, match, how));

		g_object_unref (cia);
		break;
	}

	return truth;
}