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