Back to index

d-push  2.0
Public Member Functions | Public Attributes
BackendICS Class Reference

DEPRECATED legacy class. More...

Inheritance diagram for BackendICS:
Inheritance graph
[legend]
Collaboration diagram for BackendICS:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 BackendZarafa ()
 Constructor of the Zarafa Backend.
 GetStateMachine ()
 Indicates which StateMachine should be used.
 GetSearchProvider ()
 Returns the ZarafaBackend as it implements the ISearchProvider interface This could be overwritten by the global configuration.
 GetSupportedASVersion ()
 Indicates which AS version is supported by the backend.
 Logon ($user, $domain, $pass)
 Authenticates the user with the configured Zarafa server.
 Setup ($store, $checkACLonly=false, $folderid=false)
 Setup the backend to work on a specific store or checks ACLs there.
 Logoff ()
 Logs off Free/Busy information is updated for modified calendars This is done after the synchronization process is completed.
 GetHierarchy ()
 Returns an array of SyncFolder types with the entire folder hierarchy on the server (the array itself is flat, but refers to parents via the 'parent' property.
 GetImporter ($folderid=false)
 Returns the importer to process changes from the mobile If no $folderid is given, hierarchy importer is expected.
 GetExporter ($folderid=false)
 Returns the exporter to send changes to the mobile If no $folderid is given, hierarchy exporter is expected.
 SendMail ($sm)
 Sends an e-mail This messages needs to be saved into the 'sent items' folder.
 Fetch ($folderid, $id, $contentparameters)
 Returns all available data of a single message.
 GetWasteBasket ()
 Returns the waste basket.
 GetAttachmentData ($attname)
 Returns the content of the named attachment as stream.
 EmptyFolder ($folderid, $includeSubfolders=true)
 Deletes all contents of the specified folder.
 MeetingResponse ($requestid, $folderid, $response)
 Processes a response to a meeting request.
 HasChangesSink ()
 Indicates if the backend has a ChangesSink.
 ChangesSinkInitialize ($folderid)
 The folder should be considered by the sink.
 ChangesSink ($timeout=30)
 The actual ChangesSink.
 Settings ($settings)
 Applies settings to and gets informations from the device.
 SupportsType ($searchtype)
 
Implementation of the ISearchProvider interface
 GetGALSearchResults ($searchquery, $searchrange)
 Searches the GAB of Zarafa Can be overwitten globally by configuring a SearchBackend.
 GetMailboxSearchResults ($cpo)
 Searches for the emails on the server.
 TerminateSearch ($pid)
 Terminates a search for a given PID.
 Disconnect ()
 Disconnects from the current search provider.
 GetMAPIStoreForFolderId ($store, $folderid)
 Returns the MAPI store ressource for a folderid This is not part of IBackend but necessary for the ImportChangesICS->MoveMessage() operation if the destination folder is not in the default store Note: The current backend store might be changed as IBackend->Setup() is executed.

Public Attributes

const SEARCH_GAL = "GAL"
const SEARCH_MAILBOX = "MAILBOX"
const SEARCH_DOCUMENTLIBRARY = "DOCUMENTLIBRARY"

Detailed Description

DEPRECATED legacy class.

Definition at line 1705 of file zarafa.php.


Member Function Documentation

Constructor of the Zarafa Backend.

public

Definition at line 95 of file zarafa.php.

                                    {
        $this->session = false;
        $this->store = false;
        $this->storeName = false;
        $this->storeCache = array();
        $this->importedFolders = array();
        $this->notifications = false;
        $this->changesSink = false;
        $this->changesSinkFolders = array();
        $this->changesSinkStores = array();
        $this->wastebasket = false;

        ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendZarafa using PHP-MAPI version: %s", phpversion("mapi")));
    }

Here is the call graph for this function:

BackendZarafa::ChangesSink ( timeout = 30) [inherited]

The actual ChangesSink.

For max. the $timeout value this method should block and if no changes are available return an empty array. If changes are available a list of folderids is expected.

Parameters:
int$timeoutmax. amount of seconds to block

public

Returns:
array

Implements IBackend.

Definition at line 952 of file zarafa.php.

                                               {
        $notifications = array();
        $sinkresult = @mapi_sink_timedwait($this->changesSink, $timeout * 1000);
        foreach ($sinkresult as $sinknotif) {
            // check if something in the monitored folders changed
            if (isset($sinknotif['parentid']) && array_key_exists($sinknotif['parentid'], $this->changesSinkFolders)) {
                $notifications[] = $this->changesSinkFolders[$sinknotif['parentid']];
            }
            // deletes and moves
            if (isset($sinknotif['oldparentid']) && array_key_exists($sinknotif['oldparentid'], $this->changesSinkFolders)) {
                $notifications[] = $this->changesSinkFolders[$sinknotif['oldparentid']];
            }
        }
        return $notifications;
    }
BackendZarafa::ChangesSinkInitialize ( folderid) [inherited]

The folder should be considered by the sink.

Folders which were not initialized should not result in a notification of IBackend->ChangesSink().

Parameters:
string$folderidpublic
Returns:
boolean false if entryid can not be found for that folder

Implements IBackend.

Definition at line 922 of file zarafa.php.

                                                     {
        ZLog::Write(LOGLEVEL_DEBUG, sprintf("ZarafaBackend->ChangesSinkInitialize(): folderid '%s'", $folderid));

        $entryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($folderid));
        if (!$entryid)
            return false;

        // add entryid to the monitored folders
        $this->changesSinkFolders[$entryid] = $folderid;

        // check if this store is already monitored, else advise it
        if (!in_array($this->store, $this->changesSinkStores)) {
            mapi_msgstore_advise($this->store, null, fnevObjectModified | fnevObjectCreated | fnevObjectMoved | fnevObjectDeleted, $this->changesSink);
            $this->changesSinkStores[] = $this->store;
            ZLog::Write(LOGLEVEL_DEBUG, sprintf("ZarafaBackend->ChangesSinkInitialize(): advised store '%s'", $this->store));
        }
        return true;
    }

Here is the call graph for this function:

BackendZarafa::Disconnect ( ) [inherited]

Disconnects from the current search provider.

public

Returns:
boolean

Implements ISearchProvider.

Definition at line 1203 of file zarafa.php.

                                 {
        return true;
    }
BackendZarafa::EmptyFolder ( folderid,
includeSubfolders = true 
) [inherited]

Deletes all contents of the specified folder.

This is generally used to empty the trash (wastebasked), but could also be used on any other folder.

Parameters:
string$folderid
boolean$includeSubfolders(opt) also delete sub folders, default true

public

Returns:
boolean
Exceptions:
StatusException

Implements IBackend.

Definition at line 778 of file zarafa.php.

                                                                      {
        $folderentryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($folderid));
        if (!$folderentryid)
            throw new StatusException(sprintf("BackendZarafa->EmptyFolder('%s','%s'): Error, unable to open folder (no entry id)", $folderid, Utils::PrintAsString($includeSubfolders)), SYNC_ITEMOPERATIONSSTATUS_SERVERERROR);
        $folder = mapi_msgstore_openentry($this->store, $folderentryid);

        if (!$folder)
            throw new StatusException(sprintf("BackendZarafa->EmptyFolder('%s','%s'): Error, unable to open parent folder (open entry)", $folderid, Utils::PrintAsString($includeSubfolders)), SYNC_ITEMOPERATIONSSTATUS_SERVERERROR);

        $flags = 0;
        if ($includeSubfolders)
            $flags = DEL_ASSOCIATED;

        ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendZarafa->EmptyFolder('%s','%s'): emptying folder",$folderid, Utils::PrintAsString($includeSubfolders)));

        // empty folder!
        mapi_folder_emptyfolder($folder, $flags);
        if (mapi_last_hresult())
            throw new StatusException(sprintf("BackendZarafa->EmptyFolder('%s','%s'): Error, mapi_folder_emptyfolder() failed: 0x%X", $folderid, Utils::PrintAsString($includeSubfolders), mapi_last_hresult()), SYNC_ITEMOPERATIONSSTATUS_SERVERERROR);

        return true;
    }

Here is the call graph for this function:

BackendZarafa::Fetch ( folderid,
id,
contentparameters 
) [inherited]

Returns all available data of a single message.

Parameters:
string$folderid
string$id
ContentParameters$contentparametersflag

public

Returns:
object(SyncObject)
Exceptions:
StatusException

Implements IBackend.

Definition at line 680 of file zarafa.php.

                                                              {
        // get the entry id of the message
        $entryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($folderid), hex2bin($id));
        if(!$entryid)
            throw new StatusException(sprintf("BackendZarafa->Fetch('%s','%s'): Error getting entryid: 0x%X", $folderid, $id, mapi_last_hresult()), SYNC_STATUS_OBJECTNOTFOUND);

        // open the message
        $message = mapi_msgstore_openentry($this->store, $entryid);
        if(!$message)
            throw new StatusException(sprintf("BackendZarafa->Fetch('%s','%s'): Error, unable to open message: 0x%X", $folderid, $id, mapi_last_hresult()), SYNC_STATUS_OBJECTNOTFOUND);

        // convert the mapi message into a SyncObject and return it
        $mapiprovider = new MAPIProvider($this->session, $this->store);

        // override truncation
        $contentparameters->SetTruncation(SYNC_TRUNCATION_ALL);
        // TODO check for body preferences
        return $mapiprovider->GetMessage($message, $contentparameters);
    }
BackendZarafa::GetAttachmentData ( attname) [inherited]

Returns the content of the named attachment as stream.

Parameters:
string$attnamepublic
Returns:
SyncItemOperationsAttachment
Exceptions:
StatusException

Implements IBackend.

Definition at line 732 of file zarafa.php.

                                                {
        ZLog::Write(LOGLEVEL_DEBUG, sprintf("ZarafaBackend->GetAttachmentData('%s')", $attname));
        list($id, $attachnum) = explode(":", $attname);

        if(!isset($id) || !isset($attachnum))
            throw new StatusException(sprintf("ZarafaBackend->GetAttachmentData('%s'): Error, attachment requested for non-existing item", $attname), SYNC_ITEMOPERATIONSSTATUS_INVALIDATT);

        $entryid = hex2bin($id);
        $message = mapi_msgstore_openentry($this->store, $entryid);
        if(!$message)
            throw new StatusException(sprintf("ZarafaBackend->GetAttachmentData('%s'): Error, unable to open item for attachment data for id '%s' with: 0x%X", $attname, $id, mapi_last_hresult()), SYNC_ITEMOPERATIONSSTATUS_INVALIDATT);

        $attach = mapi_message_openattach($message, $attachnum);
        if(!$attach)
            throw new StatusException(sprintf("ZarafaBackend->GetAttachmentData('%s'): Error, unable to open attachment number '%s' with: 0x%X", $attname, $attachnum, mapi_last_hresult()), SYNC_ITEMOPERATIONSSTATUS_INVALIDATT);

        $stream = mapi_openpropertytostream($attach, PR_ATTACH_DATA_BIN);
        if(!$stream)
            throw new StatusException(sprintf("ZarafaBackend->GetAttachmentData('%s'): Error, unable to open attachment data stream: 0x%X", $attname, mapi_last_hresult()), SYNC_ITEMOPERATIONSSTATUS_INVALIDATT);

        //get the mime type of the attachment
        $contenttype = mapi_getprops($attach, array(PR_ATTACH_MIME_TAG, PR_ATTACH_MIME_TAG_W));
        $attachment = new SyncItemOperationsAttachment();
        // put the mapi stream into a wrapper to get a standard stream
        $attachment->data = MapiStreamWrapper::Open($stream);
        if (isset($contenttype[PR_ATTACH_MIME_TAG]))
            $attachment->contenttype = $contenttype[PR_ATTACH_MIME_TAG];
        elseif (isset($contenttype[PR_ATTACH_MIME_TAG_W]))
            $attachment->contenttype = $contenttype[PR_ATTACH_MIME_TAG_W];
            //TODO default contenttype
        return $attachment;
    }

Here is the call graph for this function:

BackendZarafa::GetExporter ( folderid = false) [inherited]

Returns the exporter to send changes to the mobile If no $folderid is given, hierarchy exporter is expected.

Parameters:
string$folderid(opt)

public

Returns:
object(ExportChanges)
Exceptions:
StatusException

Implements IBackend.

Definition at line 375 of file zarafa.php.

                                                   {
        if($folderid !== false) {
            // check if the user of the current store has permissions to export from this folderid
            if ($this->storeName != $this->mainUser && !$this->hasSecretaryACLs($this->store, $folderid)) {
                ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendZarafa->GetExporter(): missing permissions on folderid: '%s'.", Utils::PrintAsString($folderid)));
                return false;
            }
            return new ExportChangesICS($this->session, $this->store, hex2bin($folderid));
        }
        else
            return new ExportChangesICS($this->session, $this->store);
    }

Here is the call graph for this function:

BackendZarafa::GetGALSearchResults ( searchquery,
searchrange 
) [inherited]

Searches the GAB of Zarafa Can be overwitten globally by configuring a SearchBackend.

Parameters:
string$searchquery
string$searchrangepublic
Returns:
array
Exceptions:
StatusException

Implements ISearchProvider.

Definition at line 1017 of file zarafa.php.

                                                                   {
        // only return users from who the displayName or the username starts with $name
        //TODO: use PR_ANR for this restriction instead of PR_DISPLAY_NAME and PR_ACCOUNT
        $addrbook = mapi_openaddressbook($this->session);
        if ($addrbook)
            $ab_entryid = mapi_ab_getdefaultdir($addrbook);
        if ($ab_entryid)
            $ab_dir = mapi_ab_openentry($addrbook, $ab_entryid);
        if ($ab_dir)
            $table = mapi_folder_getcontentstable($ab_dir);

        if (!$table)
            throw new StatusException(sprintf("ZarafaBackend->GetGALSearchResults(): could not open addressbook: 0x%X", mapi_last_hresult()), SYNC_SEARCHSTATUS_STORE_CONNECTIONFAILED);

        $restriction = MAPIUtils::GetSearchRestriction(u2w($searchquery));
        mapi_table_restrict($table, $restriction);
        mapi_table_sort($table, array(PR_DISPLAY_NAME => TABLE_SORT_ASCEND));

        if (mapi_last_hresult())
            throw new StatusException(sprintf("ZarafaBackend->GetGALSearchResults(): could not apply restriction: 0x%X", mapi_last_hresult()), SYNC_SEARCHSTATUS_STORE_TOOCOMPLEX);

        //range for the search results, default symbian range end is 50, wm 99,
        //so we'll use that of nokia
        $rangestart = 0;
        $rangeend = 50;

        if ($searchrange != '0') {
            $pos = strpos($searchrange, '-');
            $rangestart = substr($searchrange, 0, $pos);
            $rangeend = substr($searchrange, ($pos + 1));
        }
        $items = array();

        $querycnt = mapi_table_getrowcount($table);
        //do not return more results as requested in range
        $querylimit = (($rangeend + 1) < $querycnt) ? ($rangeend + 1) : $querycnt;
        $items['range'] = ($querylimit > 0) ? $rangestart.'-'.($querylimit - 1) : '0-0';
        $items['searchtotal'] = $querycnt;
        if ($querycnt > 0)
            $abentries = mapi_table_queryrows($table, array(PR_ACCOUNT, PR_DISPLAY_NAME, PR_SMTP_ADDRESS, PR_BUSINESS_TELEPHONE_NUMBER, PR_GIVEN_NAME, PR_SURNAME, PR_MOBILE_TELEPHONE_NUMBER, PR_HOME_TELEPHONE_NUMBER, PR_TITLE, PR_COMPANY_NAME, PR_OFFICE_LOCATION), $rangestart, $querylimit);

        for ($i = 0; $i < $querylimit; $i++) {
            $items[$i][SYNC_GAL_DISPLAYNAME] = w2u($abentries[$i][PR_DISPLAY_NAME]);

            if (strlen(trim($items[$i][SYNC_GAL_DISPLAYNAME])) == 0)
                $items[$i][SYNC_GAL_DISPLAYNAME] = w2u($abentries[$i][PR_ACCOUNT]);

            $items[$i][SYNC_GAL_ALIAS] = w2u($abentries[$i][PR_ACCOUNT]);
            //it's not possible not get first and last name of an user
            //from the gab and user functions, so we just set lastname
            //to displayname and leave firstname unset
            //this was changed in Zarafa 6.40, so we try to get first and
            //last name and fall back to the old behaviour if these values are not set
            if (isset($abentries[$i][PR_GIVEN_NAME]))
                $items[$i][SYNC_GAL_FIRSTNAME] = w2u($abentries[$i][PR_GIVEN_NAME]);
            if (isset($abentries[$i][PR_SURNAME]))
                $items[$i][SYNC_GAL_LASTNAME] = w2u($abentries[$i][PR_SURNAME]);

            if (!isset($items[$i][SYNC_GAL_LASTNAME])) $items[$i][SYNC_GAL_LASTNAME] = $items[$i][SYNC_GAL_DISPLAYNAME];

            $items[$i][SYNC_GAL_EMAILADDRESS] = w2u($abentries[$i][PR_SMTP_ADDRESS]);
            //check if an user has an office number or it might produce warnings in the log
            if (isset($abentries[$i][PR_BUSINESS_TELEPHONE_NUMBER]))
                $items[$i][SYNC_GAL_PHONE] = w2u($abentries[$i][PR_BUSINESS_TELEPHONE_NUMBER]);
            //check if an user has a mobile number or it might produce warnings in the log
            if (isset($abentries[$i][PR_MOBILE_TELEPHONE_NUMBER]))
                $items[$i][SYNC_GAL_MOBILEPHONE] = w2u($abentries[$i][PR_MOBILE_TELEPHONE_NUMBER]);
            //check if an user has a home number or it might produce warnings in the log
            if (isset($abentries[$i][PR_HOME_TELEPHONE_NUMBER]))
                $items[$i][SYNC_GAL_HOMEPHONE] = w2u($abentries[$i][PR_HOME_TELEPHONE_NUMBER]);

            if (isset($abentries[$i][PR_COMPANY_NAME]))
                $items[$i][SYNC_GAL_COMPANY] = w2u($abentries[$i][PR_COMPANY_NAME]);

            if (isset($abentries[$i][PR_TITLE]))
                $items[$i][SYNC_GAL_TITLE] = w2u($abentries[$i][PR_TITLE]);

            if (isset($abentries[$i][PR_OFFICE_LOCATION]))
                $items[$i][SYNC_GAL_OFFICE] = w2u($abentries[$i][PR_OFFICE_LOCATION]);
        }
        return $items;
    }

Here is the call graph for this function:

BackendZarafa::GetHierarchy ( ) [inherited]

Returns an array of SyncFolder types with the entire folder hierarchy on the server (the array itself is flat, but refers to parents via the 'parent' property.

provides AS 1.0 compatibility

public

Returns:
array SYNC_FOLDER

Implements IBackend.

Definition at line 318 of file zarafa.php.

                                   {
        $folders = array();
        $importer = false;
        $mapiprovider = new MAPIProvider($this->session, $this->store);

        $rootfolder = mapi_msgstore_openentry($this->store);
        $rootfolderprops = mapi_getprops($rootfolder, array(PR_SOURCE_KEY));
        $rootfoldersourcekey = bin2hex($rootfolderprops[PR_SOURCE_KEY]);

        $hierarchy =  mapi_folder_gethierarchytable($rootfolder, CONVENIENT_DEPTH);
        $rows = mapi_table_queryallrows($hierarchy, array(PR_ENTRYID));

        foreach ($rows as $row) {
            $mapifolder = mapi_msgstore_openentry($this->store, $row[PR_ENTRYID]);
            $folder = $mapiprovider->GetFolder($mapifolder);

            if (isset($folder->parentid) && $folder->parentid != $rootfoldersourcekey)
                $folders[] = $folder;
        }

        return $folders;
    }
BackendZarafa::GetImporter ( folderid = false) [inherited]

Returns the importer to process changes from the mobile If no $folderid is given, hierarchy importer is expected.

Parameters:
string$folderid(opt)

public

Returns:
object(ImportChanges)

Implements IBackend.

Definition at line 350 of file zarafa.php.

                                                   {
        ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendZarafa->GetImporter() folderid: '%s'", Utils::PrintAsString($folderid)));
        if($folderid !== false) {
            // check if the user of the current store has permissions to import to this folderid
            if ($this->storeName != $this->mainUser && !$this->hasSecretaryACLs($this->store, $folderid)) {
                ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendZarafa->GetImporter(): missing permissions on folderid: '%s'.", Utils::PrintAsString($folderid)));
                return false;
            }
            $this->importedFolders[$folderid] = $this->store;
            return new ImportChangesICS($this->session, $this->store, hex2bin($folderid));
        }
        else
            return new ImportChangesICS($this->session, $this->store);
    }

Here is the call graph for this function:

Searches for the emails on the server.

Parameters:
ContentParameter$cpo
Returns:
array

Implements ISearchProvider.

Definition at line 1107 of file zarafa.php.

                                                  {
        $searchFolder = $this->getSearchFolder();
        $searchRestriction = $this->getSearchRestriction($cpo);
        $searchRange = explode('-', $cpo->GetSearchRange());
        $searchFolderId = $cpo->GetSearchFolderid();
        $searchFolders = array();
        // search only in required folders
        if (!empty($searchFolderId)) {
            $searchFolderEntryId = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($searchFolderId));
            $searchFolders[] = $searchFolderEntryId;
        }
        // if no folder was required then search in the entire store
        else {
            $tmp = mapi_getprops($this->store, array(PR_ENTRYID,PR_DISPLAY_NAME,PR_IPM_SUBTREE_ENTRYID));
            $searchFolders[] = $tmp[PR_IPM_SUBTREE_ENTRYID];
        }
        $items = array();
        $flags = 0;
        // if subfolders are required, do a recursive search
        if ($cpo->GetSearchDeepTraversal()) {
            $flags |= SEARCH_RECURSIVE;
        }

        mapi_folder_setsearchcriteria($searchFolder, $searchRestriction, $searchFolders, $flags);

        $table = mapi_folder_getcontentstable($searchFolder);
        $searchStart = time();
        // do the search and wait for all the results available
        while (time() - $searchStart < SEARCH_WAIT) {
            $searchcriteria = mapi_folder_getsearchcriteria($searchFolder);
            if(($searchcriteria["searchstate"] & SEARCH_REBUILD) == 0)
                break; // Search is done
            sleep(1);
        }

        // if the search range is set limit the result to it, otherwise return all found messages
        $rows = (is_array($searchRange) && isset($searchRange[0]) && isset($searchRange[1])) ?
            mapi_table_queryrows($table, array(PR_SOURCE_KEY, PR_PARENT_SOURCE_KEY), $searchRange[0], $searchRange[1] - $searchRange[0] + 1) :
            mapi_table_queryrows($table, array(PR_SOURCE_KEY, PR_PARENT_SOURCE_KEY), 0, SEARCH_MAXRESULTS);

        $cnt = count($rows);
        $items['searchtotal'] = $cnt;
        $items["range"] = $cpo->GetSearchRange();
        for ($i = 0; $i < $cnt; $i++) {
            $items[$i]['class'] = 'Email';
            $items[$i]['longid'] = bin2hex($rows[$i][PR_PARENT_SOURCE_KEY]) . ":" . bin2hex($rows[$i][PR_SOURCE_KEY]);
            $items[$i]['folderid'] = bin2hex($rows[$i][PR_PARENT_SOURCE_KEY]);
        }
        return $items;
    }

Here is the call graph for this function:

BackendZarafa::GetMAPIStoreForFolderId ( store,
folderid 
) [inherited]

Returns the MAPI store ressource for a folderid This is not part of IBackend but necessary for the ImportChangesICS->MoveMessage() operation if the destination folder is not in the default store Note: The current backend store might be changed as IBackend->Setup() is executed.

Parameters:
string$storetarget store, could contain a "domain\user" value - if emtpy default store is returned
string$folderidpublic
Returns:
Ressource/boolean

Definition at line 1219 of file zarafa.php.

                                                               {
        if ($store == false) {
            ZLog::Write(LOGLEVEL_DEBUG, sprintf("ZarafaBackend->GetMAPIStoreForFolderId('%s', '%s'): no store specified, returning default store", $store, $folderid));
            return $this->defaultstore;
        }

        // setup the correct store
        if ($this->Setup($store, false, $folderid)) {
            return $this->store;
        }
        else {
            ZLog::Write(LOGLEVEL_WARN, sprintf("ZarafaBackend->GetMAPIStoreForFolderId('%s', '%s'): store is not available", $store, $folderid));
            return false;
        }
    }

Here is the call graph for this function:

Returns the ZarafaBackend as it implements the ISearchProvider interface This could be overwritten by the global configuration.

public

Returns:
object Implementation of ISearchProvider

Implements IBackend.

Definition at line 127 of file zarafa.php.

                                        {
        return $this;
    }

Indicates which StateMachine should be used.

public

Returns:
boolean ZarafaBackend uses the default FileStateMachine

Implements IBackend.

Definition at line 116 of file zarafa.php.

                                      {
        return false;
    }

Indicates which AS version is supported by the backend.

public

Returns:
string AS version constant

Implements IBackend.

Definition at line 137 of file zarafa.php.

                                            {
        return ZPush::ASV_14;
    }

Returns the waste basket.

public

Returns:
string

Implements IBackend.

Definition at line 706 of file zarafa.php.

                                     {
        if ($this->wastebasket) {
            return $this->wastebasket;
        }

        $storeprops = mapi_getprops($this->defaultstore, array(PR_IPM_WASTEBASKET_ENTRYID));
        if (isset($storeprops[PR_IPM_WASTEBASKET_ENTRYID])) {
            $wastebasket = mapi_msgstore_openentry($this->store, $storeprops[PR_IPM_WASTEBASKET_ENTRYID]);
            $wastebasketprops = mapi_getprops($wastebasket, array(PR_SOURCE_KEY));
            if (isset($wastebasketprops[PR_SOURCE_KEY])) {
                $this->wastebasket = bin2hex($wastebasketprops[PR_SOURCE_KEY]);
                ZLog::Write(LOGLEVEL_DEBUG, sprintf("Got waste basket with id '%s'", $this->wastebasket));
                return $this->wastebasket;
            }
        }
        return false;
    }

Here is the call graph for this function:

Indicates if the backend has a ChangesSink.

A sink is an active notification mechanism which does not need polling. Since Zarafa 7.0.5 such a sink is available. The Zarafa backend uses this method to initialize the sink with mapi.

public

Returns:
boolean

Implements IBackend.

Definition at line 895 of file zarafa.php.

                                     {
        if (!$this->notifications) {
            ZLog::Write(LOGLEVEL_DEBUG, "ZarafaBackend->HasChangesSink(): sink is not available");
            return false;
        }

        $this->changesSink = @mapi_sink_create();

        if (! $this->changesSink) {
            ZLog::Write(LOGLEVEL_DEBUG, "ZarafaBackend->HasChangesSink(): sink could not be created");
            return false;
        }

        ZLog::Write(LOGLEVEL_DEBUG, "ZarafaBackend->HasChangesSink(): created");
        return true;
    }

Here is the call graph for this function:

BackendZarafa::Logoff ( ) [inherited]

Logs off Free/Busy information is updated for modified calendars This is done after the synchronization process is completed.

public

Returns:
boolean

Implements IBackend.

Definition at line 283 of file zarafa.php.

                             {
        // update if the calendar which received incoming changes
        foreach($this->importedFolders as $folderid => $store) {
            // open the root of the store
            $storeprops = mapi_getprops($store, array(PR_USER_ENTRYID));
            $root = mapi_msgstore_openentry($store);
            if (!$root)
                continue;

            // get the entryid of the main calendar of the store and the calendar to be published
            $rootprops = mapi_getprops($root, array(PR_IPM_APPOINTMENT_ENTRYID));
            $entryid = mapi_msgstore_entryidfromsourcekey($store, hex2bin($folderid));

            // only publish free busy for the main calendar
            if(isset($rootprops[PR_IPM_APPOINTMENT_ENTRYID]) && $rootprops[PR_IPM_APPOINTMENT_ENTRYID] == $entryid) {
                ZLog::Write(LOGLEVEL_INFO, sprintf("ZarafaBackend->Logoff(): Updating freebusy information on folder id '%s'", $folderid));
                $calendar = mapi_msgstore_openentry($store, $entryid);

                $pub = new FreeBusyPublish($this->session, $store, $calendar, $storeprops[PR_USER_ENTRYID]);
                $pub->publishFB(time() - (7 * 24 * 60 * 60), 6 * 30 * 24 * 60 * 60); // publish from one week ago, 6 months ahead
            }
        }

        return true;
    }

Here is the call graph for this function:

BackendZarafa::Logon ( user,
domain,
pass 
) [inherited]

Authenticates the user with the configured Zarafa server.

Parameters:
string$username
string$domain
string$passwordpublic
Returns:
boolean
Exceptions:
AuthenticationRequiredException

Implements IBackend.

Definition at line 152 of file zarafa.php.

                                                 {
        ZLog::Write(LOGLEVEL_DEBUG, sprintf("ZarafaBackend->Logon(): Trying to authenticate user '%s'..", $user));
        $this->mainUser = $user;

        try {
            // check if notifications are available in php-mapi
            if(function_exists('mapi_feature') && mapi_feature('LOGONFLAGS')) {
                $this->session = @mapi_logon_zarafa($user, $pass, MAPI_SERVER, null, null, 0);
                $this->notifications = true;
            }
            // old fashioned session
            else {
                $this->session = @mapi_logon_zarafa($user, $pass, MAPI_SERVER);
                $this->notifications = false;
            }

            if (mapi_last_hresult())
                ZLog::Write(LOGLEVEL_ERROR, sprintf("ZarafaBackend->Logon(): login failed with error code: 0x%X", mapi_last_hresult()));

        }
        catch (MAPIException $ex) {
            throw new AuthenticationRequiredException($ex->getDisplayMessage());
        }

        if(!$this->session) {
            ZLog::Write(LOGLEVEL_WARN, sprintf("ZarafaBackend->Logon(): logon failed for user '%s'", $user));
            $this->defaultstore = false;
            return false;
        }

        // Get/open default store
        $this->defaultstore = $this->openMessageStore($user);

        if($this->defaultstore === false)
            throw new AuthenticationRequiredException(sprintf("ZarafaBackend->Logon(): User '%s' has no default store", $user));

        $this->store = $this->defaultstore;
        $this->storeName = $user;

        ZLog::Write(LOGLEVEL_DEBUG, sprintf("ZarafaBackend->Logon(): User '%s' is authenticated",$user));

        // check if this is a Zarafa 7 store with unicode support
        MAPIUtils::IsUnicodeStore($this->store);
        return true;
    }

Here is the call graph for this function:

BackendZarafa::MeetingResponse ( requestid,
folderid,
response 
) [inherited]

Processes a response to a meeting request.

CalendarID is a reference and has to be set if a new calendar item is created

Parameters:
string$requestidid of the object containing the request
string$folderidid of the parent folder of $requestid
string$responsepublic
Returns:
string id of the created/updated calendar obj
Exceptions:
StatusException

Implements IBackend.

Definition at line 813 of file zarafa.php.

                                                                      {
        // Use standard meeting response code to process meeting request
        $reqentryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($folderid), hex2bin($requestid));
        if (!$reqentryid)
            throw new StatusException(sprintf("BackendZarafa->MeetingResponse('%s', '%s', '%s'): Error, unable to entryid of the message 0x%X", $requestid, $folderid, $response, mapi_last_hresult()), SYNC_MEETRESPSTATUS_INVALIDMEETREQ);

        $mapimessage = mapi_msgstore_openentry($this->store, $reqentryid);
        if(!$mapimessage)
            throw new StatusException(sprintf("BackendZarafa->MeetingResponse('%s','%s', '%s'): Error, unable to open request message for response 0x%X", $requestid, $folderid, $response, mapi_last_hresult()), SYNC_MEETRESPSTATUS_INVALIDMEETREQ);

        $meetingrequest = new Meetingrequest($this->store, $mapimessage);

        if(!$meetingrequest->isMeetingRequest())
            throw new StatusException(sprintf("BackendZarafa->MeetingResponse('%s','%s', '%s'): Error, attempt to respond to non-meeting request", $requestid, $folderid, $response), SYNC_MEETRESPSTATUS_INVALIDMEETREQ);

        if($meetingrequest->isLocalOrganiser())
            throw new StatusException(sprintf("BackendZarafa->MeetingResponse('%s','%s', '%s'): Error, attempt to response to meeting request that we organized", $requestid, $folderid, $response), SYNC_MEETRESPSTATUS_INVALIDMEETREQ);

        // Process the meeting response. We don't have to send the actual meeting response
        // e-mail, because the device will send it itself.
        switch($response) {
            case 1:     // accept
            default:
                $entryid = $meetingrequest->doAccept(false, false, false, false, false, false, true); // last true is the $userAction
                break;
            case 2:        // tentative
                $entryid = $meetingrequest->doAccept(true, false, false, false, false, false, true); // last true is the $userAction
                break;
            case 3:        // decline
                $meetingrequest->doDecline(false);
                break;
        }

        // F/B will be updated on logoff

        // We have to return the ID of the new calendar item, so do that here
        if (isset($entryid)) {
            $newitem = mapi_msgstore_openentry($this->store, $entryid);
            $newprops = mapi_getprops($newitem, array(PR_SOURCE_KEY));
            $calendarid = bin2hex($newprops[PR_SOURCE_KEY]);
        }

        // on recurring items, the MeetingRequest class responds with a wrong entryid
        if ($requestid == $calendarid) {
               ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendZarafa->MeetingResponse('%s','%s', '%s'): returned calender id is the same as the requestid - re-searching", $requestid, $folderid, $response));

            $props = MAPIMapping::GetMeetingRequestProperties();
            $props = getPropIdsFromStrings($this->store, $props);

            $messageprops = mapi_getprops($mapimessage, Array($props["goidtag"]));
            $goid = $messageprops[$props["goidtag"]];

            $items = $meetingrequest->findCalendarItems($goid);

            if (is_array($items)) {
               $newitem = mapi_msgstore_openentry($this->store, $items[0]);
               $newprops = mapi_getprops($newitem, array(PR_SOURCE_KEY));
               $calendarid = bin2hex($newprops[PR_SOURCE_KEY]);
               ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendZarafa->MeetingResponse('%s','%s', '%s'): found other calendar entryid", $requestid, $folderid, $response));
            }
        }

        if ($calendarid == "" || $requestid == $calendarid)
            throw new StatusException(sprintf("BackendZarafa->MeetingResponse('%s','%s', '%s'): Error finding the accepted meeting response in the calendar", $requestid, $folderid, $response), SYNC_MEETRESPSTATUS_INVALIDMEETREQ);

        // delete meeting request from Inbox
        $folderentryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($folderid));
        $folder = mapi_msgstore_openentry($this->store, $folderentryid);
        mapi_folder_deletemessages($folder, array($reqentryid), 0);

        return $calendarid;
    }

Here is the call graph for this function:

BackendZarafa::SendMail ( sm) [inherited]

Sends an e-mail This messages needs to be saved into the 'sent items' folder.

Parameters:
SyncSendMail$smSyncSendMail object

public

Returns:
boolean
Exceptions:
StatusException

Implements IBackend.

Definition at line 398 of file zarafa.php.

                                  {
        ZLog::Write(LOGLEVEL_DEBUG, sprintf("ZarafaBackend->SendMail(): RFC822: %d bytes  forward-id: '%s' reply-id: '%s' parent-id: '%s' SaveInSent: '%s' ReplaceMIME: '%s'",
                                            strlen($sm->mime), Utils::PrintAsString($sm->forwardflag), Utils::PrintAsString($sm->replyflag),
                                            Utils::PrintAsString((isset($sm->source->folderid) ? $sm->source->folderid : false)),
                                            Utils::PrintAsString(($sm->saveinsent)), Utils::PrintAsString(isset($sm->replacemime)) ));

        // by splitting the message in several lines we can easily grep later
        foreach(preg_split("/((\r)?\n)/", $sm->mime) as $rfc822line)
            ZLog::Write(LOGLEVEL_WBXML, "RFC822: ". $rfc822line);

        $mimeParams = array('decode_headers' => true,
                            'decode_bodies' => true,
                            'include_bodies' => true,
                            'charset' => 'utf-8');

        $mimeObject = new Mail_mimeDecode($sm->mime);
        $message = $mimeObject->decode($mimeParams);

        $sendMailProps = MAPIMapping::GetSendMailProperties();
        $sendMailProps = getPropIdsFromStrings($this->store, $sendMailProps);

        // Open the outbox and create the message there
        $storeprops = mapi_getprops($this->store, array($sendMailProps["outboxentryid"], $sendMailProps["ipmsentmailentryid"]));
        if(isset($storeprops[$sendMailProps["outboxentryid"]]))
            $outbox = mapi_msgstore_openentry($this->store, $storeprops[$sendMailProps["outboxentryid"]]);

        if(!$outbox)
            throw new StatusException(sprintf("ZarafaBackend->SendMail(): No Outbox found or unable to create message: 0x%X", mapi_last_hresult()), SYNC_COMMONSTATUS_SERVERERROR);

        $mapimessage = mapi_folder_createmessage($outbox);

        //message properties to be set
        $mapiprops = array();
        // only save the outgoing in sent items folder if the mobile requests it
        $mapiprops[$sendMailProps["sentmailentryid"]] = $storeprops[$sendMailProps["ipmsentmailentryid"]];

        // Check if imtomapi function is available and use it to send the mime message.
        // It is available since ZCP 7.0.6
        // @see http://jira.zarafa.com/browse/ZCP-9508
        if(function_exists('mapi_feature') && mapi_feature('INETMAPI_IMTOMAPI')) {
            ZLog::Write(LOGLEVEL_DEBUG, "Use the mapi_inetmapi_imtomapi function");
            $ab = mapi_openaddressbook($this->session);
            mapi_inetmapi_imtomapi($this->session, $this->store, $ab, $mapimessage, $sm->mime, array());

            // Delete the PR_SENT_REPRESENTING_* properties because some android devices
            // do not send neither From nor Sender header causing empty PR_SENT_REPRESENTING_NAME and
            // PR_SENT_REPRESENTING_EMAIL_ADDRESS properties and "broken" PR_SENT_REPRESENTING_ENTRYID
            // which results in spooler not being able to send the message.
            // @see http://jira.zarafa.com/browse/ZP-85
            mapi_deleteprops($mapimessage,
                array(  $sendMailProps["sentrepresentingname"], $sendMailProps["sentrepresentingemail"], $sendMailProps["representingentryid"],
                        $sendMailProps["sentrepresentingaddt"], $sendMailProps["sentrepresentinsrchk"]));

            if(isset($sm->source->itemid) && $sm->source->itemid) {
                $entryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($sm->source->folderid), hex2bin($sm->source->itemid));
                if ($entryid)
                    $fwmessage = mapi_msgstore_openentry($this->store, $entryid);

                if(!isset($fwmessage) || !$fwmessage)
                    throw new StatusException(sprintf("ZarafaBackend->SendMail(): Could not open message id '%s' in folder id '%s' to be replied/forwarded: 0x%X", $sm->source->itemid, $sm->source->folderid, mapi_last_hresult()), SYNC_COMMONSTATUS_ITEMNOTFOUND);

                //update icon when forwarding or replying message
                if ($sm->forwardflag) mapi_setprops($fwmessage, array(PR_ICON_INDEX=>262));
                elseif ($sm->replyflag) mapi_setprops($fwmessage, array(PR_ICON_INDEX=>261));
                mapi_savechanges($fwmessage);

                // only attach the original message if the mobile does not send it itself
                if (!isset($sm->replacemime)) {
                    // get message's body in order to append forward or reply text
                    $body = MAPIUtils::readPropStream($mapimessage, PR_BODY);
                    $bodyHtml = MAPIUtils::readPropStream($mapimessage, PR_HTML);
                    if($sm->forwardflag) {
                        // attach the original attachments to the outgoing message
                        $this->copyAttachments($mapimessage, $fwmessage);
                    }

                    if (strlen($body) > 0) {
                        $fwbody = MAPIUtils::readPropStream($fwmessage, PR_BODY);
                        $mapiprops[$sendMailProps["body"]] = $body."\r\n\r\n".$fwbody;
                    }

                    if (strlen($bodyHtml) > 0) {
                        $fwbodyHtml = MAPIUtils::readPropStream($fwmessage, PR_HTML);
                        $mapiprops[$sendMailProps["html"]] = $bodyHtml."<br><br>".$fwbodyHtml;
                    }
                }
            }

            mapi_setprops($mapimessage, $mapiprops);
            mapi_message_savechanges($mapimessage);
            mapi_message_submitmessage($mapimessage);
            $hr = mapi_last_hresult();

            if ($hr)
                throw new StatusException(sprintf("ZarafaBackend->SendMail(): Error saving/submitting the message to the Outbox: 0x%X", mapi_last_hresult()), SYNC_COMMONSTATUS_MAILSUBMISSIONFAILED);

            ZLog::Write(LOGLEVEL_DEBUG, "ZarafaBackend->SendMail(): email submitted");
            return true;
        }

        $mapiprops[$sendMailProps["subject"]] = u2wi(isset($message->headers["subject"])?$message->headers["subject"]:"");
        $mapiprops[$sendMailProps["messageclass"]] = "IPM.Note";
        $mapiprops[$sendMailProps["deliverytime"]] = time();

        if(isset($message->headers["x-priority"])) {
            $this->getImportanceAndPriority($message->headers["x-priority"], $mapiprops, $sendMailProps);
        }

        $this->addRecipients($message->headers, $mapimessage);

        // Loop through message subparts.
        $body = "";
        $body_html = "";
        if($message->ctype_primary == "multipart" && ($message->ctype_secondary == "mixed" || $message->ctype_secondary == "alternative")) {
            $mparts = $message->parts;
            for($i=0; $i<count($mparts); $i++) {
                $part = $mparts[$i];

                // palm pre & iPhone send forwarded messages in another subpart which are also parsed
                if($part->ctype_primary == "multipart" && ($part->ctype_secondary == "mixed" || $part->ctype_secondary == "alternative"  || $part->ctype_secondary == "related")) {
                    foreach($part->parts as $spart)
                        $mparts[] = $spart;
                    continue;
                }

                // standard body
                if($part->ctype_primary == "text" && $part->ctype_secondary == "plain" && isset($part->body) && (!isset($part->disposition) || $part->disposition != "attachment")) {
                    $body .= u2wi($part->body); // assume only one text body
                }
                // html body
                elseif($part->ctype_primary == "text" && $part->ctype_secondary == "html") {
                    $body_html .= u2wi($part->body);
                }
                // TNEF
                elseif($part->ctype_primary == "ms-tnef" || $part->ctype_secondary == "ms-tnef") {
                    if (!isset($tnefAndIcalProps)) {
                        $tnefAndIcalProps = MAPIMapping::GetTnefAndIcalProperties();
                        $tnefAndIcalProps = getPropIdsFromStrings($this->store, $tnefAndIcalProps);
                    }

                    require_once('tnefparser.php');
                    $zptnef = new TNEFParser($this->store, $tnefAndIcalProps);

                    $zptnef->ExtractProps($part->body, $mapiprops);
                    if (is_array($mapiprops) && !empty($mapiprops)) {
                        //check if it is a recurring item
                        if (isset($mapiprops[$tnefAndIcalProps["tnefrecurr"]])) {
                            MAPIUtils::handleRecurringItem($mapiprops, $tnefAndIcalProps);
                        }
                    }
                    else ZLog::Write(LOGLEVEL_WARN, "ZarafaBackend->Sendmail(): TNEFParser: Mapi property array was empty");
                }
                // iCalendar
                elseif($part->ctype_primary == "text" && $part->ctype_secondary == "calendar") {
                    if (!isset($tnefAndIcalProps)) {
                        $tnefAndIcalProps = MAPIMapping::GetTnefAndIcalProperties();
                        $tnefAndIcalProps = getPropIdsFromStrings($this->store, $tnefAndIcalProps);
                    }

                    require_once('icalparser.php');
                    $zpical = new ICalParser($this->store, $tnefAndIcalProps);
                    $zpical->ExtractProps($part->body, $mapiprops);

                    // iPhone sends a second ICS which we ignore if we can
                    if (!isset($mapiprops[PR_MESSAGE_CLASS]) && strlen(trim($body)) == 0) {
                        ZLog::Write(LOGLEVEL_WARN, "ZarafaBackend->Sendmail(): Secondary iPhone response is being ignored!! Mail dropped!");
                        return true;
                    }

                    if (! Utils::CheckMapiExtVersion("6.30") && is_array($mapiprops) && !empty($mapiprops)) {
                        mapi_setprops($mapimessage, $mapiprops);
                    }
                    else {
                        // store ics as attachment
                        //see Utils::IcalTimezoneFix() in utils.php for more information
                        $part->body = Utils::IcalTimezoneFix($part->body);
                        MAPIUtils::StoreAttachment($mapimessage, $part);
                        ZLog::Write(LOGLEVEL_INFO, "ZarafaBackend->Sendmail(): Sending ICS file as attachment");
                    }
                }
                // any other type, store as attachment
                else
                    MAPIUtils::StoreAttachment($mapimessage, $part);
            }
        }
        // html main body
        else if($message->ctype_primary == "text" && $message->ctype_secondary == "html") {
            $body_html .= u2wi($message->body);
        }
        // standard body
        else {
            $body = u2wi($message->body);
        }

        // some devices only transmit a html body
        if (strlen($body) == 0 && strlen($body_html) > 0) {
            ZLog::Write(LOGLEVEL_WARN, "ZarafaBackend->SendMail(): only html body sent, transformed into plain text");
            $body = strip_tags($body_html);
        }

        if(isset($sm->source->itemid) && $sm->source->itemid) {
            // Append the original text body for reply/forward

            $entryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($sm->source->folderid), hex2bin($sm->source->itemid));
            if ($entryid)
                $fwmessage = mapi_msgstore_openentry($this->store, $entryid);

            if(!isset($fwmessage) || !$fwmessage)
                throw new StatusException(sprintf("ZarafaBackend->SendMail(): Could not open message id '%s' in folder id '%s' to be replied/forwarded: 0x%X", $sm->source->itemid, $sm->source->folderid, mapi_last_hresult()), SYNC_COMMONSTATUS_ITEMNOTFOUND);

            //update icon when forwarding or replying message
            if ($sm->forwardflag) mapi_setprops($fwmessage, array(PR_ICON_INDEX=>262));
            elseif ($sm->replyflag) mapi_setprops($fwmessage, array(PR_ICON_INDEX=>261));
            mapi_savechanges($fwmessage);

            // only attach the original message if the mobile does not send it itself
            if (!isset($sm->replacemime)) {
                $fwbody = MAPIUtils::readPropStream($fwmessage, PR_BODY);
                $fwbodyHtml = MAPIUtils::readPropStream($fwmessage, PR_HTML);

                if($sm->forwardflag) {
                    // 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 ..
                    $fwheader = $this->getForwardHeaders($fwmessage);

                    // add fwheader to body and body_html
                    $body .= $fwheader;
                    if (strlen($body_html) > 0)
                        $body_html .= str_ireplace("\r\n", "<br>", $fwheader);

                    // attach the original attachments to the outgoing message
                    $this->copyAttachments($mapimessage, $fwmessage);
                }

                if(strlen($body) > 0)
                    $body .= $fwbody;

                if (strlen($body_html) > 0)
                    $body_html .= $fwbodyHtml;
            }
        }

        //set PR_INTERNET_CPID to 65001 (utf-8) if store supports it and to 1252 otherwise
        $internetcpid = INTERNET_CPID_WINDOWS1252;
        if (defined('STORE_SUPPORTS_UNICODE') && STORE_SUPPORTS_UNICODE == true) {
            $internetcpid = INTERNET_CPID_UTF8;
        }

        $mapiprops[$sendMailProps["body"]] = $body;
        $mapiprops[$sendMailProps["internetcpid"]] = $internetcpid;


        if(strlen($body_html) > 0){
            $mapiprops[$sendMailProps["html"]] = $body_html;
        }

        //TODO if setting all properties fails, try setting them infividually like in mapiprovider
        mapi_setprops($mapimessage, $mapiprops);

        mapi_savechanges($mapimessage);
        mapi_message_submitmessage($mapimessage);

        if(mapi_last_hresult())
            throw new StatusException(sprintf("ZarafaBackend->SendMail(): Error saving/submitting the message to the Outbox: 0x%X", mapi_last_hresult()), SYNC_COMMONSTATUS_MAILSUBMISSIONFAILED);

        ZLog::Write(LOGLEVEL_DEBUG, "ZarafaBackend->SendMail(): email submitted");
        return true;
    }

Here is the call graph for this function:

BackendZarafa::Settings ( settings) [inherited]

Applies settings to and gets informations from the device.

Parameters:
SyncObject$settings(SyncOOF or SyncUserInformation possible)

public

Returns:
SyncObject $settings

Implements IBackend.

Definition at line 976 of file zarafa.php.

                                        {
        if ($settings instanceof SyncOOF) {
            $this->settingsOOF($settings);
        }

        if ($settings instanceof SyncUserInformation) {
            $this->settingsUserInformation($settings);
        }

        return $settings;
    }

Here is the call graph for this function:

BackendZarafa::Setup ( store,
checkACLonly = false,
folderid = false 
) [inherited]

Setup the backend to work on a specific store or checks ACLs there.

If only the $store is submitted, all Import/Export/Fetch/Etc operations should be performed on this store (switch operations store). If the ACL check is enabled, this operation should just indicate the ACL status on the submitted store, without changing the store for operations. For the ACL status, the currently logged on user MUST have access rights on

  • the entire store - admin access if no folderid is sent, or
  • on a specific folderid in the store (secretary/full access rights)

The ACLcheck MUST fail if a folder of the authenticated user is checked!

Parameters:
string$storetarget store, could contain a "domain\user" value
boolean$checkACLonlyif set to true, Setup() should just check ACLs
string$folderidif set, only ACLs on this folderid are relevant

public

Returns:
boolean

Implements IBackend.

Definition at line 217 of file zarafa.php.

                                                                            {
        list($user, $domain) = Utils::SplitDomainUser($store);

        if (!isset($this->mainUser))
            return false;

        if ($user === false)
            $user = $this->mainUser;

        // This is a special case. A user will get it's entire folder structure by the foldersync by default.
        // The ACL check is executed when an additional folder is going to be sent to the mobile.
        // Configured that way the user could receive the same folderid twice, with two different names.
        if ($this->mainUser == $user && $checkACLonly && $folderid) {
            ZLog::Write(LOGLEVEL_DEBUG, "ZarafaBackend->Setup(): Checking ACLs for folder of the users defaultstore. Fail is forced to avoid folder duplications on mobile.");
            return false;
        }

        // get the users store
        $userstore = $this->openMessageStore($user);

        // only proceed if a store was found, else return false
        if ($userstore) {
            // only check permissions
            if ($checkACLonly == true) {
                // check for admin rights
                if (!$folderid) {
                    if ($user != $this->mainUser) {
                        $zarafauserinfo = @mapi_zarafa_getuser_by_name($this->defaultstore, $this->mainUser);
                        $admin = (isset($zarafauserinfo['admin']) && $zarafauserinfo['admin'])?true:false;
                    }
                    // the user has always full access to his own store
                    else
                        $admin = true;

                    ZLog::Write(LOGLEVEL_DEBUG, sprintf("ZarafaBackend->Setup(): Checking for admin ACLs on store '%s': '%s'", $user, Utils::PrintAsString($admin)));
                    return $admin;
                }
                // check 'secretary' permissions on this folder
                else {
                    $rights = $this->hasSecretaryACLs($userstore, $folderid);
                    ZLog::Write(LOGLEVEL_DEBUG, sprintf("ZarafaBackend->Setup(): Checking for secretary ACLs on '%s' of store '%s': '%s'", $folderid, $user, Utils::PrintAsString($rights)));
                    return $rights;
                }
            }

            // switch operations store
            // this should also be done if called with user = mainuser or user = false
            // which means to switch back to the default store
            else {
                // switch active store
                $this->store = $userstore;
                $this->storeName = $user;
                return true;
            }
        }
        return false;
    }

Here is the call graph for this function:

Here is the caller graph for this function:

BackendZarafa::SupportsType ( searchtype) [inherited]


Implementation of the ISearchProvider interface

Indicates if a search type is supported by this SearchProvider Currently only the type ISearchProvider::SEARCH_GAL (Global Address List) is implemented

Parameters:
string$searchtypepublic
Returns:
boolean

Implements ISearchProvider.

Definition at line 1002 of file zarafa.php.

                                              {
        return ($searchtype == ISearchProvider::SEARCH_GAL) || ($searchtype == ISearchProvider::SEARCH_MAILBOX);
    }
BackendZarafa::TerminateSearch ( pid) [inherited]

Terminates a search for a given PID.

Parameters:
int$pid
Returns:
boolean

Implements ISearchProvider.

Definition at line 1165 of file zarafa.php.

                                          {
        ZLog::Write(LOGLEVEL_DEBUG, sprintf("ZarafaBackend->TerminateSearch(): terminating search for pid %d", $pid));
        $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;
        }

        $finderfolder = 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;
        }

        $hierarchytable = mapi_folder_gethierarchytable($finderfolder);
        mapi_table_restrict($hierarchytable,
            array(RES_CONTENT,
                array(
                    FUZZYLEVEL      => FL_PREFIX,
                    ULPROPTAG       => PR_DISPLAY_NAME,
                    VALUE           => array(PR_DISPLAY_NAME=>"Z-Push Search Folder ".$pid)
                )
            ),
            TBL_BATCH);

        $folders = mapi_table_queryallrows($hierarchytable, array(PR_ENTRYID, PR_DISPLAY_NAME, PR_LAST_MODIFICATION_TIME));
        foreach($folders as $folder) {
            mapi_folder_deletefolder($finderfolder, $folder[PR_ENTRYID]);
        }
        return true;
    }

Here is the call graph for this function:


Member Data Documentation

const ISearchProvider::SEARCH_DOCUMENTLIBRARY = "DOCUMENTLIBRARY" [inherited]

Definition at line 48 of file isearchprovider.php.

const ISearchProvider::SEARCH_GAL = "GAL" [inherited]

Definition at line 46 of file isearchprovider.php.

const ISearchProvider::SEARCH_MAILBOX = "MAILBOX" [inherited]

Definition at line 47 of file isearchprovider.php.


The documentation for this class was generated from the following file: