RFC 3391

The MIME Application/Vnd.pwg-multiplexed Content-Type

πŸ“… published December 2002, from ietf

RFC 3391 πŸ’– The MIME Application/Vnd.pwg-multiplexed Content-Type

Okay bestie, let's get into it πŸŽ€ This is RFC 3391, written by R. Herriot and published in December 2002. It's an Informational doc, so it's info for the Internet community, not a standard πŸ’… The title block doesn't list any RFCs it obsoletes or updates ✨

Status of This Memo 🌸

This memo provides information for the Internet community. It does not specify an Internet standard of any kind. Distribution of this memo is unlimited.

Copyright (C) The Internet Society (2002). All Rights Reserved.

IESG Note πŸ‘‘

Okay so the IESG is being very clear here 😭 They think this media type is only a good idea when the producer totally knows what the consumer can and can't handle. The big deal is that this mechanism depends heavily on the producer knowing when the consumer will need a particular component of a multipart object. But consumers are all different, and different consumers might need different things at different times πŸ™ˆ This mechanism gives a producer no way to figure out what a particular consumer needs or how to accommodate it.

If the producer doesn't know the consumer's capabilities, the IESG says you should look at other options first, like a protocol based on BEEP πŸ¦‹ BEEP can do two-way communication between the producer and consumer, so it's worth considering.

Abstract πŸ’œ

The Application/Vnd.pwg-multiplexed content-type is kind of like Multipart/Related: it's a way to represent objects made of multiple components ✨ An Application/Vnd.pwg-multiplexed entity is a sequence of chunks, and each chunk holds a MIME message or part of one. Each MIME message is a component of the compound object, the same way a body part of a Multipart/Related entity is a component.

Here's the lowkey big difference πŸ‘€ With a Multipart/Related entity, a body part and whatever references it in some other body part can be separated by lots of octets. With Application/Vnd.pwg-multiplexed, a message and its reference in another message can be made really close together by chunking the message that contains the reference. For example, say a long message references images, and the producer doesn't know it needs each image until it generates the reference. Then Application/Vnd.pwg-multiplexed lets the consumer handle the reference and the image before it has to consume the whole long message. That's super important for printing and scanning apps πŸ–¨οΈ

This document defines the Application/Vnd.pwg-multiplexed content-type and also gives examples of how to use it πŸ’…

Table of Contents πŸŽ€

   1. Introduction....................................................2
   2. Terminology.....................................................7
   3. Details.........................................................9
   3.1  Syntax of Application/Vnd.pwg-multiplexed Contents...........10
   3.2  Parameters for Application/Vnd.pwg-multiplexed...............12
   3.2.1  The "type" Parameter.......................................12
   3.2.2  Syntax.....................................................12
   4. Handling Application/Vnd.pwg-multiplexed Entities..............12
   5. Examples.......................................................13
   5.1  Example With Multipart/Related...............................14
   5.2  Examples with Application/Vnd.pwg-multiplexed................15
   5.2.1  Example Where Each Chunk Has a Complete Message............15
   5.2.2  Example of Chunking the Root Message.......................17
   5.2.3  Example of Chunking the Several Messages...................18
   5.2.4  Example of Chunks with Empty Payloads......................20
   6. Security Considerations........................................22
   7. Registration Information for Application/Vnd.pwg-multiplexed...22
   8. Acknowledgments................................................23
   9. References.....................................................23
   10. Author's Address..............................................24
   11. Full Copyright Statement......................................25

1. Introduction 🧚

Simple MIME content-types, like text/plain, are a way to represent a simple object, like a text document πŸ“„ The Multipart/Related [RFC2387] content-type is for representing a compound object, like a text document with two gif images πŸ–ΌοΈ

A compound object is made of multiple components πŸ’– One of them is the root component, which contains references to the other components of the compound object. Those components can also contain references to other components, so it's a whole web πŸ•ΈοΈ For example, a compound object could be a root html text component plus two gif image components, and both images are referenced by the root component.

A compound object and a component are both abstractions ✨ To send them over the wire or write them to storage, each one needs a representation. A "Multipart/Related entity" is one possible representation of a compound object, and a "body part" is one possible representation of a component.

Here's the tea β˜• Multipart/Related is not a great solution for apps that need each component to sit close to its reference in the root component. So this document defines a new MIME content-type, Application/Vnd.pwg-multiplexed, which is a better fit for some apps πŸ¦‹ Like Multipart/Related, it gives a common way to represent a compound object. A Multipart/Related entity is a sequence of body parts separated by boundary strings, and each body part represents a component. An Application/Vnd.pwg-multiplexed entity is a sequence of chunks, and each chunk's length is specified in its chunk header. Each chunk contains a message or part of a message, and each message represents a component of the compound object. Chunks from different messages can be interleaved 🌈 HTTP is the typical transport for an Application/Vnd.pwg-multiplexed entity over the wire. An Application/Vnd.pwg-multiplexed entity could also be stored in a Microsoft HTML (message/rfc822) file whose suffix is .mht πŸ—‚οΈ

The next bit gives three example apps πŸ§šβ€β™€οΈ For each one, the doc talks about the solution using Application/Vnd.pwg-multiplexed, Multipart/Related, and BEEP [RFC3080].

Example 1: a printing application. πŸ–¨οΈ A Producer creates a print stream that's a really long series of page descriptions, and each page description references one or more images. The root component is that long series of page descriptions. An image can be referenced from multiple page descriptions, and there's a mechanism to say when an image has no more references (meaning the image is out of scope) πŸ’… The Producer doesn't know which images go with a page until it generates that page. The Consumer is assumed to have enough storage to hold all the in-scope images and enough of the root component to process at least one page. The Producer doesn't need to know anything about the Consumer's storage capabilities to create an entity the Consumer can successfully process. Still, the Producer needs to be prudent about how many images are in scope at any given time. And yes, a malicious Producer might try to exceed the Consumer's storage capabilities, so the Consumer must guard against those entities (see section 6) 😈 Here are the ways to represent this compound object:

  • With the Application/Vnd.pwg-multiplexed content-type, each image is a message and the root component is a message too. The Producer breaks the root component message into chunks, with each image message showing up shortly before its first reference. When the Consumer hits a reference, it can assume it already received the referenced image in an earlier chunk πŸ₯Ή
  • With the Multipart/Related content-type, each image must either come before or after the root component.
    • If the images come after the root component, the Consumer has to read all the remaining pages of the root component before it can print the first page that references those images. The Consumer must wait to print such a page until it has the entire root component, and it may not have the space to hold the remaining pages 😡
    • If the images come before the root component, the Producer must figure out and send all of those images before it sends the root component. The Consumer must, in the best case, wait some extra time before it gets the first page of the root component. In the worst case, the Consumer may not have enough storage for all the images 😬
    • The Multipart/Related solution isn't a good one because of the wait time and because, in some cases, the Consumer may not have enough storage for all of the images.
  • With BEEP, the images and root component can be sent over separate channels. The Producer can push each image when it hits the first reference, or the Consumer can request it when it hits the first reference. The over-the-wire stream of octets looks similar to an Application/Vnd.pwg-multiplexed entity. But there's a big difference in behavior for a printing app πŸ‘€ With Application/Vnd.pwg-multiplexed, the Producer puts each image message before its first reference, so when the Consumer hits a reference, the image is guaranteed to be on the printer. With BEEP, if the Consumer pulls the image, it has to wait while the image comes over the network. If the Producer pushes the image, BEEP may put the image message after its first reference, and the Consumer may still have to wait for it. A high-speed printer shouldn't have to risk waiting for images, otherwise it can't run at full speed πŸŽοΈπŸ’¨

Example 2: a scanning (fax-like) application. πŸ“  The Producer is a scanner that scans pages and sends them along with a vnd.pwg-xhtml-print+xml root component that contains references to each page image. Each page is referenced exactly once in the root component. The Consumer is a printer that consumes vnd.pwg-xhtml-print+xml entities and their attachments. In other words, the Consumer isn't limited to print jobs that come from scanners πŸ™Œ The Producer and Consumer are each assumed to have enough storage for a few page images and most, if not all, of the root component. The Producer doesn't need any extra knowledge of the Consumer's storage capabilities to create an entity the Consumer can successfully process. Of course, a malicious Producer might try to exceed the Consumer's storage capabilities, and the Consumer must guard against such entities (see section 6) πŸ›‘οΈ Here are the ways to represent this compound object:

  • With the Application/Vnd.pwg-multiplexed content-type, each page image is a message and the root component is a message. The Producer breaks the root component message into chunks, with each image message just before or just after its reference ✨

Okay so picture this: with Multipart/Related, the images can't come before the root component πŸŽ€. The Consumer might not have room to hold them until the root shows up, the printer could mess up the job, and the Producer wouldn't even know 😭. So the images must follow the root component, which means the Producer has to scan every page before it can send the first one πŸ“„. At the very least, printing gets delayed until everything is scanned, and in the worst case the Producer doesn't have enough memory to buffer the images and the whole job fails πŸ’€.

With BEEP, it's the same problem as the previous example, except speed isn't as big a deal here πŸ¦‹. So BEEP is a viable option for this one ✨.

Example 3: a printing application. A Producer makes a print stream made of a series of pages, and each page references zero or more images. Each image is referenced exactly once. The Producer doesn't know which images go with a page until it generates that page, and it doesn't know the layout details, because the Consumer handles layout 🧚. The Producer has enough storage to send the root component and all the images. However, it may not have enough storage to hold the entire root component or all the octets of any single image. The Consumer is presumed to have enough storage to render the root component and to render each image, but it may not have enough storage to hold the entire root component or all the octets of any of the images either πŸ₯Ί. The Producer doesn't determine the Consumer's storage capabilities. Instead, it arranges the components so the Consumer is most likely to succeed 🌸. Of course, a malicious Producer might try to exceed the Consumer's storage capabilities, and the Consumer must guard against that kind of entity (see section 6) 🚨. Here are the ways to represent this compound object πŸ‘€.

With the Application/Vnd.pwg-multiplexed content-type, each image is its own message, and the root component is a message too. The Producer breaks the root component message into chunks, with each image message placed right after its reference. The references come first so the Consumer knows where each image goes before it processes that image. This strategy minimizes storage needs for both the Producer and the Consumer, and it's a good strategy if something fails 🫢. Here are the cases to think about:

  • a) When the document is made of vertically aligned blocks, where each block contains either lines of text or a single image, the sequence of chunks is the same as the sequence of printable blocks, which keeps the Consumer's buffering needs low ✨.
  • b) When a block can contain N side-by-side images, the Consumer must buffer N-1 images unless the Producer interleaves the images. If the Producer doesn't interleave them and the Consumer runs out of storage before it has received N-1 images, it can print what it has and print the remaining images below. It's not what the Producer intended, but it's better than nothing πŸ™ˆ. If the Producer does interleave the images and the Consumer runs out of storage before it has received the bands of N images, the Consumer would print portions of images mixed in with portions of other images, which is messy 😭. So, a Producer should not interleave images 🚫.
  • c) When a block contains text and an image side-by-side (in other words, run-around text), there are extra buffering requirements πŸ“š. When the Consumer processes the text that follows the reference, it places some of that text next to the image (the run-around text) and puts the rest after the image. The Producer doesn't know where the run-around ends, so it doesn't know where to end the text chunk and start the image chunk. If the Producer ends the text too soon, the Consumer either has to process the entire image (if it has enough storage) to get the remaining run-around text, or it ends the run-around text early. If the Producer ends the text too late, the Consumer may have to store too much text and might place the image later than the Producer asked for. Because text data takes way less storage than image data, a good strategy for the Producer is to err on the side of sending too much text rather than too little before the image data πŸ’….
  • d) When a block contains text and multiple side-by-side images, the problem becomes a mix of items b) and c) above πŸŒ€.

The Application/Vnd.pwg-multiplexed content-type can be made to work in this example, but a Consumer needs failure strategies, and the result may not be quite what the Producer intended πŸ₯². With Multipart/Related, the images can't come before the root component, because the Consumer might not have space to store them until the root arrived. Also, the images can't come after the root component either, because the Consumer might not have enough storage for the root component before the first image arrives 😩. So Multipart/Related is not an acceptable solution for this example 🚫.

With BEEP, the Producer can send the root component on channel 1, and the Consumer can request images on even-numbered channels when it hits a reference πŸŽ€. This solution is more flexible than Application/Vnd.pwg-multiplexed. If there are side-by-side images and/or run-around text, the Consumer can request bands of each image or run-around text over separate channels πŸ¦‹.

In all of these examples, Application/Vnd.pwg-multiplexed is a much better solution than Multipart/Related. However, it's evenly matched with BEEP 🀼. For applications where speed matters and the ordering of chunks matters to avoid printing delays, Application/Vnd.pwg-multiplexed is the best pick 🏎️. For applications where the Consumer needs more control over the ordering of the received octets, BEEP is the best pick πŸ‘‘.


2. Terminology ✨

This document uses some of the MIME terms defined in [RFC2045]. Here are the terms used in this document πŸ“–:

  • Entity: the headers and the content. In this document, "entity" describes all the octets that represent a compound object πŸ’œ.
  • Message: an entity as in [RFC2045]. In this document, "message" describes all the octets that represent one component of a compound object. That means it has MIME headers and content 🌸.
  • Body Part: an entity inside a multipart. A body part is the headers and content (i.e., the octets) between the multipart boundary strings, not including the CRLF at the beginning and end πŸŽ€. This document never uses "entity" to mean "body part" πŸ™…β€β™€οΈ.
  • Headers: the initial lines of an entity, message, or body part. An empty line (i.e., two adjacent CRLFs) ends the headers. Sometimes the term "MIME header" is used instead of just "header" 🧚.
  • Content: the part of an entity, message, or body part that follows the headers (i.e., follows the two adjacent CRLFs). The content of a body part ends at the octet before the CRLF that comes before the multipart boundary string. The content of a message ends at the octets specified by the length field in the Chunk Header 🫢.

This document uses the following additional terms πŸ‘‡.

  • Chunk: a chunk of data, made of a chunk header, a chunk payload, and a CRLF πŸ“.
  • Chunk Header: the first line of a chunk. The line consists of the CHK keyword, the message number, the length, and the continuation indicator, each separated by a single space character (ASCII 32). A CRLF ends the line. Each message in an Application/Vnd.pwg-multiplexed entity has a message number that normally differs from the message numbers of all other messages in that entity. The message number 0 is reserved for the final Chunk Header in the Application/Vnd.pwg-multiplexed entity πŸ”’.
  • Chunk Payload: the octets between the Chunk Header and the Chunk Header of the next chunk. The length field in the header specifies the number of octets in the Chunk Payload. The Chunk Payload is either a complete message or a part of a message. The continuation field in the header specifies whether the chunk is the last chunk of the message πŸ“¦.
  • CRLF: the sequence of octets for the two US-ASCII characters CR (decimal value 13) and LF (decimal value 10), which together, in this order, denote a line break. A CRLF ends each chunk to visually separate it from the next chunk header πŸ’–.
  • Consumer: the software that receives and processes a MIME entity, e.g., software in a printer or software that reads a file πŸ–¨οΈ.
  • Producer: the software that creates and sends a MIME entity, e.g., software in a scanner or software that writes a file πŸ“Έ.

3. Details ✨

okay so Application/Vnd.pwg-multiplexed is giving Multipart/Related energy πŸ’–. It's meant to hold a compound object made of several inter-related components. This doc doesn't spell out how those relationships are represented, BUT [RFC2557] has examples of Multipart/Related entities that use the Content-ID and Content-Location headers to identify body parts, and URLs (including the "cid" URL) to reference them. It is expected that Application/Vnd.pwg-multiplexed entities would use the patterns described in [RFC2557]. πŸŽ€

For an Application/Vnd.pwg-multiplexed entity there is exactly one parameter on the Content-Type header. It's a "type" parameter, lowkey just like the "type" parameter on Multipart/Related. The value of the "type" parameter MUST be the content-type of the root message, and it effectively tells you the type of the whole compound object πŸ‘‘.

An Application/Vnd.pwg-multiplexed entity is a sequence of chunks. Each chunk is made of a chunk header, a chunk payload and a CRLF πŸ¦‹.

  • The chunk header is a CHK keyword, then the message number, the chunk payload length, whether this is the last chunk of a message and, finally, a CRLF. The length field means you don't need the boundary strings that Multipart uses, which is so iconic πŸ™Œ. (See section 3.1 for the syntax of a chunk header).
  • The chunk payload is a sequence of octets that is either a complete message or a part of a message.
  • The CRLF gives visual separation from the next chunk.

Each message is a component of the compound object, and it's intended to have exactly the same representation, octet for octet, as a body part of a Multipart/Related entity that represents the same component 🧚. When a message gets split across several chunks, those chunks don't have to be contiguous.

Okay, now the contents of an Application/Vnd.pwg-multiplexed entity have these properties, and they're the main character rules πŸ’…:

  1. The first chunk contains a complete or partial message that (in either case) represents the root component of the compound object.
  2. Additional chunks contain messages or partial messages that represent some component of the compound object.
  3. The final chunk's header contains a message number of 0, a length of 0 and a last-chunk-of-message mark (i.e., the chunk header line is CHK 0 0 LAST). The final chunk contains no chunk payload πŸ“.
  4. A message can be broken into multiple parts, and each break can occur anywhere within the message. Each part of the message is zero or more bytes in length, and each part is the contents of its own chunk. The order of the chunks within the Application/Vnd.pwg-multiplexed entity MUST be the same as the order of the parts within the message 🌸.
  5. A message represents a component of a compound object, and it's intended to have exactly the same representation, octet for octet, as a body part of a Multipart/Related entity that represents the same component. In particular, the message MAY contain a Content-Type header to specify the content-type of the message content. Also, the message MAY contain a Content-ID header and/or Content-Location header to identify a message that is referenced from within another message. If a message contains no Content-Type header, then the message has an implicit content-type of text/plain; charset=us-ascii, cf. [RFC2045] πŸ”₯.

See section 4 for a discussion displaying an Application/Vnd.pwg-multiplexed entity πŸ‘€.


3.1 Syntax of Application/Vnd.pwg-multiplexed Contents

The ABNF [RFC2234] for the contents of an Application/Vnd.pwg-multiplexed entity is:

contents = *chunk finalChunk
chunk      = header payload CRLF
header     = "CHK" SP messageNumber SP length SP isMore CRLF
messageNumber   = 1..2147483647
length   = 0..2147483647
isMore       = "MORE" / "LAST"
payload    = *OCTET
finalChunk = finalHeader CRLF
finalHeader  = "CHK" SP "0" SP "0" SP "LAST" CRLF

The messageNumber field tells you which message the chunk belongs to. See the end of this section for more details 🧐.

The length field is the number of octets in the chunk payload (written as "payload" in the ABNF). The first octet of the chunk payload is the one right after the LF (i.e., final octet) of the chunk header. The last octet of the chunk payload is the one right before the two octets CRLF that end the chunk.

The isMore field is "LAST" for the last chunk of a message and "MORE" for all the other chunks of a message πŸŽ€.

Normally, each message in an Application/Vnd.pwg-multiplexed entity has a unique message number, and a message is the concatenation of all the octets from the one or more chunks with the same message number. The isMore field of the chunk header of the last chunk of each message MUST have a value of "LAST", and the isMore field of the chunk header of all other chunks MUST have a value of "MORE" πŸ’œ.

Two or more messages MAY have the same message number, though such reuse of message numbers is NOT RECOMMENDED. The chunks with the same message number represent a sequence of one or more messages, where the isMore field of the chunk header of the last chunk of each message has a value of "LAST". All chunks whose isMore field has the value "MORE" belong to the same message as the next chunk (in sequence) whose isMore field has the value "LAST". In other words, if two messages have the same message number, the last chunk of the first message must occur before the first chunk of the second message 😭.

The behavior of the Consumer is undefined if the final Chunk (i.e., the Chunk whose chunk header is CHK 0 0 LAST) occurs before the last chunk of every message occurs πŸ’€.

Two adjacent chunks usually have different message numbers. However, they MAY have the same message number. If two adjacent chunks have the same message number, the two chunks could be combined into a single chunk, but they need not be combined πŸ“.

The number of octets in a chunk payload MAY be zero, and an Application/Vnd.pwg-multiplexed entity MAY contain any number of chunks with zero octets of chunk payload. For example, the last chunk of each message MAY contain zero octets for programming convenience. As another example, suppose that a particular compound object format requires that referenced messages occur before the root message. This document requires that the first chunk of an Application/Vnd.pwg-multiplexed entity contain the root message or a part of it. So, the first chunk contains a chunk payload of zero octets, with the first octet of the root message in the second chunk. That is, all of the message headers of the root message are in the second chunk. As an extreme but unlikely example, it would be possible to have a message broken into ten chunks with zero octet chunk payloads in all chunks except for chunks 4 and 7 πŸ™ˆ.


3.2 Parameters for Application/Vnd.pwg-multiplexed

This section defines additional parameters for Application/Vnd.pwg-multiplexed 🧚.

3.2.1 The "type" Parameter

The type parameter MUST be specified. Its value is the content-type of the "root" message. It lets a Consumer work out the content-type without looking at the enclosed message. If the value of the type parameter differs from the content-type of the root message, the Consumer's behavior is undefined 🌈.

3.2.2 Syntax

The syntax for "parameter" is:

  parameter   := "type"  "=" type "/" subtype ; cf. [RFC2045]

4. Handling Application/Vnd.pwg-multiplexed Entities πŸ’…

The application that handles the Application/Vnd.pwg-multiplexed entity is responsible for displaying it. However, Application/Vnd.pwg-multiplexed messages MAY contain Content-Disposition headers that suggest how a message should be displayed and stored, and in some cases the application MAY pay attention to those headers πŸ‘‘.

As a reminder, Content-Disposition headers [RFC1806] let the sender suggest presentation styles for MIME messages. There are two presentation styles, 'inline' and 'attachment'. Content-Disposition headers can have a parameter that specifies a suggested file name for storage ✨.

There are three cases to consider for handling Application/Vnd.pwg-multiplexed entities πŸ¦‹:

  • a) The Consumer recognizes Application/Vnd.pwg-multiplexed and the content-type of the root. The Consumer determines the presentation style for the compound object, and it handles the display of the components of the compound object in the context of the compound object. In this case, the Content-Disposition header information is redundant or even misleading, and the Consumer SHALL ignore it for purposes of display. The Consumer MAY use the suggested file name if the entity is stored πŸ’–.
  • b) The Consumer recognizes Application/Vnd.pwg-multiplexed, but not the content-type of the root. The Consumer will give the user the choice of suppressing the entire Application/Vnd.pwg-multiplexed entity or treating it as a Multipart/Mixed entity where each message is a body part of the Multipart/Mixed entity. In this case (where the entity is not suppressed), the Consumer MAY find the Content-Disposition information useful for displaying each body part of the resulting Multipart/Mixed entity. If a body part has no Content-Disposition header, the Consumer SHOULD display the body part as an attachment 🌸.
  • c) The Consumer does not recognize Application/Vnd.pwg-multiplexed. The Consumer treats the entity as opaque and can do nothing with it πŸ™ˆ.

5. Examples ✨

Okay bestie, this section is the fun part πŸŽ€ There are five examples, and each one is a different way of writing down the same compound object πŸ’… The object has four components: one XHTML text component and three image components. The images are binary, so <<binary data>> and <<part of binary data>> just stand in for all or part of each image's bytes πŸ¦‹ Two images could sit side by side, and the third shows up later in the document. All the images have a Content-Id, two of them also have a Content-Location, and one image points at that Content-Location 🌸

The first example is a Multipart/Related version of the object, so you can compare it with what you already know 🧚 The other four are Application/Vnd.pwg-multiplexed versions of the same object. In example two, every chunk holds a whole message. In example three, the XHTML message is chopped into 3 chunks, and those chunks are interleaved with the three image messages πŸ’œ In example four, the XHTML message gets split into 4 chunks, the two side-by-side images are each split across two chunks, and the XHTML chunks are interleaved among the image chunks ✨ In example five, you get chunks with empty payloads and adjacent chunks that share the same message number πŸ’€

Example five might look pointless, but it's actually kinda practical πŸ™ˆ When a buffer fills up, it can be easiest to just write a chunk and not care whether the previous one had the same message number. It can also be easiest to end a message with an empty chunk. And here's the big one: the Application/Vnd.pwg-multiplexed content-type says the first chunk has to be part of the root message. Sometimes the Producer would rather start the root message after some attachments, so a chunk is allowed to be empty. That means the first chunk of the root message can be empty, with no headers at all, and the Producer just doesn't generate any octets for that chunk 🫢

Every body part of the Multipart/Related entity, and every message in the Application/Vnd.pwg-multiplexed entity, has a content-disposition header. The Consumer uses that header following the rules in section 4 πŸ“¦ Make sure you notice where the content-disposition headers sit in the examples πŸ‘‘

Here the compound object is written as a Multipart/Related entity, so you can compare it with the Application/Vnd.pwg-multiplexed versions later πŸ’–

Content-Type: multipart/related; boundary="boundary-example";
              type="text/xhtml+xml"

--boundary-example
Content-ID: <49568.44343xxx@foo.com>
Content-Type: application/vnd.pwg-xhtml-print+xml
Content-Disposition: inline

<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/TR/xhtml1">
   <body>
      <p>some text
         <img src="cid:49568.45876xxx@foo.com"/>
         <img src="http://foo.com/images/image2.gif"/>
         some more text after the images
      </p>
      <p>some more text without images
      </p>
      <p>some more text
         <img src="cid:49568.47333xxx@foo.com"/>
      </p>
      <p>some final text
      </p>
   </body>
</html>
--boundary-example
Content-ID: <49568.45876xxx@foo.com>
Content-Location: http://foo.com/images/image1.gif
Content-Type: image/gif
Content-Disposition: attachment

<<binary data>>
--boundary-example
Content-ID: <49568.46000xxx@foo.com>
Content-Location: http://foo.com/images/image2.gif
Content-Type: image/gif
Content-Disposition: attachment

<<binary data>>
--boundary-example
Content-ID: <49568.47333xxx@foo.com>
Content-Type: image/gif
Content-Disposition: attachment

<<binary data>>
--boundary-example--

5.2 Examples with Application/Vnd.pwg-multiplexed

The next four examples show the same compound object written as Application/Vnd.pwg-multiplexed entities 🌈 Heads up: each CRLF is drawn as a visual line break here, so don't panic when the lines look a little different 😭

5.2.1 Example Where Each Chunk Has a Complete Message

In this one, the compound object is an Application/Vnd.pwg-multiplexed entity, and every chunk carries an entire message. None of the messages get split across chunks πŸ“ Each message is identical to the matching body part from the Multipart/Related example back in 5.1 πŸ¦‹

Content-Type: application/vnd.pwg-multiplexed;
              type="application/vnd.pwg-xhtml-print+xml"

CHK 1 550 LAST
Content-ID: <49568.44343xxx@foo.com>
Content-Type: application/vnd.pwg-xhtml-print+xml
Content-Disposition: inline
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/TR/xhtml1">
   <body>
      <p>some text
         <img src="cid:49568.45876xxx@foo.com"/>
         <img src="http://foo.com/images/image2.gif"/>
         some more text after the images
      </p>
      <p>some more text without images
      </p>
      <p>some more text
         <img src="cid:49568.47333xxx@foo.com"/>
      </p>
      <p>some final text
      </p>
   </body>
</html>

CHK 2 6346 LAST
Content-ID: <49568.45876xxx@foo.com>
Content-Location: http://foo.com/images/image1.gif
Content-Type: image/gif
Content-Disposition: attachment

<<binary data>>
CHK 3 6401 LAST
Content-ID: <49568.46000xxx@foo.com>
Content-Location: http://foo.com/images/image2.gif
Content-Type: image/gif
Content-Disposition: attachment

<<binary data>>
CHK 4 7603 LAST
Content-ID: <49568.47333xxx@foo.com>
Content-Type: image/gif
Content-Disposition: attachment

<<binary data>>
CHK 0 0 LAST

5.2.2 Example of Chunking the Root Message

This time the XHTML message is split into 3 pieces, so the reference to an image is as close as possible to the start of its chunk 🧁 The chunk holding the referenced image message comes just before the chunk with the reference, which keeps the distance between reference and referenced message as small as it can be ✨

Quick aside: there are other valid arrangements too (check out the third example in section 5.2.3). A sender could split the XHTML message so the reference sits as close as possible to the end of its chunk. In that case, the chunk with the referenced image message should come just after the chunk with the reference. A sender can also mix the two strategies πŸ’…

Content-Type: application/vnd.pwg-multiplexed;
              type=" application/vnd.pwg-xhtml-print+xml"

CHK 1 267 MORE
Content-ID: <49568.44343xxx@foo.com>
Content-Type: application/vnd.pwg-xhtml-print+xml
Content-Disposition: inline

<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/TR/xhtml1">
   <body>
      <p>some text

CHK 2 6346 LAST
Content-ID: <49568.45876xxx@foo.com>
Content-Location: http://foo.com/images/image1.gif
Content-Type: image/gif
Content-Disposition: attachment

<<binary data>>
CHK 3 6401 LAST
Content-ID: <49568.46000xxx@foo.com>
Content-Location: http://foo.com/images/image2.gif
Content-Type: image/gif
Content-Disposition: attachment
<<binary data>>
CHK 1 166 MORE
         <img src="cid:49568.45876xxx@foo.com"/>
         <img src="http://foo.com/images/image2.gif"/>
         some more text after the images
      </p>
      <p>some more text without images
      </p>
      <p>some more text

CHK 4 7603 LAST
Content-ID: <49568.47333xxx@foo.com>
Content-Type: image/gif
Content-Disposition: attachment

<<binary data>>
CHK 1 80 LAST
         <img src="cid:49568.47333xxx@foo.com"/>
      </p>
      <p>some final text
      </p>
   </body>
</html>

CHK 0 0 LAST

5.2.3 Example of Chunking the Several Messages

Now the XHTML message is split into 4 pieces, so each image reference sits as close as possible to either the start or the end of its chunk πŸ”₯ The references to the first and second images come right after the images they point to, while the reference to the third image comes right before it. The distance between reference and referenced message stays small this way 🌸 On top of that, the first two image messages are each split into two chunks πŸŽ€

Content-Type: application/vnd.pwg-multiplexed;
              type=" application/vnd.pwg-xhtml-print+xml"

CHK 1 303 MORE
Content-ID: <49568.44343xxx@foo.com>
Content-Type: application/vnd.pwg-xhtml-print+xml
Content-Disposition: inline
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/TR/xhtml1">
   <body>
      <p>some text

CHK 2 184 MORE
Content-ID: <49568.45876xxx@foo.com>
Content-Location: http://foo.com/images/image1.gif
Content-Type: image/gif
Content-Disposition: attachment

<<part of binary data>>
CHK 3 200 MORE
Content-ID: <49568.46000xxx@foo.com>
Content-Location: http://foo.com/images/image2.gif
Content-Type: image/gif
Content-Disposition: attachment

<<part of binary data>>
CHK 1 78 MORE
         <img src="cid:49568.45876xxx@foo.com"/>
         <img src="http://foo.com/images/image2.gif"/>

CHK 2 6162 LAST
<<part of binary data>>
CHK 3 6201 LAST
<<part of binary data>>
CHK 1 127 MORE
         some more text after the images
      </p>
      <p>some more text without images
      </p>
      <p>some more text
         <img src="cid:49568.47333xxx@foo.com"/>

CHK 4 7603 LAST
Content-ID: <49568.47333xxx@foo.com>
Content-Type: image/gif
Content-Disposition: attachment
<<binary data>>
CHK 1 41 LAST
      </p>
      <p>some final text
      </p>
   </body>
</html>

CHK 0 0 LAST

5.2.4. Example of Chunks with Empty Payloads ✨

okay bestie, this one is basically the last example with a twist πŸŽ€ Some chunks have a payload of zero octets. The root message starts with an empty chunk, and every message ends with an empty chunk too πŸ’… It also has two chunks from the same message sitting next to each other. Those could be squished into one chunk, but they might stay separate just for programming convenience πŸ¦‹

   Content-Type: application/vnd.pwg-multiplexed;
                 type=" application/vnd.pwg-xhtml-print+xml"

   CHK 1 0 MORE

   CHK 2 184 MORE
   Content-ID: <49568.45876xxx@foo.com>
   Content-Location: http://foo.com/images/image1.gif
   Content-Type: image/gif
   Content-Disposition: attachment

   <<part of binary data>>
   CHK 3 200 MORE
   Content-ID: <49568.46000xxx@foo.com>
   Content-Location: http://foo.com/images/image2.gif
   Content-Type: image/gif
   Content-Disposition: attachment

   <<part of binary data>>
   CHK 1 303 MORE
   Content-ID: <49568.44343xxx@foo.com>
   Content-Type: application/vnd.pwg-xhtml-print+xml
   Content-Disposition: inline
   <?xml version="1.0"?>
   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
   <html xmlns="http://www.w3.org/TR/xhtml1">
      <body>
         <p>some text

   CHK 2 6162 MORE
   <<part of binary data>>
   CHK 3 6201 MORE
   <<part of binary data>>
   CHK 2 0 LAST

   CHK 3 0 LAST

   CHK 1 78 MORE
            <img src="cid:49568.45876xxx@foo.com"/>
            <img src="http://foo.com/images/image2.gif"/>

   CHK 4 7603 MORE
   Content-ID: <49568.47333xxx@foo.com>
   Content-Type: image/gif
   Content-Disposition: attachment

   <<binary data>>
   CHK 4 0 LAST

   CHK 1 127 MORE
            some more text after the images
         </p>
         <p>some more text without images
         </p>
         <p>some more text
            <img src="cid:49568.47333xxx@foo.com"/>

   CHK 1 41 MORE
         </p>
         <p>some final text
         </p>
      </body>
   </html>

   CHK 1 0 LAST

   CHK 0 0 LAST

6. Security Considerations πŸ”₯

okay this part is seriously important, so no giggling πŸ™ˆ Every message inside an Application/Vnd.pwg-multiplexed entity has its own security considerations, and those are covered by whatever document defines that message's content-type. This document doesn't cover them πŸ’œ

BUT the whole entity has its own risks too! A buggy or malicious Producer could send an entity that makes a Consumer ask for more storage than it has, even if it has tons of storage. A Consumer must be able to handle all of these scenarios, and any combo of them:

  • The chunks of one or more messages are separated by a very large number of octets. In the extreme case some or all of the messages don't terminate, i.e., they don't contain a closing chunk.
  • A very large number of messages are started and interleaved before their final chunk occurs.
  • A message contains one or more references to other messages that never occur or don't occur for a large number of octets.
  • A very large number of referenced messages occur before the Consumer knows that it can discard them.
Main character energy for Consumers: handle the chaos gracefully πŸ’€

7. Registration Information for Application/Vnd.pwg-multiplexed 🌸

this is the form for registering the media type with IANA, copied from RFC 1590, Appendix A 🧚 It's giving paperwork, but it's important paperwork ✨

     To: iana@iana.org

     Subject:           Registration of new Media Type
                        application/Vnd.pwg-multiplexed
     Media Type name:   Application
     Media subtype name:     Vendor Tree - vnd.pwg-multiplexed
     Required parameters:    Type, a media type/subtype.
     Optional parameters:    No optional parameters
     Encoding considerations:    Each message of an
                         Application/Vnd.pwg-multiplexed entity can be
                         encoded in any manner allowed by the Content-
                         Type of the message.  However, using the
                         reasoning of Multipart, the
                         Application/Vnd.pwg-multiplexed entity cannot
                         be encoded.  Otherwise, a message would be
                         encoded twice, once at the message level and
                         once at the Application/Vnd.pwg-multiplexed
                         level.
     Security considerations:    See section 6 (Security
                                 Considerations) of RFC 3391.
     Published specification:    RFC 3391.
     Person & email address to contact for further information:

         Robert Herriot
         706 Colorado Ave.
         Palo Alto, CA 94303
         USA
         Phone: 1-650-327-4466
         Fax: 1-650-327-4466
         EMail: bob@herriot.com

8. Acknowledgments πŸ’–

big thank-you to everyone who helped out 🫢 Ugo Corda, Dave Crocker, Melinda Sue Grant, Graham Klyne, Carl-Uno Manros, Larry Masinter, Ira McDonald, Chris Newman, Henrik Frystyk Nielsen and Dale R. Worley. Author gives a special shoutout to Chris Newman, who provided invaluable help πŸ‘‘

9. References πŸ“š

these are all the docs cited above, with every detail kept πŸ¦‹

   [RFC1806] Troost, R. and S. Dorner, "Communicating Presentation
             Information in Internet Messages: The Content-Disposition
             Header", RFC 1806, June 1995.

   [RFC1873] Levinson, E. and J. Clark, "Message/External-Body Content-
             ID Access Type",  RFC 1873, December 1995.
             Levinson, E., "Message/External-Body Content-ID Access
             Type", Work in Progress.

   [RFC2045] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
             Extensions (MIME) Part One: Format of Internet Message
             Bodies", RFC 2045, November 1996.

   [RFC2046] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
             Extensions (MIME) Part Two: Media Types", RFC 2046,
             November 1996.

   [RFC2234] Crocker, D. and P. Overell, "Augmented BNF for
             SyntaxSpecifications: ABNF", RFC 2234, November 1997.

   [RFC2387] Levinson, E., "The MIME Multipart/Related Content-type",
             RFC 2387, August 1998.

   [RFC2392] Levinson, E., "Content-ID and Message-ID Uniform Resource
             Locators", RFC 2392, August 1998.

   [RFC2557] Palme, J., "MIME Encapsulation of Aggregate Documents, such
             as HTML (MHTML", RFC 2557, March 1999.

   [RFC2822] Resnick, P., Editor, "Internet Message Format", RFC 2822,
             April 2001.

   [RFC3080] Rose, M., "The Blocks Extensible Exchange Protocol Core",
             RFC 3080, March 2001.

10. Author's Address πŸŽ€

reach out to the author here πŸ’Œ

   Robert Herriot
   706 Colorado Ave.
   Palo Alto, CA 94303
   USA

   Phone: 1-650-327-4466
   Fax: 1-650-327-4466
   EMail: bob@herriot.com

legal bit, but it's iconic in its own way πŸ’…

Copyright (C) The Internet Society (2002). All Rights Reserved.

This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Internet Society or other Internet organizations, except as needed for the purpose of developing Internet standards in which case the procedures for copyrights defined in the Internet Standards process must be followed, or as required to translate it into languages other than English.

The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assigns.

This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.

Acknowledgement 🌈

Funding for the RFC Editor function is currently provided by the Internet Society. Thank you, Internet Society 🫢✨

πŸ“¦ where this page comes from