diff --git a/mfapi/apicalls.h b/mfapi/apicalls.h index 3459443..55f115b 100644 --- a/mfapi/apicalls.h +++ b/mfapi/apicalls.h @@ -26,6 +26,19 @@ #include "folder.h" #include "mfconn.h" +enum mfconn_device_change_type { + MFCONN_DEVICE_CHANGE_DELETED_FOLDER, + MFCONN_DEVICE_CHANGE_DELETED_FILE, + MFCONN_DEVICE_CHANGE_UPDATED_FOLDER, + MFCONN_DEVICE_CHANGE_UPDATED_FILE +}; + +struct mfconn_device_change { + enum mfconn_device_change_type change; + char key[20]; + uint64_t revision; +}; + int mfconn_api_file_get_info(mfconn * conn, mffile * file, char *quickkey); @@ -60,7 +73,7 @@ int mfconn_api_folder_delete(mfconn * conn, const char *folderkey); int mfconn_api_device_get_status(mfconn * conn, uint64_t * revision); -int mfconn_api_device_get_changes(mfconn * conn, - uint64_t revision); +int mfconn_api_device_get_changes(mfconn * conn, uint64_t revision, struct mfconn_device_change + **changes); #endif diff --git a/mfapi/apicalls/device_get_changes.c b/mfapi/apicalls/device_get_changes.c index d90ed70..84a45aa 100644 --- a/mfapi/apicalls/device_get_changes.c +++ b/mfapi/apicalls/device_get_changes.c @@ -18,10 +18,11 @@ */ #include -#include #include #include #include +#include +#include #include "../../utils/http.h" #include "../../utils/json.h" @@ -30,7 +31,14 @@ static int _decode_device_get_changes(mfhttp * conn, void *data); -int mfconn_api_device_get_changes(mfconn * conn, uint64_t revision) +/* + * the mfconn_device_change array will be realloc'ed so it must either point + * to a malloc'ed memory or be NULL + * + * the returned array will be sorted by revision + */ +int mfconn_api_device_get_changes(mfconn * conn, uint64_t revision, + struct mfconn_device_change **changes) { const char *api_call; int retval; @@ -44,7 +52,9 @@ int mfconn_api_device_get_changes(mfconn * conn, uint64_t revision) "&response_format=json", revision); http = http_create(); - retval = http_get_buf(http, api_call, _decode_device_get_changes, NULL); + retval = + http_get_buf(http, api_call, _decode_device_get_changes, + (void *)changes); http_destroy(http); free((void *)api_call); @@ -52,6 +62,30 @@ int mfconn_api_device_get_changes(mfconn * conn, uint64_t revision) return retval; } +static void aux(json_t * key, json_t * revision, + enum mfconn_device_change_type change, + struct mfconn_device_change **changes, size_t * len_changes) +{ + struct mfconn_device_change *tmp_change; + + if (key == NULL || revision == NULL) + return; + (*len_changes)++; + *changes = (struct mfconn_device_change *) + realloc(*changes, + (*len_changes) * sizeof(struct mfconn_device_change)); + tmp_change = *changes + (*len_changes) - 1; + tmp_change->change = change; + strncpy(tmp_change->key, json_string_value(key), sizeof(tmp_change->key)); + tmp_change->revision = atoll(json_string_value(revision)); +} + +static int change_compare(const void *a, const void *b) +{ + return ((struct mfconn_device_change *)a)->revision + - ((struct mfconn_device_change *)b)->revision; +} + static int _decode_device_get_changes(mfhttp * conn, void *user_ptr) { json_error_t error; @@ -61,57 +95,50 @@ static int _decode_device_get_changes(mfhttp * conn, void *user_ptr) json_t *obj_array; json_t *key; - json_t *parent; json_t *revision; int array_sz; int i = 0; - if (user_ptr != NULL) + struct mfconn_device_change **changes; + size_t len_changes; + + changes = (struct mfconn_device_change **)user_ptr; + if (changes == NULL) return -1; root = http_parse_buf_json(conn, 0, &error); + len_changes = 0; + node = json_object_by_path(root, "response/updated"); obj_array = json_object_get(node, "files"); if (json_is_array(obj_array)) { array_sz = json_array_size(obj_array); - printf("updated files:\n"); for (i = 0; i < array_sz; i++) { data = json_array_get(obj_array, i); - - if (json_is_object(data)) { - key = json_object_get(data, "quickkey"); - parent = json_object_get(data, "parent_folderkey"); - revision = json_object_get(data, "revision"); - - printf(" %s %s %s\n\r", json_string_value(key), - json_string_value(parent), json_string_value(revision)); - } + if (!json_is_object(data)) + continue; + key = json_object_get(data, "quickkey"); + revision = json_object_get(data, "revision"); + aux(key, revision, MFCONN_DEVICE_CHANGE_UPDATED_FILE, changes, + &len_changes); } - printf("\n"); } - node = json_object_by_path(root, "response/updated"); - obj_array = json_object_get(node, "folders"); if (json_is_array(obj_array)) { array_sz = json_array_size(obj_array); - printf("updated folders:\n"); for (i = 0; i < array_sz; i++) { data = json_array_get(obj_array, i); - - if (json_is_object(data)) { - key = json_object_get(data, "folderkey"); - parent = json_object_get(data, "parent_folderkey"); - revision = json_object_get(data, "revision"); - - printf(" %s %s %s\n\r", json_string_value(key), - json_string_value(parent), json_string_value(revision)); - } + if (!json_is_object(data)) + continue; + key = json_object_get(data, "folderkey"); + revision = json_object_get(data, "revision"); + aux(key, revision, MFCONN_DEVICE_CHANGE_UPDATED_FOLDER, changes, + &len_changes); } - printf("\n"); } node = json_object_by_path(root, "response/deleted"); @@ -119,42 +146,39 @@ static int _decode_device_get_changes(mfhttp * conn, void *user_ptr) obj_array = json_object_get(node, "files"); if (json_is_array(obj_array)) { array_sz = json_array_size(obj_array); - printf("deleted files:\n"); for (i = 0; i < array_sz; i++) { data = json_array_get(obj_array, i); - - if (json_is_object(data)) { - key = json_object_get(data, "quickkey"); - parent = json_object_get(data, "parent_folderkey"); - revision = json_object_get(data, "revision"); - - printf(" %s %s %s\n\r", json_string_value(key), - json_string_value(parent), json_string_value(revision)); - } + if (!json_is_object(data)) + continue; + key = json_object_get(data, "quickkey"); + revision = json_object_get(data, "revision"); + aux(key, revision, MFCONN_DEVICE_CHANGE_DELETED_FILE, changes, + &len_changes); } - printf("\n"); } - node = json_object_by_path(root, "response/deleted"); - obj_array = json_object_get(node, "folders"); if (json_is_array(obj_array)) { array_sz = json_array_size(obj_array); - printf("deleted folders:\n"); for (i = 0; i < array_sz; i++) { data = json_array_get(obj_array, i); - - if (json_is_object(data)) { - key = json_object_get(data, "folderkey"); - parent = json_object_get(data, "parent_folderkey"); - revision = json_object_get(data, "revision"); - - printf(" %s %s %s\n\r", json_string_value(key), - json_string_value(parent), json_string_value(revision)); - } + if (!json_is_object(data)) + continue; + key = json_object_get(data, "folderkey"); + revision = json_object_get(data, "revision"); + aux(key, revision, MFCONN_DEVICE_CHANGE_DELETED_FOLDER, changes, + &len_changes); } - printf("\n"); } + // sort + qsort(*changes, len_changes, sizeof(struct mfconn_device_change), + change_compare); + + // put a zero valued entry at the end + len_changes++; + *changes = (struct mfconn_device_change *) + realloc(*changes, len_changes * sizeof(struct mfconn_device_change)); + memset(*changes + len_changes - 1, 0, sizeof(struct mfconn_device_change)); if (root != NULL) json_decref(root); diff --git a/mfapi/apicalls/folder_get_content.c b/mfapi/apicalls/folder_get_content.c index 1d0c315..e26eccc 100644 --- a/mfapi/apicalls/folder_get_content.c +++ b/mfapi/apicalls/folder_get_content.c @@ -40,6 +40,10 @@ static int _decode_folder_get_content_files(mfhttp * conn, void *data); * 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. + * + * results are triple pointers because we cannot create an array of mffolder + * or mffile as we do not know their sizes. We can only create an array of + * pointers to them. */ long mfconn_api_folder_get_content(mfconn * conn, int mode, mffolder * folder_curr, diff --git a/mfshell/commands/changes.c b/mfshell/commands/changes.c index 3110608..ce52ecd 100644 --- a/mfshell/commands/changes.c +++ b/mfshell/commands/changes.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "../../mfapi/apicalls.h" #include "../mfshell.h" @@ -31,6 +32,8 @@ int mfshell_cmd_changes(mfshell * mfshell, int argc, char *const argv[]) (void)argv; int retval; uint64_t revision; + struct mfconn_device_change *changes; + int i; if (mfshell == NULL) return -1; @@ -47,8 +50,32 @@ int mfshell_cmd_changes(mfshell * mfshell, int argc, char *const argv[]) return -1; } - retval = mfconn_api_device_get_changes(mfshell->conn, revision); + changes = NULL; + retval = mfconn_api_device_get_changes(mfshell->conn, revision, &changes); mfconn_update_secret_key(mfshell->conn); + for (i = 0; changes[i].revision != 0; i++) { + switch (changes[i].change) { + case MFCONN_DEVICE_CHANGE_DELETED_FOLDER: + printf("%" PRIu64 " deleted folder: %s\n", changes[i].revision, + changes[i].key); + break; + case MFCONN_DEVICE_CHANGE_DELETED_FILE: + printf("%" PRIu64 " deleted file: %s\n", changes[i].revision, + changes[i].key); + break; + case MFCONN_DEVICE_CHANGE_UPDATED_FOLDER: + printf("%" PRIu64 " updated folder: %s\n", changes[i].revision, + changes[i].key); + break; + case MFCONN_DEVICE_CHANGE_UPDATED_FILE: + printf("%" PRIu64 " updated file: %s\n", changes[i].revision, + changes[i].key); + break; + } + } + + free(changes); + return retval; } diff --git a/tests/valgrind.sh b/tests/valgrind.sh index 69cf738..7735e90 100755 --- a/tests/valgrind.sh +++ b/tests/valgrind.sh @@ -21,4 +21,4 @@ if [ ! -f "./.mediafire-tools.conf" -a ! -f "~/.mediafire-tools.conf" ]; then echo "no configuration file found" >&2 exit 1 fi -$cmd "${binary_dir}/mediafire-shell" -c "help; ls; whoami" +$cmd "${binary_dir}/mediafire-shell" -c "help; ls; changes"