From 344cce084f2085d393c9f55b8c58fb578fdc373e Mon Sep 17 00:00:00 2001 From: Maarten Billemont Date: Wed, 23 Oct 2019 13:15:21 -0400 Subject: [PATCH] Don't keep deleted sites & questions. + ability to filter / delete data children. --- .../c/core/src/mpw-marshal-util.c | 42 +++---- platform-independent/c/core/src/mpw-marshal.c | 116 ++++++++++++++---- platform-independent/c/core/src/mpw-marshal.h | 5 + 3 files changed, 114 insertions(+), 49 deletions(-) diff --git a/platform-independent/c/core/src/mpw-marshal-util.c b/platform-independent/c/core/src/mpw-marshal-util.c index 4fabf682..ab0884d9 100644 --- a/platform-independent/c/core/src/mpw-marshal-util.c +++ b/platform-independent/c/core/src/mpw-marshal-util.c @@ -122,6 +122,14 @@ bool mpw_get_json_boolean( return json_object_get_boolean( json_value ) == true; } +static bool mpw_marshal_data_keep_keyed(MPMarshalledData *child, void *args) { + return child->obj_key != NULL; +} + +static bool mpw_marshal_data_keep_unkeyed(MPMarshalledData *child, void *args) { + return child->obj_key == NULL; +} + void mpw_set_json_data( MPMarshalledData *data, json_object *obj) { @@ -150,34 +158,12 @@ void mpw_set_json_data( } // Clean up children - MPMarshalledData *newChildren = NULL; - size_t newChildrenCount = 0; - for (size_t c = 0; c < data->children_count; ++c) { - MPMarshalledData *child = &data->children[c]; - if ((type != json_type_object && type != json_type_array) || (child->obj_key && type != json_type_object)) { - // Not a valid child in this object, remove it. - mpw_marshal_data_set_null( child, NULL ); - mpw_free_string( &child->obj_key ); - if (!newChildren) - newChildren = mpw_memdup( data->children, sizeof( MPMarshalledData ) * newChildrenCount ); - } - else { - // Valid child in this object, keep it. - ++newChildrenCount; - if (newChildren) { - if (!mpw_realloc( &newChildren, NULL, sizeof( MPMarshalledData ) * newChildrenCount )) { - --newChildrenCount; - continue; - } - child->arr_index = newChildrenCount - 1; - newChildren[child->arr_index] = *child; - } - } - } - if (newChildren) { - mpw_free( &data->children, sizeof( MPMarshalledData ) * data->children_count ); - data->children = newChildren; - data->children_count = newChildrenCount; + if (type != json_type_object && type != json_type_array) { + mpw_marshal_data_keep( data, mpw_marshal_data_keep_none, NULL ); + } else if (type == json_type_array) { + mpw_marshal_data_keep( data, mpw_marshal_data_keep_unkeyed, NULL ); + } else /* type == json_type_object */ { + mpw_marshal_data_keep( data, mpw_marshal_data_keep_keyed, NULL ); } // Object diff --git a/platform-independent/c/core/src/mpw-marshal.c b/platform-independent/c/core/src/mpw-marshal.c index 3cba1d7a..d51a091f 100644 --- a/platform-independent/c/core/src/mpw-marshal.c +++ b/platform-independent/c/core/src/mpw-marshal.c @@ -441,10 +441,54 @@ bool mpw_marshal_data_set_str( return success; } +void mpw_marshal_data_keep( + MPMarshalledData *data, bool (*filter)(MPMarshalledData *, void *), void *args) { + + size_t children_count = 0; + MPMarshalledData *children = NULL; + + for (size_t c = 0; c < data->children_count; ++c) { + MPMarshalledData *child = &data->children[c]; + if (filter( child, args )) { + // Valid child in this object, keep it. + ++children_count; + + if (children) { + if (!mpw_realloc( &children, NULL, sizeof( MPMarshalledData ) * children_count )) { + --children_count; + continue; + } + child->arr_index = children_count - 1; + children[child->arr_index] = *child; + } + } + else { + // Not a valid child in this object, remove it. + mpw_marshal_data_set_null( child, NULL ); + mpw_free_string( &child->obj_key ); + + if (!children) + children = mpw_memdup( data->children, sizeof( MPMarshalledData ) * children_count ); + } + } + + if (children) { + mpw_free( &data->children, sizeof( MPMarshalledData ) * data->children_count ); + data->children = children; + data->children_count = children_count; + } +} + +bool mpw_marshal_data_keep_none( + MPMarshalledData *child, void *args) { + + return false; +} + static const char *mpw_marshal_write_flat( MPMarshalledFile *file) { - MPMarshalledData *data = file->data; + const MPMarshalledData *data = file->data; if (!data) { file->error = (MPMarshalError){ MPMarshalErrorMissing, "Missing data." }; return NULL; @@ -566,6 +610,30 @@ static const char *mpw_marshal_write_json( #endif +static bool mpw_marshal_data_keep_site_exists( + MPMarshalledData *child, void *args) { + MPMarshalledUser *user = args; + + for (size_t s = 0; s < user->sites_count; ++s) { + if (strcmp( (&user->sites[s])->siteName, child->obj_key ) == OK) + return true; + } + + return false; +} + +static bool mpw_marshal_data_keep_question_exists( + MPMarshalledData *child, void *args) { + MPMarshalledSite *site = args; + + for (size_t s = 0; s < site->questions_count; ++s) { + if (strcmp( (&site->questions[s])->keyword, child->obj_key ) == OK) + return true; + } + + return false; +} + const char *mpw_marshal_write( const MPMarshalFormat outFormat, MPMarshalledFile *file, MPMarshalledUser *user) { @@ -589,23 +657,27 @@ const char *mpw_marshal_write( masterKey = user->masterKeyProvider( user->algorithm, user->fullName ); // Section: "export" - mpw_marshal_data_set_bool( user->redacted, data, "export", "redacted", NULL ); + MPMarshalledData *data_export = mpw_marshal_data_get( data, "export", NULL ); + mpw_marshal_data_set_bool( user->redacted, data_export, "redacted", NULL ); char dateString[21]; time_t now = time( NULL ); if (strftime( dateString, sizeof( dateString ), "%FT%TZ", gmtime( &now ) )) - mpw_marshal_data_set_str( dateString, data, "export", "date", NULL ); + mpw_marshal_data_set_str( dateString, data_export, "date", NULL ); // Section: "user" - mpw_marshal_data_set_num( user->avatar, data, "user", "avatar", NULL ); - mpw_marshal_data_set_str( user->fullName, data, "user", "full_name", NULL ); - mpw_marshal_data_set_str( mpw_identicon_encode( user->identicon ), data, "user", "identicon", NULL ); - mpw_marshal_data_set_num( user->algorithm, data, "user", "algorithm", NULL ); - mpw_marshal_data_set_str( user->keyID, data, "user", "key_id", NULL ); - mpw_marshal_data_set_num( user->defaultType, data, "user", "default_type", NULL ); + MPMarshalledData *data_user = mpw_marshal_data_get( data, "user", NULL ); + mpw_marshal_data_set_num( user->avatar, data_user, "avatar", NULL ); + mpw_marshal_data_set_str( user->fullName, data_user, "full_name", NULL ); + mpw_marshal_data_set_str( mpw_identicon_encode( user->identicon ), data_user, "identicon", NULL ); + mpw_marshal_data_set_num( user->algorithm, data_user, "algorithm", NULL ); + mpw_marshal_data_set_str( user->keyID, data_user, "key_id", NULL ); + mpw_marshal_data_set_num( user->defaultType, data_user, "default_type", NULL ); if (strftime( dateString, sizeof( dateString ), "%FT%TZ", gmtime( &user->lastUsed ) )) - mpw_marshal_data_set_str( dateString, data, "user", "last_used", NULL ); + mpw_marshal_data_set_str( dateString, data_user, "last_used", NULL ); // Section "sites" + MPMarshalledData *data_sites = mpw_marshal_data_get( data, "sites", NULL ); + mpw_marshal_data_keep( data_sites, mpw_marshal_data_keep_site_exists, user ); for (size_t s = 0; s < user->sites_count; ++s) { MPMarshalledSite *site = &user->sites[s]; if (!site->siteName || !strlen( site->siteName )) @@ -633,16 +705,18 @@ const char *mpw_marshal_write( loginState = mpw_strdup( site->loginState ); } - mpw_marshal_data_set_num( site->counter, data, "sites", site->siteName, "counter", NULL ); - mpw_marshal_data_set_num( site->algorithm, data, "sites", site->siteName, "algorithm", NULL ); - mpw_marshal_data_set_num( site->resultType, data, "sites", site->siteName, "type", NULL ); - mpw_marshal_data_set_str( resultState, data, "sites", site->siteName, "password", NULL ); - mpw_marshal_data_set_num( site->loginType, data, "sites", site->siteName, "login_type", NULL ); - mpw_marshal_data_set_str( loginState, data, "sites", site->siteName, "login_name", NULL ); - mpw_marshal_data_set_num( site->uses, data, "sites", site->siteName, "uses", NULL ); + mpw_marshal_data_set_num( site->counter, data_sites, site->siteName, "counter", NULL ); + mpw_marshal_data_set_num( site->algorithm, data_sites, site->siteName, "algorithm", NULL ); + mpw_marshal_data_set_num( site->resultType, data_sites, site->siteName, "type", NULL ); + mpw_marshal_data_set_str( resultState, data_sites, site->siteName, "password", NULL ); + mpw_marshal_data_set_num( site->loginType, data_sites, site->siteName, "login_type", NULL ); + mpw_marshal_data_set_str( loginState, data_sites, site->siteName, "login_name", NULL ); + mpw_marshal_data_set_num( site->uses, data_sites, site->siteName, "uses", NULL ); if (strftime( dateString, sizeof( dateString ), "%FT%TZ", gmtime( &site->lastUsed ) )) - mpw_marshal_data_set_str( dateString, data, "sites", site->siteName, "last_used", NULL ); + mpw_marshal_data_set_str( dateString, data_sites, site->siteName, "last_used", NULL ); + MPMarshalledData *data_questions = mpw_marshal_data_get( data, "sites", site->siteName, "questions", NULL ); + mpw_marshal_data_keep( data_questions, mpw_marshal_data_keep_question_exists, site ); for (size_t q = 0; q < site->questions_count; ++q) { MPMarshalledQuestion *question = &site->questions[q]; if (!question->keyword) @@ -660,12 +734,12 @@ const char *mpw_marshal_write( MPKeyPurposeRecovery, question->keyword, question->type, question->state, site->algorithm ); } - mpw_marshal_data_set_num( question->type, data, "sites", site->siteName, "questions", question->keyword, "type", NULL ); - mpw_marshal_data_set_str( answer, data, "sites", site->siteName, "questions", question->keyword, "answer", NULL ); + mpw_marshal_data_set_num( question->type, data_questions, question->keyword, "type", NULL ); + mpw_marshal_data_set_str( answer, data_questions, question->keyword, "answer", NULL ); mpw_free_strings( &answer, NULL ); } - mpw_marshal_data_set_str( site->url, data, "sites", site->siteName, "_ext_mpw", "url", NULL ); + mpw_marshal_data_set_str( site->url, data_sites, site->siteName, "_ext_mpw", "url", NULL ); mpw_free_strings( &resultState, &loginState, NULL ); } diff --git a/platform-independent/c/core/src/mpw-marshal.h b/platform-independent/c/core/src/mpw-marshal.h index 2766b076..484b9aaa 100644 --- a/platform-independent/c/core/src/mpw-marshal.h +++ b/platform-independent/c/core/src/mpw-marshal.h @@ -253,6 +253,11 @@ bool mpw_marshal_data_set_str( const char *value, MPMarshalledData *data, ...); bool mpw_marshal_data_vset_str( const char *value, MPMarshalledData *data, va_list nodes); +/** Keep only the data children that pass the filter test. */ +void mpw_marshal_data_keep( + MPMarshalledData *data, bool (*filter)(MPMarshalledData *child, void *args), void *args); +bool mpw_marshal_data_keep_none( + MPMarshalledData *child, void *args); //// Format.