Commit ae73cd3f authored by Sebastian Kummer's avatar Sebastian Kummer

Merge branch 'develop' into bugfix/ZP-1085-update-trademark

parents 6797670b bc817b64
...@@ -158,7 +158,7 @@ class BackendKopano implements IBackend, ISearchProvider { ...@@ -158,7 +158,7 @@ class BackendKopano implements IBackend, ISearchProvider {
if (mapi_last_hresult()) { if (mapi_last_hresult()) {
ZLog::Write(LOGLEVEL_ERROR, sprintf("KopanoBackend->Logon(): login failed with error code: 0x%X", mapi_last_hresult())); ZLog::Write(LOGLEVEL_ERROR, sprintf("KopanoBackend->Logon(): login failed with error code: 0x%X", mapi_last_hresult()));
if (mapi_last_hresult() == MAPI_E_NETWORK_ERROR) if (mapi_last_hresult() == MAPI_E_NETWORK_ERROR)
throw new HTTPReturnCodeException("Error connecting to KC (login)", 503, null, LOGLEVEL_INFO); throw new ServiceUnavailableException("Error connecting to KC (login)");
} }
} }
catch (MAPIException $ex) { catch (MAPIException $ex) {
...@@ -175,7 +175,7 @@ class BackendKopano implements IBackend, ISearchProvider { ...@@ -175,7 +175,7 @@ class BackendKopano implements IBackend, ISearchProvider {
$this->defaultstore = $this->openMessageStore($this->mainUser); $this->defaultstore = $this->openMessageStore($this->mainUser);
if (mapi_last_hresult() == MAPI_E_FAILONEPROVIDER) if (mapi_last_hresult() == MAPI_E_FAILONEPROVIDER)
throw new HTTPReturnCodeException("Error connecting to KC (open store)", 503, null, LOGLEVEL_INFO); throw new ServiceUnavailableException("Error connecting to KC (open store)");
if($this->defaultstore === false) if($this->defaultstore === false)
throw new AuthenticationRequiredException(sprintf("KopanoBackend->Logon(): User '%s' has no default store", $user)); throw new AuthenticationRequiredException(sprintf("KopanoBackend->Logon(): User '%s' has no default store", $user));
......
...@@ -254,6 +254,14 @@ ...@@ -254,6 +254,14 @@
define('SYNC_TIMEOUT_MEDIUM_DEVICETYPES', "SAMSUNGGTI"); define('SYNC_TIMEOUT_MEDIUM_DEVICETYPES', "SAMSUNGGTI");
define('SYNC_TIMEOUT_LONG_DEVICETYPES', "iPod, iPad, iPhone, WP, WindowsOutlook"); define('SYNC_TIMEOUT_LONG_DEVICETYPES', "iPod, iPad, iPhone, WP, WindowsOutlook");
// Time in seconds the device should wait whenever the service is unavailable,
// e.g. when a backend service is unavailable.
// Z-Push sends a "Retry-After" header in the response with the here defined value.
// It is up to the device to respect or not this directive so even if this option is set,
// the device might not wait requested time frame.
// Number of seconds before retry, to disable set to: false
define('RETRY_AFTER_DELAY', 300);
/********************************************************************************** /**********************************************************************************
* Backend settings * Backend settings
*/ */
......
...@@ -923,11 +923,13 @@ class ASDevice extends StateObject { ...@@ -923,11 +923,13 @@ class ASDevice extends StateObject {
* @param string $folderid the folder id of the additional folder. * @param string $folderid the folder id of the additional folder.
* @param string $name the name of the additional folder (has to be unique for all folders on the device). * @param string $name the name of the additional folder (has to be unique for all folders on the device).
* @param int $flags Additional flags, like DeviceManager::FLD_FLAGS_REPLYASUSER * @param int $flags Additional flags, like DeviceManager::FLD_FLAGS_REPLYASUSER
* @param string $parentid the parentid of this folder.
* @param boolean $checkDups indicates if duplicate names and ids should be verified. Default: true
* *
* @access public * @access public
* @return boolean * @return boolean
*/ */
public function EditAdditionalFolder($folderid, $name, $flags) { public function EditAdditionalFolder($folderid, $name, $flags, $parentid = 0, $checkDups = true) {
// check if a folderid and name were sent // check if a folderid and name were sent
if (!$folderid || !$name) { if (!$folderid || !$name) {
ZLog::Write(LOGLEVEL_ERROR, sprintf("ASDevice->EditAdditionalFolder(): No valid folderid ('%s') or name ('%s') sent. Aborting. ", $folderid, $name)); ZLog::Write(LOGLEVEL_ERROR, sprintf("ASDevice->EditAdditionalFolder(): No valid folderid ('%s') or name ('%s') sent. Aborting. ", $folderid, $name));
...@@ -949,11 +951,15 @@ class ASDevice extends StateObject { ...@@ -949,11 +951,15 @@ class ASDevice extends StateObject {
} }
// check if a folder with the new name is already known on the device (regular folder) // check if a folder with the new name is already known on the device (regular folder)
foreach($this->GetHierarchyCache()->ExportFolders() as $syncedFolderid => $folder) { if ($checkDups) {
// $folder is a SyncFolder object here // in order to check for the parent-ids we need a shortid
if ($folder->displayname == $name && $folderid !== $folder->BackendId && $folderid !== $syncedFolderid) { $parentShortId = $this->GetFolderIdForBackendId($parentid, false, null, null);
ZLog::Write(LOGLEVEL_ERROR, sprintf("ASDevice->EditAdditionalFolder(): folder can not be edited because there is already a folder with the same name synchronized: '%s'", $folderid)); foreach($this->GetHierarchyCache()->ExportFolders() as $syncedFolderid => $folder) {
return false; // $folder is a SyncFolder object here
if ($folder->displayname == $name && $folderid !== $folder->BackendId && $folderid !== $syncedFolderid && ($folder->parentid == $parentid || $folder->parentid == $parentShortId)) {
ZLog::Write(LOGLEVEL_ERROR, sprintf("ASDevice->EditAdditionalFolder(): folder can not be edited because there is already a folder with the same name synchronized: '%s'", $folderid));
return false;
}
} }
} }
...@@ -961,6 +967,7 @@ class ASDevice extends StateObject { ...@@ -961,6 +967,7 @@ class ASDevice extends StateObject {
$af = $this->additionalfolders; $af = $this->additionalfolders;
$af[$folderid]['name'] = $name; $af[$folderid]['name'] = $name;
$af[$folderid]['flags'] = $flags; $af[$folderid]['flags'] = $flags;
$af[$folderid]['parentid'] = $parentid;
$this->additionalfolders = $af; $this->additionalfolders = $af;
return true; return true;
......
...@@ -422,11 +422,16 @@ class SyncCollections implements Iterator { ...@@ -422,11 +422,16 @@ class SyncCollections implements Iterator {
* previousily set or saved in a collection * previousily set or saved in a collection
* *
* @access public * @access public
* @return int returns 600 as default if nothing set or not available * @return int returns PING_HIGHER_BOUND_LIFETIME as default if nothing set or not available.
* If PING_HIGHER_BOUND_LIFETIME is not set, returns 600.
*/ */
public function GetLifetime() { public function GetLifetime() {
if (!isset( $this->refLifetime) || $this->refLifetime === false) if (!isset($this->refLifetime) || $this->refLifetime === false) {
if (PING_HIGHER_BOUND_LIFETIME !== false) {
return PING_HIGHER_BOUND_LIFETIME;
}
return 600; return 600;
}
return $this->refLifetime; return $this->refLifetime;
} }
...@@ -717,7 +722,6 @@ class SyncCollections implements Iterator { ...@@ -717,7 +722,6 @@ class SyncCollections implements Iterator {
*/ */
private function countHierarchyChange($exportChanges = false) { private function countHierarchyChange($exportChanges = false) {
$folderid = false; $folderid = false;
$spa = $this->GetCollection($folderid);
// Check with device manager if the hierarchy should be reloaded. // Check with device manager if the hierarchy should be reloaded.
// New additional folders are loaded here. // New additional folders are loaded here.
......
...@@ -325,6 +325,13 @@ class ZPush { ...@@ -325,6 +325,13 @@ class ZPush {
throw new FatalMisconfigurationException("The PING_HIGHER_BOUND_LIFETIME value must be greater or equal to PING_LOWER_BOUND_LIFETIME."); throw new FatalMisconfigurationException("The PING_HIGHER_BOUND_LIFETIME value must be greater or equal to PING_LOWER_BOUND_LIFETIME.");
} }
if (!defined('RETRY_AFTER_DELAY')) {
define('RETRY_AFTER_DELAY', 300);
}
elseif (RETRY_AFTER_DELAY !== false && (!is_int(RETRY_AFTER_DELAY) || RETRY_AFTER_DELAY < 1)) {
throw new FatalMisconfigurationException("The RETRY_AFTER_DELAY value must be 'false' or a number greater than 0.");
}
// Check KOE flags // Check KOE flags
if (!defined('KOE_CAPABILITY_GAB')) { if (!defined('KOE_CAPABILITY_GAB')) {
define('KOE_CAPABILITY_GAB', false); define('KOE_CAPABILITY_GAB', false);
...@@ -437,7 +444,7 @@ class ZPush { ...@@ -437,7 +444,7 @@ class ZPush {
if (ZPush::$stateMachine->GetStateVersion() !== ZPush::GetLatestStateVersion()) { if (ZPush::$stateMachine->GetStateVersion() !== ZPush::GetLatestStateVersion()) {
if (class_exists("TopCollector")) self::GetTopCollector()->AnnounceInformation("Run migration script!", true); if (class_exists("TopCollector")) self::GetTopCollector()->AnnounceInformation("Run migration script!", true);
throw new HTTPReturnCodeException(sprintf("The state version available to the %s is not the latest version - please run the state upgrade script. See release notes for more information.", get_class(ZPush::$stateMachine), 503)); throw new ServiceUnavailableException(sprintf("The state version available to the %s is not the latest version - please run the state upgrade script. See release notes for more information.", get_class(ZPush::$stateMachine)));
} }
} }
return ZPush::$stateMachine; return ZPush::$stateMachine;
......
...@@ -984,6 +984,7 @@ define("HTTP_CODE_200", 200); ...@@ -984,6 +984,7 @@ define("HTTP_CODE_200", 200);
define("HTTP_CODE_401", 401); define("HTTP_CODE_401", 401);
define("HTTP_CODE_449", 449); define("HTTP_CODE_449", 449);
define("HTTP_CODE_500", 500); define("HTTP_CODE_500", 500);
define("HTTP_CODE_503", 503);
define("WINDOW_SIZE_MAX", 512); define("WINDOW_SIZE_MAX", 512);
......
<?php
/***********************************************
* File : serviceunavailableexception.php
* Project : Z-Push
* Descr : Exception sending a '503 Service Unavailable' to the mobile.
*
* Created : 09.08.2016
*
* Copyright 2007 - 2016 Zarafa Deutschland GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation with the following additional
* term according to sec. 7:
*
* According to sec. 7 of the GNU Affero General Public License, version 3,
* the terms of the AGPL are supplemented with the following terms:
*
* "Zarafa" is a registered trademark of Zarafa B.V.
* "Z-Push" is a registered trademark of Zarafa Deutschland GmbH
* The licensing of the Program under the AGPL does not imply a trademark license.
* Therefore any rights, title and interest in our trademarks remain entirely with us.
*
* However, if you propagate an unmodified version of the Program you are
* allowed to use the term "Z-Push" to indicate that you distribute the Program.
* Furthermore you may use our trademarks where it is necessary to indicate
* the intended purpose of a product or service provided you use it in accordance
* with honest practices in industrial or commercial matters.
* If you want to propagate modified versions of the Program under the name "Z-Push",
* you may only do so if you have a written permission by Zarafa Deutschland GmbH
* (to acquire a permission please contact Zarafa at trademark@zarafa.com).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Consult LICENSE file for details
************************************************/
class ServiceUnavailableException extends HTTPReturnCodeException {
protected $defaultLogLevel = LOGLEVEL_INFO;
protected $httpReturnCode = HTTP_CODE_503;
protected $httpReturnMessage = "Service Unavailable";
protected $httpHeaders = array();
protected $showLegal = false;
public function __construct($message = "", $code = 0, $previous = NULL, $logLevel = false) {
parent::__construct($message, $code, $previous, $logLevel);
if (RETRY_AFTER_DELAY !== false) {
$this->httpHeaders[] = 'Retry-After: ' . RETRY_AFTER_DELAY;
}
}
}
\ No newline at end of file
...@@ -290,7 +290,7 @@ class Search extends RequestProcessor { ...@@ -290,7 +290,7 @@ class Search extends RequestProcessor {
} }
$searchprovider->Disconnect(); $searchprovider->Disconnect();
self::$topCollector->AnnounceInformation(sprintf("'%s' search found %d results", $searchname, $rows['searchtotal']), true); self::$topCollector->AnnounceInformation(sprintf("'%s' search found %d results", $searchname, (isset($rows['searchtotal']) ? $rows['searchtotal'] : 0) ), true);
self::$encoder->startWBXML(); self::$encoder->startWBXML();
self::$encoder->startTag(SYNC_SEARCH_SEARCH); self::$encoder->startTag(SYNC_SEARCH_SEARCH);
......
...@@ -34,7 +34,6 @@ class SendMail extends RequestProcessor { ...@@ -34,7 +34,6 @@ class SendMail extends RequestProcessor {
* @return boolean * @return boolean
*/ */
public function Handle($commandCode) { public function Handle($commandCode) {
$status = SYNC_COMMONSTATUS_SUCCESS;
$sm = new SyncSendMail(); $sm = new SyncSendMail();
$reply = $forward = $parent = $sendmail = $smartreply = $smartforward = false; $reply = $forward = $parent = $sendmail = $smartreply = $smartforward = false;
...@@ -123,6 +122,7 @@ class SendMail extends RequestProcessor { ...@@ -123,6 +122,7 @@ class SendMail extends RequestProcessor {
self::$topCollector->AnnounceInformation(sprintf("SendMail(): Sending email with %d bytes", strlen($sm->mime)), true); self::$topCollector->AnnounceInformation(sprintf("SendMail(): Sending email with %d bytes", strlen($sm->mime)), true);
$statusMessage = '';
try { try {
$status = self::$backend->SendMail($sm); $status = self::$backend->SendMail($sm);
} }
......
...@@ -115,14 +115,16 @@ class ZPushAdmin { ...@@ -115,14 +115,16 @@ class ZPushAdmin {
if ($fstatus !== false && isset($fstatus[ASDevice::FOLDERSYNCSTATUS])) { if ($fstatus !== false && isset($fstatus[ASDevice::FOLDERSYNCSTATUS])) {
$spa = $sc->GetCollection($folderid); $spa = $sc->GetCollection($folderid);
$total = $spa->GetFolderSyncTotal(); if ($spa) {
$todo = $spa->GetFolderSyncRemaining(); $total = $spa->GetFolderSyncTotal();
$fstatus['status'] = ($fstatus[ASDevice::FOLDERSYNCSTATUS] == 1)?'Initialized':'Synchronizing'; $todo = $spa->GetFolderSyncRemaining();
$fstatus['total'] = $total; $fstatus['status'] = ($fstatus[ASDevice::FOLDERSYNCSTATUS] == 1) ? 'Initialized' : 'Synchronizing';
$fstatus['done'] = $total - $todo; $fstatus['total'] = $total;
$fstatus['todo'] = $todo; $fstatus['done'] = $total - $todo;
$fstatus['todo'] = $todo;
$device->SetFolderSyncStatus($folderid, $fstatus);
$device->SetFolderSyncStatus($folderid, $fstatus);
}
} }
} }
} }
...@@ -959,17 +961,17 @@ class ZPushAdmin { ...@@ -959,17 +961,17 @@ class ZPushAdmin {
} }
/** /**
* Fixes potentially missing flags on additional folders. * Fixes missing flags or parentids on additional folders.
* *
* @access public * @access public
* @return array(seenDevices, devicesWithAdditionalFolders, fixedAdditionalFolders) * @return array(seenDevices, devicesWithAdditionalFolders, fixedAdditionalFolders)
*/ */
static public function FixStatesAdditionalFolderFlags() { static public function FixStatesAdditionalFolders() {
$devices = 0; $devices = 0;
$devicesWithAddFolders = 0; $devicesWithAddFolders = 0;
$fixed = 0; $fixed = 0;
$asdevices = ZPush::GetStateMachine()->GetAllDevices(false); $asdevices = ZPush::GetStateMachine()->GetAllDevices(false);
ZLog::Write(LOGLEVEL_DEBUG, sprintf("ZPushAdmin::FixStatesAdditionalFolderFlags(): found %d devices", count($asdevices))); ZLog::Write(LOGLEVEL_DEBUG, sprintf("ZPushAdmin::FixStatesAdditionalFolders(): found %d devices", count($asdevices)));
foreach ($asdevices as $devid) { foreach ($asdevices as $devid) {
try { try {
...@@ -986,8 +988,14 @@ class ZPushAdmin { ...@@ -986,8 +988,14 @@ class ZPushAdmin {
if ($addFolders) { if ($addFolders) {
$devicesWithAddFolders++; $devicesWithAddFolders++;
foreach($addFolders as $df) { foreach($addFolders as $df) {
if (!isset($df['flags'])) { if (!isset($df['flags']) || !isset($df['parentid']) ) {
$device->EditAdditionalFolder($df['folderid'], $df['name'], 0); if (!isset($df['flags'])) {
$df['flags'] = 0;
}
if (!isset($df['parentid'])) {
$df['parentid'] = 0;
}
$device->EditAdditionalFolder($df['folderid'], $df['name'], $df['flags'], $df['parentid']);
$needsFixing = true; $needsFixing = true;
} }
} }
...@@ -998,12 +1006,12 @@ class ZPushAdmin { ...@@ -998,12 +1006,12 @@ class ZPushAdmin {
} }
if ($needsFixing) { if ($needsFixing) {
ZPush::GetStateMachine()->SetState($devicedata, $devid, IStateMachine::DEVICEDATA); ZPush::GetStateMachine()->SetState($devicedata, $devid, IStateMachine::DEVICEDATA);
ZLog::Write(LOGLEVEL_DEBUG, sprintf("ZPushAdmin::FixStatesAdditionalFolderFlags(): updated device '%s' because flags were fixed", $devid)); ZLog::Write(LOGLEVEL_DEBUG, sprintf("ZPushAdmin::FixStatesAdditionalFolders(): updated device '%s' because flags or parentids were fixed", $devid));
$fixed++; $fixed++;
} }
} }
catch (StateNotFoundException $e) { catch (StateNotFoundException $e) {
ZLog::Write(LOGLEVEL_ERROR, sprintf("ZPushAdmin::FixStatesAdditionalFolderFlags(): state for device '%s' can not be found", $devid)); ZLog::Write(LOGLEVEL_ERROR, sprintf("ZPushAdmin::FixStatesAdditionalFolders(): state for device '%s' can not be found", $devid));
} }
} }
return array($devices, $devicesWithAddFolders, $fixed); return array($devices, $devicesWithAddFolders, $fixed);
......
...@@ -112,6 +112,7 @@ return array( ...@@ -112,6 +112,7 @@ return array(
'Search' => $baseDir . '/lib/request/search.php', 'Search' => $baseDir . '/lib/request/search.php',
'SearchProvider' => $baseDir . '/lib/default/searchprovider.php', 'SearchProvider' => $baseDir . '/lib/default/searchprovider.php',
'SendMail' => $baseDir . '/lib/request/sendmail.php', 'SendMail' => $baseDir . '/lib/request/sendmail.php',
'ServiceUnavailableException' => $baseDir . '/lib/exceptions/serviceunavailableexception.php',
'Settings' => $baseDir . '/lib/request/settings.php', 'Settings' => $baseDir . '/lib/request/settings.php',
'SimpleMutex' => $baseDir . '/lib/default/simplemutex.php', 'SimpleMutex' => $baseDir . '/lib/default/simplemutex.php',
'SqlStateMachine' => $baseDir . '/backend/sqlstatemachine/sqlstatemachine.php', 'SqlStateMachine' => $baseDir . '/backend/sqlstatemachine/sqlstatemachine.php',
......
...@@ -119,6 +119,7 @@ class ComposerStaticInitd6749fc2fb9944bbe86b2b7d79a7852f ...@@ -119,6 +119,7 @@ class ComposerStaticInitd6749fc2fb9944bbe86b2b7d79a7852f
'Search' => __DIR__ . '/../..' . '/lib/request/search.php', 'Search' => __DIR__ . '/../..' . '/lib/request/search.php',
'SearchProvider' => __DIR__ . '/../..' . '/lib/default/searchprovider.php', 'SearchProvider' => __DIR__ . '/../..' . '/lib/default/searchprovider.php',
'SendMail' => __DIR__ . '/../..' . '/lib/request/sendmail.php', 'SendMail' => __DIR__ . '/../..' . '/lib/request/sendmail.php',
'ServiceUnavailableException' => __DIR__ . '/../..' . '/lib/exceptions/serviceunavailableexception.php',
'Settings' => __DIR__ . '/../..' . '/lib/request/settings.php', 'Settings' => __DIR__ . '/../..' . '/lib/request/settings.php',
'SimpleMutex' => __DIR__ . '/../..' . '/lib/default/simplemutex.php', 'SimpleMutex' => __DIR__ . '/../..' . '/lib/default/simplemutex.php',
'SqlStateMachine' => __DIR__ . '/../..' . '/backend/sqlstatemachine/sqlstatemachine.php', 'SqlStateMachine' => __DIR__ . '/../..' . '/backend/sqlstatemachine/sqlstatemachine.php',
......
...@@ -728,7 +728,7 @@ class ZPushAdminCLI { ...@@ -728,7 +728,7 @@ class ZPushAdminCLI {
echo ZLog::GetLastMessage(LOGLEVEL_ERROR) . "\n"; echo ZLog::GetLastMessage(LOGLEVEL_ERROR) . "\n";
echo "\tChecking flags of shared folders: "; echo "\tChecking flags of shared folders: ";
if (($stat = ZPushAdmin::FixStatesAdditionalFolderFlags()) !== false) if (($stat = ZPushAdmin::FixStatesAdditionalFolders()) !== false)
printf("Devices: %d - Devices with additional folders: %d - Fixed: %d\n", $stat[0], $stat[1], $stat[2]); printf("Devices: %d - Devices with additional folders: %d - Fixed: %d\n", $stat[0], $stat[1], $stat[2]);
else else
echo ZLog::GetLastMessage(LOGLEVEL_ERROR) . "\n"; echo ZLog::GetLastMessage(LOGLEVEL_ERROR) . "\n";
......
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