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 * Gilbert Fang <gilbert.fang@sun.com>
18 *
19 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
20 *
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <sys/types.h>
30 #include <unistd.h>
31
32 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
34
35 #include <libebook/libebook.h>
36
37 #include "evolution-addressbook-export.h"
38
39 #define COMMA_SEPARATOR ","
40
41 typedef enum _CARD_FORMAT CARD_FORMAT;
42 typedef enum _DeliveryAddressField DeliveryAddressField;
43 typedef enum _EContactFieldCSV EContactFieldCSV;
44 typedef struct _EContactCSVFieldData EContactCSVFieldData;
45
46 enum _CARD_FORMAT
47 {
48 CARD_FORMAT_CSV,
49 CARD_FORMAT_VCARD
50 };
51
52 enum _DeliveryAddressField
53 {
54 DELIVERY_ADDRESS_STREET,
55 DELIVERY_ADDRESS_EXT,
56 DELIVERY_ADDRESS_LOCALITY,
57 DELIVERY_ADDRESS_REGION,
58 DELIVERY_ADDRESS_CODE,
59 DELIVERY_ADDRESS_COUNTRY
60 };
61
62 enum _EContactFieldCSV
63 {
64 E_CONTACT_CSV_FILE_AS,
65 E_CONTACT_CSV_FULL_NAME,
66 E_CONTACT_CSV_EMAIL_1,
67 E_CONTACT_CSV_EMAIL_2,
68 E_CONTACT_CSV_EMAIL_3,
69 E_CONTACT_CSV_EMAIL_4,
70 E_CONTACT_CSV_PHONE_PRIMARY,
71 E_CONTACT_CSV_PHONE_ASSISTANT,
72 E_CONTACT_CSV_PHONE_BUSINESS,
73 E_CONTACT_CSV_PHONE_CALLBACK,
74 E_CONTACT_CSV_PHONE_COMPANY,
75 E_CONTACT_CSV_PHONE_HOME,
76 E_CONTACT_CSV_ORG,
77 /*E_CONTACT_CSV_ADDRESS_BUSINESS, */
78 E_CONTACT_CSV_ADDRESS_BUSINESS_STREET,
79 E_CONTACT_CSV_ADDRESS_BUSINESS_EXT,
80 E_CONTACT_CSV_ADDRESS_BUSINESS_CITY,
81 E_CONTACT_CSV_ADDRESS_BUSINESS_REGION,
82 E_CONTACT_CSV_ADDRESS_BUSINESS_POSTCODE,
83 E_CONTACT_CSV_ADDRESS_BUSINESS_COUNTRY,
84 /*E_CONTACT_CSV_ADDRESS_HOME, */
85 E_CONTACT_CSV_ADDRESS_HOME_STREET,
86 E_CONTACT_CSV_ADDRESS_HOME_EXT,
87 E_CONTACT_CSV_ADDRESS_HOME_CITY,
88 E_CONTACT_CSV_ADDRESS_HOME_REGION,
89 E_CONTACT_CSV_ADDRESS_HOME_POSTCODE,
90 E_CONTACT_CSV_ADDRESS_HOME_COUNTRY,
91 E_CONTACT_CSV_PHONE_MOBILE,
92 E_CONTACT_CSV_PHONE_CAR,
93 E_CONTACT_CSV_PHONE_BUSINESS_FAX,
94 E_CONTACT_CSV_PHONE_HOME_FAX,
95 E_CONTACT_CSV_PHONE_BUSINESS_2,
96 E_CONTACT_CSV_PHONE_HOME_2,
97 E_CONTACT_CSV_PHONE_ISDN,
98 E_CONTACT_CSV_PHONE_OTHER,
99 E_CONTACT_CSV_PHONE_OTHER_FAX,
100 E_CONTACT_CSV_PHONE_PAGER,
101 E_CONTACT_CSV_PHONE_RADIO,
102 E_CONTACT_CSV_PHONE_TELEX,
103 E_CONTACT_CSV_PHONE_TTYTDD,
104 /*E_CONTACT_CSV_ADDRESS_OTHER, */
105 E_CONTACT_CSV_ADDRESS_OTHER_STREET,
106 E_CONTACT_CSV_ADDRESS_OTHER_EXT,
107 E_CONTACT_CSV_ADDRESS_OTHER_CITY,
108 E_CONTACT_CSV_ADDRESS_OTHER_REGION,
109 E_CONTACT_CSV_ADDRESS_OTHER_POSTCODE,
110 E_CONTACT_CSV_ADDRESS_OTHER_COUNTRY,
111 E_CONTACT_CSV_HOMEPAGE_URL,
112 E_CONTACT_CSV_ORG_UNIT,
113 E_CONTACT_CSV_OFFICE,
114 E_CONTACT_CSV_TITLE,
115 E_CONTACT_CSV_ROLE,
116 E_CONTACT_CSV_MANAGER,
117 E_CONTACT_CSV_ASSISTANT,
118 E_CONTACT_CSV_NICKNAME,
119 E_CONTACT_CSV_SPOUSE,
120 E_CONTACT_CSV_NOTE,
121 E_CONTACT_CSV_CALENDAR_URI,
122 E_CONTACT_CSV_FREEBUSY_URL,
123 /*E_CONTACT_CSV_ANNIVERSARY, */
124 E_CONTACT_CSV_ANNIVERSARY_YEAR,
125 E_CONTACT_CSV_ANNIVERSARY_MONTH,
126 E_CONTACT_CSV_ANNIVERSARY_DAY,
127 /*E_CONTACT_CSV_BIRTH_DATE, */
128 E_CONTACT_CSV_BIRTH_DATE_YEAR,
129 E_CONTACT_CSV_BIRTH_DATE_MONTH,
130 E_CONTACT_CSV_BIRTH_DATE_DAY,
131 E_CONTACT_CSV_MAILER,
132 E_CONTACT_CSV_NAME_OR_ORG,
133 E_CONTACT_CSV_CATEGORIES,
134 E_CONTACT_CSV_FAMILY_NAME,
135 E_CONTACT_CSV_GIVEN_NAME,
136 E_CONTACT_CSV_WANTS_HTML,
137 E_CONTACT_CSV_IS_LIST,
138 E_CONTACT_CSV_LAST
139 };
140
141 typedef enum {
142 DT_STRING,
143 DT_BOOLEAN
144 } EContactCSVDataType;
145
146 struct _EContactCSVFieldData
147 {
148 gint csv_field;
149 gint contact_field;
150 const gchar *csv_name;
151 EContactCSVDataType data_type;
152 };
153
154 #define NOMAP -1
155 static EContactCSVFieldData csv_field_data[] = {
156 {E_CONTACT_CSV_FILE_AS, E_CONTACT_FILE_AS, "", DT_STRING},
157 {E_CONTACT_CSV_FULL_NAME, E_CONTACT_CSV_FULL_NAME, "", DT_STRING},
158 {E_CONTACT_CSV_EMAIL_1, E_CONTACT_EMAIL_1, "", DT_STRING},
159 {E_CONTACT_CSV_EMAIL_2, E_CONTACT_EMAIL_2, "", DT_STRING},
160 {E_CONTACT_CSV_EMAIL_3, E_CONTACT_EMAIL_3, "", DT_STRING},
161 {E_CONTACT_CSV_EMAIL_4, E_CONTACT_EMAIL_4, "", DT_STRING},
162 {E_CONTACT_CSV_PHONE_PRIMARY, E_CONTACT_PHONE_PRIMARY, "", DT_STRING},
163 {E_CONTACT_CSV_PHONE_ASSISTANT, E_CONTACT_PHONE_ASSISTANT, "", DT_STRING},
164 {E_CONTACT_CSV_PHONE_BUSINESS, E_CONTACT_PHONE_BUSINESS, "", DT_STRING},
165 {E_CONTACT_CSV_PHONE_CALLBACK, E_CONTACT_PHONE_CALLBACK, "", DT_STRING},
166 {E_CONTACT_CSV_PHONE_COMPANY, E_CONTACT_PHONE_COMPANY, "", DT_STRING},
167 {E_CONTACT_CSV_PHONE_HOME, E_CONTACT_PHONE_HOME, "", DT_STRING},
168 {E_CONTACT_CSV_ORG, E_CONTACT_ORG, "", DT_STRING},
169 /*E_CONTACT_CSV_ADDRESS_BUSINESS, */
170 {E_CONTACT_CSV_ADDRESS_BUSINESS_STREET, NOMAP, "Business Address", DT_STRING},
171 {E_CONTACT_CSV_ADDRESS_BUSINESS_EXT, NOMAP, "Business Address2", DT_STRING},
172 {E_CONTACT_CSV_ADDRESS_BUSINESS_CITY, NOMAP, "Business Address City", DT_STRING},
173 {E_CONTACT_CSV_ADDRESS_BUSINESS_REGION, NOMAP, "Business Address State", DT_STRING},
174 {E_CONTACT_CSV_ADDRESS_BUSINESS_POSTCODE, NOMAP, "Business Address PostCode", DT_STRING},
175 {E_CONTACT_CSV_ADDRESS_BUSINESS_COUNTRY, NOMAP, "Business Address Country", DT_STRING},
176 /*E_CONTACT_CSV_ADDRESS_HOME, */
177 {E_CONTACT_CSV_ADDRESS_HOME_STREET, NOMAP, "Home Address", DT_STRING},
178 {E_CONTACT_CSV_ADDRESS_HOME_EXT, NOMAP, "Home Address2", DT_STRING},
179 {E_CONTACT_CSV_ADDRESS_HOME_CITY, NOMAP, "Home Address City", DT_STRING},
180 {E_CONTACT_CSV_ADDRESS_HOME_REGION, NOMAP, "Home Address State", DT_STRING},
181 {E_CONTACT_CSV_ADDRESS_HOME_POSTCODE, NOMAP, "Home Address PostCode", DT_STRING},
182 {E_CONTACT_CSV_ADDRESS_HOME_COUNTRY, NOMAP, "Home Address Country", DT_STRING},
183 {E_CONTACT_CSV_PHONE_MOBILE, E_CONTACT_PHONE_MOBILE, "", DT_STRING},
184 {E_CONTACT_CSV_PHONE_CAR, E_CONTACT_PHONE_CAR, "", DT_STRING},
185 {E_CONTACT_CSV_PHONE_BUSINESS_FAX, E_CONTACT_PHONE_BUSINESS_FAX, "", DT_STRING},
186 {E_CONTACT_CSV_PHONE_HOME_FAX, E_CONTACT_PHONE_HOME_FAX, "", DT_STRING},
187 {E_CONTACT_CSV_PHONE_BUSINESS_2, E_CONTACT_PHONE_BUSINESS_2, "", DT_STRING},
188 {E_CONTACT_CSV_PHONE_HOME_2, E_CONTACT_PHONE_HOME_2, "", DT_STRING},
189 {E_CONTACT_CSV_PHONE_ISDN, E_CONTACT_PHONE_ISDN, "", DT_STRING},
190 {E_CONTACT_CSV_PHONE_OTHER, E_CONTACT_PHONE_OTHER, "", DT_STRING},
191 {E_CONTACT_CSV_PHONE_OTHER_FAX, E_CONTACT_PHONE_OTHER_FAX, "", DT_STRING},
192 {E_CONTACT_CSV_PHONE_PAGER, E_CONTACT_PHONE_PAGER, "", DT_STRING},
193 {E_CONTACT_CSV_PHONE_RADIO, E_CONTACT_PHONE_RADIO, "", DT_STRING},
194 {E_CONTACT_CSV_PHONE_TELEX, E_CONTACT_PHONE_TELEX, "", DT_STRING},
195 {E_CONTACT_CSV_PHONE_TTYTDD, E_CONTACT_PHONE_TTYTDD, "", DT_STRING},
196 /*E_CONTACT_CSV_ADDRESS_OTHER, */
197 {E_CONTACT_CSV_ADDRESS_OTHER_STREET, NOMAP, "Other Address", DT_STRING},
198 {E_CONTACT_CSV_ADDRESS_OTHER_EXT, NOMAP, "Other Address2", DT_STRING},
199 {E_CONTACT_CSV_ADDRESS_OTHER_CITY, NOMAP, "Other Address City", DT_STRING},
200 {E_CONTACT_CSV_ADDRESS_OTHER_REGION, NOMAP, "Other Address State", DT_STRING},
201 {E_CONTACT_CSV_ADDRESS_OTHER_POSTCODE, NOMAP, "Other Address PostCode", DT_STRING},
202 {E_CONTACT_CSV_ADDRESS_OTHER_COUNTRY, NOMAP, "Other Address Country", DT_STRING},
203 {E_CONTACT_CSV_HOMEPAGE_URL, E_CONTACT_HOMEPAGE_URL, "", DT_STRING},
204 {E_CONTACT_CSV_ORG_UNIT, E_CONTACT_ORG_UNIT, "", DT_STRING},
205 {E_CONTACT_CSV_OFFICE, E_CONTACT_OFFICE, "", DT_STRING},
206 {E_CONTACT_CSV_TITLE, E_CONTACT_TITLE, "", DT_STRING},
207 {E_CONTACT_CSV_ROLE, E_CONTACT_ROLE, "", DT_STRING},
208 {E_CONTACT_CSV_MANAGER, E_CONTACT_MANAGER, "", DT_STRING},
209 {E_CONTACT_CSV_ASSISTANT, E_CONTACT_ASSISTANT, "", DT_STRING},
210 {E_CONTACT_CSV_NICKNAME, E_CONTACT_NICKNAME, "", DT_STRING},
211 {E_CONTACT_CSV_SPOUSE, E_CONTACT_SPOUSE, "", DT_STRING},
212 {E_CONTACT_CSV_NOTE, E_CONTACT_NOTE, "", DT_STRING},
213 {E_CONTACT_CSV_CALENDAR_URI, E_CONTACT_CALENDAR_URI, "", DT_STRING},
214 {E_CONTACT_CSV_FREEBUSY_URL, E_CONTACT_FREEBUSY_URL, "", DT_STRING},
215 /*E_CONTACT_ANNIVERSARY, */
216 {E_CONTACT_CSV_ANNIVERSARY_YEAR, NOMAP, "Anniversary Year", DT_STRING},
217 {E_CONTACT_CSV_ANNIVERSARY_MONTH, NOMAP, "Anniversary Month", DT_STRING},
218 {E_CONTACT_CSV_ANNIVERSARY_DAY, NOMAP, "Anniversary Day", DT_STRING},
219 /*E_CONTACT_BIRTH_DATE, */
220 {E_CONTACT_CSV_BIRTH_DATE_YEAR, NOMAP, "Birth Year", DT_STRING},
221 {E_CONTACT_CSV_BIRTH_DATE_MONTH, NOMAP, "Birth Month", DT_STRING},
222 {E_CONTACT_CSV_BIRTH_DATE_DAY, NOMAP, "Birth Day", DT_STRING},
223 {E_CONTACT_CSV_MAILER, E_CONTACT_MAILER, "", DT_STRING},
224 {E_CONTACT_CSV_NAME_OR_ORG, E_CONTACT_NAME_OR_ORG, "", DT_STRING},
225 {E_CONTACT_CSV_CATEGORIES, E_CONTACT_CATEGORIES, "", DT_STRING},
226 {E_CONTACT_CSV_FAMILY_NAME, E_CONTACT_FAMILY_NAME, "", DT_STRING},
227 {E_CONTACT_CSV_GIVEN_NAME, E_CONTACT_GIVEN_NAME, "", DT_STRING},
228 {E_CONTACT_CSV_WANTS_HTML, E_CONTACT_WANTS_HTML, "", DT_BOOLEAN},
229 {E_CONTACT_CSV_IS_LIST, E_CONTACT_IS_LIST, "", DT_BOOLEAN},
230 {E_CONTACT_CSV_LAST, NOMAP, "", DT_STRING}
231
232 };
233
234 static GSList *pre_defined_fields;
235
236 /*function prototypes*/
237 gint e_contact_csv_get_contact_field (EContactFieldCSV csv_field);
238 gchar *e_contact_csv_get_name (EContactFieldCSV csv_field);
239 gchar *e_contact_csv_get (EContact * contact, EContactFieldCSV csv_field);
240 gchar *e_contact_csv_get_header_line (GSList * csv_all_fields);
241 gchar *e_contact_to_csv (EContact * contact, GSList * csv_all_fields);
242 gchar *e_contact_get_csv (EContact * contact, GSList * csv_all_fields);
243 gchar *delivery_address_get_sub_field (const EContactAddress * delivery_address, DeliveryAddressField sub_field);
244 gchar *check_null_pointer (gchar * orig);
245 gchar *escape_string (gchar * orig);
246 gint output_n_cards_file (FILE * outputfile, GSList *contacts, gint size, gint begin_no, CARD_FORMAT format);
247 static void fork_to_background (void);
248 void set_pre_defined_field (GSList ** pre_defined_fields);
249
250 /* function declarations*/
251 gint
252 e_contact_csv_get_contact_field (EContactFieldCSV csv_field)
253 {
254 return csv_field_data[csv_field].contact_field;
255 }
256
257 static EContactCSVDataType
258 e_contact_csv_get_data_type (EContactFieldCSV csv_field)
259 {
260 return csv_field_data[csv_field].data_type;
261 }
262
263 gchar *
264 e_contact_csv_get_name (EContactFieldCSV csv_field)
265 {
266 gint contact_field;
267 gchar *name;
268 gchar *quoted_name;
269
270 contact_field = e_contact_csv_get_contact_field (csv_field);
271
272 if (contact_field != NOMAP) {
273 name = g_strdup (e_contact_field_name (contact_field));
274 } else {
275 name = g_strdup (csv_field_data[csv_field].csv_name);
276 }
277 quoted_name = escape_string (name);
278 g_free (name);
279 return quoted_name;
280 }
281
282 gchar *
283 e_contact_csv_get (EContact *contact,
284 EContactFieldCSV csv_field)
285 {
286 gint contact_field;
287 gchar *field_value;
288 gchar *quoted_field_value;
289
290 EContactAddress *delivery_address = NULL;
291 EContactDate *date;
292
293 contact_field = e_contact_csv_get_contact_field (csv_field);
294
295 if (contact_field != NOMAP) {
296 field_value = e_contact_get (contact, contact_field);
297 if (e_contact_csv_get_data_type (csv_field) == DT_BOOLEAN) {
298 field_value = g_strdup ((GPOINTER_TO_INT (field_value)) ? "TRUE" : "FALSE");
299 }
300 } else {
301 switch (csv_field) {
302 case E_CONTACT_CSV_ADDRESS_HOME_STREET:
303 delivery_address = e_contact_get (contact, E_CONTACT_ADDRESS_HOME);
304 field_value = delivery_address_get_sub_field (delivery_address, DELIVERY_ADDRESS_STREET);
305 break;
306 case E_CONTACT_CSV_ADDRESS_HOME_EXT:
307 delivery_address = e_contact_get (contact, E_CONTACT_ADDRESS_HOME);
308 field_value = delivery_address_get_sub_field (delivery_address, DELIVERY_ADDRESS_EXT);
309 break;
310 case E_CONTACT_CSV_ADDRESS_HOME_CITY:
311 delivery_address = e_contact_get (contact, E_CONTACT_ADDRESS_HOME);
312 field_value = delivery_address_get_sub_field (delivery_address, DELIVERY_ADDRESS_LOCALITY);
313 break;
314 case E_CONTACT_CSV_ADDRESS_HOME_REGION:
315 delivery_address = e_contact_get (contact, E_CONTACT_ADDRESS_HOME);
316 field_value = delivery_address_get_sub_field (delivery_address, DELIVERY_ADDRESS_REGION);
317 break;
318 case E_CONTACT_CSV_ADDRESS_HOME_POSTCODE:
319 delivery_address = e_contact_get (contact, E_CONTACT_ADDRESS_HOME);
320 field_value = delivery_address_get_sub_field (delivery_address, DELIVERY_ADDRESS_CODE);
321 break;
322 case E_CONTACT_CSV_ADDRESS_HOME_COUNTRY:
323 delivery_address = e_contact_get (contact, E_CONTACT_ADDRESS_HOME);
324 field_value = delivery_address_get_sub_field (delivery_address, DELIVERY_ADDRESS_COUNTRY);
325 break;
326 case E_CONTACT_CSV_ADDRESS_BUSINESS_STREET:
327 delivery_address = e_contact_get (contact, E_CONTACT_ADDRESS_WORK);
328 field_value = delivery_address_get_sub_field (delivery_address, DELIVERY_ADDRESS_STREET);
329 break;
330 case E_CONTACT_CSV_ADDRESS_BUSINESS_EXT:
331 delivery_address = e_contact_get (contact, E_CONTACT_ADDRESS_WORK);
332 field_value = delivery_address_get_sub_field (delivery_address, DELIVERY_ADDRESS_EXT);
333 break;
334 case E_CONTACT_CSV_ADDRESS_BUSINESS_CITY:
335 delivery_address = e_contact_get (contact, E_CONTACT_ADDRESS_WORK);
336 field_value = delivery_address_get_sub_field (delivery_address, DELIVERY_ADDRESS_LOCALITY);
337 break;
338 case E_CONTACT_CSV_ADDRESS_BUSINESS_REGION:
339 delivery_address = e_contact_get (contact, E_CONTACT_ADDRESS_WORK);
340 field_value = delivery_address_get_sub_field (delivery_address, DELIVERY_ADDRESS_REGION);
341 break;
342 case E_CONTACT_CSV_ADDRESS_BUSINESS_POSTCODE:
343 delivery_address = e_contact_get (contact, E_CONTACT_ADDRESS_WORK);
344 field_value = delivery_address_get_sub_field (delivery_address, DELIVERY_ADDRESS_CODE);
345 break;
346 case E_CONTACT_CSV_ADDRESS_BUSINESS_COUNTRY:
347 delivery_address = e_contact_get (contact, E_CONTACT_ADDRESS_WORK);
348 field_value = delivery_address_get_sub_field (delivery_address, DELIVERY_ADDRESS_COUNTRY);
349 break;
350 case E_CONTACT_CSV_BIRTH_DATE_YEAR:
351 date = e_contact_get (contact, E_CONTACT_BIRTH_DATE);
352 if (date) {
353 field_value = g_strdup_printf ("%04d", date->year);
354 e_contact_date_free (date);
355 }
356 else {
357 field_value = g_strdup ("");
358 }
359 break;
360
361 case E_CONTACT_CSV_BIRTH_DATE_MONTH:
362 date = e_contact_get (contact, E_CONTACT_BIRTH_DATE);
363 if (date) {
364 field_value = g_strdup_printf ("%04d", date->month);
365 e_contact_date_free (date);
366 }
367 else {
368 field_value = g_strdup ("");
369 }
370 break;
371
372 case E_CONTACT_CSV_BIRTH_DATE_DAY:
373 date = e_contact_get (contact, E_CONTACT_BIRTH_DATE);
374 if (date) {
375 field_value = g_strdup_printf ("%04d", date->day);
376 e_contact_date_free (date);
377 }
378 else {
379 field_value = g_strdup ("");
380 }
381 break;
382
383 default:
384 field_value = g_strdup ("");
385 }
386 }
387
388 /*checking to avoid the NULL pointer */
389 if (field_value == NULL)
390 field_value = g_strdup ("");
391
392 quoted_field_value = escape_string (field_value);
393 g_free (field_value);
394
395 if (delivery_address)
396 e_contact_address_free (delivery_address);
397
398 return quoted_field_value;
399 }
400
401 gchar *
402 e_contact_csv_get_header_line (GSList *csv_all_fields)
403 {
404
405 guint field_number;
406 gint csv_field;
407 gchar **field_name_array;
408 gchar *header_line;
409
410 gint loop_counter;
411
412 field_number = g_slist_length (csv_all_fields);
413 field_name_array = g_new0 (gchar *, field_number + 1);
414
415 for (loop_counter = 0; loop_counter < field_number; loop_counter++) {
416 csv_field = GPOINTER_TO_INT (g_slist_nth_data (csv_all_fields, loop_counter));
417 *(field_name_array + loop_counter) = e_contact_csv_get_name (csv_field);
418 }
419
420 header_line = g_strjoinv (COMMA_SEPARATOR, field_name_array);
421
422 for (loop_counter = 0; loop_counter < field_number; loop_counter++) {
423 g_free (*(field_name_array + loop_counter));
424 }
425 g_free (field_name_array);
426
427 return header_line;
428
429 }
430
431 gchar *
432 e_contact_to_csv (EContact *contact,
433 GSList *csv_all_fields)
434 {
435 guint field_number;
436 gint csv_field;
437 gchar **field_value_array;
438 gchar *aline;
439
440 gint loop_counter;
441
442 field_number = g_slist_length (csv_all_fields);
443 field_value_array = g_new0 (gchar *, field_number + 1);
444
445 for (loop_counter = 0; loop_counter < field_number; loop_counter++) {
446 csv_field = GPOINTER_TO_INT (g_slist_nth_data (csv_all_fields, loop_counter));
447 *(field_value_array + loop_counter) = e_contact_csv_get (contact, csv_field);
448 }
449
450 aline = g_strjoinv (COMMA_SEPARATOR, field_value_array);
451
452 for (loop_counter = 0; loop_counter < field_number; loop_counter++) {
453 g_free (*(field_value_array + loop_counter));
454 }
455 g_free (field_value_array);
456
457 return aline;
458
459 }
460
461 gchar *
462 e_contact_get_csv (EContact *contact,
463 GSList *csv_all_fields)
464 {
465 gchar *aline;
466
467 aline = e_contact_to_csv (contact, csv_all_fields);
468 return aline;
469 }
470
471 gchar *
472 check_null_pointer (gchar *orig)
473 {
474 gchar *result;
475 if (orig == NULL)
476 result = g_strdup ("");
477 else
478 result = g_strdup (orig);
479 return result;
480 }
481
482 gchar *
483 delivery_address_get_sub_field (const EContactAddress *address,
484 DeliveryAddressField sub_field)
485 {
486 gchar *sub_field_value;
487 gchar *str_temp, *str_temp_a;
488 if (address != NULL) {
489 switch (sub_field) {
490 case DELIVERY_ADDRESS_STREET:
491 str_temp_a = check_null_pointer (address->po);
492 str_temp = check_null_pointer (address->street);
493 sub_field_value = g_strdup_printf ("%s %s", str_temp_a, str_temp);
494 g_free (str_temp);
495 g_free (str_temp_a);
496 break;
497 case DELIVERY_ADDRESS_EXT:
498 sub_field_value = check_null_pointer (address->ext);
499 break;
500 case DELIVERY_ADDRESS_LOCALITY:
501 sub_field_value = check_null_pointer (address->locality);
502 break;
503 case DELIVERY_ADDRESS_REGION:
504 sub_field_value = check_null_pointer (address->region);
505 break;
506 case DELIVERY_ADDRESS_CODE:
507 sub_field_value = check_null_pointer (address->code);
508 break;
509 case DELIVERY_ADDRESS_COUNTRY:
510 sub_field_value = check_null_pointer (address->country);
511 break;
512 default:
513 sub_field_value = g_strdup ("");
514 }
515 } else {
516 sub_field_value = g_strdup ("");
517 }
518 return sub_field_value;
519 }
520
521 gchar *
522 escape_string (gchar *orig)
523 {
524 const guchar *p;
525 gchar *dest;
526 gchar *q;
527
528 if (orig == NULL)
529 return g_strdup ("\"\"");
530
531 p = (guchar *) orig;
532 /* Each source byte needs maximally two destination chars (\n), and the extra 2 is for the leading and trailing '"' */
533 q = dest = g_malloc (strlen (orig) * 2 + 1 + 2);
534
535 *q++ = '\"';
536 while (*p)
537 {
538 switch (*p)
539 {
540 case '\n':
541 *q++ = '\\';
542 *q++ = 'n';
543 break;
544 case '\r':
545 *q++ = '\\';
546 *q++ = 'r';
547 break;
548 case '\\':
549 *q++ = '\\';
550 *q++ = '\\';
551 break;
552 case '"':
553 *q++ = '"';
554 *q++ = '"';
555 break;
556 default:
557 *q++ = *p;
558 }
559 p++;
560 }
561
562 *q++ = '\"';
563 *q = 0;
564
565 return dest;
566 }
567
568 gint
569 output_n_cards_file (FILE *outputfile,
570 GSList *contacts,
571 gint size,
572 gint begin_no,
573 CARD_FORMAT format)
574 {
575 gint i;
576 if (format == CARD_FORMAT_VCARD) {
577 for (i = begin_no; i < size + begin_no; i++) {
578 EContact *contact = g_slist_nth_data (contacts, i);
579 gchar *vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
580 fprintf (outputfile, "%s\n", vcard);
581 g_free (vcard);
582 }
583 } else if (format == CARD_FORMAT_CSV) {
584 gchar *csv_fields_name;
585
586 if (!pre_defined_fields)
587 set_pre_defined_field (&pre_defined_fields);
588
589 csv_fields_name = e_contact_csv_get_header_line (pre_defined_fields);
590 fprintf (outputfile, "%s\n", csv_fields_name);
591 g_free (csv_fields_name);
592
593 for (i = begin_no; i < size + begin_no; i++) {
594 EContact *contact = g_slist_nth_data (contacts, i);
595 gchar *csv = e_contact_get_csv (contact, pre_defined_fields);
596 fprintf (outputfile, "%s\n", csv);
597 g_free (csv);
598 }
599 }
600
601 return SUCCESS;
602
603 }
604
605 static void
606 fork_to_background (void)
607 {
608 #ifndef G_OS_WIN32
609 pid_t pid;
610 pid = fork ();
611 if (pid == -1) {
612 /* ouch, fork() failed */
613 perror ("fork");
614 exit (-1);
615 } else if (pid == 0) {
616 /* child */
617 /*contunue */
618
619 } else {
620 /* parent exit, note the use of _exit() instead of exit() */
621 _exit (-1);
622 }
623 #endif
624 }
625
626 static void
627 action_list_cards (GSList *contacts,
628 ActionContext *p_actctx)
629 {
630 FILE *outputfile;
631 long length;
632 gint IsFirstOne;
633 gint series_no;
634 gchar *file_series_name;
635 CARD_FORMAT format;
636 gint size;
637
638 length = g_slist_length (contacts);
639
640 if (length <= 0) {
641 g_warning ("Couldn't load addressbook correctly!!!! %s####", p_actctx->action_list_cards.addressbook_source_uid ?
642 p_actctx->action_list_cards.addressbook_source_uid : "NULL");
643 exit (-1);
644 }
645
646 if (p_actctx->action_list_cards.async_mode == FALSE) { /* normal mode */
647
648 if (p_actctx->action_list_cards.output_file == NULL) {
649 outputfile = stdout;
650 } else {
651 /* fopen output file */
652 if (!(outputfile = g_fopen (p_actctx->action_list_cards.output_file, "w"))) {
653 g_warning (_("Can not open file"));
654 exit (-1);
655 }
656 }
657
658 if (p_actctx->action_list_cards.IsVCard == TRUE)
659 format = CARD_FORMAT_VCARD;
660 else
661 format = CARD_FORMAT_CSV;
662
663 output_n_cards_file (outputfile, contacts, length, 0, format);
664
665 if (p_actctx->action_list_cards.output_file != NULL) {
666 fclose (outputfile);
667 }
668 }
669
670 /*async mode */
671 else {
672
673 size = p_actctx->action_list_cards.file_size;
674 IsFirstOne = TRUE;
675 series_no = 0;
676
677 do {
678 /* whether it is the last file */
679 if ((series_no + 1) * size >= length) { /*last one */
680 file_series_name = g_strdup_printf ("%s.end", p_actctx->action_list_cards.output_file);
681
682 } else { /*next one */
683 file_series_name =
684 g_strdup_printf ("%s.%04d", p_actctx->action_list_cards.output_file, series_no);
685 }
686
687 if (!(outputfile = g_fopen (file_series_name, "w"))) {
688 g_warning (_("Can not open file"));
689 exit (-1);
690 }
691
692 if (p_actctx->action_list_cards.IsVCard == TRUE)
693 format = CARD_FORMAT_VCARD;
694 else
695 format = CARD_FORMAT_CSV;
696 output_n_cards_file (outputfile, contacts, size, series_no * size, format);
697
698 fclose (outputfile);
699
700 series_no++;
701
702 if (IsFirstOne == TRUE) {
703 fork_to_background ();
704 IsFirstOne = FALSE;
705 }
706
707 }
708 while (series_no * size < length);
709 g_free (file_series_name);
710 #ifdef G_OS_WIN32
711 /* On Unix the parent exits already in
712 * fork_to_background(), but without fork() exit only
713 * after doing the job. XXX Is this correct?
714 */
715 if (IsFirstOne == FALSE)
716 _exit (-1);
717 #endif
718 }
719 }
720
721 void
722 set_pre_defined_field (GSList **pre_defined_fields)
723 {
724 *pre_defined_fields = NULL;
725 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_GIVEN_NAME));
726 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_FAMILY_NAME));
727 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_FULL_NAME));
728 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_NICKNAME));
729 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_EMAIL_1));
730 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_EMAIL_2));
731 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_EMAIL_3));
732 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_EMAIL_4));
733 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_WANTS_HTML));
734 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_PHONE_BUSINESS));
735 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_PHONE_HOME));
736 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_PHONE_BUSINESS_FAX));
737 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_PHONE_PAGER));
738 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_PHONE_MOBILE));
739 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_ADDRESS_HOME_STREET));
740 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_ADDRESS_HOME_EXT));
741 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_ADDRESS_HOME_CITY));
742 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_ADDRESS_HOME_REGION));
743 *pre_defined_fields =
744 g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_ADDRESS_HOME_POSTCODE));
745 *pre_defined_fields =
746 g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_ADDRESS_HOME_COUNTRY));
747 *pre_defined_fields =
748 g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_ADDRESS_BUSINESS_STREET));
749 *pre_defined_fields =
750 g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_ADDRESS_BUSINESS_EXT));
751 *pre_defined_fields =
752 g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_ADDRESS_BUSINESS_CITY));
753 *pre_defined_fields =
754 g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_ADDRESS_BUSINESS_REGION));
755 *pre_defined_fields =
756 g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_ADDRESS_BUSINESS_POSTCODE));
757 *pre_defined_fields =
758 g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_ADDRESS_BUSINESS_COUNTRY));
759 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_TITLE));
760 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_OFFICE));
761 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_ORG));
762 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_HOMEPAGE_URL));
763 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_CALENDAR_URI));
764 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_BIRTH_DATE_YEAR));
765 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_BIRTH_DATE_MONTH));
766 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_BIRTH_DATE_DAY));
767 *pre_defined_fields = g_slist_append (*pre_defined_fields, GINT_TO_POINTER (E_CONTACT_CSV_NOTE));
768 }
769
770 guint
771 action_list_cards_init (ESourceRegistry *registry,
772 ActionContext *p_actctx)
773 {
774 EBookClient *book_client;
775 EBookQuery *query;
776 ESource *source;
777 GSList *contacts;
778 const gchar *uid;
779 gchar *query_str;
780 GError *error = NULL;
781
782 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FAILED);
783
784 uid = p_actctx->action_list_cards.addressbook_source_uid;
785
786 if (uid != NULL)
787 source = e_source_registry_ref_source (registry, uid);
788 else
789 source = e_source_registry_ref_default_address_book (registry);
790
791 book_client = e_book_client_new (source, &error);
792
793 g_object_unref (source);
794
795 if (book_client != NULL)
796 e_client_open_sync (E_CLIENT (book_client), TRUE, NULL, &error);
797
798 if (error != NULL) {
799 g_warning (
800 "Couldn't load addressbook %s: %s",
801 p_actctx->action_list_cards.addressbook_source_uid ?
802 p_actctx->action_list_cards.addressbook_source_uid :
803 "'default'", error->message);
804 if (book_client != NULL)
805 g_object_unref (book_client);
806 g_error_free (error);
807 exit (-1);
808 }
809
810 g_return_val_if_fail (E_IS_BOOK_CLIENT (book_client), FAILED);
811
812 query = e_book_query_any_field_contains ("");
813 query_str = e_book_query_to_string (query);
814 e_book_query_unref (query);
815
816 if (!e_book_client_get_contacts_sync (book_client, query_str, &contacts, NULL, &error))
817 contacts = NULL;
818
819 action_list_cards (contacts, p_actctx);
820
821 g_slist_foreach (contacts, (GFunc) g_object_unref, NULL);
822 g_slist_free (contacts);
823 g_object_unref (book_client);
824
825 if (error) {
826 g_warning ("Failed to get contacts: %s", error->message);
827 g_error_free (error);
828 }
829
830 return error ? FAILED : SUCCESS;
831 }