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