/** * Function to get a human readable string from a MAPI error code * *@param int $errcode the MAPI error code, if not given, we use mapi_last_hresult *@return string The defined name for the MAPI error code */ function get_mapi_error_name($errcode = null) { if ($errcode === null) { $errcode = mapi_last_hresult(); } if ($errcode !== 0) { // get_defined_constants(true) is preferred, but crashes PHP // https://bugs.php.net/bug.php?id=61156 $allConstants = get_defined_constants(); foreach ($allConstants as $key => $value) { /** * If PHP encounters a number beyond the bounds of the integer type, * it will be interpreted as a float instead, so when comparing these error codes * we have to manually typecast value to integer, so float will be converted in integer, * but still its out of bound for integer limit so it will be auto adjusted to minus value */ if ($errcode == (int) $value) { // Check that we have an actual MAPI error or warning definition $prefix = substr($key, 0, 7); if ($prefix == "MAPI_E_" || $prefix == "MAPI_W_") { return $key; } } } } else { return "NOERROR"; } // error code not found, return hex value (this is a fix for 64-bit systems, we can't use the dechex() function for this) $result = unpack("H*", pack("N", $errcode)); return "0x" . $result[1]; }
function checkMapiError($msg) { global $log; if (mapi_last_hresult() != 0) { $log->warn("MAPI error {$msg}: " . get_mapi_error_name()); exit; } }
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"; } }
function openMsgStore($username, $password) { $session = mapi_logon_zarafa($username, $password, SERVER); if (mapi_last_hresult() != 0) { trigger_error(sprintf("MAPI Error: 0x%x", mapi_last_hresult()), E_USER_ERROR); } $storesTable = mapi_getmsgstorestable($session); $stores = mapi_table_queryallrows($storesTable, array(PR_ENTRYID, PR_MDB_PROVIDER)); for ($i = 0; $i < count($stores); $i++) { if ($stores[$i][PR_MDB_PROVIDER] == ZARAFA_SERVICE_GUID) { $storeEntryid = $stores[$i][PR_ENTRYID]; break; } } if (!isset($storeEntryid)) { trigger_error("Default store not found", E_USER_ERROR); } $store = mapi_openmsgstore($session, $storeEntryid); isUnicodeStore($store); return $store; }
function getuserlist() { $this->companylist = mapi_zarafa_getcompanylist($this->defaultstore); if (mapi_last_hresult() == NOERROR && is_array($this->companylist)) { // multi company setup, get all users from all companies if ($this->options->company != "") { foreach ($this->companylist as $companyName => $companyData) { if ($companyName == $this->options->company) { $this->userlist = mapi_zarafa_getuserlist($this->defaultstore, $companyData["companyid"]); break; } } } else { // Sanity check: multi-company setup, but no company in options print "Running in a multi-company environment, but no company specified in command line.\n"; exit(RESULT_ERROR_NOCOMPANYSPECIFIED); } } else { // single company setup, get list of all zarafa users print "Getting user list\n"; $this->userlist = mapi_zarafa_getuserlist($this->defaultstore); } if (count($this->userlist) <= 0) { print "Unable to get user list\n"; exit(RESULT_ERROR_USERLIST); } }
/** * Reads the current state from the Exporter * * @access public * @return string * @throws StatusException */ public function GetState() { $error = false; if (!isset($this->statestream) || $this->exporter === false) { $error = true; } if ($error === true || mapi_exportchanges_updatestate($this->exporter, $this->statestream) != true) { throw new StatusException(sprintf("ExportChangesICS->GetState(): Error, state not available or unable to update: 0x%X", mapi_last_hresult()), $this->folderid ? SYNC_STATUS_FOLDERHIERARCHYCHANGED : SYNC_FSSTATUS_CODEUNKNOWN, null, LOGLEVEL_WARN); } mapi_stream_seek($this->statestream, 0, STREAM_SEEK_SET); $state = ""; while (true) { $data = mapi_stream_read($this->statestream, 4096); if (strlen($data)) { $state .= $data; } else { break; } } return $state; }
/** * Deletes a card * * @param mixed $addressBookId * @param string $cardUri * @return bool */ public function deleteCard($addressBookId, $cardUri) { $this->logger->info("deleteCard({$cardUri})"); if (READ_ONLY) { $this->logger->warn("Cannot delete card: read-only"); return false; } $folder = mapi_msgstore_openentry($this->bridge->getStore($addressBookId), $addressBookId); $entryId = $this->getContactEntryId($addressBookId, $cardUri); if ($entryId === 0) { $this->logger->warn("Contact not found!"); return false; } // $folder = mapi_msgstore_openentry($this->bridge->getStore($addressBookId), $addressBookId); mapi_folder_deletemessages($folder, array($entryId)); if (mapi_last_hresult() > 0) { return false; } return true; }
/** * Reads data of large properties from a stream * * @param MAPIMessage $message * @param long $prop * * @access public * @return string */ public static function readPropStream($message, $prop) { $stream = mapi_openproperty($message, $prop, IID_IStream, 0, 0); $ret = mapi_last_hresult(); if ($ret == MAPI_E_NOT_FOUND) { ZLog::Write(LOGLEVEL_DEBUG, sprintf("MAPIUtils->readPropStream: property 0x%s not found. It is either empty or not set. It will be ignored.", str_pad(dechex($prop), 8, 0, STR_PAD_LEFT))); return ""; } elseif ($ret) { ZLog::Write(LOGLEVEL_ERROR, "MAPIUtils->readPropStream error opening stream: 0X%X", $ret); return ""; } $data = ""; $string = ""; while (1) { $data = mapi_stream_read($stream, 1024); if (strlen($data) == 0) { break; } $string .= $data; } return $string; }
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); } }
$store = mapi_openmsgstore($l_rSession, $storeEntryId); $root = mapi_msgstore_openentry($store, null); $spamStoreProps = mapi_getprops($root, array(PR_ADDITIONAL_REN_ENTRYIDS)); $spamFolder = mapi_msgstore_openentry($store, $spamStoreProps[PR_ADDITIONAL_REN_ENTRYIDS][4]); $table = mapi_folder_getcontentstable($spamFolder); $spamRows = mapi_table_queryallrows($table, array(PR_ENTRYID, PR_CREATION_TIME)); echo (mapi_last_hresult() == 0 ? "Fetching messages from Junk Folder..." : "Some error in fetching...") . "\n"; if (count($spamRows) > 0) { $spamEntryIds = array(); echo "\nTotal messages in Junk folder found are : " . count($spamRows) . "\n"; for ($i = 0; $i < count($spamRows); $i++) { if (greaterDate(date("Y-m-d G:i:s", $spamRows[$i][PR_CREATION_TIME]), $daysBeforeDeleted)) { array_push($spamEntryIds, $spamRows[$i][PR_ENTRYID]); } } if (count($spamEntryIds) > 0) { echo "\nDeleting all " . count($spamEntryIds) . " message(s)...\n"; mapi_folder_deletemessages($spamFolder, $spamEntryIds); echo "" . (mapi_last_hresult() == 0 ? "\nHooray! there is no spam." : "Some error in deleting... There are still some spam messages.") . "\n"; } else { echo "\nNo message found before " . $daysBeforeDeleted . " days in Junk Folder."; } } else { echo "\nNo message found in Junk Folder."; } } else { echo "No default store found... Terminating process.\n"; } ?>
define("FIELD_NAMES", true); //the format of date values: true if they are as unix timestamps, false otherwise define("DATES_AS_TIMESTAMPS", false); // mapping for the csv column number to contact field (first field is 0) $csv_mapping = array("given_name" => 0, "middle_name" => 1, "surname" => 2, "display_name_prefix" => 3, "webpage" => 6, "birthday" => 8, "wedding_anniversary" => 9, "notes" => 13, "email_address_1" => 14, "email_address_2" => 15, "email_address_3" => 16, "home_telephone_number" => 18, "home2_telephone_number" => 19, "cellular_telephone_number" => 20, "pager_telephone_number" => 21, "home_fax_number" => 22, "home_address" => 23, "home_address_street" => 24, "home_address_street2" => 25, "home_address_street3" => 26, "home_address_pobox" => 27, "home_address_city" => 28, "home_address_state" => 29, "home_address_postal_code" => 30, "home_address_country" => 31, "spouse_name" => 32, "manager_name" => 34, "assistant" => 35, "company_telephone_number" => 37, "office_telephone_number" => 38, "business2_telephone_number" => 39, "business_fax_number" => 40, "assistant_telephone_number" => 41, "company_name" => 42, "job_title" => 43, "department_name" => 44, "office_location" => 45, "profession" => 47, "business_address" => 49, "business_address_street" => 50, "business_address_street2" => 51, "business_address_street3" => 52, "business_address_pobox" => 53, "business_address_city" => 54, "business_address_state" => 55, "business_address_postal_code" => 56, "business_address_country" => 57, "other_telephone_number" => 58, "other_address" => 60, "other_address_street" => 61, "other_address_street2" => 62, "other_address_street3" => 63, "other_address_pobox" => 64, "other_address_city" => 65, "other_address_state" => 66, "other_address_postal_code" => 67, "other_address_country" => 68, "callback_telephone_number" => 69, "car_telephone_number" => 70, "isdn_number" => 71, "radio_telephone_number" => 72, "ttytdd_telephone_number" => 73, "telex_telephone_number" => 74, "sensitivity" => 84, "categories" => 87); ########################## ## end of configuration ## ########################## error_reporting(E_ALL); ini_set("display_errors", true); ini_set("html_errors", false); mapidefs(); mapitags(); $session = mapi_logon_zarafa($username, $password, SERVER); if (mapi_last_hresult() != 0) { trigger_error(sprintf("MAPI Error: 0x%x", mapi_last_hresult()), E_USER_ERROR); } $storesTable = mapi_getmsgstorestable($session); $stores = mapi_table_queryallrows($storesTable, array(PR_ENTRYID, PR_MDB_PROVIDER)); for ($i = 0; $i < count($stores); $i++) { if ($stores[$i][PR_MDB_PROVIDER] == ZARAFA_SERVICE_GUID) { $storeEntryid = $stores[$i][PR_ENTRYID]; break; } } if (!isset($storeEntryid)) { trigger_error("Default store not found", E_USER_ERROR); } $store = mapi_openmsgstore($session, $storeEntryid); $root = mapi_msgstore_openentry($store, null); $rootProps = mapi_getprops($root, array(PR_IPM_CONTACT_ENTRYID));
/** * 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"); } }
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; }
function listfolders_getlist($adminStore, $session, $user) { global $supported_classes; if (strtoupper($user) == 'SYSTEM') { // Find the public store store $storestables = @mapi_getmsgstorestable($session); $result = @mapi_last_hresult(); if ($result == NOERROR) { $rows = @mapi_table_queryallrows($storestables, array(PR_ENTRYID, PR_MDB_PROVIDER)); foreach ($rows as $row) { if (isset($row[PR_MDB_PROVIDER]) && $row[PR_MDB_PROVIDER] == ZARAFA_STORE_PUBLIC_GUID) { if (!isset($row[PR_ENTRYID])) { echo "Public folder are not available.\nIf this is a multi-tenancy system, use -u and -p and login with an admin user of the company.\nThe script will exit.\n"; exit(1); } $entryid = $row[PR_ENTRYID]; break; } } } } else { $entryid = @mapi_msgstore_createentryid($adminStore, $user); } $userStore = @mapi_openmsgstore($session, $entryid); $hresult = mapi_last_hresult(); // Cache the store for later use if ($hresult != NOERROR) { echo "Could not open store for '{$user}'. The script will exit.\n"; exit(1); } if (strtoupper($user) != 'SYSTEM') { $inbox = mapi_msgstore_getreceivefolder($userStore); if (mapi_last_hresult() != NOERROR) { printf("Could not open inbox for %s (0x%08X). The script will exit.\n", $user, mapi_last_hresult()); exit(1); } $inboxProps = mapi_getprops($inbox, array(PR_SOURCE_KEY)); } $storeProps = mapi_getprops($userStore, array(PR_IPM_OUTBOX_ENTRYID, PR_IPM_SENTMAIL_ENTRYID, PR_IPM_WASTEBASKET_ENTRYID)); $root = @mapi_msgstore_openentry($userStore, null); $h_table = @mapi_folder_gethierarchytable($root, CONVENIENT_DEPTH); $subfolders = @mapi_table_queryallrows($h_table, array(PR_ENTRYID, PR_DISPLAY_NAME, PR_CONTAINER_CLASS, PR_SOURCE_KEY, PR_PARENT_SOURCE_KEY, PR_FOLDER_TYPE, PR_ATTR_HIDDEN)); echo "Available folders in store '{$user}':\n" . str_repeat("-", 50) . "\n"; foreach ($subfolders as $folder) { // do not display hidden and search folders if (isset($folder[PR_ATTR_HIDDEN]) && $folder[PR_ATTR_HIDDEN] || isset($folder[PR_FOLDER_TYPE]) && $folder[PR_FOLDER_TYPE] == FOLDER_SEARCH) { continue; } // handle some special folders if (strtoupper($user) != 'SYSTEM' && (isset($inboxProps[PR_SOURCE_KEY]) && $folder[PR_SOURCE_KEY] == $inboxProps[PR_SOURCE_KEY] || $folder[PR_ENTRYID] == $storeProps[PR_IPM_SENTMAIL_ENTRYID] || $folder[PR_ENTRYID] == $storeProps[PR_IPM_WASTEBASKET_ENTRYID])) { $folder[PR_CONTAINER_CLASS] = "IPF.Note"; } if (isset($folder[PR_CONTAINER_CLASS]) && array_key_exists($folder[PR_CONTAINER_CLASS], $supported_classes)) { echo "Folder name:\t" . $folder[PR_DISPLAY_NAME] . "\n"; echo "Folder ID:\t" . bin2hex($folder[PR_SOURCE_KEY]) . "\n"; echo "Type:\t\t" . $supported_classes[$folder[PR_CONTAINER_CLASS]] . "\n"; echo "\n"; } } }
function _openDefaultMessageStore($session) { // Find the default store $storestables = mapi_getmsgstorestable($session); $result = mapi_last_hresult(); $entryid = false; if ($result == NOERROR) { $rows = mapi_table_queryallrows($storestables, array(PR_ENTRYID, PR_DEFAULT_STORE, PR_MDB_PROVIDER)); foreach ($rows as $row) { if (isset($row[PR_DEFAULT_STORE]) && $row[PR_DEFAULT_STORE] == true) { $entryid = $row[PR_ENTRYID]; break; } } } if ($entryid) { return mapi_openmsgstore($session, $entryid); } else { return false; } }
// Open msg store by using the entryID $l_rDefaultStore = mapi_openmsgstore($l_rSession, $l_bbnEntryID); echo 'Opening default store result (0=success): ' . mapi_last_hresult() . "\n"; // Get inbox $l_rInbox = mapi_msgstore_getreceivefolder($l_rDefaultStore); echo 'Getting entryID of inbox folder result (0=success): ' . mapi_last_hresult() . "\n"; // Check if folder has been opened if ($l_rInbox) { // Open contents table $l_rInboxTable = mapi_folder_getcontentstable($l_rInbox); echo 'Opening contents table result (0=success): ' . mapi_last_hresult() . "\n"; // Find the item by restricting all items to the correct ID $restrict = array(RES_AND, array(array(RES_PROPERTY, array(RELOP => RELOP_NE, ULPROPTAG => PR_PROCESSED, VALUE => array(PR_PROCESSED => true))), array(RES_CONTENT, array(FUZZYLEVEL => FL_PREFIX, ULPROPTAG => PR_MESSAGE_CLASS, VALUE => array(PR_SUBJECT => 'IPM.Schedule.Meeting'))), array(RES_BITMASK, array(ULTYPE => BMR_EQZ, ULMASK => MSGFLAG_READ, ULPROPTAG => PR_MESSAGE_FLAGS)))); // Just get all items from table $l_aRows = mapi_table_queryallrows($l_rInboxTable, array(PR_ENTRYID, PR_MESSAGE_CLASS, PR_SUBJECT, PR_PROCESSED), $restrict); echo 'Querying contents table result (0=success): ' . mapi_last_hresult() . "\n"; //print_r(count($l_aRows)); //exit; echo 'Processing messages' . "\n"; $l_iCounter = 0; for ($i = 0; $i < count($l_aRows); $i++) { $l_sMsgClassSearch = 'IPM.Schedule.Meeting'; $l_rMessage = mapi_msgstore_openentry($l_rDefaultStore, $l_aRows[$i][PR_ENTRYID]); $req = new Meetingrequest($l_rDefaultStore, $l_rMessage, $l_rSession); if ($req->isMeetingRequest() && !$req->isLocalOrganiser()) { // Put the item in the calendar 'tentatively' $req->doAccept(true, false, false); $l_iCounter++; } elseif ($req->isMeetingCancellation()) { // Let's do some processing of this Meeting Cancellation Object we received $req->processMeetingCancellation();
/** * Function will open FINDER_ROOT folder in root container * public folder's don't have FINDER_ROOT folder * * @see getSearchFoldersRoot($store) function in the webaccess * * @return mapiFolderObject root folder for search folders */ private function getSearchFoldersRoot() { // check if we can create search folders $storeProps = mapi_getprops($this->store, array(PR_STORE_SUPPORT_MASK, PR_FINDER_ENTRYID)); if (($storeProps[PR_STORE_SUPPORT_MASK] & STORE_SEARCH_OK) != STORE_SEARCH_OK) { ZLog::Write(LOGLEVEL_WARN, "Store doesn't support search folders. Public store doesn't have FINDER_ROOT folder"); return false; } // open search folders root $searchRootFolder = mapi_msgstore_openentry($this->store, $storeProps[PR_FINDER_ENTRYID]); if (mapi_last_hresult() != NOERROR) { ZLog::Write(LOGLEVEL_WARN, sprintf("Unable to open search folder (0x%X)", mapi_last_hresult())); return false; } return $searchRootFolder; }
if ($storeEntryId) { $store = mapi_openmsgstore($l_rSession, $storeEntryId); $delStoreProps = mapi_getprops($store, array(PR_IPM_WASTEBASKET_ENTRYID)); $deletedFolder = mapi_msgstore_openentry($store, $delStoreProps[PR_IPM_WASTEBASKET_ENTRYID]); $table = mapi_folder_getcontentstable($deletedFolder); $delRows = mapi_table_queryallrows($table, array(PR_ENTRYID, PR_CREATION_TIME)); echo (mapi_last_hresult() == 0 ? "Fetching messages from Deleted Folder..." : "Some error in fetching...") . "\n"; if (count($delRows) > 0) { $delEntryIds = array(); echo 'Total messages in deleted folder found are : ' . count($delRows) . "\n"; for ($i = 0; $i < count($delRows); $i++) { if (greaterDate(date("Y-m-d G:i:s", $delRows[$i][PR_CREATION_TIME]), $daysBeforeDeleted)) { array_push($delEntryIds, $delRows[$i][PR_ENTRYID]); } } if (count($delEntryIds) > 0) { echo "\nDeleting all " . count($delEntryIds) . " messages...\n"; mapi_folder_deletemessages($deletedFolder, $delEntryIds); echo "" . (mapi_last_hresult() == 0 ? "Successfully deleted all messages" : "Some error in deleting... please try again later") . "\n"; } else { echo "\nNo message found before " . $daysBeforeDeleted . " days in Deleted Folder."; } } else { echo "\nNo message found in Deleted Folder."; } } else { echo "No default store found... Terminating process.\n"; } ?>
/** * Imports a folder deletion * * @param string $id * @param string $parent id is ignored in ICS * * @access public * @return int SYNC_FOLDERHIERARCHY_STATUS * @throws StatusException */ public function ImportFolderDeletion($id, $parent = false) { ZLog::Write(LOGLEVEL_DEBUG, sprintf("ImportChangesICS->ImportFolderDeletion('%s','%s'): importing folder deletetion", $id, $parent)); $folderentryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($id)); if (!$folderentryid) { throw new StatusException(sprintf("ImportChangesICS->ImportFolderDeletion('%s','%s'): Error, unable to resolve folder", $id, $parent, mapi_last_hresult()), SYNC_FSSTATUS_FOLDERDOESNOTEXIST); } // get the folder type from the MAPIProvider $type = $this->mapiprovider->GetFolderType($folderentryid); if (Utils::IsSystemFolder($type)) { throw new StatusException(sprintf("ImportChangesICS->ImportFolderDeletion('%s','%s'): Error deleting system/default folder", $id, $parent), SYNC_FSSTATUS_SYSTEMFOLDER); } $ret = mapi_importhierarchychanges_importfolderdeletion($this->importer, 0, array(PR_SOURCE_KEY => hex2bin($id))); if (!$ret) { throw new StatusException(sprintf("ImportChangesICS->ImportFolderDeletion('%s','%s'): Error deleting folder: 0x%X", $id, $parent, mapi_last_hresult()), SYNC_FSSTATUS_SERVERERROR); } return $ret; }
/** * 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())); } } }
/** * Function creates meeting item in resource's calendar. *@param resource $message MAPI_message which is to create in resource's calendar *@param boolean $cancel cancel meeting *@param string $prefix prefix for subject of meeting */ function bookResources($message, $cancel, $prefix, $basedate = false) { if (!$this->enableDirectBooking) { return array(); } // Get the properties of the message $messageprops = mapi_getprops($message); if ($basedate) { $recurrItemProps = mapi_getprops($this->message, array($this->proptags['goid'], $this->proptags['goid2'], $this->proptags['timezone_data'], $this->proptags['timezone'], PR_OWNER_APPT_ID)); $messageprops[$this->proptags['goid']] = $this->setBasedateInGlobalID($recurrItemProps[$this->proptags['goid']], $basedate); $messageprops[$this->proptags['goid2']] = $recurrItemProps[$this->proptags['goid2']]; // Delete properties which are not needed. $deleteProps = array($this->proptags['basedate'], PR_DISPLAY_NAME, PR_ATTACHMENT_FLAGS, PR_ATTACHMENT_HIDDEN, PR_ATTACHMENT_LINKID, PR_ATTACH_FLAGS, PR_ATTACH_METHOD); foreach ($deleteProps as $propID) { if (isset($messageprops[$propID])) { unset($messageprops[$propID]); } } if (isset($messageprops[$this->proptags['recurring']])) { $messageprops[$this->proptags['recurring']] = false; } // Set Outlook properties $messageprops[$this->proptags['clipstart']] = $messageprops[$this->proptags['startdate']]; $messageprops[$this->proptags['clipend']] = $messageprops[$this->proptags['duedate']]; $messageprops[$this->proptags['timezone_data']] = $recurrItemProps[$this->proptags['timezone_data']]; $messageprops[$this->proptags['timezone']] = $recurrItemProps[$this->proptags['timezone']]; $messageprops[$this->proptags['attendee_critical_change']] = time(); $messageprops[$this->proptags['owner_critical_change']] = time(); } // Get resource recipients $getResourcesRestriction = array(RES_AND, array(array(RES_PROPERTY, array(RELOP => RELOP_EQ, ULPROPTAG => PR_RECIPIENT_TYPE, VALUE => array(PR_RECIPIENT_TYPE => MAPI_BCC))))); $recipienttable = mapi_message_getrecipienttable($message); $resourceRecipients = mapi_table_queryallrows($recipienttable, $this->recipprops, $getResourcesRestriction); $this->errorSetResource = false; $resourceRecipData = array(); // Put appointment into store resource users $i = 0; $len = count($resourceRecipients); while (!$this->errorSetResource && $i < $len) { $request = array(array(PR_DISPLAY_NAME => $resourceRecipients[$i][PR_DISPLAY_NAME])); $ab = mapi_openaddressbook($this->session); $ret = mapi_ab_resolvename($ab, $request, EMS_AB_ADDRESS_LOOKUP); $result = mapi_last_hresult(); if ($result == NOERROR) { $result = $ret[0][PR_ENTRYID]; } $resourceUsername = $ret[0][PR_EMAIL_ADDRESS]; $resourceABEntryID = $ret[0][PR_ENTRYID]; // Get StoreEntryID by username $user_entryid = mapi_msgstore_createentryid($this->store, $resourceUsername); // Open store of the user $userStore = mapi_openmsgstore($this->session, $user_entryid); // Open root folder $userRoot = mapi_msgstore_openentry($userStore, null); // Get calendar entryID $userRootProps = mapi_getprops($userRoot, array(PR_STORE_ENTRYID, PR_IPM_APPOINTMENT_ENTRYID, PR_FREEBUSY_ENTRYIDS)); // Open Calendar folder [check hresult==0] $accessToFolder = false; try { $calFolder = mapi_msgstore_openentry($userStore, $userRootProps[PR_IPM_APPOINTMENT_ENTRYID]); if ($calFolder) { $calFolderProps = mapi_getProps($calFolder, array(PR_ACCESS)); if (($calFolderProps[PR_ACCESS] & MAPI_ACCESS_CREATE_CONTENTS) !== 0) { $accessToFolder = true; } } } catch (MAPIException $e) { $e->setHandled(); $this->errorSetResource = 1; // No access } if ($accessToFolder) { /** * Get the LocalFreebusy message that contains the properties that * are set to accept or decline resource meeting requests */ // Use PR_FREEBUSY_ENTRYIDS[1] to open folder the LocalFreeBusy msg $localFreebusyMsg = mapi_msgstore_openentry($userStore, $userRootProps[PR_FREEBUSY_ENTRYIDS][1]); if ($localFreebusyMsg) { $props = mapi_getprops($localFreebusyMsg, array(PR_PROCESS_MEETING_REQUESTS, PR_DECLINE_RECURRING_MEETING_REQUESTS, PR_DECLINE_CONFLICTING_MEETING_REQUESTS)); $acceptMeetingRequests = $props[PR_PROCESS_MEETING_REQUESTS] ? 1 : 0; $declineRecurringMeetingRequests = $props[PR_DECLINE_RECURRING_MEETING_REQUESTS] ? 1 : 0; $declineConflictingMeetingRequests = $props[PR_DECLINE_CONFLICTING_MEETING_REQUESTS] ? 1 : 0; if (!$acceptMeetingRequests) { /** * When a resource has not been set to automatically accept meeting requests, * the meeting request has to be sent to him rather than being put directly into * his calendar. No error should be returned. */ //$errorSetResource = 2; $this->nonAcceptingResources[] = $resourceRecipients[$i]; } else { if ($declineRecurringMeetingRequests && !$cancel) { // Check if appointment is recurring if ($messageprops[$this->proptags['recurring']]) { $this->errorSetResource = 3; } } if ($declineConflictingMeetingRequests && !$cancel) { // Check for conflicting items $conflicting = false; // Open the calendar $calFolder = mapi_msgstore_openentry($userStore, $userRootProps[PR_IPM_APPOINTMENT_ENTRYID]); if ($calFolder) { if ($this->isMeetingConflicting($message, $userStore, $calFolder, $messageprops)) { $conflicting = true; } } else { $this->errorSetResource = 1; // No access } if ($conflicting) { $this->errorSetResource = 4; // Conflict } } } } } if (!$this->errorSetResource && $accessToFolder) { /** * First search on GlobalID(0x3) * If (recurring and occurrence) If Resource was booked for only this occurrence then Resource should have only this occurrence in Calendar and not whole series. * If (normal meeting) then GlobalID(0x3) and CleanGlobalID(0x23) are same, so doesnt matter if search is based on GlobalID. */ $rows = $this->findCalendarItems($messageprops[$this->proptags['goid']], $calFolder); /** * If no entry is found then * 1) Resource doesnt have meeting in Calendar. Seriously!! * OR * 2) We were looking for occurrence item but Resource has whole series */ if (empty($rows)) { /** * Now search on CleanGlobalID(0x23) WHY??? * Because we are looking recurring item * * Possible results of this search * 1) If Resource was booked for more than one occurrences then this search will return all those occurrence because search is perform on CleanGlobalID * 2) If Resource was booked for whole series then it should return series. */ $rows = $this->findCalendarItems($messageprops[$this->proptags['goid2']], $calFolder, true); $newResourceMsg = false; if (!empty($rows)) { // Since we are looking for recurring item, open every result and check for 'recurring' property. foreach ($rows as $row) { $ResourceMsg = mapi_msgstore_openentry($userStore, $row); $ResourceMsgProps = mapi_getprops($ResourceMsg, array($this->proptags['recurring'])); if (isset($ResourceMsgProps[$this->proptags['recurring']]) && $ResourceMsgProps[$this->proptags['recurring']]) { $newResourceMsg = $ResourceMsg; break; } } } // Still no results found. I giveup, create new message. if (!$newResourceMsg) { $newResourceMsg = mapi_folder_createmessage($calFolder); } } else { $newResourceMsg = mapi_msgstore_openentry($userStore, $rows[0]); } // Prefix the subject if needed if ($prefix && isset($messageprops[PR_SUBJECT])) { $messageprops[PR_SUBJECT] = $prefix . $messageprops[PR_SUBJECT]; } // Set status to cancelled if needed $messageprops[$this->proptags['busystatus']] = fbBusy; // The default status (Busy) if ($cancel) { $messageprops[$this->proptags['meetingstatus']] = olMeetingCanceled; // The meeting has been canceled $messageprops[$this->proptags['busystatus']] = fbFree; // Free } else { $messageprops[$this->proptags['meetingstatus']] = olMeetingReceived; // The recipient is receiving the request } $messageprops[$this->proptags['responsestatus']] = olResponseAccepted; // The resource autmatically accepts the appointment $messageprops[PR_MESSAGE_CLASS] = "IPM.Appointment"; // Remove the PR_ICON_INDEX as it is not needed in the sent message and it also // confuses the Zarafa webaccess $messageprops[PR_ICON_INDEX] = null; $messageprops[PR_RESPONSE_REQUESTED] = true; $addrinfo = $this->getOwnerAddress($this->store); if ($addrinfo) { list($ownername, $owneremailaddr, $owneraddrtype, $ownerentryid, $ownersearchkey) = $addrinfo; $messageprops[PR_SENT_REPRESENTING_EMAIL_ADDRESS] = $owneremailaddr; $messageprops[PR_SENT_REPRESENTING_NAME] = $ownername; $messageprops[PR_SENT_REPRESENTING_ADDRTYPE] = $owneraddrtype; $messageprops[PR_SENT_REPRESENTING_ENTRYID] = $ownerentryid; $messageprops[PR_SENT_REPRESENTING_SEARCH_KEY] = $ownersearchkey; $messageprops[$this->proptags['apptreplyname']] = $ownername; $messageprops[$this->proptags['replytime']] = time(); } if ($basedate && isset($ResourceMsgProps[$this->proptags['recurring']]) && $ResourceMsgProps[$this->proptags['recurring']]) { $recurr = new Recurrence($userStore, $newResourceMsg); // Copy recipients list $reciptable = mapi_message_getrecipienttable($message); $recips = mapi_table_queryallrows($reciptable, $this->recipprops); // add owner to recipient table $this->addOrganizer($messageprops, $recips, true); // Update occurrence if ($recurr->isException($basedate)) { $recurr->modifyException($messageprops, $basedate, $recips); } else { $recurr->createException($messageprops, $basedate, false, $recips); } } else { mapi_setprops($newResourceMsg, $messageprops); // Copy attachments $this->replaceAttachments($message, $newResourceMsg); // Copy all recipients too $this->replaceRecipients($message, $newResourceMsg); // Now add organizer also to recipient table $recips = array(); $this->addOrganizer($messageprops, $recips); mapi_message_modifyrecipients($newResourceMsg, MODRECIP_ADD, $recips); } mapi_savechanges($newResourceMsg); $resourceRecipData[] = array('store' => $userStore, 'folder' => $calFolder, 'msg' => $newResourceMsg); $this->includesResources = true; } else { /** * If no other errors occured and you have no access to the * folder of the resource, throw an error=1. */ if (!$this->errorSetResource) { $this->errorSetResource = 1; } for ($j = 0, $len = count($resourceRecipData); $j < $len; $j++) { // Get the EntryID $props = mapi_message_getprops($resourceRecipData[$j]['msg']); mapi_folder_deletemessages($resourceRecipData[$j]['folder'], array($props[PR_ENTRYID]), DELETE_HARD_DELETE); } $this->recipientDisplayname = $resourceRecipients[$i][PR_DISPLAY_NAME]; } $i++; } /************************************************************** * Set the BCC-recipients (resources) tackstatus to accepted. */ // Get resource recipients $getResourcesRestriction = array(RES_AND, array(array(RES_PROPERTY, array(RELOP => RELOP_EQ, ULPROPTAG => PR_RECIPIENT_TYPE, VALUE => array(PR_RECIPIENT_TYPE => MAPI_BCC))))); $recipienttable = mapi_message_getrecipienttable($message); $resourceRecipients = mapi_table_queryallrows($recipienttable, $this->recipprops, $getResourcesRestriction); if (!empty($resourceRecipients)) { // Set Tracking status of resource recipients to olResponseAccepted (3) for ($i = 0, $len = count($resourceRecipients); $i < $len; $i++) { $resourceRecipients[$i][PR_RECIPIENT_TRACKSTATUS] = olRecipientTrackStatusAccepted; $resourceRecipients[$i][PR_RECIPIENT_TRACKSTATUS_TIME] = time(); } mapi_message_modifyrecipients($message, MODRECIP_MODIFY, $resourceRecipients); } // Publish updated free/busy information if (!$this->errorSetResource) { for ($i = 0, $len = count($resourceRecipData); $i < $len; $i++) { $storeProps = mapi_msgstore_getprops($resourceRecipData[$i]['store'], array(PR_MAILBOX_OWNER_ENTRYID)); if (isset($storeProps[PR_MAILBOX_OWNER_ENTRYID])) { $pub = new FreeBusyPublish($this->session, $resourceRecipData[$i]['store'], $resourceRecipData[$i]['folder'], $storeProps[PR_MAILBOX_OWNER_ENTRYID]); $pub->publishFB(time() - 7 * 24 * 60 * 60, 6 * 30 * 24 * 60 * 60); // publish from one week ago, 6 months ahead } } } return $resourceRecipData; }
function listfolders_getlist($adminStore, $session, $user) { global $supported_classes; if (strtoupper($user) == 'SYSTEM') { // Find the public store store $storestables = @mapi_getmsgstorestable($session); $result = @mapi_last_hresult(); if ($result == NOERROR) { $rows = @mapi_table_queryallrows($storestables, array(PR_ENTRYID, PR_MDB_PROVIDER)); foreach ($rows as $row) { if (isset($row[PR_MDB_PROVIDER]) && $row[PR_MDB_PROVIDER] == ZARAFA_STORE_PUBLIC_GUID) { if (!isset($row[PR_ENTRYID])) { echo "Public folder are not available.\nIf this is a multi-tenancy system, use -u and -p and login with an admin user of the company.\nThe script will exit.\n"; exit(1); } $entryid = $row[PR_ENTRYID]; break; } } } } else { $entryid = @mapi_msgstore_createentryid($adminStore, $user); } $userStore = @mapi_openmsgstore($session, $entryid); $hresult = mapi_last_hresult(); // Cache the store for later use if ($hresult != NOERROR) { echo "Could not open store for '{$user}'. The script will exit.\n"; exit(1); } $folder = @mapi_msgstore_openentry($userStore); $h_table = @mapi_folder_gethierarchytable($folder, CONVENIENT_DEPTH); $subfolders = @mapi_table_queryallrows($h_table, array(PR_ENTRYID, PR_DISPLAY_NAME, PR_CONTAINER_CLASS, PR_SOURCE_KEY)); echo "Available folders in store '{$user}':\n" . str_repeat("-", 50) . "\n"; foreach ($subfolders as $folder) { if (isset($folder[PR_CONTAINER_CLASS]) && array_key_exists($folder[PR_CONTAINER_CLASS], $supported_classes)) { echo "Folder name:\t" . $folder[PR_DISPLAY_NAME] . "\n"; echo "Folder ID:\t" . bin2hex($folder[PR_SOURCE_KEY]) . "\n"; echo "Type:\t\t" . $supported_classes[$folder[PR_CONTAINER_CLASS]] . "\n"; echo "\n"; } } }
/** * Get MAPI addressbook object * * @access private * @return MAPIAddressbook object to be used with mapi_ab_* or false on failure */ private function getAddressbook() { if (isset($this->addressbook) && $this->addressbook) { return $this->addressbook; } $this->addressbook = mapi_openaddressbook($this->session); $result = mapi_last_hresult(); if ($result && $this->addressbook === false) { ZLog::Write(LOGLEVEL_ERROR, sprintf("MAPIProvider->getAddressbook error opening addressbook 0x%X", $result)); return false; } return $this->addressbook; }
/** * Reads data of large properties from a stream. * * @param MAPIMessage $message * @param long $prop * * @access private * @return string */ private function readPropStream($message, $prop) { $stream = mapi_openproperty($message, $prop, IID_IStream, 0, 0); $ret = mapi_last_hresult(); if ($ret == MAPI_E_NOT_FOUND) { $this->Log(sprintf("Kopano>readPropStream: property 0x%s not found. It is either empty or not set. It will be ignored.", str_pad(dechex($prop), 8, 0, STR_PAD_LEFT))); return ""; } elseif ($ret) { $this->Log("Kopano->readPropStream error opening stream: 0x%08X", $ret); return ""; } $data = ""; $string = ""; while (1) { $data = mapi_stream_read($stream, 1024); if (strlen($data) == 0) { break; } $string .= $data; } return $string; }