From 9ac19d66051ec951890497f8baf71bf6dd445921 Mon Sep 17 00:00:00 2001 From: qorg11 Date: Fri, 30 Apr 2021 17:40:27 +0200 Subject: [PATCH] Initial commit the function to log in works, so does the function to post a status but the visibility thing doesn't work. --- readme.org | 11 +++++ src/config.h | 3 ++ src/login.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/login.h | 1 + src/main.c | 17 +++++++ src/post.c | 83 +++++++++++++++++++++++++++++++ src/post.h | 2 + src/util.c | 25 ++++++++++ src/util.h | 3 ++ 9 files changed, 282 insertions(+) create mode 100644 readme.org create mode 100644 src/config.h create mode 100644 src/login.c create mode 100644 src/login.h create mode 100644 src/main.c create mode 100644 src/post.c create mode 100644 src/post.h create mode 100644 src/util.c create mode 100644 src/util.h diff --git a/readme.org b/readme.org new file mode 100644 index 0000000..dc9a7b2 --- /dev/null +++ b/readme.org @@ -0,0 +1,11 @@ +* Demiurge + + Attempt of client of Pleroma (It may work with mastodon as well, but + haven't tried) written in C because i'm criminally insane + +* THANKS TO + + Dendy, who wrote the [[https://git.fai.su/dendy/fedibooru][Code reference]] + +* TODO + Literally everything diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..d4f440b --- /dev/null +++ b/src/config.h @@ -0,0 +1,3 @@ +/* Compilation options */ + +#define __USE_EDITLINE diff --git a/src/login.c b/src/login.c new file mode 100644 index 0000000..6ae4141 --- /dev/null +++ b/src/login.c @@ -0,0 +1,137 @@ +#include "config.h" +#include +#include +#include +#include +#include + +#include + +size_t +write_data(void *buffer, size_t size, size_t nmemb, void *userp) +{ + + memcpy(userp,buffer,nmemb*size); + return 0; +} + + +void +store_config(const char *instance, const char *client_id, + const char *client_secret, const char *access_token) +{ + FILE *fp = fopen(".demiurgerc","w+"); + + fprintf(fp,"%s=%s\n","instance",instance); + fprintf(fp,"%s=%s\n","client_id",client_id); + fprintf(fp,"%s=%s\n","client_secret",client_secret); + fprintf(fp,"%s=%s\n","access_token",access_token); + fclose(fp); +} + +/* I am confident to present you, without a doubt, the worst code i've + * ever written */ + +int +setup() +{ + char *instance = NULL; + instance = readline("Enter your instance (e.g. https://social.fnord.tld) "); + + char *api_url = "/api/v1/apps"; + + CURL *curl = curl_easy_init(); + + struct json_object *parsed_json; + struct json_object *json_client_id; + struct json_object *json_client_secret; + struct json_object *json_access_token; + + if(curl == NULL) { + fprintf(stderr,"Error creating curl (what?)\n"); + return -1; + } + + int len = strlen(instance) + strlen(api_url) + 1; + char buf[8192]; + + char *post_url = (char*)malloc(len); + if(post_url == NULL) { + fprintf(stderr,"Error allocating memory\n"); + return -1; + } + sprintf(post_url,"%s%s",instance,api_url); + curl_easy_setopt(curl,CURLOPT_URL, post_url); + curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION, write_data); + curl_easy_setopt(curl,CURLOPT_WRITEDATA,buf); + + /* TODO: Better way lol */ + curl_easy_setopt(curl,CURLOPT_POSTFIELDS, + "client_name=demiurge&redirect_uris=urn:ietf:wg:oauth:2.0:oob&scope=read write"); + + CURLcode res = curl_easy_perform(curl); + curl_easy_cleanup(curl); + parsed_json = json_tokener_parse(buf); + if(parsed_json == NULL) { + fprintf(stderr,"error\n"); + return -1; + } + + json_object_object_get_ex(parsed_json, "client_id", &json_client_id); + json_object_object_get_ex(parsed_json, "client_secret", &json_client_secret); + const char *client_id = json_object_get_string(json_client_id); + const char *client_secret = json_object_get_string(json_client_secret); + + char *fmt = "%s%sresonse_type=code&client_id=%s&redirect_uri=urn:ietf:wg:oauth:2.0:oob&force_login&scope=read write"; + api_url = "/oauth/authorize?"; + + len = strlen(instance) + strlen(api_url)+ strlen(fmt) + strlen(client_id) + 1; + free(post_url); + + post_url = (char*)malloc(len); + if(post_url == NULL) { + fprintf(stderr,"Error allocating memory\n"); + return -1; + } + + sprintf(post_url,fmt,instance,api_url,client_id); + puts(post_url); + + curl = curl_easy_init(); + + char *code = NULL; + code = readline("Please log in in that url and paste the code here: "); + + char *access_token_fmt = "client_id=%s&client_secret=%s&redirect_uri=urn:ietf:wg:oauth:2.0:oob&grant_type=authorization_code&code=%s&scope=read write"; + api_url = "/oauth/token"; + + + char *post_token_url = (char*)malloc(strlen(access_token_fmt) + strlen(client_id) + + strlen(client_secret ) + strlen(code) + 3); + if(post_token_url == NULL) { + fprintf(stderr,"Error allocating memory"); + return -1; + } + sprintf(post_token_url, access_token_fmt,client_id,client_secret,code); + + len = strlen(instance) + strlen(api_url) + 1; + + post_url = (char*)malloc(len); + if(post_url == NULL) { + fprintf(stderr,"Error allocating memory"); + return -1; + } + sprintf(post_url,"%s%s",instance,api_url); + + curl_easy_setopt(curl, CURLOPT_URL,post_url); + curl_easy_setopt(curl,CURLOPT_POSTFIELDS, post_token_url); + curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION, write_data); + curl_easy_setopt(curl,CURLOPT_WRITEDATA,buf); + curl_easy_perform(curl); + + parsed_json = json_tokener_parse(buf); + json_object_object_get_ex(parsed_json, "access_token", &json_access_token); + const char *access_token = json_object_get_string(json_access_token); + store_config(instance,client_id,client_secret,access_token); + return 0; +} diff --git a/src/login.h b/src/login.h new file mode 100644 index 0000000..77cc39a --- /dev/null +++ b/src/login.h @@ -0,0 +1 @@ +int setup(); /* Log into the account */ diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..a59c168 --- /dev/null +++ b/src/main.c @@ -0,0 +1,17 @@ +#include +#include + +#include "login.h" +#include "util.h" +#include "post.h" + +int +main(void) +{ + char client_id[50]; + char client_secret[50]; + char access_token[50]; + if(access(".demiurgerc", F_OK )) + setup(); + post_status("Hello from demiurge 2!","public"); +} diff --git a/src/post.c b/src/post.c new file mode 100644 index 0000000..60675a1 --- /dev/null +++ b/src/post.c @@ -0,0 +1,83 @@ +#include +#include +#include +#include + +#include "util.h" + +/* This function post "status" with the visibility "visibility" */ + +/* TODO: Make the visibility thing work */ + +int +post_status(const char *status, const char *scope) +{ + char instance[50]; + char client_id[50]; + char client_secret[50]; + char access_token[50]; + + get_tokens_from_file(".demiurgerc",instance,client_id,client_secret,access_token); + CURL *curl = curl_easy_init(); + if(curl == NULL) { + fprintf(stderr,"Error creating libcurl thing\n"); + return -1; + } + + char *api_url = "/api/v1/statuses"; + char *url = (char*)malloc(strlen(instance) + strlen(api_url) + 1); + + if(url == NULL) { + fprintf(stderr,"Error allocating memory!\n"); + return -1; + } + + sprintf(url,"%s%s",instance,api_url); + puts(url); + + curl_easy_setopt(curl,CURLOPT_URL,url); + + char *header_fmt = "Authorization: Bearer %s"; + int len = strlen(header_fmt) + strlen(access_token) + 1; + char *authorization_header = (char*)malloc(len); + if(authorization_header == NULL) { + fprintf(stderr,"Error allocating memory!"); + return -1; + } + + struct curl_slist *header_list = NULL; + + sprintf(authorization_header,header_fmt,access_token); + header_list = curl_slist_append(header_list, authorization_header); + + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list); + + int status_len = strlen(status) + strlen("status=") + 1; + int scope_len = strlen(scope) + strlen("visibility=") + 1; + + char *status_fmt = "status=%s"; + char *scope_fmt = "visibility=%s"; + + char *status_to_post = (char*)malloc(status_len); + char *visibility_to_post = (char*)malloc(scope_len); + + if(status_to_post == NULL) { + fprintf(stderr,"Error allocating memory\n"); + return -1; + } + + sprintf(status_to_post,status_fmt,status); + sprintf(visibility_to_post,scope_fmt,scope); + + curl_easy_setopt(curl,CURLOPT_POSTFIELDSIZE,12L); + curl_easy_setopt(curl,CURLOPT_POSTFIELDS,status_to_post); + + curl_easy_perform(curl); + + free(status_to_post); + free(visibility_to_post); + free(authorization_header); + + return 0; + +} diff --git a/src/post.h b/src/post.h new file mode 100644 index 0000000..a67a8f2 --- /dev/null +++ b/src/post.h @@ -0,0 +1,2 @@ +int +post_status(const char *status, const char *scope); diff --git a/src/util.c b/src/util.c new file mode 100644 index 0000000..64b5bd0 --- /dev/null +++ b/src/util.c @@ -0,0 +1,25 @@ +#include + +/* This function fucking sucks and should use something else. I'll + * have to rewrite this shit function some day. But for now, it will + * do the job. + * TODO: Check for errors + */ + +/* Be aware with buffer overflows, fscanf() */ + + +int +get_tokens_from_file(char *filename, char *instance, char *client_id, + char *client_secret, char *access_token) +{ + FILE *fp = fopen(filename,"r"); + if(fp == NULL) + return -1; + fscanf(fp,"instance=%s\n",instance); + fscanf(fp,"client_id=%s\n",client_id); + fscanf(fp,"client_secret=%s\n",client_secret); + fscanf(fp,"access_token=%s\n",access_token); + + return 0; +} diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..8535f84 --- /dev/null +++ b/src/util.h @@ -0,0 +1,3 @@ +int +get_tokens_from_file(char *filename, char *instance,char *client_id, + char *client_secret, char *access_token);