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