]> git.sur5r.net Git - glabels/blob - src/merge-vcard.c
Organized master branch to be top-level directory for glabels, instead of
[glabels] / src / merge-vcard.c
1 /*
2  *  merge-vcard.c
3  *  Copyright (C) 2001-2009  Jim Evins <evins@snaught.com>.
4  *  and
5  *  Copyright (C) 2005  Austin Henry <ahenry@users.sourceforge.net>
6  *
7  *  This file is part of gLabels.
8  *
9  *  gLabels is free software: you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation, either version 3 of the License, or
12  *  (at your option) any later version.
13  *
14  *  gLabels is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with gLabels.  If not, see <http://www.gnu.org/licenses/>.
21  */
22
23 #include <config.h>
24
25 #ifdef HAVE_LIBEBOOK
26
27
28 #include "merge-vcard.h"
29
30 #include <libebook/e-contact.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <errno.h>
34
35 #include "debug.h"
36
37
38 /*===========================================*/
39 /* Private types                             */
40 /*===========================================*/
41
42 struct _glMergeVCardPrivate {
43         FILE        *fp;
44 };
45
46 enum {
47         LAST_SIGNAL
48 };
49
50 enum {
51         ARG_0,
52 };
53
54
55 /*===========================================*/
56 /* Private globals                           */
57 /*===========================================*/
58
59
60 /*===========================================*/
61 /* Local function prototypes                 */
62 /*===========================================*/
63
64 static void           gl_merge_vcard_finalize        (GObject          *object);
65
66 static void           gl_merge_vcard_set_property    (GObject          *object,
67                                                       guint             param_id,
68                                                       const GValue     *value,
69                                                       GParamSpec       *pspec);
70
71 static void           gl_merge_vcard_get_property    (GObject          *object,
72                                                       guint             param_id,
73                                                       GValue           *value,
74                                                       GParamSpec       *pspec);
75
76 static GList         *gl_merge_vcard_get_key_list    (glMerge          *merge);
77 static gchar         *gl_merge_vcard_get_primary_key (glMerge          *merge);
78 static void           gl_merge_vcard_open            (glMerge          *merge);
79 static void           gl_merge_vcard_close           (glMerge          *merge);
80 static glMergeRecord *gl_merge_vcard_get_record      (glMerge          *merge);
81 static void           gl_merge_vcard_copy            (glMerge          *dst_merge,
82                                                       glMerge          *src_merge);
83 static char *         parse_next_vcard               (FILE             *fp);
84
85
86 /*****************************************************************************/
87 /* Boilerplate object stuff.                                                 */
88 /*****************************************************************************/
89 G_DEFINE_TYPE (glMergeVCard, gl_merge_vcard, GL_TYPE_MERGE);
90
91
92 static void
93 gl_merge_vcard_class_init (glMergeVCardClass *class)
94 {
95         GObjectClass *object_class = G_OBJECT_CLASS (class);
96         glMergeClass *merge_class  = GL_MERGE_CLASS (class);
97
98         gl_debug (DEBUG_MERGE, "START");
99
100         gl_merge_vcard_parent_class = g_type_class_peek_parent (class);
101
102         object_class->set_property = gl_merge_vcard_set_property;
103         object_class->get_property = gl_merge_vcard_get_property;
104
105         object_class->finalize = gl_merge_vcard_finalize;
106
107         merge_class->get_key_list    = gl_merge_vcard_get_key_list;
108         merge_class->get_primary_key = gl_merge_vcard_get_primary_key;
109         merge_class->open            = gl_merge_vcard_open;
110         merge_class->close           = gl_merge_vcard_close;
111         merge_class->get_record      = gl_merge_vcard_get_record;
112         merge_class->copy            = gl_merge_vcard_copy;
113
114         gl_debug (DEBUG_MERGE, "END");
115 }
116
117
118 static void
119 gl_merge_vcard_init (glMergeVCard *merge_vcard)
120 {
121         gl_debug (DEBUG_MERGE, "START");
122
123         merge_vcard->priv = g_new0 (glMergeVCardPrivate, 1);
124
125         gl_debug (DEBUG_MERGE, "END");
126 }
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 /*--------------------------------------------------------------------------*/
147 /* Set argument.                                                            */
148 /*--------------------------------------------------------------------------*/
149 static void
150 gl_merge_vcard_set_property (GObject      *object,
151                              guint         param_id,
152                              const GValue *value,
153                              GParamSpec   *pspec)
154 {
155         glMergeVCard *merge_vcard;
156
157         merge_vcard = GL_MERGE_VCARD (object);
158
159         switch (param_id) {
160         default:
161                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
162                 break;
163         }
164 }
165
166
167 /*--------------------------------------------------------------------------*/
168 /* Get argument.                                                            */
169 /*--------------------------------------------------------------------------*/
170 static void
171 gl_merge_vcard_get_property (GObject     *object,
172                              guint        param_id,
173                              GValue      *value,
174                              GParamSpec  *pspec)
175 {
176         glMergeVCard *merge_vcard;
177
178         merge_vcard = GL_MERGE_VCARD (object);
179
180         switch (param_id) {
181         default:
182                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
183                 break;
184         }
185
186 }
187
188
189 /*--------------------------------------------------------------------------*/
190 /* Get key list.                                                            */
191 /*--------------------------------------------------------------------------*/
192 static GList *
193 gl_merge_vcard_get_key_list (glMerge *merge)
194 {
195         glMergeVCard   *merge_vcard;
196         GList          *key_list;
197         
198         gl_debug (DEBUG_MERGE, "BEGIN");
199
200         merge_vcard = GL_MERGE_VCARD (merge);
201
202         /* extremely simple approach until I can list the available keys from the
203          * server, and return them. */
204         key_list = NULL;
205         key_list = g_list_append (key_list, g_strdup ("full_name"));
206         key_list = g_list_append (key_list, g_strdup ("home_address"));
207         key_list = g_list_append (key_list, g_strdup ("work_address"));
208
209         gl_debug (DEBUG_MERGE, "END");
210
211         return key_list;
212 }
213
214
215 /*--------------------------------------------------------------------------*/
216 /* Get "primary" key.                                                       */
217 /*--------------------------------------------------------------------------*/
218 static gchar *
219 gl_merge_vcard_get_primary_key (glMerge *merge)
220 {
221         /* For now, let's always assume the full name is the primary key. */
222         return g_strdup ("full_name");
223 }
224
225
226 /*--------------------------------------------------------------------------*/
227 /* Open merge source.                                                       */
228 /*--------------------------------------------------------------------------*/
229 static void
230 gl_merge_vcard_open (glMerge *merge)
231 {
232         glMergeVCard *merge_vcard;
233         gchar        *src;
234
235         merge_vcard = GL_MERGE_VCARD (merge);
236
237         src = gl_merge_get_src (merge);
238
239         if (src != NULL) {
240                 merge_vcard->priv->fp = fopen (src, "r");
241         }
242
243         g_free (src);
244
245         return;
246 }
247
248
249 /*--------------------------------------------------------------------------*/
250 /* Close merge source.                                                      */
251 /*--------------------------------------------------------------------------*/
252 static void
253 gl_merge_vcard_close (glMerge *merge)
254 {
255         glMergeVCard *merge_vcard;
256
257         merge_vcard = GL_MERGE_VCARD (merge);
258
259         if (merge_vcard->priv->fp != NULL) {
260                 fclose (merge_vcard->priv->fp);
261                 merge_vcard->priv->fp = NULL;
262         }
263 }
264
265
266 /*--------------------------------------------------------------------------*/
267 /* Get next record from merge source, NULL if no records left (i.e EOF)     */
268 /*--------------------------------------------------------------------------*/
269 static glMergeRecord *
270 gl_merge_vcard_get_record (glMerge *merge)
271 {
272         glMergeVCard  *merge_vcard;
273         glMergeRecord *record;
274         glMergeField  *field;
275
276         char *vcard;
277         EContact *contact;
278
279         merge_vcard = GL_MERGE_VCARD (merge);
280
281         vcard = parse_next_vcard(merge_vcard->priv->fp);
282         if (vcard == NULL || vcard[0] == '\0') {
283                 return NULL; /* EOF */
284         }
285         contact = e_contact_new_from_vcard(vcard);
286         if (contact == NULL) {
287                 return NULL; /* invalid vcard */
288         }
289
290         record = g_new0 (glMergeRecord, 1);
291         record->select_flag = TRUE;
292
293         /* Take the interesting fields one by one from the contact, and put them
294          * into the glMergeRecord structure. When done, free up the resources for
295          * that contact */
296
297         /* get the full name */
298         field = g_new0 (glMergeField, 1);
299         field->key = g_strdup ("full_name");
300         field->value = g_strdup (e_contact_get_const(contact, E_CONTACT_FULL_NAME));
301
302         record->field_list = g_list_append (record->field_list, field);
303
304         /* get the home address */
305         field = g_new0 (glMergeField, 1);
306         field->key = g_strdup ("home_address");
307         field->value = g_strdup (e_contact_get_const(contact, E_CONTACT_ADDRESS_LABEL_HOME));
308
309         record->field_list = g_list_append (record->field_list, field);
310
311         /* get the work address */
312         field = g_new0 (glMergeField, 1);
313         field->key = g_strdup ("work_address");
314         field->value = g_strdup (e_contact_get_const(contact, E_CONTACT_ADDRESS_LABEL_WORK));
315
316         record->field_list = g_list_append (record->field_list, field);
317
318         /* free the contact */
319         g_object_unref (contact);
320         g_free(vcard);
321
322         return record;
323 }
324
325
326 /*---------------------------------------------------------------------------*/
327 /* Copy merge_vcard specific fields.                                         */
328 /*---------------------------------------------------------------------------*/
329 static void
330 gl_merge_vcard_copy (glMerge *dst_merge,
331                      glMerge *src_merge)
332 {
333         glMergeVCard *dst_merge_vcard;
334         glMergeVCard *src_merge_vcard;
335
336         dst_merge_vcard = GL_MERGE_VCARD (dst_merge);
337         src_merge_vcard = GL_MERGE_VCARD (src_merge);
338 }
339
340
341 /*---------------------------------------------------------------------------*/
342 /* PRIVATE: pull out a full VCard from the open file                         */
343 /* Arguments:                                                                */
344 /*  fp - an open stream to parse in put from                                 */
345 /* Returns:                                                                  */
346 /*  a pointer to the buffer containing the vcard, the empty string on        */
347 /*  end-of-file or error, this buffer needs to be free by the caller         */
348 /*---------------------------------------------------------------------------*/
349 static char * 
350 parse_next_vcard (FILE *fp)
351 {
352         gboolean  found_begin = FALSE;
353         gboolean  found_end = FALSE;
354         char     *vcard;
355         char      line[512];
356         int       size = 2048;
357         int       cursize = 0;
358
359         /* if no source has been set up, don't try to read from the file */
360         if (!fp) {
361                 return NULL;
362         }
363
364         vcard = g_malloc0(size);
365
366         while (fgets(line, sizeof(line), fp) && found_end == FALSE) {
367                 if (found_begin == TRUE) {
368                         if (g_str_has_prefix(line, "END:VCARD")) { found_end = TRUE; }
369                 } else {
370                         if (g_str_has_prefix(line, "BEGIN:VCARD")) { found_begin = TRUE; } 
371                         else { continue; }/* skip lines not in a vcard */
372                 }
373
374                 /* if the buffer passed us isn't big enough, reallocate it */
375                 cursize += strlen(line);
376                 if (cursize >= size) {
377                         size *= 2;
378                         vcard = (char *)g_realloc(vcard, size); /* aborts program on error */
379                 }
380
381                 /* add the line (or portion thereof) to the vcard */
382                 strncat(vcard, line, size);
383         }
384
385         return vcard;
386 }
387
388
389
390 #endif /* HAVE_LIBEBOOK */
391
392
393
394 /*
395  * Local Variables:       -- emacs
396  * mode: C                -- emacs
397  * c-basic-offset: 8      -- emacs
398  * tab-width: 8           -- emacs
399  * indent-tabs-mode: nil  -- emacs
400  * End:                   -- emacs
401  */