function accept($tentative, $sendresponse, $move, $proposeNewTimeProps = array(), $body = false, $userAction = false, $store, $calFolder, $basedate = false)
 {
     $messageprops = mapi_getprops($this->message);
     $isDelegate = isset($messageprops[PR_RCVD_REPRESENTING_NAME]);
     if ($sendresponse) {
         $this->createResponse($tentative ? olResponseTentative : olResponseAccepted, $proposeNewTimeProps, $body, $store, $basedate, $calFolder);
     }
     /**
      * Further processing depends on what user is receiving. User can receive recurring item, a single occurrence or a normal meeting.
      * 1) If meeting req is of recurrence then we find all the occurrence in calendar because in past user might have recieved one or few occurrences.
      * 2) If single occurrence then find occurrence itself using globalID and if item is not found then use cleanGlobalID to find main recurring item
      * 3) Normal meeting req are handled normally as they were handled previously.
      *
      * Also user can respond(accept/decline) to item either from previewpane or from calendar by opening the item. If user is responding the meeting from previewpane
      * and that item is not found in calendar then item is move else item is opened and all properties, attachments and recipient are copied from meeting request.
      * If user is responding from calendar then item is opened and properties are set such as meetingstatus, responsestatus, busystatus etc.
      */
     if ($this->isMeetingRequest($messageprops[PR_MESSAGE_CLASS])) {
         // While processing the item mark it as read.
         mapi_message_setreadflag($this->message, SUPPRESS_RECEIPT);
         // This meeting request item is recurring, so find all occurrences and saves them all as exceptions to this meeting request item.
         if ($messageprops[$this->proptags['recurring']] == true) {
             $calendarItem = false;
             // Find main recurring item based on GlobalID (0x3)
             $items = $this->findCalendarItems($messageprops[$this->proptags['goid2']], $calFolder);
             if (is_array($items)) {
                 foreach ($items as $key => $entryid) {
                     $calendarItem = mapi_msgstore_openentry($store, $entryid);
                 }
             }
             $processed = false;
             if (!$calendarItem) {
                 // Recurring item not found, so create new meeting in Calendar
                 $calendarItem = mapi_folder_createmessage($calFolder);
             } else {
                 // we have found the main recurring item, check if this meeting request is already processed
                 if (isset($messageprops[PR_PROCESSED]) && $messageprops[PR_PROCESSED] == true) {
                     // only set required properties, other properties are already copied when processing this meeting request
                     // for the first time
                     $processed = true;
                 }
             }
             if (!$processed) {
                 // get all the properties and copy that to calendar item
                 $props = mapi_getprops($this->message);
                 /*
                  * the client which has sent this meeting request can generate wrong flagdueby
                  * time (mainly OL), so regenerate that property so we will always show reminder
                  * on right time
                  */
                 if (isset($props[$this->proptags['reminderminutes']])) {
                     $props[$this->proptags['flagdueby']] = $props[$this->proptags['startdate']] - $props[$this->proptags['reminderminutes']] * 60;
                 }
             } else {
                 // only get required properties so we will not overwrite existing updated properties from calendar
                 $props = mapi_getprops($this->message, array(PR_ENTRYID));
             }
             $props[PR_MESSAGE_CLASS] = 'IPM.Appointment';
             // When meeting requests are generated by third-party solutions, we might be missing the updatecounter property.
             if (!isset($props[$this->proptags['updatecounter']])) {
                 $props[$this->proptags['updatecounter']] = 0;
             }
             $props[$this->proptags['meetingstatus']] = olMeetingReceived;
             // when we are automatically processing the meeting request set responsestatus to olResponseNotResponded
             $props[$this->proptags['responsestatus']] = $userAction ? $tentative ? olResponseTentative : olResponseAccepted : olResponseNotResponded;
             if (isset($props[$this->proptags['intendedbusystatus']])) {
                 if ($tentative && $props[$this->proptags['intendedbusystatus']] !== fbFree) {
                     $props[$this->proptags['busystatus']] = fbTentative;
                 } else {
                     $props[$this->proptags['busystatus']] = $props[$this->proptags['intendedbusystatus']];
                 }
                 // we already have intendedbusystatus value in $props so no need to copy it
             } else {
                 $props[$this->proptags['busystatus']] = $tentative ? fbTentative : fbBusy;
             }
             if ($userAction) {
                 $addrInfo = $this->getOwnerAddress($this->store);
                 // if user has responded then set replytime and name
                 $props[$this->proptags['replytime']] = time();
                 if (!empty($addrInfo)) {
                     // @FIXME conditionally set this property only for delegation case
                     $props[$this->proptags['apptreplyname']] = $addrInfo[0];
                 }
             }
             mapi_setprops($calendarItem, $props);
             // we have already processed attachments and recipients, so no need to do it again
             if (!$processed) {
                 // Copy attachments too
                 $this->replaceAttachments($this->message, $calendarItem);
                 // Copy recipients too
                 $this->replaceRecipients($this->message, $calendarItem, $isDelegate);
             }
             // Find all occurrences based on CleanGlobalID (0x23)
             // there will be no exceptions left if $processed is true, but even if it doesn't hurt to recheck
             $items = $this->findCalendarItems($messageprops[$this->proptags['goid2']], $calFolder, true);
             if (is_array($items)) {
                 // Save all existing occurrence as exceptions
                 foreach ($items as $entryid) {
                     // Open occurrence
                     $occurrenceItem = mapi_msgstore_openentry($store, $entryid);
                     // Save occurrence into main recurring item as exception
                     if ($occurrenceItem) {
                         $occurrenceItemProps = mapi_getprops($occurrenceItem, array($this->proptags['goid'], $this->proptags['recurring']));
                         // Find basedate of occurrence item
                         $basedate = $this->getBasedateFromGlobalID($occurrenceItemProps[$this->proptags['goid']]);
                         if ($basedate && $occurrenceItemProps[$this->proptags['recurring']] != true) {
                             $this->mergeException($calendarItem, $occurrenceItem, $basedate, $store, $isDelegate);
                         }
                     }
                 }
             }
             mapi_savechanges($calendarItem);
             if ($move) {
                 // open wastebasket of currently logged in user and move the meeting request to it
                 // for delegates this will be delegate's wastebasket folder
                 $wastebasket = $this->openDefaultWastebasket($this->openDefaultStore());
                 mapi_folder_copymessages($calFolder, array($props[PR_ENTRYID]), $wastebasket, MESSAGE_MOVE);
             }
             $entryid = $props[PR_ENTRYID];
         } else {
             /**
              * This meeting request is not recurring, so can be an exception or normal meeting.
              * If exception then find main recurring item and update exception
              * If main recurring item is not found then put exception into Calendar as normal meeting.
              */
             $calendarItem = false;
             // We found basedate in GlobalID of this meeting request, so this meeting request if for an occurrence.
             if ($basedate) {
                 // Find main recurring item from CleanGlobalID of this meeting request
                 $items = $this->findCalendarItems($messageprops[$this->proptags['goid2']], $calFolder);
                 if (is_array($items)) {
                     foreach ($items as $key => $entryid) {
                         $calendarItem = mapi_msgstore_openentry($store, $entryid);
                     }
                 }
                 // Main recurring item is found, so now update exception
                 if ($calendarItem) {
                     $this->acceptException($calendarItem, $this->message, $basedate, $move, $tentative, $userAction, $store, $isDelegate);
                     $calendarItemProps = mapi_getprops($calendarItem, array(PR_ENTRYID));
                     $entryid = $calendarItemProps[PR_ENTRYID];
                 }
             }
             if (!$calendarItem) {
                 $items = $this->findCalendarItems($messageprops[$this->proptags['goid']], $calFolder);
                 if (is_array($items)) {
                     mapi_folder_deletemessages($calFolder, $items);
                 }
                 if ($move) {
                     // All we have to do is open the default calendar,
                     // set the mesage class correctly to be an appointment item
                     // and move it to the calendar folder
                     $sourcefolder = $this->openParentFolder();
                     // create a new calendar message, and copy the message to there,
                     // since we want to delete (move to wastebasket) the original message
                     $old_entryid = mapi_getprops($this->message, array(PR_ENTRYID));
                     $calmsg = mapi_folder_createmessage($calFolder);
                     mapi_copyto($this->message, array(), array(), $calmsg);
                     /* includes attachments and recipients */
                     /* release old message */
                     $message = null;
                     $calItemProps = array();
                     $calItemProps[PR_MESSAGE_CLASS] = 'IPM.Appointment';
                     /*
                      * the client which has sent this meeting request can generate wrong flagdueby
                      * time (mainly OL), so regenerate that property so we will always show reminder
                      * on right time
                      */
                     if (isset($messageprops[$this->proptags['reminderminutes']])) {
                         $calItemProps[$this->proptags['flagdueby']] = $messageprops[$this->proptags['startdate']] - $messageprops[$this->proptags['reminderminutes']] * 60;
                     }
                     if (isset($messageprops[$this->proptags['intendedbusystatus']])) {
                         if ($tentative && $messageprops[$this->proptags['intendedbusystatus']] !== fbFree) {
                             $calItemProps[$this->proptags['busystatus']] = fbTentative;
                         } else {
                             $calItemProps[$this->proptags['busystatus']] = $messageprops[$this->proptags['intendedbusystatus']];
                         }
                         $calItemProps[$this->proptags['intendedbusystatus']] = $messageprops[$this->proptags['intendedbusystatus']];
                     } else {
                         $calItemProps[$this->proptags['busystatus']] = $tentative ? fbTentative : fbBusy;
                     }
                     // when we are automatically processing the meeting request set responsestatus to olResponseNotResponded
                     $calItemProps[$this->proptags['responsestatus']] = $userAction ? $tentative ? olResponseTentative : olResponseAccepted : olResponseNotResponded;
                     if ($userAction) {
                         $addrInfo = $this->getOwnerAddress($this->store);
                         // if user has responded then set replytime and name
                         $calItemProps[$this->proptags['replytime']] = time();
                         if (!empty($addrInfo)) {
                             $calItemProps[$this->proptags['apptreplyname']] = $addrInfo[0];
                         }
                     }
                     mapi_setprops($calmsg, $proposeNewTimeProps + $calItemProps);
                     // get properties which stores owner information in meeting request mails
                     $props = mapi_getprops($calmsg, array(PR_SENT_REPRESENTING_ENTRYID, PR_SENT_REPRESENTING_NAME, PR_SENT_REPRESENTING_EMAIL_ADDRESS, PR_SENT_REPRESENTING_ADDRTYPE, PR_SENT_REPRESENTING_SEARCH_KEY));
                     // add owner to recipient table
                     $recips = array();
                     $this->addOrganizer($props, $recips);
                     if ($isDelegate) {
                         /**
                          * If user is delegate then remove that user from recipienttable of the MR.
                          * and delegate MR mail doesn't contain any of the attendees in recipient table.
                          * So, other required and optional attendees are added from 
                          * toattendeesstring and ccattendeesstring properties.
                          */
                         $this->setRecipsFromString($recips, $messageprops[$this->proptags['toattendeesstring']], MAPI_TO);
                         $this->setRecipsFromString($recips, $messageprops[$this->proptags['ccattendeesstring']], MAPI_CC);
                         mapi_message_modifyrecipients($calmsg, 0, $recips);
                     } else {
                         mapi_message_modifyrecipients($calmsg, MODRECIP_ADD, $recips);
                     }
                     mapi_message_savechanges($calmsg);
                     // Move the message to the wastebasket
                     $wastebasket = $this->openDefaultWastebasket($this->openDefaultStore());
                     mapi_folder_copymessages($sourcefolder, array($old_entryid[PR_ENTRYID]), $wastebasket, MESSAGE_MOVE);
                     $messageprops = mapi_getprops($calmsg, array(PR_ENTRYID));
                     $entryid = $messageprops[PR_ENTRYID];
                 } else {
                     // Create a new appointment with duplicate properties and recipient, but as an IPM.Appointment
                     $new = mapi_folder_createmessage($calFolder);
                     $props = mapi_getprops($this->message);
                     $props[PR_MESSAGE_CLASS] = 'IPM.Appointment';
                     /*
                      * the client which has sent this meeting request can generate wrong flagdueby
                      * time (mainly OL), so regenerate that property so we will always show reminder
                      * on right time
                      */
                     if (isset($props[$this->proptags['reminderminutes']])) {
                         $props[$this->proptags['flagdueby']] = $props[$this->proptags['startdate']] - $props[$this->proptags['reminderminutes']] * 60;
                     }
                     // When meeting requests are generated by third-party solutions, we might be missing the updatecounter property.
                     if (!isset($props[$this->proptags['updatecounter']])) {
                         $props[$this->proptags['updatecounter']] = 0;
                     }
                     // when we are automatically processing the meeting request set responsestatus to olResponseNotResponded
                     $props[$this->proptags['responsestatus']] = $userAction ? $tentative ? olResponseTentative : olResponseAccepted : olResponseNotResponded;
                     if (isset($props[$this->proptags['intendedbusystatus']])) {
                         if ($tentative && $props[$this->proptags['intendedbusystatus']] !== fbFree) {
                             $props[$this->proptags['busystatus']] = fbTentative;
                         } else {
                             $props[$this->proptags['busystatus']] = $props[$this->proptags['intendedbusystatus']];
                         }
                         // we already have intendedbusystatus value in $props so no need to copy it
                     } else {
                         $props[$this->proptags['busystatus']] = $tentative ? fbTentative : fbBusy;
                     }
                     if ($userAction) {
                         $addrInfo = $this->getOwnerAddress($this->store);
                         // if user has responded then set replytime and name
                         $props[$this->proptags['replytime']] = time();
                         if (!empty($addrInfo)) {
                             $props[$this->proptags['apptreplyname']] = $addrInfo[0];
                         }
                     }
                     mapi_setprops($new, $proposeNewTimeProps + $props);
                     $reciptable = mapi_message_getrecipienttable($this->message);
                     $recips = array();
                     if (!$isDelegate) {
                         $recips = mapi_table_queryallrows($reciptable, $this->recipprops);
                     }
                     $this->addOrganizer($props, $recips);
                     if ($isDelegate) {
                         /**
                          * If user is delegate then remove that user from recipienttable of the MR.
                          * and delegate MR mail doesn't contain any of the attendees in recipient table.
                          * So, other required and optional attendees are added from 
                          * toattendeesstring and ccattendeesstring properties.
                          */
                         $this->setRecipsFromString($recips, $messageprops[$this->proptags['toattendeesstring']], MAPI_TO);
                         $this->setRecipsFromString($recips, $messageprops[$this->proptags['ccattendeesstring']], MAPI_CC);
                         mapi_message_modifyrecipients($new, 0, $recips);
                     } else {
                         mapi_message_modifyrecipients($new, MODRECIP_ADD, $recips);
                     }
                     mapi_message_savechanges($new);
                     $props = mapi_getprops($new, array(PR_ENTRYID));
                     $entryid = $props[PR_ENTRYID];
                 }
             }
         }
     } else {
         // Here only properties are set on calendaritem, because user is responding from calendar.
         $props = array();
         $props[$this->proptags['responsestatus']] = $tentative ? olResponseTentative : olResponseAccepted;
         if (isset($messageprops[$this->proptags['intendedbusystatus']])) {
             if ($tentative && $messageprops[$this->proptags['intendedbusystatus']] !== fbFree) {
                 $props[$this->proptags['busystatus']] = fbTentative;
             } else {
                 $props[$this->proptags['busystatus']] = $messageprops[$this->proptags['intendedbusystatus']];
             }
             $props[$this->proptags['intendedbusystatus']] = $messageprops[$this->proptags['intendedbusystatus']];
         } else {
             $props[$this->proptags['busystatus']] = $tentative ? fbTentative : fbBusy;
         }
         $props[$this->proptags['meetingstatus']] = olMeetingReceived;
         $addrInfo = $this->getOwnerAddress($this->store);
         // if user has responded then set replytime and name
         $props[$this->proptags['replytime']] = time();
         if (!empty($addrInfo)) {
             $props[$this->proptags['apptreplyname']] = $addrInfo[0];
         }
         if ($basedate) {
             $recurr = new Recurrence($store, $this->message);
             // Copy recipients list
             $reciptable = mapi_message_getrecipienttable($this->message);
             $recips = mapi_table_queryallrows($reciptable, $this->recipprops);
             if ($recurr->isException($basedate)) {
                 $recurr->modifyException($proposeNewTimeProps + $props, $basedate, $recips);
             } else {
                 $props[$this->proptags['startdate']] = $recurr->getOccurrenceStart($basedate);
                 $props[$this->proptags['duedate']] = $recurr->getOccurrenceEnd($basedate);
                 $props[PR_SENT_REPRESENTING_EMAIL_ADDRESS] = $messageprops[PR_SENT_REPRESENTING_EMAIL_ADDRESS];
                 $props[PR_SENT_REPRESENTING_NAME] = $messageprops[PR_SENT_REPRESENTING_NAME];
                 $props[PR_SENT_REPRESENTING_ADDRTYPE] = $messageprops[PR_SENT_REPRESENTING_ADDRTYPE];
                 $props[PR_SENT_REPRESENTING_ENTRYID] = $messageprops[PR_SENT_REPRESENTING_ENTRYID];
                 $props[PR_SENT_REPRESENTING_SEARCH_KEY] = $messageprops[PR_SENT_REPRESENTING_SEARCH_KEY];
                 $recurr->createException($proposeNewTimeProps + $props, $basedate, false, $recips);
             }
         } else {
             mapi_setprops($this->message, $proposeNewTimeProps + $props);
         }
         mapi_savechanges($this->message);
         $entryid = $messageprops[PR_ENTRYID];
     }
     return $entryid;
 }
 function accept($tentative, $sendresponse, $move, $newProposedStartTime = false, $newProposedEndTime = false, $body = false, $userAction = false, $store, $calFolder, $basedate = false)
 {
     $messageprops = mapi_getprops($this->message);
     $isDelegate = false;
     if (isset($messageprops[PR_DELEGATED_BY_RULE])) {
         $isDelegate = true;
     }
     $goid = $messageprops[$this->proptags['goid2']];
     // Retrieve basedate from globalID, if it is not recieved as argument
     if (!$basedate) {
         $basedate = $this->getBasedateFromGlobalID($messageprops[$this->proptags['goid']]);
     }
     if ($sendresponse) {
         $this->createResponse($tentative ? olResponseTentative : olResponseAccepted, $newProposedStartTime, $newProposedEndTime, $body, $store, $basedate, $calFolder);
     }
     $entryids = $this->findCalendarItems($goid, $calFolder);
     if (is_array($entryids)) {
         // Only check the first, there should only be one anyway...
         $previtem = mapi_msgstore_openentry($store, $entryids[0]);
         $prevcounterprops = mapi_getprops($previtem, array($this->proptags['updatecounter']));
         // Check if the existing item has an updatecounter that is lower than the request we are processing. If not, then we ignore this call, since the
         // meeting request is out of date.
         /*
             if(message_counter < appointment_counter) do_nothing
             if(message_counter == appointment_counter) do_something_if_the_user_tells_us (userAction == true)
             if(message_counter > appointment_counter) do_something_even_automatically
         */
         if (isset($prevcounterprops[$this->proptags['updatecounter']]) && $messageprops[$this->proptags['updatecounter']] < $prevcounterprops[$this->proptags['updatecounter']]) {
             return false;
         } else {
             if (isset($prevcounterprops[$this->proptags['updatecounter']]) && $messageprops[$this->proptags['updatecounter']] == $prevcounterprops[$this->proptags['updatecounter']]) {
                 if ($userAction == false && !$basedate) {
                     return false;
                 }
             }
         }
     }
     // set counter proposal properties in calendar item when proposing new time
     // @FIXME this can be moved before call to createResponse function so that function doesn't need to recalculate duration
     $proposeNewTimeProps = array();
     if ($newProposedStartTime && $newProposedEndTime) {
         $proposeNewTimeProps[$this->proptags['proposed_start_whole']] = $newProposedStartTime;
         $proposeNewTimeProps[$this->proptags['proposed_end_whole']] = $newProposedEndTime;
         $proposeNewTimeProps[$this->proptags['proposed_duration']] = round($newProposedEndTime - $newProposedStartTime) / 60;
         $proposeNewTimeProps[$this->proptags['counter_proposal']] = true;
     }
     /**
      * Further processing depends on what user is receiving. User can receive recurring item, a single occurrence or a normal meeting.
      * 1) If meeting req is of recurrence then we find all the occurrence in calendar because in past user might have recivied one or few occurrences.
      * 2) If single occurrence then find occurrence itself using globalID and if item is not found then user cleanGlobalID to find main recurring item
      * 3) Normal meeting req are handled normally has they were handled previously.
      *
      * Also user can respond(accept/decline) to item either from previewpane or from calendar by opening the item. If user is responding the meeting from previewpane
      * and that item is not found in calendar then item is move else item is opened and all properties, attachments and recipient are copied from meeting request.
      * If user is responding from calendar then item is opened and properties are set such as meetingstatus, responsestatus, busystatus etc.
      */
     if ($messageprops[PR_MESSAGE_CLASS] == "IPM.Schedule.Meeting.Request") {
         // While processing the item mark it as read.
         mapi_message_setreadflag($this->message, SUPPRESS_RECEIPT);
         // This meeting request item is recurring, so find all occurrences and saves them all as exceptions to this meeting request item.
         if ($messageprops[$this->proptags['recurring']] == true) {
             $calendarItem = false;
             // Find main recurring item based on GlobalID (0x3)
             $items = $this->findCalendarItems($messageprops[$this->proptags['goid2']], $calFolder);
             if (is_array($items)) {
                 foreach ($items as $key => $entryid) {
                     $calendarItem = mapi_msgstore_openentry($store, $entryid);
                 }
             }
             // Recurring item not found, so create new meeting in Calendar
             if (!$calendarItem) {
                 $calendarItem = mapi_folder_createmessage($calFolder);
             }
             // Copy properties
             $props = mapi_getprops($this->message);
             $props[PR_MESSAGE_CLASS] = 'IPM.Appointment';
             $props[$this->proptags['meetingstatus']] = olMeetingReceived;
             // when we are automatically processing the meeting request set responsestatus to olResponseNotResponded
             $props[$this->proptags['responsestatus']] = $userAction ? $tentative ? olResponseTentative : olResponseAccepted : olResponseNotResponded;
             if (isset($props[$this->proptags['intendedbusystatus']])) {
                 if ($tentative && $props[$this->proptags['intendedbusystatus']] !== fbFree) {
                     $props[$this->proptags['busystatus']] = $tentative;
                 } else {
                     $props[$this->proptags['busystatus']] = $props[$this->proptags['intendedbusystatus']];
                 }
                 // we already have intendedbusystatus value in $props so no need to copy it
             } else {
                 $props[$this->proptags['busystatus']] = $tentative ? fbTentative : fbBusy;
             }
             if ($userAction) {
                 // if user has responded then set replytime
                 $props[$this->proptags['replytime']] = time();
             }
             mapi_setprops($calendarItem, $props);
             // Copy attachments too
             $this->replaceAttachments($this->message, $calendarItem);
             // Copy recipients too
             $this->replaceRecipients($this->message, $calendarItem, $isDelegate);
             // Find all occurrences based on CleanGlobalID (0x23)
             $items = $this->findCalendarItems($messageprops[$this->proptags['goid2']], $calFolder, true);
             if (is_array($items)) {
                 // Save all existing occurrence as exceptions
                 foreach ($items as $entryid) {
                     // Open occurrence
                     $occurrenceItem = mapi_msgstore_openentry($store, $entryid);
                     // Save occurrence into main recurring item as exception
                     if ($occurrenceItem) {
                         $occurrenceItemProps = mapi_getprops($occurrenceItem, array($this->proptags['goid'], $this->proptags['recurring']));
                         // Find basedate of occurrence item
                         $basedate = $this->getBasedateFromGlobalID($occurrenceItemProps[$this->proptags['goid']]);
                         if ($basedate && $occurrenceItemProps[$this->proptags['recurring']] != true) {
                             $this->acceptException($calendarItem, $occurrenceItem, $basedate, true, $tentative, $userAction, $store, $isDelegate);
                         }
                     }
                 }
             }
             mapi_savechanges($calendarItem);
             if ($move) {
                 $wastebasket = $this->openDefaultWastebasket();
                 mapi_folder_copymessages($calFolder, array($props[PR_ENTRYID]), $wastebasket, MESSAGE_MOVE);
             }
             $entryid = $props[PR_ENTRYID];
         } else {
             /**
              * This meeting request is not recurring, so can be an exception or normal meeting.
              * If exception then find main recurring item and update exception
              * If main recurring item is not found then put exception into Calendar as normal meeting.
              */
             $calendarItem = false;
             // We found basedate in GlobalID of this meeting request, so this meeting request if for an occurrence.
             if ($basedate) {
                 // Find main recurring item from CleanGlobalID of this meeting request
                 $items = $this->findCalendarItems($messageprops[$this->proptags['goid2']], $calFolder);
                 if (is_array($items)) {
                     foreach ($items as $key => $entryid) {
                         $calendarItem = mapi_msgstore_openentry($store, $entryid);
                     }
                 }
                 // Main recurring item is found, so now update exception
                 if ($calendarItem) {
                     $this->acceptException($calendarItem, $this->message, $basedate, $move, $tentative, $userAction, $store, $isDelegate);
                     $calendarItemProps = mapi_getprops($calendarItem, array(PR_ENTRYID));
                     $entryid = $calendarItemProps[PR_ENTRYID];
                 }
             }
             if (!$calendarItem) {
                 $items = $this->findCalendarItems($messageprops[$this->proptags['goid']], $calFolder);
                 if (is_array($items)) {
                     mapi_folder_deletemessages($calFolder, $items);
                 }
                 if ($move) {
                     // All we have to do is open the default calendar,
                     // set the mesage class correctly to be an appointment item
                     // and move it to the calendar folder
                     $sourcefolder = $this->openParentFolder();
                     /* create a new calendar message, and copy the message to there,
                        since we want to delete (move to wastebasket) the original message */
                     $old_entryid = mapi_getprops($this->message, array(PR_ENTRYID));
                     $calmsg = mapi_folder_createmessage($calFolder);
                     mapi_copyto($this->message, array(), array(), $calmsg);
                     /* includes attachments and recipients */
                     /* release old message */
                     $message = null;
                     $calItemProps = array();
                     $calItemProps[PR_MESSAGE_CLASS] = "IPM.Appointment";
                     if (isset($messageprops[$this->proptags['intendedbusystatus']])) {
                         if ($tentative && $messageprops[$this->proptags['intendedbusystatus']] !== fbFree) {
                             $calItemProps[$this->proptags['busystatus']] = $tentative;
                         } else {
                             $calItemProps[$this->proptags['busystatus']] = $messageprops[$this->proptags['intendedbusystatus']];
                         }
                         $calItemProps[$this->proptags['intendedbusystatus']] = $messageprops[$this->proptags['intendedbusystatus']];
                     } else {
                         $calItemProps[$this->proptags['busystatus']] = $tentative ? fbTentative : fbBusy;
                     }
                     // when we are automatically processing the meeting request set responsestatus to olResponseNotResponded
                     $calItemProps[$this->proptags['responsestatus']] = $userAction ? $tentative ? olResponseTentative : olResponseAccepted : olResponseNotResponded;
                     if ($userAction) {
                         // if user has responded then set replytime
                         $calItemProps[$this->proptags['replytime']] = time();
                     }
                     mapi_setprops($calmsg, $proposeNewTimeProps + $calItemProps);
                     // get properties which stores owner information in meeting request mails
                     $props = mapi_getprops($calmsg, array(PR_SENT_REPRESENTING_ENTRYID, PR_SENT_REPRESENTING_NAME, PR_SENT_REPRESENTING_EMAIL_ADDRESS, PR_SENT_REPRESENTING_ADDRTYPE));
                     // add owner to recipient table
                     $recips = array();
                     $this->addOrganizer($props, $recips);
                     if ($isDelegate) {
                         /**
                          * If user is delegate then remove that user from recipienttable of the MR.
                          * and delegate MR mail doesn't contain any of the attendees in recipient table.
                          * So, other required and optional attendees are added from
                          * toattendeesstring and ccattendeesstring properties.
                          */
                         $this->setRecipsFromString($recips, $messageprops[$this->proptags['toattendeesstring']], MAPI_TO);
                         $this->setRecipsFromString($recips, $messageprops[$this->proptags['ccattendeesstring']], MAPI_CC);
                         mapi_message_modifyrecipients($calmsg, 0, $recips);
                     } else {
                         mapi_message_modifyrecipients($calmsg, MODRECIP_ADD, $recips);
                     }
                     mapi_message_savechanges($calmsg);
                     // Move the message to the wastebasket
                     $wastebasket = $this->openDefaultWastebasket();
                     mapi_folder_copymessages($sourcefolder, array($old_entryid[PR_ENTRYID]), $wastebasket, MESSAGE_MOVE);
                     $messageprops = mapi_getprops($calmsg, array(PR_ENTRYID));
                     $entryid = $messageprops[PR_ENTRYID];
                 } else {
                     // Create a new appointment with duplicate properties and recipient, but as an IPM.Appointment
                     $new = mapi_folder_createmessage($calFolder);
                     $props = mapi_getprops($this->message);
                     $props[PR_MESSAGE_CLASS] = "IPM.Appointment";
                     // when we are automatically processing the meeting request set responsestatus to olResponseNotResponded
                     $props[$this->proptags['responsestatus']] = $userAction ? $tentative ? olResponseTentative : olResponseAccepted : olResponseNotResponded;
                     if (isset($props[$this->proptags['intendedbusystatus']])) {
                         if ($tentative && $props[$this->proptags['intendedbusystatus']] !== fbFree) {
                             $props[$this->proptags['busystatus']] = $tentative;
                         } else {
                             $props[$this->proptags['busystatus']] = $props[$this->proptags['intendedbusystatus']];
                         }
                         // we already have intendedbusystatus value in $props so no need to copy it
                     } else {
                         $props[$this->proptags['busystatus']] = $tentative ? fbTentative : fbBusy;
                     }
                     if ($userAction) {
                         // if user has responded then set replytime
                         $props[$this->proptags['replytime']] = time();
                     }
                     mapi_setprops($new, $proposeNewTimeProps + $props);
                     $reciptable = mapi_message_getrecipienttable($this->message);
                     $recips = array();
                     if (!$isDelegate) {
                         $recips = mapi_table_queryallrows($reciptable, $this->recipprops);
                     }
                     $this->addOrganizer($props, $recips);
                     if ($isDelegate) {
                         /**
                          * If user is delegate then remove that user from recipienttable of the MR.
                          * and delegate MR mail doesn't contain any of the attendees in recipient table.
                          * So, other required and optional attendees are added from
                          * toattendeesstring and ccattendeesstring properties.
                          */
                         $this->setRecipsFromString($recips, $messageprops[$this->proptags['toattendeesstring']], MAPI_TO);
                         $this->setRecipsFromString($recips, $messageprops[$this->proptags['ccattendeesstring']], MAPI_CC);
                         mapi_message_modifyrecipients($new, 0, $recips);
                     } else {
                         mapi_message_modifyrecipients($new, MODRECIP_ADD, $recips);
                     }
                     mapi_message_savechanges($new);
                     $props = mapi_getprops($new, array(PR_ENTRYID));
                     $entryid = $props[PR_ENTRYID];
                 }
             }
         }
     } else {
         // Here only properties are set on calendaritem, because user is responding from calendar.
         $props = array();
         $props[$this->proptags['responsestatus']] = $tentative ? olResponseTentative : olResponseAccepted;
         if (isset($messageprops[$this->proptags['intendedbusystatus']])) {
             if ($tentative && $messageprops[$this->proptags['intendedbusystatus']] !== fbFree) {
                 $props[$this->proptags['busystatus']] = $tentative;
             } else {
                 $props[$this->proptags['busystatus']] = $messageprops[$this->proptags['intendedbusystatus']];
             }
             $props[$this->proptags['intendedbusystatus']] = $messageprops[$this->proptags['intendedbusystatus']];
         } else {
             $props[$this->proptags['busystatus']] = $tentative ? fbTentative : fbBusy;
         }
         $props[$this->proptags['meetingstatus']] = olMeetingReceived;
         $props[$this->proptags['replytime']] = time();
         if ($basedate) {
             $recurr = new Recurrence($store, $this->message);
             // Copy recipients list
             $reciptable = mapi_message_getrecipienttable($this->message);
             $recips = mapi_table_queryallrows($reciptable, $this->recipprops);
             if ($recurr->isException($basedate)) {
                 $recurr->modifyException($proposeNewTimeProps + $props, $basedate, $recips);
             } else {
                 $props[$this->proptags['startdate']] = $recurr->getOccurrenceStart($basedate);
                 $props[$this->proptags['duedate']] = $recurr->getOccurrenceEnd($basedate);
                 $props[PR_SENT_REPRESENTING_EMAIL_ADDRESS] = $messageprops[PR_SENT_REPRESENTING_EMAIL_ADDRESS];
                 $props[PR_SENT_REPRESENTING_NAME] = $messageprops[PR_SENT_REPRESENTING_NAME];
                 $props[PR_SENT_REPRESENTING_ADDRTYPE] = $messageprops[PR_SENT_REPRESENTING_ADDRTYPE];
                 $props[PR_SENT_REPRESENTING_ENTRYID] = $messageprops[PR_SENT_REPRESENTING_ENTRYID];
                 $recurr->createException($proposeNewTimeProps + $props, $basedate, false, $recips);
             }
         } else {
             mapi_setprops($this->message, $proposeNewTimeProps + $props);
         }
         mapi_savechanges($this->message);
         $entryid = $messageprops[PR_ENTRYID];
     }
     return $entryid;
 }
Beispiel #3
0
 /**
  * Imports a change in 'read' flag
  * This can never conflict
  *
  * @param string        $id
  * @param int           $flags - read/unread
  *
  * @access public
  * @return boolean
  * @throws StatusException
  */
 public function ImportMessageReadFlag($id, $flags)
 {
     list($fsk, $sk) = Utils::SplitMessageId($id);
     // if $fsk is set, we convert it into a backend id.
     if ($fsk) {
         $fsk = ZPush::GetDeviceManager()->GetBackendIdForFolderId($fsk);
     }
     // read flag change for our current folder
     if ($this->folderidHex == $fsk || empty($fsk)) {
         // check if the message is in the current syncinterval
         if (!$this->isMessageInSyncInterval($sk)) {
             throw new StatusException(sprintf("ImportChangesICS->ImportMessageReadFlag('%s','%d'): Message is outside the sync interval. Flags not updated.", $id, $flags), SYNC_STATUS_OBJECTNOTFOUND);
         }
         // check for conflicts
         /*
         * Checking for conflicts is correct at this point, but is a very expensive operation.
         * If the message was deleted, only an error will be shown.
         *
                     $this->lazyLoadConflicts();
                     if($this->memChanges->IsDeleted($id)) {
            ZLog::Write(LOGLEVEL_INFO, sprintf("ImportChangesICS->ImportMessageReadFlag('%s'): Conflict detected. Data is already deleted. Request will be ignored.", $id));
            return true;
                     }
         */
         $readstate = array("sourcekey" => hex2bin($sk), "flags" => $flags);
         if (!mapi_importcontentschanges_importperuserreadstatechange($this->importer, array($readstate))) {
             throw new StatusException(sprintf("ImportChangesICS->ImportMessageReadFlag('%s','%d'): Error setting read state: 0x%X", $id, $flags, mapi_last_hresult()), SYNC_STATUS_OBJECTNOTFOUND);
         }
     } else {
         if (!$fsk) {
             throw new StatusException(sprintf("ImportChangesICS->ImportMessageReadFlag('%s','%d'): Error setting read state. The message is in another folder but id is unknown as no short folder id is available. Please remove your device states to fully resync your device. Operation ignored.", $id, $flags), SYNC_STATUS_OBJECTNOTFOUND);
         }
         $store = ZPush::GetBackend()->GetMAPIStoreForFolderId(ZPush::GetAdditionalSyncFolderStore($fsk), $fsk);
         $entryid = mapi_msgstore_entryidfromsourcekey($store, hex2bin($fsk), hex2bin($sk));
         $realMessage = mapi_msgstore_openentry($store, $entryid);
         $flag = 0;
         if ($flags == 0) {
             $flag |= CLEAR_READ_FLAG;
         }
         $p = mapi_message_setreadflag($realMessage, $flag);
         ZLog::Write(LOGLEVEL_DEBUG, sprintf("ImportChangesICS->ImportMessageReadFlag('%s','%d'): setting readflag on message: 0x%X", $id, $flags, mapi_last_hresult()));
     }
     return true;
 }