- - Merge with Horde Imp
+ - Merge with Horde Imp (Changes [Horde]: Extended message body; improved From, Changes [Kolab]: Do not automatically set the sequence attribute to 0 if it does not exist -> http://bugs.horde.org/ticket/4863; use lower case mailto -> http://bugs.horde.org/ticket/4872; Missing UID in the vEvent causes failure;
- Complete unit testing
*
* @param Horde_Itip_Response $response The iTip response.
*/
- public function __construct(
- Horde_Itip_Response $response
- ) {
+ public function __construct(Horde_Itip_Response $response)
+ {
$this->_response = $response;
}
/**
+ * Return the organizer mail address.
+ *
+ * @return string The mail address of the event organizer
+ */
+ public function getOrganizer()
+ {
+ return $this->_response->getRequest()->getOrganizer();
+ }
+
+ /**
* Return the response as an iCalendar vEvent object.
*
* @param Horde_Itip_Response_Type $type The response type.
* @param string $product_id The ID that should be set
* as the iCalendar product
* id.
- * @param string $subject_comment An optional comment on
- * the subject line.
- *
* @return array A list of two object: The mime headers and the mime
* message.
*/
public function getMessageResponse(
Horde_Itip_Response_Type $type,
- $product_id,
- $subject_comment = null
+ $product_id
) {
return $this->_response->getMessage(
- $type, $product_id, $subject_comment
+ $type, $product_id
+ );
+ }
+
+ /**
+ * Send the invitation response as a multi part MIME message.
+ *
+ * @param Horde_Itip_Response_Type $type The response type.
+ * @param Horde_Itip_Response_Options $options The options for the response.
+ * @param Horde_Mail_Transport $transport The mail transport.
+ *
+ * @return NULL
+ */
+ public function sendMultipartResponse(
+ Horde_Itip_Response_Type $type,
+ Horde_Itip_Response_Options $options,
+ Horde_Mail_Transport $transport
+ ) {
+ list($headers, $body) = $this->_response->getMultiPartMessage(
+ $type, $options
+ );
+ $body->send(
+ $this->_response->getRequest()->getOrganizer(),
+ $headers,
+ $transport
);
}
*/
public function getUid()
{
- return $this->_vevent->getAttributeDefault('UID', '');
+ return $this->_vevent->getAttribute('UID');
}
/**
{
$this->_vevent->setAttribute(
'ATTENDEE',
- 'MAILTO:' . $attendee,
+ 'mailto:' . $attendee,
array(
'CN' => $common_name,
'PARTSTAT' => $status
*/
private function getSequence()
{
- return $this->_vevent->getAttributeDefault('SEQUENCE', 0);
+ return $this->_vevent->getAttribute('SEQUENCE');
}
/**
*/
private function copySequence(Horde_Itip_Event $itip)
{
- $itip->setSequence($this->getSequence());
+ try {
+ $itip->setSequence($this->getSequence());
+ } catch (Horde_Icalendar_Exception $e) {
+ }
}
/**
public function getMailAddress();
/**
+ * Retrieve the reply-to address for the resource.
+ *
+ * @return string The reply-to address.
+ */
+ public function getReplyTo();
+
+ /**
* Retrieve the common name of the resource.
*
* @return string The common name.
}
/**
+ * Retrieve the reply-to address for the resource.
+ *
+ * @return string The reply-to address.
+ */
+ public function getReplyTo()
+ {
+ }
+
+ /**
* Retrieve the common name of the resource.
*
* @return string The common name.
--- /dev/null
+<?php
+/**
+ * Horde_Prefs_Identity based information provider for an invited resource.
+ *
+ * PHP version 5
+ *
+ * @category Horde
+ * @package Itip
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Itip
+ */
+
+/**
+ * Horde_Prefs_Identity based information provider for an invited resource.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you did not
+ * receive this file, see
+ * http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ *
+ * @category Horde
+ * @package Itip
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Itip
+ */
+class Horde_Itip_Resource_Identity
+implements Horde_Itip_Resource
+{
+ /**
+ * The identity.
+ *
+ * @var IMP_Prefs_Identity
+ */
+ private $_identity;
+
+ /**
+ * The selected identity for replying.
+ *
+ * @var string
+ */
+ private $_reply_to;
+
+ /**
+ * Constructor.
+ *
+ * @param IMP_Prefs_Identity $identity The IMP identity of the invited
+ * resource.
+ * @param array $attendees The attendees of the invitation.
+ * @param string $reply_to The selected identity for sending the
+ * reply.
+ */
+ public function __construct($identity, $attendees, $reply_to)
+ {
+ $this->_identity = $identity;
+ if (!is_array($attendees)) {
+ $attendees = array($attendees);
+ }
+ foreach ($attendees as $attendee) {
+ $attendee = preg_replace('/mailto:/i', '', $attendee);
+ if (!is_null($id = $identity->getMatchingIdentity($attendee))) {
+ $identity->setDefault($id);
+ break;
+ }
+ }
+ $this->_reply_to = $reply_to;
+ }
+
+ /**
+ * Retrieve the mail address of the resource.
+ *
+ * @return string The mail address.
+ */
+ public function getMailAddress()
+ {
+ return $this->_identity->getFromAddress();
+ }
+
+ /**
+ * Retrieve the reply-to address for the resource.
+ *
+ * @return string The reply-to address.
+ */
+ public function getReplyTo()
+ {
+ $original = $this->_identity->getDefault();
+ $this->_identity->setDefault($this->_reply_to);
+ $reply_to = $this->_identity->getValue('replyto_addr');
+ $this->_identity->setDefault($original);
+ return $reply_to;
+ }
+
+ /**
+ * Retrieve the common name of the resource.
+ *
+ * @return string The common name.
+ */
+ public function getCommonName()
+ {
+ return $this->_identity->getValue('fullname');
+ }
+
+ /**
+ * Retrieve the "From" address for this resource.
+ *
+ * @return string The "From" address.
+ */
+ public function getFrom()
+ {
+ $cn = $this->getCommonName();
+ if (!empty($cn)) {
+ return sprintf("%s <%s>", $cn, $this->getMailAddress());
+ } else {
+ return $this->getMailAddress();
+ }
+ }
+}
\ No newline at end of file
}
/**
+ * Return the original request.
+ *
+ * @return Horde_Itip_Event The original request.
+ */
+ public function getRequest()
+ {
+ return $this->_request;
+ }
+
+ /**
* Return the response as an iCalendar vEvent object.
*
* @param Horde_Itip_Response_Type $type The response type.
$vCal = false
) {
$itip_reply = new Horde_Itip_Event_Vevent(
- Horde_iCalendar::newComponent('VEVENT', $vCal)
+ Horde_Icalendar::newComponent('VEVENT', $vCal)
);
$this->_request->copyEventInto($itip_reply);
* Return the response as an iCalendar object.
*
* @param Horde_Itip_Response_Type $type The response type.
- * @param string $product_id The ID that should be set as
- * the iCalendar product id.
+ * @param Horde_Itip_Response_Options $options The options for the response.
*
- * @return Horde_iCalendar The response object.
+ * @return Horde_Icalendar The response object.
*/
public function getIcalendar(
Horde_Itip_Response_Type $type,
- $product_id
+ Horde_Itip_Response_Options $options
) {
- $vCal = new Horde_iCalendar();
- $vCal->setAttribute('PRODID', $product_id);
+ $vCal = new Horde_Icalendar();
+ $options->prepareIcalendar($vCal);
$vCal->setAttribute('METHOD', 'REPLY');
$vCal->addComponent($this->getVevent($type, $vCal));
return $vCal;
/**
* Return the response as a MIME message.
*
- * @param Horde_Itip_Response_Type $type The response type.
- * @param string $product_id The ID that should be set
- * as the iCalendar product
- * id.
- * @param string $subject_comment An optional comment on
- * the subject line.
+ * @param Horde_Itip_Response_Type $type The response type.
+ * @param Horde_Itip_Response_Options $options The options for the response.
*
* @return array A list of two object: The mime headers and the mime
* message.
*/
public function getMessage(
Horde_Itip_Response_Type $type,
- $product_id,
- $subject_comment = null
+ Horde_Itip_Response_Options $options
) {
- $ics = new Horde_Mime_Part();
- $ics->setType('text/calendar');
- $ics->setCharset('UTF-8');
- $ics->setContents(
- $this->getIcalendar($type, $product_id)->exportvCalendar()
- );
- $ics->setContentTypeParameter('method', 'REPLY');
-
- //$mime->addPart($body);
- //$mime->addPart($ics);
- // The following was ::convertMimePart($mime). This was removed so that we
- // send out single-part MIME replies that have the iTip file as the body,
- // with the correct mime-type header set, etc. The reason we want to do this
- // is so that Outlook interprets the messages as it does Outlook-generated
- // responses, i.e. double-clicking a reply will automatically update your
- // meetings, showing different status icons in the UI, etc.
- //$message = Horde_Mime_Message::convertMimePart($ics);
$message = new Horde_Mime_Part();
- $message->setCharset('UTF-8');
- $message->setTransferEncoding('quoted-printable');
- //$message->transferEncodeContents();
+ $message->setType('text/calendar');
+ $options->prepareIcsMimePart($message);
+ $message->setContents(
+ $this->getIcalendar($type, $options)->exportvCalendar()
+ );
+ $message->setName('event-reply.ics');
+ $message->setContentTypeParameter('METHOD', 'REPLY');
// Build the reply headers.
+ $from = $this->_resource->getFrom();
+ $reply_to = $this->_resource->getReplyTo();
$headers = new Horde_Mime_Headers();
$headers->addHeader('Date', date('r'));
- $headers->addHeader('From', $this->_resource->getFrom());
+ $headers->addHeader('From', $from);
$headers->addHeader('To', $this->_request->getOrganizer());
+ if ($reply_to != $from) {
+ $headers->addHeader('Reply-to', $reply_to);
+ }
$headers->addHeader(
- 'Subject', $type->getSubject($subject_comment)
+ 'Subject', $type->getSubject()
);
- //$headers->addMimeHeaders($message);
+
+ $options->prepareResponseMimeHeaders($headers);
+
+ return array($headers, $message);
+ }
+
+ /**
+ * Return the response as a MIME message.
+ *
+ * @param Horde_Itip_Response_Type $type The response type.
+ * @param Horde_Itip_Response_Options $options The options for the response.
+ *
+ * @return array A list of two object: The mime headers and the mime
+ * message.
+ */
+ public function getMultiPartMessage(
+ Horde_Itip_Response_Type $type,
+ Horde_Itip_Response_Options $options
+ ) {
+ $message = new Horde_Mime_Part();
+ $message->setType('multipart/alternative');
+
+ list($headers, $ics) = $this->getMessage($type, $options);
+
+ $body = new Horde_Mime_Part();
+ $body->setType('text/plain');
+ $options->prepareMessageMimePart($body);
+ $body->setContents(Horde_String::wrap($type->getMessage(), 76, "\n"));
+
+ $message->addPart($body);
+ $message->addPart($ics);
+
return array($headers, $message);
}
}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * Holds iTip response options.
+ *
+ * PHP version 5
+ *
+ * @category Horde
+ * @package Itip
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Itip
+ */
+
+/**
+ * Holds iTip response options.
+ *
+ * Copyright 2010 Kolab Systems AG
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you did not
+ * receive this file, see
+ * http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ *
+ * @category Horde
+ * @package Itip
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Itip
+ */
+interface Horde_Itip_Response_Options
+{
+ /**
+ * Prepare the iCalendar part of the response object.
+ *
+ * @param Horde_Icalendar $ical The iCalendar response object.
+ *
+ * @return NULL
+ */
+ public function prepareIcalendar(Horde_Icalendar $ical);
+
+ /**
+ * Prepare the iCalendar MIME part of the response message.
+ *
+ * @param Horde_Mime_Part $ics The iCalendar MIME part of the response
+ * message.
+ *
+ * @return NULL
+ */
+ public function prepareResponseMimeHeaders(Horde_Mime_Headers $headers);
+
+ /**
+ * Prepare the iCalendar MIME part of the response message.
+ *
+ * @param Horde_Mime_Part $ics The iCalendar MIME part of the response
+ * message.
+ *
+ * @return NULL
+ */
+ public function prepareIcsMimePart(Horde_Mime_Part $ics);
+
+ /**
+ * Prepare the message MIME part of the response.
+ *
+ * @param Horde_Mime_Part $message The message MIME part of the response.
+ *
+ * @return NULL
+ */
+ public function prepareMessageMimePart(Horde_Mime_Part $message);
+
+ /**
+ * Get the character set for the response mime parts.
+ *
+ * @return string The character set.
+ */
+ public function getCharacterSet();
+
+ /**
+ * Get the product ID of the iCalendar object embedded in the MIME response.
+ *
+ * @return string The product ID.
+ */
+ public function getProductId();
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * Holds iTip response options.
+ *
+ * PHP version 5
+ *
+ * @category Horde
+ * @package Itip
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Itip
+ */
+
+/**
+ * Holds iTip response options.
+ *
+ * Copyright 2010 Kolab Systems AG
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you did not
+ * receive this file, see
+ * http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ *
+ * @category Horde
+ * @package Itip
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Itip
+ */
+abstract class Horde_Itip_Response_Options_Base
+implements Horde_Itip_Response_Options
+{
+ /**
+ * Prepare the iCalendar part of the response object.
+ *
+ * @param Horde_Icalendar $ical The iCalendar response object.
+ *
+ * @return NULL
+ */
+ public function prepareIcalendar(Horde_Icalendar $ical)
+ {
+ $ical->setAttribute('PRODID', $this->getProductId());
+ }
+
+ /**
+ * Prepare the iCalendar MIME part of the response message.
+ *
+ * @param Horde_Mime_Part $ics The iCalendar MIME part of the response
+ * message.
+ *
+ * @return NULL
+ */
+ public function prepareIcsMimePart(Horde_Mime_Part $ics)
+ {
+ $ics->setCharset($this->getCharacterSet());
+ }
+
+ /**
+ * Prepare the message MIME part of the response.
+ *
+ * @param Horde_Mime_Part $message The message MIME part of the response.
+ *
+ * @return NULL
+ */
+ public function prepareMessageMimePart(Horde_Mime_Part $message)
+ {
+ $message->setCharset($this->getCharacterSet());
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * Handles iTip response options for Horde iTip responses.
+ *
+ * PHP version 5
+ *
+ * @category Horde
+ * @package Itip
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Itip
+ */
+
+/**
+ * Handles iTip response options for Horde iTip responses.
+ *
+ * Copyright 2010 Kolab Systems AG
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you did not
+ * receive this file, see
+ * http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ *
+ * @category Horde
+ * @package Itip
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Itip
+ */
+class Horde_Itip_Response_Options_Horde
+extends Horde_Itip_Response_Options_Base
+{
+ /**
+ * The MIME character set.
+ *
+ * @var string
+ */
+ private $_charset;
+
+ /**
+ * Options for setting the "Received" MIME header.
+ *
+ * @var array
+ */
+ private $_received_options;
+
+ /**
+ * Constructor.
+ *
+ * @param string $charset The MIME character set that should be
+ * used.
+ * @param array $received_options Options for setting the "Received" MIME
+ * header.
+ */
+ public function __construct($charset, $received_options)
+ {
+ $this->_charset = $charset;
+ $this->_received_options = $received_options;
+ }
+ /**
+ * Prepare the iCalendar MIME part of the response message.
+ *
+ * @param Horde_Mime_Part $ics The iCalendar MIME part of the response
+ * message.
+ *
+ * @return NULL
+ */
+ public function prepareResponseMimeHeaders(Horde_Mime_Headers $headers)
+ {
+ $headers->addReceivedHeader($this->_received_options);
+ $headers->addMessageIdHeader();
+ }
+
+ /**
+ * Get the character set for the response mime parts.
+ *
+ * @return string The character set.
+ */
+ public function getCharacterSet()
+ {
+ return $this->_charset;
+ }
+
+ /**
+ * Get the product ID of the iCalendar object embedded in the MIME response.
+ *
+ * @return string The product ID.
+ */
+ public function getProductId()
+ {
+ $headers = new Horde_Mime_Headers();
+ return '-//The Horde Project//' . $headers->getUserAgent() . '//EN';
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * Handles iTip response options for Kolab iTip responses.
+ *
+ * PHP version 5
+ *
+ * @category Horde
+ * @package Itip
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Itip
+ */
+
+/**
+ * Handles iTip response options for Kolab iTip responses.
+ *
+ * Copyright 2010 Kolab Systems AG
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you did not
+ * receive this file, see
+ * http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ *
+ * @category Horde
+ * @package Itip
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Itip
+ */
+class Horde_Itip_Response_Options_Kolab
+extends Horde_Itip_Response_Options_Base
+{
+ /**
+ * Prepare the iCalendar MIME part of the response message.
+ *
+ * @param Horde_Mime_Part $ics The iCalendar MIME part of the response
+ * message.
+ *
+ * @return NULL
+ */
+ public function prepareResponseMimeHeaders(Horde_Mime_Headers $headers)
+ {
+ }
+
+ /**
+ * Get the character set for the response mime parts.
+ *
+ * @return string The character set.
+ */
+ public function getCharacterSet()
+ {
+ return 'UTF-8';
+ }
+
+ /**
+ * Get the product ID of the iCalendar object embedded in the MIME response.
+ *
+ * @return string The product ID.
+ */
+ public function getProductId()
+ {
+ return '-//kolab.org//NONSGML Kolab Server 2//EN';
+ }
+}
\ No newline at end of file
public function getStatus();
/**
- * Return the abbreviated subject of the response.
+ * Return the core subject of the response.
*
* @return string The short subject.
*/
public function getShortSubject();
/**
- * Return the subject of the response.
+ * Return the subject of the response without using the comment.
*
- * @param string $comment An optional comment that should appear in the
- * response subject.
+ * @return string The subject.
+ */
+ public function getBriefSubject();
+
+ /**
+ * Return the subject of the response.
*
* @return string The subject.
*/
- public function getSubject($comment = null);
+ public function getSubject();
/**
* Return an additional message for the response.
*
* @param boolean $is_update Indicates if the request was an update.
- * @param string $comment An optional comment that should appear in the
- * response message.
*
* @return string The message.
*/
- public function getMessage($is_update = false, $comment = null);
+ public function getMessage($is_update = false);
}
\ No newline at end of file
private $_request;
/**
+ * The invited resource.
+ *
+ * @var Horde_Itip_Resource
+ */
+ private $_resource;
+
+ /**
+ * An optional comment that should appear in the response subject.
+ *
+ * @var string
+ */
+ private $_comment;
+
+ /**
+ * Constructor.
+ *
+ * @param Horde_Itip_Resource $resource The invited resource.
+ * @param string $comment A comment for the subject line.
+ */
+ public function __construct(
+ Horde_Itip_Resource $resource,
+ $comment = null
+ ) {
+ $this->_resource = $resource;
+ $this->_comment = $comment;
+ }
+
+ /**
* Set the request.
*
- * @param Horde_Itip_Event $request The request this
- * instance will respond
- * to.
+ * @param Horde_Itip_Event $request The request this instance will respond
+ * to.
*
* @return NULL
*/
}
/**
- * Return the subject of the response.
+ * Return the subject of the response without using the comment.
*
- * @param string $comment An optional comment that should appear in the
- * response subject.
+ * @return string The subject.
+ */
+ public function getBriefSubject()
+ {
+ return sprintf(
+ '%s: %s',
+ $this->getShortSubject(),
+ $this->getRequest()->getSummary()
+ );
+ }
+ /**
+ * Return the subject of the response.
*
* @return string The subject.
*/
- public function getSubject($comment = null)
+ public function getSubject()
{
- if ($comment === null) {
- return sprintf(
- '%s: %s',
- $this->getShortSubject(),
- $this->getRequest()->getSummary()
- );
+ if ($this->_comment === null) {
+ return $this->getBriefSubject();
} else {
return sprintf(
'%s [%s]: %s',
$this->getShortSubject(),
- $comment,
+ $this->_comment,
$this->getRequest()->getSummary()
);
}
* Return an additional message for the response.
*
* @param boolean $is_update Indicates if the request was an update.
- * @param string $comment An optional comment that should appear in the
- * response message.
*
* @return string The message.
*/
- public function getMessage($is_update = false, $comment = null)
+ public function getMessage($is_update = false)
{
- if ($comment === null) {
+ if ($this->_comment === null) {
return sprintf(
"%s %s:\n\n%s",
- $this->getShortMessage($update),
+ $this->_resource->getCommonName(),
+ $this->getShortMessage($is_update),
$this->getRequest()->getSummary()
);
} else {
return sprintf(
"%s %s:\n\n%s\n\n%s",
- $this->getShortMessage($update),
+ $this->_resource->getCommonName(),
+ $this->getShortMessage($is_update),
$this->getRequest()->getSummary(),
- $comment
+ $this->_comment
);
}
}
</dir> <!-- /lib/Horde/Itip/Event -->
<dir name="Resource">
<file name="Base.php" role="php" />
+ <file name="Identity.php" role="php" />
</dir> <!-- /lib/Horde/Itip/Resource -->
<dir name="Response">
+ <dir name="Options">
+ <file name="Base.php" role="php" />
+ <file name="Horde.php" role="php" />
+ <file name="Kolab.php" role="php" />
+ </dir> <!-- /lib/Horde/Itip/Response/Options -->
+ <file name="Options.php" role="php" />
<dir name="Type">
<file name="Accept.php" role="php" />
<file name="Base.php" role="php" />
<install as="Horde/Itip/Response.php" name="lib/Horde/Itip/Response.php" />
<install as="Horde/Itip/Event/Vevent.php" name="lib/Horde/Itip/Event/Vevent.php" />
<install as="Horde/Itip/Resource/Base.php" name="lib/Horde/Itip/Resource/Base.php" />
+ <install as="Horde/Itip/Resource/Identity.php" name="lib/Horde/Itip/Resource/Identity.php" />
+ <install as="Horde/Itip/Response/Options.php" name="lib/Horde/Itip/Response/Options.php" />
+ <install as="Horde/Itip/Response/Options/Base.php" name="lib/Horde/Itip/Response/Options/Base.php" />
+ <install as="Horde/Itip/Response/Options/Horde.php" name="lib/Horde/Itip/Response/Options/Horde.php" />
+ <install as="Horde/Itip/Response/Options/Kolab.php" name="lib/Horde/Itip/Response/Options/Kolab.php" />
<install as="Horde/Itip/Response/Type.php" name="lib/Horde/Itip/Response/Type.php" />
<install as="Horde/Itip/Response/Type/Accept.php" name="lib/Horde/Itip/Response/Type/Accept.php" />
<install as="Horde/Itip/Response/Type/Base.php" name="lib/Horde/Itip/Response/Type/Base.php" />
// vEvent request.
if (isset($components[$key]) &&
$components[$key]->getType() == 'vEvent') {
- $vEvent = $components[$key];
-
- // Get the organizer details.
- try {
- $organizer = $vEvent->getAttribute('ORGANIZER');
- } catch (Horde_Icalendar_Exception $e) {
- break;
- }
- $organizer = parse_url($organizer);
- $organizerEmail = $organizer['path'];
- $organizer = $vEvent->getAttribute('ORGANIZER', true);
- $organizerName = isset($organizer['cn']) ? $organizer['cn'] : '';
-
- // 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');
- $vEvent_reply = Horde_Icalendar::newComponent('vevent', $vCal);
- $vEvent_reply->setAttribute('UID', $vEvent->getAttribute('UID'));
- try {
- $vEvent->getAttribute('SUMMARY');
- $vEvent_reply->setAttribute('SUMMARY', $vEvent->getAttribute('SUMMARY'));
- } catch (Horde_Icalendar_Exception $e) {}
- try {
- $vEvent->getAttribute('DESCRIPTION');
- $vEvent_reply->setAttribute('DESCRIPTION', $vEvent->getAttribute('DESCRIPTION'));
- } catch (Horde_Icalendar_Exception $e) {}
- $dtstart = $vEvent->getAttribute('DTSTART', true);
- $vEvent_reply->setAttribute('DTSTART', $vEvent->getAttribute('DTSTART'), array_pop($dtstart));
- try {
- $vEvent->getAttribute('DTEND');
- $dtend = $vEvent->getAttribute('DTEND', true);
- $vEvent_reply->setAttribute('DTEND', $vEvent->getAttribute('DTEND'), array_pop($dtend));
- } catch (Horde_Icalendar_Exception $e) {
- $duration = $vEvent->getAttribute('DURATION', true);
- $vEvent_reply->setAttribute('DURATION', $vEvent->getAttribute('DURATION'), array_pop($duration));
- }
- try {
- $vEvent->getAttribute('SEQUENCE');
- $vEvent_reply->setAttribute('SEQUENCE', $vEvent->getAttribute('SEQUENCE'));
- } catch (Horde_Icalendar_Exception $e) {}
- $vEvent_reply->setAttribute('ORGANIZER', $vEvent->getAttribute('ORGANIZER'), array_pop($organizer));
+ $vEvent = $components[$key];
- // Find out who we are and update status.
- $identity = $GLOBALS['injector']->getInstance('IMP_Identity');
- $attendees = $vEvent->getAttribute('ATTENDEE');
- if (!is_array($attendees)) {
- $attendees = array($attendees);
- }
- foreach ($attendees as $attendee) {
- $attendee = preg_replace('/mailto:/i', '', $attendee);
- if (!is_null($id = $identity->getMatchingIdentity($attendee))) {
- $identity->setDefault($id);
- break;
- }
- }
- $name = $email = $identity->getFromAddress();
- $params = array();
- $cn = $identity->getValue('fullname');
- if (!empty($cn)) {
- $name = $params['CN'] = $cn;
- }
+ $resource = new Horde_Itip_Resource_Identity(
+ $GLOBALS['injector']->getInstance('IMP_Identity'),
+ $vEvent->getAttribute('ATTENDEE'),
+ Horde_Util::getFormData('identity')
+ );
switch ($action) {
case 'accept':
case 'accept-import':
- $message = sprintf(_("%s has accepted."), $name);
- $subject = _("Accepted: ") . $vEvent->getAttribute('SUMMARY');
- $params['PARTSTAT'] = 'ACCEPTED';
+ $type = new Horde_Itip_Response_Type_Accept($resource);
break;
-
case 'deny':
- $message = sprintf(_("%s has declined."), $name);
- $subject = _("Declined: ") . $vEvent->getAttribute('SUMMARY');
- $params['PARTSTAT'] = 'DECLINED';
+ $type = new Horde_Itip_Response_Type_Decline($resource);
break;
-
case 'tentative':
- $message = sprintf(_("%s has tentatively accepted."), $name);
- $subject = _("Tentative: ") . $vEvent->getAttribute('SUMMARY');
- $params['PARTSTAT'] = 'TENTATIVE';
+ $type = new Horde_Itip_Response_Type_Tentative($resource);
break;
}
- $vEvent_reply->setAttribute('ATTENDEE', 'mailto:' . $email, $params);
- $vCal->addComponent($vEvent_reply);
-
- $mime = new Horde_Mime_Part();
- $mime->setType('multipart/alternative');
-
- $body = new Horde_Mime_Part();
- $body->setType('text/plain');
- $body->setCharset($charset);
- $body->setContents(Horde_String::wrap($message, 76, "\n"));
-
- $ics = new Horde_Mime_Part();
- $ics->setType('text/calendar');
- $ics->setCharset($charset);
- $ics->setContents($vCal->exportvCalendar());
- $ics->setName('event-reply.ics');
- $ics->setContentTypeParameter('METHOD', 'REPLY');
-
- $mime->addPart($body);
- $mime->addPart($ics);
-
- // Build the reply headers.
- $msg_headers->addReceivedHeader(array(
- 'dns' => $GLOBALS['injector']->getInstance('Net_DNS_Resolver'),
- 'server' => $GLOBALS['conf']['server']['name']
- ));
- $msg_headers->addMessageIdHeader();
- $msg_headers->addHeader('Date', date('r'));
- $msg_headers->addHeader('From', $email);
- $msg_headers->addHeader('To', $organizerEmail);
-
- $identity->setDefault(Horde_Util::getFormData('identity'));
- $replyto = $identity->getValue('replyto_addr');
- if (!empty($replyto) && ($replyto != $email)) {
- $msg_headers->addHeader('Reply-to', $replyto);
- }
- $msg_headers->addHeader('Subject', Horde_Mime::encode($subject, $charset));
-
- // Send the reply.
try {
- $mime->send($organizerEmail, $msg_headers, $GLOBALS['injector']->getInstance('IMP_Mail'));
+ Horde_Itip::factory($vEvent, $resource)->sendMultiPartResponse(
+ $type,
+ new Horde_Itip_Response_Options_Horde(
+ $charset,
+ array(
+ 'dns' => $GLOBALS['injector']->getInstance('Net_DNS_Resolver'),
+ 'server' => $GLOBALS['conf']['server']['name']
+ )
+ ),
+ $GLOBALS['injector']->getInstance('IMP_Mail')
+ );
$msgs[] = array('success', _("Reply Sent."));
- } catch (Exception $e) {
+ } catch (Horde_Itip_Exception $e) {
$msgs[] = array('error', sprintf(_("Error sending reply: %s."), $e->getMessage()));
}
+
+ // Send the reply.
} else {
$msgs[] = array('warning', _("This action is not supported."));
}
class IMP_Stub_Identity
{
- private $id;
+ private $_id = 'default';
public function getMatchingIdentity($mail)
{
public function setDefault($id)
{
- if ($id != 'test' && $id != 'other') {
+ if ($id != 'test' && $id != 'other' && $id != 'default') {
throw new Exception("Unexpected default $id!");
}
$this->_id = $id;
}
+ public function getDefault()
+ {
+ return $this->_id;
+ }
+
public function getFromAddress()
{
return 'test@example.org';
$_GET['itip_action'] = array(0 => 'accept');
$vCal = new Horde_Icalendar();
$vCal->setAttribute('METHOD', 'REQUEST');
- $inv = Horde_Icalendar::newComponent('VEVENT', $vCal);
- $inv->setAttribute('ORGANIZER', 'somebody@example.com');
- $viewer = $this->_getViewer($inv->exportvCalendar());
- $this->assertEquals(array(), $viewer->render('inline'));
+ $viewer = $this->_getViewer("BEGIN:VEVENT\nORGANIZER:somebody@example.com\nDTSTAMP:20100816T143648Z\nDTSTART:20100816T143648Z\nEND:VEVENT");
+ $this->assertSame(array(), $viewer->render('inline'));
}
public function testResultMessageContainsCopiedSummary()
$_GET['itip_action'] = array(0 => 'accept');
$viewer = $this->_getViewer($this->_getInvitation()->exportvCalendar());
$viewer->render('inline');
- $this->assertEquals('Mr. Test has accepted.', $this->_getMimeMessage()->getPart(1)->getContents());
+ $this->assertEquals("Mr. Test has accepted the invitation to the following event:\n\nTest Invitation", $this->_getMimeMessage()->getPart(1)->getContents());
}
public function testDenyResultContainsDeclineMimeMessage()
$_GET['itip_action'] = array(0 => 'deny');
$viewer = $this->_getViewer($this->_getInvitation()->exportvCalendar());
$viewer->render('inline');
- $this->assertEquals('Mr. Test has declined.', $this->_getMimeMessage()->getPart(1)->getContents());
+ $this->assertEquals("Mr. Test has declined the invitation to the following event:\n\nTest Invitation", $this->_getMimeMessage()->getPart(1)->getContents());
}
public function testTentativeResultContainsTentativeMimeMessage()
$_GET['itip_action'] = array(0 => 'tentative');
$viewer = $this->_getViewer($this->_getInvitation()->exportvCalendar());
$viewer->render('inline');
- $this->assertEquals('Mr. Test has tentatively accepted.', $this->_getMimeMessage()->getPart(1)->getContents());
+ $this->assertEquals("Mr. Test has tentatively accepted the invitation to the following event:\n\nTest Invitation", $this->_getMimeMessage()->getPart(1)->getContents());
}
public function testResultMimeMessagePartOneHasRegistryCharset()
$_GET['itip_action'] = array(0 => 'accept');
$viewer = $this->_getViewer($this->_getInvitation()->exportvCalendar());
$viewer->render('inline');
- $this->assertEquals('BIG5', $this->_getMimeMessage()->getPart(2)->getCharset());
+ $ics = $this->_getMimeMessage()->getPart(2);
+ if (!$ics) {
+ $this->fail('Missing second message part!');
+ }
+ $this->assertEquals('BIG5', $ics->getCharset());
}
public function testResultMimeMessagePartTwoHasFileName()
$_GET['itip_action'] = array(0 => 'accept');
$viewer = $this->_getViewer($this->_getInvitation()->exportvCalendar());
$viewer->render('inline');
- $this->assertEquals('event-reply.ics', $this->_getMimeMessage()->getPart(2)->getName());
+ $ics = $this->_getMimeMessage()->getPart(2);
+ if (!$ics) {
+ $this->fail('Missing second message part!');
+ }
+ $this->assertEquals('event-reply.ics', $ics->getName());
}
public function testResultMimeMessagePartTwoHasContentTypeParameter()
$_GET['itip_action'] = array(0 => 'accept');
$viewer = $this->_getViewer($this->_getInvitation()->exportvCalendar());
$viewer->render('inline');
- $this->assertEquals('REPLY', $this->_getMimeMessage()->getPart(2)->getContentTypeParameter('METHOD'));
+ $ics = $this->_getMimeMessage()->getPart(2);
+ if (!$ics) {
+ $this->fail('Missing second message part!');
+ }
+ $this->assertEquals('REPLY', $ics->getContentTypeParameter('METHOD'));
}
public function testResultMimeMessageHeadersContainsReceivedHeader()
$_GET['itip_action'] = array(0 => 'accept');
$viewer = $this->_getViewer($this->_getInvitation()->exportvCalendar());
$viewer->render('inline');
- $this->assertEquals('test@example.org', $this->_getMailHeaders()->getValue('From'));
+ $this->assertEquals('"Mr. Test" <test@example.org>', $this->_getMailHeaders()->getValue('From'));
}
public function testResultMimeMessageHeadersContainsTo()
private function _getMailHeaders()
{
if (isset($GLOBALS['injector']->getInstance('IMP_Mail')->sentMessages[0])) {
- return Horde_Mime_Headers::parseHeaders(
+ $headers = Horde_Mime_Headers::parseHeaders(
$GLOBALS['injector']->getInstance('IMP_Mail')->sentMessages[0]['header_text']
);
+ if (!$headers instanceOf Horde_Mime_Headers) {
+ $this->fail('Failed parsing message headers!');
+ return new Horde_Mime_Headers();
+ }
+ return $headers;
}
+ $this->fail('No message has been sent!');
}
private function _getMail()
private function _getIcalendar()
{
$part = $this->_getMimeMessage();
+ $ics = $part->getPart(2);
+ if (!$ics) {
+ $this->fail('Missing second message part!');
+ }
$iCal = new Horde_Icalendar();
- $iCal->parsevCalendar($part->getPart(2)->getContents());
+ $iCal->parsevCalendar($ics->getContents());
return $iCal;
}