commit db78609f0232098e966c0334988989e965a9274b
parent 9848cad2719b83f1ce4c674d67b7773e7fbe6b4c
Author: Andreas Gruhler <agruhl@gmx.ch>
Date: Mon, 17 May 2021 09:19:59 +0200
extract_json_value and download_event
Diffstat:
M | caldav.c | | | 171 | ++++++++++++++++++++++++++++++++++++++----------------------------------------- |
M | caldav.h | | | 1 | + |
M | utils.c | | | 24 | ++++++++++++++++++++++++ |
M | utils.h | | | 2 | ++ |
4 files changed, 109 insertions(+), 89 deletions(-)
diff --git a/caldav.c b/caldav.c
@@ -77,65 +77,6 @@ char* extract_oauth_code(char* http_header) {
return res;
}
-// Extract OAuth2 token from json response
-char* extract_oauth_token(char* json) {
- char* res = (char *) malloc(strlen(json) * sizeof(char));
- strcpy(res, json);
-
- // example json:
- // {
- // "access_token": "ya29.a0AfH6SMB1xpfVS6OdyRop3OjdetuwizbG1B83wRhQMxEym0fMf9HYwKBs_ulSgZSOMgH-FRcVGEGAnVPCaKjs0afExqAuy-aOQbBu2v4uu42V7Juwb11FDqftuVJpTjErVY_KWk1yG0EgzmVAlVZK8YsxQlPB",
- // "expires_in": 3599,
- // "refresh_token": "1//09hh-LM2w29NNCgYIARAAGAkSNwF-L9Ir_cOriqpjUHd97eiWNywBWjFiMRshfxlQFxpDIg8XqhK4OasuxGlro0r1XK1OuprSlNc",
- // "scope": "https://www.googleapis.com/auth/calendar",
- // "token_type": "Bearer"
- // }
- res = strtok(res, " ");
- while (res != NULL) {
- if (strstr(res, "access_token") != NULL) {
- res = strtok(NULL, " "); // token value
- res = strtok(res, "\"");
- break;
- }
- res = strtok(NULL, " ");
- }
- return res;
-}
-
-// Extract OAuth2 token ttl
-int extract_oauth_token_ttl(char* json) {
- char* res = (char *) malloc(strlen(json) * sizeof(char));
- strcpy(res, json);
-
- res = strtok(res, " ");
- while (res != NULL) {
- if (strstr(res, "expires_in") != NULL) {
- res = strtok(NULL, " "); // ttl
- res = strtok(res, ",");
- break;
- }
- res = strtok(NULL, " ");
- }
- return atoi(res);
-}
-
-// Extract OAuth2 refresh token from json response
-char* extract_oauth_refresh_token(char* json) {
- char* res = (char *) malloc(strlen(json) * sizeof(char));
- strcpy(res, json);
-
- res = strtok(json, " ");
- while (res != NULL) {
- if (strstr(res, "refresh_token") != NULL) {
- res = strtok(NULL, " "); // token value
- res = strtok(res, "\"");
- break;
- }
- res = strtok(NULL, " ");
- }
- return res;
-}
-
// todo: refresh OAuth2 access token
char* refresh_access_token(char* refresh_token) {
return "not implemented";
@@ -154,18 +95,20 @@ void read_tokenfile() {
fseek(token_file, 0, SEEK_END);
token_bytes = ftell(token_file);
- fseek(token_file, 0L, SEEK_SET);
-
- token_buff = (char*)calloc(token_bytes, sizeof(char));
- fread(token_buff, sizeof(char), token_bytes, token_file);
+ rewind(token_file);
+
+ token_buff = malloc(token_bytes);
+ if (token_buff != NULL) {
+ fread(token_buff, sizeof(char), token_bytes, token_file);
+
+ access_token = extract_json_value(token_buff, "access_token", true);
+ token_ttl = extract_json_value(token_buff, "expires_in", false);
+ refresh_token = extract_json_value(token_buff, "refresh_token", true);
+ fprintf(stderr, "Access token: %s\n", access_token);
+ fprintf(stderr, "Token TTL: %i\n", token_ttl);
+ fprintf(stderr, "Refresh token: %s\n", refresh_token);
+ }
fclose(token_file);
-
- access_token = extract_oauth_token(token_buff);
- token_ttl = extract_oauth_token_ttl(token_buff);
- refresh_token = extract_oauth_refresh_token(token_buff);
- fprintf(stderr, "Access token: %s\n", access_token);
- fprintf(stderr, "Token TTL: %i\n", token_ttl);
- fprintf(stderr, "Refresh token: %s\n", refresh_token);
}
void get_access_token_from_code(char* code, char* verifier) {
@@ -183,11 +126,6 @@ void get_access_token_from_code(char* code, char* verifier) {
curl = curl_easy_init();
- // https://curl.se/libcurl/c/getinmemory.html
- //struct curl_mem_chunk token_result;
- //token_result.memory = malloc(1);
- //token_result.size = 0;
-
FILE* tokenfile;
char* tokenfile_path;
@@ -195,8 +133,6 @@ void get_access_token_from_code(char* code, char* verifier) {
curl_easy_setopt(curl, CURLOPT_URL, GOOGLE_OAUTH_TOKEN_URL);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postfields);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
- //curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_mem_callback);
- //curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&token_result);
tokenfile_path = expand_path(CONFIG.google_tokenfile);
tokenfile = fopen(tokenfile_path, "wb");
@@ -375,26 +311,83 @@ char* get_oauth_code(const char* verifier, WINDOW* header) {
return code;
}
+char* download_event(struct tm* date) {
+ CURLcode res;
+
+ curl = curl_easy_init();
+
+ // https://curl.se/libcurl/c/getinmemory.html
+ struct curl_mem_chunk event_result;
+ event_result.memory = malloc(1);
+ event_result.size = 0;
+
+ if (curl) {
+ struct curl_slist *header = NULL;
+ char bearer_token[strlen("Authorization: Bearer")+strlen(access_token)];
+
+ sprintf(bearer_token, "Authorization: Bearer %s", access_token);
+ header = curl_slist_append(header, "Depth: 0");
+ header = curl_slist_append(header, bearer_token);
+
+ char* postfields = "<d:propfind xmlns:d='DAV:' xmlns:cs='http://calendarserver.org/ns/'>"
+ "<d:prop><d:current-user-principal/></d:prop>"
+ "</d:propfind>";
+
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PROPFIND");
+ curl_easy_setopt(curl, CURLOPT_URL, GOOGLE_CALDAV_URI);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postfields);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_mem_callback);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&event_result);
+
+ res = curl_easy_perform(curl);
+
+ if (res != CURLE_OK) {
+ fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
+ }
+
+ fprintf(stderr, "Curl retrieved %lu bytes\n", (unsigned long)event_result.size);
+ fprintf(stderr, "Curl content: %s\n", event_result.memory);
+
+ curl_easy_cleanup(curl);
+ }
+ return event_result.memory;
+}
+
+void upload_event(struct tm* date) {
+
+}
+
void caldav_sync(struct tm* date, WINDOW* header) {
// fetch existing API tokens
read_tokenfile();
// check if we can use the existing token
+ if (access_token == NULL) {
+ // create new verifier
+ char challenge[GOOGLE_OAUTH_CODE_VERIFIER_LENGTH];
+ random_code_challenge(GOOGLE_OAUTH_CODE_VERIFIER_LENGTH, challenge);
+ fprintf(stderr, "Challenge/Verifier: %s\n", challenge);
+
+ // fetch new code with verifier
+ char* code = get_oauth_code(challenge, header);
+ if (code == NULL) {
+ fprintf(stderr, "Error retrieving access code.\n");
+ return;
+ }
- // create new verifier
- char challenge[GOOGLE_OAUTH_CODE_VERIFIER_LENGTH];
- random_code_challenge(GOOGLE_OAUTH_CODE_VERIFIER_LENGTH, challenge);
- fprintf(stderr, "Challenge/Verifier: %s\n", challenge);
-
- // fetch new code with verifier
- char* code = get_oauth_code(challenge, header);
- if (code == NULL) {
- fprintf(stderr, "Error retrieving access code.\n");
- return;
+ // get acess token using code and verifier
+ get_access_token_from_code(code, challenge);
}
- // get acess token using code and verifier
- get_access_token_from_code(code, challenge);
+ char* event = download_event(date);
+ // check LAST-MODIFIED
+ fprintf(stderr, "\nEvent: %s\n\n", event);
+
+ // if local file mod time more recent than LAST-MODIFIED
+ upload_event(date);
+
+ // else persist downloaded buffer to local file
char dstr[16];
mktime(date);
diff --git a/caldav.h b/caldav.h
@@ -31,6 +31,7 @@
#define GOOGLE_OAUTH_REDIRECT_PORT 9004
#define GOOGLE_OAUTH_REDIRECT_URI "http://" GOOGLE_OAUTH_REDIRECT_HOST ":" MKSTR(GOOGLE_OAUTH_REDIRECT_PORT)
#define GOOGLE_OAUTH_REDIRECT_SOCKET_BACKLOG 10
+#define GOOGLE_CALDAV_URI "https://apidata.googleusercontent.com/caldav/v2"
void caldav_sync(struct tm* date, WINDOW* header);
diff --git a/utils.c b/utils.c
@@ -1,5 +1,29 @@
#include "utils.h"
+char* extract_json_value(char* json, char* key, bool quoted) {
+ // work on a copy of the json
+ char* tok = (char *) malloc(strlen(json) * sizeof(char));
+ strcpy(tok, json);
+
+ tok = strtok(json, " ");
+ while (tok != NULL) {
+ if (strstr(tok, key) != NULL) {
+ tok = strtok(NULL, " "); // value
+ break;
+ }
+ // key was not in this tok, advance tok
+ tok = strtok(NULL, " ");
+ }
+
+ // remove quotes and comma or commma only
+ if (quoted) {
+ tok = strtok(tok, "\"");
+ } else {
+ tok = strtok(tok, ",");
+ }
+ return tok;
+}
+
// Return expanded file path
char* expand_path(char* str) {
char* res;
diff --git a/utils.h b/utils.h
@@ -5,6 +5,7 @@
#include <time.h>
#include <string.h>
#include <wordexp.h>
+#include <stdbool.h>
#define GOOGLE_OAUTH_TOKEN_FILE "~/.diary-token"
#ifndef GOOGLE_OAUTH_CLIENT_ID
@@ -14,6 +15,7 @@
#define GOOGLE_OAUTH_CLIENT_SECRET ""
#endif
+char* extract_json_value(char* json, char* key, bool quoted);
char* expand_path(char* str);
typedef struct