diff --git a/js/data/MDMDeviceFolderStore.js b/js/data/MDMDeviceFolderStore.js index 3b3ce4e..f3c2935 100644 --- a/js/data/MDMDeviceFolderStore.js +++ b/js/data/MDMDeviceFolderStore.js @@ -8,13 +8,6 @@ Ext.namespace('Zarafa.plugins.mdm.data'); */ Zarafa.plugins.mdm.data.MDMDeviceFolderStore = Ext.extend(Zarafa.core.data.MAPISubStore, { - /** - * @cfg {Zarafa.core.data.RecordCustomObjectType} customObjectType The custom object type - * which represents the {@link Ext.data.Record records} which should be created using - * {@link Zarafa.core.data.RecordFactory#createRecordObjectByCustomType}. - */ - customObjectType: Zarafa.core.data.RecordCustomObjectType.MDM_Device_Folder, - /** * @constructor * @param config Configuration object @@ -27,7 +20,7 @@ Zarafa.plugins.mdm.data.MDMDeviceFolderStore = Ext.extend(Zarafa.core.data.MAPIS autoLoad: true, remoteSort: false, reader: new Zarafa.plugins.mdm.data.JsonDeviceFolderReader({ - customObjectType: this.customObjectType + customObjectType: Zarafa.core.data.RecordCustomObjectType.MDM_Device_Folder }), writer: new Zarafa.plugins.mdm.data.MDMDeviceFolderWriter(), proxy: new Zarafa.core.data.IPMProxy({ diff --git a/php/class.pluginmdmmodule.php b/php/class.pluginmdmmodule.php index f57f87b..aed088a 100755 --- a/php/class.pluginmdmmodule.php +++ b/php/class.pluginmdmmodule.php @@ -444,110 +444,257 @@ class PluginMDMModule extends Module } } - /** + /** * Gets the hierarchy list of all required stores. * Function which is use to get the hierarchy list with PR_SOURCE_KEY. - * @return array the array of all hierarchy folders. - */ + * @return array the array of all hierarchy folders. + */ function getHierarchyList() - { - $storeList = $GLOBALS["mapisession"]->getAllMessageStores(); - $properties = $GLOBALS["properties"]->getFolderListProperties(); - $properties["source_key"] = PR_SOURCE_KEY; - $storeData = array(); - foreach ($storeList as $store) { - $msgstore_props = mapi_getprops($store, array(PR_ENTRYID, PR_DISPLAY_NAME, PR_IPM_SUBTREE_ENTRYID, PR_IPM_OUTBOX_ENTRYID, PR_IPM_SENTMAIL_ENTRYID, PR_IPM_WASTEBASKET_ENTRYID, PR_MDB_PROVIDER, PR_IPM_PUBLIC_FOLDERS_ENTRYID, PR_IPM_FAVORITES_ENTRYID, PR_OBJECT_TYPE, PR_STORE_SUPPORT_MASK, PR_MAILBOX_OWNER_ENTRYID, PR_MAILBOX_OWNER_NAME, PR_USER_ENTRYID, PR_USER_NAME, PR_QUOTA_WARNING_THRESHOLD, PR_QUOTA_SEND_THRESHOLD, PR_QUOTA_RECEIVE_THRESHOLD, PR_MESSAGE_SIZE_EXTENDED, PR_MAPPING_SIGNATURE, PR_COMMON_VIEWS_ENTRYID, PR_FINDER_ENTRYID)); - $storeType = $msgstore_props[PR_MDB_PROVIDER]; + { + $storeList = $GLOBALS["mapisession"]->getAllMessageStores(); + $properties = $GLOBALS["properties"]->getFolderListProperties(); + $otherUsers = $GLOBALS["mapisession"]->retrieveOtherUsersFromSettings(); + $properties["source_key"] = PR_SOURCE_KEY; + $openWholeStore = true; + $storeData = array(); - if ($storeType == ZARAFA_STORE_DELEGATE_GUID) { - $storeUserName = $GLOBALS["mapisession"]->getUserNameOfStore($msgstore_props[PR_ENTRYID]); - } else if( $storeType == ZARAFA_STORE_PUBLIC_GUID){ - $storeUserName = "SYSTEM"; + foreach ($storeList as $store) { + $msgstore_props = mapi_getprops($store, array(PR_MDB_PROVIDER, PR_ENTRYID, PR_IPM_SUBTREE_ENTRYID, PR_USER_NAME)); + $storeType = $msgstore_props[PR_MDB_PROVIDER]; + + if ($storeType == ZARAFA_SERVICE_GUID) { + continue; + } else if ($storeType == ZARAFA_STORE_DELEGATE_GUID) { + $storeUserName = $GLOBALS["mapisession"]->getUserNameOfStore($msgstore_props[PR_ENTRYID]); + } else if ($storeType == ZARAFA_STORE_PUBLIC_GUID) { + $storeUserName = "SYSTEM"; } else { - $storeUserName = $msgstore_props[PR_USER_NAME]; - } - if (isset($msgstore_props[PR_IPM_SUBTREE_ENTRYID])) { - $subtreeFolderEntryID = $msgstore_props[PR_IPM_SUBTREE_ENTRYID]; - try { - $subtreeFolder = mapi_msgstore_openentry($store, $subtreeFolderEntryID); - } catch (MAPIException $e) { - // We've handled the event - $e->setHandled(); - } - try { + $storeUserName = $msgstore_props[PR_USER_NAME]; + } - // remove hidden folders, folders with PR_ATTR_HIDDEN property set - // should not be shown to the client - $restriction = Array(RES_OR, Array( - Array(RES_PROPERTY, - Array( - RELOP => RELOP_EQ, - ULPROPTAG => PR_ATTR_HIDDEN, - VALUE => Array(PR_ATTR_HIDDEN => false) - ) - ), - Array(RES_NOT, - Array( - Array(RES_EXIST, - Array( - ULPROPTAG => PR_ATTR_HIDDEN - ) - ) - ) - ) - )); + if (is_array($otherUsers)) { + if (isset($otherUsers[$storeUserName])) { + $sharedFolders = $otherUsers[$storeUserName]; + if (!isset($otherUsers[$storeUserName]['all'])) { + $openWholeStore = false; + $a = $this->getSharedFolderList($store, $sharedFolders, $properties, $storeUserName); + $storeData = array_merge($storeData, $a); + } + } + } - $expand = Array( - Array( - 'folder' => $subtreeFolder, - 'props' => mapi_getprops($subtreeFolder, Array(PR_ENTRYID, PR_SUBFOLDERS)) - ) - ); + if ($openWholeStore) { + if (isset($msgstore_props[PR_IPM_SUBTREE_ENTRYID])) { + $subtreeFolderEntryID = $msgstore_props[PR_IPM_SUBTREE_ENTRYID]; + try { + $subtreeFolder = mapi_msgstore_openentry($store, $subtreeFolderEntryID); + } catch (MAPIException $e) { + // We've handled the event + $e->setHandled(); + } + $this->getSubFolders($subtreeFolder, $store, $properties, $storeData, $storeUserName); + } + } + } - // Start looping through the $expand array, during each loop we grab the first item in - // the array and obtain the hierarchy table for that particular folder. If one of those - // subfolders has subfolders of its own, it will be appended to $expand again to ensure - // it will be expanded later. - while (!empty($expand)) { - $item = array_shift($expand); + return $storeData; + } - $hierarchyTable = mapi_folder_gethierarchytable($item['folder'], MAPI_DEFERRED_ERRORS); - mapi_table_restrict($hierarchyTable, $restriction, TBL_BATCH); + /** + * Helper function to get the shared folder list. + * @param object $store Message Store Object. + * @param object $sharedFolders Mapi Folder Object. + * @param array $properties MAPI property mappings for folders. + * @param string $storeUserName owner name of store. + * @return array shared folders list. + */ + function getSharedFolderList($store, $sharedFolders, $properties, $storeUserName) + { + $msgstore_props = mapi_getprops($store, array(PR_ENTRYID, PR_DISPLAY_NAME, PR_IPM_SUBTREE_ENTRYID, PR_IPM_OUTBOX_ENTRYID, PR_IPM_SENTMAIL_ENTRYID, PR_IPM_WASTEBASKET_ENTRYID, PR_MDB_PROVIDER, PR_IPM_PUBLIC_FOLDERS_ENTRYID, PR_IPM_FAVORITES_ENTRYID, PR_OBJECT_TYPE, PR_STORE_SUPPORT_MASK, PR_MAILBOX_OWNER_ENTRYID, PR_MAILBOX_OWNER_NAME, PR_USER_ENTRYID, PR_USER_NAME, PR_QUOTA_WARNING_THRESHOLD, PR_QUOTA_SEND_THRESHOLD, PR_QUOTA_RECEIVE_THRESHOLD, PR_MESSAGE_SIZE_EXTENDED, PR_MAPPING_SIGNATURE, PR_COMMON_VIEWS_ENTRYID, PR_FINDER_ENTRYID)); + $storeData = array(); + $folders = array(); + try { + $inbox = mapi_msgstore_getreceivefolder($store); + $inboxProps = mapi_getprops($inbox, array(PR_ENTRYID)); + } catch (MAPIException $e) { + // don't propogate this error to parent handlers, if store doesn't support it + if ($e->getCode() === MAPI_E_NO_SUPPORT) { + $e->setHandled(); + } + } - mapi_table_setcolumns($hierarchyTable, $properties); + $root = mapi_msgstore_openentry($store, null); + $rootProps = mapi_getprops($root, array(PR_IPM_APPOINTMENT_ENTRYID, PR_IPM_CONTACT_ENTRYID, PR_IPM_DRAFTS_ENTRYID, PR_IPM_JOURNAL_ENTRYID, PR_IPM_NOTE_ENTRYID, PR_IPM_TASK_ENTRYID, PR_ADDITIONAL_REN_ENTRYIDS)); - // Load the hierarchy in small batches - $batchcount = 100; - do { - $rows = mapi_table_queryrows($hierarchyTable, null, 0, $batchcount); + $additional_ren_entryids = array(); + if (isset($rootProps[PR_ADDITIONAL_REN_ENTRYIDS])) { + $additional_ren_entryids = $rootProps[PR_ADDITIONAL_REN_ENTRYIDS]; + } - foreach ($rows as $subfolder) { + $defaultfolders = array( + "default_folder_inbox" => array("inbox" => PR_ENTRYID), + "default_folder_outbox" => array("store" => PR_IPM_OUTBOX_ENTRYID), + "default_folder_sent" => array("store" => PR_IPM_SENTMAIL_ENTRYID), + "default_folder_wastebasket" => array("store" => PR_IPM_WASTEBASKET_ENTRYID), + "default_folder_favorites" => array("store" => PR_IPM_FAVORITES_ENTRYID), + "default_folder_publicfolders" => array("store" => PR_IPM_PUBLIC_FOLDERS_ENTRYID), + "default_folder_calendar" => array("root" => PR_IPM_APPOINTMENT_ENTRYID), + "default_folder_contact" => array("root" => PR_IPM_CONTACT_ENTRYID), + "default_folder_drafts" => array("root" => PR_IPM_DRAFTS_ENTRYID), + "default_folder_journal" => array("root" => PR_IPM_JOURNAL_ENTRYID), + "default_folder_note" => array("root" => PR_IPM_NOTE_ENTRYID), + "default_folder_task" => array("root" => PR_IPM_TASK_ENTRYID), + "default_folder_junk" => array("additional" => 4), + "default_folder_syncissues" => array("additional" => 1), + "default_folder_conflicts" => array("additional" => 0), + "default_folder_localfailures" => array("additional" => 2), + "default_folder_serverfailures" => array("additional" => 3), + ); - // If the subfolders has subfolders of its own, append the folder - // to the $expand array, so it can be expanded in the next loop. - if ($subfolder[PR_SUBFOLDERS]) { - $folderObject = mapi_msgstore_openentry($store, $subfolder[PR_ENTRYID]); - array_push($expand, array('folder' => $folderObject, 'props' => $subfolder)); - } - $subfolder["user"] = $storeUserName; - // Add the folder to the return list. - array_push($storeData, $subfolder); - } + foreach ($defaultfolders as $key => $prop) { + $tag = reset($prop); + $from = key($prop); + switch ($from) { + case "inbox": + if (isset($inboxProps[$tag])) { + $storeData["props"][$key] = bin2hex($inboxProps[$tag]); + } + break; + case "store": + if (isset($msgstore_props[$tag])) { + $storeData["props"][$key] = bin2hex($msgstore_props[$tag]); + } + break; + case "root": + if (isset($rootProps[$tag])) { + $storeData["props"][$key] = bin2hex($rootProps[$tag]); + } + break; + case "additional": + if (isset($additional_ren_entryids[$tag])) { + $storeData["props"][$key] = bin2hex($additional_ren_entryids[$tag]); + } + break; + } + } - // When the server returned a different number of rows then was requested, - // we have reached the end of the table and we should exit the loop. - } while (count($rows) === $batchcount); - } + $store_access = true; + $openSubFolders = false; + foreach ($sharedFolders as $type => $sharedFolder) { + $openSubFolders = ($sharedFolder["show_subfolders"] == true); + $folderEntryID = hex2bin($storeData["props"]["default_folder_" . $sharedFolder["folder_type"]]); + try { + // load folder props + $folder = mapi_msgstore_openentry($store, $folderEntryID); + } catch (MAPIException $e) { + // Indicate that we don't have access to the store, + // so no more attempts to read properties or open entries. + $store_access = false; - } catch (MAPIException $e) { + // We've handled the event + $e->setHandled(); + } + } - // We've handled the event - $e->setHandled(); - } - } - } - return $storeData; - } + if ($store_access === true) { + $folderProps = mapi_getprops($folder, $properties); + $folderProps["user"] = $storeUserName; + array_push($folders, $folderProps); + + //If folder has sub folders then add its. + if ($openSubFolders === true) { + if ($folderProps[PR_SUBFOLDERS] != false) { + $subFoldersData = array(); + $this->getSubFolders($folder, $store, $properties, $subFoldersData, $storeUserName); + $folders =array_merge($folders, $subFoldersData); + } + } + } + return $folders; + } + + + /** + * Helper function to get the sub folders of a given folder. + * + * @access private + * @param object $folder Mapi Folder Object. + * @param object $store Message Store Object + * @param array $properties MAPI property mappings for folders + * @param array $storeData Reference to an array. The folder properties are added to this array. + * @param string $storeUserName owner name of store. + */ + function getSubFolders($folder, $store, $properties, &$storeData, $storeUserName) + { + /** + * remove hidden folders, folders with PR_ATTR_HIDDEN property set + * should not be shown to the client + */ + $restriction = Array(RES_OR, Array( + Array(RES_PROPERTY, + Array( + RELOP => RELOP_EQ, + ULPROPTAG => PR_ATTR_HIDDEN, + VALUE => Array(PR_ATTR_HIDDEN => false) + ) + ), + Array(RES_NOT, + Array( + Array(RES_EXIST, + Array( + ULPROPTAG => PR_ATTR_HIDDEN + ) + ) + ) + ) + )); + + + $expand = Array( + Array( + 'folder' => $folder, + 'props' => mapi_getprops($folder, Array(PR_ENTRYID, PR_SUBFOLDERS)) + ) + ); + + // Start looping through the $expand array, during each loop we grab the first item in + // the array and obtain the hierarchy table for that particular folder. If one of those + // subfolders has subfolders of its own, it will be appended to $expand again to ensure + // it will be expanded later. + while (!empty($expand)) { + $item = array_shift($expand); + $columns = $properties; + + $hierarchyTable = mapi_folder_gethierarchytable($item['folder'], MAPI_DEFERRED_ERRORS); + mapi_table_restrict($hierarchyTable, $restriction, TBL_BATCH); + + mapi_table_setcolumns($hierarchyTable, $columns); + $columns = null; + + // Load the hierarchy in small batches + $batchcount = 100; + do { + $rows = mapi_table_queryrows($hierarchyTable, $columns, 0, $batchcount); + + foreach ($rows as $subfolder) { + + // If the subfolders has subfolders of its own, append the folder + // to the $expand array, so it can be expanded in the next loop. + if ($subfolder[PR_SUBFOLDERS]) { + $folderObject = mapi_msgstore_openentry($store, $subfolder[PR_ENTRYID]); + array_push($expand, array('folder' => $folderObject, 'props' => $subfolder)); + } + $subfolder["user"] = $storeUserName; + // Add the folder to the return list. + array_push($storeData, $subfolder); + } + + // When the server returned a different number of rows then was requested, + // we have reached the end of the table and we should exit the loop. + } while (count($rows) === $batchcount); + + } + } /** * Function which is use get folder types from the container class