public function create_identity($p)
 {
     $rcmail = rcmail::get_instance();
     // prefs are set in create_user()
     if ($this->prefs) {
         if ($this->prefs['full_name']) {
             $p['record']['name'] = $this->prefs['full_name'];
         }
         if (($this->identities_level == 0 || $this->identities_level == 2) && $this->prefs['email_address']) {
             $p['record']['email'] = $this->prefs['email_address'];
         }
         if ($this->prefs['___signature___']) {
             $p['record']['signature'] = $this->prefs['___signature___'];
         }
         if ($this->prefs['reply_to']) {
             $p['record']['reply-to'] = $this->prefs['reply_to'];
         }
         if (($this->identities_level == 0 || $this->identities_level == 1) && isset($this->prefs['identities']) && $this->prefs['identities'] > 1) {
             for ($i = 1; $i < $this->prefs['identities']; $i++) {
                 unset($ident_data);
                 $ident_data = array('name' => '', 'email' => '');
                 // required data
                 if ($this->prefs['full_name' . $i]) {
                     $ident_data['name'] = $this->prefs['full_name' . $i];
                 }
                 if ($this->identities_level == 0 && $this->prefs['email_address' . $i]) {
                     $ident_data['email'] = $this->prefs['email_address' . $i];
                 } else {
                     $ident_data['email'] = $p['record']['email'];
                 }
                 if ($this->prefs['reply_to' . $i]) {
                     $ident_data['reply-to'] = $this->prefs['reply_to' . $i];
                 }
                 if ($this->prefs['___sig' . $i . '___']) {
                     $ident_data['signature'] = $this->prefs['___sig' . $i . '___'];
                 }
                 // insert identity
                 $identid = $rcmail->user->insert_identity($ident_data);
             }
         }
         // copy address book
         $contacts = $rcmail->get_address_book(null, true);
         if ($contacts && count($this->abook)) {
             foreach ($this->abook as $rec) {
                 // #1487096 handle multi-address and/or too long items
                 $rec['email'] = array_shift(explode(';', $rec['email']));
                 if (check_email(rcube_idn_to_ascii($rec['email']))) {
                     $rec['email'] = rcube_idn_to_utf8($rec['email']);
                     $contacts->insert($rec, true);
                 }
             }
         }
         // mark identity as complete for following hooks
         $p['complete'] = true;
     }
     return $p;
 }
Esempio n. 2
0
 /**
  * Callback function when HTML page is rendered
  * We'll add an overlay box here.
  */
 function render_page($p)
 {
     if ($_SESSION['plugin.newuserdialog'] && $p['template'] == 'mail') {
         $this->add_texts('localization');
         $rcmail = rcmail::get_instance();
         $identity = $rcmail->user->get_identity();
         $identities_level = intval($rcmail->config->get('identities_level', 0));
         // compose user-identity dialog
         $table = new html_table(array('cols' => 2));
         $table->add('title', $this->gettext('name'));
         $table->add(null, html::tag('input', array('type' => 'text', 'name' => '_name', 'value' => $identity['name'])));
         $table->add('title', $this->gettext('email'));
         $table->add(null, html::tag('input', array('type' => 'text', 'name' => '_email', 'value' => rcube_idn_to_utf8($identity['email']), 'disabled' => $identities_level == 1 || $identities_level == 3)));
         $table->add('title', $this->gettext('organization'));
         $table->add(null, html::tag('input', array('type' => 'text', 'name' => '_organization', 'value' => $identity['organization'])));
         $table->add('title', $this->gettext('signature'));
         $table->add(null, html::tag('textarea', array('name' => '_signature', 'rows' => '3'), $identity['signature']));
         // add overlay input box to html page
         $rcmail->output->add_footer(html::div(array('id' => 'newuseroverlay'), html::tag('form', array('action' => $rcmail->url('plugin.newusersave'), 'method' => 'post'), html::tag('h3', null, Q($this->gettext('identitydialogtitle'))) . html::p('hint', Q($this->gettext('identitydialoghint'))) . $table->show() . html::p(array('class' => 'formbuttons'), html::tag('input', array('type' => 'submit', 'class' => 'button mainaction', 'value' => $this->gettext('save')))))));
         // disable keyboard events for messages list (#1486726)
         $rcmail->output->add_script("rcmail.message_list.key_press = function(){};\n         rcmail.message_list.key_down = function(){};\n         \$('input[name=_name]').focus();\n        ", 'docready');
         $this->include_stylesheet('newuserdialog.css');
     }
 }
Esempio n. 3
0
 function save($curpass, $passwd)
 {
     $rcmail = rcmail::get_instance();
     if (!($sql = $rcmail->config->get('password_query'))) {
         $sql = 'SELECT update_passwd(%c, %u)';
     }
     if ($dsn = $rcmail->config->get('password_db_dsn')) {
         // #1486067: enable new_link option
         if (is_array($dsn) && empty($dsn['new_link'])) {
             $dsn['new_link'] = true;
         } else {
             if (!is_array($dsn) && !preg_match('/\\?new_link=true/', $dsn)) {
                 $dsn .= '?new_link=true';
             }
         }
         $db = rcube_db::factory($dsn, '', false);
         $db->set_debug((bool) $rcmail->config->get('sql_debug'));
         $db->db_connect('w');
     } else {
         $db = $rcmail->get_dbh();
     }
     if ($err = $db->is_error()) {
         return PASSWORD_ERROR;
     }
     // crypted password
     if (strpos($sql, '%c') !== FALSE) {
         $salt = '';
         if (!($crypt_hash = $rcmail->config->get('password_crypt_hash'))) {
             if (CRYPT_MD5) {
                 $crypt_hash = 'md5';
             } else {
                 if (CRYPT_STD_DES) {
                     $crypt_hash = 'des';
                 }
             }
         }
         switch ($crypt_hash) {
             case 'md5':
                 $len = 8;
                 $salt_hashindicator = '$1$';
                 break;
             case 'des':
                 $len = 2;
                 break;
             case 'blowfish':
                 $len = 22;
                 $salt_hashindicator = '$2a$';
                 break;
             case 'sha256':
                 $len = 16;
                 $salt_hashindicator = '$5$';
                 break;
             case 'sha512':
                 $len = 16;
                 $salt_hashindicator = '$6$';
                 break;
             default:
                 return PASSWORD_CRYPT_ERROR;
         }
         //Restrict the character set used as salt (#1488136)
         $seedchars = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
         for ($i = 0; $i < $len; $i++) {
             $salt .= $seedchars[rand(0, 63)];
         }
         $sql = str_replace('%c', $db->quote(crypt($passwd, $salt_hashindicator ? $salt_hashindicator . $salt . '$' : $salt)), $sql);
     }
     // dovecotpw
     if (strpos($sql, '%D') !== FALSE) {
         if (!($dovecotpw = $rcmail->config->get('password_dovecotpw'))) {
             $dovecotpw = 'dovecotpw';
         }
         if (!($method = $rcmail->config->get('password_dovecotpw_method'))) {
             $method = 'CRAM-MD5';
         }
         // use common temp dir
         $tmp_dir = $rcmail->config->get('temp_dir');
         $tmpfile = tempnam($tmp_dir, 'roundcube-');
         $pipe = popen("{$dovecotpw} -s '{$method}' > '{$tmpfile}'", "w");
         if (!$pipe) {
             unlink($tmpfile);
             return PASSWORD_CRYPT_ERROR;
         } else {
             fwrite($pipe, $passwd . "\n", 1 + strlen($passwd));
             usleep(1000);
             fwrite($pipe, $passwd . "\n", 1 + strlen($passwd));
             pclose($pipe);
             $newpass = trim(file_get_contents($tmpfile), "\n");
             if (!preg_match('/^\\{' . $method . '\\}/', $newpass)) {
                 return PASSWORD_CRYPT_ERROR;
             }
             if (!$rcmail->config->get('password_dovecotpw_with_method')) {
                 $newpass = trim(str_replace('{' . $method . '}', '', $newpass));
             }
             unlink($tmpfile);
         }
         $sql = str_replace('%D', $db->quote($newpass), $sql);
     }
     // hashed passwords
     if (preg_match('/%[n|q]/', $sql)) {
         if (!extension_loaded('hash')) {
             raise_error(array('code' => 600, 'type' => 'php', 'file' => __FILE__, 'line' => __LINE__, 'message' => "Password plugin: 'hash' extension not loaded!"), true, false);
             return PASSWORD_ERROR;
         }
         if (!($hash_algo = strtolower($rcmail->config->get('password_hash_algorithm')))) {
             $hash_algo = 'sha1';
         }
         $hash_passwd = hash($hash_algo, $passwd);
         $hash_curpass = hash($hash_algo, $curpass);
         if ($rcmail->config->get('password_hash_base64')) {
             $hash_passwd = base64_encode(pack('H*', $hash_passwd));
             $hash_curpass = base64_encode(pack('H*', $hash_curpass));
         }
         $sql = str_replace('%n', $db->quote($hash_passwd, 'text'), $sql);
         $sql = str_replace('%q', $db->quote($hash_curpass, 'text'), $sql);
     }
     // Handle clear text passwords securely (#1487034)
     $sql_vars = array();
     if (preg_match_all('/%[p|o]/', $sql, $m)) {
         foreach ($m[0] as $var) {
             if ($var == '%p') {
                 $sql = preg_replace('/%p/', '?', $sql, 1);
                 $sql_vars[] = (string) $passwd;
             } else {
                 // %o
                 $sql = preg_replace('/%o/', '?', $sql, 1);
                 $sql_vars[] = (string) $curpass;
             }
         }
     }
     $local_part = $rcmail->user->get_username('local');
     $domain_part = $rcmail->user->get_username('domain');
     $username = $_SESSION['username'];
     $host = $_SESSION['imap_host'];
     // convert domains to/from punnycode
     if ($rcmail->config->get('password_idn_ascii')) {
         $domain_part = rcube_idn_to_ascii($domain_part);
         $username = rcube_idn_to_ascii($username);
         $host = rcube_idn_to_ascii($host);
     } else {
         $domain_part = rcube_idn_to_utf8($domain_part);
         $username = rcube_idn_to_utf8($username);
         $host = rcube_idn_to_utf8($host);
     }
     // at least we should always have the local part
     $sql = str_replace('%l', $db->quote($local_part, 'text'), $sql);
     $sql = str_replace('%d', $db->quote($domain_part, 'text'), $sql);
     $sql = str_replace('%u', $db->quote($username, 'text'), $sql);
     $sql = str_replace('%h', $db->quote($host, 'text'), $sql);
     $res = $db->query($sql, $sql_vars);
     if (!$db->is_error()) {
         if (strtolower(substr(trim($sql), 0, 6)) == 'select') {
             if ($result = $db->fetch_array($res)) {
                 return PASSWORD_SUCCESS;
             }
         } else {
             // This is the good case: 1 row updated
             if ($db->affected_rows($res) == 1) {
                 return PASSWORD_SUCCESS;
             }
             // @TODO: Some queries don't affect any rows
             // Should we assume a success if there was no error?
         }
     }
     return PASSWORD_ERROR;
 }
Esempio n. 4
0
 /**
  * GUI object 'username'
  * Showing IMAP username of the current session
  *
  * @param array Named tag parameters (currently not used)
  * @return string HTML code for the gui object
  */
 public function current_username($attrib)
 {
     static $username;
     // alread fetched
     if (!empty($username)) {
         return $username;
     }
     // Current username is an e-mail address
     if (strpos($_SESSION['username'], '@')) {
         $username = $_SESSION['username'];
     } else {
         if ($sql_arr = $this->app->user->get_identity()) {
             $username = $sql_arr['email'];
         } else {
             $username = $this->app->user->get_username();
         }
     }
     return rcube_idn_to_utf8($username);
 }
Esempio n. 5
0
 /**
  * Handler for POST request to import an event attached to a mail message
  */
 public function mail_import_event()
 {
     $uid = get_input_value('_uid', RCUBE_INPUT_POST);
     $mbox = get_input_value('_mbox', RCUBE_INPUT_POST);
     $mime_id = get_input_value('_part', RCUBE_INPUT_POST);
     $status = get_input_value('_status', RCUBE_INPUT_POST);
     $delete = intval(get_input_value('_del', RCUBE_INPUT_POST));
     $charset = RCMAIL_CHARSET;
     // establish imap connection
     $imap = $this->rc->get_storage();
     $imap->set_mailbox($mbox);
     if ($uid && $mime_id) {
         list($mime_id, $index) = explode(':', $mime_id);
         $part = $imap->get_message_part($uid, $mime_id);
         if ($part->ctype_parameters['charset']) {
             $charset = $part->ctype_parameters['charset'];
         }
         $headers = $imap->get_message_headers($uid);
     }
     $events = $this->get_ical()->import($part, $charset);
     $error_msg = $this->gettext('errorimportingevent');
     $success = false;
     // successfully parsed events?
     if (!empty($events) && ($event = $events[$index])) {
         // find writeable calendar to store event
         $cal_id = !empty($_REQUEST['_calendar']) ? get_input_value('_calendar', RCUBE_INPUT_POST) : null;
         $calendar = null;
         if (!$cal_id) {
             $calendar = $this->get_default_calendar(true);
             $cal_id = $calendar['id'];
         }
         if ($cal_id < 0) {
             foreach ($this->get_calendars() as $cal_id => $calendar) {
                 $cal_id = $calendar['id'];
                 $driver = $this->get_driver_by_cal($cal_id);
                 $old_event = $driver->get_event($events[0]['uid']);
                 if (is_array($old_event)) {
                     $cal_id = $old_event['calendar'];
                     break;
                 }
             }
         }
         // Begin mod by Rosali (try to find the corresponding calendar)
         if (is_numeric($cal_id)) {
             $driver = $this->get_driver_by_cal($cal_id);
         } else {
             $error_msg = $this->gettext('nowritecalendarfound');
             $this->rc->output->command('display_message', $error_msg, 'error');
             $this->rc->output->send();
             return false;
         }
         // End mod by Rosali
         // Begin mod by Rosali (handle tasks)
         $create_method = 'new_event';
         $edit_method = 'edit_event';
         $get_method = 'get_event';
         // End mod by Rosali
         if (!$calendar) {
             $calendars = $driver->list_calendars(false, true);
             $calendar = $calendars[$cal_id] ?: $this->get_default_calendar(true);
         }
         // Begin mod by Rosali (handle tasks)
         if ($event['_type'] == 'task') {
             //database or caldav?
             $class_name = get_class($driver);
             $create_method = 'create_task';
             $edit_method = 'edit_task';
             $get_method = 'get_task';
             require_once INSTALL_PATH . 'plugins/libgpl/tasklist/drivers/tasklist_driver.php';
             if ($class_name == 'database_driver') {
                 require_once INSTALL_PATH . 'plugins/libgpl/tasklist/drivers/database/tasklist_database_driver.php';
                 $driver = new tasklist_database_driver($this);
             } else {
                 if ($class_name == 'caldav_driver') {
                     require_once INSTALL_PATH . 'plugins/libgpl/tasklist/drivers/caldav/tasklist_caldav_driver.php';
                     $driver = new tasklist_caldav_driver($this);
                 } else {
                     $error_msg = $this->gettext('errorimportingtask');
                     $this->rc->output->command('display_message', $error_msg, 'error');
                     $this->rc->output->send();
                 }
             }
         }
         // update my attendee status according to submitted method
         if (!empty($status) && $event['_type'] == 'event') {
             // End by Rosali (no iTip support for tasks yet)
             $organizer = null;
             $emails = $this->get_user_emails();
             foreach ($event['attendees'] as $i => $attendee) {
                 if ($attendee['role'] == 'ORGANIZER') {
                     $organizer = $attendee;
                 } else {
                     if ($attendee['email'] && in_array(strtolower($attendee['email']), $emails)) {
                         $event['attendees'][$i]['status'] = strtoupper($status);
                         $reply_sender = $attendee['email'];
                     }
                 }
             }
         }
         // save to calendar
         if ($calendar && !$calendar['readonly']) {
             $event['calendar'] = $calendar['id'];
             // check for existing event with the same UID
             $existing = $driver->{$get_method}($event['uid'], true, false, true);
             // Begin mod by Rosali (no iTip support for tasks yet)
             if ($event['_type'] == 'task') {
                 if ($existing) {
                     $event['id'] = $existing['id'];
                     $event['list'] = $event['calendar'];
                     $existing['list'] = $event['calendar'];
                     $existing_modified = $existing['changed']->format('U');
                     $event_modified = $event['changed']->format('U');
                     if ($existing_modified >= $event_modified) {
                         $message = 'newerversionexists';
                         $msgtype = 'error';
                     } else {
                         if ($event['start']) {
                             $event['startdate'] = $event['start']->format('Y-m-d');
                             $event['starttime'] = $event['start']->format('H:i:s');
                         }
                         if ($event['due']) {
                             $event['date'] = $event['due']->format('Y-m-d');
                             $event['time'] = $event['due']->format('H:i:s');
                         }
                         if ($success = $driver->{$edit_method}($event, $existing)) {
                             $message = 'importedsuccessfully';
                             $msgtype = 'confirmation';
                         } else {
                             $message = $error_msg;
                             $msgtype = 'error';
                         }
                     }
                 } else {
                     $event['list'] = $event['calendar'];
                     if ($event['start']) {
                         $event['startdate'] = $event['start']->format('Y-m-d');
                         $event['starttime'] = $event['start']->format('H:i:s');
                     }
                     if ($event['due']) {
                         $event['date'] = $event['due']->format('Y-m-d');
                         $event['time'] = $event['due']->format('H:i:s');
                     }
                     if ($success = $driver->{$create_method}($event)) {
                         $message = 'importedsuccessfully';
                         $msgtype = 'confirmation';
                     } else {
                         $message = $error_msg;
                         $msgtype = 'error';
                     }
                 }
                 $this->rc->output->command('display_message', $this->gettext(array('name' => $message, 'vars' => array('calendar' => $calendar['name']))), $msgtype);
                 $this->rc->output->send();
             }
             // End mod by Rosali
             if ($existing) {
                 // Mod by Rosali (no iTip support for tasks yet)
                 // only update attendee status
                 if ($this->ical->method == 'REPLY') {
                     // try to identify the attendee using the email sender address
                     $sender = preg_match('/([a-z0-9][a-z0-9\\-\\.\\+\\_]*@[^&@"\'.][^@&"\']*\\.([^\\x00-\\x40\\x5b-\\x60\\x7b-\\x7f]{2,}|xn--[a-z0-9]{2,}))/', $headers->from, $m) ? $m[1] : '';
                     $sender_utf = rcube_idn_to_utf8($sender);
                     $existing_attendee = -1;
                     foreach ($existing['attendees'] as $i => $attendee) {
                         if ($sender && ($attendee['email'] == $sender || $attendee['email'] == $sender_utf)) {
                             $existing_attendee = $i;
                             break;
                         }
                     }
                     $event_attendee = null;
                     foreach ($event['attendees'] as $attendee) {
                         if ($sender && ($attendee['email'] == $sender || $attendee['email'] == $sender_utf)) {
                             $event_attendee = $attendee;
                             break;
                         }
                     }
                     // found matching attendee entry in both existing and new events
                     if ($existing_attendee >= 0 && $event_attendee) {
                         $existing['attendees'][$existing_attendee] = $event_attendee;
                         $success = $driver->edit_event($existing);
                     } else {
                         if ($event['changed'] >= $existing['changed'] && $event['attendees']) {
                             $existing['attendees'] = $event['attendees'];
                             $success = $driver->edit_event($existing);
                         } else {
                             $error_msg = $this->gettext('newerversionexists');
                         }
                     }
                 } else {
                     if ($status == 'declined' && $delete) {
                         $deleted = $driver->remove_event($existing, true);
                         $success = true;
                     } else {
                         if ($event['sequence'] >= $existing['sequence'] || $event['changed'] >= $existing['changed']) {
                             $event['id'] = $existing['id'];
                             $event['calendar'] = $existing['calendar'];
                             if ($status == 'declined') {
                                 // show me as free when declined (#1670)
                                 $event['free_busy'] = 'free';
                             }
                             $success = $driver->edit_event($event);
                         } else {
                             if (!empty($status)) {
                                 $existing['attendees'] = $event['attendees'];
                                 if ($status == 'declined') {
                                     // show me as free when declined (#1670)
                                     $existing['free_busy'] = 'free';
                                 }
                                 $success = $driver->edit_event($existing);
                             } else {
                                 $error_msg = $this->gettext('newerversionexists');
                             }
                         }
                     }
                 }
             } else {
                 if (!$existing && $status != 'declined') {
                     $success = $driver->{$create_method}($event);
                 } else {
                     if ($status == 'declined') {
                         $error_msg = null;
                     }
                 }
             }
         } else {
             if ($status == 'declined') {
                 $error_msg = null;
             } else {
                 $error_msg = $this->gettext('nowritecalendarfound');
             }
         }
     }
     if ($success) {
         $message = $this->ical->method == 'REPLY' ? 'attendeupdateesuccess' : ($deleted ? 'successremoval' : 'importedsuccessfully');
         $this->rc->output->command('display_message', $this->gettext(array('name' => $message, 'vars' => array('calendar' => $calendar['name']))), 'confirmation');
         $this->rc->output->command('plugin.fetch_event_rsvp_status', array('uid' => $event['uid'], 'changed' => is_object($event['changed']) ? $event['changed']->format('U') : 0, 'sequence' => intval($event['sequence']), 'fallback' => strtoupper($status)));
         $error_msg = null;
     } else {
         if ($error_msg) {
             $this->rc->output->command('display_message', $error_msg, 'error');
         }
     }
     // Begin mod by Rosali (make the event accessible by GUI)
     $this->rc->output->command('plugin.event_callback', array('task' => $this->rc->task, 'action' => $this->rc->action, 'evt' => $this->_client_event($event)));
     // End mod by Rosali
     // send iTip reply
     if ($this->ical->method == 'REQUEST' && $organizer && !in_array(strtolower($organizer['email']), $emails) && !$error_msg) {
         $itip = $this->load_itip();
         $itip->set_sender_email($reply_sender);
         if ($itip->send_itip_message($event, 'REPLY', $organizer, 'itipsubject' . $status, 'itipmailbody' . $status)) {
             $this->rc->output->command('display_message', $this->gettext(array('name' => 'sentresponseto', 'vars' => array('mailto' => $organizer['name'] ? $organizer['name'] : $organizer['email']))), 'confirmation');
         } else {
             $this->rc->output->command('display_message', $this->gettext('itipresponseerror'), 'error');
         }
     }
     $this->rc->output->send();
 }
Esempio n. 6
0
 /**
  * Handler for request action
  */
 function save_vcard()
 {
     $this->add_texts('localization', true);
     $uid = get_input_value('_uid', RCUBE_INPUT_POST);
     $mbox = get_input_value('_mbox', RCUBE_INPUT_POST);
     $mime_id = get_input_value('_part', RCUBE_INPUT_POST);
     $rcmail = rcmail::get_instance();
     $storage = $rcmail->get_storage();
     $storage->set_folder($mbox);
     if ($uid && $mime_id) {
         list($mime_id, $index) = explode(':', $mime_id);
         $part = $storage->get_message_part($uid, $mime_id, null, null, null, true);
     }
     $error_msg = $this->gettext('vcardsavefailed');
     if ($part && ($vcards = rcube_vcard::import($part)) && ($vcard = $vcards[$index]) && $vcard->displayname && $vcard->email) {
         $CONTACTS = $this->get_address_book();
         $email = $vcard->email[0];
         $contact = $vcard->get_assoc();
         $valid = true;
         // skip entries without an e-mail address or invalid
         if (empty($email) || !$CONTACTS->validate($contact, true)) {
             $valid = false;
         } else {
             // We're using UTF8 internally
             $email = rcube_idn_to_utf8($email);
             // compare e-mail address
             $existing = $CONTACTS->search('email', $email, 1, false);
             // compare display name
             if (!$existing->count && $vcard->displayname) {
                 $existing = $CONTACTS->search('name', $vcard->displayname, 1, false);
             }
             if ($existing->count) {
                 $rcmail->output->command('display_message', $this->gettext('contactexists'), 'warning');
                 $valid = false;
             }
         }
         if ($valid) {
             $plugin = $rcmail->plugins->exec_hook('contact_create', array('record' => $contact, 'source' => null));
             $contact = $plugin['record'];
             if (!$plugin['abort'] && $CONTACTS->insert($contact)) {
                 $rcmail->output->command('display_message', $this->gettext('addedsuccessfully'), 'confirmation');
             } else {
                 $rcmail->output->command('display_message', $error_msg, 'error');
             }
         }
     } else {
         $rcmail->output->command('display_message', $error_msg, 'error');
     }
     $rcmail->output->send();
 }
 /**
  * Helper function to build a Mail_mime object to send an iTip message
  *
  * @param array   Event object to send
  * @param string  iTip method (REQUEST|REPLY|CANCEL)
  * @return object Mail_mime object with message data
  */
 public function compose_itip_message($event, $method)
 {
     $from = rcube_idn_to_ascii($this->sender['email']);
     $from_utf = rcube_idn_to_utf8($from);
     $sender = format_email_recipient($from, $this->sender['name']);
     // truncate list attendees down to the recipient of the iTip Reply.
     // constraints for a METHOD:REPLY according to RFC 5546
     if ($method == 'REPLY') {
         $replying_attendee = null;
         $reply_attendees = array();
         foreach ($event['attendees'] as $attendee) {
             if ($attendee['role'] == 'ORGANIZER') {
                 $reply_attendees[] = $attendee;
             } else {
                 if (strcasecmp($attedee['email'], $from) == 0 || strcasecmp($attendee['email'], $from_utf) == 0) {
                     $replying_attendee = $attendee;
                 }
             }
         }
         if ($replying_attendee) {
             $reply_attendees[] = $replying_attendee;
             $event['attendees'] = $reply_attendees;
         }
     }
     // compose multipart message using PEAR:Mail_Mime
     $message = new Mail_mime("\r\n");
     $message->setParam('text_encoding', 'quoted-printable');
     $message->setParam('head_encoding', 'quoted-printable');
     $message->setParam('head_charset', RCMAIL_CHARSET);
     $message->setParam('text_charset', RCMAIL_CHARSET . ";\r\n format=flowed");
     $message->setContentType('multipart/alternative');
     // compose common headers array
     $headers = array('From' => $sender, 'Date' => $this->rc->user_date(), 'Message-ID' => $this->rc->gen_message_id(), 'X-Sender' => $from);
     if ($agent = $this->rc->config->get('useragent')) {
         $headers['User-Agent'] = $agent;
     }
     $message->headers($headers);
     // attach ics file for this event
     $ical = $this->cal->get_ical();
     $ics = $ical->export(array($event), $method, false, $method == 'REQUEST' ? array($this->cal->driver, 'get_attachment_body') : false);
     $message->addAttachment($ics, 'text/calendar', 'event.ics', false, '8bit', '', RCMAIL_CHARSET . "; method=" . $method);
     return $message;
 }