aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2020-07-13 00:07:56 +0200
committerdec05eba <dec05eba@protonmail.com>2020-07-13 00:07:56 +0200
commite4bae38e3a5d345c025ed9edddbf401c81756dd5 (patch)
tree7d3b635e55845f96ca05e9ddaf167c0b79832ef1
parent978dba29a64692d9d00bf8074ea18cb70d121b75 (diff)
Finish 'downloaded' command
-rw-r--r--buffer.c4
-rw-r--r--buffer.h1
-rw-r--r--fileutils.c33
-rw-r--r--fileutils.h2
-rw-r--r--main.c152
5 files changed, 178 insertions, 14 deletions
diff --git a/buffer.c b/buffer.c
index 879a62b..5768b3a 100644
--- a/buffer.c
+++ b/buffer.c
@@ -52,3 +52,7 @@ void* buffer_begin(Buffer *self) {
void* buffer_end(Buffer *self) {
return (char*)self->data + self->size;
}
+
+size_t buffer_get_size(Buffer *self, size_t type_size) {
+ return self->size / type_size;
+}
diff --git a/buffer.h b/buffer.h
index a8c1940..0aefe99 100644
--- a/buffer.h
+++ b/buffer.h
@@ -26,5 +26,6 @@ void buffer_append(Buffer *self, const void *data, size_t size);
void* buffer_pop(Buffer *self, size_t size);
void* buffer_begin(Buffer *self);
void* buffer_end(Buffer *self);
+size_t buffer_get_size(Buffer *self, size_t type_size);
#endif
diff --git a/fileutils.c b/fileutils.c
index 233138c..137373b 100644
--- a/fileutils.c
+++ b/fileutils.c
@@ -1,6 +1,9 @@
#include "fileutils.h"
+#include "alloc.h"
+#include <stdio.h>
#include <stdlib.h>
+#include <errno.h>
#include <pwd.h>
#include <unistd.h>
@@ -12,3 +15,33 @@ const char* get_home_dir() {
}
return home_dir;
}
+
+int file_get_content(const char *filepath, char **data, long *size) {
+ int result = 0;
+ FILE *file = fopen(filepath, "rb");
+ if(!file) {
+ int err = -errno;
+ perror(filepath);
+ return err;
+ }
+
+ fseek(file, 0, SEEK_END);
+ *size = ftell(file);
+ if(*size == -1) {
+ fprintf(stderr, "Failed to tell the size of file %s, is it not a file?\n", filepath);
+ result = -1;
+ goto cleanup;
+ }
+ fseek(file, 0, SEEK_SET);
+
+ *data = alloc_or_crash(*size);
+ if((long)fread(*data, 1, *size, file) != *size) {
+ fprintf(stderr, "Failed to read all bytes in file %s\n", filepath);
+ result = -1;
+ goto cleanup;
+ }
+
+ cleanup:
+ fclose(file);
+ return result;
+}
diff --git a/fileutils.h b/fileutils.h
index 9780392..413648f 100644
--- a/fileutils.h
+++ b/fileutils.h
@@ -2,5 +2,7 @@
#define FILEUTILS_H
const char* get_home_dir();
+/* Returns 0 on success */
+int file_get_content(const char *filepath, char **data, long *size);
#endif
diff --git a/main.c b/main.c
index 6655ed5..33bc2fd 100644
--- a/main.c
+++ b/main.c
@@ -1,11 +1,13 @@
#include "program.h"
#include "buffer.h"
#include "fileutils.h"
+#include "json.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
+#include <stdbool.h>
#include <dirent.h>
@@ -50,7 +52,113 @@ static void usage_sync(void) {
exit(1);
}
-static void get_downloaded_items(const char *tracked_dir) {
+static struct json_value_s* json_object_get_field_by_name(struct json_object_s *json_obj, const char *name) {
+ struct json_object_element_s *obj_element = json_obj->start;
+ while(obj_element) {
+ if(strcmp(obj_element->name->string, name) == 0)
+ return obj_element->value;
+ obj_element = obj_element->next;
+ }
+ return NULL;
+}
+
+typedef void (*DownloadedListCallback)(const char *title, double timestamp, void *userdata);
+
+static void data_file_get_downloaded(const char *dir_name, const char *data_filepath, bool is_html, DownloadedListCallback callback, void *userdata) {
+ char *file_data;
+ long file_size;
+ if(file_get_content(data_filepath, &file_data, &file_size) != 0) {
+ fprintf(stderr, "Failed to read the content of file %s\n", data_filepath);
+ return;
+ }
+
+ struct json_value_s *json_root = json_parse(file_data, file_size);
+ if(!json_root) {
+ fprintf(stderr, "Failed to parse file %s as json\n", data_filepath);
+ goto cleanup;
+ }
+
+ struct json_object_s *json_root_obj = json_value_as_object(json_root);
+ if(!json_root_obj) {
+ fprintf(stderr, "File %s contains malformed json. Expected json root element to be an object\n", data_filepath);
+ goto cleanup;
+ }
+
+ struct json_value_s *downloaded_json = json_object_get_field_by_name(json_root_obj, "downloaded");
+ if(!downloaded_json) {
+ fprintf(stderr, "File %s contains malformed json. Expected json to contain \"downloaded\"\n", data_filepath);
+ goto cleanup;
+ }
+
+ struct json_array_s *downloaded_json_arr = json_value_as_array(downloaded_json);
+ if(!downloaded_json_arr) {
+ fprintf(stderr, "File %s contains malformed json. Expected \"downloaded\" to be an array\n", data_filepath);
+ goto cleanup;
+ }
+
+ size_t dir_name_len = strlen(dir_name);
+
+ struct json_array_element_s *downloaded_item = downloaded_json_arr->start;
+ for(; downloaded_item; downloaded_item = downloaded_item->next) {
+ struct json_object_s *downloaded_item_obj = json_value_as_object(downloaded_item->value);
+ if(!downloaded_item_obj)
+ continue;
+
+ struct json_value_s *time_json = json_object_get_field_by_name(downloaded_item_obj, "time");
+ if(!time_json || time_json->type != json_type_string)
+ continue;
+ struct json_string_s *time_json_str = json_value_as_string(time_json);
+
+ struct json_value_s *title_json = json_object_get_field_by_name(downloaded_item_obj, "title");
+ struct json_string_s *title_str = NULL;
+ if(title_json && title_json->type == json_type_string)
+ title_str = json_value_as_string(title_json);
+
+ struct json_value_s *filename_json = json_object_get_field_by_name(downloaded_item_obj, "filename");
+ struct json_string_s *filename_str = NULL;
+ if(filename_json && filename_json->type == json_type_string)
+ filename_str = json_value_as_string(filename_json);
+
+ /* Filename limit is 256, so this should be safe... */
+ char title[256];
+ if(filename_str) {
+ strcpy(title, filename_str->string);
+ } else if(title_str) {
+ if(is_html) {
+ strcpy(title, dir_name);
+ title[dir_name_len] = '/';
+ strcpy(title + dir_name_len + 1, title_str->string);
+ } else {
+ strcpy(title, title_str->string);
+ }
+ } else {
+ continue;
+ }
+
+ callback(title, atof(time_json_str->string), userdata);
+ }
+
+ cleanup:
+ if(json_root)
+ free(json_root);
+ free(file_data);
+}
+
+typedef struct {
+ char *title;
+ double timestamp;
+} DownloadedListData;
+
+static void downloaded_list_callback(const char *title, double timestamp, void *userdata) {
+ DownloadedListData list_data;
+ list_data.title = strdup(title);
+ list_data.timestamp = timestamp;
+
+ Buffer *buffer = userdata;
+ buffer_append(buffer, &list_data, sizeof(list_data));
+}
+
+static void get_downloaded_items(const char *tracked_dir, bool is_html, void *userdata) {
struct dirent *dir;
DIR *d = opendir(tracked_dir);
if(!d)
@@ -68,26 +176,42 @@ static void get_downloaded_items(const char *tracked_dir) {
strcpy(data_filepath + data_filepath_length, dir->d_name);
strcpy(data_filepath + data_filepath_length + strlen(dir->d_name), "/data");
- puts(data_filepath);
+ data_file_get_downloaded(dir->d_name, data_filepath, is_html, downloaded_list_callback, userdata);
}
closedir(d);
}
+static int compare_downloaded_item(const void *a, const void *b) {
+ const DownloadedListData *list_data_a = a;
+ const DownloadedListData *list_data_b = b;
+ return list_data_a->timestamp - list_data_b->timestamp;
+}
+
static void command_downloaded(const char *rss_config_dir, const char *html_config_dir) {
- char rss_tracked_dir[PATH_MAX] = {0};
- strcat(rss_tracked_dir, rss_config_dir);
+ char rss_tracked_dir[PATH_MAX];
+ strcpy(rss_tracked_dir, rss_config_dir);
strcat(rss_tracked_dir, "/tracked");
- char html_tracked_dir[PATH_MAX] = {0};
- strcat(html_tracked_dir, html_config_dir);
+ char html_tracked_dir[PATH_MAX];
+ strcpy(html_tracked_dir, html_config_dir);
strcat(html_tracked_dir, "/tracked");
- printf("files in %s: \n", rss_tracked_dir);
- get_downloaded_items(rss_tracked_dir);
+ Buffer downloaded_items;
+ buffer_init(&downloaded_items);
+
+ get_downloaded_items(rss_tracked_dir, false, &downloaded_items);
+ get_downloaded_items(html_tracked_dir, true, &downloaded_items);
+
+ qsort(downloaded_items.data, buffer_get_size(&downloaded_items, sizeof(DownloadedListData)), sizeof(DownloadedListData), compare_downloaded_item);
+ DownloadedListData *list_it = buffer_begin(&downloaded_items);
+ DownloadedListData *list_end = buffer_end(&downloaded_items);
+ for(; list_it != list_end; ++list_it) {
+ puts(list_it->title);
+ free(list_it->title);
+ }
- printf("files in %s: \n", html_tracked_dir);
- get_downloaded_items(html_tracked_dir);
+ buffer_deinit(&downloaded_items);
}
int main(int argc, char **argv) {
@@ -96,12 +220,12 @@ int main(int argc, char **argv) {
const char *home_dir = get_home_dir();
- char rss_config_dir[PATH_MAX] = {0};
- strcat(rss_config_dir, home_dir);
+ char rss_config_dir[PATH_MAX];;
+ strcpy(rss_config_dir, home_dir);
strcat(rss_config_dir, "/.config/automedia/rss");
- char html_config_dir[PATH_MAX] = {0};
- strcat(html_config_dir, home_dir);
+ char html_config_dir[PATH_MAX];
+ strcpy(html_config_dir, home_dir);
strcat(html_config_dir, "/.config/automedia/html");
const char *command = argv[1];