1 | <?php |
||||||
2 | /** |
||||||
3 | * EGroupware - Mail - interface class for activesync implementation |
||||||
4 | * |
||||||
5 | * @link http://www.egroupware.org |
||||||
6 | * @package mail |
||||||
7 | * @author EGroupware GmbH [[email protected]] |
||||||
8 | * @author Ralf Becker <[email protected]> |
||||||
9 | * @author Philip Herbert <[email protected]> |
||||||
10 | * @copyright (c) 2014-16 by EGroupware GmbH <info-AT-egroupware.org> |
||||||
11 | * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License |
||||||
12 | * @version $Id$ |
||||||
13 | */ |
||||||
14 | |||||||
15 | use EGroupware\Api; |
||||||
16 | use EGroupware\Api\Mail; |
||||||
0 ignored issues
–
show
|
|||||||
17 | |||||||
18 | /** |
||||||
19 | * mail eSync plugin |
||||||
20 | * |
||||||
21 | * Plugin creates a device specific file to map alphanumeric folder names to nummeric id's. |
||||||
22 | */ |
||||||
23 | class mail_zpush implements activesync_plugin_write, activesync_plugin_sendmail, activesync_plugin_meeting_response, activesync_plugin_search_mailbox |
||||||
0 ignored issues
–
show
The type
activesync_plugin_meeting_response was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths ![]() The type
activesync_plugin_search_mailbox was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths ![]() The type
activesync_plugin_sendmail was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths ![]() |
|||||||
24 | { |
||||||
25 | /** |
||||||
26 | * var activesync_backend |
||||||
27 | */ |
||||||
28 | private $backend; |
||||||
29 | |||||||
30 | /** |
||||||
31 | * Instance of Mail |
||||||
32 | * |
||||||
33 | * @var Mail |
||||||
34 | */ |
||||||
35 | private $mail; |
||||||
36 | |||||||
37 | /** |
||||||
38 | * Provides the ability to change the line ending |
||||||
39 | * @var string |
||||||
40 | */ |
||||||
41 | public static $LE = "\n"; |
||||||
42 | |||||||
43 | /** |
||||||
44 | * Integer id of trash folder |
||||||
45 | * |
||||||
46 | * @var mixed |
||||||
47 | */ |
||||||
48 | private $_wasteID = false; |
||||||
49 | |||||||
50 | /** |
||||||
51 | * Integer id of sent folder |
||||||
52 | * |
||||||
53 | * @var mixed |
||||||
54 | */ |
||||||
55 | private $_sentID = false; |
||||||
56 | |||||||
57 | /** |
||||||
58 | * Integer id of current mail account / connection |
||||||
59 | * |
||||||
60 | * @var int |
||||||
61 | */ |
||||||
62 | private $account; |
||||||
63 | |||||||
64 | private $folders; |
||||||
65 | |||||||
66 | private $messages; |
||||||
0 ignored issues
–
show
|
|||||||
67 | |||||||
68 | static $profileID; |
||||||
69 | |||||||
70 | // to control how deep one may dive into the past |
||||||
71 | const PAST_LIMIT = 178; |
||||||
72 | |||||||
73 | /** |
||||||
74 | * debugLevel - enables more debug |
||||||
75 | * |
||||||
76 | * @var int |
||||||
77 | */ |
||||||
78 | private $debugLevel = 0; |
||||||
79 | |||||||
80 | /** |
||||||
81 | * Constructor |
||||||
82 | * |
||||||
83 | * @param activesync_backend $backend |
||||||
84 | */ |
||||||
85 | public function __construct(activesync_backend $backend) |
||||||
0 ignored issues
–
show
The type
activesync_backend was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths ![]() |
|||||||
86 | { |
||||||
87 | if ($GLOBALS['egw_setup']) return; |
||||||
88 | |||||||
89 | //$this->debugLevel=2; |
||||||
90 | $this->backend = $backend; |
||||||
91 | if (!isset($GLOBALS['egw_info']['user']['preferences']['activesync']['mail-ActiveSyncProfileID'])) |
||||||
92 | { |
||||||
93 | if ($this->debugLevel>1) error_log(__METHOD__.__LINE__.' Noprefs set: using 0 as default'); |
||||||
94 | // globals preferences add appname varname value |
||||||
95 | $GLOBALS['egw']->preferences->add('activesync','mail-ActiveSyncProfileID',0,'user'); |
||||||
96 | // save prefs |
||||||
97 | $GLOBALS['egw']->preferences->save_repository(true); |
||||||
98 | } |
||||||
99 | if ($this->debugLevel>1) error_log(__METHOD__.__LINE__.' ActiveProfileID:'.array2string(self::$profileID)); |
||||||
100 | |||||||
101 | if (is_null(self::$profileID)) |
||||||
102 | { |
||||||
103 | if ($this->debugLevel>1) error_log(__METHOD__.__LINE__.' self::ProfileID isNUll:'.array2string(self::$profileID)); |
||||||
104 | self::$profileID =& Api\Cache::getSession('mail','activeSyncProfileID'); |
||||||
105 | if ($this->debugLevel>1) error_log(__METHOD__.__LINE__.' ActiveProfileID (after reading Cache):'.array2string(self::$profileID)); |
||||||
106 | } |
||||||
107 | if (isset($GLOBALS['egw_info']['user']['preferences']['activesync']['mail-ActiveSyncProfileID'])) |
||||||
108 | { |
||||||
109 | if ($this->debugLevel>1) error_log(__METHOD__.__LINE__.' Pref for ProfileID:'.array2string($GLOBALS['egw_info']['user']['preferences']['activesync']['mail-ActiveSyncProfileID'])); |
||||||
110 | if ($GLOBALS['egw_info']['user']['preferences']['activesync']['mail-ActiveSyncProfileID'] == 'G') |
||||||
111 | { |
||||||
112 | self::$profileID = 'G'; // this should trigger the fetch of the first negative profile (or if no negative profile is available the firstb there is) |
||||||
113 | } |
||||||
114 | else |
||||||
115 | { |
||||||
116 | self::$profileID = (int)$GLOBALS['egw_info']['user']['preferences']['activesync']['mail-ActiveSyncProfileID']; |
||||||
117 | } |
||||||
118 | } |
||||||
119 | if ($this->debugLevel>1) error_log(__METHOD__.__LINE__.' Profile Selected (after reading Prefs):'.array2string(self::$profileID)); |
||||||
120 | |||||||
121 | // verify we are on an existing profile, if not running in setup (settings can not be static according to interface!) |
||||||
122 | if (!isset($GLOBALS['egw_setup'])) |
||||||
123 | { |
||||||
124 | try { |
||||||
125 | Mail\Account::read(self::$profileID); |
||||||
126 | } |
||||||
127 | catch(Exception $e) { |
||||||
128 | unset($e); |
||||||
129 | self::$profileID = Mail\Account::get_default_acc_id(); |
||||||
130 | } |
||||||
131 | } |
||||||
132 | if ($this->debugLevel>0) error_log(__METHOD__.'::'.__LINE__.' ProfileSelected:'.self::$profileID); |
||||||
133 | //$this->debugLevel=0; |
||||||
134 | } |
||||||
135 | |||||||
136 | /** |
||||||
137 | * Populates $settings for the preferences |
||||||
138 | * |
||||||
139 | * @param array|string $hook_data |
||||||
140 | * @return array |
||||||
141 | */ |
||||||
142 | function egw_settings($hook_data) |
||||||
143 | { |
||||||
144 | //error_log(__METHOD__.__LINE__.array2string($hook_data)); |
||||||
145 | $identities = array(); |
||||||
146 | if (!isset($hook_data['setup']) && in_array($hook_data['type'], array('user', 'group'))) |
||||||
147 | { |
||||||
148 | $identities = iterator_to_array(Mail\Account::search((int)$hook_data['account_id'])); |
||||||
149 | } |
||||||
150 | $identities += array( |
||||||
151 | 'G' => lang('Primary Profile'), |
||||||
152 | ); |
||||||
153 | |||||||
154 | $settings['mail-ActiveSyncProfileID'] = array( |
||||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||||
155 | 'type' => 'select', |
||||||
156 | 'label' => 'eMail Account to sync', |
||||||
157 | 'name' => 'mail-ActiveSyncProfileID', |
||||||
158 | 'help' => 'eMail Account to sync ', |
||||||
159 | 'values' => $identities, |
||||||
160 | 'default'=> 'G', |
||||||
161 | 'xmlrpc' => True, |
||||||
162 | 'admin' => False, |
||||||
163 | ); |
||||||
164 | $settings['mail-allowSendingInvitations'] = array( |
||||||
165 | 'type' => 'select', |
||||||
166 | 'label' => 'allow sending of calendar invitations using this profile?', |
||||||
167 | 'name' => 'mail-allowSendingInvitations', |
||||||
168 | 'help' => 'control the sending of calendar invitations while using this profile', |
||||||
169 | 'values' => array( |
||||||
170 | 'sendifnocalnotif'=>'only send if there is no notification in calendar', |
||||||
171 | 'send'=>'yes, always send', |
||||||
172 | 'nosend'=>'no, do not send', |
||||||
173 | ), |
||||||
174 | 'xmlrpc' => True, |
||||||
175 | 'default' => 'sendifnocalnotif', |
||||||
176 | 'admin' => False, |
||||||
177 | ); |
||||||
178 | $settings['mail-maximumSyncRange'] = array( |
||||||
179 | 'type' => 'integer', |
||||||
180 | 'label' => lang('How many days to sync in the past when client does not specify a date-range (default %1)', self::PAST_LIMIT), |
||||||
0 ignored issues
–
show
The call to
lang() has too many arguments starting with self::PAST_LIMIT .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. ![]() |
|||||||
181 | 'name' => 'mail-maximumSyncRange', |
||||||
182 | 'help' => 'if the client sets no sync range, you may override the setting (preventing client crash that may be caused by too many mails/too much data). If you want to sync way-back into the past: set a large number', |
||||||
183 | 'xmlrpc' => True, |
||||||
184 | 'admin' => False, |
||||||
185 | ); |
||||||
186 | |||||||
187 | /* |
||||||
188 | $sigOptions = array( |
||||||
189 | 'send'=>'yes, always add EGroupware signatures to outgoing mails', |
||||||
190 | 'nosend'=>'no, never add EGroupware signatures to outgoing mails', |
||||||
191 | ); |
||||||
192 | if (!isset($hook_data['setup']) && in_array($hook_data['type'], array('user', 'group'))&&$hook_data['account_id']) |
||||||
193 | { |
||||||
194 | $pID=self::$profileID; |
||||||
195 | if ($GLOBALS['egw_info']['user']['preferences']['activesync']['mail-ActiveSyncProfileID']=='G') |
||||||
196 | { |
||||||
197 | $pID=Mail\Account::get_default_acc_id(); |
||||||
198 | } |
||||||
199 | $acc = Mail\Account::read($pID); |
||||||
200 | error_log(__METHOD__.__LINE__.':'.$pID.'->'.array2string($acc)); |
||||||
201 | $Identities = Mail\Account::identities($pID); |
||||||
202 | foreach($Identities as &$identity) |
||||||
203 | { |
||||||
204 | $Identity = self::identity_name($identity); |
||||||
205 | } |
||||||
206 | error_log(__METHOD__.__LINE__.array2string($Identities)); |
||||||
207 | } |
||||||
208 | $settings['mail-useSignature'] = array( |
||||||
209 | 'type' => 'select', |
||||||
210 | 'label' => 'control if and which available signature is added to outgoing mails', |
||||||
211 | 'name' => 'mail-useSignature', |
||||||
212 | 'help' => 'control the use of signatures', |
||||||
213 | 'values' => $sigOptions, |
||||||
214 | 'xmlrpc' => True, |
||||||
215 | 'default' => 'nosend', |
||||||
216 | 'admin' => False, |
||||||
217 | ); |
||||||
218 | */ |
||||||
219 | return $settings; |
||||||
220 | } |
||||||
221 | |||||||
222 | /** |
||||||
223 | * Verify preferences |
||||||
224 | * |
||||||
225 | * @param array|string $hook_data |
||||||
226 | * @return array with error-messages from all plugins |
||||||
227 | */ |
||||||
228 | function verify_settings($hook_data) |
||||||
229 | { |
||||||
230 | $errors = array(); |
||||||
231 | |||||||
232 | // check if an eSync eMail profile is set (might not be set as default or forced!) |
||||||
233 | if (isset($hook_data['prefs']['mail-ActiveSyncProfileID']) || $hook_data['type'] == 'user') |
||||||
234 | { |
||||||
235 | // eSync and eMail translations are not (yet) loaded |
||||||
236 | Api\Translation::add_app('activesync'); |
||||||
237 | Api\Translation::add_app('mail'); |
||||||
238 | |||||||
239 | // inject preference to verify and call constructor |
||||||
240 | $GLOBALS['egw_info']['user']['preferences']['activesync']['mail-ActiveSyncProfileID'] = |
||||||
241 | $hook_data['prefs']['mail-ActiveSyncProfileID']; |
||||||
242 | $this->__construct($this->backend); |
||||||
243 | |||||||
244 | try { |
||||||
245 | $this->_connect(0,true); |
||||||
0 ignored issues
–
show
The call to
mail_zpush::_connect() has too many arguments starting with true .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. ![]() |
|||||||
246 | $this->_disconnect(); |
||||||
247 | |||||||
248 | if (!$this->_wasteID) $errors[] = lang('No valid %1 folder configured!', '<b>'.lang('trash').'</b>'); |
||||||
0 ignored issues
–
show
The call to
lang() has too many arguments starting with '<b>' . lang('trash') . '</b>' .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. ![]() |
|||||||
249 | if (!$this->_sentID) $errors[] = lang('No valid %1 folder configured!', '<b>'.lang('send').'</b>'); |
||||||
250 | } |
||||||
251 | catch(Exception $e) { |
||||||
252 | $errors[] = lang('Can not open IMAP connection').': '.$e->getMessage(); |
||||||
253 | } |
||||||
254 | if ($errors) |
||||||
255 | { |
||||||
256 | $errors[] = '<b>'.lang('eSync will FAIL without a working eMail configuration!').'</b>'; |
||||||
257 | } |
||||||
258 | } |
||||||
259 | //error_log(__METHOD__.'('.array2string($hook_data).') returning '.array2string($errors)); |
||||||
260 | return $errors; |
||||||
261 | } |
||||||
262 | |||||||
263 | /** |
||||||
264 | * Open IMAP connection |
||||||
265 | * |
||||||
266 | * @param int $account integer id of account to use |
||||||
267 | * @todo support different accounts |
||||||
268 | */ |
||||||
269 | private function _connect($account=0) |
||||||
270 | { |
||||||
271 | if (!$account) $account = self::$profileID ? self::$profileID : 0; |
||||||
272 | if ($this->mail && $this->account != $account) $this->_disconnect(); |
||||||
273 | |||||||
274 | $this->_wasteID = false; |
||||||
275 | $this->_sentID = false; |
||||||
276 | |||||||
277 | if (!$this->mail) |
||||||
278 | { |
||||||
279 | $this->account = $account; |
||||||
280 | // todo: tell mail which account to use |
||||||
281 | //error_log(__METHOD__.__LINE__.' create object with ProfileID:'.array2string(self::$profileID)); |
||||||
282 | $this->mail = Mail::getInstance(false,self::$profileID,true,false,true); |
||||||
283 | if (self::$profileID == 0 && isset($this->mail->icServer->ImapServerId) && !empty($this->mail->icServer->ImapServerId)) self::$profileID = $this->mail->icServer->ImapServerId; |
||||||
284 | } |
||||||
285 | else |
||||||
286 | { |
||||||
287 | //error_log(__METHOD__.__LINE__." connect with profileID: ".self::$profileID); |
||||||
288 | if (self::$profileID == 0 && isset($this->mail->icServer->ImapServerId) && !empty($this->mail->icServer->ImapServerId)) self::$profileID = $this->mail->icServer->ImapServerId; |
||||||
289 | } |
||||||
290 | $this->mail->openConnection(self::$profileID,false); |
||||||
0 ignored issues
–
show
The call to
EGroupware\Api\Mail::openConnection() has too many arguments starting with false .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. ![]() |
|||||||
291 | |||||||
292 | $this->_wasteID = $this->mail->getTrashFolder(false); |
||||||
293 | //error_log(__METHOD__.__LINE__.' TrashFolder:'.$this->_wasteID); |
||||||
294 | $this->_sentID = $this->mail->getSentFolder(false); |
||||||
295 | $this->mail->getOutboxFolder(true); |
||||||
296 | //error_log(__METHOD__.__LINE__.' SentFolder:'.$this->_sentID); |
||||||
297 | //error_log(__METHOD__.__LINE__.' Connection Status for ProfileID:'.self::$profileID.'->'.$this->mail->icServer->_connected); |
||||||
298 | } |
||||||
299 | |||||||
300 | /** |
||||||
301 | * Close IMAP connection |
||||||
302 | */ |
||||||
303 | private function _disconnect() |
||||||
304 | { |
||||||
305 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__); |
||||||
306 | if ($this->mail) $this->mail->closeConnection(); |
||||||
307 | |||||||
308 | unset($this->mail); |
||||||
309 | unset($this->account); |
||||||
310 | unset($this->folders); |
||||||
311 | } |
||||||
312 | |||||||
313 | /** |
||||||
314 | * GetFolderList |
||||||
315 | * |
||||||
316 | * @ToDo loop over available email accounts |
||||||
317 | */ |
||||||
318 | public function GetFolderList() |
||||||
319 | { |
||||||
320 | $folderlist = array(); |
||||||
321 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__); |
||||||
322 | /*foreach($available_accounts as $account)*/ $account = 0; |
||||||
323 | { |
||||||
324 | $this->_connect($account); |
||||||
325 | if (!isset($this->folders)) $this->folders = $this->mail->getFolderObjects(true,false,$_alwaysGetDefaultFolders=true); |
||||||
326 | if ($this->debugLevel>1) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.array2string($this->folders)); |
||||||
327 | |||||||
328 | foreach ($this->folders as $folder => $folderObj) { |
||||||
329 | if ($this->debugLevel>1) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' folder='.$folder); |
||||||
330 | $folderlist[] = $f = array( |
||||||
331 | 'id' => $this->createID($account,$folder), |
||||||
332 | 'mod' => $folderObj->shortDisplayName, |
||||||
333 | 'parent' => $this->getParentID($account,$folder), |
||||||
334 | ); |
||||||
335 | if ($this->debugLevel>1) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."() returning ".array2string($f)); |
||||||
336 | } |
||||||
337 | } |
||||||
338 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."() returning ".array2string($folderlist)); |
||||||
339 | |||||||
340 | return $folderlist; |
||||||
341 | } |
||||||
342 | |||||||
343 | /** |
||||||
344 | * Sends a message which is passed as rfc822. You basically can do two things |
||||||
345 | * 1) Send the message to an SMTP server as-is |
||||||
346 | * 2) Parse the message yourself, and send it some other way |
||||||
347 | * It is up to you whether you want to put the message in the sent items folder. If you |
||||||
348 | * want it in 'sent items', then the next sync on the 'sent items' folder should return |
||||||
349 | * the new message as any other new message in a folder. |
||||||
350 | * |
||||||
351 | * @param array $smartdata = IMAP-SendMail: SyncSendMail ( |
||||||
352 | * (S) clientid => SendMail-30722448149304 |
||||||
353 | * (S) saveinsent => empty |
||||||
354 | * (S) replacemime => null |
||||||
355 | * (S) accountid => null |
||||||
356 | * (S) source => SyncSendMailSource ( |
||||||
357 | * (S) folderid => 101000000000 |
||||||
358 | * (S) itemid => 33776 |
||||||
359 | * (S) longid => null |
||||||
360 | * (S) instanceid => null |
||||||
361 | * unsetVars(Array) size: 0 |
||||||
362 | * flags => false |
||||||
363 | * content => null |
||||||
364 | * ) |
||||||
365 | * (S) mime => Date: Tue, 23 Jun 2015 14:13:23 +0200 |
||||||
366 | *Subject: AW: Blauer himmel |
||||||
367 | *.... |
||||||
368 | * (S) replyflag => true |
||||||
369 | * (S) forwardflag => null |
||||||
370 | * unsetVars(Array) size: 0 |
||||||
371 | * flags => false |
||||||
372 | * content => null |
||||||
373 | *) |
||||||
374 | * |
||||||
375 | * @return boolean true on success, false on error |
||||||
376 | * |
||||||
377 | * @see eg. BackendIMAP::SendMail() |
||||||
378 | * @todo implement either here or in mail backend |
||||||
379 | * (maybe sending here and storing to sent folder in plugin, as sending is supposed to always work in EGroupware) |
||||||
380 | */ |
||||||
381 | public function SendMail($smartdata) |
||||||
382 | { |
||||||
383 | //$this->debugLevel=2; |
||||||
384 | $ClientSideMeetingRequest = false; |
||||||
385 | $allowSendingInvitations = 'sendifnocalnotif'; |
||||||
386 | if (isset($GLOBALS['egw_info']['user']['preferences']['activesync']['mail-allowSendingInvitations']) && |
||||||
387 | $GLOBALS['egw_info']['user']['preferences']['activesync']['mail-allowSendingInvitations']=='nosend') |
||||||
388 | { |
||||||
389 | $allowSendingInvitations = false; |
||||||
390 | } |
||||||
391 | elseif (isset($GLOBALS['egw_info']['user']['preferences']['activesync']['mail-allowSendingInvitations']) && |
||||||
392 | $GLOBALS['egw_info']['user']['preferences']['activesync']['mail-allowSendingInvitations']!='nosend') |
||||||
393 | { |
||||||
394 | $allowSendingInvitations = $GLOBALS['egw_info']['user']['preferences']['activesync']['mail-allowSendingInvitations']; |
||||||
395 | } |
||||||
396 | $smartdata_task = ($smartdata->replyflag?'reply':($smartdata->forwardflag?'forward':'new')); |
||||||
397 | |||||||
398 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__ . (isset($smartdata->mime) ? $smartdata->mime : ""). "task: ".(isset($smartdata_task) ? $smartdata_task : "")." itemid: ".(isset($smartdata->source->itemid) ? $smartdata->source->itemid : "")." folder: ".(isset($smartdata->source->folderid) ? $smartdata->source->folderid : "")); |
||||||
399 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__."): Smartdata = ".array2string($smartdata)); |
||||||
400 | //error_log("IMAP-Sendmail: Smartdata = ".array2string($smartdata)); |
||||||
401 | |||||||
402 | // initialize our Mail |
||||||
403 | if (!isset($this->mail)) $this->mail = Mail::getInstance(false,self::$profileID,true,false,true); |
||||||
404 | $activeMailProfiles = $this->mail->getAccountIdentities(self::$profileID); |
||||||
405 | // use the standardIdentity |
||||||
406 | $activeMailProfile = Mail::getStandardIdentityForProfile($activeMailProfiles,self::$profileID); |
||||||
407 | |||||||
408 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__.")".' ProfileID:'.self::$profileID.' ActiveMailProfile:'.array2string($activeMailProfile)); |
||||||
409 | // collect identity / signature for later usage, and to determine if we may have to manipulate TransferEncoding and Charset |
||||||
410 | try |
||||||
411 | { |
||||||
412 | $acc = Mail\Account::read($this->mail->icServer->ImapServerId); |
||||||
413 | //error_log(__METHOD__.__LINE__.array2string($acc)); |
||||||
414 | $_signature = Mail\Account::read_identity($acc['ident_id'],true); |
||||||
415 | } |
||||||
416 | catch (Exception $e) |
||||||
417 | { |
||||||
418 | $_signature=array(); |
||||||
419 | } |
||||||
420 | $signature = $_signature['ident_signature']; |
||||||
421 | if ((isset($preferencesArray['disableRulerForSignatureSeparation']) && |
||||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||||
422 | $preferencesArray['disableRulerForSignatureSeparation']) || |
||||||
423 | empty($signature) || trim(Api\Mail\Html::convertHTMLToText($signature)) =='') |
||||||
424 | { |
||||||
425 | $disableRuler = true; |
||||||
426 | } |
||||||
427 | $beforePlain = $beforeHtml = ""; |
||||||
0 ignored issues
–
show
|
|||||||
428 | $beforeHtml = ($disableRuler ?' <br>':' <br><hr style="border:dotted 1px silver; width:90%; border:dotted 1px silver;">'); |
||||||
429 | $beforePlain = ($disableRuler ?"\r\n\r\n":"\r\n\r\n-- \r\n"); |
||||||
430 | $sigText = Mail::merge($signature,array($GLOBALS['egw']->accounts->id2name($GLOBALS['egw_info']['user']['account_id'],'person_id'))); |
||||||
431 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' Signature to use:'.$sigText); |
||||||
432 | $sigTextHtml = $beforeHtml.$sigText; |
||||||
433 | $sigTextPlain = $beforePlain.Api\Mail\Html::convertHTMLToText($sigText); |
||||||
434 | |||||||
435 | $force8bit=false; |
||||||
436 | if (Api\Translation::detect_encoding($sigTextPlain)!='ascii') $force8bit=true; |
||||||
437 | // beware. the section below might cause trouble regarding bcc and attachments, so maybe this is to be handeled differently |
||||||
438 | if ($force8bit) |
||||||
439 | { |
||||||
440 | $converterObj = new Api\Mailer('initbasic'); |
||||||
441 | $smartdata->mime = $converterObj->convertMessageTextParts($smartdata->mime,false,'utf-8'); |
||||||
442 | } |
||||||
443 | // initialize the new Api\Mailer object for sending |
||||||
444 | $mailObject = new Api\Mailer(self::$profileID); |
||||||
445 | |||||||
446 | $this->mail->parseRawMessageIntoMailObject($mailObject,$smartdata->mime,$force8bit); |
||||||
447 | // Horde SMTP Class uses utf-8 by default. as we set charset always to utf-8 |
||||||
448 | $mailObject->Sender = $activeMailProfile['ident_email']; |
||||||
0 ignored issues
–
show
|
|||||||
449 | $mailObject->setFrom($activeMailProfile['ident_email'],Mail::generateIdentityString($activeMailProfile,false)); |
||||||
450 | $mailObject->addHeader('X-Mailer', 'mail-Activesync'); |
||||||
451 | |||||||
452 | // prepare addressee list; moved the adding of addresses to the mailobject down |
||||||
453 | // to |
||||||
454 | foreach(Mail::parseAddressList($mailObject->getHeader("To")) as $addressObject) { |
||||||
455 | if (!$addressObject->valid) continue; |
||||||
456 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__.") Header Sentmail To: ".array2string($addressObject) ); |
||||||
457 | //$mailObject->AddAddress($addressObject->mailbox. ($addressObject->host ? '@'.$addressObject->host : ''),$addressObject->personal); |
||||||
458 | $toMailAddr[] = imap_rfc822_write_address($addressObject->mailbox, $addressObject->host, $addressObject->personal); |
||||||
459 | } |
||||||
460 | // CC |
||||||
461 | foreach(Mail::parseAddressList($mailObject->getHeader("Cc")) as $addressObject) { |
||||||
462 | if (!$addressObject->valid) continue; |
||||||
463 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__.") Header Sentmail CC: ".array2string($addressObject) ); |
||||||
464 | //$mailObject->AddCC($addressObject->mailbox. ($addressObject->host ? '@'.$addressObject->host : ''),$addressObject->personal); |
||||||
465 | $ccMailAddr[] = imap_rfc822_write_address($addressObject->mailbox, $addressObject->host, $addressObject->personal); |
||||||
466 | } |
||||||
467 | // BCC |
||||||
468 | foreach($mailObject->getAddresses('bcc') as $addressObject) { |
||||||
469 | if (!$addressObject->valid) continue; |
||||||
470 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__.") Header Sentmail BCC: ".array2string($addressObject) ); |
||||||
471 | //$mailObject->AddBCC($addressObject->mailbox. ($addressObject->host ? '@'.$addressObject->host : ''),$addressObject->personal); |
||||||
472 | $bccMailAddr[] = imap_rfc822_write_address($addressObject->mailbox, $addressObject->host, $addressObject->personal); |
||||||
473 | } |
||||||
474 | $mailObject->clearAllRecipients(); |
||||||
475 | |||||||
476 | $use_orgbody = false; |
||||||
477 | |||||||
478 | $k = 'Content-Type'; |
||||||
479 | $ContentType =$mailObject->getHeader('Content-Type'); |
||||||
480 | //error_log(__METHOD__.__LINE__." Header Sentmail original Header (filtered): " . $k. " = ".trim($ContentType)); |
||||||
481 | // if the message is a multipart message, then we should use the sent body |
||||||
482 | if (preg_match("/multipart/i", $ContentType)) { |
||||||
483 | $use_orgbody = true; |
||||||
484 | } |
||||||
485 | |||||||
486 | // save the original content-type header for the body part when forwarding |
||||||
487 | if ($smartdata_task == 'forward' && $smartdata->source->itemid && !$use_orgbody) { |
||||||
488 | //continue; // ignore |
||||||
489 | } |
||||||
490 | // horde/egw_ mailer does everything as utf-8, the following should not be needed |
||||||
491 | //$org_charset = $ContentType; |
||||||
492 | //$ContentType = preg_replace("/charset=([A-Za-z0-9-\"']+)/", "charset=\"utf-8\"", $ContentType); |
||||||
493 | // if the message is a multipart message, then we should use the sent body |
||||||
494 | if (($smartdata_task == 'new' || $smartdata_task == 'reply' || $smartdata_task == 'forward') && |
||||||
495 | ((isset($smartdata->replacemime) && $smartdata->replacemime == true) || |
||||||
496 | $k == "Content-Type" && preg_match("/multipart/i", $ContentType))) { |
||||||
497 | $use_orgbody = true; |
||||||
498 | } |
||||||
499 | $Body = $AltBody = ""; |
||||||
0 ignored issues
–
show
|
|||||||
500 | // get body of the transmitted message |
||||||
501 | // if this is a simple message, no structure at all |
||||||
502 | if (preg_match("/text/i", $ContentType)) |
||||||
503 | { |
||||||
504 | $simpleBodyType = (preg_match("/html/i", $ContentType)?'text/html':'text/plain'); |
||||||
505 | $bodyObj = $mailObject->findBody(preg_match("/html/i", $ContentType) ? 'html' : 'plain'); |
||||||
506 | $body = preg_replace("/(<|<)*(([\w\.,-.,_.,0-9.]+)@([\w\.,-.,_.,0-9.]+))(>|>)*/i","[$2]", $bodyObj ?$bodyObj->getContents() : null); |
||||||
0 ignored issues
–
show
|
|||||||
507 | if ($simpleBodyType == "text/plain") |
||||||
508 | { |
||||||
509 | $Body = $body; |
||||||
510 | $AltBody = "<pre>".nl2br($body)."</pre>"; |
||||||
511 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__.") fetched Body as :". $simpleBodyType.'=> Created AltBody'); |
||||||
512 | } |
||||||
513 | else |
||||||
514 | { |
||||||
515 | $AltBody = $body; |
||||||
516 | $Body = trim(Api\Mail\Html::convertHTMLToText($body)); |
||||||
517 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__.") fetched Body as :". $simpleBodyType.'=> Created Body'); |
||||||
518 | } |
||||||
519 | } |
||||||
520 | else |
||||||
521 | { |
||||||
522 | // if this is a structured message |
||||||
523 | // prefer plain over html |
||||||
524 | $Body = preg_replace("/(<|<)*(([\w\.,-.,_.,0-9.]+)@([\w\.,-.,_.,0-9.]+))(>|>)*/i","[$2]", |
||||||
525 | ($text_body = $mailObject->findBody('plain')) ? $text_body->getContents() : null); |
||||||
526 | $AltBody = preg_replace("/(<|<)*(([\w\.,-.,_.,0-9.]+)@([\w\.,-.,_.,0-9.]+))(>|>)*/i","[$2]", |
||||||
527 | ($html_body = $mailObject->findBody('html')) ? $html_body->getContents() : null); |
||||||
528 | } |
||||||
529 | if ($this->debugLevel>1 && $Body) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__.") fetched Body as with MessageContentType:". $ContentType.'=>'.$Body); |
||||||
0 ignored issues
–
show
Are you sure
$ContentType of type array|string can be used in concatenation ?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
530 | if ($this->debugLevel>1 && $AltBody) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__.") fetched AltBody as with MessageContentType:". $ContentType.'=>'.$AltBody); |
||||||
531 | //error_log(__METHOD__.__LINE__.array2string($mailObject)); |
||||||
532 | // if this is a multipart message with a boundary, we must use the original body |
||||||
533 | //if ($this->debugLevel>2) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' mailObject after Inital Parse:'.array2string($mailObject)); |
||||||
534 | if ($use_orgbody) { |
||||||
535 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__.") use_orgbody = true ContentType:".$ContentType); |
||||||
536 | // if it is a ClientSideMeetingRequest, we report it as send at all times |
||||||
537 | if (($cal_body = $mailObject->findBody('calendar')) && |
||||||
538 | ($cSMRMethod = $cal_body->getContentTypeParameter('method'))) |
||||||
539 | { |
||||||
540 | if ($cSMRMethod == 'REPLY' && class_exists('calendar_ical')) |
||||||
541 | { |
||||||
542 | $organizer = calendar_ical::getIcalOrganizer($cal_body->getContents()); |
||||||
543 | } |
||||||
544 | if ($this->debugLevel) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__.") we have a Client Side Meeting Request from organizer=$organizer"); |
||||||
545 | $ClientSideMeetingRequest = true; |
||||||
546 | } |
||||||
547 | } |
||||||
548 | // now handle the addressee list |
||||||
549 | $toCount = 0; |
||||||
550 | //error_log(__METHOD__.__LINE__.array2string($toMailAddr)); |
||||||
551 | foreach((array)$toMailAddr as $address) { |
||||||
552 | foreach(Mail::parseAddressList((get_magic_quotes_gpc()?stripslashes($address):$address)) as $addressObject) { |
||||||
553 | $emailAddress = $addressObject->mailbox. ($addressObject->host ? '@'.$addressObject->host : ''); |
||||||
554 | if ($ClientSideMeetingRequest === true && $allowSendingInvitations == 'sendifnocalnotif' && |
||||||
555 | calendar_boupdate::email_update_requested($emailAddress, isset($cSMRMethod) ? $cSMRMethod : 'REQUEST', |
||||||
556 | $organizer && !strcasecmp($emailAddress, $organizer) ? 'CHAIR' : '')) |
||||||
557 | { |
||||||
558 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__.") skiping mail to organizer '$organizer', as it will be send by calendar app"); |
||||||
559 | continue; |
||||||
560 | } |
||||||
561 | $mailObject->AddAddress($emailAddress, $addressObject->personal); |
||||||
562 | $toCount++; |
||||||
563 | } |
||||||
564 | } |
||||||
565 | $ccCount = 0; |
||||||
566 | foreach((array)$ccMailAddr as $address) { |
||||||
567 | foreach(Mail::parseAddressList((get_magic_quotes_gpc()?stripslashes($address):$address)) as $addressObject) { |
||||||
568 | $emailAddress = $addressObject->mailbox. ($addressObject->host ? '@'.$addressObject->host : ''); |
||||||
569 | if ($ClientSideMeetingRequest === true && $allowSendingInvitations == 'sendifnocalnotif' && calendar_boupdate::email_update_requested($emailAddress)) continue; |
||||||
570 | $mailObject->AddCC($emailAddress, $addressObject->personal); |
||||||
571 | $ccCount++; |
||||||
572 | } |
||||||
573 | } |
||||||
574 | $bccCount = 0; |
||||||
575 | foreach((array)$bccMailAddr as $address) { |
||||||
576 | foreach(Mail::parseAddressList((get_magic_quotes_gpc()?stripslashes($address):$address)) as $addressObject) { |
||||||
577 | $emailAddress = $addressObject->mailbox. ($addressObject->host ? '@'.$addressObject->host : ''); |
||||||
578 | if ($ClientSideMeetingRequest === true && $allowSendingInvitations == 'sendifnocalnotif' && calendar_boupdate::email_update_requested($emailAddress)) continue; |
||||||
579 | $mailObject->AddBCC($emailAddress, $addressObject->personal); |
||||||
580 | $bccCount++; |
||||||
581 | } |
||||||
582 | } |
||||||
583 | // typical organizer reply will end here with nothing send --> return true, because we suppressed the send above |
||||||
584 | if ($toCount+$ccCount+$bccCount == 0) |
||||||
585 | { |
||||||
586 | return $ClientSideMeetingRequest && $allowSendingInvitations === 'sendifnocalnotif' && $organizer ? true : 0; // noone to send mail to |
||||||
587 | } |
||||||
588 | if ($ClientSideMeetingRequest === true && $allowSendingInvitations===false) return true; |
||||||
589 | // as we use our mailer (horde mailer) it is detecting / setting the mimetype by itself while creating the mail |
||||||
590 | /* |
||||||
591 | if ($this->debugLevel>2) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' retrieved Body:'.$body); |
||||||
592 | $body = str_replace("\r",((preg_match("^text/html^i", $ContentType))?'<br>':""),$body); // what is this for? |
||||||
593 | if ($this->debugLevel>2) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' retrieved Body (modified):'.$body); |
||||||
594 | */ |
||||||
595 | // actually use prepared signature --------------------collected earlier-------------------------- |
||||||
596 | $isreply = $isforward = false; |
||||||
597 | // reply --------------------------------------------------------------------------- |
||||||
598 | if ($smartdata_task == 'reply' && isset($smartdata->source->itemid) && |
||||||
599 | isset($smartdata->source->folderid) && $smartdata->source->itemid && $smartdata->source->folderid && |
||||||
600 | (!isset($smartdata->replacemime) || |
||||||
601 | (isset($smartdata->replacemime) && $smartdata->replacemime == false))) |
||||||
602 | { |
||||||
603 | // now get on, and fetch the original mail |
||||||
604 | $uid = $smartdata->source->itemid; |
||||||
605 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__.") IMAP Smartreply is called with FolderID:".$smartdata->source->folderid.' and ItemID:'.$smartdata->source->itemid); |
||||||
606 | $this->splitID($smartdata->source->folderid, $account, $folder); |
||||||
607 | |||||||
608 | $this->mail->reopen($folder); |
||||||
609 | $bodyStruct = $this->mail->getMessageBody($uid, 'html_only'); |
||||||
610 | $bodyBUFFHtml = $this->mail->getdisplayableBody($this->mail,$bodyStruct,true,false); |
||||||
611 | if ($this->debugLevel>3) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' html_only:'.$bodyBUFFHtml); |
||||||
612 | if ($bodyBUFFHtml != "" && (is_array($bodyStruct) && $bodyStruct[0]['mimeType']=='text/html')) { |
||||||
613 | // may be html |
||||||
614 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__.") MIME Body".' Type:html (fetched with html_only):'.$bodyBUFFHtml); |
||||||
615 | $AltBody = $AltBody."</br>".$bodyBUFFHtml.$sigTextHtml; |
||||||
616 | $isreply = true; |
||||||
617 | } |
||||||
618 | // plain text Message part |
||||||
619 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__.") MIME Body".' Type:plain, fetch text:'); |
||||||
620 | // if the new part of the message is html, we must preserve it, and handle that the original mail is text/plain |
||||||
621 | $bodyStruct = $this->mail->getMessageBody($uid,'never_display');//'never_display'); |
||||||
622 | $bodyBUFF = $this->mail->getdisplayableBody($this->mail,$bodyStruct,false,false); |
||||||
623 | if ($bodyBUFF != "" && (is_array($bodyStruct) && $bodyStruct[0]['mimeType']=='text/plain')) { |
||||||
624 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__.") MIME Body".' Type:plain (fetched with never_display):'.$bodyBUFF); |
||||||
625 | $Body = $Body."\r\n".$bodyBUFF.$sigTextPlain; |
||||||
626 | $isreply = true; |
||||||
627 | } |
||||||
628 | if (!empty($bodyBUFF) && empty($bodyBUFFHtml) && !empty($AltBody)) |
||||||
629 | { |
||||||
630 | $isreply = true; |
||||||
631 | $AltBody = $AltBody."</br><pre>".nl2br($bodyBUFF).'</pre>'.$sigTextHtml; |
||||||
632 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__." no Api\Html Body found use modified plaintext body for txt/html: ".$AltBody); |
||||||
633 | } |
||||||
634 | } |
||||||
635 | |||||||
636 | // how to forward and other prefs |
||||||
637 | $preferencesArray =& $GLOBALS['egw_info']['user']['preferences']['mail']; |
||||||
638 | |||||||
639 | // forward ------------------------------------------------------------------------- |
||||||
640 | if ($smartdata_task == 'forward' && isset($smartdata->source->itemid) && |
||||||
641 | isset($smartdata->source->folderid) && $smartdata->source->itemid && $smartdata->source->folderid && |
||||||
642 | (!isset($smartdata->replacemime) || |
||||||
643 | (isset($smartdata->replacemime) && $smartdata->replacemime == false))) |
||||||
644 | { |
||||||
645 | //force the default for the forwarding -> asmail |
||||||
646 | if (is_array($preferencesArray)) { |
||||||
647 | if (!array_key_exists('message_forwarding',$preferencesArray) |
||||||
648 | || !isset($preferencesArray['message_forwarding']) |
||||||
649 | || empty($preferencesArray['message_forwarding'])) $preferencesArray['message_forwarding'] = 'asmail'; |
||||||
650 | } else { |
||||||
651 | $preferencesArray['message_forwarding'] = 'asmail'; |
||||||
652 | } |
||||||
653 | // construct the uid of the message out of the itemid - seems to be the uid, no construction needed |
||||||
654 | $uid = $smartdata->source->itemid; |
||||||
655 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__.")IMAP Smartfordward is called with FolderID:".$smartdata->source->folderid.' and ItemID:'.$smartdata->source->itemid); |
||||||
656 | $this->splitID($smartdata->source->folderid, $account, $folder); |
||||||
657 | |||||||
658 | $this->mail->reopen($folder); |
||||||
659 | // receive entire mail (header + body) |
||||||
660 | // get message headers for specified message |
||||||
661 | $headers = $this->mail->getMessageEnvelope($uid, $_partID, true, $folder); |
||||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||||
662 | // build a new mime message, forward entire old mail as file |
||||||
663 | if ($preferencesArray['message_forwarding'] == 'asmail') |
||||||
664 | { |
||||||
665 | $rawHeader = $this->mail->getMessageRawHeader($smartdata->source->itemid, $_partID,$folder); |
||||||
666 | $rawBody = $this->mail->getMessageRawBody($smartdata->source->itemid, $_partID,$folder); |
||||||
667 | $mailObject->AddStringAttachment($rawHeader.$rawBody, $headers['SUBJECT'].'.eml', 'message/rfc822'); |
||||||
668 | $AltBody = $AltBody."</br>".lang("See Attachments for Content of the Orignial Mail").$sigTextHtml; |
||||||
669 | $Body = $Body."\r\n".lang("See Attachments for Content of the Orignial Mail").$sigTextPlain; |
||||||
670 | $isforward = true; |
||||||
671 | } |
||||||
672 | else |
||||||
673 | { |
||||||
674 | // now get on, and fetch the original mail |
||||||
675 | $uid = $smartdata->source->itemid; |
||||||
676 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__.") IMAP Smartreply is called with FolderID:".$smartdata->source->folderid.' and ItemID:'.$smartdata->source->itemid); |
||||||
677 | $this->splitID($smartdata->source->folderid, $account, $folder); |
||||||
678 | |||||||
679 | $this->mail->reopen($folder); |
||||||
680 | $bodyStruct = $this->mail->getMessageBody($uid, 'html_only'); |
||||||
681 | $bodyBUFFHtml = $this->mail->getdisplayableBody($this->mail,$bodyStruct,true,false); |
||||||
682 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' html_only:'.$bodyBUFFHtml); |
||||||
683 | if ($bodyBUFFHtml != "" && (is_array($bodyStruct) && $bodyStruct[0]['mimeType']=='text/html')) { |
||||||
684 | // may be html |
||||||
685 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__.") MIME Body".' Type:html (fetched with html_only):'.$bodyBUFFHtml); |
||||||
686 | $AltBody = $AltBody."</br>".$bodyBUFFHtml.$sigTextHtml; |
||||||
687 | $isforward = true; |
||||||
688 | } |
||||||
689 | // plain text Message part |
||||||
690 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__.") MIME Body".' Type:plain, fetch text:'); |
||||||
691 | // if the new part of the message is html, we must preserve it, and handle that the original mail is text/plain |
||||||
692 | $bodyStruct = $this->mail->getMessageBody($uid,'never_display');//'never_display'); |
||||||
693 | $bodyBUFF = $this->mail->getdisplayableBody($this->mail,$bodyStruct,false,false); |
||||||
694 | if ($bodyBUFF != "" && (is_array($bodyStruct) && $bodyStruct[0]['mimeType']=='text/plain')) { |
||||||
695 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__.") MIME Body".' Type:plain (fetched with never_display):'.$bodyBUFF); |
||||||
696 | $Body = $Body."\r\n".$bodyBUFF.$sigTextPlain; |
||||||
697 | $isforward = true; |
||||||
698 | } |
||||||
699 | if (!empty($bodyBUFF) && empty($bodyBUFFHtml) && !empty($AltBody)) |
||||||
700 | { |
||||||
701 | $AltBody = $AltBody."</br><pre>".nl2br($bodyBUFF).'</pre>'.$sigTextHtml; |
||||||
702 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__." no html Body found use modified plaintext body for txt/html: ".$AltBody); |
||||||
703 | $isforward = true; |
||||||
704 | } |
||||||
705 | // get all the attachments and add them too. |
||||||
706 | // start handle Attachments |
||||||
707 | $attachments = $this->mail->getMessageAttachments($uid,null,null,true,false,true,$folder); |
||||||
708 | $attachmentNames = false; |
||||||
709 | if (is_array($attachments) && count($attachments)>0) |
||||||
710 | { |
||||||
711 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' gather Attachments for BodyCreation of/for MessageID:'.$uid.' found:'.count($attachments)); |
||||||
712 | foreach((array)$attachments as $key => $attachment) |
||||||
713 | { |
||||||
714 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' Key:'.$key.'->'.array2string($attachment)); |
||||||
715 | $attachmentNames .= $attachment['name']."\n"; |
||||||
716 | $attachmentData = $this->mail->getAttachment($uid, $attachment['partID'],0,false,false,$folder); |
||||||
717 | /*$x =*/ $mailObject->AddStringAttachment($attachmentData['attachment'], $attachment['name'], $attachment['mimeType']); |
||||||
718 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' added part with number:'.$x); |
||||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||||
719 | } |
||||||
720 | } |
||||||
721 | } |
||||||
722 | } // end forward |
||||||
723 | // add signature, in case its not already added in forward or reply |
||||||
724 | if (!$isreply && !$isforward) |
||||||
725 | { |
||||||
726 | //error_log(__METHOD__.__LINE__.'adding Signature'); |
||||||
727 | $Body = $Body.$sigTextPlain; |
||||||
728 | $AltBody = $AltBody.$sigTextHtml; |
||||||
729 | } |
||||||
730 | // now set the body |
||||||
731 | if ($AltBody && ($html_body = $mailObject->findBody('html'))) |
||||||
732 | { |
||||||
733 | if ($this->debugLevel>1) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' -> '.$AltBody); |
||||||
734 | //error_log(__METHOD__.__LINE__.' html:'.$AltBody); |
||||||
735 | $html_body->setContents($AltBody,array('encoding'=>Horde_Mime_Part::DEFAULT_ENCODING)); |
||||||
736 | } |
||||||
737 | if ($Body && ($text_body = $mailObject->findBody('plain'))) |
||||||
738 | { |
||||||
739 | if ($this->debugLevel>1) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' -> '.$Body); |
||||||
740 | //error_log(__METHOD__.__LINE__.' text:'.$Body); |
||||||
741 | $text_body->setContents($Body,array('encoding'=>Horde_Mime_Part::DEFAULT_ENCODING)); |
||||||
742 | } |
||||||
743 | //advanced debugging |
||||||
744 | // Horde SMTP Class uses utf-8 by default. |
||||||
745 | //ZLog::Write(LOGLEVEL_DEBUG, "IMAP-SendMail: parsed message: ". print_r($message,1)); |
||||||
746 | if ($this->debugLevel>2) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__."): MailObject:".array2string($mailObject)); |
||||||
747 | |||||||
748 | // set a higher timeout for big messages |
||||||
749 | @set_time_limit(120); |
||||||
0 ignored issues
–
show
It seems like you do not handle an error condition for
set_time_limit() . This can introduce security issues, and is generally not recommended.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||||||
750 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' -> '.' about to send ....'); |
||||||
751 | // send |
||||||
752 | $send = true; |
||||||
753 | try { |
||||||
754 | $mailObject->Send(); |
||||||
755 | } |
||||||
756 | catch(Exception $e) { |
||||||
757 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__.") The email could not be sent. Last-SMTP-error: ". $e->getMessage()); |
||||||
758 | $send = false; |
||||||
759 | } |
||||||
760 | |||||||
761 | if (( $smartdata_task == 'reply' || $smartdata_task == 'forward') && $send == true) |
||||||
0 ignored issues
–
show
|
|||||||
762 | { |
||||||
763 | $uid = $smartdata->source->itemid; |
||||||
764 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' tASK:'.$smartdata_task." FolderID:".$smartdata->source->folderid.' and ItemID:'.$smartdata->source->itemid); |
||||||
765 | $this->splitID($smartdata->source->folderid, $account, $folder); |
||||||
766 | //error_log(__METHOD__.__LINE__.' Folder:'.$folder.' Uid:'.$uid); |
||||||
767 | $this->mail->reopen($folder); |
||||||
768 | // if the draft folder is a starting part of the messages folder, the draft message will be deleted after the send |
||||||
769 | // unless your templatefolder is a subfolder of your draftfolder, and the message is in there |
||||||
770 | if ($this->mail->isDraftFolder($folder) && !$this->mail->isTemplateFolder($folder)) |
||||||
771 | { |
||||||
772 | $this->mail->deleteMessages(array($uid),$folder); |
||||||
773 | } else { |
||||||
774 | $this->mail->flagMessages("answered", array($uid),$folder); |
||||||
775 | if ($smartdata_task== "forward") |
||||||
776 | { |
||||||
777 | $this->mail->flagMessages("forwarded", array($uid),$folder); |
||||||
778 | } |
||||||
779 | } |
||||||
780 | } |
||||||
781 | |||||||
782 | $asf = ($send ? true:false); // initalize accordingly |
||||||
783 | if (/*($smartdata->saveinsent==1 || !isset($smartdata->saveinsent)) && */ $send==true && $this->mail->mailPreferences['sendOptions'] != 'send_only') |
||||||
0 ignored issues
–
show
|
|||||||
784 | { |
||||||
785 | $asf = false; |
||||||
786 | $sentFolder = $this->mail->getSentFolder(); |
||||||
787 | if ($this->_sentID) { |
||||||
788 | $folderArray[] = $this->_sentID; |
||||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||||
789 | } |
||||||
790 | else if(isset($sentFolder) && $sentFolder != 'none') |
||||||
791 | { |
||||||
792 | $folderArray[] = $sentFolder; |
||||||
793 | } |
||||||
794 | // No Sent folder set, try defaults |
||||||
795 | else |
||||||
796 | { |
||||||
797 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__.") IMAP-SendMail: No Sent mailbox set"); |
||||||
798 | // we dont try guessing |
||||||
799 | $asf = true; |
||||||
800 | } |
||||||
801 | if (count($folderArray) > 0) { |
||||||
802 | foreach((array)$bccMailAddr as $address) { |
||||||
803 | foreach(Mail::parseAddressList((get_magic_quotes_gpc()?stripslashes($address):$address)) as $addressObject) { |
||||||
804 | $emailAddress = $addressObject->mailbox. ($addressObject->host ? '@'.$addressObject->host : ''); |
||||||
805 | $mailAddr[] = array($emailAddress, $addressObject->personal); |
||||||
806 | } |
||||||
807 | } |
||||||
808 | //$BCCmail=''; |
||||||
809 | if (count($mailAddr)>0) $mailObject->forceBccHeader(); |
||||||
810 | //$BCCmail = $mailObject->AddrAppend("Bcc",$mailAddr); |
||||||
811 | foreach($folderArray as $folderName) { |
||||||
812 | if($this->mail->isSentFolder($folderName)) { |
||||||
813 | $flags = '\\Seen'; |
||||||
814 | } elseif($this->mail->isDraftFolder($folderName)) { |
||||||
815 | $flags = '\\Draft'; |
||||||
816 | } else { |
||||||
817 | $flags = ''; |
||||||
818 | } |
||||||
819 | $asf = true; |
||||||
820 | //ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.'->'.array2string($this->mail->icServer)); |
||||||
821 | $this->mail->openConnection(self::$profileID,false); |
||||||
0 ignored issues
–
show
The call to
EGroupware\Api\Mail::openConnection() has too many arguments starting with false .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. ![]() |
|||||||
822 | if ($this->mail->folderExists($folderName)) { |
||||||
823 | try |
||||||
824 | { |
||||||
825 | $this->mail->appendMessage($folderName,$mailObject->getRaw(), null, |
||||||
826 | $flags); |
||||||
827 | } |
||||||
828 | catch (Api\Exception\WrongUserinput $e) |
||||||
829 | { |
||||||
830 | //$asf = false; |
||||||
831 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.'->'.lang("Import of message %1 failed. Could not save message to folder %2 due to: %3",$mailObject->getHeader('Subject'),$folderName,$e->getMessage())); |
||||||
0 ignored issues
–
show
The call to
lang() has too many arguments starting with $mailObject->getHeader('Subject') .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. ![]() |
|||||||
832 | } |
||||||
833 | } |
||||||
834 | else |
||||||
835 | { |
||||||
836 | //$asf = false; |
||||||
837 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.'->'.lang("Import of message %1 failed. Destination Folder %2 does not exist.",$mailObject->getHeader('Subject'),$folderName)); |
||||||
838 | } |
||||||
839 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__."): Outgoing mail saved in configured 'Sent' folder '".$folderName."': ". (($asf)?"success":"failed")); |
||||||
840 | } |
||||||
841 | //$this->mail->closeConnection(); |
||||||
842 | } |
||||||
843 | } |
||||||
844 | |||||||
845 | $this->debugLevel=0; |
||||||
846 | |||||||
847 | if ($send && $asf) |
||||||
848 | { |
||||||
849 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' -> send successfully'); |
||||||
850 | return true; |
||||||
851 | } |
||||||
852 | else |
||||||
853 | { |
||||||
854 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__." returning ".($ClientSideMeetingRequest ? true : 120)." (MailSubmissionFailed)".($ClientSideMeetingRequest ?" is ClientSideMeetingRequest (we ignore the failure)":"")); |
||||||
0 ignored issues
–
show
Are you sure
$ClientSideMeetingRequest ? true : 120 of type integer|true can be used in concatenation ?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
855 | return ($ClientSideMeetingRequest ? true : 120); //MAIL Submission failed, see MS-ASCMD |
||||||
856 | } |
||||||
857 | } |
||||||
858 | |||||||
859 | /** |
||||||
860 | * For meeting requests (iCal attachments with method='request') we call calendar plugin with iCal to get SyncMeetingRequest object, |
||||||
861 | * and do NOT return the attachment itself! |
||||||
862 | * |
||||||
863 | * @param string $folderid |
||||||
864 | * @param string $id |
||||||
865 | * @param ContentParameters $contentparameters parameters of the requested message (truncation, mimesupport etc) |
||||||
866 | * object with attributes foldertype, truncation, rtftruncation, conflict, filtertype, bodypref, deletesasmoves, filtertype, contentclass, mimesupport, conversationmode |
||||||
867 | * bodypref object with attributes: ]truncationsize, allornone, preview |
||||||
868 | * @return $messageobject|boolean false on error |
||||||
0 ignored issues
–
show
|
|||||||
869 | */ |
||||||
870 | public function GetMessage($folderid, $id, $contentparameters) |
||||||
871 | { |
||||||
872 | //$this->debugLevel=4; |
||||||
873 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' FolderID:'.$folderid.' ID:'.$id.' ContentParams='.array2string($contentparameters)); |
||||||
874 | $truncsize = Utils::GetTruncSize($contentparameters->GetTruncation()); |
||||||
875 | $mimesupport = $contentparameters->GetMimeSupport(); |
||||||
876 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."() truncsize=$truncsize, mimeSupport=".array2string($mimesupport)); |
||||||
877 | $bodypreference = $contentparameters->GetBodyPreference(); /* fmbiete's contribution r1528, ZP-320 */ |
||||||
878 | |||||||
879 | // fix for z-push bug returning additional bodypreference type 4, even if only 1 is requested and mimessupport = 0 |
||||||
880 | if (!$mimesupport && ($key = array_search('4', $bodypreference))) unset($bodypreference[$key]); |
||||||
881 | |||||||
882 | //$this->debugLevel=4; |
||||||
883 | if (!isset($this->mail)) $this->mail = Mail::getInstance(false,self::$profileID,true,false,true); |
||||||
884 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' FolderID:'.$folderid.' ID:'.$id.' TruncSize:'.$truncsize.' Bodypreference: '.array2string($bodypreference)); |
||||||
885 | $account = $_folderName = $xid = null; |
||||||
886 | $this->splitID($folderid,$account,$_folderName,$xid); |
||||||
887 | $this->mail->reopen($_folderName); |
||||||
888 | $messages = $this->fetchMessages($folderid, NULL, $id, true); // true: return all headers |
||||||
889 | $headers = $messages[$id]; |
||||||
890 | if ($this->debugLevel>3) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.array2string($headers)); |
||||||
891 | // StatMessage should reopen the folder in question, so we dont need folderids in the following statements. |
||||||
892 | if ($headers) |
||||||
893 | { |
||||||
894 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__." Message $id with stat ".array2string($headers)); |
||||||
895 | // initialize the object |
||||||
896 | $output = new SyncMail(); |
||||||
897 | //$rawHeaders = $this->mail->getMessageRawHeader($id); |
||||||
898 | // simple style |
||||||
899 | // start AS12 Stuff (bodypreference === false) case = old behaviour |
||||||
900 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__. ' for message with ID:'.$id.' with headers:'.array2string($headers)); |
||||||
901 | |||||||
902 | if ($bodypreference === false) { |
||||||
903 | $bodyStruct = $this->mail->getMessageBody($id, 'only_if_no_text', '', null, true,$_folderName); |
||||||
904 | $raw_body = $this->mail->getdisplayableBody($this->mail,$bodyStruct,false,false); |
||||||
905 | //$body = html_entity_decode($body,ENT_QUOTES,$this->mail->detect_encoding($body)); |
||||||
906 | if (stripos($raw_body,'<style')!==false) $body = preg_replace("/<style.*?<\/style>/is", "", $raw_body); // in case there is only a html part |
||||||
0 ignored issues
–
show
|
|||||||
907 | // remove all other html |
||||||
908 | $body = strip_tags($raw_body); |
||||||
909 | if(strlen($body) > $truncsize) { |
||||||
910 | $body = Utils::Utf8_truncate($body, $truncsize); |
||||||
911 | $output->bodytruncated = 1; |
||||||
912 | } |
||||||
913 | else |
||||||
914 | { |
||||||
915 | $output->bodytruncated = 0; |
||||||
916 | } |
||||||
917 | $output->bodysize = strlen($body); |
||||||
918 | $output->body = $body; |
||||||
919 | } |
||||||
920 | else // style with bodypreferences |
||||||
921 | { |
||||||
922 | //Select body type preference |
||||||
923 | $bpReturnType = 1;//SYNC_BODYPREFERENCE_PLAIN; |
||||||
924 | if ($bodypreference !== false) { |
||||||
925 | // bodypreference can occur multiple times |
||||||
926 | // usually we would use Utils::GetBodyPreferenceBestMatch($bodypreference); |
||||||
927 | $bpReturnType = Utils::GetBodyPreferenceBestMatch($bodypreference); |
||||||
928 | /* |
||||||
929 | foreach($bodypreference as $bpv) |
||||||
930 | { |
||||||
931 | // we use the last, or MIMEMESSAGE when present |
||||||
932 | $bpReturnType = $bpv; |
||||||
933 | if ($bpReturnType==SYNC_BODYPREFERENCE_MIME) break; |
||||||
934 | } |
||||||
935 | */ |
||||||
936 | } |
||||||
937 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__." getBodyPreferenceBestMatch: ".array2string($bpReturnType)); |
||||||
938 | // set the protocoll class |
||||||
939 | $output->asbody = new SyncBaseBody(); |
||||||
940 | |||||||
941 | // return full mime-message without any (charset) conversation directly as stream |
||||||
942 | if ($bpReturnType==SYNC_BODYPREFERENCE_MIME) |
||||||
943 | { |
||||||
944 | //SYNC_BODYPREFERENCE_MIME |
||||||
945 | $output->asbody->type = SYNC_BODYPREFERENCE_MIME; |
||||||
946 | $stream = $this->mail->getMessageRawBody($id, '', $_folderName, true); |
||||||
947 | $fstat = fstat($stream); |
||||||
948 | fseek($stream, 0, SEEK_SET); |
||||||
949 | $output->asbody->data = $stream; |
||||||
950 | $output->asbody->estimatedDataSize = $fstat['size']; |
||||||
951 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__." bodypreference 4=SYNC_BODYPREFERENCE_MIME=full mime message requested, size=$fstat[size]"); |
||||||
952 | } |
||||||
953 | else |
||||||
954 | { |
||||||
955 | // fetch the body (try to gather data only once) |
||||||
956 | $css =''; |
||||||
957 | $bodyStruct = $this->mail->getMessageBody($id, 'html_only', '', null, true,$_folderName); |
||||||
958 | if ($this->debugLevel>2) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' html_only Struct:'.array2string($bodyStruct)); |
||||||
959 | $body = $this->mail->getdisplayableBody($this->mail,$bodyStruct,true,false); |
||||||
960 | if ($this->debugLevel>3) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' html_only:'.$body); |
||||||
961 | if ($body != "" && (is_array($bodyStruct) && $bodyStruct[0]['mimeType']=='text/html')) { |
||||||
962 | // may be html |
||||||
963 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG, "MIME Body".' Type:html (fetched with html_only)'); |
||||||
964 | $css = $this->mail->getStyles($bodyStruct); |
||||||
965 | $output->nativebodytype=2; |
||||||
966 | } else { |
||||||
967 | // plain text Message |
||||||
968 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG, "MIME Body".' Type:plain, fetch text (HTML, if no text available)'); |
||||||
969 | $output->nativebodytype=1; |
||||||
970 | $bodyStruct = $this->mail->getMessageBody($id,'never_display', '', null, true,$_folderName); //'only_if_no_text'); |
||||||
971 | if ($this->debugLevel>3) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' plain text Struct:'.array2string($bodyStruct)); |
||||||
972 | $body = $this->mail->getdisplayableBody($this->mail,$bodyStruct,false,false); |
||||||
973 | if ($this->debugLevel>3) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' never display html(plain text only):'.$body); |
||||||
974 | } |
||||||
975 | // whatever format decode (using the correct encoding) |
||||||
976 | if ($this->debugLevel>3) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__."MIME Body".' Type:'.($output->nativebodytype==2?' html ':' plain ').$body); |
||||||
977 | //$body = html_entity_decode($body,ENT_QUOTES,$this->mail->detect_encoding($body)); |
||||||
978 | // prepare plaintextbody |
||||||
979 | $plainBody=''; |
||||||
980 | if ($output->nativebodytype == 2) |
||||||
981 | { |
||||||
982 | $bodyStructplain = $this->mail->getMessageBody($id,'never_display', '', null, true,$_folderName); //'only_if_no_text'); |
||||||
983 | if(isset($bodyStructplain[0])&&isset($bodyStructplain[0]['error'])&&$bodyStructplain[0]['error']==1) |
||||||
984 | { |
||||||
985 | $plainBody = Api\Mail\Html::convertHTMLToText($body); // always display with preserved HTML |
||||||
986 | } |
||||||
987 | else |
||||||
988 | { |
||||||
989 | $plainBody = $this->mail->getdisplayableBody($this->mail,$bodyStructplain,false,false); |
||||||
990 | } |
||||||
991 | } |
||||||
992 | //if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG, "MIME Body".$body); |
||||||
993 | $plainBody = preg_replace("/<style.*?<\/style>/is", "", (strlen($plainBody)?$plainBody:$body)); |
||||||
994 | // remove all other html |
||||||
995 | $plainBody = preg_replace("/<br.*>/is","\r\n",$plainBody); |
||||||
996 | $plainBody = strip_tags($plainBody); |
||||||
997 | if ($this->debugLevel>3 && $output->nativebodytype==1) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' Plain Text:'.$plainBody); |
||||||
998 | //$body = str_replace("\n","\r\n", str_replace("\r","",$body)); // do we need that? |
||||||
999 | |||||||
1000 | if ($bpReturnType==2) //SYNC_BODYPREFERENCE_HTML |
||||||
1001 | { |
||||||
1002 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG, "HTML Body with requested pref 2"); |
||||||
1003 | // Send HTML if requested and native type was html |
||||||
1004 | $output->asbody->type = 2; |
||||||
1005 | $htmlbody = '<html>'. |
||||||
1006 | '<head>'. |
||||||
1007 | '<meta name="Generator" content="Z-Push">'. |
||||||
1008 | '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">'. |
||||||
1009 | $css. |
||||||
1010 | '</head>'. |
||||||
1011 | '<body>'; |
||||||
1012 | if ($output->nativebodytype==2) |
||||||
1013 | { |
||||||
1014 | if ($css) Api\Mail\Html::replaceTagsCompletley($body,'style'); |
||||||
1015 | // as we fetch html, and body is HTML, we may not need to handle this |
||||||
1016 | $htmlbody .= $body; |
||||||
1017 | } |
||||||
1018 | else |
||||||
1019 | { |
||||||
1020 | // html requested but got only plaintext, so fake html |
||||||
1021 | $htmlbody .= str_replace("\n","<BR>",str_replace("\r","<BR>", str_replace("\r\n","<BR>",$plainBody))); |
||||||
1022 | } |
||||||
1023 | $htmlbody .= '</body>'. |
||||||
1024 | '</html>'; |
||||||
1025 | |||||||
1026 | if(isset($truncsize) && strlen($htmlbody) > $truncsize) |
||||||
1027 | { |
||||||
1028 | $htmlbody = Utils::Utf8_truncate($htmlbody,$truncsize); |
||||||
1029 | $output->asbody->truncated = 1; |
||||||
1030 | } |
||||||
1031 | // output->nativebodytype is used as marker that the original message was of type ... but is now converted to, as type 2 is requested. |
||||||
1032 | $output->nativebodytype = 2; |
||||||
1033 | $output->asbody->data = StringStreamWrapper::Open($htmlbody); |
||||||
1034 | $output->asbody->estimatedDataSize = strlen($htmlbody); |
||||||
1035 | } |
||||||
1036 | else |
||||||
1037 | { |
||||||
1038 | // Send Plaintext as Fallback or if original body is plainttext |
||||||
1039 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG, "Plaintext Body:".$plainBody); |
||||||
1040 | /* we use plainBody (set above) instead |
||||||
1041 | $bodyStruct = $this->mail->getMessageBody($id,'only_if_no_text'); //'never_display'); |
||||||
1042 | $plain = $this->mail->getdisplayableBody($this->mail,$bodyStruct); |
||||||
1043 | $plain = html_entity_decode($plain,ENT_QUOTES,$this->mail->detect_encoding($plain)); |
||||||
1044 | $plain = strip_tags($plain); |
||||||
1045 | //$plain = str_replace("\n","\r\n",str_replace("\r","",$plain)); |
||||||
1046 | */ |
||||||
1047 | $output->asbody->type = 1; |
||||||
1048 | $output->nativebodytype = 1; |
||||||
1049 | if(isset($truncsize) && |
||||||
1050 | strlen($plainBody) > $truncsize) |
||||||
1051 | { |
||||||
1052 | $plainBody = Utils::Utf8_truncate($plainBody, $truncsize); |
||||||
1053 | $output->asbody->truncated = 1; |
||||||
1054 | } |
||||||
1055 | $output->asbody->data = StringStreamWrapper::Open((string)$plainBody !== '' ? $plainBody : ' '); |
||||||
1056 | $output->asbody->estimatedDataSize = strlen($plainBody); |
||||||
1057 | } |
||||||
1058 | // In case we have nothing for the body, send at least a blank... |
||||||
1059 | // dw2412 but only in case the body is not rtf! |
||||||
1060 | if ($output->asbody->type != 3 && !isset($output->asbody->data)) |
||||||
1061 | { |
||||||
1062 | $output->asbody->data = StringStreamWrapper::Open(" "); |
||||||
1063 | $output->asbody->estimatedDataSize = 1; |
||||||
1064 | } |
||||||
1065 | } |
||||||
1066 | } |
||||||
1067 | // end AS12 Stuff |
||||||
1068 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' gather Header info:'.$headers['subject'].' from:'.$headers['date']); |
||||||
1069 | $output->read = $headers["flags"]; |
||||||
1070 | |||||||
1071 | $output->flag = new SyncMailFlags(); |
||||||
1072 | if ($headers['flagged'] == 1) |
||||||
1073 | { |
||||||
1074 | $output->flag->flagstatus = 2; |
||||||
1075 | //$output->flag->flagtype = "Flag for Follow up"; |
||||||
1076 | } else { |
||||||
1077 | $output->flag->flagstatus = 0; |
||||||
1078 | } |
||||||
1079 | if ($headers['answered']) |
||||||
1080 | { |
||||||
1081 | $output->lastverexecuted = AS_REPLYTOSENDER; |
||||||
0 ignored issues
–
show
|
|||||||
1082 | } |
||||||
1083 | elseif ($headers['forwarded']) |
||||||
1084 | { |
||||||
1085 | $output->lastverexecuted = AS_FORWARD; |
||||||
1086 | } |
||||||
1087 | $output->subject = $headers['subject']; |
||||||
1088 | $output->importance = $headers['priority'] > 3 ? 0 : |
||||||
1089 | ($headers['priority'] < 3 ? 2 : 1) ; |
||||||
1090 | $output->datereceived = $this->mail->_strtotime($headers['date'],'ts',true); |
||||||
1091 | $output->to = $headers['to_address']; |
||||||
1092 | if ($headers['to']) $output->displayto = $headers['to_address']; //$headers['FETCHED_HEADER']['to_name'] |
||||||
1093 | $output->from = $headers['sender_address']; |
||||||
1094 | if (isset($headers['cc_addresses']) && $headers['cc_addresses']) $output->cc = $headers['cc_addresses']; |
||||||
1095 | if (isset($headers['reply_to_address']) && $headers['reply_to_address']) $output->reply_to = $headers['reply_to_address']; |
||||||
1096 | |||||||
1097 | $output->messageclass = "IPM.Note"; |
||||||
1098 | if (stripos($headers['mimetype'],'multipart')!== false && |
||||||
1099 | stripos($headers['mimetype'],'signed')!== false) |
||||||
1100 | { |
||||||
1101 | $output->messageclass = "IPM.Note.SMIME.MultipartSigned"; |
||||||
1102 | } |
||||||
1103 | if (Request::GetProtocolVersion() >= 12.0) { |
||||||
1104 | $output->contentclass = "urn:content-classes:message"; |
||||||
1105 | } |
||||||
1106 | |||||||
1107 | // start handle Attachments (include text/calendar multipart alternative) |
||||||
1108 | $attachments = $this->mail->getMessageAttachments($id, $_partID='', $_structure=null, $fetchEmbeddedImages=true, $fetchTextCalendar=true, true, $_folderName); |
||||||
1109 | // Attachments should not needed for MIME messages, so skip this part if bpReturnType==4 |
||||||
1110 | if (/*$bpReturnType != SYNC_BODYPREFERENCE_MIME &&*/ is_array($attachments) && count($attachments)>0) |
||||||
1111 | { |
||||||
1112 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' gather Attachments for MessageID:'.$id.' found:'.count($attachments)); |
||||||
1113 | //error_log(__METHOD__.__LINE__.array2string($attachments)); |
||||||
1114 | foreach ($attachments as $key => $attach) |
||||||
1115 | { |
||||||
1116 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' Key:'.$key.'->'.array2string($attach)); |
||||||
1117 | |||||||
1118 | // pass meeting requests to calendar plugin |
||||||
1119 | if (strtolower($attach['mimeType']) == 'text/calendar' && strtolower($attach['method']) == 'request' && |
||||||
1120 | isset($GLOBALS['egw_info']['user']['apps']['calendar']) && |
||||||
1121 | ($attachment = $this->mail->getAttachment($id, $attach['partID'],0,false,false,$_folderName)) && |
||||||
1122 | ($output->meetingrequest = calendar_zpush::meetingRequest($attachment['attachment']))) |
||||||
1123 | { |
||||||
1124 | //overwrite the globalobjId from calendar object, as: if you delete the mail, that is |
||||||
1125 | //the meeting-request its using the globalobjid as reference and deletes both: |
||||||
1126 | //mail AND meeting. we dont want this. accepting meeting requests with the mobile does nothing |
||||||
1127 | $output->meetingrequest->globalobjid = activesync_backend::uid2globalObjId($id); |
||||||
1128 | $output->messageclass = "IPM.Schedule.Meeting.Request"; |
||||||
1129 | //$output->messageclass = "IPM.Schedule.Meeting"; |
||||||
1130 | unset($attachment); |
||||||
1131 | continue; // do NOT add attachment as attachment |
||||||
1132 | } |
||||||
1133 | if (Request::GetProtocolVersion() >= 12.0) { |
||||||
1134 | $attachment = new SyncBaseAttachment(); |
||||||
1135 | if (!isset($output->asattachments) || !is_array($output->asattachments)) |
||||||
1136 | $output->asattachments = array(); |
||||||
1137 | $attachment->estimatedDataSize = $attach['size']; |
||||||
1138 | $attachment->method = 1; |
||||||
1139 | $attachment->filereference = $folderid . ":" . $id . ":" . $attach['partID']; |
||||||
1140 | } else { |
||||||
1141 | $attachment = new SyncAttachment(); |
||||||
1142 | if (!isset($output->attachments) || !is_array($output->attachments)) |
||||||
1143 | $output->attachments = array(); |
||||||
1144 | $attachment->attsize = $attach['size']; |
||||||
1145 | $attachment->attmethod = 1; |
||||||
1146 | $attachment->attname = $folderid . ":" . $id . ":" . $attach['partID'];//$key; |
||||||
1147 | } |
||||||
1148 | |||||||
1149 | $attachment->displayname = $attach['name']; |
||||||
1150 | //error_log(__METHOD__.__LINE__.'->'.$folderid . ":" . $id . ":" . $attach['partID']); |
||||||
1151 | |||||||
1152 | $attachment->attoid = "";//isset($part->headers['content-id']) ? trim($part->headers['content-id']) : ""; |
||||||
0 ignored issues
–
show
|
|||||||
1153 | //$attachment->isinline=0; // if not inline, do not use isinline |
||||||
1154 | if (!empty($attach['cid']) && $attach['cid'] <> 'NIL' ) |
||||||
1155 | { |
||||||
1156 | if ($bpReturnType != 4 && $attach['disposition'] == 'inline') |
||||||
1157 | { |
||||||
1158 | $attachment->isinline = true; |
||||||
0 ignored issues
–
show
|
|||||||
1159 | } |
||||||
1160 | if (Request::GetProtocolVersion() >= 12.0) { |
||||||
1161 | $attachment->method=1; |
||||||
0 ignored issues
–
show
|
|||||||
1162 | $attachment->contentid= str_replace(array("<",">"), "",$attach['cid']); |
||||||
0 ignored issues
–
show
|
|||||||
1163 | } else { |
||||||
1164 | $attachment->attmethod=6; |
||||||
0 ignored issues
–
show
|
|||||||
1165 | $attachment->attoid = str_replace(array("<",">"), "",$attach['cid']); |
||||||
1166 | } |
||||||
1167 | // ZLog::Write(LOGLEVEL_DEBUG, "'".$part->headers['content-id']."' ".$attachment->contentid); |
||||||
1168 | $attachment->contenttype = trim($attach['mimeType']); |
||||||
0 ignored issues
–
show
|
|||||||
1169 | // ZLog::Write(LOGLEVEL_DEBUG, "'".$part->headers['content-type']."' ".$attachment->contentid); |
||||||
1170 | } |
||||||
1171 | if (Request::GetProtocolVersion() >= 12.0) { |
||||||
1172 | array_push($output->asattachments, $attachment); |
||||||
1173 | } else { |
||||||
1174 | array_push($output->attachments, $attachment); |
||||||
1175 | } |
||||||
1176 | unset($attachment); |
||||||
1177 | } |
||||||
1178 | } |
||||||
1179 | //$this->debugLevel=0; |
||||||
1180 | // end handle Attachments |
||||||
1181 | unset($attachments); |
||||||
1182 | |||||||
1183 | // Language Code Page ID: http://msdn.microsoft.com/en-us/library/windows/desktop/dd317756%28v=vs.85%29.aspx |
||||||
1184 | $output->internetcpid = INTERNET_CPID_UTF8; |
||||||
1185 | |||||||
1186 | if ($this->debugLevel>3) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.array2string($output)); |
||||||
1187 | //$this->debugLevel=0; |
||||||
1188 | return $output; |
||||||
1189 | } |
||||||
1190 | //$this->debugLevel=0; |
||||||
1191 | return false; |
||||||
1192 | } |
||||||
1193 | |||||||
1194 | /** |
||||||
1195 | * Process response to meeting request |
||||||
1196 | * |
||||||
1197 | * mail plugin only extracts the iCal attachment and let's calendar plugin deal with adding it |
||||||
1198 | * |
||||||
1199 | * @see BackendDiff::MeetingResponse() |
||||||
1200 | * @param string $folderid folder of meeting request mail |
||||||
1201 | * @param int|string $requestid uid of mail with meeting request |
||||||
1202 | * @param int $response 1=accepted, 2=tentative, 3=decline |
||||||
1203 | * @return int|boolean id of calendar item, false on error |
||||||
1204 | */ |
||||||
1205 | function MeetingResponse($folderid, $requestid, $response) |
||||||
1206 | { |
||||||
1207 | if (!class_exists('calendar_zpush')) |
||||||
1208 | { |
||||||
1209 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(...) no EGroupware calendar installed!"); |
||||||
1210 | return null; |
||||||
1211 | } |
||||||
1212 | if (!($stat = $this->StatMessage($folderid, $requestid))) |
||||||
0 ignored issues
–
show
|
|||||||
1213 | { |
||||||
1214 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."($requestid, '$folderid', $response) returning FALSE (can NOT stat message)"); |
||||||
1215 | return false; |
||||||
1216 | } |
||||||
1217 | $ret = false; |
||||||
1218 | foreach($this->mail->getMessageAttachments($requestid, $_partID='', $_structure=null, $fetchEmbeddedImages=true, $fetchTextCalendar=true) as $key => $attach) |
||||||
1219 | { |
||||||
1220 | if (strtolower($attach['mimeType']) == 'text/calendar' && strtolower($attach['method']) == 'request' && |
||||||
1221 | ($attachment = $this->mail->getAttachment($requestid, $attach['partID'],0,false))) |
||||||
1222 | { |
||||||
1223 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."($requestid, '$folderid', $response) iCal found, calling now backend->MeetingResponse('$attachment[attachment]')"); |
||||||
1224 | |||||||
1225 | // calling backend again with iCal attachment, to let calendar add the event |
||||||
1226 | $ret = $this->backend->MeetingResponse($attachment['attachment'], |
||||||
1227 | $this->backend->createID('calendar',$GLOBALS['egw_info']['user']['account_id']), |
||||||
1228 | $response); |
||||||
1229 | |||||||
1230 | // delete message after meeting-response is processed successful by calendar |
||||||
1231 | if ($ret) $this->DeleteMessage($folderid, $requestid, null); |
||||||
1232 | break; |
||||||
1233 | } |
||||||
1234 | } |
||||||
1235 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."($requestid, '$folderid', $response) returning ".array2string($ret)); |
||||||
1236 | return $ret; |
||||||
1237 | } |
||||||
1238 | |||||||
1239 | /** |
||||||
1240 | * GetAttachmentData |
||||||
1241 | * Should return attachment data for the specified attachment. The passed attachment identifier is |
||||||
1242 | * the exact string that is returned in the 'AttName' property of an SyncAttachment. So, you should |
||||||
1243 | * encode any information you need to find the attachment in that 'attname' property. |
||||||
1244 | * |
||||||
1245 | * @param string $fid - id |
||||||
1246 | * @param string $attname - should contain (folder)id |
||||||
1247 | * @return SyncItemOperationsAttachment-object |
||||||
0 ignored issues
–
show
|
|||||||
1248 | */ |
||||||
1249 | function GetAttachmentData($fid,$attname) { |
||||||
1250 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.": $fid (attname: '$attname')"); |
||||||
1251 | return $this->_GetAttachmentData($fid,$attname); |
||||||
1252 | } |
||||||
1253 | |||||||
1254 | /** |
||||||
1255 | * ItemOperationsGetAttachmentData |
||||||
1256 | * Should return attachment data for the specified attachment. The passed attachment identifier is |
||||||
1257 | * the exact string that is returned in the 'AttName' property of an SyncAttachment. So, you should |
||||||
1258 | * encode any information you need to find the attachment in that 'attname' property. |
||||||
1259 | * |
||||||
1260 | * @param string $fid - id |
||||||
1261 | * @param string $attname - should contain (folder)id |
||||||
1262 | * @return SyncItemOperationsAttachment-object |
||||||
0 ignored issues
–
show
|
|||||||
1263 | */ |
||||||
1264 | function ItemOperationsGetAttachmentData($fid,$attname) { |
||||||
1265 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.": $fid (attname: '$attname')"); |
||||||
1266 | return $this->_GetAttachmentData($fid,$attname); |
||||||
1267 | } |
||||||
1268 | |||||||
1269 | /** |
||||||
1270 | * _GetAttachmentData implements |
||||||
1271 | * -ItemOperationsGetAttachmentData |
||||||
1272 | * -GetAttachmentData |
||||||
1273 | * |
||||||
1274 | * @param string $fid - id |
||||||
1275 | * @param string $attname - should contain (folder)id |
||||||
1276 | * @return SyncItemOperationsAttachment-object |
||||||
0 ignored issues
–
show
|
|||||||
1277 | */ |
||||||
1278 | private function _GetAttachmentData($fid,$attname) |
||||||
1279 | { |
||||||
1280 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.": $fid (attname: '$attname')".function_backtrace()); |
||||||
1281 | //error_log(__METHOD__.__LINE__." Fid: $fid (attname: '$attname')"); |
||||||
1282 | list($folderid, $id, $part) = explode(":", $attname); |
||||||
1283 | |||||||
1284 | $this->splitID($folderid, $account, $folder); |
||||||
1285 | |||||||
1286 | if (!isset($this->mail)) $this->mail = Mail::getInstance(false,self::$profileID,true,false,true); |
||||||
1287 | |||||||
1288 | $this->mail->reopen($folder); |
||||||
1289 | $attachment = $this->mail->getAttachment($id,$part,0,false,true,$folder); |
||||||
1290 | $SIOattachment = new SyncItemOperationsAttachment(); |
||||||
1291 | fseek($attachment['attachment'], 0, SEEK_SET); // z-push requires stream seeked to start |
||||||
1292 | $SIOattachment->data = $attachment['attachment']; |
||||||
1293 | //ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.": $fid (attname: '$attname') Data:".$attachment['attachment']); |
||||||
1294 | if (isset($attachment['type']) ) |
||||||
1295 | $SIOattachment->contenttype = $attachment['type']; |
||||||
1296 | |||||||
1297 | unset($attachment); |
||||||
1298 | |||||||
1299 | return $SIOattachment; |
||||||
1300 | } |
||||||
1301 | |||||||
1302 | /** |
||||||
1303 | * StatMessage should return message stats, analogous to the folder stats (StatFolder). Entries are: |
||||||
1304 | * |
||||||
1305 | * 'id' => Server unique identifier for the message. Again, try to keep this short (under 20 chars) |
||||||
1306 | * 'flags' => simply '0' for unread, '1' for read |
||||||
1307 | * 'mod' => modification signature. As soon as this signature changes, the item is assumed to be completely |
||||||
1308 | * changed, and will be sent to the PDA as a whole. Normally you can use something like the modification |
||||||
1309 | * time for this field, which will change as soon as the contents have changed. |
||||||
1310 | * |
||||||
1311 | * @param string $folderid |
||||||
1312 | * @param int $id id (uid) of message |
||||||
1313 | * @return array |
||||||
1314 | */ |
||||||
1315 | public function StatMessage($folderid, $id) |
||||||
1316 | { |
||||||
1317 | $messages = $this->fetchMessages($folderid, NULL, $id); |
||||||
1318 | //ZLog::Write(LOGLEVEL_DEBUG, __METHOD__."('$folderid','$id') returning ".array2string($messages[$id])); |
||||||
1319 | return $messages[$id]; |
||||||
1320 | } |
||||||
1321 | |||||||
1322 | /** |
||||||
1323 | * Called when a message has been changed on the mobile. |
||||||
1324 | * Added support for FollowUp flag |
||||||
1325 | * |
||||||
1326 | * @param string $folderid id of the folder |
||||||
1327 | * @param string $id id of the message |
||||||
1328 | * @param SyncXXX $message the SyncObject containing a message |
||||||
0 ignored issues
–
show
The type
SyncXXX was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths ![]() |
|||||||
1329 | * @param ContentParameters $contentParameters |
||||||
1330 | * |
||||||
1331 | * @access public |
||||||
1332 | * @return array same return value as StatMessage() |
||||||
1333 | * @throws StatusException could throw specific SYNC_STATUS_* exceptions |
||||||
1334 | */ |
||||||
1335 | function ChangeMessage($folderid, $id, $message, $contentParameters) |
||||||
1336 | { |
||||||
1337 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__." $folderid, $id,".array2string($message).",".array2string($contentParameters)); |
||||||
1338 | //unset($folderid, $id, $message, $contentParameters); |
||||||
1339 | $account = $folder = null; |
||||||
1340 | $this->splitID($folderid, $account, $folder); |
||||||
1341 | if (isset($message->flag)) { |
||||||
1342 | if (isset($message->flag->flagstatus) && $message->flag->flagstatus == 2) { |
||||||
1343 | $rv = $this->mail->flagMessages((($message->flag->flagstatus == 2) ? "flagged" : "unflagged"), $id,$folder); |
||||||
1344 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__." -> set ".array2string($id).' in Folder '.$folder." as " . (($message->flag->flagstatus == 2) ? "flagged" : "unflagged") . "-->". $rv); |
||||||
1345 | } else { |
||||||
1346 | $rv = $this->mail->flagMessages("unflagged", $id,$folder); |
||||||
1347 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__." -> set ".array2string($id).' in Folder '.$folder." as " . "unflagged" . "-->". $rv); |
||||||
1348 | } |
||||||
1349 | } |
||||||
1350 | return $this->StatMessage($folderid, $id); |
||||||
1351 | } |
||||||
1352 | |||||||
1353 | /** |
||||||
1354 | * This function is called when the user moves an item on the PDA. You should do whatever is needed |
||||||
1355 | * to move the message on disk. After this call, StatMessage() and GetMessageList() should show the items |
||||||
1356 | * to have a new parent. This means that it will disappear from GetMessageList() will not return the item |
||||||
1357 | * at all on the source folder, and the destination folder will show the new message |
||||||
1358 | * |
||||||
1359 | * @param string $folderid id of the source folder |
||||||
1360 | * @param string $id id of the message |
||||||
1361 | * @param string $newfolderid id of the destination folder |
||||||
1362 | * @param ContentParameters $contentParameters |
||||||
1363 | * |
||||||
1364 | * @return boolean status of the operation |
||||||
1365 | * @throws StatusException could throw specific SYNC_MOVEITEMSSTATUS_* exceptions |
||||||
1366 | */ |
||||||
1367 | public function MoveMessage($folderid, $id, $newfolderid, $contentParameters) |
||||||
1368 | { |
||||||
1369 | unset($contentParameters); // not used, but required by function signature |
||||||
1370 | ZLog::Write(LOGLEVEL_DEBUG, "IMAP-MoveMessage: (sfid: '$folderid' id: '$id' dfid: '$newfolderid' )"); |
||||||
1371 | $account = $srcFolder = $destFolder = null; |
||||||
1372 | $this->splitID($folderid, $account, $srcFolder); |
||||||
1373 | $this->splitID($newfolderid, $account, $destFolder); |
||||||
1374 | ZLog::Write(LOGLEVEL_DEBUG, "IMAP-MoveMessage: (SourceFolder: '$srcFolder' id: '$id' DestFolder: '$destFolder' )"); |
||||||
1375 | if (!isset($this->mail)) $this->mail = Mail::getInstance(false,self::$profileID,true,false,true); |
||||||
1376 | $this->mail->reopen($destFolder); |
||||||
1377 | $status = $this->mail->getFolderStatus($destFolder); |
||||||
1378 | $uidNext = $status['uidnext']; |
||||||
1379 | $this->mail->reopen($srcFolder); |
||||||
1380 | |||||||
1381 | // move message |
||||||
1382 | $rv = $this->mail->moveMessages($destFolder,(array)$id,true,$srcFolder,true); |
||||||
1383 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.": New Status of $destFolder :".array2string($status).", ReturnValOf moveMessage".array2string($rv)); // this may be true, so try using the nextUID value by examine |
||||||
1384 | // return the new id "as string" |
||||||
1385 | return ($rv===true ? $uidNext : $rv[$id]) . ""; |
||||||
1386 | } |
||||||
1387 | |||||||
1388 | /** |
||||||
1389 | * Get all messages of a folder with optional cutoffdate |
||||||
1390 | * |
||||||
1391 | * @param int $cutoffdate =null timestamp with cutoffdate, default 12 weeks |
||||||
1392 | */ |
||||||
1393 | public function GetMessageList($folderid, $cutoffdate=NULL) |
||||||
1394 | { |
||||||
1395 | if ($cutoffdate > 0) |
||||||
1396 | { |
||||||
1397 | ZLog::Write(LOGLEVEL_DEBUG, __METHOD__.' for Folder:'.$folderid.' SINCE:'.$cutoffdate.'/'.date("d-M-Y", $cutoffdate)); |
||||||
1398 | } |
||||||
1399 | else |
||||||
1400 | { |
||||||
1401 | $maximumSyncRangeInDays = self::PAST_LIMIT; // corresponds to our default value |
||||||
1402 | if (isset($GLOBALS['egw_info']['user']['preferences']['activesync']['mail-maximumSyncRange'])) |
||||||
1403 | { |
||||||
1404 | $maximumSyncRangeInDays = $GLOBALS['egw_info']['user']['preferences']['activesync']['mail-maximumSyncRange']; |
||||||
1405 | } |
||||||
1406 | $cutoffdate = (is_numeric($maximumSyncRangeInDays) ? Api\DateTime::to('now','ts')-(3600*24*$maximumSyncRangeInDays):null); |
||||||
1407 | if (is_numeric($maximumSyncRangeInDays)) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.' Client set no truncationdate. Using '.$maximumSyncRangeInDays.' days.'.date("d-M-Y", $cutoffdate)); |
||||||
1408 | } |
||||||
1409 | try { |
||||||
1410 | return $this->fetchMessages($folderid, $cutoffdate); |
||||||
1411 | } catch (Exception $e) |
||||||
1412 | { |
||||||
1413 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' failed for '.$e->getMessage().($e->details?$e->details:'')); |
||||||
1414 | return array(); |
||||||
1415 | } |
||||||
1416 | } |
||||||
1417 | |||||||
1418 | /** |
||||||
1419 | * Fetch headers for one or all mail of a folder using optional cutoffdate |
||||||
1420 | * |
||||||
1421 | * Headers of last fetchMessage call of complate folder are cached in static $headers, |
||||||
1422 | * to allow to use them without fetching them again. |
||||||
1423 | * Next call clears cache |
||||||
1424 | * |
||||||
1425 | * @param int $folderid |
||||||
1426 | * @param int $cutoffdate timestamp with cutoffdate |
||||||
1427 | * @param string $_id =null uid of single message to fetch |
||||||
1428 | * @param boolean $return_all_headers =false true: additinal contain all headers eg. "subject" |
||||||
1429 | * @return array uid => array StatMessage($folderid, $_id) |
||||||
1430 | */ |
||||||
1431 | private function fetchMessages($folderid, $cutoffdate=NULL, $_id=NULL, $return_all_headers=false) |
||||||
1432 | { |
||||||
1433 | static $headers = array(); |
||||||
1434 | |||||||
1435 | if ($this->debugLevel>1) $gstarttime = microtime (true); |
||||||
1436 | //ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__); |
||||||
1437 | $rv_messages = array(); |
||||||
1438 | // if the message is still available within the class, we use it instead of fetching it again |
||||||
1439 | if ($_id && isset($headers[$_id]) && is_array($headers[$_id])) |
||||||
1440 | { |
||||||
1441 | //ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__." the message ".$_id[0]." is still available within the class, we use it instead of fetching it again"); |
||||||
1442 | $rv_messages = array('header'=>array($headers[$_id])); |
||||||
1443 | } |
||||||
1444 | else |
||||||
1445 | { |
||||||
1446 | $headers = array(); // clear cache to not use too much memory |
||||||
1447 | |||||||
1448 | if ($this->debugLevel>1) $starttime = microtime (true); |
||||||
1449 | $this->_connect($this->account); |
||||||
1450 | if ($this->debugLevel>1) |
||||||
1451 | { |
||||||
1452 | $endtime = microtime(true) - $starttime; |
||||||
1453 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__. " connect took : ".$endtime.' for account:'.$this->account); |
||||||
1454 | } |
||||||
1455 | $messagelist = $_filter = array(); |
||||||
0 ignored issues
–
show
|
|||||||
1456 | // if not connected, any further action must fail |
||||||
1457 | if (!empty($cutoffdate)) $_filter = array('status'=>array('UNDELETED'),'range'=>"SINCE",'date'=> date("d-M-Y", $cutoffdate)); |
||||||
1458 | if ($this->debugLevel>1) $starttime = microtime (true); |
||||||
1459 | $account = $_folderName = $id = null; |
||||||
1460 | $this->splitID($folderid,$account,$_folderName,$id); |
||||||
1461 | if ($this->debugLevel>1) |
||||||
1462 | { |
||||||
1463 | $endtime = microtime(true) - $starttime; |
||||||
1464 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__. " splitID took : ".$endtime.' for FolderID:'.$folderid); |
||||||
1465 | } |
||||||
1466 | if ($this->debugLevel>1) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.' for Folder:'.$_folderName.' Filter:'.array2string($_filter).' Ids:'.array2string($_id).'/'.$id); |
||||||
1467 | if ($this->debugLevel>1) $starttime = microtime (true); |
||||||
1468 | $_numberOfMessages = (empty($cutoffdate)?250:99999); |
||||||
1469 | $rv_messages = $this->mail->getHeaders($_folderName, $_startMessage=1, $_numberOfMessages, $_sort=0, $_reverse=false, $_filter, $_id); |
||||||
1470 | if ($this->debugLevel>1) |
||||||
1471 | { |
||||||
1472 | $endtime = microtime(true) - $starttime; |
||||||
1473 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__. " getHeaders call took : ".$endtime.' for FolderID:'.$_folderName); |
||||||
1474 | } |
||||||
1475 | } |
||||||
1476 | if ($_id == NULL && $this->debugLevel>1) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__." found :". count($rv_messages['header'])); |
||||||
0 ignored issues
–
show
|
|||||||
1477 | //ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' Result:'.array2string($rv_messages)); |
||||||
1478 | $messagelist = array(); |
||||||
1479 | if (!isset($rv_messages['header'])||empty($rv_messages['header'])) return $messagelist; |
||||||
1480 | //if ($_returnModHash) $messageFolderHash = array(); |
||||||
1481 | foreach ((array)$rv_messages['header'] as $k => $vars) |
||||||
1482 | { |
||||||
1483 | if ($this->debugLevel>3) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' ID to process:'.$vars['uid'].' Subject:'.$vars['subject']); |
||||||
1484 | $headers[$vars['uid']] = $vars; |
||||||
1485 | if ($this->debugLevel>3) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' MailID:'.$k.'->'.array2string($vars)); |
||||||
1486 | if (!empty($vars['deleted'])) continue; // cut of deleted messages |
||||||
1487 | if ($cutoffdate && $vars['date'] < $cutoffdate) continue; // message is out of range for cutoffdate, ignore it |
||||||
0 ignored issues
–
show
The expression
$cutoffdate of type integer|null is loosely compared to true ; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.
In PHP, under loose comparison (like For 0 == false // true
0 == null // true
123 == false // false
123 == null // false
// It is often better to use strict comparison
0 === false // false
0 === null // false
![]() |
|||||||
1488 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' ID to report:'.$vars['uid'].' Subject:'.$vars['subject']); |
||||||
1489 | $mess = $return_all_headers ? $vars : array(); |
||||||
1490 | $mess["mod"] = self::doFlagsMod($vars).$vars['date']; |
||||||
1491 | $mess["id"] = $vars['uid']; |
||||||
1492 | // 'seen' aka 'read' is the only flag we want to know about |
||||||
1493 | $mess["flags"] = 0; |
||||||
1494 | // outlook supports additional flags, set them to 0 |
||||||
1495 | if($vars["seen"]) $mess["flags"] = 1; |
||||||
1496 | if ($this->debugLevel>3) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.array2string($mess)); |
||||||
1497 | $messagelist[$vars['uid']] = $mess; |
||||||
1498 | unset($mess); |
||||||
1499 | } |
||||||
1500 | if ($this->debugLevel>1) |
||||||
1501 | { |
||||||
1502 | $endtime = microtime(true) - $gstarttime; |
||||||
1503 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__. " total time used : ".$endtime.' for Folder:'.$_folderName.' Filter:'.array2string($_filter).' Ids:'.array2string($_id).'/'.$id); |
||||||
1504 | } |
||||||
1505 | return $messagelist; |
||||||
1506 | } |
||||||
1507 | |||||||
1508 | /** |
||||||
1509 | * Prepare headeinfo on a message to return some standardized string to tell which flags are set for a message |
||||||
1510 | * |
||||||
1511 | * AS currently only supports flagged, answered/replied and forwarded flags. |
||||||
1512 | * Seen/read is in under flags key of stat! |
||||||
1513 | * |
||||||
1514 | * @param array $headerFlags - array to process, a full return array from getHeaders |
||||||
1515 | * @link https://sourceforge.net/p/zimbrabackend/code/HEAD/tree/zimbra-backend/branches/z-push-2/zimbra.php#l11652 |
||||||
1516 | * @return string string of a representation of supported flags |
||||||
1517 | */ |
||||||
1518 | static function doFlagsMod($headerFlags) |
||||||
1519 | { |
||||||
1520 | $flags = 'nnn'; |
||||||
1521 | if ($headerFlags['flagged']) $flags[0] = 'f'; |
||||||
1522 | if ($headerFlags['answered']) $flags[1] = 'a'; |
||||||
1523 | if ($headerFlags['forwarded']) $flags[2] = 'f'; |
||||||
1524 | //ZLog::Write(LOGLEVEL_DEBUG, __METHOD__.'('.array2string($headerFlags).') returning '.array2string($flags)); |
||||||
1525 | return $flags; |
||||||
1526 | } |
||||||
1527 | |||||||
1528 | /** |
||||||
1529 | * Search mailbox for a given pattern |
||||||
1530 | * |
||||||
1531 | * @param object $_searchquery holds information specifying the query with GetDataArray it holds |
||||||
1532 | * [searchname] => MAILBOX |
||||||
1533 | * [searchfolderid] => 101000000000 |
||||||
1534 | * [searchfreetext] => somesearchtexgt |
||||||
1535 | * [searchdatereceivedgreater] => 1 |
||||||
1536 | * [searchvaluegreater] => 2015-07-06T22:00:00.000Z |
||||||
1537 | * [searchdatereceivedless] => 1 |
||||||
1538 | * [searchvalueless] => 2015-07-14T15:11:00.000Z |
||||||
1539 | * [searchrebuildresults] => 1 |
||||||
1540 | * [searchrange] => 0-99 |
||||||
1541 | * [bodypref] => Array([1] => BodyPreference Object([unsetdata:protected] => Array([truncationsize] => [allornone] => [preview] => )[SO_internalid:StateObject:private] => [data:protected] => |
||||||
1542 | * Array([truncationsize] => 2147483647)[changed:protected] => 1)) |
||||||
1543 | * [mimesupport] => 2) |
||||||
1544 | * @return array(["range"] = $_searchquery->GetSearchRange(), ['searchtotal'] = count of results, |
||||||
1545 | * array("class" => "Email", |
||||||
1546 | * "longid" => folderid.':'.uid', |
||||||
1547 | * "folderid" => folderid, |
||||||
1548 | * ), .... |
||||||
1549 | * ) |
||||||
1550 | */ |
||||||
1551 | public function getSearchResultsMailbox($_searchquery) |
||||||
1552 | { |
||||||
1553 | //$this->debugLevel=1; |
||||||
1554 | $searchquery=$_searchquery->GetDataArray(); |
||||||
1555 | if (!is_array($searchquery)) return array(); |
||||||
1556 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.array2string($searchquery)); |
||||||
1557 | |||||||
1558 | if (isset($searchquery['searchrebuildresults'])) { |
||||||
1559 | $rebuildresults = $searchquery['searchrebuildresults']; |
||||||
1560 | } else { |
||||||
1561 | $rebuildresults = false; |
||||||
1562 | } |
||||||
1563 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG, 'RebuildResults ['.$rebuildresults.']' ); |
||||||
1564 | |||||||
1565 | if (isset($searchquery['deeptraversal'])) { |
||||||
1566 | $deeptraversal = $searchquery['deeptraversal']; |
||||||
1567 | } else { |
||||||
1568 | $deeptraversal = false; |
||||||
1569 | } |
||||||
1570 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG, 'DeepTraversal ['.$deeptraversal.']' ); |
||||||
1571 | |||||||
1572 | if (isset($searchquery['searchrange'])) { |
||||||
1573 | $range = explode("-",$_searchquery->GetSearchRange()); |
||||||
1574 | $start =$range[0] + 1; |
||||||
1575 | $limit = $range[1] - $range[0] + 1; |
||||||
1576 | } else { |
||||||
1577 | $range = false; |
||||||
1578 | } |
||||||
1579 | if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG, 'Range ['.print_r($range, true).']' ); |
||||||
1580 | |||||||
1581 | //foreach($searchquery['query'] as $k => $value) { |
||||||
1582 | // $query = $value; |
||||||
1583 | //} |
||||||
1584 | if (isset($searchquery['searchfolderid'])) |
||||||
1585 | { |
||||||
1586 | $folderid = $searchquery['searchfolderid']; |
||||||
1587 | } |
||||||
1588 | /* |
||||||
1589 | // other types may be possible - we support quicksearch first (freeText in subject and from (or TO in Sent Folder)) |
||||||
1590 | if (is_null(Mail::$supportsORinQuery) || !isset(Mail::$supportsORinQuery[self::$profileID])) |
||||||
1591 | { |
||||||
1592 | Mail::$supportsORinQuery = Api\Cache::getCache(Api\Cache::INSTANCE,'email','supportsORinQuery'.trim($GLOBALS['egw_info']['user']['account_id']),$callback=null,$callback_params=array(),$expiration=60*60*10); |
||||||
1593 | if (!isset(Mail::$supportsORinQuery[self::$profileID])) Mail::$supportsORinQuery[self::$profileID]=true; |
||||||
1594 | } |
||||||
1595 | */ |
||||||
1596 | if (isset($searchquery['searchfreetext'])) |
||||||
1597 | { |
||||||
1598 | $searchText = $searchquery['searchfreetext']; |
||||||
1599 | } |
||||||
1600 | if (!$folderid) |
||||||
1601 | { |
||||||
1602 | $_folderName = ($this->mail->sessionData['mailbox']?$this->mail->sessionData['mailbox']:'INBOX'); |
||||||
1603 | $folderid = $this->createID($account=0,$_folderName); |
||||||
1604 | } |
||||||
1605 | $rv = $this->splitID($folderid,$account,$_folderName,$id); |
||||||
0 ignored issues
–
show
Are you sure the assignment to
$rv is correct as $this->splitID($folderid...unt, $_folderName, $id) targeting mail_zpush::splitID() seems to always return null.
This check looks for function or method calls that always return null and whose return value is assigned to a variable. class A
{
function getObject()
{
return null;
}
}
$a = new A();
$object = $a->getObject();
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||||||
1606 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' ProfileID:'.self::$profileID.' FolderID:'.$folderid.' Foldername:'.$_folderName); |
||||||
1607 | $this->_connect($account); |
||||||
1608 | // this should not be needed ??? |
||||||
1609 | Mail::$supportsORinQuery[self::$profileID]=true; // trigger quicksearch (if possible) |
||||||
1610 | $_filter = array('type'=> (Mail::$supportsORinQuery[self::$profileID]?'quick':'subject'), |
||||||
1611 | 'string'=> $searchText, |
||||||
1612 | 'status'=>'any' |
||||||
1613 | ); |
||||||
1614 | |||||||
1615 | if (isset($searchquery['searchdatereceivedgreater']) || isset($searchquery['searchdatereceivedless'])) |
||||||
1616 | { |
||||||
1617 | /* |
||||||
1618 | * We respect only the DATEPART of the RANGE specified |
||||||
1619 | * [searchdatereceivedgreater] => 1 |
||||||
1620 | * [searchvaluegreater] => 2015-07-06T22:00:00.000Z , SINCE |
||||||
1621 | * [searchdatereceivedless] => 1 |
||||||
1622 | * [searchvalueless] => 2015-07-14T15:11:00.000Z , BEFORE |
||||||
1623 | */ |
||||||
1624 | $_filter['range'] = "BETWEEN"; |
||||||
1625 | list($sincedate,$crap) = explode('T',$searchquery['searchvaluegreater']); |
||||||
1626 | list($beforedate,$crap) = explode('T',$searchquery['searchvalueless']); |
||||||
1627 | $_filter['before'] = date("d-M-Y", Api\DateTime::to($beforedate,'ts')); |
||||||
1628 | $_filter['since'] = date("d-M-Y", Api\DateTime::to($sincedate,'ts')); |
||||||
1629 | } |
||||||
1630 | //$_filter[] = array('type'=>"SINCE",'string'=> date("d-M-Y", $cutoffdate)); |
||||||
1631 | if ($this->debugLevel>1) ZLog::Write(LOGLEVEL_DEBUG, __METHOD__.' for Folder:'.$_folderName.' Filter:'.array2string($_filter)); |
||||||
1632 | $rv_messages = $this->mail->getHeaders($_folderName, $_startMessage=($range?$start:1), $_numberOfMessages=($limit?$limit:9999999), $_sort=0, $_reverse=false, $_filter, $_id=NULL); |
||||||
1633 | //ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.array2string($rv_messages)); |
||||||
1634 | $list=array(); |
||||||
1635 | |||||||
1636 | $cnt = count($rv_messages['header']); |
||||||
1637 | //$list['status'] = 1; |
||||||
1638 | $list['searchtotal'] = $cnt; |
||||||
1639 | $list["range"] = $_searchquery->GetSearchRange(); |
||||||
1640 | foreach((array)$rv_messages['header'] as $i => $vars) |
||||||
1641 | { |
||||||
1642 | $list[] = array( |
||||||
1643 | "class" => "Email", |
||||||
1644 | "longid" => $folderid.':'.$vars['uid'], |
||||||
1645 | "folderid" => $folderid, |
||||||
1646 | ); |
||||||
1647 | } |
||||||
1648 | //error_log(__METHOD__.__LINE__.array2string($list)); |
||||||
1649 | //ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.array2string($list)); |
||||||
1650 | return $list; |
||||||
1651 | } |
||||||
1652 | |||||||
1653 | /** |
||||||
1654 | * Get ID of parent Folder or '0' for folders in root |
||||||
1655 | * |
||||||
1656 | * @param int $account |
||||||
1657 | * @param string $folder |
||||||
1658 | * @return string |
||||||
1659 | */ |
||||||
1660 | private function getParentID($account,$folder) |
||||||
1661 | { |
||||||
1662 | $this->_connect($account); |
||||||
1663 | if (!isset($this->folders)) $this->folders = $this->mail->getFolderObjects(true,false); |
||||||
1664 | |||||||
1665 | $mailFolder = $this->folders[$folder]; |
||||||
1666 | if (!isset($mailFolder)) return false; |
||||||
1667 | $delimiter = (isset($mailFolder->delimiter)?$mailFolder->delimiter:$this->mail->getHierarchyDelimiter()); |
||||||
1668 | $parent = explode($delimiter,$folder); |
||||||
1669 | array_pop($parent); |
||||||
1670 | $parent = implode($delimiter,$parent); |
||||||
1671 | |||||||
1672 | $id = $parent && $this->folders[$parent] ? $this->createID($account, $parent) : '0'; |
||||||
1673 | if ($this->debugLevel>1) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."('$folder') --> parent=$parent --> $id"); |
||||||
1674 | return $id; |
||||||
1675 | } |
||||||
1676 | |||||||
1677 | /** |
||||||
1678 | * Get Information about a folder |
||||||
1679 | * |
||||||
1680 | * @param string $id |
||||||
1681 | * @return SyncFolder|boolean false on error |
||||||
1682 | */ |
||||||
1683 | public function GetFolder($id) |
||||||
1684 | { |
||||||
1685 | static $last_id = null; |
||||||
1686 | static $folderObj = null; |
||||||
1687 | if (isset($last_id) && $last_id === $id) return $folderObj; |
||||||
1688 | |||||||
1689 | try { |
||||||
1690 | $account = $folder = null; |
||||||
1691 | $this->splitID($id, $account, $folder); |
||||||
1692 | } |
||||||
1693 | catch(Exception $e) { |
||||||
1694 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' failed for '.$e->getMessage()); |
||||||
1695 | return $folderObj=false; |
||||||
1696 | } |
||||||
1697 | $this->_connect($account); |
||||||
1698 | if (!isset($this->folders)) $this->folders = $this->mail->getFolderObjects(true,false); |
||||||
1699 | |||||||
1700 | $mailFolder = $this->folders[$folder]; |
||||||
1701 | if (!isset($mailFolder)) return $folderObj=false; |
||||||
1702 | |||||||
1703 | $folderObj = new SyncFolder(); |
||||||
1704 | $folderObj->serverid = $id; |
||||||
1705 | $folderObj->parentid = $this->getParentID($account,$folder); |
||||||
1706 | $folderObj->displayname = $mailFolder->shortDisplayName; |
||||||
1707 | if ($this->debugLevel>1) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__." ID: $id, Account:$account, Folder:$folder"); |
||||||
1708 | // get folder-type |
||||||
1709 | foreach($this->folders as $inbox => $mailFolder) break; |
||||||
1710 | if ($folder == $inbox) |
||||||
1711 | { |
||||||
1712 | $folderObj->type = SYNC_FOLDER_TYPE_INBOX; |
||||||
1713 | } |
||||||
1714 | elseif($this->mail->isDraftFolder($folder, false, true)) |
||||||
1715 | { |
||||||
1716 | //ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.' isDraft'); |
||||||
1717 | $folderObj->type = SYNC_FOLDER_TYPE_DRAFTS; |
||||||
1718 | $folderObj->parentid = 0; // required by devices |
||||||
1719 | } |
||||||
1720 | elseif($this->mail->isTrashFolder($folder, false, true)) |
||||||
1721 | { |
||||||
1722 | $folderObj->type = SYNC_FOLDER_TYPE_WASTEBASKET; |
||||||
1723 | $this->_wasteID = $folder; |
||||||
1724 | //error_log(__METHOD__.__LINE__.' TrashFolder:'.$this->_wasteID); |
||||||
1725 | $folderObj->parentid = 0; // required by devices |
||||||
1726 | } |
||||||
1727 | elseif($this->mail->isSentFolder($folder, false, true)) |
||||||
1728 | { |
||||||
1729 | $folderObj->type = SYNC_FOLDER_TYPE_SENTMAIL; |
||||||
1730 | $folderObj->parentid = 0; // required by devices |
||||||
1731 | $this->_sentID = $folder; |
||||||
1732 | //error_log(__METHOD__.__LINE__.' SentFolder:'.$this->_sentID); |
||||||
1733 | } |
||||||
1734 | elseif($this->mail->isOutbox($folder, false, true)) |
||||||
1735 | { |
||||||
1736 | //ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.' isOutbox'); |
||||||
1737 | $folderObj->type = SYNC_FOLDER_TYPE_OUTBOX; |
||||||
1738 | $folderObj->parentid = 0; // required by devices |
||||||
1739 | } |
||||||
1740 | else |
||||||
1741 | { |
||||||
1742 | //ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.' isOther Folder'.$folder); |
||||||
1743 | $folderObj->type = SYNC_FOLDER_TYPE_USER_MAIL; |
||||||
1744 | } |
||||||
1745 | |||||||
1746 | if ($this->debugLevel>1) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."($id) --> $folder --> type=$folderObj->type, parentID=$folderObj->parentid, displayname=$folderObj->displayname"); |
||||||
1747 | return $folderObj; |
||||||
1748 | } |
||||||
1749 | |||||||
1750 | /** |
||||||
1751 | * Return folder stats. This means you must return an associative array with the |
||||||
1752 | * following properties: |
||||||
1753 | * |
||||||
1754 | * "id" => The server ID that will be used to identify the folder. It must be unique, and not too long |
||||||
1755 | * How long exactly is not known, but try keeping it under 20 chars or so. It must be a string. |
||||||
1756 | * "parent" => The server ID of the parent of the folder. Same restrictions as 'id' apply. |
||||||
1757 | * "mod" => This is the modification signature. It is any arbitrary string which is constant as long as |
||||||
1758 | * the folder has not changed. In practice this means that 'mod' can be equal to the folder name |
||||||
1759 | * as this is the only thing that ever changes in folders. (the type is normally constant) |
||||||
1760 | * |
||||||
1761 | * @return array with values for keys 'id', 'mod' and 'parent' |
||||||
1762 | */ |
||||||
1763 | public function StatFolder($id) |
||||||
1764 | { |
||||||
1765 | $folder = $this->GetFolder($id); |
||||||
1766 | |||||||
1767 | $stat = array( |
||||||
1768 | 'id' => $id, |
||||||
1769 | 'mod' => $folder->displayname, |
||||||
1770 | 'parent' => $folder->parentid, |
||||||
1771 | ); |
||||||
1772 | |||||||
1773 | return $stat; |
||||||
1774 | } |
||||||
1775 | |||||||
1776 | |||||||
1777 | /** |
||||||
1778 | * Return a changes array |
||||||
1779 | * |
||||||
1780 | * if changes occurr default diff engine computes the actual changes |
||||||
1781 | * |
||||||
1782 | * @param string $folderid |
||||||
1783 | * @param string &$syncstate on call old syncstate, on return new syncstate |
||||||
1784 | * @return array|boolean false if $folderid not found, array() if no changes or array(array("type" => "fakeChange")) |
||||||
1785 | */ |
||||||
1786 | function AlterPingChanges($folderid, &$syncstate) |
||||||
1787 | { |
||||||
1788 | $account = $folder = null; |
||||||
1789 | $this->splitID($folderid, $account, $folder); |
||||||
1790 | if (is_numeric($account)) $type = 'mail'; |
||||||
1791 | |||||||
1792 | if ($type != 'mail') return false; |
||||||
1793 | |||||||
1794 | if (!isset($this->mail)) $this->mail = Mail::getInstance(false,self::$profileID,true,false,true); |
||||||
1795 | if (!$this->mail->folderIsSelectable($folder)) |
||||||
1796 | { |
||||||
1797 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.": could not select folder $folder returning fake state"); |
||||||
1798 | $syncstate = "M:".'0'."-R:".'0'."-U:".'0'."-NUID:".'0'."-UIDV:".'0'; |
||||||
1799 | return array(); |
||||||
1800 | } |
||||||
1801 | |||||||
1802 | $this->mail->reopen($folder); |
||||||
1803 | |||||||
1804 | if (!($status = $this->mail->getFolderStatus($folder,$ignoreStatusCache=true))) |
||||||
1805 | { |
||||||
1806 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.": could not stat folder $folder "); |
||||||
1807 | return false; |
||||||
1808 | } |
||||||
1809 | $syncstate = "M:". $status['messages'] ."-R:". $status['recent'] ."-U:". $status['unseen']."-NUID:".$status['uidnext']."-UIDV:".$status['uidvalidity']; |
||||||
1810 | |||||||
1811 | if ($this->debugLevel) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."($folderid, ...) $folder ($account) returning ".array2string($syncstate)); |
||||||
1812 | return array(); |
||||||
1813 | } |
||||||
1814 | |||||||
1815 | /** |
||||||
1816 | * Should return a wastebasket folder if there is one. This is used when deleting |
||||||
1817 | * items; if this function returns a valid folder ID, then all deletes are handled |
||||||
1818 | * as moves and are sent to your backend as a move. If it returns FALSE, then deletes |
||||||
1819 | * are always handled as real deletes and will be sent to your importer as a DELETE |
||||||
1820 | */ |
||||||
1821 | function GetWasteBasket() |
||||||
1822 | { |
||||||
1823 | $this->_connect($this->account); |
||||||
1824 | $id = $this->createID($account=0, $this->_wasteID); |
||||||
1825 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__."() account=$this->account returned $id for folder $this->_wasteID"); |
||||||
1826 | return $id; |
||||||
1827 | } |
||||||
1828 | |||||||
1829 | /** |
||||||
1830 | * Called when the user has requested to delete (really delete) a message. Usually |
||||||
1831 | * this means just unlinking the file its in or somesuch. After this call has succeeded, a call to |
||||||
1832 | * GetMessageList() should no longer list the message. If it does, the message will be re-sent to the mobile |
||||||
1833 | * as it will be seen as a 'new' item. This means that if this method is not implemented, it's possible to |
||||||
1834 | * delete messages on the PDA, but as soon as a sync is done, the item will be resynched to the mobile |
||||||
1835 | * |
||||||
1836 | * @param string $folderid id of the folder |
||||||
1837 | * @param string $id id of the message |
||||||
1838 | * @param ContentParameters $contentParameters |
||||||
1839 | * |
||||||
1840 | * @access public |
||||||
1841 | * @return boolean status of the operation |
||||||
1842 | * @throws StatusException could throw specific SYNC_STATUS_* exceptions |
||||||
1843 | */ |
||||||
1844 | public function DeleteMessage($folderid, $id, $contentParameters) |
||||||
1845 | { |
||||||
1846 | unset($contentParameters); // not used, but required by function signature |
||||||
1847 | ZLog::Write(LOGLEVEL_DEBUG, "IMAP-DeleteMessage: (fid: '$folderid' id: '$id' )"); |
||||||
1848 | /* |
||||||
1849 | $this->imap_reopenFolder($folderid); |
||||||
1850 | $s1 = @imap_delete ($this->_mbox, $id, FT_UID); |
||||||
1851 | $s11 = @imap_setflag_full($this->_mbox, $id, "\\Deleted", FT_UID); |
||||||
1852 | $s2 = @imap_expunge($this->_mbox); |
||||||
1853 | */ |
||||||
1854 | // we may have to split folderid |
||||||
1855 | $account = $folder = null; |
||||||
1856 | $this->splitID($folderid, $account, $folder); |
||||||
1857 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' '.$folderid.'->'.$folder); |
||||||
1858 | $_messageUID = (array)$id; |
||||||
1859 | |||||||
1860 | $this->_connect($this->account); |
||||||
1861 | $this->mail->reopen($folder); |
||||||
1862 | try |
||||||
1863 | { |
||||||
1864 | $rv = $this->mail->deleteMessages($_messageUID, $folder); |
||||||
1865 | } |
||||||
1866 | catch (Api\Exception $e) |
||||||
1867 | { |
||||||
1868 | $error = $e->getMessage(); |
||||||
1869 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__." $_messageUID, $folder ->".$error); |
||||||
1870 | // if the server thinks the message does not exist report deletion as success |
||||||
1871 | if (stripos($error,'[NONEXISTENT]')!==false) return true; |
||||||
1872 | return false; |
||||||
1873 | } |
||||||
1874 | |||||||
1875 | // this may be a bit rude, it may be sufficient that GetMessageList does not list messages flagged as deleted |
||||||
1876 | if ($this->mail->mailPreferences['deleteOptions'] == 'mark_as_deleted') |
||||||
1877 | { |
||||||
1878 | // ignore mark as deleted -> Expunge! |
||||||
1879 | //$this->mail->icServer->expunge(); // do not expunge as GetMessageList does not List messages flagged as deleted |
||||||
1880 | } |
||||||
1881 | ZLog::Write(LOGLEVEL_DEBUG, "IMAP-DeleteMessage: $rv"); |
||||||
1882 | |||||||
1883 | return $rv; |
||||||
1884 | } |
||||||
1885 | |||||||
1886 | /** |
||||||
1887 | * Changes the 'read' flag of a message on disk. The $flags |
||||||
1888 | * parameter can only be '1' (read) or '0' (unread). After a call to |
||||||
1889 | * SetReadFlag(), GetMessageList() should return the message with the |
||||||
1890 | * new 'flags' but should not modify the 'mod' parameter. If you do |
||||||
1891 | * change 'mod', simply setting the message to 'read' on the mobile will trigger |
||||||
1892 | * a full resync of the item from the server. |
||||||
1893 | * |
||||||
1894 | * @param string $folderid id of the folder |
||||||
1895 | * @param string $id id of the message |
||||||
1896 | * @param int $flags read flag of the message |
||||||
1897 | * @param ContentParameters $contentParameters |
||||||
1898 | * |
||||||
1899 | * @access public |
||||||
1900 | * @return boolean status of the operation |
||||||
1901 | * @throws StatusException could throw specific SYNC_STATUS_* exceptions |
||||||
1902 | */ |
||||||
1903 | public function SetReadFlag($folderid, $id, $flags, $contentParameters) |
||||||
1904 | { |
||||||
1905 | unset($contentParameters); // not used, but required by function signature |
||||||
1906 | // ZLog::Write(LOGLEVEL_DEBUG, "IMAP-SetReadFlag: (fid: '$folderid' id: '$id' flags: '$flags' )"); |
||||||
1907 | $account = $folder = null; |
||||||
1908 | $this->splitID($folderid, $account, $folder); |
||||||
1909 | |||||||
1910 | $_messageUID = (array)$id; |
||||||
1911 | $this->_connect($this->account); |
||||||
1912 | $rv = $this->mail->flagMessages((($flags) ? "read" : "unread"), $_messageUID,$folder); |
||||||
1913 | ZLog::Write(LOGLEVEL_DEBUG, "IMAP-SetReadFlag -> set ".array2string($_messageUID).' in Folder '.$folder." as " . (($flags) ? "read" : "unread") . "-->". $rv); |
||||||
1914 | |||||||
1915 | return $rv; |
||||||
1916 | } |
||||||
1917 | |||||||
1918 | /** |
||||||
1919 | * Creates or modifies a folder |
||||||
1920 | * |
||||||
1921 | * @param string $id of the parent folder |
||||||
1922 | * @param string $oldid => if empty -> new folder created, else folder is to be renamed |
||||||
1923 | * @param string $displayname => new folder name (to be created, or to be renamed to) |
||||||
1924 | * @param string $type folder type, ignored in IMAP |
||||||
1925 | * |
||||||
1926 | * @throws StatusException could throw specific SYNC_FSSTATUS_* exceptions |
||||||
1927 | * @return array|boolean stat array or false on error |
||||||
1928 | */ |
||||||
1929 | public function ChangeFolder($id, $oldid, $displayname, $type) |
||||||
1930 | { |
||||||
1931 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."('$id', '$oldid', '$displayname', $type)"); |
||||||
1932 | $account = $parent_id = null; |
||||||
0 ignored issues
–
show
|
|||||||
1933 | $this->splitID($id, $account, $parentFolder, $app); |
||||||
1934 | |||||||
1935 | $parent_id = $this->folder2hash($account, $parentFolder); |
||||||
1936 | $old_hash = $oldFolder = null; |
||||||
1937 | |||||||
1938 | if (empty($oldid)) |
||||||
1939 | { |
||||||
1940 | $action = 'create'; |
||||||
1941 | } |
||||||
1942 | else |
||||||
1943 | { |
||||||
1944 | $action = 'rename'; |
||||||
1945 | $this->splitID($oldid, $account, $oldFolder, $app); |
||||||
1946 | $old_hash = $this->folder2hash($account, $oldFolder); |
||||||
1947 | } |
||||||
1948 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.":{$action}Folder('$id'=>($parentFolder ($parent_id)), '$oldid'".($oldid?"=>($oldFolder ($old_hash))":'').", '$displayname', $type)"); |
||||||
1949 | $this->_connect($this->account); |
||||||
1950 | try |
||||||
1951 | { |
||||||
1952 | if ($action=='rename') |
||||||
1953 | { |
||||||
1954 | $newFolderName = $this->mail->renameFolder($oldFolder, $parentFolder, $displayname); |
||||||
1955 | } |
||||||
1956 | elseif ($action=='create') |
||||||
1957 | { |
||||||
1958 | $error=null; |
||||||
1959 | $newFolderName = $this->mail->createFolder($parentFolder, $displayname, $error); |
||||||
1960 | } |
||||||
1961 | } |
||||||
1962 | catch (\Exception $e) |
||||||
1963 | { |
||||||
1964 | //throw new Exception(__METHOD__." $action failed for $oldFolder ($action: $displayname) with error:".$e->getMessage()); |
||||||
1965 | return false; |
||||||
1966 | } |
||||||
1967 | $newHash = $this->rename_folder_hash($account, $old_hash, $newFolderName); |
||||||
1968 | $newID = $this->createID($account, $newHash); |
||||||
1969 | $this->folders = $this->mail->getFolderObjects(true,false,$_alwaysGetDefaultFolders=true,false); |
||||||
1970 | ZLog::Write(LOGLEVEL_DEBUG,":{$action}Folder('$id'=>($parentFolder), '$oldid'".($oldid?"=>($oldFolder)":'').", '$displayname' => $newFolderName (ID:$newID))"); |
||||||
1971 | return $this->StatFolder($newID); |
||||||
1972 | } |
||||||
1973 | |||||||
1974 | /** |
||||||
1975 | * Deletes (really delete) a Folder |
||||||
1976 | * |
||||||
1977 | * @param string $id of the folder to delete |
||||||
1978 | * @param string $parentid (=false) of the folder to delete, may be false/not set |
||||||
1979 | * |
||||||
1980 | * @throws StatusException could throw specific SYNC_FSSTATUS_* exceptions |
||||||
1981 | * @return boolean true or false on error |
||||||
1982 | */ |
||||||
1983 | public function DeleteFolder($id, $parentid=false) |
||||||
1984 | { |
||||||
1985 | $account = $parent_id = $app = null; |
||||||
0 ignored issues
–
show
|
|||||||
1986 | $this->splitID($id, $account, $folder, $app); |
||||||
1987 | $old_hash = $this->folder2hash($account, $folder); |
||||||
1988 | if ($parentid) $this->splitID($parentid, $account, $parentfolder, $app); |
||||||
1989 | ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."( '$id (-> $folder)','$parentid ".($parentid?'(->'.$parentfolder.')':'')."') called!"); |
||||||
1990 | $ret = $this->mail->deleteFolder($folder); |
||||||
1991 | if ($ret) $newHash = $this->rename_folder_hash($account, $old_hash, "##Dele#edFolder#$folder##"); |
||||||
0 ignored issues
–
show
|
|||||||
1992 | $this->folders = $this->mail->getFolderObjects(true,false,$_alwaysGetDefaultFolders=true,false); |
||||||
1993 | return $ret; |
||||||
1994 | } |
||||||
1995 | |||||||
1996 | /** |
||||||
1997 | * modify olflags (outlook style) flag of a message |
||||||
1998 | * |
||||||
1999 | * @param $folderid |
||||||
2000 | * @param $id |
||||||
2001 | * @param $flags |
||||||
2002 | * |
||||||
2003 | * |
||||||
2004 | * @DESC The $flags parameter must contains the poommailflag Object |
||||||
2005 | */ |
||||||
2006 | function ChangeMessageFlag($folderid, $id, $flags) |
||||||
2007 | { |
||||||
2008 | $_messageUID = (array)$id; |
||||||
2009 | $this->_connect($this->account); |
||||||
2010 | $account = $folder = null; |
||||||
2011 | $this->splitID($folderid, $account, $folder); |
||||||
2012 | $rv = $this->mail->flagMessages((($flags->flagstatus == 2) ? "flagged" : "unflagged"), $_messageUID,$folder); |
||||||
2013 | ZLog::Write(LOGLEVEL_DEBUG, "IMAP-SetFlaggedFlag -> set ".array2string($_messageUID).' in Folder '.$folder." as " . (($flags->flagstatus == 2) ? "flagged" : "unflagged") . "-->". $rv); |
||||||
2014 | |||||||
2015 | return $rv; |
||||||
2016 | } |
||||||
2017 | |||||||
2018 | /** |
||||||
2019 | * Create a max. 32 hex letter ID, current 20 chars are used |
||||||
2020 | * |
||||||
2021 | * @param int $account mail account id |
||||||
2022 | * @param string $folder |
||||||
2023 | * @param int $id =0 |
||||||
2024 | * @return string |
||||||
2025 | * @throws Api\Exception\WrongParameter |
||||||
2026 | */ |
||||||
2027 | private function createID($account,$folder,$id=0) |
||||||
2028 | { |
||||||
2029 | if (!is_numeric($folder)) |
||||||
2030 | { |
||||||
2031 | // convert string $folder in numeric id |
||||||
2032 | $folder = $this->folder2hash($account,$f=$folder); |
||||||
2033 | } |
||||||
2034 | |||||||
2035 | $str = $this->backend->createID($account, $folder, $id); |
||||||
2036 | |||||||
2037 | if ($this->debugLevel>1) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."($account,'$f',$id) type=$account, folder=$folder --> '$str'"); |
||||||
2038 | |||||||
2039 | return $str; |
||||||
2040 | } |
||||||
2041 | |||||||
2042 | /** |
||||||
2043 | * Split an ID string into $app, $account $folder and $appid |
||||||
2044 | * |
||||||
2045 | * @param string $str |
||||||
2046 | * @param int &$account mail account id |
||||||
2047 | * @param string &$folder |
||||||
2048 | * @param int &$appid=null (for mail=mail is to be expected) |
||||||
2049 | * @throws Api\Exception\WrongParameter |
||||||
2050 | */ |
||||||
2051 | private function splitID($str,&$account,&$folder,&$appid=null) |
||||||
2052 | { |
||||||
2053 | $this->backend->splitID($str, $account, $folder, $appid); |
||||||
2054 | |||||||
2055 | // convert numeric folder-id back to folder name |
||||||
2056 | $folder = $this->hash2folder($account,$f=$folder); |
||||||
2057 | |||||||
2058 | if ($this->debugLevel>1) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."('$str','$account','$folder',$appid)"); |
||||||
2059 | } |
||||||
2060 | |||||||
2061 | /** |
||||||
2062 | * Methods to convert (hierarchical) folder names to nummerical id's |
||||||
2063 | * |
||||||
2064 | * This is currently done by storing a serialized array in the device specific |
||||||
2065 | * state directory. |
||||||
2066 | */ |
||||||
2067 | |||||||
2068 | /** |
||||||
2069 | * Convert folder string to nummeric hash |
||||||
2070 | * |
||||||
2071 | * @param int $account |
||||||
2072 | * @param string $folder |
||||||
2073 | * @return int |
||||||
2074 | */ |
||||||
2075 | private function folder2hash($account,$folder) |
||||||
2076 | { |
||||||
2077 | if(!isset($this->folderHashes)) $this->readFolderHashes(); |
||||||
2078 | |||||||
2079 | if (($index = array_search($folder, (array)$this->folderHashes[$account])) === false) |
||||||
2080 | { |
||||||
2081 | // new hash |
||||||
2082 | $this->folderHashes[$account][] = $folder; |
||||||
2083 | $index = array_search($folder, (array)$this->folderHashes[$account]); |
||||||
2084 | |||||||
2085 | // maybe later storing in on class destruction only |
||||||
2086 | $this->storeFolderHashes(); |
||||||
2087 | } |
||||||
2088 | return $index; |
||||||
2089 | } |
||||||
2090 | |||||||
2091 | /** |
||||||
2092 | * Convert numeric hash to folder string |
||||||
2093 | * |
||||||
2094 | * @param int $account |
||||||
2095 | * @param int $index |
||||||
2096 | * @return string NULL if not used so far |
||||||
2097 | */ |
||||||
2098 | private function hash2folder($account,$index) |
||||||
2099 | { |
||||||
2100 | if(!isset($this->folderHashes)) $this->readFolderHashes(); |
||||||
2101 | |||||||
2102 | return isset($this->folderHashes[$account]) ? $this->folderHashes[$account][$index] : null; |
||||||
2103 | } |
||||||
2104 | |||||||
2105 | /** |
||||||
2106 | * Rename or create a folder in hash table |
||||||
2107 | * |
||||||
2108 | * @param int $account |
||||||
2109 | * @param int $index or null to create |
||||||
2110 | * @param string $new_name |
||||||
2111 | * @return int $index or new hash if $index is not found |
||||||
2112 | */ |
||||||
2113 | private function rename_folder_hash($account, $index, $new_name) |
||||||
2114 | { |
||||||
2115 | if ((string)$index === '' || !$this->hash2folder($account, $index)) |
||||||
2116 | { |
||||||
2117 | return $this->folder2hash($account, $new_name); |
||||||
2118 | } |
||||||
2119 | $this->folderHashes[$account][$index] = $new_name; |
||||||
2120 | $this->storeFolderHashes(); |
||||||
2121 | return $index; |
||||||
2122 | } |
||||||
2123 | |||||||
2124 | private $folderHashes; |
||||||
2125 | |||||||
2126 | /** |
||||||
2127 | * Statemaschine instance used to store folders |
||||||
2128 | * |
||||||
2129 | * @var activesync_statemaschine |
||||||
0 ignored issues
–
show
The type
activesync_statemaschine was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths ![]() |
|||||||
2130 | */ |
||||||
2131 | private $fh_state_maschine; |
||||||
2132 | |||||||
2133 | /** |
||||||
2134 | * state_type (and _key) used to store folder hashes |
||||||
2135 | */ |
||||||
2136 | const FOLDER_STATE_TYPE = 'folder_hashes'; |
||||||
2137 | |||||||
2138 | /** |
||||||
2139 | * Read hashfile from state dir |
||||||
2140 | */ |
||||||
2141 | private function readFolderHashes() |
||||||
2142 | { |
||||||
2143 | if (!isset($this->fh_state_maschine)) |
||||||
2144 | { |
||||||
2145 | $this->fh_state_maschine = new activesync_statemachine($this->backend); |
||||||
0 ignored issues
–
show
The type
activesync_statemachine was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths ![]() |
|||||||
2146 | } |
||||||
2147 | try { |
||||||
2148 | $this->folderHashes = $this->fh_state_maschine->getState(Request::GetDeviceID(), |
||||||
2149 | self::FOLDER_STATE_TYPE, self::FOLDER_STATE_TYPE, 0); |
||||||
2150 | } |
||||||
2151 | catch (Exception $e) { |
||||||
2152 | unset($e); |
||||||
2153 | if ((file_exists($file = $this->hashFile()) || file_exists($file = $this->hashFile(true))) && |
||||||
2154 | ($hashes = file_get_contents($file))) |
||||||
2155 | { |
||||||
2156 | $this->folderHashes = json_decode($hashes,true); |
||||||
2157 | // fallback in case hashes have been serialized instead of being json-encoded |
||||||
2158 | if (json_last_error()!=JSON_ERROR_NONE) |
||||||
2159 | { |
||||||
2160 | //error_log(__METHOD__.__LINE__." error decoding with json"); |
||||||
2161 | $this->folderHashes = unserialize($hashes); |
||||||
2162 | } |
||||||
2163 | // store folder-hashes to state |
||||||
2164 | $this->storeFolderHashes(); |
||||||
2165 | } |
||||||
2166 | else |
||||||
2167 | { |
||||||
2168 | $this->folderHashes = array(); |
||||||
2169 | } |
||||||
2170 | } |
||||||
2171 | } |
||||||
2172 | |||||||
2173 | /** |
||||||
2174 | * Store hashfile via state-maschine |
||||||
2175 | * |
||||||
2176 | * return int|boolean false on error |
||||||
2177 | */ |
||||||
2178 | private function storeFolderHashes() |
||||||
2179 | { |
||||||
2180 | if (!isset($this->fh_state_maschine)) |
||||||
2181 | { |
||||||
2182 | $this->fh_state_maschine = new activesync_statemachine($this->backend); |
||||||
2183 | } |
||||||
2184 | try { |
||||||
2185 | $this->fh_state_maschine->setState($this->folderHashes, Request::GetDeviceID(), |
||||||
2186 | self::FOLDER_STATE_TYPE, self::FOLDER_STATE_TYPE, 0); |
||||||
2187 | } |
||||||
2188 | catch (Exception $e) { |
||||||
2189 | _egw_log_exception($e); |
||||||
2190 | return false; |
||||||
2191 | } |
||||||
2192 | return true; |
||||||
2193 | } |
||||||
2194 | |||||||
2195 | /** |
||||||
2196 | * Get name of hashfile in state dir |
||||||
2197 | * |
||||||
2198 | * New z-push 2 directory is in activesync_statemachine::getDeviceDirectory. |
||||||
2199 | * On request this function also returns, but never creates (!), old z-push 1 directory. |
||||||
2200 | * |
||||||
2201 | * @param boolean $old =false true: return old / pre-15 hash-file |
||||||
2202 | * @throws Api\Exception\AssertionFailed |
||||||
2203 | */ |
||||||
2204 | private function hashFile($old=false) |
||||||
2205 | { |
||||||
2206 | if (!($dev_id=Request::GetDeviceID())) |
||||||
2207 | { |
||||||
2208 | throw new Api\Exception\AssertionFailed(__METHOD__."() no DeviceID set!"); |
||||||
2209 | } |
||||||
2210 | if ($old) |
||||||
2211 | { |
||||||
2212 | return STATE_DIR.$dev_id.'/'.$dev_id.'.hashes'; |
||||||
2213 | } |
||||||
2214 | $dir = activesync_statemachine::getDeviceDirectory($dev_id); |
||||||
2215 | |||||||
2216 | return $dir.'/'.$dev_id.'.hashes'; |
||||||
2217 | } |
||||||
2218 | } |
||||||
2219 |
Let?s assume that you have a directory layout like this:
and let?s assume the following content of
Bar.php
:If both files
OtherDir/Foo.php
andSomeDir/Foo.php
are loaded in the same runtime, you will see a PHP error such as the following:PHP Fatal error: Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php
However, as
OtherDir/Foo.php
does not necessarily have to be loaded and the error is only triggered if it is loaded beforeOtherDir/Bar.php
, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias: