Commit e192808a authored by Manfred Kutas's avatar Manfred Kutas

Merge pull request #696 in ZP/z-push from develop to release/2.4

* commit '0c41fb86':
  ZP-1411 Unset undefined properties for tasks.
  ZP-1410 Dot at the end of sentences. Released under the Affero GNU General Public License (AGPL) version 3.
  ZP-1410 IMAP backend to provide user details for CalDAV backend. Released under the Affero GNU General Public License (AGPL) version 3.
  ZP-1408 Don't log a warning when a user does not enter a subject. Released under the Affero GNU General Public License (AGPL) version 3.
  ZP-1372 PHP doc fix - added a dot at the end of the sentence.
  ZP-1372 Created getter ZPush::GetDeviceManager()->GetDevid() , resumed SYNC_STATUS_INVALIDSYNCKEY for triggering a folder resync. Released under the Affero GNU General Public License (AGPL) version 3.
  ZP-250 Improve log messages in readPropStream.
  ZP-1401 Sync Kopano contacts with gab2contacts.
  ZP-1400 Picture not saved for a contact created on mobile.
  ZP-1399 Wrong state and log folder permissions for RHEL based systems.
  ZP-1398 Do not call $device->GetHierarchyCache() in loop.
  ZP-1372 Removed logging deviceid. Code style changes.
  ZP-1396 Only a meeting if meetingstatus says so. Released under the Affero GNU General Public License (AGPL) version 3.
  ZP-1369 Get foldername from MAPI when impersonating.
  ZP-1372 Moved 'Not Triggering folder re-sync' message to INFO level. Released under the Affero GNU General Public License (AGPL) version 3.
  ZP-1372 Folder re-sync is triggered on deletions ratio threshold. Released under the Affero GNU General Public License (AGPL) version 3.
  ZP-1386 Update mimedecode include. Released under the Affero GNU General Public License (AGPL) version 3.
  ZP-1391 Support disabling multiple IMAP auth methods, log the disabled methods. Released under the Affero GNU General Public License (AGPL) version 3.
  ZP-1391 Allow disabling the GSSAPI authenticator. Released under the Affero GNU General Public License (AGPL) version 3.
parents d504674d 0c41fb86
......@@ -797,10 +797,18 @@ class BackendCalDAV extends BackendDiff {
}
}
// Workaround #127 - No organizeremail defined
if (!isset($message->organizeremail)) {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendCalDAV->_ParseVEventToSyncObject(): No organizeremail defined, using username"));
$message->organizeremail = $this->originalUsername;
if ($message->meetingstatus > 0) {
// No organizer was set for the meeting, assume it is the user
if (!isset($message->organizeremail)) {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendCalDAV->_ParseVEventToSyncObject(): No organizeremail defined, using user details"));
$userDetails = ZPush::GetBackend()->GetCurrentUsername();
$message->organizeremail = $userDetails['emailaddress'];
$message->organizername = $userDetails['fullname'];
}
// Ensure the organizer name is set
if (!isset($message->organizername)) {
$message->organizername = Utils::GetLocalPartFromEmail($message->organizeremail);
}
}
$valarm = current($event->GetComponents("VALARM"));
......@@ -1081,42 +1089,25 @@ class BackendCalDAV extends BackendDiff {
$rtfparser->parse();
$vevent->AddProperty("DESCRIPTION", $rtfparser->out);
}
$is_meeting = false;
if (isset($data->meetingstatus)) {
if (isset($data->meetingstatus) && $data->meetingstatus > 0) {
switch ($data->meetingstatus) {
case "1":
$vevent->AddProperty("STATUS", "TENTATIVE");
$vevent->AddProperty("X-MICROSOFT-CDO-BUSYSTATUS", "TENTATIVE");
$vevent->AddProperty("X-MICROSOFT-DISALLOW-COUNTER", "FALSE");
$is_meeting = true;
break;
case "3":
$vevent->AddProperty("STATUS", "CONFIRMED");
$vevent->AddProperty("X-MICROSOFT-CDO-BUSYSTATUS", "CONFIRMED");
$vevent->AddProperty("X-MICROSOFT-DISALLOW-COUNTER", "FALSE");
$is_meeting = true;
break;
case "5":
case "7":
$vevent->AddProperty("STATUS", "CANCELLED");
$vevent->AddProperty("X-MICROSOFT-CDO-BUSYSTATUS", "CANCELLED");
$vevent->AddProperty("X-MICROSOFT-DISALLOW-COUNTER", "TRUE");
$is_meeting = true;
break;
}
}
if (isset($data->attendees) && is_array($data->attendees)) {
$is_meeting = true;
foreach ($data->attendees as $att) {
if (isset($att->name)) {
$vevent->AddProperty("ATTENDEE", sprintf("MAILTO:%s", $att->email), array("CN" => $att->name));
}
else {
$vevent->AddProperty("ATTENDEE", sprintf("MAILTO:%s", $att->email));
}
}
}
if ($is_meeting) {
if (isset($data->organizeremail) && isset($data->organizername)) {
$vevent->AddProperty("ORGANIZER", sprintf("MAILTO:%s", $data->organizeremail), array("CN" => $data->organizername));
}
......@@ -1125,8 +1116,18 @@ class BackendCalDAV extends BackendDiff {
}
else {
//Some phones doesn't send the organizeremail, so we gotto get it somewhere else.
//Lets use the login here ($username)
$vevent->AddProperty("ORGANIZER", sprintf("MAILTO:%s", $data->originalUsername));
$userDetails = ZPush::GetBackend()->GetCurrentUsername();
$vevent->AddProperty("ORGANIZER", sprintf("MAILTO:%s", $userDetails['emailaddress']), array("CN" => $userDetails['fullname']));
}
if (isset($data->attendees) && is_array($data->attendees)) {
foreach ($data->attendees as $att) {
if (isset($att->name)) {
$vevent->AddProperty("ATTENDEE", sprintf("MAILTO:%s", $att->email), array("CN" => $att->name));
}
else {
$vevent->AddProperty("ATTENDEE", sprintf("MAILTO:%s", $att->email));
}
}
}
}
if (isset($data->body) && strlen($data->body) > 0) {
......
......@@ -666,4 +666,22 @@ class BackendCombined extends Backend implements ISearchProvider {
return false;
}
/**
* Returns the email address and the display name of the user. Used by autodiscover and caldav.
*
* @param string $username The username
*
* @access public
* @return Array
*/
public function GetUserDetails($username) {
// Find a backend that can provide the information
foreach ($this->backends as $backend) {
if (method_exists($backend, "GetUserDetails")) {
return $backend->GetUserDetails($username);
}
}
return parent::GetUserDetails($username);
}
}
......@@ -139,6 +139,7 @@ define('IMAP_FROM_SQL_PASSWORD', '');
define('IMAP_FROM_SQL_OPTIONS', serialize(array(PDO::ATTR_PERSISTENT => true)));
define('IMAP_FROM_SQL_QUERY', "select first_name, last_name, mail_address from users where mail_address = '#username@#domain'");
define('IMAP_FROM_SQL_FIELDS', serialize(array('first_name', 'last_name', 'mail_address')));
define('IMAP_FROM_SQL_EMAIL', '#mail_address');
define('IMAP_FROM_SQL_FROM', '#first_name #last_name <#mail_address>');
define('IMAP_FROM_SQL_FULLNAME', '#first_name #last_name');
......@@ -156,6 +157,7 @@ define('IMAP_FROM_LDAP_PASSWORD', 'password');
define('IMAP_FROM_LDAP_BASE', 'dc=zpush,dc=org');
define('IMAP_FROM_LDAP_QUERY', '(mail=#username@#domain)');
define('IMAP_FROM_LDAP_FIELDS', serialize(array('givenname', 'sn', 'mail')));
define('IMAP_FROM_LDAP_EMAIL', '#mail');
define('IMAP_FROM_LDAP_FROM', '#givenname #sn <#mail>');
define('IMAP_FROM_LDAP_FULLNAME', '#givenname #sn');
......@@ -207,4 +209,9 @@ define('SYSTEM_MIME_TYPES_MAPPING', '/etc/mime.types');
// Use BackendCalDAV for Meetings. You cannot hope to get that functionality working without a caldav backend.
define('IMAP_MEETING_USE_CALDAV', false);
\ No newline at end of file
define('IMAP_MEETING_USE_CALDAV', false);
// If your IMAP server allows authenticating via GSSAPI, php-imap will not fall back properly to other authentication
// methods and you will be unable to log in. Uncomment the following line to disable that authentication method.
// Multiple methods can be specified as a comma-separated string.
// define('IMAP_DISABLE_AUTHENTICATOR', 'GSSAPI');
......@@ -52,6 +52,7 @@ class BackendIMAP extends BackendDiff implements ISearchProvider {
private $folderhierarchy;
private $excludedFolders;
private static $mimeTypes = false;
private $imapParams = array();
public function __construct() {
......@@ -68,6 +69,10 @@ class BackendIMAP extends BackendDiff implements ISearchProvider {
if (!function_exists("mb_detect_order")) {
ZLog::Write(LOGLEVEL_WARN, sprintf("BackendIMAP(): php-mbstring module is not installed, you should install it for better encoding conversions"));
}
if (defined("IMAP_DISABLE_AUTHENTICATOR")) {
ZLog::Write(LOGLEVEL_INFO, sprintf("BackendIMAP(): The following authentication methods are disabled: %s", IMAP_DISABLE_AUTHENTICATOR));
$this->imapParams = array("DISABLE_AUTHENTICATOR" => array_map('trim' ,explode(',', IMAP_DISABLE_AUTHENTICATOR)));
}
}
/**----------------------------------------------------------------------------------------------------------
......@@ -105,7 +110,7 @@ class BackendIMAP extends BackendDiff implements ISearchProvider {
/* END fmbiete's contribution r1527, ZP-319 */
// open the IMAP-mailbox
$this->mbox = @imap_open($this->server , $username, $password, OP_HALFOPEN);
$this->mbox = @imap_open($this->server , $username, $password, OP_HALFOPEN, 0, $this->imapParams);
$this->mboxFolder = "";
if ($this->mbox) {
......@@ -1755,10 +1760,9 @@ class BackendIMAP extends BackendDiff implements ISearchProvider {
* @return Array
*/
public function GetUserDetails($username) {
// If the username it's not the email address, here we will have an error. We try creating a valid address
$email = $username;
if (strpos($username, "@") === false && strlen($this->domain) > 0) {
$email .= "@" . $this->domain;
if (!USE_FULLEMAIL_FOR_LOGIN) {
$email = getDefaultEmailValue($username, $this->domain);
}
return array('emailaddress' => $email, 'fullname' => getDefaultFullNameValue($username, $this->domain));
}
......@@ -2224,7 +2228,7 @@ class BackendIMAP extends BackendDiff implements ISearchProvider {
imap_ping($this->mbox);
}
else {
$this->mbox = @imap_open($this->server, $this->username, $this->password, OP_HALFOPEN);
$this->mbox = @imap_open($this->server, $this->username, $this->password, OP_HALFOPEN, 0, $this->imapParams);
$this->mboxFolder = "";
}
}
......
......@@ -23,6 +23,40 @@
* Consult LICENSE file for details
************************************************/
/**
* Returns the default email address.
*
* @return string
*/
function getDefaultEmailValue($username, $domain) {
$v = "";
if (defined('IMAP_DEFAULTFROM')) {
switch (IMAP_DEFAULTFROM) {
case 'username':
$v = $username;
break;
case 'domain':
$v = $domain;
break;
case 'ldap':
$v = getIdentityFromLdap($username, $domain, IMAP_FROM_LDAP_EMAIL, false);
break;
case 'sql':
$v = getIdentityFromSql($username, $domain, IMAP_FROM_SQL_EMAIL, false);
break;
case 'passwd':
$v = getIdentityFromPasswd($username, $domain, 'EMAIL', false);
break;
default:
$v = $username . IMAP_DEFAULTFROM;
break;
}
}
return $v;
}
/**
* Returns the default value for "From"
*
......@@ -206,15 +240,15 @@ function getIdentityFromPasswd($username, $domain, $identity, $encode = true) {
$tmp = $local_user['gecos'];
$tmp = explode(',', $tmp);
$name = $tmp[0];
$email = $tmp[1];
unset($tmp);
switch ($identity) {
case 'EMAIL':
$ret_value = sprintf("%s", $email);
break;
case 'FROM':
if (strlen($domain) > 0) {
$ret_value = sprintf("%s <%s@%s>", $name, $username, $domain);
} else {
ZLog::Write(LOGLEVEL_WARN, sprintf("BackendIMAP->getIdentityFromPasswd() - No domain passed. Cannot construct From address."));
}
$ret_value = sprintf("%s <%s>", $name, $email);
break;
case 'FULLNAME':
$ret_value = sprintf("%s", $name);
......@@ -245,4 +279,4 @@ function encodeFrom($from) {
$items = explode("<", $from);
$name = trim($items[0]);
return "=?UTF-8?B?" . base64_encode($name) . "?= <" . $items[1];
}
\ No newline at end of file
}
......@@ -167,9 +167,46 @@ class PHPWrapper {
*/
public function ImportMessageDeletion($flags, $sourcekeys) {
$amount = count($sourcekeys);
if ($amount > 1000) {
if ((!defined('DELETION_COUNT_THR') || !defined('DELETION_RATIO_THR')) && $amount > 1000) {
throw new StatusException(sprintf("PHPWrapper->ImportMessageDeletion(): Received %d remove requests from ICS for folder '%s' (max. 1000 allowed). Triggering folder re-sync.", $amount, bin2hex($this->folderid)), SYNC_STATUS_INVALIDSYNCKEY, null, LOGLEVEL_ERROR);
}
// Analyse only if above DELETION_COUNT_THR threshold
elseif (defined('DELETION_COUNT_THR') && defined('DELETION_RATIO_THR') && $amount > DELETION_COUNT_THR) {
// Convert a PR_SOURCE_KEY to an PR_ENTRYID, for example to be able to open a folder if you only have a PR_SOURCE_KEY.
$entryid = mapi_msgstore_entryidfromsourcekey($this->store, $this->folderid);
if (!$entryid) {
ZLog::Write(LOGLEVEL_WARN, sprintf("PHPWrapper->ImportMessageDeletion(): Error, mapi_msgstore_entryidfromsourcekey failed for folder '%s'. Stop Analysis and revert to normal delete. Error 0x%08X", bin2hex($this->folderid), mapi_last_hresult()));
}
else {
// opens current folder
$wi_mfolder = mapi_msgstore_openentry($this->store, $entryid);
if (!$wi_mfolder) {
ZLog::Write(LOGLEVEL_WARN, sprintf("PHPWrapper->ImportMessageDeletion(): Error, mapi_msgstore_openentry failed for folder '%s'. Stop Analysis and revert to normal delete. Error 0x%08X", bin2hex($this->folderid), mapi_last_hresult()));
}
else {
// retrieve folder properties
$wi_mfolderProps = mapi_getprops($wi_mfolder, array(PR_CONTENT_COUNT));
if (!isset($wi_mfolderProps[PR_CONTENT_COUNT])) {
ZLog::Write(LOGLEVEL_WARN, sprintf("PHPWrapper->ImportMessageDeletion(): Error, mapi_getprops failed for folder '%s'. Stop Analysis and revert to normal delete. Error 0x%08X", bin2hex($this->folderid), mapi_last_hresult()));
}
else {
//get count of remaining folder elements
$wi_mfolderElementsCount = $wi_mfolderProps[PR_CONTENT_COUNT];
//get ratio between deleted element count and remaining elements count
$ratio = $amount / $wi_mfolderElementsCount;
$devid = ZPush::GetDeviceManager()->GetDevid();
if ($ratio > DELETION_RATIO_THR || $ratio == 0) {
throw new StatusException(sprintf("PHPWrapper->ImportMessageDeletion(): Received %d remove requests from ICS for devId='%s' folder='%s' folderCount='%d' ratio='%0.2f' threshold='%0.2f'. Triggering folder re-sync.", $amount, $devid, bin2hex($this->folderid), $wi_mfolderElementsCount, $ratio, DELETION_RATIO_THR), SYNC_STATUS_INVALIDSYNCKEY, null, LOGLEVEL_ERROR);
}
else {
ZLog::Write(LOGLEVEL_INFO, sprintf("PHPWrapper->ImportMessageDeletion(): Received %d remove requests from ICS for devId='%s' folder='%s' folderCount='%d' ratio='%0.2f' threshold='%0.2f'. Not Triggering folder re-sync. ", $amount, $devid, bin2hex($this->folderid), $wi_mfolderElementsCount, $ratio, DELETION_RATIO_THR));
}
}
}
}
}
else {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("PHPWrapper->ImportMessageDeletion(): Received %d remove requests from ICS", $amount));
}
......
......@@ -1637,13 +1637,13 @@ class MAPIProvider {
$pic = mapi_message_createattach($mapimessage);
// Set properties of the attachment
$picprops = array(
PR_ATTACH_LONG_FILENAME_A => "ContactPicture.jpg",
PR_ATTACH_LONG_FILENAME => "ContactPicture.jpg",
PR_DISPLAY_NAME => "ContactPicture.jpg",
0x7FFF000B => true,
PR_ATTACHMENT_HIDDEN => false,
PR_ATTACHMENT_FLAGS => 1,
PR_ATTACH_METHOD => ATTACH_BY_VALUE,
PR_ATTACH_EXTENSION_A => ".jpg",
PR_ATTACH_EXTENSION => ".jpg",
PR_ATTACH_NUM => 1,
PR_ATTACH_SIZE => $picsize,
PR_ATTACH_DATA_BIN => $picbinary,
......
......@@ -393,11 +393,11 @@ class MAPIUtils {
$stream = mapi_openproperty($message, $prop, IID_IStream, 0, 0);
$ret = mapi_last_hresult();
if ($ret == MAPI_E_NOT_FOUND) {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("MAPIUtils->readPropStream: property 0x%s not found. It is either empty or not set. It will be ignored.", str_pad(dechex($prop), 8, 0, STR_PAD_LEFT)));
ZLog::Write(LOGLEVEL_DEBUG, sprintf("MAPIUtils->readPropStream: property 0x%08X not found. It is either empty or not set. It will be ignored.", $prop));
return "";
}
elseif ($ret) {
ZLog::Write(LOGLEVEL_ERROR, "MAPIUtils->readPropStream error opening stream: 0X%X", $ret);
ZLog::Write(LOGLEVEL_ERROR, "MAPIUtils->readPropStream error opening stream: 0x%08X", $ret);
return "";
}
$data = "";
......
......@@ -520,6 +520,16 @@ class ReplyBackImExporter implements IImportChanges, IExportChanges {
$foldername = $folders[$folderid]->displayname;
}
// get the foldername from MAPI when impersonating - ZP-1369
if ($foldername == "unknown") {
$entryid = mapi_msgstore_entryidfromsourcekey($this->store, $this->folderid);
$mapifolder = mapi_msgstore_openentry($this->store, $entryid);
$folderprops = mapi_getprops($mapifolder, array(PR_DISPLAY_NAME));
if (isset($folderprops[PR_DISPLAY_NAME])) {
$foldername = $folderprops[PR_DISPLAY_NAME];
}
}
// get the differences between the two objects
$data = substr(get_class($oldmessage), 4) . "\r\n";
// get the suppported fields as we need them to determine the ghosted properties
......
......@@ -538,7 +538,7 @@ class Mail_mimeDecode
$hdr_name = substr($value, 0, $pos = strpos($value, ':'));
$hdr_value = substr($value, $pos+1);
if($hdr_value[0] == ' ') {
if(strlen($hdr_value) && $hdr_value[0] == ' ') {
$hdr_value = substr($hdr_value, 1);
}
......
......@@ -1278,4 +1278,14 @@ class DeviceManager {
}
return $folder;
}
/**
* Returns the device id.
*
* @access public
* @return string
*/
public function GetDevid() {
return $this->devid;
}
}
......@@ -289,6 +289,21 @@ class ZPush {
if (defined('USE_X_FORWARDED_FOR_HEADER')) {
ZLog::Write(LOGLEVEL_INFO, "The configuration parameter 'USE_X_FORWARDED_FOR_HEADER' was deprecated in favor of 'USE_CUSTOM_REMOTE_IP_HEADER'. Please update your configuration.");
}
//check folder re-sync triggering settings
if (defined('DELETION_COUNT_THR') && !defined('DELETION_RATIO_THR')) {
throw new FatalMisconfigurationException("Only DELETION_COUNT_THR defined. Please define DELETION_RATIO_THR.");
}
elseif (!defined('DELETION_COUNT_THR') && defined('DELETION_RATIO_THR')) {
throw new FatalMisconfigurationException("Only DELETION_RATIO_THR defined. Please define DELETION_COUNT_THR.");
}
if ((defined('DELETION_COUNT_THR')) && (!is_int(DELETION_COUNT_THR) || DELETION_COUNT_THR < 1)) {
throw new FatalMisconfigurationException("The DELETION_COUNT_THR value must be a number higher than 0.");
}
if ((defined('DELETION_RATIO_THR')) && (!is_numeric(DELETION_RATIO_THR) || DELETION_RATIO_THR <= 0)) {
throw new FatalMisconfigurationException("The DELETION_RATIO_THR value must be a number higher than 0.");
}
return true;
}
......
......@@ -65,7 +65,7 @@ abstract class SyncObject extends Streamer {
public function emptySupported($supportedFields) {
// Some devices do not send supported tag. In such a case remove all not set properties.
if (($supportedFields === false || !is_array($supportedFields) || (empty($supportedFields)))) {
if (defined('UNSET_UNDEFINED_PROPERTIES') && UNSET_UNDEFINED_PROPERTIES && ($this instanceof SyncContact || $this instanceof SyncAppointment)) {
if (defined('UNSET_UNDEFINED_PROPERTIES') && UNSET_UNDEFINED_PROPERTIES && ($this instanceof SyncContact || $this instanceof SyncAppointment || $this instanceof SyncTask)) {
ZLog::Write(LOGLEVEL_INFO, sprintf("%s->emptySupported(): no supported list available, emptying all not set parameters", get_class($this)));
$supportedFields = array_keys($this->mapping);
}
......@@ -96,7 +96,7 @@ abstract class SyncObject extends Streamer {
* @see SyncObject
* @param SyncObject $odo other SyncObject
* @param boolean $log flag to turn on logging
* @param boolean $strictTypeCompare to enforce type matching
* @param boolean $strictTypeCompare to enforce type matching
* @return boolean
*/
public function equals($odo, $log = false, $strictTypeCompare = false) {
......
......@@ -894,14 +894,15 @@ class Utils {
$perm_dir = stat($dir);
$perm_file = stat($file);
if ($perm_file['uid'] == 0 && $perm_dir['uid'] == 0) {
if ($perm_file['uid'] == 0 && $perm_dir['uid'] == 0 && $perm_dir['gid'] == 0) {
unlink($file);
throw new FatalException("FixFileOwner: $dir must be owned by the nginx/apache/php user instead of root");
throw new FatalException("FixFileOwner: $dir must be owned by the nginx/apache/php user instead of root for debian based systems and by root:z-push for RHEL-based systems");
}
if($perm_dir['uid'] !== $perm_file['uid'] || $perm_dir['gid'] !== $perm_file['gid']) {
chown($file, $perm_dir['uid']);
chgrp($file, $perm_dir['gid']);
chmod($file, 0664);
}
}
return true;
......@@ -1361,7 +1362,7 @@ class Utils {
if (!$rawheaders) {
return;
}
$message->headers["subject"] = Utils::convertRawHeader2Utf8($rawheaders["subject"], $message->headers["subject"]);
$message->headers["subject"] = isset($message->headers["subject"]) ? Utils::convertRawHeader2Utf8($rawheaders["subject"], $message->headers["subject"]) : "";
$message->headers["from"] = Utils::convertRawHeader2Utf8($rawheaders["from"], $message->headers["from"]);
}
}
......
......@@ -989,11 +989,12 @@ class ZPushAdminCLI {
$synchedFolders = 0;
$synchedFolderTypes = array();
$syncedFoldersInProgress = 0;
$hc = $device->GetHierarchyCache();
foreach ($folders as $folderid) {
if ($device->GetFolderUUID($folderid)) {
$synchedFolders++;
$type = $device->GetFolderType($folderid);
$folder = $device->GetHierarchyCache()->GetFolder($folderid);
$folder = $hc->GetFolder($folderid);
$name = $folder ? $folder->displayname : "unknown";
switch($type) {
case SYNC_FOLDER_TYPE_APPOINTMENT:
......
......@@ -202,17 +202,17 @@ class Kopano extends ContactWorker {
continue;
}
// ignore ROOMS
elseif (isset($entry[PR_DISPLAY_TYPE_EX]) && $entry[PR_DISPLAY_TYPE_EX] & DT_ROOM) {
elseif (isset($entry[PR_DISPLAY_TYPE_EX]) && $entry[PR_DISPLAY_TYPE_EX] == DT_ROOM) {
$ignored++;
continue;
}
// ignore EQUIPMENT
elseif (isset($entry[PR_DISPLAY_TYPE_EX]) && $entry[PR_DISPLAY_TYPE_EX] & DT_EQUIPMENT) {
elseif (isset($entry[PR_DISPLAY_TYPE_EX]) && $entry[PR_DISPLAY_TYPE_EX] == DT_EQUIPMENT) {
$ignored++;
continue;
}
// ignore ORGANIZATION
elseif (isset($entry[PR_DISPLAY_TYPE_EX]) && $entry[PR_DISPLAY_TYPE_EX] & DT_ORGANIZATION) {
elseif (isset($entry[PR_DISPLAY_TYPE_EX]) && $entry[PR_DISPLAY_TYPE_EX] == DT_ORGANIZATION) {
$ignored++;
continue;
}
......
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