Commit 78a21b31 authored by Sebastian Kummer's avatar Sebastian Kummer

Merge pull request #580 in ZP/z-push from...

Merge pull request #580 in ZP/z-push from feature/ZP-1271-impersonate-shared-folders-with-own to develop

* commit '593e8ae3':
  ZP-1271 Fixed whitespace.
  ZP-1271 Fixed typo & whitespace.
  ZP-1271 Overwrite user only if no specific username was requested.
  ZP-1271 Impersonating support for the Kopano backend. Send-As with OL working correctly.
  ZP-1271 Correctly set exporter to false if root can not be determined for hierarchy export.
parents 8479539b 593e8ae3
...@@ -82,16 +82,16 @@ class ExportChangesICS implements IExportChanges{ ...@@ -82,16 +82,16 @@ class ExportChangesICS implements IExportChanges{
} }
// Get the actual ICS exporter // Get the actual ICS exporter
if($folderid) { if ($folder) {
if ($folder) { if ($folderid) {
$this->exporter = mapi_openproperty($folder, PR_CONTENTS_SYNCHRONIZER, IID_IExchangeExportChanges, 0 , 0); $this->exporter = mapi_openproperty($folder, PR_CONTENTS_SYNCHRONIZER, IID_IExchangeExportChanges, 0 , 0);
} }
else { else {
$this->exporter = false; $this->exporter = mapi_openproperty($folder, PR_HIERARCHY_SYNCHRONIZER, IID_IExchangeExportChanges, 0 , 0);
} }
} }
else { else {
$this->exporter = mapi_openproperty($folder, PR_HIERARCHY_SYNCHRONIZER, IID_IExchangeExportChanges, 0 , 0); $this->exporter = false;
} }
} }
catch (MAPIException $me) { catch (MAPIException $me) {
......
...@@ -61,6 +61,7 @@ class BackendKopano implements IBackend, ISearchProvider { ...@@ -61,6 +61,7 @@ class BackendKopano implements IBackend, ISearchProvider {
private $wastebasket; private $wastebasket;
private $addressbook; private $addressbook;
private $folderStatCache; private $folderStatCache;
private $impersonateUser;
// KC config parameter for PR_EC_ENABLED_FEATURES / PR_EC_DISABLED_FEATURES // KC config parameter for PR_EC_ENABLED_FEATURES / PR_EC_DISABLED_FEATURES
const MOBILE_ENABLED = 'mobile'; const MOBILE_ENABLED = 'mobile';
...@@ -70,6 +71,7 @@ class BackendKopano implements IBackend, ISearchProvider { ...@@ -70,6 +71,7 @@ class BackendKopano implements IBackend, ISearchProvider {
const FREEBUSYENUMBLOCKS = 50; const FREEBUSYENUMBLOCKS = 50;
const MAXFREEBUSYSLOTS = 32767; // max length of 32k for the MergedFreeBusy element is allowed const MAXFREEBUSYSLOTS = 32767; // max length of 32k for the MergedFreeBusy element is allowed
const HALFHOURSECONDS = 1800; const HALFHOURSECONDS = 1800;
const IMPERSONATE_DELIM = '+share+';
/** /**
* Constructor of the Kopano Backend * Constructor of the Kopano Backend
...@@ -90,6 +92,7 @@ class BackendKopano implements IBackend, ISearchProvider { ...@@ -90,6 +92,7 @@ class BackendKopano implements IBackend, ISearchProvider {
$this->wastebasket = false; $this->wastebasket = false;
$this->session = false; $this->session = false;
$this->folderStatCache = array(); $this->folderStatCache = array();
$this->impersonateUser = false;
ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendKopano using PHP-MAPI version: %s - PHP version: %s", phpversion("mapi"), phpversion())); ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendKopano using PHP-MAPI version: %s - PHP version: %s", phpversion("mapi"), phpversion()));
KopanoChangesWrapper::SetBackend($this); KopanoChangesWrapper::SetBackend($this);
...@@ -139,7 +142,19 @@ class BackendKopano implements IBackend, ISearchProvider { ...@@ -139,7 +142,19 @@ class BackendKopano implements IBackend, ISearchProvider {
*/ */
public function Logon($user, $domain, $pass) { public function Logon($user, $domain, $pass) {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("KopanoBackend->Logon(): Trying to authenticate user '%s'..", $user)); ZLog::Write(LOGLEVEL_DEBUG, sprintf("KopanoBackend->Logon(): Trying to authenticate user '%s'..", $user));
$this->mainUser = strtolower($user);
// check if we are impersonating someone
// $defaultUser will be used for $this->defaultStore
if (stripos($user, self::IMPERSONATE_DELIM) !== false) {
list($this->mainUser, $this->impersonateUser) = explode(self::IMPERSONATE_DELIM, strtolower($user));
ZLog::Write(LOGLEVEL_DEBUG, sprintf("KopanoBackend->Logon(): Impersonation active - authenticating: '%s' - impersonating '%s'", $this->mainUser, $this->impersonateUser));
$defaultUser = $this->impersonateUser;
}
else {
$this->mainUser = strtolower($user);
$this->impersonateUser = false;
$defaultUser = $this->mainUser;
}
try { try {
// check if notifications are available in php-mapi // check if notifications are available in php-mapi
...@@ -148,16 +163,16 @@ class BackendKopano implements IBackend, ISearchProvider { ...@@ -148,16 +163,16 @@ class BackendKopano implements IBackend, ISearchProvider {
if (Utils::CheckMapiExtVersion('7.2.0')) { if (Utils::CheckMapiExtVersion('7.2.0')) {
$zpush_version = 'Z-Push_' . @constant('ZPUSH_VERSION'); $zpush_version = 'Z-Push_' . @constant('ZPUSH_VERSION');
$user_agent = (Request::GetDeviceID()) ? ZPush::GetDeviceManager()->GetUserAgent() : "unknown"; $user_agent = (Request::GetDeviceID()) ? ZPush::GetDeviceManager()->GetUserAgent() : "unknown";
$this->session = @mapi_logon_zarafa($user, $pass, MAPI_SERVER, null, null, 0, $zpush_version, $user_agent); $this->session = @mapi_logon_zarafa($this->mainUser, $pass, MAPI_SERVER, null, null, 0, $zpush_version, $user_agent);
} }
else { else {
$this->session = @mapi_logon_zarafa($user, $pass, MAPI_SERVER, null, null, 0); $this->session = @mapi_logon_zarafa($this->mainUser, $pass, MAPI_SERVER, null, null, 0);
} }
$this->notifications = true; $this->notifications = true;
} }
// old fashioned session // old fashioned session
else { else {
$this->session = @mapi_logon_zarafa($user, $pass, MAPI_SERVER); $this->session = @mapi_logon_zarafa($this->mainUser, $pass, MAPI_SERVER);
$this->notifications = false; $this->notifications = false;
} }
...@@ -172,7 +187,7 @@ class BackendKopano implements IBackend, ISearchProvider { ...@@ -172,7 +187,7 @@ class BackendKopano implements IBackend, ISearchProvider {
} }
if(!$this->session) { if(!$this->session) {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("KopanoBackend->Logon(): logon failed for user '%s'", $user)); ZLog::Write(LOGLEVEL_DEBUG, sprintf("KopanoBackend->Logon(): logon failed for user '%s'", $this->mainUser));
$this->defaultstore = false; $this->defaultstore = false;
return false; return false;
} }
...@@ -180,16 +195,22 @@ class BackendKopano implements IBackend, ISearchProvider { ...@@ -180,16 +195,22 @@ class BackendKopano implements IBackend, ISearchProvider {
// Get/open default store // Get/open default store
$this->defaultstore = $this->openMessageStore($this->mainUser); $this->defaultstore = $this->openMessageStore($this->mainUser);
// To impersonate, we overwrite the defaultstore. We still need to open it before we can do that.
if ($this->impersonateUser) {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("KopanoBackend->Logon(): Impersonating user '%s'", $defaultUser));
$this->defaultstore = $this->openMessageStore($defaultUser);
}
if (mapi_last_hresult() == MAPI_E_FAILONEPROVIDER) if (mapi_last_hresult() == MAPI_E_FAILONEPROVIDER)
throw new ServiceUnavailableException("Error connecting to KC (open store)"); throw new ServiceUnavailableException("Error connecting to KC (open store)");
if($this->defaultstore === false) if($this->defaultstore === false)
throw new AuthenticationRequiredException(sprintf("KopanoBackend->Logon(): User '%s' has no default store", $user)); throw new AuthenticationRequiredException(sprintf("KopanoBackend->Logon(): User '%s' has no default store", $defaultUser));
$this->store = $this->defaultstore; $this->store = $this->defaultstore;
$this->storeName = $this->mainUser; $this->storeName = $defaultUser;
ZLog::Write(LOGLEVEL_DEBUG, sprintf("KopanoBackend->Logon(): User '%s' is authenticated",$user)); ZLog::Write(LOGLEVEL_DEBUG, sprintf("KopanoBackend->Logon(): User '%s' is authenticated%s", $this->mainUser, ($this->impersonateUser ? " impersonating '".$this->impersonateUser."'" : '')));
$this->isZPushEnabled(); $this->isZPushEnabled();
...@@ -224,13 +245,19 @@ class BackendKopano implements IBackend, ISearchProvider { ...@@ -224,13 +245,19 @@ class BackendKopano implements IBackend, ISearchProvider {
if (!isset($this->mainUser)) if (!isset($this->mainUser))
return false; return false;
$mainUser = $this->mainUser;
// when impersonating we need to check against the impersonated user
if ($this->impersonateUser) {
$mainUser = $this->impersonateUser;
}
if ($user === false) if ($user === false)
$user = $this->mainUser; $user = $mainUser;
// This is a special case. A user will get his entire folder structure by the foldersync by default. // This is a special case. A user will get his entire folder structure by the foldersync by default.
// The ACL check is executed when an additional folder is going to be sent to the mobile. // The ACL check is executed when an additional folder is going to be sent to the mobile.
// Configured that way the user could receive the same folderid twice, with two different names. // Configured that way the user could receive the same folderid twice, with two different names.
if ($this->mainUser == $user && $checkACLonly && $folderid) { if ($mainUser == $user && $checkACLonly && $folderid) {
ZLog::Write(LOGLEVEL_DEBUG, "KopanoBackend->Setup(): Checking ACLs for folder of the users defaultstore. Fail is forced to avoid folder duplications on mobile."); ZLog::Write(LOGLEVEL_DEBUG, "KopanoBackend->Setup(): Checking ACLs for folder of the users defaultstore. Fail is forced to avoid folder duplications on mobile.");
return false; return false;
} }
...@@ -244,8 +271,8 @@ class BackendKopano implements IBackend, ISearchProvider { ...@@ -244,8 +271,8 @@ class BackendKopano implements IBackend, ISearchProvider {
if ($checkACLonly == true) { if ($checkACLonly == true) {
// check for admin rights // check for admin rights
if (!$folderid) { if (!$folderid) {
if ($user != $this->mainUser) { if ($user != $mainUser) {
$zarafauserinfo = @mapi_zarafa_getuser_by_name($this->defaultstore, $this->mainUser); $zarafauserinfo = @mapi_zarafa_getuser_by_name($this->defaultstore, $mainUser);
$admin = (isset($zarafauserinfo['admin']) && $zarafauserinfo['admin'])?true:false; $admin = (isset($zarafauserinfo['admin']) && $zarafauserinfo['admin'])?true:false;
} }
// the user has always full access to his own store // the user has always full access to his own store
...@@ -499,6 +526,13 @@ class BackendKopano implements IBackend, ISearchProvider { ...@@ -499,6 +526,13 @@ class BackendKopano implements IBackend, ISearchProvider {
} }
} }
// When impersonating we are also "sendingAsSomeone". We also need to switch to the defaultstore
// to put the message in our own Outbox. Kopano will save a copy in the impersonated Sent Items folder.
if ($this->impersonateUser) {
$this->defaultstore = $this->openMessageStore($this->mainUser);
$sendingAsSomeone = true;
}
$sendMailProps = MAPIMapping::GetSendMailProperties(); $sendMailProps = MAPIMapping::GetSendMailProperties();
$sendMailProps = getPropIdsFromStrings($this->defaultstore, $sendMailProps); $sendMailProps = getPropIdsFromStrings($this->defaultstore, $sendMailProps);
...@@ -563,6 +597,7 @@ class BackendKopano implements IBackend, ISearchProvider { ...@@ -563,6 +597,7 @@ class BackendKopano implements IBackend, ISearchProvider {
mapi_deleteprops($mapimessage, mapi_deleteprops($mapimessage,
array( $sendMailProps["sentrepresentingname"], $sendMailProps["sentrepresentingemail"], $sendMailProps["representingentryid"], array( $sendMailProps["sentrepresentingname"], $sendMailProps["sentrepresentingemail"], $sendMailProps["representingentryid"],
$sendMailProps["sentrepresentingaddt"], $sendMailProps["sentrepresentinsrchk"])); $sendMailProps["sentrepresentingaddt"], $sendMailProps["sentrepresentinsrchk"]));
ZLog::Write(LOGLEVEL_DEBUG, "KopanoBackend->SendMail(): removing PR_SENT_REPRESENTING_* properties");
} }
// Processing of KOE X-Push-Receipts header - delivery notification: ZP-1204 // Processing of KOE X-Push-Receipts header - delivery notification: ZP-1204
...@@ -1479,6 +1514,9 @@ class BackendKopano implements IBackend, ISearchProvider { ...@@ -1479,6 +1514,9 @@ class BackendKopano implements IBackend, ISearchProvider {
list($user, $domain) = Utils::SplitDomainUser($store); list($user, $domain) = Utils::SplitDomainUser($store);
if ($user === false) { if ($user === false) {
$user = $this->mainUser; $user = $this->mainUser;
if ($this->impersonateUser) {
$user = $this->impersonateUser;
}
} }
// if there is a ReplyBackImExporter, the exporter needs to run! // if there is a ReplyBackImExporter, the exporter needs to run!
......
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