Commit ea7f1b71 authored by Sebastian Kummer's avatar Sebastian Kummer

Merging in latest from upstream (ZP/z-push:refs/heads/develop)

* commit 'fc5bc5d3':
  ZP-842 Check if a folders parent ID is known on the mobile. If not, the folder is ignored and not synchronized to the device.
  ZP-844 Support Out-Of-Office start and end times.
  ZP-858 Ping fully reloads the hierarchy data before verifying hierarchy notifications, Ping has to wait before verifying to give other processes time to write all pending states.
  ZP-845 Improve Utils::FixFileOwner.
parents 004c6092 fc5bc5d3
......@@ -1135,6 +1135,8 @@ define('PR_EC_BASE' , 0x6700);
define('PR_EC_OUTOFOFFICE' ,mapi_prop_tag(PT_BOOLEAN, PR_EC_BASE+0x60));
define('PR_EC_OUTOFOFFICE_MSG' ,mapi_prop_tag(PT_STRING8, PR_EC_BASE+0x61));
define('PR_EC_OUTOFOFFICE_SUBJECT' ,mapi_prop_tag(PT_STRING8, PR_EC_BASE+0x62));
define('PR_EC_OUTOFOFFICE_FROM', mapi_prop_tag(PT_SYSTIME, PR_EC_BASE+0x63));
define('PR_EC_OUTOFOFFICE_UNTIL', mapi_prop_tag(PT_SYSTIME, PR_EC_BASE+0x64));
/* quota support */
define('PR_QUOTA_WARNING_THRESHOLD' ,mapi_prop_tag(PT_LONG, PR_EC_BASE+0x21));
......
......@@ -961,8 +961,9 @@ class BackendZarafa implements IBackend, ISearchProvider {
if (!empty($hierarchyNotifications)) {
$hash = $this->getHierarchyHash();
if ($hash !== $this->changesSinkHierarchyHash) {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendZarafa->ChangesSink() Hierarchy notification, pending validation. HierarchyHash: %s", $hash));
ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendZarafa->ChangesSink() Hierarchy notification, pending validation. New hierarchyHash: %s", $hash));
$notifications[] = IBackend::HIERARCHYNOTIFICATION;
$this->changesSinkHierarchyHash = $hash;
}
}
return $notifications;
......@@ -1576,7 +1577,7 @@ class BackendZarafa implements IBackend, ISearchProvider {
* @return void
*/
private function settingsOOFGEt(&$oof) {
$oofprops = mapi_getprops($this->defaultstore, array(PR_EC_OUTOFOFFICE, PR_EC_OUTOFOFFICE_MSG, PR_EC_OUTOFOFFICE_SUBJECT));
$oofprops = mapi_getprops($this->defaultstore, array(PR_EC_OUTOFOFFICE, PR_EC_OUTOFOFFICE_MSG, PR_EC_OUTOFOFFICE_SUBJECT, PR_EC_OUTOFOFFICE_FROM, PR_EC_OUTOFOFFICE_UNTIL));
$oof->oofstate = SYNC_SETTINGSOOF_DISABLED;
$oof->Status = SYNC_SETTINGSSTATUS_SUCCESS;
if ($oofprops != false) {
......@@ -1589,6 +1590,21 @@ class BackendZarafa implements IBackend, ISearchProvider {
$oofmessage->bodytype = $oof->bodytype;
unset($oofmessage->appliesToExternal, $oofmessage->appliesToExternalUnknown);
$oof->oofmessage[] = $oofmessage;
// check whether time based out of office is set
if ($oof->oofstate == SYNC_SETTINGSOOF_GLOBAL) {
if (isset($oofprops[PR_EC_OUTOFOFFICE_FROM]) && isset($oofprops[PR_EC_OUTOFOFFICE_UNTIL]) && ($oofprops[PR_EC_OUTOFOFFICE_FROM] < $oofprops[PR_EC_OUTOFOFFICE_UNTIL]) ) {
$oof->oofstate = SYNC_SETTINGSOOF_TIMEBASED;
$oof->starttime = $oofprops[PR_EC_OUTOFOFFICE_FROM];
$oof->endtime = $oofprops[PR_EC_OUTOFOFFICE_UNTIL];
}
elseif (isset($oofprops[PR_EC_OUTOFOFFICE_FROM]) || isset($oofprops[PR_EC_OUTOFOFFICE_UNTIL]) || ($oofprops[PR_EC_OUTOFOFFICE_FROM] > $oofprops[PR_EC_OUTOFOFFICE_UNTIL])) {
ZLog::Write(LOGLEVEL_WARN, sprintf("Zarafa->settingsOOFGEt(): Time based out of office set but either start time ('%s') or end time ('%s') is missing or end time is before startime.",
(isset($oofprops[PR_EC_OUTOFOFFICE_FROM]) ? date("Y-m-d H:i:s", $oofprops[PR_EC_OUTOFOFFICE_FROM]) : 'empty'),
(isset($oofprops[PR_EC_OUTOFOFFICE_UNTIL]) ? date("Y-m-d H:i:s", $oofprops[PR_EC_OUTOFOFFICE_UNTIL]) : 'empty')));
$oof->Status = SYNC_SETTINGSSTATUS_PROTOCOLLERROR;
}
}
}
else {
ZLog::Write(LOGLEVEL_WARN, "Unable to get out of office information");
......@@ -1617,9 +1633,19 @@ class BackendZarafa implements IBackend, ISearchProvider {
$props[PR_EC_OUTOFOFFICE_SUBJECT] = "Out of office";
}
}
if ($oof->oofstate == SYNC_SETTINGSOOF_TIMEBASED) {
if(isset($oof->starttime) && isset($oof->endtime)) {
$props[PR_EC_OUTOFOFFICE_FROM] = $oof->starttime;
$props[PR_EC_OUTOFOFFICE_UNTIL] = $oof->endtime;
}
elseif (isset($oof->starttime) || isset($oof->endtime)) {
$oof->Status = SYNC_SETTINGSSTATUS_PROTOCOLLERROR;
}
}
}
elseif($oof->oofstate == SYNC_SETTINGSOOF_DISABLED) {
$props[PR_EC_OUTOFOFFICE] = false;
$deleteProps = array(PR_EC_OUTOFOFFICE_FROM, PR_EC_OUTOFOFFICE_UNTIL);
}
if (!empty($props)) {
......@@ -1631,6 +1657,10 @@ class BackendZarafa implements IBackend, ISearchProvider {
}
}
if (!empty($deleteProps)) {
@mapi_deleteprops($this->defaultstore, $deleteProps);
}
return true;
}
......
......@@ -228,6 +228,12 @@ class ChangesMemoryWrapper extends HierarchyCache implements IImportChanges, IEx
return false;
}
// check if the parent ID is known on the device
if (!isset($folder->parentid) || $folder->parentid != "0" && !$this->GetFolder($folder->parentid)) {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("ChangesMemoryWrapper->ImportFolderChange(): Change for folder '%s' will not be sent as parent folder is not set or not known on mobile.", $folder->displayname));
return false;
}
// load this change into memory
$this->changes[] = array(self::CHANGE, $folder);
......
......@@ -129,15 +129,17 @@ class StateManager {
/**
* Returns a folder state (SyncParameters) for a folder id
*
* @param $folderid
* @param string $folderid
* @param boolean $fromCacheIfAvailable if set to false, the folderdata is always reloaded, default: true
*
* @access public
* @return SyncParameters
*/
public function GetSynchedFolderState($folderid) {
public function GetSynchedFolderState($folderid, $fromCacheIfAvailable = true) {
// new SyncParameters are cached
if (isset($this->synchedFolders[$folderid]))
if ($fromCacheIfAvailable && isset($this->synchedFolders[$folderid])) {
return $this->synchedFolders[$folderid];
}
$uuid = $this->device->GetFolderUUID($folderid);
if ($uuid) {
......
......@@ -175,7 +175,7 @@ class SyncCollections implements Iterator {
try {
// Get SyncParameters for the folder from the state
$spa = $this->stateManager->GetSynchedFolderState($folderid);
$spa = $this->stateManager->GetSynchedFolderState($folderid, !$loadState);
// TODO remove resync of folders for < Z-Push 2 beta4 users
// this forces a resync of all states previous to Z-Push 2 beta4
......@@ -581,6 +581,8 @@ class SyncCollections implements Iterator {
foreach ($notifications as $folderid) {
// Check hierarchy notifications
if ($folderid === IBackend::HIERARCHYNOTIFICATION) {
// wait two seconds before validating this notification, because it could potentially be made by the mobile and we need some time to update the states.
sleep(2);
// check received hierarchy notifications by exporting
if ($this->countHierarchyChange(true))
throw new StatusException("SyncCollections->CheckForChanges(): HierarchySync required.", self::HIERARCHY_CHANGED);
......@@ -718,6 +720,10 @@ class SyncCollections implements Iterator {
$changecount = false;
if ($exportChanges || $this->hierarchyExporterChecked === false) {
try {
// if this is a validation (not first run), make sure to load the hierarchy data again
if ($this->hierarchyExporterChecked === true && !$this->LoadCollection(false, true, false))
throw new StatusException("Invalid states found while re-loading hierarchy data.");
// reset backend to the main store
ZPush::GetBackend()->Setup(false);
$changesMem = ZPush::GetDeviceManager()->GetHierarchyChangesWrapper();
......
......@@ -904,11 +904,16 @@ class Utils {
if(posix_getuid() == 0 && file_exists($file)) {
$dir = dirname($file);
$perm_dir = stat($dir);
$perm_log = stat($file);
$perm_file = stat($file);
if($perm_dir[4] !== $perm_log[4] || $perm_dir[5] !== $perm_log[5]) {
chown($file, $perm_dir[4]);
chgrp($file, $perm_dir[5]);
if ($perm_file['uid'] == 0 && $perm_dir['uid'] == 0) {
unlink($file);
throw new FatalException("FixFileOwner: $dir must be owned by the nginx/apache/php user instead of root");
}
if($perm_dir['uid'] !== $perm_file['uid'] || $perm_dir['gid'] !== $perm_file['gid']) {
chown($file, $perm_dir['uid']);
chgrp($file, $perm_dir['gid']);
}
}
return true;
......
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