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); ...@@ -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' ,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_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_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 */ /* quota support */
define('PR_QUOTA_WARNING_THRESHOLD' ,mapi_prop_tag(PT_LONG, PR_EC_BASE+0x21)); define('PR_QUOTA_WARNING_THRESHOLD' ,mapi_prop_tag(PT_LONG, PR_EC_BASE+0x21));
......
...@@ -961,8 +961,9 @@ class BackendZarafa implements IBackend, ISearchProvider { ...@@ -961,8 +961,9 @@ class BackendZarafa implements IBackend, ISearchProvider {
if (!empty($hierarchyNotifications)) { if (!empty($hierarchyNotifications)) {
$hash = $this->getHierarchyHash(); $hash = $this->getHierarchyHash();
if ($hash !== $this->changesSinkHierarchyHash) { 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; $notifications[] = IBackend::HIERARCHYNOTIFICATION;
$this->changesSinkHierarchyHash = $hash;
} }
} }
return $notifications; return $notifications;
...@@ -1576,7 +1577,7 @@ class BackendZarafa implements IBackend, ISearchProvider { ...@@ -1576,7 +1577,7 @@ class BackendZarafa implements IBackend, ISearchProvider {
* @return void * @return void
*/ */
private function settingsOOFGEt(&$oof) { 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->oofstate = SYNC_SETTINGSOOF_DISABLED;
$oof->Status = SYNC_SETTINGSSTATUS_SUCCESS; $oof->Status = SYNC_SETTINGSSTATUS_SUCCESS;
if ($oofprops != false) { if ($oofprops != false) {
...@@ -1589,6 +1590,21 @@ class BackendZarafa implements IBackend, ISearchProvider { ...@@ -1589,6 +1590,21 @@ class BackendZarafa implements IBackend, ISearchProvider {
$oofmessage->bodytype = $oof->bodytype; $oofmessage->bodytype = $oof->bodytype;
unset($oofmessage->appliesToExternal, $oofmessage->appliesToExternalUnknown); unset($oofmessage->appliesToExternal, $oofmessage->appliesToExternalUnknown);
$oof->oofmessage[] = $oofmessage; $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 { else {
ZLog::Write(LOGLEVEL_WARN, "Unable to get out of office information"); ZLog::Write(LOGLEVEL_WARN, "Unable to get out of office information");
...@@ -1617,9 +1633,19 @@ class BackendZarafa implements IBackend, ISearchProvider { ...@@ -1617,9 +1633,19 @@ class BackendZarafa implements IBackend, ISearchProvider {
$props[PR_EC_OUTOFOFFICE_SUBJECT] = "Out of office"; $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) { elseif($oof->oofstate == SYNC_SETTINGSOOF_DISABLED) {
$props[PR_EC_OUTOFOFFICE] = false; $props[PR_EC_OUTOFOFFICE] = false;
$deleteProps = array(PR_EC_OUTOFOFFICE_FROM, PR_EC_OUTOFOFFICE_UNTIL);
} }
if (!empty($props)) { if (!empty($props)) {
...@@ -1631,6 +1657,10 @@ class BackendZarafa implements IBackend, ISearchProvider { ...@@ -1631,6 +1657,10 @@ class BackendZarafa implements IBackend, ISearchProvider {
} }
} }
if (!empty($deleteProps)) {
@mapi_deleteprops($this->defaultstore, $deleteProps);
}
return true; return true;
} }
......
...@@ -228,6 +228,12 @@ class ChangesMemoryWrapper extends HierarchyCache implements IImportChanges, IEx ...@@ -228,6 +228,12 @@ class ChangesMemoryWrapper extends HierarchyCache implements IImportChanges, IEx
return false; 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 // load this change into memory
$this->changes[] = array(self::CHANGE, $folder); $this->changes[] = array(self::CHANGE, $folder);
......
...@@ -129,15 +129,17 @@ class StateManager { ...@@ -129,15 +129,17 @@ class StateManager {
/** /**
* Returns a folder state (SyncParameters) for a folder id * 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 * @access public
* @return SyncParameters * @return SyncParameters
*/ */
public function GetSynchedFolderState($folderid) { public function GetSynchedFolderState($folderid, $fromCacheIfAvailable = true) {
// new SyncParameters are cached // new SyncParameters are cached
if (isset($this->synchedFolders[$folderid])) if ($fromCacheIfAvailable && isset($this->synchedFolders[$folderid])) {
return $this->synchedFolders[$folderid]; return $this->synchedFolders[$folderid];
}
$uuid = $this->device->GetFolderUUID($folderid); $uuid = $this->device->GetFolderUUID($folderid);
if ($uuid) { if ($uuid) {
......
...@@ -175,7 +175,7 @@ class SyncCollections implements Iterator { ...@@ -175,7 +175,7 @@ class SyncCollections implements Iterator {
try { try {
// Get SyncParameters for the folder from the state // 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 // TODO remove resync of folders for < Z-Push 2 beta4 users
// this forces a resync of all states previous to Z-Push 2 beta4 // this forces a resync of all states previous to Z-Push 2 beta4
...@@ -581,6 +581,8 @@ class SyncCollections implements Iterator { ...@@ -581,6 +581,8 @@ class SyncCollections implements Iterator {
foreach ($notifications as $folderid) { foreach ($notifications as $folderid) {
// Check hierarchy notifications // Check hierarchy notifications
if ($folderid === IBackend::HIERARCHYNOTIFICATION) { 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 // check received hierarchy notifications by exporting
if ($this->countHierarchyChange(true)) if ($this->countHierarchyChange(true))
throw new StatusException("SyncCollections->CheckForChanges(): HierarchySync required.", self::HIERARCHY_CHANGED); throw new StatusException("SyncCollections->CheckForChanges(): HierarchySync required.", self::HIERARCHY_CHANGED);
...@@ -718,6 +720,10 @@ class SyncCollections implements Iterator { ...@@ -718,6 +720,10 @@ class SyncCollections implements Iterator {
$changecount = false; $changecount = false;
if ($exportChanges || $this->hierarchyExporterChecked === false) { if ($exportChanges || $this->hierarchyExporterChecked === false) {
try { 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 // reset backend to the main store
ZPush::GetBackend()->Setup(false); ZPush::GetBackend()->Setup(false);
$changesMem = ZPush::GetDeviceManager()->GetHierarchyChangesWrapper(); $changesMem = ZPush::GetDeviceManager()->GetHierarchyChangesWrapper();
......
...@@ -904,11 +904,16 @@ class Utils { ...@@ -904,11 +904,16 @@ class Utils {
if(posix_getuid() == 0 && file_exists($file)) { if(posix_getuid() == 0 && file_exists($file)) {
$dir = dirname($file); $dir = dirname($file);
$perm_dir = stat($dir); $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]) { if ($perm_file['uid'] == 0 && $perm_dir['uid'] == 0) {
chown($file, $perm_dir[4]); unlink($file);
chgrp($file, $perm_dir[5]); 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; 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