Persist unknown JSON properties, expose to API, safety improvements.
This commit is contained in:
parent
fc1e86f0ca
commit
ddb786c332
@ -489,7 +489,7 @@ void cli_user(Arguments *args, Operation *operation) {
|
||||
mpw_free_string( &operation->sitesPath );
|
||||
mpw_marshal_free( &operation->file );
|
||||
operation->file = mpw_marshal_file( mpw_marshal_user(
|
||||
operation->fullName, cli_masterKeyProvider_op( operation ), MPAlgorithmVersionCurrent ) );
|
||||
operation->fullName, cli_masterKeyProvider_op( operation ), MPAlgorithmVersionCurrent ), NULL );
|
||||
}
|
||||
|
||||
else {
|
||||
@ -550,7 +550,7 @@ void cli_site(Arguments *args, Operation *operation) {
|
||||
// Load the site object from mpsites.
|
||||
MPMarshalledUser *user = operation->file->user;
|
||||
for (size_t s = 0; !operation->site && s < user->sites_count; ++s)
|
||||
if (strcmp( operation->siteName, (&user->sites[s])->siteName ) == 0)
|
||||
if (strcmp( operation->siteName, (&user->sites[s])->siteName ) == OK)
|
||||
operation->site = &user->sites[s];
|
||||
|
||||
// If no site from mpsites, create a new one.
|
||||
@ -571,8 +571,11 @@ void cli_question(Arguments *args, Operation *operation) {
|
||||
break;
|
||||
case MPKeyPurposeRecovery:
|
||||
for (size_t q = 0; !operation->question && q < operation->site->questions_count; ++q)
|
||||
if ((!operation->keyContext && !strlen( (&operation->site->questions[q])->keyword )) ||
|
||||
(operation->keyContext && strcmp( (&operation->site->questions[q])->keyword, operation->keyContext ) == 0))
|
||||
if (operation->keyContext == (&operation->site->questions[q])->keyword ||
|
||||
(!operation->keyContext && !strlen( (&operation->site->questions[q])->keyword )) ||
|
||||
(!(&operation->site->questions[q])->keyword && !strlen( operation->keyContext )) ||
|
||||
((operation->keyContext && (&operation->site->questions[q])->keyword) &&
|
||||
strcmp( (&operation->site->questions[q])->keyword, operation->keyContext ) == OK))
|
||||
operation->question = &operation->site->questions[q];
|
||||
|
||||
// If no question from mpsites, create a new one.
|
||||
@ -700,7 +703,7 @@ void cli_algorithmVersion(Arguments *args, Operation *operation) {
|
||||
void cli_sitesRedacted(Arguments *args, Operation *operation) {
|
||||
|
||||
if (args->sitesRedacted)
|
||||
operation->file->user->redacted = strcmp( args->sitesRedacted, "1" ) == 0;
|
||||
operation->file->user->redacted = strcmp( args->sitesRedacted, "1" ) == OK;
|
||||
|
||||
else if (!operation->file->user->redacted)
|
||||
wrn( "Sites configuration is not redacted. Use -R 1 to change this." );
|
||||
|
@ -45,18 +45,21 @@ static xmlChar const *mpw_xmlPath(xmlNodePtr context) {
|
||||
|
||||
xmlNodePtr mpw_xmlTestCaseNode(xmlNodePtr testCaseNode, const char *nodeName) {
|
||||
|
||||
if (!nodeName)
|
||||
return NULL;
|
||||
|
||||
// Try to find an attribute node.
|
||||
for (xmlAttrPtr child = testCaseNode->properties; child; child = child->next)
|
||||
if (xmlStrcmp( child->name, BAD_CAST nodeName ) == 0)
|
||||
if (xmlStrcmp( child->name, BAD_CAST nodeName ) == OK)
|
||||
return (xmlNodePtr)child;
|
||||
|
||||
// Try to find an element node.
|
||||
for (xmlNodePtr child = testCaseNode->children; child; child = child->next)
|
||||
if (xmlStrcmp( child->name, BAD_CAST nodeName ) == 0)
|
||||
if (xmlStrcmp( child->name, BAD_CAST nodeName ) == OK)
|
||||
return child;
|
||||
|
||||
// Missing content, try to find parent case.
|
||||
if (strcmp( nodeName, "parent" ) == 0)
|
||||
if (strcmp( nodeName, "parent" ) == OK)
|
||||
// Was just searching for testCaseNode's parent, none found.
|
||||
return NULL;
|
||||
xmlChar *parentId = mpw_xmlTestCaseString( testCaseNode, "parent" );
|
||||
@ -66,7 +69,7 @@ xmlNodePtr mpw_xmlTestCaseNode(xmlNodePtr testCaseNode, const char *nodeName) {
|
||||
|
||||
for (xmlNodePtr otherTestCaseNode = testCaseNode->parent->children; otherTestCaseNode; otherTestCaseNode = otherTestCaseNode->next) {
|
||||
xmlChar *id = mpw_xmlTestCaseString( otherTestCaseNode, "id" );
|
||||
int foundParent = id && xmlStrcmp( id, parentId ) == 0;
|
||||
int foundParent = id && xmlStrcmp( id, parentId ) == OK;
|
||||
xmlFree( id );
|
||||
|
||||
if (foundParent) {
|
||||
@ -81,12 +84,18 @@ xmlNodePtr mpw_xmlTestCaseNode(xmlNodePtr testCaseNode, const char *nodeName) {
|
||||
|
||||
xmlChar *mpw_xmlTestCaseString(xmlNodePtr context, const char *nodeName) {
|
||||
|
||||
if (!nodeName)
|
||||
return NULL;
|
||||
|
||||
xmlNodePtr child = mpw_xmlTestCaseNode( context, nodeName );
|
||||
return child? xmlNodeGetContent( child ): NULL;
|
||||
}
|
||||
|
||||
uint32_t mpw_xmlTestCaseInteger(xmlNodePtr context, const char *nodeName) {
|
||||
|
||||
if (!nodeName)
|
||||
return 0;
|
||||
|
||||
xmlChar *string = mpw_xmlTestCaseString( context, nodeName );
|
||||
uint32_t integer = string? (uint32_t)atol( (char *)string ): 0;
|
||||
xmlFree( string );
|
||||
|
@ -58,26 +58,27 @@ time_t mpw_timegm(const char *time) {
|
||||
}
|
||||
|
||||
#if MPW_JSON
|
||||
json_object *mpw_get_json_section(
|
||||
json_object *obj, const char *section) {
|
||||
|
||||
json_object *json_value = obj;
|
||||
char *sectionTokenizer = mpw_strdup( section ), *sectionToken = sectionTokenizer;
|
||||
for (sectionToken = strtok( sectionToken, "." ); sectionToken; sectionToken = strtok( NULL, "." ))
|
||||
if (!json_object_object_get_ex( json_value, sectionToken, &json_value ) || !json_value) {
|
||||
trc( "While resolving: %s: Missing value for: %s", section, sectionToken );
|
||||
json_object *mpw_get_json_object(
|
||||
json_object *obj, const char *key, bool create) {
|
||||
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
json_object *json_value = NULL;
|
||||
if (!json_object_object_get_ex( obj, key, &json_value ) || !json_value)
|
||||
if (!create || json_object_object_add( obj, key, json_value = json_object_new_object() ) != OK) {
|
||||
trc( "Missing value for: %s", key );
|
||||
json_value = NULL;
|
||||
break;
|
||||
}
|
||||
free( sectionTokenizer );
|
||||
|
||||
return json_value;
|
||||
}
|
||||
|
||||
const char *mpw_get_json_string(
|
||||
json_object *obj, const char *section, const char *defaultValue) {
|
||||
json_object *obj, const char *key, const char *defaultValue) {
|
||||
|
||||
json_object *json_value = mpw_get_json_section( obj, section );
|
||||
json_object *json_value = mpw_get_json_object( obj, key, false );
|
||||
if (!json_value)
|
||||
return defaultValue;
|
||||
|
||||
@ -85,9 +86,9 @@ const char *mpw_get_json_string(
|
||||
}
|
||||
|
||||
int64_t mpw_get_json_int(
|
||||
json_object *obj, const char *section, int64_t defaultValue) {
|
||||
json_object *obj, const char *key, int64_t defaultValue) {
|
||||
|
||||
json_object *json_value = mpw_get_json_section( obj, section );
|
||||
json_object *json_value = mpw_get_json_object( obj, key, false );
|
||||
if (!json_value)
|
||||
return defaultValue;
|
||||
|
||||
@ -95,14 +96,15 @@ int64_t mpw_get_json_int(
|
||||
}
|
||||
|
||||
bool mpw_get_json_boolean(
|
||||
json_object *obj, const char *section, bool defaultValue) {
|
||||
json_object *obj, const char *key, bool defaultValue) {
|
||||
|
||||
json_object *json_value = mpw_get_json_section( obj, section );
|
||||
json_object *json_value = mpw_get_json_object( obj, key, false );
|
||||
if (!json_value)
|
||||
return defaultValue;
|
||||
|
||||
return json_object_get_boolean( json_value ) == true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool mpw_update_master_key(MPMasterKey *masterKey, MPAlgorithmVersion *masterKeyAlgorithm, MPAlgorithmVersion targetKeyAlgorithm,
|
||||
|
@ -43,26 +43,27 @@ time_t mpw_timegm(
|
||||
/// JSON parsing.
|
||||
|
||||
#if MPW_JSON
|
||||
/** Search for a JSON child object in a JSON object tree.
|
||||
* @param section A dot-delimited list of JSON object keys to walk toward the child object.
|
||||
* @return A JSON object (shared) or NULL if one of the section's object keys was not found in the source object's tree. */
|
||||
json_object *mpw_get_json_section(
|
||||
json_object *obj, const char *section);
|
||||
/** Search for an object in a JSON object tree.
|
||||
* @param key A JSON object key for the child in this object.
|
||||
* @param create If true, create and insert new objects for any missing path components.
|
||||
* @return An object (shared) or a new object (shared) installed in the tree if the path's object path was not found. */
|
||||
json_object *mpw_get_json_object(
|
||||
json_object *obj, const char *key, bool create);
|
||||
/** Search for a string in a JSON object tree.
|
||||
* @param section A dot-delimited list of JSON object keys to walk toward the child object.
|
||||
* @return A string (shared) or defaultValue if one of the section's object keys was not found in the source object's tree. */
|
||||
* @param key A dot-delimited list of JSON object keys to walk toward the child object.
|
||||
* @return A string (shared) or defaultValue if one of the path's object keys was not found in the source object's tree. */
|
||||
const char *mpw_get_json_string(
|
||||
json_object *obj, const char *section, const char *defaultValue);
|
||||
json_object *obj, const char *key, const char *defaultValue);
|
||||
/** Search for an integer in a JSON object tree.
|
||||
* @param section A dot-delimited list of JSON object keys to walk toward the child object.
|
||||
* @return The integer value or defaultValue if one of the section's object keys was not found in the source object's tree. */
|
||||
* @param key A dot-delimited list of JSON object keys to walk toward the child object.
|
||||
* @return The integer value or defaultValue if one of the path's object keys was not found in the source object's tree. */
|
||||
int64_t mpw_get_json_int(
|
||||
json_object *obj, const char *section, int64_t defaultValue);
|
||||
json_object *obj, const char *key, int64_t defaultValue);
|
||||
/** Search for a boolean in a JSON object tree.
|
||||
* @param section A dot-delimited list of JSON object keys to walk toward the child object.
|
||||
* @return The boolean value or defaultValue if one of the section's object keys was not found in the source object's tree. */
|
||||
* @param key A dot-delimited list of JSON object keys to walk toward the child object.
|
||||
* @return The boolean value or defaultValue if one of the path's object keys was not found in the source object's tree. */
|
||||
bool mpw_get_json_boolean(
|
||||
json_object *obj, const char *section, bool defaultValue);
|
||||
json_object *obj, const char *key, bool defaultValue);
|
||||
#endif
|
||||
|
||||
/// mpw.
|
||||
|
@ -25,6 +25,7 @@ MP_LIBS_BEGIN
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
MP_LIBS_END
|
||||
|
||||
MPMarshalledUser *mpw_marshal_user(
|
||||
@ -56,8 +57,12 @@ MPMarshalledSite *mpw_marshal_site(
|
||||
MPMarshalledUser *user, const char *siteName, const MPResultType resultType,
|
||||
const MPCounterValue siteCounter, const MPAlgorithmVersion algorithmVersion) {
|
||||
|
||||
if (!siteName || !mpw_realloc( &user->sites, NULL, sizeof( MPMarshalledSite ) * ++user->sites_count ))
|
||||
if (!siteName)
|
||||
return NULL;
|
||||
if (!mpw_realloc( &user->sites, NULL, sizeof( MPMarshalledSite ) * ++user->sites_count )) {
|
||||
user->sites_count--;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MPMarshalledSite *site = &user->sites[user->sites_count - 1];
|
||||
*site = (MPMarshalledSite){
|
||||
@ -84,8 +89,10 @@ MPMarshalledSite *mpw_marshal_site(
|
||||
MPMarshalledQuestion *mpw_marshal_question(
|
||||
MPMarshalledSite *site, const char *keyword) {
|
||||
|
||||
if (!mpw_realloc( &site->questions, NULL, sizeof( MPMarshalledQuestion ) * ++site->questions_count ))
|
||||
if (!mpw_realloc( &site->questions, NULL, sizeof( MPMarshalledQuestion ) * ++site->questions_count )) {
|
||||
site->questions_count--;
|
||||
return NULL;
|
||||
}
|
||||
if (!keyword)
|
||||
keyword = "";
|
||||
|
||||
@ -151,16 +158,20 @@ static bool mpw_marshal_user_free(
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool mpw_marshal_data_free(
|
||||
MPMarshalledData **data) {
|
||||
static bool mpw_marshal_data_null(
|
||||
MPMarshalledData *data) {
|
||||
|
||||
if (!data || !*data)
|
||||
if (!data)
|
||||
return true;
|
||||
|
||||
bool success = mpw_free_strings( &(*data)->key, &(*data)->str_value, NULL );
|
||||
for (unsigned int c = 0; c < (*data)->obj_children_count; ++c)
|
||||
success &= mpw_marshal_data_free( &(*data)->obj_children[c] );
|
||||
success &= mpw_free( data, sizeof( MPMarshalledData ) );
|
||||
bool success = mpw_free_strings( &data->key, &data->str_value, NULL );
|
||||
for (unsigned int c = 0; c < data->children_count; ++c)
|
||||
success &= mpw_marshal_data_null( &data->children[c] );
|
||||
success &= mpw_free( &data->children, sizeof( MPMarshalledData ) * data->children_count );
|
||||
data->children_count = 0;
|
||||
data->num_value = NAN;
|
||||
data->is_bool = false;
|
||||
data->is_null = true;
|
||||
|
||||
return success;
|
||||
}
|
||||
@ -175,7 +186,8 @@ bool mpw_marshal_free(
|
||||
|
||||
success &= mpw_marshal_info_free( &(*file)->info );
|
||||
success &= mpw_marshal_user_free( &(*file)->user );
|
||||
success &= mpw_marshal_data_free( &(*file)->data );
|
||||
success &= mpw_marshal_data_null( (*file)->data );
|
||||
success &= mpw_free( &(*file)->data, sizeof( MPMarshalledData ) );
|
||||
success &= mpw_free( file, sizeof( MPMarshalledFile ) );
|
||||
|
||||
return success;
|
||||
@ -272,6 +284,37 @@ static const char *mpw_marshal_write_flat(
|
||||
|
||||
#if MPW_JSON
|
||||
|
||||
static json_object *mpw_get_json_data(
|
||||
MPMarshalledData *data) {
|
||||
|
||||
if (!data || data->is_null)
|
||||
return NULL;
|
||||
if (data->is_bool)
|
||||
return json_object_new_boolean( data->num_value != false );
|
||||
if (!isnan( data->num_value ))
|
||||
return json_object_new_double_s( data->num_value, data->str_value );
|
||||
if (data->str_value)
|
||||
return json_object_new_string( data->str_value );
|
||||
|
||||
json_object *obj = NULL;
|
||||
for (size_t index = 0; index < data->children_count; ++index) {
|
||||
MPMarshalledData *child = &data->children[index];
|
||||
if (!obj) {
|
||||
if (child->key)
|
||||
obj = json_object_new_object();
|
||||
else
|
||||
obj = json_object_new_array();
|
||||
}
|
||||
|
||||
if (child->key)
|
||||
json_object_object_add( obj, child->key, mpw_get_json_data( child ) );
|
||||
else
|
||||
json_object_array_add( obj, mpw_get_json_data( child ) );
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static const char *mpw_marshal_write_json(
|
||||
const MPMarshalledFile *file, MPMarshalError *error) {
|
||||
|
||||
@ -290,9 +333,10 @@ static const char *mpw_marshal_write_json(
|
||||
masterKey = user->masterKeyProvider( user->algorithm, user->fullName );
|
||||
|
||||
// Section: "export"
|
||||
json_object *json_file = json_object_new_object();
|
||||
json_object *json_export = json_object_new_object();
|
||||
json_object_object_add( json_file, "export", json_export );
|
||||
json_object *json_file = mpw_get_json_data( file->data );
|
||||
if (!json_file)
|
||||
json_file = json_object_new_object();
|
||||
json_object *json_export = mpw_get_json_object( json_file, "export", true );
|
||||
json_object_object_add( json_export, "format", json_object_new_int( 1 ) );
|
||||
json_object_object_add( json_export, "redacted", json_object_new_boolean( user->redacted ) );
|
||||
|
||||
@ -302,8 +346,7 @@ static const char *mpw_marshal_write_json(
|
||||
json_object_object_add( json_export, "date", json_object_new_string( dateString ) );
|
||||
|
||||
// Section: "user"
|
||||
json_object *json_user = json_object_new_object();
|
||||
json_object_object_add( json_file, "user", json_user );
|
||||
json_object *json_user = mpw_get_json_object( json_file, "user", true );
|
||||
json_object_object_add( json_user, "avatar", json_object_new_int( (int32_t)user->avatar ) );
|
||||
json_object_object_add( json_user, "full_name", json_object_new_string( user->fullName ) );
|
||||
|
||||
@ -318,8 +361,7 @@ static const char *mpw_marshal_write_json(
|
||||
json_object_object_add( json_user, "default_type", json_object_new_int( (int32_t)user->defaultType ) );
|
||||
|
||||
// Section "sites"
|
||||
json_object *json_sites = json_object_new_object();
|
||||
json_object_object_add( json_file, "sites", json_sites );
|
||||
json_object *json_sites = mpw_get_json_object( json_file, "sites", true );
|
||||
for (size_t s = 0; s < user->sites_count; ++s) {
|
||||
MPMarshalledSite *site = &user->sites[s];
|
||||
if (!site->siteName || !strlen( site->siteName ))
|
||||
@ -348,8 +390,7 @@ static const char *mpw_marshal_write_json(
|
||||
loginState = mpw_strdup( site->loginState );
|
||||
}
|
||||
|
||||
json_object *json_site = json_object_new_object();
|
||||
json_object_object_add( json_sites, site->siteName, json_site );
|
||||
json_object *json_site = mpw_get_json_object( json_sites, site->siteName, true );
|
||||
json_object_object_add( json_site, "type", json_object_new_int( (int32_t)site->resultType ) );
|
||||
json_object_object_add( json_site, "counter", json_object_new_int( (int32_t)site->counter ) );
|
||||
json_object_object_add( json_site, "algorithm", json_object_new_int( (int32_t)site->algorithm ) );
|
||||
@ -364,15 +405,13 @@ static const char *mpw_marshal_write_json(
|
||||
json_object_object_add( json_site, "last_used", json_object_new_string( dateString ) );
|
||||
|
||||
if (site->questions_count) {
|
||||
json_object *json_site_questions = json_object_new_object();
|
||||
json_object_object_add( json_site, "questions", json_site_questions );
|
||||
json_object *json_site_questions = mpw_get_json_object( json_site, "questions", true );
|
||||
for (size_t q = 0; q < site->questions_count; ++q) {
|
||||
MPMarshalledQuestion *question = &site->questions[q];
|
||||
if (!question->keyword)
|
||||
continue;
|
||||
|
||||
json_object *json_site_question = json_object_new_object();
|
||||
json_object_object_add( json_site_questions, question->keyword, json_site_question );
|
||||
json_object *json_site_question = mpw_get_json_object( json_site_questions, question->keyword, true );
|
||||
json_object_object_add( json_site_question, "type", json_object_new_int( (int32_t)question->type ) );
|
||||
|
||||
if (!user->redacted) {
|
||||
@ -389,11 +428,11 @@ static const char *mpw_marshal_write_json(
|
||||
}
|
||||
}
|
||||
|
||||
json_object *json_site_mpw = json_object_new_object();
|
||||
json_object *json_site_mpw = mpw_get_json_object( json_site, "_ext_mpw", true );
|
||||
if (site->url)
|
||||
json_object_object_add( json_site_mpw, "url", json_object_new_string( site->url ) );
|
||||
if (json_object_object_length( json_site_mpw ))
|
||||
json_object_object_add( json_site, "_ext_mpw", json_site_mpw );
|
||||
if (!json_object_object_length( json_site_mpw ))
|
||||
json_object_object_del( json_site, "_ext_mpw" );
|
||||
|
||||
mpw_free_strings( &resultState, &loginState, NULL );
|
||||
}
|
||||
@ -414,22 +453,31 @@ static const char *mpw_marshal_write_json(
|
||||
#endif
|
||||
|
||||
const char *mpw_marshal_write(
|
||||
const MPMarshalFormat outFormat, const MPMarshalledFile *file, MPMarshalError *error) {
|
||||
const MPMarshalFormat outFormat, MPMarshalledFile *file, MPMarshalError *error) {
|
||||
|
||||
const char *out = NULL;
|
||||
switch (outFormat) {
|
||||
case MPMarshalFormatNone:
|
||||
*error = (MPMarshalError){ .type = MPMarshalSuccess };
|
||||
return NULL;
|
||||
break;
|
||||
case MPMarshalFormatFlat:
|
||||
return mpw_marshal_write_flat( file, error );
|
||||
out = mpw_marshal_write_flat( file, error );
|
||||
break;
|
||||
#if MPW_JSON
|
||||
case MPMarshalFormatJSON:
|
||||
return mpw_marshal_write_json( file, error );
|
||||
out = mpw_marshal_write_json( file, error );
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
*error = (MPMarshalError){ MPMarshalErrorFormat, mpw_str( "Unsupported output format: %u", outFormat ) };
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
if (file) {
|
||||
mpw_marshal_info_free( &file->info );
|
||||
file->info = mpw_marshal_read_info( out );
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static void mpw_marshal_read_flat_info(
|
||||
@ -462,19 +510,19 @@ static void mpw_marshal_read_flat_info(
|
||||
if (!headerName || !headerValue)
|
||||
continue;
|
||||
|
||||
if (strcmp( headerName, "Date" ) == 0)
|
||||
if (strcmp( headerName, "Date" ) == OK)
|
||||
info->exportDate = info->lastUsed = mpw_timegm( headerValue );
|
||||
if (strcmp( headerName, "Passwords" ) == 0)
|
||||
info->redacted = strcmp( headerValue, "VISIBLE" ) != 0;
|
||||
if (strcmp( headerName, "Algorithm" ) == 0)
|
||||
if (strcmp( headerName, "Passwords" ) == OK)
|
||||
info->redacted = strcmp( headerValue, "VISIBLE" ) != OK;
|
||||
if (strcmp( headerName, "Algorithm" ) == OK)
|
||||
info->algorithm = (MPAlgorithmVersion)atoi( headerValue );
|
||||
if (strcmp( headerName, "Avatar" ) == 0)
|
||||
if (strcmp( headerName, "Avatar" ) == OK)
|
||||
info->avatar = (unsigned int)atoi( headerValue );
|
||||
if (strcmp( headerName, "Full Name" ) == 0 || strcmp( headerName, "User Name" ) == 0)
|
||||
if (strcmp( headerName, "Full Name" ) == OK || strcmp( headerName, "User Name" ) == OK)
|
||||
info->fullName = mpw_strdup( headerValue );
|
||||
if (strcmp( headerName, "Identicon" ) == 0)
|
||||
if (strcmp( headerName, "Identicon" ) == OK)
|
||||
info->identicon = mpw_identicon_encoded( headerValue );
|
||||
if (strcmp( headerName, "Key ID" ) == 0)
|
||||
if (strcmp( headerName, "Key ID" ) == OK)
|
||||
info->keyID = mpw_strdup( headerValue );
|
||||
|
||||
mpw_free_strings( &headerName, &headerValue, NULL );
|
||||
@ -569,13 +617,13 @@ static MPMarshalledFile *mpw_marshal_read_flat(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strcmp( headerName, "Format" ) == 0)
|
||||
if (strcmp( headerName, "Format" ) == OK)
|
||||
format = (unsigned int)atoi( headerValue );
|
||||
if (strcmp( headerName, "Date" ) == 0)
|
||||
if (strcmp( headerName, "Date" ) == OK)
|
||||
exportDate = mpw_timegm( headerValue );
|
||||
if (strcmp( headerName, "Passwords" ) == 0)
|
||||
importRedacted = strcmp( headerValue, "VISIBLE" ) != 0;
|
||||
if (strcmp( headerName, "Algorithm" ) == 0) {
|
||||
if (strcmp( headerName, "Passwords" ) == OK)
|
||||
importRedacted = strcmp( headerValue, "VISIBLE" ) != OK;
|
||||
if (strcmp( headerName, "Algorithm" ) == OK) {
|
||||
int value = atoi( headerValue );
|
||||
if (value < MPAlgorithmVersionFirst || value > MPAlgorithmVersionLast) {
|
||||
*error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid user algorithm version: %s", headerValue ) };
|
||||
@ -587,15 +635,15 @@ static MPMarshalledFile *mpw_marshal_read_flat(
|
||||
}
|
||||
algorithm = (MPAlgorithmVersion)value;
|
||||
}
|
||||
if (strcmp( headerName, "Avatar" ) == 0)
|
||||
if (strcmp( headerName, "Avatar" ) == OK)
|
||||
avatar = (unsigned int)atoi( headerValue );
|
||||
if (strcmp( headerName, "Full Name" ) == 0 || strcmp( headerName, "User Name" ) == 0)
|
||||
if (strcmp( headerName, "Full Name" ) == OK || strcmp( headerName, "User Name" ) == OK)
|
||||
fullName = mpw_strdup( headerValue );
|
||||
if (strcmp( headerName, "Identicon" ) == 0)
|
||||
if (strcmp( headerName, "Identicon" ) == OK)
|
||||
identicon = mpw_identicon_encoded( headerValue );
|
||||
if (strcmp( headerName, "Key ID" ) == 0)
|
||||
if (strcmp( headerName, "Key ID" ) == OK)
|
||||
keyID = mpw_strdup( headerValue );
|
||||
if (strcmp( headerName, "Default Type" ) == 0) {
|
||||
if (strcmp( headerName, "Default Type" ) == OK) {
|
||||
int value = atoi( headerValue );
|
||||
if (!mpw_type_short_name( (MPResultType)value )) {
|
||||
*error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid user default type: %s", headerValue ) };
|
||||
@ -783,6 +831,110 @@ static MPMarshalledFile *mpw_marshal_read_flat(
|
||||
|
||||
#if MPW_JSON
|
||||
|
||||
static void mpw_set_json_data(
|
||||
MPMarshalledData *data, json_object *obj) {
|
||||
|
||||
json_type type = json_object_get_type( obj );
|
||||
data->is_null = type == json_type_null;
|
||||
data->is_bool = type == json_type_boolean;
|
||||
|
||||
if (type == json_type_boolean)
|
||||
data->num_value = json_object_get_boolean( obj );
|
||||
else if (type == json_type_double)
|
||||
data->num_value = json_object_get_double( obj );
|
||||
else if (type == json_type_int)
|
||||
data->num_value = json_object_get_int64( obj );
|
||||
else
|
||||
data->num_value = NAN;
|
||||
|
||||
const char *str = NULL;
|
||||
if (type == json_type_string || !isnan( data->num_value ))
|
||||
str = json_object_get_string( obj );
|
||||
if (!str || !data->str_value || strcmp( str, data->str_value ) != OK) {
|
||||
mpw_free_string( &data->str_value );
|
||||
data->str_value = mpw_strdup( str );
|
||||
}
|
||||
|
||||
// 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->key && type != json_type_object) || (!isnan( child->index ) && type != json_type_array)) {
|
||||
mpw_marshal_data_null( child );
|
||||
if (!newChildren) {
|
||||
newChildren = malloc( sizeof( MPMarshalledData ) * newChildrenCount );
|
||||
if (newChildren)
|
||||
memcpy( newChildren, data->children, sizeof( MPMarshalledData ) * newChildrenCount );
|
||||
}
|
||||
}
|
||||
else {
|
||||
++newChildrenCount;
|
||||
if (newChildren) {
|
||||
if (!mpw_realloc( &newChildren, NULL, sizeof( MPMarshalledData ) * newChildrenCount )) {
|
||||
--newChildrenCount;
|
||||
continue;
|
||||
}
|
||||
child->index = newChildrenCount - 1;
|
||||
newChildren[child->index] = *child;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (newChildren) {
|
||||
mpw_free( &data->children, sizeof( MPMarshalledData ) * data->children_count );
|
||||
data->children = newChildren;
|
||||
data->children_count = newChildrenCount;
|
||||
}
|
||||
|
||||
// Object
|
||||
if (type == json_type_object) {
|
||||
json_object_iter entry;
|
||||
json_object_object_foreachC( obj, entry ) {
|
||||
MPMarshalledData *child = NULL;
|
||||
|
||||
// Find existing child.
|
||||
for (size_t c = 0; c < data->children_count; ++c)
|
||||
if (data->children[c].key == entry.key ||
|
||||
(data->children[c].key && entry.key && strcmp( data->children[c].key, entry.key )) == OK) {
|
||||
child = &data->children[c];
|
||||
break;
|
||||
}
|
||||
|
||||
// Create new child.
|
||||
if (!child) {
|
||||
if (!mpw_realloc( &data->children, NULL, sizeof( MPMarshalledData ) * ++data->children_count )) {
|
||||
--data->children_count;
|
||||
continue;
|
||||
}
|
||||
*(child = &data->children[data->children_count - 1]) = (MPMarshalledData){ .key = mpw_strdup( entry.key ) };
|
||||
}
|
||||
|
||||
mpw_set_json_data( child, entry.val );
|
||||
}
|
||||
}
|
||||
|
||||
// Array
|
||||
if (type == json_type_array) {
|
||||
for (size_t index = 0; index < json_object_array_length( obj ); ++index) {
|
||||
MPMarshalledData *child = NULL;
|
||||
|
||||
if (index < data->children_count)
|
||||
child = &data->children[index];
|
||||
|
||||
else {
|
||||
if (!mpw_realloc( &data->children, NULL, sizeof( MPMarshalledData ) * ++data->children_count )) {
|
||||
--data->children_count;
|
||||
continue;
|
||||
}
|
||||
*(child = &data->children[data->children_count - 1]) = (MPMarshalledData){ .index = index };
|
||||
}
|
||||
|
||||
mpw_set_json_data( child, json_object_array_get_idx( obj, index ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mpw_marshal_read_json_info(
|
||||
const char *in, MPMarshalInfo *info) {
|
||||
|
||||
@ -793,19 +945,21 @@ static void mpw_marshal_read_json_info(
|
||||
return;
|
||||
|
||||
// Section: "export"
|
||||
int64_t fileFormat = mpw_get_json_int( json_file, "export.format", 0 );
|
||||
json_object *json_export = mpw_get_json_object( json_file, "export", false );
|
||||
int64_t fileFormat = mpw_get_json_int( json_export, "format", 0 );
|
||||
if (fileFormat < 1)
|
||||
return;
|
||||
info->exportDate = mpw_timegm( mpw_get_json_string( json_file, "export.date", NULL ) );
|
||||
info->redacted = mpw_get_json_boolean( json_file, "export.redacted", true );
|
||||
info->exportDate = mpw_timegm( mpw_get_json_string( json_export, "date", NULL ) );
|
||||
info->redacted = mpw_get_json_boolean( json_export, "redacted", true );
|
||||
|
||||
// Section: "user"
|
||||
info->algorithm = (MPAlgorithmVersion)mpw_get_json_int( json_file, "user.algorithm", MPAlgorithmVersionCurrent );
|
||||
info->avatar = (unsigned int)mpw_get_json_int( json_file, "user.avatar", 0 );
|
||||
info->fullName = mpw_strdup( mpw_get_json_string( json_file, "user.full_name", NULL ) );
|
||||
info->identicon = mpw_identicon_encoded( mpw_get_json_string( json_file, "user.identicon", NULL ) );
|
||||
info->keyID = mpw_strdup( mpw_get_json_string( json_file, "user.key_id", NULL ) );
|
||||
info->lastUsed = mpw_timegm( mpw_get_json_string( json_file, "user.last_used", NULL ) );
|
||||
json_object *json_user = mpw_get_json_object( json_file, "user", false );
|
||||
info->algorithm = (MPAlgorithmVersion)mpw_get_json_int( json_user, "algorithm", MPAlgorithmVersionCurrent );
|
||||
info->avatar = (unsigned int)mpw_get_json_int( json_user, "avatar", 0 );
|
||||
info->fullName = mpw_strdup( mpw_get_json_string( json_user, "full_name", NULL ) );
|
||||
info->identicon = mpw_identicon_encoded( mpw_get_json_string( json_user, "identicon", NULL ) );
|
||||
info->keyID = mpw_strdup( mpw_get_json_string( json_user, "key_id", NULL ) );
|
||||
info->lastUsed = mpw_timegm( mpw_get_json_string( json_user, "last_used", NULL ) );
|
||||
|
||||
json_object_put( json_file );
|
||||
}
|
||||
@ -830,38 +984,40 @@ static MPMarshalledFile *mpw_marshal_read_json(
|
||||
}
|
||||
|
||||
// Section: "export"
|
||||
int64_t fileFormat = mpw_get_json_int( json_file, "export.format", 0 );
|
||||
json_object *json_export = mpw_get_json_object( json_file, "export", false );
|
||||
int64_t fileFormat = mpw_get_json_int( json_export, "format", 0 );
|
||||
if (fileFormat < 1) {
|
||||
*error = (MPMarshalError){ MPMarshalErrorFormat, mpw_str( "Unsupported format: %u", fileFormat ) };
|
||||
json_object_put( json_file );
|
||||
return NULL;
|
||||
}
|
||||
bool fileRedacted = mpw_get_json_boolean( json_file, "export.redacted", true );
|
||||
bool fileRedacted = mpw_get_json_boolean( json_export, "redacted", true );
|
||||
|
||||
// Section: "user"
|
||||
int64_t value = mpw_get_json_int( json_file, "user.algorithm", MPAlgorithmVersionCurrent );
|
||||
json_object *json_user = mpw_get_json_object( json_file, "user", false );
|
||||
int64_t value = mpw_get_json_int( json_user, "algorithm", MPAlgorithmVersionCurrent );
|
||||
if (value < MPAlgorithmVersionFirst || value > MPAlgorithmVersionLast) {
|
||||
*error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid user algorithm version: %u", value ) };
|
||||
json_object_put( json_file );
|
||||
return NULL;
|
||||
}
|
||||
MPAlgorithmVersion algorithm = (MPAlgorithmVersion)value;
|
||||
unsigned int avatar = (unsigned int)mpw_get_json_int( json_file, "user.avatar", 0 );
|
||||
const char *fullName = mpw_get_json_string( json_file, "user.full_name", NULL );
|
||||
unsigned int avatar = (unsigned int)mpw_get_json_int( json_user, "avatar", 0 );
|
||||
const char *fullName = mpw_get_json_string( json_user, "full_name", NULL );
|
||||
if (!fullName || !strlen( fullName )) {
|
||||
*error = (MPMarshalError){ MPMarshalErrorMissing, "Missing value for full name." };
|
||||
json_object_put( json_file );
|
||||
return NULL;
|
||||
}
|
||||
MPIdenticon identicon = mpw_identicon_encoded( mpw_get_json_string( json_file, "user.identicon", NULL ) );
|
||||
const char *keyID = mpw_get_json_string( json_file, "user.key_id", NULL );
|
||||
MPResultType defaultType = (MPResultType)mpw_get_json_int( json_file, "user.default_type", MPResultTypeDefault );
|
||||
MPIdenticon identicon = mpw_identicon_encoded( mpw_get_json_string( json_user, "identicon", NULL ) );
|
||||
const char *keyID = mpw_get_json_string( json_user, "key_id", NULL );
|
||||
MPResultType defaultType = (MPResultType)mpw_get_json_int( json_user, "default_type", MPResultTypeDefault );
|
||||
if (!mpw_type_short_name( defaultType )) {
|
||||
*error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid user default type: %u", defaultType ) };
|
||||
json_object_put( json_file );
|
||||
return NULL;
|
||||
}
|
||||
const char *str_lastUsed = mpw_get_json_string( json_file, "user.last_used", NULL );
|
||||
const char *str_lastUsed = mpw_get_json_string( json_user, "last_used", NULL );
|
||||
time_t lastUsed = mpw_timegm( str_lastUsed );
|
||||
if (!lastUsed) {
|
||||
*error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid user last used: %s", str_lastUsed ) };
|
||||
@ -901,7 +1057,7 @@ static MPMarshalledFile *mpw_marshal_read_json(
|
||||
|
||||
// Section "sites"
|
||||
json_object_iter json_site;
|
||||
json_object *json_sites = mpw_get_json_section( json_file, "sites" );
|
||||
json_object *json_sites = mpw_get_json_object( json_file, "sites", false );
|
||||
json_object_object_foreachC( json_sites, json_site ) {
|
||||
const char *siteName = json_site.key;
|
||||
value = mpw_get_json_int( json_site.val, "algorithm", (int32_t)user->algorithm );
|
||||
@ -951,7 +1107,7 @@ static MPMarshalledFile *mpw_marshal_read_json(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
json_object *json_site_mpw = mpw_get_json_section( json_site.val, "_ext_mpw" );
|
||||
json_object *json_site_mpw = mpw_get_json_object( json_site.val, "_ext_mpw", false );
|
||||
const char *siteURL = mpw_get_json_string( json_site_mpw, "url", NULL );
|
||||
|
||||
MPMarshalledSite *site = mpw_marshal_site( user, siteName, siteType, siteCounter, siteAlgorithm );
|
||||
@ -993,7 +1149,7 @@ static MPMarshalledFile *mpw_marshal_read_json(
|
||||
site->loginState = mpw_strdup( siteLoginState );
|
||||
}
|
||||
|
||||
json_object *json_site_questions = mpw_get_json_section( json_site.val, "questions" );
|
||||
json_object *json_site_questions = mpw_get_json_object( json_site.val, "questions", false );
|
||||
if (json_site_questions) {
|
||||
json_object_iter json_site_question;
|
||||
json_object_object_foreachC( json_site_questions, json_site_question ) {
|
||||
@ -1016,9 +1172,15 @@ static MPMarshalledFile *mpw_marshal_read_json(
|
||||
}
|
||||
}
|
||||
mpw_free( &masterKey, MPMasterKeySize );
|
||||
|
||||
MPMarshalledData *data = malloc( sizeof( MPMarshalledData ) );
|
||||
if (data) {
|
||||
*data = (MPMarshalledData){};
|
||||
mpw_set_json_data( data, json_file );
|
||||
}
|
||||
json_object_put( json_file );
|
||||
|
||||
MPMarshalledFile *file = mpw_marshal_file( user, NULL );
|
||||
MPMarshalledFile *file = mpw_marshal_file( user, data );
|
||||
if (!file) {
|
||||
*error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't allocate a new marshal file." };
|
||||
mpw_marshal_user_free( &user );
|
||||
@ -1064,6 +1226,9 @@ MPMarshalledFile *mpw_marshal_read(
|
||||
const char *in, MPMasterKeyProvider masterKeyProvider, MPMarshalError *error) {
|
||||
|
||||
MPMarshalInfo *info = mpw_marshal_read_info( in );
|
||||
if (!info)
|
||||
return NULL;
|
||||
|
||||
MPMarshalledFile *file = NULL;
|
||||
switch (info->format) {
|
||||
case MPMarshalFormatNone:
|
||||
@ -1081,8 +1246,10 @@ MPMarshalledFile *mpw_marshal_read(
|
||||
*error = (MPMarshalError){ MPMarshalErrorFormat, mpw_str( "Unsupported input format: %u", info->format ) };
|
||||
break;
|
||||
}
|
||||
if (file)
|
||||
if (file) {
|
||||
mpw_marshal_info_free( &(file->info) );
|
||||
file->info = info;
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
@ -1093,11 +1260,11 @@ const MPMarshalFormat mpw_format_named(
|
||||
if (!formatName || !strlen( formatName ))
|
||||
return MPMarshalFormatNone;
|
||||
|
||||
if (mpw_strncasecmp( mpw_format_name( MPMarshalFormatNone ), formatName, strlen( formatName ) ) == 0)
|
||||
if (mpw_strncasecmp( mpw_format_name( MPMarshalFormatNone ), formatName, strlen( formatName ) ) == OK)
|
||||
return MPMarshalFormatNone;
|
||||
if (mpw_strncasecmp( mpw_format_name( MPMarshalFormatFlat ), formatName, strlen( formatName ) ) == 0)
|
||||
if (mpw_strncasecmp( mpw_format_name( MPMarshalFormatFlat ), formatName, strlen( formatName ) ) == OK)
|
||||
return MPMarshalFormatFlat;
|
||||
if (mpw_strncasecmp( mpw_format_name( MPMarshalFormatJSON ), formatName, strlen( formatName ) ) == 0)
|
||||
if (mpw_strncasecmp( mpw_format_name( MPMarshalFormatJSON ), formatName, strlen( formatName ) ) == OK)
|
||||
return MPMarshalFormatJSON;
|
||||
|
||||
dbg( "Not a format name: %s", formatName );
|
||||
|
@ -126,18 +126,20 @@ typedef struct MPMarshalledData {
|
||||
// If data is held in a parent object.
|
||||
const char *key;
|
||||
// If data is held in a parent array.
|
||||
unsigned int index;
|
||||
size_t index;
|
||||
|
||||
// If data is a null.
|
||||
bool is_null;
|
||||
// If data is a boolean.
|
||||
bool is_bool;
|
||||
// If data is a string.
|
||||
const char *str_value;
|
||||
// If data is a boolean.
|
||||
bool bool_value;
|
||||
// If data is a number.
|
||||
double num_value;
|
||||
|
||||
// If data is an object or array.
|
||||
struct MPMarshalledData **obj_children;
|
||||
size_t obj_children_count;
|
||||
size_t children_count;
|
||||
struct MPMarshalledData *children;
|
||||
} MPMarshalledData;
|
||||
|
||||
typedef struct MPMarshalledFile {
|
||||
@ -151,7 +153,7 @@ typedef struct MPMarshalledFile {
|
||||
/** Write the user and all associated data out using the given marshalling format.
|
||||
* @return A string (allocated), or NULL if the format is unrecognized, does not support marshalling or a format error occurred. */
|
||||
const char *mpw_marshal_write(
|
||||
const MPMarshalFormat outFormat, const MPMarshalledFile *file, MPMarshalError *error);
|
||||
const MPMarshalFormat outFormat, MPMarshalledFile *file, MPMarshalError *error);
|
||||
/** Best effort parse of metadata on the sites in the input buffer. Fields that could not be parsed remain at their type's initial value.
|
||||
* @return A metadata object (allocated); NULL if the object could not be allocated or the format was not understood. */
|
||||
MPMarshalInfo *mpw_marshal_read_info(
|
||||
|
@ -63,27 +63,27 @@ const MPResultType mpw_type_named(const char *typeName) {
|
||||
}
|
||||
|
||||
// Find what password type is represented by the type name.
|
||||
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplateMaximum ), typeName, strlen( typeName ) ) == 0)
|
||||
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplateMaximum ), typeName, strlen( typeName ) ) == OK)
|
||||
return MPResultTypeTemplateMaximum;
|
||||
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplateLong ), typeName, strlen( typeName ) ) == 0)
|
||||
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplateLong ), typeName, strlen( typeName ) ) == OK)
|
||||
return MPResultTypeTemplateLong;
|
||||
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplateMedium ), typeName, strlen( typeName ) ) == 0)
|
||||
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplateMedium ), typeName, strlen( typeName ) ) == OK)
|
||||
return MPResultTypeTemplateMedium;
|
||||
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplateBasic ), typeName, strlen( typeName ) ) == 0)
|
||||
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplateBasic ), typeName, strlen( typeName ) ) == OK)
|
||||
return MPResultTypeTemplateBasic;
|
||||
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplateShort ), typeName, strlen( typeName ) ) == 0)
|
||||
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplateShort ), typeName, strlen( typeName ) ) == OK)
|
||||
return MPResultTypeTemplateShort;
|
||||
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplatePIN ), typeName, strlen( typeName ) ) == 0)
|
||||
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplatePIN ), typeName, strlen( typeName ) ) == OK)
|
||||
return MPResultTypeTemplatePIN;
|
||||
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplateName ), typeName, strlen( typeName ) ) == 0)
|
||||
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplateName ), typeName, strlen( typeName ) ) == OK)
|
||||
return MPResultTypeTemplateName;
|
||||
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplatePhrase ), typeName, strlen( typeName ) ) == 0)
|
||||
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeTemplatePhrase ), typeName, strlen( typeName ) ) == OK)
|
||||
return MPResultTypeTemplatePhrase;
|
||||
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeStatefulPersonal ), typeName, strlen( typeName ) ) == 0)
|
||||
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeStatefulPersonal ), typeName, strlen( typeName ) ) == OK)
|
||||
return MPResultTypeStatefulPersonal;
|
||||
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeStatefulDevice ), typeName, strlen( typeName ) ) == 0)
|
||||
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeStatefulDevice ), typeName, strlen( typeName ) ) == OK)
|
||||
return MPResultTypeStatefulDevice;
|
||||
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeDeriveKey ), typeName, strlen( typeName ) ) == 0)
|
||||
if (mpw_strncasecmp( mpw_type_short_name( MPResultTypeDeriveKey ), typeName, strlen( typeName ) ) == OK)
|
||||
return MPResultTypeDeriveKey;
|
||||
|
||||
dbg( "Not a generated type name: %s", typeName );
|
||||
@ -243,11 +243,11 @@ const char *mpw_type_template(MPResultType type, uint8_t templateIndex) {
|
||||
|
||||
const MPKeyPurpose mpw_purpose_named(const char *purposeName) {
|
||||
|
||||
if (mpw_strncasecmp( mpw_purpose_name( MPKeyPurposeAuthentication ), purposeName, strlen( purposeName ) ) == 0)
|
||||
if (mpw_strncasecmp( mpw_purpose_name( MPKeyPurposeAuthentication ), purposeName, strlen( purposeName ) ) == OK)
|
||||
return MPKeyPurposeAuthentication;
|
||||
if (mpw_strncasecmp( mpw_purpose_name( MPKeyPurposeIdentification ), purposeName, strlen( purposeName ) ) == 0)
|
||||
if (mpw_strncasecmp( mpw_purpose_name( MPKeyPurposeIdentification ), purposeName, strlen( purposeName ) ) == OK)
|
||||
return MPKeyPurposeIdentification;
|
||||
if (mpw_strncasecmp( mpw_purpose_name( MPKeyPurposeRecovery ), purposeName, strlen( purposeName ) ) == 0)
|
||||
if (mpw_strncasecmp( mpw_purpose_name( MPKeyPurposeRecovery ), purposeName, strlen( purposeName ) ) == OK)
|
||||
return MPKeyPurposeRecovery;
|
||||
|
||||
dbg( "Not a purpose name: %s", purposeName );
|
||||
|
Loading…
Reference in New Issue
Block a user