コード例 #1
0
ファイル: mapi.util.php プロジェクト: tuksik/zarafa-rest-api
/**
 * 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];
}
コード例 #2
0
ファイル: server.php プロジェクト: RobertWang/sabre-zarafa
function checkMapiError($msg)
{
    global $log;
    if (mapi_last_hresult() != 0) {
        $log->warn("MAPI error {$msg}: " . get_mapi_error_name());
        exit;
    }
}
コード例 #3
0
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";
    }
}
コード例 #4
0
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;
}
コード例 #5
0
 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);
     }
 }
コード例 #6
0
 /**
  * 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;
 }
コード例 #7
0
 /**
  * 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;
 }
コード例 #8
0
ファイル: mapiutils.php プロジェクト: SvKn/Z-Push-contrib
 /**
  * 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;
 }
コード例 #9
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);
    }
}
コード例 #10
0
ファイル: spam.php プロジェクト: marco-uniware/zarafa-tools
    $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";
}
?>

コード例 #11
0
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));
コード例 #12
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");
     }
 }
コード例 #13
0
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;
}
コード例 #14
0
ファイル: listfolders.php プロジェクト: EGroupware/z-push
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";
        }
    }
}
コード例 #15
0
ファイル: ics.php プロジェクト: nnaannoo/paskot
 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;
     }
 }
コード例 #16
0
 // 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();
コード例 #17
0
 /**
  * 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;
 }
コード例 #18
0
ファイル: delete.php プロジェクト: marco-uniware/zarafa-tools
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";
}
?>

コード例 #19
0
ファイル: importer.php プロジェクト: netconstructor/sogosync
 /**
  * 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;
 }
コード例 #20
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()));
         }
     }
 }
コード例 #21
0
 /**
  * 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;
 }
コード例 #22
0
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";
        }
    }
}
コード例 #23
0
 /**
  * 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;
 }
コード例 #24
0
ファイル: kopano.php プロジェクト: EGroupware/z-push
 /**
  * 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;
 }