/* Copyright (c) 2008 Michael Rasmussen (mir@datanom.net) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "caldav.h" #include "caldav-utils.h" #include "get-caldav-report.h" #include "add-caldav-object.h" #include "delete-caldav-object.h" #include "modify-caldav-object.h" #include "get-display-name.h" #include "options-caldav-server.h" #include "get-freebusy-report.h" #include #include #include #include #include static void init_runtime(runtime_info* info) { if (! info) return; if (! info->error) info->error = g_new0(caldav_error, 1); if (! info->options) { info->options = g_new0(debug_curl, 1); info->options->trace_ascii = 1; info->options->debug = 0; info->options->verify_ssl_certificate = TRUE; info->options->use_locking = TRUE; info->options->custom_cacert = NULL; } } /** * @param curl An instance of libcurl. * @param settings Defines CalDAV resource. Receiver is responsible for freeing * the memory. URL is part of the structure. [http://][username:password@]host[:port]/url-path. * See (RFC1738). * @return FALSE (zero) mens URL does not reference a CalDAV calendar * resource. TRUE if the URL does reference a CalDAV calendar resource. */ static gboolean test_caldav_enabled(CURL* curl, caldav_settings* settings, caldav_error* error) { return caldav_getoptions(curl, settings, NULL, error, TRUE); } /* * @param settings An instance of caldav_settings. @see caldav_settings * @return TRUE if there was an error. Error can be in libcurl, in libcaldav, * or an error related to the CalDAV protocol. */ static gboolean make_caldav_call(caldav_settings* settings, runtime_info* info) { CURL* curl; gboolean result = FALSE; g_return_val_if_fail(info != NULL, TRUE); curl = get_curl(settings); if (!curl) { info->error->str = g_strdup("Could not initialize libcurl"); g_free(settings->file); settings->file = NULL; return TRUE; } if (!test_caldav_enabled(curl, settings, info->error)) { g_free(settings->file); settings->file = NULL; curl_easy_cleanup(curl); return TRUE; } curl_easy_cleanup(curl); switch (settings->ACTION) { case GETALL: result = caldav_getall(settings, info->error); break; case GET: result = caldav_getrange(settings, info->error); break; case GETALLTASKS: result = caldav_tasks_getall(settings, info->error); break; case GETTASKS: result = caldav_tasks_getrange(settings, info->error); break; case ADD: result = caldav_add(settings, info->error); break; case DELETE: result = caldav_delete(settings, info->error); break; case MODIFY: result = caldav_modify(settings, info->error); break; case DELETETASKS: result = caldav_tasks_delete(settings, info->error); break; case MODIFYTASKS: result = caldav_tasks_modify(settings, info->error); break; case GETCALNAME: result = caldav_getname(settings, info->error); break; case FREEBUSY: result = caldav_freebusy(settings, info->error); break; default: break; } return result; } /** * Function for adding a new event. * @param object Appointment following ICal format (RFC2445). Receiver is * responsible for freeing the memory. * @param URL Defines CalDAV resource. Receiver is responsible for freeing * the memory. [http://][username[:password]@]host[:port]/url-path. * See (RFC1738). * @return Ok, FORBIDDEN, or CONFLICT. @see CALDAV_RESPONSE */ CALDAV_RESPONSE caldav_add_object(const char* object, const char* URL, runtime_info* info) { caldav_settings settings; CALDAV_RESPONSE caldav_response; g_return_val_if_fail(info != NULL, TRUE); init_runtime(info); init_caldav_settings(&settings); settings.file = g_strdup(object); settings.ACTION = ADD; if (info->options->debug) settings.debug = TRUE; else settings.debug = FALSE; if (info->options->trace_ascii) settings.trace_ascii = 1; else settings.trace_ascii = 0; if (info->options->use_locking) settings.use_locking = 1; else settings.use_locking = 0; parse_url(&settings, URL); gboolean res = make_caldav_call(&settings, info); if (res) { if (info->error->code > 0) { switch (info->error->code) { case 403: caldav_response = FORBIDDEN; break; case 409: caldav_response = CONFLICT; break; case 423: caldav_response = LOCKED; break; case 501: caldav_response = NOTIMPLEMENTED; break; default: caldav_response = CONFLICT; break; } } else { /* fall-back to conflicting state */ caldav_response = CONFLICT; } } else { caldav_response = OK; } free_caldav_settings(&settings); return caldav_response; } /** * Function for deleting an event. * @param object Appointment following ICal format (RFC2445). Receiver is * responsible for freeing the memory. * @param URL Defines CalDAV resource. Receiver is responsible for freeing * the memory. [http://][username[:password]@]host[:port]/url-path. * See (RFC1738). * @return Ok, FORBIDDEN, or CONFLICT. @see CALDAV_RESPONSE */ CALDAV_RESPONSE caldav_delete_object(const char* object, const char* URL, runtime_info* info) { caldav_settings settings; CALDAV_RESPONSE caldav_response; g_return_val_if_fail(info != NULL, TRUE); init_runtime(info); init_caldav_settings(&settings); settings.file = g_strdup(object); settings.ACTION = DELETE; if (info->options->debug) settings.debug = TRUE; else settings.debug = FALSE; if (info->options->trace_ascii) settings.trace_ascii = 1; else settings.trace_ascii = 0; if (info->options->use_locking) settings.use_locking = 1; else settings.use_locking = 0; parse_url(&settings, URL); gboolean res = make_caldav_call(&settings, info); if (res) { if (info->error->code > 0) { switch (info->error->code) { case 403: caldav_response = FORBIDDEN; break; case 409: caldav_response = CONFLICT; break; case 423: caldav_response = LOCKED; break; case 501: caldav_response = NOTIMPLEMENTED; break; default: caldav_response = CONFLICT; break; } } else { /* fall-back to conflicting state */ caldav_response = CONFLICT; } } else { caldav_response = OK; } free_caldav_settings(&settings); return caldav_response; } /** * Function for modifying an event. * @param object Appointment following ICal format (RFC2445). Receiver is * responsible for freeing the memory. * @param URL Defines CalDAV resource. Receiver is responsible for freeing * the memory. [http://][username[:password]@]host[:port]/url-path. * See (RFC1738). * @return Ok, FORBIDDEN, or CONFLICT. @see CALDAV_RESPONSE */ CALDAV_RESPONSE caldav_modify_object(const char* object, const char* URL, runtime_info* info) { caldav_settings settings; CALDAV_RESPONSE caldav_response; g_return_val_if_fail(info != NULL, TRUE); init_runtime(info); init_caldav_settings(&settings); settings.file = g_strdup(object); settings.ACTION = MODIFY; if (info->options->debug) settings.debug = TRUE; else settings.debug = FALSE; if (info->options->trace_ascii) settings.trace_ascii = 1; else settings.trace_ascii = 0; if (info->options->use_locking) settings.use_locking = 1; else settings.use_locking = 0; parse_url(&settings, URL); gboolean res = make_caldav_call(&settings, info); if (res) { if (info->error->code > 0) { switch (info->error->code) { case 403: caldav_response = FORBIDDEN; break; case 409: caldav_response = CONFLICT; break; case 423: caldav_response = LOCKED; break; case 501: caldav_response = NOTIMPLEMENTED; break; default: caldav_response = CONFLICT; break; } } else { /* fall-back to conflicting state */ caldav_response = CONFLICT; } } else { caldav_response = OK; } free_caldav_settings(&settings); return caldav_response; } /** * Function for getting a collection of events determined by time range. * @param result A pointer to struct _response where the result is to stored. * @see response. Caller is responsible for freeing the memory. * @param start time_t variable specifying start and end for range. Both * are included in range. * @param end time_t variable specifying start and end for range. Both * are included in range. * @param URL Defines CalDAV resource. Receiver is responsible for freeing * the memory. [http://][username[:password]@]host[:port]/url-path. * See (RFC1738). * @return Ok, FORBIDDEN, or CONFLICT. @see CALDAV_RESPONSE */ CALDAV_RESPONSE caldav_get_object(response *result, time_t start, time_t end, const char* URL, runtime_info* info) { caldav_settings settings; CALDAV_RESPONSE caldav_response; g_return_val_if_fail(info != NULL, TRUE); g_return_val_if_fail(result != NULL, NOTIMPLEMENTED); init_runtime(info); init_caldav_settings(&settings); settings.ACTION = GET; settings.start = start; settings.end = end; if (info->options->debug) settings.debug = TRUE; else settings.debug = FALSE; if (info->options->trace_ascii) settings.trace_ascii = 1; else settings.trace_ascii = 0; if (info->options->use_locking) settings.use_locking = 1; else settings.use_locking = 0; parse_url(&settings, URL); gboolean res = make_caldav_call(&settings, info); if (res) { result->msg = NULL; if (info->error->code > 0) { switch (info->error->code) { case 403: caldav_response = FORBIDDEN; break; case 409: caldav_response = CONFLICT; break; case 423: caldav_response = LOCKED; break; case 501: caldav_response = NOTIMPLEMENTED; break; default: caldav_response = CONFLICT; break; } } else { /* fall-back to conflicting state */ caldav_response = CONFLICT; } } else { result->msg = g_strdup(settings.file); caldav_response = OK; } free_caldav_settings(&settings); return caldav_response; } /** * Function for getting all events from the collection. * @param result A pointer to struct _response where the result is to stored. * @see response. Caller is responsible for freeing the memory. * @param URL Defines CalDAV resource. Receiver is responsible for freeing * the memory. [http://][username[:password]@]host[:port]/url-path. * See (RFC1738). * @return Ok, FORBIDDEN, or CONFLICT. @see CALDAV_RESPONSE */ CALDAV_RESPONSE caldav_getall_object(response* result, const char* URL, runtime_info* info) { caldav_settings settings; CALDAV_RESPONSE caldav_response; g_return_val_if_fail(info != NULL, TRUE); g_return_val_if_fail(result != NULL, NOTIMPLEMENTED); init_runtime(info); init_caldav_settings(&settings); settings.ACTION = GETALL; if (info->options->debug) settings.debug = TRUE; else settings.debug = FALSE; if (info->options->trace_ascii) settings.trace_ascii = 1; else settings.trace_ascii = 0; if (info->options->use_locking) settings.use_locking = 1; else settings.use_locking = 0; parse_url(&settings, URL); gboolean res = make_caldav_call(&settings, info); if (res) { result->msg = NULL; if (info->error->code > 0) { switch (info->error->code) { case 403: caldav_response = FORBIDDEN; break; case 409: caldav_response = CONFLICT; break; case 423: caldav_response = LOCKED; break; case 501: caldav_response = NOTIMPLEMENTED; break; default: caldav_response = CONFLICT; break; } } else { /* fall-back to conflicting state */ caldav_response = CONFLICT; } } else { result->msg = g_strdup(settings.file); caldav_response = OK; } free_caldav_settings(&settings); return caldav_response; } /** * Function for deleting a task. * @param object Appointment following ICal format (RFC2445). Receiver is * responsible for freeing the memory. * @param URL Defines CalDAV resource. Receiver is responsible for freeing * the memory. [http://][username[:password]@]host[:port]/url-path. * See (RFC1738). * @return Ok, FORBIDDEN, or CONFLICT. @see CALDAV_RESPONSE */ CALDAV_RESPONSE caldav_tasks_delete_object(const char* object, const char* URL, runtime_info* info) { caldav_settings settings; CALDAV_RESPONSE caldav_response; g_return_val_if_fail(info != NULL, TRUE); init_runtime(info); init_caldav_settings(&settings); settings.file = g_strdup(object); settings.ACTION = DELETETASKS; if (info->options->debug) settings.debug = TRUE; else settings.debug = FALSE; if (info->options->trace_ascii) settings.trace_ascii = 1; else settings.trace_ascii = 0; if (info->options->use_locking) settings.use_locking = 1; else settings.use_locking = 0; parse_url(&settings, URL); gboolean res = make_caldav_call(&settings, info); if (res) { if (info->error->code > 0) { switch (info->error->code) { case 403: caldav_response = FORBIDDEN; break; case 409: caldav_response = CONFLICT; break; case 423: caldav_response = LOCKED; break; case 501: caldav_response = NOTIMPLEMENTED; break; default: caldav_response = CONFLICT; break; } } else { /* fall-back to conflicting state */ caldav_response = CONFLICT; } } else { caldav_response = OK; } free_caldav_settings(&settings); return caldav_response; } /** * Function for modifying a task. * @param object Appointment following ICal format (RFC2445). Receiver is * responsible for freeing the memory. * @param URL Defines CalDAV resource. Receiver is responsible for freeing * the memory. [http://][username[:password]@]host[:port]/url-path. * See (RFC1738). * @return Ok, FORBIDDEN, or CONFLICT. @see CALDAV_RESPONSE */ CALDAV_RESPONSE caldav_tasks_modify_object(const char* object, const char* URL, runtime_info* info) { caldav_settings settings; CALDAV_RESPONSE caldav_response; g_return_val_if_fail(info != NULL, TRUE); init_runtime(info); init_caldav_settings(&settings); settings.file = g_strdup(object); settings.ACTION = MODIFYTASKS; if (info->options->debug) settings.debug = TRUE; else settings.debug = FALSE; if (info->options->trace_ascii) settings.trace_ascii = 1; else settings.trace_ascii = 0; if (info->options->use_locking) settings.use_locking = 1; else settings.use_locking = 0; parse_url(&settings, URL); gboolean res = make_caldav_call(&settings, info); if (res) { if (info->error->code > 0) { switch (info->error->code) { case 403: caldav_response = FORBIDDEN; break; case 409: caldav_response = CONFLICT; break; case 423: caldav_response = LOCKED; break; case 501: caldav_response = NOTIMPLEMENTED; break; default: caldav_response = CONFLICT; break; } } else { /* fall-back to conflicting state */ caldav_response = CONFLICT; } } else { caldav_response = OK; } free_caldav_settings(&settings); return caldav_response; } /** * Function for getting a collection of tasks determined by time range. * @param result A pointer to struct _response where the result is to stored. * @see response. Caller is responsible for freeing the memory. * @param start time_t variable specifying start and end for range. Both * are included in range. * @param end time_t variable specifying start and end for range. Both * are included in range. * @param URL Defines CalDAV resource. Receiver is responsible for freeing * the memory. [http://][username[:password]@]host[:port]/url-path. * See (RFC1738). * @return Ok, FORBIDDEN, or CONFLICT. @see CALDAV_RESPONSE */ CALDAV_RESPONSE caldav_tasks_get_object(response *result, time_t start, time_t end, const char* URL, runtime_info* info) { caldav_settings settings; CALDAV_RESPONSE caldav_response; g_return_val_if_fail(info != NULL, TRUE); g_return_val_if_fail(result != NULL, NOTIMPLEMENTED); init_runtime(info); init_caldav_settings(&settings); settings.ACTION = GETTASKS; settings.start = start; settings.end = end; if (info->options->debug) settings.debug = TRUE; else settings.debug = FALSE; if (info->options->trace_ascii) settings.trace_ascii = 1; else settings.trace_ascii = 0; if (info->options->use_locking) settings.use_locking = 1; else settings.use_locking = 0; parse_url(&settings, URL); gboolean res = make_caldav_call(&settings, info); if (res) { result->msg = NULL; if (info->error->code > 0) { switch (info->error->code) { case 403: caldav_response = FORBIDDEN; break; case 409: caldav_response = CONFLICT; break; case 423: caldav_response = LOCKED; break; case 501: caldav_response = NOTIMPLEMENTED; break; default: caldav_response = CONFLICT; break; } } else { /* fall-back to conflicting state */ caldav_response = CONFLICT; } } else { result->msg = g_strdup(settings.file); caldav_response = OK; } free_caldav_settings(&settings); return caldav_response; } /** * Function for getting all tasks from the collection. * @param result A pointer to struct _response where the result is to stored. * @see response. Caller is responsible for freeing the memory. * @param URL Defines CalDAV resource. Receiver is responsible for freeing * the memory. [http://][username[:password]@]host[:port]/url-path. * See (RFC1738). * @return Ok, FORBIDDEN, or CONFLICT. @see CALDAV_RESPONSE */ CALDAV_RESPONSE caldav_tasks_getall_object(response* result, const char* URL, runtime_info* info) { caldav_settings settings; CALDAV_RESPONSE caldav_response; g_return_val_if_fail(info != NULL, TRUE); g_return_val_if_fail(result != NULL, NOTIMPLEMENTED); init_runtime(info); init_caldav_settings(&settings); settings.ACTION = GETALLTASKS; if (info->options->debug) settings.debug = TRUE; else settings.debug = FALSE; if (info->options->trace_ascii) settings.trace_ascii = 1; else settings.trace_ascii = 0; if (info->options->use_locking) settings.use_locking = 1; else settings.use_locking = 0; parse_url(&settings, URL); gboolean res = make_caldav_call(&settings, info); if (res) { result->msg = NULL; if (info->error->code > 0) { switch (info->error->code) { case 403: caldav_response = FORBIDDEN; break; case 409: caldav_response = CONFLICT; break; case 423: caldav_response = LOCKED; break; case 501: caldav_response = NOTIMPLEMENTED; break; default: caldav_response = CONFLICT; break; } } else { /* fall-back to conflicting state */ caldav_response = CONFLICT; } } else { result->msg = g_strdup(settings.file); caldav_response = OK; } free_caldav_settings(&settings); return caldav_response; } /** * Function for getting the stored display name for the collection. * @param result A pointer to struct _response where the result is to stored. * @see response. Caller is responsible for freeing the memory. * @param URL Defines CalDAV resource. Receiver is responsible for freeing * the memory. [http://][username[:password]@]host[:port]/url-path. * See (RFC1738). * @return Ok, FORBIDDEN, or CONFLICT. @see CALDAV_RESPONSE */ CALDAV_RESPONSE caldav_get_displayname(response* result, const char* URL, runtime_info* info) { caldav_settings settings; CALDAV_RESPONSE caldav_response; g_return_val_if_fail(info != NULL, TRUE); g_return_val_if_fail(result != NULL, NOTIMPLEMENTED); init_runtime(info); init_caldav_settings(&settings); settings.ACTION = GETCALNAME; if (info->options->debug) settings.debug = TRUE; else settings.debug = FALSE; if (info->options->trace_ascii) settings.trace_ascii = 1; else settings.trace_ascii = 0; if (info->options->use_locking) settings.use_locking = 1; else settings.use_locking = 0; parse_url(&settings, URL); gboolean res = make_caldav_call(&settings, info); if (res) { result->msg = NULL; if (info->error->code > 0) { switch (info->error->code) { case 403: caldav_response = FORBIDDEN; break; case 409: caldav_response = CONFLICT; break; case 423: caldav_response = LOCKED; break; case 501: caldav_response = NOTIMPLEMENTED; break; default: caldav_response = CONFLICT; break; } } else { /* fall-back to conflicting state */ caldav_response = CONFLICT; } } else { result->msg = g_strdup(settings.file); caldav_response = OK; } free_caldav_settings(&settings); return caldav_response; } /** * Function to test wether a calendar resource is CalDAV enabled or not. * @param URL Defines CalDAV resource. Receiver is responsible for * freeing the memory. [http://][username[:password]@]host[:port]/url-path. * See (RFC1738). * @result 0 (zero) means no CalDAV support, otherwise CalDAV support * detechted. */ int caldav_enabled_resource(const char* URL, runtime_info* info) { CURL* curl; caldav_settings settings; struct config_data data; g_return_val_if_fail(info != NULL, TRUE); init_runtime(info); init_caldav_settings(&settings); parse_url(&settings, URL); curl = get_curl(&settings); if (!curl) { info->error->code = -1; info->error->str = g_strdup("Could not initialize libcurl"); settings.file = NULL; return TRUE; } if (info->options->trace_ascii) data.trace_ascii = 1; else data.trace_ascii = 0; if (info->options->use_locking) settings.use_locking = 1; else settings.use_locking = 0; if (info->options->debug) { curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace); curl_easy_setopt(curl, CURLOPT_DEBUGDATA, &data); curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); } gboolean res = test_caldav_enabled(curl, &settings, info->error); free_caldav_settings(&settings); curl_easy_cleanup(curl); return (res && (info->error->code == 0 || info->error->code == 200)) ? 1 : 0; } /** * Function for getting free/busy information. * @param result A pointer to struct _response where the result is to stored. * @see response. Caller is responsible for freeing the memory. * @param start time_t variable specifying start and end for range. Both * are included in range. * @param end time_t variable specifying start and end for range. Both * are included in range. * @param URL Defines CalDAV resource. Receiver is responsible for freeing * the memory. [http://][username[:password]@]host[:port]/url-path. * See (RFC1738). * @return Ok, FORBIDDEN, or CONFLICT. @see CALDAV_RESPONSE */ CALDAV_RESPONSE caldav_get_freebusy(response *result, time_t start, time_t end, const char* URL, runtime_info* info) { caldav_settings settings; CALDAV_RESPONSE caldav_response; g_return_val_if_fail(info != NULL, TRUE); g_return_val_if_fail(result != NULL, NOTIMPLEMENTED); init_runtime(info); init_caldav_settings(&settings); settings.ACTION = FREEBUSY; settings.start = start; settings.end = end; if (info->options->debug) settings.debug = TRUE; else settings.debug = FALSE; if (info->options->trace_ascii) settings.trace_ascii = 1; else settings.trace_ascii = 0; if (info->options->use_locking) settings.use_locking = 1; else settings.use_locking = 0; parse_url(&settings, URL); gboolean res = make_caldav_call(&settings, info); if (res) { result->msg = NULL; if (info->error->code > 0) { switch (info->error->code) { case 403: caldav_response = FORBIDDEN; break; case 409: caldav_response = CONFLICT; break; case 423: caldav_response = LOCKED; break; case 501: caldav_response = NOTIMPLEMENTED; break; default: caldav_response = CONFLICT; break; } } else { /* fall-back to conflicting state */ caldav_response = CONFLICT; } } else { result->msg = g_strdup(settings.file); caldav_response = OK; } free_caldav_settings(&settings); return caldav_response; } /** * Function which supports sending various options inside the library. * @param curl_options A struct debug_curl. See debug_curl. */ void caldav_set_options(debug_curl curl_options) { } /** * @deprecated Function to call in case of errors. * Caller provides a pointer to a local caldav_error structure. * Caldav_get_error will initialize pointer if NULL. * Caller is responsible for freeing returned memory. * After the first call the internal error buffer is reset. * @param lib_error A pointer to a struct _caldav_error. @see _caldav_error * @return An initialized caldav_error pointer to memory where error * messages can be found from the last call to the library. */ caldav_error* caldav_get_error(caldav_error* lib_error) { if (!lib_error) { lib_error = g_new0(caldav_error, 1); } return lib_error; } /** * Function for freeing memory for a previous initialization of a * caldav_error. @see caldav_get_error() * Caller provides a pointer to a local caldav_error structure. * @param lib_error A pointer to a struct _caldav_error. @see _caldav_error */ void caldav_free_error(caldav_error* lib_error) { if (lib_error->str) g_free(lib_error->str); g_free(lib_error); lib_error = NULL; } /** * Function to call to get a list of supported CalDAV options for a server * @param URL Defines CalDAV resource. Receiver is responsible for * freeing the memory. [http://][username[:password]@]host[:port]/url-path. * See (RFC1738). * @result A list of available options or NULL in case of any error. */ char** caldav_get_server_options(const char* URL, runtime_info* info) { CURL* curl; caldav_settings settings; response server_options; gchar** option_list = NULL; gchar** tmp; gboolean res = FALSE; g_return_val_if_fail(info != NULL, NULL); init_runtime(info); tmp = option_list = NULL; init_caldav_settings(&settings); parse_url(&settings, URL); curl = get_curl(&settings); if (!curl) { info->error->code = -1; info->error->str = g_strdup("Could not initialize libcurl"); settings.file = NULL; return NULL; } if (info->options->use_locking) settings.use_locking = 1; else settings.use_locking = 0; res = caldav_getoptions(curl, &settings, &server_options, info->error, FALSE); if (res) { if (server_options.msg) { option_list = g_strsplit(server_options.msg, ", ", 0); tmp = &(*(option_list)); while (*tmp) { g_strstrip(*tmp++); } } } free_caldav_settings(&settings); curl_easy_cleanup(curl); return (option_list) ? option_list : NULL; } /** * Function for getting an initialized runtime_info structure * @return runtime_info. @see runtime_info */ runtime_info* caldav_get_runtime_info() { runtime_info* rt_info; rt_info = g_new0(runtime_info, 1); rt_info->error = g_new0(caldav_error, 1); rt_info->options = g_new0(debug_curl, 1); return rt_info; } /** * Function for freeing memory for a previous initialization of an info * structure * @param info Address to a pointer to a runtime_info structure. @see * runtime_info */ void caldav_free_runtime_info(runtime_info** info) { runtime_info* ri; if (*info) { ri = *info; if (ri->error) { if (ri->error->str) g_free(ri->error->str); g_free(ri->error); ri->error = NULL; } if (ri->options) { if (ri->options->custom_cacert) g_free(ri->options->custom_cacert); g_free(ri->options); ri->options = NULL; } g_free(ri); *info = ri = NULL; } } /** * Function for getting an initialized response structure * @return response. @see _response */ response* caldav_get_response() { response* r; r = g_new0(response, 1); return r; } /** * Function for freeing memory for a previous initialization of an response * structure * @param info Address to a pointer to a response structure. @see * _response */ void caldav_free_response(response** resp) { response* r; if (*resp) { r = *resp; if (r->msg) g_free(r->msg); g_free(r); *resp = r = NULL; } }