stephan: server/horde CHANGELOG, NONE, 1.1 Kolab.php, NONE, 1.1 String.php, NONE, 1.1 iCalendar.php, NONE, 1.1 kronolith_kolab.php, NONE, 1.1 mnemo_kolab.php, NONE, 1.1 nag_kolab.php, NONE, 1.1 turba_kolab.php, NONE, 1.1 valarm.php, NONE, 1.1 vevent.php, NONE, 1.1 vfreebusy.php, NONE, 1.1 vjournal.php, NONE, 1.1 vtimezone.php, NONE, 1.1 vtodo.php, NONE, 1.1
cvs at intevation.de
cvs at intevation.de
Mon Sep 1 09:54:35 CEST 2003
- Previous message: stephan: server/horde Makefile, 1.4, 1.5 horde.spec, 1.6, 1.7 horde_registry.php, 1.3, 1.4 imp_servers.php, 1.3, 1.4 kronolith_conf.php, 1.1, 1.2 nag_conf.php, 1.1, 1.2
- Next message: stephan: server/horde Makefile,1.5,1.6
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Author: stephan
Update of /kolabrepository/server/horde
In directory doto:/tmp/cvs-serv18112
Added Files:
CHANGELOG Kolab.php String.php iCalendar.php
kronolith_kolab.php mnemo_kolab.php nag_kolab.php
turba_kolab.php valarm.php vevent.php vfreebusy.php
vjournal.php vtimezone.php vtodo.php
Log Message:
Files needed for the webclient to function
--- NEW FILE: CHANGELOG ---
(This appears to be a binary file; contents omitted.)
--- NEW FILE: Kolab.php ---
<?php
/**
* Horde Kolab utility library, providing various utility functions for dealing with the Kolab server.
* Consists mainly of IMAP related functions.
*
* Copyright (C) 2003 Code Fusion, cc.
* Written by Stuart Bingë <s.binge at codefusion.co.za>
*
* Created 2003-08-28
* Last Modified 2003-08-29 by Stuart Bingë
*/
define('MIME_NL', "\r\n");
define('ERR_MBOX_DNE', 'Mailbox does not exist');
define('X_HEAD_CAT', 'X-Horde-Category');
define('X_HEAD_ID', 'X-Horde-ID');
class Kolab {
/**
* Tests imap_last_error() against $error and returns true if they are equal.
*/
function TestError($error)
{
return strcasecmp(imap_last_error(), $error) == 0;
}
/**
* Returns an array of the form (username, password) for the currently logged in horde user.
* The returned username/password pair can be used for authentication with the Kolab IMAP server.
*/
function GetAuthentication()
{
$userID = Auth::getAuth();
//return array(substr($userID, 0, strrpos($userID, "@")), Auth::getCredential('password'));
return array($userID, Auth::getCredential('password'));
}
/**
* Returns an IMAP stream connected to $server that has been opened to $mailbox, or
* false on failure. If the folder does not exist and $create == true, the function
* tries to create the folder.
*/
function OpenImapConnection($server, $mailbox, $create = true)
{
list ($user, $pass) = Kolab::GetAuthentication();
$host = Kolab::MailboxURI($server);
$box = Kolab::MailboxURI($server, $mailbox);
$imapstream = @imap_open($box, $user, $pass); // Firstly try a straight imap_open()
if ($create && Kolab::TestError(ERR_MBOX_DNE)) // Box does not exist, try to create it
{
if (!$imapstream) @imap_close($imapstream);
$imapstream = @imap_open($host, $user, $pass, OP_HALFOPEN);
if (!$imapstream) return false;
if (!@imap_createmailbox($imapstream, $box)) return false;
$imapstream = @imap_reopen($box); // Successfully created the box, now try to open it
}
if (!$imapstream) return false;
return $imapstream;
}
/**
* Closes $imapstream, returns a boolean indicating success.
*/
function CloseImapConnection($imapstream)
{
if ($imapstream && !is_null($imapstream))
return @imap_close($imapstream, CL_EXPUNGE);
return true;
}
/**
* Returns an associative array of the headers of message $messageid in the currently open message box
* designated by $imapstream, or false on failure. On success each item of the returned array, of
* the form $key => $value, corresponds to <HeaderName>: <HeaderValue> respectively in the headers.
* If $uid == true then $messageid is treated as an IMAP unique message identifier, as opposed to
* a message sequence number.
*/
function GetMessageHeaders($imapstream, $messageid, $uid = false)
{
if (!$imapstream || is_null($imapstream)) return false;
if ($uid) $options = FT_UID; else $options = 0;
$headerdata = @imap_fetchheader($imapstream, $messageid, $options);
if (!$headerdata || is_null($headerdata) || $headerdata == "") return false;
$headerlines = explode(MIME_NL, $headerdata);
for ($i = 0; $i < count($headerlines); $i++)
{
if (strpos($headerlines[$i], ':') == 0) continue;
list($hname, $hval) = explode(':', $headerlines[$i]);
$headers[trim($hname)] = trim($hval);
}
return $headers;
}
/**
* Returns the value of the header attribute with name $name in the header list $headers. If $name
* does not exist in $headers, $default is returned instead.
*/
function GetHeaderValue(&$headers, $name, $default = NULL)
{
if (array_key_exists($name, $headers))
return $headers[$name];
else
return $default;
}
/**
* Returns a string of the form "{<localhost>:143/imap/notls}<INBOX>" for use in various IMAP
* functions, where <localhost> and <INBOX> are example values of $host and $mailbox, respectively.
*/
function MailboxURI($host, $mailbox = "")
{
return '{' . $host . ':143/imap/notls}' . $mailbox;
}
/**
* Appends a message to the message box $mailbox on the imap stream $imapstream. Returns a boolean
* indicating success. The message is constructed by setting the Content-Type to $conttype,
* setting From and To to $user, setting User-Agent to $ua, appending any additional headers
* specified in $headers, and finally setting $body as the message body.
*
* NOTE: $mailbox must include the host address; this can be achieved by using the result of
* Kolab::MailboxURI("localhost", "INBOX/Mailbox"), for example, as the value for $mailbox.
* NOTE: Ensure $body does not contain bare newlines ('\n') or else the function will fail.
*/
function AddMessage($imapstream, $mailbox, $user, $conttype, $body, $ua = "", $headers = array())
{
$msg =
'Content-Type: ' . $conttype . '; charset="utf-8"' . MIME_NL
. 'From: ' . $user . MIME_NL
. 'Reply-To:' . MIME_NL
. 'To: ' . $user . MIME_NL
. 'User-Agent: Horde/' . $ua . '/Kolab' . MIME_NL
. 'Date: ' . date('r') . MIME_NL;
foreach ($headers as $key => $value)
$msg .= $key . ': ' . $value . MIME_NL;
$msg .= MIME_NL. $body;
if (!@imap_append($imapstream, $mailbox, $msg)) return false;
return true;
}
/**
* Returns an array of message ids corresponding to the current messages in the mailbox specified
* by $imapstream.
*/
function GetMessageList($imapstream)
{
return imap_sort($imapstream, SORTDATE, 0);
}
/**
* Converts the date object $obj to a timestamp value (Yoinked from Kronolith).
*/
function ObjectToTimestamp($obj)
{
return @mktime($obj->hour, $obj->min, $obj->sec, $obj->month, $obj->mday, $obj->year);
}
/**
* Converts the associative array $arr to a timestamp value (Yoinked with modification from Kronolith).
*/
function ArrayToTimestamp($arr)
{
if (!is_array($arr)) return 0;
$h = 0; $mi = 0; $s = 0; $mo = 0; $d = 0; $y = 0;
foreach ($arr as $key => $value)
switch ($key)
{
case 'hour': $h = $value; break;
case 'min': $mi = $value; break;
case 'sec': $s = $value; break;
case 'month': $mo = $value; break;
case 'mday': $d = $value; break;
case 'year': $y = $value; break;
}
return @mktime($h, $mi, $s, $mo, $d, $y);
}
/**
* Converts the timestamp value $timestamp to a date object (Yoinked from Kronolith).
*/
function TimestampToObject($timestamp)
{
$res = new stdClass();
list($res->hour, $res->min, $res->sec, $res->mday, $res->month, $res->year) = explode('/', date('H/i/s/j/n/Y', $timestamp));
return $res;
}
/**
* Converts the timestamp value $timestamp to an associative array (Yoinked from Kronolith).
*/
function TimestampToArray($timestamp)
{
$obj = Kolab::TimestampToObject($timestamp);
return array('hour' => $obj->hour,
'min' => $obj->min,
'sec' => $obj->sec,
'month' => $obj->month,
'mday' => $obj->mday,
'year' => $obj->year);
}
}
--- NEW FILE: String.php ---
<?php
/**
* The String:: class provides methods for charset and locale safe string
* manipulation.
*
* $Horde: horde/lib/String.php,v 1.22 2003/06/26 21:24:24 jan Exp $
*
* Copyright 2003 Jan Schneider <jan at horde.org>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Jan Schneider <jan at horde.org>
* @version $Revision: 1.1 $
* @since Horde 3.0
* @package horde
*/
class String {
/**
* Converts a string from one charset to another.
*
* Works only if either the iconv or the mbstring extension
* are present and best if both are available.
* The original string is returned if conversion failed or none
* of the extensions were available.
*
* @access public
*
* @param mixed $input The data to be converted. If $input is an
* an array, the array's values get converted
* recursively.
* @param string $from The string's current charset.
* @param optional string $to The charset to convert the string to.
*
* @return string The converted string.
*/
function convertCharset($input, $from, $to = null)
{
if (is_array($input)) {
$tmp = array();
foreach ($input as $key => $val) {
$tmp[String::convertCharset($key, $from, $to)] = String::convertCharset($val, $from, $to);
}
return $tmp;
}
if (is_object($input)) {
$vars = get_object_vars($input);
foreach ($vars as $key => $val) {
$input->$key = String::convertCharset($val, $from, $to);
}
return $input;
}
if (!is_string($input)) {
return $input;
}
global $nls;
$output = false;
/* Get the user's default character set if none passed in. */
if (is_null($to)) {
$to = NLS::getCharset();
}
/* If the from and to chaacter sets are identical, return now. */
$str_from = String::lower($from);
$str_to = String::lower($to);
if ($str_from == $str_to) {
return $input;
}
/* Use utf8_[en|de]code() if possible. */
$str_from_check = (($str_from == 'iso-8859-1') || ($str_from == 'us-ascii'));
if ($str_from_check && ($str_to == 'utf-8')) {
return utf8_encode($input);
}
$str_to_check = (($str_to == 'iso-8859-1') || ($str_to == 'us-ascii'));
if (($str_from == 'utf-8') && $str_to_check) {
return utf8_decode($input);
}
/* First try iconv with transliteration. */
if (Horde::extensionExists('iconv')) {
ini_set('track_errors', 1);
/* We need to tack an extra character temporarily
because of a bug in iconv() if the last character
is not a 7 bit ASCII character. */
$output = @iconv($from, $to . '//TRANSLIT', $input . 'x');
if (isset($php_errormsg)) {
$output = false;
} else {
$output = substr($output, 0, -1);
}
ini_restore('track_errors');
}
/* Next try mbstring. */
if (!$output && Horde::extensionExists('mbstring')) {
$output = @mb_convert_encoding($input, $to, $from);
}
/* At last try imap_utf7_[en|de]code if appropriate. */
if (!$output && Horde::extensionExists('imap')) {
if ($str_from_check && ($str_to == 'utf7-imap')) {
return @imap_utf7_encode($input);
}
if (($str_from == 'utf7-imap') && $str_to_check) {
return @imap_utf7_decode($input);
}
}
return (!$output) ? $input : $output;
}
/**
* Makes a string lowercase.
*
* @param string $string The string to be converted.
* @param bool $locale If true the string will be converted based on a
* given charset, locale independent else.
* @param string $charset If $locale is true, the charset to use when
* converting. If not provided the current charset.
*
* @return string The string with lowercase characters
*/
function lower($string, $locale = false, $charset = null)
{
static $lowers;
if ($locale) {
/* The existence of mb_strtolower() depends on the platform,
as of PHP 4.3.0. */
if (Horde::extensionExists('mbstring') &&
function_exists('mb_strtolower')) {
if (is_null($charset)) {
$charset = NLS::getCharset();
}
$ret = @mb_strtolower($string, $charset);
if (!empty($ret)) {
return $ret;
}
}
return strtolower($string);
}
if (!isset($lowers)) {
$lowers = array();
}
if (!isset($lowers[$string])) {
$language = setlocale(LC_CTYPE, 0);
setlocale(LC_CTYPE, 'en');
$lowers[$string] = strtolower($string);
setlocale(LC_CTYPE, $language);
}
return $lowers[$string];
}
/**
* Makes a string uppercase.
*
* @param string $string The string to be converted.
* @param bool $locale If true the string will be converted based on a
* given charset, locale independent else.
* @param string $charset If $locale is true, the charset to use when
* converting. If not provided the current charset.
*
* @return string The string with uppercase characters
*/
function upper($string, $locale = false, $charset = null)
{
static $uppers;
if ($locale) {
/* The existence of mb_strtoupper() depends on the platform,
as of PHP 4.3.0. */
if (Horde::extensionExists('mbstring') &&
function_exists('mb_strtoupper')) {
if (is_null($charset)) {
$charset = NLS::getCharset();
}
$ret = @mb_strtoupper($string, $charset);
if (!empty($ret)) {
return $ret;
}
}
return strtoupper($string);
}
if (!isset($uppers)) {
$uppers = array();
}
if (!isset($uppers[$string])) {
$language = setlocale(LC_CTYPE, 0);
setlocale(LC_CTYPE, 'en');
$uppers[$string] = strtoupper($string);
setlocale(LC_CTYPE, $language);
}
return $uppers[$string];
}
/**
* Returns part of a string.
*
* @param string $string The string to be converted.
* @param int $start The part's start position, zero based.
* @param int $length The part's length.
* @param string $charset The charset to use when calculating the part's
* position and length, defaults to current charset.
*
* @return string The string's part.
*/
function substr($string, $start, $length = null, $charset = null)
{
if (Horde::extensionExists('mbstring')) {
if (is_null($charset)) {
$charset = NLS::getCharset();
}
if (is_null($length)) {
$length = String::length($string, $charset);
}
$ret = @mb_substr($string, $start, $length, $charset);
if (!empty($ret)) {
return $ret;
}
}
if (is_null($length)) {
$length = String::length($string);
}
return substr($string, $start, $length);
}
/**
* Returns the character (not byte) length of a string.
*
* @param string $string The string to return the length of.
* @param string $charset The charset to use when calculating the string's
* length.
*
* @return string The string's part.
*/
function length($string, $charset = null)
{
if (Horde::extensionExists('mbstring')) {
if (is_null($charset)) {
$charset = NLS::getCharset();
}
$ret = @mb_strlen($string, $charset);
if (!empty($ret)) {
return $ret;
}
}
return strlen($string);
}
/**
* Returns the numeric position of the first occurrence of $needle in
* the $haystack string.
*
* @param string $haystack The string to search through.
* @param string $needle The string to search for.
* @param int $offset Allows to specify which character in haystack
* to start searching.
* @param string $charset The charset to use when searching for the
* $needle string.
*
* @return int The position of first occurrence.
*/
function pos($haystack, $needle, $offset = 0, $charset = null)
{
if (Horde::extensionExists('mbstring')) {
if (is_null($charset)) {
$charset = NLS::getCharset();
}
ini_set('track_errors', 1);
$ret = @mb_strpos($haystack, $needle, $offset, $charset);
ini_restore('track_errors');
if (!isset($php_errormsg)) {
return $ret;
}
}
return strpos($haystack, $needle, $offset);
}
function isAlpha($string, $charset = null)
{
/*
if (Horde::extensionExists('mbstring')) {
if (is_null($charset)) {
$charset = NLS::getCharset();
}
mb_regex_encoding($charset);
return mb_ereg_match('/\\w+/', $string) &&
!strstr($string, '_') &&
!mb_ereg_match('/\\d+/', $string);
}
*/
return ctype_alpha($string);
}
/**
* Returns true if every character in the parameter is a lowercase
* letter in the current locale.
*
* @param $string The string to test.
* @param $charset The charset to use when testing the string.
*
* @return bool True if the parameter was lowercase.
*/
function isLower($string, $charset = null)
{
return ((String::lower($string, true, $charset) === $string) &&
String::isAlpha($string, $charset));
}
/**
* Returns true if every character in the parameter is an uppercase
* letter in the current locale.
*
* @param $string The string to test.
* @param $charset The charset to use when testing the string.
*
* @return bool True if the parameter was uppercase.
*/
function isUpper($string, $charset = null)
{
return ((String::upper($string, true, $charset) === $string) &&
String::isAlpha($string, $charset));
}
}
--- NEW FILE: iCalendar.php ---
<?php
require_once(HORDE_BASE . '/lib/String.php');
/**
* Class representing iCalendar files
*
* $Horde: horde/lib/iCalendar.php,v 1.18 2003/07/03 09:22:13 mikec Exp $
*
* Copyright 2003 Mike Cochrane <mike at graftonhall.co.nz>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Mike Cochrane <mike at graftonhall.co.nz>
* @version $Revision: 1.1 $
* @since Horde 3.0
* @package horde.iCalendar
*/
class Horde_iCalendar {
var $_container = null;
var $_attributes = array();
var $_components = array();
/**
* Return a reference to a new component
*
* @param String $type The type of component to return
* @param Object $container A container that this component
* will be associtated with.
*
* @return Object Reference to a Horde_iCalendar_* object as specified.
*/
function &newComponent($type, &$container)
{
$class = 'Horde_iCalendar_' . String::lower($type);
@include_once dirname(__FILE__) . '/iCalendar/' . String::lower($type) . '.php';
if (class_exists($class)) {
return new $class($container);
} else {
// should return an dummy x-unknown type class here.
return false;
}
}
/**
* Include all the component classes, usefull if unserializing
* objects and needing to garantee all the classes have been defined.
*/
function includeComponentClasses()
{
static $allreadyRun;
if (!isset($allreadyRun) || $allreadyRun !== true) {
$dir = opendir(dirname(__FILE__) . '/iCalendar/');
while (($file = readdir($dir)) !== false) {
if (strstr($file, '.php') !== false) {
include_once dirname(__FILE__) . '/iCalendar/' . $file;
}
}
closedir($dir);
}
$allreadyRun == true;
}
/**
* Set the value of an attribute
*
* @param String $name The name of the attribute
* @param String $value The value of the attribute
* @param Array $params (optional) Array containing any addition
* parameters for this attribute.
*/
function setAttribute($name, $value, $params = array())
{
$found = false;
for ($i = 0; $i < count($this->_attributes); $i++)
{
if ($this->_attributes[$i]['name'] == $name)
{
$this->_attributes[$i]['params'] = $params;
$this->_attributes[$i]['value'] = $value;
$found = true;
}
}
if (!$found) // If not found, append
$this->_attributes[] = array('name' => $name, 'params' => $params, 'value' => $value);
}
function clearAttribute($name)
{
$cnt = count($this->_attributes);
for ($i = 0; $i < $cnt; $i++)
{
if ($this->_attributes[$i]['name'] == $name)
unset($this->_attributes[$i]);
}
}
/**
* Get the value of an attribute
*
* @param String $name The name of hte attribute
* @param Boolean $params Return the parameters for this attribute
* instead of its value
*
* @return mixed (boolean) False if the attribute does not exist
* (string) The value of the attribute
* (array) The parameters for the attribute or
* multiple values for an attribute
*/
function getAttribute($name, $params = false)
{
$result = array();
foreach ($this->_attributes as $attribute) {
if ($attribute['name'] == $name) {
if ($params) {
$result[] = $attribute['params'];
} else {
$result[] = $attribute['value'];
}
}
}
if (count($result) == 0) {
return PEAR::raiseError(_("Attribute Not Found"));
} if (count($result) == 1 && !$params) {
return $result[0];
} else {
return $result;
}
}
/**
* Get all attributes
*
* @return Array Array containsing all the attributes and their types.
*
*/
function getAllAttributes()
{
return $this->_attributes;
}
/**
* Add a vCalendar component (eg vEvent)
*
* @param Horde_iCalendar_* $component Component to add
*/
function addComponent(&$component)
{
$this->_components[] =& $component;
}
function &addNewComponent($type)
{
$obj = Horde_iCalendar::newComponent($type, $this);
if (!$obj) return NULL;
$this->addComponent($obj);
return $obj;
}
/**
* Retrieve all the components.
*
* @return Array Array of Horde_iCalendar_* objects
*/
function getComponents()
{
return $this->_components;
}
/**
* Retrieve a specific component.
*
* @param Integer $idx The index of the object to retrieve.
*
* @return mixed (boolean) False if the index does not exist.
* (Horde_iCalendar_*) The requested component.
*/
function getComponent($idx)
{
if (array_key_exists($idx, $this->_components)) {
return $this->_components[$idx];
} else {
return false;
}
}
/**
* Export as vCalendar format
*/
function exportvCalendar()
{
// Default values
$requiredAttributes['VERSION'] = '2.0';
$requiredAttributes['PRODID'] = '-//The Horde Project//Horde_iCalendar Library, Horde 3.0-cvs //EN';
$requiredAttributes['METHOD'] = 'PUBLISH';
foreach ($requiredAttributes as $name => $default_value) {
if (is_a($this->getattribute($name), 'PEAR_Error')) {
$this->setAttribute($name, $default_value);
}
}
return $this->_exportvData('VCALENDAR') . "\n";
}
function &findComponent($childclass)
{
$childclass = String::lower($childclass);
for ($i = 0; $i < count($this->_components); $i++)
if (is_a($this->_components[$i], 'Horde_iCalendar_' . $childclass))
return $this->_components[$i];
return NULL;
}
function clear()
{
$this->_components = array();
$this->_attributes = array();
}
function generateUID()
{
return uniqid('Horde.iCal-');
}
/**
* Parse a string containing vCalendar data.
*
* @param String $text The data to parse
* @param String $base The type of the base object.
*
*/
function parsevCalendar($text, $base = 'VCALENDAR', $clear = true)
{
if ($clear) $this->clear();
if (preg_match('/(BEGIN:' . $base . '\r?\n)([\W\w]*)(END:' . $base . '\r?\n?)/', $text, $matches)) {
$vCal = $matches[2];
} else {
return false;
}
// All sub components
$matches = null;
if (preg_match_all('/(BEGIN:)([\W\w]*)\r?\n?([\W\w]*)(END:)\2(\r\n|\r|\n)/', $vCal, $matches)) {
foreach ($matches[0] as $key => $data) {
$type = $matches[2][$key];
$component = &Horde_iCalendar::newComponent(trim($type), $this);
$component->parsevCalendar($data);
$this->addComponent($component);
// Remove from the vCalendar data
$vCal = str_replace($data, '', $vCal);
}
}
// Unfold any folded lines
$vCal = preg_replace ('/(\r|\n)+ /', '', $vCal);
// Parse the remain attributes
if (preg_match_all('/(.*):(.*)(\r|\n)+/', $vCal, $matches)) {
foreach ($matches[0] as $attribute) {
preg_match('/([^;^:]*)((;[^:]*)?):(.*)/', $attribute, $parts);
$tag = trim($parts[1]);
$value = trim($parts[4]);
$params = array();
if (!empty($parts[2])) {
preg_match_all('/;(([^;=]*)(=([^;]*))?)/', $parts[2], $param_parts);
foreach ($param_parts[2] as $key => $paramName) {
$paramValue = $param_parts[4][$key];
$params[$paramName] = $paramValue;
}
}
switch ($tag) {
case 'DESCRIPTION':
$value = preg_replace('/\\\\,/', ',', $value);
$value = preg_replace('/\\\\n/', "\n", $value);
$this->setAttribute($tag, $value, $params);
break;
// Date fields
case 'DTSTAMP':
case 'COMPLETED':
case 'CREATED':
case 'LAST-MODIFIED':
$this->setAttribute($tag, $this->_parseDateTime($value), $params);
break;
case 'DTEND':
case 'DTSTART':
case 'DUE':
case 'RECURRENCE-ID':
if (array_key_exists('VALUE', $params)) {
if ($params['VALUE'] == 'DATE') {
$this->setAttribute($tag, $this->_parseDate($value), $params);
} else {
$this->setAttribute($tag, $this->_parseDateTime($value), $params);
}
} else {
$this->setAttribute($tag, $this->_parseDateTime($value), $params);
}
break;
case 'RDATE':
if (array_key_exists('VALUE', $params)) {
if ($params['VALUE'] == 'DATE') {
$this->setAttribute($tag, $this->_parseDate($value), $params);
} else if ($params['VALUE'] == 'PERIOD') {
$this->setAttribute($tag, $this->_parsePeriod($value), $params);
} else {
$this->setAttribute($tag, $this->_parseDateTime($value), $params);
}
} else {
$this->setAttribute($tag, $this->_parseDateTime($value), $params);
}
break;
case 'TRIGGER':
if (array_key_exists('VALUE', $params)) {
if ($params['VALUE'] == 'DATE-TIME') {
$this->setAttribute($tag, $this->_parseDateTime($value), $params);
} else {
$this->setAttribute($tag, $this->_parseDuration($value), $params);
}
} else {
$this->setAttribute($tag, $this->_parseDuration($value), $params);
}
break;
case 'EXDATE':
// comma seperated dates
$values = array();
$dates = array();
preg_match_all('/,([^,]*)/', ',' . $value, $values);
foreach ($values as $value) {
if (array_key_exists('VALUE', $params)) {
if ($params['VALUE'] == 'DATE-TIME') {
$dates[] = $this->_parseDateTime($value);
} else if ($params['VALUE'] == 'DATE') {
$dates[] = $this->_parseDate($value);
}
} else {
$dates[] = $this->_parseDateTime($value);
}
}
$this->setAttribute($tag, $dates, $params);
break;
// Duration fields
case 'DURATION':
$this->setAttribute($tag, $this->_parseDuration($value), $params);
break;
// Period of time fields
case 'FREEBUSY':
$values = array();
$periods = array();
preg_match_all('/,([^,]*)/', ',' . $value, $values);
foreach ($values[1] as $value) {
$periods[] = $this->_parsePeriod($value);
}
$this->setAttribute($tag, $periods, $params);
break;
// UTC offset fields
case 'TZOFFSETFROM':
case 'TZOFFSETTO':
$this->setAttribute($tag, $this->_parseUtcOffset($value), $params);
break;
// Integer fields
case 'PERCENT-COMPLETE':
case 'PRIORITY':
case 'REPEAT':
case 'SEQUENCE':
$this->setAttribute($tag, intval($value), $params);
break;
// Geo fields
case 'GEO':
$floats = split(';', $value);
$value['latitude'] = floatval($floats[0]);
$value['longitude'] = floatval($floats[1]);
$this->setAttribute($tag, $value, $params);
break;
// Recursion fields
case 'EXRULE':
case 'RRULE':
default:
// string fields
$this->setAttribute($tag, trim($value), $params);
break;
}
}
}
return true;
}
/**
* Export this component as vCal format
*
* @param String $base (optional) The type of the base object.
*
* @return String vCal format data
*/
function _exportvData($base = 'VCALENDAR')
{
$newline = "\n";
$result = "BEGIN:" . $base . $newline;
foreach ($this->_attributes as $attribute) {
$name = $attribute['name'];
$params = $attribute['params'];
$params_str = '';
if (count($params) > 0) {
foreach ($params as $param_name => $param_value) {
$params_str .= ";$param_name=$param_value";
}
}
$value = $attribute['value'];
switch ($name) {
// Date fields
case 'DTSTAMP':
case 'COMPLETED':
case 'CREATED':
case 'LAST-MODIFIED':
$value = $this->_exportDateTime($value);
break;
case 'DTEND':
case 'DTSTART':
case 'DUE':
case 'RECURRENCE-ID':
if (array_key_exists('VALUE', $params)) {
if ($params['VALUE'] == 'DATE') {
$value = $this->_exportDate($value);
} else {
$value = $this->_exportDateTime($value);
}
} else {
$value = $this->_exportDateTime($value);
}
break;
case 'RDATE':
if (array_key_exists('VALUE', $params)) {
if ($params['VALUE'] == 'DATE') {
$value = $this->_exportDate($value);
} else if ($params['VALUE'] == 'PERIOD') {
$value = $this->_exportPeriod($value);
} else {
$value = $this->_exportDateTime($value);
}
} else {
$value = $this->_exportDateTime($value);
}
break;
case 'TRIGGER':
if (array_key_exists('VALUE', $params)) {
if ($params['VALUE'] == 'DATE-TIME') {
$value = $this->_exportDateTime($value);
} else if ($params['VALUE'] == 'DURATION') {
$value = $this->_exportDuration($value);
}
} else {
$value = $this->_exportDuration($value);
}
break;
// Duration fields
case 'DURATION':
$value = $this->_exportDuration($value);
break;
// Period of time fields
case 'FREEBUSY':
$value_str = '';
foreach ($value as $period) {
$value_str .= empty($value_str) ? '' : ',';
$value_str .= $this->_exportPeriod($period);
}
$value = $value_str;
break;
// UTC offset fields
case 'TZOFFSETFROM':
case 'TZOFFSETTO':
$value = $this->_exportUtcOffset($value);
break;
// Integer fields
case 'PERCENT-COMPLETE':
case 'PRIORITY':
case 'REPEAT':
case 'SEQUENCE':
$value = "$value";
break;
// Geo fields
case 'GEO':
$value = $value['latitude'] . ',' . $value['longitude'];
break;
// Recursion fields
case 'EXRULE':
case 'RRULE':
}
$attr_string = "$name$params_str:$value";
$result .= $this->_foldLine($attr_string, $newline) . $newline;
}
foreach ($this->getComponents() as $component) {
$result .= $component->exportvCalendar($this) . $newline;
}
$result .= "END:" . $base;
return $result;
}
/**
* Parse a UTC Offset field
*/
function _parseUtcOffset($text)
{
$offset = array();
if (preg_match('/(\+|-)([0-9]{2})([0-9]{2})([0-9]{2})?/', $text, $timeParts)) {
$offset['ahead'] = (boolean)($timeParts[1] == '+');
$offset['hour'] = intval($timeParts[2]);
$offset['minute'] = intval($timeParts[3]);
if (array_key_exists(4, $timeParts)) {
$offset['second'] = intval($timeParts[4]);
}
return $offset;
} else {
return false;
}
}
/**
* Export a UTC Offset field
*/
function _exportUtcOffset($value)
{
$offset = $value['ahead'] ? '+' : '-';
$offset .= sprintf('%02d%02d',
$value['hour'], $value['minute']);
if (array_key_exists('second', $value)) {
$offset .= sprintf('%02d', $value['second']);
}
return $offset;
}
/**
* Parse a Time Period field
*/
function _parsePeriod($text)
{
$periodParts = split('/', $text);
$start = $this->_parseDateTime($periodParts[0]);
if ($duration = $this->_parseDuration($periodParts[1])) {
return array('start' => $start, 'duration' => $duration);
} else if($end = $this->_parseDateTime($periodParts[1])) {
return array('start' => $start, 'end' => $end);
}
}
/**
* Export a Time Period field
*/
function _exportPeriod($value)
{
$period = $this->_exportDateTime($value['start']);
$period .= '/';
if (array_key_exists('duration', $value)) {
$period .= $this->_exportDuration($value['duration']);
} else {
$period .= $this->_exportDateTime($value['end']);
}
return $period;
}
/**
* Parse a DateTime field
*/
function _parseDateTime($text)
{
$dateParts = split('T', $text);
if (count($dateParts) != 2 && !empty($text)) {
// not a date time field but may be just a date field
if (!$date = $this->_parseDate($text)) {
return $date;
}
return gmmktime (0, 0, 0, $date['month'], $date['mday'], $date['year']);
}
if (!$date = $this->_parseDate($dateParts[0])) {
return $date;
}
if (!$time = $this->_parseTime($dateParts[1])) {
return $time;
}
if ($time['zone'] == 'UTC') {
return gmmktime ($time['hour'], $time['minute'], $time['second'],
$date['month'], $date['mday'], $date['year']);
} else {
return mktime ($time['hour'], $time['minute'], $time['second'],
$date['month'], $date['mday'], $date['year']);
}
}
/**
* Export a DateTime field
*/
function _exportDateTime($value)
{
$temp = array();
if (!is_object($value)) {
$TZOffset = 3600 * substr(date('O'), 0, 3);
$TZOffset += 60 * substr(date('O'), 3, 2);
$value -= $TZOffset;
$temp['zone'] = 'UTC';
$temp['year'] = date('Y', $value);
$temp['month'] = date('n', $value);
$temp['mday'] = date('j', $value);
$temp['hour'] = date('G', $value);
$temp['minute'] = date('i', $value);
$temp['second'] = date('s', $value);
} else {
$dateOb = $value;
// minutes
$TZOffset = substr(date('O'), 3, 2);
$thisMin = $dateOb->min - $TZOffset;
// hours
$TZOffset = substr(date('O'), 0, 3);
$thisHour = $dateOb->hour - $TZOffset;
if ($thisMin < 0) {
$thisHour -= 1;
$thisMin += 60;
}
if ($thisHour < 0) {
require_once 'Date/Calc.php';
$prevday = Date_Calc::prevDay($dateOb->mday, $dateOb->month, $dateOb->year);
$dateOb->mday = substr($prevday, 6, 2);
$dateOb->month = substr($prevday, 4, 2);
$dateOb->year = substr($prevday, 0, 4);
$thisHour += 24;
}
$temp['zone'] = 'UTC';
$temp['year'] = $dateOb->year;
$temp['month'] = $dateOb->month;
$temp['mday'] = $dateOb->mday;
$temp['hour'] = $thisHour;
$temp['minute'] = $dateOb->min;
$temp['second'] = $dateOb->sec;
}
return Horde_iCalendar::_exportDate($temp) . 'T' . Horde_iCalendar::_exportTime($temp);
}
/**
* Parse a Time field
*/
function _parseTime($text)
{
if (preg_match('/([0-9]{2})([0-9]{2})([0-9]{2})(Z)?/', $text, $timeParts)) {
$time['hour'] = intval($timeParts[1]);
$time['minute'] = intval($timeParts[2]);
$time['second'] = intval($timeParts[3]);
if (array_key_exists(4, $timeParts)) {
$time['zone'] = 'UTC';
} else {
$time['zone'] = 'Local';
}
return $time;
} else {
return false;
}
}
/**
* Export a Time field
*/
function _exportTime($value)
{
$time = sprintf('%02d%02d%02d',
$value['hour'], $value['minute'], $value['second']);
if ($value['zone'] == 'UTC') {
$time .= 'Z';
}
return $time;
}
/**
* Parse a Date field
*/
function _parseDate($text)
{
if (strlen($text) != 8) {
return false;
}
$date['year'] = intval(substr($text, 0, 4));
$date['month'] = intval(substr($text, 4, 2));
$date['mday'] = intval(substr($text, 6, 2));
return $date;
}
/**
* Export a Date field
*/
function _exportDate($value)
{
return sprintf('%04d%02d%02d',
$value['year'], $value['month'], $value['mday']);
}
/**
* Parse a Duration Value field
*/
function _parseDuration($text)
{
if (preg_match('/([+]?|[-])P(([0-9]+W)|([0-9]+D)|)(T(([0-9]+H)|([0-9]+M)|([0-9]+S))+)?/', trim($text), $durvalue)) {
// weeks
$duration = 7 * 86400 * intval($durvalue[3]);
if (count($durvalue) > 4) {
// days
$duration += 86400 * intval($durvalue[4]);
}
if (count($durvalue) > 5) {
// hours
$duration += 3600 * intval($durvalue[7]);
// mins
if (array_key_exists(8, $durvalue)) {
$duration += 60 * intval($durvalue[8]);
}
// secs
if (array_key_exists(9, $durvalue)) {
$duration += intval($durvalue[9]);
}
}
// sign
if ($durvalue[1] == "-") {
$duration *= -1;
}
return $duration;
} else {
return false;
}
}
/**
* Export a duration value
*/
function _exportDuration($value)
{
$duration = '';
if ($value < 0) {
$value *= -1;
$duration .= '-';
}
$duration .= 'P';
$weeks = floor($value / (7 * 86400));
$value = $value % (7 * 86400);
if ($weeks) {
$duration .= $weeks . 'W';
}
$days = floor($value / (86400));
$value = $value % (86400);
if ($days) {
$duration .= $days . 'D';
}
if ($value) {
$duration .= 'T';
$hours = floor($value / 3600);
$value = $value % 3600;
if ($hours) {
$duration .= $hours . 'H';
}
$mins = floor($value / 60);
$value = $value % 60;
if ($mins) {
$duration .= $mins . 'M';
}
if ($value) {
$duration .= $value . 'S';
}
}
return $duration;
}
/**
* Return the folded version of a line
*/
function _foldLine($line, $newline)
{
$line = preg_replace ('/(\r\n|\n|\r)/', '\n', $line);
if (strlen($line) > 75) {
$foldedline = '';
while(!empty($line)) {
$maxLine = substr($line, 0, 75);
$cutPoint = max(60, max(strrpos($maxLine, ';'), strrpos($maxLine, ':')) + 1);
$foldedline .= (empty($foldedline)) ?
substr($line, 0, $cutPoint) :
$newline . ' ' . substr($line, 0, $cutPoint);
$line = (strlen($line) <= $cutPoint) ? '' : substr($line, $cutPoint);
}
return $foldedline;
}
return $line;
}
}
--- NEW FILE: kronolith_kolab.php ---
<?php
/**
* Horde Kronolith driver for the Kolab IMAP server.
* Based on code by Adriaan Putter <kougom at yahoo.com>
*
* Copyright (C) 2003 Code Fusion, cc.
* Written by Stuart Bingë <s.binge at codefusion.co.za>
*
* Created 2003-08-25
* Last Modified 2003-08-29 by Stuart Bingë
*/
require_once(HORDE_BASE . '/lib/Kolab.php');
require_once(HORDE_BASE . '/lib/iCalendar.php');
class Kronolith_Driver_kolab extends Kronolith_Driver {
var $params = array();
var $_folder;
var $_server;
var $imap;
function Kronolith_Driver_kolab($params = array())
{
$this->type = 'kolab';
$this->params = $params;
$this->_folder = $params['folder'];
$this->_server = $params['server'];
}
function open($calendar)
{
$this->_calendar = $calendar;
$this->imap = Kolab::OpenImapConnection($this->_server, $this->_folder);
if (!$this->imap) return PEAR::raiseError('Unable to open IMAP connection.');
return true;
}
function close()
{
Kolab::CloseIMAPConnection($this->imap);
}
function delete($calendar)
{
// nothing for now...
}
function listEvents($startDate = null, $endDate = null)
{
$events = array();
$msgs = Kolab::GetMessageList($this->imap);
$cal = new Horde_iCalendar;
for ($i = 0; $i < count($msgs); $i++)
{
$body = imap_body($this->imap, $msgs[$i]);
$cal->_components = array();
$cal->parsevCalendar($body);
$components = $cal->getComponents();
$ispresent = false;
foreach ($components as $component)
{
if (!is_a($component, 'Horde_iCalendar_vevent')) continue;
$startattr = $component->getAttribute('DTSTART');
if (is_array($startattr) || is_a($startattr, 'PEAR_Error')) continue;
$start = getdate($startattr);
if (!$ispresent &&
$start['year'] >= $startDate->year && $start['year'] <= $endDate->year &&
$start['mon'] >= $startDate->month && $start['mon'] <= $endDate->month &&
$start['mday'] >= $startDate->mday && $start['mday'] <= $endDate->mday)
{
array_push($events, $component->getAttribute('UID'));
$ispresent = true;
}
}
}
return $events;
}
function listAlarms($date)
{
$events = $this->listEvents($date, $date);
$alarms = array();
$cal = new Horde_iCalendar;
foreach ($events as $event)
{
$matches = imap_search($this->imap, "SUBJECT $event");
if (!is_array($matches) || count($matches) < 1) continue;
$body = imap_body($this->imap, $matches[0]);
$cal->parsevCalendar($body);
$components = $cal->getComponents();
foreach ($components as $component)
{
if (!is_a($component, 'Horde_iCalendar_vevent')) continue;
$subcomps = $component->getComponents();
foreach ($subcomps as $subcomp)
{
if (!is_a($subcomp, 'Horde_iCalendar_valarm')) continue;
$ts = Kronolith::objectToTimestamp($date);
$dateattr = $component->getAttribute('DTSTART');
if (is_array($dateattr) || is_a($dateattr, 'PEAR_Error')) continue;
$offset = $subcomp->getAttribute("TRIGGER");
$diff = $ts - $dateattr;
if ($diff >= $offset && $diff <= 0)
array_push($alarms, $event);
}
}
}
return $alarms;
}
function &getEventObject($eventID = null)
{
if (!is_null($eventID)) {
$cal = new Horde_iCalendar;
$matches = imap_search($this->imap, "SUBJECT $eventID");
if (!is_array($matches) || count($matches) < 1) return false;
$body = imap_body($this->imap, $matches[0]);
$headers = Kolab::GetMessageHeaders($this->imap, $matches[0]);
$cat = Kolab::GetHeaderValue($headers, X_HEAD_CAT, 0);
$cal->parsevCalendar($body);
$components = $cal->getComponents();
foreach ($components as $component)
{
if (!is_a($component, 'Horde_iCalendar_vevent')) continue;
$obj = new Kronolith_Event_kolab($this, $component);
$obj->category = $cat;
return $obj;
}
return false;
} else {
return new Kronolith_Event_kolab($this);
}
}
function saveEvent($event)
{
// $event should be a Kronolith_Event_kolab
list($user, $pass) = Kolab::GetAuthentication();
$mailbox = Kolab::MailboxURI($this->_server, $this->_folder);
$eventID = $event->getID();
$cal = new Horde_iCalendar;
$alobj = NULL;
if (!is_null($eventID))
{
$matches = imap_search($this->imap, "SUBJECT $eventID");
if (!is_array($matches) || count($matches) < 1) return false;
$body = imap_body($this->imap, $matches[0]);
imap_delete($this->imap, $matches[0]);
imap_expunge($this->imap);
$cal->parsevCalendar($body);
$evobj =& $cal->findComponent('VEVENT');
if (!is_null($evobj))
$alobj =& $evobj->findComponent('VALARM');
}
else
{
$eventID = uniqid('kronolith-');
$evobj =& $cal->addNewComponent('VEVENT');
$evobj->setAttribute('CREATED', time());
$evobj->setAttribute('UID', $eventID);
}
if (is_null($evobj)) return PEAR::raiseError("Unable to locate event object for event $eventID");
$evobj->setAttribute('SUMMARY', $event->getTitle());
$evobj->setAttribute('DESCRIPTION', $event->getDescription());
$evobj->setAttribute('LOCATION', $event->getLocation());
$evobj->setAttribute('LAST-MODIFIED', time());
$evobj->setAttribute('ORGANIZER', $user);//$event->getCreatorID());
$evobj->setAttribute('DTSTART', $event->getStartTimestamp());
$evobj->setAttribute('DTEND', $event->getEndTimestamp());
$trigger = $event->getAlarm();
if ($trigger != 0)
{
if (is_null($alobj))
$alobj =& $evobj->addNewComponent('VALARM');
$alobj->setAttribute('TRIGGER', $trigger);
}
$body = str_replace("\n", MIME_NL, $cal->exportvCalendar());
if (!Kolab::AddMessage($this->imap, $mailbox, $user, 'text/calendar', $body, 'Kronolith', array(
'Subject' => $eventID,
X_HEAD_CAT => $event->getCategory()
)))
return PEAR::raiseError('Unable to add task.');
return true;
}
function nextRecurrence($eventID, $afterDate, $weekstart = KRONOLITH_SUNDAY)
{
return false; // nothing for now...
}
function deleteEvent($eventID)
{
$matches = imap_search($this->imap, "SUBJECT $eventID");
if (!is_array($matches) || count($matches) < 1) return false;
imap_delete($this->imap, $matches[0]);
imap_expunge($this->imap);
}
}
class Kronolith_Event_kolab extends Kronolith_Event {
function toDriver()
{
// Nothing - all this is done in the drivers' saveEvent() function
}
function fromDriver($icalEvent)
{
// $icalEvent should be a Horde_iCalendar_vevent
$tmp = $icalEvent->getAttribute('SUMMARY');
if (!is_array($tmp) && !is_a($tmp, 'PEAR_Error'))
$this->title = $tmp;
$tmp = $icalEvent->getAttribute('DESCRIPTION');
if (!is_array($tmp) && !is_a($tmp, 'PEAR_Error'))
$this->description = $tmp;
$tmp = $icalEvent->getAttribute('LOCATION');
if (!is_array($tmp) && !is_a($tmp, 'PEAR_Error'))
$this->location = $tmp;
$tmp = $icalEvent->getAttribute('ORGANIZER');
if (!is_array($tmp) && !is_a($tmp, 'PEAR_Error'))
$this->creatorID = $tmp;
$tmp = $icalEvent->getAttribute('DTSTART');
if (!is_array($tmp) && !is_a($tmp, 'PEAR_Error'))
{
$this->startTimestamp = $tmp;
$this->start = Kronolith::timestampToObject($this->startTimestamp);
}
$tmp = $icalEvent->getAttribute('DTEND');
if (!is_array($tmp) && !is_a($tmp, 'PEAR_Error'))
{
$this->endTimestamp = $tmp;
$this->end = Kronolith::timestampToObject($this->endTimestamp);
}
$this->durMin = ($this->endTimestamp - $this->startTimestamp) / 60;
$this->eventID = $icalEvent->getAttribute('UID');
// No recurring events for now...
$this->recurType = KRONOLITH_RECUR_NONE;
$this->recurInterval = 0;
$subcomps = $icalEvent->getComponents();
foreach ($subcomps as $subcomp)
{
if (!is_a($subcomp, 'Horde_iCalendar_valarm')) continue;
$tmp = $subcomp->getAttribute('TRIGGER');
if (!is_array($tmp) && !is_a($tmp, 'PEAR_Error'))
$this->alarm = $tmp;
}
$this->initialized = true;
}
}
--- NEW FILE: mnemo_kolab.php ---
<?php
/**
* Horde Mnemo driver for the Kolab IMAP server.
* Based on code by Adriaan Putter <kougom at yahoo.com>
*
* Copyright (C) 2003 Code Fusion, cc.
* Written by Stuart Bingë <s.binge at codefusion.co.za>
*
* Created 2003-08-20
* Last Modified 2003-08-29 by Stuart Bingë
*/
require_once(HORDE_BASE . '/lib/Kolab.php');
require_once(HORDE_BASE . '/lib/iCalendar.php');
class Mnemo_Driver_kolab extends Mnemo_Driver {
var $_params = array();
var $_folder;
var $_server;
function Mnemo_Driver_kolab($user, $params)
{
$this->type = 'kolab';
$this->user = $user;
$this->_params = $params;
$this->_folder = $params['folder'];
$this->_server = $params['server'];
}
function retrieve()
{
$imap = Kolab::OpenImapConnection($this->_server, $this->_folder);
if (!$imap) return PEAR::raiseError('Unable to open IMAP connection.');
$this->memos = array();
$mod = false;
$msgs = Kolab::GetMessageList($imap);
for ($i = 0; $i < count($msgs); $i++)
{
$body = imap_body($imap, $msgs[$i]);
$desc = explode(MIME_NL, $body);
$body = str_replace(MIME_NL, "\n", $body);
$headers = Kolab::GetMessageHeaders($imap, $msgs[$i]);
$cat = Kolab::GetHeaderValue($headers, X_HEAD_CAT, 0);
$uid = Kolab::GetHeaderValue($headers, X_HEAD_ID);
$flags = 0;
if (is_null($uid))
{
$uid = uniqid("0x");
$flags = memo_MODIFIED;
$mod = true;
}
$memo = array();
$memo['message_id'] = $msgs[$i];
$memo['memo_id'] = $uid;
$memo['desc'] = $desc[0];
$memo['body'] = $body;
$memo['category'] = $cat;
$memo['private'] = "";
$memo['flags'] = $flags;
$this->memos[$uid] = $memo;
}
Kolab::CloseIMAPConnection($imap);
if ($mod)
$this->store(); // Re-save the non-Mnemo memos to ensure they have their Message IDs set corerctly
return true;
}
function store()
{
$added_memos = $this->listMemos(MEMO_ADDED);
$modified_memos = $this->listMemos(MEMO_MODIFIED);
$deleted_memos = $this->listMemos(MEMO_DELETED);
if ((count($added_memos) == 0) && (count($modified_memos) == 0) && (count($deleted_memos) == 0))
return true; // No-op
$imap = Kolab::OpenImapConnection($this->_server, $this->_folder);
if (!$imap) return PEAR::raiseError('Unable to open IMAP connection.');
list($user, $pass) = Kolab::GetAuthentication();
$mailbox = Kolab::MailboxURI($this->_server, $this->_folder);
foreach ($added_memos as $memo_id => $memo)
{
$body = str_replace("\n", MIME_NL, $memo['body']);
if (!Kolab::AddMessage($imap, $mailbox, $user, 'text/plain', $body, 'Mnemo', array(
X_HEAD_ID => strval($memo_id),
X_HEAD_CAT => $memo['category']
)))
{
Kolab::CloseIMAPConnection($imap);
return PEAR::raiseError('Unable to add memo.');
}
$this->setFlag($memo_id, MEMO_ADDED, false);
}
foreach ($modified_memos as $memo_id => $memo)
{
$mid = $memo['message_id'];
if (is_null($mid)) continue;
@imap_delete($imap, $mid);
$body = str_replace("\n", MIME_NL, $memo['body']);
if (!Kolab::AddMessage($imap, $mailbox, $user, 'text/plain', $body, 'Mnemo', array(
X_HEAD_ID => strval($memo_id),
X_HEAD_CAT => $memo['category']
)))
{
Kolab::CloseIMAPConnection($imap);
return PEAR::raiseError('Unable to add memo.');
}
$this->setFlag($memo_id, MEMO_MODIFIED, false);
}
foreach ($deleted_memos as $memo_id => $memo)
{
$mid = $memo['message_id'];
if (is_null($mid)) continue;
@imap_delete($imap, $mid);
}
$this->purgeDeleted();
Kolab::CloseIMAPConnection($imap);
return true;
}
}
--- NEW FILE: nag_kolab.php ---
<?php
/**
* Horde Nag driver for the Kolab IMAP server.
* Based on code by Adriaan Putter <kougom at yahoo.com>
*
* Copyright (C) 2003 Code Fusion, cc.
* Written by Stuart Bingë <s.binge at codefusion.co.za>
*
* Created 2003-08-25
* Last Modified 2003-08-29 by Stuart Bingë
*/
require_once(HORDE_BASE . '/lib/Kolab.php');
require_once(HORDE_BASE . '/lib/iCalendar.php');
class Nag_Driver_kolab extends Nag_Driver {
var $_params = array();
var $_folder;
var $_server;
function Nag_Driver_kolab($user, $params = array())
{
$this->type = 'kolab';
$this->_user = $user;
$this->_params = $params;
$this->_folder = $params['folder'];
$this->_server = $params['server'];
}
function retrieve()
{
$imap = Kolab::OpenImapConnection($this->_server, $this->_folder);
if (!$imap) return PEAR::raiseError('Unable to open IMAP connection.');
$this->_tasks = array();
$mod = false;
$cal = new Horde_iCalendar;
$msgs = Kolab::GetMessageList($imap);
for ($i = 0; $i < count($msgs); $i++)
{
$cal->parsevCalendar(imap_body($imap, $msgs[$i]));
$todo =& $cal->findComponent('VTODO');
if (is_null($todo)) continue;
$headers = Kolab::GetMessageHeaders($imap, $msgs[$i]);
$cat = Kolab::GetHeaderValue($headers, X_HEAD_CAT, 0);
$uid = Kolab::GetHeaderValue($headers, X_HEAD_ID);
$flags = 0;
if (is_null($uid))
{
$uid = uniqid("0x");
$flags = TASK_MODIFIED;
$mod = true;
}
$due = $todo->getAttribute('DUE');
if (is_a($due, 'PEAR_Error')) $due = 0;
else if (is_array($due)) $due = Kolab::ArrayToTimestamp($due);
$com = $todo->getAttribute('PERCENT-COMPLETE');
if (is_a($com, 'PEAR_Error')) $com = 0; else if ($com == 100) $com = 1; else $com = 0;
$task = array();
$task['message_id'] = $msgs[$i];
$task['task_id'] = $uid;
$task['name'] = $todo->getAttribute('SUMMARY');
$task['desc'] = $todo->getAttribute('DESCRIPTION');
$task['category'] = $cat;
$task['due'] = $due;
$task['priority'] = $todo->getAttribute('PRIORITY');
$task['completed'] = $com;
$task['flags'] = $flags;
$this->_tasks[$uid] = $task;
}
Kolab::CloseIMAPConnection($imap);
if ($mod)
$this->store(); // Re-save the non-Nag tasks to ensure they have their Message IDs set corerctly
return true;
}
function store()
{
$added_tasks = $this->listTasks(TASK_ADDED);
$modified_tasks = $this->listTasks(TASK_MODIFIED);
$deleted_tasks = $this->listTasks(TASK_DELETED);
if ((count($added_tasks) == 0) && (count($modified_tasks) == 0) && (count($deleted_tasks) == 0))
return true; // No-op
$imap = Kolab::OpenImapConnection($this->_server, $this->_folder);
if (!$imap) return PEAR::raiseError('Unable to open IMAP connection.');
list($user, $pass) = Kolab::GetAuthentication();
$cal = new Horde_iCalendar;
$mailbox = Kolab::MailboxURI($this->_server, $this->_folder);
foreach ($added_tasks as $task_id => $task)
{
$cal->clear();
$todo =& $cal->addNewComponent('VTODO');
if (!$todo)
{
Kolab::CloseIMAPConnection($imap);
return PEAR::raiseError('Unable to add task.');
}
if ($task['completed']) $com = 100; else $com = 0;
$uid = $cal->generateUID();
$todo->setAttribute('UID', $uid);
$todo->setAttribute('SUMMARY', $task['name']);
$todo->setAttribute('DESCRIPTION', $task['desc']);
$todo->setAttribute('PRIORITY', $task['priority']);
$todo->setAttribute('PERCENT-COMPLETE', $com);
$todo->setAttribute('ORGANIZER', 'MAILTO:' . $user);
$todo->setAttribute('CREATED', time());
$todo->setAttribute('LAST-MODIFIED', time());
if ($task['due'] != 0) $todo->setAttribute('DUE', $task['due']);
$body = str_replace("\n", MIME_NL, $cal->exportvCalendar());
if (!Kolab::AddMessage($imap, $mailbox, $user, 'text/calendar', $body, 'Nag', array(
'Subject' => $uid,
X_HEAD_ID => strval($task_id),
X_HEAD_CAT => $task['category']
)))
{
Kolab::CloseIMAPConnection($imap);
return PEAR::raiseError('Unable to add task.');
}
$this->setFlag($task_id, TASK_ADDED, false);
}
foreach ($modified_tasks as $task_id => $task)
{
$mid = $task['message_id'];
if (is_null($mid)) continue;
$cal->parsevCalendar(imap_body($imap, $mid));
@imap_delete($imap, $mid);
$todo =& $cal->findComponent('VTODO');
if (!$todo)
{
Kolab::CloseIMAPConnection($imap);
return PEAR::raiseError('Unable to modify task.');
}
if ($task['completed']) $com = 100; else $com = 0;
$todo->setAttribute('SUMMARY', $task['name']);
$todo->setAttribute('DESCRIPTION', $task['desc']);
$todo->setAttribute('PRIORITY', $task['priority']);
$todo->setAttribute('PERCENT-COMPLETE', $com);
$todo->setAttribute('ORGANIZER', 'MAILTO:' . $user);
$todo->setAttribute('LAST-MODIFIED', time());
if ($task['due'] != 0)
$todo->setAttribute('DUE', $task['due']);
else
$todo->clearAttribute('DUE');
$body = str_replace("\n", MIME_NL, $cal->exportvCalendar());
if (!Kolab::AddMessage($imap, $mailbox, $user, 'text/calendar', $body, 'Nag', array(
'Subject' => $todo->getAttribute('UID'),
X_HEAD_ID => strval($task_id),
X_HEAD_CAT => $task['category']
)))
{
Kolab::CloseIMAPConnection($imap);
return PEAR::raiseError('Unable to modify task.');
}
$this->setFlag($task_id, TASK_MODIFIED, false);
}
foreach ($deleted_tasks as $task_id => $task)
{
$mid = $task['message_id'];
if (is_null($mid)) continue;
@imap_delete($imap, $mid);
}
$this->purgeDeleted();
Kolab::CloseIMAPConnection($imap);
return true;
}
}
?>
--- NEW FILE: turba_kolab.php ---
<?php
/**
* Turba directory driver implementation for KOLAB extension.
*
*
* Adriaan Putter <kougom at yahoo.com>
*/
class Turba_Driver_kolab extends Turba_Driver {
/** String containg the name of the IMAP Folder containing Contacts. */
var $folder = '';
var $server = '';
var $cbox; // imap stream
var $err_mbox_dne = "Mailbox does not exist";
// This is used for error checking on function return - is there a better way to do this other than string comparison?
function TestError($error)
{
return strcasecmp(imap_last_error(), $error) == 0;
}
/**
* Constructs a new Turba Kolab driver object.
*
* @param $params Hash containing additional configuration parameters.
*/
function Turba_Driver_kolab($params)
{
$this->type = 'kolab';
$this->params = $params;
$this->folder = $params['folder'];
$this->server = $params['server'];
// Use the same username and password to connect to IMAP server
// It is also assumed that Horde uses the imap driver for authentication
$user = Auth::getAuth();
// $userID is of the format user at host@kolabtest, and we need the user at host portion, so use strrpos('@')
//$user = substr($userID, 0, strrpos($userID, "@"));
$pass = Auth::getCredential('password');
$connbase = '{' . $this->server . ':143/imap/notls}';
$connstr = $connbase . $this->folder;
$this->cbox = imap_open($connstr, $user, $pass);
if ($this->TestError($this->err_mbox_dne))
{
Horde::raiseMessage("Contacts folder does not exist, creating...", HORDE_MESSAGE);
$this->cbox = imap_open($connbase, $user, $pass, OP_HALFOPEN);
if (!$this->cbox)
{
Horde::raiseMessage("Error creating contacts folder - \"" . imap_last_error() . "\".", HORDE_ERROR);
$this->errno = -1;
return;
}
if (!@imap_createmailbox($this->cbox, $connstr))
{
Horde::raiseMessage("Error creating contacts folder - \"" . imap_last_error() . "\".", HORDE_ERROR);
$this->errno = -1;
return;
}
imap_close($this->cbox);
$this->cbox = imap_open($connstr, $user, $pass);
}
if (!$this->cbox)
{
Horde::raiseMessage("Error opening contacts folder - \"" . imap_last_error() . "\".", HORDE_ERROR);
$this->errno = -1;
return;
}
// Horde::raiseMessage("IMAPHost=\"" . $connstr . "\" Login=\"" . $user . ":" . $pass . "\"" , HORDE_MESSAGE);
}
/**
* Searches the Kolab contacts filter with the given criteria and returns a
* filtered list of results. If the criteria parameter is an empty
* array, all records will be returned.
*
* @param $criteria Array containing the search criteria.
* @param $fields List of fields to return.
* @param $strict_fields (optional) Array of fields which must be matched
* exactly.
* @param const $match Do an 'and' or an 'or' search (defaults to TURBA_SEARCH_AND).
*
* @return Hash containing the search results.
*/
function search($criteria, $fields, $strict_fields = array(), $match = TURBA_SEARCH_AND)
{
$results = array();
/* Get how many messages is in folder */
$msgs = imap_num_msg( $this->cbox );
$sort = imap_sort( $this->cbox, SORTDATE, 0 );
$entry = array();
for ( $i = 0; $i < $msgs; $i++) {
$vcard = imap_body( $this->cbox, $sort[$i] );
$vc = $this->loadVCard( $vcard );
if (count($criteria) > 0 ) {
foreach( $criteria as $key => $val ) {
/* This needs work to do advance searches */
/* filter for each criteria */
if( preg_match("/" . $val . "/i", $vc[$key] ) ) {
foreach($fields as $field) {
$entry[$field] = $vc[$field];
}
}
}
}
else {
foreach($fields as $field) {
$entry[$field] = $vc[$field];
}
}
$results[] = $entry;
}
return $results;
}
/**
* Read the given data from the Kolab Contacts Folder and returns
* the result's fields.
*
* @param $criteria Search criteria.
* @param $id Data identifier.
* @param $fields List of fields to return.
*
* @return Hash containing the search results.
*/
function read($criteria, $id, $fields)
{
$result = array();
$sort = imap_sort($this->cbox, SORTDATE, 0);
$msgs = imap_num_msg( $this->cbox );
$entry = array();
// Go through each message to search for the types and values
for ( $i = 0; $i < $msgs; $i++) {
$vcard = imap_body( $this->cbox, $sort[$i]);
$vc = $this->loadVCard( $vcard );
if ( preg_match( "/" . $id . "/", $vc[$criteria] ) ) {
foreach($fields as $field) {
$entry[$field] = $vc[$field];
}
$result[] = $entry;
}
}
return $result;
}
/**
* Closes the current (IMAP) Kolab Contacts Folder connection.
*
* @return The result of the disconnect() call.
*/
function close()
{
return imap_close( $this->cbox );
}
/**
* Adds the specified object to the Kolab Contacts Folder.
*/
function addObject($attributes)
{
$nl = "\r\n";
if ( $attributes['fn'] == "" )
return new PEAR_Error("Must specify a Name");
$vcard = $this->createVCard( $attributes );
// Create message header and add vCard
$userID = Auth::getAuth();
$msg = 'Content-Type: Text/X-VCard; charset="utf-8"'.$nl
.'From: '.$userID.$nl
.'Reply-To:'.$nl
.'To: '.$attributes['fn'].$nl
.'Subject: Contact: '.$attributes['fn'].$nl
.'User-Agent: Horde/Turba/Kolab'.$nl
.'Date: '.date('r').$nl
.$nl
.$vcard;
$connstr = '{' . $this->server . ':143/imap}' . $this->folder;
if (!imap_append( $this->cbox, $connstr, $msg )){
return new PEAR_Error( 'Could not save message in Contacts folder! because, '.imap_last_error() );
}
else {
return true;
}
}
/**
* Deletes the specified object from the Kolab Contacts Folder.
*/
function removeObject($object_key, $object_id)
{
// Find message with UID and delete and expunge the mailbox
$msg = imap_search( $this->cbox, "BODY \"".strtoupper($object_key).":".$object_id."\"" );
if ( count($msg) == 0 || count($msg) > 1 )
return new PEAR_Error('Could not delete, there are none found or no many found');
else
{
if(!imap_delete( $this->cbox, $msg[0] ))
return new PEAR_Error('Could not delete, because: '.imap_last_error() );
else
imap_expunge( $this->cbox );
}
return true;
}
/**
* Saves the specified object in the Kolab Contacts Folder.
*/
function setObject($object_key, $object_id, $attributes)
{
// Find message that contains the UID
$msg = imap_search( $this->cbox, "BODY \"".strtoupper($object_key).":".$object_id."\"" );
if ( count($msg) == 0 || count($msg) > 1 )
return new PEAR_Error('Could not edit, there are none found or no many found');
// Save original to get the types not supported by us
$orig_vcard = $this->loadVCard(imap_body( $this->cbox, $msg[0] ));
// Get original header, we don't change header info on already existing contacts
$header = imap_fetchheader( $this->cbox, $msg[0], FT_INTERNAL );
$rev = date("Ymd\THis\Z"); // create the REV: type so that other clients can see this contact has changed
$vcard = $this->createVCard( $attributes, $rev, $orig_vcard['otherstuff'] );
$m = $header . $vcard;
$connstr = '{' . $this->server . ':143/imap}' . $this->folder;
// Delete message and re-create it
if (!imap_append( $this->cbox, $connstr, $m))
return new PEAR_Error( 'Could not save message! Because: '.imap_last_error());
else{
imap_delete( $this->cbox, $msg[0] );
imap_expunge($this->cbox );
return true;
}
}
/**
* Create an object key for a new object.
*
* @param array $attributes The attributes (in driver keys) of the
* object being added.
*
* @return string A unique ID for the new object.
*/
function makeKey($attributes)
{
return md5(uniqid(rand()));
}
/**
* Loads a vCard message into an array.
*
* @vcard string The vCard string message.
*
*/
function loadVCard( $vcard )
{
// Put whole message in nice array
$lines = explode( "\n", $vcard );
$data = array();
foreach( $lines as $line )
{
$k = substr($line, 0, strpos($line,':'));
$v = substr($line, strpos($line,':')+1);
$attributes = explode(';', $k);
$k = array_shift($attributes);
if ( strncmp($k,"X-",2) != 0 )
$k = strtolower($k);
foreach($attributes as $attr)
{
$k .= ';' . strtolower($attr);
}
$data[$k] = $v;
}
// Create the expected array that the driver needs
$vc = array();
$vc['uid'] = trim($data['uid'],"\r\n");
$vc['fn'] = $data['fn'];
$vc['nickname'] = $data['nickname'];
$vc['email'] = $data['email'];
$vc['org'] = $data['org'];
$address = explode(';',$data['adr;type=home']);
/* KMail don't seem to split the street address with ',' which
* is explained in the RFC2426, so I added extra replace for
* new lines.
*/
$vc['home_street'] = str_replace('\n',"\n",$address[2]);
$vc['home_street'] = str_replace(',',"\n",$vc['home_street']);
$vc['home_postalbox'] = $address[0];
$vc['home_locality'] = $address[3];
$vc['home_region'] = $address[4];
$vc['home_code'] = $address[5];
$vc['home_country'] = $address[6];
$address = explode(';',$data['adr;type=work']);
// KMail See above
$vc['work_street'] = str_replace('\n', "\n", $address[2]);
$vc['work_street'] = str_replace(',',"\n", $vc['work_street']);
$vc['work_postalbox'] = $address[0];
$vc['work_locality'] = $address[3];
$vc['work_region'] = $address[4];
$vc['work_code'] = $address[5];
$vc['work_country'] = $address[6];
$vc['work_phone'] = $data['tel;type=work'];
$vc['home_phone'] = $data['tel;type=home'];
$vc['cell_phone'] = $data['tel;type=cell'];
$vc['fax'] = $data['tel;type=fax'];
$vc['note'] = $data['note'];
// All the other types that we don't support
$vc['otherstuff'] = array();
foreach($data as $key => $value )
{
switch($key){
case "uid":
case "fn":
case "n":
case "nickname":
case "email":
case "org":
case "adr;type=home":
case "adr;type=work":
case "tel;type=work":
case "tel;type=home":
case "tel;type=cell":
case "tel;type=fax":
case "note":
case "name":
case "version":
case "begin":
case "rev":
case "class":
case "end":
case "":
break;
default:
$vc['otherstuff'][$key] = trim($value,"\r\n");
break;
}
}
return $vc;
}
/**
* Creates a vCard body message.
*
* @attributes array The attributes to be converted to msgbody.
*
* @rev string The REV tag date
*
* @otherstuff array An Array of types that was not created with
* this Kolab/Turba client.
*/
function createVCard( $attributes, $rev = "", $otherstuff = array() )
{
$nl = "\r\n";
if ( $attributes['fn'] == "" )
return new PEAR_Error("Must specify a Name");
$vcard = 'BEGIN:VCARD'.$nl
.'VERSION: 3.0'.$nl
.'NAME:'.$attributes['fn'].$nl
.'UID:'.trim($attributes['uid'],$nl).$nl
.'FN:'.$attributes['fn'].$nl;
if ( $attributes['email'] != "" )
$vcard .= 'EMAIL:'.$attributes['email'].$nl;
if(!strrchr($attributes['fn']," ")){
$surname = "";
$name = $attributes['fn'];
}
else {
$surname = substr( strrchr($attributes['fn']," "),1);
$name = substr( $attributes['fn'], 0, strpos($attributes['fn']," "));
}
$vcard .= 'N:'.$surname.';'.$name.';;;'.$nl;
$vcard .= $attributes['nickname'] != "" ? 'NICKNAME:'.$attributes['nickname'].$nl : null;
$vcard .= $attributes['org'] != "" ? 'ORG:'.$attributes['org'].$nl : "";
$vcard .= $attributes['note'] != "" ? 'NOTE:'.$attributes['note'].$nl : "";
$homeaddy = $attributes['home_postalbox'].';;'.str_replace("\r\n",',',$attributes['home_street'])
.';'.$attributes['home_locality'].';'.$attributes['home_region'].';'.$attributes['home_code']
.';'.$attributes['home_country'];
$vcard .= trim($homeaddy,';') != "" ? 'ADR;TYPE=home:'.$homeaddy.$nl : "";
$workaddy = $attributes['work_postalbox'].';;'.str_replace("\r\n",',',$attributes['work_street'])
.';'.$attributes['work_locality'].';'.$attributes['work_region'].';'.$attributes['work_code']
.';'.$attributes['work_country'];
$vcard .= trim($workaddy,';') != "" ? 'ADR;TYPE=work:'.$workaddy.$nl : "";
$vcard .= $attributes['work_phone'] != "" ? 'TEL;TYPE=work:'.$attributes['work_phone'].$nl : "";
$vcard .= $attributes['home_phone'] != "" ? 'TEL;TYPE=home:'.$attributes['home_phone'].$nl : "";
$vcard .= $attributes['cell_phone'] != "" ? 'TEL;TYPE=cell:'.$attributes['cell_phone'].$nl : "";
$vcard .= $attributes['fax'] != "" ? 'TEL;TYPE=fax:'.$attributes['fax'].$nl : "";
$vcard .= $rev != "" ? 'REV:'.$rev.$nl : "";
// Add the types that we did not create
foreach( $otherstuff as $key => $value ){
if ( strncmp($key, "X-",2) != 0 )
$vcard .= strtoupper($key) . ":" . $value . $nl;
else
$vcard .= $key . ":" . $value . $nl;
}
$vcard .= 'CLASS:PRIVATE'.$nl.'END:VCARD'.$nl;
return $vcard;
}
}
--- NEW FILE: valarm.php ---
<?php
/**
* Class representing vAlarms
*
* $Horde: horde/lib/iCalendar/valarm.php,v 1.3 2003/07/03 09:16:39 mikec Exp $
*
* Copyright 2003 Mike Cochrane <mike at graftonhall.co.nz>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Mike Cochrane <mike at graftonhall.co.nz>
* @version $Revision: 1.1 $
* @since Horde 3.0
* @package horde.iCalendar
*/
class Horde_iCalendar_valarm extends Horde_iCalendar {
function getType()
{
return 'vAlarm';
}
function parsevCalendar($data)
{
parent::parsevCalendar($data, 'VALARM');
}
function exportvCalendar(&$container)
{
return parent::_exportvData('VALARM');
}
}
--- NEW FILE: vevent.php ---
<?php
/**
* Class representing vEvents
*
* $Horde: horde/lib/iCalendar/vevent.php,v 1.13 2003/07/03 09:16:39 mikec Exp $
*
* Copyright 2003 Mike Cochrane <mike at graftonhall.co.nz>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Mike Cochrane <mike at graftonhall.co.nz>
* @version $Revision: 1.1 $
* @since Horde 3.0
* @package horde.iCalendar
*/
class Horde_iCalendar_vevent extends Horde_iCalendar {
function getType()
{
return 'vEvent';
}
function parsevCalendar($data)
{
parent::parsevCalendar($data, 'VEVENT');
}
function exportvCalendar(&$container)
{
// Default values
$requiredAttributes = array();
$requiredAttributes['DTSTAMP'] = time();
$requiredAttributes['ORGANIZER'] = _('Unknown Organizer');
$requiredAttributes['UID'] = $this->_exportDateTime(time()) . '@' . $_SERVER["SERVER_NAME"];
switch ($container->getAttribute('METHOD')) {
case 'PUBLISH':
$requiredAttributes['DTSTART'] = time();
$requiredAttributes['SUMMARY'] = '';
break;
case 'REQUEST':
$requiredAttributes['ATTENDEE'] = '';
$requiredAttributes['DTSTART'] = time();
$requiredAttributes['SUMMARY'] = '';
break;
case 'REPLY':
$requiredAttributes['ATTENDEE'] = '';
break;
case 'ADD':
$requiredAttributes['DTSTART'] = time();
$requiredAttributes['SEQUENCE'] = 1;
$requiredAttributes['SUMMARY'] = '';
break;
case 'CANCEL':
$requiredAttributes['ATTENDEE'] = '';
$requiredAttributes['SEQUENCE'] = 1;
break;
case 'REFRESH':
$requiredAttributes['ATTENDEE'] = '';
break;
}
foreach ($requiredAttributes as $name => $default_value) {
if (is_a($this->getAttribute($name), 'PEAR_Error')) {
$this->setAttribute($name, $default_value);
}
}
return parent::_exportvData('VEVENT');
}
/**
* Update the status of an attendee of an event
*
* @param $email The email address of the attendee
* @param $status The participant status to set.
* @param $fullname The full name of the participant to set.
*/
function updateAttendee($email, $status, $fullname = '')
{
foreach ($this->_attributes as $key => $attribute) {
if ($attribute['name'] == 'ATTENDEE' && $attribute['value'] == 'MAILTO:' . $email) {
$this->_attributes[$key]['params']['PARTSTAT'] = $status;
if (!empty($fullname)) {
$this->_attributes[$key]['params']['CN'] = $fullname;
}
unset($this->_attributes[$key]['params']['RSVP']);
return;
}
}
$params = array('PARTSTAT' => $status);
if (!empty($fullname)) {
$params['CN'] = $fullname;
}
$this->setAttribute('ATTENDEE', 'MAILTO:' . $email, $params);
}
/**
* Convert this event to a Kronolith Hash
*
* @return Array Array containing the details of the event as used
* by Kronolith
*/
function toKronolithHash()
{
$hash = array();
$title = $this->getAttribute('SUMMARY');
if (!is_array($title) && !is_a($title, 'PEAR_Error')) {
$hash['title'] = $title;
}
$desc = $this->getAttribute('DESCRIPTION');
if (!is_array($desc) && !is_a($desc, 'PEAR_Error')) {
$hash['description'] = $desc;
}
$location = $this->getAttribute('LOCATION');
if (!is_array($location) && !is_a($location, 'PEAR_Error')) {
$hash['location'] = $location;
}
$start = $this->getAttribute('DTSTART');
if (!is_array($start) && !is_a($start, 'PEAR_Error')) {
$hash['start_date'] = date('Y', $start) . '-' . date('m', $start) . '-' . date('j', $start);
$hash['start_time'] = date('H', $start) . ':' . date('i', $start) . ':' . date('s', $start);
}
$end = $this->getAttribute('DTEND');
if (!is_array($end) && !is_a($end, 'PEAR_Error')) {
$hash['end_date'] = date('Y', $end) . '-' . date('m', $end) . '-' . date('j', $end);
$hash['end_time'] = date('H', $end) . ':' . date('i', $end) . ':' . date('s', $end);
}
return $hash;
}
/**
* Return the organizer display name or email.
*
* @return String The organizer name to display for this event.
*/
function organizerName()
{
$organizer = $this->getAttribute('ORGANIZER', true);
if (array_key_exists('CN', $organizer[0])) {
return $organizer[0]['CN'];
}
$organizer = parse_url($this->getAttribute('ORGANIZER'));
return $organizer['path'];
}
/**
* Update this event with details from another event.
*
* @param Horde_iCalendar_vEvent $vevent The vEvent with latest details
*/
function updateFromvEvent($vevent)
{
$newAttributes = $vevent->getAllAttributes();
foreach ($newAttributes as $newAttribute) {
$currentValue = $this->getAttribute($newAttribute['name']);
if (is_a($currentValue, 'PEAR_error')) {
// already exists so just add it
$this->setAttribute($newAttribute['name'], $newAttribute['value'], $newAttribute['params']);
} else {
// already exists so locate and modify
$found = false;
// Try matching the attribte name and value incase only the
// params changed (eg attendee updating status).
foreach ($this->_attributes as $id => $attr) {
if ($attr['name'] == $newAttribute['name'] &&
$attr['value'] == $newAttribute['value']) {
// merge the params
foreach ($newAttribute['params'] as $param_id => $param_name) {
$this->_attributes[$id]['params'][$param_id] = $param_name;
}
$found = true;
break;
}
}
if (!$found) {
// Else match the first attribute with the same name (eg changing
// start time)
foreach ($this->_attributes as $id => $attr) {
if ($attr['name'] == $newAttribute['name']) {
$this->_attributes[$id]['value'] = $newAttribute['value'];
// merge the params
foreach ($newAttribute['params'] as $param_id => $param_name) {
$this->_attributes[$id]['params'][$param_id] = $param_name;
}
break;
}
}
}
}
}
}
/**
* Update just the attendess of event with details from another event.
*
* @param Horde_iCalendar_vEvent $vevent The vEvent with latest details
*/
function updateAttendeesFromvEvent($vevent)
{
$newAttributes = $vevent->getAllAttributes();
foreach ($newAttributes as $newAttribute) {
if (!$newAttribute['name'] == 'ATTENDEE') {
continue;
}
$currentValue = $this->getAttribute($newAttribute['name']);
if (is_a($currentValue, 'PEAR_error')) {
// already exists so just add it
$this->setAttribute($newAttribute['name'], $newAttribute['value'], $newAttribute['params']);
} else {
// already exists so locate and modify
$found = false;
// Try matching the attribte name and value incase only the
// params changed (eg attendee updating status).
foreach ($this->_attributes as $id => $attr) {
if ($attr['name'] == $newAttribute['name'] &&
$attr['value'] == $newAttribute['value']) {
// merge the params
foreach ($newAttribute['params'] as $param_id => $param_name) {
$this->_attributes[$id]['params'][$param_id] = $param_name;
}
$found = true;
break;
}
}
if (!$found) {
// Else match the first attribute with the same name (eg changing
// start time)
foreach ($this->_attributes as $id => $attr) {
if ($attr['name'] == $newAttribute['name']) {
$this->_attributes[$id]['value'] = $newAttribute['value'];
// merge the params
foreach ($newAttribute['params'] as $param_id => $param_name) {
$this->_attributes[$id]['params'][$param_id] = $param_name;
}
break;
}
}
}
}
}
}
}
--- NEW FILE: vfreebusy.php ---
<?php
/**
* Class representing vFreebusys
*
* $Horde: horde/lib/iCalendar/vfreebusy.php,v 1.9 2003/07/03 09:16:39 mikec Exp $
*
* Copyright 2003 Mike Cochrane <mike at graftonhall.co.nz>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Mike Cochrane <mike at graftonhall.co.nz>
* @version $Revision: 1.1 $
* @since Horde 3.0
* @package horde.iCalendar
*/
class Horde_iCalendar_vfreebusy extends Horde_iCalendar {
var $_busyPeriods = array();
function Horde_iCalendar_vfreebusy(&$container)
{
$this->_container = $container;
}
function getType()
{
return 'vFreebusy';
}
function parsevCalendar($data)
{
parent::parsevCalendar($data, 'VFREEBUSY');
// do something with all the busy periods
foreach ($this->_attributes as $key => $attribute) {
if ($attribute['name'] == 'FREEBUSY') {
foreach ($attribute['value'] as $value) {
if (array_key_exists('duration', $attribute['value'])) {
$this->addBusyPeriod('BUSY', $value['start'], null, $value['duration']);
} else {
$this->addBusyPeriod('BUSY', $value['start'], $value['end']);
}
}
unset($this->_attributes[$key]);
}
}
}
function exportvCalendar(&$container)
{
foreach ($this->_busyPeriods as $start => $end) {
$periods = array(array('start' => $start, 'end' => $end));
$this->setAttribute('FREEBUSY', $periods);
}
$res = parent::_exportvData('VFREEBUSY');
foreach ($this->_attributes as $key => $attribute) {
if ($attribute['name'] == 'FREEBUSY') {
unset($this->_attributes[$key]);
}
}
return $res;
}
/**
* Get a display name for this object
*/
function getName()
{
$name = '';
$method = $this->_container->getAttribute('METHOD');
if (is_a($method, 'PEAR_Error') || $method == 'PUBLISH') {
$attr = 'ORGANIZER';
} else if ($method == 'REPLY') {
$attr = 'ATTENDEE';
}
$name = $this->getAttribute($attr, true);
if (array_key_exists('CN', $name[0])) {
return $name[0]['CN'];
}
$name = $this->getAttribute($attr);
if (is_a($name, 'PEAR_Error')) {
return '';
} else {
$name = parse_url($name);
return $name['path'];
}
}
/**
* Get the email address for this object
*/
function getEmail()
{
$name = '';
$method = $this->_container->getAttribute('METHOD');
if (is_a($method, 'PEAR_Error') || $method == 'PUBLISH') {
$attr = 'ORGANIZER';
} else if ($method == 'REPLY') {
$attr = 'ATTENDEE';
}
$name = $this->getAttribute($attr);
if (is_a($name, 'PEAR_Error')) {
return '';
} else {
$name = parse_url($name);
return $name['path'];
}
}
function getBusyPeriods()
{
return $this->_busyPeriods;
}
/**
* Return all the free periods of time in a given period
*/
function getFreePeriods($startStamp, $endStamp)
{
$this->simplify();
$periods = array();
// Check that we have data for some part of this period
if ($this->getEnd() < $startStamp || $this->getStart() > $endStamp) {
return $periods;
}
// Locate the first time in the requested period we have
// data for.
$nextstart = max($startStamp, $this->getStart());
// Check each busy period and add free periods in between
foreach ($this->_busyPeriods as $start => $end) {
if ($start <= $endStamp && $end >= $nextstart) {
$periods[$nextstart] = min($start, $endStamp);
$nextstart = min($end, $endStamp);
}
}
// If we didn't read the end of the requested period but
// still have data then mark as free to the end of the period
// or available data.
if ($nextstart < $endStamp && $nextstart < $this->getEnd()) {
$periods[$nextstart] = min($this->getEnd(), $endStamp);
}
return $periods;
}
/**
* Add a busy period to the info.
*/
function addBusyPeriod($type, $start, $end = null, $duration = null)
{
if ($type == "FREE") {
// Make sure this period is not marked as busy.
return false;
}
// Calculate the end time is duration was specified
$tempEnd = is_null($duration) ? $end : $start + $duration;
// Make sure the period length is always positive.
$end = max($start, $tempEnd);
$start = min($start, $tempEnd);
if (isset($this->_busyPeriods[$start])) {
// Allready a period starting at this time. Extend to
// the length of the longest of the two
$this->_busyPeriods[$start] = max($end, $this->_busyPeriods[$start]);
} else {
// Add a new busy period
$this->_busyPeriods[$start] = $end;
}
return true;
}
/**
* Get the timestamp of the start of the time period this
* free busy information covers.
*/
function getStart()
{
if (!is_a($this->getAttribute('DTSTART'), 'PEAR_Error')) {
return $this->getAttribute('DTSTART');
} else if (count($this->_busyPeriods)) {
return min(array_keys($this->_busyPeriods));
} else {
return false;
}
}
/**
* Get the timestamp of the end of the time period this
* free busy information covers.
*/
function getEnd()
{
if (!is_a($this->getAttribute('DTEND'), 'PEAR_Error')) {
return $this->getAttribute('DTEND');
} else if (count($this->_busyPeriods)) {
return max(array_values($this->_busyPeriods));
} else {
return false;
}
}
/**
* Merge the busy periods of another VFreebusy into this one.
*/
function merge($freebusy, $simplify = true)
{
if (!is_a($freebusy, 'Horde_iCalendar_vfreebusy')) {
return false;
}
foreach ($freebusy->getBusyPeriods() as $start => $end) {
$this->addBusyPeriod('BUSY', $start, $end);
}
if ($simplify) {
$this->simplify();
}
return true;
}
/**
* Remove all overlaps and simplify the busy periods array
* as much as possible.
*/
function simplify()
{
$checked = array();
$checkedEmpty = true;
foreach ($this->_busyPeriods as $start => $end) {
if ($checkedEmpty) {
$checked[$start] = $end;
$checkedEmpty = false;
} else {
$added = false;
foreach ($checked as $testStart => $testEnd) {
if ($start == $testStart) {
$checked[$testStart] = max($testEnd, $end);
$added = true;
} else if ($end <= $testEnd && $end >= $testStart) {
unset($checked[$testStart]);
$checked[min($testStart, $start)] = max($testEnd, $end);
$added = true;
}
if ($added) {
break;
}
}
if (!$added) {
$checked[$start] = $end;
}
}
}
ksort($checked, SORT_NUMERIC);
$this->_busyPeriods = $checked;
}
}
--- NEW FILE: vjournal.php ---
<?php
/**
* Class representing vJounrals
*
* $Horde: horde/lib/iCalendar/vjournal.php,v 1.3 2003/07/03 09:16:40 mikec Exp $
*
* Copyright 2003 Mike Cochrane <mike at graftonhall.co.nz>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Mike Cochrane <mike at graftonhall.co.nz>
* @version $Revision: 1.1 $
* @since Horde 3.0
* @package horde.iCalendar
*/
class Horde_iCalendar_vjournal extends Horde_iCalendar {
function getType()
{
return 'vJournal';
}
function parsevCalendar($data)
{
parent::parsevCalendar($data, 'VJOURNAL');
}
function exportvCalendar(&$container)
{
return parent::_exportvData('VJOURNAL');
}
}
--- NEW FILE: vtimezone.php ---
<?php
/**
* Class representing vTimezones
*
* $Horde: horde/lib/iCalendar/vtimezone.php,v 1.3 2003/07/03 09:16:40 mikec Exp $
*
* Copyright 2003 Mike Cochrane <mike at graftonhall.co.nz>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Mike Cochrane <mike at graftonhall.co.nz>
* @version $Revision: 1.1 $
* @since Horde 3.0
* @package horde.iCalendar
*/
class Horde_iCalendar_vtimezone extends Horde_iCalendar {
function getType()
{
return 'vTimeZone';
}
function parsevCalendar($data)
{
parent::parsevCalendar($data, 'VTIMEZONE');
}
function exportvCalendar(&$container)
{
return parent::_exportvData('VTIMEZONE');
}
}
class Horde_iCalendar_standard extends Horde_iCalendar {
function getType()
{
return 'standard';
}
function parsevCalendar($data)
{
parent::parsevCalendar($data, 'STANDARD');
}
function exportvCalendar(&$container)
{
return parent::_exportvData('STANDARD');
}
}
class Horde_iCalendar_daylight extends Horde_iCalendar {
function getType()
{
return 'daylight';
}
function parsevCalendar($data)
{
parent::parsevCalendar($data, 'DAYLIGHT');
}
function exportvCalendar(&$container)
{
return parent::_exportvData('DAYLIGHT');
}
}
--- NEW FILE: vtodo.php ---
<?php
/**
* Class representing vTodos
*
* $Horde: horde/lib/iCalendar/vtodo.php,v 1.3 2003/07/03 09:16:40 mikec Exp $
*
* Copyright 2003 Mike Cochrane <mike at graftonhall.co.nz>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Mike Cochrane <mike at graftonhall.co.nz>
* @version $Revision: 1.1 $
* @since Horde 3.0
* @package horde.iCalendar
*/
class Horde_iCalendar_vtodo extends Horde_iCalendar {
function getType()
{
return 'vTodo';
}
function parsevCalendar($data)
{
parent::parsevCalendar($data, 'VTODO');
}
function exportvCalendar(&$container)
{
return parent::_exportvData('VTODO');
}
}
- Previous message: stephan: server/horde Makefile, 1.4, 1.5 horde.spec, 1.6, 1.7 horde_registry.php, 1.3, 1.4 imp_servers.php, 1.3, 1.4 kronolith_conf.php, 1.1, 1.2 nag_conf.php, 1.1, 1.2
- Next message: stephan: server/horde Makefile,1.5,1.6
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the commits
mailing list