Gltf.Buffer (Gltf v0.1.0)

Copy Markdown View Source

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

Decodes the body of a data: URI.

Resolves every buffer in a document, in document order.

Functions

decode_data_uri(rest, index \\ nil)

@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.

resolve(document, opts \\ [])

@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 no uri.
  • :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 to true.
  • :allow_outside_base — permit a resolved path outside :base. Defaults to false.