commit | author | age
|
4e17e6
|
1 |
<?php |
T |
2 |
|
a95874
|
3 |
/** |
4e17e6
|
4 |
+-----------------------------------------------------------------------+ |
T |
5 |
| program/steps/mail/compose.inc | |
|
6 |
| | |
e019f2
|
7 |
| This file is part of the Roundcube Webmail client | |
ce3105
|
8 |
| Copyright (C) 2005-2016, The Roundcube Dev Team | |
7fe381
|
9 |
| | |
T |
10 |
| Licensed under the GNU General Public License version 3 or | |
|
11 |
| any later version with exceptions for skins & plugins. | |
|
12 |
| See the README file for a full license statement. | |
4e17e6
|
13 |
| | |
T |
14 |
| PURPOSE: | |
|
15 |
| Compose a new mail message with all headers and attachments | |
|
16 |
| | |
|
17 |
+-----------------------------------------------------------------------+ |
|
18 |
| Author: Thomas Bruederli <roundcube@gmail.com> | |
|
19 |
+-----------------------------------------------------------------------+ |
|
20 |
*/ |
|
21 |
|
8d4bcd
|
22 |
// define constants for message compose mode |
a0e3dc
|
23 |
define('RCUBE_COMPOSE_REPLY', 'reply'); |
AM |
24 |
define('RCUBE_COMPOSE_FORWARD', 'forward'); |
|
25 |
define('RCUBE_COMPOSE_DRAFT', 'draft'); |
|
26 |
define('RCUBE_COMPOSE_EDIT', 'edit'); |
8d4bcd
|
27 |
|
72ff6a
|
28 |
$MESSAGE_FORM = null; |
6b2b2e
|
29 |
$COMPOSE_ID = rcube_utils::get_input_value('_id', rcube_utils::INPUT_GET); |
72ff6a
|
30 |
$COMPOSE = null; |
f0f98f
|
31 |
|
72ff6a
|
32 |
if ($COMPOSE_ID && $_SESSION['compose_data_'.$COMPOSE_ID]) |
A |
33 |
$COMPOSE =& $_SESSION['compose_data_'.$COMPOSE_ID]; |
4591de
|
34 |
|
81f5dd
|
35 |
// give replicated session storage some time to synchronize |
T |
36 |
$retries = 0; |
72ff6a
|
37 |
while ($COMPOSE_ID && !is_array($COMPOSE) && $RCMAIL->db->is_replicated() && $retries++ < 5) { |
5e3034
|
38 |
usleep(500000); |
AM |
39 |
$RCMAIL->session->reload(); |
|
40 |
if ($_SESSION['compose_data_'.$COMPOSE_ID]) { |
|
41 |
$COMPOSE =& $_SESSION['compose_data_'.$COMPOSE_ID]; |
|
42 |
} |
81f5dd
|
43 |
} |
T |
44 |
|
86df15
|
45 |
// Nothing below is called during message composition, only at "new/forward/reply/draft" initialization or |
T |
46 |
// if a compose-ID is given (i.e. when the compose step is opened in a new window/tab). |
5e3034
|
47 |
if (!is_array($COMPOSE)) { |
AM |
48 |
// Infinite redirect prevention in case of broken session (#1487028) |
|
49 |
if ($COMPOSE_ID) { |
4b72a1
|
50 |
// if we know the message with specified ID was already sent |
AM |
51 |
// we can ignore the error and compose a new message (#1490009) |
|
52 |
if ($COMPOSE_ID != $_SESSION['last_compose_session']) { |
|
53 |
rcube::raise_error(array('code' => 450), false, true); |
|
54 |
} |
76791c
|
55 |
} |
5f314d
|
56 |
|
5e3034
|
57 |
$COMPOSE_ID = uniqid(mt_rand()); |
5d42a9
|
58 |
$params = rcube_utils::request2param(rcube_utils::INPUT_GET, 'task|action', true); |
AM |
59 |
|
5e3034
|
60 |
$_SESSION['compose_data_'.$COMPOSE_ID] = array( |
AM |
61 |
'id' => $COMPOSE_ID, |
5d42a9
|
62 |
'param' => $params, |
AM |
63 |
'mailbox' => $params['mbox'] ?: $RCMAIL->storage->get_folder(), |
5e3034
|
64 |
); |
AM |
65 |
$COMPOSE =& $_SESSION['compose_data_'.$COMPOSE_ID]; |
|
66 |
rcmail_process_compose_params($COMPOSE); |
|
67 |
|
|
68 |
// check if folder for saving sent messages exists and is subscribed (#1486802) |
|
69 |
if ($sent_folder = $COMPOSE['param']['sent_mbox']) { |
|
70 |
rcmail_check_sent_folder($sent_folder, true); |
|
71 |
} |
|
72 |
|
|
73 |
// redirect to a unique URL with all parameters stored in session |
|
74 |
$OUTPUT->redirect(array( |
|
75 |
'_action' => 'compose', |
|
76 |
'_id' => $COMPOSE['id'], |
|
77 |
'_search' => $_REQUEST['_search'], |
|
78 |
)); |
4315b0
|
79 |
} |
76791c
|
80 |
|
4e17e6
|
81 |
|
10a699
|
82 |
// add some labels to client |
3f9712
|
83 |
$OUTPUT->add_label('nosubject', 'nosenderwarning', 'norecipientwarning', 'nosubjectwarning', 'cancel', |
V |
84 |
'nobodywarning', 'notsentwarning', 'notuploadedwarning', 'savingmessage', 'sendingmessage', |
1abb97
|
85 |
'messagesaved', 'converting', 'editorwarning', 'searching', 'uploading', 'uploadingmany', |
6eb08d
|
86 |
'fileuploaderror', 'sendmessage', 'newresponse', 'responsename', 'responsetext', 'save', |
08da30
|
87 |
'savingresponse', 'restoresavedcomposedata', 'restoremessage', 'delete', 'restore', 'ignore', |
3167e5
|
88 |
'selectimportfile', 'messageissent', 'loadingdata', 'nopubkeyfor', 'nopubkeyforsender', |
2965a9
|
89 |
'encryptnoattachments','encryptedsendialog','searchpubkeyservers', 'importpubkeys', |
TB |
90 |
'encryptpubkeysfound', 'search', 'close', 'import', 'keyid', 'keylength', 'keyexpired', |
d56091
|
91 |
'keyrevoked', 'keyimportsuccess', 'keyservererror', 'attaching'); |
10a699
|
92 |
|
6b2b2e
|
93 |
$OUTPUT->set_pagetitle($RCMAIL->gettext('compose')); |
4591de
|
94 |
|
5e3034
|
95 |
$OUTPUT->set_env('compose_id', $COMPOSE['id']); |
AM |
96 |
$OUTPUT->set_env('session_id', session_id()); |
c321a9
|
97 |
$OUTPUT->set_env('mailbox', $RCMAIL->storage->get_folder()); |
651c7b
|
98 |
$OUTPUT->set_env('top_posting', intval($RCMAIL->config->get('reply_mode')) > 0); |
09225a
|
99 |
$OUTPUT->set_env('sig_below', $RCMAIL->config->get('sig_below')); |
62c861
|
100 |
$OUTPUT->set_env('recipients_separator', trim($RCMAIL->config->get('recipients_separator', ','))); |
44b47d
|
101 |
$OUTPUT->set_env('save_localstorage', (bool)$RCMAIL->config->get('compose_save_localstorage')); |
c5c8e7
|
102 |
$OUTPUT->set_env('is_sent', false); |
10a699
|
103 |
|
f5d2ee
|
104 |
$drafts_mbox = $RCMAIL->config->get('drafts_mbox'); |
AM |
105 |
$config_show_sig = $RCMAIL->config->get('show_sig', 1); |
|
106 |
|
5e3034
|
107 |
// add config parameters to client script |
f5d2ee
|
108 |
if (strlen($drafts_mbox)) { |
AM |
109 |
$OUTPUT->set_env('drafts_mailbox', $drafts_mbox); |
|
110 |
$OUTPUT->set_env('draft_autosave', $RCMAIL->config->get('draft_autosave')); |
5e3034
|
111 |
} |
AM |
112 |
|
7e263e
|
113 |
// default font for HTML editor |
6b2b2e
|
114 |
$font = rcmail::font_defs($RCMAIL->config->get('default_font')); |
7e263e
|
115 |
if ($font && !is_array($font)) { |
5e3034
|
116 |
$OUTPUT->set_env('default_font', $font); |
7e263e
|
117 |
} |
A |
118 |
|
965dea
|
119 |
// default font size for HTML editor |
f7b2bf
|
120 |
if ($font_size = $RCMAIL->config->get('default_font_size')) { |
5e3034
|
121 |
$OUTPUT->set_env('default_font_size', $font_size); |
f7b2bf
|
122 |
} |
965dea
|
123 |
|
8d4bcd
|
124 |
// get reference message and set compose mode |
72ff6a
|
125 |
if ($msg_uid = $COMPOSE['param']['draft_uid']) { |
5e3034
|
126 |
$compose_mode = RCUBE_COMPOSE_DRAFT; |
AM |
127 |
$OUTPUT->set_env('draft_id', $msg_uid); |
f5d2ee
|
128 |
$RCMAIL->storage->set_folder($drafts_mbox); |
4591de
|
129 |
} |
d9f109
|
130 |
else if ($msg_uid = $COMPOSE['param']['reply_uid']) { |
5e3034
|
131 |
$compose_mode = RCUBE_COMPOSE_REPLY; |
d9f109
|
132 |
} |
AM |
133 |
else if ($msg_uid = $COMPOSE['param']['forward_uid']) { |
5e3034
|
134 |
$compose_mode = RCUBE_COMPOSE_FORWARD; |
AM |
135 |
$COMPOSE['forward_uid'] = $msg_uid; |
|
136 |
$COMPOSE['as_attachment'] = !empty($COMPOSE['param']['attachment']); |
d9f109
|
137 |
} |
AM |
138 |
else if ($msg_uid = $COMPOSE['param']['uid']) { |
5e3034
|
139 |
$compose_mode = RCUBE_COMPOSE_EDIT; |
d9f109
|
140 |
} |
66a549
|
141 |
|
fa424e
|
142 |
if ($compose_mode) { |
AM |
143 |
$COMPOSE['mode'] = $compose_mode; |
|
144 |
$OUTPUT->set_env('compose_mode', $compose_mode); |
|
145 |
} |
50f56d
|
146 |
|
a9bb50
|
147 |
if ($compose_mode == RCUBE_COMPOSE_EDIT || $compose_mode == RCUBE_COMPOSE_DRAFT) { |
5e3034
|
148 |
// don't add signature in draft/edit mode, we'll also not remove the old-one |
AM |
149 |
// but only on page display, later we should be able to change identity/sig (#1489229) |
|
150 |
if ($config_show_sig == 1 || $config_show_sig == 2) { |
|
151 |
$OUTPUT->set_env('show_sig_later', true); |
|
152 |
} |
a9bb50
|
153 |
} |
AM |
154 |
else if ($config_show_sig == 1) |
5e3034
|
155 |
$OUTPUT->set_env('show_sig', true); |
a9bb50
|
156 |
else if ($config_show_sig == 2 && empty($compose_mode)) |
5e3034
|
157 |
$OUTPUT->set_env('show_sig', true); |
0207c4
|
158 |
else if ($config_show_sig == 3 && ($compose_mode == RCUBE_COMPOSE_REPLY || $compose_mode == RCUBE_COMPOSE_FORWARD)) |
5e3034
|
159 |
$OUTPUT->set_env('show_sig', true); |
8d4bcd
|
160 |
|
b62049
|
161 |
// set line length for body wrapping |
6b6f2e
|
162 |
$LINE_LENGTH = $RCMAIL->config->get('line_length', 72); |
b62049
|
163 |
|
5e3034
|
164 |
if (!empty($msg_uid) && empty($COMPOSE['as_attachment'])) { |
AM |
165 |
$mbox_name = $RCMAIL->storage->get_folder(); |
a02c77
|
166 |
|
5e3034
|
167 |
// set format before rcube_message construction |
AM |
168 |
// use the same format as for the message view |
|
169 |
if (isset($_SESSION['msg_formats'][$mbox_name.':'.$msg_uid])) { |
|
170 |
$RCMAIL->config->set('prefer_html', $_SESSION['msg_formats'][$mbox_name.':'.$msg_uid]); |
eeb85f
|
171 |
} |
5e3034
|
172 |
else { |
f5d2ee
|
173 |
$prefer_html = $RCMAIL->config->get('prefer_html') || $RCMAIL->config->get('htmleditor') |
AM |
174 |
|| $compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT; |
|
175 |
|
5e3034
|
176 |
$RCMAIL->config->set('prefer_html', $prefer_html); |
AM |
177 |
} |
bc404f
|
178 |
|
5e3034
|
179 |
$MESSAGE = new rcube_message($msg_uid); |
bc404f
|
180 |
|
5e3034
|
181 |
// make sure message is marked as read |
ce3105
|
182 |
if ($MESSAGE->headers && $MESSAGE->context === null && empty($MESSAGE->headers->flags['SEEN'])) { |
5e3034
|
183 |
$RCMAIL->storage->set_flag($msg_uid, 'SEEN'); |
AM |
184 |
} |
|
185 |
|
|
186 |
if (!empty($MESSAGE->headers->charset)) { |
|
187 |
$RCMAIL->storage->set_charset($MESSAGE->headers->charset); |
|
188 |
} |
|
189 |
|
|
190 |
if (!$MESSAGE->headers) { |
|
191 |
// error |
|
192 |
} |
73076d
|
193 |
else if ($compose_mode == RCUBE_COMPOSE_FORWARD || $compose_mode == RCUBE_COMPOSE_REPLY) { |
AM |
194 |
if ($compose_mode == RCUBE_COMPOSE_REPLY) { |
ce3105
|
195 |
$COMPOSE['reply_uid'] = $MESSAGE->context === null ? $msg_uid : null; |
73076d
|
196 |
|
AM |
197 |
if (!empty($COMPOSE['param']['all'])) { |
|
198 |
$MESSAGE->reply_all = $COMPOSE['param']['all']; |
|
199 |
} |
|
200 |
} |
|
201 |
else { |
|
202 |
$COMPOSE['forward_uid'] = $msg_uid; |
|
203 |
} |
|
204 |
|
5e3034
|
205 |
$COMPOSE['reply_msgid'] = $MESSAGE->headers->messageID; |
AM |
206 |
$COMPOSE['references'] = trim($MESSAGE->headers->references . " " . $MESSAGE->headers->messageID); |
eeb85f
|
207 |
|
10936f
|
208 |
// Save the sent message in the same folder of the message being replied to |
5e3034
|
209 |
if ($RCMAIL->config->get('reply_same_folder') && ($sent_folder = $COMPOSE['mailbox']) |
AM |
210 |
&& rcmail_check_sent_folder($sent_folder, false) |
10936f
|
211 |
) { |
5e3034
|
212 |
$COMPOSE['param']['sent_mbox'] = $sent_folder; |
10936f
|
213 |
} |
95fd38
|
214 |
} |
5e3034
|
215 |
else if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT) { |
AM |
216 |
if ($compose_mode == RCUBE_COMPOSE_DRAFT) { |
|
217 |
if ($draft_info = $MESSAGE->headers->get('x-draft-info')) { |
|
218 |
// get reply_uid/forward_uid to flag the original message when sending |
|
219 |
$info = rcmail_draftinfo_decode($draft_info); |
eeb85f
|
220 |
|
5e3034
|
221 |
if ($info['type'] == 'reply') |
AM |
222 |
$COMPOSE['reply_uid'] = $info['uid']; |
|
223 |
else if ($info['type'] == 'forward') |
|
224 |
$COMPOSE['forward_uid'] = $info['uid']; |
bc404f
|
225 |
|
5e3034
|
226 |
$COMPOSE['mailbox'] = $info['folder']; |
AM |
227 |
|
|
228 |
// Save the sent message in the same folder of the message being replied to |
|
229 |
if ($RCMAIL->config->get('reply_same_folder') && ($sent_folder = $info['folder']) |
|
230 |
&& rcmail_check_sent_folder($sent_folder, false) |
|
231 |
) { |
|
232 |
$COMPOSE['param']['sent_mbox'] = $sent_folder; |
|
233 |
} |
|
234 |
} |
|
235 |
|
|
236 |
$COMPOSE['param']['message-id'] = $MESSAGE->headers->get('message-id'); |
|
237 |
|
|
238 |
// use message UID as draft_id |
|
239 |
$OUTPUT->set_env('draft_id', $msg_uid); |
|
240 |
} |
|
241 |
|
|
242 |
if ($in_reply_to = $MESSAGE->headers->get('in-reply-to')) { |
|
243 |
$COMPOSE['reply_msgid'] = '<' . $in_reply_to . '>'; |
|
244 |
} |
|
245 |
|
|
246 |
$COMPOSE['references'] = $MESSAGE->headers->references; |
|
247 |
} |
252d27
|
248 |
} |
A |
249 |
else { |
5e3034
|
250 |
$MESSAGE = new stdClass(); |
eafd5b
|
251 |
|
5e3034
|
252 |
// apply mailto: URL parameters |
AM |
253 |
if (!empty($COMPOSE['param']['in-reply-to'])) { |
|
254 |
$COMPOSE['reply_msgid'] = '<' . $COMPOSE['param']['in-reply-to'] . '>'; |
|
255 |
} |
|
256 |
|
|
257 |
if (!empty($COMPOSE['param']['references'])) { |
|
258 |
$COMPOSE['references'] = $COMPOSE['param']['references']; |
|
259 |
} |
4315b0
|
260 |
} |
4e17e6
|
261 |
|
73076d
|
262 |
if (!empty($COMPOSE['reply_msgid'])) { |
AM |
263 |
$OUTPUT->set_env('reply_msgid', $COMPOSE['reply_msgid']); |
|
264 |
} |
90dc9b
|
265 |
|
da142b
|
266 |
$MESSAGE->compose = array(); |
A |
267 |
|
|
268 |
// get user's identities |
0247b8
|
269 |
$MESSAGE->identities = $RCMAIL->user->list_identities(null, true); |
da142b
|
270 |
|
A |
271 |
// Set From field value |
|
272 |
if (!empty($_POST['_from'])) { |
5e3034
|
273 |
$MESSAGE->compose['from'] = rcube_utils::get_input_value('_from', rcube_utils::INPUT_POST); |
da142b
|
274 |
} |
72ff6a
|
275 |
else if (!empty($COMPOSE['param']['from'])) { |
5e3034
|
276 |
$MESSAGE->compose['from'] = $COMPOSE['param']['from']; |
da142b
|
277 |
} |
A |
278 |
else if (count($MESSAGE->identities)) { |
5e3034
|
279 |
$ident = rcmail_identity_select($MESSAGE, $MESSAGE->identities, $compose_mode); |
da142b
|
280 |
|
1414e3
|
281 |
$MESSAGE->compose['from'] = $ident['identity_id']; |
AM |
282 |
$MESSAGE->compose['ident'] = $ident; |
da142b
|
283 |
} |
A |
284 |
|
087c7d
|
285 |
// process $MESSAGE body/attachments, set $MESSAGE_BODY/$HTML_MODE vars and some session data |
A |
286 |
$MESSAGE_BODY = rcmail_prepare_message_body(); |
4e17e6
|
287 |
|
87cf0a
|
288 |
$OUTPUT->include_script('publickey.js'); |
087c7d
|
289 |
|
5e3034
|
290 |
// register UI objects |
AM |
291 |
$OUTPUT->add_handlers(array( |
|
292 |
'composeheaders' => 'rcmail_compose_headers', |
|
293 |
'composesubject' => 'rcmail_compose_subject', |
|
294 |
'composebody' => 'rcmail_compose_body', |
|
295 |
'composeattachmentlist' => 'rcmail_compose_attachment_list', |
|
296 |
'composeattachmentform' => 'rcmail_compose_attachment_form', |
|
297 |
'composeattachment' => 'rcmail_compose_attachment_field', |
|
298 |
'filedroparea' => 'compose_file_drop_area', |
|
299 |
'priorityselector' => 'rcmail_priority_selector', |
|
300 |
'editorselector' => 'rcmail_editor_selector', |
f65021
|
301 |
'receiptcheckbox' => 'rcmail_mdn_checkbox', // deprecated |
AM |
302 |
'mdncheckbox' => 'rcmail_mdn_checkbox', |
5e3034
|
303 |
'dsncheckbox' => 'rcmail_dsn_checkbox', |
AM |
304 |
'storetarget' => 'rcmail_store_target_selection', |
|
305 |
'addressbooks' => 'rcmail_addressbook_list', |
|
306 |
'addresslist' => 'rcmail_contacts_list', |
|
307 |
'responseslist' => 'rcmail_compose_responses_list', |
|
308 |
)); |
|
309 |
|
|
310 |
$OUTPUT->send('compose'); |
|
311 |
|
|
312 |
|
087c7d
|
313 |
/****** compose mode functions ********/ |
0247b8
|
314 |
|
eafd5b
|
315 |
// process compose request parameters |
AM |
316 |
function rcmail_process_compose_params(&$COMPOSE) |
|
317 |
{ |
5e3034
|
318 |
if ($COMPOSE['param']['to']) { |
AM |
319 |
$mailto = explode('?', $COMPOSE['param']['to'], 2); |
eafd5b
|
320 |
|
5e3034
|
321 |
// #1486037: remove "mailto:" prefix |
AM |
322 |
$COMPOSE['param']['to'] = preg_replace('/^mailto:/i', '', $mailto[0]); |
1a7e66
|
323 |
// #1490346: decode the recipient address |
8297ea
|
324 |
// #1490510: use raw encoding for correct "+" character handling as specified in RFC6068 |
AM |
325 |
$COMPOSE['param']['to'] = rawurldecode($COMPOSE['param']['to']); |
eafd5b
|
326 |
|
5e3034
|
327 |
// Supported case-insensitive tokens in mailto URL |
AM |
328 |
$url_tokens = array('to', 'cc', 'bcc', 'reply-to', 'in-reply-to', 'references', 'subject', 'body'); |
eafd5b
|
329 |
|
5e3034
|
330 |
if (!empty($mailto[1])) { |
AM |
331 |
parse_str($mailto[1], $query); |
|
332 |
foreach ($query as $f => $val) { |
|
333 |
if (($key = array_search(strtolower($f), $url_tokens)) !== false) { |
|
334 |
$f = $url_tokens[$key]; |
|
335 |
} |
eafd5b
|
336 |
|
5e3034
|
337 |
// merge mailto: addresses with addresses from 'to' parameter |
AM |
338 |
if ($f == 'to' && !empty($COMPOSE['param']['to'])) { |
|
339 |
$to_addresses = rcube_mime::decode_address_list($COMPOSE['param']['to'], null, true, null, true); |
|
340 |
$add_addresses = rcube_mime::decode_address_list($val, null, true); |
|
341 |
|
|
342 |
foreach ($add_addresses as $addr) { |
|
343 |
if (!in_array($addr['mailto'], $to_addresses)) { |
|
344 |
$to_addresses[] = $addr['mailto']; |
|
345 |
$COMPOSE['param']['to'] = (!empty($to_addresses) ? ', ' : '') . $addr['string']; |
|
346 |
} |
|
347 |
} |
|
348 |
} |
|
349 |
else { |
|
350 |
$COMPOSE['param'][$f] = $val; |
|
351 |
} |
eafd5b
|
352 |
} |
AM |
353 |
} |
|
354 |
} |
|
355 |
|
aafbe8
|
356 |
// resolve _forward_uid=* to an absolute list of messages from a search result |
TB |
357 |
if ($COMPOSE['param']['forward_uid'] == '*' && is_object($_SESSION['search'][1])) { |
|
358 |
$COMPOSE['param']['forward_uid'] = $_SESSION['search'][1]->get(); |
|
359 |
} |
|
360 |
|
5e3034
|
361 |
// clean HTML message body which can be submitted by URL |
AM |
362 |
if (!empty($COMPOSE['param']['body'])) { |
b0a8e3
|
363 |
if ($COMPOSE['param']['html'] = strpos($COMPOSE['param']['body'], '<') !== false) { |
AM |
364 |
$wash_params = array('safe' => false, 'inline_html' => true); |
|
365 |
$COMPOSE['param']['body'] = rcmail_wash_html($COMPOSE['param']['body'], $wash_params, array()); |
|
366 |
$COMPOSE['param']['body'] = preg_replace('/<!--[^>\n]+>/', '', $COMPOSE['param']['body']); |
|
367 |
$COMPOSE['param']['body'] = preg_replace('/<\/?body>/', '', $COMPOSE['param']['body']); |
|
368 |
} |
5e3034
|
369 |
} |
2af374
|
370 |
|
5e3034
|
371 |
$RCMAIL = rcmail::get_instance(); |
eafd5b
|
372 |
|
5e3034
|
373 |
// select folder where to save the sent message |
AM |
374 |
$COMPOSE['param']['sent_mbox'] = $RCMAIL->config->get('sent_mbox'); |
eafd5b
|
375 |
|
5e3034
|
376 |
// pipe compose parameters thru plugins |
AM |
377 |
$plugin = $RCMAIL->plugins->exec_hook('message_compose', $COMPOSE); |
|
378 |
$COMPOSE['param'] = array_merge($COMPOSE['param'], $plugin['param']); |
37b9e0
|
379 |
|
AM |
380 |
// add attachments listed by message_compose hook |
|
381 |
if (is_array($plugin['attachments'])) { |
|
382 |
foreach ($plugin['attachments'] as $attach) { |
|
383 |
// we have structured data |
|
384 |
if (is_array($attach)) { |
8ed382
|
385 |
$attachment = $attach + array('group' => $COMPOSE_ID); |
37b9e0
|
386 |
} |
AM |
387 |
// only a file path is given |
|
388 |
else { |
|
389 |
$filename = basename($attach); |
|
390 |
$attachment = array( |
|
391 |
'group' => $COMPOSE_ID, |
|
392 |
'name' => $filename, |
|
393 |
'mimetype' => rcube_mime::file_content_type($attach, $filename), |
bb1ed2
|
394 |
'size' => filesize($attach), |
37b9e0
|
395 |
'path' => $attach, |
AM |
396 |
); |
|
397 |
} |
|
398 |
|
|
399 |
// save attachment if valid |
|
400 |
if (($attachment['data'] && $attachment['name']) || ($attachment['path'] && file_exists($attachment['path']))) { |
|
401 |
$attachment = rcmail::get_instance()->plugins->exec_hook('attachment_save', $attachment); |
|
402 |
} |
|
403 |
|
|
404 |
if ($attachment['status'] && !$attachment['abort']) { |
|
405 |
unset($attachment['data'], $attachment['status'], $attachment['abort']); |
|
406 |
$COMPOSE['attachments'][$attachment['id']] = $attachment; |
|
407 |
} |
|
408 |
} |
|
409 |
} |
eafd5b
|
410 |
} |
AM |
411 |
|
4e17e6
|
412 |
function rcmail_compose_headers($attrib) |
4315b0
|
413 |
{ |
5e3034
|
414 |
global $RCMAIL, $MESSAGE; |
4e17e6
|
415 |
|
5e3034
|
416 |
list($form_start,) = get_form_tags($attrib); |
8958d0
|
417 |
|
5e3034
|
418 |
$out = ''; |
AM |
419 |
$part = strtolower($attrib['part']); |
8958d0
|
420 |
|
5e3034
|
421 |
switch ($part) { |
4e17e6
|
422 |
case 'from': |
5e3034
|
423 |
return $form_start . rcmail_compose_header_from($attrib); |
4e17e6
|
424 |
|
T |
425 |
case 'to': |
|
426 |
case 'cc': |
|
427 |
case 'bcc': |
5e3034
|
428 |
$fname = '_' . $part; |
AM |
429 |
$header = $param = $part; |
8958d0
|
430 |
|
5e3034
|
431 |
$allow_attrib = array('id', 'class', 'style', 'cols', 'rows', 'tabindex'); |
AM |
432 |
$field_type = 'html_textarea'; |
|
433 |
break; |
4e17e6
|
434 |
|
T |
435 |
case 'replyto': |
|
436 |
case 'reply-to': |
5e3034
|
437 |
$fname = '_replyto'; |
AM |
438 |
$param = 'replyto'; |
|
439 |
$header = 'reply-to'; |
e25a35
|
440 |
|
3ee5a7
|
441 |
case 'followupto': |
A |
442 |
case 'followup-to': |
5e3034
|
443 |
if (!$fname) { |
AM |
444 |
$fname = '_followupto'; |
|
445 |
$param = 'followupto'; |
|
446 |
$header = 'mail-followup-to'; |
|
447 |
} |
e25a35
|
448 |
|
5e3034
|
449 |
$allow_attrib = array('id', 'class', 'style', 'size', 'tabindex'); |
AM |
450 |
$field_type = 'html_inputfield'; |
|
451 |
break; |
|
452 |
} |
e99991
|
453 |
|
5e3034
|
454 |
if ($fname && $field_type) { |
AM |
455 |
// pass the following attributes to the form class |
|
456 |
$field_attrib = array('name' => $fname, 'spellcheck' => 'false'); |
|
457 |
foreach ($attrib as $attr => $value) { |
|
458 |
if (in_array($attr, $allow_attrib)) { |
|
459 |
$field_attrib[$attr] = $value; |
|
460 |
} |
|
461 |
} |
4e17e6
|
462 |
|
5e3034
|
463 |
// create teaxtarea object |
AM |
464 |
$input = new $field_type($field_attrib); |
1414e3
|
465 |
$out = $input->show(rcmail_compose_header_value($param)); |
5e3034
|
466 |
} |
0213f8
|
467 |
|
5e3034
|
468 |
if ($form_start) { |
AM |
469 |
$out = $form_start . $out; |
|
470 |
} |
1966c5
|
471 |
|
5e3034
|
472 |
// configure autocompletion |
AM |
473 |
$RCMAIL->autocomplete_init(); |
0213f8
|
474 |
|
5e3034
|
475 |
return $out; |
4315b0
|
476 |
} |
4e17e6
|
477 |
|
T |
478 |
|
1cded8
|
479 |
function rcmail_compose_header_from($attrib) |
4315b0
|
480 |
{ |
1414e3
|
481 |
global $MESSAGE, $OUTPUT, $RCMAIL, $COMPOSE; |
da142b
|
482 |
|
5e3034
|
483 |
// pass the following attributes to the form class |
AM |
484 |
$field_attrib = array('name' => '_from'); |
|
485 |
foreach ($attrib as $attr => $value) { |
|
486 |
if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex'))) { |
|
487 |
$field_attrib[$attr] = $value; |
a0109c
|
488 |
} |
4315b0
|
489 |
} |
e25a35
|
490 |
|
5e3034
|
491 |
if (count($MESSAGE->identities)) { |
AM |
492 |
$a_signatures = array(); |
|
493 |
$identities = array(); |
09225a
|
494 |
$top_posting = intval($RCMAIL->config->get('reply_mode')) > 0 |
AM |
495 |
&& !$RCMAIL->config->get('sig_below') |
1414e3
|
496 |
&& ($COMPOSE['mode'] == RCUBE_COMPOSE_REPLY || $COMPOSE['mode'] == RCUBE_COMPOSE_FORWARD); |
399a2d
|
497 |
|
AM |
498 |
$separator = $top_posting ? '---' : '-- '; |
|
499 |
$add_separator = (bool) $RCMAIL->config->get('sig_separator'); |
4e17e6
|
500 |
|
5e3034
|
501 |
$field_attrib['onchange'] = rcmail_output::JS_OBJECT_NAME.".change_identity(this)"; |
AM |
502 |
$select_from = new html_select($field_attrib); |
4e17e6
|
503 |
|
5e3034
|
504 |
// create SELECT element |
AM |
505 |
foreach ($MESSAGE->identities as $sql_arr) { |
|
506 |
$identity_id = $sql_arr['identity_id']; |
|
507 |
$select_from->add(format_email_recipient($sql_arr['email'], $sql_arr['name']), $identity_id); |
|
508 |
|
|
509 |
// add signature to array |
|
510 |
if (!empty($sql_arr['signature']) && empty($COMPOSE['param']['nosig'])) { |
|
511 |
$text = $html = $sql_arr['signature']; |
|
512 |
|
|
513 |
if ($sql_arr['html_signature']) { |
c4daf3
|
514 |
$text = $RCMAIL->html2text($html, array('links' => false)); |
399a2d
|
515 |
$text = trim($text, "\r\n"); |
5e3034
|
516 |
} |
AM |
517 |
else { |
aa38c5
|
518 |
$t2h = new rcube_text2html($text, false); |
AM |
519 |
$html = $t2h->get_html(); |
5e3034
|
520 |
} |
AM |
521 |
|
399a2d
|
522 |
if ($add_separator && !preg_match('/^--[ -]\r?\n/m', $text)) { |
AM |
523 |
$text = $separator . "\n" . ltrim($text, "\r\n"); |
5e3034
|
524 |
$html = $separator . "<br>" . $html; |
AM |
525 |
} |
|
526 |
|
|
527 |
$a_signatures[$identity_id]['text'] = $text; |
|
528 |
$a_signatures[$identity_id]['html'] = $html; |
|
529 |
} |
|
530 |
|
|
531 |
// add bcc and reply-to |
|
532 |
if (!empty($sql_arr['reply-to'])) { |
|
533 |
$identities[$identity_id]['replyto'] = $sql_arr['reply-to']; |
|
534 |
} |
|
535 |
if (!empty($sql_arr['bcc'])) { |
|
536 |
$identities[$identity_id]['bcc'] = $sql_arr['bcc']; |
|
537 |
} |
40d152
|
538 |
|
TB |
539 |
$identities[$identity_id]['email'] = $sql_arr['email']; |
5e3034
|
540 |
} |
AM |
541 |
|
56a4e1
|
542 |
$out = $select_from->show($MESSAGE->compose['from']); |
5e3034
|
543 |
|
AM |
544 |
// add signatures to client |
|
545 |
$OUTPUT->set_env('signatures', $a_signatures); |
|
546 |
$OUTPUT->set_env('identities', $identities); |
|
547 |
} |
|
548 |
// no identities, display text input field |
|
549 |
else { |
|
550 |
$field_attrib['class'] = 'from_address'; |
|
551 |
$input_from = new html_inputfield($field_attrib); |
56a4e1
|
552 |
$out = $input_from->show($MESSAGE->compose['from']); |
5e3034
|
553 |
} |
AM |
554 |
|
|
555 |
return $out; |
4315b0
|
556 |
} |
4e17e6
|
557 |
|
1414e3
|
558 |
function rcmail_compose_header_value($header) |
AM |
559 |
{ |
|
560 |
global $COMPOSE, $MESSAGE; |
|
561 |
|
|
562 |
$RCMAIL = rcube::get_instance(); |
|
563 |
$fvalue = ''; |
|
564 |
$decode_header = true; |
|
565 |
$charset = $MESSAGE->headers->charset; |
|
566 |
$separator = trim($RCMAIL->config->get('recipients_separator', ',')) . ' '; |
|
567 |
|
|
568 |
// we have a set of recipients stored is session |
|
569 |
if ($header == 'to' && ($mailto_id = $COMPOSE['param']['mailto']) |
|
570 |
&& $_SESSION['mailto'][$mailto_id] |
|
571 |
) { |
|
572 |
$fvalue = urldecode($_SESSION['mailto'][$mailto_id]); |
|
573 |
$decode_header = false; |
|
574 |
$charset = $RCMAIL->output->charset; |
|
575 |
|
|
576 |
// make session to not grow up too much |
|
577 |
unset($_SESSION['mailto'][$mailto_id]); |
|
578 |
$COMPOSE['param']['to'] = $fvalue; |
|
579 |
} |
|
580 |
else if (!empty($_POST['_' . $header])) { |
|
581 |
$fvalue = rcube_utils::get_input_value('_' . $header, rcube_utils::INPUT_POST, true); |
|
582 |
$charset = $RCMAIL->output->charset; |
|
583 |
} |
|
584 |
else if (!empty($COMPOSE['param'][$header])) { |
|
585 |
$fvalue = $COMPOSE['param'][$header]; |
|
586 |
$charset = $RCMAIL->output->charset; |
|
587 |
} |
|
588 |
else if ($COMPOSE['mode'] == RCUBE_COMPOSE_REPLY) { |
|
589 |
// get recipent address(es) out of the message headers |
|
590 |
if ($header == 'to') { |
|
591 |
$mailfollowup = $MESSAGE->headers->others['mail-followup-to']; |
|
592 |
$mailreplyto = $MESSAGE->headers->others['mail-reply-to']; |
|
593 |
|
|
594 |
// Reply to mailing list... |
|
595 |
if ($MESSAGE->reply_all == 'list' && $mailfollowup) { |
|
596 |
$fvalue = $mailfollowup; |
|
597 |
} |
|
598 |
else if ($MESSAGE->reply_all == 'list' |
|
599 |
&& preg_match('/<mailto:([^>]+)>/i', $MESSAGE->headers->others['list-post'], $m) |
|
600 |
) { |
|
601 |
$fvalue = $m[1]; |
|
602 |
} |
|
603 |
// Reply to... |
|
604 |
else if ($MESSAGE->reply_all && $mailfollowup) { |
|
605 |
$fvalue = $mailfollowup; |
|
606 |
} |
|
607 |
else if ($mailreplyto) { |
|
608 |
$fvalue = $mailreplyto; |
|
609 |
} |
|
610 |
else if (!empty($MESSAGE->headers->replyto)) { |
|
611 |
$fvalue = $MESSAGE->headers->replyto; |
|
612 |
$replyto = true; |
|
613 |
} |
|
614 |
else if (!empty($MESSAGE->headers->from)) { |
|
615 |
$fvalue = $MESSAGE->headers->from; |
|
616 |
} |
|
617 |
|
|
618 |
// Reply to message sent by yourself (#1487074, #1489230, #1490439) |
|
619 |
// Reply-To address need to be unset (#1490233) |
|
620 |
if (!empty($MESSAGE->compose['ident']) && empty($replyto)) { |
|
621 |
foreach (array($fvalue, $MESSAGE->headers->from) as $sender) { |
|
622 |
$senders = rcube_mime::decode_address_list($sender, null, false, $charset, true); |
|
623 |
|
|
624 |
if (in_array($MESSAGE->compose['ident']['email_ascii'], $senders)) { |
|
625 |
$fvalue = $MESSAGE->headers->to; |
|
626 |
break; |
|
627 |
} |
|
628 |
} |
|
629 |
} |
|
630 |
} |
|
631 |
// add recipient of original message if reply to all |
|
632 |
else if ($header == 'cc' && !empty($MESSAGE->reply_all) && $MESSAGE->reply_all != 'list') { |
|
633 |
if ($v = $MESSAGE->headers->to) { |
|
634 |
$fvalue .= $v; |
|
635 |
} |
|
636 |
if ($v = $MESSAGE->headers->cc) { |
|
637 |
$fvalue .= (!empty($fvalue) ? $separator : '') . $v; |
|
638 |
} |
|
639 |
// Use Sender header (#1489011) |
192467
|
640 |
if ($v = $MESSAGE->headers->get('Sender', false)) { |
AM |
641 |
// Skip common mailing lists addresses: *-bounces@ and *-request@ (#1490452) |
|
642 |
if (empty($MESSAGE->headers->others['list-post']) || !preg_match('/-(bounces|request)@/', $v)) { |
|
643 |
$fvalue .= (!empty($fvalue) ? $separator : '') . $v; |
|
644 |
} |
1414e3
|
645 |
} |
AM |
646 |
|
|
647 |
// When To: and Reply-To: are the same we add From: address to the list (#1489037) |
|
648 |
if ($v = $MESSAGE->headers->from) { |
|
649 |
$from = rcube_mime::decode_address_list($v, null, false, $charset, true); |
|
650 |
$to = rcube_mime::decode_address_list($MESSAGE->headers->to, null, false, $charset, true); |
|
651 |
$replyto = rcube_mime::decode_address_list($MESSAGE->headers->replyto, null, false, $charset, true); |
|
652 |
|
|
653 |
if (count($replyto) && !count(array_diff($to, $replyto)) && count(array_diff($from, $to))) { |
|
654 |
$fvalue .= (!empty($fvalue) ? $separator : '') . $v; |
|
655 |
} |
|
656 |
} |
|
657 |
} |
|
658 |
} |
|
659 |
else if (in_array($COMPOSE['mode'], array(RCUBE_COMPOSE_DRAFT, RCUBE_COMPOSE_EDIT))) { |
|
660 |
// get drafted headers |
|
661 |
if ($header == 'to' && !empty($MESSAGE->headers->to)) { |
|
662 |
$fvalue = $MESSAGE->get_header('to', true); |
|
663 |
} |
|
664 |
else if ($header == 'cc' && !empty($MESSAGE->headers->cc)) { |
|
665 |
$fvalue = $MESSAGE->get_header('cc', true); |
|
666 |
} |
|
667 |
else if ($header == 'bcc' && !empty($MESSAGE->headers->bcc)) { |
|
668 |
$fvalue = $MESSAGE->get_header('bcc', true); |
|
669 |
} |
|
670 |
else if ($header == 'replyto' && !empty($MESSAGE->headers->others['mail-reply-to'])) { |
|
671 |
$fvalue = $MESSAGE->get_header('mail-reply-to'); |
|
672 |
} |
|
673 |
else if ($header == 'replyto' && !empty($MESSAGE->headers->replyto)) { |
|
674 |
$fvalue = $MESSAGE->get_header('reply-to'); |
|
675 |
} |
|
676 |
else if ($header == 'followupto' && !empty($MESSAGE->headers->others['mail-followup-to'])) { |
|
677 |
$fvalue = $MESSAGE->get_header('mail-followup-to'); |
|
678 |
} |
|
679 |
} |
|
680 |
|
|
681 |
// split recipients and put them back together in a unique way |
|
682 |
if (!empty($fvalue) && in_array($header, array('to', 'cc', 'bcc'))) { |
|
683 |
$from_email = @mb_strtolower($MESSAGE->compose['ident']['email']); |
|
684 |
$to_addresses = rcube_mime::decode_address_list($fvalue, null, $decode_header, $charset); |
|
685 |
$fvalue = array(); |
|
686 |
|
|
687 |
foreach ($to_addresses as $addr_part) { |
|
688 |
if (empty($addr_part['mailto'])) { |
|
689 |
continue; |
|
690 |
} |
|
691 |
|
|
692 |
// According to RFC5321 local part of email address is case-sensitive |
|
693 |
// however, here it is better to compare addresses in case-insensitive manner |
|
694 |
$mailto = format_email(rcube_utils::idn_to_utf8($addr_part['mailto'])); |
|
695 |
$mailto_lc = mb_strtolower($addr_part['mailto']); |
|
696 |
|
|
697 |
if (($header == 'to' || $COMPOSE['mode'] != RCUBE_COMPOSE_REPLY || $mailto_lc != $from_email) |
|
698 |
&& !in_array($mailto_lc, (array) $MESSAGE->recipients) |
|
699 |
) { |
|
700 |
if ($addr_part['name'] && $mailto != $addr_part['name']) { |
|
701 |
$mailto = format_email_recipient($mailto, $addr_part['name']); |
|
702 |
} |
|
703 |
|
|
704 |
$fvalue[] = $mailto; |
|
705 |
$MESSAGE->recipients[] = $mailto_lc; |
|
706 |
} |
|
707 |
} |
|
708 |
|
|
709 |
$fvalue = implode($separator, $fvalue); |
|
710 |
} |
|
711 |
|
|
712 |
return $fvalue; |
|
713 |
} |
4e17e6
|
714 |
|
868deb
|
715 |
function rcmail_compose_editor_mode() |
A |
716 |
{ |
8bed5e
|
717 |
global $RCMAIL, $COMPOSE; |
5e3034
|
718 |
static $useHtml; |
868deb
|
719 |
|
5e3034
|
720 |
if ($useHtml !== null) { |
AM |
721 |
return $useHtml; |
|
722 |
} |
|
723 |
|
1414e3
|
724 |
$html_editor = intval($RCMAIL->config->get('htmleditor')); |
AM |
725 |
$compose_mode = $COMPOSE['mode']; |
5e3034
|
726 |
|
b0a8e3
|
727 |
if (is_bool($COMPOSE['param']['html'])) { |
AM |
728 |
$useHtml = $COMPOSE['param']['html']; |
|
729 |
} |
|
730 |
else if (isset($_POST['_is_html'])) { |
5e3034
|
731 |
$useHtml = !empty($_POST['_is_html']); |
AM |
732 |
} |
|
733 |
else if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT) { |
|
734 |
$useHtml = rcmail_message_is_html(); |
|
735 |
} |
|
736 |
else if ($compose_mode == RCUBE_COMPOSE_REPLY) { |
6ca1e6
|
737 |
$useHtml = $html_editor == 1 || ($html_editor >= 2 && rcmail_message_is_html()); |
5e3034
|
738 |
} |
AM |
739 |
else if ($compose_mode == RCUBE_COMPOSE_FORWARD) { |
6ca1e6
|
740 |
$useHtml = $html_editor == 1 || $html_editor == 4 |
AM |
741 |
|| ($html_editor == 3 && rcmail_message_is_html()); |
5e3034
|
742 |
} |
AM |
743 |
else { |
6ca1e6
|
744 |
$useHtml = $html_editor == 1 || $html_editor == 4; |
5e3034
|
745 |
} |
AM |
746 |
|
868deb
|
747 |
return $useHtml; |
A |
748 |
} |
|
749 |
|
abf467
|
750 |
function rcmail_message_is_html() |
AM |
751 |
{ |
a02c77
|
752 |
global $RCMAIL, $MESSAGE; |
5e3034
|
753 |
|
a02c77
|
754 |
return $RCMAIL->config->get('prefer_html') && ($MESSAGE instanceof rcube_message) && $MESSAGE->has_html_part(true); |
abf467
|
755 |
} |
868deb
|
756 |
|
087c7d
|
757 |
function rcmail_prepare_message_body() |
4315b0
|
758 |
{ |
1414e3
|
759 |
global $RCMAIL, $MESSAGE, $COMPOSE, $HTML_MODE; |
a0109c
|
760 |
|
5e3034
|
761 |
// use posted message body |
AM |
762 |
if (!empty($_POST['_message'])) { |
|
763 |
$body = rcube_utils::get_input_value('_message', rcube_utils::INPUT_POST, true); |
|
764 |
$isHtml = (bool) rcube_utils::get_input_value('_is_html', rcube_utils::INPUT_POST); |
b62049
|
765 |
} |
5e3034
|
766 |
else if ($COMPOSE['param']['body']) { |
AM |
767 |
$body = $COMPOSE['param']['body']; |
|
768 |
$isHtml = (bool) $COMPOSE['param']['html']; |
|
769 |
} |
|
770 |
// forward as attachment |
1414e3
|
771 |
else if ($COMPOSE['mode'] == RCUBE_COMPOSE_FORWARD && $COMPOSE['as_attachment']) { |
5e3034
|
772 |
$isHtml = rcmail_compose_editor_mode(); |
AM |
773 |
$body = ''; |
|
774 |
|
|
775 |
rcmail_write_forward_attachments(); |
|
776 |
} |
|
777 |
// reply/edit/draft/forward |
1414e3
|
778 |
else if ($COMPOSE['mode'] && ($COMPOSE['mode'] != RCUBE_COMPOSE_REPLY || intval($RCMAIL->config->get('reply_mode')) != -1)) { |
5e3034
|
779 |
$isHtml = rcmail_compose_editor_mode(); |
AM |
780 |
$messages = array(); |
|
781 |
|
|
782 |
if (!empty($MESSAGE->parts)) { |
|
783 |
// collect IDs of message/rfc822 parts |
ce3105
|
784 |
foreach ($MESSAGE->mime_parts() as $part) { |
be3460
|
785 |
if ($part->mimetype == 'message/rfc822') { |
AM |
786 |
$messages[] = $part->mime_id; |
5e3034
|
787 |
} |
AM |
788 |
} |
|
789 |
|
|
790 |
foreach ($MESSAGE->parts as $part) { |
3167e5
|
791 |
if ($part->realtype == 'multipart/encrypted') { |
TB |
792 |
// find the encrypted message payload part |
f7f75f
|
793 |
if ($pgp_mime_part = $MESSAGE->get_multipart_encrypted_part()) { |
TB |
794 |
$RCMAIL->output->set_env('pgp_mime_message', array( |
|
795 |
'_mbox' => $RCMAIL->storage->get_folder(), |
|
796 |
'_uid' => $MESSAGE->uid, |
|
797 |
'_part' => $pgp_mime_part->mime_id, |
|
798 |
)); |
3167e5
|
799 |
} |
TB |
800 |
continue; |
|
801 |
} |
|
802 |
|
5e3034
|
803 |
// skip no-content and attachment parts (#1488557) |
AM |
804 |
if ($part->type != 'content' || !$part->size || $MESSAGE->is_attachment($part)) { |
|
805 |
continue; |
|
806 |
} |
|
807 |
|
be3460
|
808 |
// skip all content parts inside the message/rfc822 part |
5e3034
|
809 |
foreach ($messages as $mimeid) { |
AM |
810 |
if (strpos($part->mime_id, $mimeid . '.') === 0) { |
|
811 |
continue 2; |
|
812 |
} |
|
813 |
} |
|
814 |
|
|
815 |
if ($part_body = rcmail_compose_part_body($part, $isHtml)) { |
|
816 |
$body .= ($body ? ($isHtml ? '<br/>' : "\n") : '') . $part_body; |
|
817 |
} |
|
818 |
} |
|
819 |
} |
|
820 |
else { |
|
821 |
$body = rcmail_compose_part_body($MESSAGE, $isHtml); |
|
822 |
} |
|
823 |
|
|
824 |
// compose reply-body |
f189d7
|
825 |
if ($COMPOSE['mode'] == RCUBE_COMPOSE_REPLY) { |
5e3034
|
826 |
$body = rcmail_create_reply_body($body, $isHtml); |
3167e5
|
827 |
|
TB |
828 |
if ($MESSAGE->pgp_mime) { |
|
829 |
$RCMAIL->output->set_env('compose_reply_header', rcmail_get_reply_header($MESSAGE)); |
|
830 |
} |
|
831 |
} |
5e3034
|
832 |
// forward message body inline |
f189d7
|
833 |
else if ($COMPOSE['mode'] == RCUBE_COMPOSE_FORWARD) { |
5e3034
|
834 |
$body = rcmail_create_forward_body($body, $isHtml); |
3167e5
|
835 |
} |
5e3034
|
836 |
// load draft message body |
f189d7
|
837 |
else if ($COMPOSE['mode'] == RCUBE_COMPOSE_DRAFT || $COMPOSE['mode'] == RCUBE_COMPOSE_EDIT) { |
5e3034
|
838 |
$body = rcmail_create_draft_body($body, $isHtml); |
3167e5
|
839 |
} |
5e3034
|
840 |
} |
AM |
841 |
else { // new message |
|
842 |
$isHtml = rcmail_compose_editor_mode(); |
4e17e6
|
843 |
} |
80815d
|
844 |
|
5e3034
|
845 |
$plugin = $RCMAIL->plugins->exec_hook('message_compose_body', |
1414e3
|
846 |
array('body' => $body, 'html' => $isHtml, 'mode' => $COMPOSE['mode'])); |
a0109c
|
847 |
|
5e3034
|
848 |
$body = $plugin['body']; |
AM |
849 |
unset($plugin); |
8abe54
|
850 |
|
5e3034
|
851 |
// add blocked.gif attachment (#1486516) |
c6efcf
|
852 |
if ($isHtml && preg_match('#<img src="program/resources/blocked\.gif"#', $body)) { |
AM |
853 |
$content = $RCMAIL->get_resource_content('blocked.gif'); |
|
854 |
if ($content && ($attachment = rcmail_save_image('blocked.gif', 'image/gif', $content))) { |
5e3034
|
855 |
$COMPOSE['attachments'][$attachment['id']] = $attachment; |
AM |
856 |
$url = sprintf('%s&_id=%s&_action=display-attachment&_file=rcmfile%s', |
|
857 |
$RCMAIL->comm_path, $COMPOSE['id'], $attachment['id']); |
c6efcf
|
858 |
$body = preg_replace('#program/resources/blocked\.gif#', $url, $body); |
5e3034
|
859 |
} |
b575fa
|
860 |
} |
f52c4f
|
861 |
|
5e3034
|
862 |
$HTML_MODE = $isHtml; |
f52c4f
|
863 |
|
5e3034
|
864 |
return $body; |
33423a
|
865 |
} |
A |
866 |
|
|
867 |
function rcmail_compose_part_body($part, $isHtml = false) |
|
868 |
{ |
f189d7
|
869 |
global $RCMAIL, $COMPOSE, $MESSAGE, $LINE_LENGTH; |
33423a
|
870 |
|
A |
871 |
// Check if we have enough memory to handle the message in it |
|
872 |
// #1487424: we need up to 10x more memory than the body |
6b2b2e
|
873 |
if (!rcube_utils::mem_check($part->size * 10)) { |
33423a
|
874 |
return ''; |
A |
875 |
} |
|
876 |
|
|
877 |
// fetch part if not available |
48ba44
|
878 |
$body = $MESSAGE->get_part_body($part->mime_id, true); |
33423a
|
879 |
|
A |
880 |
// message is cached but not exists (#1485443), or other error |
48ba44
|
881 |
if ($body === false) { |
33423a
|
882 |
return ''; |
3167e5
|
883 |
} |
TB |
884 |
|
|
885 |
// register this part as pgp encrypted |
82dcbb
|
886 |
if (strpos($body, '-----BEGIN PGP MESSAGE-----') !== false) { |
3167e5
|
887 |
$MESSAGE->pgp_mime = true; |
TB |
888 |
$RCMAIL->output->set_env('pgp_mime_message', array( |
|
889 |
'_mbox' => $RCMAIL->storage->get_folder(), '_uid' => $MESSAGE->uid, '_part' => $part->mime_id, |
|
890 |
)); |
33423a
|
891 |
} |
A |
892 |
|
|
893 |
if ($isHtml) { |
|
894 |
if ($part->ctype_secondary == 'html') { |
|
895 |
} |
52d0d9
|
896 |
else if ($part->ctype_secondary == 'enriched') { |
0fa54d
|
897 |
$body = rcube_enriched::to_html($body); |
52d0d9
|
898 |
} |
33423a
|
899 |
else { |
A |
900 |
// try to remove the signature |
1414e3
|
901 |
if ($COMPOSE['mode'] != RCUBE_COMPOSE_DRAFT && $COMPOSE['mode'] != RCUBE_COMPOSE_EDIT) { |
a9bb50
|
902 |
if ($RCMAIL->config->get('strip_existing_sig', true)) { |
AM |
903 |
$body = rcmail_remove_signature($body); |
|
904 |
} |
33423a
|
905 |
} |
621a2e
|
906 |
|
33423a
|
907 |
// add HTML formatting |
eda92e
|
908 |
$body = rcmail_plain_body($body, $part->ctype_parameters['format'] == 'flowed'); |
33423a
|
909 |
} |
A |
910 |
} |
|
911 |
else { |
52d0d9
|
912 |
if ($part->ctype_secondary == 'enriched') { |
0fa54d
|
913 |
$body = rcube_enriched::to_html($body); |
52d0d9
|
914 |
$part->ctype_secondary = 'html'; |
AM |
915 |
} |
|
916 |
|
33423a
|
917 |
if ($part->ctype_secondary == 'html') { |
A |
918 |
// use html part if it has been used for message (pre)viewing |
|
919 |
// decrease line length for quoting |
a63f14
|
920 |
$len = $COMPOSE['mode'] == RCUBE_COMPOSE_REPLY ? $LINE_LENGTH-2 : $LINE_LENGTH; |
AM |
921 |
$body = $RCMAIL->html2text($body, array('width' => $len)); |
33423a
|
922 |
} |
A |
923 |
else { |
|
924 |
if ($part->ctype_secondary == 'plain' && $part->ctype_parameters['format'] == 'flowed') { |
|
925 |
$body = rcube_mime::unfold_flowed($body); |
|
926 |
} |
|
927 |
|
|
928 |
// try to remove the signature |
1414e3
|
929 |
if ($COMPOSE['mode'] != RCUBE_COMPOSE_DRAFT && $COMPOSE['mode'] != RCUBE_COMPOSE_EDIT) { |
a9bb50
|
930 |
if ($RCMAIL->config->get('strip_existing_sig', true)) { |
AM |
931 |
$body = rcmail_remove_signature($body); |
|
932 |
} |
33423a
|
933 |
} |
A |
934 |
} |
|
935 |
} |
|
936 |
|
|
937 |
return $body; |
087c7d
|
938 |
} |
A |
939 |
|
|
940 |
function rcmail_compose_body($attrib) |
|
941 |
{ |
f5d2ee
|
942 |
global $RCMAIL, $OUTPUT, $HTML_MODE, $MESSAGE_BODY; |
f52c4f
|
943 |
|
5e3034
|
944 |
list($form_start, $form_end) = get_form_tags($attrib); |
AM |
945 |
unset($attrib['form']); |
f52c4f
|
946 |
|
5e3034
|
947 |
if (empty($attrib['id'])) |
AM |
948 |
$attrib['id'] = 'rcmComposeBody'; |
087c7d
|
949 |
|
5e3034
|
950 |
$attrib['name'] = '_message'; |
087c7d
|
951 |
|
5e3034
|
952 |
$isHtml = $HTML_MODE; |
f52c4f
|
953 |
|
5e3034
|
954 |
$out = $form_start ? "$form_start\n" : ''; |
1966c5
|
955 |
|
5e3034
|
956 |
$saveid = new html_hiddenfield(array('name' => '_draft_saveid', 'value' => $RCMAIL->output->get_env('draft_id'))); |
AM |
957 |
$out .= $saveid->show(); |
1966c5
|
958 |
|
5e3034
|
959 |
$drafttoggle = new html_hiddenfield(array('name' => '_draft', 'value' => 'yes')); |
AM |
960 |
$out .= $drafttoggle->show(); |
1966c5
|
961 |
|
5e3034
|
962 |
$msgtype = new html_hiddenfield(array('name' => '_is_html', 'value' => ($isHtml ? "1" : "0"))); |
AM |
963 |
$out .= $msgtype->show(); |
a0109c
|
964 |
|
5e3034
|
965 |
$framed = new html_hiddenfield(array('name' => '_framed', 'value' => '1')); |
AM |
966 |
$out .= $framed->show(); |
85e60a
|
967 |
|
5e3034
|
968 |
// If desired, set this textarea to be editable by TinyMCE |
AM |
969 |
if ($isHtml) { |
|
970 |
$MESSAGE_BODY = htmlentities($MESSAGE_BODY, ENT_NOQUOTES, RCUBE_CHARSET); |
|
971 |
$attrib['class'] = 'mce_editor'; |
|
972 |
$attrib['is_escaped'] = true; |
|
973 |
$textarea = new html_textarea($attrib); |
|
974 |
$out .= $textarea->show($MESSAGE_BODY); |
|
975 |
} |
|
976 |
else { |
|
977 |
$textarea = new html_textarea($attrib); |
|
978 |
$out .= $textarea->show(''); |
6084d7
|
979 |
|
5e3034
|
980 |
// quote plain text, inject into textarea |
AM |
981 |
$table = get_html_translation_table(HTML_SPECIALCHARS); |
|
982 |
$MESSAGE_BODY = strtr($MESSAGE_BODY, $table); |
|
983 |
$out = substr($out, 0, -11) . $MESSAGE_BODY . '</textarea>'; |
c287f3
|
984 |
} |
66df08
|
985 |
|
5e3034
|
986 |
$out .= $form_end ? "\n$form_end" : ''; |
ed5d29
|
987 |
|
5e3034
|
988 |
$OUTPUT->set_env('composebody', $attrib['id']); |
f52c4f
|
989 |
|
5e3034
|
990 |
// include HTML editor |
AM |
991 |
$RCMAIL->html_editor(); |
41fa0b
|
992 |
|
5e3034
|
993 |
// Set language list |
f5d2ee
|
994 |
if ($RCMAIL->config->get('enable_spellcheck')) { |
5e3034
|
995 |
$engine = new rcube_spellchecker(); |
AM |
996 |
$dictionary = (bool) $RCMAIL->config->get('spellcheck_dictionary'); |
|
997 |
$spellcheck_langs = $engine->languages(); |
|
998 |
$lang = $_SESSION['language']; |
|
999 |
|
|
1000 |
// if not found in the list, try with two-letter code |
|
1001 |
if (!$spellcheck_langs[$lang]) { |
|
1002 |
$lang = strtolower(substr($lang, 0, 2)); |
|
1003 |
} |
|
1004 |
|
|
1005 |
if (!$spellcheck_langs[$lang]) { |
|
1006 |
$lang = 'en'; |
|
1007 |
} |
|
1008 |
|
|
1009 |
$OUTPUT->set_env('spell_langs', $spellcheck_langs); |
|
1010 |
$OUTPUT->set_env('spell_lang', $lang); |
|
1011 |
|
|
1012 |
$editor_lang_set = array(); |
|
1013 |
foreach ($spellcheck_langs as $key => $name) { |
|
1014 |
$editor_lang_set[] = ($key == $lang ? '+' : '') . rcube::JQ($name).'='.rcube::JQ($key); |
|
1015 |
} |
|
1016 |
|
|
1017 |
// include GoogieSpell |
|
1018 |
$OUTPUT->include_script('googiespell.js'); |
|
1019 |
$OUTPUT->add_script(sprintf( |
|
1020 |
"var googie = new GoogieSpell('%s/images/googiespell/','%s&lang=', %s);\n". |
|
1021 |
"googie.lang_chck_spell = \"%s\";\n". |
|
1022 |
"googie.lang_rsm_edt = \"%s\";\n". |
|
1023 |
"googie.lang_close = \"%s\";\n". |
|
1024 |
"googie.lang_revert = \"%s\";\n". |
|
1025 |
"googie.lang_no_error_found = \"%s\";\n". |
|
1026 |
"googie.lang_learn_word = \"%s\";\n". |
|
1027 |
"googie.setLanguages(%s);\n". |
|
1028 |
"googie.setCurrentLanguage('%s');\n". |
|
1029 |
"googie.setDecoration(false);\n". |
646b64
|
1030 |
"googie.decorateTextarea('%s');\n", |
681ba6
|
1031 |
$RCMAIL->output->asset_url($RCMAIL->output->get_skin_path()), |
5e3034
|
1032 |
$RCMAIL->url(array('_task' => 'utils', '_action' => 'spell', '_remote' => 1)), |
AM |
1033 |
!empty($dictionary) ? 'true' : 'false', |
|
1034 |
rcube::JQ(rcube::Q($RCMAIL->gettext('checkspelling'))), |
|
1035 |
rcube::JQ(rcube::Q($RCMAIL->gettext('resumeediting'))), |
|
1036 |
rcube::JQ(rcube::Q($RCMAIL->gettext('close'))), |
|
1037 |
rcube::JQ(rcube::Q($RCMAIL->gettext('revertto'))), |
|
1038 |
rcube::JQ(rcube::Q($RCMAIL->gettext('nospellerrors'))), |
|
1039 |
rcube::JQ(rcube::Q($RCMAIL->gettext('addtodict'))), |
|
1040 |
rcube_output::json_serialize($spellcheck_langs), |
|
1041 |
$lang, |
646b64
|
1042 |
$attrib['id']), 'foot'); |
5e3034
|
1043 |
|
AM |
1044 |
$OUTPUT->add_label('checking'); |
|
1045 |
$OUTPUT->set_env('spellcheck_langs', join(',', $editor_lang_set)); |
|
1046 |
} |
|
1047 |
|
b2992d
|
1048 |
$out .= "\n".'<iframe name="savetarget" src="program/resources/blank.gif" style="width:0;height:0;border:none;visibility:hidden;" aria-hidden="true"></iframe>'; |
5e3034
|
1049 |
|
AM |
1050 |
return $out; |
4315b0
|
1051 |
} |
4e17e6
|
1052 |
|
T |
1053 |
|
a0109c
|
1054 |
function rcmail_create_reply_body($body, $bodyIsHtml) |
4315b0
|
1055 |
{ |
5e3034
|
1056 |
global $RCMAIL, $MESSAGE, $LINE_LENGTH; |
4e17e6
|
1057 |
|
3167e5
|
1058 |
$prefix = rcmail_get_reply_header($MESSAGE); |
0b96b1
|
1059 |
$reply_mode = intval($RCMAIL->config->get('reply_mode')); |
AM |
1060 |
|
5e3034
|
1061 |
if (!$bodyIsHtml) { |
AM |
1062 |
// soft-wrap and quote message text |
|
1063 |
$body = rcmail_wrap_and_quote($body, $LINE_LENGTH); |
4e17e6
|
1064 |
|
5e3034
|
1065 |
$prefix .= "\n"; |
9f9664
|
1066 |
|
0b96b1
|
1067 |
if ($reply_mode > 0) { // top-posting |
5e3034
|
1068 |
$prefix = "\n\n\n" . $prefix; |
0b96b1
|
1069 |
$suffix = ''; |
AM |
1070 |
} |
|
1071 |
else { |
|
1072 |
$suffix = "\n"; |
5e3034
|
1073 |
} |
50f56d
|
1074 |
} |
A |
1075 |
else { |
5e3034
|
1076 |
// save inline images to files |
AM |
1077 |
$cid_map = rcmail_write_inline_attachments($MESSAGE); |
|
1078 |
// set is_safe flag (we need this for html body washing) |
|
1079 |
rcmail_check_safe($MESSAGE); |
|
1080 |
// clean up html tags |
|
1081 |
$body = rcmail_wash_html($body, array('safe' => $MESSAGE->is_safe), $cid_map); |
a0109c
|
1082 |
|
5e3034
|
1083 |
// build reply (quote content) |
AM |
1084 |
$prefix = '<p>' . rcube::Q($prefix) . "</p>\n"; |
|
1085 |
$prefix .= '<blockquote>'; |
|
1086 |
|
0b96b1
|
1087 |
if ($reply_mode > 0) { // top-posting |
5e3034
|
1088 |
$prefix = '<br>' . $prefix; |
AM |
1089 |
$suffix = '</blockquote>'; |
|
1090 |
} |
|
1091 |
else { |
c4daf3
|
1092 |
$suffix = '</blockquote><p><br/></p>'; |
5e3034
|
1093 |
} |
AM |
1094 |
} |
|
1095 |
|
|
1096 |
return $prefix . $body . $suffix; |
4315b0
|
1097 |
} |
4e17e6
|
1098 |
|
3167e5
|
1099 |
function rcmail_get_reply_header($message) |
TB |
1100 |
{ |
|
1101 |
global $RCMAIL; |
|
1102 |
|
|
1103 |
$from = array_pop(rcube_mime::decode_address_list($message->get_header('from'), 1, false, $message->headers->charset)); |
|
1104 |
return $RCMAIL->gettext(array( |
|
1105 |
'name' => 'mailreplyintro', |
|
1106 |
'vars' => array( |
|
1107 |
'date' => $RCMAIL->format_date($message->headers->date, $RCMAIL->config->get('date_long')), |
|
1108 |
'sender' => $from['name'] ?: rcube_utils::idn_to_utf8($from['mailto']), |
|
1109 |
) |
|
1110 |
)); |
|
1111 |
} |
4e17e6
|
1112 |
|
a0109c
|
1113 |
function rcmail_create_forward_body($body, $bodyIsHtml) |
4315b0
|
1114 |
{ |
5e3034
|
1115 |
global $RCMAIL, $MESSAGE, $COMPOSE; |
ec603f
|
1116 |
|
5e3034
|
1117 |
// add attachments |
AM |
1118 |
if (!isset($COMPOSE['forward_attachments']) && is_array($MESSAGE->mime_parts)) { |
|
1119 |
$cid_map = rcmail_write_compose_attachments($MESSAGE, $bodyIsHtml); |
|
1120 |
} |
4e17e6
|
1121 |
|
5e3034
|
1122 |
$date = $RCMAIL->format_date($MESSAGE->headers->date, $RCMAIL->config->get('date_long')); |
f5c108
|
1123 |
|
5e3034
|
1124 |
if (!$bodyIsHtml) { |
AM |
1125 |
$prefix = "\n\n\n-------- " . $RCMAIL->gettext('originalmessage') . " --------\n"; |
|
1126 |
$prefix .= $RCMAIL->gettext('subject') . ': ' . $MESSAGE->subject . "\n"; |
|
1127 |
$prefix .= $RCMAIL->gettext('date') . ': ' . $date . "\n"; |
|
1128 |
$prefix .= $RCMAIL->gettext('from') . ': ' . $MESSAGE->get_header('from') . "\n"; |
|
1129 |
$prefix .= $RCMAIL->gettext('to') . ': ' . $MESSAGE->get_header('to') . "\n"; |
a4cf45
|
1130 |
|
5e3034
|
1131 |
if ($cc = $MESSAGE->headers->get('cc')) { |
AM |
1132 |
$prefix .= $RCMAIL->gettext('cc') . ': ' . $cc . "\n"; |
|
1133 |
} |
|
1134 |
if (($replyto = $MESSAGE->headers->get('reply-to')) && $replyto != $MESSAGE->get_header('from')) { |
|
1135 |
$prefix .= $RCMAIL->gettext('replyto') . ': ' . $replyto . "\n"; |
|
1136 |
} |
a4cf45
|
1137 |
|
5e3034
|
1138 |
$prefix .= "\n"; |
AM |
1139 |
$body = trim($body, "\r\n"); |
|
1140 |
} |
|
1141 |
else { |
|
1142 |
// set is_safe flag (we need this for html body washing) |
|
1143 |
rcmail_check_safe($MESSAGE); |
ec603f
|
1144 |
|
5e3034
|
1145 |
// clean up html tags |
AM |
1146 |
$body = rcmail_wash_html($body, array('safe' => $MESSAGE->is_safe), $cid_map); |
5758b9
|
1147 |
|
5e3034
|
1148 |
$prefix = sprintf( |
AM |
1149 |
"<br /><p>-------- " . $RCMAIL->gettext('originalmessage') . " --------</p>" . |
|
1150 |
"<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody>" . |
|
1151 |
"<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>" . |
|
1152 |
"<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>" . |
|
1153 |
"<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>" . |
|
1154 |
"<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>", |
|
1155 |
$RCMAIL->gettext('subject'), rcube::Q($MESSAGE->subject), |
|
1156 |
$RCMAIL->gettext('date'), rcube::Q($date), |
|
1157 |
$RCMAIL->gettext('from'), rcube::Q($MESSAGE->get_header('from'), 'replace'), |
|
1158 |
$RCMAIL->gettext('to'), rcube::Q($MESSAGE->get_header('to'), 'replace')); |
a4cf45
|
1159 |
|
5e3034
|
1160 |
if ($cc = $MESSAGE->headers->get('cc')) |
AM |
1161 |
$prefix .= sprintf("<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>", |
|
1162 |
$RCMAIL->gettext('cc'), rcube::Q($cc, 'replace')); |
5758b9
|
1163 |
|
5e3034
|
1164 |
if (($replyto = $MESSAGE->headers->get('reply-to')) && $replyto != $MESSAGE->get_header('from')) |
AM |
1165 |
$prefix .= sprintf("<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>", |
|
1166 |
$RCMAIL->gettext('replyto'), rcube::Q($replyto, 'replace')); |
f52c4f
|
1167 |
|
5e3034
|
1168 |
$prefix .= "</tbody></table><br>"; |
AM |
1169 |
} |
|
1170 |
|
|
1171 |
return $prefix . $body; |
4315b0
|
1172 |
} |
4e17e6
|
1173 |
|
8d4bcd
|
1174 |
|
a0109c
|
1175 |
function rcmail_create_draft_body($body, $bodyIsHtml) |
4315b0
|
1176 |
{ |
5e3034
|
1177 |
global $MESSAGE, $COMPOSE; |
f52c4f
|
1178 |
|
5e3034
|
1179 |
// add attachments |
AM |
1180 |
// sizeof($MESSAGE->mime_parts can be 1 - e.g. attachment, but no text! |
|
1181 |
if (empty($COMPOSE['forward_attachments']) |
|
1182 |
&& is_array($MESSAGE->mime_parts) |
|
1183 |
&& count($MESSAGE->mime_parts) > 0 |
|
1184 |
) { |
|
1185 |
$cid_map = rcmail_write_compose_attachments($MESSAGE, $bodyIsHtml); |
f2a9a9
|
1186 |
} |
f52c4f
|
1187 |
|
5e3034
|
1188 |
// clean up HTML tags - XSS prevention (#1489251) |
AM |
1189 |
if ($bodyIsHtml) { |
|
1190 |
$body = rcmail_wash_html($body, array('safe' => 1), $cid_map); |
|
1191 |
|
d5f6d6
|
1192 |
// cleanup |
AM |
1193 |
$body = preg_replace(array( |
|
1194 |
// remove comments (produced by washtml) |
|
1195 |
'/<!--[^>]+-->/', |
|
1196 |
// remove <body> tags |
|
1197 |
'/<body([^>]*)>/i', |
|
1198 |
'/<\/body>/i', |
|
1199 |
// convert TinyMCE's empty-line sequence (#1490463) |
|
1200 |
'/<p>\xC2\xA0<\/p>/', |
|
1201 |
), |
|
1202 |
array( |
|
1203 |
'', |
|
1204 |
'', |
|
1205 |
'', |
|
1206 |
'<p><br /></p>', |
|
1207 |
), |
|
1208 |
$body |
|
1209 |
); |
5e3034
|
1210 |
|
AM |
1211 |
// replace cid with href in inline images links |
|
1212 |
if (!empty($cid_map)) { |
|
1213 |
$body = str_replace(array_keys($cid_map), array_values($cid_map), $body); |
|
1214 |
} |
|
1215 |
} |
|
1216 |
|
|
1217 |
return $body; |
4315b0
|
1218 |
} |
ba12c7
|
1219 |
|
A |
1220 |
|
|
1221 |
function rcmail_remove_signature($body) |
|
1222 |
{ |
5e3034
|
1223 |
global $RCMAIL; |
ba12c7
|
1224 |
|
5e3034
|
1225 |
$body = str_replace("\r\n", "\n", $body); |
AM |
1226 |
$len = strlen($body); |
|
1227 |
$sig_max_lines = $RCMAIL->config->get('sig_max_lines', 15); |
ba12c7
|
1228 |
|
5e3034
|
1229 |
while (($sp = strrpos($body, "-- \n", $sp ? -$len+$sp-1 : 0)) !== false) { |
AM |
1230 |
if ($sp == 0 || $body[$sp-1] == "\n") { |
|
1231 |
// do not touch blocks with more that X lines |
|
1232 |
if (substr_count($body, "\n", $sp) < $sig_max_lines) { |
|
1233 |
$body = substr($body, 0, max(0, $sp-1)); |
|
1234 |
} |
|
1235 |
break; |
|
1236 |
} |
ba12c7
|
1237 |
} |
A |
1238 |
|
5e3034
|
1239 |
return $body; |
ba12c7
|
1240 |
} |
A |
1241 |
|
|
1242 |
|
1bc48e
|
1243 |
function rcmail_write_compose_attachments(&$message, $bodyIsHtml) |
4315b0
|
1244 |
{ |
1414e3
|
1245 |
global $RCMAIL, $COMPOSE; |
5503cc
|
1246 |
|
5e3034
|
1247 |
$loaded_attachments = array(); |
AM |
1248 |
foreach ((array)$COMPOSE['attachments'] as $attachment) { |
|
1249 |
$loaded_attachments[$attachment['name'] . $attachment['mimetype']] = $attachment; |
8d4bcd
|
1250 |
} |
cc97ea
|
1251 |
|
5e3034
|
1252 |
$cid_map = array(); |
AM |
1253 |
$messages = array(); |
ec603f
|
1254 |
|
3167e5
|
1255 |
if ($message->pgp_mime) { |
TB |
1256 |
return $cid_map; |
|
1257 |
} |
|
1258 |
|
ce3105
|
1259 |
foreach ((array) $message->mime_parts() as $pid => $part) { |
be3460
|
1260 |
if ($part->mimetype == 'message/rfc822') { |
AM |
1261 |
$messages[] = $part->mime_id; |
|
1262 |
} |
|
1263 |
|
5e3034
|
1264 |
if ($part->disposition == 'attachment' || ($part->disposition == 'inline' && $bodyIsHtml) || $part->filename) { |
AM |
1265 |
// skip parts that aren't valid attachments |
|
1266 |
if ($part->ctype_primary == 'multipart' || $part->mimetype == 'application/ms-tnef') { |
|
1267 |
continue; |
|
1268 |
} |
|
1269 |
|
|
1270 |
// skip message attachments in reply mode |
1414e3
|
1271 |
if ($part->ctype_primary == 'message' && $COMPOSE['mode'] == RCUBE_COMPOSE_REPLY) { |
5e3034
|
1272 |
continue; |
AM |
1273 |
} |
|
1274 |
|
|
1275 |
// skip inline images when forwarding in text mode |
1414e3
|
1276 |
if ($part->content_id && $part->disposition == 'inline' && !$bodyIsHtml && $COMPOSE['mode'] == RCUBE_COMPOSE_FORWARD) { |
5e3034
|
1277 |
continue; |
AM |
1278 |
} |
|
1279 |
|
f7f75f
|
1280 |
// skip version.txt parts of multipart/encrypted messages |
TB |
1281 |
if ($message->pgp_mime && $part->mimetype == 'application/pgp-encrypted' && $part->filename == 'version.txt') { |
|
1282 |
continue; |
|
1283 |
} |
|
1284 |
|
be3460
|
1285 |
// skip attachments included in message/rfc822 attachment (#1486487, #1490607) |
AM |
1286 |
foreach ($messages as $mimeid) { |
|
1287 |
if (strpos($part->mime_id, $mimeid . '.') === 0) { |
|
1288 |
continue 2; |
5e3034
|
1289 |
} |
AM |
1290 |
} |
|
1291 |
|
|
1292 |
if (($attachment = $loaded_attachments[rcmail_attachment_name($part) . $part->mimetype]) |
d56091
|
1293 |
|| ($attachment = rcmail_save_attachment($message, $pid, $COMPOSE['id'])) |
5e3034
|
1294 |
) { |
AM |
1295 |
if ($bodyIsHtml && ($part->content_id || $part->content_location)) { |
|
1296 |
$url = sprintf('%s&_id=%s&_action=display-attachment&_file=rcmfile%s', |
|
1297 |
$RCMAIL->comm_path, $COMPOSE['id'], $attachment['id']); |
|
1298 |
|
|
1299 |
if ($part->content_id) |
|
1300 |
$cid_map['cid:'.$part->content_id] = $url; |
|
1301 |
else |
|
1302 |
$cid_map[$part->content_location] = $url; |
|
1303 |
} |
|
1304 |
} |
|
1305 |
} |
|
1306 |
} |
|
1307 |
|
|
1308 |
$COMPOSE['forward_attachments'] = true; |
|
1309 |
|
|
1310 |
return $cid_map; |
4315b0
|
1311 |
} |
4e17e6
|
1312 |
|
T |
1313 |
|
2f746d
|
1314 |
function rcmail_write_inline_attachments(&$message) |
A |
1315 |
{ |
5e3034
|
1316 |
global $RCMAIL, $COMPOSE; |
ec603f
|
1317 |
|
be3460
|
1318 |
$cid_map = array(); |
AM |
1319 |
$messages = array(); |
3167e5
|
1320 |
|
TB |
1321 |
if ($message->pgp_mime) { |
|
1322 |
return $cid_map; |
|
1323 |
} |
|
1324 |
|
ce3105
|
1325 |
foreach ((array) $message->mime_parts() as $pid => $part) { |
be3460
|
1326 |
if ($part->mimetype == 'message/rfc822') { |
AM |
1327 |
$messages[] = $part->mime_id; |
|
1328 |
} |
|
1329 |
|
5e3034
|
1330 |
if (($part->content_id || $part->content_location) && $part->filename) { |
be3460
|
1331 |
// skip attachments included in message/rfc822 attachment (#1486487, #1490607) |
AM |
1332 |
foreach ($messages as $mimeid) { |
|
1333 |
if (strpos($part->mime_id, $mimeid . '.') === 0) { |
|
1334 |
continue 2; |
|
1335 |
} |
|
1336 |
} |
|
1337 |
|
d56091
|
1338 |
if ($attachment = rcmail_save_attachment($message, $pid, $COMPOSE['id'])) { |
5e3034
|
1339 |
$url = sprintf('%s&_id=%s&_action=display-attachment&_file=rcmfile%s', |
AM |
1340 |
$RCMAIL->comm_path, $COMPOSE['id'], $attachment['id']); |
|
1341 |
|
|
1342 |
if ($part->content_id) |
|
1343 |
$cid_map['cid:'.$part->content_id] = $url; |
|
1344 |
else |
|
1345 |
$cid_map[$part->content_location] = $url; |
|
1346 |
} |
|
1347 |
} |
2f746d
|
1348 |
} |
8f2b46
|
1349 |
|
5e3034
|
1350 |
return $cid_map; |
2f746d
|
1351 |
} |
A |
1352 |
|
d9f109
|
1353 |
// Creates attachment(s) from the forwarded message(s) |
AM |
1354 |
function rcmail_write_forward_attachments() |
a208a4
|
1355 |
{ |
5e3034
|
1356 |
global $RCMAIL, $COMPOSE, $MESSAGE; |
a208a4
|
1357 |
|
5e3034
|
1358 |
$storage = $RCMAIL->get_storage(); |
AM |
1359 |
$names = array(); |
73076d
|
1360 |
$refs = array(); |
d9f109
|
1361 |
|
3167e5
|
1362 |
if ($MESSAGE->pgp_mime) { |
TB |
1363 |
return; |
|
1364 |
} |
|
1365 |
|
5e3034
|
1366 |
$loaded_attachments = array(); |
AM |
1367 |
foreach ((array)$COMPOSE['attachments'] as $attachment) { |
|
1368 |
$loaded_attachments[$attachment['name'] . $attachment['mimetype']] = $attachment; |
d9f109
|
1369 |
} |
AM |
1370 |
|
5e3034
|
1371 |
if ($COMPOSE['forward_uid'] == '*') { |
AM |
1372 |
$index = $storage->index(null, rcmail_sort_column(), rcmail_sort_order()); |
|
1373 |
$COMPOSE['forward_uid'] = $index->get(); |
d9f109
|
1374 |
} |
aafbe8
|
1375 |
else if (!is_array($COMPOSE['forward_uid']) && strpos($COMPOSE['forward_uid'], ':')) { |
03de13
|
1376 |
$COMPOSE['forward_uid'] = rcube_imap_generic::uncompressMessageSet($COMPOSE['forward_uid']); |
AM |
1377 |
} |
aafbe8
|
1378 |
else if (is_string($COMPOSE['forward_uid'])) { |
5e3034
|
1379 |
$COMPOSE['forward_uid'] = explode(',', $COMPOSE['forward_uid']); |
d9f109
|
1380 |
} |
AM |
1381 |
|
5e3034
|
1382 |
foreach ((array)$COMPOSE['forward_uid'] as $uid) { |
AM |
1383 |
$message = new rcube_message($uid); |
d9f109
|
1384 |
|
5e3034
|
1385 |
if (empty($message->headers)) { |
AM |
1386 |
continue; |
|
1387 |
} |
d9f109
|
1388 |
|
5e3034
|
1389 |
if (!empty($message->headers->charset)) { |
AM |
1390 |
$storage->set_charset($message->headers->charset); |
|
1391 |
} |
|
1392 |
|
|
1393 |
if (empty($MESSAGE->subject)) { |
|
1394 |
$MESSAGE->subject = $message->subject; |
|
1395 |
} |
|
1396 |
|
|
1397 |
// generate (unique) attachment name |
|
1398 |
$name = strlen($message->subject) ? mb_substr($message->subject, 0, 64) : 'message_rfc822'; |
|
1399 |
if (!empty($names[$name])) { |
|
1400 |
$names[$name]++; |
|
1401 |
$name .= '_' . $names[$name]; |
|
1402 |
} |
|
1403 |
$names[$name] = 1; |
|
1404 |
$name .= '.eml'; |
|
1405 |
|
|
1406 |
if (!empty($loaded_attachments[$name . 'message/rfc822'])) { |
|
1407 |
continue; |
|
1408 |
} |
|
1409 |
|
d56091
|
1410 |
rcmail_save_attachment($message, null, $COMPOSE['id'], array('filename' => $name)); |
73076d
|
1411 |
|
AM |
1412 |
if ($message->headers->messageID) { |
|
1413 |
$refs[] = $message->headers->messageID; |
|
1414 |
} |
|
1415 |
} |
|
1416 |
|
|
1417 |
// set In-Reply-To and References headers |
|
1418 |
if (count($refs) == 1) { |
|
1419 |
$COMPOSE['reply_msgid'] = $refs[0]; |
|
1420 |
} |
|
1421 |
if (!empty($refs)) { |
|
1422 |
$COMPOSE['references'] = implode(' ', $refs); |
d9f109
|
1423 |
} |
2f746d
|
1424 |
} |
A |
1425 |
|
c6efcf
|
1426 |
function rcmail_save_image($path, $mimetype = '', $data = null) |
b575fa
|
1427 |
{ |
5e3034
|
1428 |
global $COMPOSE; |
72ff6a
|
1429 |
|
5e3034
|
1430 |
// handle attachments in memory |
c6efcf
|
1431 |
if (empty($data)) { |
AM |
1432 |
$data = file_get_contents($path); |
|
1433 |
$is_file = true; |
|
1434 |
} |
|
1435 |
|
5e3034
|
1436 |
$name = rcmail_basename($path); |
c6efcf
|
1437 |
|
AM |
1438 |
if (empty($mimetype)) { |
|
1439 |
if ($is_file) { |
|
1440 |
$mimetype = rcube_mime::file_content_type($path, $name); |
|
1441 |
} |
|
1442 |
else { |
|
1443 |
$mimetype = rcube_mime::file_content_type($data, $name, 'application/octet-stream', true); |
|
1444 |
} |
|
1445 |
} |
b575fa
|
1446 |
|
5e3034
|
1447 |
$attachment = array( |
AM |
1448 |
'group' => $COMPOSE['id'], |
|
1449 |
'name' => $name, |
c6efcf
|
1450 |
'mimetype' => $mimetype, |
5e3034
|
1451 |
'data' => $data, |
AM |
1452 |
'size' => strlen($data), |
|
1453 |
); |
b575fa
|
1454 |
|
5e3034
|
1455 |
$attachment = rcmail::get_instance()->plugins->exec_hook('attachment_save', $attachment); |
b575fa
|
1456 |
|
5e3034
|
1457 |
if ($attachment['status']) { |
AM |
1458 |
unset($attachment['data'], $attachment['status'], $attachment['content_id'], $attachment['abort']); |
|
1459 |
return $attachment; |
|
1460 |
} |
f52c4f
|
1461 |
|
5e3034
|
1462 |
return false; |
b575fa
|
1463 |
} |
A |
1464 |
|
|
1465 |
function rcmail_basename($filename) |
|
1466 |
{ |
5e3034
|
1467 |
// basename() is not unicode safe and locale dependent |
AM |
1468 |
if (stristr(PHP_OS, 'win') || stristr(PHP_OS, 'netware')) { |
|
1469 |
return preg_replace('/^.*[\\\\\\/]/', '', $filename); |
|
1470 |
} |
|
1471 |
else { |
|
1472 |
return preg_replace('/^.*[\/]/', '', $filename); |
|
1473 |
} |
b575fa
|
1474 |
} |
2f746d
|
1475 |
|
60ab55
|
1476 |
/** |
AM |
1477 |
* Creates reply subject by removing common subject |
|
1478 |
* prefixes/suffixes from the original message subject |
|
1479 |
*/ |
|
1480 |
function rcmail_reply_subject($subject) |
|
1481 |
{ |
|
1482 |
$subject = trim($subject); |
|
1483 |
|
|
1484 |
// replace Re:, Re[x]:, Re-x (#1490497) |
|
1485 |
$prefix = '/^(re:|re\[\d\]:|re-\d:)\s*/i'; |
|
1486 |
do { |
|
1487 |
$subject = preg_replace($prefix, '', $subject, -1, $count); |
|
1488 |
} |
|
1489 |
while ($count); |
|
1490 |
|
|
1491 |
// replace (was: ...) (#1489375) |
|
1492 |
$subject = preg_replace('/\s*\([wW]as:[^\)]+\)\s*$/', '', $subject); |
|
1493 |
|
|
1494 |
return 'Re: ' . $subject; |
|
1495 |
} |
|
1496 |
|
4e17e6
|
1497 |
function rcmail_compose_subject($attrib) |
4315b0
|
1498 |
{ |
1414e3
|
1499 |
global $MESSAGE, $COMPOSE; |
72ff6a
|
1500 |
|
5e3034
|
1501 |
list($form_start, $form_end) = get_form_tags($attrib); |
AM |
1502 |
unset($attrib['form']); |
72ff6a
|
1503 |
|
5e3034
|
1504 |
$attrib['name'] = '_subject'; |
AM |
1505 |
$attrib['spellcheck'] = 'true'; |
4e17e6
|
1506 |
|
5e3034
|
1507 |
$textfield = new html_inputfield($attrib); |
AM |
1508 |
$subject = ''; |
4e17e6
|
1509 |
|
5e3034
|
1510 |
// use subject from post |
AM |
1511 |
if (isset($_POST['_subject'])) { |
|
1512 |
$subject = rcube_utils::get_input_value('_subject', rcube_utils::INPUT_POST, TRUE); |
|
1513 |
} |
968601
|
1514 |
else if (!empty($COMPOSE['param']['subject'])) { |
AM |
1515 |
$subject = $COMPOSE['param']['subject']; |
|
1516 |
} |
5e3034
|
1517 |
// create a reply-subject |
1414e3
|
1518 |
else if ($COMPOSE['mode'] == RCUBE_COMPOSE_REPLY) { |
60ab55
|
1519 |
$subject = rcmail_reply_subject($MESSAGE->subject); |
5e3034
|
1520 |
} |
AM |
1521 |
// create a forward-subject |
1414e3
|
1522 |
else if ($COMPOSE['mode'] == RCUBE_COMPOSE_FORWARD) { |
5e3034
|
1523 |
if (preg_match('/^fwd:/i', $MESSAGE->subject)) |
AM |
1524 |
$subject = $MESSAGE->subject; |
|
1525 |
else |
|
1526 |
$subject = 'Fwd: '.$MESSAGE->subject; |
|
1527 |
} |
|
1528 |
// creeate a draft-subject |
1414e3
|
1529 |
else if ($COMPOSE['mode'] == RCUBE_COMPOSE_DRAFT || $COMPOSE['mode'] == RCUBE_COMPOSE_EDIT) { |
5e3034
|
1530 |
$subject = $MESSAGE->subject; |
AM |
1531 |
} |
72ff6a
|
1532 |
|
5e3034
|
1533 |
$out = $form_start ? "$form_start\n" : ''; |
AM |
1534 |
$out .= $textfield->show($subject); |
|
1535 |
$out .= $form_end ? "\n$form_end" : ''; |
e99991
|
1536 |
|
5e3034
|
1537 |
return $out; |
4315b0
|
1538 |
} |
4e17e6
|
1539 |
|
T |
1540 |
function rcmail_compose_attachment_list($attrib) |
4315b0
|
1541 |
{ |
f5d2ee
|
1542 |
global $RCMAIL, $OUTPUT, $COMPOSE; |
72ff6a
|
1543 |
|
5e3034
|
1544 |
// add ID if not given |
AM |
1545 |
if (!$attrib['id']) |
|
1546 |
$attrib['id'] = 'rcmAttachmentList'; |
72ff6a
|
1547 |
|
8ccfc2
|
1548 |
$out = "\n"; |
AM |
1549 |
$jslist = array(); |
|
1550 |
$button = ''; |
087c7d
|
1551 |
|
5e3034
|
1552 |
if (is_array($COMPOSE['attachments'])) { |
AM |
1553 |
if ($attrib['deleteicon']) { |
|
1554 |
$button = html::img(array( |
8ccfc2
|
1555 |
'src' => $RCMAIL->output->abs_url($attrib['deleteicon'], true), |
5e3034
|
1556 |
'alt' => $RCMAIL->gettext('delete') |
AM |
1557 |
)); |
|
1558 |
} |
|
1559 |
else if (rcube_utils::get_boolean($attrib['textbuttons'])) { |
|
1560 |
$button = rcube::Q($RCMAIL->gettext('delete')); |
|
1561 |
} |
|
1562 |
|
|
1563 |
foreach ($COMPOSE['attachments'] as $id => $a_prop) { |
|
1564 |
if (empty($a_prop)) { |
|
1565 |
continue; |
|
1566 |
} |
|
1567 |
|
bb1ed2
|
1568 |
$content = sprintf('%s <span class="attachment-size">(%s)</span>', |
AM |
1569 |
rcube::Q($a_prop['name']), $RCMAIL->show_bytes($a_prop['size'])); |
|
1570 |
|
5e3034
|
1571 |
$out .= html::tag('li', array( |
AM |
1572 |
'id' => 'rcmfile'.$id, |
|
1573 |
'class' => rcube_utils::file2class($a_prop['mimetype'], $a_prop['name']), |
|
1574 |
'onmouseover' => "rcube_webmail.long_subject_title_ex(this, 0)", |
|
1575 |
), |
|
1576 |
html::a(array( |
|
1577 |
'href' => "#delete", |
|
1578 |
'title' => $RCMAIL->gettext('delete'), |
|
1579 |
'onclick' => sprintf("return %s.command('remove-attachment','rcmfile%s', this)", rcmail_output::JS_OBJECT_NAME, $id), |
9240c9
|
1580 |
'class' => 'delete', |
TB |
1581 |
'tabindex' => $attrib['tabindex'] ?: '0', |
|
1582 |
'aria-label' => $RCMAIL->gettext('delete') . ' ' . $a_prop['name'], |
5e3034
|
1583 |
), |
AM |
1584 |
$button |
bb1ed2
|
1585 |
) . $content |
5e3034
|
1586 |
); |
AM |
1587 |
|
|
1588 |
$jslist['rcmfile'.$id] = array( |
|
1589 |
'name' => $a_prop['name'], |
|
1590 |
'complete' => true, |
|
1591 |
'mimetype' => $a_prop['mimetype'] |
|
1592 |
); |
|
1593 |
} |
2efe33
|
1594 |
} |
a894ba
|
1595 |
|
5e3034
|
1596 |
if ($attrib['deleteicon']) |
8ccfc2
|
1597 |
$COMPOSE['deleteicon'] = $RCMAIL->output->abs_url($attrib['deleteicon'], true); |
5e3034
|
1598 |
else if (rcube_utils::get_boolean($attrib['textbuttons'])) |
AM |
1599 |
$COMPOSE['textbuttons'] = true; |
|
1600 |
if ($attrib['cancelicon']) |
8ccfc2
|
1601 |
$OUTPUT->set_env('cancelicon', $RCMAIL->output->abs_url($attrib['cancelicon'], true)); |
5e3034
|
1602 |
if ($attrib['loadingicon']) |
8ccfc2
|
1603 |
$OUTPUT->set_env('loadingicon', $RCMAIL->output->abs_url($attrib['loadingicon'], true)); |
72ff6a
|
1604 |
|
5e3034
|
1605 |
$OUTPUT->set_env('attachments', $jslist); |
AM |
1606 |
$OUTPUT->add_gui_object('attachmentlist', $attrib['id']); |
7152f5
|
1607 |
|
9240c9
|
1608 |
// put tabindex value into data-tabindex attribute |
TB |
1609 |
if (isset($attrib['tabindex'])) { |
|
1610 |
$attrib['data-tabindex'] = $attrib['tabindex']; |
|
1611 |
unset($attrib['tabindex']); |
|
1612 |
} |
|
1613 |
|
5e3034
|
1614 |
return html::tag('ul', $attrib, $out, html::$common_attrib); |
4315b0
|
1615 |
} |
4e17e6
|
1616 |
|
T |
1617 |
|
|
1618 |
function rcmail_compose_attachment_form($attrib) |
4315b0
|
1619 |
{ |
5e3034
|
1620 |
global $OUTPUT, $RCMAIL; |
4e17e6
|
1621 |
|
5e3034
|
1622 |
// set defaults |
AM |
1623 |
$attrib += array('id' => 'rcmUploadbox', 'buttons' => 'yes'); |
7df0e3
|
1624 |
|
5e3034
|
1625 |
// Get filesize, enable upload progress bar |
AM |
1626 |
$max_filesize = $RCMAIL->upload_init(); |
4171c5
|
1627 |
|
5e3034
|
1628 |
$button = new html_inputfield(array('type' => 'button')); |
AM |
1629 |
$content = html::div(null, rcmail_compose_attachment_field()) |
|
1630 |
. html::div('hint', $RCMAIL->gettext(array('name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize)))); |
fe0cb6
|
1631 |
|
5e3034
|
1632 |
if (rcube_utils::get_boolean($attrib['buttons'])) { |
AM |
1633 |
$content .= html::div('buttons', |
|
1634 |
$button->show($RCMAIL->gettext('close'), array('class' => 'button', 'onclick' => "$('#$attrib[id]').hide()")) . ' ' . |
|
1635 |
$button->show($RCMAIL->gettext('upload'), array('class' => 'button mainaction', 'onclick' => rcmail_output::JS_OBJECT_NAME . ".command('send-attachment', this.form)")) |
|
1636 |
); |
|
1637 |
} |
fe0cb6
|
1638 |
|
5e3034
|
1639 |
$out = html::div($attrib, $OUTPUT->form_tag(array( |
AM |
1640 |
'id' => $attrib['id'] . 'Frm', |
|
1641 |
'name' => 'uploadform', |
|
1642 |
'method' => 'post', |
|
1643 |
'enctype' => 'multipart/form-data' |
|
1644 |
), $content |
|
1645 |
)); |
|
1646 |
|
|
1647 |
$OUTPUT->add_gui_object('uploadform', $attrib['id'] . 'Frm'); |
|
1648 |
|
|
1649 |
return $out; |
4315b0
|
1650 |
} |
4e17e6
|
1651 |
|
T |
1652 |
|
5a8ee3
|
1653 |
function rcmail_compose_attachment_field($attrib = array()) |
4315b0
|
1654 |
{ |
5e3034
|
1655 |
$attrib['type'] = 'file'; |
AM |
1656 |
$attrib['name'] = '_attachments[]'; |
|
1657 |
$attrib['multiple'] = 'multiple'; |
7fc056
|
1658 |
|
5e3034
|
1659 |
$field = new html_inputfield($attrib); |
AM |
1660 |
|
|
1661 |
return $field->show(); |
4315b0
|
1662 |
} |
4e17e6
|
1663 |
|
66e2bf
|
1664 |
|
4e17e6
|
1665 |
function rcmail_priority_selector($attrib) |
4315b0
|
1666 |
{ |
5e3034
|
1667 |
global $RCMAIL, $MESSAGE; |
7152f5
|
1668 |
|
5e3034
|
1669 |
list($form_start, $form_end) = get_form_tags($attrib); |
AM |
1670 |
unset($attrib['form']); |
8958d0
|
1671 |
|
5e3034
|
1672 |
$attrib['name'] = '_priority'; |
AM |
1673 |
$prio_list = array( |
|
1674 |
$RCMAIL->gettext('lowest') => 5, |
|
1675 |
$RCMAIL->gettext('low') => 4, |
|
1676 |
$RCMAIL->gettext('normal') => 0, |
|
1677 |
$RCMAIL->gettext('high') => 2, |
|
1678 |
$RCMAIL->gettext('highest') => 1, |
|
1679 |
); |
4e17e6
|
1680 |
|
5e3034
|
1681 |
$selector = new html_select($attrib); |
AM |
1682 |
$selector->add(array_keys($prio_list), array_values($prio_list)); |
8958d0
|
1683 |
|
5e3034
|
1684 |
if (isset($_POST['_priority'])) |
AM |
1685 |
$sel = $_POST['_priority']; |
|
1686 |
else if (isset($MESSAGE->headers->priority) && intval($MESSAGE->headers->priority) != 3) |
|
1687 |
$sel = $MESSAGE->headers->priority; |
|
1688 |
else |
|
1689 |
$sel = 0; |
4e17e6
|
1690 |
|
5e3034
|
1691 |
$out = $form_start ? "$form_start\n" : ''; |
ddc161
|
1692 |
$out .= $selector->show((int) $sel); |
5e3034
|
1693 |
$out .= $form_end ? "\n$form_end" : ''; |
8958d0
|
1694 |
|
5e3034
|
1695 |
return $out; |
4315b0
|
1696 |
} |
4e17e6
|
1697 |
|
T |
1698 |
|
f65021
|
1699 |
function rcmail_mdn_checkbox($attrib) |
4315b0
|
1700 |
{ |
1414e3
|
1701 |
global $RCMAIL, $MESSAGE; |
8958d0
|
1702 |
|
5e3034
|
1703 |
list($form_start, $form_end) = get_form_tags($attrib); |
AM |
1704 |
unset($attrib['form']); |
8958d0
|
1705 |
|
5e3034
|
1706 |
if (!isset($attrib['id'])) |
AM |
1707 |
$attrib['id'] = 'receipt'; |
620439
|
1708 |
|
f65021
|
1709 |
$attrib['name'] = '_mdn'; |
5e3034
|
1710 |
$attrib['value'] = '1'; |
620439
|
1711 |
|
5e3034
|
1712 |
$checkbox = new html_checkbox($attrib); |
b3660b
|
1713 |
|
f65021
|
1714 |
if (isset($_POST['_mdn'])) |
AM |
1715 |
$mdn_default = $_POST['_mdn']; |
1414e3
|
1716 |
else if (in_array($COMPOSE['mode'], array(RCUBE_COMPOSE_DRAFT, RCUBE_COMPOSE_EDIT))) |
5e3034
|
1717 |
$mdn_default = (bool) $MESSAGE->headers->mdn_to; |
AM |
1718 |
else |
|
1719 |
$mdn_default = $RCMAIL->config->get('mdn_default'); |
620439
|
1720 |
|
5e3034
|
1721 |
$out = $form_start ? "$form_start\n" : ''; |
AM |
1722 |
$out .= $checkbox->show($mdn_default); |
|
1723 |
$out .= $form_end ? "\n$form_end" : ''; |
|
1724 |
|
|
1725 |
return $out; |
4315b0
|
1726 |
} |
620439
|
1727 |
|
T |
1728 |
|
f22ea7
|
1729 |
function rcmail_dsn_checkbox($attrib) |
A |
1730 |
{ |
5e3034
|
1731 |
global $RCMAIL; |
f22ea7
|
1732 |
|
5e3034
|
1733 |
list($form_start, $form_end) = get_form_tags($attrib); |
AM |
1734 |
unset($attrib['form']); |
f22ea7
|
1735 |
|
5e3034
|
1736 |
if (!isset($attrib['id'])) |
AM |
1737 |
$attrib['id'] = 'dsn'; |
f22ea7
|
1738 |
|
5e3034
|
1739 |
$attrib['name'] = '_dsn'; |
AM |
1740 |
$attrib['value'] = '1'; |
f22ea7
|
1741 |
|
5e3034
|
1742 |
$checkbox = new html_checkbox($attrib); |
271efe
|
1743 |
|
5e3034
|
1744 |
if (isset($_POST['_dsn'])) |
AM |
1745 |
$dsn_value = (int) $_POST['_dsn']; |
|
1746 |
else |
|
1747 |
$dsn_value = $RCMAIL->config->get('dsn_default'); |
f22ea7
|
1748 |
|
5e3034
|
1749 |
$out = $form_start ? "$form_start\n" : ''; |
AM |
1750 |
$out .= $checkbox->show($dsn_value); |
|
1751 |
$out .= $form_end ? "\n$form_end" : ''; |
|
1752 |
|
|
1753 |
return $out; |
f22ea7
|
1754 |
} |
A |
1755 |
|
|
1756 |
|
a0109c
|
1757 |
function rcmail_editor_selector($attrib) |
S |
1758 |
{ |
5e3034
|
1759 |
global $RCMAIL; |
6b2b2e
|
1760 |
|
5e3034
|
1761 |
// determine whether HTML or plain text should be checked |
AM |
1762 |
$useHtml = rcmail_compose_editor_mode(); |
d9344f
|
1763 |
|
5e3034
|
1764 |
if (empty($attrib['editorid'])) |
AM |
1765 |
$attrib['editorid'] = 'rcmComposeBody'; |
79af0b
|
1766 |
|
5e3034
|
1767 |
if (empty($attrib['name'])) |
AM |
1768 |
$attrib['name'] = 'editorSelect'; |
8958d0
|
1769 |
|
646b64
|
1770 |
$attrib['onchange'] = "return rcmail.command('toggle-editor', {id: '".$attrib['editorid']."', html: this.value == 'html'}, '', event)"; |
309d2f
|
1771 |
|
5e3034
|
1772 |
$select = new html_select($attrib); |
309d2f
|
1773 |
|
5e3034
|
1774 |
$select->add(rcube::Q($RCMAIL->gettext('htmltoggle')), 'html'); |
AM |
1775 |
$select->add(rcube::Q($RCMAIL->gettext('plaintoggle')), 'plain'); |
309d2f
|
1776 |
|
5e3034
|
1777 |
return $select->show($useHtml ? 'html' : 'plain'); |
a0109c
|
1778 |
} |
S |
1779 |
|
|
1780 |
|
faf876
|
1781 |
function rcmail_store_target_selection($attrib) |
T |
1782 |
{ |
5e3034
|
1783 |
global $COMPOSE, $RCMAIL; |
72ff6a
|
1784 |
|
5e3034
|
1785 |
$attrib['name'] = '_store_target'; |
AM |
1786 |
$select = $RCMAIL->folder_selector(array_merge($attrib, array( |
|
1787 |
'noselection' => '- ' . $RCMAIL->gettext('dontsave') . ' -', |
|
1788 |
'folder_filter' => 'mail', |
|
1789 |
'folder_rights' => 'w', |
|
1790 |
))); |
|
1791 |
|
|
1792 |
return $select->show(isset($_POST['_store_target']) ? $_POST['_store_target'] : $COMPOSE['param']['sent_mbox'], $attrib); |
faf876
|
1793 |
} |
T |
1794 |
|
|
1795 |
|
eeb85f
|
1796 |
function rcmail_check_sent_folder($folder, $create=false) |
A |
1797 |
{ |
5e3034
|
1798 |
global $RCMAIL; |
eeb85f
|
1799 |
|
5e3034
|
1800 |
// we'll not save the message, so it doesn't matter |
AM |
1801 |
if ($RCMAIL->config->get('no_save_sent_messages')) { |
|
1802 |
return true; |
|
1803 |
} |
e04e31
|
1804 |
|
5e3034
|
1805 |
if ($RCMAIL->storage->folder_exists($folder, true)) { |
AM |
1806 |
return true; |
|
1807 |
} |
eeb85f
|
1808 |
|
5e3034
|
1809 |
// folder may exist but isn't subscribed (#1485241) |
AM |
1810 |
if ($create) { |
|
1811 |
if (!$RCMAIL->storage->folder_exists($folder)) |
|
1812 |
return $RCMAIL->storage->create_folder($folder, true); |
|
1813 |
else |
|
1814 |
return $RCMAIL->storage->subscribe($folder); |
|
1815 |
} |
eeb85f
|
1816 |
|
5e3034
|
1817 |
return false; |
eeb85f
|
1818 |
} |
A |
1819 |
|
|
1820 |
|
4e17e6
|
1821 |
function get_form_tags($attrib) |
4315b0
|
1822 |
{ |
5e3034
|
1823 |
global $RCMAIL, $MESSAGE_FORM, $COMPOSE; |
4e17e6
|
1824 |
|
5e3034
|
1825 |
$form_start = ''; |
AM |
1826 |
if (!$MESSAGE_FORM) { |
|
1827 |
$hiddenfields = new html_hiddenfield(array('name' => '_task', 'value' => $RCMAIL->task)); |
|
1828 |
$hiddenfields->add(array('name' => '_action', 'value' => 'send')); |
|
1829 |
$hiddenfields->add(array('name' => '_id', 'value' => $COMPOSE['id'])); |
|
1830 |
$hiddenfields->add(array('name' => '_attachments')); |
1966c5
|
1831 |
|
5e3034
|
1832 |
$form_start = empty($attrib['form']) ? $RCMAIL->output->form_tag(array('name' => "form", 'method' => "post")) : ''; |
AM |
1833 |
$form_start .= $hiddenfields->show(); |
|
1834 |
} |
eeb85f
|
1835 |
|
827159
|
1836 |
$form_end = ($MESSAGE_FORM && !strlen($attrib['form'])) ? '</form>' : ''; |
AM |
1837 |
$form_name = $attrib['form'] ?: 'form'; |
eeb85f
|
1838 |
|
5e3034
|
1839 |
if (!$MESSAGE_FORM) |
AM |
1840 |
$RCMAIL->output->add_gui_object('messageform', $form_name); |
eeb85f
|
1841 |
|
5e3034
|
1842 |
$MESSAGE_FORM = $form_name; |
4e17e6
|
1843 |
|
5e3034
|
1844 |
return array($form_start, $form_end); |
4315b0
|
1845 |
} |
4e17e6
|
1846 |
|
T |
1847 |
|
635722
|
1848 |
function rcmail_addressbook_list($attrib = array()) |
eeb73c
|
1849 |
{ |
T |
1850 |
global $RCMAIL, $OUTPUT; |
|
1851 |
|
|
1852 |
$attrib += array('id' => 'rcmdirectorylist'); |
|
1853 |
|
|
1854 |
$out = ''; |
|
1855 |
$line_templ = html::tag('li', array( |
|
1856 |
'id' => 'rcmli%s', 'class' => '%s'), |
|
1857 |
html::a(array('href' => '#list', |
|
1858 |
'rel' => '%s', |
d686b5
|
1859 |
'onclick' => "return ".rcmail_output::JS_OBJECT_NAME.".command('list-addresses','%s',this)"), '%s')); |
eeb73c
|
1860 |
|
65dff8
|
1861 |
foreach ($RCMAIL->get_address_sources(false, true) as $j => $source) { |
eeb73c
|
1862 |
$id = strval(strlen($source['id']) ? $source['id'] : $j); |
6b2b2e
|
1863 |
$js_id = rcube::JQ($id); |
eeb73c
|
1864 |
|
T |
1865 |
// set class name(s) |
|
1866 |
$class_name = 'addressbook'; |
|
1867 |
if ($source['class_name']) |
|
1868 |
$class_name .= ' ' . $source['class_name']; |
|
1869 |
|
|
1870 |
$out .= sprintf($line_templ, |
6b2b2e
|
1871 |
rcube_utils::html_identifier($id,true), |
eeb73c
|
1872 |
$class_name, |
T |
1873 |
$source['id'], |
827159
|
1874 |
$js_id, ($source['name'] ?: $id)); |
eeb73c
|
1875 |
} |
T |
1876 |
|
635722
|
1877 |
$OUTPUT->add_gui_object('addressbookslist', $attrib['id']); |
eeb73c
|
1878 |
|
T |
1879 |
return html::tag('ul', $attrib, $out, html::$common_attrib); |
|
1880 |
} |
|
1881 |
|
|
1882 |
// return the contacts list as HTML table |
|
1883 |
function rcmail_contacts_list($attrib = array()) |
|
1884 |
{ |
6b2b2e
|
1885 |
global $RCMAIL, $OUTPUT; |
eeb73c
|
1886 |
|
T |
1887 |
$attrib += array('id' => 'rcmAddressList'); |
|
1888 |
|
|
1889 |
// set client env |
|
1890 |
$OUTPUT->add_gui_object('contactslist', $attrib['id']); |
|
1891 |
$OUTPUT->set_env('pagecount', 0); |
|
1892 |
$OUTPUT->set_env('current_page', 0); |
|
1893 |
$OUTPUT->include_script('list.js'); |
|
1894 |
|
6b2b2e
|
1895 |
return $RCMAIL->table_output($attrib, array(), array('name'), 'ID'); |
eeb73c
|
1896 |
} |
T |
1897 |
|
|
1898 |
|
ae6d2d
|
1899 |
/** |
TB |
1900 |
* Register a certain container as active area to drop files onto |
|
1901 |
*/ |
|
1902 |
function compose_file_drop_area($attrib) |
|
1903 |
{ |
|
1904 |
global $OUTPUT; |
|
1905 |
|
|
1906 |
if ($attrib['id']) { |
|
1907 |
$OUTPUT->add_gui_object('filedrop', $attrib['id']); |
|
1908 |
$OUTPUT->set_env('filedrop', array('action' => 'upload', 'fieldname' => '_attachments')); |
|
1909 |
} |
|
1910 |
} |
|
1911 |
|
eeb73c
|
1912 |
|
0b1de8
|
1913 |
/** |
TB |
1914 |
* |
|
1915 |
*/ |
|
1916 |
function rcmail_compose_responses_list($attrib) |
|
1917 |
{ |
|
1918 |
global $RCMAIL, $OUTPUT; |
|
1919 |
|
|
1920 |
$attrib += array('id' => 'rcmresponseslist', 'tagname' => 'ul', 'cols' => 1); |
|
1921 |
|
|
1922 |
$jsenv = array(); |
0ce212
|
1923 |
$list = new html_table($attrib); |
TB |
1924 |
foreach ($RCMAIL->get_compose_responses(true) as $response) { |
|
1925 |
$key = $response['key']; |
|
1926 |
$item = html::a(array( |
b2992d
|
1927 |
'href' => '#'.urlencode($response['name']), |
0b1de8
|
1928 |
'class' => rtrim('insertresponse ' . $attrib['itemclass']), |
0933d6
|
1929 |
'unselectable' => 'on', |
b2992d
|
1930 |
'tabindex' => '0', |
0b1de8
|
1931 |
'rel' => $key, |
6b2b2e
|
1932 |
), rcube::Q($response['name'])); |
0b1de8
|
1933 |
|
TB |
1934 |
$jsenv[$key] = $response; |
|
1935 |
$list->add(array(), $item); |
|
1936 |
} |
|
1937 |
|
|
1938 |
// set client env |
|
1939 |
$OUTPUT->set_env('textresponses', $jsenv); |
|
1940 |
$OUTPUT->add_gui_object('responseslist', $attrib['id']); |
|
1941 |
|
|
1942 |
return $list->show(); |
|
1943 |
} |