source: github/program/steps/mail/compose.inc @ b8ae5093

HEADcourier-fixdev-browser-capabilitiespdorelease-0.6release-0.7release-0.8
Last change on this file since b8ae5093 was b8ae5093, checked in by alecpl <alec@…>, 5 years ago
  • Fix HTML editor initialization on IE (#1485304)
  • move back toggle_editor function to editor.js
  • merge identity and compose editor init functions
  • Property mode set to 100644
File size: 29.7 KB
Line 
1<?php
2
3/*
4 +-----------------------------------------------------------------------+
5 | program/steps/mail/compose.inc                                        |
6 |                                                                       |
7 | This file is part of the RoundCube Webmail client                     |
8 | Copyright (C) 2005-2008, RoundCube Dev. - Switzerland                 |
9 | Licensed under the GNU GPL                                            |
10 |                                                                       |
11 | PURPOSE:                                                              |
12 |   Compose a new mail message with all headers and attachments         |
13 |                                                                       |
14 +-----------------------------------------------------------------------+
15 | Author: Thomas Bruederli <roundcube@gmail.com>                        |
16 +-----------------------------------------------------------------------+
17
18 $Id$
19
20*/
21
22// define constants for message compose mode
23define('RCUBE_COMPOSE_REPLY', 0x0106);
24define('RCUBE_COMPOSE_FORWARD', 0x0107);
25define('RCUBE_COMPOSE_DRAFT', 0x0108);
26
27
28// remove an attachment
29if ($RCMAIL->action=='remove-attachment' && preg_match('/^rcmfile([0-9]+)$/', $_POST['_file'], $regs))
30{
31  $id = $regs[1];
32  if (is_array($_SESSION['compose']['attachments'][$id]))
33  {
34    @unlink($_SESSION['compose']['attachments'][$id]['path']);
35    unset($_SESSION['compose']['attachments'][$id]);
36    $OUTPUT->command('remove_from_attachment_list', "rcmfile$id");
37    $OUTPUT->send();
38  }
39  exit;
40}
41
42if ($RCMAIL->action=='display-attachment' && preg_match('/^rcmfile([0-9]+)$/', $_GET['_file'], $regs))
43{
44  $id = $regs[1];
45  if (is_array($_SESSION['compose']['attachments'][$id]))
46  {
47    $apath = $_SESSION['compose']['attachments'][$id]['path'];
48    header('Content-Type: ' . $_SESSION['compose']['attachments'][$id]['mimetype']);
49    header('Content-Length: ' . filesize($apath));
50    readfile($apath);
51  }
52  exit;
53}
54
55$MESSAGE_FORM = NULL;
56$MESSAGE = NULL;
57
58// Nothing below is called during message composition, only at "new/forward/reply/draft" initialization or
59// if a compose-ID is given (i.e. when the compose step is opened in a new window/tab).
60// Since there are many ways to leave the compose page improperly, it seems necessary to clean-up an old
61// compose when a "new/forward/reply/draft" is called - otherwise the old session attachments will appear
62
63if (!is_array($_SESSION['compose']) || $_SESSION['compose']['id'] != get_input_value('_id', RCUBE_INPUT_GET))
64{
65  rcmail_compose_cleanup();
66  $_SESSION['compose'] = array('id' => uniqid(rand()), 'param' => array_map('strip_tags', $_GET));
67 
68  // process values like "mailto:foo@bar.com?subject=new+message&cc=another"
69  if ($_SESSION['compose']['param']['_to']) {
70    $mailto = explode('?', $_SESSION['compose']['param']['_to']);
71    if (count($mailto) > 1) {
72      $_SESSION['compose']['param']['_to'] = $mailto[0];
73      parse_str($mailto[1], $query);
74      foreach ($query as $f => $val)
75        $_SESSION['compose']['param']["_$f"] = $val;
76    }
77  }
78
79  // redirect to a unique URL with all parameters stored in session
80  $OUTPUT->redirect(array('_action' => 'compose', '_id' => $_SESSION['compose']['id']));
81}
82
83// add some labels to client
84$OUTPUT->add_label('nosubject', 'nosenderwarning', 'norecipientwarning', 'nosubjectwarning',
85    'nobodywarning', 'notsentwarning', 'savingmessage', 'sendingmessage', 'messagesaved',
86    'converting', 'editorwarning');
87
88// add config parameters to client script
89if (!empty($CONFIG['drafts_mbox'])) {
90  $OUTPUT->set_env('drafts_mailbox', $CONFIG['drafts_mbox']);
91  $OUTPUT->set_env('draft_autosave', $CONFIG['draft_autosave']);
92}
93// set current mailbox in client environment
94$OUTPUT->set_env('mailbox', $IMAP->get_mailbox_name());
95
96// get reference message and set compose mode
97if ($msg_uid = $_SESSION['compose']['param']['_reply_uid'])
98  $compose_mode = RCUBE_COMPOSE_REPLY;
99else if ($msg_uid = $_SESSION['compose']['param']['_forward_uid'])
100  $compose_mode = RCUBE_COMPOSE_FORWARD;
101else if ($msg_uid = $_SESSION['compose']['param']['_draft_uid'])
102  $compose_mode = RCUBE_COMPOSE_DRAFT;
103
104if (!empty($msg_uid))
105{
106  // similar as in program/steps/mail/show.inc
107  $MESSAGE = new rcube_message($msg_uid);
108 
109  if (!empty($MESSAGE->headers->charset))
110    $IMAP->set_charset($MESSAGE->headers->charset);
111   
112  if ($compose_mode == RCUBE_COMPOSE_REPLY)
113  {
114    $_SESSION['compose']['reply_uid'] = $msg_uid;
115    $_SESSION['compose']['reply_msgid'] = $MESSAGE->headers->messageID;
116    $_SESSION['compose']['references']  = trim($MESSAGE->headers->references . " " . $MESSAGE->headers->messageID);
117
118    if (!empty($_SESSION['compose']['param']['_all']))
119      $MESSAGE->reply_all = 1;
120  }
121  else if ($compose_mode == RCUBE_COMPOSE_DRAFT)
122  {
123    if($MESSAGE->headers->in_reply_to)
124    {
125      // TODO: how to get reply_uid/forward_uid value, maybe we must set X-Reply-UID/X-Forward-UID
126      // $_SESSION['compose']['reply_uid'] = ?
127      // $_SESSION['compose']['forward_uid'] = ?
128      $_SESSION['compose']['reply_msgid'] = '<'.$MESSAGE->headers->in_reply_to.'>';
129    }
130    $_SESSION['compose']['references']  = $MESSAGE->headers->references;
131  }
132  else if ($compose_mode == RCUBE_COMPOSE_FORWARD)
133  {
134    $_SESSION['compose']['forward_uid'] = $msg_uid;
135  }
136}
137
138/****** compose mode functions ********/
139
140
141function rcmail_compose_headers($attrib)
142{
143  global $IMAP, $MESSAGE, $DB, $compose_mode;
144  static $sa_recipients = array();
145
146  list($form_start, $form_end) = get_form_tags($attrib);
147 
148  $out = '';
149  $part = strtolower($attrib['part']);
150 
151  switch ($part)
152  {
153    case 'from':
154      return rcmail_compose_header_from($attrib);
155
156    case 'to':
157      $fname = '_to';
158      $header = 'to';
159     
160      // we have a set of recipients stored is session
161      if (($mailto_id = $_SESSION['compose']['param']['_mailto']) && $_SESSION['mailto'][$mailto_id])
162        $fvalue = urldecode($_SESSION['mailto'][$mailto_id]);
163     
164    case 'cc':
165      if (!$fname)
166      {
167        $fname = '_cc';
168        $header = 'cc';
169      }
170    case 'bcc':
171      if (!$fname)
172      {
173        $fname = '_bcc';
174        $header = 'bcc';
175      }
176       
177      $allow_attrib = array('id', 'class', 'style', 'cols', 'rows', 'tabindex');
178      $field_type = 'html_textarea';
179      break;
180
181    case 'replyto':
182    case 'reply-to':
183      $fname = '_replyto';
184      $allow_attrib = array('id', 'class', 'style', 'size', 'tabindex');
185      $field_type = 'html_inputfield';
186      break;
187  }
188 
189  if ($fname && !empty($_POST[$fname]))
190    $fvalue = get_input_value($fname, RCUBE_INPUT_POST, TRUE);
191  else if ($fname && !$fvalue && !empty($_SESSION['compose']['param'][$fname]))
192    $fvalue = $_SESSION['compose']['param'][$fname];
193
194  else if ($header && $compose_mode == RCUBE_COMPOSE_REPLY)
195  {
196    // get recipent address(es) out of the message headers
197    if ($header=='to' && !empty($MESSAGE->headers->replyto))
198      $fvalue = $MESSAGE->headers->replyto;
199
200    else if ($header=='to' && !empty($MESSAGE->headers->from))
201      $fvalue = $MESSAGE->headers->from;
202
203    // add recipent of original message if reply to all
204    else if ($header=='cc' && !empty($MESSAGE->reply_all))
205    {
206      if ($v = $MESSAGE->headers->to)
207        $fvalue .= $v;
208
209      if ($v = $MESSAGE->headers->cc)
210        $fvalue .= (!empty($fvalue) ? ', ' : '') . $v;
211    }
212
213    // split recipients and put them back together in a unique way
214    if (!empty($fvalue))
215    {
216      $to_addresses = $IMAP->decode_address_list($fvalue);
217      $fvalue = '';
218
219      foreach ($to_addresses as $addr_part)
220      {
221        if (!empty($addr_part['mailto'])
222            && !in_array($addr_part['mailto'], $sa_recipients)
223            && (!$MESSAGE->compose_from
224                || !in_array_nocase($addr_part['mailto'], $MESSAGE->compose_from)
225                || count($to_addresses)==1)) // allow reply to yourself
226        {
227          $fvalue .= (strlen($fvalue) ? ', ':'').$addr_part['string'];
228          $sa_recipients[] = $addr_part['mailto'];
229        }
230      }
231    }
232  }
233  else if ($header && $compose_mode == RCUBE_COMPOSE_DRAFT)
234  {
235    // get drafted headers
236    if ($header=='to' && !empty($MESSAGE->headers->to))
237      $fvalue = $MESSAGE->get_header('to');
238
239    if ($header=='cc' && !empty($MESSAGE->headers->cc))
240      $fvalue = $MESSAGE->get_header('cc');
241
242    if ($header=='bcc' && !empty($MESSAGE->headers->bcc))
243      $fvalue = $MESSAGE->get_header('bcc');
244  }
245
246       
247  if ($fname && $field_type)
248  {
249    // pass the following attributes to the form class
250    $field_attrib = array('name' => $fname, 'spellcheck' => 'false');
251    foreach ($attrib as $attr => $value)
252      if (in_array($attr, $allow_attrib))
253        $field_attrib[$attr] = $value;
254
255    // create teaxtarea object
256    $input = new $field_type($field_attrib);
257    $out = $input->show($fvalue);
258  }
259 
260  if ($form_start)
261    $out = $form_start.$out;
262
263  return $out; 
264}
265
266
267
268function rcmail_compose_header_from($attrib)
269{
270  global $IMAP, $MESSAGE, $DB, $USER, $OUTPUT, $compose_mode;
271   
272  // pass the following attributes to the form class
273  $field_attrib = array('name' => '_from');
274  foreach ($attrib as $attr => $value)
275    if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex')))
276      $field_attrib[$attr] = $value;
277
278  // extract all recipients of the reply-message
279  $a_recipients = array();
280  if ($compose_mode == RCUBE_COMPOSE_REPLY && is_object($MESSAGE->headers))
281  {
282    $MESSAGE->compose_from = array();
283
284    $a_to = $IMAP->decode_address_list($MESSAGE->headers->to);
285    foreach ($a_to as $addr)
286    {
287      if (!empty($addr['mailto']))
288        $a_recipients[] = rc_strtolower($addr['mailto']);
289    }
290
291    if (!empty($MESSAGE->headers->cc))
292    {
293      $a_cc = $IMAP->decode_address_list($MESSAGE->headers->cc);
294      foreach ($a_cc as $addr)
295      {
296        if (!empty($addr['mailto']))
297          $a_recipients[] = rc_strtolower($addr['mailto']);
298      }
299    }
300  }
301
302  // get this user's identities
303  $sql_result = $USER->list_identities();
304
305  if ($DB->num_rows($sql_result))
306  {
307    $from_id = 0;
308    $a_signatures = array();
309
310    $field_attrib['onchange'] = JS_OBJECT_NAME.".change_identity(this)";
311    $select_from = new html_select($field_attrib);
312
313    while ($sql_arr = $DB->fetch_assoc($sql_result))
314    {
315      $identity_id = $sql_arr['identity_id'];
316      $select_from->add(format_email_recipient($sql_arr['email'], $sql_arr['name']), $identity_id);
317
318      // add signature to array
319      if (!empty($sql_arr['signature']))
320      {
321        $a_signatures[$identity_id]['text'] = $sql_arr['signature'];
322        $a_signatures[$identity_id]['is_html'] = ($sql_arr['html_signature'] == 1) ? true : false;
323        if ($a_signatures[$identity_id]['is_html'])
324        {
325            $h2t = new html2text($a_signatures[$identity_id]['text'], false, false);
326            $plainTextPart = $h2t->get_text();
327            $a_signatures[$identity_id]['plain_text'] = trim(html_entity_decode($plainTextPart, ENT_NOQUOTES, 'UTF-8'));
328        }
329      }
330
331      if ($compose_mode == RCUBE_COMPOSE_REPLY && is_array($MESSAGE->compose_from))
332        $MESSAGE->compose_from[] = $sql_arr['email'];
333
334      if (empty($_POST['_from']))
335      {
336        // set draft's identity
337        if ($compose_mode == RCUBE_COMPOSE_DRAFT && strstr($MESSAGE->headers->from, $sql_arr['email']))
338          $from_id = $sql_arr['identity_id'];
339        // set identity if it's one of the reply-message recipients (with prio for default identity)
340        else if (in_array(rc_strtolower($sql_arr['email']), $a_recipients) && (empty($from_id) || $sql_arr['standard']))
341          $from_id = $sql_arr['identity_id'];
342      }
343    }
344
345    // overwrite identity selection with post parameter
346    if (!empty($_POST['_from']))
347      $from_id = get_input_value('_from', RCUBE_INPUT_POST);
348
349    $out = $select_from->show($from_id);
350
351    // add signatures to client
352    $OUTPUT->set_env('signatures', $a_signatures);
353  }
354  else
355  {
356    $input_from = new html_inputfield($field_attrib);
357    $out = $input_from->show($_POST['_from']);
358  }
359 
360  if ($form_start)
361    $out = $form_start.$out;
362
363  return $out;
364}
365
366
367function rcmail_compose_body($attrib)
368{
369  global $RCMAIL, $CONFIG, $OUTPUT, $MESSAGE, $compose_mode;
370 
371  list($form_start, $form_end) = get_form_tags($attrib);
372  unset($attrib['form']);
373 
374  if (empty($attrib['id']))
375    $attrib['id'] = 'rcmComposeMessage';
376
377  $attrib['name'] = '_message';
378
379  if ($CONFIG['htmleditor'])
380    $isHtml = true;
381  else
382    $isHtml = false;
383
384  $body = '';
385
386  // use posted message body
387  if (!empty($_POST['_message']))
388  {
389    $body = get_input_value('_message', RCUBE_INPUT_POST, true);
390  }
391  else if ($compose_mode)
392  {
393    if ($isHtml && $MESSAGE->has_html_part())
394    {
395      $body = $MESSAGE->first_html_part();
396      $isHtml = true;
397    }
398    else
399    {
400      $body = $MESSAGE->first_text_part();
401      $isHtml = false;
402    }
403   
404    // compose reply-body
405    if ($compose_mode == RCUBE_COMPOSE_REPLY)
406      $body = rcmail_create_reply_body($body, $isHtml);
407    // forward message body inline
408    else if ($compose_mode == RCUBE_COMPOSE_FORWARD)
409      $body = rcmail_create_forward_body($body, $isHtml);
410    // load draft message body
411    else if ($compose_mode == RCUBE_COMPOSE_DRAFT)
412      $body = rcmail_create_draft_body($body, $isHtml);
413
414    if ($isHtml) {
415      // replace cid with href in inline images links
416      foreach ((array)$_SESSION['compose']['attachments'] as $pid => $attachment) {
417        if ($attachment['content_id']) {
418          $body = str_replace('cid:'. $attachment['content_id'],
419            $OUTPUT->app->comm_path.'&_action=display-attachment&_file=rcmfile'.$pid, $body);
420        }
421      }
422    }
423  }
424  else if (!empty($_SESSION['compose']['param']['_body']))
425  {
426    $body = $_SESSION['compose']['param']['_body'];
427  }
428
429  rcube_html_editor();
430
431  $out = $form_start ? "$form_start\n" : '';
432
433  $saveid = new html_hiddenfield(array('name' => '_draft_saveid', 'value' => $compose_mode==RCUBE_COMPOSE_DRAFT ? str_replace(array('<','>'), "", $MESSAGE->headers->messageID) : ''));
434  $out .= $saveid->show();
435
436  $drafttoggle = new html_hiddenfield(array('name' => '_draft', 'value' => 'yes'));
437  $out .= $drafttoggle->show();
438
439  $msgtype = new html_hiddenfield(array('name' => '_is_html', 'value' => ($isHtml?"1":"0")));
440  $out .= $msgtype->show();
441
442  // If desired, set this textarea to be editable by TinyMCE
443  if ($isHtml) $attrib['class'] = 'mce_editor';
444  $textarea = new html_textarea($attrib);
445  $out .= $textarea->show($body);
446  $out .= $form_end ? "\n$form_end" : '';
447
448  // include GoogieSpell
449  if (!empty($CONFIG['enable_spellcheck'])) {
450    $spellcheck_langs = (array)$RCMAIL->config->get('spellcheck_languages', array('da'=>'Dansk', 'de'=>'Deutsch', 'en' => 'English', 'es'=>'Español', 'fr'=>'Français', 'it'=>'Italiano', 'nl'=>'Nederlands', 'pl'=>'Polski', 'pt'=>'Português', 'fi'=>'Suomi', 'sv'=>'Svenska'));
451    if (!$spellcheck_langs[$lang])
452      $lang = 'en';
453   
454    $editor_lang_set = array();
455    foreach ($spellcheck_langs as $key => $name) {
456      $editor_lang_set[] = ($key == $lang ? '+' : '') . JQ($name).'='.JQ($key);
457    }
458   
459    $OUTPUT->include_script('googiespell.js');
460    $OUTPUT->add_script(sprintf(
461      "var googie = new GoogieSpell('\$__skin_path/images/googiespell/','%s&_action=spell&lang=');\n".
462      "googie.lang_chck_spell = \"%s\";\n".
463      "googie.lang_rsm_edt = \"%s\";\n".
464      "googie.lang_close = \"%s\";\n".
465      "googie.lang_revert = \"%s\";\n".
466      "googie.lang_no_error_found = \"%s\";\n".
467      "googie.setLanguages(%s);\n".
468      "googie.setCurrentLanguage('%s');\n".
469      "googie.decorateTextarea('%s');\n".
470      "%s.set_env('spellcheck', googie);",
471      $RCMAIL->comm_path,
472      JQ(Q(rcube_label('checkspelling'))),
473      JQ(Q(rcube_label('resumeediting'))),
474      JQ(Q(rcube_label('close'))),
475      JQ(Q(rcube_label('revertto'))),
476      JQ(Q(rcube_label('nospellerrors'))),
477      json_serialize($spellcheck_langs),
478      $lang,
479      $attrib['id'],
480      JS_OBJECT_NAME), 'foot');
481
482    $OUTPUT->add_label('checking');
483    $OUTPUT->set_env('spellcheck_langs', join(',', $editor_lang_set));
484  }
485 
486  $out .= "\n".'<iframe name="savetarget" src="program/blank.gif" style="width:0;height:0;border:none;visibility:hidden;"></iframe>';
487
488  return $out;
489}
490
491
492function rcmail_create_reply_body($body, $bodyIsHtml)
493{
494  global $IMAP, $MESSAGE, $OUTPUT;
495
496  if (! $bodyIsHtml)
497  {
498    // try to remove the signature
499    if (($sp = strrpos($body, '-- ')) !== false && ($sp == 0 || $body{$sp-1} == "\n"))
500      {
501      if ($body{$sp+3}==' ' || $body{$sp+3}=="\n" || $body{$sp+3}=="\r")
502        $body = substr($body, 0, max(0, $sp-1));
503      }
504
505    // soft-wrap message first
506    $body = rcmail_wrap_quoted($body, 75);
507
508    $body = rtrim($body, "\r\n");
509
510    if ($body) {
511      // split body into single lines
512      $a_lines = preg_split('/\r?\n/', $body);
513
514      // add > to each line
515      for($n=0; $n<sizeof($a_lines); $n++) {
516        if (strpos($a_lines[$n], '>')===0)
517          $a_lines[$n] = '>'.$a_lines[$n];
518        else
519          $a_lines[$n] = '> '.$a_lines[$n];
520        }
521 
522      $body = join("\n", $a_lines);
523      }
524
525    // add title line(s)
526    $prefix = wordwrap(sprintf("On %s, %s wrote:\n",
527      $MESSAGE->headers->date,
528      $MESSAGE->get_header('from')), 76);
529
530    $suffix = '';
531  }
532  else
533  {
534    $prefix = sprintf("On %s, %s wrote:<br />\n",
535      $MESSAGE->headers->date,
536      htmlspecialchars(Q($MESSAGE->get_header('from'), 'replace'), ENT_COMPAT, $OUTPUT->get_charset()));
537    $prefix .= '<blockquote type="cite" style="padding-left:5px; border-left:#1010ff 2px solid; margin-left:5px; width:100%">';
538    $suffix = "</blockquote>";
539
540    rcmail_write_inline_attachments($MESSAGE);
541  }
542
543  return $prefix.$body.$suffix;
544}
545
546
547function rcmail_create_forward_body($body, $bodyIsHtml)
548{
549  global $IMAP, $MESSAGE, $OUTPUT;
550
551  if (!$bodyIsHtml)
552  {
553    $prefix = "\n\n\n-------- Original Message --------\n";
554    $prefix .= 'Subject: ' . $MESSAGE->subject . "\n";
555    $prefix .= 'Date: ' . $MESSAGE->headers->date . "\n";
556    $prefix .= 'From: ' . $MESSAGE->get_header('from') . "\n";
557    $prefix .= 'To: ' . $MESSAGE->get_header('to') . "\n";
558    if ($MESSAGE->headers->replyto && $MESSAGE->headers->replyto != $MESSAGE->headers->from)
559      $prefix .= 'Reply-To: ' . $MESSAGE->get_header('replyto') . "\n";
560    $prefix .= "\n";
561  }
562  else
563  {
564    $prefix = sprintf(
565      "<br><br>-------- Original Message --------" .
566        "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody>" .
567        "<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">Subject: </th><td>%s</td></tr>" .
568        "<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">Date: </th><td>%s</td></tr>" .
569        "<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">From: </th><td>%s</td></tr>" .
570        "<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">To: </th><td>%s</td></tr>",
571      Q($MESSAGE->subject),
572      Q($MESSAGE->headers->date),
573      htmlspecialchars(Q($MESSAGE->get_header('from'), 'replace'), ENT_COMPAT, $OUTPUT->get_charset(), true),
574        htmlspecialchars(Q($MESSAGE->get_header('to'), 'replace'), ENT_COMPAT, $OUTPUT->get_charset(), true));
575
576    if ($MESSAGE->headers->replyto && $MESSAGE->headers->replyto != $MESSAGE->headers->from)
577      $prefix .= sprintf("<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">Reply-To: </th><td>%s</td></tr>",
578        htmlspecialchars(Q($MESSAGE->get_header('replyto'), 'replace'), ENT_COMPAT, $OUTPUT->get_charset(), true));
579
580    $prefix .= "</tbody></table><br>";
581  }
582
583  // add attachments
584  if (!isset($_SESSION['compose']['forward_attachments']) && is_array($MESSAGE->mime_parts))
585    rcmail_write_compose_attachments($MESSAGE, $bodyIsHtml);
586   
587  return $prefix.$body;
588}
589
590
591function rcmail_create_draft_body($body, $bodyIsHtml)
592{
593  global $MESSAGE;
594 
595  /**
596   * add attachments
597   * sizeof($MESSAGE->mime_parts can be 1 - e.g. attachment, but no text!
598   */
599  if (!isset($_SESSION['compose']['forward_attachments'])
600      && is_array($MESSAGE->mime_parts)
601      && count($MESSAGE->mime_parts) > 0)
602    rcmail_write_compose_attachments($MESSAGE, $bodyIsHtml);
603
604  return $body;
605}
606 
607 
608function rcmail_write_compose_attachments(&$message, $bodyIsHtml)
609{
610  foreach ((array)$message->mime_parts as $pid => $part)
611  {
612    if (($part->ctype_primary != 'message' || !$bodyIsHtml) &&
613        ($part->disposition=='attachment' || $part->disposition=='inline' || $part->headers['content-id']
614        || (empty($part->disposition) && $part->filename)))
615    {
616      if ($attachment = rcmail_save_attachment($message, $pid))
617        $_SESSION['compose']['attachments'][] = $attachment;
618    }
619  }
620       
621  $_SESSION['compose']['forward_attachments'] = true;
622}
623
624
625function rcmail_write_inline_attachments(&$message)
626{
627  foreach ((array)$message->mime_parts as $pid => $part)
628  {
629    if ($part->content_id && $part->filename)
630    {
631      if ($attachment = rcmail_save_attachment($message, $pid))
632        $_SESSION['compose']['attachments'][] = $attachment;
633    }
634  }
635}
636
637function rcmail_save_attachment(&$message, $pid)
638{
639  global $RCMAIL;
640
641  $temp_dir = unslashify($RCMAIL->config->get('temp_dir'));
642  $tmp_path = tempnam($temp_dir, 'rcmAttmnt');
643  $part = $message->mime_parts[$pid];
644 
645  if ($fp = fopen($tmp_path, 'w'))
646  {
647    $message->get_part_content($pid, $fp);
648    fclose($fp);
649
650    return array(
651        'mimetype' => $part->ctype_primary . '/' . $part->ctype_secondary,
652        'name' => $part->filename,
653        'path' => $tmp_path,
654        'content_id' => $part->content_id
655    );
656  }
657}
658
659
660function rcmail_compose_subject($attrib)
661{
662  global $MESSAGE, $compose_mode;
663 
664  list($form_start, $form_end) = get_form_tags($attrib);
665  unset($attrib['form']);
666 
667  $attrib['name'] = '_subject';
668  $attrib['spellcheck'] = 'true';
669  $textfield = new html_inputfield($attrib);
670
671  $subject = '';
672
673  // use subject from post
674  if (isset($_POST['_subject'])) {
675    $subject = get_input_value('_subject', RCUBE_INPUT_POST, TRUE);
676  }
677  // create a reply-subject
678  else if ($compose_mode == RCUBE_COMPOSE_REPLY) {
679    if (eregi('^re:', $MESSAGE->subject))
680      $subject = $MESSAGE->subject;
681    else
682      $subject = 'Re: '.$MESSAGE->subject;
683  }
684  // create a forward-subject
685  else if ($compose_mode == RCUBE_COMPOSE_FORWARD) {
686    if (eregi('^fwd:', $MESSAGE->subject))
687      $subject = $MESSAGE->subject;
688    else
689      $subject = 'Fwd: '.$MESSAGE->subject;
690  }
691  // creeate a draft-subject
692  else if ($compose_mode == RCUBE_COMPOSE_DRAFT) {
693    $subject = $MESSAGE->subject;
694  }
695  else if (!empty($_SESSION['compose']['param']['_subject'])) {
696    $subject = $_SESSION['compose']['param']['_subject'];
697  }
698 
699  $out = $form_start ? "$form_start\n" : '';
700  $out .= $textfield->show($subject);
701  $out .= $form_end ? "\n$form_end" : '';
702         
703  return $out;
704}
705
706
707function rcmail_compose_attachment_list($attrib)
708{
709  global $OUTPUT, $CONFIG;
710 
711  // add ID if not given
712  if (!$attrib['id'])
713    $attrib['id'] = 'rcmAttachmentList';
714 
715  $out = "\n";
716 
717  if (is_array($_SESSION['compose']['attachments']))
718  {
719    if ($attrib['deleteicon'])
720      $button = html::img(array(
721        'src' => $CONFIG['skin_path'] . $attrib['deleteicon'],
722        'alt' => rcube_label('delete'),
723        'style' => "padding-right:2px;vertical-align:middle"));
724    else
725      $button = Q(rcube_label('delete'));
726
727    foreach ($_SESSION['compose']['attachments'] as $id => $a_prop)
728    {
729      if (empty($a_prop))
730        continue;
731     
732      $out .= html::tag('li', array('id' => "rcmfile".$id),
733        html::a(array(
734            'href' => "#delete",
735            'title' => rcube_label('delete'),
736            'onclick' => sprintf("return %s.command('remove-attachment','rcmfile%d', this)", JS_OBJECT_NAME, $id)),
737          $button) . Q($a_prop['name']));
738    }
739  }
740
741  $OUTPUT->add_gui_object('attachmentlist', $attrib['id']);
742   
743  return html::tag('ul', $attrib, $out, html::$common_attrib);
744}
745
746
747function rcmail_compose_attachment_form($attrib)
748{
749  global $OUTPUT;
750
751  // add ID if not given
752  if (!$attrib['id'])
753    $attrib['id'] = 'rcmUploadbox';
754 
755  $button = new html_inputfield(array('type' => 'button', 'class' => 'button'));
756 
757  $out = html::div($attrib,
758    $OUTPUT->form_tag(array('name' => 'form', 'method' => 'post', 'enctype' => 'multipart/form-data'),
759      html::div(null, rcmail_compose_attachment_field(array())) .
760      html::div('hint', rcube_label(array('name' => 'maxuploadsize', 'vars' => array('size' => show_bytes(parse_bytes(ini_get('upload_max_filesize'))))))) .
761      html::div('buttons',
762        $button->show(rcube_label('close'), array('onclick' => "document.getElementById('$attrib[id]').style.visibility='hidden'")) . ' ' .
763        $button->show(rcube_label('upload'), array('onclick' => JS_OBJECT_NAME . ".command('send-attachment', this.form)"))
764      )
765    )
766  );
767 
768  $OUTPUT->add_gui_object('uploadbox', $attrib['id']);
769  return $out;
770}
771
772
773function rcmail_compose_attachment_field($attrib)
774{
775  $attrib['type'] = 'file';
776  $attrib['name'] = '_attachments[]';
777  $field = new html_inputfield($attrib);
778  return $field->show();
779}
780
781
782function rcmail_priority_selector($attrib)
783{
784  global $MESSAGE;
785 
786  list($form_start, $form_end) = get_form_tags($attrib);
787  unset($attrib['form']);
788 
789  $attrib['name'] = '_priority';
790  $selector = new html_select($attrib);
791
792  $selector->add(array(rcube_label('lowest'),
793                       rcube_label('low'),
794                       rcube_label('normal'),
795                       rcube_label('high'),
796                       rcube_label('highest')),
797                 array(5, 4, 0, 2, 1));
798                 
799  $sel = isset($_POST['_priority']) ? $_POST['_priority'] : intval($MESSAGE->headers->priority);
800
801  $out = $form_start ? "$form_start\n" : '';
802  $out .= $selector->show($sel);
803  $out .= $form_end ? "\n$form_end" : '';
804         
805  return $out;
806}
807
808
809function rcmail_receipt_checkbox($attrib)
810{
811  global $MESSAGE, $compose_mode;
812 
813  list($form_start, $form_end) = get_form_tags($attrib);
814  unset($attrib['form']);
815 
816  if (!isset($attrib['id']))
817    $attrib['id'] = 'receipt'; 
818
819  $attrib['name'] = '_receipt';
820  $attrib['value'] = '1';
821  $checkbox = new html_checkbox($attrib);
822
823  $out = $form_start ? "$form_start\n" : '';
824  $out .= $checkbox->show(
825    $compose_mode == RCUBE_COMPOSE_DRAFT && $MESSAGE->headers->mdn_to ? 1 : 0);
826  $out .= $form_end ? "\n$form_end" : '';
827
828  return $out;
829}
830
831
832function rcmail_editor_selector($attrib)
833{
834  global $CONFIG, $MESSAGE, $compose_mode;
835
836  $choices = array(
837    'html'  => 'htmltoggle',
838    'plain' => 'plaintoggle'
839  );
840
841  // determine whether HTML or plain text should be checked
842  $useHtml = $CONFIG['htmleditor'] ? true : false;
843
844  if ($compose_mode)
845    $useHtml = ($useHtml && $MESSAGE->has_html_part());
846
847  $editorid = empty($attrib['editorid']) ? 'rcmComposeMessage' : $attrib['editorid'];
848
849  $selector = '';
850  $chosenvalue = $useHtml ? 'html' : 'plain';
851  $radio = new html_radiobutton(array('name' => '_editorSelect',
852    'onclick' => "return rcmail_toggle_editor(this.value=='html', '$editorid', '_is_html')"));
853
854  foreach ($choices as $value => $text)
855  {
856    $attrib['id'] = '_' . $value;
857    $attrib['value'] = $value;
858    $selector .= $radio->show($chosenvalue, $attrib) . html::label($attrib['id'], Q(rcube_label($text)));
859  }
860
861  return $selector;
862}
863
864
865function rcmail_store_target_selection($attrib)
866{
867  $attrib['name'] = '_store_target';
868  $select = rcmail_mailbox_select(array_merge($attrib, array('noselection' => '- '.rcube_label('dontsave').' -')));
869  return $select->show(rcmail::get_instance()->config->get('sent_mbox'), $attrib);
870}
871
872
873function get_form_tags($attrib)
874{
875  global $RCMAIL, $MESSAGE_FORM;
876
877  $form_start = '';
878  if (!strlen($MESSAGE_FORM))
879  {
880    $hiddenfields = new html_hiddenfield(array('name' => '_task', 'value' => $RCMAIL->task));
881    $hiddenfields->add(array('name' => '_action', 'value' => 'send'));
882
883    $form_start = empty($attrib['form']) ? $RCMAIL->output->form_tag(array('name' => "form", 'method' => "post")) : '';
884    $form_start .= $hiddenfields->show();
885  }
886   
887  $form_end = (strlen($MESSAGE_FORM) && !strlen($attrib['form'])) ? '</form>' : '';
888  $form_name = !empty($attrib['form']) ? $attrib['form'] : 'form';
889 
890  if (!strlen($MESSAGE_FORM))
891    $RCMAIL->output->add_gui_object('messageform', $form_name);
892 
893  $MESSAGE_FORM = $form_name;
894
895  return array($form_start, $form_end);
896}
897
898
899// register UI objects
900$OUTPUT->add_handlers(array(
901  'composeheaders' => 'rcmail_compose_headers',
902  'composesubject' => 'rcmail_compose_subject',
903  'composebody' => 'rcmail_compose_body',
904  'composeattachmentlist' => 'rcmail_compose_attachment_list',
905  'composeattachmentform' => 'rcmail_compose_attachment_form',
906  'composeattachment' => 'rcmail_compose_attachment_field',
907  'priorityselector' => 'rcmail_priority_selector',
908  'editorselector' => 'rcmail_editor_selector',
909  'receiptcheckbox' => 'rcmail_receipt_checkbox',
910  'storetarget' => 'rcmail_store_target_selection',
911));
912
913/****** get contacts for this user and add them to client scripts ********/
914
915$CONTACTS = new rcube_contacts($DB, $USER->ID);
916$CONTACTS->set_pagesize(1000);
917
918$a_contacts = array();
919                                   
920if ($result = $CONTACTS->list_records())
921  {
922  while ($sql_arr = $result->iterate())
923    if ($sql_arr['email'])
924      $a_contacts[] = format_email_recipient($sql_arr['email'], $sql_arr['name']);
925  }
926if (!empty($CONFIG['ldap_public']) && is_array($CONFIG['ldap_public']))
927  {
928  /* LDAP autocompletion */
929  foreach ($CONFIG['ldap_public'] as $ldapserv_config)
930    {
931    if ($ldapserv_config['fuzzy_search'] != 1 ||
932        $ldapserv_config['global_search'] != 1)
933      {
934      continue;
935      }
936         
937    $LDAP = new rcube_ldap($ldapserv_config);
938    $LDAP->connect();
939    $LDAP->set_pagesize(1000);
940 
941    $results = $LDAP->search($ldapserv_config['mail_field'], "");
942 
943    for ($i = 0; $i < $results->count; $i++)
944          {
945          if ($results->records[$i]['email'] != '')
946            {
947            $email = $results->records[$i]['email'];
948            $name = $results->records[$i]['name'];
949                 
950            $a_contacts[] = format_email_recipient($email, $name);
951            }
952          }
953    $LDAP->close();
954    }
955  }
956if ($a_contacts)
957  {
958        $OUTPUT->set_env('contacts', $a_contacts);
959  }
960
961$OUTPUT->send('compose');
962
963?>
Note: See TracBrowser for help on using the repository browser.