Into

Modules

Documentation

classPiiMultipartDecoder

#include <PiiMultipartDecoder.h>

A class that decodes MIME multipart messages.

Inherits QIODevice

Description

PiiMultipartDecoder is an IO device that decodes a multipart MIME message and splits the input stream into chunks based on the extracted information. Once a header has been fetched, read operations will be terminated to the next boundary of the multipart message body. The class recognizes nested multiparts.

Consider the following multipart MIME message (example from http://www.w3.org/TR/html401/interact/forms.html):

Content-Type: multipart/form-data; boundary=AaB03x
--AaB03x
Content-Disposition: form-data; name="submit-name"
Larry
--AaB03x
Content-Disposition: form-data; name="files"
Content-Type: multipart/mixed; boundary=BbC04y
--BbC04y
Content-Disposition: file; filename="text.txt"
Content-Type: text/plain
... contents of text.txt ...
--BbC04y
Content-Disposition: file; filename="image.png"
Content-Type: image/png
Content-Transfer-Encoding: binary
...contents of image.png...
--BbC04y--
--AaB03x--

The code to read the message is as follows:

 // Assume you have a tcp connection through "socket"
 PiiMultipartDecoder decoder(socket);
 while (decoder.nextMessage())
   {
     // Read body contents
     QByteArray aBody = decoder.readAll();
     if (decoder.header().contentType() == "image/png")
       decodePngImage(aBody);
   }

The decoder will read the topmost header first. Since the header represents a multipart message, the header of the first body part will also be read. After the first call to #bodyPartHeader(), there will be two headers on the header stack (depth() will return 2). The first call to readAll() will return "Larry".

The next round will also read two headers because the message contains a nested multipart message (depth() will return 3). The second readAll() call will return the contents of file1.txt. The third round fetches the contents of file2.gif, after which the loop will break.

Constructors and destructor

( )

Create a new multipart message decoder with a header that has already been read from the input device.

Create a new multipart message decoder.

Public member functions

qint64
int
( )

Returns the depth of the current body part stack.

(
  • int level = 0
)

Returns the header of a nested body part.

bool
bool

Reads headers from the input stream until an ordinary (non-multipart) message header is found and puts all read headers into the header stack.

Protected member functions

qint64
(
  • char * data
  • qint64 maxSize
)

Reads data from the underlying device.

qint64
(
  • const char * data
  • qint64 maxSize
)

Writes data to the underlying device.

Function details

  • PiiMultipartDecoder

    ( )

    Create a new multipart message decoder with a header that has already been read from the input device.

     void MyHandler::handleRequest(const QString& uri,
                                   PiiHttpDevice* h,
                                   PiiProgressController* controller)
     {
       if (!h->readHeader()) return;
       if (h->requestMethod() == "POST" &&
           h->requestHeader().contentType().startsWith("multipart/"))
         {
            PiiMultipartDecoder decoder(h, h->requestHeader());
            // Read message preamble
            decoder.readAll();
            while (decoder.nextMessage())
              {
                // ...
              }
         }
     }
    
  • PiiMultipartDecoder

    ( )

    Create a new multipart message decoder.

    This constructor assumes that the message header has not been read yet.

  • ~PiiMultipartDecoder

    ()
  • qint64 bytesAvailable

    ()
  • int depth

    ()

    Returns the depth of the current body part stack.

    The depth increases with each nesting level inside multipart messages. The preamble of the first-level multipart message is at depth one, and the first entity within the message is at depth two.

  • PiiMimeHeader header

    (
    • int level = 0
    )

    Returns the header of a nested body part.

    The bottommost header in the stack is either the one given in the constructor or the first one read from the input strem. If the body is a multipart message as of RFC 2387, more headers will be added to the stack when the message body is being parsed. Once all body parts have been read, the body part stack will be emptied.

    Since a multipart message can contain another multipart message, the depth of the header stack can be arbitrary. The level parameter can be used to obtain information about enclosing messages. If there are no more body parts, or an incorrect level is given, an invalid header will be returned.

    Parameters
    level

    the stacking level. 0 refers to the body part the device is currently reading, 1 is its parent and so on.

    Returns

    a MIME header or an invalid header if there is no such level.

  • bool isSequential

    ()
  • bool nextMessage

    ()

    Reads headers from the input stream until an ordinary (non-multipart) message header is found and puts all read headers into the header stack.

    Headers can only be read once all the data in a message body has been read.

    Returns

    true if a message was successfully read, false if no more messages could be read.

    Exceptions
    PiiMimeException&

    if the header is incorrectly encoded

  • qint64 readData

    (
    • char * data
    • qint64 maxSize
    )
    [protected]

    Reads data from the underlying device.

    Stops at message boundaries.

  • qint64 writeData

    (
    • const char * data
    • qint64 maxSize
    )
    [protected]

    Writes data to the underlying device.

    Provided just for completeness. Decoders aren't often used for writing.

Notes (0)

Add a note

Not a single note added yet. Be the first, add yours.