#include "rss_html_common.h" #include "json.h" #include "fileutils.h" #include #include #include #include int write_plugin_json_to_file(const char *dir, const char *filename, const char *url, const char *updated, const char *start_after, const char *start_after_url, const char *plugin_name) { struct json_string_s title_json_key; create_json_string(&title_json_key, "title", 5); struct json_string_s title_json_value_str; create_json_string(&title_json_value_str, start_after, start_after ? strlen(start_after) : 0); struct json_value_s title_json_value; init_json_value_str(&title_json_value, &title_json_value_str); struct json_string_s time_json_key; create_json_string(&time_json_key, "time", 4); struct json_string_s time_value_str; create_json_string(&time_value_str, updated, strlen(updated)); struct json_value_s time_json_value; init_json_value_str(&time_json_value, &time_value_str); struct json_string_s url_json_key; create_json_string(&url_json_key, "url", 3); struct json_string_s url_value_str; create_json_string(&url_value_str, start_after_url, start_after_url ? strlen(start_after_url) : 0); struct json_value_s url_json_value; init_json_value_str(&url_json_value, &url_value_str); struct json_string_s plugin_json_key; create_json_string(&plugin_json_key, "plugin", 6); struct json_string_s plugin_json_value_str; create_json_string(&plugin_json_value_str, plugin_name, plugin_name ? strlen(plugin_name) : 0); struct json_value_s plugin_json_value; init_json_value_str(&plugin_json_value, &plugin_json_value_str); struct json_string_s link_json_key; create_json_string(&link_json_key, "link", 4); struct json_string_s link_json_value_str; create_json_string(&link_json_value_str, url, strlen(url)); struct json_value_s link_json_value; init_json_value_str(&link_json_value, &link_json_value_str); struct json_string_s updated_json_key; create_json_string(&updated_json_key, "updated", 7); struct json_string_s updated_json_value_str; create_json_string(&updated_json_value_str, updated, strlen(updated)); struct json_value_s updated_json_value; init_json_value_str(&updated_json_value, &updated_json_value_str); struct json_string_s downloaded_json_key; create_json_string(&downloaded_json_key, "downloaded", 10); struct json_object_s downloaded_json; downloaded_json.start = NULL; downloaded_json.length = 0; struct json_value_s downloaded_json_value; downloaded_json_value.payload = &downloaded_json; downloaded_json_value.type = json_type_object; struct json_object_element_s downloaded_title_element; downloaded_title_element.name = &title_json_key; downloaded_title_element.value = &title_json_value; struct json_object_element_s downloaded_time_element; downloaded_time_element.name = &time_json_key; downloaded_time_element.value = &time_json_value; struct json_object_element_s downloaded_url_element; downloaded_url_element.name = &url_json_key; downloaded_url_element.value = &url_json_value; downloaded_title_element.next = &downloaded_time_element; downloaded_time_element.next = &downloaded_url_element; downloaded_url_element.next = NULL; struct json_array_s downloaded_json_array; downloaded_json_array.start = NULL; downloaded_json_array.length = 0; struct json_array_element_s downloaded_json_array_element; if(start_after) { downloaded_json.start = &downloaded_title_element; downloaded_json.length = 3; downloaded_json_array_element.value = &downloaded_json_value; downloaded_json_array_element.next = NULL; downloaded_json_array.start = &downloaded_json_array_element; downloaded_json_array.length = 1; } struct json_value_s downloaded_json_array_value; downloaded_json_array_value.payload = &downloaded_json_array; downloaded_json_array_value.type = json_type_array; struct json_object_s json_root; json_root.length = 3; struct json_object_element_s link_element; link_element.name = &link_json_key; link_element.value = &link_json_value; struct json_object_element_s updated_element; updated_element.name = &updated_json_key; updated_element.value = &updated_json_value; struct json_object_element_s downloaded_element; downloaded_element.name = &downloaded_json_key; downloaded_element.value = &downloaded_json_array_value; struct json_object_element_s plugin_element; plugin_element.name = &plugin_json_key; plugin_element.value = &plugin_json_value; link_element.next = &updated_element; updated_element.next = &downloaded_element; downloaded_element.next = NULL; if(plugin_name) { json_root.start = &plugin_element; plugin_element.next = &link_element; } else { json_root.start = &link_element; } struct json_value_s json_root_value; json_root_value.payload = &json_root; json_root_value.type = json_type_object; size_t json_body_size = 0; char *json_body_str = json_write_pretty(&json_root_value, " ", "\n", &json_body_size); if(!json_body_str) { fprintf(stderr, "Failed to write json data to file %s/%s\n", dir, filename); return -1; } /* Workaround json bug (?) */ json_body_size = strlen(json_body_str); int result = file_overwrite_in_dir(dir, filename, json_body_str, json_body_size); free(json_body_str); return result; } static struct json_array_element_s* get_last_element_in_json_array(struct json_array_s *json_array) { struct json_array_element_s *json_element = json_array->start; while(json_element) { struct json_array_element_s *next_json_element = json_element->next; if(next_json_element) json_element = next_json_element; else return json_element; } return NULL; } /* TODO: If this fails in the middle, recover and update the next time somehow */ int tracked_item_update_latest(TrackedItem *tracked_item, char *tracked_dir, DownloadItemsData **download_items, char **filenames, int num_download_items) { assert(num_download_items <= MAX_UPDATE_ITEMS); int tracked_dir_len = strlen(tracked_dir); int result = 0; char *item_filepath = tracked_dir; strcat(item_filepath, tracked_item->title); char updated[32]; assert(sizeof(time_t) == sizeof(long)); sprintf(updated, "%ld", time(NULL)); int updated_len = strlen(updated); result = file_overwrite_in_dir(item_filepath, "updated", updated, updated_len); if(result != 0) { fprintf(stderr, "Failed to update %s/updated\n", item_filepath); goto cleanup; } struct json_value_s *updated_field = json_object_get_field_by_name(tracked_item->json_data, "updated"); if(updated_field) { struct json_string_s *updated_json = json_value_as_string(updated_field); updated_json->string = updated; updated_json->string_size = updated_len; } else { fprintf(stderr, "Corrupt json for rss item: %s\n", item_filepath); } struct json_value_s *downloaded_json = json_object_get_field_by_name(tracked_item->json_data, "downloaded"); struct json_array_s *downloaded_json_array = NULL; struct json_array_s new_downloaded_array; new_downloaded_array.length = 1; new_downloaded_array.start = NULL; struct json_value_s new_downloaded_array_val; new_downloaded_array_val.payload = &new_downloaded_array; new_downloaded_array_val.type = json_type_array; struct json_string_s downloaded_json_key; create_json_string(&downloaded_json_key, "downloaded", 10); struct json_object_element_s new_downloaded_array_obj_el; new_downloaded_array_obj_el.name = &downloaded_json_key; new_downloaded_array_obj_el.value = &new_downloaded_array_val; if(downloaded_json) { downloaded_json_array = json_value_as_array(downloaded_json); if(!downloaded_json_array) { fprintf(stderr, "Corrupt json for rss item: %s\n", item_filepath); result = -1; goto cleanup; } } else { downloaded_json_array = &new_downloaded_array; } struct json_string_s title_json_key; create_json_string(&title_json_key, "title", 5); struct json_string_s filename_json_key; create_json_string(&filename_json_key, "filename", 8); struct json_string_s time_json_key; create_json_string(&time_json_key, "time", 4); struct json_string_s url_json_key; create_json_string(&url_json_key, "url", 3); struct json_string_s title_json_value_str[MAX_UPDATE_ITEMS]; struct json_value_s title_json_value[MAX_UPDATE_ITEMS]; struct json_string_s filename_json_value_str[MAX_UPDATE_ITEMS]; struct json_value_s filename_json_value[MAX_UPDATE_ITEMS]; struct json_string_s time_value_str[MAX_UPDATE_ITEMS]; struct json_value_s time_json_value[MAX_UPDATE_ITEMS]; struct json_string_s url_value_str[MAX_UPDATE_ITEMS]; struct json_value_s url_json_value[MAX_UPDATE_ITEMS]; struct json_object_element_s downloaded_title_element[MAX_UPDATE_ITEMS]; struct json_object_element_s downloaded_filename_element[MAX_UPDATE_ITEMS]; struct json_object_element_s downloaded_time_element[MAX_UPDATE_ITEMS]; struct json_object_element_s downloaded_url_element[MAX_UPDATE_ITEMS]; struct json_object_s new_downloaded_json_obj[MAX_UPDATE_ITEMS]; struct json_value_s new_downloaded_json_val[MAX_UPDATE_ITEMS]; struct json_array_element_s new_downloaded_item_element[MAX_UPDATE_ITEMS]; struct json_array_element_s *last_downloaded_element = NULL; for(int i = 0; i < num_download_items; ++i) { create_json_string(&title_json_value_str[i], download_items[i]->title, strlen(download_items[i]->title)); init_json_value_str(&title_json_value[i], &title_json_value_str[i]); if(filenames) { create_json_string(&filename_json_value_str[i], filenames[i], strlen(filenames[i])); init_json_value_str(&filename_json_value[i], &filename_json_value_str[i]); } create_json_string(&time_value_str[i], updated, updated_len); init_json_value_str(&time_json_value[i], &time_value_str[i]); create_json_string(&url_value_str[i], download_items[i]->link, strlen(download_items[i]->link)); init_json_value_str(&url_json_value[i], &url_value_str[i]); downloaded_title_element[i].name = &title_json_key; downloaded_title_element[i].value = &title_json_value[i]; if(filenames) { downloaded_filename_element[i].name = &filename_json_key; downloaded_filename_element[i].value = &filename_json_value[i]; } downloaded_time_element[i].name = &time_json_key; downloaded_time_element[i].value = &time_json_value[i]; downloaded_url_element[i].name = &url_json_key; downloaded_url_element[i].value = &url_json_value[i]; downloaded_title_element[i].next = &downloaded_time_element[i]; downloaded_time_element[i].next = &downloaded_url_element[i]; downloaded_url_element[i].next = NULL; if(filenames) { downloaded_url_element[i].next = &downloaded_filename_element[i]; downloaded_filename_element[i].next = NULL; new_downloaded_json_obj[i].length = 4; } else { new_downloaded_json_obj[i].length = 3; } new_downloaded_json_obj[i].start = &downloaded_title_element[i]; new_downloaded_json_val[i].payload = &new_downloaded_json_obj[i]; new_downloaded_json_val[i].type = json_type_object; new_downloaded_item_element[i].value = &new_downloaded_json_val[i]; new_downloaded_item_element[i].next = NULL; if(downloaded_json_array->length > 0) { if(!last_downloaded_element) last_downloaded_element = get_last_element_in_json_array(downloaded_json_array); if(last_downloaded_element) last_downloaded_element->next = &new_downloaded_item_element[i]; else downloaded_json_array->start = &new_downloaded_item_element[i]; last_downloaded_element = &new_downloaded_item_element[i]; downloaded_json_array->length++; } else { downloaded_json_array->start = &new_downloaded_item_element[i]; downloaded_json_array->length = 1; last_downloaded_element = &new_downloaded_item_element[i]; struct json_object_element_s *prev_start = tracked_item->json_data->start; tracked_item->json_data->start = &new_downloaded_array_obj_el; new_downloaded_array_obj_el.next = prev_start; tracked_item->json_data->length++; } } struct json_value_s json_root_value; json_root_value.payload = tracked_item->json_data; json_root_value.type = json_type_object; size_t json_body_size = 0; char *json_body_str = json_write_pretty(&json_root_value, " ", "\n", &json_body_size); if(!json_body_str) { fprintf(stderr, "Failed to write json data to file %s/data\n", item_filepath); result = -1; goto cleanup; } /* Workaround json bug (?) */ json_body_size = strlen(json_body_str); result = file_overwrite_in_dir(item_filepath, "data", json_body_str, json_body_size); free(json_body_str); cleanup: tracked_dir[tracked_dir_len] = '\0'; return result; } 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; } void create_json_string(struct json_string_s *json_result, const char *str, int len) { json_result->string = str; json_result->string_size = len; } void init_json_value_str(struct json_value_s *json_value, struct json_string_s *json_str) { json_value->payload = json_str; json_value->type = json_type_string; }