PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / 11.1.1
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress v11.1.1
11.1.1 11.1.0 11.0.5 11.0.4 11.0.3 11.0.2 11.0.1 11.0.0 10.11.1 10.11.0 10.10.2 10.10.1 10.10.0 10.9.1 trunk 10.0.0 10.0.1 10.1.0 10.1.1 10.1.2 10.1.3 10.1.4 10.2.0 10.2.1 10.2.2 All 62 releases
← All changes | back/Libraries/Imap2/Roundcube/ResultIndex.php +0 -423 11.0.2 → 11.1.1 View file →
@@ -1,423 +1,0 @@
1 -<?php
2 -
3 -/**
4 - * +-----------------------------------------------------------------------+
5 - * | This file is part of the Roundcube Webmail client |
6 - * | |
7 - * | Copyright (C) The Roundcube Dev Team |
8 - * | Copyright (C) Kolab Systems AG |
9 - * | |
10 - * | Licensed under the GNU General Public License version 3 or |
11 - * | any later version with exceptions for skins & plugins. |
12 - * | See the README file for a full license statement. |
13 - * | |
14 - * | PURPOSE: |
15 - * | SORT/SEARCH/ESEARCH response handler |
16 - * +-----------------------------------------------------------------------+
17 - * | Author: Thomas Bruederli <[email protected]> |
18 - * | Author: Aleksander Machniak <[email protected]> |
19 - * +-----------------------------------------------------------------------+
20 - */
21 -
22 -namespace AcyMailing\Libraries\Imap2\Roundcube;
23 -
24 -/**
25 - * Class for accessing IMAP's SORT/SEARCH/ESEARCH result
26 - *
27 - * @package Framework
28 - * @subpackage Storage
29 - */
30 -class ResultIndex
31 -{
32 - public $incomplete = false;
33 -
34 - protected $raw_data;
35 - protected $mailbox;
36 - protected $meta = [];
37 - protected $params = [];
38 - protected $order = 'ASC';
39 -
40 - const SEPARATOR_ELEMENT = ' ';
41 -
42 -
43 - /**
44 - * Object constructor.
45 - */
46 - public function __construct($mailbox = null, $data = null, $order = null)
47 - {
48 - $this->mailbox = $mailbox;
49 - $this->order = $order == 'DESC' ? 'DESC' : 'ASC';
50 - $this->init($data);
51 - }
52 -
53 - /**
54 - * Initializes object with SORT command response
55 - *
56 - * @param string $data IMAP response string
57 - */
58 - public function init($data = null)
59 - {
60 - $this->meta = [];
61 -
62 - $data = explode('*', (string)$data);
63 -
64 - // ...skip unilateral untagged server responses
65 - for ($i = 0, $len = count($data) ; $i < $len ; $i++) {
66 - $data_item = &$data[$i];
67 - if (preg_match('/^ SORT/i', $data_item)) {
68 - // valid response, initialize raw_data for is_error()
69 - $this->raw_data = '';
70 - $data_item = substr($data_item, 5);
71 - break;
72 - } elseif (preg_match('/^ (E?SEARCH)/i', $data_item, $m)) {
73 - // valid response, initialize raw_data for is_error()
74 - $this->raw_data = '';
75 - $data_item = substr($data_item, strlen($m[0]));
76 -
77 - if (strtoupper($m[1]) == 'ESEARCH') {
78 - $data_item = trim($data_item);
79 - // remove MODSEQ response
80 - if (preg_match('/\(MODSEQ ([0-9]+)\)$/i', $data_item, $m)) {
81 - $data_item = substr($data_item, 0, -strlen($m[0]));
82 - $this->params['MODSEQ'] = $m[1];
83 - }
84 - // remove TAG response part
85 - if (preg_match('/^\(TAG ["a-z0-9]+\)\s*/i', $data_item, $m)) {
86 - $data_item = substr($data_item, strlen($m[0]));
87 - }
88 - // remove UID
89 - $data_item = preg_replace('/^UID\s*/i', '', $data_item);
90 -
91 - // ESEARCH parameters
92 - while (preg_match('/^([a-z]+) ([0-9:,]+)\s*/i', $data_item, $m)) {
93 - $param = strtoupper($m[1]);
94 - $value = $m[2];
95 -
96 - $this->params[$param] = $value;
97 - $data_item = substr($data_item, strlen($m[0]));
98 -
99 - if (in_array($param, ['COUNT', 'MIN', 'MAX'])) {
100 - $this->meta[strtolower($param)] = (int)$value;
101 - }
102 - }
103 -
104 - // @TODO: Implement compression using compressMessageSet() in __sleep() and __wakeup() ?
105 - // @TODO: work with compressed result?!
106 - if (isset($this->params['ALL'])) {
107 - $data_item = implode(
108 - self::SEPARATOR_ELEMENT,
109 - ImapClient::uncompressMessageSet($this->params['ALL'])
110 - );
111 - }
112 - }
113 -
114 - break;
115 - }
116 -
117 - unset($data[$i]);
118 - }
119 -
120 - $data = array_filter($data);
121 -
122 - if (empty($data)) {
123 - return;
124 - }
125 -
126 - $data = array_shift($data);
127 - $data = trim($data);
128 - $data = preg_replace('/[\r\n]/', '', $data);
129 - $data = preg_replace('/\s+/', ' ', $data);
130 -
131 - $this->raw_data = $data;
132 - }
133 -
134 - /**
135 - * Checks the result from IMAP command
136 - *
137 - * @return bool True if the result is an error, False otherwise
138 - */
139 - public function is_error()
140 - {
141 - return $this->raw_data === null;
142 - }
143 -
144 - /**
145 - * Checks if the result is empty
146 - *
147 - * @return bool True if the result is empty, False otherwise
148 - */
149 - public function is_empty()
150 - {
151 - return empty($this->raw_data);
152 - }
153 -
154 - /**
155 - * Returns number of elements in the result
156 - *
157 - * @return int Number of elements
158 - */
159 - public function count()
160 - {
161 - if (isset($this->meta['count']) && $this->meta['count'] !== null) {
162 - return $this->meta['count'];
163 - }
164 -
165 - if (empty($this->raw_data)) {
166 - $this->meta['count'] = 0;
167 - $this->meta['length'] = 0;
168 - } else {
169 - $this->meta['count'] = 1 + substr_count($this->raw_data, self::SEPARATOR_ELEMENT);
170 - }
171 -
172 - return $this->meta['count'];
173 - }
174 -
175 - /**
176 - * Returns number of elements in the result.
177 - * Alias for count() for compatibility with ResultThread
178 - *
179 - * @return int Number of elements
180 - */
181 - public function count_messages()
182 - {
183 - return $this->count();
184 - }
185 -
186 - /**
187 - * Returns maximal message identifier in the result
188 - *
189 - * @return int Maximal message identifier
190 - */
191 - public function max()
192 - {
193 - if (!isset($this->meta['max'])) {
194 - $this->meta['max'] = (int)@max($this->get());
195 - }
196 -
197 - return $this->meta['max'];
198 - }
199 -
200 - /**
201 - * Returns minimal message identifier in the result
202 - *
203 - * @return int Minimal message identifier
204 - */
205 - public function min()
206 - {
207 - if (!isset($this->meta['min'])) {
208 - $this->meta['min'] = (int)@min($this->get());
209 - }
210 -
211 - return $this->meta['min'];
212 - }
213 -
214 - /**
215 - * Slices data set.
216 - *
217 - * @param $offset (as for PHP's array_slice())
218 - * @param $length Number of elements (as for PHP's array_slice())
219 - */
220 - public function slice($offset, $length)
221 - {
222 - $data = $this->get();
223 - $data = array_slice($data, $offset, $length);
224 -
225 - $this->meta = [];
226 - $this->meta['count'] = count($data);
227 - $this->raw_data = implode(self::SEPARATOR_ELEMENT, $data);
228 - }
229 -
230 - /**
231 - * Filters data set. Removes elements not listed in $ids list.
232 - *
233 - * @param array $ids List of IDs to remove.
234 - */
235 - public function filter($ids = [])
236 - {
237 - $data = $this->get();
238 - $data = array_intersect($data, $ids);
239 -
240 - $this->meta = [];
241 - $this->meta['count'] = count($data);
242 - $this->raw_data = implode(self::SEPARATOR_ELEMENT, $data);
243 - }
244 -
245 - /**
246 - * Reverts order of elements in the result
247 - */
248 - public function revert()
249 - {
250 - $this->order = $this->order == 'ASC' ? 'DESC' : 'ASC';
251 -
252 - if (empty($this->raw_data)) {
253 - return;
254 - }
255 -
256 - $data = $this->get();
257 - $data = array_reverse($data);
258 - $this->raw_data = implode(self::SEPARATOR_ELEMENT, $data);
259 -
260 - $this->meta['pos'] = [];
261 - }
262 -
263 - /**
264 - * Check if the given message ID exists in the object
265 - *
266 - * @param int $msgid Message ID
267 - * @param bool $get_index When enabled element's index will be returned.
268 - * Elements are indexed starting with 0
269 - *
270 - * @return mixed False if message ID doesn't exist, True if exists or
271 - * index of the element if $get_index=true
272 - */
273 - public function exists($msgid, $get_index = false)
274 - {
275 - if (empty($this->raw_data)) {
276 - return false;
277 - }
278 -
279 - $msgid = (int)$msgid;
280 - $begin = implode('|', ['^', preg_quote(self::SEPARATOR_ELEMENT, '/')]);
281 - $end = implode('|', ['$', preg_quote(self::SEPARATOR_ELEMENT, '/')]);
282 -
283 - if (preg_match(
284 - "/($begin)$msgid($end)/",
285 - $this->raw_data,
286 - $m,
287 - $get_index ? PREG_OFFSET_CAPTURE : null
288 - )
289 - ) {
290 - if ($get_index) {
291 - $idx = 0;
292 - if ($m[0][1]) {
293 - $idx = 1 + substr_count($this->raw_data, self::SEPARATOR_ELEMENT, 0, $m[0][1]);
294 - }
295 - // cache position of this element, so we can use it in get_element()
296 - $this->meta['pos'][$idx] = (int)$m[0][1];
297 -
298 - return $idx;
299 - }
300 -
301 - return true;
302 - }
303 -
304 - return false;
305 - }
306 -
307 - /**
308 - * Return all messages in the result.
309 - *
310 - * @return array List of message IDs
311 - */
312 - public function get()
313 - {
314 - if (empty($this->raw_data)) {
315 - return [];
316 - }
317 -
318 - return explode(self::SEPARATOR_ELEMENT, $this->raw_data);
319 - }
320 -
321 - /**
322 - * Return result element at specified index
323 - *
324 - * @param int|string $index Element's index or "FIRST" or "LAST"
325 - *
326 - * @return int Element value
327 - */
328 - public function get_element($index)
329 - {
330 - $count = $this->count();
331 -
332 - if (!$count) {
333 - return null;
334 - }
335 -
336 - // first element
337 - if ($index === 0 || $index === '0' || $index === 'FIRST') {
338 - $pos = strpos($this->raw_data, self::SEPARATOR_ELEMENT);
339 - if ($pos === false) {
340 - $result = (int)$this->raw_data;
341 - } else {
342 - $result = (int)substr($this->raw_data, 0, $pos);
343 - }
344 -
345 - return $result;
346 - }
347 -
348 - // last element
349 - if ($index === 'LAST' || $index == $count - 1) {
350 - $pos = strrpos($this->raw_data, self::SEPARATOR_ELEMENT);
351 - if ($pos === false) {
352 - $result = (int)$this->raw_data;
353 - } else {
354 - $result = (int)substr($this->raw_data, $pos);
355 - }
356 -
357 - return $result;
358 - }
359 -
360 - // do we know the position of the element or the neighbour of it?
361 - if (!empty($this->meta['pos'])) {
362 - if (isset($this->meta['pos'][$index])) {
363 - $pos = $this->meta['pos'][$index];
364 - } elseif (isset($this->meta['pos'][$index - 1])) {
365 - $pos = strpos(
366 - $this->raw_data,
367 - self::SEPARATOR_ELEMENT,
368 - $this->meta['pos'][$index - 1] + 1
369 - );
370 - } elseif (isset($this->meta['pos'][$index + 1])) {
371 - $pos = strrpos(
372 - $this->raw_data,
373 - self::SEPARATOR_ELEMENT,
374 - $this->meta['pos'][$index + 1] - $this->length() - 1
375 - );
376 - }
377 -
378 - if (isset($pos) && preg_match('/([0-9]+)/', $this->raw_data, $m, null, $pos)) {
379 - return (int)$m[1];
380 - }
381 - }
382 -
383 - // Finally use less effective method
384 - $data = explode(self::SEPARATOR_ELEMENT, $this->raw_data);
385 -
386 - return $data[$index];
387 - }
388 -
389 - /**
390 - * Returns response parameters, e.g. ESEARCH's MIN/MAX/COUNT/ALL/MODSEQ
391 - * or internal data e.g. MAILBOX, ORDER
392 - *
393 - * @param string $param Parameter name
394 - *
395 - * @return array|string Response parameters or parameter value
396 - */
397 - public function get_parameters($param = null)
398 - {
399 - $params = $this->params;
400 - $params['MAILBOX'] = $this->mailbox;
401 - $params['ORDER'] = $this->order;
402 -
403 - if ($param !== null) {
404 - return $params[$param];
405 - }
406 -
407 - return $params;
408 - }
409 -
410 - /**
411 - * Returns length of internal data representation
412 - *
413 - * @return int Data length
414 - */
415 - protected function length()
416 - {
417 - if (!isset($this->meta['length'])) {
418 - $this->meta['length'] = strlen($this->raw_data);
419 - }
420 -
421 - return $this->meta['length'];
422 - }
423 -}