grommunio /
grommunio-web
| 1 | <?php |
||
| 2 | /** |
||
| 3 | * DelegatesModule |
||
| 4 | * Class can be used to get delegate information of a particular user. |
||
| 5 | * The delegate information can be created/update using this class as well. |
||
| 6 | */ |
||
| 7 | class DelegatesModule extends Module |
||
| 8 | { |
||
| 9 | /** |
||
| 10 | * @var array contains entryid's of all default folders. |
||
| 11 | */ |
||
| 12 | private $defaultFolders; |
||
| 13 | |||
| 14 | /** |
||
| 15 | * @var array contains delegate properties from special message (LocalFreebusy). |
||
| 16 | */ |
||
| 17 | private $delegateProps; |
||
| 18 | |||
| 19 | /** |
||
| 20 | * @var Resource of LocalFreeBusy Message. This contains $delegateProps for delegates. |
||
| 21 | */ |
||
| 22 | private $localFreeBusyMessage; |
||
| 23 | |||
| 24 | /** |
||
| 25 | * @var Resource of FreeBusy Folder in IPM_SUBTREE. This permissions for freebusy folder used in calendar. |
||
| 26 | */ |
||
| 27 | private $freeBusyFolder; |
||
| 28 | |||
| 29 | /** |
||
| 30 | * @var Resource of default store of the current user. |
||
| 31 | */ |
||
| 32 | private $defaultStore; |
||
| 33 | |||
| 34 | /** |
||
| 35 | * Constructor |
||
| 36 | * @param int $id unique id. |
||
| 37 | * @param array $data list of all actions. |
||
| 38 | */ |
||
| 39 | function __construct($id, $data) |
||
| 40 | { |
||
| 41 | $this->defaultFolders = array(); |
||
| 42 | $this->delegateProps = array(); |
||
| 43 | $this->localFreeBusyMessage = false; |
||
| 44 | $this->freeBusyFolder = false; |
||
| 45 | $this->defaultStore = false; |
||
| 46 | |||
| 47 | parent::__construct($id, $data); |
||
| 48 | } |
||
| 49 | |||
| 50 | /** |
||
| 51 | * Executes all the actions in the $data variable |
||
| 52 | */ |
||
| 53 | function execute() |
||
| 54 | { |
||
| 55 | foreach($this->data as $actionType => $action) |
||
| 56 | { |
||
| 57 | if(isset($actionType)) { |
||
| 58 | try { |
||
| 59 | switch($actionType) |
||
| 60 | { |
||
| 61 | case 'list': |
||
| 62 | $this->delegateList(); |
||
| 63 | break; |
||
| 64 | case 'open': |
||
| 65 | $this->openDelegate($action); |
||
| 66 | break; |
||
| 67 | case 'save': |
||
| 68 | $this->saveDelegates($action); |
||
| 69 | break; |
||
| 70 | case 'delete': |
||
| 71 | $this->deleteDelegates($action); |
||
| 72 | break; |
||
| 73 | default: |
||
| 74 | $this->handleUnknownActionType($actionType); |
||
| 75 | } |
||
| 76 | } catch (MAPIException $e) { |
||
| 77 | $this->processException($e, $actionType); |
||
| 78 | } |
||
| 79 | } |
||
| 80 | } |
||
| 81 | } |
||
| 82 | |||
| 83 | /******** Generic functions to access data ***********/ |
||
| 84 | |||
| 85 | /** |
||
| 86 | * Function will return values of the properties PR_DELEGATES_SEE_PRIVATE, PR_SCHDINFO_DELEGATE_ENTRYIDS and |
||
| 87 | * PR_SCHDINFO_DELEGATE_NAMES from LocalFreeBusyMessage of the user's store. |
||
| 88 | * @param {MAPIMessage} $localFreeBusyMessage (optional) local freebusy message of the user's store. |
||
| 89 | * @return {Array} values of delegate properties. |
||
| 90 | */ |
||
| 91 | function getDelegateProps($localFreeBusyMessage = false) |
||
| 92 | { |
||
| 93 | if(empty($this->delegateProps)) { |
||
| 94 | if($localFreeBusyMessage === false) { |
||
| 95 | $localFreeBusyMessage = freebusy::getLocalFreeBusyMessage(); |
||
| 96 | } |
||
| 97 | |||
| 98 | $this->delegateProps = mapi_getprops($localFreeBusyMessage, array(PR_DELEGATES_SEE_PRIVATE, PR_SCHDINFO_DELEGATE_ENTRYIDS, PR_SCHDINFO_DELEGATE_NAMES)); |
||
| 99 | |||
| 100 | // check if properties exists or not, if not then initialize with default values |
||
| 101 | // this way in caller functions we don't need to check for non-existent properties |
||
| 102 | if(!isset($this->delegateProps[PR_DELEGATES_SEE_PRIVATE])) { |
||
| 103 | $this->delegateProps[PR_DELEGATES_SEE_PRIVATE] = array(); |
||
| 104 | } |
||
| 105 | |||
| 106 | if(!isset($this->delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS])) { |
||
| 107 | $this->delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS] = array(); |
||
| 108 | } |
||
| 109 | |||
| 110 | if(!isset($this->delegateProps[PR_SCHDINFO_DELEGATE_NAMES])) { |
||
| 111 | $this->delegateProps[PR_SCHDINFO_DELEGATE_NAMES] = array(); |
||
| 112 | } |
||
| 113 | } |
||
| 114 | |||
| 115 | return $this->delegateProps; |
||
| 116 | } |
||
| 117 | |||
| 118 | /** |
||
| 119 | * Function will return array of entryids of default folders of the user's store. |
||
| 120 | * @param {MAPIStore} $store (optional) user's store. |
||
| 121 | * @return {Array} default folder entryids. |
||
| 122 | */ |
||
| 123 | function getDefaultFolders($store = false) |
||
| 124 | { |
||
| 125 | if(empty($this->defaultFolders)) { |
||
| 126 | if($store === false) { |
||
| 127 | $store = $this->getDefaultStore(); |
||
| 128 | } |
||
| 129 | |||
| 130 | // Get root store |
||
| 131 | $root = mapi_msgstore_openentry($store, null); |
||
| 132 | |||
| 133 | // Get Inbox folder |
||
| 134 | $inbox = mapi_msgstore_getreceivefolder($store); |
||
| 135 | $inboxprops = mapi_getprops($inbox, Array(PR_ENTRYID)); |
||
| 136 | |||
| 137 | // Get entryids of default folders. |
||
| 138 | $rootStoreProps = mapi_getprops($root, array(PR_IPM_APPOINTMENT_ENTRYID, PR_IPM_TASK_ENTRYID, PR_IPM_CONTACT_ENTRYID, PR_IPM_NOTE_ENTRYID, PR_IPM_JOURNAL_ENTRYID)); |
||
| 139 | |||
| 140 | $this->defaultFolders = array( |
||
| 141 | 'calendar' => $rootStoreProps[PR_IPM_APPOINTMENT_ENTRYID], |
||
| 142 | 'tasks' => $rootStoreProps[PR_IPM_TASK_ENTRYID], |
||
| 143 | 'inbox' => $inboxprops[PR_ENTRYID], |
||
| 144 | 'contacts' => $rootStoreProps[PR_IPM_CONTACT_ENTRYID], |
||
| 145 | 'notes' => $rootStoreProps[PR_IPM_NOTE_ENTRYID], |
||
| 146 | 'journal' => $rootStoreProps[PR_IPM_JOURNAL_ENTRYID] |
||
| 147 | ); |
||
| 148 | } |
||
| 149 | |||
| 150 | return $this->defaultFolders; |
||
| 151 | } |
||
| 152 | |||
| 153 | /** |
||
| 154 | * Function will return index of a particular delegate, this index can be used to get information of |
||
| 155 | * delegate from PR_DELEGATES_SEE_PRIVATE, PR_SCHDINFO_DELEGATE_ENTRYIDS and |
||
| 156 | * PR_SCHDINFO_DELEGATE_NAMES properties. |
||
| 157 | * @param {BinEntryid} $entryId entryid of delegate. |
||
| 158 | * @return {Number} index of the delegate information. |
||
| 159 | */ |
||
| 160 | function getDelegateIndex($entryId) |
||
| 161 | { |
||
| 162 | $delegateProps = $this->getDelegateProps(); |
||
| 163 | |||
| 164 | // Check if user is existing delegate. |
||
| 165 | if(!empty($delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS])) { |
||
| 166 | return array_search($entryId, $delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS]); |
||
| 167 | } else { |
||
| 168 | return false; |
||
| 169 | } |
||
| 170 | } |
||
| 171 | |||
| 172 | /** |
||
| 173 | * Function will return resource of the default store of the current logged in user. |
||
| 174 | * @return {MAPIStore} current user's store. |
||
| 175 | */ |
||
| 176 | function getDefaultStore() |
||
| 177 | { |
||
| 178 | if(!$this->defaultStore) { |
||
| 179 | $this->defaultStore = $GLOBALS['mapisession']->getDefaultMessageStore(); |
||
| 180 | } |
||
| 181 | |||
| 182 | return $this->defaultStore; |
||
| 183 | } |
||
| 184 | |||
| 185 | /** |
||
| 186 | * Function will return properties of the user from addressbook based on passed user's entryid. |
||
| 187 | * @param {BinEntryid} $userEntryId entryid of the user from addressbook. |
||
| 188 | * @return {Array} properties of user from addressbook. |
||
| 189 | */ |
||
| 190 | function getUserInfo($userEntryId) |
||
| 191 | { |
||
| 192 | // default return stuff |
||
| 193 | $result = array( |
||
| 194 | 'display_name' => _('Unknown user/group'), |
||
| 195 | 'entryid' => null |
||
| 196 | ); |
||
| 197 | |||
| 198 | // open the addressbook |
||
| 199 | $ab = $GLOBALS['mapisession']->getAddressbook(); |
||
| 200 | |||
| 201 | try { |
||
| 202 | // try userid as normal user |
||
| 203 | $user = mapi_ab_openentry($ab, $userEntryId); |
||
| 204 | } catch (MAPIException $e) { |
||
| 205 | if($e->getCode() === MAPI_E_NOT_FOUND) { |
||
| 206 | $e->setHandled(); |
||
| 207 | return $result; |
||
| 208 | } |
||
| 209 | } |
||
| 210 | |||
| 211 | $props = mapi_getprops($user, array(PR_DISPLAY_NAME)); |
||
| 212 | $result['display_name'] = $props[PR_DISPLAY_NAME]; |
||
| 213 | $result['entryid'] = bin2hex($userEntryId); |
||
| 214 | |||
| 215 | return $result; |
||
| 216 | } |
||
| 217 | |||
| 218 | /******** Functions to get delegates information ***********/ |
||
| 219 | |||
| 220 | /** |
||
| 221 | * Function will return all the delegates information for current user. |
||
| 222 | */ |
||
| 223 | function delegateList() |
||
| 224 | { |
||
| 225 | $delegateProps = $this->getDelegateProps(); |
||
| 226 | |||
| 227 | $data = array(); |
||
| 228 | |||
| 229 | // get delegate meeting rule |
||
| 230 | $delegateMeetingRule = $this->getDelegateMeetingRule(); |
||
| 231 | |||
| 232 | // Get permissions of all delegates. |
||
| 233 | if(!empty($delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS])) { |
||
| 234 | for($i = 0, $len = count($delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS]); $i < $len; $i++) { |
||
| 235 | array_push($data, $this->getDelegatePermissions($delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS][$i], $delegateMeetingRule)); |
||
| 236 | } |
||
| 237 | } |
||
| 238 | |||
| 239 | $this->addActionData('list', array('item' => $data)); |
||
| 240 | $GLOBALS['bus']->addData($this->getResponseData()); |
||
| 241 | } |
||
| 242 | |||
| 243 | /** |
||
| 244 | * Function will return the permissions assigned for a particular delegate user. |
||
| 245 | * @param {Array} $delegate the delegate information sent by client. |
||
| 246 | */ |
||
| 247 | function openDelegate($delegate) |
||
| 248 | { |
||
| 249 | // Get permissions of a delegate. |
||
| 250 | $data = $this->getDelegatePermissions(hex2bin($delegate['entryid'])); |
||
| 251 | |||
| 252 | $this->addActionData('item', array('item' => $data)); |
||
| 253 | $GLOBALS['bus']->addData($this->getResponseData()); |
||
| 254 | } |
||
| 255 | |||
| 256 | /** |
||
| 257 | * Function will return information of a particular delegate from current user's store. |
||
| 258 | * @param {BinEntryid} $userEntryId entryid of the delegate. |
||
| 259 | * @param {Array} $delegateMeetingRule (optional) information of the delegate meeting rule that can be used to check if |
||
| 260 | * current delegate exists in the meeting rule. |
||
| 261 | * @return {Array} delegate information. |
||
| 262 | */ |
||
| 263 | function getDelegatePermissions($userEntryId, $delegateMeetingRule = false) |
||
| 264 | { |
||
| 265 | $delegateProps = $this->getDelegateProps(); |
||
| 266 | $delegateIndex = $this->getDelegateIndex($userEntryId); |
||
| 267 | $userinfo = $this->getUserInfo($userEntryId); |
||
| 268 | |||
| 269 | $delegate = array(); |
||
| 270 | $delegate['entryid'] = bin2hex($userEntryId); |
||
| 271 | |||
| 272 | $delegate['props'] = array(); |
||
| 273 | $delegate['props']['display_name'] = $userinfo['display_name']; |
||
| 274 | $delegate['props']['can_see_private'] = isset($delegateProps[PR_DELEGATES_SEE_PRIVATE][$delegateIndex]) ? ($delegateProps[PR_DELEGATES_SEE_PRIVATE][$delegateIndex] == 1) : false; |
||
| 275 | |||
| 276 | $delegate['props'] = array_merge($delegate['props'], $this->getFolderPermissions($userEntryId)); |
||
| 277 | |||
| 278 | return $delegate; |
||
| 279 | } |
||
| 280 | |||
| 281 | /** |
||
| 282 | * Function will return folder permissions of a delegate user. |
||
| 283 | * @param {BinEntryid} $userEntryId entryid of the delegate. |
||
| 284 | * @return {Array} folder permissions of a delegate user. |
||
| 285 | */ |
||
| 286 | function getFolderPermissions($userEntryId) |
||
| 287 | { |
||
| 288 | $delegateRights = array(); |
||
| 289 | $store = $this->getDefaultStore(); |
||
| 290 | |||
| 291 | foreach($this->getDefaultFolders($store) as $folderName => $folderEntryId) { |
||
| 292 | $folder = mapi_msgstore_openentry($store, $folderEntryId); |
||
| 293 | |||
| 294 | // Get all users who has permissions |
||
| 295 | $grants = mapi_zarafa_getpermissionrules($folder, ACCESS_TYPE_GRANT); |
||
| 296 | |||
| 297 | // Find current delegate and get permission. |
||
| 298 | foreach($grants as $id => $grant) { |
||
| 299 | if($GLOBALS["entryid"]->compareABEntryIds(bin2hex($userEntryId), bin2hex($grant['userid']))) { |
||
| 300 | $delegateRights['rights_' . $folderName] = $grant['rights']; |
||
| 301 | } |
||
| 302 | } |
||
| 303 | } |
||
| 304 | |||
| 305 | return $delegateRights; |
||
| 306 | } |
||
| 307 | |||
| 308 | /** |
||
| 309 | * Function will return properties of meeting rule that is used to send meeting related messages to delegate. |
||
| 310 | * @return {Array} delegate meeting rule information. |
||
| 311 | */ |
||
| 312 | function getDelegateMeetingRule() |
||
| 313 | { |
||
| 314 | $inbox = mapi_msgstore_getreceivefolder($this->getDefaultStore()); |
||
| 315 | $rulesTable = mapi_folder_getrulestable($inbox); |
||
| 316 | // get delegate meeting rule |
||
| 317 | $restriction = Array(RES_CONTENT, |
||
| 318 | Array( |
||
| 319 | FUZZYLEVEL => FL_FULLSTRING | FL_IGNORECASE, |
||
| 320 | ULPROPTAG => PR_RULE_PROVIDER, |
||
| 321 | VALUE => Array( |
||
| 322 | PR_RULE_PROVIDER => 'Schedule+ EMS Interface' |
||
| 323 | ) |
||
| 324 | ) |
||
| 325 | ); |
||
| 326 | mapi_table_restrict($rulesTable, $restriction); |
||
| 327 | // there will be only one rule, so fetch that only |
||
| 328 | $delegateMeetingRule = mapi_table_queryrows($rulesTable, $GLOBALS['properties']->getRulesProperties(), 0, 1); |
||
| 329 | return !empty($delegateMeetingRule) ? $delegateMeetingRule[0] : false; |
||
| 330 | } |
||
| 331 | |||
| 332 | /******** Functions to update delegates information ***********/ |
||
| 333 | |||
| 334 | /** |
||
| 335 | * Function which saves delegates information sent from client. |
||
| 336 | * @param {Array} $delegates the delegates information sent by client. |
||
| 337 | */ |
||
| 338 | function saveDelegates($delegates) |
||
| 339 | { |
||
| 340 | $responseData = array(); |
||
| 341 | |||
| 342 | // @FIXME currently client only sends a single delegate in a request, if we can change that to contain |
||
| 343 | // multiple delegates that would be good |
||
| 344 | |||
| 345 | if(is_assoc_array($delegates)) { |
||
| 346 | // wrap single delegate in an array |
||
| 347 | $delegates = array($delegates); |
||
| 348 | } |
||
| 349 | |||
| 350 | for($index = 0, $len = count($delegates); $index < $len; $index++) { |
||
| 351 | $delegate = $delegates[$index]; |
||
| 352 | $this->setFolderPermissions($delegate); |
||
| 353 | // set properties for delegates on user's freebusy folder |
||
| 354 | array_push($responseData, array('entryid' => $delegate['entryid'])); |
||
| 355 | } |
||
| 356 | $this->setDelegateProps($delegates); |
||
| 357 | // set delegate meeting rule |
||
| 358 | $this->setDelegateMeetingRule($delegates); |
||
| 359 | |||
| 360 | // send response to indicate success |
||
| 361 | if(!empty($responseData)) { |
||
| 362 | $this->addActionData('update', array('item' => $responseData)); |
||
| 363 | $GLOBALS['bus']->addData($this->getResponseData()); |
||
| 364 | } |
||
| 365 | } |
||
| 366 | |||
| 367 | /** |
||
| 368 | * Function will update PR_DELEGATES_SEE_PRIVATE, PR_SCHDINFO_DELEGATE_ENTRYIDS and |
||
| 369 | * PR_SCHDINFO_DELEGATE_NAMES properties in the current user's store. |
||
| 370 | */ |
||
| 371 | function setDelegateProps($delegates) |
||
| 372 | { |
||
| 373 | $localFreeBusyMessage = freebusy::getLocalFreeBusyMessage(); |
||
| 374 | $delegateProps = $this->getDelegateProps($localFreeBusyMessage); |
||
| 375 | $len = count($delegates); |
||
| 376 | for ($i=0; $i<$len; $i++) { |
||
| 377 | $delegate = $delegates[$i]; |
||
| 378 | $len1 = count($delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS]); |
||
| 379 | for ($j=0; $j<$len1; $j++) { |
||
| 380 | if ($delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS][$j] == hex2bin($delegate['entryid'])) { |
||
| 381 | break; |
||
| 382 | } |
||
| 383 | } |
||
| 384 | $delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS][$j] = hex2bin($delegate['entryid']); |
||
| 385 | if (isset($delegate['props']['display_name'])) { |
||
| 386 | $delegateProps[PR_SCHDINFO_DELEGATE_NAMES][$j] = $delegate['props']['display_name']; |
||
| 387 | } else { |
||
| 388 | $addrBook = $GLOBALS['mapisession']->getAddressbook(); |
||
| 389 | $user = mapi_ab_openentry($addrBook, hex2bin($delegate['entryid'])); |
||
| 390 | if (empty($user)) { |
||
| 391 | $delegateProps[PR_SCHDINFO_DELEGATE_NAMES][$j] = ""; |
||
| 392 | } else { |
||
| 393 | $userProps = mapi_getprops($user, array(PR_SMTP_ADDRESS)); |
||
| 394 | if (empty($userProps[PR_SMTP_ADDRESS])) { |
||
| 395 | $delegateProps[PR_SCHDINFO_DELEGATE_NAMES][$j] = ""; |
||
| 396 | } else { |
||
| 397 | $delegateProps[PR_SCHDINFO_DELEGATE_NAMES][$j] = $userProps[PR_SMTP_ADDRESS]; |
||
| 398 | } |
||
| 399 | } |
||
| 400 | } |
||
| 401 | if (isset($delegate['props']['can_see_private'])) { |
||
| 402 | $delegateProps[PR_DELEGATES_SEE_PRIVATE][$j] = $delegate['props']['can_see_private']; |
||
| 403 | } else { |
||
| 404 | $delegateProps[PR_DELEGATES_SEE_PRIVATE][$j] = false; |
||
| 405 | } |
||
| 406 | } |
||
| 407 | mapi_setprops($localFreeBusyMessage, $delegateProps); |
||
| 408 | mapi_savechanges($localFreeBusyMessage); |
||
| 409 | // unset the module variable, so subsequent calls will have the updated value |
||
| 410 | unset($this->delegateProps); |
||
| 411 | } |
||
| 412 | |||
| 413 | /** |
||
| 414 | * Function will set folder permissions for a delegate user. |
||
| 415 | * @param {Array} $delegate delegate information sent from client. |
||
| 416 | */ |
||
| 417 | function setFolderPermissions($delegate) |
||
| 418 | { |
||
| 419 | $store = $this->getDefaultStore(); |
||
| 420 | |||
| 421 | // Get all default folders and set permissions. |
||
| 422 | foreach($this->getDefaultFolders($store) as $folderName => $folderEntryID) { |
||
| 423 | // we need to only modify those permissions which are modified on client |
||
| 424 | if(isset($delegate['props']['rights_' . $folderName]) && $delegate['props']['rights_' . $folderName] !== '') { |
||
| 425 | $folder = mapi_msgstore_openentry($store, $folderEntryID); |
||
| 426 | |||
| 427 | // Set new permissions. |
||
| 428 | $acls = array( |
||
| 429 | array( |
||
| 430 | 'type' => ACCESS_TYPE_GRANT, |
||
| 431 | 'userid' => hex2bin($delegate['entryid']), |
||
| 432 | 'rights' => $delegate['props']['rights_' . $folderName], |
||
| 433 | 'state' => RIGHT_NEW | RIGHT_AUTOUPDATE_DENIED |
||
| 434 | ) |
||
| 435 | ); |
||
| 436 | |||
| 437 | mapi_zarafa_setpermissionrules($folder, $acls); |
||
| 438 | mapi_savechanges($folder); |
||
| 439 | |||
| 440 | if ($folderName === 'calendar') { |
||
| 441 | $freeBusyFolder = freebusy::getLocalFreeBusyFolder($store); |
||
| 442 | |||
| 443 | if(isset($freeBusyFolder)) { |
||
| 444 | // set permissions on free/busy message |
||
| 445 | $acls[0]['rights'] |= ecRightsDefaultPublic; |
||
| 446 | |||
| 447 | mapi_zarafa_setpermissionrules($freeBusyFolder, $acls); |
||
| 448 | mapi_savechanges($freeBusyFolder); |
||
| 449 | } |
||
| 450 | } |
||
| 451 | } |
||
| 452 | } |
||
| 453 | } |
||
| 454 | |||
| 455 | /** |
||
| 456 | * Function which creates/modifies delegate meeting rule in user store |
||
| 457 | * to send meeting request mails to delegates also. |
||
| 458 | * @param {Array} $delegates all delegate information |
||
| 459 | */ |
||
| 460 | function setDelegateMeetingRule($delegates) |
||
| 461 | { |
||
| 462 | $delegateMeetingRule = $this->getDelegateMeetingRule(); |
||
| 463 | if (isset($delegateMeetingRule)) { |
||
| 464 | $users = $delegateMeetingRule[PR_RULE_ACTIONS][0]['adrlist']; |
||
| 465 | } else { |
||
| 466 | $users = array(); |
||
| 467 | } |
||
| 468 | // open addressbook to get information of all users |
||
| 469 | $addrBook = $GLOBALS['mapisession']->getAddressbook(); |
||
| 470 | $len = count($delegates); |
||
| 471 | for ($i=0; $i<$len; $i++) { |
||
| 472 | $delegate = $delegates[$i]; |
||
| 473 | // get user info, using entryid |
||
| 474 | $user = mapi_ab_openentry($addrBook, hex2bin($delegate['entryid'])); |
||
| 475 | $userProps = mapi_getprops($user, Array(PR_ENTRYID, PR_ADDRTYPE, PR_EMAIL_ADDRESS, PR_DISPLAY_NAME, PR_SEARCH_KEY, PR_SMTP_ADDRESS, PR_OBJECT_TYPE, PR_DISPLAY_TYPE, PR_DISPLAY_TYPE_EX)); |
||
| 476 | |||
| 477 | if (is_array($userProps)) { |
||
| 478 | // add recipient type prop, to specify type of recipient in mail |
||
| 479 | $userProps[PR_RECIPIENT_TYPE] = MAPI_TO; |
||
| 480 | $len1 = count($users); |
||
| 481 | for ($j=0; $j<$len1; $j++) { |
||
| 482 | if ($userProps[PR_ENTRYID] == $users[$j][PR_ENTRYID]) { |
||
| 483 | break; |
||
| 484 | } |
||
| 485 | } |
||
| 486 | $users[$j] = $userProps; |
||
| 487 | } |
||
| 488 | } |
||
| 489 | // only continue if any delegate has set the flag |
||
| 490 | if (!empty($users)) { |
||
| 491 | if ($delegateMeetingRule === false) { |
||
| 492 | $this->createDelegateMeetingRule($users); |
||
| 493 | } else { |
||
| 494 | $this->modifyDelegateMeetingRule($delegateMeetingRule, $users); |
||
| 495 | } |
||
| 496 | } |
||
| 497 | } |
||
| 498 | |||
| 499 | /** |
||
| 500 | * Function will create a new delegate meeting rule if it is not present in current user's store. |
||
| 501 | * @param {Array} $usersInfo user properties which should be added in PR_RULE_ACTIONS. |
||
| 502 | */ |
||
| 503 | function createDelegateMeetingRule($usersInfo) |
||
| 504 | { |
||
| 505 | // create new rule |
||
| 506 | $rule = Array(); |
||
| 507 | |||
| 508 | // no need to pass rule_id when creating new rule |
||
| 509 | $rule[PR_RULE_ACTIONS] = Array( |
||
| 510 | Array( |
||
| 511 | 'action' => OP_DELEGATE, |
||
| 512 | // don't set this value it will have no effect, its hardcoded to FWD_PRESERVE_SENDER | FWD_DO_NOT_MUNGE_MSG |
||
| 513 | 'flavor' => 0, |
||
| 514 | 'flags' => 0, |
||
| 515 | 'adrlist' => $usersInfo |
||
| 516 | ) |
||
| 517 | ); |
||
| 518 | |||
| 519 | $rule[PR_RULE_CONDITION] = Array(RES_AND, |
||
| 520 | Array( |
||
| 521 | Array(RES_CONTENT, |
||
| 522 | Array( |
||
| 523 | FUZZYLEVEL => FL_PREFIX, |
||
| 524 | ULPROPTAG => PR_MESSAGE_CLASS, |
||
| 525 | VALUE => Array(PR_MESSAGE_CLASS => 'IPM.Schedule.Meeting') |
||
| 526 | ) |
||
| 527 | ), |
||
| 528 | Array(RES_NOT, |
||
| 529 | Array( |
||
| 530 | Array(RES_EXIST, |
||
| 531 | Array( |
||
| 532 | ULPROPTAG => PR_DELEGATED_BY_RULE |
||
| 533 | ) |
||
| 534 | ) |
||
| 535 | ) |
||
| 536 | ), |
||
| 537 | Array(RES_OR, |
||
| 538 | Array( |
||
| 539 | Array(RES_NOT, |
||
| 540 | Array( |
||
| 541 | Array(RES_EXIST, |
||
| 542 | Array( |
||
| 543 | ULPROPTAG => PR_SENSITIVITY |
||
| 544 | ) |
||
| 545 | ) |
||
| 546 | ) |
||
| 547 | ), |
||
| 548 | Array(RES_PROPERTY, |
||
| 549 | Array( |
||
| 550 | RELOP => RELOP_NE, |
||
| 551 | ULPROPTAG => PR_SENSITIVITY, |
||
| 552 | VALUE => Array(PR_SENSITIVITY => SENSITIVITY_PRIVATE) |
||
| 553 | ) |
||
| 554 | ) |
||
| 555 | ) |
||
| 556 | ), |
||
| 557 | ) |
||
| 558 | ); |
||
| 559 | |||
| 560 | $rule[PR_RULE_NAME] = ''; |
||
| 561 | $rule[PR_RULE_PROVIDER_DATA] = ''; // 0 byte binary string |
||
| 562 | $rule[PR_RULE_STATE] = ST_ENABLED; |
||
| 563 | $rule[PR_RULE_LEVEL] = 0; |
||
| 564 | $rule[PR_RULE_SEQUENCE] = 0; |
||
| 565 | $rule[PR_RULE_PROVIDER] = 'Schedule+ EMS Interface'; |
||
| 566 | $rule[PR_RULE_USER_FLAGS] = 0; |
||
| 567 | |||
| 568 | $rows = Array( |
||
| 569 | 0 => Array( |
||
| 570 | 'rowflags' => ROW_ADD, |
||
| 571 | 'properties' => $rule |
||
| 572 | ) |
||
| 573 | ); |
||
| 574 | $inbox = mapi_msgstore_getreceivefolder($this->getDefaultStore()); |
||
| 575 | mapi_folder_modifyrules($inbox, $rows); |
||
| 576 | } |
||
| 577 | |||
| 578 | function modifyDelegateMeetingRule($delegateMeetingRule, $users) |
||
| 579 | { |
||
| 580 | $inbox = mapi_msgstore_getreceivefolder($this->getDefaultStore()); |
||
| 581 | if(count($users) > 0) { |
||
| 582 | // update the adrlist in the rule |
||
| 583 | $delegateMeetingRule[PR_RULE_ACTIONS][0]['adrlist'] = $users; |
||
| 584 | |||
| 585 | $rows = Array( |
||
| 586 | Array( |
||
| 587 | 'rowflags' => ROW_MODIFY, |
||
| 588 | 'properties' => $delegateMeetingRule |
||
| 589 | ) |
||
| 590 | ); |
||
| 591 | |||
| 592 | } else { |
||
| 593 | // no users remaining in the rule so delete the rule |
||
| 594 | $rows = Array( |
||
| 595 | 0 => Array( |
||
| 596 | 'rowflags' => ROW_REMOVE, |
||
| 597 | 'properties' => $delegateMeetingRule |
||
| 598 | ) |
||
| 599 | ); |
||
| 600 | } |
||
| 601 | mapi_folder_modifyrules($inbox, $rows); |
||
| 602 | } |
||
| 603 | |||
| 604 | /******** Functions to delete delegates information ***********/ |
||
| 605 | |||
| 606 | /** |
||
| 607 | * Function which deletes delegates information sent by client. |
||
| 608 | * @param {Array} $delegates delegates information sent by client |
||
| 609 | */ |
||
| 610 | function deleteDelegates($delegates) |
||
| 611 | { |
||
| 612 | if (is_assoc_array($delegates)) { |
||
| 613 | // wrap single delegate in an array |
||
| 614 | $delegates = array($delegates); |
||
| 615 | } |
||
| 616 | foreach ($delegates as $delegate) { |
||
| 617 | // set properties for delegates on user's freebusy folder |
||
| 618 | $this->deleteDelegateProps($delegate); |
||
| 619 | |||
| 620 | // set permissions on user's default folders |
||
| 621 | $this->deleteFolderPermissions($delegate); |
||
| 622 | } |
||
| 623 | // delete delegate meeting rule |
||
| 624 | $this->removeDelegatesFromDelegateMeetingRule($delegates); |
||
| 625 | $this->sendFeedback(true); |
||
| 626 | } |
||
| 627 | |||
| 628 | /** |
||
| 629 | * Function will delete values from PR_DELEGATES_SEE_PRIVATE, PR_SCHDINFO_DELEGATE_ENTRYIDS and PR_SCHDINFO_DELEGATE_NAMES and save the properties back if its not empty. |
||
| 630 | * @param {Array} $delegate delegate information sent from client. |
||
| 631 | */ |
||
| 632 | function deleteDelegateProps($delegate) |
||
| 633 | { |
||
| 634 | $localFreeBusyMessage = freebusy::getLocalFreeBusyMessage(); |
||
| 635 | $delegateProps = $this->getDelegateProps($localFreeBusyMessage); |
||
| 636 | $delegateIndex = -1; |
||
| 637 | $len = count($delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS]); |
||
| 638 | for ($i=0; $i<$len; $i++) { |
||
| 639 | if ($delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS][$i] == hex2bin($delegate["entryid"])) { |
||
| 640 | $delegateIndex = $i; |
||
| 641 | break; |
||
| 642 | } |
||
| 643 | } |
||
| 644 | if (-1 == $delegateIndex) { |
||
| 645 | return; |
||
| 646 | } |
||
| 647 | unset($delegateProps[PR_DELEGATES_SEE_PRIVATE][$delegateIndex]); |
||
| 648 | unset($delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS][$delegateIndex]); |
||
| 649 | unset($delegateProps[PR_SCHDINFO_DELEGATE_NAMES][$delegateIndex]); |
||
| 650 | |||
| 651 | // unset will remove the value but will not regenerate array keys, so we need to |
||
| 652 | // do it here |
||
| 653 | $delegateProps[PR_DELEGATES_SEE_PRIVATE] = array_values($delegateProps[PR_DELEGATES_SEE_PRIVATE]); |
||
| 654 | $delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS] = array_values($delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS]); |
||
| 655 | $delegateProps[PR_SCHDINFO_DELEGATE_NAMES] = array_values($delegateProps[PR_SCHDINFO_DELEGATE_NAMES]); |
||
| 656 | |||
| 657 | if(!empty($delegateProps[PR_SCHDINFO_DELEGATE_ENTRYIDS])) { |
||
| 658 | mapi_setprops($localFreeBusyMessage, $delegateProps); |
||
| 659 | } else { |
||
| 660 | // Delete delegate properties. |
||
| 661 | mapi_deleteprops($localFreeBusyMessage, array(PR_DELEGATES_SEE_PRIVATE, PR_SCHDINFO_DELEGATE_ENTRYIDS, PR_SCHDINFO_DELEGATE_NAMES)); |
||
| 662 | } |
||
| 663 | |||
| 664 | mapi_savechanges($localFreeBusyMessage); |
||
| 665 | |||
| 666 | // unset the module variable, so subsequent calls will have the updated value |
||
| 667 | unset($this->delegateProps); |
||
| 668 | } |
||
| 669 | |||
| 670 | /** |
||
| 671 | * Function which deletes permissions from all default folder for a particular delegate. |
||
| 672 | * @param {Array} $delegate delegate's information sent by client. |
||
| 673 | */ |
||
| 674 | function deleteFolderPermissions($delegate) |
||
| 675 | { |
||
| 676 | $store = $this->getDefaultStore(); |
||
| 677 | |||
| 678 | // Get all default folders and set permissions. |
||
| 679 | foreach($this->getDefaultFolders($store) as $folderName => $folderEntryID) { |
||
| 680 | $folder = mapi_msgstore_openentry($store, $folderEntryID); |
||
| 681 | |||
| 682 | // delete current acl's |
||
| 683 | $acls = array( |
||
| 684 | array( |
||
| 685 | 'type' => ACCESS_TYPE_GRANT, |
||
| 686 | 'userid' => hex2bin($delegate['entryid']), |
||
| 687 | 'rights' => ecRightsNone, |
||
| 688 | 'state' => RIGHT_DELETED | RIGHT_AUTOUPDATE_DENIED |
||
| 689 | ) |
||
| 690 | ); |
||
| 691 | |||
| 692 | mapi_zarafa_setpermissionrules($folder, $acls); |
||
| 693 | |||
| 694 | if ($folderName === 'calendar') { |
||
| 695 | $freeBusyFolder = freebusy::getLocalFreeBusyFolder($store); |
||
| 696 | |||
| 697 | if(isset($freeBusyFolder)) { |
||
| 698 | mapi_zarafa_setpermissionrules($freeBusyFolder, $acls); |
||
| 699 | mapi_savechanges($freeBusyFolder); |
||
| 700 | } |
||
| 701 | } |
||
| 702 | |||
| 703 | mapi_savechanges($folder); |
||
| 704 | } |
||
| 705 | } |
||
| 706 | |||
| 707 | /** |
||
| 708 | * Function will remove delegates from delegate meeting rule when the user is deleted from delegate list. |
||
| 709 | * @param {Array} $delegates all delegate information that are deleted |
||
| 710 | */ |
||
| 711 | function removeDelegatesFromDelegateMeetingRule($delegates) |
||
| 712 | { |
||
| 713 | $delegateMeetingRule = $this->getDelegateMeetingRule(); |
||
| 714 | if ($delegateMeetingRule === false) { |
||
| 715 | // no delegate rule exists, nothing to do |
||
| 716 | return; |
||
| 717 | } |
||
| 718 | $len = count($delegates); |
||
| 719 | $old_users = $delegateMeetingRule[PR_RULE_ACTIONS][0]['adrlist']; |
||
| 720 | $new_users = array(); |
||
| 721 | foreach ($old_users as $user) { |
||
| 722 | for($index=0; $index<$len; $index++) { |
||
| 723 | if ($user[PR_ENTRYID] == hex2bin($delegates[$index]['entryid'])) { |
||
| 724 | break; |
||
| 725 | } |
||
| 726 | } |
||
| 727 | if ($index == $len) { |
||
| 728 | $new_users[] = $user; |
||
| 729 | } |
||
| 730 | } |
||
| 731 | $this->modifyDelegateMeetingRule($delegateMeetingRule, $new_users); |
||
| 732 | } |
||
| 733 | |||
| 734 | /******** Functions for exception handling ***********/ |
||
| 735 | |||
| 736 | /** |
||
| 737 | * Function does customization of MAPIException based on module data. |
||
| 738 | * like, here it will generate display message based on actionType |
||
| 739 | * for particular exception. |
||
| 740 | * |
||
| 741 | * @param object $e Exception object |
||
| 742 | * @param string $actionType the action type, sent by the client |
||
| 743 | * @param MAPIobject $store Store object of the current user. |
||
| 744 | * @param string $parententryid parent entryid of the message. |
||
| 745 | * @param string $entryid entryid of the message/folder. |
||
| 746 | * @param array $action the action data, sent by the client |
||
| 747 | */ |
||
| 748 | function handleException(&$e, $actionType = null, $store = null, $parententryid = null, $entryid = null, $action = null) |
||
| 749 | { |
||
| 750 | switch($actionType) { |
||
| 751 | case 'save': |
||
| 752 | $e->setDisplayMessage(_('Could not save delegate information.')); |
||
| 753 | break; |
||
| 754 | case 'delete': |
||
| 755 | $e->setDisplayMessage(_('Could not delete delegate.')); |
||
| 756 | break; |
||
| 757 | case 'list': |
||
| 758 | $e->setDisplayMessage(_('Can not get list of delegates.')); |
||
| 759 | break; |
||
| 760 | } |
||
| 761 | |||
| 762 | parent::handleException($e, $actionType, $store, $parententryid, $entryid, $action); |
||
| 763 | } |
||
| 764 | } |
||
| 765 | ?> |
||
|
0 ignored issues
–
show
|
|||
| 766 |
Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.
A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.