evolution-3.6.4/addressbook/util/eab-book-util.c

No issues found

  1 /*
  2  * This program is free software; you can redistribute it and/or
  3  * modify it under the terms of the GNU Lesser General Public
  4  * License as published by the Free Software Foundation; either
  5  * version 2 of the License, or (at your option) version 3.
  6  *
  7  * This program is distributed in the hope that it will be useful,
  8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 10  * Lesser General Public License for more details.
 11  *
 12  * You should have received a copy of the GNU Lesser General Public
 13  * License along with the program; if not, see <http://www.gnu.org/licenses/>
 14  *
 15  *
 16  * Authors:
 17  *		Jon Trowbridge <trow@ximian.com>
 18  *      Chris Toshok <toshok@ximian.com>
 19  *
 20  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 21  *
 22  */
 23 
 24 #ifdef HAVE_CONFIG_H
 25 #include <config.h>
 26 #endif
 27 
 28 #include <string.h>
 29 
 30 #include "eab-book-util.h"
 31 
 32 /* Copied from camel_strstrcase */
 33 static gchar *
 34 eab_strstrcase (const gchar *haystack,
 35                 const gchar *needle)
 36 {
 37 	/* find the needle in the haystack neglecting case */
 38 	const gchar *ptr;
 39 	guint len;
 40 
 41 	g_return_val_if_fail (haystack != NULL, NULL);
 42 	g_return_val_if_fail (needle != NULL, NULL);
 43 
 44 	len = strlen (needle);
 45 	if (len > strlen (haystack))
 46 		return NULL;
 47 
 48 	if (len == 0)
 49 		return (gchar *) haystack;
 50 
 51 	for (ptr = haystack; *(ptr + len - 1) != '\0'; ptr++)
 52 		if (!g_ascii_strncasecmp (ptr, needle, len))
 53 			return (gchar *) ptr;
 54 
 55 	return NULL;
 56 }
 57 
 58 GSList *
 59 eab_contact_list_from_string (const gchar *str)
 60 {
 61 	GSList *contacts = NULL;
 62 	GString *gstr = g_string_new (NULL);
 63 	gchar *str_stripped;
 64 	gchar *p = (gchar *) str;
 65 	gchar *q;
 66 
 67 	if (!p)
 68 		return NULL;
 69 
 70 	if (!strncmp (p, "Book: ", 6)) {
 71 		p = strchr (p, '\n');
 72 		if (!p) {
 73 			g_warning (G_STRLOC ": Got book but no newline!");
 74 			return NULL;
 75 		}
 76 		p++;
 77 	}
 78 
 79 	while (*p) {
 80 		if (*p != '\r') g_string_append_c (gstr, *p);
 81 
 82 		p++;
 83 	}
 84 
 85 	p = str_stripped = g_string_free (gstr, FALSE);
 86 
 87 	/* Note: The vCard standard says
 88 	 *
 89 	 * vcard = "BEGIN" [ws] ":" [ws] "VCARD" [ws] 1*CRLF
 90 	 *         items *CRLF "END" [ws] ":" [ws] "VCARD"
 91 	 *
 92 	 * which means we can have whitespace (e.g. "BEGIN : VCARD"). So we're not being
 93 	 * fully compliant here, although I'm not sure it matters. The ideal solution
 94 	 * would be to have a vcard parsing function that returned the end of the vcard
 95 	 * parsed. Arguably, contact list parsing should all be in libebook's e-vcard.c,
 96 	 * where we can do proper parsing and validation without code duplication. */
 97 
 98 	for (p = eab_strstrcase (p, "BEGIN:VCARD"); p; p = eab_strstrcase (q, "\nBEGIN:VCARD")) {
 99 		gchar *card_str;
100 
101 		if (*p == '\n')
102 			p++;
103 
104 		for (q = eab_strstrcase (p, "END:VCARD"); q; q = eab_strstrcase (q, "END:VCARD")) {
105 			gchar *temp;
106 
107 			q += 9;
108 			temp = q;
109 			if (*temp)
110 				temp += strspn (temp, "\r\n\t ");
111 
112 			if (*temp == '\0' || !g_ascii_strncasecmp (temp, "BEGIN:VCARD", 11))
113 				break;  /* Found the outer END:VCARD */
114 		}
115 
116 		if (!q)
117 			break;
118 
119 		card_str = g_strndup (p, q - p);
120 		contacts = g_slist_prepend (contacts, e_contact_new_from_vcard (card_str));
121 		g_free (card_str);
122 	}
123 
124 	g_free (str_stripped);
125 
126 	return g_slist_reverse (contacts);
127 }
128 
129 gchar *
130 eab_contact_list_to_string (const GSList *contacts)
131 {
132 	GString *str = g_string_new ("");
133 	const GSList *l;
134 
135 	for (l = contacts; l; l = l->next) {
136 		EContact *contact = l->data;
137 		gchar *vcard_str;
138 
139 		e_contact_inline_local_photos (contact, NULL);
140 		vcard_str = e_vcard_to_string (
141 			E_VCARD (contact), EVC_FORMAT_VCARD_30);
142 
143 		g_string_append (str, vcard_str);
144 		if (l->next)
145 			g_string_append (str, "\r\n\r\n");
146 	}
147 
148 	return g_string_free (str, FALSE);
149 }
150 
151 gboolean
152 eab_book_and_contact_list_from_string (ESourceRegistry *registry,
153                                        const gchar *str,
154                                        EBookClient **book_client,
155                                        GSList **contacts)
156 {
157 	ESource *source;
158 	const gchar *s0, *s1;
159 	gchar *uid;
160 
161 	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
162 	g_return_val_if_fail (str != NULL, FALSE);
163 	g_return_val_if_fail (book_client != NULL, FALSE);
164 	g_return_val_if_fail (contacts != NULL, FALSE);
165 
166 	*contacts = eab_contact_list_from_string (str);
167 
168 	if (!strncmp (str, "Book: ", 6)) {
169 		s0 = str + 6;
170 		s1 = strchr (str, '\r');
171 
172 		if (!s1)
173 			s1 = strchr (str, '\n');
174 	} else {
175 		s0 = NULL;
176 		s1 = NULL;
177 	}
178 
179 	if (!s0 || !s1) {
180 		*book_client = NULL;
181 		return FALSE;
182 	}
183 
184 	uid = g_strndup (s0, s1 - s0);
185 	source = e_source_registry_ref_source (registry, uid);
186 	if (source != NULL) {
187 		*book_client = e_book_client_new (source, NULL);
188 		g_object_unref (source);
189 	} else {
190 		*book_client = NULL;
191 	}
192 	g_free (uid);
193 
194 	return (*book_client != NULL);
195 }
196 
197 gchar *
198 eab_book_and_contact_list_to_string (EBookClient *book_client,
199                                      const GSList *contacts)
200 {
201 	gchar *s0, *s1;
202 
203 	s0 = eab_contact_list_to_string (contacts);
204 	if (!s0)
205 		s0 = g_strdup ("");
206 
207 	if (book_client != NULL) {
208 		EClient *client;
209 		ESource *source;
210 		const gchar *uid;
211 
212 		client = E_CLIENT (book_client);
213 		source = e_client_get_source (client);
214 		uid = e_source_get_uid (source);
215 		s1 = g_strconcat ("Book: ", uid, "\r\n", s0, NULL);
216 	} else
217 		s1 = g_strdup (s0);
218 
219 	g_free (s0);
220 	return s1;
221 }
222 
223 /* bad place for this i know. */
224 gint
225 e_utf8_casefold_collate_len (const gchar *str1,
226                              const gchar *str2,
227                              gint len)
228 {
229 	gchar *s1 = g_utf8_casefold (str1, len);
230 	gchar *s2 = g_utf8_casefold (str2, len);
231 	gint rv;
232 
233 	rv = g_utf8_collate (s1, s2);
234 
235 	g_free (s1);
236 	g_free (s2);
237 
238 	return rv;
239 }
240 
241 gint
242 e_utf8_casefold_collate (const gchar *str1,
243                          const gchar *str2)
244 {
245 	return e_utf8_casefold_collate_len (str1, str2, -1);
246 }