function renamefolder($store, $entryid, $name)
{
    if (!$entryid) {
        print "Unable to find {$name} folder\n";
        return;
    }
    $folder = mapi_msgstore_openentry($store, $entryid);
    if (!$folder) {
        print "Unable to open folder " . bin2hex($entryid) . "\n";
        return;
    }
    mapi_setprops($folder, array(PR_DISPLAY_NAME => $name));
    if (mapi_last_hresult() != 0) {
        print "Unable to rename " . bin2hex($entryid) . " to '{$name}'\n";
    } else {
        print "Renamed " . bin2hex($entryid) . " to '{$name}'\n";
    }
}
Exemplo n.º 2
0
 /**
  * Copies attachments from one message to another.
  *
  * @param MAPIMessage $toMessage
  * @param MAPIMessage $fromMessage
  *
  * @return void
  */
 private function copyAttachments(&$toMessage, $fromMessage)
 {
     $attachtable = mapi_message_getattachmenttable($fromMessage);
     $rows = mapi_table_queryallrows($attachtable, array(PR_ATTACH_NUM));
     foreach ($rows as $row) {
         if (isset($row[PR_ATTACH_NUM])) {
             $attach = mapi_message_openattach($fromMessage, $row[PR_ATTACH_NUM]);
             $newattach = mapi_message_createattach($toMessage);
             // Copy all attachments from old to new attachment
             $attachprops = mapi_getprops($attach);
             mapi_setprops($newattach, $attachprops);
             if (isset($attachprops[mapi_prop_tag(PT_ERROR, mapi_prop_id(PR_ATTACH_DATA_BIN))])) {
                 // Data is in a stream
                 $srcstream = mapi_openpropertytostream($attach, PR_ATTACH_DATA_BIN);
                 $dststream = mapi_openpropertytostream($newattach, PR_ATTACH_DATA_BIN, MAPI_MODIFY | MAPI_CREATE);
                 while (1) {
                     $data = mapi_stream_read($srcstream, 4096);
                     if (strlen($data) == 0) {
                         break;
                     }
                     mapi_stream_write($dststream, $data);
                 }
                 mapi_stream_commit($dststream);
             }
             mapi_savechanges($newattach);
         }
     }
 }
Exemplo n.º 3
0
 /**
  * Generates and stores recurrence pattern string to recurring_pattern property.
  */
 function saveRecurrencePattern()
 {
     // Start formatting the properties in such a way we can apply
     // them directly into the recurrence pattern.
     $type = $this->recur['type'];
     $everyn = $this->recur['everyn'];
     $start = $this->recur['start'];
     $end = $this->recur['end'];
     $term = $this->recur['term'];
     $numocc = isset($this->recur['numoccur']) ? $this->recur['numoccur'] : false;
     $startocc = $this->recur['startocc'];
     $endocc = $this->recur['endocc'];
     $pattern = '';
     $occSingleDayRank = false;
     $occTimeRange = $startocc != 0 && $endocc != 0;
     switch ($type) {
         // Daily
         case 0xa:
             if ($everyn == 1) {
                 $type = _('workday');
                 $occSingleDayRank = true;
             } else {
                 if ($everyn == 24 * 60) {
                     $type = _('day');
                     $occSingleDayRank = true;
                 } else {
                     $everyn /= 24 * 60;
                     $type = _('days');
                     $occSingleDayRank = false;
                 }
             }
             break;
             // Weekly
         // Weekly
         case 0xb:
             if ($everyn == 1) {
                 $type = _('week');
                 $occSingleDayRank = true;
             } else {
                 $type = _('weeks');
                 $occSingleDayRank = false;
             }
             break;
             // Monthly
         // Monthly
         case 0xc:
             if ($everyn == 1) {
                 $type = _('month');
                 $occSingleDayRank = true;
             } else {
                 $type = _('months');
                 $occSingleDayRank = false;
             }
             break;
             // Yearly
         // Yearly
         case 0xd:
             if ($everyn <= 12) {
                 $everyn = 1;
                 $type = _('year');
                 $occSingleDayRank = true;
             } else {
                 $everyn = $everyn / 12;
                 $type = _('years');
                 $occSingleDayRank = false;
             }
             break;
     }
     // get timings of the first occurence
     $firstoccstartdate = isset($startocc) ? $start + (int) $startocc * 60 : $start;
     $firstoccenddate = isset($endocc) ? $end + (int) $endocc * 60 : $end;
     $start = gmdate(_('d-m-Y'), $firstoccstartdate);
     $end = gmdate(_('d-m-Y'), $firstoccenddate);
     $startocc = gmdate(_('G:i'), $firstoccstartdate);
     $endocc = gmdate(_('G:i'), $firstoccenddate);
     // Based on the properties, we need to generate the recurrence pattern string.
     // This is obviously very easy since we can simply concatenate a bunch of strings,
     // however this messes up translations for languages which order their words
     // differently.
     // To improve translation quality we create a series of default strings, in which
     // we only have to fill in the correct variables. The base string is thus selected
     // based on the available properties.
     if ($term == 0x23) {
         // Never ends
         if ($occTimeRange) {
             if ($occSingleDayRank) {
                 $pattern = sprintf(_('Occurs every %s effective %s from %s to %s.'), $type, $start, $startocc, $endocc);
             } else {
                 $pattern = sprintf(_('Occurs every %s %s effective %s from %s to %s.'), $everyn, $type, $start, $startocc, $endocc);
             }
         } else {
             if ($occSingleDayRank) {
                 $pattern = sprintf(_('Occurs every %s effective %s.'), $type, $start);
             } else {
                 $pattern = sprintf(_('Occurs every %s %s effective %s.'), $everyn, $type, $start);
             }
         }
     } else {
         if ($term == 0x22) {
             // After a number of times
             if ($occTimeRange) {
                 if ($occSingleDayRank) {
                     $pattern = sprintf(ngettext('Occurs every %s effective %s for %s occurence from %s to %s.', 'Occurs every %s effective %s for %s occurences from %s to %s.', $numocc), $type, $start, $numocc, $startocc, $endocc);
                 } else {
                     $pattern = sprintf(ngettext('Occurs every %s %s effective %s for %s occurence from %s to %s.', 'Occurs every %s %s effective %s for %s occurences %s to %s.', $numocc), $everyn, $type, $start, $numocc, $startocc, $endocc);
                 }
             } else {
                 if ($occSingleDayRank) {
                     $pattern = sprintf(ngettext('Occurs every %s effective %s for %s occurence.', 'Occurs every %s effective %s for %s occurences.', $numocc), $type, $start, $numocc);
                 } else {
                     $pattern = sprintf(ngettext('Occurs every %s %s effective %s for %s occurence.', 'Occurs every %s %s effective %s for %s occurences.', $numocc), $everyn, $type, $start, $numocc);
                 }
             }
         } else {
             if ($term == 0x21) {
                 // After the given enddate
                 if ($occTimeRange) {
                     if ($occSingleDayRank) {
                         $pattern = sprintf(_('Occurs every %s effective %s until %s from %s to %s.'), $type, $start, $end, $startocc, $endocc);
                     } else {
                         $pattern = sprintf(_('Occurs every %s %s effective %s until %s from %s to %s.'), $everyn, $type, $start, $end, $startocc, $endocc);
                     }
                 } else {
                     if ($occSingleDayRank) {
                         $pattern = sprintf(_('Occurs every %s effective %s until %s.'), $type, $start, $end);
                     } else {
                         $pattern = sprintf(_('Occurs every %s %s effective %s until %s.'), $everyn, $type, $start, $end);
                     }
                 }
             }
         }
     }
     if (!empty($pattern)) {
         mapi_setprops($this->message, array($this->proptags["recurring_pattern"] => $pattern));
     }
 }
Exemplo n.º 4
0
 function _storeAttachment($mapimessage, $part)
 {
     // attachment
     $attach = mapi_message_createattach($mapimessage);
     $filename = "";
     // Filename is present in both Content-Type: name=.. and in Content-Disposition: filename=
     if (isset($part->ctype_parameters["name"])) {
         $filename = $part->ctype_parameters["name"];
     } else {
         if (isset($part->d_parameters["name"])) {
             $filename = $part->d_parameters["filename"];
         } else {
             if (isset($part->d_parameters["filename"])) {
                 // sending appointment with nokia & android only filename is set
                 $filename = $part->d_parameters["filename"];
             } else {
                 if (isset($part->d_parameters["filename*0"])) {
                     for ($i = 0; $i < count($part->d_parameters); $i++) {
                         if (isset($part->d_parameters["filename*" . $i])) {
                             $filename .= $part->d_parameters["filename*" . $i];
                         }
                     }
                 } else {
                     $filename = "untitled";
                 }
             }
         }
     }
     // Android just doesn't send content-type, so mimeDecode doesn't performs base64 decoding
     // on meeting requests text/calendar somewhere inside content-transfer-encoding
     if (isset($part->headers['content-transfer-encoding']) && strpos($part->headers['content-transfer-encoding'], 'base64')) {
         if (strpos($part->headers['content-transfer-encoding'], 'text/calendar') !== false) {
             $part->ctype_primary = 'text';
             $part->ctype_secondary = 'calendar';
         }
         if (!isset($part->headers['content-type'])) {
             $part->body = base64_decode($part->body);
         }
     }
     // Set filename and attachment type
     mapi_setprops($attach, array(PR_ATTACH_LONG_FILENAME => u2wi($filename), PR_ATTACH_METHOD => ATTACH_BY_VALUE));
     // Set attachment data
     mapi_setprops($attach, array(PR_ATTACH_DATA_BIN => $part->body));
     // Set MIME type
     mapi_setprops($attach, array(PR_ATTACH_MIME_TAG => $part->ctype_primary . "/" . $part->ctype_secondary));
     mapi_savechanges($attach);
 }
Exemplo n.º 5
0
 /**
  * Imports a change on a folder
  *
  * @param object        $folder     SyncFolder
  *
  * @access public
  * @return string       id of the folder
  * @throws StatusException
  */
 public function ImportFolderChange($folder)
 {
     $id = isset($folder->serverid) ? $folder->serverid : false;
     $parent = $folder->parentid;
     $displayname = u2wi($folder->displayname);
     $type = $folder->type;
     if (Utils::IsSystemFolder($type)) {
         throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, system folder can not be created/modified", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname), SYNC_FSSTATUS_SYSTEMFOLDER);
     }
     // create a new folder if $id is not set
     if (!$id) {
         // the root folder is "0" - get IPM_SUBTREE
         if ($parent == "0") {
             $parentprops = mapi_getprops($this->store, array(PR_IPM_SUBTREE_ENTRYID));
             if (isset($parentprops[PR_IPM_SUBTREE_ENTRYID])) {
                 $parentfentryid = $parentprops[PR_IPM_SUBTREE_ENTRYID];
             }
         } else {
             $parentfentryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($parent));
         }
         if (!$parentfentryid) {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to open parent folder (no entry id)", Utils::PrintAsString(false), $folder->parentid, $displayname), SYNC_FSSTATUS_PARENTNOTFOUND);
         }
         $parentfolder = mapi_msgstore_openentry($this->store, $parentfentryid);
         if (!$parentfolder) {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to open parent folder (open entry)", Utils::PrintAsString(false), $folder->parentid, $displayname), SYNC_FSSTATUS_PARENTNOTFOUND);
         }
         //  mapi_folder_createfolder() fails if a folder with this name already exists -> MAPI_E_COLLISION
         $newfolder = mapi_folder_createfolder($parentfolder, $displayname, "");
         if (mapi_last_hresult()) {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, mapi_folder_createfolder() failed: 0x%X", Utils::PrintAsString(false), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_FOLDEREXISTS);
         }
         mapi_setprops($newfolder, array(PR_CONTAINER_CLASS => MAPIUtils::GetContainerClassFromFolderType($type)));
         $props = mapi_getprops($newfolder, array(PR_SOURCE_KEY));
         if (isset($props[PR_SOURCE_KEY])) {
             $sourcekey = bin2hex($props[PR_SOURCE_KEY]);
             ZLog::Write(LOGLEVEL_DEBUG, sprintf("Created folder '%s' with id: '%s'", $displayname, $sourcekey));
             return $sourcekey;
         } else {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, folder created but PR_SOURCE_KEY not available: 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_SERVERERROR);
         }
         return false;
     }
     // open folder for update
     $entryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($id));
     if (!$entryid) {
         throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to open folder (no entry id): 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_PARENTNOTFOUND);
     }
     // check if this is a MAPI default folder
     if ($this->mapiprovider->IsMAPIDefaultFolder($entryid)) {
         throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, MAPI default folder can not be created/modified", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname), SYNC_FSSTATUS_SYSTEMFOLDER);
     }
     $mfolder = mapi_msgstore_openentry($this->store, $entryid);
     if (!$mfolder) {
         throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to open folder (open entry): 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_PARENTNOTFOUND);
     }
     $props = mapi_getprops($mfolder, array(PR_SOURCE_KEY, PR_PARENT_SOURCE_KEY, PR_DISPLAY_NAME, PR_CONTAINER_CLASS));
     if (!isset($props[PR_SOURCE_KEY]) || !isset($props[PR_PARENT_SOURCE_KEY]) || !isset($props[PR_DISPLAY_NAME]) || !isset($props[PR_CONTAINER_CLASS])) {
         throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, folder data not available: 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_SERVERERROR);
     }
     // get the real parent source key from mapi
     if ($parent == "0") {
         $parentprops = mapi_getprops($this->store, array(PR_IPM_SUBTREE_ENTRYID));
         $parentfentryid = $parentprops[PR_IPM_SUBTREE_ENTRYID];
         $mapifolder = mapi_msgstore_openentry($this->store, $parentfentryid);
         $rootfolderprops = mapi_getprops($mapifolder, array(PR_SOURCE_KEY));
         $parent = bin2hex($rootfolderprops[PR_SOURCE_KEY]);
         ZLog::Write(LOGLEVEL_DEBUG, sprintf("ImportChangesICS->ImportFolderChange(): resolved AS parent '0' to sourcekey '%s'", $parent));
     }
     // a changed parent id means that the folder should be moved
     if (bin2hex($props[PR_PARENT_SOURCE_KEY]) !== $parent) {
         $sourceparentfentryid = mapi_msgstore_entryidfromsourcekey($this->store, $props[PR_PARENT_SOURCE_KEY]);
         if (!$sourceparentfentryid) {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to open parent source folder (no entry id): 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_PARENTNOTFOUND);
         }
         $sourceparentfolder = mapi_msgstore_openentry($this->store, $sourceparentfentryid);
         if (!$sourceparentfolder) {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to open parent source folder (open entry): 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_PARENTNOTFOUND);
         }
         $destparentfentryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($parent));
         if (!$sourceparentfentryid) {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to open destination folder (no entry id): 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_SERVERERROR);
         }
         $destfolder = mapi_msgstore_openentry($this->store, $destparentfentryid);
         if (!$destfolder) {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to open destination folder (open entry): 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_SERVERERROR);
         }
         // mapi_folder_copyfolder() fails if a folder with this name already exists -> MAPI_E_COLLISION
         if (!mapi_folder_copyfolder($sourceparentfolder, $entryid, $destfolder, $displayname, FOLDER_MOVE)) {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to move folder: 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_FOLDEREXISTS);
         }
         $folderProps = mapi_getprops($mfolder, array(PR_SOURCE_KEY));
         return $folderProps[PR_SOURCE_KEY];
     }
     // update the display name
     $props = array(PR_DISPLAY_NAME => $displayname);
     mapi_setprops($mfolder, $props);
     mapi_savechanges($mfolder);
     if (mapi_last_hresult()) {
         throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, mapi_savechanges() failed: 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_SERVERERROR);
     }
     ZLog::Write(LOGLEVEL_DEBUG, "Imported changes for folder: {$id}");
     return $id;
 }
Exemplo n.º 6
0
 /**
  * Function will be used to decode smime messages and convert it to normal messages.
  *
  * @param MAPISession       $session
  * @param MAPIStore         $store
  * @param MAPIAdressBook    $addressBook
  * @param MAPIMessage       $message smime message
  *
  * @access public
  * @return void
  */
 public static function ParseSmime($session, $store, $addressBook, &$mapimessage)
 {
     $props = mapi_getprops($mapimessage, array(PR_MESSAGE_CLASS));
     if (isset($props[PR_MESSAGE_CLASS]) && stripos($props[PR_MESSAGE_CLASS], 'IPM.Note.SMIME.MultipartSigned') !== false) {
         // this is a signed message. decode it.
         $attachTable = mapi_message_getattachmenttable($mapimessage);
         $rows = mapi_table_queryallrows($attachTable, array(PR_ATTACH_MIME_TAG, PR_ATTACH_NUM));
         $attnum = false;
         foreach ($rows as $row) {
             if (isset($row[PR_ATTACH_MIME_TAG]) && $row[PR_ATTACH_MIME_TAG] == 'multipart/signed') {
                 $attnum = $row[PR_ATTACH_NUM];
             }
         }
         if ($attnum !== false) {
             $att = mapi_message_openattach($mapimessage, $attnum);
             $data = mapi_openproperty($att, PR_ATTACH_DATA_BIN);
             mapi_message_deleteattach($mapimessage, $attnum);
             mapi_inetmapi_imtomapi($session, $store, $addressBook, $mapimessage, $data, array("parse_smime_signed" => 1));
             ZLog::Write(LOGLEVEL_DEBUG, "Convert a smime signed message to a normal message.");
         }
         mapi_setprops($mapimessage, array(PR_MESSAGE_CLASS => 'IPM.Note.SMIME.MultipartSigned'));
     }
     // TODO check if we need to do this for encrypted (and signed?) message as well
 }
 /**
  * Function which sets reminder on recurring task after existing occurrence has been deleted or marked complete.
  *@param array $nextOccurrence properties of next occurrence
  */
 function setReminder($nextOccurrence)
 {
     $props = array();
     if ($nextOccurrence) {
         // Check if reminder is reset. Default is 'false'
         $reset_reminder = isset($this->messageprops[$this->proptags['reset_reminder']]) ? $this->messageprops[$this->proptags['reset_reminder']] : false;
         $reminder = $this->messageprops[$this->proptags['reminder']];
         // Either reminder was already set OR reminder was set but was dismissed bty user
         if ($reminder || $reset_reminder) {
             // Reminder can be set at any time either before or after the duedate, so get duration between the reminder time and duedate
             $reminder_time = isset($this->messageprops[$this->proptags['reminder_time']]) ? $this->messageprops[$this->proptags['reminder_time']] : 0;
             $reminder_difference = isset($this->messageprops[$this->proptags['duedate']]) ? $this->messageprops[$this->proptags['duedate']] : 0;
             $reminder_difference = $reminder_difference - $reminder_time;
             // Apply duration to next calculated duedate
             $next_reminder_time = $nextOccurrence[$this->proptags['duedate']] - $reminder_difference;
             $props[$this->proptags['reminder_time']] = $next_reminder_time;
             $props[$this->proptags['flagdueby']] = $next_reminder_time;
             $this->action['reminder'] = $props[$this->proptags['reminder']] = true;
         }
     } else {
         // Didn't get next occurrence, probably this is the last occurrence
         $props[$this->proptags['reminder']] = false;
         $props[$this->proptags['reset_reminder']] = false;
     }
     if (!empty($props)) {
         mapi_setprops($this->message, $props);
     }
 }
Exemplo n.º 8
0
 /**
  * Sets the out of office settings.
  *
  * @param SyncObject $oof
  *
  * @access private
  * @return void
  */
 private function settingsOOFSEt(&$oof)
 {
     $oof->Status = SYNC_SETTINGSSTATUS_SUCCESS;
     $props = array();
     if ($oof->oofstate == SYNC_SETTINGSOOF_GLOBAL || $oof->oofstate == SYNC_SETTINGSOOF_TIMEBASED) {
         $props[PR_EC_OUTOFOFFICE] = true;
         foreach ($oof->oofmessage as $oofmessage) {
             if (isset($oofmessage->appliesToInternal)) {
                 $props[PR_EC_OUTOFOFFICE_MSG] = isset($oofmessage->replymessage) ? u2w($oofmessage->replymessage) : "";
                 $props[PR_EC_OUTOFOFFICE_SUBJECT] = "Out of office";
             }
         }
     } elseif ($oof->oofstate == SYNC_SETTINGSOOF_DISABLED) {
         $props[PR_EC_OUTOFOFFICE] = false;
     }
     if (!empty($props)) {
         @mapi_setprops($this->defaultstore, $props);
         $result = mapi_last_hresult();
         if ($result != NOERROR) {
             ZLog::Write(LOGLEVEL_ERROR, sprintf("Setting oof information failed (%X)", $result));
             return false;
         }
     }
     return true;
 }
Exemplo n.º 9
0
 function SendMail($rfc822, $forward = false, $reply = false, $parent = false)
 {
     $message = Mail_mimeDecode::decode(array('decode_headers' => true, 'decode_bodies' => true, 'include_bodies' => true, 'input' => $rfc822, 'crlf' => "\r\n", 'charset' => 'utf-8'));
     // Open the outbox and create the message there
     $storeprops = mapi_getprops($this->_defaultstore, array(PR_IPM_OUTBOX_ENTRYID, PR_IPM_SENTMAIL_ENTRYID));
     if (!isset($storeprops[PR_IPM_OUTBOX_ENTRYID])) {
         debugLog("Outbox not found to create message");
         return false;
     }
     $outbox = mapi_msgstore_openentry($this->_defaultstore, $storeprops[PR_IPM_OUTBOX_ENTRYID]);
     if (!$outbox) {
         debugLog("Unable to open outbox");
         return false;
     }
     $mapimessage = mapi_folder_createmessage($outbox);
     mapi_setprops($mapimessage, array(PR_SUBJECT => u2w($message->headers["subject"]), PR_SENTMAIL_ENTRYID => $storeprops[PR_IPM_SENTMAIL_ENTRYID], PR_MESSAGE_CLASS => "IPM.Note", PR_MESSAGE_DELIVERY_TIME => time()));
     if (isset($message->headers["x-priority"])) {
         switch ($message->headers["x-priority"]) {
             case 1:
             case 2:
                 $priority = PRIO_URGENT;
                 $importance = IMPORTANCE_HIGH;
                 break;
             case 4:
             case 5:
                 $priority = PRIO_NONURGENT;
                 $importance = IMPORTANCE_LOW;
                 break;
             case 3:
             default:
                 $priority = PRIO_NORMAL;
                 $importance = IMPORTANCE_NORMAL;
                 break;
         }
         mapi_setprops($mapimessage, array(PR_IMPORTANCE => $importance, PR_PRIORITY => $priority));
     }
     $addresses = array();
     $toaddr = $ccaddr = $bccaddr = array();
     if (isset($message->headers["to"])) {
         $toaddr = Mail_RFC822::parseAddressList($message->headers["to"]);
     }
     if (isset($message->headers["cc"])) {
         $ccaddr = Mail_RFC822::parseAddressList($message->headers["cc"]);
     }
     if (isset($message->headers["bcc"])) {
         $bccaddr = Mail_RFC822::parseAddressList($message->headers["bcc"]);
     }
     // Add recipients
     $recips = array();
     if (isset($toaddr)) {
         foreach (array(MAPI_TO => $toaddr, MAPI_CC => $ccaddr, MAPI_BCC => $bccaddr) as $type => $addrlist) {
             foreach ($addrlist as $addr) {
                 $mapirecip[PR_ADDRTYPE] = "SMTP";
                 $mapirecip[PR_EMAIL_ADDRESS] = $addr->mailbox . "@" . $addr->host;
                 if (isset($addr->personal) && strlen($addr->personal) > 0) {
                     $mapirecip[PR_DISPLAY_NAME] = u2w($addr->personal);
                 } else {
                     $mapirecip[PR_DISPLAY_NAME] = $mapirecip[PR_EMAIL_ADDRESS];
                 }
                 $mapirecip[PR_RECIPIENT_TYPE] = $type;
                 $mapirecip[PR_ENTRYID] = mapi_createoneoff($mapirecip[PR_DISPLAY_NAME], $mapirecip[PR_ADDRTYPE], $mapirecip[PR_EMAIL_ADDRESS]);
                 array_push($recips, $mapirecip);
             }
         }
     }
     mapi_message_modifyrecipients($mapimessage, 0, $recips);
     // Loop through subparts. We currently only support single-level
     // multiparts. The PDA currently only does this because you are adding
     // an attachment and the type will be multipart/mixed.
     if ($message->ctype_primary == "multipart" && $message->ctype_secondary == "mixed") {
         foreach ($message->parts as $part) {
             if ($part->ctype_primary == "text") {
                 $body = u2w($part->body);
             } else {
                 // attachment
                 $attach = mapi_message_createattach($mapimessage);
                 // Filename is present in both Content-Type: name=.. and in Content-Disposition: filename=
                 if (isset($part->ctype_parameters["name"])) {
                     $filename = $part->ctype_parameters["name"];
                 } else {
                     if (isset($part->d_parameters["name"])) {
                         $filename = $part->d_parameters["filename"];
                     } else {
                         $filename = "untitled";
                     }
                 }
                 // Set filename and attachment type
                 mapi_setprops($attach, array(PR_ATTACH_LONG_FILENAME => u2w($filename), PR_ATTACH_METHOD => ATTACH_BY_VALUE));
                 // Set attachment data
                 mapi_setprops($attach, array(PR_ATTACH_DATA_BIN => $part->body));
                 // Set MIME type
                 mapi_setprops($attach, array(PR_ATTACH_MIME_TAG => $part->ctype_primary . "/" . $part->ctype_secondary));
                 mapi_savechanges($attach);
             }
         }
     } else {
         $body = u2w($message->body);
     }
     if ($forward) {
         $orig = $forward;
     }
     if ($reply) {
         $orig = $reply;
     }
     if (isset($orig) && $orig) {
         // Append the original text body for reply/forward
         $entryid = mapi_msgstore_entryidfromsourcekey($this->_defaultstore, hex2bin($parent), hex2bin($orig));
         $fwmessage = mapi_msgstore_openentry($this->_defaultstore, $entryid);
         if ($fwmessage) {
             $messageprops = mapi_getprops($fwmessage, array(PR_BODY));
             if (isset($messageprops[PR_BODY])) {
                 if ($forward) {
                     // During a forward, we have to add the forward header ourselves. This is because
                     // normally the forwarded message is added as an attachment. However, we don't want this
                     // because it would be rather complicated to copy over the entire original message due
                     // to the lack of IMessage::CopyTo ..
                     $fwmessageprops = mapi_getprops($fwmessage, array(PR_SENT_REPRESENTING_NAME, PR_DISPLAY_TO, PR_DISPLAY_CC, PR_SUBJECT, PR_CLIENT_SUBMIT_TIME));
                     $body .= "\r\n\r\n";
                     $body .= "-----Original Message-----\r\n";
                     if (isset($fwmessageprops[PR_SENT_REPRESENTING_NAME])) {
                         $body .= "From: " . $fwmessageprops[PR_SENT_REPRESENTING_NAME] . "\r\n";
                     }
                     if (isset($fwmessageprops[PR_DISPLAY_TO]) && strlen($fwmessageprops[PR_DISPLAY_TO]) > 0) {
                         $body .= "To: " . $fwmessageprops[PR_DISPLAY_TO] . "\r\n";
                     }
                     if (isset($fwmessageprops[PR_DISPLAY_CC]) && strlen($fwmessageprops[PR_DISPLAY_CC]) > 0) {
                         $body .= "Cc: " . $fwmessageprops[PR_DISPLAY_CC] . "\r\n";
                     }
                     if (isset($fwmessageprops[PR_CLIENT_SUBMIT_TIME])) {
                         $body .= "Sent: " . strftime("%x %X", $fwmessageprops[PR_CLIENT_SUBMIT_TIME]) . "\r\n";
                     }
                     if (isset($fwmessageprops[PR_SUBJECT])) {
                         $body .= "Subject: " . $fwmessageprops[PR_SUBJECT] . "\r\n";
                     }
                     $body .= "\r\n";
                 }
                 $body .= $messageprops[PR_BODY];
             }
         } else {
             debugLog("Unable to open item with id {$orig} for forward/reply");
         }
     }
     if ($forward) {
         // Add attachments from the original message in a forward
         $entryid = mapi_msgstore_entryidfromsourcekey($this->_defaultstore, hex2bin($parent), hex2bin($orig));
         $fwmessage = mapi_msgstore_openentry($this->_defaultstore, $entryid);
         $attachtable = mapi_message_getattachmenttable($fwmessage);
         $rows = mapi_table_queryallrows($attachtable, array(PR_ATTACH_NUM));
         foreach ($rows as $row) {
             if (isset($row[PR_ATTACH_NUM])) {
                 $attach = mapi_message_openattach($fwmessage, $row[PR_ATTACH_NUM]);
                 $newattach = mapi_message_createattach($mapimessage);
                 // Copy all attachments from old to new attachment
                 $attachprops = mapi_getprops($attach);
                 mapi_setprops($newattach, $attachprops);
                 if (isset($attachprops[mapi_prop_tag(PT_ERROR, mapi_prop_id(PR_ATTACH_DATA_BIN))])) {
                     // Data is in a stream
                     $srcstream = mapi_openpropertytostream($attach, PR_ATTACH_DATA_BIN);
                     $dststream = mapi_openpropertytostream($newattach, PR_ATTACH_DATA_BIN, MAPI_MODIFY | MAPI_CREATE);
                     while (1) {
                         $data = mapi_stream_read($srcstream, 4096);
                         if (strlen($data) == 0) {
                             break;
                         }
                         mapi_stream_write($dststream, $data);
                     }
                     mapi_stream_commit($dststream);
                 }
                 mapi_savechanges($newattach);
             }
         }
     }
     mapi_setprops($mapimessage, array(PR_BODY => $body));
     mapi_savechanges($mapimessage);
     mapi_message_submitmessage($mapimessage);
     return true;
 }
Exemplo n.º 10
0
 /**
  * Assign a contact picture to a contact
  * @param entryId contact entry id
  * @param contactPicture must be a valid jpeg file. If contactPicture is NULL will remove contact picture from contact if exists
  */
 public function setContactPicture(&$contact, $contactPicture)
 {
     $this->logger->trace("setContactPicture");
     // Find if contact picture is already set
     $contactAttachment = -1;
     $hasattachProp = mapi_getprops($contact, array(PR_HASATTACH));
     if ($hasattachProp) {
         $attachmentTable = mapi_message_getattachmenttable($contact);
         $attachments = mapi_table_queryallrows($attachmentTable, array(PR_ATTACH_NUM, PR_ATTACH_SIZE, PR_ATTACH_LONG_FILENAME, PR_ATTACH_FILENAME, PR_ATTACHMENT_HIDDEN, PR_DISPLAY_NAME, PR_ATTACH_METHOD, PR_ATTACH_CONTENT_ID, PR_ATTACH_MIME_TAG, PR_ATTACHMENT_CONTACTPHOTO, PR_EC_WA_ATTACHMENT_HIDDEN_OVERRIDE));
         foreach ($attachments as $attachmentRow) {
             if (isset($attachmentRow[PR_ATTACHMENT_CONTACTPHOTO]) && $attachmentRow[PR_ATTACHMENT_CONTACTPHOTO]) {
                 $contactAttachment = $attachmentRow[PR_ATTACH_NUM];
                 break;
             }
         }
     }
     // Remove existing attachment if necessary
     if ($contactAttachment != -1) {
         $this->logger->trace("removing existing contact picture");
         $attach = mapi_message_deleteattach($contact, $contactAttachment);
     }
     if ($contactPicture !== NULL) {
         $this->logger->debug("Saving contact picture as attachment");
         // Create attachment
         $attach = mapi_message_createattach($contact);
         // Update contact attachment properties
         $properties = array(PR_ATTACH_SIZE => strlen($contactPicture), PR_ATTACH_LONG_FILENAME => 'ContactPicture.jpg', PR_ATTACHMENT_HIDDEN => false, PR_DISPLAY_NAME => 'ContactPicture.jpg', PR_ATTACH_METHOD => ATTACH_BY_VALUE, PR_ATTACH_MIME_TAG => 'image/jpeg', PR_ATTACHMENT_CONTACTPHOTO => true, PR_ATTACH_DATA_BIN => $contactPicture, PR_ATTACHMENT_FLAGS => 1, PR_ATTACH_EXTENSION_A => '.jpg', PR_ATTACH_NUM => 1);
         mapi_setprops($attach, $properties);
         mapi_savechanges($attach);
     }
     // Test
     if (mapi_last_hresult() > 0) {
         $this->logger->warn("Error saving contact picture: " . get_mapi_error_name());
     } else {
         $this->logger->trace("contact picture done");
     }
 }
Exemplo n.º 11
0
    if (isset($props[$properties["business_address"]])) {
        $props[$properties["mailing_address"]] = 2;
        setMailingAdress($props[$properties["business_address_street"]], $props[$properties["business_address_postal_code"]], $props[$properties["business_address_city"]], $props[$properties["business_address_state"]], $props[$properties["business_address_country"]], $props[$properties["business_address"]], $props, $properties);
    } elseif (isset($props[$properties["home_address"]])) {
        $props[$properties["mailing_address"]] = 1;
        setMailingAdress($props[$properties["home_address_street"]], $props[$properties["home_address_postal_code"]], $props[$properties["home_address_city"]], $props[$properties["home_address_state"]], $props[$properties["home_address_country"]], $props[$properties["home_address"]], $props, $properties);
    } elseif (isset($props[$properties["other_address"]])) {
        $props[$properties["mailing_address"]] = 3;
        setMailingAdress($props[$properties["other_address_street"]], $props[$properties["other_address_postal_code"]], $props[$properties["other_address_city"]], $props[$properties["other_address_state"]], $props[$properties["other_address_country"]], $props[$properties["other_address"]], $props, $properties);
    }
    // if the display name is set, then it is a valid contact: save it to the folder
    if (isset($props[$properties["display_name"]])) {
        $props[$properties["message_class"]] = "IPM.Contact";
        $props[$properties["icon_index"]] = "512";
        $message = mapi_folder_createmessage($folder);
        mapi_setprops($message, $props);
        mapi_savechanges($message);
        printf("New contact added \"%s\".\n", $props[$properties["display_name"]]);
    }
    $i++;
}
// EOF
function getPropIdsFromStrings($store, $mapping)
{
    $props = array();
    $ids = array("name" => array(), "id" => array(), "guid" => array(), "type" => array());
    // this array stores all the information needed to retrieve a named property
    $num = 0;
    // caching
    $guids = array();
    foreach ($mapping as $name => $val) {
function clearSuggestionList($session, $store, $userName)
{
    // create entryid of user's store
    $userStoreEntryId = mapi_msgstore_createentryid($store, $userName);
    if (!$userStoreEntryId) {
        print "Error in creating entryid for user's store - " . $userName . "\n";
        return false;
    }
    // open user's store
    $userStore = mapi_openmsgstore($session, $userStoreEntryId);
    if (!$userStore) {
        print "Error in opening user's store - " . $userName . "\n";
        return false;
    }
    // we are not checking here that property exists or not because it could happen that getprops will return
    // MAPI_E_NOT_ENOUGH_MEMORY for very large property, if property does not exists then it will be created
    // remove property data, overwirte existing data with a blank string (PT_STRING8)
    mapi_setprops($userStore, array(PR_EC_RECIPIENT_HISTORY => ""));
    $result = mapi_last_hresult();
    if ($result == NOERROR) {
        // Save changes
        mapi_savechanges($userStore);
        return mapi_last_hresult() == NOERROR ? true : false;
    }
    return false;
}
Exemplo n.º 13
0
function import($store, $csv_file, $delete_old_items, $categories)
{
    $folder = getContactsFolder($store);
    // open the csv file and start reading
    $fh = fopen($csv_file, "r");
    if (!$fh) {
        trigger_error("Can't read CSV file \"" . $csv_file . "\".", E_USER_ERROR);
    }
    // Delete all existing items if requested.
    if ($delete_old_items) {
        mapi_folder_emptyfolder($folder, DEL_ASSOCIATED);
        printf("Old items deleted.\n");
    }
    $properties = getProperties();
    $properties = replaceStringPropertyTags($store, $properties);
    //composed properties which require more work
    $special_properties = getSpecialPropertyNames();
    $csv_mapping = getMapping();
    $i = 1;
    while (!feof($fh)) {
        $line = fgetcsv($fh, CSV_MAX_LENGTH, CSV_DELIMITER, CSV_ENCLOSURE);
        // print_r($line);
        if (!$line) {
            continue;
        }
        if ($i == 1 && defined('FIELD_NAMES') && FIELD_NAMES) {
            $i++;
            continue;
        }
        $propValues = array();
        //set "simple" properties
        foreach ($csv_mapping as $property => $cnt) {
            if (!in_array($property, $special_properties)) {
                setProperty($property, $line[$csv_mapping[$property]], $propValues, $properties);
            }
        }
        // set display name
        if (isset($csv_mapping["display_name"]) && isset($line[$csv_mapping["display_name"]])) {
            $name = to_windows1252($line[$csv_mapping["display_name"]]);
            $propValues[$properties["display_name"]] = $propValues[$properties["subject"]] = $propValues[$properties["fileas"]] = $name;
            $propValues[$properties["fileas_selection"]] = -1;
        } else {
            $propValues[$properties["display_name"]] = $propValues[$properties["subject"]] = $propValues[$properties["fileas"]] = "";
            if (isset($propValues[$properties["given_name"]])) {
                $propValues[$properties["display_name"]] .= $propValues[$properties["given_name"]];
                $propValues[$properties["subject"]] .= $propValues[$properties["given_name"]];
            }
            if (isset($propValues[$properties["surname"]])) {
                if (strlen($propValues[$properties["display_name"]]) > 0) {
                    $propValues[$properties["display_name"]] .= " " . $propValues[$properties["surname"]];
                    $propValues[$properties["subject"]] .= " " . $propValues[$properties["surname"]];
                } else {
                    $propValues[$properties["display_name"]] .= $propValues[$properties["surname"]];
                    $propValues[$properties["subject"]] .= $propValues[$properties["surname"]];
                }
            }
            if (isset($propValues[$properties["surname"]])) {
                $propValues[$properties["fileas"]] .= $propValues[$properties["surname"]];
            }
            if (isset($propValues[$properties["given_name"]])) {
                if (strlen($propValues[$properties["fileas"]]) > 0) {
                    $propValues[$properties["fileas"]] .= ", " . $propValues[$properties["given_name"]];
                } else {
                    $propValues[$properties["fileas"]] .= $propValues[$properties["given_name"]];
                }
            }
        }
        $nremails = array();
        $abprovidertype = 0;
        if (isset($csv_mapping["email_address_1"]) && isset($line[$csv_mapping["email_address_1"]])) {
            setEmailAddress($line[$csv_mapping["email_address_1"]], $propValues[$properties["display_name"]], 1, $propValues, $properties, $nremails, $abprovidertype);
        }
        if (isset($csv_mapping["email_address_2"]) && isset($line[$csv_mapping["email_address_2"]])) {
            setEmailAddress($line[$csv_mapping["email_address_2"]], $propValues[$properties["display_name"]], 2, $propValues, $properties, $nremails, $abprovidertype);
        }
        if (isset($csv_mapping["email_address_3"]) && isset($line[$csv_mapping["email_address_3"]])) {
            setEmailAddress($line[$csv_mapping["email_address_3"]], $propValues[$properties["display_name"]], 3, $propValues, $properties, $nremails, $abprovidertype);
        }
        if (!empty($nremails)) {
            $propValues[$properties["address_book_mv"]] = $nremails;
        }
        $propValues[$properties["address_book_long"]] = $abprovidertype;
        //set addresses
        if (isset($csv_mapping["home_address_street2"])) {
            mergeStreet("home", $line[$csv_mapping["home_address_street2"]], $propValues, $properties);
        }
        if (isset($csv_mapping["home_address_street3"])) {
            mergeStreet("home", $line[$csv_mapping["home_address_street3"]], $propValues, $properties);
        }
        if (!isset($propValues[$properties["home_address"]]) && isset($propValues[$properties["home_address_street"]]) && isset($propValues[$properties["home_address_postal_code"]]) && isset($propValues[$properties["home_address_city"]]) && isset($propValues[$properties["home_address_state"]]) && isset($propValues[$properties["home_address_country"]])) {
            buildAddressString("home", $propValues[$properties["home_address_street"]], $propValues[$properties["home_address_postal_code"]], $propValues[$properties["home_address_city"]], $propValues[$properties["home_address_state"]], $propValues[$properties["home_address_country"]], $propValues, $properties);
        }
        if (isset($csv_mapping["business_address_street2"])) {
            mergeStreet("business", $line[$csv_mapping["business_address_street2"]], $propValues, $properties);
        }
        if (isset($csv_mapping["business_address_street3"])) {
            mergeStreet("business", $line[$csv_mapping["business_address_street3"]], $propValues, $properties);
        }
        if (!isset($propValues[$properties["business_address"]]) && isset($propValues[$properties["business_address_street"]]) && isset($propValues[$properties["business_address_postal_code"]]) && isset($propValues[$properties["business_address_city"]]) && isset($propValues[$properties["business_address_state"]]) && isset($propValues[$properties["business_address_country"]])) {
            buildAddressString("business", $propValues[$properties["business_address_street"]], $propValues[$properties["business_address_postal_code"]], $propValues[$properties["business_address_city"]], $propValues[$properties["business_address_state"]], $propValues[$properties["business_address_country"]], $propValues, $properties);
        }
        if (isset($csv_mapping["other_address_street2"])) {
            mergeStreet("other", $line[$csv_mapping["other_address_street2"]], $propValues, $properties);
        }
        if (isset($csv_mapping["other_address_street3"])) {
            mergeStreet("other", $line[$csv_mapping["other_address_street3"]], $propValues, $properties);
        }
        if (!isset($propValues[$properties["other_address"]]) && isset($propValues[$properties["other_address_street"]]) && isset($propValues[$properties["other_address_postal_code"]]) && isset($propValues[$properties["other_address_city"]]) && isset($propValues[$properties["other_address_state"]]) && isset($propValues[$properties["other_address_country"]])) {
            buildAddressString("other", $propValues[$properties["other_address_street"]], $propValues[$properties["other_address_postal_code"]], $propValues[$properties["other_address_city"]], $propValues[$properties["other_address_state"]], $propValues[$properties["other_address_country"]], $propValues, $properties);
        }
        if (isset($propValues[$properties["home_address"]])) {
            $propValues[$properties["mailing_address"]] = 1;
            setMailingAdress($propValues[$properties["home_address_street"]], $propValues[$properties["home_address_postal_code"]], $propValues[$properties["home_address_city"]], $propValues[$properties["home_address_state"]], $propValues[$properties["home_address_country"]], $propValues[$properties["home_address"]], $propValues, $properties);
        } elseif (isset($propValues[$properties["business_address"]])) {
            $propValues[$properties["mailing_address"]] = 2;
            setMailingAdress($propValues[$properties["business_address_street"]], $propValues[$properties["business_address_postal_code"]], $propValues[$properties["business_address_city"]], $propValues[$properties["business_address_state"]], $propValues[$properties["business_address_country"]], $propValues[$properties["business_address"]], $propValues, $properties);
        } elseif (isset($propValues[$properties["other_address"]])) {
            $propValues[$properties["mailing_address"]] = 3;
            setMailingAdress($propValues[$properties["other_address_street"]], $propValues[$properties["other_address_postal_code"]], $propValues[$properties["other_address_city"]], $propValues[$properties["other_address_state"]], $propValues[$properties["other_address_country"]], $propValues[$properties["other_address"]], $propValues, $properties);
        }
        if (isset($categories) && !empty($categories)) {
            setProperty("categories", $categories, $propValues, $properties);
        }
        // if the display name is set, then it is a valid contact: save it to the folder
        if (isset($propValues[$properties["display_name"]])) {
            $propValues[$properties["message_class"]] = "IPM.Contact";
            $propValues[$properties["icon_index"]] = "512";
            $message = mapi_folder_createmessage($folder);
            mapi_setprops($message, $propValues);
            mapi_savechanges($message);
            printf("New contact added: \"%s\".\n", $propValues[$properties["display_name"]]);
        }
        $i++;
    }
}
 /**
  * Updates a card
  * 
  * @param mixed $addressBookId 
  * @param string $cardUri 
  * @param string $cardData 
  * @return bool 
  */
 public function updateCard($addressBookId, $cardUri, $cardData)
 {
     $this->logger->info("updateCard - {$cardUri}");
     if (READ_ONLY) {
         $this->logger->warn("Cannot update card: read-only");
         return false;
     }
     // Update object properties
     $entryId = $this->getContactEntryId($addressBookId, $cardUri);
     if ($entryId === 0) {
         $this->logger->warn("Cannot find contact");
         return false;
     }
     $mapiProperties = $this->bridge->vcardToMapiProperties($cardData);
     $contact = mapi_msgstore_openentry($this->bridge->getStore($addressBookId), $entryId);
     if (SAVE_RAW_VCARD) {
         // Save RAW vCard
         $this->logger->debug("Saving raw vcard");
         $mapiProperties[PR_CARDDAV_RAW_DATA] = $cardData;
         $mapiProperties[PR_CARDDAV_RAW_DATA_GENERATION_TIME] = time();
     } else {
         $this->logger->trace("Saving raw vcard skiped by config");
     }
     // Handle contact picture
     if (array_key_exists('ContactPicture', $mapiProperties)) {
         $this->logger->debug("Updating contact picture");
         $contactPicture = $mapiProperties['ContactPicture'];
         unset($mapiProperties['ContactPicture']);
         $this->bridge->setContactPicture($contact, $contactPicture);
     }
     // Remove NULL properties
     if (CLEAR_MISSING_PROPERTIES) {
         $this->logger->debug("Clearing missing properties");
         $nullProperties = array();
         foreach ($mapiProperties as $p => $v) {
             if ($v == NULL) {
                 $nullProperties[] = $p;
                 unset($mapiProperties[$p]);
             }
         }
         $dump = print_r($nullProperties, true);
         $this->logger->trace("Removing properties\n{$dump}");
         mapi_deleteprops($contact, $nullProperties);
     }
     // Set properties
     $mapiProperties[PR_LAST_MODIFICATION_TIME] = time();
     mapi_setprops($contact, $mapiProperties);
     // Save changes to backend
     mapi_savechanges($contact);
     return mapi_last_hresult() == 0;
 }
Exemplo n.º 15
0
function zpa_remove_device($adminStore, $session, $user, $deviceid)
{
    $userEntryId = @mapi_msgstore_createentryid($adminStore, $user);
    $userStore = @mapi_openmsgstore($session, $userEntryId);
    $hresult = mapi_last_hresult();
    if ($hresult != NOERROR) {
        echo "Could not open store for {$user}. The script will exit.\n";
        exit(1);
    }
    $devicesprops = mapi_getprops($userStore, array(0x6880101e, 0x6881101e, 0x6882101e, 0x6883101e, 0x68841003, 0x6885101e, 0x6886101e, 0x6887101e, 0x68881040, 0x68891040));
    if (isset($devicesprops[0x6881101e]) && is_array($devicesprops[0x6881101e])) {
        $ak = array_search($deviceid, $devicesprops[0x6881101e]);
        if ($ak !== false) {
            if (count($devicesprops[0x6880101e]) == 1) {
                mapi_deleteprops($userStore, array(0x6880101e, 0x6881101e, 0x6882101e, 0x6883101e, 0x68841003, 0x6885101e, 0x6886101e, 0x6887101e, 0x68881040, 0x68891040));
            } else {
                unset($devicesprops[0x6880101e][$ak], $devicesprops[0x6881101e][$ak], $devicesprops[0x6882101e][$ak], $devicesprops[0x6883101e][$ak], $devicesprops[0x68841003][$ak], $devicesprops[0x6885101e][$ak], $devicesprops[0x6886101e][$ak], $devicesprops[0x6887101e][$ak], $devicesprops[0x68881040][$ak], $devicesprops[0x68891040][$ak]);
                mapi_setprops($userStore, array(0x6880101e => isset($devicesprops[0x6880101e]) ? $devicesprops[0x6880101e] : array(), 0x6881101e => isset($devicesprops[0x6881101e]) ? $devicesprops[0x6881101e] : array(), 0x6882101e => isset($devicesprops[0x6882101e]) ? $devicesprops[0x6882101e] : array(), 0x6883101e => isset($devicesprops[0x6883101e]) ? $devicesprops[0x6883101e] : array(), 0x68841003 => isset($devicesprops[0x68841003]) ? $devicesprops[0x68841003] : array(), 0x6885101e => isset($devicesprops[0x6885101e]) ? $devicesprops[0x6885101e] : array(), 0x6886101e => isset($devicesprops[0x6886101e]) ? $devicesprops[0x6886101e] : array(), 0x6887101e => isset($devicesprops[0x6887101e]) ? $devicesprops[0x6887101e] : array(), 0x68881040 => isset($devicesprops[0x68881040]) ? $devicesprops[0x68881040] : array(), 0x68891040 => isset($devicesprops[0x68891040]) ? $devicesprops[0x68891040] : array()));
            }
            $hresult = mapi_last_hresult();
            if ($hresult != NOERROR) {
                echo "Could not remove device from list for {$user}. Errorcode 0x" . sprintf("%x", $hresult) . ". The script will exit.\n";
                exit(1);
            } else {
                echo "Removed device from list.\n";
            }
        } else {
            echo "No device found with the given id.\n";
            exit(1);
        }
    } else {
        echo "No devices found for the user {$user}.\n";
        exit(1);
    }
}
Exemplo n.º 16
0
 /**
  * Saves the recurrence data to the recurrence property
  * @param array $properties the recurrence data.
  * @return string binary string
  */
 function saveRecurrence()
 {
     // Only save if a message was passed
     if (!isset($this->message)) {
         return;
     }
     // Abort if no recurrence was set
     if (!isset($this->recur["type"]) && !isset($this->recur["subtype"])) {
         return;
     }
     if (!isset($this->recur["start"]) && !isset($this->recur["end"])) {
         return;
     }
     if (!isset($this->recur["startocc"]) && !isset($this->recur["endocc"])) {
         return;
     }
     $rdata = pack("CCCCCCV", 0x4, 0x30, 0x4, 0x30, (int) $this->recur["type"], 0x20, (int) $this->recur["subtype"]);
     $weekstart = 1;
     //monday
     $forwardcount = 0;
     $restocc = 0;
     $dayofweek = (int) gmdate("w", (int) $this->recur["start"]);
     //0 (for Sunday) through 6 (for Saturday)
     $term = (int) $this->recur["type"];
     switch ($term) {
         case 0xa:
             // Daily
             if (!isset($this->recur["everyn"])) {
                 return;
             }
             if ($this->recur["subtype"] == 1) {
                 // Daily every workday
                 $rdata .= pack("VVVV", 6 * 24 * 60, 1, 0, 0x3e);
             } else {
                 // Daily every N days (everyN in minutes)
                 $everyn = (int) $this->recur["everyn"] / 1440;
                 // Calc first occ
                 $firstocc = $this->unixDataToRecurData($this->recur["start"]) % (int) $this->recur["everyn"];
                 $rdata .= pack("VVV", $firstocc, (int) $this->recur["everyn"], $this->recur["regen"] ? 1 : 0);
             }
             break;
         case 0xb:
             // Weekly
             if (!isset($this->recur["everyn"])) {
                 return;
             }
             if (!$this->recur["regen"] && !isset($this->recur["weekdays"])) {
                 return;
             }
             // No need to calculate startdate if sliding flag was set.
             if (!$this->recur['regen']) {
                 // Calculate start date of recurrence
                 // Find the first day that matches one of the weekdays selected
                 $daycount = 0;
                 $dayskip = -1;
                 for ($j = 0; $j < 7; $j++) {
                     if ((int) $this->recur["weekdays"] & 1 << ($dayofweek + $j) % 7) {
                         if ($dayskip == -1) {
                             $dayskip = $j;
                         }
                         $daycount++;
                     }
                 }
                 // $dayskip is the number of days to skip from the startdate until the first occurrence
                 // $daycount is the number of days per week that an occurrence occurs
                 $weekskip = 0;
                 if ($dayofweek < $weekstart && $dayskip > 0 || $dayofweek + $dayskip > 6) {
                     $weekskip = 1;
                 }
                 // Check if the recurrence ends after a number of occurences, in that case we must calculate the
                 // remaining occurences based on the start of the recurrence.
                 if ((int) $this->recur["term"] == 0x22) {
                     // $weekskip is the amount of weeks to skip from the startdate before the first occurence
                     // $forwardcount is the maximum number of week occurrences we can go ahead after the first occurrence that
                     // is still inside the recurrence. We subtract one to make sure that the last week is never forwarded over
                     // (eg when numoccur = 2, and daycount = 1)
                     $forwardcount = floor((int) ($this->recur["numoccur"] - 1) / $daycount);
                     // $restocc is the number of occurrences left after $forwardcount whole weeks of occurrences, minus one
                     // for the occurrence on the first day
                     $restocc = (int) $this->recur["numoccur"] - $forwardcount * $daycount - 1;
                     // $forwardcount is now the number of weeks we can go forward and still be inside the recurrence
                     $forwardcount *= (int) $this->recur["everyn"];
                 }
                 // The real start is start + dayskip + weekskip-1 (since dayskip will already bring us into the next week)
                 $this->recur["start"] = (int) $this->recur["start"] + $dayskip * 24 * 60 * 60 + $weekskip * ((int) $this->recur["everyn"] - 1) * 7 * 24 * 60 * 60;
             }
             // Calc first occ
             $firstocc = $this->unixDataToRecurData($this->recur["start"]) % ((int) $this->recur["everyn"] * 7 * 24 * 60);
             $firstocc -= ((int) gmdate("w", (int) $this->recur["start"]) - 1) * 24 * 60;
             if ($this->recur["regen"]) {
                 $rdata .= pack("VVV", $firstocc, (int) $this->recur["everyn"], 1);
             } else {
                 $rdata .= pack("VVVV", $firstocc, (int) $this->recur["everyn"], 0, (int) $this->recur["weekdays"]);
             }
             break;
         case 0xc:
             // Monthly
         // Monthly
         case 0xd:
             // Yearly
             if (!isset($this->recur["everyn"])) {
                 return;
             }
             if ($term == 0xd && !isset($this->recur["month"])) {
                 return;
             }
             if ($term == 0xc) {
                 $everyn = (int) $this->recur["everyn"];
             } else {
                 $everyn = $this->recur["regen"] ? (int) $this->recur["everyn"] * 12 : 12;
             }
             // Get montday/month/year of original start
             $curmonthday = gmdate("j", (int) $this->recur["start"]);
             $curyear = gmdate("Y", (int) $this->recur["start"]);
             $curmonth = gmdate("n", (int) $this->recur["start"]);
             // Check if the recurrence ends after a number of occurences, in that case we must calculate the
             // remaining occurences based on the start of the recurrence.
             if ((int) $this->recur["term"] == 0x22) {
                 // $forwardcount is the number of occurrences we can skip and still be inside the recurrence range (minus
                 // one to make sure there are always at least one occurrence left)
                 $forwardcount = ((int) $this->recur["numoccur"] - 1) * $everyn;
             }
             // Get month for yearly on D'th day of month M
             if ($term == 0xd) {
                 $selmonth = floor((int) $this->recur["month"] / (24 * 60 * 29)) + 1;
                 // 1=jan, 2=feb, eg
             }
             switch ((int) $this->recur["subtype"]) {
                 // on D day of every M month
                 case 2:
                     if (!isset($this->recur["monthday"])) {
                         return;
                     }
                     // Recalc startdate
                     // Set on the right begin day
                     // Go the beginning of the month
                     $this->recur["start"] -= ($curmonthday - 1) * 24 * 60 * 60;
                     // Go the the correct month day
                     $this->recur["start"] += ((int) $this->recur["monthday"] - 1) * 24 * 60 * 60;
                     // If the previous calculation gave us a start date *before* the original start date, then we need to skip to the next occurrence
                     if ($term == 0xc && (int) $this->recur["monthday"] < $curmonthday || $term == 0xd && ($selmonth < $curmonth || $selmonth == $curmonth && (int) $this->recur["monthday"] < $curmonthday)) {
                         if ($term == 0xd) {
                             $count = $everyn - ($curmonth - $selmonth);
                         } else {
                             $count = $everyn;
                         }
                         // Monthly, go to next occurrence in 'everyn' months
                         // Forward by $count months. This is done by getting the number of days in that month and forwarding that many days
                         for ($i = 0; $i < $count; $i++) {
                             $this->recur["start"] += $this->getMonthInSeconds($curyear, $curmonth);
                             if ($curmonth == 12) {
                                 $curyear++;
                                 $curmonth = 0;
                             }
                             $curmonth++;
                         }
                     }
                     // "start" is now pointing to the first occurrence, except that it will overshoot if the
                     // month in which it occurs has less days than specified as the day of the month. So 31st
                     // of each month will overshoot in february (29 days). We compensate for that by checking
                     // if the day of the month we got is wrong, and then back up to the last day of the previous
                     // month.
                     if ((int) $this->recur["monthday"] >= 28 && (int) $this->recur["monthday"] <= 31 && gmdate("j", (int) $this->recur["start"]) < (int) $this->recur["monthday"]) {
                         $this->recur["start"] -= gmdate("j", (int) $this->recur["start"]) * 24 * 60 * 60;
                     }
                     // "start" is now the first occurrence
                     if ($term == 0xc) {
                         // Calc first occ
                         $monthIndex = (12 % $everyn * (((int) gmdate("Y", $this->recur["start"]) - 1601) % $everyn) % $everyn + ((int) gmdate("n", $this->recur["start"]) - 1)) % $everyn;
                         $firstocc = 0;
                         for ($i = 0; $i < $monthIndex; $i++) {
                             $firstocc += $this->getMonthInSeconds(1601 + floor($i / 12), $i % 12 + 1) / 60;
                         }
                         $rdata .= pack("VVVV", $firstocc, $everyn, $this->recur["regen"], (int) $this->recur["monthday"]);
                     } else {
                         // Calc first occ
                         $firstocc = 0;
                         $monthIndex = (int) gmdate("n", $this->recur["start"]);
                         for ($i = 1; $i < $monthIndex; $i++) {
                             $firstocc += $this->getMonthInSeconds(1601 + floor($i / 12), $i) / 60;
                         }
                         $rdata .= pack("VVVV", $firstocc, $everyn, $this->recur["regen"], (int) $this->recur["monthday"]);
                     }
                     break;
                 case 3:
                     // monthly: on Nth weekday of every M month
                     // yearly: on Nth weekday of M month
                     if (!isset($this->recur["weekdays"]) && !isset($this->recur["nday"])) {
                         return;
                     }
                     $weekdays = (int) $this->recur["weekdays"];
                     $nday = (int) $this->recur["nday"];
                     // Calc startdate
                     $monthbegindow = (int) $this->recur["start"];
                     if ($nday == 5) {
                         // Set date on the last day of the last month
                         $monthbegindow += (gmdate("t", $monthbegindow) - gmdate("j", $monthbegindow)) * 24 * 60 * 60;
                     } else {
                         // Set on the first day of the month
                         $monthbegindow -= (gmdate("j", $monthbegindow) - 1) * 24 * 60 * 60;
                     }
                     if ($term == 0xd) {
                         // Set on right month
                         if ($selmonth < $curmonth) {
                             $tmp = 12 - $curmonth + $selmonth;
                         } else {
                             $tmp = $selmonth - $curmonth;
                         }
                         for ($i = 0; $i < $tmp; $i++) {
                             $monthbegindow += $this->getMonthInSeconds($curyear, $curmonth);
                             if ($curmonth == 12) {
                                 $curyear++;
                                 $curmonth = 0;
                             }
                             $curmonth++;
                         }
                     } else {
                         // Check or you exist in the right month
                         for ($i = 0; $i < 7; $i++) {
                             if ($nday == 5 && 1 << (gmdate("w", $monthbegindow) - $i) % 7 & $weekdays) {
                                 $day = gmdate("j", $monthbegindow) - $i;
                                 break;
                             } else {
                                 if ($nday != 5 && 1 << (gmdate("w", $monthbegindow) + $i) % 7 & $weekdays) {
                                     $day = ($nday - 1) * 7 + ($i + 1);
                                     break;
                                 }
                             }
                         }
                         // Goto the next X month
                         if (isset($day) && $day < gmdate("j", (int) $this->recur["start"])) {
                             if ($nday == 5) {
                                 $monthbegindow += 24 * 60 * 60;
                                 if ($curmonth == 12) {
                                     $curyear++;
                                     $curmonth = 0;
                                 }
                                 $curmonth++;
                             }
                             for ($i = 0; $i < $everyn; $i++) {
                                 $monthbegindow += $this->getMonthInSeconds($curyear, $curmonth);
                                 if ($curmonth == 12) {
                                     $curyear++;
                                     $curmonth = 0;
                                 }
                                 $curmonth++;
                             }
                             if ($nday == 5) {
                                 $monthbegindow -= 24 * 60 * 60;
                             }
                         }
                     }
                     //FIXME: weekstart?
                     $day = 0;
                     // Set start on the right day
                     for ($i = 0; $i < 7; $i++) {
                         if ($nday == 5 && 1 << (gmdate("w", $monthbegindow) - $i) % 7 & $weekdays) {
                             $day = $i;
                             break;
                         } else {
                             if ($nday != 5 && 1 << (gmdate("w", $monthbegindow) + $i) % 7 & $weekdays) {
                                 $day = ($nday - 1) * 7 + ($i + 1);
                                 break;
                             }
                         }
                     }
                     if ($nday == 5) {
                         $monthbegindow -= $day * 24 * 60 * 60;
                     } else {
                         $monthbegindow += ($day - 1) * 24 * 60 * 60;
                     }
                     $firstocc = 0;
                     if ($term == 0xc) {
                         // Calc first occ
                         $monthIndex = (12 % $everyn * (((int) gmdate("Y", $this->recur["start"]) - 1601) % $everyn) % $everyn + ((int) gmdate("n", $this->recur["start"]) - 1)) % $everyn;
                         for ($i = 0; $i < $monthIndex; $i++) {
                             $firstocc += $this->getMonthInSeconds(1601 + floor($i / 12), $i % 12 + 1) / 60;
                         }
                         $rdata .= pack("VVVVV", $firstocc, $everyn, 0, $weekdays, $nday);
                     } else {
                         // Calc first occ
                         $monthIndex = (int) gmdate("n", $this->recur["start"]);
                         for ($i = 1; $i < $monthIndex; $i++) {
                             $firstocc += $this->getMonthInSeconds(1601 + floor($i / 12), $i) / 60;
                         }
                         $rdata .= pack("VVVVV", $firstocc, $everyn, 0, $weekdays, $nday);
                     }
                     break;
             }
             break;
     }
     if (!isset($this->recur["term"])) {
         return;
     }
     // Terminate
     $term = (int) $this->recur["term"];
     $rdata .= pack("CCCC", $term, 0x20, 0x0, 0x0);
     switch ($term) {
         // After the given enddate
         case 0x21:
             $rdata .= pack("V", 10);
             break;
             // After a number of times
         // After a number of times
         case 0x22:
             if (!isset($this->recur["numoccur"])) {
                 return;
             }
             $rdata .= pack("V", (int) $this->recur["numoccur"]);
             break;
             // Never ends
         // Never ends
         case 0x23:
             $rdata .= pack("V", 0);
             break;
     }
     // Strange little thing for the recurrence type "every workday"
     if ((int) $this->recur["type"] == 0xb && (int) $this->recur["subtype"] == 1) {
         $rdata .= pack("V", 1);
     } else {
         // Other recurrences
         $rdata .= pack("V", 0);
     }
     // Exception data
     // Get all exceptions
     $deleted_items = $this->recur["deleted_occurences"];
     $changed_items = $this->recur["changed_occurences"];
     // Merge deleted and changed items into one list
     $items = $deleted_items;
     foreach ($changed_items as $changed_item) {
         array_push($items, $changed_item["basedate"]);
     }
     sort($items);
     // Add the merged list in to the rdata
     $rdata .= pack("V", count($items));
     foreach ($items as $item) {
         $rdata .= pack("V", $this->unixDataToRecurData($item));
     }
     // Loop through the changed exceptions (not deleted)
     $rdata .= pack("V", count($changed_items));
     $items = array();
     foreach ($changed_items as $changed_item) {
         $items[] = $this->dayStartOf($changed_item["start"]);
     }
     sort($items);
     // Add the changed items list int the rdata
     foreach ($items as $item) {
         $rdata .= pack("V", $this->unixDataToRecurData($item));
     }
     // Set start date
     $rdata .= pack("V", $this->unixDataToRecurData((int) $this->recur["start"]));
     // Set enddate
     switch ($term) {
         // After the given enddate
         case 0x21:
             $rdata .= pack("V", $this->unixDataToRecurData((int) $this->recur["end"]));
             break;
             // After a number of times
         // After a number of times
         case 0x22:
             // @todo: calculate enddate with intval($this->recur["startocc"]) + intval($this->recur["duration"]) > 24 hour
             $occenddate = (int) $this->recur["start"];
             switch ((int) $this->recur["type"]) {
                 case 0xa:
                     //daily
                     if ($this->recur["subtype"] == 1) {
                         // Daily every workday
                         $restocc = (int) $this->recur["numoccur"];
                         // Get starting weekday
                         $nowtime = $this->gmtime($occenddate);
                         $j = $nowtime["tm_wday"];
                         while (1) {
                             if ($j % 7 > 0 && $j % 7 < 6) {
                                 $restocc--;
                             }
                             $j++;
                             if ($restocc <= 0) {
                                 break;
                             }
                             $occenddate += 24 * 60 * 60;
                         }
                     } else {
                         // -1 because the first day already counts (from 1-1-1980 to 1-1-1980 is 1 occurrence)
                         $occenddate += (int) $this->recur["everyn"] * 60 * ((int) $this->recur["numoccur"] - 1);
                     }
                     break;
                 case 0xb:
                     //weekly
                     // Needed values
                     // $forwardcount - number of weeks we can skip forward
                     // $restocc - number of remaning occurrences after the week skip
                     // Add the weeks till the last item
                     $occenddate += $forwardcount * 7 * 24 * 60 * 60;
                     $dayofweek = gmdate("w", $occenddate);
                     // Loop through the last occurrences until we have had them all
                     for ($j = 1; $restocc > 0; $j++) {
                         // Jump to the next week (which may be N weeks away) when going over the week boundary
                         if (($dayofweek + $j) % 7 == $weekstart) {
                             $occenddate += ((int) $this->recur["everyn"] - 1) * 7 * 24 * 60 * 60;
                         }
                         // If this is a matching day, once less occurrence to process
                         if ((int) $this->recur["weekdays"] & 1 << ($dayofweek + $j) % 7) {
                             $restocc--;
                         }
                         // Next day
                         $occenddate += 24 * 60 * 60;
                     }
                     break;
                 case 0xc:
                     //monthly
                 //monthly
                 case 0xd:
                     //yearly
                     $curyear = gmdate("Y", (int) $this->recur["start"]);
                     $curmonth = gmdate("n", (int) $this->recur["start"]);
                     // $forwardcount = months
                     switch ((int) $this->recur["subtype"]) {
                         case 2:
                             // on D day of every M month
                             while ($forwardcount > 0) {
                                 $occenddate += $this->getMonthInSeconds($curyear, $curmonth);
                                 if ($curmonth >= 12) {
                                     $curmonth = 1;
                                     $curyear++;
                                 } else {
                                     $curmonth++;
                                 }
                                 $forwardcount--;
                             }
                             // compensation between 28 and 31
                             if ((int) $this->recur["monthday"] >= 28 && (int) $this->recur["monthday"] <= 31 && gmdate("j", $occenddate) < (int) $this->recur["monthday"]) {
                                 if (gmdate("j", $occenddate) < 28) {
                                     $occenddate -= gmdate("j", $occenddate) * 24 * 60 * 60;
                                 } else {
                                     $occenddate += (gmdate("t", $occenddate) - gmdate("j", $occenddate)) * 24 * 60 * 60;
                                 }
                             }
                             break;
                         case 3:
                             // on Nth weekday of every M month
                             $nday = (int) $this->recur["nday"];
                             //1 tot 5
                             $weekdays = (int) $this->recur["weekdays"];
                             while ($forwardcount > 0) {
                                 $occenddate += $this->getMonthInSeconds($curyear, $curmonth);
                                 if ($curmonth >= 12) {
                                     $curmonth = 1;
                                     $curyear++;
                                 } else {
                                     $curmonth++;
                                 }
                                 $forwardcount--;
                             }
                             if ($nday == 5) {
                                 // Set date on the last day of the last month
                                 $occenddate += (gmdate("t", $occenddate) - gmdate("j", $occenddate)) * 24 * 60 * 60;
                             } else {
                                 // Set date on the first day of the last month
                                 $occenddate -= (gmdate("j", $occenddate) - 1) * 24 * 60 * 60;
                             }
                             for ($i = 0; $i < 7; $i++) {
                                 if ($nday == 5 && 1 << (gmdate("w", $occenddate) - $i) % 7 & $weekdays) {
                                     $occenddate -= $i * 24 * 60 * 60;
                                     break;
                                 } else {
                                     if ($nday != 5 && 1 << (gmdate("w", $occenddate) + $i) % 7 & $weekdays) {
                                         $occenddate += ($i + ($nday - 1) * 7) * 24 * 60 * 60;
                                         break;
                                     }
                                 }
                             }
                             break;
                             //case 3:
                     }
                     break;
             }
             if (defined("PHP_INT_MAX") && $occenddate > PHP_INT_MAX) {
                 $occenddate = PHP_INT_MAX;
             }
             $this->recur["end"] = $occenddate;
             $rdata .= pack("V", $this->unixDataToRecurData((int) $this->recur["end"]));
             break;
             // Never ends
         // Never ends
         case 0x23:
         default:
             $this->recur["end"] = 0x7fffffff;
             // max date -> 2038
             $rdata .= pack("V", 0x5ae980df);
             break;
     }
     // UTC date
     $utcstart = $this->toGMT($this->tz, (int) $this->recur["start"]);
     $utcend = $this->toGMT($this->tz, (int) $this->recur["end"]);
     //utc date+time
     $utcfirstoccstartdatetime = isset($this->recur["startocc"]) ? $utcstart + (int) $this->recur["startocc"] * 60 : $utcstart;
     $utcfirstoccenddatetime = isset($this->recur["endocc"]) ? $utcstart + (int) $this->recur["endocc"] * 60 : $utcstart;
     // update reminder time
     mapi_setprops($this->message, array($this->proptags["reminder_time"] => $utcfirstoccstartdatetime));
     // update first occurrence date
     mapi_setprops($this->message, array($this->proptags["startdate"] => $utcfirstoccstartdatetime));
     mapi_setprops($this->message, array($this->proptags["duedate"] => $utcfirstoccenddatetime));
     mapi_setprops($this->message, array($this->proptags["commonstart"] => $utcfirstoccstartdatetime));
     mapi_setprops($this->message, array($this->proptags["commonend"] => $utcfirstoccenddatetime));
     // Set Outlook properties, if it is an appointment
     if (isset($this->recur["message_class"]) && $this->recur["message_class"] == "IPM.Appointment") {
         // update real begin and real end date
         mapi_setprops($this->message, array($this->proptags["startdate_recurring"] => $utcstart));
         mapi_setprops($this->message, array($this->proptags["enddate_recurring"] => $utcend));
         // recurrencetype
         // Strange enough is the property recurrencetype, (type-0x9) and not the CDO recurrencetype
         mapi_setprops($this->message, array($this->proptags["recurrencetype"] => (int) $this->recur["type"] - 0x9));
         // set named prop 'side_effects' to 369, needed for Outlook to ask for single or total recurrence when deleting
         mapi_setprops($this->message, array($this->proptags["side_effects"] => 369));
     } else {
         mapi_setprops($this->message, array($this->proptags["side_effects"] => 3441));
     }
     // FlagDueBy is datetime of the first reminder occurrence. Outlook gives on this time a reminder popup dialog
     // Any change of the recurrence (including changing and deleting exceptions) causes the flagdueby to be reset
     // to the 'next' occurrence; this makes sure that deleting the next ocurrence will correctly set the reminder to
     // the occurrence after that. The 'next' occurrence is defined as being the first occurrence that starts at moment X (server time)
     // with the reminder flag set.
     $reminderprops = mapi_getprops($this->message, array($this->proptags["reminder_minutes"]));
     if (isset($reminderprops[$this->proptags["reminder_minutes"]])) {
         $occ = false;
         $occurrences = $this->getItems(time(), 0x7ff00000, 3, true);
         for ($i = 0, $len = count($occurrences); $i < $len; $i++) {
             // This will actually also give us appointments that have already started, but not yet ended. Since we want the next
             // reminder that occurs after time(), we may have to skip the first few entries. We get 3 entries since that is the maximum
             // number that would be needed (assuming reminder for item X cannot be before the previous occurrence starts). Worst case:
             // time() is currently after start but before end of item, but reminder of next item has already passed (reminder for next item
             // can be DURING the previous item, eg daily allday events). In that case, the first and second items must be skipped.
             if ($occurrences[$i][$this->proptags["startdate"]] - $reminderprops[$this->proptags["reminder_minutes"]] * 60 > time()) {
                 $occ = $occurrences[$i];
                 break;
             }
         }
         if ($occ) {
             mapi_setprops($this->message, array($this->proptags["flagdueby"] => $occ[$this->proptags["startdate"]] - $reminderprops[$this->proptags["reminder_minutes"]] * 60));
         } else {
             // Last reminder passed, no reminders any more.
             mapi_setprops($this->message, array($this->proptags["reminder"] => false, $this->proptags["flagdueby"] => 0x7ff00000));
         }
     }
     // Default data
     // Second item (0x08) indicates the Outlook version (see documentation at the bottom of this file for more information)
     $rdata .= pack("VCCCC", 0x3006, 0x8, 0x30, 0x0, 0x0);
     if (isset($this->recur["startocc"]) && isset($this->recur["endocc"])) {
         // Set start and endtime in minutes
         $rdata .= pack("VV", (int) $this->recur["startocc"], (int) $this->recur["endocc"]);
     }
     // Detailed exception data
     $changed_items = $this->recur["changed_occurences"];
     $rdata .= pack("v", count($changed_items));
     foreach ($changed_items as $changed_item) {
         // Set start and end time of exception
         $rdata .= pack("V", $this->unixDataToRecurData($changed_item["start"]));
         $rdata .= pack("V", $this->unixDataToRecurData($changed_item["end"]));
         $rdata .= pack("V", $this->unixDataToRecurData($changed_item["basedate"]));
         //Bitmask
         $bitmask = 0;
         // Check for changed strings
         if (isset($changed_item["subject"])) {
             $bitmask |= 1 << 0;
         }
         if (isset($changed_item["remind_before"])) {
             $bitmask |= 1 << 2;
         }
         if (isset($changed_item["reminder_set"])) {
             $bitmask |= 1 << 3;
         }
         if (isset($changed_item["location"])) {
             $bitmask |= 1 << 4;
         }
         if (isset($changed_item["busystatus"])) {
             $bitmask |= 1 << 5;
         }
         if (isset($changed_item["alldayevent"])) {
             $bitmask |= 1 << 7;
         }
         if (isset($changed_item["label"])) {
             $bitmask |= 1 << 8;
         }
         $rdata .= pack("v", $bitmask);
         // Set "subject"
         if (isset($changed_item["subject"])) {
             // convert utf-8 to non-unicode blob string (us-ascii?)
             $subject = iconv("UTF-8", "windows-1252//TRANSLIT", $changed_item["subject"]);
             $length = strlen($subject);
             $rdata .= pack("vv", $length + 1, $length);
             $rdata .= pack("a" . $length, $subject);
         }
         if (isset($changed_item["remind_before"])) {
             $rdata .= pack("V", $changed_item["remind_before"]);
         }
         if (isset($changed_item["reminder_set"])) {
             $rdata .= pack("V", $changed_item["reminder_set"]);
         }
         if (isset($changed_item["location"])) {
             $location = iconv("UTF-8", "windows-1252//TRANSLIT", $changed_item["location"]);
             $length = strlen($location);
             $rdata .= pack("vv", $length + 1, $length);
             $rdata .= pack("a" . $length, $location);
         }
         if (isset($changed_item["busystatus"])) {
             $rdata .= pack("V", $changed_item["busystatus"]);
         }
         if (isset($changed_item["alldayevent"])) {
             $rdata .= pack("V", $changed_item["alldayevent"]);
         }
         if (isset($changed_item["label"])) {
             $rdata .= pack("V", $changed_item["label"]);
         }
     }
     $rdata .= pack("V", 0);
     // write extended data
     foreach ($changed_items as $changed_item) {
         $rdata .= pack("V", 0);
         if (isset($changed_item["subject"]) || isset($changed_item["location"])) {
             $rdata .= pack("V", $this->unixDataToRecurData($changed_item["start"]));
             $rdata .= pack("V", $this->unixDataToRecurData($changed_item["end"]));
             $rdata .= pack("V", $this->unixDataToRecurData($changed_item["basedate"]));
         }
         if (isset($changed_item["subject"])) {
             $subject = iconv("UTF-8", "UCS-2LE", $changed_item["subject"]);
             $length = iconv_strlen($subject, "UCS-2LE");
             $rdata .= pack("v", $length);
             $rdata .= pack("a" . $length * 2, $subject);
         }
         if (isset($changed_item["location"])) {
             $location = iconv("UTF-8", "UCS-2LE", $changed_item["location"]);
             $length = iconv_strlen($location, "UCS-2LE");
             $rdata .= pack("v", $length);
             $rdata .= pack("a" . $length * 2, $location);
         }
         if (isset($changed_item["subject"]) || isset($changed_item["location"])) {
             $rdata .= pack("V", 0);
         }
     }
     $rdata .= pack("V", 0);
     // Set props
     mapi_setprops($this->message, array($this->proptags["recurring_data"] => $rdata, $this->proptags["recurring"] => true));
     if (isset($this->tz) && $this->tz) {
         $timezone = "GMT";
         if ($this->tz["timezone"] != 0) {
             // Create user readable timezone information
             $timezone = sprintf("(GMT %s%02d:%02d)", -$this->tz["timezone"] > 0 ? "+" : "-", abs($this->tz["timezone"] / 60), abs($this->tz["timezone"] % 60));
         }
         mapi_setprops($this->message, array($this->proptags["timezone_data"] => $this->getTimezoneData($this->tz), $this->proptags["timezone"] => $timezone));
     }
 }
Exemplo n.º 17
0
 /**
  * Imports a change on a folder
  *
  * @param object        $folder     SyncFolder
  *
  * @access public
  * @return string       id of the folder
  * @throws StatusException
  */
 public function ImportFolderChange($folder)
 {
     $id = isset($folder->serverid) ? $folder->serverid : false;
     $parent = $folder->parentid;
     $displayname = u2wi($folder->displayname);
     $type = $folder->type;
     if (Utils::IsSystemFolder($type)) {
         throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, system folder can not be created/modified", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname), SYNC_FSSTATUS_SYSTEMFOLDER);
     }
     // create a new folder if $id is not set
     if (!$id) {
         // the root folder is "0" - get IPM_SUBTREE
         if ($parent == "0") {
             $parentprops = mapi_getprops($this->store, array(PR_IPM_SUBTREE_ENTRYID));
             if (isset($parentprops[PR_IPM_SUBTREE_ENTRYID])) {
                 $parentfentryid = $parentprops[PR_IPM_SUBTREE_ENTRYID];
             }
         } else {
             $parentfentryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($parent));
         }
         if (!$parentfentryid) {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to open parent folder (no entry id)", Utils::PrintAsString(false), $folder->parentid, $displayname), SYNC_FSSTATUS_PARENTNOTFOUND);
         }
         $parentfolder = mapi_msgstore_openentry($this->store, $parentfentryid);
         if (!$parentfolder) {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to open parent folder (open entry)", Utils::PrintAsString(false), $folder->parentid, $displayname), SYNC_FSSTATUS_PARENTNOTFOUND);
         }
         //  mapi_folder_createfolder() fails if a folder with this name already exists -> MAPI_E_COLLISION
         $newfolder = mapi_folder_createfolder($parentfolder, $displayname, "");
         if (mapi_last_hresult()) {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, mapi_folder_createfolder() failed: 0x%X", Utils::PrintAsString(false), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_FOLDEREXISTS);
         }
         mapi_setprops($newfolder, array(PR_CONTAINER_CLASS => MAPIUtils::GetContainerClassFromFolderType($type)));
         $props = mapi_getprops($newfolder, array(PR_SOURCE_KEY));
         if (isset($props[PR_SOURCE_KEY])) {
             $sourcekey = bin2hex($props[PR_SOURCE_KEY]);
             ZLog::Write(LOGLEVEL_DEBUG, sprintf("Created folder '%s' with id: '%s'", $displayname, $sourcekey));
             return $sourcekey;
         } else {
             throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, folder created but PR_SOURCE_KEY not available: 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_SERVERERROR);
         }
         return false;
     }
     // update folder
     $entryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($id));
     if (!$entryid) {
         throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to open folder (no entry id): 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_PARENTNOTFOUND);
     }
     $folder = mapi_msgstore_openentry($this->store, $entryid);
     if (!$folder) {
         throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, unable to open folder (open entry): 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_PARENTNOTFOUND);
     }
     $props = mapi_getprops($folder, array(PR_SOURCE_KEY, PR_PARENT_SOURCE_KEY, PR_DISPLAY_NAME, PR_CONTAINER_CLASS));
     if (!isset($props[PR_SOURCE_KEY]) || !isset($props[PR_PARENT_SOURCE_KEY]) || !isset($props[PR_DISPLAY_NAME]) || !isset($props[PR_CONTAINER_CLASS])) {
         throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, folder data not available: 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_SERVERERROR);
     }
     if ($parent == "0") {
         $parentprops = mapi_getprops($this->store, array(PR_IPM_SUBTREE_ENTRYID));
         $parentfentryid = $parentprops[PR_IPM_SUBTREE_ENTRYID];
         $mapifolder = mapi_msgstore_openentry($this->store, $parentfentryid);
         $rootfolderprops = mapi_getprops($mapifolder, array(PR_SOURCE_KEY));
         $parent = bin2hex($rootfolderprops[PR_SOURCE_KEY]);
         ZLog::Write(LOGLEVEL_DEBUG, sprintf("ImportChangesICS->ImportFolderChange(): resolved AS parent '0' to sourcekey '%s'", $parent));
     }
     // In theory the parent id could change, which means that the folder was moved.
     // It is unknown if any device supports this, so we do currently not implement it (no known device is able to do this)
     if (bin2hex($props[PR_PARENT_SOURCE_KEY]) !== $parent) {
         throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Folder was moved to another location, which is currently not supported. Please report this to the Z-Push dev team together with the WBXML log and your device details (model, firmware etc).", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_UNKNOWNERROR);
     }
     $props = array(PR_DISPLAY_NAME => $displayname);
     mapi_setprops($folder, $props);
     mapi_savechanges($folder);
     if (mapi_last_hresult()) {
         throw new StatusException(sprintf("ImportChangesICS->ImportFolderChange('%s','%s','%s'): Error, mapi_savechanges() failed: 0x%X", Utils::PrintAsString($folder->serverid), $folder->parentid, $displayname, mapi_last_hresult()), SYNC_FSSTATUS_SERVERERROR);
     }
     ZLog::Write(LOGLEVEL_DEBUG, "Imported changes for folder: {$id}");
     return $id;
 }
Exemplo n.º 18
0
 function _storeAttachment($mapimessage, $part)
 {
     // attachment
     $attach = mapi_message_createattach($mapimessage);
     // Filename is present in both Content-Type: name=.. and in Content-Disposition: filename=
     if (isset($part->ctype_parameters["name"])) {
         $filename = $part->ctype_parameters["name"];
     } else {
         if (isset($part->d_parameters["name"])) {
             $filename = $part->d_parameters["filename"];
         } else {
             if (isset($part->d_parameters["filename"])) {
                 //sending appointment with nokia only filename is set
                 $filename = $part->d_parameters["filename"];
             } else {
                 $filename = "untitled";
             }
         }
     }
     // Set filename and attachment type
     mapi_setprops($attach, array(PR_ATTACH_LONG_FILENAME => u2w($filename), PR_ATTACH_METHOD => ATTACH_BY_VALUE));
     // Set attachment data
     mapi_setprops($attach, array(PR_ATTACH_DATA_BIN => $part->body));
     // Set MIME type
     mapi_setprops($attach, array(PR_ATTACH_MIME_TAG => $part->ctype_primary . "/" . $part->ctype_secondary));
     mapi_savechanges($attach);
 }
 /**
  * Checks if there has been any significant changes on appointment/meeting item.
  * Significant changes be:
  * 1) startdate has been changed
  * 2) duedate has been changed OR
  * 3) recurrence pattern has been created, modified or removed
  *
  * @param Array oldProps old props before an update
  * @param Number basedate basedate
  * @param Boolean isRecurrenceChanged for change in recurrence pattern.
  * isRecurrenceChanged true means Recurrence pattern has been changed, so clear all attendees response
  */
 function checkSignificantChanges($oldProps, $basedate, $isRecurrenceChanged = false)
 {
     $message = null;
     $attach = null;
     // If basedate is specified then we need to open exception message to clear recipient responses
     if ($basedate) {
         $recurrence = new Recurrence($this->store, $this->message);
         if ($recurrence->isException($basedate)) {
             $attach = $recurrence->getExceptionAttachment($basedate);
             if ($attach) {
                 $message = mapi_attach_openobj($attach, MAPI_MODIFY);
             }
         }
     } else {
         // use normal message or recurring series message
         $message = $this->message;
     }
     if (!$message) {
         return;
     }
     $newProps = mapi_getprops($message, array($this->proptags['startdate'], $this->proptags['duedate'], $this->proptags['updatecounter']));
     // Check whether message is updated or not.
     if (isset($newProps[$this->proptags['updatecounter']]) && $newProps[$this->proptags['updatecounter']] == 0) {
         return;
     }
     if ($newProps[$this->proptags['startdate']] != $oldProps[$this->proptags['startdate']] || $newProps[$this->proptags['duedate']] != $oldProps[$this->proptags['duedate']] || $isRecurrenceChanged) {
         $this->clearRecipientResponse($message);
         mapi_setprops($message, array($this->proptags['owner_critical_change'] => time()));
         mapi_savechanges($message);
         if ($attach) {
             // Also save attachment Object.
             mapi_savechanges($attach);
         }
     }
 }
 function sendCompleteUpdate($prefix, $action, $prefixComplete)
 {
     $messageprops = mapi_getprops($this->message, array($this->props['taskstate']));
     if (!isset($messageprops[$this->props['taskstate']]) || $messageprops[$this->props['taskstate']] != tdsOWN) {
         return false;
     }
     // Can only decline assignee task
     mapi_setprops($this->message, array($this->props['complete'] => true, $this->props['datecompleted'] => $action["dateCompleted"], $this->props['status'] => 2, $this->props['percent_complete'] => 1));
     $this->doUpdate($prefix, $prefixComplete);
 }
Exemplo n.º 21
0
 /**
  * Sets the properties one by one in a MAPI object
  *
  * @param mixed             &$mapimessage
  * @param array             &$propsToSet
  * @param array             &$mapiprops
  *
  * @access private
  * @return
  */
 private function setPropsIndividually(&$mapimessage, &$propsToSet, &$mapiprops)
 {
     foreach ($propsToSet as $prop => $value) {
         mapi_setprops($mapimessage, array($prop => $value));
         if (mapi_last_hresult()) {
             Zlog::Write(LOGLEVEL_ERROR, sprintf("Failed setting property [%s] with value [%s], error code was:%x", array_search($prop, $mapiprops), $value, mapi_last_hresult()));
         }
     }
 }
Exemplo n.º 22
0
 /**
  * Updates the chunk data in the hidden folder if it changed.
  * If the chunkId is not available, it's created.
  *
  * @param string    $folderid
  * @param string    $chunkName      The name of the chunk (used to find/update the chunk message).
  *                                  The name is to be saved in the 'subject' of the chunk message.
  * @param int       $amountEntries  Amount of entries in the chunkdata.
  * @param string    $chunkData      The data containing all the data.
  * @param string    $chunkCRC       A checksum of the chunk data. To be saved in the 'location' of
  *                                  the chunk message. Used to identify changed chunks.
  * @param string    $gabId          Id that uniquely identifies the GAB. If not set or null the default GAB is assumed.
  * @param string    $gabName        String that uniquely identifies the GAB. If not set the default GAB is assumed.
  *
  * @access protected
  * @return boolean
  */
 protected function setChunkData($folderid, $chunkName, $amountEntries, $chunkData, $chunkCRC, $gabId = null, $gabName = 'default')
 {
     $log = sprintf("Kopano->setChunkData: %s\tEntries: %d\t Size: %d B\tCRC: %s  -  ", $chunkName, $amountEntries, strlen($chunkData), $chunkCRC);
     // find the chunk message in the folder
     $store = $this->getStore($gabId, $gabName);
     if (!$store) {
         return false;
     }
     $chunkdata = $this->findChunk($store, $folderid, $chunkName);
     $message = false;
     // message not found, create it
     if (empty($chunkdata)) {
         $folder = $this->getFolder($store, $folderid);
         $message = mapi_folder_createmessage($folder);
         mapi_setprops($message, array(PR_MESSAGE_CLASS => "IPM.Appointment", $this->mapiprops['chunktype'] => $this->chunkType, PR_SUBJECT => $chunkName, $this->mapiprops['createtime'] => time(), $this->mapiprops['reminderset'] => 0, $this->mapiprops['isrecurring'] => 0, $this->mapiprops['busystatus'] => 0));
         $log .= "creating - ";
     } else {
         // we need to update the chunk if the CRC does not match!
         if ($chunkdata[$this->mapiprops['chunkCRC']] != $chunkCRC) {
             $message = mapi_msgstore_openentry($store, $chunkdata[PR_ENTRYID]);
             $log .= "opening - ";
         } else {
             $log .= "unchanged";
         }
     }
     // update chunk if necessary
     if ($message) {
         mapi_setprops($message, array($this->mapiprops['chunkCRC'] => $chunkCRC, PR_BODY => $chunkData, $this->mapiprops['updatetime'] => time()));
         @mapi_savechanges($message);
         if (mapi_last_hresult()) {
             $log .= sprintf("error saving: 0x%08X", mapi_last_hresult());
         } else {
             $log .= "saved";
         }
     }
     // output log
     $this->log($log);
     return true;
 }