Beispiel #1
0
 /**
  * Imports a change on a folder
  *
  * @param object        $folder     SyncFolder
  *
  * @access public
  * @return string       id of the folder
  * @throws StatusException
  */
 public function ImportFolderChange($folder)
 {
     $id = isset($folder->serverid) ? $folder->serverid : false;
     $parent = $folder->parentid;
     $displayname = u2wi($folder->displayname);
     $type = $folder->type;
     if (Utils::IsSystemFolder($type)) {
         throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, system folder can not be created/modified", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname), SYNC_FSSTATUS_SYSTEMFOLDER);
     }
     // create a new folder if $id is not set
     if (!$id) {
         // the root folder is "0" - get IPM_SUBTREE
         if ($parent == "0") {
             $parentprops = mapi_getprops($this->store, array(PR_IPM_SUBTREE_ENTRYID));
             if (isset($parentprops[PR_IPM_SUBTREE_ENTRYID])) {
                 $parentfentryid = $parentprops[PR_IPM_SUBTREE_ENTRYID];
             }
         } else {
             $parentfentryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($parent));
         }
         if (!$parentfentryid) {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to open parent folder (no entry id)", Utils::PrintAsString(false), $folder->parentid, $displayname), SYNC_FSSTATUS_PARENTNOTFOUND);
         }
         $parentfolder = mapi_msgstore_openentry($this->store, $parentfentryid);
         if (!$parentfolder) {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to open parent folder (open entry)", Utils::PrintAsString(false), $folder->parentid, $displayname), SYNC_FSSTATUS_PARENTNOTFOUND);
         }
         //  mapi_folder_createfolder() fails if a folder with this name already exists -> MAPI_E_COLLISION
         $newfolder = mapi_folder_createfolder($parentfolder, $displayname, "");
         if (mapi_last_hresult()) {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, mapi_folder_createfolder() failed: 0x%X", Utils::PrintAsString(false), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_FOLDEREXISTS);
         }
         mapi_setprops($newfolder, array(PR_CONTAINER_CLASS => MAPIUtils::GetContainerClassFromFolderType($type)));
         $props = mapi_getprops($newfolder, array(PR_SOURCE_KEY));
         if (isset($props[PR_SOURCE_KEY])) {
             $sourcekey = bin2hex($props[PR_SOURCE_KEY]);
             ZLog::Write(LOGLEVEL_DEBUG, sprintf("Created folder '%s' with id: '%s'", $displayname, $sourcekey));
             return $sourcekey;
         } else {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, folder created but PR_SOURCE_KEY not available: 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_SERVERERROR);
         }
         return false;
     }
     // update folder
     $entryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($id));
     if (!$entryid) {
         throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to open folder (no entry id): 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_PARENTNOTFOUND);
     }
     $folder = mapi_msgstore_openentry($this->store, $entryid);
     if (!$folder) {
         throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to open folder (open entry): 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_PARENTNOTFOUND);
     }
     $props = mapi_getprops($folder, array(PR_SOURCE_KEY, PR_PARENT_SOURCE_KEY, PR_DISPLAY_NAME, PR_CONTAINER_CLASS));
     if (!isset($props[PR_SOURCE_KEY]) || !isset($props[PR_PARENT_SOURCE_KEY]) || !isset($props[PR_DISPLAY_NAME]) || !isset($props[PR_CONTAINER_CLASS])) {
         throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, folder data not available: 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_SERVERERROR);
     }
     if ($parent == "0") {
         $parentprops = mapi_getprops($this->store, array(PR_IPM_SUBTREE_ENTRYID));
         $parentfentryid = $parentprops[PR_IPM_SUBTREE_ENTRYID];
         $mapifolder = mapi_msgstore_openentry($this->store, $parentfentryid);
         $rootfolderprops = mapi_getprops($mapifolder, array(PR_SOURCE_KEY));
         $parent = bin2hex($rootfolderprops[PR_SOURCE_KEY]);
         ZLog::Write(LOGLEVEL_DEBUG, sprintf("ImportChangesICS->ImportFolderChange(): resolved AS parent '0' to sourcekey '%s'", $parent));
     }
     // In theory the parent id could change, which means that the folder was moved.
     // It is unknown if any device supports this, so we do currently not implement it (no known device is able to do this)
     if (bin2hex($props[PR_PARENT_SOURCE_KEY]) !== $parent) {
         throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Folder was moved to another location, which is currently not supported. Please report this to the Z-Push dev team together with the WBXML log and your device details (model, firmware etc).", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_UNKNOWNERROR);
     }
     $props = array(PR_DISPLAY_NAME => $displayname);
     mapi_setprops($folder, $props);
     mapi_savechanges($folder);
     if (mapi_last_hresult()) {
         throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, mapi_savechanges() failed: 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_SERVERERROR);
     }
     ZLog::Write(LOGLEVEL_DEBUG, "Imported changes for folder: {$id}");
     return $id;
 }
 /**
  * Imports a change on a folder
  *
  * @param object        $folder     SyncFolder
  *
  * @access public
  * @return string       id of the folder
  * @throws StatusException
  */
 public function ImportFolderChange($folder)
 {
     $id = isset($folder->serverid) ? $folder->serverid : false;
     $parent = $folder->parentid;
     $displayname = u2wi($folder->displayname);
     $type = $folder->type;
     if (Utils::IsSystemFolder($type)) {
         throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, system folder can not be created/modified", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname), SYNC_FSSTATUS_SYSTEMFOLDER);
     }
     // create a new folder if $id is not set
     if (!$id) {
         // the root folder is "0" - get IPM_SUBTREE
         if ($parent == "0") {
             $parentprops = mapi_getprops($this->store, array(PR_IPM_SUBTREE_ENTRYID));
             if (isset($parentprops[PR_IPM_SUBTREE_ENTRYID])) {
                 $parentfentryid = $parentprops[PR_IPM_SUBTREE_ENTRYID];
             }
         } else {
             $parentfentryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($parent));
         }
         if (!$parentfentryid) {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to open parent folder (no entry id)", Utils::PrintAsString(false), $folder->parentid, $displayname), SYNC_FSSTATUS_PARENTNOTFOUND);
         }
         $parentfolder = mapi_msgstore_openentry($this->store, $parentfentryid);
         if (!$parentfolder) {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to open parent folder (open entry)", Utils::PrintAsString(false), $folder->parentid, $displayname), SYNC_FSSTATUS_PARENTNOTFOUND);
         }
         //  mapi_folder_createfolder() fails if a folder with this name already exists -> MAPI_E_COLLISION
         $newfolder = mapi_folder_createfolder($parentfolder, $displayname, "");
         if (mapi_last_hresult()) {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, mapi_folder_createfolder() failed: 0x%X", Utils::PrintAsString(false), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_FOLDEREXISTS);
         }
         mapi_setprops($newfolder, array(PR_CONTAINER_CLASS => MAPIUtils::GetContainerClassFromFolderType($type)));
         $props = mapi_getprops($newfolder, array(PR_SOURCE_KEY));
         if (isset($props[PR_SOURCE_KEY])) {
             $sourcekey = bin2hex($props[PR_SOURCE_KEY]);
             ZLog::Write(LOGLEVEL_DEBUG, sprintf("Created folder '%s' with id: '%s'", $displayname, $sourcekey));
             return $sourcekey;
         } else {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, folder created but PR_SOURCE_KEY not available: 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_SERVERERROR);
         }
         return false;
     }
     // open folder for update
     $entryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($id));
     if (!$entryid) {
         throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to open folder (no entry id): 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_PARENTNOTFOUND);
     }
     // check if this is a MAPI default folder
     if ($this->mapiprovider->IsMAPIDefaultFolder($entryid)) {
         throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, MAPI default folder can not be created/modified", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname), SYNC_FSSTATUS_SYSTEMFOLDER);
     }
     $mfolder = mapi_msgstore_openentry($this->store, $entryid);
     if (!$mfolder) {
         throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to open folder (open entry): 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_PARENTNOTFOUND);
     }
     $props = mapi_getprops($mfolder, array(PR_SOURCE_KEY, PR_PARENT_SOURCE_KEY, PR_DISPLAY_NAME, PR_CONTAINER_CLASS));
     if (!isset($props[PR_SOURCE_KEY]) || !isset($props[PR_PARENT_SOURCE_KEY]) || !isset($props[PR_DISPLAY_NAME]) || !isset($props[PR_CONTAINER_CLASS])) {
         throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, folder data not available: 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_SERVERERROR);
     }
     // get the real parent source key from mapi
     if ($parent == "0") {
         $parentprops = mapi_getprops($this->store, array(PR_IPM_SUBTREE_ENTRYID));
         $parentfentryid = $parentprops[PR_IPM_SUBTREE_ENTRYID];
         $mapifolder = mapi_msgstore_openentry($this->store, $parentfentryid);
         $rootfolderprops = mapi_getprops($mapifolder, array(PR_SOURCE_KEY));
         $parent = bin2hex($rootfolderprops[PR_SOURCE_KEY]);
         ZLog::Write(LOGLEVEL_DEBUG, sprintf("ImportChangesICS->ImportFolderChange(): resolved AS parent '0' to sourcekey '%s'", $parent));
     }
     // a changed parent id means that the folder should be moved
     if (bin2hex($props[PR_PARENT_SOURCE_KEY]) !== $parent) {
         $sourceparentfentryid = mapi_msgstore_entryidfromsourcekey($this->store, $props[PR_PARENT_SOURCE_KEY]);
         if (!$sourceparentfentryid) {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to open parent source folder (no entry id): 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_PARENTNOTFOUND);
         }
         $sourceparentfolder = mapi_msgstore_openentry($this->store, $sourceparentfentryid);
         if (!$sourceparentfolder) {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to open parent source folder (open entry): 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_PARENTNOTFOUND);
         }
         $destparentfentryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($parent));
         if (!$sourceparentfentryid) {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to open destination folder (no entry id): 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_SERVERERROR);
         }
         $destfolder = mapi_msgstore_openentry($this->store, $destparentfentryid);
         if (!$destfolder) {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to open destination folder (open entry): 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_SERVERERROR);
         }
         // mapi_folder_copyfolder() fails if a folder with this name already exists -> MAPI_E_COLLISION
         if (!mapi_folder_copyfolder($sourceparentfolder, $entryid, $destfolder, $displayname, FOLDER_MOVE)) {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to move folder: 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_FOLDEREXISTS);
         }
         $folderProps = mapi_getprops($mfolder, array(PR_SOURCE_KEY));
         return $folderProps[PR_SOURCE_KEY];
     }
     // update the display name
     $props = array(PR_DISPLAY_NAME => $displayname);
     mapi_setprops($mfolder, $props);
     mapi_savechanges($mfolder);
     if (mapi_last_hresult()) {
         throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, mapi_savechanges() failed: 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_SERVERERROR);
     }
     ZLog::Write(LOGLEVEL_DEBUG, "Imported changes for folder: {$id}");
     return $id;
 }