]> git.sur5r.net Git - glabels/blob - src/merge-vcard.c
Imported Upstream version 2.2.8
[glabels] / src / merge-vcard.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
2
3 /*
4  *  (GLABELS) Label and Business Card Creation program for GNOME
5  *
6  *  merge_vcard.c:  vcard merge backend module
7  *
8  *  Copyright (C) 2001  Jim Evins <evins@snaught.com>.
9  *  and
10  *  Copyright (C) 2005  Austin Henry <ahenry@users.sourceforge.net>
11  *
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.
16  *
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.
21  *
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
25  */
26
27 #include <config.h>
28
29 #ifdef HAVE_LIBEBOOK
30
31
32 #include "merge-vcard.h"
33 #include <libebook/e-contact.h>
34
35 #include <stdio.h>
36 #include <string.h>
37 #include <errno.h>
38
39 #include "debug.h"
40
41 /*===========================================*/
42 /* Private types                             */
43 /*===========================================*/
44
45 struct _glMergeVCardPrivate {
46         FILE        *fp;
47 };
48
49 enum {
50         LAST_SIGNAL
51 };
52
53 enum {
54         ARG_0,
55 };
56
57 /*===========================================*/
58 /* Private globals                           */
59 /*===========================================*/
60
61
62 /*===========================================*/
63 /* Local function prototypes                 */
64 /*===========================================*/
65
66 static void           gl_merge_vcard_finalize        (GObject          *object);
67
68 static void           gl_merge_vcard_set_property    (GObject          *object,
69                                                       guint             param_id,
70                                                       const GValue     *value,
71                                                       GParamSpec       *pspec);
72
73 static void           gl_merge_vcard_get_property    (GObject          *object,
74                                                       guint             param_id,
75                                                       GValue           *value,
76                                                       GParamSpec       *pspec);
77
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,
84                                                       glMerge          *src_merge);
85 static char *         parse_next_vcard               (FILE             *fp);
86
87
88 \f
89 /*****************************************************************************/
90 /* Boilerplate object stuff.                                                 */
91 /*****************************************************************************/
92 G_DEFINE_TYPE (glMergeVCard, gl_merge_vcard, GL_TYPE_MERGE);
93
94 static void
95 gl_merge_vcard_class_init (glMergeVCardClass *class)
96 {
97         GObjectClass *object_class = G_OBJECT_CLASS (class);
98         glMergeClass *merge_class  = GL_MERGE_CLASS (class);
99
100         gl_debug (DEBUG_MERGE, "START");
101
102         gl_merge_vcard_parent_class = g_type_class_peek_parent (class);
103
104         object_class->set_property = gl_merge_vcard_set_property;
105         object_class->get_property = gl_merge_vcard_get_property;
106
107         object_class->finalize = gl_merge_vcard_finalize;
108
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;
115
116         gl_debug (DEBUG_MERGE, "END");
117 }
118
119 static void
120 gl_merge_vcard_init (glMergeVCard *merge_vcard)
121 {
122         gl_debug (DEBUG_MERGE, "START");
123
124         merge_vcard->priv = g_new0 (glMergeVCardPrivate, 1);
125
126         gl_debug (DEBUG_MERGE, "END");
127 }
128
129 static void
130 gl_merge_vcard_finalize (GObject *object)
131 {
132         glMergeVCard *merge_vcard = GL_MERGE_VCARD (object);
133
134         gl_debug (DEBUG_MERGE, "START");
135
136         g_return_if_fail (object && GL_IS_MERGE_VCARD (object));
137
138         g_free (merge_vcard->priv);
139
140         G_OBJECT_CLASS (gl_merge_vcard_parent_class)->finalize (object);
141
142         gl_debug (DEBUG_MERGE, "END");
143 }
144
145 /*--------------------------------------------------------------------------*/
146 /* Set argument.                                                            */
147 /*--------------------------------------------------------------------------*/
148 static void
149 gl_merge_vcard_set_property (GObject      *object,
150                              guint         param_id,
151                              const GValue *value,
152                              GParamSpec   *pspec)
153 {
154         glMergeVCard *merge_vcard;
155
156         merge_vcard = GL_MERGE_VCARD (object);
157
158         switch (param_id) {
159         default:
160                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
161                 break;
162         }
163 }
164
165 /*--------------------------------------------------------------------------*/
166 /* Get argument.                                                            */
167 /*--------------------------------------------------------------------------*/
168 static void
169 gl_merge_vcard_get_property (GObject     *object,
170                              guint        param_id,
171                              GValue      *value,
172                              GParamSpec  *pspec)
173 {
174         glMergeVCard *merge_vcard;
175
176         merge_vcard = GL_MERGE_VCARD (object);
177
178         switch (param_id) {
179         default:
180                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
181                 break;
182         }
183
184 }
185
186 /* TODO */
187 /*--------------------------------------------------------------------------*/
188 /* Get key list.                                                            */
189 /*--------------------------------------------------------------------------*/
190 static GList *
191 gl_merge_vcard_get_key_list (glMerge *merge)
192 {
193         glMergeVCard   *merge_vcard;
194         GList          *key_list;
195         
196         gl_debug (DEBUG_MERGE, "BEGIN");
197
198         merge_vcard = GL_MERGE_VCARD (merge);
199
200         /* extremely simple approach until I can list the available keys from the
201          * server, and return them. */
202         key_list = NULL;
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"));
206
207         gl_debug (DEBUG_MERGE, "END");
208
209         return key_list;
210 }
211
212 /* TODO? */
213 /*--------------------------------------------------------------------------*/
214 /* Get "primary" key.                                                       */
215 /*--------------------------------------------------------------------------*/
216 static gchar *
217 gl_merge_vcard_get_primary_key (glMerge *merge)
218 {
219         /* For now, let's always assume the full name is the primary key. */
220         return g_strdup ("full_name");
221 }
222
223 /*--------------------------------------------------------------------------*/
224 /* Open merge source.                                                       */
225 /*--------------------------------------------------------------------------*/
226 static void
227 gl_merge_vcard_open (glMerge *merge)
228 {
229         glMergeVCard *merge_vcard;
230         gchar        *src;
231
232         merge_vcard = GL_MERGE_VCARD (merge);
233
234         src = gl_merge_get_src (merge);
235
236         if (src != NULL) {
237                 merge_vcard->priv->fp = fopen (src, "r");
238         }
239
240         g_free (src);
241
242         return;
243 }
244
245 /*--------------------------------------------------------------------------*/
246 /* Close merge source.                                                      */
247 /*--------------------------------------------------------------------------*/
248 static void
249 gl_merge_vcard_close (glMerge *merge)
250 {
251         glMergeVCard *merge_vcard;
252
253         merge_vcard = GL_MERGE_VCARD (merge);
254
255         if (merge_vcard->priv->fp != NULL) {
256                 fclose (merge_vcard->priv->fp);
257                 merge_vcard->priv->fp = NULL;
258         }
259 }
260
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)
266 {
267         glMergeVCard  *merge_vcard;
268         glMergeRecord *record;
269         glMergeField  *field;
270
271         char *vcard;
272         EContact *contact;
273
274         merge_vcard = GL_MERGE_VCARD (merge);
275
276         vcard = parse_next_vcard(merge_vcard->priv->fp);
277         if (vcard == NULL || vcard[0] == '\0') {
278                 return NULL; /* EOF */
279         }
280         contact = e_contact_new_from_vcard(vcard);
281         if (contact == NULL) {
282                 return NULL; /* invalid vcard */
283         }
284
285         record = g_new0 (glMergeRecord, 1);
286         record->select_flag = TRUE;
287
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
290          * that contact */
291
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));
296
297         record->field_list = g_list_append (record->field_list, field);
298
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));
303
304         record->field_list = g_list_append (record->field_list, field);
305
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));
310
311         record->field_list = g_list_append (record->field_list, field);
312
313         /* free the contact */
314         g_object_unref (contact);
315         g_free(vcard);
316
317         return record;
318 }
319
320 /*---------------------------------------------------------------------------*/
321 /* Copy merge_vcard specific fields.                                         */
322 /*---------------------------------------------------------------------------*/
323 static void
324 gl_merge_vcard_copy (glMerge *dst_merge,
325                      glMerge *src_merge)
326 {
327         glMergeVCard *dst_merge_vcard;
328         glMergeVCard *src_merge_vcard;
329
330         dst_merge_vcard = GL_MERGE_VCARD (dst_merge);
331         src_merge_vcard = GL_MERGE_VCARD (src_merge);
332 }
333
334 /*---------------------------------------------------------------------------*/
335 /* PRIVATE: pull out a full VCard from the open file                         */
336 /* Arguments:                                                                */
337 /*  fp - an open stream to parse in put from                                 */
338 /* Returns:                                                                  */
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 /*---------------------------------------------------------------------------*/
342 static char * 
343 parse_next_vcard (FILE *fp)
344 {
345         gboolean  found_begin = FALSE;
346         gboolean  found_end = FALSE;
347         char     *vcard;
348         char      line[512];
349         int       size = 2048;
350         int       cursize = 0;
351
352         /* if no source has been set up, don't try to read from the file */
353         if (!fp) {
354                 return NULL;
355         }
356
357         vcard = g_malloc0(size);
358
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; }
362                 } else {
363                         if (g_str_has_prefix(line, "BEGIN:VCARD")) { found_begin = TRUE; } 
364                         else { continue; }/* skip lines not in a vcard */
365                 }
366
367                 /* if the buffer passed us isn't big enough, reallocate it */
368                 cursize += strlen(line);
369                 if (cursize >= size) {
370                         size *= 2;
371                         vcard = (char *)g_realloc(vcard, size); /* aborts program on error */
372                 }
373
374                 /* add the line (or portion thereof) to the vcard */
375                 strncat(vcard, line, size);
376         }
377
378         return vcard;
379 }
380
381
382
383 #endif /* HAVE_LIBEBOOK */