1 | <?php |
||||||
2 | /* |
||||||
3 | * SPDX-License-Identifier: AGPL-3.0-only |
||||||
4 | * SPDX-FileCopyrightText: Copyright 2007-2016 Zarafa Deutschland GmbH |
||||||
5 | * SPDX-FileCopyrightText: Copyright 2020-2024 grommunio GmbH |
||||||
6 | * |
||||||
7 | * Provides the SEARCH command |
||||||
8 | */ |
||||||
9 | |||||||
10 | class Search extends RequestProcessor { |
||||||
11 | /** |
||||||
12 | * Handles the Search command. |
||||||
13 | * |
||||||
14 | * @param int $commandCode |
||||||
15 | * |
||||||
16 | * @return bool |
||||||
17 | */ |
||||||
18 | public function Handle($commandCode) { |
||||||
19 | $searchrange = '0'; |
||||||
20 | $searchpicture = false; |
||||||
21 | $cpo = new ContentParameters(); |
||||||
22 | |||||||
23 | if (!self::$decoder->getElementStartTag(SYNC_SEARCH_SEARCH)) { |
||||||
24 | return false; |
||||||
25 | } |
||||||
26 | |||||||
27 | // TODO check: possible to search in other stores? |
||||||
28 | if (!self::$decoder->getElementStartTag(SYNC_SEARCH_STORE)) { |
||||||
29 | return false; |
||||||
30 | } |
||||||
31 | |||||||
32 | if (!self::$decoder->getElementStartTag(SYNC_SEARCH_NAME)) { |
||||||
33 | return false; |
||||||
34 | } |
||||||
35 | $searchname = strtoupper(self::$decoder->getElementContent()); |
||||||
36 | if (!self::$decoder->getElementEndTag()) { |
||||||
37 | return false; |
||||||
38 | } |
||||||
39 | |||||||
40 | if (!self::$decoder->getElementStartTag(SYNC_SEARCH_QUERY)) { |
||||||
41 | return false; |
||||||
42 | } |
||||||
43 | |||||||
44 | // check if it is a content of an element (= GAL search) |
||||||
45 | // or a starttag (= mailbox or documentlibrary search) |
||||||
46 | $searchquery = self::$decoder->getElementContent(); |
||||||
47 | if ($searchquery && !self::$decoder->getElementEndTag()) { |
||||||
48 | return false; |
||||||
49 | } |
||||||
50 | |||||||
51 | if ($searchquery === false) { |
||||||
52 | $cpo->SetSearchName($searchname); |
||||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||||
53 | if (self::$decoder->getElementStartTag(SYNC_SEARCH_AND)) { |
||||||
54 | if (self::$decoder->getElementStartTag(SYNC_FOLDERID)) { |
||||||
55 | $searchfolderid = self::$decoder->getElementContent(); |
||||||
56 | $cpo->SetSearchFolderid($searchfolderid); |
||||||
0 ignored issues
–
show
The method
SetSearchFolderid() does not exist on ContentParameters . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
57 | if (!self::$decoder->getElementEndTag()) { // SYNC_FOLDERID |
||||||
58 | return false; |
||||||
59 | } |
||||||
60 | } |
||||||
61 | |||||||
62 | if (self::$decoder->getElementStartTag(SYNC_FOLDERTYPE)) { |
||||||
63 | $searchclass = self::$decoder->getElementContent(); |
||||||
64 | $cpo->SetSearchClass($searchclass); |
||||||
0 ignored issues
–
show
The method
SetSearchClass() does not exist on ContentParameters . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
65 | if (!self::$decoder->getElementEndTag()) { // SYNC_FOLDERTYPE |
||||||
66 | return false; |
||||||
67 | } |
||||||
68 | } |
||||||
69 | |||||||
70 | if (self::$decoder->getElementStartTag(SYNC_SEARCH_FREETEXT)) { |
||||||
71 | $searchfreetext = self::$decoder->getElementContent(); |
||||||
72 | $cpo->SetSearchFreeText($searchfreetext); |
||||||
0 ignored issues
–
show
The method
SetSearchFreeText() does not exist on ContentParameters . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
73 | if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_FREETEXT |
||||||
74 | return false; |
||||||
75 | } |
||||||
76 | } |
||||||
77 | |||||||
78 | // TODO - review |
||||||
79 | if (self::$decoder->getElementStartTag(SYNC_SEARCH_GREATERTHAN)) { |
||||||
80 | if (self::$decoder->getElementStartTag(SYNC_POOMMAIL_DATERECEIVED)) { |
||||||
81 | $datereceivedgreater = true; |
||||||
82 | if (($dam = self::$decoder->getElementContent()) !== false) { |
||||||
0 ignored issues
–
show
|
|||||||
83 | $datereceivedgreater = true; |
||||||
84 | if (!self::$decoder->getElementEndTag()) { |
||||||
85 | return false; |
||||||
86 | } |
||||||
87 | } |
||||||
88 | $cpo->SetSearchDateReceivedGreater($datereceivedgreater); |
||||||
0 ignored issues
–
show
The method
SetSearchDateReceivedGreater() does not exist on ContentParameters . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
89 | } |
||||||
90 | |||||||
91 | if (self::$decoder->getElementStartTag(SYNC_SEARCH_VALUE)) { |
||||||
92 | $searchvalue = self::$decoder->getElementContent(); |
||||||
93 | $cpo->SetSearchValueGreater($searchvalue); |
||||||
0 ignored issues
–
show
The method
SetSearchValueGreater() does not exist on ContentParameters . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
94 | if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_VALUE |
||||||
95 | return false; |
||||||
96 | } |
||||||
97 | } |
||||||
98 | |||||||
99 | if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_GREATERTHAN |
||||||
100 | return false; |
||||||
101 | } |
||||||
102 | } |
||||||
103 | |||||||
104 | if (self::$decoder->getElementStartTag(SYNC_SEARCH_LESSTHAN)) { |
||||||
105 | if (self::$decoder->getElementStartTag(SYNC_POOMMAIL_DATERECEIVED)) { |
||||||
106 | $datereceivedless = true; |
||||||
107 | if (($dam = self::$decoder->getElementContent()) !== false) { |
||||||
108 | $datereceivedless = true; |
||||||
109 | if (!self::$decoder->getElementEndTag()) { |
||||||
110 | return false; |
||||||
111 | } |
||||||
112 | } |
||||||
113 | $cpo->SetSearchDateReceivedLess($datereceivedless); |
||||||
0 ignored issues
–
show
The method
SetSearchDateReceivedLess() does not exist on ContentParameters . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
114 | } |
||||||
115 | |||||||
116 | if (self::$decoder->getElementStartTag(SYNC_SEARCH_VALUE)) { |
||||||
117 | $searchvalue = self::$decoder->getElementContent(); |
||||||
118 | $cpo->SetSearchValueLess($searchvalue); |
||||||
0 ignored issues
–
show
The method
SetSearchValueLess() does not exist on ContentParameters . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
119 | if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_VALUE |
||||||
120 | return false; |
||||||
121 | } |
||||||
122 | } |
||||||
123 | |||||||
124 | if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_LESSTHAN |
||||||
125 | return false; |
||||||
126 | } |
||||||
127 | } |
||||||
128 | |||||||
129 | if (self::$decoder->getElementStartTag(SYNC_SEARCH_FREETEXT)) { |
||||||
130 | $searchfreetext = self::$decoder->getElementContent(); |
||||||
131 | $cpo->SetSearchFreeText($searchfreetext); |
||||||
132 | if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_FREETEXT |
||||||
133 | return false; |
||||||
134 | } |
||||||
135 | } |
||||||
136 | |||||||
137 | if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_AND |
||||||
138 | return false; |
||||||
139 | } |
||||||
140 | } |
||||||
141 | elseif (self::$decoder->getElementStartTag(SYNC_SEARCH_EQUALTO)) { |
||||||
142 | // linkid can be an empty tag as well as have value |
||||||
143 | if (self::$decoder->getElementStartTag(SYNC_DOCUMENTLIBRARY_LINKID)) { |
||||||
144 | if (($linkId = self::$decoder->getElementContent()) !== false) { |
||||||
145 | $cpo->SetLinkId($linkId); |
||||||
0 ignored issues
–
show
The method
SetLinkId() does not exist on ContentParameters . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
146 | if (!self::$decoder->getElementEndTag()) { // SYNC_DOCUMENTLIBRARY_LINKID |
||||||
147 | return false; |
||||||
148 | } |
||||||
149 | } |
||||||
150 | } |
||||||
151 | |||||||
152 | if (self::$decoder->getElementStartTag(SYNC_SEARCH_VALUE)) { |
||||||
153 | $searchvalue = self::$decoder->getElementContent(); |
||||||
154 | $cpo->SetSearchValueEqualTo($searchvalue); |
||||||
0 ignored issues
–
show
The method
SetSearchValueEqualTo() does not exist on ContentParameters . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
155 | if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_VALUE |
||||||
156 | return false; |
||||||
157 | } |
||||||
158 | } |
||||||
159 | |||||||
160 | if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_EQUALTO |
||||||
161 | return false; |
||||||
162 | } |
||||||
163 | } |
||||||
164 | |||||||
165 | if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_QUERY |
||||||
166 | return false; |
||||||
167 | } |
||||||
168 | } |
||||||
169 | |||||||
170 | if (self::$decoder->getElementStartTag(SYNC_SEARCH_OPTIONS)) { |
||||||
171 | WBXMLDecoder::ResetInWhile("searchOptions"); |
||||||
172 | while (WBXMLDecoder::InWhile("searchOptions")) { |
||||||
173 | if (self::$decoder->getElementStartTag(SYNC_SEARCH_RANGE)) { |
||||||
174 | $searchrange = self::$decoder->getElementContent(); |
||||||
175 | $cpo->SetSearchRange($searchrange); |
||||||
0 ignored issues
–
show
The method
SetSearchRange() does not exist on ContentParameters . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
176 | if (!self::$decoder->getElementEndTag()) { |
||||||
177 | return false; |
||||||
178 | } |
||||||
179 | } |
||||||
180 | |||||||
181 | if (self::$decoder->getElementStartTag(SYNC_SEARCH_REBUILDRESULTS)) { |
||||||
182 | $rebuildresults = true; |
||||||
183 | if (($dam = self::$decoder->getElementContent()) !== false) { |
||||||
184 | $rebuildresults = true; |
||||||
185 | if (!self::$decoder->getElementEndTag()) { |
||||||
186 | return false; |
||||||
187 | } |
||||||
188 | } |
||||||
189 | $cpo->SetSearchRebuildResults($rebuildresults); |
||||||
0 ignored issues
–
show
The method
SetSearchRebuildResults() does not exist on ContentParameters . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
190 | } |
||||||
191 | |||||||
192 | if (self::$decoder->getElementStartTag(SYNC_SEARCH_DEEPTRAVERSAL)) { |
||||||
193 | $deeptraversal = true; |
||||||
194 | if (($dam = self::$decoder->getElementContent()) !== false) { |
||||||
195 | $deeptraversal = true; |
||||||
196 | if (!self::$decoder->getElementEndTag()) { |
||||||
197 | return false; |
||||||
198 | } |
||||||
199 | } |
||||||
200 | $cpo->SetSearchDeepTraversal($deeptraversal); |
||||||
0 ignored issues
–
show
The method
SetSearchDeepTraversal() does not exist on ContentParameters . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
201 | } |
||||||
202 | |||||||
203 | if (self::$decoder->getElementStartTag(SYNC_MIMESUPPORT)) { |
||||||
204 | $cpo->SetMimeSupport(self::$decoder->getElementContent()); |
||||||
0 ignored issues
–
show
The method
SetMimeSupport() does not exist on ContentParameters . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
205 | if (!self::$decoder->getElementEndTag()) { |
||||||
206 | return false; |
||||||
207 | } |
||||||
208 | } |
||||||
209 | |||||||
210 | // TODO body preferences |
||||||
211 | while (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_BODYPREFERENCE)) { |
||||||
212 | if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TYPE)) { |
||||||
213 | $bptype = self::$decoder->getElementContent(); |
||||||
214 | $cpo->BodyPreference($bptype); |
||||||
215 | if (!self::$decoder->getElementEndTag()) { |
||||||
216 | return false; |
||||||
217 | } |
||||||
218 | } |
||||||
219 | |||||||
220 | if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TRUNCATIONSIZE)) { |
||||||
221 | $cpo->BodyPreference($bptype)->SetTruncationSize(self::$decoder->getElementContent()); |
||||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||||
222 | if (!self::$decoder->getElementEndTag()) { |
||||||
223 | return false; |
||||||
224 | } |
||||||
225 | } |
||||||
226 | |||||||
227 | if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_ALLORNONE)) { |
||||||
228 | $cpo->BodyPreference($bptype)->SetAllOrNone(self::$decoder->getElementContent()); |
||||||
229 | if (!self::$decoder->getElementEndTag()) { |
||||||
230 | return false; |
||||||
231 | } |
||||||
232 | } |
||||||
233 | |||||||
234 | if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_PREVIEW)) { |
||||||
235 | $cpo->BodyPreference($bptype)->SetPreview(self::$decoder->getElementContent()); |
||||||
236 | if (!self::$decoder->getElementEndTag()) { |
||||||
237 | return false; |
||||||
238 | } |
||||||
239 | } |
||||||
240 | |||||||
241 | if (!self::$decoder->getElementEndTag()) { |
||||||
242 | return false; |
||||||
243 | } |
||||||
244 | } |
||||||
245 | |||||||
246 | if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_BODYPARTPREFERENCE)) { |
||||||
247 | if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TYPE)) { |
||||||
248 | $bpptype = self::$decoder->getElementContent(); |
||||||
249 | $cpo->BodyPartPreference($bpptype); |
||||||
250 | if (!self::$decoder->getElementEndTag()) { |
||||||
251 | return false; |
||||||
252 | } |
||||||
253 | } |
||||||
254 | |||||||
255 | if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TRUNCATIONSIZE)) { |
||||||
256 | $cpo->BodyPartPreference($bpptype)->SetTruncationSize(self::$decoder->getElementContent()); |
||||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||||
257 | if (!self::$decoder->getElementEndTag()) { |
||||||
258 | return false; |
||||||
259 | } |
||||||
260 | } |
||||||
261 | |||||||
262 | if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_ALLORNONE)) { |
||||||
263 | $cpo->BodyPartPreference($bpptype)->SetAllOrNone(self::$decoder->getElementContent()); |
||||||
264 | if (!self::$decoder->getElementEndTag()) { |
||||||
265 | return false; |
||||||
266 | } |
||||||
267 | } |
||||||
268 | |||||||
269 | if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_PREVIEW)) { |
||||||
270 | $cpo->BodyPartPreference($bpptype)->SetPreview(self::$decoder->getElementContent()); |
||||||
271 | if (!self::$decoder->getElementEndTag()) { |
||||||
272 | return false; |
||||||
273 | } |
||||||
274 | } |
||||||
275 | |||||||
276 | if (!self::$decoder->getElementEndTag()) { |
||||||
277 | return false; |
||||||
278 | } |
||||||
279 | } |
||||||
280 | |||||||
281 | if (self::$decoder->getElementStartTag(SYNC_RIGHTSMANAGEMENT_SUPPORT)) { |
||||||
282 | $cpo->SetRmSupport(self::$decoder->getElementContent()); |
||||||
0 ignored issues
–
show
The method
SetRmSupport() does not exist on ContentParameters . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
283 | if (!self::$decoder->getElementEndTag()) { |
||||||
284 | return false; |
||||||
285 | } |
||||||
286 | } |
||||||
287 | |||||||
288 | if (self::$decoder->getElementStartTag(SYNC_SEARCH_PICTURE)) { // TODO - do something with maxsize and maxpictures in the backend |
||||||
289 | $searchpicture = new SyncResolveRecipientsPicture(); |
||||||
290 | if (self::$decoder->getElementStartTag(SYNC_SEARCH_MAXSIZE)) { |
||||||
291 | $searchpicture->maxsize = self::$decoder->getElementContent(); |
||||||
292 | if (!self::$decoder->getElementEndTag()) { |
||||||
293 | return false; |
||||||
294 | } |
||||||
295 | } |
||||||
296 | |||||||
297 | if (self::$decoder->getElementStartTag(SYNC_SEARCH_MAXPICTURES)) { |
||||||
298 | $searchpicture->maxpictures = self::$decoder->getElementContent(); |
||||||
299 | if (!self::$decoder->getElementEndTag()) { |
||||||
300 | return false; |
||||||
301 | } |
||||||
302 | } |
||||||
303 | |||||||
304 | // iOs devices send empty picture tag: <Search:Picture/> |
||||||
305 | if (($sp = self::$decoder->getElementContent()) !== false) { |
||||||
0 ignored issues
–
show
|
|||||||
306 | if (!self::$decoder->getElementEndTag()) { |
||||||
307 | return false; |
||||||
308 | } |
||||||
309 | } |
||||||
310 | } |
||||||
311 | |||||||
312 | $e = self::$decoder->peek(); |
||||||
313 | if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { |
||||||
314 | self::$decoder->getElementEndTag(); |
||||||
315 | |||||||
316 | break; |
||||||
317 | } |
||||||
318 | } |
||||||
319 | } |
||||||
320 | if (!self::$decoder->getElementEndTag()) { // store |
||||||
321 | return false; |
||||||
322 | } |
||||||
323 | |||||||
324 | if (!self::$decoder->getElementEndTag()) { // search |
||||||
325 | return false; |
||||||
326 | } |
||||||
327 | |||||||
328 | // get SearchProvider |
||||||
329 | $searchprovider = GSync::GetBackend()->GetSearchProvider(); |
||||||
330 | $status = SYNC_SEARCHSTATUS_SUCCESS; |
||||||
331 | $rows = []; |
||||||
332 | |||||||
333 | // TODO support other searches |
||||||
334 | if ($searchprovider->SupportsType($searchname)) { |
||||||
335 | $storestatus = SYNC_SEARCHSTATUS_STORE_SUCCESS; |
||||||
336 | |||||||
337 | try { |
||||||
338 | if ($searchname == ISearchProvider::SEARCH_GAL) { |
||||||
339 | // get search results from the searchprovider |
||||||
340 | $rows = $searchprovider->GetGALSearchResults($searchquery, $searchrange, $searchpicture); |
||||||
341 | } |
||||||
342 | elseif ($searchname == ISearchProvider::SEARCH_MAILBOX) { |
||||||
343 | $backendFolderId = self::$deviceManager->GetBackendIdForFolderId($cpo->GetSearchFolderid()); |
||||||
0 ignored issues
–
show
The method
GetSearchFolderid() does not exist on ContentParameters . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
344 | $cpo->SetSearchFolderid($backendFolderId); |
||||||
345 | $rows = $searchprovider->GetMailboxSearchResults($cpo); |
||||||
346 | } |
||||||
347 | } |
||||||
348 | catch (StatusException $stex) { |
||||||
349 | $storestatus = $stex->getCode(); |
||||||
350 | } |
||||||
351 | } |
||||||
352 | else { |
||||||
353 | $rows = ['searchtotal' => 0]; |
||||||
354 | $status = SYNC_SEARCHSTATUS_SERVERERROR; |
||||||
355 | SLog::Write(LOGLEVEL_WARN, sprintf("Searchtype '%s' is not supported.", $searchname)); |
||||||
356 | self::$topCollector->AnnounceInformation(sprintf("Unsupported type '%s''", $searchname), true); |
||||||
357 | } |
||||||
358 | $searchprovider->Disconnect(); |
||||||
359 | |||||||
360 | self::$topCollector->AnnounceInformation(sprintf("'%s' search found %d results", $searchname, isset($rows['searchtotal']) ? $rows['searchtotal'] : 0), true); |
||||||
361 | |||||||
362 | self::$encoder->startWBXML(); |
||||||
363 | self::$encoder->startTag(SYNC_SEARCH_SEARCH); |
||||||
364 | |||||||
365 | self::$encoder->startTag(SYNC_SEARCH_STATUS); |
||||||
366 | self::$encoder->content($status); |
||||||
367 | self::$encoder->endTag(); |
||||||
368 | |||||||
369 | if ($status == SYNC_SEARCHSTATUS_SUCCESS) { |
||||||
370 | self::$encoder->startTag(SYNC_SEARCH_RESPONSE); |
||||||
371 | self::$encoder->startTag(SYNC_SEARCH_STORE); |
||||||
372 | |||||||
373 | self::$encoder->startTag(SYNC_SEARCH_STATUS); |
||||||
374 | self::$encoder->content($storestatus); |
||||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||||
375 | self::$encoder->endTag(); |
||||||
376 | |||||||
377 | if (isset($rows['range'])) { |
||||||
378 | $searchrange = $rows['range']; |
||||||
379 | unset($rows['range']); |
||||||
380 | } |
||||||
381 | if (isset($rows['searchtotal'])) { |
||||||
382 | $searchtotal = $rows['searchtotal']; |
||||||
383 | unset($rows['searchtotal']); |
||||||
384 | } |
||||||
385 | if ($searchname == ISearchProvider::SEARCH_GAL) { |
||||||
386 | if (is_array($rows) && !empty($rows)) { |
||||||
387 | foreach ($rows as $u) { |
||||||
388 | self::$encoder->startTag(SYNC_SEARCH_RESULT); |
||||||
389 | self::$encoder->startTag(SYNC_SEARCH_PROPERTIES); |
||||||
390 | |||||||
391 | self::$encoder->startTag(SYNC_GAL_DISPLAYNAME); |
||||||
392 | self::$encoder->content((isset($u[SYNC_GAL_DISPLAYNAME])) ? $u[SYNC_GAL_DISPLAYNAME] : "No name"); |
||||||
393 | self::$encoder->endTag(); |
||||||
394 | |||||||
395 | if (isset($u[SYNC_GAL_PHONE])) { |
||||||
396 | self::$encoder->startTag(SYNC_GAL_PHONE); |
||||||
397 | self::$encoder->content($u[SYNC_GAL_PHONE]); |
||||||
398 | self::$encoder->endTag(); |
||||||
399 | } |
||||||
400 | |||||||
401 | if (isset($u[SYNC_GAL_OFFICE])) { |
||||||
402 | self::$encoder->startTag(SYNC_GAL_OFFICE); |
||||||
403 | self::$encoder->content($u[SYNC_GAL_OFFICE]); |
||||||
404 | self::$encoder->endTag(); |
||||||
405 | } |
||||||
406 | |||||||
407 | if (isset($u[SYNC_GAL_TITLE])) { |
||||||
408 | self::$encoder->startTag(SYNC_GAL_TITLE); |
||||||
409 | self::$encoder->content($u[SYNC_GAL_TITLE]); |
||||||
410 | self::$encoder->endTag(); |
||||||
411 | } |
||||||
412 | |||||||
413 | if (isset($u[SYNC_GAL_COMPANY])) { |
||||||
414 | self::$encoder->startTag(SYNC_GAL_COMPANY); |
||||||
415 | self::$encoder->content($u[SYNC_GAL_COMPANY]); |
||||||
416 | self::$encoder->endTag(); |
||||||
417 | } |
||||||
418 | |||||||
419 | if (isset($u[SYNC_GAL_ALIAS])) { |
||||||
420 | self::$encoder->startTag(SYNC_GAL_ALIAS); |
||||||
421 | self::$encoder->content($u[SYNC_GAL_ALIAS]); |
||||||
422 | self::$encoder->endTag(); |
||||||
423 | } |
||||||
424 | |||||||
425 | // Always send the firstname, even empty. Nokia needs this to display the entry |
||||||
426 | self::$encoder->startTag(SYNC_GAL_FIRSTNAME); |
||||||
427 | self::$encoder->content((isset($u[SYNC_GAL_FIRSTNAME])) ? $u[SYNC_GAL_FIRSTNAME] : ""); |
||||||
428 | self::$encoder->endTag(); |
||||||
429 | |||||||
430 | self::$encoder->startTag(SYNC_GAL_LASTNAME); |
||||||
431 | self::$encoder->content((isset($u[SYNC_GAL_LASTNAME])) ? $u[SYNC_GAL_LASTNAME] : "No name"); |
||||||
432 | self::$encoder->endTag(); |
||||||
433 | |||||||
434 | if (isset($u[SYNC_GAL_HOMEPHONE])) { |
||||||
435 | self::$encoder->startTag(SYNC_GAL_HOMEPHONE); |
||||||
436 | self::$encoder->content($u[SYNC_GAL_HOMEPHONE]); |
||||||
437 | self::$encoder->endTag(); |
||||||
438 | } |
||||||
439 | |||||||
440 | if (isset($u[SYNC_GAL_MOBILEPHONE])) { |
||||||
441 | self::$encoder->startTag(SYNC_GAL_MOBILEPHONE); |
||||||
442 | self::$encoder->content($u[SYNC_GAL_MOBILEPHONE]); |
||||||
443 | self::$encoder->endTag(); |
||||||
444 | } |
||||||
445 | |||||||
446 | self::$encoder->startTag(SYNC_GAL_EMAILADDRESS); |
||||||
447 | self::$encoder->content((isset($u[SYNC_GAL_EMAILADDRESS])) ? $u[SYNC_GAL_EMAILADDRESS] : ""); |
||||||
448 | self::$encoder->endTag(); |
||||||
449 | |||||||
450 | if (isset($u[SYNC_GAL_PICTURE])) { |
||||||
451 | self::$encoder->startTag(SYNC_GAL_PICTURE); |
||||||
452 | self::$encoder->startTag(SYNC_GAL_STATUS); |
||||||
453 | self::$encoder->content(SYNC_SEARCHSTATUS_PICTURE_SUCCESS); // FIXME: status code |
||||||
454 | self::$encoder->endTag(); // SYNC_SEARCH_STATUS |
||||||
455 | |||||||
456 | self::$encoder->startTag(SYNC_GAL_DATA); |
||||||
457 | self::$encoder->contentStream($u[SYNC_GAL_PICTURE], false, true); |
||||||
458 | self::$encoder->endTag(); // SYNC_GAL_DATA |
||||||
459 | self::$encoder->endTag(); // SYNC_GAL_PICTURE |
||||||
460 | } |
||||||
461 | |||||||
462 | self::$encoder->endTag(); // result |
||||||
463 | self::$encoder->endTag(); // properties |
||||||
464 | } |
||||||
465 | } |
||||||
466 | } |
||||||
467 | elseif ($searchname == ISearchProvider::SEARCH_MAILBOX) { |
||||||
468 | foreach ($rows as $u) { |
||||||
469 | // TODO: unclear if any clients *require* the folder id where the message is located (it's not available anymore) |
||||||
470 | // $folderid = self::$deviceManager->GetFolderIdForBackendId($u['folderid']); |
||||||
471 | |||||||
472 | self::$encoder->startTag(SYNC_SEARCH_RESULT); |
||||||
473 | self::$encoder->startTag(SYNC_FOLDERTYPE); |
||||||
474 | self::$encoder->content($u['class']); |
||||||
475 | self::$encoder->endTag(); |
||||||
476 | self::$encoder->startTag(SYNC_SEARCH_LONGID); |
||||||
477 | self::$encoder->content($u['longid']); |
||||||
478 | self::$encoder->endTag(); |
||||||
479 | if (isset($searchfolderid)) { |
||||||
480 | self::$encoder->startTag(SYNC_FOLDERID); |
||||||
481 | self::$encoder->content($searchfolderid); |
||||||
482 | self::$encoder->endTag(); |
||||||
483 | } |
||||||
484 | |||||||
485 | self::$encoder->startTag(SYNC_SEARCH_PROPERTIES); |
||||||
486 | $message = self::$backend->Fetch(false, $u['longid'], $cpo); |
||||||
487 | $message->Encode(self::$encoder); |
||||||
488 | |||||||
489 | self::$encoder->endTag(); // result |
||||||
490 | self::$encoder->endTag(); // properties |
||||||
491 | } |
||||||
492 | } |
||||||
493 | // it seems that android 4 requires range and searchtotal |
||||||
494 | // or it won't display the search results |
||||||
495 | if (isset($searchrange)) { |
||||||
496 | self::$encoder->startTag(SYNC_SEARCH_RANGE); |
||||||
497 | self::$encoder->content($searchrange); |
||||||
498 | self::$encoder->endTag(); |
||||||
499 | } |
||||||
500 | if (isset($searchtotal) && $searchtotal > 0) { |
||||||
501 | self::$encoder->startTag(SYNC_SEARCH_TOTAL); |
||||||
502 | self::$encoder->content($searchtotal); |
||||||
503 | self::$encoder->endTag(); |
||||||
504 | } |
||||||
505 | |||||||
506 | self::$encoder->endTag(); // store |
||||||
507 | self::$encoder->endTag(); // response |
||||||
508 | } |
||||||
509 | self::$encoder->endTag(); // search |
||||||
510 | |||||||
511 | return true; |
||||||
512 | } |
||||||
513 | } |
||||||
514 |