1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
4 * (GLABELS) Label and Business Card Creation program for GNOME
6 * merge_vcard.c: vcard merge backend module
8 * Copyright (C) 2001 Jim Evins <evins@snaught.com>.
10 * Copyright (C) 2005 Austin Henry <ahenry@users.sourceforge.net>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 #include "merge-vcard.h"
33 #include <libebook/e-contact.h>
41 /*===========================================*/
43 /*===========================================*/
45 struct _glMergeVCardPrivate {
57 /*===========================================*/
59 /*===========================================*/
62 /*===========================================*/
63 /* Local function prototypes */
64 /*===========================================*/
66 static void gl_merge_vcard_finalize (GObject *object);
68 static void gl_merge_vcard_set_property (GObject *object,
73 static void gl_merge_vcard_get_property (GObject *object,
78 static GList *gl_merge_vcard_get_key_list (glMerge *merge);
79 static gchar *gl_merge_vcard_get_primary_key (glMerge *merge);
80 static void gl_merge_vcard_open (glMerge *merge);
81 static void gl_merge_vcard_close (glMerge *merge);
82 static glMergeRecord *gl_merge_vcard_get_record (glMerge *merge);
83 static void gl_merge_vcard_copy (glMerge *dst_merge,
85 static char * parse_next_vcard (FILE *fp);
89 /*****************************************************************************/
90 /* Boilerplate object stuff. */
91 /*****************************************************************************/
92 G_DEFINE_TYPE (glMergeVCard, gl_merge_vcard, GL_TYPE_MERGE);
95 gl_merge_vcard_class_init (glMergeVCardClass *class)
97 GObjectClass *object_class = G_OBJECT_CLASS (class);
98 glMergeClass *merge_class = GL_MERGE_CLASS (class);
100 gl_debug (DEBUG_MERGE, "START");
102 gl_merge_vcard_parent_class = g_type_class_peek_parent (class);
104 object_class->set_property = gl_merge_vcard_set_property;
105 object_class->get_property = gl_merge_vcard_get_property;
107 object_class->finalize = gl_merge_vcard_finalize;
109 merge_class->get_key_list = gl_merge_vcard_get_key_list;
110 merge_class->get_primary_key = gl_merge_vcard_get_primary_key;
111 merge_class->open = gl_merge_vcard_open;
112 merge_class->close = gl_merge_vcard_close;
113 merge_class->get_record = gl_merge_vcard_get_record;
114 merge_class->copy = gl_merge_vcard_copy;
116 gl_debug (DEBUG_MERGE, "END");
120 gl_merge_vcard_init (glMergeVCard *merge_vcard)
122 gl_debug (DEBUG_MERGE, "START");
124 merge_vcard->priv = g_new0 (glMergeVCardPrivate, 1);
126 gl_debug (DEBUG_MERGE, "END");
130 gl_merge_vcard_finalize (GObject *object)
132 glMergeVCard *merge_vcard = GL_MERGE_VCARD (object);
134 gl_debug (DEBUG_MERGE, "START");
136 g_return_if_fail (object && GL_IS_MERGE_VCARD (object));
138 g_free (merge_vcard->priv);
140 G_OBJECT_CLASS (gl_merge_vcard_parent_class)->finalize (object);
142 gl_debug (DEBUG_MERGE, "END");
145 /*--------------------------------------------------------------------------*/
147 /*--------------------------------------------------------------------------*/
149 gl_merge_vcard_set_property (GObject *object,
154 glMergeVCard *merge_vcard;
156 merge_vcard = GL_MERGE_VCARD (object);
160 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
165 /*--------------------------------------------------------------------------*/
167 /*--------------------------------------------------------------------------*/
169 gl_merge_vcard_get_property (GObject *object,
174 glMergeVCard *merge_vcard;
176 merge_vcard = GL_MERGE_VCARD (object);
180 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
187 /*--------------------------------------------------------------------------*/
189 /*--------------------------------------------------------------------------*/
191 gl_merge_vcard_get_key_list (glMerge *merge)
193 glMergeVCard *merge_vcard;
196 gl_debug (DEBUG_MERGE, "BEGIN");
198 merge_vcard = GL_MERGE_VCARD (merge);
200 /* extremely simple approach until I can list the available keys from the
201 * server, and return them. */
203 key_list = g_list_append (key_list, g_strdup ("full_name"));
204 key_list = g_list_append (key_list, g_strdup ("home_address"));
205 key_list = g_list_append (key_list, g_strdup ("work_address"));
207 gl_debug (DEBUG_MERGE, "END");
213 /*--------------------------------------------------------------------------*/
214 /* Get "primary" key. */
215 /*--------------------------------------------------------------------------*/
217 gl_merge_vcard_get_primary_key (glMerge *merge)
219 /* For now, let's always assume the full name is the primary key. */
220 return g_strdup ("full_name");
223 /*--------------------------------------------------------------------------*/
224 /* Open merge source. */
225 /*--------------------------------------------------------------------------*/
227 gl_merge_vcard_open (glMerge *merge)
229 glMergeVCard *merge_vcard;
232 merge_vcard = GL_MERGE_VCARD (merge);
234 src = gl_merge_get_src (merge);
237 merge_vcard->priv->fp = fopen (src, "r");
245 /*--------------------------------------------------------------------------*/
246 /* Close merge source. */
247 /*--------------------------------------------------------------------------*/
249 gl_merge_vcard_close (glMerge *merge)
251 glMergeVCard *merge_vcard;
253 merge_vcard = GL_MERGE_VCARD (merge);
255 if (merge_vcard->priv->fp != NULL) {
256 fclose (merge_vcard->priv->fp);
257 merge_vcard->priv->fp = NULL;
261 /*--------------------------------------------------------------------------*/
262 /* Get next record from merge source, NULL if no records left (i.e EOF) */
263 /*--------------------------------------------------------------------------*/
264 static glMergeRecord *
265 gl_merge_vcard_get_record (glMerge *merge)
267 glMergeVCard *merge_vcard;
268 glMergeRecord *record;
274 merge_vcard = GL_MERGE_VCARD (merge);
276 vcard = parse_next_vcard(merge_vcard->priv->fp);
277 if (vcard == NULL || vcard[0] == '\0') {
278 return NULL; /* EOF */
280 contact = e_contact_new_from_vcard(vcard);
281 if (contact == NULL) {
282 return NULL; /* invalid vcard */
285 record = g_new0 (glMergeRecord, 1);
286 record->select_flag = TRUE;
288 /* Take the interesting fields one by one from the contact, and put them
289 * into the glMergeRecord structure. When done, free up the resources for
292 /* get the full name */
293 field = g_new0 (glMergeField, 1);
294 field->key = g_strdup ("full_name");
295 field->value = g_strdup (e_contact_get_const(contact, E_CONTACT_FULL_NAME));
297 record->field_list = g_list_append (record->field_list, field);
299 /* get the home address */
300 field = g_new0 (glMergeField, 1);
301 field->key = g_strdup ("home_address");
302 field->value = g_strdup (e_contact_get_const(contact, E_CONTACT_ADDRESS_LABEL_HOME));
304 record->field_list = g_list_append (record->field_list, field);
306 /* get the work address */
307 field = g_new0 (glMergeField, 1);
308 field->key = g_strdup ("work_address");
309 field->value = g_strdup (e_contact_get_const(contact, E_CONTACT_ADDRESS_LABEL_WORK));
311 record->field_list = g_list_append (record->field_list, field);
313 /* free the contact */
314 g_object_unref (contact);
320 /*---------------------------------------------------------------------------*/
321 /* Copy merge_vcard specific fields. */
322 /*---------------------------------------------------------------------------*/
324 gl_merge_vcard_copy (glMerge *dst_merge,
327 glMergeVCard *dst_merge_vcard;
328 glMergeVCard *src_merge_vcard;
330 dst_merge_vcard = GL_MERGE_VCARD (dst_merge);
331 src_merge_vcard = GL_MERGE_VCARD (src_merge);
334 /*---------------------------------------------------------------------------*/
335 /* PRIVATE: pull out a full VCard from the open file */
337 /* fp - an open stream to parse in put from */
339 /* a pointer to the buffer containing the vcard, the empty string on */
340 /* end-of-file or error, this buffer needs to be free by the caller */
341 /*---------------------------------------------------------------------------*/
343 parse_next_vcard (FILE *fp)
345 gboolean found_begin = FALSE;
346 gboolean found_end = FALSE;
352 /* if no source has been set up, don't try to read from the file */
357 vcard = g_malloc0(size);
359 while (fgets(line, sizeof(line), fp) && found_end == FALSE) {
360 if (found_begin == TRUE) {
361 if (g_str_has_prefix(line, "END:VCARD")) { found_end = TRUE; }
363 if (g_str_has_prefix(line, "BEGIN:VCARD")) { found_begin = TRUE; }
364 else { continue; }/* skip lines not in a vcard */
367 /* if the buffer passed us isn't big enough, reallocate it */
368 cursize += strlen(line);
369 if (cursize >= size) {
371 vcard = (char *)g_realloc(vcard, size); /* aborts program on error */
374 /* add the line (or portion thereof) to the vcard */
375 strncat(vcard, line, size);
383 #endif /* HAVE_LIBEBOOK */