]> git.datanom.net - vcard-parser.git/blob - src/vcard.c
Completed initialization
[vcard-parser.git] / src / vcard.c
1 /*
2 * vcard.c
3 *
4 * Copyright 2019 Michael Rasmussen <mir@datanom.net>
5 *
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.
10 *
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.
15 *
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,
19 * MA 02110-1301, USA.
20 */
21
22 #include <unistd.h>
23 #include <errno.h>
24 #include <glib/gprintf.h>
25 #include <vcard.h>
26 #include <vcard-parser.h>
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 struct _VCard {
33 VCardParserResponse state;
34 VCardVersion version;
35 GHashTable* vcard;
36 };
37
38 static char *replaceWord(const char *s, const char *oldW, const char *newW) {
39 char *result;
40 int i, cnt = 0;
41 int newWlen = strlen(newW);
42 int oldWlen = strlen(oldW);
43
44 for (i = 0; s[i] != '\0'; i++) {
45 if (strstr(&s[i], oldW) == &s[i]) {
46 cnt++;
47 i += oldWlen - 1;
48 }
49 }
50
51 result = (char *) malloc(i + cnt * (newWlen - oldWlen) + 1);
52
53 i = 0;
54 while (*s) {
55 if (strstr(s, oldW) == s) {
56 strcpy(&result[i], newW);
57 i += newWlen;
58 s += oldWlen;
59 }
60 else
61 result[i++] = *s++;
62 }
63
64 result[i] = '\0';
65 return result;
66 }
67
68 static void hash_table_cb(gpointer key, gpointer value, gpointer data) {
69 GSList* list = (GSList*) value;
70 gchar** str = (gchar**) data;
71 gchar* s = NULL;
72
73 if (!list) return;
74
75 while (list) {
76 VCardProperty* vp = (VCardProperty*) list->data;
77 gchar* s0 = replaceWord(vp->value, "\n", "\n ");
78 if (!*str)
79 s = g_strconcat(vp->name, ":", s0, NULL);
80 else {
81 s = g_strconcat(*str, "\n", vp->name, ":", s0, NULL);
82 g_free(*str);
83 }
84 g_free(s0);
85 *str = g_strdup(s);
86 g_free(s);
87 list = list->next;
88 }
89 }
90
91 static gchar** make_chunks(const gchar* text) {
92 gchar** chunks = NULL;
93 gchar* v_text = g_strdup(text);
94 g_strstrip(v_text);
95
96 gchar** tmp = g_strsplit(v_text, "END:VCARD", 0);
97 g_free(v_text);
98 guint lines = g_strv_length(tmp);
99 if (lines < 2)
100 return tmp;
101
102 if (strlen(tmp[lines-1]) < 1) {
103 chunks = g_new0(gchar*, lines);
104 lines--;
105 } else
106 chunks = g_new0(gchar*, lines + 1);
107
108 for(int i = 0; i < lines; i++) {
109 g_strchug(tmp[i]);
110 chunks[i] = g_strconcat(tmp[i], "END:VCARD", NULL);
111 }
112 g_strfreev(tmp);
113
114 return chunks;
115 }
116
117 void VCard_free(VCard* object) {
118 if (object == NULL) return;
119
120 if (object->vcard)
121 destroy_hash_table(object->vcard);
122 g_free(object);
123 }
124
125 void VCard_list_free(GSList* list) {
126 GSList* tmp = list;
127
128 while(tmp) {
129 VCard* object = (VCard*) tmp->data;
130 VCard_free(object);
131 tmp = tmp->next;
132 }
133
134 if(list)
135 g_slist_free(list);
136 }
137
138 /*
139 VCard* VCard_new(VCardVersion version) {
140 VCard* vc = g_new0(VCard, 1);
141 vc->version = version;
142
143 return vc;
144 }
145 */
146
147 GSList* VCard_new_from_text(const gchar* text, VCardVersion version, gboolean skip_broken) {
148 GSList* list = NULL;
149 VCard* vc = NULL;
150
151 if (!text || strlen(text) < 1) return NULL;
152
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;
157
158 VCardParserResponse r = vcard_parse_text(chunks[i], &vc->version, &vc->vcard);
159 if (r != VCARD_PARSER_OK && skip_broken) {
160 VCard_free(vc);
161 continue;
162 }
163 vc->state = r;
164 list = g_slist_prepend(list, vc);
165 }
166 g_strfreev(chunks);
167
168 return list;
169 }
170
171 GSList* VCard_new_from_file(FILE* file, VCardVersion version, gboolean skip_broken) {
172 GSList* list = NULL;
173 VCard* vc = g_new0(VCard, 1);
174
175 vc->version = version;
176 list = g_slist_prepend(list, vc);
177
178 return list;
179 }
180
181 void VCard_print_list(GSList* list) {
182 VCard_print_list_fd(list, STDOUT_FILENO);
183 }
184
185 void VCard_print_list_fd(GSList* list, int fd) {
186 GSList* tmp = list;
187 if (fd > 0) {
188 while(tmp) {
189 VCard* object = (VCard*) tmp->data;
190 VCard_print_fd(object, fd);
191 if (tmp->next) {
192 ssize_t len = strlen("\n");
193 if (write(fd, "\n", len) < len)
194 g_warning(strerror(errno));
195 }
196 tmp = tmp->next;
197 }
198 }
199 }
200
201 void VCard_print(VCard* object){
202 VCard_print_fd(object, STDOUT_FILENO);
203 }
204
205 void VCard_print_fd(VCard* object, int fd) {
206 gchar *body = NULL, *s = NULL;
207
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);
211 g_free(version);
212 g_hash_table_foreach(object->vcard, hash_table_cb, &s);
213 body = g_strdup_printf("%s\nEND:VCARD", s);
214 g_free(s);
215 ssize_t len = strlen(body);
216 if (write(fd, body, len) < len)
217 g_warning(strerror(errno));
218 g_free(body);
219 }
220 }
221
222 gchar* VCard_get_state(VCard* object) {
223 gchar* message = NULL;
224
225 if (!object) return NULL;
226
227 switch (object->state) {
228 case VCARD_PARSER_OK:
229 message = g_strdup("OK");
230 break;
231 case VCARD_PARSER_VERSION_MISMATCH:
232 message = g_strdup("Version mismatch");
233 break;
234 case VCARD_PARSER_ATTRIBUTE_VERSION_MISMATCH:
235 message = g_strdup("Attribute not supported in this version");
236 break;
237 case VCARD_PARSER_BAD_FORMAT:
238 message = g_strdup("Bad input format");
239 break;
240 case VCARD_PARSER_ERROR:
241 message = g_strdup("Unknown error");
242 break;
243 default:
244 message = g_strdup("Unhandled error");
245 break;
246 }
247
248 return message;
249 }
250
251 GSList* VCard_get_property(VCard* object, const gchar* property) {
252 GSList *values = NULL, *tmp;
253 GSList *iter;
254 VCardProperty* vp = NULL;
255
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));
261 }
262 }
263
264 return values;
265 }
This page took 0.076019 seconds and 6 git commands to generate.