diff --git a/src/core/settings.c b/src/core/settings.c index e660ae7c..a1299ee2 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -28,6 +28,7 @@ #include #include #include +#include #include /** @file @@ -745,6 +746,58 @@ struct setting_type setting_type_string __setting_type = { .fetchf = fetchf_string, }; +/** + * Parse and store value of URI-encoded string setting + * + * @v settings Settings block + * @v setting Setting to store + * @v value Formatted setting data + * @ret rc Return status code + */ +static int storef_uristring ( struct settings *settings, + struct setting *setting, + const char *value ) { + char buf[ strlen ( value ) + 1 ]; /* Decoding never expands string */ + size_t len; + + len = uri_decode ( value, buf, sizeof ( buf ) ); + return store_setting ( settings, setting, buf, len ); +} + +/** + * Fetch and format value of URI-encoded string setting + * + * @v settings Settings block, or NULL to search all blocks + * @v setting Setting to fetch + * @v buf Buffer to contain formatted value + * @v len Length of buffer + * @ret len Length of formatted value, or negative error + */ +static int fetchf_uristring ( struct settings *settings, + struct setting *setting, + char *buf, size_t len ) { + size_t raw_len; + + /* We need to always retrieve the full raw string to know the + * length of the encoded string. + */ + raw_len = fetch_setting ( settings, setting, NULL, 0 ); + { + char raw_buf[ raw_len + 1 ]; + + fetch_string_setting ( settings, setting, raw_buf, + sizeof ( raw_buf ) ); + return uri_encode ( raw_buf, buf, len ); + } +} + +/** A URI-encoded string setting type */ +struct setting_type setting_type_uristring __setting_type = { + .name = "uristring", + .storef = storef_uristring, + .fetchf = fetchf_uristring, +}; + /** * Parse and store value of IPv4 address setting *