Resolved Native API Reference issues for calendar-service
[platform/core/pim/calendar-service.git] / common / cal_vcalendar.c
1 /*
2  * Calendar Service
3  *
4  * Copyright (c) 2012 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <stdlib.h>
21
22 #include "calendar_vcalendar.h"
23 #include "cal_internal.h"
24 #include "cal_typedef.h"
25 #include "cal_record.h"
26 #include "cal_view.h"
27 #include "cal_time.h"
28 #include "cal_list.h"
29 #include "cal_vcalendar.h"
30 #include "cal_vcalendar_make.h"
31 #include "cal_vcalendar_parse.h"
32 #include "cal_utils.h"
33
34 #define ICALENAR_BUFFER_MAX (1024*1024)
35
36 /*
37  * vcalendar should not have multi version: ver1.0 or 2.0 only.
38  * could have multi timezone events: MULTI BEGIN:VCALENDAR.
39  */
40 EXPORT_API int calendar_vcalendar_make_from_records(calendar_list_h list, char **vcalendar_stream)
41 {
42         CHECK_CALENDAR_SUPPORTED(CALENDAR_FEATURE);
43
44         int ret;
45         cal_make_s *b;
46         char *ical = NULL;
47
48         RETV_IF(NULL == list, CALENDAR_ERROR_INVALID_PARAMETER);
49         RETV_IF(NULL == vcalendar_stream, CALENDAR_ERROR_INVALID_PARAMETER);
50
51         b = cal_vcalendar_make_new();
52         RETVM_IF(!b, CALENDAR_ERROR_OUT_OF_MEMORY,
53                         "cal_vcalendar_make_new() Fail");
54
55         ret = cal_vcalendar_make_vcalendar(b, list);
56
57         if (ret < 0) {
58                 cal_vcalendar_make_free(&b);
59                 return ret;
60         }
61
62         ical = cal_vcalendar_make_get_data(b);
63         cal_vcalendar_make_free(&b);
64
65         if (!ical) {
66                 /* LCOV_EXCL_START */
67                 ERR("cal_vcalendar_make_get_data() Fail");
68                 return CALENDAR_ERROR_OUT_OF_MEMORY;
69                 /* LCOV_EXCL_STOP */
70         }
71
72         if (!*ical) {
73                 /* LCOV_EXCL_START */
74                 ERR("No ical data");
75                 free(ical);
76                 return CALENDAR_ERROR_NO_DATA;
77                 /* LCOV_EXCL_STOP */
78         }
79
80         *vcalendar_stream = ical;
81
82         return CALENDAR_ERROR_NONE;
83 }
84
85 static const char* __calendar_vcalendar_get_vcalendar_object(const char *original, char **pvcalendar_object)
86 {
87         int len = 0;
88         const char *vcal_start = original;
89         const char *vcal_cursor = NULL;
90         bool new_line = false;
91         char *vcalendar_object = NULL;
92
93         RETV_IF(NULL == pvcalendar_object, original);
94         *pvcalendar_object = NULL;
95
96         while ('\n' == *vcal_start || '\r' == *vcal_start)
97                 vcal_start++;
98
99         if (strncmp(vcal_start, "BEGIN:VCALENDAR", strlen("BEGIN:VCALENDAR")))
100                 return vcal_start;
101
102         vcal_start += strlen("BEGIN:VCALENDAR");
103         while ('\n' == *vcal_start || '\r' == *vcal_start)
104                 vcal_start++;
105         vcal_cursor = vcal_start;
106
107         while (*vcal_cursor) {
108                 if (new_line) {
109                         if (CAL_STRING_EQUAL == strncmp(vcal_cursor, "END:VCALENDAR", strlen("END:VCALENDAR"))) {
110                                 vcal_cursor += strlen("END:VCALENDAR");
111                                 while ('\r' == *vcal_cursor || '\n' == *vcal_cursor) {
112                                         new_line = true;
113                                         vcal_cursor++;
114                                 }
115
116                                 len = (int)((long)vcal_cursor - (long)vcal_start);
117                                 vcalendar_object = calloc(len + 1, sizeof(char));
118                                 if (NULL == vcalendar_object) {
119                                         /* LCOV_EXCL_START */
120                                         ERR("calloc() Fail");
121                                         return NULL;
122                                         /* LCOV_EXCL_STOP */
123                                 }
124                                 memcpy(vcalendar_object, vcal_start, len);
125                                 *pvcalendar_object = vcalendar_object;
126                                 return vcal_cursor;
127                         }
128                         new_line = false;
129                 }
130                 vcal_cursor++;
131                 while ('\r' == *vcal_cursor || '\n' == *vcal_cursor) {
132                         new_line = true;
133                         vcal_cursor++;
134                 }
135         }
136         return vcal_cursor;
137 }
138
139 /*
140  * parse from here
141  */
142 EXPORT_API int calendar_vcalendar_parse_to_calendar(const char* vcalendar_stream, calendar_list_h *out_list)
143 {
144         CHECK_CALENDAR_SUPPORTED(CALENDAR_FEATURE);
145
146         int count = 0;
147         const char *cursor = NULL;
148         char *vcalendar_object = NULL;
149         calendar_error_e err;
150         calendar_list_h list = NULL;
151
152         RETV_IF(NULL == vcalendar_stream, CALENDAR_ERROR_INVALID_PARAMETER);
153         RETV_IF(NULL == out_list, CALENDAR_ERROR_INVALID_PARAMETER);
154
155         /* get vcalendar object */
156         cursor = vcalendar_stream;
157
158         int ret = 0;
159         ret = calendar_list_create(&list);
160         RETVM_IF(CALENDAR_ERROR_NONE != ret, ret, "calendar_list_create() Fail(%d)", ret);
161
162         cal_time_init();
163
164         while (NULL != (cursor = __calendar_vcalendar_get_vcalendar_object(cursor, &vcalendar_object))) {
165                 if (NULL == vcalendar_object)
166                         break;
167
168                 err = cal_vcalendar_parse_vcalendar_object(vcalendar_object, list, NULL);
169                 if (CALENDAR_ERROR_NONE != err) {
170                         /* LCOV_EXCL_START */
171                         ERR("cal_vcalendar_parse_vcalendar_object() failed(%d)", err);
172                         calendar_list_destroy(list, true);
173                         free(vcalendar_object);
174                         cal_time_fini();
175                         return err;
176                         /* LCOV_EXCL_STOP */
177                 }
178                 free(vcalendar_object);
179         }
180         calendar_list_get_count(list, &count);
181         if (count <= 0) {
182                 calendar_list_destroy(list, true);
183                 cal_time_fini();
184                 return CALENDAR_ERROR_INVALID_PARAMETER;
185         }
186         calendar_list_first(list);
187         *out_list = list;
188         cal_time_fini();
189         return CALENDAR_ERROR_NONE;
190 }
191
192 EXPORT_API int calendar_vcalendar_parse_to_calendar_foreach(const char *vcalendar_file_path, calendar_vcalendar_parse_cb callback, void *user_data)
193 {
194         CHECK_CALENDAR_SUPPORTED(CALENDAR_FEATURE);
195
196         FILE *file;
197         int buf_size, len;
198         char *stream;
199         char buf[CAL_STR_MIDDLE_LEN];
200         vcalendar_foreach_s *foreach_data = NULL;
201
202         RETV_IF(NULL == vcalendar_file_path, CALENDAR_ERROR_INVALID_PARAMETER);
203         RETV_IF(NULL == callback, CALENDAR_ERROR_INVALID_PARAMETER);
204
205         int ret = 0;
206         calendar_list_h list = NULL;
207         ret = calendar_list_create(&list);
208         RETVM_IF(CALENDAR_ERROR_NONE != ret, ret, "calendar_list_create() Fail(%d)", ret);
209
210         file = fopen(vcalendar_file_path, "r");
211         if (NULL == file) {
212                 /* LCOV_EXCL_START */
213                 ERR("Invalid argument: no file");
214                 calendar_list_destroy(list, true);
215                 return CALENDAR_ERROR_INVALID_PARAMETER;
216                 /* LCOV_EXCL_STOP */
217         }
218
219         len = 0;
220         buf_size = ICALENAR_BUFFER_MAX;
221         stream = calloc(ICALENAR_BUFFER_MAX, sizeof(char));
222         if (NULL == stream) {
223                 /* LCOV_EXCL_START */
224                 ERR("calloc() Fail");
225                 fclose(file);
226                 calendar_list_destroy(list, true);
227                 return CALENDAR_ERROR_OUT_OF_MEMORY;
228                 /* LCOV_EXCL_STOP */
229         }
230
231         foreach_data = calloc(1, sizeof(vcalendar_foreach_s));
232         if (NULL == foreach_data) {
233                 /* LCOV_EXCL_START */
234                 ERR("calloc() Fail");
235                 free(stream);
236                 fclose(file);
237                 calendar_list_destroy(list, true);
238                 return CALENDAR_ERROR_OUT_OF_MEMORY;
239                 /* LCOV_EXCL_STOP */
240         }
241         foreach_data->callback = callback;
242         foreach_data->user_data = user_data;
243         foreach_data->ret = true;
244
245         int error = CALENDAR_ERROR_NONE;
246
247         while (fgets(buf, sizeof(buf), file)) {
248                 int added_len = cal_add_safe(len, strlen(buf));
249                 if (added_len < 0) {
250                         ERR("cal_add_safe() Fail");
251                         error = CALENDAR_ERROR_SYSTEM;
252                         break;
253                 }
254                 if (buf_size <= added_len) {
255                         char *new_stream;
256                         buf_size *= 2;
257                         new_stream = realloc(stream, buf_size);
258                         if (NULL == new_stream) {
259                                 /* LCOV_EXCL_START */
260                                 ERR("out of memory");
261                                 error = CALENDAR_ERROR_OUT_OF_MEMORY;
262                                 break;
263                                 /* LCOV_EXCL_STOP */
264                         }
265                         stream = new_stream;
266                 }
267
268                 int copyed_len = snprintf(stream + len, strlen(buf) +1, "%s", buf);
269                 len = cal_add_safe(copyed_len, len);
270                 if (len < 0) {
271                         /* LCOV_EXCL_START */
272                         ERR("cal_add_safe() Fail");
273                         error = CALENDAR_ERROR_SYSTEM;
274                         break;
275                         /* LCOV_EXCL_STOP */
276                 }
277
278                 if (CAL_STRING_EQUAL == strncmp(buf, "END:VCALENDAR", strlen("END:VCALENDAR"))) {
279                         DBG("end vcalendar");
280                         char *vcalendar_object = NULL;
281                         __calendar_vcalendar_get_vcalendar_object(stream, &vcalendar_object);
282                         error = cal_vcalendar_parse_vcalendar_object(vcalendar_object, list, foreach_data);
283                         if (CALENDAR_ERROR_NONE != error) {
284                                 /* LCOV_EXCL_START */
285                                 ERR("cal_vcalendar_parse_vcalendar_object() failed(%d)", error);
286                                 free(vcalendar_object);
287                                 break;
288                                 /* LCOV_EXCL_STOP */
289                         }
290                         if (false == foreach_data->ret) {
291                                 /* LCOV_EXCL_START */
292                                 ERR("foreach_data->ret is NULL");
293                                 free(vcalendar_object);
294                                 error = CALENDAR_ERROR_SYSTEM;
295                                 break;
296                                 /* LCOV_EXCL_STOP */
297                         }
298                         free(vcalendar_object);
299                         len = 0;
300                 }
301         }
302
303         calendar_list_destroy(list, true);
304         free(stream);
305         free(foreach_data);
306         fclose(file);
307
308         return error;
309 }