summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornirav <nirav@teisuu.com>2019-03-10 23:45:19 +0530
committerDandelion <nirav@teisuu.com>2019-03-11 23:05:22 +0530
commit63e8c7f9d095fe0b1e0b44f950230c0e238f166d (patch)
tree01e0211f4fdede1eccda010fc944b3a0180a9632
parent7e8ea36eb8106b4847af13a27a3e8f3177d25809 (diff)
downloadap_client-63e8c7f9d095fe0b1e0b44f950230c0e238f166d.tar.gz
ap_client-63e8c7f9d095fe0b1e0b44f950230c0e238f166d.zip
Add config and log
-rw-r--r--Makefile4
-rw-r--r--src/auth.c144
-rw-r--r--src/auth.h11
-rw-r--r--src/config.c146
-rw-r--r--src/config.h20
-rw-r--r--src/http.c138
-rw-r--r--src/http.h2
-rw-r--r--src/instance_info.c8
-rw-r--r--src/log.c29
-rw-r--r--src/log.h13
-rw-r--r--src/login_window.c13
-rw-r--r--src/main.c49
-rw-r--r--src/option.c64
-rw-r--r--src/option.h14
-rw-r--r--src/status.c11
-rw-r--r--src/timeline.c99
-rw-r--r--src/timeline.h6
-rw-r--r--src/timeline_window.c20
18 files changed, 460 insertions, 331 deletions
diff --git a/Makefile b/Makefile
index 8b84c4a..d214f26 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,9 @@ OBJECTS=$(OUTDIR)/main.o \
$(OUTDIR)/timeline.o \
$(OUTDIR)/auth.o \
$(OUTDIR)/login_window.o \
- $(OUTDIR)/timeline_window.o
+ $(OUTDIR)/timeline_window.o \
+ $(OUTDIR)/config.o \
+ $(OUTDIR)/log.o
all: ap_client
diff --git a/src/auth.c b/src/auth.c
index 648c2c8..ab37016 100644
--- a/src/auth.c
+++ b/src/auth.c
@@ -7,18 +7,43 @@
#include "string-util.h"
#include "auth.h"
#include "http.h"
+#include "config.h"
+#include "log.h"
#define CLIENT_NAME "ap_client"
#define PROTOCOL_PREFIX "https://"
-char *instance_domain;
-char *client_id;
-char *client_secret;
-char *access_token;
-char *scope;
+static const char *app_register_url = "/api/v1/apps";
+static const char *login_url = "/oauth/token";
-static char *app_register_url = "/api/v1/apps";
-static char *login_url = "/oauth/token";
+int read_local_credentials()
+{
+ if (!(config->access_token) || !*(config->access_token) ||
+ !(config->instance_url) || !*(config->instance_url)) {
+ log_msg(LOG_ERROR, "read_local_credentials",
+ "access_token not found");
+ return -1;
+ }
+ printf("token: %s\niu: %s\n", config->access_token, config->instance_url);
+ return 0;
+}
+
+bool is_logged_in()
+{
+ if (config->access_token)
+ return true;
+ return false;
+}
+
+const char *get_access_token()
+{
+ return (const char *)config->access_token;
+}
+
+const char *get_instance_url()
+{
+ return (const char *)config->instance_url;
+}
struct register_call_arg {
char *url;
@@ -35,46 +60,46 @@ static void *register_call(void *req_arg)
arg = (struct register_call_arg *)req_arg;
if (!arg || !(arg->url)) {
- fprintf(stderr, "register_call(): invalid arguments\n");
+ log_msg(LOG_ERROR, "register_call", "invalid arguments");
goto error;
}
resp = post_request(arg->url, arg->post_data);
if (!resp) {
- fprintf(stderr, "register_call(): failed to send http request\n");
+ log_msg(LOG_ERROR, "register_call", "failed to send http request");
goto error;
}
if (!resp) {
- fprintf(stderr, "register_call(): null response\n");
+ log_msg(LOG_ERROR, "register_call", "null response");
goto error;
}
root = json_loads(resp, 0, NULL);
if (!root) {
- fprintf(stderr, "register_call(): failed to parse json\n");
+ log_msg(LOG_ERROR, "register_call", "failed to parse json");
goto error;
}
if (!json_is_object(root)) {
- fprintf(stderr, "register_call(): json root is not object\n");
+ log_msg(LOG_ERROR, "register_call", "json root is not object");
goto error;
}
json_t *cid = json_object_get(root, "client_id");
json_t *csec = json_object_get(root, "client_secret");
if (!json_is_string(cid) || !json_is_string(csec)) {
- fprintf(stderr,
- "register_call(): invalid client_id or client_secret\n");
+ log_msg(LOG_ERROR, "register_call",
+ "invalid client_id or client_secret");
goto error;
}
- client_id = strdup(json_string_value(cid));
- client_secret = strdup(json_string_value(csec));
- instance_domain = arg->domain;
- if (strlen(client_id) < 1 || strlen(client_secret) < 1) {
- fprintf(stderr,
- "register_call(): invalid client_id or client_secret\n");
+ config_set_client_id(json_string_value(cid));
+ config_set_client_secret(json_string_value(csec));
+ config_set_instance_url(arg->domain);
+ if (!*(config->client_id) || !*(config->client_secret)) {
+ log_msg(LOG_ERROR, "register_call",
+ "invalid client_id or client_secret");
goto error;
}
@@ -114,14 +139,14 @@ int register_app(const char *instance, void (*callback)(bool success))
pthread_t t;
if (!instance || strlen(instance) < 1 || !callback) {
- fprintf(stderr, "register_app(): invalid argument\n");
+ log_msg(LOG_ERROR, "register_app", "invalid argument");
return -1;
}
size = sizeof(PROTOCOL_PREFIX) + sizeof(instance) + 1;
instance_prefix = malloc(size);
if (!instance_prefix) {
- err(1, "register_app(): malloc failed");
+ err(1, NULL);
return -1;
}
strlcpy(instance_prefix, PROTOCOL_PREFIX, size);
@@ -132,7 +157,7 @@ int register_app(const char *instance, void (*callback)(bool success))
"read write push");
if (!root) {
- fprintf(stderr, "register_app(): json pack error: line %d: %s\n",
+ log_msg(LOG_ERROR, "register_app", "json pack error: line %d: %s",
error.line, error.text);
return -1;
}
@@ -140,14 +165,14 @@ int register_app(const char *instance, void (*callback)(bool success))
req_data = json_dumps(root, 0);
json_decref(root);
if (!req_data) {
- fprintf(stderr, "register_app(): failed to dump json\n");
+ log_msg(LOG_ERROR, "register_app", "failed to dump json");
return -1;
}
size = strlen(instance_prefix) + strlen(app_register_url) + 1;
url = malloc(size);
if (!url) {
- err(1, "register_app(): malloc failed");
+ err(1, NULL);
return -1;
}
@@ -156,7 +181,7 @@ int register_app(const char *instance, void (*callback)(bool success))
arg = calloc(1, sizeof(struct register_call_arg));
if (!arg) {
- err(1, "register_app(): calloc failed");
+ err(1, NULL);
return -1;
}
arg->url = url;
@@ -181,29 +206,29 @@ static void *login_call(void *req_arg)
arg = (struct login_call_arg *)req_arg;
if (!arg || !(arg->url)) {
- fprintf(stderr, "login_call(): invalid arguments\n");
+ log_msg(LOG_ERROR, "login_call", "invalid arguments");
goto error;
}
resp = post_request(arg->url, arg->post_data);
if (!resp) {
- fprintf(stderr, "login_call(): failed to send http request\n");
+ log_msg(LOG_ERROR, "login_call", "failed to send http request");
goto error;
}
if (!resp) {
- fprintf(stderr, "login_call(): null response\n");
+ log_msg(LOG_ERROR, "login_call", "null response");
goto error;
}
root = json_loads(resp, 0, NULL);
if (!root) {
- fprintf(stderr, "login_call(): failed to parse json\n");
+ log_msg(LOG_ERROR, "login_call", "failed to parse json");
goto error;
}
if (!json_is_object(root)) {
- fprintf(stderr, "login_call(): json root is not object\n");
+ log_msg(LOG_ERROR, "login_call", "json root is not object");
goto error;
}
@@ -212,12 +237,17 @@ static void *login_call(void *req_arg)
if (!json_is_string(access_token_j) || !json_is_string(scope_j) ||
strlen(json_string_value(access_token_j)) < 1 ||
strlen(json_string_value(scope_j)) < 1) {
- fprintf(stderr, "login_call(): invalid access_token or scope\n");
+ log_msg(LOG_ERROR, "login_call", "invalid access_token or scope");
goto error;
}
- access_token = strdup(json_string_value(access_token_j));
- scope = strdup(json_string_value(scope_j));
+ config_set_access_token(json_string_value(access_token_j));
+ /* scope = strdup(json_string_value(scope_j)); */
+
+ if (config_save()) {
+ log_msg(LOG_ERROR, "login_call", "failed to save config");
+ goto error;
+ }
free(arg->url);
if (arg->post_data)
@@ -227,7 +257,7 @@ static void *login_call(void *req_arg)
json_decref(root);
(*(arg->callback))(true);
- printf("access_token: %s\n", access_token);
+ printf("access_token: %s", config->access_token);
return NULL;
error:
@@ -257,49 +287,46 @@ int login(
struct login_call_arg *arg;
if (!email || strlen(email) < 1 || !password || strlen(password) < 1) {
- fprintf(stderr, "login(): invalid argument\n");
+ log_msg(LOG_ERROR, "login", "invalid argument");
return -1;
}
- if (!client_id || strlen(client_id) < 1 || !client_secret ||
- strlen(client_secret) < 1 || !instance_domain ||
- strlen(instance_domain) < 1) {
- fprintf(stderr, "login(): invalid client_id or client_secret\n");
- printf("cid: %s\n", client_id);
- printf("csec: %s\n", client_secret);
- printf("in: %s\n", instance_domain);
+ if (!(config->client_id) || !*(config->client_id) ||
+ !(config->client_secret) || !*(config->client_secret) ||
+ !(config->instance_url) || !*(config->instance_url)) {
+ log_msg(LOG_ERROR, "login", "invalid client_id or client_secret");
return -1;
}
root = json_pack_ex(&error, 1, "{s:s, s:s, s:s, s:s, s:s}", "client_id",
- client_id, "client_secret", client_secret, "grant_type", "password",
- "username", email, "password", password);
+ config->client_id, "client_secret", config->client_secret,
+ "grant_type", "password", "username", email, "password", password);
if (!root) {
- fprintf(stderr, "login(): json pack error: line %d: %s\n", error.line,
- error.text);
+ log_msg(LOG_ERROR, "login", "json pack error: line %d: %s",
+ error.line, error.text);
return -1;
}
req_data = json_dumps(root, 0);
json_decref(root);
if (!req_data) {
- fprintf(stderr, "login(): failed to dump json\n");
+ log_msg(LOG_ERROR, "login", "failed to dump json");
return -1;
}
- size = strlen(instance_domain) + strlen(login_url) + 1;
+ size = strlen(config->instance_url) + strlen(login_url) + 1;
url = malloc(size);
if (!url) {
- err(1, "login(): malloc failed");
+ err(1, NULL);
return -1;
}
- strlcpy(url, instance_domain, size);
+ strlcpy(url, config->instance_url, size);
strlcat(url, login_url, size);
arg = calloc(1, sizeof(struct login_call_arg));
if (!arg) {
- err(1, "login(): calloc failed");
+ err(1, NULL);
return -1;
}
arg->url = url;
@@ -307,17 +334,4 @@ int login(
arg->callback = callback;
return pthread_create(&t, NULL, &login_call, arg);
- return 0;
-}
-
-void auth_cleanup()
-{
- if (instance_domain)
- free(instance_domain);
- if (access_token)
- free(access_token);
- if (client_id)
- free(client_id);
- if (client_secret)
- free(client_secret);
}
diff --git a/src/auth.h b/src/auth.h
index e6691dd..bc9c58b 100644
--- a/src/auth.h
+++ b/src/auth.h
@@ -3,15 +3,12 @@
#include <stdbool.h>
-extern char *instance_domain;
-extern char *client_id;
-extern char *client_secret;
-extern char *access_token;
-extern char *scope;
-
+bool is_logged_in();
+const char* get_access_token();
+const char* get_instance_url();
+int read_local_credentials();
int register_app(const char *instance, void (*callback) (bool success));
int login(const char *email, const char *password, void (*callback) (bool success));
-void auth_cleanup();
#endif
diff --git a/src/config.c b/src/config.c
new file mode 100644
index 0000000..c4aecf0
--- /dev/null
+++ b/src/config.c
@@ -0,0 +1,146 @@
+#define _POSIX_C_SOURCE 200809L
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <limits.h>
+#include <libgen.h>
+#include <jansson.h>
+#include "string-util.h"
+#include "config.h"
+#include "log.h"
+
+#define CONFIG_PATH_SUFFIX "/.config/ap_client/config"
+
+struct config _config;
+const struct config *config = (const struct config *)&_config;
+
+char *get_config_path()
+{
+ char *home = getenv("HOME");
+ if (!home || !*home) {
+ return NULL;
+ }
+ char config_path[PATH_MAX];
+ strlcpy(config_path, home, sizeof(config_path));
+ strlcat(config_path, CONFIG_PATH_SUFFIX, sizeof(config_path));
+ return strdup(config_path);
+}
+
+void config_load()
+{
+ json_t *root;
+ json_error_t error;
+
+ char *path = get_config_path();
+ root = json_load_file(path, 0, &error);
+ if (!root) {
+ log_msg(LOG_ERROR, "load_config", "json parse error: line %d: %s",
+ error.line, error.text);
+ free(path);
+ return;
+ }
+ free(path);
+
+ if (!json_is_object(root)) {
+ log_msg(LOG_ERROR, "load_config", "json root is not object");
+ json_decref(root);
+ return;
+ }
+
+ json_t *instance_url = json_object_get(root, "instance_url");
+ if (json_is_string(instance_url)) {
+ _config.instance_url = strdup(json_string_value(instance_url));
+ }
+
+ json_t *client_id = json_object_get(root, "client_id");
+ if (json_is_string(client_id)) {
+ _config.client_id = strdup(json_string_value(client_id));
+ }
+
+ json_t *client_secret = json_object_get(root, "client_secret");
+ if (json_is_string(client_secret)) {
+ _config.client_secret = strdup(json_string_value(client_secret));
+ }
+
+ json_t *access_token = json_object_get(root, "access_token");
+ if (json_is_string(access_token)) {
+ _config.access_token = strdup(json_string_value(access_token));
+ }
+
+ json_decref(root);
+}
+
+int config_save()
+{
+ json_t *root;
+ json_error_t error;
+
+ root = json_pack_ex(&error, 1, "{s:s, s:s, s:s, s:s}", "instance_url",
+ _config.instance_url, "client_id", _config.client_id,
+ "client_secret", _config.client_secret, "access_token",
+ _config.access_token);
+
+ if (!root) {
+ log_msg(LOG_ERROR, "register_app", "json pack error: line %d: %s",
+ error.line, error.text);
+ return -1;
+ }
+
+ char *config_path = get_config_path();
+ struct stat st;
+ char *dir = dirname(config_path);
+ if (stat(dir, &st)) {
+ if (mkdir(dir, S_IRWXU)) {
+ free(config_path);
+ log_msg(LOG_ERROR, "load_config", "failed to create config dir");
+ return -1;
+ }
+ }
+ free(config_path);
+
+ if (json_dump_file(root, get_config_path(), 0)) {
+ log_msg(LOG_ERROR, "load_config", "unable to save json");
+ json_decref(root);
+ return -1;
+ }
+
+ json_decref(root);
+ return 0;
+}
+
+void config_set_client_id(const char *cid)
+{
+ _config.client_id = strdup(cid);
+}
+
+void config_set_client_secret(const char *cs)
+{
+ _config.client_secret = strdup(cs);
+}
+
+void config_set_instance_url(const char *iu)
+{
+ printf("updating url: %s", iu);
+ _config.instance_url = strdup(iu);
+}
+
+void config_set_access_token(const char *a)
+{
+ _config.access_token = strdup(a);
+}
+
+void config_cleanup()
+{
+ if (_config.client_id)
+ free(_config.client_id);
+ if (_config.client_secret)
+ free(_config.client_secret);
+ if (_config.instance_url)
+ free(_config.instance_url);
+ if (_config.access_token)
+ free(_config.access_token);
+}
diff --git a/src/config.h b/src/config.h
new file mode 100644
index 0000000..3875a1b
--- /dev/null
+++ b/src/config.h
@@ -0,0 +1,20 @@
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+struct config {
+ char *instance_url;
+ char *client_id;
+ char *client_secret;
+ char *access_token;
+};
+
+extern const struct config *config;
+void config_load();
+int config_save();
+void config_set_client_id(const char *cid);
+void config_set_client_secret(const char *cs);
+void config_set_instance_url(const char *iu);
+void config_set_access_token(const char *a);
+void config_cleanup();
+
+#endif
diff --git a/src/http.c b/src/http.c
index 4c9f9dc..ec1ecc5 100644
--- a/src/http.c
+++ b/src/http.c
@@ -6,6 +6,7 @@
#include <curl/curl.h>
#include "string-util.h"
#include "auth.h"
+#include "log.h"
#define BUFFER_SIZE (256 * 1024)
#define AUTH_HEADER_STR_PREFIX "Authorization: Bearer "
@@ -31,7 +32,7 @@ static size_t write_response(void *ptr, size_t size, size_t nmemb, void *stream)
struct write_result *result = (struct write_result *)stream;
if (result->pos + size * nmemb >= BUFFER_SIZE - 1) {
- fprintf(stderr, "error: too small buffer\n");
+ log_msg(LOG_ERROR, "write_response", "buffer too small");
return 0;
}
@@ -60,12 +61,12 @@ char *get_request(const char *url)
struct write_result write_result = {.data = data, .pos = 0};
- if (access_token) {
- char *auth_header_val =
- malloc(strlen(AUTH_HEADER_STR_PREFIX) + strlen(access_token) + 1);
- strlcpy(auth_header_val, AUTH_HEADER_STR_PREFIX,
- sizeof(auth_header_val));
- strlcat(auth_header_val, access_token, sizeof(auth_header_val));
+ if (is_logged_in()) {
+ const char *token = get_access_token();
+ size_t s = strlen(AUTH_HEADER_STR_PREFIX) + strlen(token) + 1;
+ char *auth_header_val = malloc(s);
+ strlcpy(auth_header_val, AUTH_HEADER_STR_PREFIX, s);
+ strlcat(auth_header_val, token, s);
headers = curl_slist_append(headers, auth_header_val);
}
@@ -76,14 +77,16 @@ char *get_request(const char *url)
status = curl_easy_perform(curl);
if (status != 0) {
- fprintf(stderr, "get_request(): unable to request data from %s: %s\n",
- url, curl_easy_strerror(status));
+ log_msg(LOG_ERROR, "get_request",
+ "unable to request data from %s: %s", url,
+ curl_easy_strerror(status));
goto error;
}
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
if (code != 200) {
- fprintf(stderr, "error: server responded with code %ld\n", code);
+ log_msg(LOG_ERROR, "get_request", "server responded with code %ld",
+ code);
goto error;
}
@@ -121,12 +124,12 @@ char *post_request(const char *url, char *post_data)
struct write_result write_result = {.data = data, .pos = 0};
- if (access_token) {
- char *auth_header_val =
- malloc(strlen(AUTH_HEADER_STR_PREFIX) + strlen(access_token) + 1);
- strlcpy(auth_header_val, AUTH_HEADER_STR_PREFIX,
- sizeof(auth_header_val));
- strlcat(auth_header_val, access_token, sizeof(auth_header_val));
+ if (is_logged_in()) {
+ const char *token = get_access_token();
+ size_t s = strlen(AUTH_HEADER_STR_PREFIX) + strlen(token) + 1;
+ char *auth_header_val = malloc(s);
+ strlcpy(auth_header_val, AUTH_HEADER_STR_PREFIX, s);
+ strlcat(auth_header_val, token, s);
headers = curl_slist_append(headers, auth_header_val);
}
if (post_data) {
@@ -138,18 +141,19 @@ char *post_request(const char *url, char *post_data)
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_response);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &write_result);
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data);
+ if (post_data)
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data);
status = curl_easy_perform(curl);
if (status != 0) {
- fprintf(stderr, "post_request(): unable to request data from %s: %s\n",
+ log_msg(LOG_ERROR, "post_request", "unable to request data from %s: %s",
url, curl_easy_strerror(status));
goto error;
}
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
if (code != 200) {
- fprintf(stderr, "error: server responded with code %ld\n", code);
+ log_msg(LOG_ERROR, "post_request", "server responded with code %ld", code);
goto error;
}
@@ -168,99 +172,3 @@ error:
curl_easy_cleanup(curl);
return NULL;
}
-
-struct post_request_arg {
- char *url;
- char *post_data;
- void (*callback)(char *);
-};
-
-void *post_one_url(void *arg)
-{
-
- struct post_request_arg *req_args = (struct post_request_arg *)arg;
- CURL *curl = NULL;
- CURLcode status;
- struct curl_slist *headers = NULL;
- char *data = NULL;
- long code;
-
- curl = curl_easy_init();
- if (!curl)
- goto error;
-
- data = malloc(BUFFER_SIZE);
- if (!data)
- goto error;
-
- struct write_result write_result = {.data = data, .pos = 0};
-
- if (access_token) {
- char *auth_header_val =
- malloc(strlen(AUTH_HEADER_STR_PREFIX) + strlen(access_token) + 1);
- strlcpy(auth_header_val, AUTH_HEADER_STR_PREFIX,
- sizeof(auth_header_val));
- strlcat(auth_header_val, access_token, sizeof(auth_header_val));
- headers = curl_slist_append(headers, auth_header_val);
- }
- if (req_args->post_data) {
- char *content_type_header_val = "Content-Type: application/json";
- headers = curl_slist_append(headers, content_type_header_val);
- }
-
- curl_easy_setopt(curl, CURLOPT_URL, req_args->url);
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_response);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, &write_result);
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, req_args->post_data);
-
- status = curl_easy_perform(curl);
- if (status != 0) {
- fprintf(stderr, "post_request(): unable to request data from %s: %s\n",
- req_args->url, curl_easy_strerror(status));
- goto error;
- }
-
- fprintf(stderr, "http method: POST, url: %s, res: %s\n", req_args->url, data);
- curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
- if (code != 200) {
- fprintf(stderr, "post_request(): server responded with code %ld\n", code);
- goto error;
- }
-
- data[write_result.pos] = '\0';
-
- curl_slist_free_all(headers);
- curl_easy_cleanup(curl);
-
- (*(req_args->callback))(data);
- return NULL;
-
-error:
- if (data)
- free(data);
- if (headers)
- curl_slist_free_all(headers);
- if (curl)
- curl_easy_cleanup(curl);
-
- (*(req_args->callback))(NULL);
- return NULL;
-}
-
-int http_post_async(char *url, char *post_data, void (*callback)(char *))
-{
- struct post_request_arg *arg;
- pthread_t t;
-
- arg = calloc(1, sizeof(struct post_request_arg));
- if (!arg) {
- err(1, "http_post_async(): calloc failed");
- return -1;
- }
- arg->url = url;
- arg->post_data = post_data;
- arg->callback = callback;
-
- return pthread_create(&t, NULL, post_one_url, arg);
-}
diff --git a/src/http.h b/src/http.h
index 32828db..8e69b55 100644
--- a/src/http.h
+++ b/src/http.h
@@ -5,6 +5,6 @@ int http_init();
void http_cleanup();
char *get_request(const char *url);
char *post_request(const char *url, char *data);
-int http_post_async(char *url, char *post_data, void (*callback)(char *));
+/* int http_post_async(char *url, char *post_data, void (*callback)(char *)); */
#endif
diff --git a/src/instance_info.c b/src/instance_info.c
index 6dab351..7b9326e 100644
--- a/src/instance_info.c
+++ b/src/instance_info.c
@@ -2,6 +2,7 @@
#include <string.h>
#include <jansson.h>
#include "instance_info.h"
+#include "log.h"
struct instance_info *instance_info_from_json(char *json_data)
{
@@ -14,19 +15,20 @@ struct instance_info *instance_info_from_json(char *json_data)
root = json_loads(json_data, 0, &error);
if (!root) {
- fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
+ log_msg(LOG_ERROR, "instance_info_from_json", "error: on line %d: %s",
+ error.line, error.text);
return NULL;
}
if (!json_is_object(root)) {
- fprintf(stderr, "root is not object");
+ log_msg(LOG_ERROR, "instance_info_from_json", "root is not object");
json_decref(root);
return NULL;
}
json_t *title = json_object_get(root, "title");
if (!json_is_string(title)) {
- fprintf(stderr, "title is not string");
+ log_msg(LOG_ERROR, "instance_info_from_json", "title is not string");
return NULL;
}
info->title = strdup(json_string_value(title));
diff --git a/src/log.c b/src/log.c
new file mode 100644
index 0000000..52d7028
--- /dev/null
+++ b/src/log.c
@@ -0,0 +1,29 @@
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "log.h"
+
+static const char *log_levels[] = {
+ "info"
+ "warning",
+ "error",
+ "fatal",
+};
+
+void log_msg(enum log_level level, const char *namespace, const char *format, ...) {
+ va_list args;
+ va_start(args, format);
+
+ fprintf(stderr, "%s: %s: ", log_levels[level], namespace);
+ vfprintf(stderr, format, args);
+ fprintf(stderr, "\n");
+
+ if (level == LOG_ERROR) {
+ exit(EXIT_FAILURE);
+ } else if (level == LOG_FATAL) {
+ abort();
+ }
+
+ va_end(args);
+}
+
diff --git a/src/log.h b/src/log.h
new file mode 100644
index 0000000..ecd3428
--- /dev/null
+++ b/src/log.h
@@ -0,0 +1,13 @@
+#ifndef __LOG_H
+#define __LOG_H
+
+enum log_level {
+ LOG_INFO = 0,
+ LOG_WARNING,
+ LOG_ERROR,
+ LOG_FATAL
+};
+
+void log_msg(enum log_level level, const char *namespace, const char *format, ...);
+
+#endif
diff --git a/src/login_window.c b/src/login_window.c
index 32f88a0..8bf82c1 100644
--- a/src/login_window.c
+++ b/src/login_window.c
@@ -8,6 +8,7 @@
#include "http.h"
#include "timeline.h"
#include "timeline_window.h"
+#include "log.h"
GtkApplication *application;
static GtkWidget *window;
@@ -19,13 +20,13 @@ static GtkWidget *spinner;
static void window_removed(
GtkApplication *application, GtkWindow *w, gpointer user_data)
{
- gtk_widget_destroy(GTK_WIDGET(w));
+ /* gtk_widget_destroy(GTK_WIDGET(w)); */
}
static void login_callback(bool success)
{
if (!success) {
- fprintf(stderr, "login_callback(): login failed\n");
+ log_msg(LOG_ERROR, "login_callback", "login failed");
gtk_spinner_stop(GTK_SPINNER(spinner));
return;
}
@@ -33,16 +34,16 @@ static void login_callback(bool success)
printf("login success\n");
gtk_spinner_stop(GTK_SPINNER(spinner));
create_timeline_window(application, NULL);
- gtk_window_close(GTK_WINDOW(window));
- gtk_application_remove_window(
- GTK_APPLICATION(application), GTK_WINDOW(window));
+ /* gtk_window_close(GTK_WINDOW(window)); */
+ /* gtk_application_remove_window( */
+ /* GTK_APPLICATION(application), GTK_WINDOW(window)); */
}
static void register_callback(bool success)
{
if (!success) {
gtk_spinner_stop(GTK_SPINNER(spinner));
- fprintf(stderr, "register_callback(): register failed\n");
+ log_msg(LOG_ERROR, "register_callback", "register failed");
return;
}
printf("register success\n");
diff --git a/src/main.c b/src/main.c
index 45ea3cd..bf23496 100644
--- a/src/main.c
+++ b/src/main.c
@@ -8,23 +8,28 @@
#include "http.h"
#include "timeline.h"
#include "login_window.h"
-
+#include "config.h"
+#include "timeline_window.h"
+#include "log.h"
static void activate(GtkApplication *app, gpointer user_data)
{
- create_login_window(app, user_data);
+ if (read_local_credentials()) {
+ create_login_window(app, user_data);
+ return;
+ }
+ create_timeline_window(app, NULL);
}
int main(int argc, char **argv)
{
- /* gtk_init(&argc, &argv); */
- /* create_main_window(); */
- /* gtk_main(); */
if (http_init()) {
- fprintf(stderr, "main(): failed to load http library\n");
+ log_msg(LOG_ERROR, "main", "failed to load http library");
return EXIT_FAILURE;
}
+ config_load();
+
GtkApplication *app;
int status;
@@ -34,37 +39,7 @@ int main(int argc, char **argv)
g_object_unref(app);
http_cleanup();
- auth_cleanup();
+ config_cleanup();
return status;
-
- /* char *text; */
- /* struct timeline *t; */
- /* char *url = "https://mstdn.io/api/v1/timelines/home"; */
- /* char *token = */
- /* "580acfb412e927c2030fb5519f417b03ced1482c862d44376922cd81ee8a3655";
- */
-
- /* text = request(url, token); */
- /* if (!text) { */
- /* fprintf(stderr, "main(): failed to get http response\n"); */
- /* return EXIT_FAILURE; */
- /* } */
-
- /* t = timeline_from_json(text); */
- /* if (t == NULL) { */
- /* fprintf(stderr, "main(): failed to parse timeline\n"); */
- /* return EXIT_FAILURE; */
- /* } */
-
- /* for (size_t i = 0; i < t->size; i++) { */
- /* printf("status id: %s\n", t->statuses[i]->id); */
- /* printf("content: %s\n", t->statuses[i]->content); */
- /* printf("reblog count: %d\n", t->statuses[i]->reblogs_count); */
- /* printf("fav count: %d\n", t->statuses[i]->favourites_count); */
- /* printf("\n"); */
- /* } */
-
- /* free(text); */
- /* timeline_free(t); */
}
diff --git a/src/option.c b/src/option.c
deleted file mode 100644
index 011bd94..0000000
--- a/src/option.c
+++ /dev/null
@@ -1,64 +0,0 @@
-#define _POSIX_C_SOURCE 200809L
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <unistd.h>
-#include "option.h"
-
-static const char version[] = "qwe version 0.01";
-static const char usage[] =
- "Usage: qwe [options...] <file>\n"
- "\n"
- " -i Hide info bar by default.\n"
- " -f Use fullscreen mode by default.\n"
- " -h Show help message and quit.\n"
- " -v Show the version number and quit.\n";
-
-void print_usage()
-{
- printf("%s\n", usage);
-}
-
-void print_version()
-{
- printf("%s\n", version);
-}
-
-struct option _options;
-const struct option *options = (const struct option *)&_options;
-
-void parse_options(int argc, char **argv)
-{
- // default options
- _options.fullscreen = false;
- _options.show_info = true;
-
- // override options from commandline parameters
- int opt;
- while ((opt = getopt(argc, argv, "hvif")) != -1) {
- switch (opt) {
- case '?':
- print_usage();
- exit(EXIT_FAILURE);
- case 'h':
- print_usage();
- exit(EXIT_SUCCESS);
- case 'v':
- print_version();
- exit(EXIT_SUCCESS);
- case 'i':
- _options.show_info = false;
- break;
- case 'f':
- _options.fullscreen = true;
- break;
- }
- }
-
- if (optind >= argc) {
- print_usage();
- exit(EXIT_FAILURE);
- }
-
- _options.file_name = argv[optind];
-}
diff --git a/src/option.h b/src/option.h
deleted file mode 100644
index 33b8335..0000000
--- a/src/option.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __OPTION_H
-#define __OPTION_H
-
-#include <stdbool.h>
-
-struct option {
- char *file_name;
- bool fullscreen;
- bool show_info;
-};
-extern const struct option *options;
-void parse_options(int argc, char **argv);
-
-#endif
diff --git a/src/status.c b/src/status.c
index 36cd865..139c719 100644
--- a/src/status.c
+++ b/src/status.c
@@ -3,6 +3,7 @@
#include <string.h>
#include <jansson.h>
#include "status.h"
+#include "log.h"
struct status *status_from_json(char *json_data)
{
@@ -11,7 +12,7 @@ struct status *status_from_json(char *json_data)
root = json_loads(json_data, 0, &error);
if (!root) {
- fprintf(stderr, "status_from_json(): json parse error: line %d: %s\n",
+ log_msg(LOG_ERROR, "status_from_json", "json parse error: line %d: %s",
error.line, error.text);
return NULL;
}
@@ -23,19 +24,19 @@ struct status *status_from_json_t(json_t *root)
{
struct status *s;
if (!root) {
- fprintf(stderr, "status_from_json_t(): json data is null\n");
+ log_msg(LOG_ERROR, "status_from_json_t", "json data is null");
return NULL;
}
if (!json_is_object(root)) {
- fprintf(stderr, "status_from_json_t(): json root is not object\n");
+ log_msg(LOG_ERROR, "status_from_json_t", "json root is not object");
json_decref(root);
return NULL;
}
s = calloc(1, sizeof(struct status));
if (!s) {
- err(1, "status_from_json_t(): failed to allocate memory");
+ err(1, NULL);
json_decref(root);
return NULL;
}
@@ -94,7 +95,7 @@ struct status *status_from_json_t(json_t *root)
void status_free(struct status *s)
{
if (!s) {
- fprintf(stderr, "status_free(): status not initializes");
+ log_msg(LOG_ERROR, "status_free", "status not initializes");
return;
}
if (s->id)
diff --git a/src/timeline.c b/src/timeline.c
index 7b0a567..fbd123e 100644
--- a/src/timeline.c
+++ b/src/timeline.c
@@ -1,10 +1,17 @@
#define _POSIX_C_SOURCE 200809L
#include <err.h>
#include <string.h>
+#include <pthread.h>
#include <jansson.h>
#include "timeline.h"
+#include "auth.h"
+#include "http.h"
+#include "string-util.h"
+#include "log.h"
-struct timeline *timeline_from_json(char *json_data)
+static char *timeline_url = "/api/v1/timelines/home";
+
+struct timeline *timeline_from_json(const char *json_data)
{
json_t *root;
json_error_t error;
@@ -13,19 +20,19 @@ struct timeline *timeline_from_json(char *json_data)
root = json_loads(json_data, 0, &error);
if (!root) {
- fprintf(stderr, "timeline_free(): json root it null\n");
+ log_msg(LOG_ERROR, "timeline_free", "json root it null");
return NULL;
}
if (!json_is_array(root)) {
- fprintf(stderr, "timeline_free(): timeline not initialized\n");
+ log_msg(LOG_ERROR, "timeline_free", "timeline not initialized");
json_decref(root);
return NULL;
}
t = calloc(1, sizeof(struct timeline));
if (!t) {
- err(1, "timeline_from_json(): failed to allocate memory");
+ err(1, NULL);
json_decref(root);
return NULL;
}
@@ -33,7 +40,7 @@ struct timeline *timeline_from_json(char *json_data)
t->size = json_array_size(root);
t->statuses = calloc(t->size, sizeof(struct status *));
if (!(t->statuses)) {
- err(1, "timeline_from_json(): failed to allocate memory");
+ err(1, NULL);
json_decref(root);
return NULL;
}
@@ -59,7 +66,7 @@ error:
void timeline_free(struct timeline *t)
{
if (!t) {
- fprintf(stderr, "timeline_free(): timeline not initialized\n");
+ log_msg(LOG_ERROR, "timeline_free", "timeline not initialized");
return;
}
for (size_t i = 0; i < t->size; i++) {
@@ -69,7 +76,83 @@ void timeline_free(struct timeline *t)
free(t);
}
-int lod_timeline(const char *max_id, const char *since_id, const char *min_id, int limit)
+struct load_timeline_call_arg {
+ char *url;
+ void (*callback)(bool, struct timeline *t);
+};
+
+static void *load_timeline_call(void *req_arg)
+{
+ struct load_timeline_call_arg *arg;
+ char *resp;
+ struct timeline *t;
+
+ arg = (struct load_timeline_call_arg *)req_arg;
+ if (!(arg->url)) {
+ log_msg(LOG_ERROR, "load_timeline_call", "invalid arguments");
+ goto error;
+ }
+
+ resp = get_request(arg->url);
+ if (!resp) {
+ log_msg(LOG_ERROR, "load_timeline_call", "failed to send http request");
+ goto error;
+ }
+
+ if (!resp) {
+ log_msg(LOG_ERROR, "load_timeline_call", "null response");
+ goto error;
+ }
+
+ t = timeline_from_json(resp);
+ if (!t) {
+ log_msg(LOG_ERROR, "load_timeline_call", "null response");
+ goto error;
+ }
+
+ free(arg->url);
+ free(arg);
+ free(resp);
+
+ (*(arg->callback))(true, t);
+ return NULL;
+
+error:
+ if (arg->url)
+ free(arg->url);
+ free(arg);
+ if (resp)
+ free(resp);
+ (*(arg->callback))(false, NULL);
+ return NULL;
+}
+
+int get_timeline(const char *max_id, const char *since_id, const char *min_id,
+ int limit, void (*callback)(bool success, struct timeline *t))
{
- return 0;
+ size_t size;
+ char *url;
+ struct load_timeline_call_arg *arg;
+ pthread_t t;
+
+ size = strlen(get_instance_url()) + strlen(timeline_url) + 1;
+ url = malloc(size);
+ if (!url) {
+ err(1, NULL);
+ return -1;
+ }
+
+ strlcpy(url, get_instance_url(), size);
+ strlcat(url, timeline_url, size);
+
+ arg = calloc(1, sizeof(struct load_timeline_call_arg));
+ if (!arg) {
+ err(1, NULL);
+ return -1;
+ }
+
+ arg->url = url;
+ arg->callback = callback;
+
+ return pthread_create(&t, NULL, &load_timeline_call, arg);
}
diff --git a/src/timeline.h b/src/timeline.h
index f31f618..ea72e5c 100644
--- a/src/timeline.h
+++ b/src/timeline.h
@@ -8,9 +8,9 @@ struct timeline {
size_t size;
};
-struct timeline *timeline_from_json(char *);
+struct timeline *timeline_from_json(const char *);
void timeline_free(struct timeline *);
-int lod_timeline(const char *max_id, const char *since_id, const char *min_id,
- int limit);
+int get_timeline(const char *max_id, const char *since_id, const char *min_id,
+ int limit, void (*callback)(bool success, struct timeline *t));
#endif
diff --git a/src/timeline_window.c b/src/timeline_window.c
index c09397a..10f2a84 100644
--- a/src/timeline_window.c
+++ b/src/timeline_window.c
@@ -7,13 +7,29 @@
#include "auth.h"
#include "http.h"
#include "timeline.h"
+#include "log.h"
static GtkWidget *window;
static GtkWidget *box;
static GtkWidget *label;
-static void load_tieline()
+static void timeline_callback(bool success, struct timeline *t)
{
+ for (size_t i = 0; i < t->size; i++) {
+ printf("status id: %s\n", t->statuses[i]->id);
+ printf("content: %s\n", t->statuses[i]->content);
+ printf("reblog count: %d\n", t->statuses[i]->reblogs_count);
+ printf("fav count: %d\n", t->statuses[i]->favourites_count);
+ printf("\n");
+ }
+}
+
+static void load_timeline()
+{
+ if (get_timeline(NULL, NULL, NULL, 20, &timeline_callback)) {
+ log_msg(LOG_ERROR, "load_timeline", "failed");
+ return;
+ }
return;
}
@@ -34,5 +50,5 @@ void create_timeline_window(GtkApplication *app, gpointer user_data)
gtk_container_add(GTK_CONTAINER(box), label);
gtk_widget_show_all(window);
- load_tieline();
+ load_timeline();
}