Commit 19f9cb6e authored by Sebastian Kummer's avatar Sebastian Kummer

Merge branch 'develop' into feature/ZP-705-implement-support-for-streamer_type_stream_asplain

parents 7304e954 989e8537
...@@ -5,6 +5,6 @@ ...@@ -5,6 +5,6 @@
"homepage": "http://z-push.org/", "homepage": "http://z-push.org/",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"require": { "require": {
"php": ">=5.2.0" "php": ">=5.4.0"
} }
} }
composer.phar
After creating a new file or removing an existing one you must refresh the autoload code.
curl -sS https://getcomposer.org/installer | php
php composer.phar dump-autoload -o
...@@ -41,24 +41,12 @@ ...@@ -41,24 +41,12 @@
* Consult LICENSE file for details * Consult LICENSE file for details
************************************************/ ************************************************/
include_once('../lib/core/zpushdefs.php'); require_once '../vendor/autoload.php';
include_once('../lib/exceptions/exceptions.php'); require_once '../config.php';
include_once('../lib/utils/compat.php');
include_once('../lib/utils/utils.php');
include_once('../lib/core/zpush.php');
include_once('../lib/core/zlog.php');
include_once('../lib/interface/ibackend.php');
include_once('../lib/interface/ichanges.php');
include_once('../lib/interface/iexportchanges.php');
include_once('../lib/interface/iimportchanges.php');
include_once('../lib/interface/isearchprovider.php');
include_once('../lib/interface/istatemachine.php');
include_once('../lib/request/request.php');
include_once('../version.php');
include_once('config.php');
class ZPushAutodiscover { class ZPushAutodiscover {
const ACCEPTABLERESPONSESCHEMA = 'http://schemas.microsoft.com/exchange/autodiscover/mobilesync/responseschema/2006'; const ACCEPTABLERESPONSESCHEMAMOBILESYNC = 'http://schemas.microsoft.com/exchange/autodiscover/mobilesync/responseschema/2006';
const ACCEPTABLERESPONSESCHEMAOUTLOOK = 'http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a';
const MAXINPUTSIZE = 8192; // Bytes, the autodiscover request shouldn't exceed that value const MAXINPUTSIZE = 8192; // Bytes, the autodiscover request shouldn't exceed that value
private static $instance; private static $instance;
...@@ -111,8 +99,11 @@ class ZPushAutodiscover { ...@@ -111,8 +99,11 @@ class ZPushAutodiscover {
$email = ($this->getAttribFromUserDetails($userDetails, 'emailaddress')) ? $this->getAttribFromUserDetails($userDetails, 'emailaddress') : $incomingXml->Request->EMailAddress; $email = ($this->getAttribFromUserDetails($userDetails, 'emailaddress')) ? $this->getAttribFromUserDetails($userDetails, 'emailaddress') : $incomingXml->Request->EMailAddress;
$userFullname = ($this->getAttribFromUserDetails($userDetails, 'fullname')) ? $this->getAttribFromUserDetails($userDetails, 'fullname') : $email; $userFullname = ($this->getAttribFromUserDetails($userDetails, 'fullname')) ? $this->getAttribFromUserDetails($userDetails, 'fullname') : $email;
ZLog::Write(LOGLEVEL_WBXML, sprintf("Resolved user's '%s' fullname to '%s'", $username, $userFullname)); ZLog::Write(LOGLEVEL_WBXML, sprintf("Resolved user's '%s' fullname to '%s'", $username, $userFullname));
$response = $this->createResponse($email, $userFullname); // At the moment Z-Push only supports mobile response schema for autodiscover. Send empty response if the client request outlook response schema.
setcookie("membername", $username); if ($incomingXml->Request->AcceptableResponseSchema == ZPushAutodiscover::ACCEPTABLERESPONSESCHEMAMOBILESYNC) {
$response = $this->createResponse($email, $userFullname);
setcookie("membername", $username);
}
} }
catch (AuthenticationRequiredException $ex) { catch (AuthenticationRequiredException $ex) {
...@@ -175,7 +166,7 @@ class ZPushAutodiscover { ...@@ -175,7 +166,7 @@ class ZPushAutodiscover {
throw new FatalException('Invalid input XML: no AcceptableResponseSchema.'); throw new FatalException('Invalid input XML: no AcceptableResponseSchema.');
} }
if ($xml->Request->AcceptableResponseSchema != ZPushAutodiscover::ACCEPTABLERESPONSESCHEMA) { if ($xml->Request->AcceptableResponseSchema != ZPushAutodiscover::ACCEPTABLERESPONSESCHEMAMOBILESYNC && $xml->Request->AcceptableResponseSchema != ZPushAutodiscover::ACCEPTABLERESPONSESCHEMAOUTLOOK) {
throw new FatalException('Invalid input XML: not a mobilesync responseschema.'); throw new FatalException('Invalid input XML: not a mobilesync responseschema.');
} }
...@@ -265,4 +256,14 @@ class ZPushAutodiscover { ...@@ -265,4 +256,14 @@ class ZPushAutodiscover {
} }
} }
// set time zone
// code contributed by Robert Scheck (rsc)
if(defined('TIMEZONE') ? constant('TIMEZONE') : false) {
if (! @date_default_timezone_set(TIMEZONE))
throw new FatalMisconfigurationException(sprintf("The configured TIMEZONE '%s' is not valid. Please check supported timezones at http://www.php.net/manual/en/timezones.php", constant('TIMEZONE')));
}
else if(!ini_get('date.timezone')) {
date_default_timezone_set('Europe/Amsterdam');
}
ZPushAutodiscover::DoZPushAutodiscover(); ZPushAutodiscover::DoZPushAutodiscover();
...@@ -44,6 +44,9 @@ ...@@ -44,6 +44,9 @@
/********************************************************************************** /**********************************************************************************
* Default settings * Default settings
*/ */
// Defines the default time zone, change e.g. to "Europe/London" if necessary
define('TIMEZONE', '');
// Defines the base path on the server // Defines the base path on the server
define('BASE_PATH', dirname($_SERVER['SCRIPT_FILENAME']). '/'); define('BASE_PATH', dirname($_SERVER['SCRIPT_FILENAME']). '/');
......
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 <?php
/*********************************************** /***********************************************
* File : exceptions.php * File : config.php
* Project : Z-Push * Project : Z-Push
* Descr : Includes all Z-Push exceptions * Descr : CalDAV backend configuration file
* *
* Created : 06.02.2012 * Created : 27.11.2012
* *
* Copyright 2007 - 2013 Zarafa Deutschland GmbH * 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 * 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,
...@@ -41,24 +43,32 @@ ...@@ -41,24 +43,32 @@
* Consult LICENSE file for details * Consult LICENSE file for details
************************************************/ ************************************************/
// main exception // ************************
include_once('zpushexception.php'); // 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);
// Fatal exceptions
include_once('fatalexception.php');
include_once('fatalmisconfigurationexception.php');
include_once('fatalnotimplementedexception.php');
include_once('wbxmlexception.php');
include_once('nopostrequestexception.php');
include_once('httpreturncodeexception.php');
include_once('authenticationrequiredexception.php');
include_once('provisioningrequiredexception.php');
// Non fatal exceptions // Maximum period to sync.
include_once('notimplementedexception.php'); // Some servers don't support more than 10 years so you will need to change this
include_once('syncobjectbrokenexception.php'); define('CALDAV_MAX_SYNC_PERIOD', 2147483647);
include_once('statusexception.php'); \ No newline at end of file
include_once('statenotfoundexception.php');
include_once('stateinvalidexception.php');
include_once('nohierarchycacheavailableexception.php');
include_once('statenotyetavailableexception.php');
This is a CardDAV backend based in the vcarddir backend.
It supports DAViCal, Sogo, OwnCloud, SabreDav... and should works with any carddav server. So if it doesn't work with your server, please open a issue.
It supports ChangesSink method that will detect and send faster changes to your device.
DAViCal implements the SYNC operation, it's a very fast method to detect changes in your vcards.
The others servers don't implement it, so the code will fallback to a slower method (suggest your carddav server developers to implement it!!).
This is controlled with a flag in the config.php file.
Also, it can autodetect multiple addressbooks and will present them to the mobile device as an unique addressbook (only iOS supports multiple addressbook).
REQUIREMENTS:
php-curl
php-xsl
CardDAV server (DAViCal, Sabredav, Sogo, Owncloud...)
\ No newline at end of file
*Drenalina SRL (www.drenalina.com)* sponsored the development of the following features in the BackendCardDAV, any existing bug it's my fault not theirs ;-)
Thank you very much for helping to improve it!!
- Autodetecting addressbooks within a DAV principal.
- Merging multiple addressbooks so the device will see a unique one. Only iOS based devices support multiple addressbooks, so we will merge them for now.
- Selecting default addressbook to store new contacts created from the device.
- GAL addressbook and GAL search.
\ No newline at end of file
This diff is collapsed.
<?php
/***********************************************
* File : config.php
* Project : Z-Push
* Descr : CardDAV backend configuration file
*
* Created : 16.03.2013
*
* Copyright 2013 - 2016 Francisco Miguel Biete
*
* 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
************************************************/
// ************************
// BackendCardDAV settings
// ************************
// Server protocol: http or https
define('CARDDAV_PROTOCOL', 'https');
// Server name
define('CARDDAV_SERVER', 'localhost');
// Server port
define('CARDDAV_PORT', '443');
// Server path to the addressbook, or the principal with the addressbooks
// If your user has more than 1 addressbook point it to the principal.
// Example: user test@domain.com will have 2 addressbooks
// http://localhost/caldav.php/test@domain.com/addresses/personal
// http://localhost/caldav.php/test@domain.com/addresses/work
// You set the CARDDAV_PATH to '/caldav.php/%u/addresses/' and personal and work will be autodiscovered
// %u: replaced with the username
// %d: replaced with the domain
// Add the trailing /
define('CARDDAV_PATH', '/caldav.php/%u/');
// Server path to the default addressbook
// Mobile device will create new contacts here. It must be under CARDDAV_PATH
// %u: replaced with the username
// %d: replaced with the domain
// Add the trailing /
define('CARDDAV_DEFAULT_PATH', '/caldav.php/%u/addresses/');
// Server path to the GAL addressbook. This addressbook is readonly and searchable by the user, but it will NOT be synced.
// If you don't want GAL, comment it
// %u: replaced with the username
// %d: replaced with the domain
// Add the trailing /
define('CARDDAV_GAL_PATH', '/caldav.php/%d/GAL/');
// Minimal length for the search pattern to do the real search.
define('CARDDAV_GAL_MIN_LENGTH', 5);
// Addressbook display name, the name showed in the mobile device
// %u: replaced with the username
// %d: replaced with the domain
define('CARDDAV_CONTACTS_FOLDER_NAME', '%u Addressbook');
// If the CardDAV server supports the sync-collection operation
// DAViCal and SabreDav support it, but Owncloud, SOGo don't
// 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: 1 petition for the href of vcards, and 1 petition for each vcard
define('CARDDAV_SUPPORTS_SYNC', false);
// If the CardDAV server supports the FN attribute for searches
// DAViCal supports it, but SabreDav, Owncloud and SOGo don't
// Setting this to true will search by FN. If false will search by sn, givenName and email
// It's safe to leave it as false
define('CARDDAV_SUPPORTS_FN_SEARCH', false);
// If your carddav server needs to use file extension to recover a vcard.
// Davical needs it
// SOGo official demo online needs it, but some SOGo installation don't need it, so test it
define('CARDDAV_URL_VCARD_EXTENSION', '.vcf');
\ No newline at end of file
...@@ -74,6 +74,15 @@ class BackendCombinedConfig { ...@@ -74,6 +74,15 @@ class BackendCombinedConfig {
'v' => array( 'v' => array(
'name' => 'BackendVCardDir', 'name' => 'BackendVCardDir',
), ),
'l' => array(
'name' => 'BackendLDAP',
),
'd' => array(
'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;
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* *
* Created : 14.02.2011 * Created : 14.02.2011
* *
* Copyright 2007 - 2013 Zarafa Deutschland GmbH * Copyright 2007 - 2015 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,
...@@ -311,17 +311,23 @@ class ImportChangesICS implements IImportChanges { ...@@ -311,17 +311,23 @@ class ImportChangesICS implements IImportChanges {
$potConflicts = $exporter->GetChangeCount(); $potConflicts = $exporter->GetChangeCount();
$started = time(); $started = time();
$exported = 0; $exported = 0;
while(is_array($exporter->Synchronize())) { try {
$exported++; while(is_array($exporter->Synchronize())) {
$exported++;
// stop if this takes more than 15 seconds and there are more than 5 changes still to be exported
// within 20 seconds this should be finished or it will not be performed // stop if this takes more than 15 seconds and there are more than 5 changes still to be exported
if ((time() - $started) > 15 && ($potConflicts - $exported) > 5 ) { // within 20 seconds this should be finished or it will not be performed
ZLog::Write(LOGLEVEL_WARN, sprintf("ImportChangesICS->lazyLoadConflicts(): conflict detection cancelled as operation is too slow. In %d seconds only %d from %d changes were processed.",(time() - $started), $exported, $potConflicts)); if ((time() - $started) > 15 && ($potConflicts - $exported) > 5 ) {
$this->conflictsLoaded = true; ZLog::Write(LOGLEVEL_WARN, sprintf("ImportChangesICS->lazyLoadConflicts(): conflict detection cancelled as operation is too slow. In %d seconds only %d from %d changes were processed.",(time() - $started), $exported, $potConflicts));
return; $this->conflictsLoaded = true;
return;
}
} }
} }
// something really bad happened while exporting changes
catch (StatusException $stex) {
ZLog::Write(LOGLEVEL_WARN, sprintf("ImportChangesICS->lazyLoadConflicts(): got StatusException code %d while exporting changes. Ignore and mark conflicts as loaded.",$stex->getCode()));
}
$this->conflictsLoaded = true; $this->conflictsLoaded = true;
} }
} }
......
...@@ -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",
); );
} }
...@@ -400,6 +401,7 @@ class MAPIMapping { ...@@ -400,6 +401,7 @@ class MAPIMapping {
"status" => "PT_LONG:PSETID_Task:0x8101", "status" => "PT_LONG:PSETID_Task:0x8101",
"icon" => PR_ICON_INDEX, "icon" => PR_ICON_INDEX,
"owner" => "PT_STRING8:PSETID_Task:0x811F", "owner" => "PT_STRING8:PSETID_Task:0x811F",
"private" => "PT_BOOLEAN:PSETID_Common:0x8506",
); );
} }
...@@ -459,7 +461,7 @@ class MAPIMapping { ...@@ -459,7 +461,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,
); );
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Created : 14.02.2011 * Created : 14.02.2011
* *
* Copyright 2007 - 2013 Zarafa Deutschland GmbH * Copyright 2007 - 2015 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,
...@@ -847,6 +847,14 @@ class MAPIProvider { ...@@ -847,6 +847,14 @@ class MAPIProvider {
$storeprops = $this->getStoreProps(); $storeprops = $this->getStoreProps();
// For ZCP 7.0.x we need to retrieve more properties explicitly, see ZP-780
if (isset($folderprops[PR_SOURCE_KEY]) && !isset($folderprops[PR_ENTRYID]) && !isset($folderprops[PR_CONTAINER_CLASS])) {
$entryid = mapi_msgstore_entryidfromsourcekey($this->store, $folderprops[PR_SOURCE_KEY]);
$mapifolder = mapi_msgstore_openentry($this->store, $entryid);
$folderprops = mapi_getprops($mapifolder, array(PR_DISPLAY_NAME, PR_PARENT_ENTRYID, PR_ENTRYID, PR_SOURCE_KEY, PR_PARENT_SOURCE_KEY, PR_CONTAINER_CLASS, PR_ATTR_HIDDEN));
ZLog::Write(LOGLEVEL_DEBUG, "MAPIProvider->GetFolder(): received insuffient of data from ICS. Fetching required data.");
}
if(!isset($folderprops[PR_DISPLAY_NAME]) || if(!isset($folderprops[PR_DISPLAY_NAME]) ||
!isset($folderprops[PR_PARENT_ENTRYID]) || !isset($folderprops[PR_PARENT_ENTRYID]) ||
!isset($folderprops[PR_SOURCE_KEY]) || !isset($folderprops[PR_SOURCE_KEY]) ||
...@@ -1045,6 +1053,11 @@ class MAPIProvider { ...@@ -1045,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));
...@@ -1576,6 +1589,8 @@ class MAPIProvider { ...@@ -1576,6 +1589,8 @@ class MAPIProvider {
$recurrence->setRecurrence($recur); $recurrence->setRecurrence($recur);
} }
$props[$taskprops["private"]] = (isset($task->sensitivity) && $task->sensitivity == SENSITIVITY_PRIVATE) ? true : false;
//open addresss book for user resolve to set the owner //open addresss book for user resolve to set the owner
$addrbook = $this->getAddressbook(); $addrbook = $this->getAddressbook();
......
{
"autoload": {
"classmap": ["autodiscover/", "include/", "lib/"],
"files": ["version.php", "lib/core/zpushdefs.php", "lib/utils/compat.php"]
}
}
...@@ -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.
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;
}
}
}
...@@ -54,82 +54,10 @@ else { ...@@ -54,82 +54,10 @@ else {
// ignore user abortions because this can lead to weird errors - see ZP-239 // ignore user abortions because this can lead to weird errors - see ZP-239
ignore_user_abort(true); ignore_user_abort(true);
include_once('lib/exceptions/exceptions.php'); require_once 'vendor/autoload.php';
include_once('lib/utils/utils.php');
include_once('lib/utils/compat.php');
include_once('lib/utils/timezoneutil.php');
include_once('lib/utils/stringstreamwrapper.php');
include_once('lib/core/zpushdefs.php');
include_once('lib/core/stateobject.php');
include_once('lib/core/interprocessdata.php');
include_once('lib/core/pingtracking.php');
include_once('lib/core/topcollector.php');
include_once('lib/core/loopdetection.php');
include_once('lib/core/asdevice.php');
include_once('lib/core/statemanager.php');
include_once('lib/core/devicemanager.php');
include_once('lib/core/zpush.php');
include_once('include/z_syslog.php');
include_once('lib/core/zlog.php');
include_once('lib/interface/ibackend.php');
include_once('lib/interface/ichanges.php');
include_once('lib/interface/iexportchanges.php');
include_once('lib/interface/iimportchanges.php');
include_once('lib/interface/isearchprovider.php');
include_once('lib/interface/istatemachine.php');
include_once('lib/core/streamer.php');
include_once('lib/core/streamimporter.php');
include_once('lib/core/synccollections.php');
include_once('lib/core/hierarchycache.php');
include_once('lib/core/changesmemorywrapper.php');
include_once('lib/core/syncparameters.php');
include_once('lib/core/bodypreference.php');
include_once('lib/core/contentparameters.php');
include_once('lib/wbxml/wbxmldefs.php');
include_once('lib/wbxml/wbxmldecoder.php');
include_once('lib/wbxml/wbxmlencoder.php');
include_once('lib/syncobjects/syncobject.php');
include_once('lib/syncobjects/syncbasebody.php');
include_once('lib/syncobjects/syncbaseattachment.php');
include_once('lib/syncobjects/syncmailflags.php');
include_once('lib/syncobjects/syncrecurrence.php');
include_once('lib/syncobjects/syncappointment.php');
include_once('lib/syncobjects/syncappointmentexception.php');
include_once('lib/syncobjects/syncattachment.php');
include_once('lib/syncobjects/syncattendee.php');
include_once('lib/syncobjects/syncmeetingrequestrecurrence.php');
include_once('lib/syncobjects/syncmeetingrequest.php');
include_once('lib/syncobjects/syncmail.php');
include_once('lib/syncobjects/syncnote.php');
include_once('lib/syncobjects/synccontact.php');
include_once('lib/syncobjects/syncfolder.php');
include_once('lib/syncobjects/syncprovisioning.php');
include_once('lib/syncobjects/synctaskrecurrence.php');
include_once('lib/syncobjects/synctask.php');
include_once('lib/syncobjects/syncoofmessage.php');
include_once('lib/syncobjects/syncoof.php');
include_once('lib/syncobjects/syncuserinformation.php');
include_once('lib/syncobjects/syncdeviceinformation.php');
include_once('lib/syncobjects/syncdevicepassword.php');
include_once('lib/syncobjects/syncitemoperationsattachment.php');
include_once('lib/syncobjects/syncsendmail.php');
include_once('lib/syncobjects/syncsendmailsource.php');
include_once('lib/syncobjects/syncvalidatecert.php');
include_once('lib/syncobjects/syncresolverecipients.php');
include_once('lib/syncobjects/syncresolverecipient.php');
include_once('lib/syncobjects/syncresolverecipientsresponse.php');
include_once('lib/syncobjects/syncresolverecipientsoptions.php');
include_once('lib/syncobjects/syncresolverecipientsavailability.php');
include_once('lib/syncobjects/syncresolverecipientscertificates.php');
include_once('lib/syncobjects/syncresolverecipientspicture.php');
include_once('lib/default/backend.php');
include_once('lib/default/searchprovider.php');
include_once('lib/request/request.php');
include_once('lib/request/requestprocessor.php');
if (!defined('ZPUSH_CONFIG')) define('ZPUSH_CONFIG', 'config.php'); if (!defined('ZPUSH_CONFIG')) define('ZPUSH_CONFIG', 'config.php');
include_once(ZPUSH_CONFIG); include_once(ZPUSH_CONFIG);
include_once('version.php');
// Attempt to set maximum execution time // Attempt to set maximum execution time
...@@ -165,7 +93,7 @@ include_once('version.php'); ...@@ -165,7 +93,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
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* Created : 11.04.2011 * Created : 11.04.2011
* *
* Copyright 2007 - 2013 Zarafa Deutschland GmbH * Copyright 2007 - 2015 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,
...@@ -68,6 +68,7 @@ class ASDevice extends StateObject { ...@@ -68,6 +68,7 @@ class ASDevice extends StateObject {
'ignoredmessages' => array(), 'ignoredmessages' => array(),
'announcedASversion' => false, 'announcedASversion' => false,
'foldersynccomplete' => true, 'foldersynccomplete' => true,
'additionalfolders' => array(),
); );
static private $loadedData; static private $loadedData;
...@@ -686,4 +687,155 @@ class ASDevice extends StateObject { ...@@ -686,4 +687,155 @@ class ASDevice extends StateObject {
return true; return true;
} }
/**----------------------------------------------------------------------------------------------------------
* Additional Folders operations
*/
/**
* Returns a list of all additional folders of this device.
*
* @access public
* @return array
*/
public function GetAdditionalFolders() {
return array_values($this->additionalfolders);
}
/**
* Returns an additional folder by folder ID.
*
* @param string $folderid
*
* @access public
* @return array|false Returns a list of properties. Else false if folder id is unknown.
*/
public function GetAdditionalFolder($folderid) {
// check if the $folderid is one of our own - this will in mostly NOT be the case, so we do not log here
if (!isset($this->additionalfolders[$folderid])) {
return false;
}
return $this->additionalfolders[$folderid];
}
/**
* Adds an additional folder to this device & user.
*
* @param string $store the store where this folder is located, e.g. "SYSTEM" (for public folder) or a username.
* @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 $type AS foldertype of SYNC_FOLDER_TYPE_USER_*
*
* @access public
* @return boolean
*/
public function AddAdditionalFolder($store, $folderid, $name, $type) {
// check if type is of a additional user type
if (!in_array($type, array(SYNC_FOLDER_TYPE_USER_CONTACT, SYNC_FOLDER_TYPE_USER_APPOINTMENT, SYNC_FOLDER_TYPE_USER_TASK, SYNC_FOLDER_TYPE_USER_MAIL, SYNC_FOLDER_TYPE_USER_NOTE, SYNC_FOLDER_TYPE_USER_JOURNAL))) {
ZLog::Write(LOGLEVEL_ERROR, sprintf("ASDevice->AddAdditionalFolder(): folder can not be added because the specified type '%s' is not a permitted user type.", $type));
return false;
}
// check if a folder with this ID is already in the list
if (isset($this->additionalfolders[$folderid])) {
ZLog::Write(LOGLEVEL_ERROR, sprintf("ASDevice->AddAdditionalFolder(): folder can not be added because there is already an additional folder with the same folder id: '%s'", $folderid));
return false;
}
// check if a folder with that Name is already in the list
foreach ($this->additionalfolders as $k => $folder) {
if ($folder['name'] == $name) {
ZLog::Write(LOGLEVEL_ERROR, sprintf("ASDevice->AddAdditionalFolder(): folder can not be added because there is already an additional folder with the same name: '%s'", $name));
return false;
}
}
// check if a folder with this ID or Name is already known on the device (regular folder)
foreach($this->GetHierarchyCache()->ExportFolders() as $syncedFolderid => $folder) {
if ($syncedFolderid == $folderid) {
ZLog::Write(LOGLEVEL_ERROR, sprintf("ASDevice->AddAdditionalFolder(): folder can not be added because there is already a folder with the same folder id synchronized: '%s'", $folderid));
return false;
}
// $folder is a SyncFolder object here
if ($folder->displayname == $name) {
ZLog::Write(LOGLEVEL_ERROR, sprintf("ASDevice->AddAdditionalFolder(): folder can not be added because there is already a folder with the same name synchronized: '%s'", $name));
return false;
}
}
// add the folder
$af = $this->additionalfolders;
$af[$folderid] = array(
'store' => $store,
'folderid' => $folderid,
'name' => $name,
'type' => $type,
);
$this->additionalfolders = $af;
return true;
}
/**
* Edits (sets a new name) for an additional folder. Store, folderid and type can not be edited. Remove and add instead.
*
* @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).
*
* @access public
* @return boolean
*/
public function EditAdditionalFolder($folderid, $name) {
// check if a folder with this ID is known
if (!isset($this->additionalfolders[$folderid])) {
ZLog::Write(LOGLEVEL_ERROR, sprintf("ASDevice->EditAdditionalFolder(): folder can not be edited because there is no folder known with this folder id: '%s'. Add the folder first.", $folderid));
return false;
}
// check if a folder with the new name is already in the list
foreach ($this->additionalfolders as $k => $folder) {
if ($folder['name'] == $name) {
ZLog::Write(LOGLEVEL_ERROR, sprintf("ASDevice->EditAdditionalFolder(): folder can not be added because there is already an additional folder with the same name: '%s'", $name));
return false;
}
}
// check if a folder with the new name is already known on the device (regular folder)
foreach($this->GetHierarchyCache()->ExportFolders() as $syncedFolderid => $folder) {
// $folder is a SyncFolder object here
if ($folder->displayname == $name) {
ZLog::Write(LOGLEVEL_ERROR, sprintf("ASDevice->EditAdditionalFolder(): folder can not be added because there is already a folder with the same name synchronized: '%s'", $folderid));
return false;
}
}
// update the name
$af = $this->additionalfolders;
$af[$folderid]['name'] = $name;
$this->additionalfolders = $af;
return true;
}
/**
* Removes an additional folder from this device & user.
*
* @access public
* @return boolean
*/
public function RemoveAdditionalFolder($folderid) {
// check if a folder with this ID is known
if (!isset($this->additionalfolders[$folderid])) {
ZLog::Write(LOGLEVEL_ERROR, sprintf("ASDevice->RemoveAdditionalFolder(): folder can not be removed because there is no folder known with this folder id: '%s'", $folderid));
return false;
}
// remove the folder
$af = $this->additionalfolders;
unset($af[$folderid]);
$this->additionalfolders = $af;
return true;
}
} }
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* Created : 11.04.2011 * Created : 11.04.2011
* *
* Copyright 2007 - 2013 Zarafa Deutschland GmbH * Copyright 2007 - 2015 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,
...@@ -403,6 +403,46 @@ class DeviceManager { ...@@ -403,6 +403,46 @@ class DeviceManager {
return $class; return $class;
} }
/**
* Returns the additional folders as SyncFolder objects.
*
* @access public
* @return array of SyncFolder
*/
public function GetAdditionalUserSyncFolders() {
$folders = array();
foreach($this->device->GetAdditionalFolders() as $df) {
$folder = new SyncFolder();
$folder->serverid = $df['folderid'];
$folder->parentid = 0; // only top folders are supported
$folder->displayname = $df['name'];
$folder->type = $df['type'];
// save store as custom property which is not streamed directly to the device
$folder->NoBackendFolder = true;
$folder->Store = $df['store'];
$folders[$folder->serverid] = $folder;
}
return $folders;
}
/**
* Get the store of an additional folder.
*
* @param string $folderid
*
* @access public
* @return boolean|string
*/
public function GetAdditionalUserSyncFolderStore($folderid) {
$f = $this->device->GetAdditionalFolder($folderid);
if ($f) {
return $f['store'];
}
return false;
}
/** /**
* Checks if the message should be streamed to a mobile * Checks if the message should be streamed to a mobile
* Should always be called before a message is sent to the mobile * Should always be called before a message is sent to the mobile
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* Created : 20.10.2011 * Created : 20.10.2011
* *
* Copyright 2007 - 2013 Zarafa Deutschland GmbH * Copyright 2007 - 2015 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,
...@@ -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;
} }
...@@ -572,12 +572,12 @@ class LoopDetection extends InterProcessData { ...@@ -572,12 +572,12 @@ class LoopDetection extends InterProcessData {
$obsolete = true; $obsolete = true;
} }
else { else {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("LoopDetection->IsSyncStateObsolete(): check folderid: '%s' uuid '%s' counter: %d - last counter: %d with %d queued", ZLog::Write(LOGLEVEL_DEBUG, sprintf("LoopDetection->IsSyncStateObsolete(): check folderid: '%s' uuid '%s' counter: %d - last counter: %d with %d queued",
$folderid, $uuid, $counter, $current["count"], $current["queued"])); $folderid, $uuid, $counter, $current["count"], $current["queued"]));
if ($current["uuid"] == $uuid && ( if ($current["uuid"] == $uuid && (
$current["count"] > $counter || $current["count"] > $counter ||
($current["count"] == $counter && $current["queued"] > 0) || ($current["count"] == $counter && $current["queued"] > 0) ||
(isset($current["usage"]) && $current["usage"] >= $counter) (isset($current["usage"]) && $current["usage"] >= $counter)
)) { )) {
$usage = isset($current["usage"]) ? sprintf(" - counter %d already expired",$current["usage"]) : ""; $usage = isset($current["usage"]) ? sprintf(" - counter %d already expired",$current["usage"]) : "";
...@@ -736,7 +736,7 @@ class LoopDetection extends InterProcessData { ...@@ -736,7 +736,7 @@ class LoopDetection extends InterProcessData {
ZLog::Write(LOGLEVEL_DEBUG, "LoopDetection->Detect(): case 3.1 detected - loop detected, init loop mode"); ZLog::Write(LOGLEVEL_DEBUG, "LoopDetection->Detect(): case 3.1 detected - loop detected, init loop mode");
$current['loopcount'] = 1; $current['loopcount'] = 1;
// the MaxCount is the max number of messages exported before // the MaxCount is the max number of messages exported before
$current['maxCount'] = $counter + (($maxItems < $queuedMessages)? $maxItems: $queuedMessages); $current['maxCount'] = $counter + (($maxItems < $queuedMessages) ? $maxItems : $queuedMessages);
$loop = true; // loop mode!! $loop = true; // loop mode!!
} }
else if ($queuedMessages == 0) { else if ($queuedMessages == 0) {
...@@ -758,7 +758,7 @@ class LoopDetection extends InterProcessData { ...@@ -758,7 +758,7 @@ class LoopDetection extends InterProcessData {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("LoopDetection->Detect(): case 3.3.1 detected - broken item should be next, attempt to ignore it - id '%s'", $current['potential'])); ZLog::Write(LOGLEVEL_DEBUG, sprintf("LoopDetection->Detect(): case 3.3.1 detected - broken item should be next, attempt to ignore it - id '%s'", $current['potential']));
$this->ignore_messageid = $current['potential']; $this->ignore_messageid = $current['potential'];
} }
$current['maxCount'] = $counter + $queuedMessages; $current['maxCount'] = $counter + (($maxItems < $queuedMessages) ? $maxItems : $queuedMessages);
$loop = true; // loop mode!! $loop = true; // loop mode!!
} }
} }
......
...@@ -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);
} }
catch (\Exception $e) {
// should we write this into the user log? //@TODO How should we handle logging error ?
if ($loglevel <= LOGUSERLEVEL && self::$userLog) { // Ignore any error.
// 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;
}
}
if (($loglevel & LOGLEVEL_FATAL) || ($loglevel & LOGLEVEL_ERROR)) {
self::writeToLog($loglevel, $data, LOGERRORFILE);
} }
if ($loglevel & LOGLEVEL_WBXMLSTACK) { if ($loglevel & LOGLEVEL_WBXMLSTACK) {
self::$wbxmlDebug .= $message. "\n"; self::$wbxmlDebug .= $message . PHP_EOL;
} }
} }
...@@ -193,101 +151,41 @@ class ZLog { ...@@ -193,101 +151,41 @@ 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) {
if (RequestProcessor::isUserAuthenticated()) { $logger = LOGBACKEND_CLASS;
$authuser = Request::GetAuthUser(); if (!class_exists($logger)) {
if ($authuser && in_array($authuser, $specialLogUsers)) $errmsg = 'The configured logging class `'.$logger.'` does not exist. Check your configuration.';
self::$authUser = preg_replace('/[^a-z0-9]/', '_', strtolower($authuser)); error_log($errmsg);
throw new \Exception($errmsg);
} }
}
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) self::$logger = new $logger();
return self::$pidstr . self::getLogLevelString($loglevel, (LOGLEVEL > LOGLEVEL_INFO)) . " " . self::$user . self::$devid; self::$logger->SetUser($user);
else self::$logger->SetAuthUser(Request::GetAuthUser());
return Utils::GetFormattedTime() . " " . self::$pidstr . self::getLogLevelString($loglevel, (LOGLEVEL > LOGLEVEL_INFO)) . " " . self::$user . self::$devid; self::$logger->SetSpecialLogUsers($specialLogUsers);
} self::$logger->SetDevid('['. Request::GetDeviceID() .']');
self::$logger->SetPidstr('[' . str_pad(@getmypid(),5," ",STR_PAD_LEFT) . ']');
/** self::$logger->AfterInitialize();
* Returns the string representation of the LOGLEVEL.
* String can be padded
*
* @param int $loglevel one of the LOGLEVELs
* @param boolean $pad
*
* @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);
}
}
}
} }
/**---------------------------------------------------------------------------------------------------------- /**----------------------------------------------------------------------------------------------------------
......
This diff is collapsed.
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Created : 01.10.2007 * Created : 01.10.2007
* *
* Copyright 2007 - 2013 Zarafa Deutschland GmbH * Copyright 2007 - 2015 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,
...@@ -324,6 +324,7 @@ define("SYNC_FOLDERHIERARCHY_COUNT","FolderHierarchy:Count"); ...@@ -324,6 +324,7 @@ define("SYNC_FOLDERHIERARCHY_COUNT","FolderHierarchy:Count");
define("SYNC_FOLDERHIERARCHY_VERSION","FolderHierarchy:Version"); define("SYNC_FOLDERHIERARCHY_VERSION","FolderHierarchy:Version");
// only for internal use - never to be streamed to the mobile // only for internal use - never to be streamed to the mobile
define("SYNC_FOLDERHIERARCHY_IGNORE_STORE","FolderHierarchy:IgnoreStore"); define("SYNC_FOLDERHIERARCHY_IGNORE_STORE","FolderHierarchy:IgnoreStore");
define("SYNC_FOLDERHIERARCHY_IGNORE_NOBCKENDFLD","FolderHierarchy:IgnoreNoBackendFolder");
// MeetingResponse // MeetingResponse
define("SYNC_MEETINGRESPONSE_CALENDARID","MeetingResponse:CalendarId"); define("SYNC_MEETINGRESPONSE_CALENDARID","MeetingResponse:CalendarId");
......
...@@ -183,8 +183,22 @@ abstract class Backend implements IBackend { ...@@ -183,8 +183,22 @@ abstract class Backend implements IBackend {
* @return SyncObject $settings * @return SyncObject $settings
*/ */
public function Settings($settings) { public function Settings($settings) {
if ($settings instanceof SyncOOF || $settings instanceof SyncUserInformation) if ($settings instanceof SyncOOF) {
$isget = !empty($settings->bodytype);
$settings = new SyncOOF();
if ($isget) {
//oof get
$settings->oofstate = 0;
$settings->Status = SYNC_SETTINGSSTATUS_SUCCESS;
} else {
//oof set
$settings->Status = SYNC_SETTINGSSTATUS_PROTOCOLLERROR;
}
}
if ($settings instanceof SyncUserInformation) {
$settings->emailaddresses = array(ZPush::GetBackend()->GetUserDetails(Request::GetAuthUser())['emailaddress']);
$settings->Status = SYNC_SETTINGSSTATUS_SUCCESS; $settings->Status = SYNC_SETTINGSSTATUS_SUCCESS;
}
return $settings; return $settings;
} }
...@@ -303,7 +317,7 @@ abstract class Backend implements IBackend { ...@@ -303,7 +317,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) { }
......
This diff is collapsed.
This diff is collapsed.
...@@ -55,8 +55,8 @@ class ZPushException extends Exception { ...@@ -55,8 +55,8 @@ class ZPushException extends Exception {
if (!$logLevel) if (!$logLevel)
$logLevel = $this->defaultLogLevel; $logLevel = $this->defaultLogLevel;
ZLog::Write($logLevel, get_class($this) .': '. $message . ' - code: '.$code, false);
parent::__construct($message, (int) $code); parent::__construct($message, (int) $code);
ZLog::Write($logLevel, get_class($this) .': '. $message . ' - code: '.$code. ' - file: '. $this->getFile().':'.$this->getLine(), false);
} }
public function getHTTPCodeString() { public function getHTTPCodeString() {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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