Commit 610cf709 authored by Sebastian Kummer's avatar Sebastian Kummer

Merge branch 'develop' of https://stash.z-hub.io/scm/zp/z-push into...

Merge branch 'develop' of https://stash.z-hub.io/scm/zp/z-push into feature/ZP-684-New-backend-CardDAV

Conflicts:
	src/backend/combined/config.php
parents 318fe1be 9eb72b3b
The Author of this backend is dupondje, I could have modified it.
You can find the original code here:
https://github.com/dupondje/PHP-Push-2
REQUIREMENTS:
php-curl
libawl-php
INSTALL:
Add your awl folder to the include_path variable (/etc/php.ini or similar)
CalDAV server (DAViCal, Sabredav, Sogo, Owncloud...)
This diff is collapsed.
<?php
/***********************************************
* File : config.php
* Project : Z-Push
* Descr : CalDAV backend configuration file
*
* Created : 27.11.2012
*
* Copyright 2012 - 2014 Jean-Louis Dupond
*
* Jean-Louis Dupond released this code as AGPLv3 here: https://github.com/dupondje/PHP-Push-2/issues/93
*
* 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
************************************************/
// ************************
// BackendCalDAV settings
// ************************
// Server protocol: http or https
define('CALDAV_PROTOCOL', 'https');
// Server name
define('CALDAV_SERVER', 'caldavserver.domain.com');
// Server port
define('CALDAV_PORT', '443');
// Path
define('CALDAV_PATH', '/caldav.php/%u/');
// Default CalDAV folder (calendar folder/principal). This will be marked as the default calendar in the mobile
define('CALDAV_PERSONAL', 'PRINCIPAL');
// If the CalDAV server supports the sync-collection operation
// DAViCal, SOGo and SabreDav support it
// SabreDav version must be at least 1.9.0, otherwise set this to false
// Setting this to false will work with most servers, but it will be slower
define('CALDAV_SUPPORTS_SYNC', false);
// Maximum period to sync.
// Some servers don't support more than 10 years so you will need to change this
define('CALDAV_MAX_SYNC_PERIOD', 2147483647);
\ No newline at end of file
...@@ -77,6 +77,9 @@ class BackendCombinedConfig { ...@@ -77,6 +77,9 @@ class BackendCombinedConfig {
'd' => array( 'd' => array(
'name' => 'BackendCardDAV', 'name' => 'BackendCardDAV',
), ),
'c' => array(
'name' => 'BackendCalDAV',
),
), ),
'delimiter' => '/', 'delimiter' => '/',
//force one type of folder to one backend //force one type of folder to one backend
......
...@@ -1192,7 +1192,7 @@ class BackendIMAP extends BackendDiff { ...@@ -1192,7 +1192,7 @@ class BackendIMAP extends BackendDiff {
$attachment = new SyncBaseAttachment(); $attachment = new SyncBaseAttachment();
$attachment->estimatedDataSize = isset($part->d_parameters['size']) ? $part->d_parameters['size'] : isset($part->body) ? strlen($part->body) : 0; $attachment->estimatedDataSize = isset($part->d_parameters['size']) ? $part->d_parameters['size'] : (isset($part->body) ? strlen($part->body) : 0);
$attachment->displayname = $attname; $attachment->displayname = $attname;
$attachment->filereference = $folderid . ":" . $id . ":" . $i; $attachment->filereference = $folderid . ":" . $id . ":" . $i;
...@@ -1213,7 +1213,7 @@ class BackendIMAP extends BackendDiff { ...@@ -1213,7 +1213,7 @@ class BackendIMAP extends BackendDiff {
$attachment = new SyncAttachment(); $attachment = new SyncAttachment();
$attachment->attsize = isset($part->d_parameters['size']) ? $part->d_parameters['size'] : isset($part->body) ? strlen($part->body) : 0; $attachment->attsize = isset($part->d_parameters['size']) ? $part->d_parameters['size'] : (isset($part->body) ? strlen($part->body) : 0);
$attachment->displayname = $attname; $attachment->displayname = $attname;
$attachment->attname = $folderid . ":" . $id . ":" . $i; $attachment->attname = $folderid . ":" . $id . ":" . $i;
......
...@@ -186,6 +186,7 @@ class MAPIMapping { ...@@ -186,6 +186,7 @@ class MAPIMapping {
"nativebodytype" => PR_NATIVE_BODY_INFO, "nativebodytype" => PR_NATIVE_BODY_INFO,
"lastverbexecuted" => PR_LAST_VERB_EXECUTED, "lastverbexecuted" => PR_LAST_VERB_EXECUTED,
"lastverbexectime" => PR_LAST_VERB_EXECUTION_TIME, "lastverbexectime" => PR_LAST_VERB_EXECUTION_TIME,
"categories" => "PT_MV_STRING8:PS_PUBLIC_STRINGS:Keywords",
); );
} }
...@@ -459,7 +460,7 @@ class MAPIMapping { ...@@ -459,7 +460,7 @@ class MAPIMapping {
public static function GetNoteMapping() { public static function GetNoteMapping() {
return array( return array(
"categories" => "PT_MV_STRING8:PS_PUBLIC_STRINGS:Keywords", "categories" => "PT_MV_STRING8:PS_PUBLIC_STRINGS:Keywords",
"lastmodificationtime" => PR_LAST_MODIFICATION_TIME, "lastmodified" => PR_LAST_MODIFICATION_TIME,
"messageclass" => PR_MESSAGE_CLASS, "messageclass" => PR_MESSAGE_CLASS,
"subject" => PR_SUBJECT, "subject" => PR_SUBJECT,
); );
......
...@@ -1053,6 +1053,11 @@ class MAPIProvider { ...@@ -1053,6 +1053,11 @@ class MAPIProvider {
* @param SyncMail $message * @param SyncMail $message
*/ */
private function setEmail($mapimessage, $message) { private function setEmail($mapimessage, $message) {
// update categories
if (!isset($message->categories)) $message->categories = array();
$emailmap = MAPIMapping::GetEmailMapping();
$this->setPropsInMAPI($mapimessage, $message, array("categories" => $emailmap["categories"]));
$flagmapping = MAPIMapping::GetMailFlagsMapping(); $flagmapping = MAPIMapping::GetMailFlagsMapping();
$flagprops = MAPIMapping::GetMailFlagsProperties(); $flagprops = MAPIMapping::GetMailFlagsProperties();
$flagprops = array_merge($this->getPropIdsFromStrings($flagmapping), $this->getPropIdsFromStrings($flagprops)); $flagprops = array_merge($this->getPropIdsFromStrings($flagmapping), $this->getPropIdsFromStrings($flagprops));
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Created : 01.10.2007 * Created : 01.10.2007
* *
* Copyright 2007 - 2013 Zarafa Deutschland GmbH * Copyright 2007 - 2016 Zarafa Deutschland GmbH
* *
* This program is free software: you can redistribute it and/or modify * 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, * it under the terms of the GNU Affero General Public License, version 3,
...@@ -78,6 +78,12 @@ ...@@ -78,6 +78,12 @@
/********************************************************************************** /**********************************************************************************
* Logging settings * Logging settings
*
* The LOGBACKEND specifies where the logs are sent to.
* Either to file ("filelog") or to a "syslog" server or a custom log class in core/log/logclass.
* filelog and syslog have several options that can be set below.
* For more information about the syslog configuration, see https://wiki.z-hub.io/x/HIAT
* Possible LOGLEVEL and LOGUSERLEVEL values are: * Possible LOGLEVEL and LOGUSERLEVEL values are:
* LOGLEVEL_OFF - no logging * LOGLEVEL_OFF - no logging
* LOGLEVEL_FATAL - log only critical errors * LOGLEVEL_FATAL - log only critical errors
...@@ -92,14 +98,13 @@ ...@@ -92,14 +98,13 @@
* The verbosity increases from top to bottom. More verbose levels include less verbose * The verbosity increases from top to bottom. More verbose levels include less verbose
* ones, e.g. setting to LOGLEVEL_DEBUG will also output LOGLEVEL_FATAL, LOGLEVEL_ERROR, * ones, e.g. setting to LOGLEVEL_DEBUG will also output LOGLEVEL_FATAL, LOGLEVEL_ERROR,
* LOGLEVEL_WARN and LOGLEVEL_INFO level entries. * LOGLEVEL_WARN and LOGLEVEL_INFO level entries.
*
* LOGAUTHFAIL is logged to the LOGBACKEND.
*/ */
define('LOGFILEDIR', '/var/log/z-push/'); define('LOGBACKEND', 'filelog');
define('LOGFILE', LOGFILEDIR . 'z-push.log');
define('LOGERRORFILE', LOGFILEDIR . 'z-push-error.log');
define('LOGLEVEL', LOGLEVEL_WBXML); define('LOGLEVEL', LOGLEVEL_WBXML);
define('LOGAUTHFAIL', false); define('LOGAUTHFAIL', false);
// To save e.g. WBXML data only for selected users, add the usernames to the array // To save e.g. WBXML data only for selected users, add the usernames to the array
// The data will be saved into a dedicated file per user in the LOGFILEDIR // The data will be saved into a dedicated file per user in the LOGFILEDIR
// Users have to be encapusulated in quotes, several users are comma separated, like: // Users have to be encapusulated in quotes, several users are comma separated, like:
...@@ -107,15 +112,20 @@ ...@@ -107,15 +112,20 @@
define('LOGUSERLEVEL', LOGLEVEL_DEVICEID); define('LOGUSERLEVEL', LOGLEVEL_DEVICEID);
$specialLogUsers = array(); $specialLogUsers = array();
// If you want to disable log to file, and log to syslog instead // Filelog settings
define('LOG_SYSLOG_ENABLED', false); define('LOGFILEDIR', '/var/log/z-push/');
define('LOGFILE', LOGFILEDIR . 'z-push.log');
define('LOGERRORFILE', LOGFILEDIR . 'z-push-error.log');
// Syslog settings
// false will log to local syslog, otherwise put the remote syslog IP here // false will log to local syslog, otherwise put the remote syslog IP here
define('LOG_SYSLOG_HOST', false); define('LOG_SYSLOG_HOST', false);
// Syslog port // Syslog port
define('LOG_SYSLOG_PORT', 514); define('LOG_SYSLOG_PORT', 514);
// Program showed in the syslog. Useful if you have more than one instance login to the same syslog // Program showed in the syslog. Useful if you have more than one instance login to the same syslog
define('LOG_SYSLOG_PROGRAM', '[z-push]'); define('LOG_SYSLOG_PROGRAM', 'z-push');
// Syslog facility - use LOG_USER when running on Windows
define('LOG_SYSLOG_FACILITY', LOG_LOCAL0);
// Location of the trusted CA, e.g. '/etc/ssl/certs/EmailCA.pem' // Location of the trusted CA, e.g. '/etc/ssl/certs/EmailCA.pem'
// Uncomment and modify the following line if the validation of the certificates fails. // Uncomment and modify the following line if the validation of the certificates fails.
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<?php
/*
* Copyright 2015 Leon van Kammen / Coder of Salvation. All rights reserved.
* Modifications 2015 - Francisco Miguel Biete
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY Leon van Kammen / Coder of Salvation AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Leon van Kammen / Coder of Salvation OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of Leon van Kammen / Coder of Salvation
*
* https://github.com/coderofsalvation/syslog-flexible
*/
class ZSyslog {
private static $hostname = false;
private static $port = 514;
private static $program = "[z-push]";
/**
* Initializes the logging
*
* @access public
* @return boolean
*/
public static function Initialize() {
if (defined('LOG_SYSLOG_HOST'))
self::$hostname = LOG_SYSLOG_HOST;
if (defined('LOG_SYSLOG_PORT'))
self::$port = LOG_SYSLOG_PORT;
if (defined('LOG_SYSLOG_PROGRAM'))
self::$program = LOG_SYSLOG_PROGRAM;
}
/**
* Send a message in the syslog facility.
*
* @params int $zlog_level Z-Push LogLevel
* @params string $message
*
* @access public
* @return boolean
*/
public static function send($zlog_level, $message) {
$level = self::zlogLevel2SyslogLevel($zlog_level);
if ($level === false) {
return false;
}
if (self::$hostname === false) {
return syslog($level, $message);
}
else {
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
$facility = 1; // user level
$pri = ($facility*8) + $level; // multiplying the Facility number by 8 + adding the level
foreach (explode("\n", $message) as $line) {
if (strlen(trim($line)) > 0) {
$syslog_message = "<{$pri}>" . date('M d H:i:s ') . self::$program . ': ' . $line;
socket_sendto($sock, $syslog_message, strlen($syslog_message), 0, self::$hostname, self::$port);
}
}
socket_close($sock);
}
return true;
}
/**
* Converts the ZLog level to SYSLOG level.
*
* @params int $loglevel Z-Push LogLevel
*
* @access private
* @return SYSLOG_LEVEL or false
*/
private static function zlogLevel2SyslogLevel($loglevel) {
switch($loglevel) {
case LOGLEVEL_OFF: return false; break;
case LOGLEVEL_FATAL: return LOG_ALERT; break;
case LOGLEVEL_ERROR: return LOG_ERR; break;
case LOGLEVEL_WARN: return LOG_WARNING; break;
case LOGLEVEL_INFO: return LOG_INFO; break;
case LOGLEVEL_DEBUG: return LOG_DEBUG; break;
case LOGLEVEL_WBXML: return LOG_DEBUG; break;
case LOGLEVEL_DEVICEID: return LOG_DEBUG; break;
case LOGLEVEL_WBXMLSTACK: return LOG_DEBUG; break;
}
}
}
...@@ -69,8 +69,10 @@ include_once('lib/core/asdevice.php'); ...@@ -69,8 +69,10 @@ include_once('lib/core/asdevice.php');
include_once('lib/core/statemanager.php'); include_once('lib/core/statemanager.php');
include_once('lib/core/devicemanager.php'); include_once('lib/core/devicemanager.php');
include_once('lib/core/zpush.php'); include_once('lib/core/zpush.php');
include_once('include/z_syslog.php');
include_once('lib/core/zlog.php'); include_once('lib/core/zlog.php');
include_once('lib/log/log.php');
include_once('lib/log/filelog.php');
include_once('lib/log/syslog.php');
include_once('lib/interface/ibackend.php'); include_once('lib/interface/ibackend.php');
include_once('lib/interface/ichanges.php'); include_once('lib/interface/ichanges.php');
include_once('lib/interface/iexportchanges.php'); include_once('lib/interface/iexportchanges.php');
...@@ -165,7 +167,7 @@ include_once('version.php'); ...@@ -165,7 +167,7 @@ include_once('version.php');
$backend = ZPush::GetBackend(); $backend = ZPush::GetBackend();
// always request the authorization header // always request the authorization header
if (! Request::AuthenticationInfo() || !Request::GetGETUser()) if (! Request::HasAuthenticationInfo() || !Request::GetGETUser())
throw new AuthenticationRequiredException("Access denied. Please send authorisation information"); throw new AuthenticationRequiredException("Access denied. Please send authorisation information");
// check the provisioning information // check the provisioning information
......
...@@ -108,7 +108,7 @@ class LoopDetection extends InterProcessData { ...@@ -108,7 +108,7 @@ class LoopDetection extends InterProcessData {
*/ */
public static function GetProcessIdentifier() { public static function GetProcessIdentifier() {
if (!isset(self::$processident)) if (!isset(self::$processident))
self::$processident = sprintf('%04x%04', mt_rand(0, 0xffff), mt_rand(0, 0xffff)); self::$processident = sprintf('%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff));
return self::$processident; return self::$processident;
} }
......
...@@ -316,8 +316,8 @@ class StateManager { ...@@ -316,8 +316,8 @@ class StateManager {
*/ */
public function SetBackendStorage($data, $type = self::BACKENDSTORAGE_PERMANENT) { public function SetBackendStorage($data, $type = self::BACKENDSTORAGE_PERMANENT) {
if ($type == self::BACKENDSTORAGE_STATE) { if ($type == self::BACKENDSTORAGE_STATE) {
if (!$this->uuid) if (!$this->uuid)
throw new StateNotYetAvailableException(); throw new StateNotYetAvailableException();
// TODO serialization should be done in the StateMachine // TODO serialization should be done in the StateMachine
return $this->statemachine->SetState($data, $this->device->GetDeviceId(), IStateMachine::BACKENDSTORAGE, $this->uuid, $this->newStateCounter); return $this->statemachine->SetState($data, $this->device->GetDeviceId(), IStateMachine::BACKENDSTORAGE, $this->uuid, $this->newStateCounter);
......
...@@ -111,20 +111,23 @@ class ImportChangesStream implements IImportChanges { ...@@ -111,20 +111,23 @@ class ImportChangesStream implements IImportChanges {
if ($message->flags === false || $message->flags === SYNC_NEWMESSAGE) if ($message->flags === false || $message->flags === SYNC_NEWMESSAGE)
$this->encoder->startTag(SYNC_ADD); $this->encoder->startTag(SYNC_ADD);
else { else {
// on update of an SyncEmail we only export the flags // on update of an SyncEmail we only export the flags and categories
if($message instanceof SyncMail && isset($message->flag) && $message->flag instanceof SyncMailFlags) { if($message instanceof SyncMail && ((isset($message->flag) && $message->flag instanceof SyncMailFlags) || isset($message->categories))) {
$newmessage = new SyncMail(); $newmessage = new SyncMail();
$newmessage->read = $message->read; $newmessage->read = $message->read;
$newmessage->flag = $message->flag; if (isset($message->flag)) $newmessage->flag = $message->flag;
if (isset($message->lastverbexectime)) $newmessage->lastverbexectime = $message->lastverbexectime; if (isset($message->lastverbexectime)) $newmessage->lastverbexectime = $message->lastverbexectime;
if (isset($message->lastverbexecuted)) $newmessage->lastverbexecuted = $message->lastverbexecuted; if (isset($message->lastverbexecuted)) $newmessage->lastverbexecuted = $message->lastverbexecuted;
if (isset($message->categories)) $newmessage->categories = $message->categories;
$message = $newmessage; $message = $newmessage;
unset($newmessage); unset($newmessage);
ZLog::Write(LOGLEVEL_DEBUG, sprintf("ImportChangesStream->ImportMessageChange('%s'): SyncMail message updated. Message content is striped, only flags are streamed.", $id)); ZLog::Write(LOGLEVEL_DEBUG, sprintf("ImportChangesStream->ImportMessageChange('%s'): SyncMail message updated. Message content is striped, only flags/categories are streamed.", $id));
} }
$this->encoder->startTag(SYNC_MODIFY); $this->encoder->startTag(SYNC_MODIFY);
} }
// TAG: SYNC_ADD / SYNC_MODIFY
$this->encoder->startTag(SYNC_SERVERENTRYID); $this->encoder->startTag(SYNC_SERVERENTRYID);
$this->encoder->content($id); $this->encoder->content($id);
$this->encoder->endTag(); $this->encoder->endTag();
......
...@@ -42,15 +42,13 @@ ...@@ -42,15 +42,13 @@
************************************************/ ************************************************/
class ZLog { class ZLog {
static private $devid = '';
static private $user = '';
static private $authUser = false;
static private $pidstr;
static private $wbxmlDebug = ''; static private $wbxmlDebug = '';
static private $lastLogs = array(); static private $lastLogs = array();
static private $userLog = false; static private $userLog = false;
static private $unAuthCache = array(); /**
static private $syslogEnabled = false; * @var Log $logger
*/
static private $logger = null;
/** /**
* Initializes the logging * Initializes the logging
...@@ -59,12 +57,7 @@ class ZLog { ...@@ -59,12 +57,7 @@ class ZLog {
* @return boolean * @return boolean
*/ */
static public function Initialize() { static public function Initialize() {
global $specialLogUsers; $logger = self::getLogger();
if (defined('LOG_SYSLOG_ENABLED') && LOG_SYSLOG_ENABLED) {
self::$syslogEnabled = true;
ZSyslog::Initialize();
}
// define some constants for the logging // define some constants for the logging
if (!defined('LOGUSERLEVEL')) if (!defined('LOGUSERLEVEL'))
...@@ -73,27 +66,14 @@ class ZLog { ...@@ -73,27 +66,14 @@ class ZLog {
if (!defined('LOGLEVEL')) if (!defined('LOGLEVEL'))
define('LOGLEVEL', LOGLEVEL_OFF); define('LOGLEVEL', LOGLEVEL_OFF);
list($user,) = Utils::SplitDomainUser(strtolower(Request::GetGETUser())); if (!defined('WBXML_DEBUG')) {
self::$userLog = in_array($user, $specialLogUsers);
if (!defined('WBXML_DEBUG') && $user) {
// define the WBXML_DEBUG mode on user basis depending on the configurations // define the WBXML_DEBUG mode on user basis depending on the configurations
if (LOGLEVEL >= LOGLEVEL_WBXML || (LOGUSERLEVEL >= LOGLEVEL_WBXML && self::$userLog)) if (LOGLEVEL >= LOGLEVEL_WBXML || (LOGUSERLEVEL >= LOGLEVEL_WBXML && $logger->HasSpecialLogUsers()))
define('WBXML_DEBUG', true); define('WBXML_DEBUG', true);
else else
define('WBXML_DEBUG', false); define('WBXML_DEBUG', false);
} }
if ($user)
self::$user = '['. $user .'] ';
else
self::$user = '';
// log the device id if the global loglevel is set to log devid or the user is in and has the right log level
if (Request::GetDeviceID() != "" && (LOGLEVEL >= LOGLEVEL_DEVICEID || (LOGUSERLEVEL >= LOGLEVEL_DEVICEID && self::$userLog)))
self::$devid = '['. Request::GetDeviceID() .'] ';
else
self::$devid = '';
return true; return true;
} }
...@@ -114,39 +94,17 @@ class ZLog { ...@@ -114,39 +94,17 @@ class ZLog {
$message = substr($message, 0, 10240) . sprintf(" <log message with %d bytes truncated>", $messagesize); $message = substr($message, 0, 10240) . sprintf(" <log message with %d bytes truncated>", $messagesize);
self::$lastLogs[$loglevel] = $message; self::$lastLogs[$loglevel] = $message;
$data = self::buildLogString($loglevel) . $message . "\n";
if ($loglevel <= LOGLEVEL) { try {
self::writeToLog($loglevel, $data, LOGFILE); self::getLogger()->Log($loglevel, $message);
}
// should we write this into the user log?
if ($loglevel <= LOGUSERLEVEL && self::$userLog) {
// padd level for better reading
$data = str_replace(self::getLogLevelString($loglevel), self::getLogLevelString($loglevel,true), $data);
// is the user authenticated?
if (self::logToUserFile()) {
// something was logged before the user was authenticated, write this to the log
if (!empty(self::$unAuthCache)) {
self::writeToLog($loglevel, implode('', self::$unAuthCache), LOGFILEDIR . self::logToUserFile() . ".log");
self::$unAuthCache = array();
}
// only use plain old a-z characters for the generic log file
self::writeToLog($loglevel, $data, LOGFILEDIR . self::logToUserFile() . ".log");
}
// the user is not authenticated yet, we save the log into memory for now
else {
self::$unAuthCache[] = $data;
}
} }
catch (\Exception $e) {
if (($loglevel & LOGLEVEL_FATAL) || ($loglevel & LOGLEVEL_ERROR)) { //@TODO How should we handle logging error ?
self::writeToLog($loglevel, $data, LOGERRORFILE); // Ignore any error.
} }
if ($loglevel & LOGLEVEL_WBXMLSTACK) { if ($loglevel & LOGLEVEL_WBXMLSTACK) {
self::$wbxmlDebug .= $message. "\n"; self::$wbxmlDebug .= $message . PHP_EOL;
} }
} }
...@@ -193,101 +151,38 @@ class ZLog { ...@@ -193,101 +151,38 @@ class ZLog {
} }
} }
/**----------------------------------------------------------------------------------------------------------
* private log stuff
*/
/** /**
* Returns the filename logs for a WBXML debug log user should be saved to * Returns the logger object. If no logger has been initialized, FileLog will be initialized and returned.
* *
* @access private * @access private
* @return string * @return Log
* @throws Exception thrown if the logger class cannot be instantiated.
*/ */
static private function logToUserFile() { static private function getLogger() {
global $specialLogUsers; if (!self::$logger) {
global $specialLogUsers; // This variable comes from the configuration file (config.php)
if (self::$authUser === false) { $logger = LOGBACKEND;
if (RequestProcessor::isUserAuthenticated()) { if (!class_exists($logger)) {
$authuser = Request::GetAuthUser(); throw new FatalNotImplementedException('The logging class `'.$logger.'` does not exist.');
if ($authuser && in_array($authuser, $specialLogUsers))
self::$authUser = preg_replace('/[^a-z0-9]/', '_', strtolower($authuser));
} }
}
return self::$authUser;
}
/** list($user) = Utils::SplitDomainUser(strtolower(Request::GetGETUser()));
* Returns the string to be logged $user = '['.$user.']';
*
* @access private
* @return string
*/
static private function buildLogString($loglevel) {
if (!isset(self::$pidstr))
self::$pidstr = '[' . str_pad(@getmypid(),5," ",STR_PAD_LEFT) . '] ';
if (!isset(self::$user))
self::$user = '';
if (!isset(self::$devid))
self::$devid = '';
if (self::$syslogEnabled)
return self::$pidstr . self::getLogLevelString($loglevel, (LOGLEVEL > LOGLEVEL_INFO)) . " " . self::$user . self::$devid;
else
return Utils::GetFormattedTime() . " " . self::$pidstr . self::getLogLevelString($loglevel, (LOGLEVEL > LOGLEVEL_INFO)) . " " . self::$user . self::$devid;
}
/** self::$logger = new $logger();
* Returns the string representation of the LOGLEVEL. self::$logger->SetUser($user);
* String can be padded self::$logger->SetAuthUser(Request::GetAuthUser());
* self::$logger->SetSpecialLogUsers($specialLogUsers);
* @param int $loglevel one of the LOGLEVELs self::$logger->SetDevid('['. Request::GetDeviceID() .']');
* @param boolean $pad self::$logger->SetPidstr('[' . str_pad(@getmypid(),5," ",STR_PAD_LEFT) . ']');
* self::$logger->AfterInitialize();
* @access private
* @return string
*/
static private function getLogLevelString($loglevel, $pad = false) {
if ($pad) $s = " ";
else $s = "";
switch($loglevel) {
case LOGLEVEL_OFF: return ""; break;
case LOGLEVEL_FATAL: return "[FATAL]"; break;
case LOGLEVEL_ERROR: return "[ERROR]"; break;
case LOGLEVEL_WARN: return "[".$s."WARN]"; break;
case LOGLEVEL_INFO: return "[".$s."INFO]"; break;
case LOGLEVEL_DEBUG: return "[DEBUG]"; break;
case LOGLEVEL_WBXML: return "[WBXML]"; break;
case LOGLEVEL_DEVICEID: return "[DEVICEID]"; break;
case LOGLEVEL_WBXMLSTACK: return "[WBXMLSTACK]"; break;
} }
return self::$logger;
} }
/** /**----------------------------------------------------------------------------------------------------------
* Write the message to the log facility. * private log stuff
*
* @param int $loglevel
* @param string $data
* @param string $logfile
*
* @access private
* @return void
*/ */
static private function writeToLog($loglevel, $data, $logfile = null) {
if (self::$syslogEnabled) {
if (ZSyslog::send($loglevel, $data) === false) {
error_log("Unable to send to syslog");
error_log($data);
}
}
else {
if (@file_put_contents($logfile, $data, FILE_APPEND) === false) {
error_log(sprintf("Unable to write in %s", $logfile));
error_log($data);
}
}
}
} }
/**---------------------------------------------------------------------------------------------------------- /**----------------------------------------------------------------------------------------------------------
......
...@@ -220,24 +220,57 @@ class ZPush { ...@@ -220,24 +220,57 @@ class ZPush {
else else
define('REAL_BASE_PATH', BASE_PATH); define('REAL_BASE_PATH', BASE_PATH);
if (!defined('LOGFILEDIR')) if (!defined('LOGBACKEND')) {
throw new FatalMisconfigurationException("The LOGFILEDIR is not configured. Check if the config.php file is in place."); define('LOGBACKEND', 'filelog');
}
if (substr(LOGFILEDIR, -1,1) != "/") if (LOGBACKEND == 'syslog') {
throw new FatalMisconfigurationException("The LOGFILEDIR should terminate with a '/'");
if (!file_exists(LOGFILEDIR)) if (!defined('LOG_SYSLOG_FACILITY')) {
throw new FatalMisconfigurationException("The configured LOGFILEDIR does not exist or can not be accessed."); define('LOG_SYSLOG_FACILITY', LOG_LOCAL0);
}
if ((!file_exists(LOGFILE) && !touch(LOGFILE)) || !is_writable(LOGFILE)) if (!defined('LOG_SYSLOG_HOST')) {
throw new FatalMisconfigurationException("The configured LOGFILE can not be modified."); define('LOG_SYSLOG_HOST', false);
}
if ((!file_exists(LOGERRORFILE) && !touch(LOGERRORFILE)) || !is_writable(LOGERRORFILE)) if (!defined('LOG_SYSLOG_PORT')) {
throw new FatalMisconfigurationException("The configured LOGERRORFILE can not be modified."); define('LOG_SYSLOG_PORT', 514);
}
// check ownership on the (eventually) just created files if (!defined('LOG_SYSLOG_PROGRAM')) {
Utils::FixFileOwner(LOGFILE); define('LOG_SYSLOG_PROGRAM', 'z-push');
Utils::FixFileOwner(LOGERRORFILE); }
if (!is_numeric(LOG_SYSLOG_PORT)) {
throw new FatalMisconfigurationException("The LOG_SYSLOG_PORT must a be a number.");
}
if (LOG_SYSLOG_HOST && LOG_SYSLOG_PORT <= 0) {
throw new FatalMisconfigurationException("LOG_SYSLOG_HOST is defined but the LOG_SYSLOG_PORT does not seem to be valid.");
}
}
elseif (LOGBACKEND == 'filelog') {
if (!defined('LOGFILEDIR'))
throw new FatalMisconfigurationException("The LOGFILEDIR is not configured. Check if the config.php file is in place.");
if (substr(LOGFILEDIR, -1,1) != "/")
throw new FatalMisconfigurationException("The LOGFILEDIR should terminate with a '/'");
if (!file_exists(LOGFILEDIR))
throw new FatalMisconfigurationException("The configured LOGFILEDIR does not exist or can not be accessed.");
if ((!file_exists(LOGFILE) && !touch(LOGFILE)) || !is_writable(LOGFILE))
throw new FatalMisconfigurationException("The configured LOGFILE can not be modified.");
if ((!file_exists(LOGERRORFILE) && !touch(LOGERRORFILE)) || !is_writable(LOGERRORFILE))
throw new FatalMisconfigurationException("The configured LOGERRORFILE can not be modified.");
// check ownership on the (eventually) just created files
Utils::FixFileOwner(LOGFILE);
Utils::FixFileOwner(LOGERRORFILE);
}
// set time zone // set time zone
// code contributed by Robert Scheck (rsc) // code contributed by Robert Scheck (rsc)
......
...@@ -303,7 +303,7 @@ abstract class Backend implements IBackend { ...@@ -303,7 +303,7 @@ abstract class Backend implements IBackend {
} }
if (isset($this->stateStorage)) { if (isset($this->stateStorage)) {
try { try {
$this->storage_state = ZPush::GetDeviceManager()->GetStateManager()->SetBackendStorage($this->stateStorage, StateManager::BACKENDSTORAGE_STATE); ZPush::GetDeviceManager()->GetStateManager()->SetBackendStorage($this->stateStorage, StateManager::BACKENDSTORAGE_STATE);
} }
catch (StateNotYetAvailableException $snyae) { } catch (StateNotYetAvailableException $snyae) { }
catch(StateNotFoundException $snfe) { } catch(StateNotFoundException $snfe) { }
......
...@@ -154,7 +154,7 @@ class FileStateMachine implements IStateMachine { ...@@ -154,7 +154,7 @@ class FileStateMachine implements IStateMachine {
$state = serialize($state); $state = serialize($state);
$filename = $this->getFullFilePath($devid, $type, $key, $counter); $filename = $this->getFullFilePath($devid, $type, $key, $counter);
if (($bytes = file_put_contents($filename, $state)) === false) if (($bytes = Utils::SafePutContents($filename, $state)) === false)
throw new FatalMisconfigurationException(sprintf("FileStateMachine->SetState(): Could not write state '%s'",$filename)); throw new FatalMisconfigurationException(sprintf("FileStateMachine->SetState(): Could not write state '%s'",$filename));
ZLog::Write(LOGLEVEL_DEBUG, sprintf("FileStateMachine->SetState() written %d bytes on file: '%s'", $bytes, $filename)); ZLog::Write(LOGLEVEL_DEBUG, sprintf("FileStateMachine->SetState() written %d bytes on file: '%s'", $bytes, $filename));
...@@ -233,7 +233,7 @@ class FileStateMachine implements IStateMachine { ...@@ -233,7 +233,7 @@ class FileStateMachine implements IStateMachine {
} }
if ($changed) { if ($changed) {
$bytes = file_put_contents($this->userfilename, serialize($users)); $bytes = Utils::SafePutContents($this->userfilename, serialize($users));
ZLog::Write(LOGLEVEL_DEBUG, sprintf("FileStateMachine->LinkUserDevice(): wrote %d bytes to users file", $bytes)); ZLog::Write(LOGLEVEL_DEBUG, sprintf("FileStateMachine->LinkUserDevice(): wrote %d bytes to users file", $bytes));
} }
else else
...@@ -282,7 +282,7 @@ class FileStateMachine implements IStateMachine { ...@@ -282,7 +282,7 @@ class FileStateMachine implements IStateMachine {
} }
if ($changed) { if ($changed) {
$bytes = file_put_contents($this->userfilename, serialize($users)); $bytes = Utils::SafePutContents($this->userfilename, serialize($users));
ZLog::Write(LOGLEVEL_DEBUG, sprintf("FileStateMachine->UnLinkUserDevice(): wrote %d bytes to users file", $bytes)); ZLog::Write(LOGLEVEL_DEBUG, sprintf("FileStateMachine->UnLinkUserDevice(): wrote %d bytes to users file", $bytes));
} }
else else
...@@ -370,7 +370,7 @@ class FileStateMachine implements IStateMachine { ...@@ -370,7 +370,7 @@ class FileStateMachine implements IStateMachine {
$settings[self::VERSION] = $version; $settings[self::VERSION] = $version;
ZLog::Write(LOGLEVEL_INFO, sprintf("FileStateMachine->SetStateVersion() saving supported state version, value '%d'", $version)); ZLog::Write(LOGLEVEL_INFO, sprintf("FileStateMachine->SetStateVersion() saving supported state version, value '%d'", $version));
$status = file_put_contents($this->settingsfilename, serialize($settings)); $status = Utils::SafePutContents($this->settingsfilename, serialize($settings));
Utils::FixFileOwner($this->settingsfilename); Utils::FixFileOwner($this->settingsfilename);
return $status; return $status;
} }
......
<?php
/***********************************************
* File : filelog.php
* Project : Z-Push
* Descr : Logging functionalities
*
* Created : 13.11.2015
*
* Copyright 2007 - 2015 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 FileLog extends Log {
/**
* @var string|bool
*/
private $log_to_user_file = false;
/**
* Get the log user file.
*
* @access private
* @return string
*/
private function getLogToUserFile() {
if ($this->log_to_user_file === false) {
$this->setLogToUserFile(preg_replace('/[^a-z0-9]/', '_', strtolower($this->GetAuthUser())) . '.log');
}
return $this->log_to_user_file;
}
/**
* @param string $value
*/
private function setLogToUserFile($value) {
$this->log_to_user_file = $value;
}
public function __construct() {
}
/**
* Returns the string to be logged
*
* @param int $loglevel
* @param string $message
*
* @access public
* @return string
*/
public function BuildLogString($loglevel, $message) {
$log = Utils::GetFormattedTime() . ' ' . $this->GetPidstr() . ' ' . $this->GetLogLevelString($loglevel, $loglevel >= LOGLEVEL_INFO) . ' ' . $this->GetUser();
if (LOGLEVEL >= LOGLEVEL_DEVICEID || (LOGUSERLEVEL >= LOGLEVEL_DEVICEID && $this->IsAuthUserInSpecialLogUsers())) {
$log .= ' ' . $this->GetDevid();
}
$log .= ' ' . $message;
return $log;
}
//
// Implementation of Log
//
protected function Write($loglevel, $message) {
$data = $this->buildLogString($loglevel, $message) . PHP_EOL;
@file_put_contents(LOGFILE, $data, FILE_APPEND);
if (($loglevel & LOGLEVEL_FATAL) || ($loglevel & LOGLEVEL_ERROR)) {
@file_put_contents(LOGERRORFILE, $data, FILE_APPEND);
}
}
public function WriteForUser($loglevel, $message) {
$data = $this->buildLogString($loglevel, $message) . PHP_EOL;
@file_put_contents(LOGFILEDIR . $this->getLogToUserFile(), $data, FILE_APPEND);
}
protected function afterLog($loglevel, $message) {
if (($loglevel & LOGLEVEL_FATAL) || ($loglevel & LOGLEVEL_ERROR)) {
$data = $this->buildLogString($loglevel, $message) . PHP_EOL;
@file_put_contents(LOGERRORFILE, $data, FILE_APPEND);
}
}
}
This diff is collapsed.
This diff is collapsed.
...@@ -52,9 +52,6 @@ class FolderSync extends RequestProcessor { ...@@ -52,9 +52,6 @@ class FolderSync extends RequestProcessor {
* @return boolean * @return boolean
*/ */
public function Handle ($commandCode) { public function Handle ($commandCode) {
// Maps serverid -> clientid for items that are received from the PIM
$map = array();
// Parse input // Parse input
if(!self::$decoder->getElementStartTag(SYNC_FOLDERHIERARCHY_FOLDERSYNC)) if(!self::$decoder->getElementStartTag(SYNC_FOLDERHIERARCHY_FOLDERSYNC))
return false; return false;
...@@ -141,10 +138,6 @@ class FolderSync extends RequestProcessor { ...@@ -141,10 +138,6 @@ class FolderSync extends RequestProcessor {
$serverid = $changesMem->ImportFolderDeletion($folder); $serverid = $changesMem->ImportFolderDeletion($folder);
break; break;
} }
// TODO what does $map??
if($serverid)
$map[$serverid] = $folder->clientid;
} }
else { else {
ZLog::Write(LOGLEVEL_WARN, sprintf("Request->HandleFolderSync(): ignoring incoming folderchange for folder '%s' as status indicates problem.", $folder->displayname)); ZLog::Write(LOGLEVEL_WARN, sprintf("Request->HandleFolderSync(): ignoring incoming folderchange for folder '%s' as status indicates problem.", $folder->displayname));
...@@ -219,7 +212,7 @@ class FolderSync extends RequestProcessor { ...@@ -219,7 +212,7 @@ class FolderSync extends RequestProcessor {
// say that we are done with partial synching // say that we are done with partial synching
self::$deviceManager->SetFolderSyncComplete(true); self::$deviceManager->SetFolderSyncComplete(true);
// reset the loop data to prevent any loop detection to kick in now // reset the loop data to prevent any loop detection to kick in now
self::$deviceManager->ClearLoopDetectionData(Request::GetAuthUser(), Request::GetDeviceId()); self::$deviceManager->ClearLoopDetectionData(Request::GetAuthUser(), Request::GetDeviceID());
ZLog::Write(LOGLEVEL_INFO, "Request->HandleFolderSync(): Chunked exporting of folders completed successfully"); ZLog::Write(LOGLEVEL_INFO, "Request->HandleFolderSync(): Chunked exporting of folders completed successfully");
} }
......
...@@ -91,7 +91,7 @@ class GetItemEstimate extends RequestProcessor { ...@@ -91,7 +91,7 @@ class GetItemEstimate extends RequestProcessor {
elseif(self::$decoder->getElementStartTag(SYNC_CONVERSATIONMODE)) { elseif(self::$decoder->getElementStartTag(SYNC_CONVERSATIONMODE)) {
$spa->SetConversationMode(true); $spa->SetConversationMode(true);
if(($conversationmode = self::$decoder->getElementContent()) !== false) { if(($conversationmode = self::$decoder->getElementContent()) !== false) {
$spa->SetConversationMode((boolean)$conversationmode); $spa->SetConversationMode((bool)$conversationmode);
if(!self::$decoder->getElementEndTag()) if(!self::$decoder->getElementEndTag())
return false; return false;
} }
......
...@@ -213,7 +213,7 @@ class ItemOperations extends RequestProcessor { ...@@ -213,7 +213,7 @@ class ItemOperations extends RequestProcessor {
if(self::$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_DELETESUBFOLDERS)) { if(self::$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_DELETESUBFOLDERS)) {
$operation['deletesubfolders'] = true; $operation['deletesubfolders'] = true;
if (($dsf = self::$decoder->getElementContent()) !== false) { if (($dsf = self::$decoder->getElementContent()) !== false) {
$operation['deletesubfolders'] = (boolean)$dsf; $operation['deletesubfolders'] = (bool)$dsf;
if(!self::$decoder->getElementEndTag()) if(!self::$decoder->getElementEndTag())
return false; return false;
} }
......
...@@ -74,9 +74,7 @@ class Request { ...@@ -74,9 +74,7 @@ class Request {
static private $input; static private $input;
static private $output; static private $output;
static private $headers; static private $headers;
static private $getparameters;
static private $command; static private $command;
static private $device;
static private $method; static private $method;
static private $remoteAddr; static private $remoteAddr;
static private $getUser; static private $getUser;
...@@ -91,7 +89,7 @@ class Request { ...@@ -91,7 +89,7 @@ class Request {
static private $attachmentName; static private $attachmentName;
static private $collectionId; static private $collectionId;
static private $itemId; static private $itemId;
static private $longId; //TODO static private $longId; // TODO
static private $occurence; //TODO static private $occurence; //TODO
static private $saveInSent; static private $saveInSent;
static private $acceptMultipart; static private $acceptMultipart;
...@@ -186,6 +184,16 @@ class Request { ...@@ -186,6 +184,16 @@ class Request {
self::$getUser = Utils::GetLocalPartFromEmail(self::$getUser); self::$getUser = Utils::GetLocalPartFromEmail(self::$getUser);
} }
} }
// authUser & authPassword are unfiltered!
// split username & domain if received as one
if (isset($_SERVER['PHP_AUTH_USER'])) {
list(self::$authUser, self::$authDomain) = Utils::SplitDomainUser($_SERVER['PHP_AUTH_USER']);
self::$authPassword = (isset($_SERVER['PHP_AUTH_PW']))?$_SERVER['PHP_AUTH_PW'] : "";
}
if(defined('USE_FULLEMAIL_FOR_LOGIN') && ! USE_FULLEMAIL_FOR_LOGIN) {
self::$authUser = Utils::GetLocalPartFromEmail(self::$authUser);
}
} }
/** /**
...@@ -234,21 +242,10 @@ class Request { ...@@ -234,21 +242,10 @@ class Request {
} }
/** /**
* Reads and parses the HTTP-Basic-Auth data
*
* @access public * @access public
* @return boolean data sent or not * @return boolean data sent or not
*/ */
static public function AuthenticationInfo() { static public function HasAuthenticationInfo() {
// split username & domain if received as one
if (isset($_SERVER['PHP_AUTH_USER'])) {
list(self::$authUser, self::$authDomain) = Utils::SplitDomainUser($_SERVER['PHP_AUTH_USER']);
self::$authPassword = (isset($_SERVER['PHP_AUTH_PW']))?$_SERVER['PHP_AUTH_PW'] : "";
}
if(defined('USE_FULLEMAIL_FOR_LOGIN') && ! USE_FULLEMAIL_FOR_LOGIN) {
self::$authUser = Utils::GetLocalPartFromEmail(self::$authUser);
}
// authUser & authPassword are unfiltered!
return (self::$authUser != "" && self::$authPassword != ""); return (self::$authUser != "" && self::$authPassword != "");
} }
......
This diff is collapsed.
...@@ -210,8 +210,8 @@ class SyncAppointment extends SyncObject { ...@@ -210,8 +210,8 @@ class SyncAppointment extends SyncObject {
} }
} }
// do not sync a recurrent appointment without a timezone // do not sync a recurrent appointment without a timezone (except all day events)
if (isset($this->recurrence) && !isset($this->timezone)) { if (isset($this->recurrence) && !isset($this->timezone) && empty($this->alldayevent)) {
ZLog::Write(LOGLEVEL_ERROR, "SyncAppointment->Check(): timezone for a recurring appointment is not set."); ZLog::Write(LOGLEVEL_ERROR, "SyncAppointment->Check(): timezone for a recurring appointment is not set.");
return false; return false;
} }
......
...@@ -86,6 +86,7 @@ class SyncMail extends SyncObject { ...@@ -86,6 +86,7 @@ class SyncMail extends SyncObject {
public $lastverbexectime; public $lastverbexectime;
public $receivedasbcc; public $receivedasbcc;
public $sender; public $sender;
public $categories;
function SyncMail() { function SyncMail() {
$mapping = array ( $mapping = array (
......
This diff is collapsed.
This diff is collapsed.
...@@ -759,7 +759,7 @@ class ZPushAdmin { ...@@ -759,7 +759,7 @@ class ZPushAdmin {
$users = self::ListUsers($devid); $users = self::ListUsers($devid);
foreach ($users as $username) { foreach ($users as $username) {
$seen++; $seen++;
ZLog::Write(LOGLEVEL_DEBUG, sprintf("ZPushAdmin::FixStatesDeviceToUserLinking(): linking user '%s' to device '%d'", $username, $devid)); ZLog::Write(LOGLEVEL_DEBUG, sprintf("ZPushAdmin::FixStatesDeviceToUserLinking(): linking user '%s' to device '%s'", $username, $devid));
if (ZPush::GetStateMachine()->LinkUserDevice($username, $devid)) if (ZPush::GetStateMachine()->LinkUserDevice($username, $devid))
$fixed++; $fixed++;
......
...@@ -384,7 +384,7 @@ class WBXMLDecoder extends WBXMLDefs { ...@@ -384,7 +384,7 @@ class WBXMLDecoder extends WBXMLDefs {
switch($byte) { switch($byte) {
case WBXML_SWITCH_PAGE: case WBXML_SWITCH_PAGE:
$this->tagcp = $this->getByte(); $this->tagcp = $this->getByte();
continue; break;
case WBXML_END: case WBXML_END:
$element[EN_TYPE] = EN_TYPE_ENDTAG; $element[EN_TYPE] = EN_TYPE_ENDTAG;
......
This diff is collapsed.
This diff is collapsed.
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