From 150496c410d7c650a6e955c8bca758543f90341e Mon Sep 17 00:00:00 2001 From: Michael M Slusarz Date: Thu, 18 Dec 2008 11:10:16 -0700 Subject: [PATCH] Fix Ticket #7361 - content-encoding on strip Also, general fixes to stripping code (was broken in transition to IMP 5) Rework stripping algorithm - only allow stripping non-body parts; and only allow stripping of entire part - not subparts (since subparts may be required to view parent part). Still a WIP. --- imp/lib/Contents.php | 57 ++++++++++++++++++++++++------------- imp/lib/Message.php | 80 +++++++++++++++++++++++++--------------------------- imp/message.php | 2 +- 3 files changed, 77 insertions(+), 62 deletions(-) diff --git a/imp/lib/Contents.php b/imp/lib/Contents.php index 5f9f99f05..ec2a5eca3 100644 --- a/imp/lib/Contents.php +++ b/imp/lib/Contents.php @@ -580,9 +580,12 @@ class IMP_Contents $part['img_save'] = Horde::link('#', _("Save Image in Gallery"), 'saveImgAtc', null, IMP::popupIMPString('saveimage.php', array('index' => ($this->_index . IMP::IDX_SEP . $this->_mailbox), 'id' => $id), 450, 200) . "return false;") . ''; } - /* Strip the Attachment? */ + /* Strip Attachment? Allow stripping of base parts other than the + * base multipart and the base text (body) part. */ if (($mask & self::SUMMARY_STRIP_LINK) && - !$this->isParent($id, 'message/rfc822')) { + ($id != 0) && + (intval($id) != 1) && + (strpos($id, '.') === false)) { $url = Util::removeParameter(Horde::selfUrl(true), array('actionID', 'imapid', 'index')); $url = Util::addParameter($url, array('actionID' => 'strip_attachment', 'imapid' => $id, 'index' => $this->_index, 'message_token' => IMP::getRequestToken('imp.impcontents'))); $part['strip'] = Horde::link($url, _("Strip Attachment"), 'stripAtc', null, "return window.confirm('" . addslashes(_("Are you sure you wish to PERMANENTLY delete this attachment?")) . "');") . ''; @@ -832,23 +835,6 @@ class IMP_Contents } /** - * Given a MIME ID, determines if the given MIME type is a parent. - * - * @param string $id The MIME ID string. - * @param string $type The MIME type to search for. - * - * @return boolean True if the MIME type is a parent. - */ - public function isParent($id, $type) - { - $cmap = $this->getContentTypeMap(); - while (($id = Horde_Mime::mimeIdArithmetic($id, 'up')) !== null) { - return isset($cmap[$id]) && ($cmap[$id] == $type); - } - return false; - } - - /** * Returns the Content-Type map for the entire message, regenerating * embedded parts if needed. * @@ -889,4 +875,37 @@ class IMP_Contents return $ret; } + + /** + * Injects body contents into the base Horde_Mime_part object. If given + * a list of IDs, does not add body contents for that part or children + * of that part. + * + * @param array $ignore A list of MIME IDs to ignore. + * + * @return Horde_Mime_Part The part with body contents set. + */ + public function buildMessageContents($ignore = array()) + { + $message = $this->_message; + $curr_ignore = null; + + foreach ($message->contentTypeMap() as $key => $val) { + if (is_null($curr_ignore) && in_array($key, $ignore)) { + $curr_ignore = $key . '.'; + } elseif (is_null($curr_ignore) || + (strpos($key, $curr_ignore) === false)) { + $curr_ignore = null; + if (($key != 0) && + ($val != 'message/rfc822') && + (strpos($val, 'multipart/') === false)) { + $part = $this->getMIMEPart($key, array('nodecode' => true)); + $message->alterPart($key, $part); + } + } + } + + return $message; + } + } diff --git a/imp/lib/Message.php b/imp/lib/Message.php index 5b2219dcd..606b3d358 100644 --- a/imp/lib/Message.php +++ b/imp/lib/Message.php @@ -424,53 +424,54 @@ class IMP_Message * Strips one or all MIME parts out of a message. * Handles the IMP::SEARCH_MBOX mailbox. * - * @param IMP_Mailbox $imp_mailbox The IMP_Mailbox object with the - * current index set to the message to be - * processed. - * @param string $partid The MIME ID of the part to strip. All - * parts are stripped if null. + * @param mixed $indices See IMP::parseIndicesList(). + * @param string $partid The MIME ID of the part to strip. All parts are + * stripped if null. * * @return mixed Returns true on success, or PEAR_Error on error. */ - public function stripPart(&$imp_mailbox, $partid = null) + public function stripPart($indices, $partid = null) { global $imp_imap; /* Return error if no index was provided. */ - if (!($msgList = IMP::parseIndicesList($imp_mailbox))) { - return PEAR::raiseError('No index provided to IMP_Message::stripPart().'); + if (!($msgList = IMP::parseIndicesList($indices))) { + return PEAR::raiseError(_("An error occured while attempting to strip the attachment.")); } /* If more than one index provided, return error. */ reset($msgList); - list($folder, $index) = each($msgList); + list($mbox, $index) = each($msgList); if (each($msgList) || (count($index) > 1)) { - return PEAR::raiseError('More than 1 index provided to IMP_Message::stripPart().'); + return PEAR::raiseError(_("An error occured while attempting to strip the attachment.")); } $index = implode('', $index); - if ($imp_imap->isReadOnly($folder)) { - return PEAR::raiseError(_("Cannot strip the MIME part as the folder is read-only")); + if ($imp_imap->isReadOnly($mbox)) { + return PEAR::raiseError(_("Cannot strip the MIME part as the mailbox is read-only")); } /* Get a local copy of the message. */ - $contents = &IMP_Contents::singleton($index . IMP::IDX_SEP . $folder); - $contents->rebuildMessage(); - $message = $contents->getMIMEMessage(); + $contents = &IMP_Contents::singleton($index . IMP::IDX_SEP . $mbox); /* Loop through all to-be-stripped mime parts. */ if (is_null($partid)) { - // TODO - $partids = array_slice(array_keys($message->contentTypeMap()), 1); - } else { - /* Sanity checking: make sure part does not live under a - * message/rfc822 part. */ - if ($contents->isParent($partid, 'message/rfc822')) { - return PEAR::raiseError(_("Cannot strip a MIME part contained within a message/rfc822 part.")); + /* 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; } + } else { $partids = array($partid); } + $message = $contents->buildMessageContents($partids); + foreach ($partids as $partid) { $oldPart = $message->getPart($partid); if (!is_a($oldPart, 'Horde_Mime_Part')) { @@ -488,7 +489,7 @@ class IMP_Message /* Get the headers for the message. */ try { - $res = $GLOBALS['imp_imap']->ob->fetch($folder, array( + $res = $GLOBALS['imp_imap']->ob->fetch($mbox, array( Horde_Imap_Client::FETCH_HEADERTEXT => array(array('peek' => true)), Horde_Imap_Client::FETCH_ENVELOPE => true, Horde_Imap_Client::FETCH_FLAGS => true @@ -497,23 +498,24 @@ class IMP_Message /* If in Virtual Inbox, we need to reset flag to unseen so that it * appears again in the mailbox list. */ - if ($GLOBALS['imp_search']->isVINBOXFolder($imp_mailbox->getMailboxName()) && + if ($GLOBALS['imp_search']->isVINBOXFolder($mbox) && ($pos = array_search('\\seen', $res['flags']))) { unset($res['flags'][$pos]); } - $uid = $GLOBALS['imp_imap']->ob->append($folder, array(array('data' => $res['headertext'][0] . $contents->toString($message, true), 'flags' => $res['flags'], 'messageid' => $res['envelope']['message-id']))); - + $uid = $GLOBALS['imp_imap']->ob->append($mbox, array(array('data' => $res['headertext'][0] . $message->toString(false), 'flags' => $res['flags'], 'messageid' => $res['envelope']['message-id']))); } catch (Horde_Imap_Client_Exception $e) { return PEAR::raiseError(_("An error occured while attempting to strip the attachment.")); } - $this->delete($imp_mailbox, true, true); + $this->delete($indices, true, true); + + $imp_mailbox = &IMP_Mailbox::singleton($mbox); $imp_mailbox->setIndex(reset($uid)); /* We need to replace the old index in the query string with the * new index. */ - $_SERVER['QUERY_STRING'] = preg_replace('/' . $index . '/', $ids[0], $_SERVER['QUERY_STRING']); + $_SERVER['QUERY_STRING'] = preg_replace('/' . $index . '/', $reset($uid), $_SERVER['QUERY_STRING']); return true; } @@ -538,11 +540,9 @@ class IMP_Message return false; } - if ($action) { - $action_array = array('add' => $flags); - } else { - $action_array = array('remove' => $flags); - } + $action_array = $action + ? array('add' => $flags) + : array('remove' => $flags); foreach ($msgList as $mbox => $msgIndices) { if ($imp_imap->isReadOnly($mbox)) { @@ -575,21 +575,17 @@ class IMP_Message */ public function flagAllInMailbox($flags, $mboxes, $action = true) { - global $imp_imap; - if (empty($mboxes) || !is_array($mboxes)) { return false; } - if ($action) { - $action_array = array('add' => $flags); - } else { - $action_array = array('remove' => $flags); - } + $action_array = $action + ? array('add' => $flags) + : array('remove' => $flags); foreach ($mboxes as $val) { try { - $imp_imap->ob->store($val, $action_array); + $GLOBALS['imp_imap']->ob->store($val, $action_array); } catch (Horde_Imap_Client_Exception $e) { return false; } @@ -636,7 +632,7 @@ class IMP_Message try { $imp_imap->ob->expunge($key, array('ids' => is_array($val) ? $val : array())); - $imp_mailbox = &IMP_Mailbox::singleton($mbox); + $imp_mailbox = &IMP_Mailbox::singleton($key); if ($imp_mailbox->isBuilt()) { $imp_mailbox->removeMsgs(is_array($val) ? array($key => $val) : true); } diff --git a/imp/message.php b/imp/message.php index 82cc6e3c0..d5e9dec04 100644 --- a/imp/message.php +++ b/imp/message.php @@ -180,7 +180,7 @@ case 'add_address': case 'strip_all': case 'strip_attachment': $imp_message = &IMP_Message::singleton(); - $result = $imp_message->stripPart($imp_mailbox, ($actionID == 'strip_all') ? null : Util::getFormData('imapid')); + $result = $imp_message->stripPart($indices_array, ($actionID == 'strip_all') ? null : Util::getFormData('imapid')); if (is_a($result, 'PEAR_Error')) { $notification->push($result, 'horde.error'); } -- 2.11.0