4 * Copyright 2019 Michael Rasmussen <mir@datanom.net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
24 #include <glib/gprintf.h>
26 #include <vcard-parser.h>
33 VCardParserResponse state
;
38 static char *replaceWord(const char *s
, const char *oldW
, const char *newW
) {
41 int newWlen
= strlen(newW
);
42 int oldWlen
= strlen(oldW
);
44 for (i
= 0; s
[i
] != '\0'; i
++) {
45 if (strstr(&s
[i
], oldW
) == &s
[i
]) {
51 result
= (char *) malloc(i
+ cnt
* (newWlen
- oldWlen
) + 1);
55 if (strstr(s
, oldW
) == s
) {
56 strcpy(&result
[i
], newW
);
68 static void hash_table_cb(gpointer key
, gpointer value
, gpointer data
) {
69 GSList
* list
= (GSList
*) value
;
70 gchar
** str
= (gchar
**) data
;
76 VCardProperty
* vp
= (VCardProperty
*) list
->data
;
77 gchar
* s0
= replaceWord(vp
->value
, "\n", "\n ");
79 s
= g_strconcat(vp
->name
, ":", s0
, NULL
);
81 s
= g_strconcat(*str
, "\n", vp
->name
, ":", s0
, NULL
);
91 static gchar
** make_chunks(const gchar
* text
) {
92 gchar
** chunks
= NULL
;
93 gchar
* v_text
= g_strdup(text
);
96 gchar
** tmp
= g_strsplit(v_text
, "END:VCARD", 0);
98 guint lines
= g_strv_length(tmp
);
102 if (strlen(tmp
[lines
-1]) < 1) {
103 chunks
= g_new0(gchar
*, lines
);
106 chunks
= g_new0(gchar
*, lines
+ 1);
108 for(int i
= 0; i
< lines
; i
++) {
110 chunks
[i
] = g_strconcat(tmp
[i
], "END:VCARD", NULL
);
117 void VCard_free(VCard
* object
) {
118 if (object
== NULL
) return;
121 destroy_hash_table(object
->vcard
);
125 void VCard_list_free(GSList
* list
) {
129 VCard
* object
= (VCard
*) tmp
->data
;
138 VCard
* VCard_new(VCardVersion version
) {
139 VCard
* vc
= g_new0(VCard
, 1);
140 vc
->version
= version
;
145 GSList
* VCard_new_from_text(const gchar
* text
, VCardVersion version
, gboolean skip_broken
) {
149 if (!text
|| strlen(text
) < 1) return NULL
;
151 gchar
** chunks
= make_chunks(text
);
152 for (int i
= 0; i
< g_strv_length(chunks
); i
++) {
153 vc
= g_new0(VCard
, 1);
154 vc
->version
= version
;
156 VCardParserResponse r
= vcard_parse_text(chunks
[i
], &vc
->version
, &vc
->vcard
);
157 if (r
!= VCARD_PARSER_OK
&& skip_broken
) {
162 list
= g_slist_prepend(list
, vc
);
169 GSList
* VCard_new_from_file(FILE* file
, VCardVersion version
, gboolean skip_broken
) {
171 VCard
* vc
= g_new0(VCard
, 1);
173 vc
->version
= version
;
174 list
= g_slist_prepend(list
, vc
);
179 void VCard_print_list(GSList
* list
) {
180 VCard_print_list_fd(list
, STDOUT_FILENO
);
183 void VCard_print_list_fd(GSList
* list
, int fd
) {
187 VCard
* object
= (VCard
*) tmp
->data
;
188 VCard_print_fd(object
, fd
);
190 ssize_t len
= strlen("\n");
191 if (write(fd
, "\n", len
) < len
)
192 g_warning(strerror(errno
));
199 void VCard_print(VCard
* object
){
200 VCard_print_fd(object
, STDOUT_FILENO
);
203 void VCard_print_fd(VCard
* object
, int fd
) {
204 gchar
*body
= NULL
, *s
= NULL
;
206 if (object
&& object
->vcard
&& fd
> 0) {
207 gchar
* version
= vcard_version_2_str(object
->version
);
208 s
= g_strdup_printf("BEGIN:VCARD\nVERSION:%s", version
);
210 g_hash_table_foreach(object
->vcard
, hash_table_cb
, &s
);
211 body
= g_strdup_printf("%s\nEND:VCARD", s
);
213 ssize_t len
= strlen(body
);
214 if (write(fd
, body
, len
) < len
)
215 g_warning(strerror(errno
));
220 gchar
* VCard_get_state(VCard
* object
) {
221 gchar
* message
= NULL
;
223 if (!object
) return NULL
;
225 switch (object
->state
) {
226 case VCARD_PARSER_OK
:
227 message
= g_strdup("OK");
229 case VCARD_PARSER_VERSION_MISMATCH
:
230 message
= g_strdup("Version mismatch");
232 case VCARD_PARSER_ATTRIBUTE_VERSION_MISMATCH
:
233 message
= g_strdup("Attribute not supported in this version");
235 case VCARD_PARSER_BAD_FORMAT
:
236 message
= g_strdup("Bad input format");
238 case VCARD_PARSER_ERROR
:
239 message
= g_strdup("Unknown error");
242 message
= g_strdup("Unhandled error");
249 GSList
* VCard_get_property(VCard
* object
, const gchar
* property
) {
250 GSList
*values
= NULL
, *tmp
;
252 VCardProperty
* vp
= NULL
;
254 if (object
&& object
->vcard
&& property
) {
255 tmp
= g_hash_table_lookup(object
->vcard
, property
);
256 for (iter
= tmp
; iter
; iter
= g_slist_next(iter
)) {
257 vp
= (VCardProperty
*) iter
->data
;
258 values
= g_slist_prepend(values
, g_strdup_printf("%s:%s", vp
->name
, vp
->value
));