commit dfa6876fe79a49cbd2faaa2fb7250e346057d57f
parent 3014f4b315e5e0c40c015499b2e80e1728e1fd31
Author: Bharatvaj <bharatvaj@yahoo.com>
Date: Wed, 20 Apr 2022 23:30:56 +0530
Add qlic_oauth.h
Add config.h for storing compile time values
Handle basic argument parsing for testing
Diffstat:
12 files changed, 170 insertions(+), 27 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,5 +1,5 @@
-qlic: qlic.c
- $(CC) qlic.c qlic_response_handler.c qlic_common.c cliq_apis.c -o qlic -I. -lcurl -g
+qlic: qlic.c qlic_response_handler.* qlic_common.* cliq_apis.* qlic_oauth.h
+ $(CC) qlic.c qlic_response_handler.c qlic_common.c cliq_apis.c -o qlic -I. -I${HOME}/sysroot/include -L${HOME}/sysroot/lib -lnxjson -loauth -lcurl -g
test: qlic
./qlic -r
diff --git a/cliq_apis.c b/cliq_apis.c
@@ -3,13 +3,12 @@
#include <stdio.h>
#include <stdlib.h>
-#define __QLIC_SEND_MESSAGE_STR "https://cliq.zoho.com/api/v2/chats/%s/message"
QlicString* qlic_send_message_str(QlicString* chat_id) {
+#define __QLIC_SEND_MESSAGE_API_STR "https://cliq.zoho.com/api/v2/chats/%s/message"
QlicString* send_message = init_qlic_string();
- // tenet moment
// minus 2 for removing the format specifier :(
- send_message->len = sizeof(__QLIC_SEND_MESSAGE_STR) + chat_id->len - 2;
- send_message->string = (char*)malloc(send_message->len);
- snprintf(send_message->string, send_message->len, __QLIC_SEND_MESSAGE_STR, chat_id->string);
+ send_message->len = sizeof(__QLIC_SEND_MESSAGE_API_STR) + chat_id->len - 2;
+ send_message->string = (char *)malloc(send_message->len * sizeof(char));
+ snprintf(send_message->string, send_message->len, __QLIC_SEND_MESSAGE_API_STR, chat_id->string);
return send_message;
}
diff --git a/config.h b/config.h
@@ -0,0 +1,11 @@
+#ifndef __CLIQ_CONFIG_H
+#define __CLIQ_CONFIG_H
+#define CLIQ_AUTH_ENDPOINT "https://accounts.zoho.com/oauth/v2/auth"
+#define CLIQ_TOKEN_ENDPOINT "https://accounts.zoho.com/oauth/v2/token"
+
+#define CLIQ_CLIENT_ID ""
+#define CLIQ_CLIENT_SECRET ""
+#define CLIQ_REDIRECT_URI "https://127.0.0.1:8443/hello"
+#define CLIQ_SCOPE "ZohoCliq.Chats.READ,ZohoCliq.Messages.READ,ZohoCliq.Webhooks.CREATE"
+
+#endif
diff --git a/config.json b/config.json
@@ -0,0 +1,6 @@
+{
+ "user_id": {
+ "client_id": "",
+ "client_secret": ""
+ }
+}
diff --git a/qlic.c b/qlic.c
@@ -4,27 +4,44 @@
#include <qlic_common.h>
#include <cliq_apis.h>
#include <qlic_response_handler.h>
+#include <qlic_oauth.h>
+int qlic_send_text_msg(const char* __access_token, const char* __chat_id) {
+ QlicString* access_token = NULL;
+ access_token = init_qlic_string();
+ access_token->len = strlen(__access_token);
+ access_token->string = (char*)malloc(access_token->len * sizeof(__access_token));
+ strncpy(access_token->string, __access_token, access_token->len);
+ QlicContext* qlic_context = qlic_context_access_init(access_token);
+ if (qlic_context == NULL) {
+ qlic_error("Cannot init network library");
+ return -1;
+ }
+ QlicString* chat_id = init_qlic_string();
+ __QLIC_ASSIGN_STRING(chat_id, __chat_id);
+ qlic_context->request_url = qlic_send_message_str(chat_id);
+ qlic_request(qlic_context, qlic_handle_send_message, true);
+ return 0;
+}
// TODO Send error back
-#define __QLIC_ACCESS_TOKEN "Zoho-oauthtoken "
int main(int argc, char* argv[]) {
- QlicString* access_token = init_qlic_string();
- __QLIC_ASSIGN_STRING(access_token, __QLIC_ACCESS_TOKEN);
if (argc == 1) {
qlic_error("Not enough arguments");
return -1;
}
+ // TODO Use an argument parsing library
if (strcmp(argv[1], "-r") == 0) {
- QlicContext* qlic_context = qlic_context_access_init(access_token);
- if (qlic_context == NULL) {
- qlic_error("Cannot init network library");
+ // TODO read access_token from state.json
+ char* access_token = "1000.429cf5132d6cc978960bfdd6e0a425cc.80bbd5584b0c35133c4f82143e6811b2";
+ // FIXME possible buffer overflow here
+ qlic_send_text_msg(access_token, argv[2]);
+ } else if (strcmp(argv[1], "-a") == 0) {
+ char* access_token = start_oauth_server();
+ if (access_token == NULL) {
+ qlic_error("Access token is empty, authentication failed");
return -1;
}
- QlicString* chat_id = init_qlic_string();
- __QLIC_ASSIGN_STRING(chat_id, "2243227993181997558");
- qlic_context->request_url = qlic_send_message_str(chat_id);
- qlic_request(qlic_context, qlic_handle_send_message, true);
}
return 0;
}
diff --git a/qlic_common.c b/qlic_common.c
@@ -2,6 +2,7 @@
#include <curl/curl.h>
#include <stdlib.h>
#include <string.h>
+#include <qlic_response_handler.h>
void qlic_error(const char* error_message) {
fprintf(stderr, error_message);
@@ -13,8 +14,8 @@ static struct curl_slist* __qlic_set_request_headers(QlicContext* context, QlicS
return NULL;
}
struct curl_slist* list = NULL;
-#define __QLIC_AUTHORIZATION_HEADER "Authorization: "
- // TODO cleanup authorization_header if curl doesn't handle it?
+#define __QLIC_AUTHORIZATION_HEADER "Authorization: Zoho-oauthtoken "
+ // TODO free up authorization_header if curl doesn't handle
size_t authorization_header_len = sizeof(__QLIC_AUTHORIZATION_HEADER) + access_token->len;
char* authorization_header = (char*)malloc(authorization_header_len);
strncpy(authorization_header, __QLIC_AUTHORIZATION_HEADER, sizeof(__QLIC_AUTHORIZATION_HEADER));
@@ -67,12 +68,15 @@ void qlic_request(QlicContext* context, qlic_response_callback callback, bool is
CURL* curl = (CURL*)context->context;
CURLcode res;
curl_easy_setopt(curl, CURLOPT_URL, context->request_url->string);
- /* curl_easy_setopt(curl, CURLOPT_GET, 1); */
/* curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); */
- curl_easy_setopt(curl, CURLOPT_READFUNCTION, callback);
if (is_post_request) {
curl_easy_setopt(curl, CURLOPT_POST, 1);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "{\"text\": \"Hi\"}");
}
+ /* curl_easy_setopt(curl, CURLOPT_READFUNCTION, qlic_handle_read_chat); */
+ /* curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); */
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, curl);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
diff --git a/qlic_common.h b/qlic_common.h
@@ -6,7 +6,7 @@
#define __QLIC_ASSIGN_STRING(X,Y) \
X->string = Y; \
- X->len = sizeof(Y);
+ X->len = strlen(Y);
void qlic_error(const char* error_message);
diff --git a/qlic_oauth.h b/qlic_oauth.h
@@ -0,0 +1,91 @@
+#ifndef __QLIC_OAUTH_H
+#define __QLIC_OAUTH_H
+
+#include <oauth2.h>
+#include <stdio.h>
+#include <config.h>
+#include <nxjson.h>
+
+// TODO Choose between DB and text files for saving this information
+// If using text, choose between formats, yaml or json or other format, which is more suckless
+// If DB, sliqte3 is a good choice, but don't
+// Going to need a json parser and writer, might as well make the config files as json as well
+const char* saved_grant_token = NULL;
+const char* saved_access_token = NULL;
+/* const char* saved_grant_token = ""; */
+
+/* const char* saved_access_token = ""; */
+
+// TODO rethink this decision later, char* or const char* ?
+// Have to free the returning string at the end, who does that?
+char *json_access_code_transformer(char* str) {
+ const nx_json* json = nx_json_parse(str, nx_json_unicode_to_utf8);
+ if (json->type == NX_JSON_OBJECT) {
+ const nx_json* at = nx_json_get(json, "access_token");
+ if (at->type == NX_JSON_STRING) {
+ printf("str: %s\n", str);
+ const char* value = at->text_value;
+ size_t len = strlen(value);
+ char* copy = (char*)malloc(len);
+ strncpy(copy, value, len);
+ printf("copy: %s\n", copy);
+ return copy;
+ }
+ }
+ return NULL;
+}
+
+char* start_oauth_server() {
+ oauth2_config* conf = oauth2_init(CLIQ_CLIENT_ID, CLIQ_CLIENT_SECRET);
+ conf->access_auth_code_transformer = json_access_code_transformer;
+ oauth2_set_redirect_uri(conf, CLIQ_REDIRECT_URI);
+ // TODO generate true state instead of LOL
+ char* redir_uri = NULL;
+ char* grant_token = malloc(255 * sizeof(char));
+ if (saved_grant_token == NULL) {
+ redir_uri = oauth2_request_auth_code(conf, CLIQ_AUTH_ENDPOINT, CLIQ_SCOPE, "LOL", "online");
+
+ printf("Visit this url and hit authorize: %s\n", redir_uri);
+ printf("Now put the auth token here: ");
+
+ scanf("%s", grant_token);
+ } else {
+ strcpy(grant_token, saved_grant_token);
+ }
+
+ if (grant_token == NULL) {
+ printf("grant_token is null");
+ return NULL;
+ }
+
+ //Now test token based auth
+ char* access_token = NULL;
+ if (saved_access_token == NULL) {
+ access_token = oauth2_access_auth_code(conf, CLIQ_TOKEN_ENDPOINT, grant_token, CLIQ_SCOPE);
+ if (access_token == NULL) {
+ printf("access_token: %ld is null\n", (long)access_token);
+ return NULL;
+ }
+ } else {
+ access_token = malloc(255 * sizeof(char));
+ strcpy(access_token, saved_access_token);
+ }
+
+ oauth2_set_auth_code(conf, access_token);
+ printf("Access Token: %s\n", access_token);
+ /* free(access_token); */
+
+ /* printf("Enter your Facebook status: "); */
+ /* char status[255]; */
+ /* scanf("%s", status); */
+ /* char status2[255]; */
+ /* sprintf(status2, "message=%s", status); */
+
+ /* access_token = oauth2_request(conf, "https://graph.facebook.com/slugonamission/feed", status2); */
+
+ /* printf("%s\n", access_token); */
+
+ oauth2_cleanup(conf);
+ return access_token;
+}
+#endif
diff --git a/qlic_response_handler.c b/qlic_response_handler.c
@@ -1,12 +1,19 @@
#include <qlic_response_handler.h>
#include <stdio.h>
+#include <string.h>
-int qlic_handle_read_chat(char* response, size_t response_size, size_t nmemb, void *userp) {
+int qlic_handle_read_chat(char* response, size_t item_size, size_t nmemb, void *userp) {
/* printf("helo: %s\n", response); */
+ /* size_t bytes = item_size * nmemb; */
+/* #define QLIC_TEST_TEST "{\"text\": \"Hi\"}" */
+/* printf("Test: item_size %zu", item_size); */
+/* printf("Test: response %s", response); */
return 0;
}
-int qlic_handle_send_message(char* response, size_t response_size, size_t nmemb, void *userp) {
+size_t qlic_handle_send_message(char* response, size_t item_size, size_t nmemb, void *userp) {
+ size_t bytes = item_size * nmemb;
+ printf("Chunk size: %zu\n", nmemb);
printf("%s\n", response);
- return 0;
+ return bytes;
}
diff --git a/qlic_response_handler.h b/qlic_response_handler.h
@@ -4,6 +4,6 @@
#include <stddef.h>
int qlic_handle_read_chat(char* response, size_t response_size, size_t nmemb, void *userp);
-int qlic_handle_send_message(char* response, size_t response_size, size_t nmemb, void *userp);
+size_t qlic_handle_send_message(char* response, size_t response_size, size_t nmemb, void *userp);
#endif
diff --git a/qlic_types.h b/qlic_types.h
@@ -3,7 +3,7 @@
#include <stddef.h>
-typedef int (*qlic_response_callback)(char*, size_t, size_t, void*);
+typedef size_t (*qlic_response_callback)(char*, size_t, size_t, void*);
typedef struct QlicString {
char* string;
diff --git a/state.json b/state.json
@@ -0,0 +1,8 @@
+{
+ "user_id": {
+ "grant_token": "",
+ "access_token": "",
+ "refresh_token": "",
+ "time_generated": ""
+ }
+}