size_t curl_easy::header_callback()

in src/Linux/curl_easy.cpp [224:307]


size_t curl_easy::header_callback(
    char* buffer,
    size_t size,
    size_t nitems,
    void* user_data)
{
    // CURL promises that the total size will never be greater than
    // CURL_MAX_WRITE_SIZE.
    if (size > CURL_MAX_HTTP_HEADER || nitems > CURL_MAX_HTTP_HEADER)
    {
        log(SGX_QL_LOG_ERROR, "Header callback buffer size is too large");
        return 0;
    }

    const size_t buffer_size = size * nitems;

    // the string should end with CRLF
    if (buffer_size < 2 || buffer[buffer_size - 1] != '\n' ||
        buffer[buffer_size - 2] != '\r')
    {
        log(SGX_QL_LOG_ERROR, "Header data not properly terminated with CRLF.");
        return 0;
    }

    // CURL likes to pass the header/body separator line as a header (CRLF).
    // Just
    // skip it.
    if (buffer_size == 2)
    {
        return buffer_size;
    }

    // look for the delimiter
    size_t field_name_end_index = 0;
    while (field_name_end_index < buffer_size &&
           buffer[field_name_end_index] != ':')
    {
        ++field_name_end_index;
    }

    if (field_name_end_index >= buffer_size)
    {
        // CURL, for some reason, considers the status line a "header". Skip it
        // if we encounter it.
        return is_http_version(buffer, buffer_size) ? buffer_size : 0;
    }

    // next, find the start of the header data
    size_t content_start_index = field_name_end_index + 1;
    while (content_start_index < buffer_size &&
           is_optional_whitespace(buffer[content_start_index]))
    {
        ++content_start_index;
    }

    if (content_start_index >= buffer_size)
    {
        log(SGX_QL_LOG_ERROR, "Header is empty.");
        return 0;
    }

    // last, find the end of the header data (skip CRLF)
    size_t content_end_index = buffer_size - 2;
    while (content_end_index > content_start_index &&
           is_optional_whitespace(buffer[content_end_index]))
    {
        --content_end_index;
    }

    if (content_end_index <= content_start_index)
    {
        log(SGX_QL_LOG_ERROR, "Header delimiter is missing.");
        return 0;
    }

    const std::string field_name =
        to_lower(std::string(buffer, field_name_end_index));
    const std::string content(
        buffer + content_start_index, content_end_index - content_start_index);

    static_cast<curl_easy*>(user_data)->headers[field_name] = content;

    return buffer_size;
}