2 Copyright (c) 2008 Instituto Nokia de Tecnologia
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
8 * Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright notice,
11 this list of conditions and the following disclaimer in the documentation
12 and/or other materials provided with the distribution.
13 * Neither the name of the INdT nor the names of its contributors
14 may be used to endorse or promote products derived from this software
15 without specific prior written permission.
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 POSSIBILITY OF SUCH DAMAGE.
31 * @author Adenilson Cavalcanti da Silva <adenilson.silva@indt.org.br>
32 * @date Tue Jun 24 16:17:25 2008
34 * @brief libgcal calendar user public API.
36 * Use this functions to handle common tasks when dealing with google calendar.
47 #include "gcalendar.h"
48 #include "internal_gcal.h"
49 #include "gcal_parser.h"
50 #include "msvc_hacks.h"
52 gcal_t
gcal_new(gservice mode
)
54 return gcal_construct(mode
);
57 void gcal_delete(gcal_t gcal_obj
)
59 gcal_destroy(gcal_obj
);
62 gcal_event_t
gcal_event_new(char *raw_xml
)
64 gcal_event_t event
= NULL
;
68 event
= malloc(sizeof(struct gcal_event
));
71 gcal_init_event(event
);
75 /* Builds a doc, parse and init object */
76 doc
= build_dom_document(raw_xml
);
80 result
= extract_all_entries(doc
, event
, 1);
81 clean_dom_document(doc
);
93 void gcal_event_delete(gcal_event_t event
)
99 gcal_destroy_entry(event
);
103 int gcal_get_edit_url(char *entry
, char **extracted_url
)
109 result
= get_edit_url(entry
, strlen(entry
), extracted_url
);
116 int gcal_get_extract_etag(char *entry
, char **extracted_etag
)
122 result
= get_edit_etag(entry
, strlen(entry
), extracted_etag
);
129 int gcal_add_xmlentry(gcal_t gcal_obj
, char *xml_entry
, char **xml_updated
)
131 int result
= -1, length
= 0;
134 if ((!gcal_obj
) || (!xml_entry
))
137 if (!(strcmp(gcal_obj
->service
, "cl")))
138 result
= up_entry(xml_entry
, strlen(xml_entry
), gcal_obj
,
140 POST
, NULL
, GCAL_EDIT_ANSWER
);
144 length
= sizeof(GCONTACT_START
) + sizeof(GCONTACT_END
) +
145 strlen(gcal_obj
->user
) + sizeof(GCAL_DELIMITER
) +
146 strlen(gcal_obj
->domain
) + 1;
147 buffer
= (char *) malloc(length
);
150 snprintf(buffer
, length
- 1, "%s%s%s%s%s", GCONTACT_START
,
151 gcal_obj
->user
, GCAL_DELIMITER
, gcal_obj
->domain
,
154 result
= up_entry(xml_entry
, strlen(xml_entry
), gcal_obj
,
156 POST
, NULL
, GCAL_EDIT_ANSWER
);
161 *xml_updated
= strdup(gcal_obj
->buffer
);
171 int gcal_update_xmlentry(gcal_t gcal_obj
, char *xml_entry
, char **xml_updated
,
172 char *edit_url
, char *etag
)
174 char *url
= NULL
, *pvt_etag
= NULL
;
177 const char if_match
[] = "If-Match: ";
179 memset(buffer
, '\0', sizeof(buffer
));
181 if ((!gcal_obj
) || (!xml_entry
))
185 result
= get_edit_url(xml_entry
, strlen(xml_entry
), &url
);
190 if (!(url
= strdup(edit_url
)))
194 if ((result
= get_edit_etag(xml_entry
, strlen(xml_entry
),
201 /* Mounts costum HTTP header using ETag */
202 snprintf(buffer
, sizeof(buffer
) - 1, "%s\%s",
205 result
= up_entry(xml_entry
, strlen(xml_entry
), gcal_obj
, url
, buffer
,
206 PUT
, NULL
, GCAL_DEFAULT_ANSWER
);
210 *xml_updated
= strdup(gcal_obj
->buffer
);
222 int gcal_erase_xmlentry(gcal_t gcal_obj
, char *xml_entry
)
224 char *edit_url
= NULL
;
226 /* I could use just 1 structure object and benefit from the fact
227 * that both have the same field type/name alignment (that would
228 * save 1 structure from the stack). But it would break with any
229 * change in the field type/alignment, I don't think its worthwhile.
231 struct gcal_event event
;
232 struct gcal_contact contact
;
234 if ((!gcal_obj
) || (!xml_entry
))
237 result
= get_edit_url(xml_entry
, strlen(xml_entry
), &edit_url
);
240 event
.common
.edit_uri
= edit_url
;
241 contact
.common
.edit_uri
= edit_url
;
243 if (!(strcmp(gcal_obj
->service
, "cl")))
244 result
= gcal_delete_event(gcal_obj
, &event
);
247 result
= gcal_delete_contact(gcal_obj
, &contact
);
257 int gcal_add_event(gcal_t gcal_obj
, gcal_event_t event
)
260 struct gcal_event updated
;
261 gcal_init_event(&updated
);
263 if ((!gcal_obj
) || (!event
))
266 result
= gcal_create_event(gcal_obj
, event
, &updated
);
270 /* Swap updated fields: id, updated, edit_uri, etag */
271 if (event
->common
.id
)
272 free(event
->common
.id
);
273 event
->common
.id
= updated
.common
.id
;
274 updated
.common
.id
= NULL
;
276 if (event
->common
.updated
)
277 free(event
->common
.updated
);
278 event
->common
.updated
= updated
.common
.updated
;
279 updated
.common
.updated
= NULL
;
281 if (event
->common
.edit_uri
)
282 free(event
->common
.edit_uri
);
283 event
->common
.edit_uri
= updated
.common
.edit_uri
;
284 updated
.common
.edit_uri
= NULL
;
286 if (event
->common
.etag
)
287 free(event
->common
.etag
);
288 event
->common
.etag
= updated
.common
.etag
;
289 updated
.common
.etag
= NULL
;
291 /* Cleanup updated event */
292 gcal_destroy_entry(&updated
);
297 int gcal_update_event(gcal_t gcal_obj
, gcal_event_t event
)
300 struct gcal_event updated
;
302 if ((!gcal_obj
) || (!event
))
305 result
= gcal_edit_event(gcal_obj
, event
, &updated
);
309 /* Swap updated fields: updated, edit_uri, etag */
310 if (event
->common
.updated
)
311 free(event
->common
.updated
);
312 event
->common
.updated
= updated
.common
.updated
;
313 updated
.common
.updated
= NULL
;
315 if (event
->common
.edit_uri
)
316 free(event
->common
.edit_uri
);
317 event
->common
.edit_uri
= updated
.common
.edit_uri
;
318 updated
.common
.edit_uri
= NULL
;
320 if (event
->common
.etag
)
321 free(event
->common
.etag
);
322 event
->common
.etag
= updated
.common
.etag
;
323 updated
.common
.etag
= NULL
;
325 /* Cleanup updated event */
326 gcal_destroy_entry(&updated
);
332 int gcal_erase_event(gcal_t gcal_obj
, gcal_event_t event
)
335 if ((!gcal_obj
) || (!event
))
338 result
= gcal_delete_event(gcal_obj
, event
);
343 int gcal_get_updated_events(gcal_t gcal_obj
, struct gcal_event_array
*events
,
350 if ((!gcal_obj
) || (!events
))
353 result
= gcal_query_updated(gcal_obj
, timestamp
, "GData-Version: 2");
355 events
->entries
= NULL
;
360 events
->entries
= gcal_get_entries(gcal_obj
, &events
->length
);
367 int gcal_get_events(gcal_t gcalobj
, struct gcal_event_array
*events_array
)
371 events_array
->length
= 0;
373 if ((!gcalobj
) || (!events_array
))
376 result
= gcal_dump(gcalobj
, "GData-Version: 2");
378 events_array
->entries
= NULL
;
379 events_array
->length
= 0;
383 events_array
->entries
= gcal_get_entries(gcalobj
, &events_array
->length
);
384 if (!events_array
->entries
)
391 void gcal_cleanup_events(struct gcal_event_array
*events
)
396 gcal_destroy_entries(events
->entries
, events
->length
);
398 events
->entries
= NULL
;
401 gcal_event_t
gcal_event_element(struct gcal_event_array
*events
, size_t _index
)
403 struct gcal_event
*event
= NULL
;
404 if ((!events
) || (_index
> (events
->length
- 1)) ||
405 (events
->length
== 0))
408 event
= &events
->entries
[_index
];
412 char *gcal_event_get_xml(gcal_event_t event
)
416 return gcal_get_xml(&(event
->common
));
419 char gcal_event_is_deleted(gcal_event_t event
)
423 return gcal_get_deleted(&(event
->common
));
426 char *gcal_event_get_id(gcal_event_t event
)
430 return gcal_get_id(&(event
->common
));
433 char *gcal_event_get_updated(gcal_event_t event
)
437 return gcal_get_updated(&(event
->common
));
440 char *gcal_event_get_title(gcal_event_t event
)
444 return gcal_get_title(&(event
->common
));
447 char *gcal_event_get_url(gcal_event_t event
)
451 return gcal_get_url(&(event
->common
));
454 char *gcal_event_get_etag(gcal_event_t event
)
458 return gcal_get_etag(&(event
->common
));
461 /* This are the fields unique to calendar events */
462 char *gcal_event_get_content(gcal_event_t event
)
466 return event
->content
;
469 char *gcal_event_get_recurrent(gcal_event_t event
)
473 return event
->dt_recurrent
;
476 char *gcal_event_get_start(gcal_event_t event
)
480 return event
->dt_start
;
483 char *gcal_event_get_end(gcal_event_t event
)
487 return event
->dt_end
;
490 char *gcal_event_get_where(gcal_event_t event
)
497 char *gcal_event_get_status(gcal_event_t event
)
501 return event
->status
;
505 /* Here starts the setters */
506 int gcal_event_set_title(gcal_event_t event
, const char *field
)
510 if ((!event
) || (!field
))
513 if (event
->common
.title
)
514 free(event
->common
.title
);
516 event
->common
.title
= strdup(field
);
517 if (event
->common
.title
)
523 int gcal_event_set_content(gcal_event_t event
, const char *field
)
527 if ((!event
) || (!field
))
531 free(event
->content
);
533 event
->content
= strdup(field
);
540 int gcal_event_set_start(gcal_event_t event
, const char *field
)
544 if ((!event
) || (!field
))
548 free(event
->dt_start
);
550 event
->dt_start
= strdup(field
);
557 int gcal_event_set_end(gcal_event_t event
, const char *field
)
561 if ((!event
) || (!field
))
567 event
->dt_end
= strdup(field
);
574 int gcal_event_set_where(gcal_event_t event
, const char *field
)
578 if ((!event
) || (!field
))
584 event
->where
= strdup(field
);
592 int gcal_event_set_url(gcal_event_t event
, const char *field
)
596 if ((!event
) || (!field
))
599 if (event
->common
.edit_uri
)
600 free(event
->common
.edit_uri
);
602 event
->common
.edit_uri
= strdup(field
);
603 if (event
->common
.edit_uri
)
610 int gcal_event_set_id(gcal_event_t event
, const char *field
)
614 if ((!event
) || (!field
))
617 if (event
->common
.id
)
618 free(event
->common
.id
);
620 event
->common
.id
= strdup(field
);
621 if (event
->common
.id
)
628 int gcal_event_set_etag(gcal_event_t event
, const char *field
)
632 if ((!event
) || (!field
))
635 if (event
->common
.etag
)
636 free(event
->common
.etag
);
638 event
->common
.etag
= strdup(field
);
639 if (event
->common
.etag
)