Skip to content

CurlHttpClient::setIntuitResponse() uses mb_substr on the raw response → corrupts binary bodies (DownloadPDF returns a blank/damaged PDF) #581

Description

@akolahi

SDK version: 6.3.1 (regressed from 6.2.0, which used substr) PHP: 8.3 · HTTP client: cURL (CurlHttpClient)
Summary DownloadPDF() returns a corrupted PDF (damaged xref/trailer, renders blank) because CurlHttpClient::setIntuitResponse() splits the raw cURL response into headers/body with mb_substr() using a byte offset.
Root cause — src/Core/HttpClients/CurlHttpClient.php (~line 120):
$headerSize = $this->basecURL->getInfo(CURLINFO_HEADER_SIZE); // BYTES
$rawHeaders = mb_substr($response, 0, $headerSize);
$rawBody = mb_substr($response, $headerSize);
CURLINFO_HEADER_SIZE is a byte count, but mb_substr() splits by multibyte characters. For a binary response body (e.g. a PDF), the split lands at the wrong byte and mangles the content. Text responses (XML/JSON) are valid UTF-8, so they happen to survive — which is why only binary downloads (DownloadPDF) are affected, and CRUD/query still work.
Steps to reproduce

  1. On PHP 8.x with the cURL client, call DataService::DownloadPDF($invoice) for any invoice.
  2. Open the resulting file. It is a structurally-damaged PDF ("Couldn't read xref table" / "Couldn't find trailer dictionary") and renders blank.
    Expected: a valid PDF (as in 6.2.0). Actual: corrupted/blank PDF; any binary response is byte-mangled.
    Suggested fix Use byte-based splitting, since $headerSize is bytes:
    $rawHeaders = substr($response, 0, $headerSize);
    $rawBody = substr($response, $headerSize);
    (or, if mb_substr is intentional, force byte mode: mb_substr($response, 0, $headerSize, '8bit')).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions