trg_response *dispatch_public_http(TrgClient *tc, trg_request *req) {
	trg_response *response = g_new0(trg_response, 1);
    CURL* curl = get_curl(tc, HTTP_CLASS_PUBLIC);
    struct curl_slist *headers = NULL;
    long httpCode = 0;
    gchar *cookie_header = NULL;

    response->size = 0;
    response->raw = NULL;

	curl_easy_setopt(curl, CURLOPT_URL, req->url);
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) response);

	if (req->cookie) {
		cookie_header = g_strdup_printf("Cookie: %s", req->cookie);
		headers = curl_slist_append(NULL, cookie_header);
	}

	if (headers)
		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

    response->status = curl_easy_perform(curl);

    trg_request_free(req);

    g_free(cookie_header);

    if (headers)
    	curl_slist_free_all(headers);

    //g_message(response->raw);

    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);

    if (response->status == CURLE_OK && httpCode != HTTP_OK) {
      response->status = (-httpCode) - 100;
    }

	return response;
}
static inline int
trg_http_perform_inner(TrgClient * tc, trg_request * request,
                       trg_response * response, gboolean recurse)
{
    CURL* curl = get_curl(tc, HTTP_CLASS_TRANSMISSION);
	struct curl_slist *headers = NULL;
	gchar *session_id = NULL;
    long httpCode = 0;

    response->size = 0;
    response->raw = NULL;

    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request->body);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) response);

	session_id = trg_client_get_session_id(tc);
	if (session_id)
		headers = curl_slist_append(NULL, session_id);

	curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

    response->status = curl_easy_perform(curl);

    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);

    g_free(session_id);

    if (headers)
    	curl_slist_free_all(headers);

    if (response->status == CURLE_OK) {
        if (httpCode == HTTP_CONFLICT && recurse == TRUE)
            return trg_http_perform_inner(tc, request, response, FALSE);
        else if (httpCode != HTTP_OK)
            response->status = (-httpCode) - 100;
    }

    return response->status;
}
示例#3
0
/**
 * 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;
}
示例#4
0
/* 
 * @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;
}
示例#5
0
/**
 * Function for getting freebusy within a time range from collection.
 * @param settings A pointer to caldav_settings. @see caldav_settings
 * @param error A pointer to caldav_error. @see caldav_error
 * @return TRUE in case of error, FALSE otherwise.
 */
gboolean caldav_freebusy(caldav_settings* settings, caldav_error* error) {
	CURL* curl;
	CURLcode res = 0;
	char error_buf[CURL_ERROR_SIZE + 1];
	struct config_data data;
	struct MemoryStruct chunk;
	struct MemoryStruct headers;
	struct curl_slist *http_header = NULL;
	gboolean result = FALSE;
	gchar* request = NULL;

	chunk.memory = NULL; /* we expect realloc(NULL, size) to work */
	chunk.size = 0;    /* no data at this point */
	headers.memory = NULL;
	headers.size = 0;

	curl = get_curl(settings);
	if (!curl) {
		error->code = -1;
		error->str = g_strdup("Could not initialize libcurl");
		g_free(settings->file);
		settings->file = NULL;
		return TRUE;
	}

	http_header = curl_slist_append(http_header,
			"Content-Type: application/xml; charset=\"utf-8\"");
	http_header = curl_slist_append(http_header, "Depth: 1");
	http_header = curl_slist_append(http_header, "Expect:");
	http_header = curl_slist_append(http_header, "Transfer-Encoding:");
	http_header = curl_slist_append(http_header, "Connection: close");
	data.trace_ascii = settings->trace_ascii;
	curl_easy_setopt(curl, CURLOPT_HTTPHEADER, http_header);
	/* send all data to this function  */
	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
	/* we pass our 'chunk' struct to the callback function */
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
	/* send all data to this function  */
	curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION,	WriteHeaderCallback);
	/* we pass our 'headers' struct to the callback function */
	curl_easy_setopt(curl, CURLOPT_WRITEHEADER, (void *)&headers);
	curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, (char *) &error_buf);
	if (settings->debug) {
		curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace);
		curl_easy_setopt(curl, CURLOPT_DEBUGDATA, &data);
		curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
	}
	request = g_strdup_printf(
		"%s\r\n<C:time-range start=\"%s\"\r\n end=\"%s\"/>\r\n%s",
			getrange_request_head, get_caldav_datetime(&settings->start),
			get_caldav_datetime(&settings->end), getrange_request_foot);
	/* enable uploading */
	curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request);
	curl_easy_setopt (curl, CURLOPT_POSTFIELDSIZE, strlen(request));
	curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "REPORT");
	curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
	curl_easy_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, 1);
	curl_easy_setopt(curl, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL);
	res = curl_easy_perform(curl);
	if (res != 0) {
		error->code = -1;
		error->str = g_strdup_printf("%s", error_buf);
		g_free(settings->file);
		settings->file = NULL;
		result = TRUE;
	}
	else {
		long code;
		res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
		if (code != 200) {
			error->code = code;
			error->str = g_strdup(headers.memory);
			result = TRUE;
		}
		else {
			/*gchar* report;
			report = parse_caldav_report(chunk.memory, "calendar-data", "VFREEBUSY");
			settings->file = g_strdup(report);*/
			settings->file = g_strdup(chunk.memory);
			/*g_free(report);*/
		}
	}
	g_free(request);
	if (chunk.memory)
		free(chunk.memory);
	if (headers.memory)
		free(headers.memory);
	curl_slist_free_all(http_header);
	curl_easy_cleanup(curl);
	return result;
}
示例#6
0
/**
 * Function for modifying an event.
 * @param settings A pointer to caldav_settings. @see caldav_settings
 * @param error A pointer to caldav_error. @see caldav_error
 * @return TRUE in case of error, FALSE otherwise.
 */
gboolean caldav_modify(caldav_settings* settings, caldav_error* error) {
	CURL* curl;
	CURLcode res = 0;
	char error_buf[CURL_ERROR_SIZE];
	struct config_data data;
	struct MemoryStruct chunk;
	struct MemoryStruct headers;
	struct curl_slist *http_header = NULL;
	gchar* search;
	gchar* uid;
	gboolean result = FALSE;
	gboolean LOCKSUPPORT = FALSE;
	gchar* lock_token = NULL;

	chunk.memory = NULL; /* we expect realloc(NULL, size) to work */
	chunk.size = 0;    /* no data at this point */
	headers.memory = NULL;
	headers.size = 0;

	curl = get_curl(settings);
	if (!curl) {
		error->code = -1;
		error->str = g_strdup("Could not initialize libcurl");
		g_free(settings->file);
		settings->file = NULL;
		return TRUE;
	}

	http_header = curl_slist_append(http_header,
			"Content-Type: application/xml; charset=\"utf-8\"");
	http_header = curl_slist_append(http_header, "Depth: 1");
	http_header = curl_slist_append(http_header, "Expect:");
	http_header = curl_slist_append(http_header, "Transfer-Encoding:");
	http_header = curl_slist_append(http_header, "Connection: close");
	data.trace_ascii = settings->trace_ascii;
	curl_easy_setopt(curl, CURLOPT_HTTPHEADER, http_header);
	/* send all data to this function  */
	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
	/* we pass our 'chunk' struct to the callback function */
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
	/* send all data to this function  */
	curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION,	WriteHeaderCallback);
	/* we pass our 'headers' struct to the callback function */
	curl_easy_setopt(curl, CURLOPT_WRITEHEADER, (void *)&headers);
	curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, (char *) &error_buf);
	if (settings->debug) {
		curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace);
		curl_easy_setopt(curl, CURLOPT_DEBUGDATA, &data);
		curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
	}
	gchar* file = g_strdup(settings->file);
	if ((uid = get_response_header("uid", file, FALSE)) == NULL) {
		g_free(file);
		error->code = 1;
		error->str = g_strdup("Error: Missing required UID for object");
		return TRUE;
	}
	g_free(file);
	/*
	 * collation is not supported by ICalendar.
	 * <C:text-match collation=\"i;ascii-casemap\">%s</C:text-match>
	 */
	search = g_strdup_printf(
		"%s\r\n<C:text-match>%s</C:text-match>\r\n%s",
		search_head, uid, search_tail);
	g_free(uid);
	/* enable uploading */
	curl_easy_setopt(curl, CURLOPT_POSTFIELDS, search);
	curl_easy_setopt (curl, CURLOPT_POSTFIELDSIZE, strlen(search));
	curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "REPORT");
	curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
	curl_easy_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, 1);
	curl_easy_setopt(curl, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL);
	res = curl_easy_perform(curl);
	curl_slist_free_all(http_header);
	http_header = NULL;
	g_free(search);
	if (res != 0) {
		error->code = -1;
		error->str = g_strdup_printf("%s", error_buf);
		g_free(settings->file);
		settings->file = NULL;
		result = TRUE;
	}
	else {
		long code;
		res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
		if (code != 207) {
			error->code = code;
			error->str = g_strdup(chunk.memory);
			result = TRUE;
		}
		else {
			/* enable uploading */
			gchar* url = NULL;
			gchar* etag = NULL;
			url = get_url(chunk.memory);
			if (url) {
				etag = get_etag(chunk.memory);
				if (etag) {
					gchar* host = get_host(settings->url);
					if (host) {
						file = g_strdup(url);
						g_free(url);
						url = g_strdup_printf("%s%s", host, file);
						g_free(file);
						g_free(host);
					}
					else {
						g_free(etag);
						g_free(url);
						url = NULL;
					}
				}
				else {
					g_free(url);
					url = NULL;
				}
				if (url) {
					int lock = 0;
					caldav_error lock_error;
	
					file = g_strdup(etag);
					g_free(etag);
					etag = g_strdup_printf("If-Match: %s", file);
					g_free(file);
					http_header = curl_slist_append(http_header, etag);
					g_free(etag);
					http_header = curl_slist_append(http_header,
						"Content-Type: text/calendar; charset=\"utf-8\"");
					http_header = curl_slist_append(http_header, "Expect:");
					http_header = curl_slist_append(
									http_header, "Transfer-Encoding:");
					http_header = curl_slist_append(http_header, "Connection: close");
					if (settings->use_locking)
						LOCKSUPPORT = caldav_lock_support(settings, &lock_error);
					else
						LOCKSUPPORT = FALSE;
					if (LOCKSUPPORT) {
						lock_token = caldav_lock_object(url, settings, &lock_error);
						if (lock_token) {
							http_header = curl_slist_append(
								http_header, g_strdup_printf(
										"If: (%s)", lock_token));
						}
						/*
						 * If error code is 423 (Resource is LOCKED) bail out
						 */
						else if (lock_error.code == 423) {
							lock = -1;
						}
						/*
						 * If error code is 501 (Not implemented) we continue
						 * hoping for the best.
						 */
						else if (lock_error.code == 501) {
							lock_token = g_strdup("");
						}
						else {
							lock = -1;
						}
					}
					if (! LOCKSUPPORT || (LOCKSUPPORT && lock_token && lock_error.code != 423)) {
						curl_easy_setopt(curl, CURLOPT_HTTPHEADER, http_header);
						curl_easy_setopt(curl, CURLOPT_URL, rebuild_url(settings, url));
						curl_easy_setopt(curl, CURLOPT_POSTFIELDS, settings->file);
						curl_easy_setopt (curl, CURLOPT_POSTFIELDSIZE, 
									strlen(settings->file));
						curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
						curl_easy_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, 1);
						curl_easy_setopt(curl, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL);
						curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
						res = curl_easy_perform(curl);
						if (LOCKSUPPORT && lock_token) {
							caldav_unlock_object(
									lock_token, url, settings, &lock_error);
						}
					}
					g_free(url);
					g_free(lock_token);
					if (res != 0 || lock < 0) {
						/* Is this a lock_error don't change error*/
						if (lock == 0 || lock_error.code == 423) {
							error->code = code;
							error->str = g_strdup(chunk.memory);
						}
						else {
							error->code = lock_error.code;
							error->str = g_strdup(lock_error.str);
						}
						result = TRUE;
						g_free(settings->file);
						settings->file = NULL;
					}
					else {
						long code;
						res = curl_easy_getinfo(
									curl, CURLINFO_RESPONSE_CODE, &code);
						if (code != 204) {
							error->code = code;
							error->str = g_strdup(chunk.memory);
							result = TRUE;
						}
					}
					curl_slist_free_all(http_header);
				}
				else {
					error->code = code;
					if (chunk.memory)
						error->str = g_strdup(chunk.memory);
					else
						error->str = g_strdup("No object found");
					result = TRUE;
				}
			}
			else {
				/* 
				 * No object found on server. Posible synchronization
				 * problem or a server side race condition
				 */
				error->code = 409;
				error->str = g_strdup("No object found");
				result = TRUE;
			}
		}
	}
	if (chunk.memory)
		free(chunk.memory);
	if (headers.memory)
		free(headers.memory);
	curl_easy_cleanup(curl);
	return result;
}