Commit 43ef5d64 authored by Sebastian Kummer's avatar Sebastian Kummer

ZP-1177 Strip private data from objects that support that, else continue

to ignore them. SyncObject->StripData() now takes uses a flag decide how
to strip.

Released under the Affero GNU General Public License (AGPL) version 3.
parent b3a40500
...@@ -114,15 +114,21 @@ class PHPWrapper { ...@@ -114,15 +114,21 @@ class PHPWrapper {
try { try {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("PHPWrapper->ImportMessageChange(): Getting message from MAPIProvider, sourcekey: '%s', parentsourcekey: '%s', entryid: '%s'", bin2hex($sourcekey), bin2hex($parentsourcekey), bin2hex($entryid))); ZLog::Write(LOGLEVEL_DEBUG, sprintf("PHPWrapper->ImportMessageChange(): Getting message from MAPIProvider, sourcekey: '%s', parentsourcekey: '%s', entryid: '%s'", bin2hex($sourcekey), bin2hex($parentsourcekey), bin2hex($entryid)));
// do not send private messages from shared folders to the device $message = $this->mapiprovider->GetMessage($mapimessage, $this->contentparameters);
// strip or do not send private messages from shared folders to the device
$sensitivity = mapi_getprops($mapimessage, array(PR_SENSITIVITY)); $sensitivity = mapi_getprops($mapimessage, array(PR_SENSITIVITY));
$sharedUser = ZPush::GetAdditionalSyncFolderStore(bin2hex($this->folderid)); $sharedUser = ZPush::GetAdditionalSyncFolderStore(bin2hex($this->folderid));
if ($sharedUser != false && $sharedUser != 'SYSTEM' && isset($sensitivity[PR_SENSITIVITY]) && $sensitivity[PR_SENSITIVITY] >= SENSITIVITY_PRIVATE) { if ($sharedUser != false && $sharedUser != 'SYSTEM' && isset($sensitivity[PR_SENSITIVITY]) && $sensitivity[PR_SENSITIVITY] >= SENSITIVITY_PRIVATE) {
ZLog::Write(LOGLEVEL_DEBUG, "PHPWrapper->ImportMessageChange(): ignoring private message from a shared folder"); if ($message->SupportsPrivateStripping()) {
return SYNC_E_IGNORE; ZLog::Write(LOGLEVEL_DEBUG, "PHPWrapper->ImportMessageChange(): stripping data of private message from a shared folder");
$message->StripData(Streamer::STRIP_PRIVATE_DATA);
}
else {
ZLog::Write(LOGLEVEL_DEBUG, "PHPWrapper->ImportMessageChange(): ignoring private message from a shared folder");
return SYNC_E_IGNORE;
}
} }
$message = $this->mapiprovider->GetMessage($mapimessage, $this->contentparameters);
} }
catch (SyncObjectBrokenException $mbe) { catch (SyncObjectBrokenException $mbe) {
$brokenSO = $mbe->GetSyncObject(); $brokenSO = $mbe->GetSyncObject();
......
...@@ -48,6 +48,9 @@ class Streamer implements Serializable { ...@@ -48,6 +48,9 @@ class Streamer implements Serializable {
const STREAMER_TYPE_MULTIPART = 10; const STREAMER_TYPE_MULTIPART = 10;
const STREAMER_TYPE_STREAM_ASBASE64 = 11; const STREAMER_TYPE_STREAM_ASBASE64 = 11;
const STREAMER_TYPE_STREAM_ASPLAIN = 12; const STREAMER_TYPE_STREAM_ASPLAIN = 12;
const STREAMER_PRIVATE = 13;
const STRIP_PRIVATE_DATA = 1;
const STRIP_PRIVATE_SUBSTITUTE = 'Private';
protected $mapping; protected $mapping;
public $flags; public $flags;
...@@ -353,22 +356,40 @@ class Streamer implements Serializable { ...@@ -353,22 +356,40 @@ class Streamer implements Serializable {
* @access public * @access public
* @return boolean * @return boolean
*/ */
public function StripData() { public function StripData($flags = 0) {
foreach ($this->mapping as $k=>$v) { foreach ($this->mapping as $k=>$v) {
if (isset($this->{$v[self::STREAMER_VAR]})) { if (isset($this->{$v[self::STREAMER_VAR]})) {
if (is_object($this->{$v[self::STREAMER_VAR]}) && method_exists($this->{$v[self::STREAMER_VAR]}, "StripData") ) { if (is_object($this->{$v[self::STREAMER_VAR]}) && method_exists($this->{$v[self::STREAMER_VAR]}, "StripData") ) {
$this->{$v[self::STREAMER_VAR]}->StripData(); $this->{$v[self::STREAMER_VAR]}->StripData($flags);
} }
else if (isset($v[self::STREAMER_ARRAY]) && !empty($this->{$v[self::STREAMER_VAR]})) { else if (isset($v[self::STREAMER_ARRAY]) && !empty($this->{$v[self::STREAMER_VAR]})) {
foreach ($this->{$v[self::STREAMER_VAR]} as $element) { foreach ($this->{$v[self::STREAMER_VAR]} as $element) {
if (is_object($element) && method_exists($element, "StripData") ) { if (is_object($element) && method_exists($element, "StripData") ) {
$element->StripData(); $element->StripData($flags);
}
elseif ($flags === Streamer::STRIP_PRIVATE_DATA && isset($v[self::STREAMER_PRIVATE])) {
if ($v[self::STREAMER_PRIVATE] !== true) {
$this->{$v[self::STREAMER_VAR]} = $v[self::STREAMER_PRIVATE];
}
else {
unset($this->{$v[self::STREAMER_VAR]});
}
} }
} }
} }
elseif ($flags === Streamer::STRIP_PRIVATE_DATA && isset($v[self::STREAMER_PRIVATE])) {
if ($v[self::STREAMER_PRIVATE] !== true) {
$this->{$v[self::STREAMER_VAR]} = $v[self::STREAMER_PRIVATE];
}
else {
unset($this->{$v[self::STREAMER_VAR]});
}
}
} }
} }
unset($this->mapping); if ($flags === 0) {
unset($this->mapping);
}
return true; return true;
} }
......
...@@ -79,13 +79,17 @@ class SyncAppointment extends SyncObject { ...@@ -79,13 +79,17 @@ class SyncAppointment extends SyncObject {
SYNC_POOMCAL_SUBJECT => array ( self::STREAMER_VAR => "subject", SYNC_POOMCAL_SUBJECT => array ( self::STREAMER_VAR => "subject",
self::STREAMER_CHECKS => array( self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETEMPTY), self::STREAMER_CHECKS => array( self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETEMPTY),
self::STREAMER_RONOTIFY => true), self::STREAMER_RONOTIFY => true,
self::STREAMER_PRIVATE => self::STRIP_PRIVATE_SUBSTITUTE ),
SYNC_POOMCAL_UID => array ( self::STREAMER_VAR => "uid"), SYNC_POOMCAL_UID => array ( self::STREAMER_VAR => "uid"),
SYNC_POOMCAL_ORGANIZERNAME => array ( self::STREAMER_VAR => "organizername"), // verified below SYNC_POOMCAL_ORGANIZERNAME => array ( self::STREAMER_VAR => "organizername", // verified below
SYNC_POOMCAL_ORGANIZEREMAIL => array ( self::STREAMER_VAR => "organizeremail"), // verified below self::STREAMER_PRIVATE => 'Undisclosed Organizer' ),
SYNC_POOMCAL_ORGANIZEREMAIL => array ( self::STREAMER_VAR => "organizeremail", // verified below
self::STREAMER_PRIVATE => 'undisclosed@localhost' ),
SYNC_POOMCAL_LOCATION => array ( self::STREAMER_VAR => "location", SYNC_POOMCAL_LOCATION => array ( self::STREAMER_VAR => "location",
self::STREAMER_RONOTIFY => true), self::STREAMER_RONOTIFY => true,
self::STREAMER_PRIVATE => true),
SYNC_POOMCAL_ENDTIME => array ( self::STREAMER_VAR => "endtime", SYNC_POOMCAL_ENDTIME => array ( self::STREAMER_VAR => "endtime",
self::STREAMER_TYPE => self::STREAMER_TYPE_DATE, self::STREAMER_TYPE => self::STREAMER_TYPE_DATE,
self::STREAMER_CHECKS => array( self::STREAMER_CHECK_CMPHIGHER => SYNC_POOMCAL_STARTTIME ), self::STREAMER_CHECKS => array( self::STREAMER_CHECK_CMPHIGHER => SYNC_POOMCAL_STARTTIME ),
...@@ -118,6 +122,7 @@ class SyncAppointment extends SyncObject { ...@@ -118,6 +122,7 @@ class SyncAppointment extends SyncObject {
self::STREAMER_CHECKS => array( self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETTWO, self::STREAMER_CHECKS => array( self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETTWO,
self::STREAMER_CHECK_ONEVALUEOF => array(0,1,2,3,4) ), self::STREAMER_CHECK_ONEVALUEOF => array(0,1,2,3,4) ),
self::STREAMER_RONOTIFY => true, self::STREAMER_RONOTIFY => true,
self::STREAMER_PRIVATE => 2, // if private is stripped, value will be set to 2 (busy)
self::STREAMER_VALUEMAP => array( 0 => "Free", self::STREAMER_VALUEMAP => array( 0 => "Free",
1 => "Tentative", 1 => "Tentative",
2 => "Busy", 2 => "Busy",
...@@ -132,9 +137,11 @@ class SyncAppointment extends SyncObject { ...@@ -132,9 +137,11 @@ class SyncAppointment extends SyncObject {
SYNC_POOMCAL_REMINDER => array ( self::STREAMER_VAR => "reminder", SYNC_POOMCAL_REMINDER => array ( self::STREAMER_VAR => "reminder",
self::STREAMER_CHECKS => array( self::STREAMER_CHECK_CMPHIGHER => -1), self::STREAMER_CHECKS => array( self::STREAMER_CHECK_CMPHIGHER => -1),
self::STREAMER_RONOTIFY => true), self::STREAMER_RONOTIFY => true,
self::STREAMER_PRIVATE => true ), // if private is stripped, value will be unset (no reminder)
SYNC_POOMCAL_RTF => array ( self::STREAMER_VAR => "rtf"), SYNC_POOMCAL_RTF => array ( self::STREAMER_VAR => "rtf",
self::STREAMER_PRIVATE => true),
// Meetingstatus values // Meetingstatus values
// 0 = is not a meeting // 0 = is not a meeting
...@@ -162,11 +169,14 @@ class SyncAppointment extends SyncObject { ...@@ -162,11 +169,14 @@ class SyncAppointment extends SyncObject {
SYNC_POOMCAL_ATTENDEES => array ( self::STREAMER_VAR => "attendees", SYNC_POOMCAL_ATTENDEES => array ( self::STREAMER_VAR => "attendees",
self::STREAMER_TYPE => "SyncAttendee", self::STREAMER_TYPE => "SyncAttendee",
self::STREAMER_ARRAY => SYNC_POOMCAL_ATTENDEE, self::STREAMER_ARRAY => SYNC_POOMCAL_ATTENDEE,
self::STREAMER_RONOTIFY => true), self::STREAMER_RONOTIFY => true,
self::STREAMER_PRIVATE => true),
SYNC_POOMCAL_BODY => array ( self::STREAMER_VAR => "body", SYNC_POOMCAL_BODY => array ( self::STREAMER_VAR => "body",
self::STREAMER_RONOTIFY => true), self::STREAMER_RONOTIFY => true,
SYNC_POOMCAL_BODYTRUNCATED => array ( self::STREAMER_VAR => "bodytruncated"), self::STREAMER_PRIVATE => true),
SYNC_POOMCAL_BODYTRUNCATED => array ( self::STREAMER_VAR => "bodytruncated",
self::STREAMER_PRIVATE => true),
SYNC_POOMCAL_EXCEPTIONS => array ( self::STREAMER_VAR => "exceptions", SYNC_POOMCAL_EXCEPTIONS => array ( self::STREAMER_VAR => "exceptions",
self::STREAMER_TYPE => "SyncAppointmentException", self::STREAMER_TYPE => "SyncAppointmentException",
self::STREAMER_ARRAY => SYNC_POOMCAL_EXCEPTION, self::STREAMER_ARRAY => SYNC_POOMCAL_EXCEPTION,
...@@ -174,13 +184,16 @@ class SyncAppointment extends SyncObject { ...@@ -174,13 +184,16 @@ class SyncAppointment extends SyncObject {
SYNC_POOMCAL_CATEGORIES => array ( self::STREAMER_VAR => "categories", SYNC_POOMCAL_CATEGORIES => array ( self::STREAMER_VAR => "categories",
self::STREAMER_ARRAY => SYNC_POOMCAL_CATEGORY, self::STREAMER_ARRAY => SYNC_POOMCAL_CATEGORY,
self::STREAMER_RONOTIFY => true), self::STREAMER_RONOTIFY => true,
self::STREAMER_PRIVATE => true),
); );
if (Request::GetProtocolVersion() >= 12.0) { if (Request::GetProtocolVersion() >= 12.0) {
$mapping[SYNC_AIRSYNCBASE_BODY] = array ( self::STREAMER_VAR => "asbody", $mapping[SYNC_AIRSYNCBASE_BODY] = array ( self::STREAMER_VAR => "asbody",
self::STREAMER_TYPE => "SyncBaseBody", self::STREAMER_TYPE => "SyncBaseBody",
self::STREAMER_RONOTIFY => true); self::STREAMER_RONOTIFY => true,
self::STREAMER_PRIVATE => true
);
$mapping[SYNC_AIRSYNCBASE_NATIVEBODYTYPE] = array ( self::STREAMER_VAR => "nativebodytype"); $mapping[SYNC_AIRSYNCBASE_NATIVEBODYTYPE] = array ( self::STREAMER_VAR => "nativebodytype");
...@@ -190,7 +203,8 @@ class SyncAppointment extends SyncObject { ...@@ -190,7 +203,8 @@ class SyncAppointment extends SyncObject {
if(Request::GetProtocolVersion() >= 14.0) { if(Request::GetProtocolVersion() >= 14.0) {
$mapping[SYNC_POOMCAL_DISALLOWNEWTIMEPROPOSAL] = array ( self::STREAMER_VAR => "disallownewtimeprop", $mapping[SYNC_POOMCAL_DISALLOWNEWTIMEPROPOSAL] = array ( self::STREAMER_VAR => "disallownewtimeprop",
self::STREAMER_RONOTIFY => true); self::STREAMER_RONOTIFY => true,
self::STREAMER_PRIVATE => 1); // don't permit new time proposal
$mapping[SYNC_POOMCAL_RESPONSEREQUESTED] = array ( self::STREAMER_VAR => "responserequested", $mapping[SYNC_POOMCAL_RESPONSEREQUESTED] = array ( self::STREAMER_VAR => "responserequested",
self::STREAMER_RONOTIFY => true); self::STREAMER_RONOTIFY => true);
$mapping[SYNC_POOMCAL_RESPONSETYPE] = array ( self::STREAMER_VAR => "responsetype", $mapping[SYNC_POOMCAL_RESPONSETYPE] = array ( self::STREAMER_VAR => "responsetype",
...@@ -198,6 +212,9 @@ class SyncAppointment extends SyncObject { ...@@ -198,6 +212,9 @@ class SyncAppointment extends SyncObject {
} }
parent::__construct($mapping); parent::__construct($mapping);
// Indicates that this SyncObject supports the private flag and stripping of private data.
$this->supportsPrivateStripping = true;
} }
/** /**
......
...@@ -61,5 +61,8 @@ class SyncAppointmentException extends SyncAppointment { ...@@ -61,5 +61,8 @@ class SyncAppointmentException extends SyncAppointment {
$this->mapping[SYNC_POOMCAL_REMINDER][self::STREAMER_RONOTIFY] = true; $this->mapping[SYNC_POOMCAL_REMINDER][self::STREAMER_RONOTIFY] = true;
$this->mapping[SYNC_POOMCAL_EXCEPTIONS][self::STREAMER_CHECKS] = array(self::STREAMER_CHECK_NOTALLOWED => true); $this->mapping[SYNC_POOMCAL_EXCEPTIONS][self::STREAMER_CHECKS] = array(self::STREAMER_CHECK_NOTALLOWED => true);
// Indicates that this SyncObject supports the private flag and stripping of private data.
// It behaves as a SyncAppointment.
$this->supportsPrivateStripping = true;
} }
} }
...@@ -35,20 +35,29 @@ class SyncAttendee extends SyncObject { ...@@ -35,20 +35,29 @@ class SyncAttendee extends SyncObject {
$mapping = array( $mapping = array(
SYNC_POOMCAL_EMAIL => array ( self::STREAMER_VAR => "email", SYNC_POOMCAL_EMAIL => array ( self::STREAMER_VAR => "email",
self::STREAMER_CHECKS => array( self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETEMPTY), self::STREAMER_CHECKS => array( self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETEMPTY),
self::STREAMER_RONOTIFY => true), self::STREAMER_RONOTIFY => true,
self::STREAMER_PRIVATE => 'attendee@localhost'),
SYNC_POOMCAL_NAME => array ( self::STREAMER_VAR => "name", SYNC_POOMCAL_NAME => array ( self::STREAMER_VAR => "name",
self::STREAMER_CHECKS => array( self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETEMPTY), self::STREAMER_CHECKS => array( self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETEMPTY),
self::STREAMER_RONOTIFY => true) self::STREAMER_RONOTIFY => true,
self::STREAMER_PRIVATE => 'Undisclosed Attendee')
); );
if (Request::GetProtocolVersion() >= 12.0) { if (Request::GetProtocolVersion() >= 12.0) {
$mapping[SYNC_POOMCAL_ATTENDEESTATUS] = array ( self::STREAMER_VAR => "attendeestatus", $mapping[SYNC_POOMCAL_ATTENDEESTATUS] = array ( self::STREAMER_VAR => "attendeestatus",
self::STREAMER_RONOTIFY => true); self::STREAMER_RONOTIFY => true,
self::STREAMER_PRIVATE => true
);
$mapping[SYNC_POOMCAL_ATTENDEETYPE] = array ( self::STREAMER_VAR => "attendeetype", $mapping[SYNC_POOMCAL_ATTENDEETYPE] = array ( self::STREAMER_VAR => "attendeetype",
self::STREAMER_RONOTIFY => true); self::STREAMER_RONOTIFY => true,
self::STREAMER_PRIVATE => true
);
} }
parent::__construct($mapping); parent::__construct($mapping);
// Indicates that this SyncObject supports the private flag and stripping of private data.
$this->supportsPrivateStripping = true;
} }
} }
...@@ -36,16 +36,23 @@ class SyncBaseBody extends SyncObject { ...@@ -36,16 +36,23 @@ class SyncBaseBody extends SyncObject {
function __construct() { function __construct() {
$mapping = array( $mapping = array(
SYNC_AIRSYNCBASE_TYPE => array (self::STREAMER_VAR => "type"), SYNC_AIRSYNCBASE_TYPE => array (self::STREAMER_VAR => "type"),
SYNC_AIRSYNCBASE_ESTIMATEDDATASIZE => array (self::STREAMER_VAR => "estimatedDataSize"), SYNC_AIRSYNCBASE_ESTIMATEDDATASIZE => array (self::STREAMER_VAR => "estimatedDataSize",
self::STREAMER_PRIVATE => 0), // when stripping private we remove the body, so the size needs to be 0
SYNC_AIRSYNCBASE_TRUNCATED => array (self::STREAMER_VAR => "truncated"), SYNC_AIRSYNCBASE_TRUNCATED => array (self::STREAMER_VAR => "truncated"),
SYNC_AIRSYNCBASE_DATA => array (self::STREAMER_VAR => "data", SYNC_AIRSYNCBASE_DATA => array (self::STREAMER_VAR => "data",
self::STREAMER_TYPE => self::STREAMER_TYPE_STREAM_ASPLAIN, self::STREAMER_TYPE => self::STREAMER_TYPE_STREAM_ASPLAIN,
self::STREAMER_RONOTIFY => true), self::STREAMER_RONOTIFY => true,
self::STREAMER_PRIVATE => true), // just remove the body when stripping private
); );
if(Request::GetProtocolVersion() >= 14.0) { if(Request::GetProtocolVersion() >= 14.0) {
$mapping[SYNC_AIRSYNCBASE_PREVIEW] = array (self::STREAMER_VAR => "preview"); $mapping[SYNC_AIRSYNCBASE_PREVIEW] = array (self::STREAMER_VAR => "preview",
self::STREAMER_PRIVATE => true
);
} }
parent::__construct($mapping); parent::__construct($mapping);
// Indicates that this SyncObject supports the private flag and stripping of private data.
$this->supportsPrivateStripping = true;
} }
} }
...@@ -44,10 +44,12 @@ abstract class SyncObject extends Streamer { ...@@ -44,10 +44,12 @@ abstract class SyncObject extends Streamer {
const STREAMER_CHECK_EMAIL = 16; const STREAMER_CHECK_EMAIL = 16;
protected $unsetVars; protected $unsetVars;
protected $supportsPrivateStripping;
public function __construct($mapping) { public function __construct($mapping) {
$this->unsetVars = array(); $this->unsetVars = array();
$this->supportsPrivateStripping = false;
parent::__construct($mapping); parent::__construct($mapping);
} }
...@@ -368,11 +370,22 @@ abstract class SyncObject extends Streamer { ...@@ -368,11 +370,22 @@ abstract class SyncObject extends Streamer {
* @access public * @access public
* @return boolean * @return boolean
*/ */
public function StripData() { public function StripData($flags = 0) {
if (isset($this->unsetVars)) { if ($flags === 0 && isset($this->unsetVars)) {
unset($this->unsetVars); unset($this->unsetVars);
} }
return parent::StripData(); return parent::StripData($flags);
}
/**
* Indicates if a SyncObject supports the private flag and stripping of private data.
* If an object does not support it, it will not be sent to the client but permanently be excluded from the sync.
*
* @access public
* @return boolean - default false defined in constructor - overwritten by implementation
*/
public function SupportsPrivateStripping() {
return $this->supportsPrivateStripping;
} }
/** /**
......
...@@ -110,5 +110,9 @@ class SyncRecurrence extends SyncObject { ...@@ -110,5 +110,9 @@ class SyncRecurrence extends SyncObject {
} }
parent::__construct($mapping); parent::__construct($mapping);
// Indicates that this SyncObject supports the private flag and stripping of private data.
// There is nothing concrete to be stripped here, but as it's part of an appointment it supports it.
$this->supportsPrivateStripping = true;
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment