diff --git a/mfapi/apicalls.h b/mfapi/apicalls.h index 784f7f4..a0de610 100644 --- a/mfapi/apicalls.h +++ b/mfapi/apicalls.h @@ -36,7 +36,9 @@ int mfconn_api_folder_create(mfconn * conn, const char *parent, const char *name); long mfconn_api_folder_get_content(mfconn * conn, int mode, - mffolder * folder_curr); + mffolder * folder_curr, + mffolder ***folder_result, + mffile ***file_result); int mfconn_api_folder_get_info(mfconn * conn, mffolder * folder, const char *folderkey); diff --git a/mfapi/apicalls/folder_get_content.c b/mfapi/apicalls/folder_get_content.c index 9aebc6f..1f5bc27 100644 --- a/mfapi/apicalls/folder_get_content.c +++ b/mfapi/apicalls/folder_get_content.c @@ -17,9 +17,12 @@ * */ +#define _XOPEN_SOURCE // for strptime +#include #include #include #include +#include #include "../../utils/http.h" #include "../../utils/json.h" @@ -32,8 +35,14 @@ static int _decode_folder_get_content_folders(mfhttp * conn, void *data); static int _decode_folder_get_content_files(mfhttp * conn, void *data); +/* + * the helper functions will do a realloc on the values pointed to by + * mffolder_result and mffile_result so make sure that those are either NULL + * or values of already malloc'ed regions. They must not be uninitialized + * values. + */ long -mfconn_api_folder_get_content(mfconn * conn, int mode, mffolder * folder_curr) +mfconn_api_folder_get_content(mfconn * conn, int mode, mffolder * folder_curr, mffolder ***mffolder_result, mffile ***mffile_result) { const char *api_call; int retval; @@ -67,11 +76,11 @@ mfconn_api_folder_get_content(mfconn * conn, int mode, mffolder * folder_curr) if (mode == 0) retval = http_get_buf(http, api_call, - _decode_folder_get_content_folders, NULL); + _decode_folder_get_content_folders, (void *)mffolder_result); else retval = http_get_buf(http, api_call, - _decode_folder_get_content_files, NULL); + _decode_folder_get_content_files, (void *)mffile_result); http_destroy(http); free((void *)api_call); @@ -89,12 +98,20 @@ static int _decode_folder_get_content_folders(mfhttp * conn, void *user_ptr) json_t *folders_array; json_t *folderkey; json_t *folder_name; - char *folder_name_tmp; + json_t *j_obj; + + char *ret; + struct tm tm; int array_sz; int i = 0; - if (user_ptr != NULL) + mffolder ***mffolder_result; + mffolder *tmp_folder; + size_t len_mffolder_result; + + mffolder_result = (mffolder ***)user_ptr; + if (mffolder_result == NULL) return -1; root = http_parse_buf_json(conn, 0, &error); @@ -110,6 +127,7 @@ static int _decode_folder_get_content_folders(mfhttp * conn, void *user_ptr) return -1; } + len_mffolder_result = 0; array_sz = json_array_size(folders_array); for (i = 0; i < array_sz; i++) { data = json_array_get(folders_array, i); @@ -120,17 +138,45 @@ static int _decode_folder_get_content_folders(mfhttp * conn, void *user_ptr) folder_name = json_object_get(data, "name"); if (folderkey != NULL && folder_name != NULL) { - folder_name_tmp = strdup_printf("< %s >", - json_string_value(folder_name)); + tmp_folder = folder_alloc(); - printf(" %-15.13s %s\n\r", - json_string_value(folderkey), folder_name_tmp); + folder_set_key(tmp_folder, json_string_value(folderkey)); + folder_set_name(tmp_folder, json_string_value(folder_name)); - free(folder_name_tmp); + j_obj = json_object_get(data, "revision"); + if (j_obj != NULL) { + folder_set_revision(tmp_folder, atoll(json_string_value(j_obj))); + } + + j_obj = json_object_get(data, "parent"); + if (j_obj != NULL) { + folder_set_parent(tmp_folder, json_string_value(j_obj)); + } + + j_obj = json_object_get(data, "created"); + if (j_obj != NULL) { + memset(&tm, 0, sizeof(struct tm)); + ret = strptime(json_string_value(j_obj), "%F %T", &tm); + if (ret[0] == '\0') { + folder_set_created(tmp_folder, mktime(&tm)); + } + } + + len_mffolder_result++; + *mffolder_result = + (mffolder**)realloc(*mffolder_result, + len_mffolder_result*sizeof(mffolder*)); + (*mffolder_result)[len_mffolder_result - 1] = tmp_folder; } } } + // append an terminating empty mffolder + len_mffolder_result++; + *mffolder_result = (mffolder**)realloc(*mffolder_result, len_mffolder_result*sizeof(mffolder*)); + // write an empty last element + (*mffolder_result)[len_mffolder_result-1] = NULL; + if (root != NULL) json_decref(root); @@ -147,10 +193,20 @@ static int _decode_folder_get_content_files(mfhttp * conn, void *user_ptr) json_t *files_array; json_t *quickkey; json_t *file_name; + json_t *j_obj; + + char *ret; + struct tm tm; + int array_sz; int i = 0; - if (user_ptr != NULL) + mffile ***mffile_result; + mffile *tmp_file; + size_t len_mffile_result; + + mffile_result = (mffile ***)user_ptr; + if (mffile_result == NULL) return -1; root = http_parse_buf_json(conn, 0, &error); @@ -163,6 +219,7 @@ static int _decode_folder_get_content_files(mfhttp * conn, void *user_ptr) return -1; } + len_mffile_result = 0; array_sz = json_array_size(files_array); for (i = 0; i < array_sz; i++) { data = json_array_get(files_array, i); @@ -173,13 +230,51 @@ static int _decode_folder_get_content_files(mfhttp * conn, void *user_ptr) file_name = json_object_get(data, "filename"); if (quickkey != NULL && file_name != NULL) { - printf(" %-15.15s %s\n\r", - json_string_value(quickkey), - json_string_value(file_name)); + tmp_file = file_alloc(); + + file_set_key(tmp_file, json_string_value(quickkey)); + file_set_name(tmp_file, json_string_value(file_name)); + + j_obj = json_object_get(data, "size"); + if (j_obj != NULL) { + file_set_size(tmp_file, atoll(json_string_value(j_obj))); + } + + j_obj = json_object_get(data, "created"); + if (j_obj != NULL ) { + memset(&tm, 0, sizeof(struct tm)); + ret = strptime(json_string_value(j_obj), "%F %T", &tm); + if (ret[0] == '\0') { + file_set_created(tmp_file, mktime(&tm)); + } + } + + j_obj = json_object_get(data, "revision"); + if (j_obj != NULL) { + file_set_revision(tmp_file, atoll(json_string_value(j_obj))); + } + + // FIXME don't save hex ascii string but binary chars instead + j_obj = json_object_get(data, "hash"); + if (j_obj != NULL) { + file_set_hash(tmp_file, json_string_value(j_obj)); + } + + len_mffile_result++; + *mffile_result = + (mffile**)realloc(*mffile_result, + len_mffile_result*sizeof(mffile*)); + (*mffile_result)[len_mffile_result - 1] = tmp_file; } } } + // append a terminating empty file + len_mffile_result++; + *mffile_result = (mffile**)realloc(*mffile_result, len_mffile_result*sizeof(mffile*)); + // write an empty last element + (*mffile_result)[len_mffile_result - 1] = NULL; + if (root != NULL) json_decref(root); diff --git a/mfapi/file.c b/mfapi/file.c index d36d259..8cf033e 100644 --- a/mfapi/file.c +++ b/mfapi/file.c @@ -32,8 +32,9 @@ struct mffile { char quickkey[18]; char hash[65]; char name[256]; - char mtime[16]; + time_t created; uint64_t revision; + uint64_t size; char *share_link; char *direct_link; @@ -142,6 +143,60 @@ const char *file_get_name(mffile * file) return file->name; } +int file_set_size(mffile * file, uint64_t size) +{ + if (file == NULL) + return -1; + + file->size = size; + + return 0; +} + +uint64_t file_get_size(mffile * file) +{ + if (file == NULL) + return -1; + + return file->size; +} + +int file_set_revision(mffile * file, uint64_t revision) +{ + if (file == NULL) + return -1; + + file->revision = revision; + + return 0; +} + +uint64_t file_get_revision(mffile * file) +{ + if (file == NULL) + return -1; + + return file->revision; +} + +int file_set_created(mffile * file, time_t created) +{ + if (file == NULL) + return -1; + + file->created = created; + + return 0; +} + +time_t file_get_created(mffile * file) +{ + if (file == NULL) + return -1; + + return file->created; +} + int file_set_share_link(mffile * file, const char *share_link) { if (file == NULL) diff --git a/mfapi/file.h b/mfapi/file.h index b20570c..fd121bc 100644 --- a/mfapi/file.h +++ b/mfapi/file.h @@ -54,4 +54,16 @@ const char *file_get_onetime_link(mffile * file); ssize_t file_download_direct(mffile * file, const char *local_dir); +int file_set_size(mffile * file, uint64_t size); + +uint64_t file_get_size(mffile * file); + +int file_set_revision(mffile * file, uint64_t revision); + +uint64_t file_get_revision(mffile * file); + +int file_set_created(mffile * file, time_t created); + +time_t file_get_created(mffile * file); + #endif diff --git a/mfshell/commands/list.c b/mfshell/commands/list.c index bea5e4d..922d756 100644 --- a/mfshell/commands/list.c +++ b/mfshell/commands/list.c @@ -22,12 +22,17 @@ #include "../../mfapi/apicalls.h" #include "../mfshell.h" #include "../../mfapi/mfconn.h" +#include "../../mfapi/folder.h" +#include "../../mfapi/file.h" #include "../commands.h" // IWYU pragma: keep int mfshell_cmd_list(mfshell * mfshell, int argc, char *const argv[]) { (void)argv; int retval; + mffolder **folder_result; + mffile **file_result; + int i; if (mfshell == NULL) return -1; @@ -36,15 +41,26 @@ int mfshell_cmd_list(mfshell * mfshell, int argc, char *const argv[]) fprintf(stderr, "Invalid number of arguments\n"); return -1; } + // first folders + folder_result = NULL; retval = - mfconn_api_folder_get_content(mfshell->conn, 0, mfshell->folder_curr); + mfconn_api_folder_get_content(mfshell->conn, 0, mfshell->folder_curr, &folder_result, NULL); mfconn_update_secret_key(mfshell->conn); + for (i = 0; folder_result[i] != NULL; i++) { + printf("%s %s\n", folder_get_name(folder_result[i]), folder_get_key(folder_result[i])); + } + // then files + file_result = NULL; retval = - mfconn_api_folder_get_content(mfshell->conn, 1, mfshell->folder_curr); + mfconn_api_folder_get_content(mfshell->conn, 1, mfshell->folder_curr, NULL, &file_result); mfconn_update_secret_key(mfshell->conn); + for (i = 0; file_result[i] != NULL; i++) { + printf("%s %s\n", file_get_name(file_result[i]), file_get_key(file_result[i])); + } + return retval; } diff --git a/mfshell/commands/status.c b/mfshell/commands/status.c index 368ed4b..a7e3ebf 100644 --- a/mfshell/commands/status.c +++ b/mfshell/commands/status.c @@ -18,6 +18,7 @@ */ #include +#include #include "../../mfapi/apicalls.h" #include "../mfshell.h" @@ -28,6 +29,7 @@ int mfshell_cmd_status(mfshell * mfshell, int argc, char *const argv[]) { (void)argv; int retval; + uint64_t revision; if (mfshell == NULL) return -1; @@ -37,8 +39,13 @@ int mfshell_cmd_status(mfshell * mfshell, int argc, char *const argv[]) return -1; } // then files - retval = mfconn_api_device_get_status(mfshell->conn); + retval = mfconn_api_device_get_status(mfshell->conn, &revision); mfconn_update_secret_key(mfshell->conn); + if (retval == 0) { + printf("device_revision: %" PRIu64 "\n", revision); + } else { + fprintf(stderr, "device/get_status() unsuccessful\n"); + } return retval; }