Resolves the buffers a glTF document refers to.
A buffer arrives one of three ways:
- No
uri— the data lives in the GLB container's BIN chunk. Only the first buffer may do this. - A
data:URI — base64 embedded in the JSON. Convenient, and about a third larger than the bytes it carries, which is why GLB exists. - A relative URI — a sibling file, resolved against the directory the document was read from.
Reading someone else's file
That third case means a glTF document names paths that get opened. A document
is data, often downloaded, and "uri": "../../../etc/passwd" is a valid
string. External buffers are therefore confined to the base directory by
default.
The confinement resolves symbolic links before comparing, which is the part
that is easy to get wrong: Path.expand/1 collapses .. lexically, but
the filesystem does not, so a symlink sitting inside the asset's directory
and pointing anywhere at all passes a purely textual check while File.read/1
follows it. An asset bundle carrying a .gltf next to a symlink is an
ordinary way to receive one of these.
resolve/2 takes allow_outside_base: true for callers who genuinely mean
to follow a symlinked asset library, and external: false to refuse sibling
files outright.
Summary
Functions
@spec decode_data_uri(String.t(), non_neg_integer() | nil) :: {:ok, binary()} | {:error, Gltf.Error.t()}
Decodes the body of a data: URI.
Both base64 and percent-encoded payloads are accepted; the media type is ignored, since the document already says what the bytes are for.
@spec resolve( map(), keyword() ) :: {:ok, [binary()]} | {:error, Gltf.Error.t()}
Resolves every buffer in a document, in document order.
Options
:bin— the GLB BIN chunk, for a buffer with nouri.:base— the directory external URIs resolve against. Without it, an external URI is an error, since there is nothing to resolve against.:external— whether to read sibling files at all. Defaults totrue.:allow_outside_base— permit a resolved path outside:base. Defaults tofalse.