diff -urN ../z-push-2.5.orig/src/backend/searchcombined/config.php.dist ./src/backend/searchcombined/config.php.dist --- ../z-push-2.5.orig/src/backend/searchcombined/config.php.dist 1970-01-01 03:00:00.000000000 +0300 +++ ./src/backend/searchcombined/config.php.dist 2023-09-26 16:26:31.987516000 +0300 @@ -0,0 +1,34 @@ +. +* +* Consult LICENSE file for details +************************************************/ + +global $searchcombined_conf; +$searchcombined_conf = array(); + +//$searchcombined_conf[] = 'BackendSearchMySQL'; +//$searchcombined_conf[] = 'BackendSearchCardDAV'; +//$searchcombined_conf[] = 'BackendSearchPasswd'; +//$searchcombined_conf[] = 'BackendSearchLDAP'; diff -urN ../z-push-2.5.orig/src/backend/searchcombined/searchcombined.php ./src/backend/searchcombined/searchcombined.php --- ../z-push-2.5.orig/src/backend/searchcombined/searchcombined.php 1970-01-01 03:00:00.000000000 +0300 +++ ./src/backend/searchcombined/searchcombined.php 2022-01-29 15:58:48.939390000 +0200 @@ -0,0 +1,174 @@ +. +* +* Consult LICENSE file for details +************************************************/ + +require_once("backend/searchcombined/config.php"); + +class BackendSearchCombined implements ISearchProvider{ + static $searchProviders = false; + + /** + * Constructor + * initializes the searchprovider to perform the search + * + * @access public + * @return + * @throws StatusException, FatalException + */ + public function __construct() { + global $searchcombined_conf; + + if (!self::$searchProviders) { + + foreach ($searchcombined_conf as $searchClass) { + // is a global searchprovider configured ? It will outrank the backend + if ($searchClass) { + if (! class_exists($searchClass)) + ZPush::IncludeBackend($searchClass); + + if (class_exists($searchClass)) + $aSearchProvider = new $searchClass(); + else + throw new FatalMisconfigurationException(sprintf("BackendSearchCombined(): Search provider '%s' can not be loaded. Check configuration!", $searchClass)); + } + // get the searchprovider from the backend + else + $aSearchProvider = ZPush::GetBackend()->GetSearchProvider(); + + if (in_array('ISearchProvider', class_implements($aSearchProvider))) + self::$searchProviders[] = $aSearchProvider; + else + throw new FatalNotImplementedException("BackendSearchCombined(): Instantiated SearchProvider does not implement 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 + * + * @param string $searchtype + * + * @access public + * @return boolean + */ + public function SupportsType($searchtype) { + return ($searchtype == ISearchProvider::SEARCH_GAL); + } + + /** + * Searches the GAL + * + * @param string $searchquery string to be searched for + * @param string $searchrange specified searchrange + * @param SyncResolveRecipientsPicture $searchpicture limitations for picture + * + * @access public + * @return array search results + * @throws StatusException + */ + public function GetGALSearchResults($searchquery, $searchrange, $searchpicture) { + if (!self::$searchProviders) { + throw new StatusException("BackendSearchCombined(): No search backend defined! Search aborted.", SYNC_SEARCHSTATUS_STORE_CONNECTIONFAILED, null, LOGLEVEL_ERROR); + } + + $items = array(); + foreach (self::$searchProviders as $searchProvider) { + $searchProviderItems = $searchProvider->GetGALSearchResults($searchquery, '0-10000', $searchpicture); + unset($searchProviderItems['range']); + unset($searchProviderItems['searchtotal']); + $items = array_merge($items, $searchProviderItems); + } + +// ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendSearchCombined(): got total items: %s", print_r($items, true))); + + $searchtotal = count($items); + + $rangestart = 0; + $rangeend = 50; + if (!empty($searchrange) and ($searchrange != '0')) { + $pos = strpos($searchrange, '-'); + if ($pos !== false) { + $rangestart = substr($searchrange, 0, $pos); + $rangeend = substr($searchrange, ($pos + 1)); + } + } + + while (count($items) > $rangeend + 1) array_pop($items); + for ($i = 0; $i < $rangestart; $i++) { + if (count($items) > 0) array_shift($items); + } + $items['range'] = $rangestart . '-' . ($rangestart + count($items) - 1); + $items['searchtotal'] = $searchtotal; + +// ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendSearchCombined(): got ranged items: %s", print_r($items, true))); + + return $items; + } + + /** + * Searches for the emails on the server + * + * @param ContentParameter $cpo + * + * @return array + */ + public function GetMailboxSearchResults($cpo){ + return array(); + } + + /** + * Terminates a search for a given PID + * + * @param int $pid + * + * @return boolean + */ + public function TerminateSearch($pid) { + return true; + } + + /** + * Disconnects from the current search provider + * + * @access public + * @return boolean + */ + public function Disconnect() { + if (!self::$searchProviders) { + throw new StatusException("BackendSearchCombined(): No search backend defined! Search aborted.", SYNC_SEARCHSTATUS_STORE_CONNECTIONFAILED, null, LOGLEVEL_ERROR); + } + + $items = array(); + foreach (self::$searchProviders as $searchProvider) { + $searchProvider->Disconnect(); + } + + return true; + } +}