Replace Crashlytics/Fabric with Countly & Sentry.
This commit is contained in:
		@@ -185,7 +185,6 @@ void cli_mpw(Arguments *args, Operation *operation);
 | 
			
		||||
void cli_save(Arguments *args, Operation *operation);
 | 
			
		||||
 | 
			
		||||
MPMasterKeyProvider cli_masterKeyProvider_op(Operation *operation);
 | 
			
		||||
MPMasterKeyProvider cli_masterKeyProvider_str(const char *masterPassword);
 | 
			
		||||
void cli_masterKeyProvider_free(void);
 | 
			
		||||
 | 
			
		||||
/** ========================================================================
 | 
			
		||||
@@ -825,7 +824,7 @@ void cli_save(Arguments *args, Operation *operation) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const char *buf = mpw_marshal_write( operation->sitesFormat, operation->file, operation->user );
 | 
			
		||||
    const char *buf = mpw_marshal_write( operation->sitesFormat, &operation->file, operation->user );
 | 
			
		||||
    if (!buf || operation->file->error.type != MPMarshalSuccess)
 | 
			
		||||
        wrn( "Couldn't encode updated configuration file:\n  %s: %s", operation->sitesPath, operation->file->error.message );
 | 
			
		||||
 | 
			
		||||
@@ -836,47 +835,25 @@ void cli_save(Arguments *args, Operation *operation) {
 | 
			
		||||
    fclose( sitesFile );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MPMasterKey __cli_masterKeyProvider_currentKey = NULL;
 | 
			
		||||
static MPAlgorithmVersion __cli_masterKeyProvider_currentAlgorithm = (MPAlgorithmVersion)-1;
 | 
			
		||||
static const char *__cli_masterKeyProvider_currentPassword = NULL;
 | 
			
		||||
static Operation *__cli_masterKeyProvider_currentOperation = NULL;
 | 
			
		||||
 | 
			
		||||
static MPMasterKey __cli_masterKeyProvider_op(MPAlgorithmVersion algorithm, const char *fullName) {
 | 
			
		||||
static bool __cli_masterKeyProvider_op(MPMasterKey *currentKey, MPAlgorithmVersion *currentAlgorithm,
 | 
			
		||||
        MPAlgorithmVersion algorithm, const char *fullName) {
 | 
			
		||||
 | 
			
		||||
    if (mpw_update_master_key( &__cli_masterKeyProvider_currentKey, &__cli_masterKeyProvider_currentAlgorithm,
 | 
			
		||||
            algorithm, fullName, __cli_masterKeyProvider_currentOperation->masterPassword ))
 | 
			
		||||
        return mpw_memdup( __cli_masterKeyProvider_currentKey, MPMasterKeySize );
 | 
			
		||||
    if (!currentKey)
 | 
			
		||||
        __cli_masterKeyProvider_currentOperation = NULL;
 | 
			
		||||
    if (!__cli_masterKeyProvider_currentOperation)
 | 
			
		||||
        return false;
 | 
			
		||||
    if (!mpw_update_master_key( currentKey, currentAlgorithm, algorithm, fullName,
 | 
			
		||||
            __cli_masterKeyProvider_currentOperation->masterPassword ))
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MPMasterKey __cli_masterKeyProvider_str(MPAlgorithmVersion algorithm, const char *fullName) {
 | 
			
		||||
 | 
			
		||||
    if (mpw_update_master_key( &__cli_masterKeyProvider_currentKey, &__cli_masterKeyProvider_currentAlgorithm,
 | 
			
		||||
            algorithm, fullName, __cli_masterKeyProvider_currentPassword ))
 | 
			
		||||
        return mpw_memdup( __cli_masterKeyProvider_currentKey, MPMasterKeySize );
 | 
			
		||||
 | 
			
		||||
    return NULL;
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MPMasterKeyProvider cli_masterKeyProvider_op(Operation *operation) {
 | 
			
		||||
 | 
			
		||||
    mpw_free_string( &__cli_masterKeyProvider_currentPassword );
 | 
			
		||||
    mpw_masterKeyProvider_free();
 | 
			
		||||
    __cli_masterKeyProvider_currentOperation = operation;
 | 
			
		||||
    return __cli_masterKeyProvider_op;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MPMasterKeyProvider cli_masterKeyProvider_str(const char *masterPassword) {
 | 
			
		||||
 | 
			
		||||
    mpw_free_string( &__cli_masterKeyProvider_currentPassword );
 | 
			
		||||
    __cli_masterKeyProvider_currentPassword = mpw_strdup( masterPassword );
 | 
			
		||||
    return __cli_masterKeyProvider_str;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cli_masterKeyProvider_free() {
 | 
			
		||||
 | 
			
		||||
    mpw_free( &__cli_masterKeyProvider_currentKey, MPMasterKeySize );
 | 
			
		||||
    __cli_masterKeyProvider_currentAlgorithm = (MPAlgorithmVersion)-1;
 | 
			
		||||
    mpw_free_string( &__cli_masterKeyProvider_currentPassword );
 | 
			
		||||
    __cli_masterKeyProvider_currentOperation = NULL;
 | 
			
		||||
    return mpw_masterKeyProvider_proxy( __cli_masterKeyProvider_op );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -28,6 +28,55 @@ MP_LIBS_BEGIN
 | 
			
		||||
#include <math.h>
 | 
			
		||||
MP_LIBS_END
 | 
			
		||||
 | 
			
		||||
static MPMasterKey __mpw_masterKeyProvider_currentKey = NULL;
 | 
			
		||||
static MPAlgorithmVersion __mpw_masterKeyProvider_currentAlgorithm = (MPAlgorithmVersion)-1;
 | 
			
		||||
static MPMasterKeyProviderProxy __mpw_masterKeyProvider_currentProxy = NULL;
 | 
			
		||||
static const char *__mpw_masterKeyProvider_currentPassword = NULL;
 | 
			
		||||
 | 
			
		||||
static bool __mpw_masterKeyProvider_str(MPMasterKey *currentKey, MPAlgorithmVersion *currentAlgorithm,
 | 
			
		||||
        MPAlgorithmVersion algorithm, const char *fullName) {
 | 
			
		||||
 | 
			
		||||
    if (!currentKey)
 | 
			
		||||
        return mpw_free_string( &__mpw_masterKeyProvider_currentPassword );
 | 
			
		||||
 | 
			
		||||
    return mpw_update_master_key( currentKey, currentAlgorithm, algorithm, fullName, __mpw_masterKeyProvider_currentPassword );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MPMasterKey __mpw_masterKeyProvider_proxy(MPAlgorithmVersion algorithm, const char *fullName) {
 | 
			
		||||
 | 
			
		||||
    if (!__mpw_masterKeyProvider_currentProxy)
 | 
			
		||||
        return NULL;
 | 
			
		||||
    if (!__mpw_masterKeyProvider_currentProxy(
 | 
			
		||||
            &__mpw_masterKeyProvider_currentKey, &__mpw_masterKeyProvider_currentAlgorithm, algorithm, fullName ))
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    return mpw_memdup( __mpw_masterKeyProvider_currentKey, MPMasterKeySize );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MPMasterKeyProvider mpw_masterKeyProvider_str(const char *masterPassword) {
 | 
			
		||||
 | 
			
		||||
    mpw_masterKeyProvider_free();
 | 
			
		||||
    __mpw_masterKeyProvider_currentPassword = mpw_strdup( masterPassword );
 | 
			
		||||
    return mpw_masterKeyProvider_proxy( __mpw_masterKeyProvider_str );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MPMasterKeyProvider mpw_masterKeyProvider_proxy(const MPMasterKeyProviderProxy proxy) {
 | 
			
		||||
 | 
			
		||||
    mpw_masterKeyProvider_free();
 | 
			
		||||
    __mpw_masterKeyProvider_currentProxy = proxy;
 | 
			
		||||
    return __mpw_masterKeyProvider_proxy;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mpw_masterKeyProvider_free() {
 | 
			
		||||
 | 
			
		||||
    mpw_free( &__mpw_masterKeyProvider_currentKey, MPMasterKeySize );
 | 
			
		||||
    __mpw_masterKeyProvider_currentAlgorithm = (MPAlgorithmVersion)-1;
 | 
			
		||||
    if (__mpw_masterKeyProvider_currentProxy) {
 | 
			
		||||
        __mpw_masterKeyProvider_currentProxy( NULL, NULL, MPAlgorithmVersionCurrent, NULL );
 | 
			
		||||
        __mpw_masterKeyProvider_currentProxy = NULL;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MPMarshalledUser *mpw_marshal_user(
 | 
			
		||||
        const char *fullName, MPMasterKeyProvider masterKeyProvider, const MPAlgorithmVersion algorithmVersion) {
 | 
			
		||||
 | 
			
		||||
@@ -612,6 +661,7 @@ static const char *mpw_marshal_write_json(
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
@@ -624,6 +674,7 @@ static bool mpw_marshal_data_keep_site_exists(
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
@@ -635,16 +686,15 @@ static bool mpw_marshal_data_keep_question_exists(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *mpw_marshal_write(
 | 
			
		||||
        const MPMarshalFormat outFormat, MPMarshalledFile *file, MPMarshalledUser *user) {
 | 
			
		||||
        const MPMarshalFormat outFormat, MPMarshalledFile **file_, MPMarshalledUser *user) {
 | 
			
		||||
 | 
			
		||||
    MPMarshalledFile *file = file_? *file_: NULL;
 | 
			
		||||
    file = mpw_marshal_file( file, NULL, file && file->data? file->data: mpw_marshal_data_new() );
 | 
			
		||||
    if (file_)
 | 
			
		||||
        *file_ = file;
 | 
			
		||||
    if (!file)
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    MPMarshalledData *data = file->data? file->data: mpw_marshal_data_new();
 | 
			
		||||
    mpw_marshal_file( file, NULL, data );
 | 
			
		||||
 | 
			
		||||
    file->error = (MPMarshalError){ MPMarshalSuccess, NULL };
 | 
			
		||||
    if (!data) {
 | 
			
		||||
    if (!file->data) {
 | 
			
		||||
        file->error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't allocate data." };
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
@@ -652,12 +702,14 @@ const char *mpw_marshal_write(
 | 
			
		||||
        file->error = (MPMarshalError){ MPMarshalErrorMissing, "Missing full name." };
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
    file->error = (MPMarshalError){ MPMarshalSuccess, NULL };
 | 
			
		||||
 | 
			
		||||
    MPMasterKey masterKey = NULL;
 | 
			
		||||
    if (user->masterKeyProvider)
 | 
			
		||||
        masterKey = user->masterKeyProvider( user->algorithm, user->fullName );
 | 
			
		||||
 | 
			
		||||
    // Section: "export"
 | 
			
		||||
    MPMarshalledData *data_export = mpw_marshal_data_get( data, "export", NULL );
 | 
			
		||||
    MPMarshalledData *data_export = mpw_marshal_data_get( file->data, "export", NULL );
 | 
			
		||||
    char dateString[21];
 | 
			
		||||
    time_t now = time( NULL );
 | 
			
		||||
    if (strftime( dateString, sizeof( dateString ), "%FT%TZ", gmtime( &now ) ))
 | 
			
		||||
@@ -665,7 +717,7 @@ const char *mpw_marshal_write(
 | 
			
		||||
    mpw_marshal_data_set_bool( user->redacted, data_export, "redacted", NULL );
 | 
			
		||||
 | 
			
		||||
    // Section: "user"
 | 
			
		||||
    MPMarshalledData *data_user = mpw_marshal_data_get( data, "user", NULL );
 | 
			
		||||
    MPMarshalledData *data_user = mpw_marshal_data_get( file->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 );
 | 
			
		||||
@@ -676,7 +728,7 @@ const char *mpw_marshal_write(
 | 
			
		||||
        mpw_marshal_data_set_str( dateString, data_user, "last_used", NULL );
 | 
			
		||||
 | 
			
		||||
    // Section "sites"
 | 
			
		||||
    MPMarshalledData *data_sites = mpw_marshal_data_get( data, "sites", NULL );
 | 
			
		||||
    MPMarshalledData *data_sites = mpw_marshal_data_get( file->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];
 | 
			
		||||
@@ -715,7 +767,7 @@ const char *mpw_marshal_write(
 | 
			
		||||
        if (strftime( dateString, sizeof( dateString ), "%FT%TZ", gmtime( &site->lastUsed ) ))
 | 
			
		||||
            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 );
 | 
			
		||||
        MPMarshalledData *data_questions = mpw_marshal_data_get( file->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];
 | 
			
		||||
@@ -761,7 +813,11 @@ const char *mpw_marshal_write(
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
    if (out && file->error.type == MPMarshalSuccess)
 | 
			
		||||
        mpw_marshal_read( file, out );
 | 
			
		||||
        file = mpw_marshal_read( file, out );
 | 
			
		||||
    if (file_)
 | 
			
		||||
        *file_ = file;
 | 
			
		||||
    else
 | 
			
		||||
        mpw_marshal_file_free( &file );
 | 
			
		||||
 | 
			
		||||
    return out;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -28,8 +28,8 @@ MP_LIBS_END
 | 
			
		||||
 | 
			
		||||
//// Types.
 | 
			
		||||
 | 
			
		||||
#define mpw_default( __default, __value ) ({ __typeof__ (__default) _v = (__typeof__ (__default))(__value); _v = _v? _v: __default; })
 | 
			
		||||
#define mpw_default_n( __default, __num ) ({ __typeof__ (__num) _n = (__num); !isnan( _n )? (__typeof__ (__default))_n: __default; })
 | 
			
		||||
#define mpw_default(__default, __value) ({ __typeof__ (__default) _v = (__typeof__ (__default))(__value); _v = _v? _v: __default; })
 | 
			
		||||
#define mpw_default_n(__default, __num) ({ __typeof__ (__num) _n = (__num); !isnan( _n )? (__typeof__ (__default))_n: __default; })
 | 
			
		||||
 | 
			
		||||
typedef mpw_enum( unsigned int, MPMarshalFormat ) {
 | 
			
		||||
    /** Do not marshal. */
 | 
			
		||||
@@ -66,6 +66,15 @@ typedef mpw_enum( unsigned int, MPMarshalErrorType ) {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef MPMasterKey (*MPMasterKeyProvider)(MPAlgorithmVersion algorithm, const char *fullName);
 | 
			
		||||
typedef bool (*MPMasterKeyProviderProxy)(MPMasterKey *, MPAlgorithmVersion *, MPAlgorithmVersion algorithm, const char *fullName);
 | 
			
		||||
 | 
			
		||||
/** Create a key provider which handles key generation by proxying the given function.
 | 
			
		||||
 * The proxy function receives the currently cached key and its algorithm.  If those are NULL, the proxy function should clean up its state. */
 | 
			
		||||
MPMasterKeyProvider mpw_masterKeyProvider_proxy(const MPMasterKeyProviderProxy proxy);
 | 
			
		||||
/** Create a key provider that computes a master key for the given master password. */
 | 
			
		||||
MPMasterKeyProvider mpw_masterKeyProvider_str(const char *masterPassword);
 | 
			
		||||
/** Free the cached keys and proxy state. */
 | 
			
		||||
void mpw_masterKeyProvider_free(void);
 | 
			
		||||
 | 
			
		||||
typedef struct MPMarshalError {
 | 
			
		||||
    MPMarshalErrorType type;
 | 
			
		||||
@@ -148,9 +157,11 @@ typedef struct MPMarshalledFile {
 | 
			
		||||
//// Marshalling.
 | 
			
		||||
 | 
			
		||||
/** Write the user and all associated data out using the given marshalling format.
 | 
			
		||||
 * @param file A pointer to the original file object to update with the user's data or to NULL to make a new.
 | 
			
		||||
 *             File object will be updated with state or new (allocated).  May be NULL if not interested in a file object.
 | 
			
		||||
 * @return A string (allocated), or NULL if the file is missing, format is unrecognized, does not support marshalling or a format error occurred. */
 | 
			
		||||
const char *mpw_marshal_write(
 | 
			
		||||
        const MPMarshalFormat outFormat, MPMarshalledFile *file, MPMarshalledUser *user);
 | 
			
		||||
        const MPMarshalFormat outFormat, MPMarshalledFile **file, MPMarshalledUser *user);
 | 
			
		||||
/** Parse the user configuration in the input buffer.  Fields that could not be parsed remain at their type's initial value.
 | 
			
		||||
 * @return The updated file object or a new one (allocated) if none was provided; NULL if a file object could not be allocated. */
 | 
			
		||||
MPMarshalledFile *mpw_marshal_read(
 | 
			
		||||
 
 | 
			
		||||
@@ -579,20 +579,23 @@ const char *mpw_hex_l(const uint32_t number) {
 | 
			
		||||
    return mpw_hex( &buf, sizeof( buf ) );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const uint8_t *mpw_unhex(const char *hex) {
 | 
			
		||||
const uint8_t *mpw_unhex(const char *hex, size_t *length) {
 | 
			
		||||
 | 
			
		||||
    if (!hex)
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    size_t length = strlen( hex );
 | 
			
		||||
    if (length == 0 || length % 2 != 0)
 | 
			
		||||
    size_t hexLength = strlen( hex );
 | 
			
		||||
    if (hexLength == 0 || hexLength % 2 != 0)
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    size_t bytes = length / 2;
 | 
			
		||||
    uint8_t *buf = malloc( bytes );
 | 
			
		||||
    for (size_t b = 0; b < bytes; ++b)
 | 
			
		||||
    size_t bufLength = hexLength / 2;
 | 
			
		||||
    if (length)
 | 
			
		||||
        *length = bufLength;
 | 
			
		||||
 | 
			
		||||
    uint8_t *buf = malloc( bufLength );
 | 
			
		||||
    for (size_t b = 0; b < bufLength; ++b)
 | 
			
		||||
        if (sscanf( hex + b * 2, "%02hhX", &buf[b] ) != 1) {
 | 
			
		||||
            mpw_free( &buf, bytes );
 | 
			
		||||
            mpw_free( &buf, bufLength );
 | 
			
		||||
            return NULL;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -230,13 +230,13 @@ const char *mpw_hotp(
 | 
			
		||||
 * @return A string (shared); or NULL if the format is missing or the result could not be allocated or formatted. */
 | 
			
		||||
const char *mpw_str(const char *format, ...);
 | 
			
		||||
const char *mpw_vstr(const char *format, va_list args);
 | 
			
		||||
/** Encode a buffer as a string of hexadecimal characters.
 | 
			
		||||
/** Encode length-bytes from a buffer as a string of hexadecimal characters.
 | 
			
		||||
 * @return A string (shared); or NULL if the buffer is missing or the result could not be allocated. */
 | 
			
		||||
const char *mpw_hex(const void *buf, const size_t length);
 | 
			
		||||
const char *mpw_hex_l(const uint32_t number);
 | 
			
		||||
/** Decode a string of hexadecimal characters into a buffer.
 | 
			
		||||
 * @return A buffer (allocated, strlen(hex) / 2); or NULL if hex is NULL, empty, or not an even-length hexadecimal string. */
 | 
			
		||||
const uint8_t *mpw_unhex(const char *hex);
 | 
			
		||||
/** Decode a string of hexadecimal characters into a buffer of length-bytes.
 | 
			
		||||
 * @return A buffer (allocated, *length); or NULL if hex is NULL, empty, or not an even-length hexadecimal string. */
 | 
			
		||||
const uint8_t *mpw_unhex(const char *hex, size_t *length);
 | 
			
		||||
/** Encode a fingerprint for a buffer.
 | 
			
		||||
 * @return A string (shared); or NULL if the buffer is missing or the result could not be allocated. */
 | 
			
		||||
const MPKeyID mpw_id_buf(const void *buf, const size_t length);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user