/** * If this MIME part can contain embedded MIME part(s), and those part(s) * exist, return a representation of that data. * * @return mixed A Horde_Mime_Part object representing the embedded data. * Returns null if no embedded MIME part(s) exist. */ protected function _getEmbeddedMimeParts() { /* Get the data from the attachment. */ try { if (!($tnef = $this->getConfigParam('tnef'))) { $tnef = Horde_Compress::factory('Tnef'); $this->setConfigParam('tnef', $tnef); } $tnefData = $tnef->decompress($this->_mimepart->getContents()); } catch (Horde_Compress_Exception $e) { $tnefData = array(); } if (!count($tnefData)) { return null; } $mixed = new Horde_Mime_Part(); $mixed->setType('multipart/mixed'); reset($tnefData); while (list(, $data) = each($tnefData)) { $temp_part = new Horde_Mime_Part(); $temp_part->setName($data['name']); $temp_part->setDescription($data['name']); $temp_part->setContents($data['stream']); /* Short-circuit MIME-type guessing for winmail.dat parts; * we're showing enough entries for them already. */ $type = $data['type'] . '/' . $data['subtype']; if (in_array($type, array('application/octet-stream', 'application/base64'))) { $type = Horde_Mime_Magic::filenameToMIME($data['name']); } $temp_part->setType($type); $mixed->addPart($temp_part); } return $mixed; }
/** * Save an object in this folder. * * @param array $object The array that holds the data of the object. * @param int $data_version The format handler version. * @param string $object_type The type of the kolab object. * @param string $id The IMAP id of the old object if it * existed before * @param array $old_object The array that holds the current data of the * object. * * @return boolean True on success. */ public function saveObject(&$object, $data_version, $object_type, $id = null, &$old_object = null) { // Select folder $this->_driver->select($this->_path); $new_headers = new Horde_Mime_Headers(); $new_headers->setEOL("\r\n"); $formats = $this->getFormats(); $handlers = array(); foreach ($formats as $type) { $handlers[$type] =& Horde_Kolab_Format::factory($type, $object_type, $data_version); if (is_a($handlers[$type], 'PEAR_Error')) { if ($type == 'XML') { return $handlers[$type]; } Horde::log(sprintf('Loading format handler "%s" failed: %s', $type, $handlers[$type]->getMessage()), 'ERR'); continue; } } if ($id != null) { /** Update an existing kolab object */ if (!in_array($id, $this->_driver->getUids($this->_path))) { return PEAR::raiseError(sprintf(Horde_Kolab_Storage_Translation::t("The message with ID %s does not exist. This probably means that the Kolab object has been modified by somebody else while you were editing it. Your edits have been lost."), $id)); } /** Parse email and load Kolab format structure */ $result = $this->parseMessage($id, $handlers['XML']->getMimeType(), true, $formats); if (is_a($result, 'PEAR_Error')) { return $result; } list($old_message, $part_ids, $mime_message, $mime_headers) = $result; if (is_a($old_message, 'PEAR_Error')) { return $old_message; } if (isset($object['_attachments']) && isset($old_object['_attachments'])) { $attachments = array_keys($object['_attachments']); foreach (array_keys($old_object['_attachments']) as $attachment) { if (!in_array($attachment, $attachments)) { foreach ($mime_message->getParts() as $part) { if ($part->getName() === $attachment) { foreach (array_keys($mime_message->_parts) as $key) { if ($mime_message->_parts[$key]->getMimeId() == $part->getMimeId()) { unset($mime_message->_parts[$key]); break; } } $mime_message->_generateIdMap($mime_message->_parts); } } } } } $object = array_merge($old_object, $object); if (isset($attachments)) { foreach ($mime_message->getParts() as $part) { $name = $part->getName(); foreach ($attachments as $attachment) { if ($name === $attachment) { $object['_attachments'][$attachment]['id'] = $part->getMimeId(); } } } } /** Copy email header */ if (!empty($mime_headers) && !$mime_headers === false) { foreach ($mime_headers as $header => $value) { $new_headers->addheader($header, $value); } } } else { $mime_message = $this->_prepareNewMessage($new_headers); $mime_part_id = false; } if (isset($object['_attachments'])) { $attachments = array_keys($object['_attachments']); foreach ($attachments as $attachment) { $data = $object['_attachments'][$attachment]; if (!isset($data['content']) && !isset($data['path'])) { /** * There no new content and no new path. Do not rewrite the * attachment. */ continue; } $part = new Horde_Mime_Part(); $part->setType(isset($data['type']) ? $data['type'] : null); $part->setContents(isset($data['content']) ? $data['content'] : file_get_contents($data['path'])); $part->setCharset('UTF-8'); $part->setTransferEncoding('quoted-printable'); $part->setDisposition('attachment'); $part->setName($attachment); if (!isset($data['id'])) { $mime_message->addPart($part); } else { $mime_message->alterPart($data['id'], $part); } } } foreach ($formats as $type) { $new_content = $handlers[$type]->save($object); if (is_a($new_content, 'PEAR_Error')) { return $new_content; } /** Update mime part */ $part = new Horde_Mime_Part(); $part->setType($handlers[$type]->getMimeType()); $part->setContents($new_content); $part->setCharset('UTF-8'); $part->setTransferEncoding('quoted-printable'); $part->setDisposition($handlers[$type]->getDisposition()); $part->setDispositionParameter('x-kolab-type', $type); $part->setName($handlers[$type]->getName()); if (!isset($part_ids) || $part_ids[$type] === false) { $mime_message->addPart($part); } else { $mime_message->alterPart($part_ids[$type], $part); } } // Update email headers $new_headers->addHeader('From', $this->_driver->getAuth()); $new_headers->addHeader('To', $this->_driver->getAuth()); $new_headers->addHeader('Date', date('r')); $new_headers->addHeader('X-Kolab-Type', $handlers['XML']->getMimeType()); $new_headers->addHeader('Subject', $object['uid']); $new_headers->addHeader('User-Agent', 'Horde::Kolab::Storage v0.2'); $new_headers->addHeader('MIME-Version', '1.0'); $mime_message->addMimeHeaders(array('headers' => $new_headers)); $msg = $new_headers->toString() . $mime_message->toString(array('canonical' => true, 'headers' => false)); // delete old email? if ($id != null) { $this->_driver->deleteMessages($this->_path, $id); } // store new email try { $result = $this->_driver->appendMessage($this->_path, $msg); } catch (Horde_Kolab_Storage_Exception $e) { if ($id != null) { $this->_driver->undeleteMessages($id); } } // remove deleted object if ($id != null) { $this->_driver->expunge($this->_path); } }
/** * Scan text for UUencode data an, if it exists, convert the part to the * embedded MIME representation. * * @return mixed See self::_getEmbeddedMimeParts(). */ protected function _parseUUencode() { $text = Horde_String::convertCharset($this->_mimepart->getContents(), $this->_mimepart->getCharset(), 'UTF-8'); $files = Horde_Mime::uudecode($text); if (empty($files)) { return null; } $new_part = new Horde_Mime_Part(); $new_part->setType('multipart/mixed'); $text_part = new Horde_Mime_Part(); $text_part->setType('text/plain'); $text_part->setCharset($this->getConfigParam('charset')); $text_part->setContents(preg_replace("/begin [0-7]{3} .+\r?\n.+\r?\nend/Us", "\n", $text)); $new_part->addPart($text_part); reset($files); while (list(, $file) = each($files)) { $uupart = new Horde_Mime_Part(); $uupart->setType('application/octet-stream'); $uupart->setContents($file['data']); $uupart->setName(strip_tags($file['name'])); $new_part->addPart($uupart); } return $new_part; }
/** * Prints a descriptive blurb at the end of directory listings. * * @param Luxor_File $files An instance of Luxor_File. * @param string $path The directory where to look for a README file. */ function dirDesc($files, $path) { $table_head = '<br /><br /><table width="100%" cellpadding="5"><tr><td class="text"><span class="fixed">'; $table_foot = '</span></td></tr></table>'; if (file_exists($filename = $files->toReal($path . '/README')) || file_exists($filename = $files->toReal($path . '/README.txt'))) { $contents = file_get_contents($filename); return $table_head . $GLOBALS['injector']->getInstance('Horde_Core_Factory_TextFilter')->filter($contents, 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO)) . $table_foot; } elseif ($filename = file_exists($files->toReal($path . '/README.html'))) { global $mime_drivers, $mime_drivers_map; $result = Horde::loadConfiguration('mime_drivers.php', array('mime_drivers', 'mime_drivers_map'), 'horde'); extract($result); $result = Horde::loadConfiguration('mime_drivers.php', array('mime_drivers', 'mime_drivers_map'), 'luxor'); $mime_drivers = array_replace_recursive($mime_drivers, $result['mime_drivers']); $mime_drivers_map = array_replace_recursive($mime_drivers_map, $result['mime_drivers_map']); $contents = file_get_contents($filename); $mime_part = new Horde_Mime_Part('text/plain', $contents); $mime_part->setName('README'); return $table_head . $GLOBALS['injector']->getInstance('Horde_Core_Factory_MimeViewer')->create($mime_part)->render() . $table_foot; } }
/** * Sends out iTip task notification to the assignee. * * Can be used to send task invitations, updates, and cancellations. * * @param Nag_Task $task The task in question. * @param Horde_Notification_Handler $notification * A notification object used to show result status. * @param integer $action * The type of notification to send. One of the Nag::ITIP_* values. * @param Horde_Date $instance * If cancelling a single instance of a recurring task, the date of * this instance. * @param string $range The range parameter if this is a recurring event. * Possible values are self::RANGE_THISANDFUTURE */ public static function sendITipNotifications(Nag_Task $task, Horde_Notification_Handler $notification, $action, Horde_Date $instance = null, $range = null) { global $injector, $registry, $nag_shares; if (!$task->assignee) { return; } $ident = $injector->getInstance('Horde_Core_Factory_Identity')->create($task->creator); if (!$ident->getValue('from_addr')) { $notification->push(sprintf(_("You do not have an email address configured in your Personal Information Preferences. You must set one %shere%s before event notifications can be sent."), $registry->getServiceLink('prefs', 'kronolith')->add(array('app' => 'horde', 'group' => 'identities'))->link(), '</a>'), 'horde.error', array('content.raw')); return; } // Generate image mime part first and only once, because we // need the Content-ID. $image = self::getImagePart('big_invitation.png'); $share = $nag_shares->getShare($task->tasklist); $view = new Horde_View(array('templatePath' => NAG_TEMPLATES . '/itip')); new Horde_View_Helper_Text($view); $view->identity = $ident; $view->task = $task; $view->imageId = $image->getContentId(); $email = Nag::getUserEmail($task->assignee); if (strpos($email, '@') === false) { continue; } /* Determine all notification-specific strings. */ $method = 'REQUEST'; switch ($action) { case self::ITIP_CANCEL: /* Cancellation. */ $method = 'CANCEL'; $filename = 'task-cancellation.ics'; $view->subject = sprintf(_("Cancelled: %s"), $task->name); if (empty($instance)) { $view->header = sprintf(_("%s has cancelled \"%s\"."), $ident->getName(), $task->name); } else { $view->header = sprintf(_("%s has cancelled an instance of the recurring \"%s\"."), $ident->getName(), $task->name); } break; case self::ITIP_UPDATE: if (!empty($task->organizer) && $task->organizer != Nag::getUserEmail($task->creator)) { // Sending a progress update. $method = 'REPLY'; } else { $method = 'UPDATE'; } case self::ITIP_REQUEST: default: if (empty($task->status) || $task->status == self::RESPONSE_NONE) { /* Invitation. */ $filename = 'task-invitation.ics'; $view->subject = $task->name; $view->header = sprintf(_("%s wishes to make you aware of \"%s\"."), $ident->getName(), $task->name); } else { $filename = 'task-update.ics'; $view->subject = sprintf(_("Updated: %s."), $task->name); $view->header = sprintf(_("%s wants to notify you about changes of \"%s\"."), $ident->getName(), $task->name); } break; } $view->attendees = $email; $view->organizer = empty($task->organizer) ? $registry->convertUserName($task->creator, false) : $task->organizer; /* Build the iCalendar data */ $iCal = new Horde_Icalendar(); $iCal->setAttribute('METHOD', $method); $vevent = $task->toiCalendar($iCal); $iCal->addComponent($vevent); /* text/calendar part */ $ics = new Horde_Mime_Part(); $ics->setType('text/calendar'); $ics->setContents($iCal->exportvCalendar()); $ics->setName($filename); $ics->setContentTypeParameter('METHOD', $method); $ics->setCharset('UTF-8'); $ics->setEOL("\r\n"); /* application/ics part */ $ics2 = clone $ics; $ics2->setType('application/ics'); /* multipart/mixed part */ $multipart = new Horde_Mime_Part(); $multipart->setType('multipart/mixed'); $inner = self::buildMimeMessage($view, 'notification', $image); $inner->addPart($ics); $multipart->addPart($inner); $multipart->addPart($ics2); $recipient = $method != 'REPLY' ? new Horde_Mail_Rfc822_Address($email) : new Horde_Mail_Rfc822_Address($task->organizer); $mail = new Horde_Mime_Mail(array('Subject' => $view->subject, 'To' => $recipient, 'From' => $ident->getDefaultFromAddress(true), 'User-Agent' => 'Nag ' . $registry->getVersion())); $mail->setBasePart($multipart); try { $mail->send($injector->getInstance('Horde_Mail')); $notification->push(sprintf(_("The task request notification to %s was successfully sent."), $recipient), 'horde.success'); } catch (Horde_Mime_Exception $e) { $notification->push(sprintf(_("There was an error sending a task request notification to %s: %s"), $recipient, $e->getMessage(), $e->getCode()), 'horde.error'); } }
/** * Convert a TNEF attachment into a multipart/mixed part. * * @param integer|Horde_Mime_part $data Either a mime part id or a * Horde_Mime_Part object containing * the TNEF attachment. * * @return Horde_Mime_Part The multipart/mixed MIME part containing any * attachment data we can decode. */ protected function _decodeTnefData($data) { $wrapper = new Horde_Mime_Part(); $wrapper->setType('multipart/mixed'); if (!$data instanceof Horde_Mime_Part) { $mime_part = $this->getMimePart($data); } else { $mime_part = $data; } $tnef_parser = Horde_Compress::factory('Tnef'); try { $tnef_data = $tnef_parser->decompress($mime_part->getContents()); } catch (Horde_Compress_Exception $e) { return false; } if (!count($tnef_data)) { return false; } reset($tnef_data); while (list(, $data) = each($tnef_data)) { $tmp_part = new Horde_Mime_Part(); $tmp_part->setName($data['name']); $tmp_part->setDescription($data['name']); $tmp_part->setContents($data['stream']); $type = $data['type'] . '/' . $data['subtype']; if (in_array($type, array('application/octet-stream', 'application/base64'))) { $type = Horde_Mime_Magic::filenameToMIME($data['name']); } $tmp_part->setType($type); $wrapper->addPart($tmp_part); } return $wrapper; }
/** * Embed the Kolab content into a new MIME Part. * * @param resource $content The Kolab content. * * @return Horde_Mime_Part The MIME part that encapsules the Kolab content. */ protected function createFreshKolabPart($content) { $part = new Horde_Mime_Part(); $part->setCharset('utf-8'); $part->setDisposition('inline'); $part->setDispositionParameter('x-kolab-type', 'xml'); $part->setName('kolab.xml'); $part->setType(Horde_Kolab_Storage_Object_MimeType::getMimeTypeFromObjectType($this->getType())); $part->setContents($content, array('encoding' => 'quoted-printable')); return $part; }
/** * Adds an attachment to the outgoing compose message. * * @param string $atc_file Temporary file containing attachment contents. * @param integer $bytes Size of data, in bytes. * @param string $filename Filename of data. * @param string $type MIME type of data. * * @return IMP_Compose_Attachment Attachment object. * @throws IMP_Compose_Exception */ protected function _addAttachment($atc_file, $bytes, $filename, $type) { global $conf, $injector; $atc = new Horde_Mime_Part(); $atc->setBytes($bytes); /* Try to determine the MIME type from 1) the extension and * then 2) analysis of the file (if available). */ if (strlen($filename)) { $atc->setName($filename); if ($type == 'application/octet-stream') { $type = Horde_Mime_Magic::filenameToMIME($filename, false); } } $atc->setType($type); if ($atc->getType() == 'application/octet-stream' || $atc->getPrimaryType() == 'text') { $analyze = Horde_Mime_Magic::analyzeFile($atc_file, empty($conf['mime']['magic_db']) ? null : $conf['mime']['magic_db'], array('nostrip' => true)); $atc->setCharset('UTF-8'); if ($analyze) { $ctype = new Horde_Mime_Headers_ContentParam('Content-Type', $analyze); $atc->setType($ctype->value); if (isset($ctype->params['charset'])) { $atc->setCharset($ctype->params['charset']); } } } else { $atc->setHeaderCharset('UTF-8'); } $atc_ob = new IMP_Compose_Attachment($this, $atc, $atc_file); /* Check for attachment size limitations. */ $size_limit = null; if ($atc_ob->linked) { if (!empty($conf['compose']['link_attach_size_limit'])) { $linked = true; $size_limit = 'link_attach_size_limit'; } } elseif (!empty($conf['compose']['attach_size_limit'])) { $linked = false; $size_limit = 'attach_size_limit'; } if (!is_null($size_limit)) { $total_size = $conf['compose'][$size_limit] - $bytes; foreach ($this as $val) { if ($val->linked == $linked) { $total_size -= $val->getPart()->getBytes(); } } if ($total_size < 0) { throw new IMP_Compose_Exception(strlen($filename) ? sprintf(_("Attached file \"%s\" exceeds the attachment size limits. File NOT attached."), $filename) : _("Attached file exceeds the attachment size limits. File NOT attached.")); } } try { $injector->getInstance('Horde_Core_Hooks')->callHook('compose_attachment', 'imp', array($atc_ob)); } catch (Horde_Exception_HookNotSet $e) { } $this->_atc[$atc_ob->id] = $atc_ob; $this->changed = 'changed'; return $atc_ob; }
/** * Sends out iTip event notifications to all attendees of a specific * event. * * Can be used to send event invitations, event updates as well as event * cancellations. * * @param Kronolith_Event $event * The event in question. * @param Horde_Notification_Handler $notification * A notification object used to show result status. * @param integer $action * The type of notification to send. One of the Kronolith::ITIP_* * values. * @param Horde_Date $instance * If cancelling a single instance of a recurring event, the date of * this instance. * @param string $range The range parameter if this is a recurring event. * Possible values are self::RANGE_THISANDFUTURE * @param array $cancellations If $action is 'CANCEL', but it is due to * removing attendees and not canceling the * entire event, these are the email addresses * of the uninvited attendees and are the ONLY * people that will receive the CANCEL iTIP. * @since 4.2.10 * */ public static function sendITipNotifications(Kronolith_Event $event, Horde_Notification_Handler $notification, $action, Horde_Date $instance = null, $range = null, array $cancellations = array()) { global $injector, $registry; if (!$event->attendees) { return; } $ident = $injector->getInstance('Horde_Core_Factory_Identity')->create($event->creator); if (!$ident->getValue('from_addr')) { $notification->push(sprintf(_("You do not have an email address configured in your Personal Information Preferences. You must set one %shere%s before event notifications can be sent."), $registry->getServiceLink('prefs', 'kronolith')->add(array('app' => 'horde', 'group' => 'identities'))->link(), '</a>'), 'horde.error', array('content.raw')); return; } // Generate image mime part first and only once, because we // need the Content-ID. $image = self::getImagePart('big_invitation.png'); $share = $injector->getInstance('Kronolith_Shares')->getShare($event->calendar); $view = new Horde_View(array('templatePath' => KRONOLITH_TEMPLATES . '/itip')); new Horde_View_Helper_Text($view); $view->identity = $ident; $view->event = $event; $view->imageId = $image->getContentId(); if ($action == self::ITIP_CANCEL && !empty($cancellations)) { $mail_attendees = $cancellations; } else { $mail_attendees = $event->attendees; } foreach ($mail_attendees as $email => $status) { /* Don't bother sending an invitation/update if the recipient does * not need to participate, or has declined participating, or * doesn't have an email address. */ if (strpos($email, '@') === false || $status['response'] == self::RESPONSE_DECLINED) { continue; } /* Determine all notification-specific strings. */ switch ($action) { case self::ITIP_CANCEL: /* Cancellation. */ $method = 'CANCEL'; $filename = 'event-cancellation.ics'; $view->subject = sprintf(_("Cancelled: %s"), $event->getTitle()); if (empty($instance)) { $view->header = sprintf(_("%s has cancelled \"%s\"."), $ident->getName(), $event->getTitle()); } else { $view->header = sprintf(_("%s has cancelled an instance of the recurring \"%s\"."), $ident->getName(), $event->getTitle()); } break; case self::ITIP_REQUEST: default: $method = 'REQUEST'; if ($status['response'] == self::RESPONSE_NONE) { /* Invitation. */ $filename = 'event-invitation.ics'; $view->subject = $event->getTitle(); $view->header = sprintf(_("%s wishes to make you aware of \"%s\"."), $ident->getName(), $event->getTitle()); } else { /* Update. */ $filename = 'event-update.ics'; $view->subject = sprintf(_("Updated: %s."), $event->getTitle()); $view->header = sprintf(_("%s wants to notify you about changes of \"%s\"."), $ident->getName(), $event->getTitle()); } break; } $view->attendees = strval(self::getAttendeeEmailList($event->attendees)); $view->organizer = $registry->convertUserName($event->creator, false); if ($action == self::ITIP_REQUEST) { $attend_link = Horde::url('attend.php', true, -1)->add(array('c' => $event->calendar, 'e' => $event->id, 'u' => $email)); $view->linkAccept = (string) $attend_link->add('a', 'accept'); $view->linkTentative = (string) $attend_link->add('a', 'tentative'); $view->linkDecline = (string) $attend_link->add('a', 'decline'); } /* Build the iCalendar data */ $iCal = new Horde_Icalendar(); $iCal->setAttribute('METHOD', $method); $iCal->setAttribute('X-WR-CALNAME', $share->get('name')); $vevent = $event->toiCalendar($iCal); if ($action == self::ITIP_CANCEL && !empty($instance)) { // Recurring event instance deletion, need to specify the // RECURRENCE-ID but NOT the EXDATE. foreach ($vevent as &$ve) { try { $uid = $ve->getAttribute('UID'); } catch (Horde_Icalendar_Exception $e) { continue; } if ($event->uid == $uid) { $ve->setAttribute('RECURRENCE-ID', $instance); if (!empty($range)) { $ve->setParameter('RECURRENCE-ID', array('RANGE' => $range)); } $ve->setAttribute('DTSTART', $instance, array(), false); $diff = $event->end->timestamp() - $event->start->timestamp(); $end = clone $instance; $end->sec += $diff; $ve->setAttribute('DTEND', $end, array(), false); $ve->removeAttribute('EXDATE'); break; } } } $iCal->addComponent($vevent); /* text/calendar part */ $ics = new Horde_Mime_Part(); $ics->setType('text/calendar'); $ics->setContents($iCal->exportvCalendar()); $ics->setName($filename); $ics->setContentTypeParameter('method', $method); $ics->setCharset('UTF-8'); $ics->setEOL("\r\n"); /* application/ics part */ $ics2 = clone $ics; $ics2->setType('application/ics'); /* multipart/mixed part */ $multipart = new Horde_Mime_Part(); $multipart->setType('multipart/mixed'); $inner = self::buildMimeMessage($view, 'notification', $image); $inner->addPart($ics); $multipart->addPart($inner); $multipart->addPart($ics2); $recipient = new Horde_Mail_Rfc822_Address($email); if (!empty($status['name'])) { $recipient->personal = $status['name']; } $mail = new Horde_Mime_Mail(array('Subject' => $view->subject, 'To' => $recipient, 'From' => $ident->getDefaultFromAddress(true), 'User-Agent' => 'Kronolith ' . $registry->getVersion())); $mail->setBasePart($multipart); try { $mail->send($injector->getInstance('Horde_Mail')); $notification->push(sprintf(_("The event notification to %s was successfully sent."), $recipient), 'horde.success'); } catch (Horde_Mime_Exception $e) { $notification->push(sprintf(_("There was an error sending an event notification to %s: %s"), $recipient, $e->getMessage(), $e->getCode()), 'horde.error'); } } }
public function testNullCharactersNotAllowedInMimeHeaderData() { $part = new Horde_Mime_Part(); $part->setType("text/plain"); $this->assertEquals('text/plain', $part->getType()); $part->setDisposition("inline"); $this->assertEquals('inline', $part->getDisposition()); $part->setDispositionParameter('size', '123' . "" . '456'); $this->assertEquals(123456, $part->getDispositionParameter('size')); $part->setDispositionParameter('foo', "foobar"); $this->assertEquals('foobar', $part->getDispositionParameter('foo')); $part->setCharset("utf-8"); $this->assertEquals('utf-8', $part->getCharset()); $part->setName("foobar"); $this->assertEquals('foobar', $part->getName()); $this->assertEquals('foobar', $part->getDispositionParameter('filename')); $this->assertEquals('foobar', $part->getContentTypeParameter('name')); $part->setLanguage("en"); $this->assertEquals(array('en'), $part->getLanguage()); $part->setLanguage(array("en", "de")); $this->assertEquals(array('en', 'de'), $part->getLanguage()); $part->setDuration('123' . "" . '456'); $this->assertEquals(123456, $part->getDuration()); $part->setBytes('123' . "" . '456'); $this->assertEquals(123456, $part->getBytes()); $part->setDescription("foobar"); $this->assertEquals('foobar', $part->getDescription()); $part->setContentTypeParameter('foo', "foobar"); $this->assertEquals('foobar', $part->getContentTypeParameter('foo')); $part->setContentId("foobar"); $this->assertEquals('foobar', $part->getContentId()); }
throw new Horde_Exception(sprintf(_("You are not allowed to view ticket %d."), $id)); } try { $vfs = $injector->getInstance('Horde_Core_Factory_Vfs')->create(); } catch (Horde_Exception $e) { throw new Horde_Exception(_("The VFS backend needs to be configured to enable attachment uploads.")); } try { $data = $vfs->read(Whups::VFS_ATTACH_PATH . '/' . $id, $filename); } catch (Horde_Vfs_Exception $e) { throw Horde_Exception(sprintf(_("Access denied to %s"), $filename)); } $mime_part = new Horde_Mime_Part(); $mime_part->setType(Horde_Mime_Magic::extToMime($type)); $mime_part->setContents($data); $mime_part->setName($filename); // We don't know better. $mime_part->setCharset('US-ASCII'); $ret = $injector->getInstance('Horde_Core_Factory_MimeViewer')->create($mime_part)->render('full'); reset($ret); $key = key($ret); if (empty($ret)) { $browser->downloadHeaders($filename, null, false, strlen($data)); echo $data; } elseif (strpos($ret[$key]['type'], 'text/html') !== false) { $page_output->topbar = $page_output->sidebar = false; $page_output->header(); echo $ret[$key]['data']; $page_output->footer(); } else { $browser->downloadHeaders($filename, $ret[$key]['type'], true, strlen($ret[$key]['data']));
function printfile_raw($pathname) { global $mime_drivers, $mime_drivers_map; $result = Horde::loadConfiguration('mime_drivers.php', array('mime_drivers', 'mime_drivers_map'), 'horde'); extract($result); $result = Horde::loadConfiguration('mime_drivers.php', array('mime_drivers', 'mime_drivers_map'), 'luxor'); if (isset($result['mime_drivers'])) { $mime_drivers = array_replace_recursive($mime_drivers, $result['mime_drivers']); } if (isset($result['mime_drivers_map'])) { $mime_drivers_map = array_replace_recursive($mime_drivers_map, $result['mime_drivers_map']); } $filename = $GLOBALS['files']->toReal($pathname); $data = file_get_contents($filename); $mime_part = new Horde_Mime_Part(Horde_Mime_Magic::filenameToMime($pathname), $data); $mime_part->setName($pathname); $viewer = $GLOBALS['injector']->getInstance('Horde_Core_Factory_MimeViewer')->create($mime_part); if ($viewer->getType() == 'text/plain') { return '<pre class="fixed">' . htmlspecialchars($viewer->render()) . '</pre>'; } else { return $viewer->render(); } }
<?php $part1 = new Horde_Mime_Part(); $part1->setType('text/plain'); $part1->setTransferEncoding('quoted-printable'); $part1->setCharset('UTF-8'); $part1->setDisposition('inline'); $part1->setBytes(249); $part2 = new Horde_Mime_Part(); $part2->setType('application/x-vnd.kolab.note'); $part2->setTransferEncoding('quoted-printable'); $part2->setName('kolab.xml'); $part2->setDisposition('attachment'); $part2->setBytes(704); $message = new Horde_Mime_Part(); $message->setType('multipart/mixed'); $message->addPart($part1); $message->addPart($part2); $message->buildMimeIds(0); return $message;
protected function _setIcsFilename(Horde_Mime_Part &$message) { $message->setName('event-reply.ics'); }
$stream = null; $data = ''; try { if (is_callable(array($gollem_vfs, 'readStream'))) { $stream = $gollem_vfs->readStream($vars->dir, $vars->file); } else { $data = $gollem_vfs->read($vars->dir, $vars->file); } } catch (Horde_Vfs_Exception $e) { Horde::log($e, 'NOTICE'); throw $e; } $mime_part = new Horde_Mime_Part(); $mime_part->setType(Horde_Mime_Magic::extToMime($vars->type)); $mime_part->setContents(is_resource($stream) ? $stream : $data); $mime_part->setName($vars->file); // We don't know better. $mime_part->setCharset('US-ASCII'); $ret = $injector->getInstance('Horde_Core_Factory_MimeViewer')->create($mime_part)->render('full'); reset($ret); $key = key($ret); try { $size = $gollem_vfs->size($vars->dir, $vars->file); } catch (Horde_Vfs_Exception $e) { $size = null; } if (empty($ret)) { $browser->downloadHeaders($vars->file, null, false, $size); if (is_resource($stream)) { fseek($stream, 0); while ($buffer = fread($stream, 8192)) {
/** * Variables required in form input: * - identity (TODO: ? Code uses it, but it is never set anywhere) * - imple_submit: itip_action(s) * - mime_id * - muid * * @return boolean True on success. */ protected function _handle(Horde_Variables $vars) { global $injector, $notification, $registry; $actions = (array) $vars->imple_submit; $result = false; $vCal = new Horde_Icalendar(); /* Retrieve the calendar data from the message. */ try { $contents = $injector->getInstance('IMP_Factory_Contents')->create(new IMP_Indices_Mailbox($vars)); $mime_part = $contents->getMIMEPart($vars->mime_id); if (empty($mime_part)) { throw new IMP_Exception(_("Cannot retrieve calendar data from message.")); } elseif (!$vCal->parsevCalendar($mime_part->getContents(), 'VCALENDAR', $mime_part->getCharset())) { throw new IMP_Exception(_("The calendar data is invalid")); } $components = $vCal->getComponents(); } catch (Exception $e) { $notification->push($e, 'horde.error'); $actions = array(); } foreach ($actions as $key => $action) { $pos = strpos($key, '['); $key = substr($key, $pos + 1, strlen($key) - $pos - 2); switch ($action) { case 'delete': // vEvent cancellation. if ($registry->hasMethod('calendar/delete')) { $guid = $components[$key]->getAttribute('UID'); $recurrenceId = null; try { // This is a cancellation of a recurring event instance. $recurrenceId = $components[$key]->getAttribute('RECURRENCE-ID'); $atts = $components[$key]->getAttribute('RECURRENCE-ID', true); $range = null; foreach ($atts as $att) { if (array_key_exists('RANGE', $att)) { $range = $att['RANGE']; } } } catch (Horde_Icalendar_Exception $e) { } try { $registry->call('calendar/delete', array($guid, $recurrenceId, $range)); $notification->push(_("Event successfully deleted."), 'horde.success'); $result = true; } catch (Horde_Exception $e) { $notification->push(sprintf(_("There was an error deleting the event: %s"), $e->getMessage()), 'horde.error'); } } else { $notification->push(_("This action is not supported."), 'horde.warning'); } break; case 'update': // vEvent reply. if ($registry->hasMethod('calendar/updateAttendee')) { try { $from = $contents->getHeader()->getOb('from'); $registry->call('calendar/updateAttendee', array($components[$key], $from[0]->bare_address)); $notification->push(_("Respondent Status Updated."), 'horde.success'); $result = true; } catch (Horde_Exception $e) { $notification->push(sprintf(_("There was an error updating the event: %s"), $e->getMessage()), 'horde.error'); } } else { $notification->push(_("This action is not supported."), 'horde.warning'); } break; case 'import': case 'accept-import': // vFreebusy reply. // vFreebusy publish. // vEvent request. // vEvent publish. // vTodo publish. // vJournal publish. switch ($components[$key]->getType()) { case 'vEvent': $result = $this->_handlevEvent($key, $components, $mime_part); // Must check for exceptions. foreach ($components as $k => $component) { try { if ($component->getType() == 'vEvent' && $component->getAttribute('RECURRENCE-ID')) { $uid = $component->getAttribute('UID'); if ($uid == $components[$key]->getAttribute('UID')) { $this->_handlevEvent($k, $components, $mime_part); } } } catch (Horde_Icalendar_Exception $e) { } } break; case 'vFreebusy': // Import into Kronolith. if ($registry->hasMethod('calendar/import_vfreebusy')) { try { $registry->call('calendar/import_vfreebusy', array($components[$key])); $notification->push(_("The user's free/busy information was sucessfully stored."), 'horde.success'); $result = true; } catch (Horde_Exception $e) { $notification->push(sprintf(_("There was an error importing user's free/busy information: %s"), $e->getMessage()), 'horde.error'); } } else { $notification->push(_("This action is not supported."), 'horde.warning'); } break; case 'vTodo': // Import into Nag. if ($registry->hasMethod('tasks/import')) { try { $guid = $registry->call('tasks/import', array($components[$key], $mime_part->getType())); $url = Horde::url($registry->link('tasks/show', array('uid' => $guid))); $notification->push(_("The task has been added to your tasklist.") . ' ' . Horde::link($url, _("View task"), null, '_blank') . Horde_Themes_Image::tag('mime/icalendar.png', array('alt' => _("View task"))) . '</a>', 'horde.success', array('content.raw')); $result = true; } catch (Horde_Exception $e) { $notification->push(sprintf(_("There was an error importing the task: %s"), $e->getMessage()), 'horde.error'); } } else { $notification->push(_("This action is not supported."), 'horde.warning'); } break; case 'vJournal': default: $notification->push(_("This action is not supported."), 'horde.warning'); } if ($action == 'import') { break; } // Fall-through for 'accept-import' // Fall-through for 'accept-import' case 'accept': case 'deny': case 'tentative': // vEvent request. if (isset($components[$key]) && $components[$key]->getType() == 'vEvent') { $vEvent = $components[$key]; $resource = new Horde_Itip_Resource_Identity($injector->getInstance('IMP_Identity'), $vEvent->getAttribute('ATTENDEE'), $vars->identity); switch ($action) { case 'accept': case 'accept-import': $type = new Horde_Itip_Response_Type_Accept($resource); break; case 'deny': $type = new Horde_Itip_Response_Type_Decline($resource); break; case 'tentative': $type = new Horde_Itip_Response_Type_Tentative($resource); break; } try { // Send the reply. Horde_Itip::factory($vEvent, $resource)->sendMultiPartResponse($type, new Horde_Core_Itip_Response_Options_Horde('UTF-8', array()), $injector->getInstance('IMP_Mail')); $notification->push(_("Reply Sent."), 'horde.success'); $result = true; } catch (Horde_Itip_Exception $e) { $notification->push(sprintf(_("Error sending reply: %s."), $e->getMessage()), 'horde.error'); } } else { $notification->push(_("This action is not supported."), 'horde.warning'); } break; case 'send': case 'reply': case 'reply2m': // vfreebusy request. if (isset($components[$key]) && $components[$key]->getType() == 'vFreebusy') { $vFb = $components[$key]; // Get the organizer details. try { $organizer = parse_url($vFb->getAttribute('ORGANIZER')); } catch (Horde_Icalendar_Exception $e) { break; } $organizerEmail = $organizer['path']; $organizer = $vFb->getAttribute('ORGANIZER', true); $organizerFullEmail = new Horde_Mail_Rfc822_Address($organizerEmail); if (isset($organizer['cn'])) { $organizerFullEmail->personal = $organizer['cn']; } if ($action == 'reply2m') { $startStamp = time(); $endStamp = $startStamp + 60 * 24 * 3600; } else { try { $startStamp = $vFb->getAttribute('DTSTART'); } catch (Horde_Icalendar_Exception $e) { $startStamp = time(); } try { $endStamp = $vFb->getAttribute('DTEND'); } catch (Horde_Icalendar_Exception $e) { } if (!$endStamp) { try { $duration = $vFb->getAttribute('DURATION'); $endStamp = $startStamp + $duration; } catch (Horde_Icalendar_Exception $e) { $endStamp = $startStamp + 60 * 24 * 3600; } } } $vfb_reply = $registry->call('calendar/getFreeBusy', array($startStamp, $endStamp)); // Find out who we are and update status. $identity = $injector->getInstance('IMP_Identity'); $email = $identity->getFromAddress(); // Build the reply. $msg_headers = new Horde_Mime_Headers(); $vCal = new Horde_Icalendar(); $vCal->setAttribute('PRODID', '-//The Horde Project//' . $msg_headers->getUserAgent() . '//EN'); $vCal->setAttribute('METHOD', 'REPLY'); $vCal->addComponent($vfb_reply); $message = _("Attached is a reply to a calendar request you sent."); $body = new Horde_Mime_Part(); $body->setType('text/plain'); $body->setCharset('UTF-8'); $body->setContents(Horde_String::wrap($message, 76)); $ics = new Horde_Mime_Part(); $ics->setType('text/calendar'); $ics->setCharset('UTF-8'); $ics->setContents($vCal->exportvCalendar()); $ics->setName('icalendar.ics'); $ics->setContentTypeParameter('METHOD', 'REPLY'); $mime = new Horde_Mime_Part(); $mime->addPart($body); $mime->addPart($ics); // Build the reply headers. $msg_headers->addReceivedHeader(array('dns' => $injector->getInstance('Net_DNS2_Resolver'), 'server' => $conf['server']['name'])); $msg_headers->addMessageIdHeader(); $msg_headers->addHeader('Date', date('r')); $msg_headers->addHeader('From', $email); $msg_headers->addHeader('To', $organizerFullEmail); $identity->setDefault($vars->identity); $replyto = $identity->getValue('replyto_addr'); if (!empty($replyto) && !$email->match($replyto)) { $msg_headers->addHeader('Reply-To', $replyto); } $msg_headers->addHeader('Subject', _("Free/Busy Request Response")); // Send the reply. try { $mime->send($organizerEmail, $msg_headers, $injector->getInstance('IMP_Mail')); $notification->push(_("Reply Sent."), 'horde.success'); $result = true; } catch (Exception $e) { $notification->push(sprintf(_("Error sending reply: %s."), $e->getMessage()), 'horde.error'); } } else { $notification->push(_("Invalid Action selected for this component."), 'horde.warning'); } break; case 'nosup': // vFreebusy request. // vFreebusy request. default: $notification->push(_("This action is not supported."), 'horde.warning'); break; } } return $result; }
protected function _handleAttachments() { // New attachments foreach ($this->_draftMessage->airsyncbaseattachments as $atc) { switch (get_class($atc)) { case 'Horde_ActiveSync_Message_AirSyncBaseAdd': $atc_mime = new Horde_Mime_Part(); $atc_mime->setType($atc->contenttype); $atc_mime->setName($atc->displayname); $atc_mime->setContents($atc->content); $this->_atcAdd[] = $atc_mime; break; case 'Horde_ActiveSync_Message_AirSyncBaseDelete': list($mailbox, $uid, $part) = explode(':', $atc->filereference, 3); $this->_atcDelete[] = $part; } } }