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
;
139 VCard* VCard_new(VCardVersion version) {
140 VCard* vc = g_new0(VCard, 1);
141 vc->version = version;
147 GSList
* VCard_new_from_text(const gchar
* text
, VCardVersion version
, gboolean skip_broken
) {
151 if (!text
|| strlen(text
) < 1) return NULL
;
153 gchar
** chunks
= make_chunks(text
);
154 for (int i
= 0; i
< g_strv_length(chunks
); i
++) {
155 vc
= g_new0(VCard
, 1);
156 vc
->version
= version
;
158 VCardParserResponse r
= vcard_parse_text(chunks
[i
], &vc
->version
, &vc
->vcard
);
159 if (r
!= VCARD_PARSER_OK
&& skip_broken
) {
164 list
= g_slist_prepend(list
, vc
);
171 GSList
* VCard_new_from_file(FILE* file
, VCardVersion version
, gboolean skip_broken
) {
173 VCard
* vc
= g_new0(VCard
, 1);
175 vc
->version
= version
;
176 list
= g_slist_prepend(list
, vc
);
181 void VCard_print_list(GSList
* list
) {
182 VCard_print_list_fd(list
, STDOUT_FILENO
);
185 void VCard_print_list_fd(GSList
* list
, int fd
) {
189 VCard
* object
= (VCard
*) tmp
->data
;
190 VCard_print_fd(object
, fd
);
192 ssize_t len
= strlen("\n");
193 if (write(fd
, "\n", len
) < len
)
194 g_warning(strerror(errno
));
201 void VCard_print(VCard
* object
){
202 VCard_print_fd(object
, STDOUT_FILENO
);
205 void VCard_print_fd(VCard
* object
, int fd
) {
206 gchar
*body
= NULL
, *s
= NULL
;
208 if (object
&& object
->vcard
&& fd
> 0) {
209 gchar
* version
= vcard_version_2_str(object
->version
);
210 s
= g_strdup_printf("BEGIN:VCARD\nVERSION:%s", version
);
212 g_hash_table_foreach(object
->vcard
, hash_table_cb
, &s
);
213 body
= g_strdup_printf("%s\nEND:VCARD", s
);
215 ssize_t len
= strlen(body
);
216 if (write(fd
, body
, len
) < len
)
217 g_warning(strerror(errno
));
222 gchar
* VCard_get_state(VCard
* object
) {
223 gchar
* message
= NULL
;
225 if (!object
) return NULL
;
227 switch (object
->state
) {
228 case VCARD_PARSER_OK
:
229 message
= g_strdup("OK");
231 case VCARD_PARSER_VERSION_MISMATCH
:
232 message
= g_strdup("Version mismatch");
234 case VCARD_PARSER_ATTRIBUTE_VERSION_MISMATCH
:
235 message
= g_strdup("Attribute not supported in this version");
237 case VCARD_PARSER_BAD_FORMAT
:
238 message
= g_strdup("Bad input format");
240 case VCARD_PARSER_ERROR
:
241 message
= g_strdup("Unknown error");
244 message
= g_strdup("Unhandled error");
251 GSList
* VCard_get_property(VCard
* object
, const gchar
* property
) {
252 GSList
*values
= NULL
, *tmp
;
254 VCardProperty
* vp
= NULL
;
256 if (object
&& object
->vcard
&& property
) {
257 tmp
= g_hash_table_lookup(object
->vcard
, property
);
258 for (iter
= tmp
; iter
; iter
= g_slist_next(iter
)) {
259 vp
= (VCardProperty
*) iter
->data
;
260 values
= g_slist_prepend(values
, g_strdup_printf("%s:%s", vp
->name
, vp
->value
));