<?xml version="1.0" encoding="UTF-8"?>
  <?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
  <!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.32 (Ruby 3.3.0) -->


<!DOCTYPE rfc  [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">

]>


<rfc ipr="trust200902" docName="draft-gondwana-jmap-blobext-06" category="std" consensus="true" submissionType="IETF" updates="8620, 9404" tocInclude="true" sortRefs="true" symRefs="true">
  <front>
    <title abbrev="JMAP Blob Extended">JMAP Blob Extensions</title>

    <author initials="B." surname="Gondwana" fullname="Bron Gondwana">
      <organization>Fastmail</organization>
      <address>
        <email>brong@fastmailteam.com</email>
      </address>
    </author>

    <date year="2026" month="April" day="07"/>

    
    
    <keyword>Internet-Draft</keyword>

    <abstract>


<?line 29?>

<t>The JMAP base protocol (RFC8620) provides the ability to upload and download
arbitrary binary data.  This binary data is called a "blob", and can be used
in all other JMAP extensions.</t>

<t>The JMAP blob extension (RFC9404) added additional ways to create and access
blobs by making inline method calls within a standard JMAP request.</t>

<t>This extension adds more methods to work with blobs, including handling large
blobs by processing them in chunks (building on RFC9404's blob construction
support), and providing server-side blob conversion operations: image format
conversion, archive creation and extraction (zip, tar, cpio), compression
and decompression, and delta/patch operations.</t>



    </abstract>



  </front>

  <middle>


<?line 44?>

<section anchor="introduction"><name>Introduction</name>

<t>The JMAP Blob extension (<xref target="JMAP-BLOB"/> — JMAP Blob Management) offers additional
ways to create blobs, and query where they are used.</t>

<t>This extension builds on that work, offering ways to find more information about
the internal structure of the server's blob store in order to work efficiently
with it, and a new Blob/convert method for server-side blob transformations
including image format conversion, archive creation and extraction, compression
and decompression, and delta/patch operations.</t>

<section anchor="conventions-used-in-this-document"><name>Conventions Used in This Document</name>

<t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL
NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
"<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as
described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they
appear in all capitals, as shown here.</t>

<?line -18?>

</section>
</section>
<section anchor="addition-to-the-capabilities-object"><name>Addition to the Capabilities Object</name>

<t>The capabilities object is returned as part of the JMAP Session
object; see <xref target="JMAP-CORE"/>, Section 2.</t>

<t>This document defines an additional capability URI.</t>

<section anchor="urnietfparamsjmapblobext"><name>urn:ietf:params:jmap:blobext</name>

<t>The capability <spanx style="verb">urn:ietf:params:jmap:blobext</spanx> being present in the
"accountCapabilities" property of an account represents support for
these extended properties on that account.  This capability depends
on <spanx style="verb">urn:ietf:params:jmap:blob</spanx> (<xref target="JMAP-BLOB"/>); both <bcp14>MUST</bcp14> be present
in the account's "accountCapabilities" and in the request's <spanx style="verb">using</spanx>
array.  If this capability is present in one or more
"accountCapabilities" properties then the server <bcp14>MUST</bcp14> also include
the key in the "capabilities" property.</t>

<t>The value of this property in the JMAP session "capabilities"
property <bcp14>MUST</bcp14> be an empty object.</t>

<t>The value of this property in an account's "accountCapabilities"
property is an object that <bcp14>MUST</bcp14> contain the following information
on server capabilities and permissions for that account:</t>

<t><list style="symbols">
  <t>chunkSize: "UnsignedInt|null"  <vspace blankLines='1'/>
A hint indicating the preferred chunk size in octets.  If a
  client uploads blobs with exactly this size except for the
  final chunk, and uses Blob/upload with DataSourceObjects
  referencing these chunks, the server can optimise storage of
  these chunks.  Servers <bcp14>MUST</bcp14> allow other sizes for the
  individual data blocks in Blob/upload though, and will then
  choose whether to store them as an array of blobs still, or
  to combine them.</t>
  <t>supportedImageReadTypes: "String[]|null"  <vspace blankLines='1'/>
The media types (<xref target="MEDIA-TYPES"/>) that the server can read as
  input to ImageConvertRecipe.  If null, the server does not
  support image conversion.</t>
  <t>supportedImageWriteTypes: "String[]|null"  <vspace blankLines='1'/>
The media types (<xref target="MEDIA-TYPES"/>) that the server can produce
  as output from ImageConvertRecipe.  If null, the server does
  not support image conversion.</t>
  <t>supportedArchiveTypes: "String[]|null"  <vspace blankLines='1'/>
The archive MIME types supported for creating archives via
  ArchiveRecipe.  Defined values are "application/zip",
  "application/x-tar", and "application/x-cpio".  If null,
  the server does not support archive creation.</t>
  <t>supportedExtractTypes: "String[]|null"  <vspace blankLines='1'/>
The archive MIME types supported for extracting archives via
  ExtractRecipe.  This <bcp14>MAY</bcp14> include types not in
  <spanx style="verb">supportedArchiveTypes</spanx> (e.g., "application/vnd.ms-tnef").
  If null, the server does not support archive extraction.</t>
  <t>supportedCompressTypes: "String[]|null"  <vspace blankLines='1'/>
The compression MIME types supported for compressing via
  CompressRecipe.  Defined values are "application/gzip",
  "application/x-bzip2", "application/x-xz", and
  "application/zstd".  If null, the server does not support
  compression.</t>
  <t>supportedDecompressTypes: "String[]|null"  <vspace blankLines='1'/>
The compression MIME types supported for decompressing via
  DecompressRecipe.  This <bcp14>MAY</bcp14> include types not in
  <spanx style="verb">supportedCompressTypes</spanx>.  If null, the server does not
  support decompression.</t>
  <t>supportedDeltaTypes: "String[]|null"  <vspace blankLines='1'/>
The delta media types supported for computing deltas via
  DeltaRecipe.  Defined values are
  "application/x-rdiff-delta", "application/x-bsdiff", and
  "text/x-diff" (unified diff).  If null, the server does
  not support delta computation.</t>
  <t>supportedPatchTypes: "String[]|null"  <vspace blankLines='1'/>
The delta media types supported for applying patches via
  PatchRecipe.  This <bcp14>MAY</bcp14> include types not in
  <spanx style="verb">supportedDeltaTypes</spanx>.  If null, the server does not
  support patch application.</t>
  <t>maxConvertSize: "UnsignedInt|null"  <vspace blankLines='1'/>
If supplied, the maximum size in octets of any single input
  blob to a Blob/convert operation.  Requests referencing a blob
  larger than this value <bcp14>MUST</bcp14> be rejected with a "tooLarge"
  SetError.  If null, the server does not advertise a specific
  limit but <bcp14>MAY</bcp14> still reject blobs that are too large.</t>
  <t>maxArchiveEntries: "UnsignedInt|null"  <vspace blankLines='1'/>
If supplied, the maximum number of entries allowed in an
  ArchiveRecipe.  Requests exceeding this limit <bcp14>MUST</bcp14> be rejected
  with a "tooLarge" SetError.  If null, the server does not
  advertise a specific limit but <bcp14>MAY</bcp14> still reject requests with
  too many entries.</t>
  <t>maxImageDimension: "UnsignedInt|null"  <vspace blankLines='1'/>
If supplied, the maximum value accepted for <spanx style="verb">width</spanx> or <spanx style="verb">height</spanx>
  in an ImageConvertRecipe, in pixels.  Requests exceeding this
  limit <bcp14>MUST</bcp14> be rejected with a "tooLarge" SetError.  If null,
  the server does not advertise a specific limit but <bcp14>MAY</bcp14> still
  reject requests with dimensions that are too large.</t>
</list></t>

<section anchor="capability-example"><name>Capability Example</name>

<figure><sourcecode type="json"><![CDATA[
{
  "urn:ietf:params:jmap:blobext": {
    "chunkSize": 5242880,
    "supportedImageReadTypes": [
      "image/png",
      "image/jpeg",
      "image/gif",
      "image/tiff"
    ],
    "supportedImageWriteTypes": [
      "image/png",
      "image/jpeg"
    ],
    "supportedArchiveTypes": [
      "application/zip",
      "application/x-tar"
    ],
    "supportedExtractTypes": [
      "application/zip",
      "application/x-tar",
      "application/vnd.ms-tnef"
    ],
    "supportedCompressTypes": [
      "application/gzip",
      "application/zstd"
    ],
    "supportedDecompressTypes": [
      "application/gzip",
      "application/x-bzip2",
      "application/zstd"
    ],
    "supportedDeltaTypes": [
      "application/x-rdiff-delta",
      "text/x-diff"
    ],
    "supportedPatchTypes": [
      "application/x-rdiff-delta",
      "text/x-diff"
    ],
    "maxConvertSize": 104857600,
    "maxArchiveEntries": 10000,
    "maxImageDimension": 8192
  }
}
]]></sourcecode></figure>

</section>
</section>
<section anchor="additions-to-datasourceobject"><name>Additions to DataSourceObject</name>

<t>When this capability is present, the DataSourceObject (as defined in
<xref target="JMAP-BLOB"/>, Section 4.2) is extended with the following additional
properties.  These apply both to the <spanx style="verb">chunks</spanx> returned by Blob/get
and to DataSourceObjects used in Blob/upload.  The <spanx style="verb">offset</spanx> and
<spanx style="verb">length</spanx> properties are already defined in <xref target="JMAP-BLOB"/>; they are
listed here to document their use in the <spanx style="verb">chunks</spanx> response context,
where they describe the range of each chunk's underlying data source
that contributes to the containing blob.</t>

<t><list style="symbols">
  <t>offset: "UnsignedInt|null"
The offset within the data source from which to start copying
octets (see <xref target="JMAP-BLOB"/>).  <bcp14>MUST</bcp14> fit within the data source
(i.e. offset <bcp14>MUST</bcp14> be less than or equal to the data source size).
If null, defaults to 0 (the start of the data source).</t>
  <t>length: "UnsignedInt|null"
The number of octets to copy from the data source (see
<xref target="JMAP-BLOB"/>).  <bcp14>MUST</bcp14> fit within the data source (i.e. offset +
length <bcp14>MUST</bcp14> be less than or equal to the data source size).  If
null, copy from <spanx style="verb">offset</spanx> to the end of the data source.</t>
  <t>size: "UnsignedInt|null"
The full size of the chunk's underlying data source in octets.</t>
  <t>position: "UnsignedInt|null"
The byte offset of the start of this chunk within the outer
(containing) blob.</t>
</list></t>

<t>If a <spanx style="verb">digest:*</spanx> property (e.g. <spanx style="verb">digest:sha</spanx>, <spanx style="verb">digest:sha-256</spanx>) is
included in <spanx style="verb">dataSourceProperties</spanx>, each DataSourceObject in the
<spanx style="verb">chunks</spanx> array will include the corresponding digest value computed
over the octets that this chunk contributes (i.e. after applying
<spanx style="verb">offset</spanx> and <spanx style="verb">length</spanx>).</t>

<t>When a server provides <spanx style="verb">size</spanx>, <spanx style="verb">position</spanx>, or <spanx style="verb">digest:*</spanx> values in
a Blob/get response, it <bcp14>MUST</bcp14> calculate them correctly.  When a
DataSourceObject containing <spanx style="verb">size</spanx>, <spanx style="verb">position</spanx>, or <spanx style="verb">digest:*</spanx> values
is used in Blob/upload, the server <bcp14>MUST</bcp14> reject the object if any
provided value does not match the actual data.</t>

</section>
<section anchor="additions-to-blobget"><name>Additions to Blob/get</name>

<t>When this capability is present, Blob/get accepts an additional
request argument:</t>

<t><list style="symbols">
  <t>dataSourceProperties: "String[]" (default: ["blobId", "size"])
If supplied, only the properties listed in the array are returned
for each DataSourceObject in the <spanx style="verb">chunks</spanx> array.  If omitted, the
default of <spanx style="verb">["blobId", "size"]</spanx> is used.  Available properties
include <spanx style="verb">blobId</spanx>, <spanx style="verb">size</spanx>, <spanx style="verb">offset</spanx>, <spanx style="verb">length</spanx>, <spanx style="verb">position</spanx>, and
<spanx style="verb">digest:*</spanx> values where <spanx style="verb">*</spanx> is a hash algorithm name from the
IANA "Hash Function Textual Names" registry (e.g.
<spanx style="verb">digest:sha-256</spanx>).</t>
</list></t>

<t>Blob/get also returns an additional response property (returned by
default when this capability is included in <spanx style="verb">using</spanx>):</t>

<t><list style="symbols">
  <t>chunks: "DataSourceObject[]"  <vspace blankLines='1'/>
An array of one or more data source objects (as defined in <xref target="JMAP-BLOB"/>,
  Section 4.2).  The blob is reconstructed by concatenating the data
  from each data source object in the listed order.  While it is
  expected that each data source object will reference the entire
  underlying chunk blob, the server <bcp14>MAY</bcp14> return offset and length values
  that select only a portion of a chunk's blob.  The client <bcp14>MUST</bcp14> use
  the offset and length to determine which octets to read from each
  chunk.</t>
</list></t>

<t>Blob/get also accepts the following additional property in
the <spanx style="verb">properties</spanx> array:</t>

<t><list style="symbols">
  <t>imageData: "ImageData|null" (server-set)  <vspace blankLines='1'/>
If the blob is an image or video type and the server can
  extract metadata, this is an ImageData object.  Otherwise
  null.  Only returned if explicitly requested in
  <spanx style="verb">properties</spanx>.  The server <bcp14>MAY</bcp14> need to read the blob content
  to compute this data, so clients <bcp14>SHOULD</bcp14> only request it
  when needed.  Since blobs are immutable, the result for a
  given blobId will never change, and the server <bcp14>SHOULD</bcp14> cache
  it.  <vspace blankLines='1'/>
An ImageData object has the following properties:  <list style="symbols">
      <t>width: "UnsignedInt|null"
Width of the image in pixels, if known.</t>
      <t>height: "UnsignedInt|null"
Height of the image in pixels, if known.</t>
      <t>orientation: "UnsignedInt|null"
EXIF orientation value (1-8) as defined in the EXIF
specification (CIPA DC-008).  If present, indicates how
the image should be rotated/flipped for display.</t>
      <t>date: "UTCDate|null"
Date the image or video was captured (from EXIF
DateTimeOriginal or equivalent), if present.</t>
      <t>gps: "ImageGPS|null"
GPS coordinates from EXIF, if present.  An ImageGPS
object has the following properties:
      <list style="symbols">
          <t>latitude: "Number" — Latitude in decimal degrees.</t>
          <t>longitude: "Number" — Longitude in decimal degrees.</t>
        </list></t>
      <t>duration: "Number|null"
Duration in seconds for video content, if known.  This
is a floating-point number to allow sub-second precision.</t>
      <t>comment: "String|null"
Embedded EXIF comment or description, if present.  This
is read-only — it reflects the metadata stored in the
blob content and is not a user-editable property.</t>
    </list></t>
</list></t>

</section>
<section anchor="additions-to-blobupload"><name>Additions to Blob/upload</name>

<t>When this capability is present, each object in the Blob/upload
(<xref target="JMAP-BLOB"/>, Section 4) <spanx style="verb">create</spanx> map <bcp14>MAY</bcp14> include the following
additional property:</t>

<t><list style="symbols">
  <t>noPersist: "Boolean" (default: false)
If true, the resulting blob is ephemeral: it may be referenced via
creation id backreferences within the same JMAP request, but the
server is not required to persist it beyond the lifetime of the
request.  The server <bcp14>MAY</bcp14> omit ephemeral blobs from the <spanx style="verb">created</spanx>
map of the response and from the <spanx style="verb">createdIds</spanx> of the final Response
object if it did not create a referenceable blob.  This allows
servers to optimise pipelines where intermediate blobs are never
needed after the request completes.</t>
</list></t>

<t>When this capability is present, Blob/upload also gains the
following additional request properties:</t>

<t><list style="symbols">
  <t>update: "Id[Object]" (default: null)
A map of blobId to an empty object.  No properties may be
set on a blob; the purpose of update is to "touch" the blob,
refreshing its lifetime on the server.  The response includes
an <spanx style="verb">updated</spanx> map of blobId to an object which <bcp14>MAY</bcp14> contain an
<spanx style="verb">expires</spanx> property with the new expiry time.  If the blobId
does not exist, it <bcp14>MUST</bcp14> be reported in a <spanx style="verb">notUpdated</spanx> map
with a <spanx style="verb">notFound</spanx> SetError.</t>
  <t>destroy: "Id[]" (default: null)
An array of blobIds to destroy.  The server <bcp14>MUST</bcp14> reject
any blob that is still referenced by another object with a
<spanx style="verb">blobHasReference</spanx> SetError.  If the blobId does not exist, the
server <bcp14>MUST</bcp14> return a <spanx style="verb">notFound</spanx> SetError.  Successfully
destroyed blobIds are returned in a <spanx style="verb">destroyed</spanx> array.
Failed destroys are returned in a <spanx style="verb">notDestroyed</spanx> map of
blobId to SetError.</t>
</list></t>

</section>
<section anchor="the-expires-response-property"><name>The "expires" response property</name>

<t>When this capability is present, the Blob/upload response
(<xref target="JMAP-BLOB"/>, Section 4) and the Blob/convert response defined
below include an additional property.</t>

<t><list style="symbols">
  <t>expires: "UTCDate|null"
A hint from the server indicating the likely availability of
the blob.  The blob is likely to remain available until this
time, and likely not to be available after it.  This is not a
guarantee in either direction: the server <bcp14>MAY</bcp14> garbage collect
the blob before this time if it is unreferenced, and <bcp14>MAY</bcp14>
retain it longer.  If null, the server does not have a
specific expiry time for the blob.</t>
</list></t>

<t>Clients that need the blob to persist beyond the <spanx style="verb">expires</spanx> time
should reference it from a persistent object (e.g., a FileNode
or an Email) before it expires.</t>

</section>
<section anchor="new-method-blobconvert"><name>New method Blob/convert</name>

<t>Blob/convert is defined under the <spanx style="verb">urn:ietf:params:jmap:blobext</spanx>
capability and requires that capability in the request's <spanx style="verb">using</spanx>
array.</t>

<t>Blob/convert performs server-side transformations on blobs.  Like
Blob/upload (<xref target="JMAP-BLOB"/>, Section 4), it takes an <spanx style="verb">accountId</spanx> and a
<spanx style="verb">create</spanx> argument that maps creation ids to conversion request objects.</t>

<t>Each conversion request object <bcp14>MAY</bcp14> also include the following property:</t>

<t><list style="symbols">
  <t>noPersist: "Boolean" (default: false)
If true, the resulting blob is ephemeral: it may be referenced via
creation id backreferences within the same JMAP request, but the
server is not required to persist it beyond the lifetime of the
request.  The server <bcp14>MAY</bcp14> omit ephemeral blobs from the <spanx style="verb">created</spanx>
map of the response and from the <spanx style="verb">createdIds</spanx> of the final Response
object if it did not create a referenceable blob.</t>
</list></t>

<t>Each conversion request object <bcp14>MUST</bcp14> contain exactly one of the
following properties, which determines the type of conversion:</t>

<t><list style="symbols">
  <t>imageConvert: ImageConvertRecipe</t>
  <t>archive: ArchiveRecipe</t>
  <t>extract: ExtractRecipe</t>
  <t>compress: CompressRecipe</t>
  <t>decompress: DecompressRecipe</t>
  <t>delta: DeltaRecipe</t>
  <t>patch: PatchRecipe</t>
</list></t>

<t>The response has the same structure as Blob/upload (<xref target="JMAP-BLOB"/>,
Section 4): a <spanx style="verb">created</spanx> map of creation id to an object containing
<spanx style="verb">id</spanx>, <spanx style="verb">type</spanx>, and <spanx style="verb">size</spanx> for each successful conversion, and a
<spanx style="verb">notCreated</spanx> map of creation id to a SetError object for each failed
conversion.  The <spanx style="verb">id</spanx> is the blobId of the created blob.  The
response also includes an <spanx style="verb">expires</spanx> property (see "The expires
response property" above).</t>

<t>If the conversion completed but encountered problems (e.g., a
corrupt archive where some entries extracted successfully but
others did not, or a truncated compressed stream that partially
decompressed), the response for that creation also includes:</t>

<t><list style="symbols">
  <t>isIncomplete: "Boolean" (default: false)
If true, the conversion did not complete cleanly.  The output
blob may be partial or missing some content.</t>
  <t>description: "String|null"
A human-readable description of the problem, if any.</t>
</list></t>

<t>If the conversion failed entirely and no usable output could be
produced, the server <bcp14>MUST</bcp14> return a <spanx style="verb">conversionFailed</spanx> SetError
in the <spanx style="verb">notCreated</spanx> map.</t>

<t>Creation id backreferences (using the <spanx style="verb">#</spanx> prefix) resolve to
the <spanx style="verb">id</spanx> of the created blob and may be used in subsequent
conversions within the same Blob/convert call or in later
method calls within the same JMAP request.</t>

<t>A server <bcp14>MAY</bcp14> return a blobId for a conversion result without
immediately generating the output data.  In this case the server
<bcp14>MUST</bcp14> generate the data when the blob is later accessed (e.g., via
a download request or as input to another operation).  This allows
the server to respond quickly to Blob/convert requests while
deferring expensive work such as image resizing or archive
creation.  The returned blobId <bcp14>MUST</bcp14> be usable in all contexts
where a regular blobId is accepted.  If the deferred generation
later fails (e.g., the source blob has expired), the server
<bcp14>SHOULD</bcp14> return an appropriate HTTP error when the blob is
downloaded.  If the exact size of the output is not yet known, the
server <bcp14>MUST</bcp14> omit the <spanx style="verb">size</spanx> property from the response for that
creation.  If a client later requests the <spanx style="verb">size</spanx> property via
Blob/get for a deferred blob, the server <bcp14>MUST</bcp14> generate the blob
at that point and return the actual size.</t>

<t>The server <bcp14>MUST</bcp14> resolve the order of dependencies between entries
in the <spanx style="verb">create</spanx> map and process them in an order such that all
backreferences are satisfied.  If a dependency cycle is detected,
all members of the cycle <bcp14>MUST</bcp14> be rejected with an
"invalidProperties" error.</t>

<section anchor="imageconvertrecipe"><name>ImageConvertRecipe</name>

<t>An ImageConvertRecipe converts an image blob to a different format
or size.  It is an object with the following properties:</t>

<t><list style="symbols">
  <t>blobId: "BlobId"
The blobId of the source image.</t>
  <t>type: "String"
Media type (<xref target="MEDIA-TYPES"/>) of the image to create (e.g.
"image/png").  <bcp14>MUST</bcp14> be one of the values in the server's
<spanx style="verb">supportedImageWriteTypes</spanx> capability.  The source image <bcp14>MUST</bcp14>
be in a format listed in <spanx style="verb">supportedImageReadTypes</spanx>.</t>
  <t>width: "UnsignedInt|null"
Maximum width in pixels of the image to create.  If null, the
server preserves the source width (or scales proportionally if
only <spanx style="verb">height</spanx> is given).</t>
  <t>height: "UnsignedInt|null"
Maximum height in pixels of the image to create.  If null, the
server preserves the source height (or scales proportionally if
only <spanx style="verb">width</spanx> is given).</t>
  <t>ignoreAspect: "Boolean|null"
If true, resize to exactly the given width and height, even if
the aspect ratio is changed.  If null or false, the image is
scaled to fit within the given dimensions while preserving the
aspect ratio.</t>
  <t>quality: "UnsignedInt|null"
Compression quality for lossy formats, as a value from 1 (lowest
quality, smallest file) to 100 (highest quality, largest file).
Only meaningful for formats that support lossy compression such as
image/jpeg and image/webp.  If null, the server selects a sensible
default.</t>
  <t>colorSpace: "String|null"
The color space for the output image.  Defined values are "sRGB"
and "grayscale".  If null, the server preserves the source image's
color space where possible.</t>
  <t>background: "String|null"
A fill color to use when the source image has transparency but the
target format does not support it (e.g. converting PNG to JPEG).
The value is a CSS-style hex color string (e.g. "#ffffff" for white).
If null, the server selects a sensible default (typically white).</t>
  <t>stripMetadata: "Boolean|null"
If true, strip image metadata such as EXIF, XMP, and IPTC data from
the output.  If null or false, the server preserves metadata where
the target format supports it.</t>
  <t>autoOrient: "Boolean|null"
If true, automatically rotate and flip the image according to its
EXIF orientation tag, then reset the tag.  If null or false, the
image data is not reoriented.</t>
</list></t>

<t>Errors:</t>

<t><list style="symbols">
  <t>"notFound" — the referenced blobId does not exist.</t>
  <t>"invalidProperties" — the type is not in
<spanx style="verb">supportedImageWriteTypes</spanx>, or the source blob is not in a format
listed in <spanx style="verb">supportedImageReadTypes</spanx>.</t>
  <t>"tooLarge" — the source blob exceeds <spanx style="verb">maxConvertSize</spanx>, or the
requested dimensions exceed <spanx style="verb">maxImageDimension</spanx>.</t>
  <t>"conversionFailed" — the image conversion failed entirely.</t>
</list></t>

</section>
<section anchor="archiverecipe"><name>ArchiveRecipe</name>

<t>An ArchiveRecipe creates an archive blob from a list of entries.
It is an object with the following properties:</t>

<t><list style="symbols">
  <t>type: "String"
The MIME type of the archive to create.  <bcp14>MUST</bcp14> be one of the values
in the server's <spanx style="verb">supportedArchiveTypes</spanx> capability.  Defined values
are "application/zip", "application/x-tar", and "application/x-cpio".</t>
  <t>entries: "ArchiveEntry[]"
An array of ArchiveEntry objects describing the contents of the
archive.</t>
</list></t>

<t>Errors:</t>

<t><list style="symbols">
  <t>"notFound" — a referenced entry blobId does not exist.</t>
  <t>"invalidProperties" — the type is not in <spanx style="verb">supportedArchiveTypes</spanx>;
an entry has an unsupported entryType for the archive format; or
a required field (e.g. linkTarget for symlink entries) is missing.</t>
  <t>"tooLarge" — the number of entries exceeds <spanx style="verb">maxArchiveEntries</spanx>,
or a referenced blob exceeds <spanx style="verb">maxConvertSize</spanx>.</t>
  <t>"conversionFailed" — the archive creation failed entirely.</t>
</list></t>

</section>
<section anchor="archiveentry"><name>ArchiveEntry</name>

<t>An ArchiveEntry describes a single entry in an archive.  It is used
both as input (in ArchiveRecipe) and as output (in ExtractRecipe
results).  It is an object with the following properties:</t>

<t><list style="symbols">
  <t>name: "String"
The path of the entry within the archive.  Directory entries <bcp14>MUST</bcp14>
have a name ending with "/".</t>
  <t>blobId: "BlobId|null"
The blobId of the content for this entry.  <bcp14>MUST</bcp14> be non-null for
file entries.  <bcp14>MUST</bcp14> be null or absent for directory, symlink,
hardlink, fifo, and device entries.  Violating these constraints
is an "invalidProperties" error.</t>
  <t>entryType: "String|null"
The type of the entry.  If null, defaults to "file".  Defined values
are "file" (a regular file, the default), "directory", "symlink"
(a symbolic link), "hardlink" (a hard link), "fifo" (a named pipe),
"blockDevice" (a block device node), and "charDevice" (a character
device node).  The server <bcp14>MUST</bcp14> reject entries with unsupported
types for the chosen archive format with an "invalidProperties"
error.</t>
  <t>modified: "UTCDate|null"
The modification time of the entry as an RFC 3339 timestamp.
If null, defaults to the current server time.</t>
  <t>linkTarget: "String|null"
The target path for symlink and hardlink entries.  <bcp14>MUST</bcp14> be non-null
when entryType is "symlink" or "hardlink".  <bcp14>MUST</bcp14> be null for all
other entry types.</t>
  <t>mode: "String|null"
Unix file permissions as an octal string (e.g. "0755", "0644").
If null, the server chooses a reasonable default.  This is
represented as a string rather than an integer to avoid ambiguity
between octal and decimal interpretation.</t>
  <t>uid: "UnsignedInt|null"
The numeric user ID of the entry owner.</t>
  <t>gid: "UnsignedInt|null"
The numeric group ID of the entry owner.</t>
  <t>ownerName: "String|null"
The user name of the entry owner.</t>
  <t>groupName: "String|null"
The group name of the entry owner.</t>
  <t>devMajor: "UnsignedInt|null"
The major device number for "blockDevice" and "charDevice" entries.</t>
  <t>devMinor: "UnsignedInt|null"
The minor device number for "blockDevice" and "charDevice" entries.</t>
  <t>comment: "String|null"
A comment string for this entry.</t>
  <t>compressionMethod: "String|null"
The per-entry compression method.  Defined values are "store" (no
compression) and "deflate".  If null, the server chooses a
reasonable default.</t>
</list></t>

<section anchor="considerations-for-applicationzip"><name>Considerations for application/zip</name>

<t>The zip format only supports "file" and "directory" entry types.
The <spanx style="verb">comment</spanx> and <spanx style="verb">compressionMethod</spanx> properties are only meaningful
for zip archives.  The <spanx style="verb">mode</spanx>, <spanx style="verb">uid</spanx>, <spanx style="verb">gid</spanx>, <spanx style="verb">ownerName</spanx>,
<spanx style="verb">groupName</spanx>, <spanx style="verb">devMajor</spanx>, and <spanx style="verb">devMinor</spanx> properties are ignored.</t>

</section>
<section anchor="considerations-for-applicationx-tar"><name>Considerations for application/x-tar</name>

<t>The tar format supports all entry types.  The <spanx style="verb">mode</spanx>, <spanx style="verb">uid</spanx>, <spanx style="verb">gid</spanx>,
<spanx style="verb">ownerName</spanx>, <spanx style="verb">groupName</spanx>, <spanx style="verb">devMajor</spanx>, and <spanx style="verb">devMinor</spanx> properties are
meaningful for tar archives.  The <spanx style="verb">comment</spanx> and <spanx style="verb">compressionMethod</spanx>
properties are ignored.</t>

<t>Tar archives are not inherently compressed.  To create a compressed
tar archive (e.g. a .tar.gz file), first create the tar archive
using ArchiveRecipe, then compress the result using CompressRecipe.
The following example creates a .tar.gz containing three files in a
single Blob/convert call, using a backreference from the archive
creation to the compression step:</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/convert", {
  "accountId": "abc",
  "create": {
    "t1": {
      "archive": {
        "type": "application/x-tar",
        "entries": [
          {
            "name": "site/index.html",
            "blobId": "Baaaa",
            "modified": "2026-03-01T12:00:00Z",
            "mode": "0644"
          },
          {
            "name": "site/logo.png",
            "blobId": "Bbbbb",
            "modified": "2026-02-15T09:30:00Z",
            "mode": "0644"
          },
          {
            "name": "site/style.css",
            "blobId": "Bcccc",
            "modified": "2026-03-01T12:00:00Z",
            "mode": "0644"
          }
        ]
      }
    },
    "t2": {
      "compress": {
        "blobId": "#t1",
        "type": "application/gzip"
      }
    }
  }
}, "0"]]
]]></sourcecode></figure>

</section>
<section anchor="considerations-for-applicationx-cpio"><name>Considerations for application/x-cpio</name>

<t>The cpio format supports all entry types except that <spanx style="verb">ownerName</spanx> and
<spanx style="verb">groupName</spanx> are not supported.  The <spanx style="verb">comment</spanx> and
<spanx style="verb">compressionMethod</spanx> properties are ignored.</t>

</section>
</section>
<section anchor="extractrecipe"><name>ExtractRecipe</name>

<t>An ExtractRecipe extracts the entry listing from an existing archive
blob.  It is an object with the following properties:</t>

<t><list style="symbols">
  <t>blobId: "BlobId"
The blobId of the archive to extract.</t>
  <t>type: "String|null"
The MIME type of the archive format.  If null, the server <bcp14>SHOULD</bcp14>
attempt to auto-detect the format from the blob content (e.g. by
inspecting magic bytes).  If auto-detection fails, the server <bcp14>MUST</bcp14>
return an "unknownFormat" error.</t>
</list></t>

<t>In addition to the standard creation response properties, a
successful ExtractRecipe result includes:</t>

<t><list style="symbols">
  <t>entries: "ArchiveEntry[]"
An array of ArchiveEntry objects describing the contents of the
archive.  Each file entry will have a blobId that can be used to
access the content of that entry.</t>
</list></t>

<t>Errors:</t>

<t><list style="symbols">
  <t>"notFound" — the referenced blobId does not exist.</t>
  <t>"unknownFormat" — the server could not determine or does not support
the archive format.</t>
  <t>"invalidProperties" — the type is not in <spanx style="verb">supportedExtractTypes</spanx>.</t>
  <t>"tooLarge" — the source blob exceeds <spanx style="verb">maxConvertSize</spanx>.</t>
  <t>"conversionFailed" — the extraction failed entirely.</t>
</list></t>

</section>
<section anchor="compressrecipe"><name>CompressRecipe</name>

<t>A CompressRecipe compresses a blob using a specified compression
algorithm.  It is an object with the following properties:</t>

<t><list style="symbols">
  <t>blobId: "BlobId"
The blobId of the data to compress.</t>
  <t>type: "String"
The MIME type of the compression format to use.  <bcp14>MUST</bcp14> be one of the
values in the server's <spanx style="verb">supportedCompressTypes</spanx> capability.
Defined values are "application/gzip", "application/x-bzip2",
"application/x-xz", and "application/zstd".</t>
  <t>level: "UnsignedInt|null"
The compression level, where higher values produce smaller output
at the cost of more CPU time.  If null, the server uses the
format's default level.  The valid range depends on the format;
if the requested level is outside the valid range, the server
<bcp14>SHOULD</bcp14> use the nearest valid value.</t>
  <t>checksum: "Boolean|null"
If true, include an integrity checksum in the compressed output.
If null, the server uses the format's default behaviour.</t>
</list></t>

<t>Errors:</t>

<t><list style="symbols">
  <t>"notFound" — the referenced blobId does not exist.</t>
  <t>"invalidProperties" — the type is not in <spanx style="verb">supportedCompressTypes</spanx>.</t>
  <t>"tooLarge" — the source blob exceeds <spanx style="verb">maxConvertSize</spanx>.</t>
  <t>"conversionFailed" — the compression failed entirely.</t>
</list></t>

<section anchor="considerations-for-applicationgzip"><name>Considerations for application/gzip</name>

<t>Compression level ranges from 1 (fastest) to 9 (best compression).
The default is typically 6.  Gzip always includes a CRC-32 checksum;
the <spanx style="verb">checksum</spanx> property is ignored.</t>

</section>
<section anchor="considerations-for-applicationx-bzip2"><name>Considerations for application/x-bzip2</name>

<t>Compression level ranges from 1 (fastest, 100k block size) to 9
(best compression, 900k block size).  The default is typically 9.
Bzip2 always includes a CRC-32 checksum; the <spanx style="verb">checksum</spanx> property is
ignored.</t>

</section>
<section anchor="considerations-for-applicationx-xz"><name>Considerations for application/x-xz</name>

<t>Compression level ranges from 0 (fastest) to 9 (best compression).
The default is typically 6.  Xz always includes an integrity check;
if <spanx style="verb">checksum</spanx> is true the server <bcp14>SHOULD</bcp14> use SHA-256, otherwise CRC-64
is used by default.</t>

</section>
<section anchor="considerations-for-applicationzstd"><name>Considerations for application/zstd</name>

<t>Compression level ranges from 1 (fastest) to 22 (best compression).
The default is typically 3.  If <spanx style="verb">checksum</spanx> is true, an xxHash-64
checksum is included in the frame; the default is false.</t>

</section>
</section>
<section anchor="decompressrecipe"><name>DecompressRecipe</name>

<t>A DecompressRecipe decompresses a compressed blob.  It is an object
with the following properties:</t>

<t><list style="symbols">
  <t>blobId: "BlobId"
The blobId of the compressed data to decompress.</t>
  <t>type: "String|null"
The MIME type of the compression format.  If null, the server <bcp14>SHOULD</bcp14>
attempt to auto-detect the format from magic bytes.  If auto-detection
fails, the server <bcp14>MUST</bcp14> return an "unknownFormat" error.</t>
</list></t>

<t>Errors:</t>

<t><list style="symbols">
  <t>"notFound" — the referenced blobId does not exist.</t>
  <t>"unknownFormat" — the server could not determine or does not support
the compression format.</t>
  <t>"invalidProperties" — the type is not in <spanx style="verb">supportedDecompressTypes</spanx>.</t>
  <t>"tooLarge" — the source blob exceeds <spanx style="verb">maxConvertSize</spanx>.</t>
  <t>"conversionFailed" — the decompression failed entirely.</t>
</list></t>

</section>
<section anchor="deltarecipe"><name>DeltaRecipe</name>

<t>A DeltaRecipe computes a delta between two blobs.  It is an object
with the following properties:</t>

<t><list style="symbols">
  <t>blobId: "BlobId"
The blobId of the original (base) blob.</t>
  <t>newBlobId: "BlobId"
The blobId of the new blob to compare against.</t>
  <t>type: "String"
The media type of the delta format to produce.  <bcp14>MUST</bcp14> be one of the
values in the server's <spanx style="verb">supportedDeltaTypes</spanx> capability.</t>
</list></t>

<t>The result blob is the computed delta, which can be applied to the
base blob using PatchRecipe to reconstruct the new blob.</t>

<t>Errors:</t>

<t><list style="symbols">
  <t>"notFound" — a referenced blobId does not exist.</t>
  <t>"invalidProperties" — the type is not in <spanx style="verb">supportedDeltaTypes</spanx>.</t>
  <t>"tooLarge" — a referenced blob exceeds <spanx style="verb">maxConvertSize</spanx>.</t>
  <t>"conversionFailed" — the delta computation failed entirely.</t>
</list></t>

<section anchor="considerations-for-applicationx-rdiff-delta"><name>Considerations for application/x-rdiff-delta</name>

<t>The server computes an rdiff signature of the base blob and then
generates a delta against the new blob.  The resulting delta blob
can only be applied to the exact base blob used to generate it.</t>

</section>
<section anchor="considerations-for-applicationx-bsdiff"><name>Considerations for application/x-bsdiff</name>

<t>The server produces a bsdiff-format patch.  Both blobs must fit in
memory; servers <bcp14>MAY</bcp14> reject very large blobs with a "tooLarge" error.</t>

</section>
<section anchor="considerations-for-textx-diff"><name>Considerations for text/x-diff</name>

<t>The server produces a unified diff.  Both blobs are interpreted as
text.  If either blob contains content that cannot be interpreted as
text, the server <bcp14>MUST</bcp14> return an "unknownFormat" error.</t>

</section>
</section>
<section anchor="patchrecipe"><name>PatchRecipe</name>

<t>A PatchRecipe applies a delta to a base blob to produce a new blob.
It is an object with the following properties:</t>

<t><list style="symbols">
  <t>blobId: "BlobId"
The blobId of the base blob to patch.</t>
  <t>deltaBlobId: "BlobId"
The blobId of the delta to apply.</t>
  <t>deltaType: "String"
The media type of the delta format.  <bcp14>MUST</bcp14> be one of the values in
the server's <spanx style="verb">supportedPatchTypes</spanx> capability.</t>
</list></t>

<t>The result blob is the patched output.</t>

<t>Errors:</t>

<t><list style="symbols">
  <t>"notFound" — a referenced blobId does not exist.</t>
  <t>"unknownFormat" — the delta blob is not valid for the specified
format (e.g., corrupt or malformed delta data).</t>
  <t>"invalidProperties" — the deltaType is not in <spanx style="verb">supportedPatchTypes</spanx>.</t>
  <t>"tooLarge" — a referenced blob exceeds <spanx style="verb">maxConvertSize</spanx>.</t>
  <t>"conversionFailed" — the patch application failed entirely.</t>
</list></t>

</section>
</section>
</section>
<section anchor="examples"><name>Examples</name>

<section anchor="querying-blob-chunks"><name>Querying Blob Chunks</name>

<t>This example fetches a blob's chunk structure with offsets, sizes,
and SHA-256 digests:</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/get", {
  "accountId": "abc",
  "ids": ["B1a2b3c"],
  "dataSourceProperties": [
    "blobId", "size", "offset", "length", "position",
    "digest:sha-256"
  ]
}, "0"]]
]]></sourcecode></figure>

<t>The response shows the blob is stored as two chunks:</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/get", {
  "accountId": "abc",
  "list": [{
    "id": "B1a2b3c",
    "size": 10485760,
    "chunks": [
      {
        "blobId": "Bchunk1",
        "size": 5242880,
        "offset": 0,
        "length": 5242880,
        "position": 0,
        "digest:sha-256": "a1b2c3..."
      },
      {
        "blobId": "Bchunk2",
        "size": 5242880,
        "offset": 0,
        "length": 5242880,
        "position": 5242880,
        "digest:sha-256": "d4e5f6..."
      }
    ]
  }],
  "notFound": []
}, "0"]]
]]></sourcecode></figure>

<t>The <spanx style="verb">position</spanx> values show where each chunk fits in the assembled
blob, and the <spanx style="verb">digest:sha-256</spanx> values can be used to verify chunk
integrity.</t>

</section>
<section anchor="creating-a-zip-archive"><name>Creating a Zip Archive</name>

<t>This example creates a zip file containing an HTML document, a CSS
file, and a JPEG image:</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/convert", {
  "accountId": "abc",
  "create": {
    "z1": {
      "archive": {
        "type": "application/zip",
        "entries": [
          {
            "name": "site/index.html",
            "blobId": "Baaaa"
          },
          {
            "name": "site/style.css",
            "blobId": "Bbbbb"
          },
          {
            "name": "site/photo.jpg",
            "blobId": "Bcccc"
          }
        ]
      }
    }
  }
}, "0"]]
]]></sourcecode></figure>

<t>The response includes the blobId, type, and size of the created
archive:</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/convert", {
  "accountId": "abc",
  "created": {
    "z1": {
      "id": "B9f2a4e",
      "type": "application/zip",
      "size": 104857
    }
  },
  "notCreated": {}
}, "0"]]
]]></sourcecode></figure>

</section>
<section anchor="creating-a-compressed-tar-archive"><name>Creating a Compressed Tar Archive</name>

<t>This example creates a .tar.gz file from the same three files.
The intermediate tar blob uses <spanx style="verb">noPersist</spanx> since only the final
compressed result is needed:</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/convert", {
  "accountId": "abc",
  "create": {
    "t1": {
      "noPersist": true,
      "archive": {
        "type": "application/x-tar",
        "entries": [
          {
            "name": "site/index.html",
            "blobId": "Baaaa",
            "modified": "2026-03-01T12:00:00Z",
            "mode": "0644"
          },
          {
            "name": "site/style.css",
            "blobId": "Bbbbb",
            "modified": "2026-03-01T12:00:00Z",
            "mode": "0644"
          },
          {
            "name": "site/photo.jpg",
            "blobId": "Bcccc",
            "modified": "2026-02-15T09:30:00Z",
            "mode": "0644"
          }
        ]
      }
    },
    "t2": {
      "compress": {
        "blobId": "#t1",
        "type": "application/gzip"
      }
    }
  }
}, "0"]]
]]></sourcecode></figure>

<t>Because "t1" was created with <spanx style="verb">noPersist</spanx>, the server may omit it
from the response:</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/convert", {
  "accountId": "abc",
  "created": {
    "t2": {
      "id": "Bd81c7f",
      "type": "application/gzip",
      "size": 98304
    }
  },
  "notCreated": {}
}, "0"]]
]]></sourcecode></figure>

</section>
<section anchor="extracting-a-compressed-tar-archive"><name>Extracting a Compressed Tar Archive</name>

<t>This example decompresses and extracts a .tar.gz file to discover
its contents.  The intermediate decompressed tar blob uses
<spanx style="verb">noPersist</spanx>:</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/convert", {
  "accountId": "abc",
  "create": {
    "u1": {
      "noPersist": true,
      "decompress": {
        "blobId": "Bd81c7f",
        "type": "application/gzip"
      }
    },
    "u2": {
      "extract": {
        "blobId": "#u1",
        "type": "application/x-tar"
      }
    }
  }
}, "0"]]
]]></sourcecode></figure>

<t>The response for the ExtractRecipe includes the standard creation
response properties plus an <spanx style="verb">entries</spanx> array listing the archive
contents, with a blobId for each file entry:</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/convert", {
  "accountId": "abc",
  "created": {
    "u2": {
      "id": "Be3a901",
      "type": "application/x-tar",
      "size": 102400,
      "entries": [
        {
          "name": "site/index.html",
          "blobId": "Bdd001",
          "entryType": "file",
          "modified": "2026-03-01T12:00:00Z",
          "mode": "0644"
        },
        {
          "name": "site/style.css",
          "blobId": "Bdd002",
          "entryType": "file",
          "modified": "2026-03-01T12:00:00Z",
          "mode": "0644"
        },
        {
          "name": "site/photo.jpg",
          "blobId": "Bdd003",
          "entryType": "file",
          "modified": "2026-02-15T09:30:00Z",
          "mode": "0644"
        }
      ]
    }
  },
  "notCreated": {}
}, "0"]]
]]></sourcecode></figure>

<t>The returned blobIds ("Bdd001", "Bdd002", "Bdd003") can be used
to download individual files or as inputs to further Blob/convert
operations.</t>

</section>
<section anchor="computing-and-applying-a-delta"><name>Computing and Applying a Delta</name>

<t>This example computes a unified diff between two versions of a
text file:</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/convert", {
  "accountId": "abc",
  "create": {
    "d1": {
      "delta": {
        "blobId": "BoldVersion",
        "newBlobId": "BnewVersion",
        "type": "text/x-diff"
      }
    }
  }
}, "0"]]
]]></sourcecode></figure>

<t>The response contains the delta blob:</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/convert", {
  "accountId": "abc",
  "created": {
    "d1": {
      "id": "Bdelta789",
      "type": "text/x-diff",
      "size": 1234
    }
  },
  "notCreated": {}
}, "0"]]
]]></sourcecode></figure>

<t>The delta can later be applied to the original blob to reconstruct
the new version:</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/convert", {
  "accountId": "abc",
  "create": {
    "p1": {
      "patch": {
        "blobId": "BoldVersion",
        "deltaBlobId": "Bdelta789",
        "deltaType": "text/x-diff"
      }
    }
  }
}, "0"]]
]]></sourcecode></figure>

<t>The result is a blob identical to "BnewVersion":</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/convert", {
  "accountId": "abc",
  "created": {
    "p1": {
      "id": "Breconstructed",
      "type": "application/octet-stream",
      "size": 48576
    }
  },
  "notCreated": {}
}, "0"]]
]]></sourcecode></figure>

</section>
</section>
<section anchor="security-considerations"><name>Security Considerations</name>

<t>All security considerations from <xref target="JMAP-CORE"/> and <xref target="JMAP-BLOB"/> apply
to this document.</t>

<section anchor="resource-consumption"><name>Resource Consumption</name>

<t>Several operations defined in this document can consume significant
server resources.</t>

<t>Archive and compression operations may require substantial CPU and
memory.  Servers <bcp14>SHOULD</bcp14> impose reasonable limits on archive size,
number of entries, nesting depth of archives within archives,
compression ratios (to mitigate zip bomb attacks), and total
processing time.  Servers <bcp14>SHOULD</bcp14> reject requests that would exceed
these limits with a "tooLarge" or "serverFail" error as appropriate.</t>

<t>Image conversion can also consume significant resources, especially
for very large images or high output dimensions.</t>

<t>Delta and patch operations can also be resource-intensive,
particularly for large blobs.  Servers <bcp14>SHOULD</bcp14> impose limits on the
size of blobs that can be used as inputs to these operations.</t>

<t>Servers <bcp14>SHOULD</bcp14> advertise their limits via the <spanx style="verb">maxConvertSize</spanx>,
<spanx style="verb">maxArchiveEntries</spanx>, and <spanx style="verb">maxImageDimension</spanx> capability properties
so that clients can avoid making requests that will be rejected.
Even when these properties are not advertised, servers <bcp14>SHOULD</bcp14> set
sensible internal limits and reject requests that exceed them.</t>

</section>
<section anchor="archive-path-traversal"><name>Archive Path Traversal</name>

<t>Archive formats allow entry names containing path separators and
relative path components such as "../".  Malicious archives may use
names like "../../etc/passwd" to attempt directory traversal.  While
ExtractRecipe only returns entry metadata and blob references
(not files on the server filesystem), clients that extract archive
contents to a filesystem <bcp14>MUST</bcp14> validate entry names and reject or
sanitize paths containing ".." components or absolute paths.
Servers <bcp14>SHOULD</bcp14> reject ArchiveRecipe requests containing entry names
with ".." path components.</t>

</section>
<section anchor="content-smuggling"><name>Content Smuggling</name>

<t>The ability to split content into multiple blobs, recombine them via
Blob/upload, and apply delta patches may be used to bypass security
scanners that inspect blob content.  Servers that perform content
scanning <bcp14>SHOULD</bcp14> scan the output of Blob/convert operations as well
as the inputs.</t>

</section>
</section>
<section anchor="iana-considerations"><name>IANA Considerations</name>

<section anchor="jmap-capability-registration-for-urnietfparamsjmapblobext"><name>JMAP Capability Registration for urn:ietf:params:jmap:blobext</name>

<t>IANA is requested to register the "Blob Extended" Capability as follows:</t>

<t>Capability Name: urn:ietf:params:jmap:blobext</t>

<t>Intended use: common</t>

<t>Change Controller: IETF</t>

<t>Specification document: this document</t>

<t>Security and privacy considerations: this document, Security Considerations</t>

</section>
<section anchor="jmap-error-code-registrations"><name>JMAP Error Code Registrations</name>

<t>IANA is requested to register the following entries in the "JMAP
Error Codes" registry:</t>

<section anchor="unknownformat"><name>unknownFormat</name>

<t>JMAP Error Code: unknownFormat</t>

<t>Intended use: common</t>

<t>Change Controller: IETF</t>

<t>Description: The server could not determine the format of the blob,
or the detected format is not supported.  This error is returned
when auto-detection of archive or compression format fails, or when
the blob content does not match the specified format.</t>

<t>Reference: this document</t>

</section>
<section anchor="blobhasreference"><name>blobHasReference</name>

<t>JMAP Error Code: blobHasReference</t>

<t>Intended use: common</t>

<t>Change Controller: IETF</t>

<t>Description: The blob cannot be destroyed because it is still
referenced by one or more objects.  The client can use Blob/lookup
(<xref target="JMAP-BLOB"/>, Section 5) to discover which objects reference
the blob.</t>

<t>Reference: this document</t>

</section>
<section anchor="conversionfailed"><name>conversionFailed</name>

<t>JMAP Error Code: conversionFailed</t>

<t>Intended use: common</t>

<t>Change Controller: IETF</t>

<t>Description: The server was unable to perform the requested blob
conversion.</t>

<t>Reference: this document</t>

</section>
</section>
</section>
<section anchor="changes"><name>Changes</name>

<t>EDITOR: please remove this section before publication.</t>

<t>The source of this document exists on github at: https://github.com/brong/draft-gondwana-jmap-blobext/</t>

<t><strong>draft-gondwana-jmap-blobext-06</strong></t>

<t><list style="symbols">
  <t>Removed resumableUploadUrl capability property.</t>
  <t>Added isIncomplete and description response properties for
partial conversion results.</t>
  <t>Added conversionFailed error code for total conversion failure.</t>
  <t>Made expires always present (null if indeterminate) rather than
optional.</t>
  <t>Split supportedImageTypes into supportedImageReadTypes and
supportedImageWriteTypes.</t>
  <t>Made all supported type lists nullable (null = not supported).</t>
  <t>Changed imageData duration from UnsignedInt to Number for
sub-second precision.</t>
  <t>Clarified imageData comment as read-only.</t>
  <t>Added EXIF orientation reference and digest algorithm registry
reference.</t>
  <t>Fixed grammar and consistent error ordering across recipes.</t>
  <t>Structural reorder: DataSourceObject before Blob/get, ArchiveEntry
promoted to peer section.</t>
</list></t>

<t><strong>draft-gondwana-jmap-blobext-05</strong></t>

<t><list style="symbols">
  <t>Added imageData property to Blob/get for image/video metadata
extraction (dimensions, orientation, date, GPS, duration).</t>
  <t>Renamed UnArchiveRecipe to ExtractRecipe and UnCompressRecipe
to DecompressRecipe.</t>
  <t>Split capability lists into separate create/extract pairs:
supportedArchiveTypes/supportedExtractTypes,
supportedCompressTypes/supportedDecompressTypes,
supportedDeltaTypes/supportedPatchTypes.</t>
</list></t>

<t><strong>draft-gondwana-jmap-blobext-04</strong></t>

<t><list style="symbols">
  <t>Moved noPersist from top-level Blob/upload property to per-item
in the create map, for consistency with Blob/convert.</t>
</list></t>

<t><strong>draft-gondwana-jmap-blobext-03</strong></t>

<t><list style="symbols">
  <t>Added update (touch) and destroy operations to Blob/upload.</t>
</list></t>

<t><strong>draft-gondwana-jmap-blobext-02</strong></t>

<t><list style="symbols">
  <t>Replaced RdiffRecipe with generic DeltaRecipe and PatchRecipe using
media types (rdiff, bsdiff, unified diff).</t>
  <t>Replaced supportsRdiff with supportedPatchTypes capability.</t>
  <t>Clarified chunkSize as a hint, not a definitive statement.</t>
  <t>Added lazy generation text for Blob/convert (deferred output).</t>
  <t>Defined "expires" response property for blob creation responses.</t>
</list></t>

<t><strong>draft-gondwana-jmap-blobext-01</strong></t>

<t><list style="symbols">
  <t>Added Blob/convert method with recipes for image conversion, archiving,
compression, and rdiff.</t>
  <t>Added noPersist option to Blob/upload and Blob/convert for ephemeral
intermediate blobs in pipelines.</t>
  <t>Removed rdiffSignature and rdiffPatch from Blob/get and DataSourceObject.</t>
  <t>Fleshed out capability object with supported type lists.</t>
  <t>Added capability and method examples.</t>
  <t>Expanded Security Considerations.</t>
  <t>Updated IANA registrations with error codes and corrected capability URI.</t>
  <t>Added limit capability properties: maxConvertSize, maxArchiveEntries,
maxImageDimension, and supportsRdiff.</t>
  <t>Added dependency resolution requirement for Blob/convert create map
with cycle detection.</t>
  <t>Now updates both RFC 8620 and RFC 9404.</t>
</list></t>

<t><strong>draft-gondwana-jmap-blobext-00</strong></t>

<t><list style="symbols">
  <t>initial proposal</t>
</list></t>

</section>
<section anchor="acknowledgements"><name>Acknowledgements</name>

<t>TODO</t>

<t>{backmatter}</t>

</section>


  </middle>

  <back>



    <references title='Normative References' anchor="sec-normative-references">



<reference anchor="JMAP-CORE">
  <front>
    <title>The JSON Meta Application Protocol (JMAP)</title>
    <author fullname="N. Jenkins" initials="N." surname="Jenkins"/>
    <author fullname="C. Newman" initials="C." surname="Newman"/>
    <date month="July" year="2019"/>
    <abstract>
      <t>This document specifies a protocol for clients to efficiently query, fetch, and modify JSON-based data objects, with support for push notification of changes and fast resynchronisation and for out-of- band binary data upload/download.</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="8620"/>
  <seriesInfo name="DOI" value="10.17487/RFC8620"/>
</reference>

<reference anchor="JMAP-BLOB">
  <front>
    <title>JSON Meta Application Protocol (JMAP) Blob Management Extension</title>
    <author fullname="B. Gondwana" initials="B." role="editor" surname="Gondwana"/>
    <date month="August" year="2023"/>
    <abstract>
      <t>The JSON Meta Application Protocol (JMAP) base protocol (RFC 8620) provides the ability to upload and download arbitrary binary data via HTTP POST and GET on a defined endpoint. This binary data is called a "blob".</t>
      <t>This extension adds additional ways to create and access blobs by making inline method calls within a standard JMAP request.</t>
      <t>This extension also adds a reverse lookup mechanism to discover where blobs are referenced within other data types.</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="9404"/>
  <seriesInfo name="DOI" value="10.17487/RFC9404"/>
</reference>

<reference anchor="MEDIA-TYPES">
  <front>
    <title>Media Type Specifications and Registration Procedures</title>
    <author fullname="N. Freed" initials="N." surname="Freed"/>
    <author fullname="J. Klensin" initials="J." surname="Klensin"/>
    <author fullname="T. Hansen" initials="T." surname="Hansen"/>
    <date month="January" year="2013"/>
    <abstract>
      <t>This document defines procedures for the specification and registration of media types for use in HTTP, MIME, and other Internet protocols. This memo documents an Internet Best Current Practice.</t>
    </abstract>
  </front>
  <seriesInfo name="BCP" value="13"/>
  <seriesInfo name="RFC" value="6838"/>
  <seriesInfo name="DOI" value="10.17487/RFC6838"/>
</reference>

<reference anchor="RFC2119">
  <front>
    <title>Key words for use in RFCs to Indicate Requirement Levels</title>
    <author fullname="S. Bradner" initials="S." surname="Bradner"/>
    <date month="March" year="1997"/>
    <abstract>
      <t>In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
    </abstract>
  </front>
  <seriesInfo name="BCP" value="14"/>
  <seriesInfo name="RFC" value="2119"/>
  <seriesInfo name="DOI" value="10.17487/RFC2119"/>
</reference>

<reference anchor="RFC8174">
  <front>
    <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
    <author fullname="B. Leiba" initials="B." surname="Leiba"/>
    <date month="May" year="2017"/>
    <abstract>
      <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
    </abstract>
  </front>
  <seriesInfo name="BCP" value="14"/>
  <seriesInfo name="RFC" value="8174"/>
  <seriesInfo name="DOI" value="10.17487/RFC8174"/>
</reference>




    </references>





  </back>

<!-- ##markdown-source:
H4sIAAAAAAAAA+196XbbSHfgfzxFDftHSw4pS7LbbdOZZGRZ7lZOe4kk5/u+
dPsMQaJIoQ0CDABKpnv8nXmIPECeZR5lnmTuVhsWSvKSZM6MT5/TIlCo5dat
u99bo9EoqtM602P1Dy+P3qhnWTFVJx9qnVdpkVdRPJ2W+qr1MtFJlBSzPF7C
h0kZz+vRosiT6ziPR78v49VoCk31h3q0/yiq1tNlWmF3F5sVND89uXgRzeJa
L4pyM1ZVnUTrVQK/q7F6/Ohwf6iePNx/GBXTqsg0Po3SVTlWdbmu6sP9/Sf7
h9F7vbkuygT6ymtd5roePcc5RFUd58l/j7Mih3E2uopW6Vj9WhezoaqKsi71
vIK/Nkv8410Uxev6sijHkRpFCv6lOczg2Z76SVZCD3mJz8oiD58X5WKsXsRV
vYzTjJ5o/GusptB08d/m8qbW8XJvViyjKC/KZVynV3pMrRGgo+PXZydjdfbi
GNftHj/75fUzekyAwMcvT56fHo0u/vLm5JxePHr84HEURWk+d71Go9FIxdOq
LuNZHUUXl5p3bRpXWq3KAsBQZGpHRtvFR1dpoitVQ8t4mmZpvVF1odarrIgT
BZBUSXGd448oLqcp9Ftu1DTN8X+wX/GeUheXaeU/UvBzFmeZhu/VAJFgMKSe
ZnGuplqtK0CcNFfQRBUwbslT1Bbh9vyJI7rZVzRzBMiuipMEB0iStIYXcaau
402FU5+VGvCIBoxnM11VEfYBM9yoZfw+zRewx1maa7XUsPMJTbVS12l9iXNS
hD5xmfDwpf6Xta5qmhEsy00EBq7UsihNNzQ04ON76ommDWiW5rNsneCYl9Br
hn9kcbnQbkqwAThHfAOgWMIXana5zt9Xame6TjP6FoaTZX9fMUBmACU4CzNc
Opyt1QoQe5eBzDuKn1W6vNLlqIL9tV/BA5p+sdJljF8DtqfLeKEVI1Hk2kB3
5ewSsIohSouG/gEEiFu0GR/T1VDVcTlUs1VawAQAyVelpnMeEe5o7wnPL9FZ
Hd9fxfXs0pvFHmPuMk2STEfRd3ioyyKRFTp0eNZAhz/+sIfl0yf1v//nv3rN
XsIxXeilzutdVcznsCoPXaIGusiG4QxhxwGTrwExNe7JBuDASNvGAtqiCjeo
voxr2v8hj4UbYIaYp9Ar4Yo9qwjMabGuIzx3KREwQGHe0zU0LOZ0InkLza5X
NfcBdCeBU2MQTs/n6SyFZWabiJAvrXkhscr1NcHiPm9rbXAeZtFGD9jXvLLz
qyKHvD6GqDtgyJchxHffqWMcK6cH6i3sAC6etuB5MVvjzjJqACtAUMBODF6+
Pb8AckP/V69e099nJ//49vTs5Dn+ff7z0S+/2D8iaXH+8+u3vzx3f7kvj1+/
fHny6jl/DE9V8CgavDz6i1C3wes3F6evXx39MsBZ1jjLRGZJGATbNZW9BgDU
SLyqCEjvrEynvLJnx2/+178dPFR//PFf4LwfHhw8AZzmH48PfnwIPwApBWpF
nm3kJ+JoFK9WOi6VkNVZvErrOEOErlR1CRRcIToDUO/9ipB5N1Z/O52tDh7+
nTzABQcPDcyChwSz9pPWxwzEjkcdw1hoBs8bkA7ne/SX4LeBu/fwb/+eKPzo
4PHf/12E5ORIDj7uAh6s43jF3C4F3vd6+rs23HLmvyjoBfIz2LA1yBi4Z2oV
w0GSA0rU5lwQnJs/hZOllRAmZO6fPg2hCZPMQ0NDLGokGsgDjBXnPjOz09io
t2enfBhgAuNU1/MxTCBeVmOUscYiYzUmv1GTba0ngIl4rvEg4hwIX3U0AH5Z
rPPaB84AGQqcSugSloyT5DYAEfkaEIwZEBIIpGcgaWiRD83HBEwhktKBERy8
OSd6BV9VEbTsn/6kQfR3n6opSBGKsHiqzZoiXpMZDUho9+rwLElT4fXQdLJG
hjwBiaeMNzDR0zmfZ2+u8MuDHsiaQJSJxm+HYsqiVu5Rd545HNZCxAVNTAFp
mkxsMOvcEBGTruJsLQyDJiW7Jd8SglaMoI2OItvWwA62Vy9XuNWEyTcO4NCh
D75ujJRQXE4UIQKNCtykjmWu8yLLimuW0CwfQmwQQAVnk2QdXYpWURFL8/EL
ZOF7LEqdpx9Beh+8BZa9gCMMksVv/yNfZ9kgIrH6SIHgh7uYpKCQiCCGmwtc
vAQUpj5UBZ3QTs9qXVeME6wEzDLkvSIxM6dmcRJOAbBBINMEN+pAf5jpVS1z
1fQ5nH487zgIU3aQNCpm2iKEU1/PQbA+L9blTDO1quhjmqTOZzJrOHksPA59
/EKxu1jVKYBKkwyBzLyYUwf+R7Coc/qiMigJuyESOs6+CuaN8AJBcw2TJ6Ef
1j0DqRXZmDd3kDbWi0te2HUKnAmRn8F2WRQwNLAwGgDoMos3JAXHTA/x+CHi
MUyrGjoA8arkmRcoXEyRzOMnyNoMIYI9RoHlTMcJapsg4g7Oa5TIfn0X7Dwi
91InaaxqbIaExdOxgLQwQjVACaIOsW4Gwmpd41RowGMWss70LF1pRhEcLdiM
pICB8qKmzw3hZPnKCVYdi/lTmdb6G6xmRVI2bylAHURSXNG8LJZ3WxPryUV9
yzUdseB444KMgPny9OWJrMv2QejIkiegv7Ss1FXK51KGsDN/Tow2YXJWkUg2
AKkpo1Nf5PdBmQGBDr8MHn8YgYJjRLzwBSo9Aw8m5kQ199rCpCkuhzA5Ybn5
y2FiBPAuqMggFirEg0GiMrxHOsRZp3xQJ52bBmxY7y32hiFMrvJkb1mN6lzP
B7t79Pm2Q9ACjFMdQtAci9JwI2w87WILzphGACADFzPCrdFl0YsvU3hzOBg2
H3/4yFjU/uRjVSeDG+iFWQLTTrfKEE7PrXr1dSDlqWserNwon4VGwWZO7kIn
A+2xuXLQIm9cNOmaAZVsY8aaDg61rLwlw88tuNGFB2WSzucj6qiNDdMK3/oY
UQPywwt6rHbWeTpPYQj8uXsXustL5IV0EJk3qGd/MZxwLRvSILA7j7xQ95+F
FW4D74QSbDfwYEvLXcYfhHHdIPzBONgTiHAJjwVfpsv1siHvse6zUXgMMs1s
n75nw0mh4tDMYu0YsJQzViuqQFgjeWlKXZBBkGRXsRqwvG1k8lKjuKdFDIwB
T4riF/xkQF+f6/qkLIvyJvIRJzgxlABjVa1gg+bpjIcHubBWU2D6uFEkY8mY
InaxUE0GjIIna0As/OAkBzQifLozlPP1cgqzBOhq7oSFTjaHxHknH7fwRGFa
Jyz6Ath4IU2wURct0N0WbCwWdYBuG9hKM0EcVmTVApYM+COrNAAkCet5umRr
4ucAkHEF7dwrczYn12lSX05QH51c6nRxWU9EVkWZui3UoZVardIPOqv6oeuh
ys2I2QXdXtnottAVfacNYSCRAsAeXP0ODYlOcz/5EC9XaGT+61//+nsFCuYf
0PVgm7lkMFZ/MI22+iQ8+uHw4eHjx/siAvSoHtDuV2oATUgivr/KFyI22Ee/
r3Tr2SKdNx/VyBno0bvOQZ2KcPtRu7vzBT2/r25xuVNg7u7YF3E/s+POV77c
2T1yIHT0Db3oHZtEtO6eGzLX3fu2EuOdBzYcs2/MhgximviSRnfXTkr4Wl2H
HBl6Pdh/+PiHHx/t77sGIT+hNvv++5BcwvvHB08O4e2n6BMeZjKSGkMvOV6a
RpMo+hPb3vpseUxcm5+pHZAEE5H5QHAJ7I/Otvtw73BXGfdQYghjaNjyHFDO
IkiSEtphSKxic6bYqSdsmpk4A/R0w6LGQtfkUelYZkXeqoYphgdRk2I+r3Q9
Iblzkul8gbzCs04i9YwzNHJsvDWrYM1PrV8sytIKeQA7ywpn1oYGaYnzMIZI
byXVCvaHbAOILsPIc7UZfwgbZOOcLFVKxyDj0fffw9oAtiVLn2R4qmjlEZF+
7BI+X9e6MhAUAyM2R3JOrJdh0M1vGUzcwniFsR9vLDaPXF+ms0u2W6FDYFas
cE7wvYiMO54bQEzVsAfEPedpX9fw+U66B2KOTMAw2wzIC4uIqN//C1rdZH3+
vFBoJbXbyjSwg/E6qwka+2qHGHDt+S+8r+HDe4oRYhtknMgm6yRD3GrDQGnO
CIEAH94VDCEQ/gZ64Il9FjwQHNADA8RN1Z4E+VCjV60FFQRK1atDMEjm8Dcr
DPL9dlT1zMjQ+aqoiCJsG2C6qS1KGs+w20UkZmSj9mBZwBFAO+mOQ/9dg/9o
uVaTJF2ACDW+N3EWfbLo2DfVZTwZ+r9Ghz88miCFE88wE4ZJYqnPG0tF4EM6
sy1KKp4mSwzYxEuWYasj0qEtmUyQAMpTEFmXNVsQ7Isr0pq0xUO2blpo+LSA
0SmeA1Cs7hr5pFAZUgingJlEbCRVGyIzwS1GkJgtmwxJyHaQFHsAsIjYEmlL
70DONj6POJutM4w6IGM3LRYdBYCpPHTUgptHxW47jSjt5AOBnkPTEaGaQCm7
RNpuJCsXO4cT2Zekc7N3rTYOgL02+7V86ma2a6HFqkzDHRqJwA/osiD2Qs6d
LsTzjBoDtSPUb6x++5XikE4TNMQg/Aa/vduNGnoVudTZ92O5obA340wkbEUO
adgx9EEW1y3IrkJkZ52oAP2mFmUO+pCJ4nmetKb6bqJkK+Hbo6s4zeJp5s8y
UvbwTPhbRA+DJoLlQ4viIeqw/amNxMyUJ/do8FhdxhUoedmiACXjckkRcZbi
IyCPXh2pwc/Y6MU6Z3noApg7YscraFsNAGQLAGYpZMYb05IWQCGHB+gPZSg3
feNWgHCEy5OOIgPL6x6cC4gXO3p3nbMQMai5kYBL4ir0fFKeyzcg7oWIYKHM
GHLAoZhunNwo0hmZkyjcwEZ4scgHPzFaMncOShyTHYi4C4SA7WkYFBQ0prgh
ojIpWrEwsoGjFj+sWJUnGtrX1zXbONiIpYVn1qkYPz1ex/QX1xISG1DleaMM
L0PCK4xdaBb2RJOodIZj0pmMFWolFLaGrMtwV2JnYsxmHyyRMzgo1tjQHgdl
VF2j3zjXIsI5OYZcexae4qaEwVqIaahUn3Dve8nJmz9xp1XoAKEcaeKIboB1
p+Zv4f0oO3GElq53rRmo9rAEjgV72QAPkVAXZF+l1YZePtlk0r0xBCzG3R3y
4eB+7ODG9a/Ua/TLXqcCTZwSPsT9sKcN+ASgDuiEaU2PiUizjoTf+IuWjfJQ
Idc6sUC3yyKlIK89Fy9yewmnolkD+Hm7KyVBRUXuRgesZpMfnn4cgqjmeYoY
y/ZMJN/pcrmukYoOJfKjQopBlm36egFqaK6YljLe55pgeYkqybAJYpnHDJBG
nOMYOyEUowlaJKUNxHFwGvNn9xQZ8fpkQvz3J2xgpEFGA2vHG+LOvM+L63xP
umND4Lb+fqYWt+4Q+ABsQbxNcsV/J38+feG3FVFi52D0eFeFFBKHxebypbEF
8mc7x6dvjtTz49H+/mNxh1jZQSI3gGddFtfytVtDdVmss4QMlgXMQSf351m6
WhkHV1qtMmDKsiqMQMflXBzDhulwKc9FYGueueuYOAyGbSZqh6iHtwz86iJd
6tdluqBID9ZXUoADBqYSYGUlZhKLVWXIwU9vzsNJwAM4E0DHoS9csR0u6Mjh
HbSXL2+FfNwU1ECAeg1MEubxivS9AcXW/iKPcbsS2J4lyn56UWo0adtvi3zR
+bF53vs1wH9dGpTiTxtbIK+xhwpZZMIxKbwRQjo8XGUPlHxMYswcRGBkoaNV
gUE/osyiA4eCXar1dMQdIyxnKfsZeW5Aikj0NBJmA9GhI4pIJ4yXtopcqGjR
WHE4bLBH4dyQDI6IkiGwUtQb5hlJEmTvF6LNQTLmvMjXPuHkgDYxrSMvLEca
uJIvMW76RHVWEG4hrZOEEEoYfgc7fQayXZCFKdx6AjrEKvQM+jgZdXBS4pd5
8QajSSrchWdFkek498X8OTBnLXI9CE8BdTcGILLQrUDv0mWcjRHQSxDoyJ8h
kk0i3kwb1JwC+Yhn722Dyte0K5SE/VyBIfkteHeEP8h+YIO0ZK634nXg+FO9
KYSfZOlc10AthAxHyiYgtNgnahBuIcLbrA1G4Jyg6wdBLWTdis6IJa3GpwkI
J9KSw9LOpH2kPNUQxk0AJLgik2vhgEeIZiWzVBx6lYUFYZuNRlulK51R+Cur
GxQdTW7n2mfXxHzRhEP8XPR4L2STxATKE9q7ra5pElxQmluAZk3HLOqU5cwg
AZe+pzhfCSl18tuvrCj8FiidSB4QGY/MDog8gdSmEWip1KvCVzsZJQloKAOL
u/gpa6frcoWRc9AhTwEXB30O6mI9uxxYUWpI2DOHVV9SSGVdeejlB6AKblnc
kCOJexajikSDJJPOVRjVgARpREsTz0lC5wSkQ0D4yrMxWZs4pibQa9C5YUp7
gXR7ijqptTfoDykeq8D3KMEIlLIzgUZvvVlG1uOLb14UoJpMnE+STAewn2Wx
oc37tXvTGuGHp5zhIx82jqOzohDMNhIWgHpMWlnnsCUvoM/FOcdVWtUKp4sQ
wy9BjT4zrScNZ6qDUAs+AcmROZG21Q0HkIrXlB+F5ssNGSFobThBWbBv6RBQ
20bGnAEfvohTTPaSV52fwfjP3ZeMSZHycMnbHuBNCNyBIM+grfDf0o/jH3TT
xzbmZKT6IJTDDi6iajTVKCkYvhWaJjwOe0/J/LvkSYk5thTY8IkwBjlL32tU
f9nkw2sksBkkaFgNpD3pVEs6hNZYtAZFPTOefDxvrMPIF4hEnJ7ivmAim9o4
fSNTwPeLdVzGQKlJktMpIXKSlgzIcVPlX8TllENBs4xPiFX2pnrOIb9IwZAu
MXdBa1fuzgtPFboigkbUBRqhmKlvDHu5jK80zdmGFng0x8QzG8P4saiVdHBZ
PTUz9Ti2x64dfcPuIlE1nIkklS2OzcckE4pPkcMnY/UCDs+rItERap85CJKw
A7sGNMjjeQw+GK+AakoOl4+lYp8wOJs6xYrMMjzZrRkhkXeOENwiqwgw/EO2
PVmiMRNYN0byV0G2WSPRDLkR8XrYzF8AISP/3PYfV2IIdfyec2cmEvZ/mrA9
P46sqGmMxrwUWHTli3biwLKZkYbbix0PFnRC3se+FoTjfvZGt3r1/+XX/9vk
15s33s9fMbkeZBaeN4RJJ9kNRVSyNkhW78huB5+5wZx5UMImxh2hW9hGQqfH
YZwc8x8y+I3DmG+ydEvAyrgR9syikXvbDPTl9xmaK72AWHxKYZhjP/yTc4fs
hhm7A6Gby3ONw1SXxmmP3GkfoxRhkMKghI/hgTzq3GXRJCVvCEKYvR3iGXF+
m8qKQWFuK1MRQJPjG4a1wosZ3nY9J8nIS6o2URgwKRLbnTRnXMc8lsfeI4f0
HpVhoteWrynqYIBjyLuoJT0NMPX4Cv39kQiUHo4bTSohKgAnAomqLjmVD84G
kHLDuSJ0XK5XLnqfdbiqWGobzik4CJ9XnrCJfUckAFfmKJIPM0aqR46OxOIo
floDUJZMvjH5Mo1RYHWIqpPdYUgebDKYS0z2YceHqzrNzWrvQo49YFkyIt2o
GXaRGfWAk2lEzDVkWhZAvqOU4+oJYmK/2WPtxJiMOqxNIDuul3E+QoMRUSuv
ucEi2auheHI7d5pxU1w4GXP9vFDrijqVRKCZGE8jyRPqdB8bJcN1zhqBUzZM
NmbzNKHQ1c+ldtamLoKafDehlLz0wy7ucpFdYbgRu1bwLHWcHlqQAN34wav1
tEIinvuFDtrsMBBhZlSnglKr0WdfRl11Izo5KazuqMP5FZsjT/6GkMGQHwL7
xNoA6VJMIbA7C51TSLnAQ7ZHKnCcWl2o0t7+RLQ/8qV2kS3XJgHVKg4xBUbQ
AUUjNh9wlCJiW/7Dcb8SqbbNfLOarAl5321Yfjx8Ic2EwjoUSBKz96ysNNQt
E9qLPkp05uqSiimgjzKviMxg0QMgJ5c0DzLGQ6/pRyqVURpqFNkkK2PeMC5i
Br4xJQi+m8R5jkmrJCYNBYPFOotL8xUuS4KtnT6emFRRs0lFHjFI8YxZgkmA
YI8qAR5ZIhNpQ79k28SdZNAlx5AVoN0lWcV+vrh4ozRxm+Y+Rmav/MmRYBJE
JwnuiFC30TVby9mA4J9sEtHoiDHHtEzGSl4tgutDneKMxDPL4LCb29Upopv1
svLRsIBt+5JbmE35FLEI+WzdZz2GgOgFq+CwktkckjGhKgghqq8B4OKMdMzZ
AHI01fW1BogLb7M0zTdpSwWWGYencT2X2BTsIJzlEPUsixrEDo0mFYCuwrQf
Az07/kbNNrNMs2ZXk7N+GCHCLjV6MCpLAKlVT4h+Hg3S/CrO0sQFzAwYlyRM
vkvEPOpKGhCqVXtOaJcKg9G/uKzaFJUpOIEYV1WHieAdIbINMysfPGTQHBUT
OZuHk5pMYB1OBDloTUWmhHXiJy9tKlNHXmzg83QlYUycihdCb0MXp9qT9F3c
l4ei36OlZdIXoT/xVGqjG3lroEFQcGDCZEqvuGikSU++wQRXv9V3/FIyR6iR
8/D2AKFhX3EqIRnayivRX2Tu3OcObjdwR83FAjh0A0U2kEZQEUMfl8lMQWwg
ZztFn273UpuZc6uvPHXp9FZzlwSbYOow3aLUR2hm8pR7N3krQhKromm68gBa
Ag4YfkhDeDpDpfFxamx+MXWviMVQlS0KR0jcSpH/kdQ69L345H3BRSVcjSiI
uuWRvRwaYrwGSCJvoFnbGxsXjDG3gLx9m3XspZdKUyLqWVFVG8FnLk8TS0wA
MZUDtYP5XxVKzfLZUFVLrCYGosccZraLazjY31c7lwAifGrbUcKPaYYnl6JV
lrAPsAxU73ACMjTTYZNFyLPyU2JFvsDQOpstw75V+nmtp6se2yNHLlUUQAqQ
AeHCBfjtkfKdFeX5Kp7pDuH+gmT0DLEQW1gLpeHZROC6k5Ors5+eDcj/kKjB
oow3tOV9ecWdh4C6J8Llz4FFoRWACBeDS0DWtSjRn9Cpn8xTkqSwBywlx1Ue
8tZAbBNAWyDoRMTjnOGpxq00/KOdL56K/dSwIUTTN69+wuH+4c3JT7T5F4Yw
s+f/+Px8VNWbDI/6B7M+mrp0NfhuTv8GBHQ4BXUjln7rHtsQzh1gMumMSIbp
4x4NtHopPvyt5IFaCnyc01+EXQ70+PPLN2ydOH1zccwSPZ4doRGMKb0kobX9
dhDaZukkBL9AvaKwpnsqXtfFawrp2boSbIYWXoYFB9+w3S6DFTryhIbbkhMN
C/RSRh1RQ3W8oOmTiqRrmeOib5Xm1NpyhGy95B6pjhtppSxgDIxvjMNUWKx1
vrouXxtCoUuUMt+TnJF6ic79cgDZPZqagf3Usn7MgLgd8/fSMM10/K45rbNS
kzAhy87DmWwp+dxyBf6OPgvTsHjQpurvBm/WAWnaHUTybFgvQegMnghPl7Iw
bG6i9Yh/BYHjpRHvRXcXNFsyIxIQWxnBCBlmcF/M6JUIKTA7kAl7q2kE4mBI
3pGmdxYruWOhEjQJ21RtL9dug/HNocfbf2sjmiU3y5ggxGBVOVu/wGbr8Yr9
w6Wp/69wxPrA+pRjGHicS64qtM5dLQN6gU0tozX7y8fuKVcbip3rA7SzTCwk
gHT5+wtLKbGmLD4xQKZcQDHx9RzMdvq7fzzDdMgJxnOQVtygTr1H+oaD2ard
uPVgEir455Jxw+TrESvk4ggMbKkOJhhhFD8q/Ur5jdaEtJM2jjr74V0tImwQ
ejDYTFbtfpY+ybV8G8d8FbtYWp6/JyG7RTwnJ3dR2kR+o6exm5mzIjQnLdFM
Bvfp2DV02EZyV2j/lzA+xkf09eF0PCKTF/mION6cUBNlXUv1vFbCE+NpZXpL
zOSHBlOHNPMyob+hp3lhKnJepTO/139Ki8zaHjlzEysMpzlxa96ALaaFe+6c
9Yi8PoU1C+7MYRzgege9JJLeqh1ntsMHQ2Okw152gWpaSFCKDcMCZwLfwa9p
kVEFgvw9tjXwoV7xh32D8KKnuOsJhbLtIkQHVAntOcGQ3tNvA9S8SLRU6h2A
+lZ67fAn+kpK0hdc695gI4uFhGseXUMpjiqtGKo2uywqnTeIm7EKdW0d9GA3
b1kkVIumK5AFJ8bvJVDb8/7KSWKqe/biWD148OAJNajqeLnqzVOlCa9LMiAZ
wzFGiGF6qqW4fYjE5JjOs0+TSaeWrew6LnKoIkkccHwBkNuiCB4ohxDN00Ym
S+qCDeK8etoHgWIX9r/N0w98iP1ihgyzYlZzUWBPSdn/8YcfEG33Hz18OOjV
T7i4XkXMIq6KPPY0FBfQQ7KeRExxadPYjAZq/qUpSoMWPmiwkEDpqyKFtstp
uliDtEJGKraL8nSlyi9Fd9tit1KZ555ap8kNycW6hNOHccvq9HmISMV1rgkh
F7frBDXUVX8v9McrnxuE3dAciKL3zAK73/I9D7+lAzjjL+Pfi3LbWpbYwFID
FhcQ0UIi06ImVgzmUdL8hlGwwReN0h8cf2SD4QW1GpzNC0cAHHlJvrUeiK4w
mJ1g6Ftq2B3XZxTBcHmgrnkRBWXTWMgYwJFAz0SfkcQeIzoprYNEAhIVqcaw
JilcbetjeaI6exvgD0N5yY5o1WphWzwjy5tCAkJRAwJJyVhuga1Vx6EI7V8R
Tg1nYaoCmmgEpE0YJLHmWIkF/88eEBA9JxbbKSdcMNcEVBgca02AraLJLSFF
GgzDqo7LlvUB3R0+TLZMPvInrz5v8lHDcIhTagLupg2JeuFx4fXGMe6kyFyS
3yTbeOEPOJa71cB7EXkzEvYQqz14uLf4yDZQFOrKyoY5iWXHekjZvR4I32Jl
MYN48WeKWzfqJNJmOVlbc20lp63b+XgJ7PVlqTVNkFwmcSSKQ8vrPpQx4zAw
wLkfm65eV/PDM+TWejV2xZ5+/XXgjwOslMo/2ejBAdCeeDqjijYDXoYr/1Qf
2L/xGx7de4RNADWpj97CRdBI2wo3v9qHyuuFGiHnwJ6qtNb30zzRH/Yu62Xm
9UPNJFkclYsY/jVfG+ENGxzuHz4a7T8Y7R9cHByO9/fhv3/uaE+jknzhvfo0
vOVMs2JR7PnlptrznMK/m+d5ODr44WL/yfjBt5kn2YL3ZlW1ZaIz+PfNAGr/
fhf5T2QBg/rQxzWD0SGyual+B6g53I6FVIAqHCqi2kkoTQ7evTMllG5Dp9Gg
JCXn4a+bKLUpe00uF48ycw0iR5wtHbSKTBedjW7B+AK+04x/PGrYE0yQWuUJ
aWhPJGGFzIs526S8grqRxOd9I3+2Z2WUybW82qFo1Gun5K3pkW840ASV57rG
fCSS79d1MeIYA1kI7a2luUGyIXOd6YYMneQgxBUv4wWI31i0ppJcXa9TY2mq
WvEcHN4vIS+DdU5RKS9oeBelcOryLQy1tzf2WDbQDHmkwFvgMy7QM0QA4XBB
eOC/j6lUKQoytlYcqYUj9iSTHsMh+PbyJIx8UxKuFRiNqPu4NpL11/ByNLbB
uhREQKbwQPzCFVUoOosWd+Dk51p4/SKCX+LyuME+6l101G0ZbcZOHzWeOFGt
kr208oxko3hhrhgzZsurfDvCQg4xqauAw3YGy3QSFF+mEprAzt1OBwj00h0U
01sH2veARLctv91fSLGn+HZX4W0qe3als20asr96ajwUtzgFIZRmmhIlKxEL
pYsAlsL7s4LdVFQ15vjNWy/1sUWc6R4IBiXD+/vKOplpCnvWx50mUitPblAx
+Z3ixEDqbPInjGuPekAUgylyUk7YVRCQqEyFi7XEl+YaNoRLcqWyR6TIX+rZ
+2q93OoX9jLnyKxUYmiI+dKgixf9LQ7tHkuXgVIbRlMNVDQFOvDv7O7tr3T+
zUhVcDa7aNWNIt2CrBTHTSxnXKhsbA7eaAj7TjE4T9TO1OReG6sK64NmBzDB
wQZDPAJ0/YmMDxndi+byGNTx2fHowaHFgacc1m1+eiGiaLW8o0WBKMLtVzbE
0KL3YrKn8oG01Ki11KF60mi4Z0qndyz+yV70DCdyi8Wr/sVHd138h483rXz/
i/f0zx/bi2qd7KcRECBvUdgLEIO2LEoU5vznIywINmRDOpYgIig9emhL2k03
dzXC4Q2jd8Pvw8O7AeMB0/H2KpHxqA8fsDgarsGRurAWGRGxEvSgp76/CltR
YIsIHe2UrKPWMy+Hi1DMI6bdakv0laQLbyAjaLip3FWDaQscX0mL8dSTLu0E
+W2nfnIL7eQ/mcDdAcLPZWWNKtffkJkFl3z0iN5B9uGR/9NUDKsoeh5vsTDu
qfq6sGnG3wj/C1PkaQfv2zUFV+9hrYtnt/kea2KYMHpcB9Vipuokbf3f+m5c
ZLuR8WnZTkYXofSz5XTvZo5ASDcJniRsSdiawbo1hY/hhybjVfTXmKttiu4e
0b3EnmrkJZBytpCtgxgA6PYhRl9XoPMvKWkfgK8WmtO6w+UzpbqgSHuQ8uJO
Sa6ojULFJ/bvnnVbI3Ux8sgk3LjDJdgZbo6tJyNp63IOMUGH7qJDr1QLFSRR
yUcIfmezfNLbMntzu06wYjkFpIrT25GcEEpdhjk/K8y9zWq5pihyCt5calDW
Nk9t+SJO5COd/ArvCaagc//Wv+AmDC+5pnPaXr38vtn6NwGF04xNxSR3nyz2
x0xN6nJYcx3VODKGImNRQgRvX0pLVdk/g/vhGoMM8KPgPPN+O9yhXCG3345S
ycXFfNC/kSEkHJdQwCS334pUuyVgOWn77cXdSfQNKUWR6qPL7pKG29FlvqvJ
KdRfTkJ7ZBV33g0RZTuBiUay1i9r2jApkiajHJOj4wzfGTZCAuXuTYTb7kEn
9fYA9i2pd+tKqi7qba6hqaisyz/ileOIyohy6pgKEdvLxtmlOtd80xYD9ntT
5dyVUqCDwQVvQXalCzuHdEOEqFNSRr3qcIYu9A2O0DQhZ+Xg2UF8OH0wG9Ct
HoOuAtzWp9msYg3/58nhX1yMF/8ylajNVXphTWg8Qe8aHirBbjbw493WrowC
V9uiAomYWgICn9R0/owlowcIFyOu35Q9grJ+c19KeJWJPOUxPedup8fuGTUL
vHZVx8VC9EIAN1b+Q4FhV3sL1PCLBmxxtQfTw9mDvb096xgc3jznw2895/bL
9syTh/qH+SN/5vR/9KV+Yuy0FA02oguHXBF0Q2wRmcSs624cQTnASscx6LbL
KZb04IxkUzGsWcrc9Bg6bVBgSOcb7jeyJhK56t5eZKr+OV0Zt1KDCLi4Cgom
Qq+RF1gBg/188fIXewnLkNOeIg6CpahqSo/inIyvFRTx8fOCIvzrkL5xSMS3
Cg+gOIbP6Xx1WdTF3u+rbUESFHtwm3iBDid+QCKtWa62QsyQhBFGieDeEi6f
EZmaQl+EIUkfiggpfTI/jB9q7+qoG5AkpLZu7eawH7tR20EN/vE6dlYqjMK6
6aT5EVVexT6M6/QimdgwGNQvraVsBPsoJrb21wQzJWba3TdBtaoiz3hm/NGV
VDz9NvFLdkLwkOyUdz7D/08FNt2aIvxHT/TW1OVbhWD1Uar/2MimZ3oWo3cB
TwEXbZdiQSQ4e8czUH2xgBDVQUnrqFX25KsRyBAkQiCTxwezH+fbCeSii0I+
efxg/+FdCeSJd2n47Uhk6GUAVmLjqBpEE90AaTXDC5siFKZMOIwYigKi6Vf1
Cilo5G3R1yKI69sRRDepPixtbtbtMVUOxTrAAIFk75lY33gmvFs4by0pGP08
DI4K5IdWrFWrvBxaeFbZWurTSe6ihEuZqDovGCgyyDA01jOvOJYOY6O+2nFb
dx03/SB+sn+w/bg1riC1Esnhw32rrnQyQZ9e34oBBriV7O8fhG9tghI2oPSB
4PWdeE4PIff4Tf/su5lic/KH/zkn380om5N/8IWT38JE+yYvf727Ew3noxwU
OavUjsUetxV2Xbu+fhrR7Z1S6w0LUV+lCZbL4jh9r+gb5ejN1yWZl/1DGNkS
cFKs+JicDKyZJurI3Bkfs7+uKXA7v51v8Q7cd7ZgH94DRWZqmt7X4gZJwA34
Zts+el9kyT/xbHxKbB191AZ+dbQxdKV1Ve6t6bQ154fG1q9GHpMudY3G+fHx
kzaB9BfSIo2HD+4miVw491csBRc7fEXW0Wos+J6jMDK+KFdJ96tgxyqAChl5
74gdnnehG6SmzcUXoIgojsb+nqDRecbXowYY+dWwZdWFLcEFdtt5Kl2/NuIa
ry38IcPq3URZLBG+ptCj0N8WRUd4Tat5OWs441C2l+rDx6/PTj59IqIV1CNm
X09EOIiF+MTMxsTuTEvsA466XlI51ig6x5tLsNqrJY3hlVdeN4TwM/pYkzeW
kqrz2pRkLGUAJK4ikNMU/WgJbxhUXKRqBZU9BcGN6s5i1ClmUbBfE2+BEMem
BGClS7pdxEt3zNIlSu2Fyx/HzRlGreoVQzh2lXh8V1xQwaa4ST0F83sY+dOm
OQOzAsjCUOkCFQE0cE6L5RSjeuLZ+0qS5uui5ruzMfidZEmOoG2sQjy0XsFJ
zHen4Bn26iCVqOza2o5bzH5lwKN7R3yclCLtanFiOkKzug1uItUa7thJt4VD
pckJRoWM6QYr50om4yxxXIwttpVebSkeGPU5+96x1iT5mrxtt+NT+UceboQa
FtVOHUZUfhhvny0zKcjm/Ne9yOAwAGM2jMWQndCt5IRATmAoB4JBY4g4oQJe
HFiclmasK/SYomW9Waco6iqNwvmX7dpE/sUF3n2pVSHTlgsfCGiU176M31P6
e4g3mJLhldPci06oWp8UNQt1H5PDZNeVDG3sgCy50niopW4Yab/IymThXLS0
A3ulAhMMuJQLvOQ0vsFiBxdljEPA2bDEwVS646vNOLsE5d/K9xlQpYRK45UQ
dVHS8KDSYbWPKymLgge1yAlOpg7ZYG/vPtU/iPHuxwKVPXPOkezgDZw8EN4v
Qq3hP13P7q/iqrpOBuQ3l2A9m/CMpeB4CeaG0ihURAt396Qkj7viZQg1Yniu
omq0g9sg4qsf3MTPNhWMD0Rl5l/6Ye7IbCqnHKvgvmOPPbmhkVb5sPX2ryij
Ks6BoH1kUAaAB6gMfNhysZYiw9suqfFe86RIr2FdLIsjXtfedDiyjcZqbKYR
0Tkg5Hy5XiwyrJdPcoQ5M3i7PXDq2gaOALYCjca4npXck1ANSfhaTjEUEZHT
FfI1F06T5wlZp0h2HIhQBcW58fqZDaKH5dBRhQEqdGMYXaTE+WVB/plHsLjs
L982Yi8RpR4QIubg4UEn+ZGJKhCxIOnYo6OA5dc6yyK5toApGjnu6arjpmgB
oKTK38eO3pzxfccSAQDbu+3+FeAk2C3dA2hSNEisxT7kAhcS0tA4gyWB4RB5
Y8WVhMOgq9t7zuUpbhg45w5xH8ZUrAEFl2MqLUr4UeLFPeVYnZ5cvADyHdzL
aYSXcSjLIJUXOYsrIqdX8awpczW+GfYLbga6fMnCMSjNAXSr20DPS1KXqjni
0x1g15Hr2ruqeswxTUGYSxQ1pjJuvr8jQJ/71f6DEL12qK8XymzimNAPHYnh
zpSGNm3SqiOdFnVumjyBS64xJ17WyNJ04hsSp478LwmTlkrkkY3CMMSi48J4
l/hm4pEje9VZC4cQ9tihfx9aB/jbTb50B3gVNjzOuxhNfAipu9gtCi92868F
N1cIBXdUIwnCLojwZEXxfr3qvZPsh13fdm6uq5YcUzuuBfyNwGzGLHUAs93k
K6EzelzWrFDw9UFEqcOkNA4RdZelbF2P4inA4T95fnrx+mysgCXFpLosiyu5
VawSSMp1Wqv11OidpgS8XHE+byhjFORGgsMCOOga1ZCxuqzrVTW+f58f7QEs
7k/LIl/cT8p4Xo8WRZ5cx3k8QgI7EgJ7P4ru3dvyfrT/6N49DME7o2mz83eJ
cHpL7PNtmXVIsRRxeEQXzvr3mEj1JXcfSJd1ngvHmXtIWtdPVK7rJjII4Zgh
ASZnASpjzdqe65JyAV/Gib2DxmQISa0ptUMFs/AqptzQNhCjdv2qUzDDYsXF
t7G3c5JCwrqnFMnHEklPQVSSZpXqK75qp4n1ClxRSArUzGj7cZ6Esjzj/xqS
UwpHZCxM3FXu9hJjtil4KaWI+K9sdSWaWNd1w9AnKGVMJV2vpopS7F0V7Haq
VTHXVUshlKDwJGUTjC2Hi5Rrib29SD/gPRYgJiyxUAyZF3Jzcx3vPt1lQHbc
WVlUOBsURAmY5xKMSJemUrsxXoAtQYJ8R6o5iiYKbxhWmFSIqcuiNreMUbHl
mRzYGw7SD3yQ5FhYyNkMOnPXiCnYyaW8+fJoo0nABLzE7x2ndg998A7ppvAh
Xsc9tPtN6HCmuRzg2zyU02HsUJtB2L7NGznkdOd9M53L4b9HBxg/GflZezMx
K/eNErOK05Lu9O6sjXq/M59+6DcP0lfv96UCBZ+4BIn7HWG3N2/hQ97Cl0QJ
rT9Wwm6K1Yiz9jztIthdLBAGhxtLYZs8Yq58BGMMacstNs/kKlpf/r95eg98
DJPbd3fo3t1dQ3pRUvAVifBy7ZuHODTcYJXFKFOcofVXcIZmTPkQ6SxIesKx
/VB7SqYBKLjI80rtUJ7HULIfhoGXRVBXhjR1XGhoHrRjM4OYc59mUXgjGmu4
oiDedDqU+8jJ9pmSbaHCeuBLufGKAZrFHzfeHTqKHTxF6GWi+7n4VhjW4mju
plzAlktjqSeW7Jp1Qm6BmAf+zgfzkeugCExCCx11CW+Uo+MHO4NHJsglJqMB
JXjYMRzyMx9sIBJ9EsyDHObmPkU6Aa27tOnKDLlxe88XOXDoc5sAZGdDm82H
zxJOfNmk6cQ5Ml1JdoFPp/ysjS4W6wkb4QWkAlZxD1K7kw+rmCTRHkUR28g9
0Kyll76SyHNwEkwl7K0sWWfyxn97duphJdrlug2JYxVaJ4eqZZvErW7ZJSXy
0j9mbjzvzh+6k2gtqEqm/KWp5htsvaNykVx9zfcAWV0Oe39VXAvJqhSVYMaS
rI8fHe7TZPDHk4f7D28+Cft8Eugcy5XHBdkdv1NHM1SEQVBc0EQxheH189dR
9AfWb1uixa/8FP0f3M0c626yAAA=

-->

</rfc>

