merge with master
[framework/pim/calendar-service.git] / common / cal_vcalendar.c
1 /*
2  * Calendar Service
3  *
4  * Copyright (c) 2012 - 2013 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
24 #include "cal_internal.h"
25 #include "cal_typedef.h"
26 #include "cal_record.h"
27 #include "cal_view.h"
28 #include "cal_time.h"
29 #include "cal_list.h"
30
31 #include "cal_vcalendar.h"
32 #include "cal_vcalendar_make.h"
33 #include "cal_vcalendar_parse.h"
34
35 #define ICALENAR_BUFFER_MAX (1024*1024)
36
37 API int calendar_vcalendar_make_from_records(calendar_list_h list, char **vcalendar_stream)
38 {
39         int ret;
40         cal_make_s *b;
41         char *ical;
42
43         retvm_if(list == NULL, CALENDAR_ERROR_INVALID_PARAMETER,
44                         "Invalid argument: calendar_list_h is NULL");
45         retvm_if(vcalendar_stream == NULL, CALENDAR_ERROR_INVALID_PARAMETER,
46                         "Invalid argument: vcalendar_stream is NULL");
47
48         b = _cal_vcalendar_make_new();
49         retvm_if(!b, CALENDAR_ERROR_OUT_OF_MEMORY,
50                          "_cal_vcalendar_make_new() Failed");
51
52         ret = _cal_vcalendar_make_vcalendar(b, list);
53
54         if (ret < 0) {
55                 _cal_vcalendar_make_free(&b);
56                 return ret;
57         }
58
59         ical = _cal_vcalendar_make_get_data(b);
60         _cal_vcalendar_make_free(&b);
61
62         if (!ical) {
63                 ERR("Failed to get ical data");
64                 return CALENDAR_ERROR_OUT_OF_MEMORY;
65         }
66
67         if (!*ical) {
68                 ERR("No ical data");
69                 return CALENDAR_ERROR_NO_DATA;
70         }
71
72         *vcalendar_stream = ical;
73
74         return CALENDAR_ERROR_NONE;
75 }
76
77 /*
78  * parse from here
79  */
80
81 API int calendar_vcalendar_parse_to_calendar(const char* vcalendar_stream, calendar_list_h *out_list)
82 {
83         char *prop, *cont;
84         char *stream = NULL;
85         char *cursor = NULL;
86         calendar_list_h list = NULL;
87
88         retvm_if(vcalendar_stream == NULL, CALENDAR_ERROR_INVALID_PARAMETER,
89                         "Invalid argument: vcalendar_stream is NULL");
90         retvm_if(out_list == NULL, CALENDAR_ERROR_INVALID_PARAMETER,
91                         "Invalid argument: calendar_list_h * is NULL");
92
93         stream  = strdup(vcalendar_stream);
94         cursor = stream;
95
96         cursor = _cal_vcalendar_parse_remove_space(cursor);
97         if (cursor == NULL) {
98                 ERR("_cal_vcalendar_parse_remove_space() failed");
99                 CAL_FREE(stream);
100                 return CALENDAR_ERROR_OUT_OF_MEMORY;
101         }
102         _cal_vcalendar_parse_unfolding(cursor);
103
104         cursor = _cal_vcalendar_parse_read_line(cursor, &prop, &cont);
105         if (cursor == NULL) {
106                 ERR("_cal_vcalendar_parse_read_line() failed");
107                 CAL_FREE(prop);
108                 CAL_FREE(cont);
109                 CAL_FREE(stream);
110                 return CALENDAR_ERROR_OUT_OF_MEMORY;
111         }
112
113         if (strncmp(prop, "BEGIN", strlen("BEGIN")) ||
114                         strncmp(cont + 1, "VCALENDAR", strlen("VCALENDAR"))) {
115                 ERR("Failed to find BEGIN:VCALDENDAR [%s][%s]", prop, cont);
116                 CAL_FREE(prop);
117                 CAL_FREE(cont);
118                 return -1;
119         }
120         CAL_FREE(prop);
121         CAL_FREE(cont);
122
123         _cal_vcalendar_parse_vcalendar(&list, cursor);
124         if (list == NULL) {
125                 ERR("No schedules");
126                 CAL_FREE(stream);
127                 return CALENDAR_ERROR_NO_DATA;
128         }
129
130         calendar_list_first(list);
131         *out_list = list;
132
133         CAL_FREE(stream);
134         return CALENDAR_ERROR_NONE;
135 }
136
137 API int calendar_vcalendar_parse_to_calendar_foreach(const char *vcalendar_file_path, calendar_vcalendar_parse_cb callback, void *user_data)
138 {
139     FILE *file;
140         int ret = CALENDAR_ERROR_NONE;
141     int buf_size, len;
142     char *stream;
143     char buf[1024];
144
145     retvm_if(vcalendar_file_path == NULL, CALENDAR_ERROR_INVALID_PARAMETER,
146             "Invalid argument: vcalendar_file_path is NULL");
147     retvm_if(callback == NULL, CALENDAR_ERROR_INVALID_PARAMETER,
148             "Invalid argument: callback is NULL");
149
150     file = fopen(vcalendar_file_path, "r");
151
152     retvm_if(file == NULL, CALENDAR_ERROR_INVALID_PARAMETER,
153             "Invalid argument: no file");
154
155     len = 0;
156     buf_size = ICALENAR_BUFFER_MAX;
157     stream = malloc(ICALENAR_BUFFER_MAX);
158
159     while (fgets(buf, sizeof(buf), file))
160     {
161         if (len + sizeof(buf) < buf_size)
162         {
163             len += snprintf(stream + len, strlen(buf) +1, "%s", buf);
164         }
165         else
166         {
167             char *new_stream;
168             buf_size *= 2;
169             new_stream = realloc(stream, buf_size);
170             if (new_stream)
171             {
172                 stream = new_stream;
173             } else
174             {
175                 if (stream) free(stream);
176                 fclose(file);
177                 ERR("out of memory");
178                 return CALENDAR_ERROR_OUT_OF_MEMORY;
179             }
180             len += snprintf(stream + len, strlen(buf) +1, "%s", buf);
181         }
182
183         if (!strncmp(buf, "END:VCALENDAR", strlen("END:VCALENDAR")))
184         {
185             DBG("end vcalendar");
186             calendar_list_h list = NULL;
187             int count = 0, i = 0;
188
189             if (calendar_vcalendar_parse_to_calendar(stream, &list) != CALENDAR_ERROR_NONE)
190             {
191                 ERR("calendar_vcalendar_parse_to_calendar fail");
192                 if (stream) free(stream);
193                 fclose(file);
194                 return CALENDAR_ERROR_INVALID_PARAMETER;
195             }
196
197             ret = calendar_list_get_count(list, &count);
198                         if (ret != CALENDAR_ERROR_NONE || count < 1)
199                         {
200                                 ERR("calendar_list_get_count() failed");
201                                 calendar_list_destroy(list, true);
202                                 if (stream) free(stream);
203                                 fclose(file);
204                                 return ret;
205                         }
206
207                         DBG("vcalendar has count(%d)", count);
208             calendar_list_first(list);
209             for(i = 0; i < count; i++)
210             {
211                 calendar_record_h record = NULL;
212                 if (calendar_list_get_current_record_p(list,&record) != CALENDAR_ERROR_NONE)
213                 {
214                     ERR("calendar_list_get_count fail");
215                     calendar_list_destroy(list, true);
216                     if (stream) free(stream);
217                     fclose(file);
218                     return CALENDAR_ERROR_INVALID_PARAMETER;
219                 }
220                 if (!callback(record, user_data))
221                 {
222                     ERR("callback is false");
223                     calendar_list_destroy(list, true);
224                     if (stream) free(stream);
225                     fclose(file);
226                     return CALENDAR_ERROR_INVALID_PARAMETER;
227                 }
228                                 calendar_list_next(list);
229             }
230
231             calendar_list_destroy(list, true);
232             len = 0;
233         }
234     }
235     if (stream) free(stream);
236     fclose(file);
237
238     return CALENDAR_ERROR_NONE;
239 }