/**
* Recursively parse BODYSTRUCTURE data from a FETCH return (see
* RFC 3501 [7.4.2]).
*
* @param array $data The tokenized information from the server.
*
* @return array The array of bodystructure information.
*/
protected function _parseStructure($data)
{
$ob = new Horde_Mime_Part();
// If index 0 is an array, this is a multipart part.
if (is_array($data[0])) {
// Keep going through array values until we find a non-array.
for ($i = 0, $cnt = count($data); $i < $cnt; ++$i) {
if (!is_array($data[$i])) {
break;
}
$ob->addPart($this->_parseStructure($data[$i]));
}
// The first string entry after an array entry gives us the
// subpart type.
$ob->setType('multipart/' . $data[$i]);
// After the subtype is further extension information. This
// information MAY not appear for BODYSTRUCTURE requests.
// This is parameter information.
if (isset($data[++$i]) && is_array($data[$i])) {
foreach ($this->_parseStructureParams($data[$i], 'content-type') as $key => $val) {
$ob->setContentTypeParameter($key, $val);
}
}
// This is disposition information.
if (isset($data[++$i]) && is_array($data[$i])) {
$ob->setDisposition($data[$i][0]);
foreach ($this->_parseStructureParams($data[$i][1], 'content-disposition') as $key => $val) {
$ob->setDispositionParameter($key, $val);
}
}
// This is language information. It is either a single value or
// a list of values.
if (isset($data[++$i])) {
$ob->setLanguage($data[$i]);
}
// Ignore: location (RFC 2557)
// There can be further information returned in the future, but
// for now we are done.
} else {
$ob->setType($data[0] . '/' . $data[1]);
foreach ($this->_parseStructureParams($data[2], 'content-type') as $key => $val) {
$ob->setContentTypeParameter($key, $val);
}
if ($data[3] !== null) {
$ob->setContentId($data[3]);
}
if ($data[4] !== null) {
$ob->setDescription(Horde_Mime::decode($data[4]));
}
if ($data[5] !== null) {
$ob->setTransferEncoding($data[5]);
}
if ($data[6] !== null) {
$ob->setBytes($data[6]);
}
// If the type is 'message/rfc822' or 'text/*', several extra
// fields are included
switch ($ob->getPrimaryType()) {
case 'message':
if ($ob->getSubType() == 'rfc822') {
// Ignore: envelope
$ob->addPart($this->_parseStructure($data[8]));
// Ignore: lines
$i = 10;
} else {
$i = 7;
}
break;
case 'text':
// Ignore: lines
$i = 8;
break;
default:
$i = 7;
break;
}
// After the subtype is further extension information. This
// information MAY appear for BODYSTRUCTURE requests.
// Ignore: MD5
// This is disposition information
if (isset($data[++$i]) && is_array($data[$i])) {
$ob->setDisposition($data[$i][0]);
foreach ($this->_parseStructureParams($data[$i][1], 'content-disposition') as $key => $val) {
$ob->setDispositionParameter($key, $val);
}
}
// This is language information. It is either a single value or
// a list of values.
if (isset($data[++$i])) {
$ob->setLanguage($data[$i]);
}
// Ignore: location (RFC 2557)
}
return $ob;
}