static bool s_parse_profile_declaration()

in source/aws_profile.c [849:964]


static bool s_parse_profile_declaration(
    const struct aws_byte_cursor *line_cursor,
    struct profile_file_parse_context *context) {

    /*
     * Strip comment and right-side whitespace
     */
    struct aws_byte_cursor profile_line_cursor = s_trim_trailing_comment(line_cursor);
    struct aws_byte_cursor profile_cursor = aws_byte_cursor_right_trim_pred(&profile_line_cursor, s_is_whitespace);

    /*
     * "[" + <whitespace>? + <"profile ">? + <profile name = identifier> + <whitespace>? + "]"
     */
    if (!s_parse_by_character_predicate(&profile_cursor, s_is_profile_start, NULL, 1)) {
        /*
         * This isn't a profile declaration, try something else
         */
        return false;
    }

    context->has_seen_profile = true;
    context->current_profile = NULL;
    context->current_property = NULL;

    s_parse_by_character_predicate(&profile_cursor, s_is_whitespace, NULL, 0);

    /*
     * Check if the profile name starts with the 'profile' keyword.  We need to check for
     * "profile" and at least one whitespace character.  A partial match
     * ("[profilefoo]" for example) should rewind and use the whole name properly.
     */
    struct aws_byte_cursor backtrack_cursor = profile_cursor;
    bool has_profile_prefix = s_parse_by_token(&profile_cursor, s_profile_token, NULL) &&
                              s_parse_by_character_predicate(&profile_cursor, s_is_whitespace, NULL, 1);

    if (has_profile_prefix) {
        if (context->profile_collection->profile_source == AWS_PST_CREDENTIALS) {
            AWS_LOGF_WARN(
                AWS_LS_SDKUTILS_PROFILE,
                "Profile declarations in credentials files are not allowed to begin with the \"profile\" keyword");
            s_log_parse_context(AWS_LL_WARN, context);

            context->parse_error = AWS_ERROR_SDKUTILS_PARSE_RECOVERABLE;
            return true;
        }

        s_parse_by_character_predicate(&profile_cursor, s_is_whitespace, NULL, 0);
    } else {
        profile_cursor = backtrack_cursor;
    }

    struct aws_byte_cursor profile_name;
    if (!s_parse_by_character_predicate(&profile_cursor, s_is_identifier, &profile_name, 0)) {
        AWS_LOGF_WARN(AWS_LS_SDKUTILS_PROFILE, "Profile declarations must contain a valid identifier for a name");
        s_log_parse_context(AWS_LL_WARN, context);

        context->parse_error = AWS_ERROR_SDKUTILS_PARSE_RECOVERABLE;
        return true;
    }

    if (context->profile_collection->profile_source == AWS_PST_CONFIG && !has_profile_prefix &&
        !s_is_default_profile_name(&profile_name)) {
        AWS_LOGF_WARN(
            AWS_LS_SDKUTILS_PROFILE,
            "Non-default profile declarations in config files must use the \"profile\" keyword");
        s_log_parse_context(AWS_LL_WARN, context);

        context->parse_error = AWS_ERROR_SDKUTILS_PARSE_RECOVERABLE;
        return true;
    }

    s_parse_by_character_predicate(&profile_cursor, s_is_whitespace, NULL, 0);

    /*
     * Special case the right side bracket check.  We need to distinguish between a missing right bracket
     * (fatal error) and invalid profile name (spaces, non-identifier characters).
     *
     * Do so by consuming all non right-bracket characters.  If the remainder is empty it is missing,
     * otherwise it is an invalid profile name (non-empty invalid_chars) or a good definition
     * (empty invalid_chars cursor).
     */
    struct aws_byte_cursor invalid_chars;
    s_parse_by_character_predicate(&profile_cursor, s_is_not_profile_end, &invalid_chars, 0);
    if (profile_cursor.len == 0) {
        AWS_LOGF_WARN(AWS_LS_SDKUTILS_PROFILE, "Profile declaration missing required ending bracket");
        s_log_parse_context(AWS_LL_WARN, context);

        context->parse_error = AWS_ERROR_SDKUTILS_PARSE_FATAL;
        return true;
    }

    if (invalid_chars.len > 0) {
        AWS_LOGF_WARN(
            AWS_LS_SDKUTILS_PROFILE,
            "Profile declaration contains invalid characters: \"" PRInSTR "\"",
            AWS_BYTE_CURSOR_PRI(invalid_chars));
        s_log_parse_context(AWS_LL_WARN, context);

        context->parse_error = AWS_ERROR_SDKUTILS_PARSE_RECOVERABLE;
        return true;
    }

    /*
     * Apply to the profile collection
     */
    if (s_profile_collection_add_profile(
            context->profile_collection, &profile_name, has_profile_prefix, context, &context->current_profile)) {
        AWS_LOGF_ERROR(AWS_LS_SDKUTILS_PROFILE, "Failed to add profile to profile collection");
        s_log_parse_context(AWS_LL_ERROR, context);

        context->parse_error = AWS_ERROR_SDKUTILS_PARSE_FATAL;
        return true;
    }

    return true;
}