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 { ...@@ -797,10 +797,18 @@ class BackendCalDAV extends BackendDiff {
} }
} }
// Workaround #127 - No organizeremail defined if ($message->meetingstatus > 0) {
// No organizer was set for the meeting, assume it is the user
if (!isset($message->organizeremail)) { if (!isset($message->organizeremail)) {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendCalDAV->_ParseVEventToSyncObject(): No organizeremail defined, using username")); ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendCalDAV->_ParseVEventToSyncObject(): No organizeremail defined, using user details"));
$message->organizeremail = $this->originalUsername; $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")); $valarm = current($event->GetComponents("VALARM"));
...@@ -1081,32 +1089,37 @@ class BackendCalDAV extends BackendDiff { ...@@ -1081,32 +1089,37 @@ class BackendCalDAV extends BackendDiff {
$rtfparser->parse(); $rtfparser->parse();
$vevent->AddProperty("DESCRIPTION", $rtfparser->out); $vevent->AddProperty("DESCRIPTION", $rtfparser->out);
} }
$is_meeting = false; if (isset($data->meetingstatus) && $data->meetingstatus > 0) {
if (isset($data->meetingstatus)) {
switch ($data->meetingstatus) { switch ($data->meetingstatus) {
case "1": case "1":
$vevent->AddProperty("STATUS", "TENTATIVE"); $vevent->AddProperty("STATUS", "TENTATIVE");
$vevent->AddProperty("X-MICROSOFT-CDO-BUSYSTATUS", "TENTATIVE"); $vevent->AddProperty("X-MICROSOFT-CDO-BUSYSTATUS", "TENTATIVE");
$vevent->AddProperty("X-MICROSOFT-DISALLOW-COUNTER", "FALSE"); $vevent->AddProperty("X-MICROSOFT-DISALLOW-COUNTER", "FALSE");
$is_meeting = true;
break; break;
case "3": case "3":
$vevent->AddProperty("STATUS", "CONFIRMED"); $vevent->AddProperty("STATUS", "CONFIRMED");
$vevent->AddProperty("X-MICROSOFT-CDO-BUSYSTATUS", "CONFIRMED"); $vevent->AddProperty("X-MICROSOFT-CDO-BUSYSTATUS", "CONFIRMED");
$vevent->AddProperty("X-MICROSOFT-DISALLOW-COUNTER", "FALSE"); $vevent->AddProperty("X-MICROSOFT-DISALLOW-COUNTER", "FALSE");
$is_meeting = true;
break; break;
case "5": case "5":
case "7": case "7":
$vevent->AddProperty("STATUS", "CANCELLED"); $vevent->AddProperty("STATUS", "CANCELLED");
$vevent->AddProperty("X-MICROSOFT-CDO-BUSYSTATUS", "CANCELLED"); $vevent->AddProperty("X-MICROSOFT-CDO-BUSYSTATUS", "CANCELLED");
$vevent->AddProperty("X-MICROSOFT-DISALLOW-COUNTER", "TRUE"); $vevent->AddProperty("X-MICROSOFT-DISALLOW-COUNTER", "TRUE");
$is_meeting = true;
break; break;
} }
if (isset($data->organizeremail) && isset($data->organizername)) {
$vevent->AddProperty("ORGANIZER", sprintf("MAILTO:%s", $data->organizeremail), array("CN" => $data->organizername));
}
elseif (isset($data->organizeremail)) {
$vevent->AddProperty("ORGANIZER", sprintf("MAILTO:%s", $data->organizeremail));
}
else {
//Some phones doesn't send the organizeremail, so we gotto get it somewhere else.
$userDetails = ZPush::GetBackend()->GetCurrentUsername();
$vevent->AddProperty("ORGANIZER", sprintf("MAILTO:%s", $userDetails['emailaddress']), array("CN" => $userDetails['fullname']));
} }
if (isset($data->attendees) && is_array($data->attendees)) { if (isset($data->attendees) && is_array($data->attendees)) {
$is_meeting = true;
foreach ($data->attendees as $att) { foreach ($data->attendees as $att) {
if (isset($att->name)) { if (isset($att->name)) {
$vevent->AddProperty("ATTENDEE", sprintf("MAILTO:%s", $att->email), array("CN" => $att->name)); $vevent->AddProperty("ATTENDEE", sprintf("MAILTO:%s", $att->email), array("CN" => $att->name));
...@@ -1116,18 +1129,6 @@ class BackendCalDAV extends BackendDiff { ...@@ -1116,18 +1129,6 @@ class BackendCalDAV extends BackendDiff {
} }
} }
} }
if ($is_meeting) {
if (isset($data->organizeremail) && isset($data->organizername)) {
$vevent->AddProperty("ORGANIZER", sprintf("MAILTO:%s", $data->organizeremail), array("CN" => $data->organizername));
}
elseif (isset($data->organizeremail)) {
$vevent->AddProperty("ORGANIZER", sprintf("MAILTO:%s", $data->organizeremail));
}
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));
}
} }
if (isset($data->body) && strlen($data->body) > 0) { if (isset($data->body) && strlen($data->body) > 0) {
$vevent->AddProperty("DESCRIPTION", $data->body); $vevent->AddProperty("DESCRIPTION", $data->body);
......
...@@ -666,4 +666,22 @@ class BackendCombined extends Backend implements ISearchProvider { ...@@ -666,4 +666,22 @@ class BackendCombined extends Backend implements ISearchProvider {
return false; 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', ''); ...@@ -139,6 +139,7 @@ define('IMAP_FROM_SQL_PASSWORD', '');
define('IMAP_FROM_SQL_OPTIONS', serialize(array(PDO::ATTR_PERSISTENT => true))); 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_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_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_FROM', '#first_name #last_name <#mail_address>');
define('IMAP_FROM_SQL_FULLNAME', '#first_name #last_name'); define('IMAP_FROM_SQL_FULLNAME', '#first_name #last_name');
...@@ -156,6 +157,7 @@ define('IMAP_FROM_LDAP_PASSWORD', 'password'); ...@@ -156,6 +157,7 @@ define('IMAP_FROM_LDAP_PASSWORD', 'password');
define('IMAP_FROM_LDAP_BASE', 'dc=zpush,dc=org'); define('IMAP_FROM_LDAP_BASE', 'dc=zpush,dc=org');
define('IMAP_FROM_LDAP_QUERY', '(mail=#username@#domain)'); define('IMAP_FROM_LDAP_QUERY', '(mail=#username@#domain)');
define('IMAP_FROM_LDAP_FIELDS', serialize(array('givenname', 'sn', 'mail'))); 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_FROM', '#givenname #sn <#mail>');
define('IMAP_FROM_LDAP_FULLNAME', '#givenname #sn'); define('IMAP_FROM_LDAP_FULLNAME', '#givenname #sn');
...@@ -208,3 +210,8 @@ define('SYSTEM_MIME_TYPES_MAPPING', '/etc/mime.types'); ...@@ -208,3 +210,8 @@ define('SYSTEM_MIME_TYPES_MAPPING', '/etc/mime.types');
// Use BackendCalDAV for Meetings. You cannot hope to get that functionality working without a caldav backend. // Use BackendCalDAV for Meetings. You cannot hope to get that functionality working without a caldav backend.
define('IMAP_MEETING_USE_CALDAV', false); 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 { ...@@ -52,6 +52,7 @@ class BackendIMAP extends BackendDiff implements ISearchProvider {
private $folderhierarchy; private $folderhierarchy;
private $excludedFolders; private $excludedFolders;
private static $mimeTypes = false; private static $mimeTypes = false;
private $imapParams = array();
public function __construct() { public function __construct() {
...@@ -68,6 +69,10 @@ class BackendIMAP extends BackendDiff implements ISearchProvider { ...@@ -68,6 +69,10 @@ class BackendIMAP extends BackendDiff implements ISearchProvider {
if (!function_exists("mb_detect_order")) { 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")); 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 { ...@@ -105,7 +110,7 @@ class BackendIMAP extends BackendDiff implements ISearchProvider {
/* END fmbiete's contribution r1527, ZP-319 */ /* END fmbiete's contribution r1527, ZP-319 */
// open the IMAP-mailbox // 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 = ""; $this->mboxFolder = "";
if ($this->mbox) { if ($this->mbox) {
...@@ -1755,10 +1760,9 @@ class BackendIMAP extends BackendDiff implements ISearchProvider { ...@@ -1755,10 +1760,9 @@ class BackendIMAP extends BackendDiff implements ISearchProvider {
* @return Array * @return Array
*/ */
public function GetUserDetails($username) { 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; $email = $username;
if (strpos($username, "@") === false && strlen($this->domain) > 0) { if (!USE_FULLEMAIL_FOR_LOGIN) {
$email .= "@" . $this->domain; $email = getDefaultEmailValue($username, $this->domain);
} }
return array('emailaddress' => $email, 'fullname' => getDefaultFullNameValue($username, $this->domain)); return array('emailaddress' => $email, 'fullname' => getDefaultFullNameValue($username, $this->domain));
} }
...@@ -2224,7 +2228,7 @@ class BackendIMAP extends BackendDiff implements ISearchProvider { ...@@ -2224,7 +2228,7 @@ class BackendIMAP extends BackendDiff implements ISearchProvider {
imap_ping($this->mbox); imap_ping($this->mbox);
} }
else { 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 = ""; $this->mboxFolder = "";
} }
} }
......
...@@ -23,6 +23,40 @@ ...@@ -23,6 +23,40 @@
* Consult LICENSE file for details * 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" * Returns the default value for "From"
* *
...@@ -206,15 +240,15 @@ function getIdentityFromPasswd($username, $domain, $identity, $encode = true) { ...@@ -206,15 +240,15 @@ function getIdentityFromPasswd($username, $domain, $identity, $encode = true) {
$tmp = $local_user['gecos']; $tmp = $local_user['gecos'];
$tmp = explode(',', $tmp); $tmp = explode(',', $tmp);
$name = $tmp[0]; $name = $tmp[0];
$email = $tmp[1];
unset($tmp); unset($tmp);
switch ($identity) { switch ($identity) {
case 'EMAIL':
$ret_value = sprintf("%s", $email);
break;
case 'FROM': case 'FROM':
if (strlen($domain) > 0) { $ret_value = sprintf("%s <%s>", $name, $email);
$ret_value = sprintf("%s <%s@%s>", $name, $username, $domain);
} else {
ZLog::Write(LOGLEVEL_WARN, sprintf("BackendIMAP->getIdentityFromPasswd() - No domain passed. Cannot construct From address."));
}
break; break;
case 'FULLNAME': case 'FULLNAME':
$ret_value = sprintf("%s", $name); $ret_value = sprintf("%s", $name);
......
...@@ -167,9 +167,46 @@ class PHPWrapper { ...@@ -167,9 +167,46 @@ class PHPWrapper {
*/ */
public function ImportMessageDeletion($flags, $sourcekeys) { public function ImportMessageDeletion($flags, $sourcekeys) {
$amount = count($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); 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 { else {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("PHPWrapper->ImportMessageDeletion(): Received %d remove requests from ICS", $amount)); ZLog::Write(LOGLEVEL_DEBUG, sprintf("PHPWrapper->ImportMessageDeletion(): Received %d remove requests from ICS", $amount));
} }
......
...@@ -1637,13 +1637,13 @@ class MAPIProvider { ...@@ -1637,13 +1637,13 @@ class MAPIProvider {
$pic = mapi_message_createattach($mapimessage); $pic = mapi_message_createattach($mapimessage);
// Set properties of the attachment // Set properties of the attachment
$picprops = array( $picprops = array(
PR_ATTACH_LONG_FILENAME_A => "ContactPicture.jpg", PR_ATTACH_LONG_FILENAME => "ContactPicture.jpg",
PR_DISPLAY_NAME => "ContactPicture.jpg", PR_DISPLAY_NAME => "ContactPicture.jpg",
0x7FFF000B => true, 0x7FFF000B => true,
PR_ATTACHMENT_HIDDEN => false, PR_ATTACHMENT_HIDDEN => false,
PR_ATTACHMENT_FLAGS => 1, PR_ATTACHMENT_FLAGS => 1,
PR_ATTACH_METHOD => ATTACH_BY_VALUE, PR_ATTACH_METHOD => ATTACH_BY_VALUE,
PR_ATTACH_EXTENSION_A => ".jpg", PR_ATTACH_EXTENSION => ".jpg",
PR_ATTACH_NUM => 1, PR_ATTACH_NUM => 1,
PR_ATTACH_SIZE => $picsize, PR_ATTACH_SIZE => $picsize,
PR_ATTACH_DATA_BIN => $picbinary, PR_ATTACH_DATA_BIN => $picbinary,
......
...@@ -393,11 +393,11 @@ class MAPIUtils { ...@@ -393,11 +393,11 @@ class MAPIUtils {
$stream = mapi_openproperty($message, $prop, IID_IStream, 0, 0); $stream = mapi_openproperty($message, $prop, IID_IStream, 0, 0);
$ret = mapi_last_hresult(); $ret = mapi_last_hresult();
if ($ret == MAPI_E_NOT_FOUND) { 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 ""; return "";
} }
elseif ($ret) { 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 ""; return "";
} }
$data = ""; $data = "";
......
...@@ -520,6 +520,16 @@ class ReplyBackImExporter implements IImportChanges, IExportChanges { ...@@ -520,6 +520,16 @@ class ReplyBackImExporter implements IImportChanges, IExportChanges {
$foldername = $folders[$folderid]->displayname; $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 // get the differences between the two objects
$data = substr(get_class($oldmessage), 4) . "\r\n"; $data = substr(get_class($oldmessage), 4) . "\r\n";
// get the suppported fields as we need them to determine the ghosted properties // get the suppported fields as we need them to determine the ghosted properties
......
...@@ -538,7 +538,7 @@ class Mail_mimeDecode ...@@ -538,7 +538,7 @@ class Mail_mimeDecode
$hdr_name = substr($value, 0, $pos = strpos($value, ':')); $hdr_name = substr($value, 0, $pos = strpos($value, ':'));
$hdr_value = substr($value, $pos+1); $hdr_value = substr($value, $pos+1);
if($hdr_value[0] == ' ') { if(strlen($hdr_value) && $hdr_value[0] == ' ') {
$hdr_value = substr($hdr_value, 1); $hdr_value = substr($hdr_value, 1);
} }
......
...@@ -1278,4 +1278,14 @@ class DeviceManager { ...@@ -1278,4 +1278,14 @@ class DeviceManager {
} }
return $folder; return $folder;
} }
/**
* Returns the device id.
*
* @access public
* @return string
*/
public function GetDevid() {
return $this->devid;
}
} }
...@@ -289,6 +289,21 @@ class ZPush { ...@@ -289,6 +289,21 @@ class ZPush {
if (defined('USE_X_FORWARDED_FOR_HEADER')) { 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."); 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; return true;
} }
......
...@@ -65,7 +65,7 @@ abstract class SyncObject extends Streamer { ...@@ -65,7 +65,7 @@ abstract class SyncObject extends Streamer {
public function emptySupported($supportedFields) { public function emptySupported($supportedFields) {
// Some devices do not send supported tag. In such a case remove all not set properties. // 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 (($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))); ZLog::Write(LOGLEVEL_INFO, sprintf("%s->emptySupported(): no supported list available, emptying all not set parameters", get_class($this)));
$supportedFields = array_keys($this->mapping); $supportedFields = array_keys($this->mapping);
} }
......
...@@ -894,14 +894,15 @@ class Utils { ...@@ -894,14 +894,15 @@ class Utils {
$perm_dir = stat($dir); $perm_dir = stat($dir);
$perm_file = stat($file); $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); 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']) { if($perm_dir['uid'] !== $perm_file['uid'] || $perm_dir['gid'] !== $perm_file['gid']) {
chown($file, $perm_dir['uid']); chown($file, $perm_dir['uid']);
chgrp($file, $perm_dir['gid']); chgrp($file, $perm_dir['gid']);
chmod($file, 0664);
} }
} }
return true; return true;
...@@ -1361,7 +1362,7 @@ class Utils { ...@@ -1361,7 +1362,7 @@ class Utils {
if (!$rawheaders) { if (!$rawheaders) {
return; 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"]); $message->headers["from"] = Utils::convertRawHeader2Utf8($rawheaders["from"], $message->headers["from"]);
} }
} }
......
...@@ -989,11 +989,12 @@ class ZPushAdminCLI { ...@@ -989,11 +989,12 @@ class ZPushAdminCLI {
$synchedFolders = 0; $synchedFolders = 0;
$synchedFolderTypes = array(); $synchedFolderTypes = array();
$syncedFoldersInProgress = 0; $syncedFoldersInProgress = 0;
$hc = $device->GetHierarchyCache();
foreach ($folders as $folderid) { foreach ($folders as $folderid) {
if ($device->GetFolderUUID($folderid)) { if ($device->GetFolderUUID($folderid)) {
$synchedFolders++; $synchedFolders++;
$type = $device->GetFolderType($folderid); $type = $device->GetFolderType($folderid);
$folder = $device->GetHierarchyCache()->GetFolder($folderid); $folder = $hc->GetFolder($folderid);
$name = $folder ? $folder->displayname : "unknown"; $name = $folder ? $folder->displayname : "unknown";
switch($type) { switch($type) {
case SYNC_FOLDER_TYPE_APPOINTMENT: case SYNC_FOLDER_TYPE_APPOINTMENT:
......
...@@ -202,17 +202,17 @@ class Kopano extends ContactWorker { ...@@ -202,17 +202,17 @@ class Kopano extends ContactWorker {
continue; continue;
} }
// ignore ROOMS // 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++; $ignored++;
continue; continue;
} }
// ignore EQUIPMENT // 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++; $ignored++;
continue; continue;
} }
// ignore ORGANIZATION // 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++; $ignored++;
continue; 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