Commit 4c5f014c authored by Manfred Kutas's avatar Manfred Kutas

ZP-1295 Merge MAPI classes from webapp.

Released under the Affero GNU General Public License (AGPL) version 3.
parent c9c700d9
...@@ -335,7 +335,7 @@ class BackendKopano implements IBackend, ISearchProvider { ...@@ -335,7 +335,7 @@ class BackendKopano implements IBackend, ISearchProvider {
$calendar = mapi_msgstore_openentry($store, $entryid); $calendar = mapi_msgstore_openentry($store, $entryid);
$pub = new FreeBusyPublish($this->session, $store, $calendar, $storeprops[PR_USER_ENTRYID]); $pub = new FreeBusyPublish($this->session, $store, $calendar, $storeprops[PR_USER_ENTRYID]);
$pub->publishFB(time() - (7 * 24 * 60 * 60), 6 * 30 * 24 * 60 * 60); // publish from one week ago, 6 months ahead $pub->publishFB(time() - (7 * 24 * 60 * 60), time() + (6 * 30 * 24 * 60 * 60)); // publish from one week ago, 6 months ahead
} }
} }
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
/** /**
* Defines a base exception class for all custom exceptions, so every exceptions that * Defines a base exception class for all custom exceptions, so every exceptions that
* is thrown/caught by this application should extend this base class and make use of it. * is thrown/caught by this application should extend this base class and make use of it.
* it removes some peculiarities between different versions of PHP and exception handling.
* *
* Some basic function of Exception class * Some basic function of Exception class
* getMessage()- message of exception * getMessage()- message of exception
...@@ -32,12 +31,6 @@ ...@@ -32,12 +31,6 @@
*/ */
class BaseException extends Exception class BaseException extends Exception
{ {
/**
* Reference of previous exception, only used for PHP < 5.3
* can't use $previous here as its a private variable of parent class
*/
private $_previous = null;
/** /**
* Base name of the file, so we don't have to use static path of the file * Base name of the file, so we don't have to use static path of the file
*/ */
...@@ -62,36 +55,12 @@ class BaseException extends Exception ...@@ -62,36 +55,12 @@ class BaseException extends Exception
* @param string $displayMessage * @param string $displayMessage
* @return void * @return void
*/ */
public function __construct($errorMessage, $code = 0, Exception $previous = null, $displayMessage = null) { public function __construct($errorMessage, $code = 0, Exception $previous = null, $displayMessage = null)
{
// assign display message // assign display message
$this->displayMessage = $displayMessage; $this->displayMessage = $displayMessage;
if (version_compare(PHP_VERSION, '5.3.0', '<')) { parent::__construct($errorMessage, (int) $code, $previous);
parent::__construct($errorMessage, (int) $code);
// set previous exception
if(!is_null($previous)) {
$this->_previous = $previous;
}
} else {
parent::__construct($errorMessage, (int) $code, $previous);
}
}
/**
* Overloading of final methods to get rid of incompatibilities between different PHP versions.
*
* @param string $method
* @param array $args
* @return mixed
*/
public function __call($method, array $args)
{
if ('getprevious' == strtolower($method)) {
return $this->_getPrevious();
}
return null;
} }
/** /**
...@@ -146,39 +115,6 @@ class BaseException extends Exception ...@@ -146,39 +115,6 @@ class BaseException extends Exception
return $this->baseFile; return $this->baseFile;
} }
/**
* Function will check for PHP version if it is greater than 5.3 then we can use its default implementation
* otherwise we have to use our own implementation of chanining functionality.
*
* @return Exception returns previous exception
*/
public function _getPrevious()
{
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
return $this->_previous;
} else {
return parent::getPrevious();
}
}
/**
* String representation of the exception, also handles previous exception.
*
* @return string
*/
public function __toString()
{
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
if (($e = $this->getPrevious()) !== null) {
return $e->__toString()
. "\n\nNext "
. parent::__toString();
}
}
return parent::__toString();
}
/** /**
* Name of the class of exception. * Name of the class of exception.
* *
......
...@@ -740,14 +740,24 @@ ...@@ -740,14 +740,24 @@
// Go the the correct month day // Go the the correct month day
$this->recur["start"] += (((int) $this->recur["monthday"])-1) * 24*60*60; $this->recur["start"] += (((int) $this->recur["monthday"])-1) * 24*60*60;
// If the previous calculation gave us a start date *before* the original start date, then we need to skip to the next occurrence // If the previous calculation gave us a start date different than the original start date, then we need to skip to the first occurrence
if ( ($term == 0x0C /*monthly*/ && ((int) $this->recur["monthday"]) < $curmonthday) || if ( ($term == 0x0C /*monthly*/ && ((int) $this->recur["monthday"]) < $curmonthday) ||
($term == 0x0D /*yearly*/ &&( $selmonth < $curmonth || ($selmonth == $curmonth && ((int) $this->recur["monthday"]) < $curmonthday)) )) ($term == 0x0D /*yearly*/ && ( $selmonth != $curmonth || ($selmonth == $curmonth && ((int) $this->recur["monthday"]) < $curmonthday)) ))
{ {
if($term == 0x0D /*yearly*/) if ($term == 0x0D /*yearly*/) {
$count = ($everyn - ($curmonth - $selmonth)); // Yearly, go to next occurrence in 'everyn' months minus difference in first occurence and original date if ($curmonth > $selmonth) {//go to next occurrence in 'everyn' months minus difference in first occurrence and original date
else $count = $everyn - ($curmonth - $selmonth);
} else if ($curmonth < $selmonth) {//go to next occurrence upto difference in first occurrence and original date
$count = $selmonth - $curmonth;
} else {
// Go to next occurrence while recurrence start date is greater than occurrence date but within same month
if (((int) $this->recur["monthday"]) < $curmonthday) {
$count = $everyn;
}
}
} else {
$count = $everyn; // Monthly, go to next occurrence in 'everyn' months $count = $everyn; // Monthly, go to next occurrence in 'everyn' months
}
// Forward by $count months. This is done by getting the number of days in that month and forwarding that many days // Forward by $count months. This is done by getting the number of days in that month and forwarding that many days
for($i=0; $i < $count; $i++) { for($i=0; $i < $count; $i++) {
...@@ -1173,7 +1183,7 @@ ...@@ -1173,7 +1183,7 @@
mapi_setprops($this->message, Array($this->proptags["commonend"] => $utcfirstoccenddatetime )); mapi_setprops($this->message, Array($this->proptags["commonend"] => $utcfirstoccenddatetime ));
// Set Outlook properties, if it is an appointment // Set Outlook properties, if it is an appointment
if (isset($this->recur["message_class"]) && $this->recur["message_class"] == "IPM.Appointment") { if (isset($this->messageprops[$this->proptags["message_class"]]) && $this->messageprops[$this->proptags["message_class"]] == "IPM.Appointment") {
// update real begin and real end date // update real begin and real end date
mapi_setprops($this->message, Array($this->proptags["startdate_recurring"] => $utcstart)); mapi_setprops($this->message, Array($this->proptags["startdate_recurring"] => $utcstart));
mapi_setprops($this->message, Array($this->proptags["enddate_recurring"] => $utcend)); mapi_setprops($this->message, Array($this->proptags["enddate_recurring"] => $utcend));
...@@ -1657,8 +1667,8 @@ ...@@ -1657,8 +1667,8 @@
// From here on, the dates of the occurrences are calculated in local time, so the days we're looking // From here on, the dates of the occurrences are calculated in local time, so the days we're looking
// at are calculated from the local time dates of $start and $end // at are calculated from the local time dates of $start and $end
// TODO use one isset
if ($this->recur['regen'] && isset($this->action['datecompleted'])) { if (isset($this->recur['regen']) && $this->recur['regen'] && isset($this->action['datecompleted'])) {
$daystart = $this->dayStartOf($this->action['datecompleted']); $daystart = $this->dayStartOf($this->action['datecompleted']);
} else { } else {
$daystart = $this->dayStartOf($this->recur["start"]); // start on first day of occurrence $daystart = $this->dayStartOf($this->recur["start"]); // start on first day of occurrence
......
...@@ -79,13 +79,16 @@ class FreeBusyPublish { ...@@ -79,13 +79,16 @@ class FreeBusyPublish {
} }
/** /**
* Publishes the infomation * Function is used to get the calender data based on give date range.
* @paam timestamp $starttime Time from which to publish data (usually now) *
* @paam integer $length Amount of seconds from $starttime we should publish * @param timestamp $starttime Time from which to get the calender data.
* @param timestamp $length Time up till now get the calender data.
* @return Array return the calender data array.
*/ */
function publishFB($starttime, $length) { function getCalendarData($starttime, $length)
{
$start = $starttime; $start = $starttime;
$end = $starttime + $length; $end = $length;
// Get all the items in the calendar that we need // Get all the items in the calendar that we need
...@@ -220,7 +223,7 @@ class FreeBusyPublish { ...@@ -220,7 +223,7 @@ class FreeBusyPublish {
if(isset($row[$this->proptags['recurring']]) && $row[$this->proptags['recurring']]) { if(isset($row[$this->proptags['recurring']]) && $row[$this->proptags['recurring']]) {
$recur = new Recurrence($this->store, $row); $recur = new Recurrence($this->store, $row);
$occurrences = $recur->getItems($starttime, $starttime + $length); $occurrences = $recur->getItems($starttime, $length);
} else { } else {
$occurrences[] = $row; $occurrences[] = $row;
} }
...@@ -232,10 +235,19 @@ class FreeBusyPublish { ...@@ -232,10 +235,19 @@ class FreeBusyPublish {
// $calendaritems now contains all the calendar items in the specified time // $calendaritems now contains all the calendar items in the specified time
// frame. We now need to merge these into a flat array of begin/end/status // frame. We now need to merge these into a flat array of begin/end/status
// objects. This also filters out all the 'free' items (status 0) // objects. This also filters out all the 'free' items (status 0)
$freebusy = $this->mergeItemsFB($calendaritems); $freebusy = $this->mergeItemsFB($calendaritems);
// $freebusy now contains the start, end and status of all items, merged. return $freebusy;
}
/**
* Publishes Free/Busy infomation of user.
* @param timestamp $starttime Time from which to publish data (usually now)
* @param timestamp $length Time of seconds from $starttime we should publish
*/
function publishFB($start, $end)
{
$freebusy = $this->getCalendarData($start, $end);
// Get the FB interface // Get the FB interface
try { try {
...@@ -243,9 +255,7 @@ class FreeBusyPublish { ...@@ -243,9 +255,7 @@ class FreeBusyPublish {
} catch (MAPIException $e) { } catch (MAPIException $e) {
if($e->getCode() == MAPI_E_NOT_FOUND) { if($e->getCode() == MAPI_E_NOT_FOUND) {
$e->setHandled(); $e->setHandled();
if(function_exists("dump")) { ZLog::Write(LOGLEVEL_WARN, "Error in opening freebusysupport object.");
dump("Error in opening freebusysupport object.");
}
} }
} }
...@@ -300,13 +310,13 @@ class FreeBusyPublish { ...@@ -300,13 +310,13 @@ class FreeBusyPublish {
$ts["type"] = 0; $ts["type"] = 0;
$ts["time"] = $item[$this->proptags["startdate"]]; $ts["time"] = $item[$this->proptags["startdate"]];
$ts["subject"] = $item[PR_SUBJECT]; $ts["subject"] = $item[PR_SUBJECT];
$ts["status"] = (isset($item[$this->proptags["busystatus"]])) ? $item[$this->proptags["busystatus"]] : 0; //ZP-197 $ts["status"] = (isset($item[$this->proptags["busystatus"]])) ? $item[$this->proptags["busystatus"]] : fbFree; //ZP-197
$timestamps[] = $ts; $timestamps[] = $ts;
$ts["type"] = 1; $ts["type"] = 1;
$ts["time"] = $item[$this->proptags["duedate"]]; $ts["time"] = $item[$this->proptags["duedate"]];
$ts["subject"] = $item[PR_SUBJECT]; $ts["subject"] = $item[PR_SUBJECT];
$ts["status"] = (isset($item[$this->proptags["busystatus"]])) ? $item[$this->proptags["busystatus"]] : 0; //ZP-197 $ts["status"] = (isset($item[$this->proptags["busystatus"]])) ? $item[$this->proptags["busystatus"]] : fbFree; //ZP-197
$timestamps[] = $ts; $timestamps[] = $ts;
} }
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -19,8 +19,6 @@ ...@@ -19,8 +19,6 @@
/** /**
* Recurrence * Recurrence
* @author Steve Hardy <steve@zarafa.com>
* @author Michel de Ron <michel@zarafa.com>
*/ */
class Recurrence extends BaseRecurrence class Recurrence extends BaseRecurrence
{ {
...@@ -226,7 +224,6 @@ ...@@ -226,7 +224,6 @@
} }
$baseday = $this->dayStartOf($base_date); $baseday = $this->dayStartOf($base_date);
$basetime = $baseday + $this->recur["startocc"] * 60;
$extomodify = false; $extomodify = false;
for($i = 0, $len = count($this->recur["changed_occurences"]); $i < $len; $i++) { for($i = 0, $len = count($this->recur["changed_occurences"]); $i < $len; $i++) {
...@@ -373,8 +370,6 @@ ...@@ -373,8 +370,6 @@
*/ */
function isValidReminderTime($basedate, $reminderminutes, $startdate) function isValidReminderTime($basedate, $reminderminutes, $startdate)
{ {
$isreminderrangeset = false;
// get all occurence items before the seleceted items occurence starttime // get all occurence items before the seleceted items occurence starttime
$occitems = $this->getItems($this->messageprops[$this->proptags["startdate"]], $this->toGMT($this->tz, $basedate)); $occitems = $this->getItems($this->messageprops[$this->proptags["startdate"]], $this->toGMT($this->tz, $basedate));
...@@ -789,13 +784,14 @@ ...@@ -789,13 +784,14 @@
*/ */
function getExceptionAttachment($base_date) function getExceptionAttachment($base_date)
{ {
// Retrieve only embedded messages // Retrieve only exceptions which are stored as embedded messages
$attach_res = Array(RES_AND, $attach_res = Array(RES_AND,
Array( Array(
Array(RES_PROPERTY, Array(RES_PROPERTY,
Array(RELOP => RELOP_EQ, Array(
RELOP => RELOP_EQ,
ULPROPTAG => PR_ATTACH_METHOD, ULPROPTAG => PR_ATTACH_METHOD,
VALUE => array(PR_ATTACH_METHOD => 5) VALUE => array(PR_ATTACH_METHOD => ATTACH_EMBEDDED_MSG)
) )
) )
) )
...@@ -811,7 +807,13 @@ ...@@ -811,7 +807,13 @@
$data = mapi_message_getprops($exception, array($this->proptags["basedate"])); $data = mapi_message_getprops($exception, array($this->proptags["basedate"]));
if(isset($data[$this->proptags["basedate"]]) && $this->isSameDay($this->fromGMT($this->tz,$data[$this->proptags["basedate"]]), $base_date)) { if(!isset($data[$this->proptags["basedate"]])) {
// if no basedate found then it could be embedded message so ignore it
// we need proper restriction to exclude embedded messages aswell
continue;
}
if($this->isSameDay($this->fromGMT($this->tz, $data[$this->proptags["basedate"]]), $base_date)) {
return $tempattach; return $tempattach;
} }
} }
...@@ -1061,7 +1063,7 @@ ...@@ -1061,7 +1063,7 @@
} }
// Add organizer to meeting only if it is not organized. // Add organizer to meeting only if it is not organized.
$msgprops = mapi_getprops($exception, array(PR_SENT_REPRESENTING_ENTRYID, PR_SENT_REPRESENTING_EMAIL_ADDRESS, PR_SENT_REPRESENTING_NAME, PR_SENT_REPRESENTING_ADDRTYPE, $this->proptags['responsestatus'])); $msgprops = mapi_getprops($exception, array(PR_SENT_REPRESENTING_ENTRYID, PR_SENT_REPRESENTING_EMAIL_ADDRESS, PR_SENT_REPRESENTING_NAME, PR_SENT_REPRESENTING_ADDRTYPE, PR_SENT_REPRESENTING_SEARCH_KEY, $this->proptags['responsestatus']));
if (isset($msgprops[$this->proptags['responsestatus']]) && $msgprops[$this->proptags['responsestatus']] != olResponseOrganized){ if (isset($msgprops[$this->proptags['responsestatus']]) && $msgprops[$this->proptags['responsestatus']] != olResponseOrganized){
$this->addOrganizer($msgprops, $exception_recips['add']); $this->addOrganizer($msgprops, $exception_recips['add']);
} }
...@@ -1116,7 +1118,7 @@ ...@@ -1116,7 +1118,7 @@
} }
// Add organizer to meeting only if it is not organized. // Add organizer to meeting only if it is not organized.
$msgprops = mapi_getprops($message, array(PR_SENT_REPRESENTING_ENTRYID, PR_SENT_REPRESENTING_EMAIL_ADDRESS, PR_SENT_REPRESENTING_NAME, PR_SENT_REPRESENTING_ADDRTYPE, $this->proptags['responsestatus'])); $msgprops = mapi_getprops($message, array(PR_SENT_REPRESENTING_ENTRYID, PR_SENT_REPRESENTING_EMAIL_ADDRESS, PR_SENT_REPRESENTING_NAME, PR_SENT_REPRESENTING_ADDRTYPE, PR_SENT_REPRESENTING_SEARCH_KEY, $this->proptags['responsestatus']));
if (isset($msgprops[$this->proptags['responsestatus']]) && $msgprops[$this->proptags['responsestatus']] != olResponseOrganized){ if (isset($msgprops[$this->proptags['responsestatus']]) && $msgprops[$this->proptags['responsestatus']] != olResponseOrganized){
$this->addOrganizer($msgprops, $exception_recips); $this->addOrganizer($msgprops, $exception_recips);
} }
...@@ -1125,7 +1127,7 @@ ...@@ -1125,7 +1127,7 @@
foreach($recipientRows as $key => $recipient) { foreach($recipientRows as $key => $recipient) {
$found = false; $found = false;
foreach($exception_recips as $excep_recip) { foreach($exception_recips as $excep_recip) {
if (isset($recipient[PR_SEARCH_KEY]) && isset($excep_recip[PR_SEARCH_KEY]) && $recipient[PR_SEARCH_KEY] == $excep_recip[PR_SEARCH_KEY]) if (isset($recipient[PR_SEARCH_KEY], $excep_recip[PR_SEARCH_KEY]) && $recipient[PR_SEARCH_KEY] == $excep_recip[PR_SEARCH_KEY])
$found = true; $found = true;
} }
...@@ -1201,8 +1203,8 @@ ...@@ -1201,8 +1203,8 @@
* @param array $recipients recipients list of message. * @param array $recipients recipients list of message.
* @param boolean $isException true if we are processing recipient of exception * @param boolean $isException true if we are processing recipient of exception
*/ */
function addOrganizer($messageProps, &$recipients, $isException = false){ function addOrganizer($messageProps, &$recipients, $isException = false)
{
$hasOrganizer = false; $hasOrganizer = false;
// Check if meeting already has an organizer. // Check if meeting already has an organizer.
foreach ($recipients as $key => $recipient){ foreach ($recipients as $key => $recipient){
...@@ -1225,6 +1227,7 @@ ...@@ -1225,6 +1227,7 @@
$organizer[PR_ADDRTYPE] = empty($messageProps[PR_SENT_REPRESENTING_ADDRTYPE])?'SMTP':$messageProps[PR_SENT_REPRESENTING_ADDRTYPE]; $organizer[PR_ADDRTYPE] = empty($messageProps[PR_SENT_REPRESENTING_ADDRTYPE])?'SMTP':$messageProps[PR_SENT_REPRESENTING_ADDRTYPE];
$organizer[PR_RECIPIENT_TRACKSTATUS] = olRecipientTrackStatusNone; $organizer[PR_RECIPIENT_TRACKSTATUS] = olRecipientTrackStatusNone;
$organizer[PR_RECIPIENT_FLAGS] = recipSendable | recipOrganizer; $organizer[PR_RECIPIENT_FLAGS] = recipSendable | recipOrganizer;
$organizer[PR_SEARCH_KEY] = $messageProps[PR_SENT_REPRESENTING_SEARCH_KEY];
// Add organizer to recipients list. // Add organizer to recipients list.
array_unshift($recipients, $organizer); array_unshift($recipients, $organizer);
......
...@@ -299,12 +299,12 @@ ...@@ -299,12 +299,12 @@
// Update body of original message // Update body of original message
$msgbody = mapi_message_openproperty($this->message, PR_BODY); $msgbody = mapi_message_openproperty($this->message, PR_BODY);
$msgbody = trim($this->windows1252_to_utf8($msgbody), "\0"); $msgbody = trim($msgbody, "\0");
$separator = "------------\r\n"; $separator = "------------\r\n";
if (!empty($msgbody) && strrpos($msgbody, $separator) === false) { if (!empty($msgbody) && strrpos($msgbody, $separator) === false) {
$msgbody = $separator . $msgbody; $msgbody = $separator . $msgbody;
$stream = mapi_openproperty($this->message, PR_BODY, IID_IStream, 0, MAPI_CREATE | MAPI_MODIFY); $stream = mapi_openproperty($this->message, PR_BODY, IID_IStream, 0, 0);
mapi_stream_setsize($stream, strlen($msgbody)); mapi_stream_setsize($stream, strlen($msgbody));
mapi_stream_write($stream, $msgbody); mapi_stream_write($stream, $msgbody);
mapi_stream_commit($stream); mapi_stream_commit($stream);
...@@ -409,21 +409,4 @@ ...@@ -409,21 +409,4 @@
return $result; return $result;
} }
/**
* Convert from windows-1252 encoded string to UTF-8 string
*
* The same conversion rules as utf8_to_windows1252 apply.
*
* @param string $string the Windows-1252 string to convert
* @return string UTF-8 representation of the string
*/
function windows1252_to_utf8($string)
{
if (function_exists("iconv")){
return iconv("Windows-1252", "UTF-8//TRANSLIT", $string);
}else{
return utf8_encode($string); // no euro support here
}
}
} }
...@@ -35,24 +35,7 @@ ...@@ -35,24 +35,7 @@
*/ */
function makeGuid($guid) function makeGuid($guid)
{ {
// remove the { and } from the string and explode it into an array return pack("vvvv", hexdec(substr($guid, 5, 4)), hexdec(substr($guid, 1, 4)), hexdec(substr($guid, 10, 4)), hexdec(substr($guid, 15, 4))) . hex2bin(substr($guid, 20, 4)) . hex2bin(substr($guid, 25, 12));
$guidArray = explode('-', substr($guid, 1,strlen($guid)-2));
// convert to hex!
$data1[0] = intval(substr($guidArray[0], 0, 4),16); // we need to split the unsigned long
$data1[1] = intval(substr($guidArray[0], 4, 4),16);
$data2 = intval($guidArray[1], 16);
$data3 = intval($guidArray[2], 16);
$data4[0] = intval(substr($guidArray[3], 0, 2),16);
$data4[1] = intval(substr($guidArray[3], 2, 2),16);
for($i=0; $i < 6; $i++)
{
$data4[] = intval(substr($guidArray[4], $i*2, 2),16);
}
return pack("vvvvCCCCCCCC", $data1[1], $data1[0], $data2, $data3, $data4[0],$data4[1],$data4[2],$data4[3],$data4[4],$data4[5],$data4[6],$data4[7]);
} }
/** /**
...@@ -68,11 +51,9 @@ function get_mapi_error_name($errcode=null) ...@@ -68,11 +51,9 @@ function get_mapi_error_name($errcode=null)
} }
if ($errcode !== 0) { if ($errcode !== 0) {
// get_defined_constants(true) is preferred, but crashes PHP // Retrieve constants categories, MAPI error names are defined
// https://bugs.php.net/bug.php?id=61156 // in the 'user' category, since the WebApp code defines it in mapicode.php.
$allConstants = get_defined_constants(); foreach (get_defined_constants(true)['user'] as $key => $value) {
foreach ($allConstants as $key => $value) {
/** /**
* If PHP encounters a number beyond the bounds of the integer type, * If PHP encounters a number beyond the bounds of the integer type,
* it will be interpreted as a float instead, so when comparing these error codes * it will be interpreted as a float instead, so when comparing these error codes
...@@ -271,7 +252,6 @@ function getCalendarItems($store, $calendar, $viewstart, $viewend, $propsrequest ...@@ -271,7 +252,6 @@ function getCalendarItems($store, $calendar, $viewstart, $viewend, $propsrequest
// Get requested properties, plus whatever we need // Get requested properties, plus whatever we need
$proplist = array(PR_ENTRYID, $properties["recurring"], $properties["recurring_data"], $properties["timezone_data"]); $proplist = array(PR_ENTRYID, $properties["recurring"], $properties["recurring_data"], $properties["timezone_data"]);
$proplist = array_merge($proplist, $propsrequested); $proplist = array_merge($proplist, $propsrequested);
$propslist = array_unique($proplist);
$rows = mapi_table_queryallrows($table, $proplist, $restriction); $rows = mapi_table_queryallrows($table, $proplist, $restriction);
......
...@@ -34,7 +34,7 @@ define('SEVERITY_ERROR', 1); ...@@ -34,7 +34,7 @@ define('SEVERITY_ERROR', 1);
/* from winerror.h */ /* from winerror.h */
/** /**
* Function to make a error * Function to make an error
*/ */
function make_mapi_e($code) function make_mapi_e($code)
{ {
...@@ -43,7 +43,7 @@ function make_mapi_e($code) ...@@ -43,7 +43,7 @@ function make_mapi_e($code)
/** /**
* Function to make an warning * Function to make a warning
*/ */
function make_mapi_s($code) function make_mapi_s($code)
{ {
...@@ -95,11 +95,16 @@ function make_mapi_s($code) ...@@ -95,11 +95,16 @@ function make_mapi_s($code)
*/ */
define('NOERROR' ,0); define('NOERROR' ,0);
define('MAPI_E_CALL_FAILED' ,(int) 0x80004005); // The following codes don't use make_mapi_e because they are in the 0x000FF000 range,
define('MAPI_E_NOT_ENOUGH_MEMORY' ,(int) 0x8007000E); // but we cannot use the HEX value as would make most sense as that would break in 64bit PHP
define('MAPI_E_INVALID_PARAMETER' ,(int) 0x80070057); // (Kopano Core server will return a negative value, but PHP would convert this define into a positive
define('MAPI_E_INTERFACE_NOT_SUPPORTED' ,(int) 0x80004002); // value). Hence we declare the value exactly as we need it as integer and bypass the
define('MAPI_E_NO_ACCESS' ,(int) 0x80070005); // 32bit/64bit hell.
define('MAPI_E_CALL_FAILED' ,(int)-2147467259); // 0x80004005
define('MAPI_E_NOT_ENOUGH_MEMORY' ,(int)-2147024882); // 0x8007000E
define('MAPI_E_INVALID_PARAMETER' ,(int)-2147024809); // 0x80070057
define('MAPI_E_INTERFACE_NOT_SUPPORTED' ,(int)-2147467262); // 0x80004002
define('MAPI_E_NO_ACCESS' ,(int)-2147024891); // 0x80070005
define('MAPI_E_NO_SUPPORT' ,make_mapi_e(0x102)); define('MAPI_E_NO_SUPPORT' ,make_mapi_e(0x102));
define('MAPI_E_BAD_CHARWIDTH' ,make_mapi_e(0x103)); define('MAPI_E_BAD_CHARWIDTH' ,make_mapi_e(0x103));
......
...@@ -97,6 +97,11 @@ define('TABLE_SORT_ASCEND' ,(0x00000000)); ...@@ -97,6 +97,11 @@ define('TABLE_SORT_ASCEND' ,(0x00000000));
define('TABLE_SORT_DESCEND' ,(0x00000001)); define('TABLE_SORT_DESCEND' ,(0x00000001));
define('TABLE_SORT_COMBINE' ,(0x00000002)); define('TABLE_SORT_COMBINE' ,(0x00000002));
/* Bookmarks in Table */
define('BOOKMARK_BEGINNING' , 0); /* Before first row */
define('BOOKMARK_CURRENT' , 1); /* Before current row */
define('BOOKMARK_END' , 2); /* After last row */
define('MAPI_UNICODE' ,0x80000000); define('MAPI_UNICODE' ,0x80000000);
/* IMAPIFolder Interface --------------------------------------------------- */ /* IMAPIFolder Interface --------------------------------------------------- */
...@@ -634,3 +639,22 @@ define('fnevTableModified' ,0x00000100); ...@@ -634,3 +639,22 @@ define('fnevTableModified' ,0x00000100);
define('fnevStatusObjectModified' ,0x00000200); define('fnevStatusObjectModified' ,0x00000200);
define('fnevReservedForMapi' ,0x40000000); define('fnevReservedForMapi' ,0x40000000);
define('fnevExtended' ,0x80000000); define('fnevExtended' ,0x80000000);
/* PersistBlockType values PR_IPM_OL2007_ENTRYIDS / PR_ADDITIONAL_REN_ENTRYIDS_EX PersistIDs*/
define('PERSIST_SENTINEL' ,0x0000); // Indicates that the PersistData structure is the last one contained in the PidTagAdditionalRenEntryIdsEx property
define('RSF_PID_RSS_SUBSCRIPTION' ,0x8001); // Indicates that the structure contains data for the RSS Feeds folder
define('RSF_PID_SEND_AND_TRACK' ,0x8002); // Indicates that the structure contains data for the Tracked Mail Processing folder
define('RSF_PID_TODO_SEARCH' ,0x8004); // Indicates that the structure contains data for the To-Do folder
define('RSF_PID_CONV_ACTIONS' ,0x8006); // Indicates that the structure contains data for the Conversation Action Settings folder
define('RSF_PID_COMBINED_ACTIONS' ,0x8007); // This value is reserved.
define('RSF_PID_SUGGESTED_CONTACTS' ,0x8008); // Indicates that the structure contains data for the Suggested Contacts folder.
define('RSF_PID_CONTACT_SEARCH' ,0x8009); // Indicates that the structure contains data for the Contacts Search folder.
define('RSF_PID_BUDDYLIST_PDLS' ,0x800A); // Indicates that the structure contains data for the IM Contacts List folder.
define('RSF_PID_BUDDYLIST_CONTACTS' ,0x800B); // Indicates that the structure contains data for the Quick Contacts folder.
/* PersistElementType Values ElementIDs for persist data of PR_IPM_OL2007_ENTRYIDS / PR_ADDITIONAL_REN_ENTRYIDS_EX */
define('ELEMENT_SENTINEL' ,0x0000); // 0 bytes Indicates that the PersistElement structure is the last one contained in the DataElements field of the PersistData structure.
define('RSF_ELID_ENTRYID' ,0x0001); // variable Indicates that the ElementData field contains the entry ID of the special folder
// that is of the type indicated by the value of the PersistID field of the PersistData structure.
define('RSF_ELID_HEADER' ,0x0002); // 4 bytes Indicates that the ElementData field contains a 4-byte header value equal to 0x00000000.
...@@ -37,5 +37,10 @@ define('PS_MAPI', makeguid("{00020328-0000-0000-C0 ...@@ -37,5 +37,10 @@ define('PS_MAPI', makeguid("{00020328-0000-0000-C0
define('PS_PUBLIC_STRINGS', makeguid("{00020329-0000-0000-C000-000000000046}")); define('PS_PUBLIC_STRINGS', makeguid("{00020329-0000-0000-C000-000000000046}"));
define('PS_INTERNET_HEADERS', makeguid("{00020386-0000-0000-c000-000000000046}")); define('PS_INTERNET_HEADERS', makeguid("{00020386-0000-0000-c000-000000000046}"));
define('MUIDECSAB', makeguid("{50A921AC-D340-48ee-B319-FBA753304425}"));
// Kopano Contact Provider GUIDs
define('MUIDZCSAB', makeguid("{30047F72-92E3-DA4F-B86A-E52A7FE46571}"));
// sk added for Z-Push // sk added for Z-Push
define ('PSETID_AirSync', makeguid("{71035549-0739-4DCB-9163-00F0580DBBDF}")); define ('PSETID_AirSync', makeguid("{71035549-0739-4DCB-9163-00F0580DBBDF}"));
This diff is collapsed.
...@@ -621,4 +621,186 @@ class MAPIUtils { ...@@ -621,4 +621,186 @@ class MAPIUtils {
} }
// TODO check if we need to do this for encrypted (and signed?) message as well // TODO check if we need to do this for encrypted (and signed?) message as well
} }
/**
* Compares two entryIds. It is possible to have two different entryIds that should match as they
* represent the same object (in multiserver environments).
* @param string $entryId1
* @param string $entryId2
*
* @access public
* @return boolean
*/
public static function CompareEntryIds($entryId1, $entryId2) {
if (!is_string($entryId1) || !is_string($entryId2)) {
return false;
}
if ($entryId1 === $entryId2) {
// if normal comparison succeeds then we can directly say that entryids are same
return true;
}
$eid1 = self::createEntryIdObj($entryId1);
$eid2 = self::createEntryIdObj($entryId2);
if ($eid1['length'] != $eid2['length'] ||
$eid1['abFlags'] != $eid2['abFlags'] ||
$eid1['version'] != $eid2['version'] ||
$eid1['type'] != $eid2['type']) {
return false;
}
if ($eid1['name'] == 'EID_V0') {
if ($eid1['length'] < $eid1['min_length'] || $eid1['id'] != $eid2['id']) {
return false;
}
}
elseif ($eid1['length'] < $eid1['min_length'] || $eid1['uniqueId'] != $eid2['uniqueId']) {
return false;
}
return true;
}
/**
* Creates an object that has split up all the components of an entryID.
* @param string $entryid Entryid
*
* @access private
* @return Object EntryID object
*/
private static function createEntryIdObj($entryid) {
// check if we are dealing with old or new object entryids
return (substr($entryid, 40, 8) == '00000000') ? self::getEID_V0Version($entryid) : self::getEIDVersion($entryid);
}
/**
* The entryid from the begin of zarafa till 5.20.
* @param string $entryid
*
* @access private
* @return Object EntryID object
*
*/
private static function getEID_V0Version($entryid) {
// always make entryids in uppercase so comparison will be case insensitive
$entryId = strtoupper($entryid);
$res = array(
'abFlags' => '', // BYTE[4], 4 bytes, 8 hex characters
'guid' => '', // GUID, 16 bytes, 32 hex characters
'version' => '', // ULONG, 4 bytes, 8 hex characters
'type' => '', // ULONG, 4 bytes, 8 hex characters
'id' => '', // ULONG, 4 bytes, 8 hex characters
'server' => '', // CHAR, variable length
'padding' => '', // TCHAR[3], 4 bytes, 8 hex characters (upto 4 bytes)
);
$res['length'] = strlen($entryId);
$offset = 0;
// First determine padding, and remove if from the entryId
$res['padding'] = self::getPadding($entryId);
$entryId = substr($entryId, 0, strlen($entryId) - strlen($res['padding']));
$res['abFlags'] = substr($entryId, $offset, 8);
$offset =+ 8;
$res['guid'] = substr($entryId, $offset, 32);
$offset += 32;
$res['version'] = substr($entryId, $offset, 8);
$offset += 8;
$res['type'] = substr($entryId, $offset, 8);
$offset += 8;
$res['id'] = substr($entryId, $offset, 8);
$offset += 8;
$res['server'] = substr($entryId, $offset);
$res['min_lenth'] = 64;
$res['name'] = 'EID_V0';
return $res;
}
/**
* Entryid from version 6.
* @param string $entryid
*
* @access private
* @return string[]|number[]|NULL[]
*/
private static function getEIDVersion($entryid) {
// always make entryids in uppercase so comparison will be case insensitive
$entryId = strtoupper($entryid);
$res = array(
'abFlags' => '', // BYTE[4], 4 bytes, 8 hex characters
'guid' => '', // GUID, 16 bytes, 32 hex characters
'version' => '', // ULONG, 4 bytes, 8 hex characters
'type' => '', // ULONG, 4 bytes, 8 hex characters
'uniqueId' => '', // ULONG, 16 bytes, 32 hex characters
'server' => '', // CHAR, variable length
'padding' => '', // TCHAR[3], 4 bytes, 8 hex characters (upto 4 bytes)
);
$res['length'] = strlen($entryId);
$offset = 0;
// First determine padding, and remove if from the entryId
$res['padding'] = self::getPadding($entryId);
$entryId = substr($entryId, 0, strlen($entryId) - strlen($res['padding']));
$res['abFlags'] = substr($entryId, $offset, 8);
$offset =+ 8;
$res['guid'] = substr($entryId, $offset, 32);
$offset += 32;
$res['version'] = substr($entryId, $offset, 8);
$offset += 8;
$res['type'] = substr($entryId, $offset, 8);
$offset += 8;
$res['uniqueId'] = substr($entryId, $offset, 32);
$offset += 32;
$res['server'] = substr($entryId, $offset);
$res['min_length'] = 88;
$res['name'] = 'EID';
return $res;
}
/**
* Detect padding (max 3 bytes) from the entryId.
* @param string $entryId
*
* @access private
* @return string
*/
private static function getPadding($entryId) {
$len = strlen($entryId);
$padding = '';
$offset = 0;
for ($iterations = 4; $iterations > 0; $iterations--) {
if (substr($entryId, $len - ($offset + 2), $len - $offset) == '00') {
$padding .= '00';
$offset += 2;
}
else {
// if non-null character found then break the loop
break;
}
}
return $padding;
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment