thomascube
2006-01-13 be2380fb47b05a222ec5b22deff36d5156a8c943
commit | author | age
4e17e6 1 <?php
T 2
3 /*
4  +-----------------------------------------------------------------------+
5  | program/steps/mail/compose.inc                                        |
6  |                                                                       |
7  | This file is part of the RoundCube Webmail client                     |
8  | Copyright (C) 2005, RoundCube Dev. - Switzerland                      |
30233b 9  | Licensed under the GNU GPL                                            |
4e17e6 10  |                                                                       |
T 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
23 require_once('Mail/mimeDecode.php');
24
25
26 $MESSAGE_FORM = NULL;
27 $REPLY_MESSAGE = NULL;
28 $FORWARD_MESSAGE = NULL;
29
30
31 if (!is_array($_SESSION['compose']))
32   $_SESSION['compose'] = array('id' => uniqid(rand()));
33
34
10a699 35 // add some labels to client
977a29 36 rcube_add_label('nosubject', 'norecipientwarning', 'nosubjectwarning', 'nobodywarning', 'sendingmessage', 'notsentwarning');
10a699 37
T 38
4e17e6 39 if ($_GET['_reply_uid'] || $_GET['_forward_uid'])
T 40   {
41   $msg_uid = $_GET['_reply_uid'] ? $_GET['_reply_uid'] : $_GET['_forward_uid'];
42
43   // similar as in program/steps/mail/show.inc
44   $MESSAGE = array();
45   $MESSAGE['headers'] = $IMAP->get_headers($msg_uid);
46   
47   $MESSAGE['source'] = rcmail_message_source($msg_uid);
48   
49   $mmd = new Mail_mimeDecode($MESSAGE['source']);
50   $MESSAGE['structure'] = $mmd->decode(array('include_bodies' => TRUE,
51                                              'decode_headers' => TRUE,
52                                              'decode_bodies' => FALSE));
583f1c 53
4e17e6 54   $MESSAGE['subject'] = $IMAP->decode_header($MESSAGE['headers']->subject);
T 55   $MESSAGE['parts'] = $mmd->getMimeNumbers($MESSAGE['structure']);
56   
57   if ($_GET['_reply_uid'])
58     {
583f1c 59     $REPLY_MESSAGE = &$MESSAGE;
4e17e6 60     $_SESSION['compose']['reply_uid'] = $_GET['_reply_uid'];
T 61     $_SESSION['compose']['reply_msgid'] = $REPLY_MESSAGE['headers']->messageID;
583f1c 62
T 63     if ($_GET['_all'])
64       $REPLY_MESSAGE['reply_all'] = 1;
4e17e6 65     }
T 66   else
67     {
68     $FORWARD_MESSAGE = $MESSAGE;
69     $_SESSION['compose']['forward_uid'] = $_GET['_forward_uid'];
70     }
71   }
72
73
74
75 /****** compose mode functions ********/
76
77
78 function rcmail_compose_headers($attrib)
79   {
80   global $IMAP, $REPLY_MESSAGE, $DB;
583f1c 81   static $sa_recipients = array();
4e17e6 82
T 83   list($form_start, $form_end) = get_form_tags($attrib);
84   
85   $out = '';
86   $part = strtolower($attrib['part']);
87   
88   switch ($part)
89     {
90     case 'from':
1cded8 91       return rcmail_compose_header_from($attrib);
4e17e6 92
T 93     case 'to':
94       $fname = '_to';
95       $header = 'to';
1cded8 96
4e17e6 97       // we have contact id's as get parameters
1cded8 98       if (!empty($_GET['_to']) && preg_match('/^([0-9]+,?)+$/', $_GET['_to']))
4e17e6 99         {
T 100         $a_recipients = array();
d7cb77 101         $sql_result = $DB->query("SELECT name, email
1cded8 102                                   FROM ".get_table_name('contacts')."
T 103                                   WHERE user_id=?
104                                   AND    del<>1
d7cb77 105                                   AND    contact_id IN (".$_GET['_to'].")",
S 106                                   $_SESSION['user_id']);
4e17e6 107                                          
T 108         while ($sql_arr = $DB->fetch_assoc($sql_result))
109           $a_recipients[] = format_email_recipient($sql_arr['email'], $sql_arr['name']);
110           
111         if (sizeof($a_recipients))
112           $fvalue = join(', ', $a_recipients);
113         }
597170 114       else if (!empty($_GET['_to']))
4e17e6 115         $fvalue = $_GET['_to'];
T 116         
117     case 'cc':
118       if (!$fname)
119         {
120         $fname = '_cc';
583f1c 121         $header = 'cc';
4e17e6 122         }
T 123     case 'bcc':
124       if (!$fname)
125         $fname = '_bcc';
126         
317219 127       $allow_attrib = array('id', 'class', 'style', 'cols', 'rows', 'wrap', 'tabindex');
4e17e6 128       $field_type = 'textarea';            
T 129       break;
130
131     case 'replyto':
132     case 'reply-to':
133       $fname = '_replyto';
317219 134       $allow_attrib = array('id', 'class', 'style', 'size', 'tabindex');
4e17e6 135       $field_type = 'textfield';
T 136       break;
137     
138     }
583f1c 139
4e17e6 140     
597170 141   if ($fname && !empty($_POST[$fname]))
4e17e6 142     $fvalue = $_POST[$fname];
T 143   else if ($header && is_object($REPLY_MESSAGE['headers']))
144     {
145     // get recipent address(es) out of the message headers
146     if ($header=='to' && $REPLY_MESSAGE['headers']->replyto)
147       $fvalue = $IMAP->decode_header($REPLY_MESSAGE['headers']->replyto);
148     else if ($header=='to' && $REPLY_MESSAGE['headers']->from)
149       $fvalue = $IMAP->decode_header($REPLY_MESSAGE['headers']->from);
583f1c 150     // add recipent of original message if reply to all
T 151     else if ($header=='cc' && $REPLY_MESSAGE['reply_all'])
152       {
153       if ($IMAP->decode_header($REPLY_MESSAGE['headers']->to))
154         $fvalue .= $IMAP->decode_header($REPLY_MESSAGE['headers']->to);
155
156       if ($IMAP->decode_header($REPLY_MESSAGE['headers']->cc))
157         {
158         if($fvalue)
159           $fvalue .= ', ';
160
161         $fvalue .= $IMAP->decode_header($REPLY_MESSAGE['headers']->cc);
162         }
163       }
164
4e17e6 165     // split recipients and put them back together in a unique way
583f1c 166     if (!empty($fvalue))
T 167       {
168       $to_addresses = $IMAP->decode_address_list($fvalue);
169       $fvalue = '';
170       foreach ($to_addresses as $addr_part)
171         {
172         if (!in_array($addr_part['mailto'], $sa_recipients))
173           {
174           $fvalue .= (strlen($fvalue) ? ', ':'').$addr_part['string'];
175           $sa_recipients[] = $addr_part['mailto'];
176           }
177         }
178       }
4e17e6 179     }
583f1c 180
4e17e6 181         
T 182   if ($fname && $field_type)
183     {
184     // pass the following attributes to the form class
185     $field_attrib = array('name' => $fname);
186     foreach ($attrib as $attr => $value)
187       if (in_array($attr, $allow_attrib))
188         $field_attrib[$attr] = $value;
189
190     // create teaxtarea object
191     $input = new $field_type($field_attrib);
192     $out = $input->show($fvalue);    
193     }
194   
195   if ($form_start)
196     $out = $form_start.$out;
197   
198   return $out;  
199   }
200
201
1cded8 202
T 203 function rcmail_compose_header_from($attrib)
4e17e6 204   {
1cded8 205   global $IMAP, $REPLY_MESSAGE, $DB, $OUTPUT, $JS_OBJECT_NAME;
T 206     
207   // pass the following attributes to the form class
208   $field_attrib = array('name' => '_from');
209   foreach ($attrib as $attr => $value)
210     if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex')))
211       $field_attrib[$attr] = $value;
4e17e6 212
1cded8 213   // extract all recipients of the reply-message
T 214   $a_recipients = array();
215   if ($REPLY_MESSAGE && is_object($REPLY_MESSAGE['headers']))
216     {
217     $a_to = $IMAP->decode_address_list($REPLY_MESSAGE['headers']->to);        
218     foreach ($a_to as $addr)
219       {
220       if (!empty($addr['mailto']))
221         $a_recipients[] = $addr['mailto'];
222       }
4e17e6 223
1cded8 224     if (!empty($REPLY_MESSAGE['headers']->cc))
T 225       {
226       $a_cc = $IMAP->decode_address_list($REPLY_MESSAGE['headers']->cc);
227       foreach ($a_cc as $addr)
228         {
229         if (!empty($addr['mailto']))
230           $a_recipients[] = $addr['mailto'];
231         }
232       }
233     }
4e17e6 234
1cded8 235   // get this user's identities
T 236   $sql_result = $DB->query("SELECT identity_id, name, email, signature
237                             FROM   ".get_table_name('identities')."
238                             WHERE user_id=?
239                             AND    del<>1
240                             ORDER BY ".$DB->quoteIdentifier('standard')." DESC, name ASC",
241                            $_SESSION['user_id']);
242                                    
243   if ($DB->num_rows($sql_result))
244     {
245     $from_id = 0;
246     $a_signatures = array();
247     
248     $field_attrib['onchange'] = "$JS_OBJECT_NAME.change_identity(this)";
249     $select_from = new select($field_attrib);
250     
251     while ($sql_arr = $DB->fetch_assoc($sql_result))
252       {
253       $select_from->add(format_email_recipient($sql_arr['email'], $sql_arr['name']), $sql_arr['identity_id']);
4e17e6 254
1cded8 255       // add signature to array
T 256       if (!empty($sql_arr['signature']))
257         $a_signatures[$sql_arr['identity_id']] = $sql_arr['signature'];
258       
259       // set identity if it's one of the reply-message recipients
260       if (in_array($sql_arr['email'], $a_recipients))
261         $from_id = $sql_arr['identity_id'];
262       }
4e17e6 263
1cded8 264     // overwrite identity selection with post parameter
T 265     if (isset($_POST['_from']))
266       $from_id = $_POST['_from'];
4e17e6 267
1cded8 268     $out = $select_from->show($from_id);
T 269     
4e17e6 270
1cded8 271     // add signatures to client
T 272     $OUTPUT->add_script(sprintf("%s.set_env('signatures', %s);", $JS_OBJECT_NAME, array2js($a_signatures)));  
273     }
274   else
275     {
276     $input_from = new textfield($field_attrib);
277     $out = $input_from->show($_POST['_from']);
278     }
279     
280   if ($form_start)
281     $out = $form_start.$out;
4e17e6 282
1cded8 283   return $out;
4e17e6 284   }
T 285
1cded8 286   
4e17e6 287
T 288 function rcmail_compose_body($attrib)
289   {
290   global $CONFIG, $REPLY_MESSAGE, $FORWARD_MESSAGE;
291   
292   list($form_start, $form_end) = get_form_tags($attrib);
293   unset($attrib['form']);
294   
295   $attrib['name'] = '_message';
296   $textarea = new textarea($attrib);
297
298   $body = '';
299   
300   // use posted message body
597170 301   if (!empty($_POST['_message']))
30233b 302     $body = stripslashes($_POST['_message']);
4e17e6 303     
T 304   // compose reply-body
305   else if (is_array($REPLY_MESSAGE['parts']))
306     {
307     $body = rcmail_first_text_part($REPLY_MESSAGE['parts']);
308     if (strlen($body))
309       $body = rcmail_create_reply_body($body);
310     }
311
312   // forward message body inline
313   else if (is_array($FORWARD_MESSAGE['parts']))
314     {
315     $body = rcmail_first_text_part($FORWARD_MESSAGE['parts']);
316     if (strlen($body))
317       $body = rcmail_create_forward_body($body);
318     }
319   
320   $out = $form_start ? "$form_start\n" : '';
321   $out .= $textarea->show($body);
322   $out .= $form_end ? "\n$form_end" : '';
323          
324   return $out;
325   }
326
327
328 function rcmail_create_reply_body($body)
329   {
330   global $IMAP, $REPLY_MESSAGE;
331
332   // soft-wrap message first
333   $body = wordwrap($body, 75);
334   
335   // split body into single lines
336   $a_lines = preg_split('/\r?\n/', $body);
337   
338   // add > to each line
339   for($n=0; $n<sizeof($a_lines); $n++)
340     {
341     if (strpos($a_lines[$n], '>')===0)
342       $a_lines[$n] = '>'.$a_lines[$n];
343     else
344       $a_lines[$n] = '> '.$a_lines[$n];
345     }
346  
347   $body = join("\n", $a_lines);
348
349   // add title line
350   $pefix = sprintf("\n\n\nOn %s, %s wrote:\n",
351            $REPLY_MESSAGE['headers']->date,
352            $IMAP->decode_header($REPLY_MESSAGE['headers']->from));
1cded8 353            
T 354
355   // try to remove the signature
749b07 356   if ($sp = strrpos($body, '-- '))
1cded8 357     {
T 358     if ($body{$sp+3}==' ' || $body{$sp+3}=="\n" || $body{$sp+3}=="\r")
359       $body = substr($body, 0, $sp-1);
360     }
4e17e6 361
T 362   return $pefix.$body;
363   }
364
365
366 function rcmail_create_forward_body($body)
367   {
368   global $IMAP, $FORWARD_MESSAGE;
369
370   // soft-wrap message first
371   $body = wordwrap($body, 80);
372   
373   $prefix = sprintf("\n\n\n-------- Original Message --------\nSubject: %s\nDate: %s\nFrom: %s\nTo: %s\n\n",
374                    $FORWARD_MESSAGE['subject'],
375                    $FORWARD_MESSAGE['headers']->date,
376                    $IMAP->decode_header($FORWARD_MESSAGE['headers']->from),
377                    $IMAP->decode_header($FORWARD_MESSAGE['headers']->to));
378
597170 379   // add attachments
T 380   if (!isset($_SESSION['compose']['forward_attachments']) && is_array($FORWARD_MESSAGE['parts']) && sizeof($FORWARD_MESSAGE['parts'])>1)
381     {
382     $temp_dir = rcmail_create_compose_tempdir();
383
384     if (!is_array($_SESSION['compose']['attachments']))
385       $_SESSION['compose']['attachments'] = array();
386   
387     foreach ($FORWARD_MESSAGE['parts'] as $part)
388       {
389       if ($part->disposition != 'attachment')
390         continue;
391
392       $tmp_path = tempnam($temp_dir, 'rcmAttmnt');
393       if ($fp = fopen($tmp_path, 'w'))
394         {
395         fwrite($fp, $IMAP->mime_decode($part->body, $part->headers['content-transfer-encoding']));
396         fclose($fp);
397
398         $_SESSION['compose']['attachments'][] = array('name' => $part->d_parameters['filename'],
399                                                       'mimetype' => $part->ctype_primary . '/' . $part->ctype_secondary,
400                                                       'path' => $tmp_path);
401         }
402       }
403
404     $_SESSION['compose']['forward_attachments'] = TRUE;
405     }
406
4e17e6 407   return $prefix.$body;
T 408   }
409
410
411
412 function rcmail_compose_subject($attrib)
413   {
414   global $CONFIG, $REPLY_MESSAGE, $FORWARD_MESSAGE;
415   
416   list($form_start, $form_end) = get_form_tags($attrib);
417   unset($attrib['form']);
418   
419   $attrib['name'] = '_subject';
420   $textfield = new textfield($attrib);
421
422   $subject = '';
423
424   // use subject from post
597170 425   if (isset($_POST['_subject']))
30233b 426     $subject = stripslashes($_POST['_subject']);
4e17e6 427     
T 428   // create a reply-subject
429   else if (isset($REPLY_MESSAGE['subject']))
520c36 430     {
09941e 431     if (eregi('^re:', $REPLY_MESSAGE['subject']))
520c36 432       $subject = $REPLY_MESSAGE['subject'];
T 433     else
434       $subject = 'Re: '.$REPLY_MESSAGE['subject'];
435     }
4e17e6 436
T 437   // create a forward-subject
438   else if (isset($FORWARD_MESSAGE['subject']))
09941e 439     {
T 440     if (eregi('^fwd:', $REPLY_MESSAGE['subject']))
441       $subject = $FORWARD_MESSAGE['subject'];
442     else
443       $subject = 'Fwd: '.$FORWARD_MESSAGE['subject'];
444     }
4e17e6 445
T 446   
447   $out = $form_start ? "$form_start\n" : '';
448   $out .= $textfield->show($subject);
449   $out .= $form_end ? "\n$form_end" : '';
450          
451   return $out;
452   }
453
454
455 function rcmail_compose_attachment_list($attrib)
456   {
457   global $OUTPUT, $JS_OBJECT_NAME;
458   
459   // add ID if not given
460   if (!$attrib['id'])
461     $attrib['id'] = 'rcmAttachmentList';
462   
463   // allow the following attributes to be added to the <ul> tag
464   $attrib_str = create_attrib_string($attrib, array('id', 'class', 'style'));
465  
466   $out = '<ul'. $attrib_str . ">\n";
467   
468   if (is_array($_SESSION['compose']['attachments']))
469     {
470     foreach ($_SESSION['compose']['attachments'] as $i => $a_prop)
471       $out .= sprintf("<li>%s</li>\n", $a_prop['name']);
472     }
473
474   $OUTPUT->add_script(sprintf("%s.gui_object('attachmentlist', '%s');", $JS_OBJECT_NAME, $attrib['id']));  
475     
476   $out .= '</ul>';
477   return $out;
478   }
479
480
481
482 function rcmail_compose_attachment_form($attrib)
483   {
484   global $OUTPUT, $JS_OBJECT_NAME, $SESS_HIDDEN_FIELD;
485
486   // add ID if not given
487   if (!$attrib['id'])
488     $attrib['id'] = 'rcmUploadbox';
489   
490   // allow the following attributes to be added to the <div> tag
491   $attrib_str = create_attrib_string($attrib, array('id', 'class', 'style'));
492   $input_field = rcmail_compose_attachment_field(array());
493   $label_send = rcube_label('upload');
494   $label_close = rcube_label('close');
495   
496   $out = <<<EOF
497 <div$attrib_str>
498 <form action="./" method="post" enctype="multipart/form-data">
499 $SESS_HIDDEN_FIELD
500 $input_field<br />
501 <input type="button" value="$label_close" class="button" onclick="document.getElementById('$attrib[id]').style.visibility='hidden'" />
502 <input type="button" value="$label_send" class="button" onclick="$JS_OBJECT_NAME.command('send-attachment', this.form)" />
503 </form>
504 </div>
505 EOF;
506
507   
508   $OUTPUT->add_script(sprintf("%s.gui_object('uploadbox', '%s');", $JS_OBJECT_NAME, $attrib['id']));  
509   return $out;
510   }
511
512
513 function rcmail_compose_attachment_field($attrib)
514   {
515   // allow the following attributes to be added to the <input> tag
516   $attrib_str = create_attrib_string($attrib, array('id', 'class', 'style', 'size'));
517  
518   $out = '<input type="file" name="_attachments[]"'. $attrib_str . " />";
519   return $out;
520   }
521
522
523 function rcmail_priority_selector($attrib)
524   {
525   list($form_start, $form_end) = get_form_tags($attrib);
526   unset($attrib['form']);
527   
528   $attrib['name'] = '_priority';
529   $selector = new select($attrib);
530
531   $selector->add(array(rcube_label('lowest'),
532                        rcube_label('low'),
533                        rcube_label('normal'),
534                        rcube_label('high'),
535                        rcube_label('highest')),
7902df 536                  array(5, 4, 0, 2, 1));
4e17e6 537                  
597170 538   $sel = isset($_POST['_priority']) ? $_POST['_priority'] : 0;
4e17e6 539
T 540   $out = $form_start ? "$form_start\n" : '';
541   $out .= $selector->show($sel);
542   $out .= $form_end ? "\n$form_end" : '';
543          
544   return $out;
545   }
546
547
548 function get_form_tags($attrib)
549   {
550   global $CONFIG, $OUTPUT, $JS_OBJECT_NAME, $MESSAGE_FORM, $SESS_HIDDEN_FIELD;  
551
552   $form_start = '';
553   if (!strlen($MESSAGE_FORM))
554     {
555     $hiddenfields = new hiddenfield(array('name' => '_task', 'value' => $GLOBALS['_task']));
556     $hiddenfields->add(array('name' => '_action', 'value' => 'send'));
557     
597170 558     $form_start = empty($attrib['form']) ? '<form name="form" action="./" method="post">' : '';
4e17e6 559     $form_start .= "\n$SESS_HIDDEN_FIELD\n";
T 560     $form_start .= $hiddenfields->show();
561     }
562     
563   $form_end = (strlen($MESSAGE_FORM) && !strlen($attrib['form'])) ? '</form>' : '';
597170 564   $form_name = !empty($attrib['form']) ? $attrib['form'] : 'form';
4e17e6 565   
T 566   if (!strlen($MESSAGE_FORM))
567     $OUTPUT->add_script("$JS_OBJECT_NAME.gui_object('messageform', '$form_name');");
568   
569   $MESSAGE_FORM = $form_name;
570
571   return array($form_start, $form_end);  
572   }
573
574
575 function format_email_recipient($email, $name='')
576   {
577   if ($name && $name != $email)
578     return sprintf('%s <%s>', strpos($name, ",") ? '"'.$name.'"' : $name, $email);
579   else
580     return $email;
581   }
582
583
fd8c50 584 function rcmail_charset_pulldown($selected='ISO-8859-1')
T 585   {
586   $select = new select();
587   
588   
589   return $select->show($selected);
590   }
591
592
4e17e6 593 /****** get contacts for this user and add them to client scripts ********/
T 594
d7cb77 595 $sql_result = $DB->query("SELECT name, email
S 596                           FROM ".get_table_name('contacts')." WHERE  user_id=?
1cded8 597                           AND  del<>1",$_SESSION['user_id']);
4e17e6 598                                    
T 599 if ($DB->num_rows($sql_result))
600   {        
601   $a_contacts = array();
602   while ($sql_arr = $DB->fetch_assoc($sql_result))
603     if ($sql_arr['email'])
604       $a_contacts[] = format_email_recipient($sql_arr['email'], rep_specialchars_output($sql_arr['name'], 'js'));
605   
606   $OUTPUT->add_script(sprintf("$JS_OBJECT_NAME.set_env('contacts', %s);", array2js($a_contacts)));
607   }
608
609
610
611
612 parse_template('compose');
613 ?>