Skip to content

Commit

Permalink
Merge pull request #2 from matidau/php8.x-upstream-umgfoin
Browse files Browse the repository at this point in the history
PHP8.x community commits
  • Loading branch information
matidau authored Apr 6, 2023
2 parents b84efc5 + 5d3d827 commit 4c5d0a2
Show file tree
Hide file tree
Showing 25 changed files with 1,225 additions and 573 deletions.
590 changes: 475 additions & 115 deletions src/backend/caldav/caldav.php

Large diffs are not rendered by default.

17 changes: 13 additions & 4 deletions src/backend/combined/combined.php
Original file line number Diff line number Diff line change
Expand Up @@ -438,26 +438,35 @@ public function ChangesSinkInitialize($folderid) {
* @access public
* @return array
*/

public function ChangesSink($timeout = 30) {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendCombined->ChangesSink(%d)", $timeout));

$notifications = array();
if ($this->numberChangesSink == 0) {
ZLog::Write(LOGLEVEL_DEBUG, "BackendCombined doesn't include any Sinkable backends");
} else {
$time_each = $timeout / $this->numberChangesSink;
$stopat = time() + $timeout - 1;

foreach ($this->backends as $i => $b) {
if ($this->backends[$i]->HasChangesSink()) {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendCombined->ChangesSink - Calling in '%s' with %d", get_class($b), $time_each));
ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendCombined->ChangesSink - Calling in '%s'", get_class($b)));

$notifications_backend = $this->backends[$i]->ChangesSink($time_each);
//preppend backend delimiter
$notifications_backend = $this->backends[$i]->ChangesSink(1);
// prepend backend delimiter
for ($c = 0; $c < count($notifications_backend); $c++) {
$notifications_backend[$c] = $i . $this->config['delimiter'] . $notifications_backend[$c];
}
$notifications = array_merge($notifications, $notifications_backend);
}
}

// If nothing changed, wait until timeout
if (empty($notifications)) {
while ($stopat > time()) {
sleep(1);
}
}
}

return $notifications;
Expand Down
13 changes: 11 additions & 2 deletions src/backend/imap/imap.php
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,10 @@ public function SendMail($sm) {
$message->headers["cc"] = Utils::CheckAndFixEncodingInHeadersOfSentMail($Mail_RFC822->parseAddressList($message->headers["cc"], null, null, false, null));
}

if (isset($message->headers["bcc"])) {
$message->headers["bcc"] = Utils::CheckAndFixEncodingInHeadersOfSentMail($Mail_RFC822->parseAddressList($message->headers["bcc"], null, null, false, null));
}

unset($Mail_RFC822);

if (isset($message->headers["subject"]) && mb_detect_encoding($message->headers["subject"], "UTF-8") != false && preg_match('/[^\x00-\x7F]/', $message->headers["subject"]) == 1) {
Expand Down Expand Up @@ -2635,11 +2639,11 @@ private function sendMessage($fromaddr, $toaddr, $headers, $body) {
if (is_array($toaddr)) {
$recipients = $toaddr;
}
else {
elseif ($toaddr !== "") {
$recipients = array($toaddr);
}

// Cc and Bcc headers are sent, but we need to make sure that the recipient list contains them
// add Bcc and Cc header fields to recipients
foreach (array("CC", "cc", "Cc", "BCC", "Bcc", "bcc") as $key) {
if (!empty($headers[$key])) {
if (is_array($headers[$key])) {
Expand All @@ -2648,6 +2652,11 @@ private function sendMessage($fromaddr, $toaddr, $headers, $body) {
else {
$recipients[] = $headers[$key];
}

// remove BCC header field from message
if (strcasecmp($key, "BCC") == 0) {
unset($headers[$key]);
}
}
}

Expand Down
122 changes: 109 additions & 13 deletions src/backend/imap/mime_calendar.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ function delete_calendar_dav($uid) {
$caldav->Logoff();
}
else {
ZLog::Write(LOGLEVEL_ERROR, "BackendIMAP->delete_calendar_dav(): event not found, we will end with zombie events");
ZLog::Write(LOGLEVEL_WARN, "BackendIMAP->delete_calendar_dav(): event not found, we may have zombie events");
}
}
else {
Expand Down Expand Up @@ -167,6 +167,17 @@ function is_calendar($message) {
* @param $is_sent_folder boolean
*/
function parse_meeting_calendar($part, &$output, $is_sent_folder) {
$connected = false;
if (defined('IMAP_MEETING_USE_CALDAV') && IMAP_MEETING_USE_CALDAV) {
$caldav = new BackendCalDAV();
if ($caldav->Logon(Request::GetAuthUser(), Request::GetAuthDomain(), Request::GetAuthPassword())) {
$connected = true;
}
else {
ZLog::Write(LOGLEVEL_ERROR, "BackendIMAP->parse_meeting_calendar(): Error connecting with BackendCalDAV");
}
}

$ical = new iCalComponent();
$ical->ParseFrom($part->body);
ZLog::Write(LOGLEVEL_WBXML, sprintf("BackendIMAP->parse_meeting_calendar(): %s", $part->body));
Expand Down Expand Up @@ -200,12 +211,17 @@ function parse_meeting_calendar($part, &$output, $is_sent_folder) {
case "cancel":
$output->messageclass = "IPM.Schedule.Meeting.Canceled";
ZLog::Write(LOGLEVEL_DEBUG, "BackendIMAP->parse_meeting_calendar(): Event canceled, removing calendar object");
delete_calendar_dav($uid);

// don't delete the recurring event on receiving cancelled exception
if (count($ical->GetPropertiesByPath("VEVENT/RECURRENCE-ID")) == 0) {
delete_calendar_dav($uid);
}
break;
case "declinecounter":
ZLog::Write(LOGLEVEL_DEBUG, "BackendIMAP->parse_meeting_calendar(): Declining a counter is not implemented.");
case "counter":
ZLog::Write(LOGLEVEL_DEBUG, "BackendIMAP->parse_meeting_calendar(): Counter received");
$output->messageclass = "IPM.Schedule.Meeting.Resp.Tent";
$output->meetingrequest->disallownewtimeproposal = 0;
break;
case "reply":
ZLog::Write(LOGLEVEL_DEBUG, "BackendIMAP->parse_meeting_calendar(): Reply received");
Expand Down Expand Up @@ -248,18 +264,24 @@ function parse_meeting_calendar($part, &$output, $is_sent_folder) {
}
}
}
$output->meetingrequest->disallownewtimeproposal = 1;
$output->meetingrequest->disallownewtimeproposal = "1";
break;
case "request":
$output->messageclass = "IPM.Schedule.Meeting.Request";
$output->meetingrequest->disallownewtimeproposal = 0;
ZLog::Write(LOGLEVEL_DEBUG, "BackendIMAP->parse_meeting_calendar(): New request");
// New meeting, we don't create it now, because we need to confirm it first, but if we don't create it we won't see it in the calendar
break;
case "add":
ZLog::Write(LOGLEVEL_DEBUG, "BackendIMAP->parse_meeting_calendar(): Add method is not implemented.");
$output->messageclass = "IPM.Appointment";
break;
case "publish":
ZLog::Write(LOGLEVEL_DEBUG, "BackendIMAP->parse_meeting_calendar(): Publish method is not a meeting request.");
$output->messageclass = "IPM.Appointment";
break;
default:
ZLog::Write(LOGLEVEL_WARN, sprintf("BackendIMAP->parse_meeting_calendar() - Unknown method <%s>, please report it to the developers", strtolower($part->headers["method"])));
ZLog::Write(LOGLEVEL_WARN, sprintf("BackendIMAP->parse_meeting_calendar() - Unknown method <%s>, please report it to the developers", $method));
$output->messageclass = "IPM.Appointment";
$output->meetingrequest->disallownewtimeproposal = 0;
break;
}
}
Expand Down Expand Up @@ -318,7 +340,7 @@ function parse_meeting_calendar($part, &$output, $is_sent_folder) {
}

// Get $tz from first timezone
$props = $ical->GetPropertiesByPath("VTIMEZONE/TZID");
$props = $ical->GetPropertiesByPath('VTIMEZONE/TZID');
if (count($props) > 0) {
// TimeZones shouldn't have dots
$tzname = str_replace(".", "", $props[0]->Value());
Expand All @@ -329,13 +351,87 @@ function parse_meeting_calendar($part, &$output, $is_sent_folder) {
}
$output->meetingrequest->timezone = base64_encode(TimezoneUtil::GetSyncBlobFromTZ($tz));

// Fixed values
$output->meetingrequest->instancetype = 0;
// guess instancetype by checking for recurrence rules or ids
if (count($ical->GetPropertiesByPath('VEVENT/RRULE')) == 1) {
$output->meetingrequest->instancetype = 1;
}
elseif (count($ical->GetPropertiesByPath('VEVENT/RECURRENCE-ID')) == 1) {
if ($connected && count($caldav->FindCalendar($uid)) == 1) {
$output->meetingrequest->instancetype = 3;
}
else {
$output->meetingrequest->instancetype = 2;
}
}
else {
$output->meetingrequest->instancetype = 0;
}

$output->meetingrequest->responserequested = 1;
$output->meetingrequest->busystatus = 2;

// TODO: reminder
$output->meetingrequest->reminder = "";
// get intended busystatus
$props = $ical->GetPropertiesByPath('VEVENT/X-MICROSOFT-CDO-INTENDEDSTATUS');
if (count($props) == 1) {
switch ($props[0]->Value()) {
case "FREE":
$output->meetingrequest->busystatus = "0";
break;
case "TENTATIVE":
$output->meetingrequest->busystatus = "1";
break;
case "BUSY":
$output->meetingrequest->busystatus = "2";
break;
case "OOF":
$output->meetingrequest->busystatus = "3";
break;
}
}
elseif (count($props = $ical->GetPropertiesByPath('VEVENT/TRANSP')) == 1) {
switch ($props[0]->Value()) {
case "TRANSPARENT":
$output->meetingrequest->busystatus = "0";
break;
case "OPAQUE":
$output->meetingrequest->busystatus = "2";
break;
}
}
else {
$output->meetingrequest->busystatus = 2;
}

// is counter allowed
$props = $ical->GetPropertiesByPath('VEVENT/X-MICROSOFT-DISALLOW-COUNTER');
if (count($props) > 0) {
switch ($props[0]->Value()) {
case "TRUE":
$output->meetingrequest->disallownewtimeproposal = "1";
break;
case "FALSE":
$output->meetingrequest->disallownewtimeproposal = "0";
break;
}
}

// use reminder with smallest interval
$props = $ical->GetPropertiesByPath('VEVENT/VALARM/TRIGGER');
if (count($props) > 0) {
foreach ($props as $vAlarmTrigger) {
$vAlarmTriggerValue = $vAlarmTrigger->Value();
if ($vAlarmTriggerValue[0] == "-") {
$reminderSeconds = new DateInterval(substr($vAlarmTriggerValue, 1));
$reminderSeconds = $reminderSeconds->format("%s") + $reminderSeconds->format("%i") * 60 + $reminderSeconds->format("%h") * 3600 + $reminderSeconds->format("%d") * 86400;
if (!isset($output->meetingrequest->reminderSeconds) || $output->meetingrequest->reminder > $reminderSeconds) {
$output->meetingrequest->reminder = $reminderSeconds;
}
}
}
}

if ($connected) {
$caldav->Logoff();
}
}


Expand Down
12 changes: 10 additions & 2 deletions src/backend/imap/user_identity.php
Original file line number Diff line number Diff line change
Expand Up @@ -136,23 +136,31 @@ function getIdentityFromLdap($username, $domain, $identity, $encode = true) {

if ($ldap_conn) {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->getIdentityFromLdap() - Connected to LDAP"));

ldap_set_option($ldap_conn, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldap_conn, LDAP_OPT_REFERRALS, 0);
$ldap_bind = ldap_bind($ldap_conn, IMAP_FROM_LDAP_USER, IMAP_FROM_LDAP_PASSWORD);

if ($ldap_bind) {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->getIdentityFromLdap() - Authenticated in LDAP"));

$filter = str_replace('#username', $username, str_replace('#domain', $domain, IMAP_FROM_LDAP_QUERY));
ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->getIdentityFromLdap() - Searching From with filter: %s", $filter));

$search = ldap_search($ldap_conn, IMAP_FROM_LDAP_BASE, $filter, unserialize(IMAP_FROM_LDAP_FIELDS));
$items = ldap_get_entries($ldap_conn, $search);
if ($items['count'] > 0) {
$ret_value = $identity;
ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->getIdentityFromLdap() - Found entry in LDAP. Generating From"));
// We get the first object. It's your responsability to make the query unique

// We get the first object. It's your responsibility to make the query unique.
foreach (unserialize(IMAP_FROM_LDAP_FIELDS) as $field) {
$ret_value = str_replace('#'.$field, $items[0][$field][0], $ret_value);
if (isset($items[0][$field][0])) {
$ret_value = str_replace('#' . $field, $items[0][$field][0], $ret_value);
}
}
$ret_value = trim($ret_value);

if ($encode) {
$ret_value = encodeFrom($ret_value);
}
Expand Down
4 changes: 2 additions & 2 deletions src/backend/ipcsharedmemory/ipcsharedmemoryprovider.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ public function __construct($type, $allocate, $class, $serverKey) {
$this->type = $type;
$this->allocate = $allocate;

if ($this->initSharedMem())
ZLog::Write(LOGLEVEL_DEBUG, sprintf("%s(): Initialized mutexid %s and memid %s.", $class, $this->mutexid, $this->memid));
if ($this->initSharedMem())
ZLog::Write(LOGLEVEL_DEBUG, sprintf("%s(): Initialized.", $class));
}

/**
Expand Down
17 changes: 9 additions & 8 deletions src/backend/kopano/mapi/class.meetingrequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -690,9 +690,9 @@ function doAccept($tentative, $sendresponse, $move, $newProposedStartTime=false,
// instead of tentative, and accept the same as per the intended busystatus.
$senderEntryId = isset($messageprops[PR_SENT_REPRESENTING_ENTRYID]) ? $messageprops[PR_SENT_REPRESENTING_ENTRYID] : $messageprops[PR_SENDER_ENTRYID];
if(isset($messageprops[PR_RECEIVED_BY_ENTRYID]) && MAPIUtils::CompareEntryIds($senderEntryId, $messageprops[PR_RECEIVED_BY_ENTRYID])) {
$entryid = $this->accept(false, $sendresponse, $move, $proposeNewTimeProps, $body, true, $store, $calFolder, $basedate);
$entryid = $this->accept(false, $sendresponse, $move, $proposeNewTimeProps, $store, $calFolder, $body, true, $basedate);
} else {
$entryid = $this->accept($tentative, $sendresponse, $move, $proposeNewTimeProps, $body, $userAction, $store, $calFolder, $basedate);
$entryid = $this->accept($tentative, $sendresponse, $move, $proposeNewTimeProps, $store, $calFolder, $body, $userAction, $basedate);
}

// if we have first time processed this meeting then set PR_PROCESSED property
Expand All @@ -707,13 +707,13 @@ function doAccept($tentative, $sendresponse, $move, $newProposedStartTime=false,
return $entryid;
}

function accept($tentative, $sendresponse, $move, $proposeNewTimeProps = array(), $body = false, $userAction = false, $store, $calFolder, $basedate = false)
function accept($tentative, $sendresponse, $move, $proposeNewTimeProps, $store, $calFolder, $body = false, $userAction = false, $basedate = false)
{
$messageprops = mapi_getprops($this->message);
$isDelegate = isset($messageprops[PR_RCVD_REPRESENTING_NAME]);

if ($sendresponse) {
$this->createResponse($tentative ? olResponseTentative : olResponseAccepted, $proposeNewTimeProps, $body, $store, $basedate, $calFolder);
$this->createResponse($tentative ? olResponseTentative : olResponseAccepted, $proposeNewTimeProps, $store, $calFolder, $body, $basedate);
}

/**
Expand Down Expand Up @@ -875,7 +875,7 @@ function accept($tentative, $sendresponse, $move, $proposeNewTimeProps = array()

// Main recurring item is found, so now update exception
if ($calendarItem) {
$this->acceptException($calendarItem, $this->message, $basedate, $move, $tentative, $userAction, $store, $isDelegate);
$this->acceptException($calendarItem, $this->message, $basedate, $store, $tentative, $userAction, $move, $isDelegate);
$calendarItemProps = mapi_getprops($calendarItem, array(PR_ENTRYID));
$entryid = $calendarItemProps[PR_ENTRYID];
}
Expand Down Expand Up @@ -1141,7 +1141,7 @@ function doDecline($sendresponse, $basedate = false, $body = false)
}

if($sendresponse) {
$this->createResponse(olResponseDeclined, array(), $body, $store, $basedate, $calFolder);
$this->createResponse(olResponseDeclined, $store, $calFolder, $body, $basedate);
}

if ($basedate) {
Expand Down Expand Up @@ -1856,7 +1856,7 @@ function openCustomUserStore($ownerentryid)
* @param Array $proposeNewTimeProps properties of attendee's proposal
* @param integer $basedate date of occurrence which attendee has responded
*/
function createResponse($status, $proposeNewTimeProps = array(), $body = false, $store, $basedate = false, $calFolder) {
function createResponse($status, $store, $calFolder, $proposeNewTimeProps = array(), $body = false, $basedate = false) {
$messageprops = mapi_getprops($this->message, Array(PR_SENT_REPRESENTING_ENTRYID,
PR_SENT_REPRESENTING_EMAIL_ADDRESS,
PR_SENT_REPRESENTING_ADDRTYPE,
Expand Down Expand Up @@ -2691,7 +2691,8 @@ function bookResources($message, $cancel, $prefix, $basedate = false)
* @param resource $store user store
* @param boolean $isDelegate true if delegate is processing this meeting request
*/
function acceptException(&$recurringItem, &$occurrenceItem, $basedate, $move = false, $tentative, $userAction = false, $store, $isDelegate = false)

function acceptException(&$recurringItem, &$occurrenceItem, $basedate, $store, $tentative, $userAction = false, $move = false, $isDelegate = false)
{
$recurr = new Recurrence($store, $recurringItem);

Expand Down
9 changes: 8 additions & 1 deletion src/backend/kopano/mapiprovider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2907,7 +2907,14 @@ private function getSpecialFoldersData() {
if (strlen($persistData) == 4 && $persistData == PERSIST_SENTINEL) {
break;
}
$unpackedData = unpack("vdataSize/velementID/velDataSize", substr($persistData, 2, 6));
// incase of empty $persistData: Suppress error 'unpack(): Type v: not enough input, need 2, have 0'
$part = substr($persistData, 2, 6);
if(strlen($part)==6)
$unpackedData = unpack("vdataSize/velementID/velDataSize", $part);
else{
ZLog::Write(LOGLEVEL_INFO, "MAPIProvider->getSpecialFoldersData(): Not enough data");
$unpackedData = array();
}
if (isset($unpackedData['dataSize']) && isset($unpackedData['elementID']) && $unpackedData['elementID'] == RSF_ELID_ENTRYID && isset($unpackedData['elDataSize'])) {
$this->specialFoldersData[] = substr($persistData, 8, $unpackedData['elDataSize']);
// Add PersistId and DataElementsSize lenghts to the data size as they're not part of it
Expand Down
Loading

0 comments on commit 4c5d0a2

Please sign in to comment.