function delete_messages($folder, $messages)
{
    global $hard_delete_messages;
    if ($hard_delete_messages) {
        $result = mapi_folder_deletemessages($folder, $messages, DELETE_HARD_DELETE);
    } else {
        $result = mapi_folder_deletemessages($folder, $messages);
    }
    if ($result == false) {
        echo " [-] Failed to delete message\n";
    }
}
 /**
  * Function creates meeting item in resource's calendar.
  *@param resource $message MAPI_message which is to create in resource's calendar
  *@param boolean $cancel cancel meeting
  *@param string $prefix prefix for subject of meeting
  */
 function bookResources($message, $cancel, $prefix, $basedate = false)
 {
     if (!$this->enableDirectBooking) {
         return array();
     }
     // Get the properties of the message
     $messageprops = mapi_getprops($message);
     if ($basedate) {
         $recurrItemProps = mapi_getprops($this->message, array($this->proptags['goid'], $this->proptags['goid2'], $this->proptags['timezone_data'], $this->proptags['timezone'], PR_OWNER_APPT_ID));
         $messageprops[$this->proptags['goid']] = $this->setBasedateInGlobalID($recurrItemProps[$this->proptags['goid']], $basedate);
         $messageprops[$this->proptags['goid2']] = $recurrItemProps[$this->proptags['goid2']];
         // Delete properties which are not needed.
         $deleteProps = array($this->proptags['basedate'], PR_DISPLAY_NAME, PR_ATTACHMENT_FLAGS, PR_ATTACHMENT_HIDDEN, PR_ATTACHMENT_LINKID, PR_ATTACH_FLAGS, PR_ATTACH_METHOD);
         foreach ($deleteProps as $propID) {
             if (isset($messageprops[$propID])) {
                 unset($messageprops[$propID]);
             }
         }
         if (isset($messageprops[$this->proptags['recurring']])) {
             $messageprops[$this->proptags['recurring']] = false;
         }
         // Set Outlook properties
         $messageprops[$this->proptags['clipstart']] = $messageprops[$this->proptags['startdate']];
         $messageprops[$this->proptags['clipend']] = $messageprops[$this->proptags['duedate']];
         $messageprops[$this->proptags['timezone_data']] = $recurrItemProps[$this->proptags['timezone_data']];
         $messageprops[$this->proptags['timezone']] = $recurrItemProps[$this->proptags['timezone']];
         $messageprops[$this->proptags['attendee_critical_change']] = time();
         $messageprops[$this->proptags['owner_critical_change']] = time();
     }
     // Get resource recipients
     $getResourcesRestriction = array(RES_AND, array(array(RES_PROPERTY, array(RELOP => RELOP_EQ, ULPROPTAG => PR_RECIPIENT_TYPE, VALUE => array(PR_RECIPIENT_TYPE => MAPI_BCC)))));
     $recipienttable = mapi_message_getrecipienttable($message);
     $resourceRecipients = mapi_table_queryallrows($recipienttable, $this->recipprops, $getResourcesRestriction);
     $this->errorSetResource = false;
     $resourceRecipData = array();
     // Put appointment into store resource users
     $i = 0;
     $len = count($resourceRecipients);
     while (!$this->errorSetResource && $i < $len) {
         $request = array(array(PR_DISPLAY_NAME => $resourceRecipients[$i][PR_DISPLAY_NAME]));
         $ab = mapi_openaddressbook($this->session);
         $ret = mapi_ab_resolvename($ab, $request, EMS_AB_ADDRESS_LOOKUP);
         $result = mapi_last_hresult();
         if ($result == NOERROR) {
             $result = $ret[0][PR_ENTRYID];
         }
         $resourceUsername = $ret[0][PR_EMAIL_ADDRESS];
         $resourceABEntryID = $ret[0][PR_ENTRYID];
         // Get StoreEntryID by username
         $user_entryid = mapi_msgstore_createentryid($this->store, $resourceUsername);
         // Open store of the user
         $userStore = mapi_openmsgstore($this->session, $user_entryid);
         // Open root folder
         $userRoot = mapi_msgstore_openentry($userStore, null);
         // Get calendar entryID
         $userRootProps = mapi_getprops($userRoot, array(PR_STORE_ENTRYID, PR_IPM_APPOINTMENT_ENTRYID, PR_FREEBUSY_ENTRYIDS));
         // Open Calendar folder   [check hresult==0]
         $accessToFolder = false;
         try {
             $calFolder = mapi_msgstore_openentry($userStore, $userRootProps[PR_IPM_APPOINTMENT_ENTRYID]);
             if ($calFolder) {
                 $calFolderProps = mapi_getProps($calFolder, array(PR_ACCESS));
                 if (($calFolderProps[PR_ACCESS] & MAPI_ACCESS_CREATE_CONTENTS) !== 0) {
                     $accessToFolder = true;
                 }
             }
         } catch (MAPIException $e) {
             $e->setHandled();
             $this->errorSetResource = 1;
             // No access
         }
         if ($accessToFolder) {
             /**
              * Get the LocalFreebusy message that contains the properties that
              * are set to accept or decline resource meeting requests
              */
             // Use PR_FREEBUSY_ENTRYIDS[1] to open folder the LocalFreeBusy msg
             $localFreebusyMsg = mapi_msgstore_openentry($userStore, $userRootProps[PR_FREEBUSY_ENTRYIDS][1]);
             if ($localFreebusyMsg) {
                 $props = mapi_getprops($localFreebusyMsg, array(PR_PROCESS_MEETING_REQUESTS, PR_DECLINE_RECURRING_MEETING_REQUESTS, PR_DECLINE_CONFLICTING_MEETING_REQUESTS));
                 $acceptMeetingRequests = $props[PR_PROCESS_MEETING_REQUESTS] ? 1 : 0;
                 $declineRecurringMeetingRequests = $props[PR_DECLINE_RECURRING_MEETING_REQUESTS] ? 1 : 0;
                 $declineConflictingMeetingRequests = $props[PR_DECLINE_CONFLICTING_MEETING_REQUESTS] ? 1 : 0;
                 if (!$acceptMeetingRequests) {
                     /**
                      * When a resource has not been set to automatically accept meeting requests,
                      * the meeting request has to be sent to him rather than being put directly into
                      * his calendar. No error should be returned.
                      */
                     //$errorSetResource = 2;
                     $this->nonAcceptingResources[] = $resourceRecipients[$i];
                 } else {
                     if ($declineRecurringMeetingRequests && !$cancel) {
                         // Check if appointment is recurring
                         if ($messageprops[$this->proptags['recurring']]) {
                             $this->errorSetResource = 3;
                         }
                     }
                     if ($declineConflictingMeetingRequests && !$cancel) {
                         // Check for conflicting items
                         $conflicting = false;
                         // Open the calendar
                         $calFolder = mapi_msgstore_openentry($userStore, $userRootProps[PR_IPM_APPOINTMENT_ENTRYID]);
                         if ($calFolder) {
                             if ($this->isMeetingConflicting($message, $userStore, $calFolder, $messageprops)) {
                                 $conflicting = true;
                             }
                         } else {
                             $this->errorSetResource = 1;
                             // No access
                         }
                         if ($conflicting) {
                             $this->errorSetResource = 4;
                             // Conflict
                         }
                     }
                 }
             }
         }
         if (!$this->errorSetResource && $accessToFolder) {
             /**
              * First search on GlobalID(0x3)
              * If (recurring and occurrence) If Resource was booked for only this occurrence then Resource should have only this occurrence in Calendar and not whole series.
              * If (normal meeting) then GlobalID(0x3) and CleanGlobalID(0x23) are same, so doesnt matter if search is based on GlobalID.
              */
             $rows = $this->findCalendarItems($messageprops[$this->proptags['goid']], $calFolder);
             /**
              * If no entry is found then
              * 1) Resource doesnt have meeting in Calendar. Seriously!!
              * OR
              * 2) We were looking for occurrence item but Resource has whole series
              */
             if (empty($rows)) {
                 /**
                  * Now search on CleanGlobalID(0x23) WHY???
                  * Because we are looking recurring item
                  *
                  * Possible results of this search
                  * 1) If Resource was booked for more than one occurrences then this search will return all those occurrence because search is perform on CleanGlobalID
                  * 2) If Resource was booked for whole series then it should return series.
                  */
                 $rows = $this->findCalendarItems($messageprops[$this->proptags['goid2']], $calFolder, true);
                 $newResourceMsg = false;
                 if (!empty($rows)) {
                     // Since we are looking for recurring item, open every result and check for 'recurring' property.
                     foreach ($rows as $row) {
                         $ResourceMsg = mapi_msgstore_openentry($userStore, $row);
                         $ResourceMsgProps = mapi_getprops($ResourceMsg, array($this->proptags['recurring']));
                         if (isset($ResourceMsgProps[$this->proptags['recurring']]) && $ResourceMsgProps[$this->proptags['recurring']]) {
                             $newResourceMsg = $ResourceMsg;
                             break;
                         }
                     }
                 }
                 // Still no results found. I giveup, create new message.
                 if (!$newResourceMsg) {
                     $newResourceMsg = mapi_folder_createmessage($calFolder);
                 }
             } else {
                 $newResourceMsg = mapi_msgstore_openentry($userStore, $rows[0]);
             }
             // Prefix the subject if needed
             if ($prefix && isset($messageprops[PR_SUBJECT])) {
                 $messageprops[PR_SUBJECT] = $prefix . $messageprops[PR_SUBJECT];
             }
             // Set status to cancelled if needed
             $messageprops[$this->proptags['busystatus']] = fbBusy;
             // The default status (Busy)
             if ($cancel) {
                 $messageprops[$this->proptags['meetingstatus']] = olMeetingCanceled;
                 // The meeting has been canceled
                 $messageprops[$this->proptags['busystatus']] = fbFree;
                 // Free
             } else {
                 $messageprops[$this->proptags['meetingstatus']] = olMeetingReceived;
                 // The recipient is receiving the request
             }
             $messageprops[$this->proptags['responsestatus']] = olResponseAccepted;
             // The resource autmatically accepts the appointment
             $messageprops[PR_MESSAGE_CLASS] = "IPM.Appointment";
             // Remove the PR_ICON_INDEX as it is not needed in the sent message and it also
             // confuses the Zarafa webaccess
             $messageprops[PR_ICON_INDEX] = null;
             $messageprops[PR_RESPONSE_REQUESTED] = true;
             $addrinfo = $this->getOwnerAddress($this->store);
             if ($addrinfo) {
                 list($ownername, $owneremailaddr, $owneraddrtype, $ownerentryid, $ownersearchkey) = $addrinfo;
                 $messageprops[PR_SENT_REPRESENTING_EMAIL_ADDRESS] = $owneremailaddr;
                 $messageprops[PR_SENT_REPRESENTING_NAME] = $ownername;
                 $messageprops[PR_SENT_REPRESENTING_ADDRTYPE] = $owneraddrtype;
                 $messageprops[PR_SENT_REPRESENTING_ENTRYID] = $ownerentryid;
                 $messageprops[PR_SENT_REPRESENTING_SEARCH_KEY] = $ownersearchkey;
                 $messageprops[$this->proptags['apptreplyname']] = $ownername;
                 $messageprops[$this->proptags['replytime']] = time();
             }
             if ($basedate && isset($ResourceMsgProps[$this->proptags['recurring']]) && $ResourceMsgProps[$this->proptags['recurring']]) {
                 $recurr = new Recurrence($userStore, $newResourceMsg);
                 // Copy recipients list
                 $reciptable = mapi_message_getrecipienttable($message);
                 $recips = mapi_table_queryallrows($reciptable, $this->recipprops);
                 // add owner to recipient table
                 $this->addOrganizer($messageprops, $recips, true);
                 // Update occurrence
                 if ($recurr->isException($basedate)) {
                     $recurr->modifyException($messageprops, $basedate, $recips);
                 } else {
                     $recurr->createException($messageprops, $basedate, false, $recips);
                 }
             } else {
                 mapi_setprops($newResourceMsg, $messageprops);
                 // Copy attachments
                 $this->replaceAttachments($message, $newResourceMsg);
                 // Copy all recipients too
                 $this->replaceRecipients($message, $newResourceMsg);
                 // Now add organizer also to recipient table
                 $recips = array();
                 $this->addOrganizer($messageprops, $recips);
                 mapi_message_modifyrecipients($newResourceMsg, MODRECIP_ADD, $recips);
             }
             mapi_savechanges($newResourceMsg);
             $resourceRecipData[] = array('store' => $userStore, 'folder' => $calFolder, 'msg' => $newResourceMsg);
             $this->includesResources = true;
         } else {
             /**
              * If no other errors occured and you have no access to the
              * folder of the resource, throw an error=1.
              */
             if (!$this->errorSetResource) {
                 $this->errorSetResource = 1;
             }
             for ($j = 0, $len = count($resourceRecipData); $j < $len; $j++) {
                 // Get the EntryID
                 $props = mapi_message_getprops($resourceRecipData[$j]['msg']);
                 mapi_folder_deletemessages($resourceRecipData[$j]['folder'], array($props[PR_ENTRYID]), DELETE_HARD_DELETE);
             }
             $this->recipientDisplayname = $resourceRecipients[$i][PR_DISPLAY_NAME];
         }
         $i++;
     }
     /**************************************************************
      * Set the BCC-recipients (resources) tackstatus to accepted.
      */
     // Get resource recipients
     $getResourcesRestriction = array(RES_AND, array(array(RES_PROPERTY, array(RELOP => RELOP_EQ, ULPROPTAG => PR_RECIPIENT_TYPE, VALUE => array(PR_RECIPIENT_TYPE => MAPI_BCC)))));
     $recipienttable = mapi_message_getrecipienttable($message);
     $resourceRecipients = mapi_table_queryallrows($recipienttable, $this->recipprops, $getResourcesRestriction);
     if (!empty($resourceRecipients)) {
         // Set Tracking status of resource recipients to olResponseAccepted (3)
         for ($i = 0, $len = count($resourceRecipients); $i < $len; $i++) {
             $resourceRecipients[$i][PR_RECIPIENT_TRACKSTATUS] = olRecipientTrackStatusAccepted;
             $resourceRecipients[$i][PR_RECIPIENT_TRACKSTATUS_TIME] = time();
         }
         mapi_message_modifyrecipients($message, MODRECIP_MODIFY, $resourceRecipients);
     }
     // Publish updated free/busy information
     if (!$this->errorSetResource) {
         for ($i = 0, $len = count($resourceRecipData); $i < $len; $i++) {
             $storeProps = mapi_msgstore_getprops($resourceRecipData[$i]['store'], array(PR_MAILBOX_OWNER_ENTRYID));
             if (isset($storeProps[PR_MAILBOX_OWNER_ENTRYID])) {
                 $pub = new FreeBusyPublish($this->session, $resourceRecipData[$i]['store'], $resourceRecipData[$i]['folder'], $storeProps[PR_MAILBOX_OWNER_ENTRYID]);
                 $pub->publishFB(time() - 7 * 24 * 60 * 60, 6 * 30 * 24 * 60 * 60);
                 // publish from one week ago, 6 months ahead
             }
         }
     }
     return $resourceRecipData;
 }
Example #3
0
 /**
  * Imports a move of a message. This occurs when a user moves an item to another folder
  *
  * Normally, we would implement this via the 'offical' importmessagemove() function on the ICS importer,
  * but the Zarafa importer does not support this. Therefore we currently implement it via a standard mapi
  * call. This causes a mirror 'add/delete' to be sent to the PDA at the next sync.
  * Manfred, 2010-10-21. For some mobiles import was causing duplicate messages in the destination folder
  * (Mantis #202). Therefore we will create a new message in the destination folder, copy properties
  * of the source message to the new one and then delete the source message.
  *
  * @param string        $id
  * @param string        $newfolder      destination folder
  *
  * @access public
  * @return boolean
  * @throws StatusException
  */
 public function ImportMessageMove($id, $newfolder)
 {
     if (strtolower($newfolder) == strtolower(bin2hex($this->folderid))) {
         throw new StatusException(sprintf("ImportChangesICS->ImportMessageMove('%s','%s'): Error, source and destination are equal", $id, $newfolder), SYNC_MOVEITEMSSTATUS_SAMESOURCEANDDEST);
     }
     // Get the entryid of the message we're moving
     $entryid = mapi_msgstore_entryidfromsourcekey($this->store, $this->folderid, hex2bin($id));
     if (!$entryid) {
         throw new StatusException(sprintf("ImportChangesICS->ImportMessageMove('%s','%s'): Error, unable to resolve source message id", $id, $newfolder), SYNC_MOVEITEMSSTATUS_INVALIDSOURCEID);
     }
     //open the source message
     $srcmessage = mapi_msgstore_openentry($this->store, $entryid);
     if (!$srcmessage) {
         throw new StatusException(sprintf("ImportChangesICS->ImportMessageMove('%s','%s'): Error, unable to open source message: 0x%X", $id, $newfolder, mapi_last_hresult()), SYNC_MOVEITEMSSTATUS_INVALIDSOURCEID);
     }
     // get correct mapi store for the destination folder
     $dststore = ZPush::GetBackend()->GetMAPIStoreForFolderId(ZPush::GetAdditionalSyncFolderStore($newfolder), $newfolder);
     if ($dststore === false) {
         throw new StatusException(sprintf("ImportChangesICS->ImportMessageMove('%s','%s'): Error, unable to open store of destination folder", $id, $newfolder), SYNC_MOVEITEMSSTATUS_INVALIDDESTID);
     }
     $dstentryid = mapi_msgstore_entryidfromsourcekey($dststore, hex2bin($newfolder));
     if (!$dstentryid) {
         throw new StatusException(sprintf("ImportChangesICS->ImportMessageMove('%s','%s'): Error, unable to resolve destination folder", $id, $newfolder), SYNC_MOVEITEMSSTATUS_INVALIDDESTID);
     }
     $dstfolder = mapi_msgstore_openentry($dststore, $dstentryid);
     if (!$dstfolder) {
         throw new StatusException(sprintf("ImportChangesICS->ImportMessageMove('%s','%s'): Error, unable to open destination folder", $id, $newfolder), SYNC_MOVEITEMSSTATUS_INVALIDDESTID);
     }
     $newmessage = mapi_folder_createmessage($dstfolder);
     if (!$newmessage) {
         throw new StatusException(sprintf("ImportChangesICS->ImportMessageMove('%s','%s'): Error, unable to create message in destination folder: 0x%X", $id, $newfolder, mapi_last_hresult()), SYNC_MOVEITEMSSTATUS_INVALIDDESTID);
     }
     // Copy message
     mapi_copyto($srcmessage, array(), array(), $newmessage);
     if (mapi_last_hresult()) {
         throw new StatusException(sprintf("ImportChangesICS->ImportMessageMove('%s','%s'): Error, copy to destination message failed: 0x%X", $id, $newfolder, mapi_last_hresult()), SYNC_MOVEITEMSSTATUS_CANNOTMOVE);
     }
     $srcfolderentryid = mapi_msgstore_entryidfromsourcekey($this->store, $this->folderid);
     if (!$srcfolderentryid) {
         throw new StatusException(sprintf("ImportChangesICS->ImportMessageMove('%s','%s'): Error, unable to resolve source folder", $id, $newfolder), SYNC_MOVEITEMSSTATUS_INVALIDSOURCEID);
     }
     $srcfolder = mapi_msgstore_openentry($this->store, $srcfolderentryid);
     if (!$srcfolder) {
         throw new StatusException(sprintf("ImportChangesICS->ImportMessageMove('%s','%s'): Error, unable to open source folder: 0x%X", $id, $newfolder, mapi_last_hresult()), SYNC_MOVEITEMSSTATUS_INVALIDSOURCEID);
     }
     // Save changes
     mapi_savechanges($newmessage);
     if (mapi_last_hresult()) {
         throw new StatusException(sprintf("ImportChangesICS->ImportMessageMove('%s','%s'): Error, mapi_savechanges() failed: 0x%X", $id, $newfolder, mapi_last_hresult()), SYNC_MOVEITEMSSTATUS_CANNOTMOVE);
     }
     // Delete the old message
     if (!mapi_folder_deletemessages($srcfolder, array($entryid))) {
         throw new StatusException(sprintf("ImportChangesICS->ImportMessageMove('%s','%s'): Error, delete of source message failed: 0x%X. Possible duplicates.", $id, $newfolder, mapi_last_hresult()), SYNC_MOVEITEMSSTATUS_SOURCEORDESTLOCKED);
     }
     $sourcekeyprops = mapi_getprops($newmessage, array(PR_SOURCE_KEY));
     if (isset($sourcekeyprops[PR_SOURCE_KEY]) && $sourcekeyprops[PR_SOURCE_KEY]) {
         return bin2hex($sourcekeyprops[PR_SOURCE_KEY]);
     }
     return false;
 }
Example #4
0
 /**
  * Processes a response to a meeting request.
  * CalendarID is a reference and has to be set if a new calendar item is created
  *
  * @param string        $requestid      id of the object containing the request
  * @param string        $folderid       id of the parent folder of $requestid
  * @param string        $response
  *
  * @access public
  * @return string       id of the created/updated calendar obj
  * @throws StatusException
  */
 public function MeetingResponse($requestid, $folderid, $response)
 {
     // Use standard meeting response code to process meeting request
     $reqentryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($folderid), hex2bin($requestid));
     if (!$reqentryid) {
         throw new StatusException(sprintf("BackendZarafa->MeetingResponse('%s', '%s', '%s'): Error, unable to entryid of the message 0x%X", $requestid, $folderid, $response, mapi_last_hresult()), SYNC_MEETRESPSTATUS_INVALIDMEETREQ);
     }
     $mapimessage = mapi_msgstore_openentry($this->store, $reqentryid);
     if (!$mapimessage) {
         throw new StatusException(sprintf("BackendZarafa->MeetingResponse('%s','%s', '%s'): Error, unable to open request message for response 0x%X", $requestid, $folderid, $response, mapi_last_hresult()), SYNC_MEETRESPSTATUS_INVALIDMEETREQ);
     }
     $meetingrequest = new Meetingrequest($this->store, $mapimessage);
     if (!$meetingrequest->isMeetingRequest()) {
         throw new StatusException(sprintf("BackendZarafa->MeetingResponse('%s','%s', '%s'): Error, attempt to respond to non-meeting request", $requestid, $folderid, $response), SYNC_MEETRESPSTATUS_INVALIDMEETREQ);
     }
     if ($meetingrequest->isLocalOrganiser()) {
         throw new StatusException(sprintf("BackendZarafa->MeetingResponse('%s','%s', '%s'): Error, attempt to response to meeting request that we organized", $requestid, $folderid, $response), SYNC_MEETRESPSTATUS_INVALIDMEETREQ);
     }
     // Process the meeting response. We don't have to send the actual meeting response
     // e-mail, because the device will send it itself.
     switch ($response) {
         case 1:
             // accept
         // accept
         default:
             $entryid = $meetingrequest->doAccept(false, false, false, false, false, false, true);
             // last true is the $userAction
             break;
         case 2:
             // tentative
             $entryid = $meetingrequest->doAccept(true, false, false, false, false, false, true);
             // last true is the $userAction
             break;
         case 3:
             // decline
             $meetingrequest->doDecline(false);
             break;
     }
     // F/B will be updated on logoff
     // We have to return the ID of the new calendar item, so do that here
     $calendarid = "";
     if (isset($entryid)) {
         $newitem = mapi_msgstore_openentry($this->store, $entryid);
         $newprops = mapi_getprops($newitem, array(PR_SOURCE_KEY));
         $calendarid = bin2hex($newprops[PR_SOURCE_KEY]);
     }
     // on recurring items, the MeetingRequest class responds with a wrong entryid
     if ($requestid == $calendarid) {
         ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendZarafa->MeetingResponse('%s','%s', '%s'): returned calender id is the same as the requestid - re-searching", $requestid, $folderid, $response));
         $props = MAPIMapping::GetMeetingRequestProperties();
         $props = getPropIdsFromStrings($this->store, $props);
         $messageprops = mapi_getprops($mapimessage, array($props["goidtag"]));
         $goid = $messageprops[$props["goidtag"]];
         $items = $meetingrequest->findCalendarItems($goid);
         if (is_array($items)) {
             $newitem = mapi_msgstore_openentry($this->store, $items[0]);
             $newprops = mapi_getprops($newitem, array(PR_SOURCE_KEY));
             $calendarid = bin2hex($newprops[PR_SOURCE_KEY]);
             ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendZarafa->MeetingResponse('%s','%s', '%s'): found other calendar entryid", $requestid, $folderid, $response));
         }
         if ($requestid == $calendarid) {
             throw new StatusException(sprintf("BackendZarafa->MeetingResponse('%s','%s', '%s'): Error finding the accepted meeting response in the calendar", $requestid, $folderid, $response), SYNC_MEETRESPSTATUS_INVALIDMEETREQ);
         }
     }
     // delete meeting request from Inbox
     $folderentryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($folderid));
     $folder = mapi_msgstore_openentry($this->store, $folderentryid);
     mapi_folder_deletemessages($folder, array($reqentryid), 0);
     return $calendarid;
 }
Example #5
0
 function MeetingResponse($requestid, $folderid, $response, &$calendarid)
 {
     // Use standard meeting response code to process meeting request
     $reqentryid = mapi_msgstore_entryidfromsourcekey($this->_defaultstore, hex2bin($folderid), hex2bin($requestid));
     $mapimessage = mapi_msgstore_openentry($this->_defaultstore, $reqentryid);
     if (!$mapimessage) {
         debugLog("Unable to open request message for response");
         return false;
     }
     $meetingrequest = new Meetingrequest($this->_defaultstore, $mapimessage);
     if (!$meetingrequest->isMeetingRequest()) {
         debugLog("Attempt to respond to non-meeting request");
         return false;
     }
     if ($meetingrequest->isLocalOrganiser()) {
         debugLog("Attempt to response to meeting request that we organized");
         return false;
     }
     // Process the meeting response. We don't have to send the actual meeting response
     // e-mail, because the device will send it itself.
     switch ($response) {
         case 1:
             // accept
         // accept
         default:
             $entryid = $meetingrequest->doAccept(false, false, false, false, false, false, true);
             // last true is the $userAction
             break;
         case 2:
             // tentative
             $entryid = $meetingrequest->doAccept(true, false, false, false, false, false, true);
             // last true is the $userAction
             break;
         case 3:
             // decline
             $meetingrequest->doDecline(false);
             break;
     }
     // F/B will be updated on logoff
     // We have to return the ID of the new calendar item, so do that here
     if (isset($entryid)) {
         $newitem = mapi_msgstore_openentry($this->_defaultstore, $entryid);
         $newprops = mapi_getprops($newitem, array(PR_SOURCE_KEY));
         $calendarid = bin2hex($newprops[PR_SOURCE_KEY]);
     }
     // on recurring items, the MeetingRequest class responds with a wrong entryid
     if ($requestid == $calendarid) {
         debugLog("returned calender id is the same as the requestid - re-searching");
         $goidprop = GetPropIDFromString($this->_defaultstore, "PT_BINARY:{6ED8DA90-450B-101B-98DA-00AA003F1305}:0x3");
         $messageprops = mapi_getprops($mapimessage, array($goidprop, PR_OWNER_APPT_ID));
         $goid = $messageprops[$goidprop];
         if (isset($messageprops[PR_OWNER_APPT_ID])) {
             $apptid = $messageprops[PR_OWNER_APPT_ID];
         } else {
             $apptid = false;
         }
         //findCalendarItems signature was changed in 6.40.8, Mantis #485
         $items = checkMapiExtVersion("6.40.8") ? $meetingrequest->findCalendarItems($goid) : $meetingrequest->findCalendarItems($goid, $apptid);
         if (is_array($items)) {
             $newitem = mapi_msgstore_openentry($this->_defaultstore, $items[0]);
             $newprops = mapi_getprops($newitem, array(PR_SOURCE_KEY));
             $calendarid = bin2hex($newprops[PR_SOURCE_KEY]);
             debugLog("found other calendar entryid");
         }
     }
     // delete meeting request from Inbox
     $folderentryid = mapi_msgstore_entryidfromsourcekey($this->_defaultstore, hex2bin($folderid));
     $folder = mapi_msgstore_openentry($this->_defaultstore, $folderentryid);
     mapi_folder_deletemessages($folder, array($reqentryid), 0);
     return true;
 }
Example #6
0
    $store = mapi_openmsgstore($l_rSession, $storeEntryId);
    $root = mapi_msgstore_openentry($store, null);
    $spamStoreProps = mapi_getprops($root, array(PR_ADDITIONAL_REN_ENTRYIDS));
    $spamFolder = mapi_msgstore_openentry($store, $spamStoreProps[PR_ADDITIONAL_REN_ENTRYIDS][4]);
    $table = mapi_folder_getcontentstable($spamFolder);
    $spamRows = mapi_table_queryallrows($table, array(PR_ENTRYID, PR_CREATION_TIME));
    echo (mapi_last_hresult() == 0 ? "Fetching messages from Junk Folder..." : "Some error in fetching...") . "\n";
    if (count($spamRows) > 0) {
        $spamEntryIds = array();
        echo "\nTotal messages in Junk folder found are : " . count($spamRows) . "\n";
        for ($i = 0; $i < count($spamRows); $i++) {
            if (greaterDate(date("Y-m-d G:i:s", $spamRows[$i][PR_CREATION_TIME]), $daysBeforeDeleted)) {
                array_push($spamEntryIds, $spamRows[$i][PR_ENTRYID]);
            }
        }
        if (count($spamEntryIds) > 0) {
            echo "\nDeleting all " . count($spamEntryIds) . " message(s)...\n";
            mapi_folder_deletemessages($spamFolder, $spamEntryIds);
            echo "" . (mapi_last_hresult() == 0 ? "\nHooray! there is no spam." : "Some error in deleting... There are still some spam messages.") . "\n";
        } else {
            echo "\nNo message found before " . $daysBeforeDeleted . " days in Junk Folder.";
        }
    } else {
        echo "\nNo message found in Junk Folder.";
    }
} else {
    echo "No default store found... Terminating process.\n";
}
?>

Example #7
0
if ($storeEntryId) {
    $store = mapi_openmsgstore($l_rSession, $storeEntryId);
    $delStoreProps = mapi_getprops($store, array(PR_IPM_WASTEBASKET_ENTRYID));
    $deletedFolder = mapi_msgstore_openentry($store, $delStoreProps[PR_IPM_WASTEBASKET_ENTRYID]);
    $table = mapi_folder_getcontentstable($deletedFolder);
    $delRows = mapi_table_queryallrows($table, array(PR_ENTRYID, PR_CREATION_TIME));
    echo (mapi_last_hresult() == 0 ? "Fetching messages from Deleted Folder..." : "Some error in fetching...") . "\n";
    if (count($delRows) > 0) {
        $delEntryIds = array();
        echo 'Total messages in deleted folder found are : ' . count($delRows) . "\n";
        for ($i = 0; $i < count($delRows); $i++) {
            if (greaterDate(date("Y-m-d G:i:s", $delRows[$i][PR_CREATION_TIME]), $daysBeforeDeleted)) {
                array_push($delEntryIds, $delRows[$i][PR_ENTRYID]);
            }
        }
        if (count($delEntryIds) > 0) {
            echo "\nDeleting all " . count($delEntryIds) . " messages...\n";
            mapi_folder_deletemessages($deletedFolder, $delEntryIds);
            echo "" . (mapi_last_hresult() == 0 ? "Successfully deleted all messages" : "Some error in deleting... please try again later") . "\n";
        } else {
            echo "\nNo message found before " . $daysBeforeDeleted . " days in Deleted Folder.";
        }
    } else {
        echo "\nNo message found in Deleted Folder.";
    }
} else {
    echo "No default store found... Terminating process.\n";
}
?>

Example #8
0
 function MeetingResponse($requestid, $folderid, $response, &$calendarid)
 {
     // Use standard meeting response code to process meeting request
     $reqentryid = mapi_msgstore_entryidfromsourcekey($this->_defaultstore, hex2bin($folderid), hex2bin($requestid));
     $mapimessage = mapi_msgstore_openentry($this->_defaultstore, $reqentryid);
     if (!$mapimessage) {
         debugLog("Unable to open request message for response");
         return false;
     }
     $meetingrequest = new Meetingrequest($this->_defaultstore, $mapimessage);
     if (!$meetingrequest->isMeetingRequest()) {
         debugLog("Attempt to respond to non-meeting request");
         return false;
     }
     if ($meetingrequest->isLocalOrganiser()) {
         debugLog("Attempt to response to meeting request that we organized");
         return false;
     }
     // Process the meeting response. We don't have to send the actual meeting response
     // e-mail, because the device will send it itself.
     switch ($response) {
         case 1:
             // accept
         // accept
         default:
             $entryid = $meetingrequest->doAccept(false, false, false, false, false, false, true);
             // last true is the $userAction
             break;
         case 2:
             // tentative
             $entryid = $meetingrequest->doAccept(true, false, false, false, false, false, true);
             // last true is the $userAction
             break;
         case 3:
             // decline
             $meetingrequest->doDecline(false);
             break;
     }
     // F/B will be updated on logoff
     // We have to return the ID of the new calendar item, so do that here
     $newitem = mapi_msgstore_openentry($this->_defaultstore, $entryid);
     $newprops = mapi_getprops($newitem, array(PR_SOURCE_KEY));
     $calendarid = bin2hex($newprops[PR_SOURCE_KEY]);
     // delete meeting request from Inbox
     $folderentryid = mapi_msgstore_entryidfromsourcekey($this->_defaultstore, hex2bin($folderid));
     $folder = mapi_msgstore_openentry($this->_defaultstore, $folderentryid);
     mapi_folder_deletemessages($folder, array($reqentryid), 0);
     return true;
 }
Example #9
0
 /**
  * Imports a move of a message. This occurs when a user moves an item to another folder
  *
  * Normally, we would implement this via the 'offical' importmessagemove() function on the ICS importer,
  * but the Zarafa/Kopano importer does not support this. Therefore we currently implement it via a standard mapi
  * call. This causes a mirror 'add/delete' to be sent to the PDA at the next sync.
  * Manfred, 2010-10-21. For some mobiles import was causing duplicate messages in the destination folder
  * (Mantis #202). Therefore we will create a new message in the destination folder, copy properties
  * of the source message to the new one and then delete the source message.
  *
  * @param string        $id
  * @param string        $newfolder      destination folder
  *
  * @access public
  * @return boolean
  * @throws StatusException
  */
 public function ImportMessageMove($id, $newfolder)
 {
     list(, $sk) = Utils::SplitMessageId($id);
     if (strtolower($newfolder) == strtolower(bin2hex($this->folderid))) {
         throw new StatusException(sprintf("ImportChangesICS->ImportMessageMove('%s','%s'): Error, source and destination are equal", $id, $newfolder), SYNC_MOVEITEMSSTATUS_SAMESOURCEANDDEST);
     }
     // Get the entryid of the message we're moving
     $entryid = mapi_msgstore_entryidfromsourcekey($this->store, $this->folderid, hex2bin($sk));
     $srcmessage = false;
     if ($entryid) {
         //open the source message
         $srcmessage = mapi_msgstore_openentry($this->store, $entryid);
     }
     if (!$entryid || !$srcmessage) {
         $code = SYNC_MOVEITEMSSTATUS_INVALIDSOURCEID;
         // if we move to the trash and the source message is not found, we can also just tell the mobile that we successfully moved to avoid errors (ZP-624)
         if ($newfolder == ZPush::GetBackend()->GetWasteBasket()) {
             $code = SYNC_MOVEITEMSSTATUS_SUCCESS;
         }
         $errorCase = !$entryid ? "resolve source message id" : "open source message";
         throw new StatusException(sprintf("ImportChangesICS->ImportMessageMove('%s','%s'): Error, unable to %s: 0x%X", $sk, $newfolder, $errorCase, mapi_last_hresult()), $code);
     }
     // check if the source message is in the current syncinterval
     if (!$this->isMessageInSyncInterval($sk)) {
         throw new StatusException(sprintf("ImportChangesICS->ImportMessageMove('%s','%s'): Source message is outside the sync interval. Move not performed.", $sk, $newfolder), SYNC_MOVEITEMSSTATUS_INVALIDSOURCEID);
     }
     // get correct mapi store for the destination folder
     $dststore = ZPush::GetBackend()->GetMAPIStoreForFolderId(ZPush::GetAdditionalSyncFolderStore($newfolder), $newfolder);
     if ($dststore === false) {
         throw new StatusException(sprintf("ImportChangesICS->ImportMessageMove('%s','%s'): Error, unable to open store of destination folder", $sk, $newfolder), SYNC_MOVEITEMSSTATUS_INVALIDDESTID);
     }
     $dstentryid = mapi_msgstore_entryidfromsourcekey($dststore, hex2bin($newfolder));
     if (!$dstentryid) {
         throw new StatusException(sprintf("ImportChangesICS->ImportMessageMove('%s','%s'): Error, unable to resolve destination folder", $sk, $newfolder), SYNC_MOVEITEMSSTATUS_INVALIDDESTID);
     }
     $dstfolder = mapi_msgstore_openentry($dststore, $dstentryid);
     if (!$dstfolder) {
         throw new StatusException(sprintf("ImportChangesICS->ImportMessageMove('%s','%s'): Error, unable to open destination folder", $sk, $newfolder), SYNC_MOVEITEMSSTATUS_INVALIDDESTID);
     }
     $newmessage = mapi_folder_createmessage($dstfolder);
     if (!$newmessage) {
         throw new StatusException(sprintf("ImportChangesICS->ImportMessageMove('%s','%s'): Error, unable to create message in destination folder: 0x%X", $sk, $newfolder, mapi_last_hresult()), SYNC_MOVEITEMSSTATUS_INVALIDDESTID);
     }
     // Copy message
     mapi_copyto($srcmessage, array(), array(), $newmessage);
     if (mapi_last_hresult()) {
         throw new StatusException(sprintf("ImportChangesICS->ImportMessageMove('%s','%s'): Error, copy to destination message failed: 0x%X", $sk, $newfolder, mapi_last_hresult()), SYNC_MOVEITEMSSTATUS_CANNOTMOVE);
     }
     $srcfolderentryid = mapi_msgstore_entryidfromsourcekey($this->store, $this->folderid);
     if (!$srcfolderentryid) {
         throw new StatusException(sprintf("ImportChangesICS->ImportMessageMove('%s','%s'): Error, unable to resolve source folder", $sk, $newfolder), SYNC_MOVEITEMSSTATUS_INVALIDSOURCEID);
     }
     $srcfolder = mapi_msgstore_openentry($this->store, $srcfolderentryid);
     if (!$srcfolder) {
         throw new StatusException(sprintf("ImportChangesICS->ImportMessageMove('%s','%s'): Error, unable to open source folder: 0x%X", $sk, $newfolder, mapi_last_hresult()), SYNC_MOVEITEMSSTATUS_INVALIDSOURCEID);
     }
     // Save changes
     mapi_savechanges($newmessage);
     if (mapi_last_hresult()) {
         throw new StatusException(sprintf("ImportChangesICS->ImportMessageMove('%s','%s'): Error, mapi_savechanges() failed: 0x%X", $sk, $newfolder, mapi_last_hresult()), SYNC_MOVEITEMSSTATUS_CANNOTMOVE);
     }
     // Delete the old message
     if (!mapi_folder_deletemessages($srcfolder, array($entryid))) {
         throw new StatusException(sprintf("ImportChangesICS->ImportMessageMove('%s','%s'): Error, delete of source message failed: 0x%X. Possible duplicates.", $sk, $newfolder, mapi_last_hresult()), SYNC_MOVEITEMSSTATUS_SOURCEORDESTLOCKED);
     }
     $sourcekeyprops = mapi_getprops($newmessage, array(PR_SOURCE_KEY));
     if (isset($sourcekeyprops[PR_SOURCE_KEY]) && $sourcekeyprops[PR_SOURCE_KEY]) {
         $prefix = "";
         // prepend the destination short folderid, if it exists
         $destShortId = ZPush::GetDeviceManager()->GetFolderIdForBackendId($newfolder);
         if ($destShortId !== $newfolder) {
             $prefix = $destShortId . ":";
         }
         return $prefix . bin2hex($sourcekeyprops[PR_SOURCE_KEY]);
     }
     return false;
 }
 /**
  * Deletes a card
  * 
  * @param mixed $addressBookId 
  * @param string $cardUri 
  * @return bool 
  */
 public function deleteCard($addressBookId, $cardUri)
 {
     $this->logger->info("deleteCard({$cardUri})");
     if (READ_ONLY) {
         $this->logger->warn("Cannot delete card: read-only");
         return false;
     }
     $folder = mapi_msgstore_openentry($this->bridge->getStore($addressBookId), $addressBookId);
     $entryId = $this->getContactEntryId($addressBookId, $cardUri);
     if ($entryId === 0) {
         $this->logger->warn("Contact not found!");
         return false;
     }
     // $folder = mapi_msgstore_openentry($this->bridge->getStore($addressBookId), $addressBookId);
     mapi_folder_deletemessages($folder, array($entryId));
     if (mapi_last_hresult() > 0) {
         return false;
     }
     return true;
 }
Example #11
0
 /**
  * Removes all messages that do not match the current ChunkType.
  *
  * @param string $folderid
  * @param string $gabId         the id of the gab where the hidden folder should be cleared. If not set (null) the default gab is used.
  * @param string $gabName       the name of the gab where the hidden folder should be cleared. If not set (null) the default gab is used.
  *
  * @access protected
  * @return boolean
  */
 protected function clearAllNotCurrentChunkType($folderid, $gabId = null, $gabName = 'default')
 {
     $store = $this->getStore($gabId, $gabName);
     if (!$store) {
         return false;
     }
     $folder = $this->getFolder($store, $folderid);
     $table = mapi_folder_getcontentstable($folder);
     if (!$table) {
         $this->Terminate(sprintf("Kopano->clearAllNotCurrentChunkType: Error, unable to read contents table on '%s': 0x%08X", $gabName, mapi_last_hresult()));
     }
     $restriction = array(RES_PROPERTY, array(RELOP => RELOP_NE, ULPROPTAG => $this->mapiprops['chunktype'], VALUE => $this->chunkType));
     mapi_table_restrict($table, $restriction);
     $querycnt = mapi_table_getrowcount($table);
     if ($querycnt == 0) {
         $this->Log("Kopano->clearAllNotCurrentChunkType: no invalid items, done!");
     } else {
         $this->Log(sprintf("Kopano->clearAllNotCurrentChunkType: found %d invalid items, deleting", $querycnt));
         $entries = mapi_table_queryallrows($table, array(PR_ENTRYID, $this->mapiprops['chunktype']));
         $entry_ids = array_reduce($entries, function ($result, $item) {
             $result[] = $item[PR_ENTRYID];
             return $result;
         }, array());
         mapi_folder_deletemessages($folder, array_values($entry_ids));
         $this->Log("Kopano->clearAllNotCurrentChunkType: done");
     }
     $this->Log("");
     return true;
 }
Example #12
0
 /**
  * Processes a response to a meeting request.
  * CalendarID is a reference and has to be set if a new calendar item is created
  *
  * @param string        $requestid      id of the object containing the request
  * @param string        $folderid       id of the parent folder of $requestid
  * @param string        $response
  *
  * @access public
  * @return string       id of the created/updated calendar obj
  * @throws StatusException
  */
 public function MeetingResponse($requestid, $folderid, $response)
 {
     // Use standard meeting response code to process meeting request
     list($fid, $requestid) = Utils::SplitMessageId($requestid);
     $reqentryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($folderid), hex2bin($requestid));
     if (!$reqentryid) {
         throw new StatusException(sprintf("BackendKopano->MeetingResponse('%s', '%s', '%s'): Error, unable to entryid of the message 0x%X", $requestid, $folderid, $response, mapi_last_hresult()), SYNC_MEETRESPSTATUS_INVALIDMEETREQ);
     }
     $mapimessage = mapi_msgstore_openentry($this->store, $reqentryid);
     if (!$mapimessage) {
         throw new StatusException(sprintf("BackendKopano->MeetingResponse('%s','%s', '%s'): Error, unable to open request message for response 0x%X", $requestid, $folderid, $response, mapi_last_hresult()), SYNC_MEETRESPSTATUS_INVALIDMEETREQ);
     }
     $meetingrequest = new Meetingrequest($this->store, $mapimessage, $this->session);
     if (!$meetingrequest->isMeetingRequest()) {
         throw new StatusException(sprintf("BackendKopano->MeetingResponse('%s','%s', '%s'): Error, attempt to respond to non-meeting request", $requestid, $folderid, $response), SYNC_MEETRESPSTATUS_INVALIDMEETREQ);
     }
     if ($meetingrequest->isLocalOrganiser()) {
         throw new StatusException(sprintf("BackendKopano->MeetingResponse('%s','%s', '%s'): Error, attempt to response to meeting request that we organized", $requestid, $folderid, $response), SYNC_MEETRESPSTATUS_INVALIDMEETREQ);
     }
     // Process the meeting response. We don't have to send the actual meeting response
     // e-mail, because the device will send it itself.
     switch ($response) {
         case 1:
             // accept
         // accept
         default:
             $entryid = $meetingrequest->doAccept(false, false, false, false, false, false, true);
             // last true is the $userAction
             break;
         case 2:
             // tentative
             $entryid = $meetingrequest->doAccept(true, false, false, false, false, false, true);
             // last true is the $userAction
             break;
         case 3:
             // decline
             $meetingrequest->doDecline(false);
             break;
     }
     // F/B will be updated on logoff
     // We have to return the ID of the new calendar item, so do that here
     $calendarid = "";
     $calFolderId = "";
     if (isset($entryid)) {
         $newitem = mapi_msgstore_openentry($this->store, $entryid);
         // new item might be in a delegator's store. ActiveSync does not support accepting them.
         if (!$newitem) {
             throw new StatusException(sprintf("BackendKopano->MeetingResponse('%s','%s', '%s'): Object with entryid '%s' was not found in user's store (0x%X). It might be in a delegator's store.", $requestid, $folderid, $response, bin2hex($entryid), mapi_last_hresult()), SYNC_MEETRESPSTATUS_SERVERERROR, null, LOGLEVEL_WARN);
         }
         $newprops = mapi_getprops($newitem, array(PR_SOURCE_KEY, PR_PARENT_SOURCE_KEY));
         $calendarid = bin2hex($newprops[PR_SOURCE_KEY]);
         $calFolderId = bin2hex($newprops[PR_PARENT_SOURCE_KEY]);
     }
     // on recurring items, the MeetingRequest class responds with a wrong entryid
     if ($requestid == $calendarid) {
         ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendKopano->MeetingResponse('%s','%s', '%s'): returned calender id is the same as the requestid - re-searching", $requestid, $folderid, $response));
         $props = MAPIMapping::GetMeetingRequestProperties();
         $props = getPropIdsFromStrings($this->store, $props);
         $messageprops = mapi_getprops($mapimessage, array($props["goidtag"]));
         $goid = $messageprops[$props["goidtag"]];
         $items = $meetingrequest->findCalendarItems($goid);
         if (is_array($items)) {
             $newitem = mapi_msgstore_openentry($this->store, $items[0]);
             $newprops = mapi_getprops($newitem, array(PR_SOURCE_KEY, PR_PARENT_SOURCE_KEY));
             $calendarid = bin2hex($newprops[PR_SOURCE_KEY]);
             $calFolderId = bin2hex($newprops[PR_PARENT_SOURCE_KEY]);
             ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendKopano->MeetingResponse('%s','%s', '%s'): found other calendar entryid", $requestid, $folderid, $response));
         }
         if ($requestid == $calendarid) {
             throw new StatusException(sprintf("BackendKopano->MeetingResponse('%s','%s', '%s'): Error finding the accepted meeting response in the calendar", $requestid, $folderid, $response), SYNC_MEETRESPSTATUS_INVALIDMEETREQ);
         }
     }
     // delete meeting request from Inbox
     $folderentryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($folderid));
     $folder = mapi_msgstore_openentry($this->store, $folderentryid);
     mapi_folder_deletemessages($folder, array($reqentryid), 0);
     $prefix = '';
     // prepend the short folderid of the target calendar: if available and short ids are used
     if ($calFolderId) {
         $shortFolderId = ZPush::GetDeviceManager()->GetFolderIdForBackendId($calFolderId);
         if ($calFolderId != $shortFolderId) {
             $prefix = $shortFolderId . ':';
         }
     }
     return $prefix . $calendarid;
 }