source: subversion/trunk/roundcubemail/program/steps/mail/compose.inc @ 1747

Last change on this file since 1747 was 1747, checked in by thomasb, 5 years ago

Correctly handle options in mailto-links (#1485228)

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