From: Michael M Slusarz Date: Mon, 26 Apr 2010 07:36:28 +0000 (-0600) Subject: Request #8092: Use CATENATE (RFC 4469) to strip MIME parts X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=6d09e5a4cff91180789155a863ef6e65d9ff7864;p=horde.git Request #8092: Use CATENATE (RFC 4469) to strip MIME parts Even if IMAP server doesn't support CATENATE, use the same process to build the message data as with CATENATE - by defining the parts on the server using IMAP URLs. --- diff --git a/imp/docs/CHANGES b/imp/docs/CHANGES index 59156263e..0712ae4de 100644 --- a/imp/docs/CHANGES +++ b/imp/docs/CHANGES @@ -2,6 +2,8 @@ v5.0-git -------- +[mms] Use CATENATE (RFC 4469), if available, to strip MIME parts (Request + #8092). [mms] Add preference to show flags created by other MUAs (Request #8882). [mms] Added HTML signature support (Request #1406). [mms] Simplified date sorting display (Ticket #8936). diff --git a/imp/docs/RFCS b/imp/docs/RFCS index 71b51e4c1..4a6fb6d53 100644 --- a/imp/docs/RFCS +++ b/imp/docs/RFCS @@ -34,6 +34,7 @@ RFC 3691 UNSELECT RFC 4315 UIDPLUS RFC 4422 SASL Authentication (for DIGEST-MD5) RFC 4466 Collected extensions (updates RFCs 2088, 3501, 3502, 3516) +RFC 4469/5550 CATENATE RFC 4551 CONDSTORE RFC 4731 ESEARCH RFC 4959 SASL-IR diff --git a/imp/lib/Message.php b/imp/lib/Message.php index 68c302eb6..7404de9c3 100644 --- a/imp/lib/Message.php +++ b/imp/lib/Message.php @@ -452,63 +452,90 @@ class IMP_Message throw new IMP_Exception(_("An error occured while attempting to strip the attachment.")); } - /* If more than one index provided, return error. */ + /* If more than one UID provided, return error. */ reset($msgList); - list($mbox, $index) = each($msgList); - if (each($msgList) || (count($index) > 1)) { + list($mbox, $uid) = each($msgList); + if (each($msgList) || (count($uid) > 1)) { throw new IMP_Exception(_("An error occured while attempting to strip the attachment.")); } - $index = implode('', $index); + $uid = reset($uid); if ($GLOBALS['imp_imap']->isReadOnly($mbox)) { - throw new IMP_Exception(_("Cannot strip the MIME part as the mailbox is read-only")); + throw new IMP_Exception(_("Cannot strip the MIME part as the mailbox is read-only.")); } - $GLOBALS['imp_imap']->checkUidvalidity($mbox); - - /* Get a local copy of the message. */ - $contents = $GLOBALS['injector']->getInstance('IMP_Contents')->getOb($mbox, $index); - - /* Loop through all to-be-stripped mime parts. */ - if (is_null($partid)) { - /* For stripping all parts, it only makes sense to strip base - * parts. Stripping subparts may cause issues with display of the - * parent multipart type. */ - for ($i = 2;; ++$i) { - $part = $contents->getMIMEPart($i, array('nocontents' => true)); - if (!$part) { - break; - } - $partids[] = $i; + $uidvalidity = $GLOBALS['imp_imap']->checkUidvalidity($mbox); + + $contents = $GLOBALS['injector']->getInstance('IMP_Contents')->getOb($mbox, $uid); + $imap_ob = $GLOBALS['imp_imap']->ob(); + $message = $contents->getMIMEMessage(); + $boundary = trim($message->getContentTypeParameter('boundary'), '"'); + + $url_array = array( + 'mailbox' => $mbox, + 'uid' => $uid , + 'uidvalidity' => $uidvalidity + ); + + /* Always add the header to output. */ + $parts = array( + array( + 't' => 'url', + 'v' => $imap_ob->utils->createUrl(array_merge($url_array, array('section' => 'HEADER'))) + ) + ); + + for ($id = 1; ; ++$id) { + $part = $message->getPart($id); + if (!$part) { + break; } - } else { - $partids = array($partid); - } - $message = $contents->buildMessageContents($partids); - - foreach ($partids as $partid) { - $oldPart = $message->getPart($partid); - if (!($oldPart instanceof Horde_Mime_Part)) { - continue; + $parts[] = array( + 't' => 'text', + 'v' => "\r\n--" . $boundary . "\r\n" + ); + + if (($id != 1) && is_null($partid) || ($id == $partid)) { + $newPart = new Horde_Mime_Part(); + $newPart->setType('text/plain'); + + /* Need to make sure all text is in the correct charset. */ + $part_name = $part->getName(true); + $newPart->setCharset(Horde_Nls::getCharset()); + $newPart->setContents(sprintf(_("[Attachment stripped: Original attachment type: %s, name: %s]"), $part->getType(), $part_name ? $part_name : _("unnamed"))); + + $parts[] = array( + 't' => 'text', + 'v' => $newPart->toString(array( + 'canonical' => true, + 'headers' => true, + 'stream' => true + )) + ); + } else { + $parts[] = array( + 't' => 'url', + 'v' => $imap_ob->utils->createUrl(array_merge($url_array, array('section' => $id . '.MIME'))) + ); + $parts[] = array( + 't' => 'url', + 'v' => $imap_ob->utils->createUrl(array_merge($url_array, array('section' => $id))) + ); } - $newPart = new Horde_Mime_Part(); - $newPart->setType('text/plain'); - $newPart->setDisposition('attachment'); - - /* We need to make sure all text is in the correct charset. */ - $part_name = $oldPart->getName(true); - $newPart->setCharset(Horde_Nls::getCharset()); - $newPart->setContents(sprintf(_("[Attachment stripped: Original attachment type: %s, name: %s]"), $oldPart->getType(), $part_name ? $part_name : _("unnamed"))); - $message->alterPart($partid, $newPart); } + $parts[] = array( + 't' => 'text', + 'v' => "\r\n--" . $boundary . "--\r\n" + ); + /* Get the headers for the message. */ try { - $res = $GLOBALS['imp_imap']->ob()->fetch($mbox, array( - Horde_Imap_Client::FETCH_HEADERTEXT => array(array('peek' => true)), + $res = $imap_ob->fetch($mbox, array( + Horde_Imap_Client::FETCH_DATE => true, Horde_Imap_Client::FETCH_FLAGS => true - ), array('ids' => array($index))); + ), array('ids' => array($uid))); $res = reset($res); /* If in Virtual Inbox, we need to reset flag to unseen so that it @@ -518,19 +545,25 @@ class IMP_Message unset($res['flags'][$pos]); } - $uid = $GLOBALS['imp_imap']->ob()->append($mbox, array(array('data' => $message->toString(array('headers' => $res['headertext'][0], 'stream' => true)), 'flags' => $res['flags']))); + $new_uid = $imap_ob->append($mbox, array( + array( + 'data' => $parts, + 'flags' => $res['flags'], + 'internaldate' => $res['date'] + ) + )); + $new_uid = reset($new_uid); } catch (Horde_Imap_Client_Exception $e) { throw new IMP_Exception(_("An error occured while attempting to strip the attachment.")); } $this->delete($indices, array('nuke' => true, 'keeplog' => true)); - $imp_mailbox = $GLOBALS['injector']->getInstance('IMP_Mailbox')->getOb($mbox); - $imp_mailbox->setIndex(reset($uid)); + $GLOBALS['injector']->getInstance('IMP_Mailbox')->getOb($mbox)->setIndex($new_uid . IMP::IDX_SEP . $mbox); /* We need to replace the old index in the query string with the * new index. */ - $_SERVER['QUERY_STRING'] = preg_replace('/' . $index . '/', reset($uid), $_SERVER['QUERY_STRING']); + $_SERVER['QUERY_STRING'] = str_replace($uid, $new_uid, $_SERVER['QUERY_STRING']); } /** diff --git a/imp/message.php b/imp/message.php index 52d635393..90088a623 100644 --- a/imp/message.php +++ b/imp/message.php @@ -162,6 +162,7 @@ case 'strip_all': case 'strip_attachment': try { $imp_message->stripPart($indices_array, ($vars->actionID == 'strip_all') ? null : $vars->imapid); + $notification->push(_("Attachment successfully stripped."), 'horde.success'); } catch (Horde_Exception $e) { $notification->push($e); }