source: github/program/steps/mail/compose.inc @ 7902df4

HEADcourier-fixdev-browser-capabilitiespdorelease-0.6release-0.7release-0.8
Last change on this file since 7902df4 was 7902df4, checked in by thomascube <thomas@…>, 8 years ago

Fixed SSL support; improved Courier compatibility; some visual enhancements and bugfixes

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