True, 'compose' => True, 'composeFromDraft' => True, 'getAttachment' => True, 'fileSelector' => True, 'forward' => True, 'composeAsNew' => True, 'composeAsForward'=> True, 'reply' => True, 'replyAll' => True, 'selectFolder' => True, ); var $destinations = array( 'to' => 'to', 'cc' => 'cc', 'bcc' => 'bcc', 'replyto' => 'replyto', 'folder' => 'folder' ); /** * Instance of bofelamimail * * @var bofelamimail */ var $bofelamimail; /** * Instance of bocompose * * @var bocompose */ var $bocompose; /** * Active preferences, reference to $this->bofelamimail->mailPreferences * * @var array */ var $mailPreferences; /** * Instance of Template class * * @var Template */ var $t; function uicompose() { $this->displayCharset = $GLOBALS['egw']->translation->charset(); if (!isset($_POST['composeid']) && !isset($_GET['composeid'])) { // create new compose session $this->bocompose = CreateObject('felamimail.bocompose','',$this->displayCharset); $this->composeID = $this->bocompose->getComposeID(); } else { // reuse existing compose session if (isset($_POST['composeid'])) $this->composeID = $_POST['composeid']; else $this->composeID = $_GET['composeid']; $this->bocompose = CreateObject('felamimail.bocompose',$this->composeID,$this->displayCharset); } $this->t = CreateObject('phpgwapi.Template',EGW_APP_TPL); $this->bofelamimail =& $this->bocompose->bofelamimail; $this->mailPreferences =& $this->bofelamimail->mailPreferences; $this->t->set_unknowns('remove'); $this->rowColor[0] = $GLOBALS['egw_info']["theme"]["bg01"]; $this->rowColor[1] = $GLOBALS['egw_info']["theme"]["bg02"]; } function unhtmlentities ($string) { $trans_tbl = get_html_translation_table (HTML_ENTITIES); $trans_tbl = array_flip ($trans_tbl); return strtr ($string, $trans_tbl); } function action() { $formData['identity'] = (int)$_POST['identity']; foreach((array)$_POST['destination'] as $key => $destination) { if(!empty($_POST['address'][$key])) { if($destination == 'folder') { $formData[$destination][] = $GLOBALS['egw']->translation->convert($_POST['address'][$key], $this->charset, 'UTF7-IMAP'); } else { $formData[$destination][] = $_POST['address'][$key]; } } } $formData['subject'] = $this->bocompose->stripSlashes($_POST['subject']); $formData['body'] = $this->bocompose->stripSlashes($_POST['body']); // if the body is empty, maybe someone pasted something with scripts, into the message body if(empty($formData['body'])) { // this is to be found with the egw_unset_vars array for the _POST['body'] array $name='_POST'; $key='body'; #error_log($GLOBALS['egw_unset_vars'][$name.'['.$key.']']); if (isset($GLOBALS['egw_unset_vars'][$name.'['.$key.']'])) { $formData['body'] = bocompose::_getCleanHTML( $GLOBALS['egw_unset_vars'][$name.'['.$key.']']); } } $formData['priority'] = $this->bocompose->stripSlashes($_POST['priority']); $formData['signatureID'] = (int)$_POST['signatureID']; $formData['stationeryID'] = $_POST['stationeryID']; $formData['mimeType'] = $this->bocompose->stripSlashes($_POST['mimeType']); if ($formData['mimeType'] == 'html' && html::htmlarea_availible()===false) { $formData['mimeType'] = 'plain'; $formData['body'] = $this->bocompose->convertHTMLToText($formData['body']); } $formData['disposition'] = (bool)$_POST['disposition']; $formData['to_infolog'] = $_POST['to_infolog']; $formData['to_tracker'] = $_POST['to_tracker']; //$formData['mailbox'] = $_GET['mailbox']; if((bool)$_POST['printit'] == true) { $formData['printit'] = 1; $formData['isDraft'] = 1; // pint the composed message. therefore save it as draft and reopen it as plain printwindow $formData['subject'] = "[".lang('printview').":]".$formData['subject']; $messageUid = $this->bocompose->saveAsDraft($formData,$destinationFolder); if (!$messageUid) { print ""; return; } $uidisplay = CreateObject('felamimail.uidisplay'); $uidisplay->printMessage($messageUid, $formData['printit'],$destinationFolder); //egw::link('/index.php',array('menuaction' => 'felamimail.uidisplay.printMessage','uid'=>$messageUid)); return; } if((bool)$_POST['saveAsDraft'] == true) { $formData['isDraft'] = 1; // save as draft $folder = ($this->mailPreferences->ic_server[$this->bofelamimail->profileID]->draftfolder ? $this->mailPreferences->ic_server[$this->bofelamimail->profileID]->draftfolder : $this->mailPreferences->preferences['draftFolder']); $this->bofelamimail->reopen($folder); $status = $this->bofelamimail->getFolderStatus($folder); //error_log(__METHOD__.__LINE__.array2string(array('Folder'=>$folder,'Status'=>$status))); $uidNext = $status['uidnext']; // we may need that, if the server does not return messageUIDs of saved/appended messages $messageUid = $this->bocompose->saveAsDraft($formData,$folder); // folder may change if (!$messageUid) { print ""; //try to reopen the mail from session data $this->compose('to',true); return; } // saving as draft, does not mean closing the message unset($_POST['composeid']); unset($_GET['composeid']); $uicompose = CreateObject('felamimail.uicompose'); $messageUid = ($messageUid===true ? $uidNext : $messageUid); if (!$uicompose->bofelamimail->icServer->_connected) $uicompose->bofelamimail->openConnection($uicompose->bofelamimail->profileID); if ($uicompose->bofelamimail->getMessageHeader($messageUid)) { //error_log(__METHOD__.__LINE__.' (re)open drafted message with new UID: '.$messageUid.' in folder:'.$folder); $uicompose->bocompose->getDraftData($uicompose->bofelamimail->icServer, $folder, $messageUid); $uicompose->compose('to',true); return; } } else { if(!$this->bocompose->send($formData)) { // print ""; $this->compose(); return; } } #common::egw_exit(); print ""; } function composeAsForward($_focusElement='to') { if (isset($_GET['forwardmails'])) { unset($_GET['forwardmails']); $replyID = $_GET['reply_id']; $replyIds = explode(',',$replyID); $icServer = $this->bofelamimail->profileID; $folder = (isset($_GET['folder'])?base64_decode($_GET['folder']):base64_decode($_GET['mailbox'])); //_debug_array(array('reply_id'=>$replyIds,'folder'=>$folder)); if (!empty($folder) && !empty($replyID) ) { // this fill the session data with the values from the original email $buff = $this->bocompose->preferencesArray['message_forwarding']; $this->bocompose->preferencesArray['message_forwarding'] = 'asmail'; foreach($replyIds as $key => $id) { $this->bocompose->getForwardData($icServer, $folder, $id,NULL); } $this->bocompose->preferencesArray['message_forwarding'] = $buff; } } $this->compose($_focusElement); } /** * function compose * this function is used to fill the compose dialog with the content provided by session data * * @var _focusElement varchar subject, to, body supported * @var suppressSigOnTop boolean * @var isReply boolean */ function compose($_focusElement='to',$suppressSigOnTop=false, $isReply=false) { // read the data from session // all values are empty for a new compose window $sessionData = $this->bocompose->getSessionData(); $alwaysAttachVCardAtCompose = false; // we use this to eliminate double attachments, if users VCard is already present/attached if ( isset($GLOBALS['egw_info']['apps']['stylite']) && (isset($this->bocompose->preferencesArray['attachVCardAtCompose']) && $this->bocompose->preferencesArray['attachVCardAtCompose'])) { $alwaysAttachVCardAtCompose = true; if (!is_array($_REQUEST['preset']['file']) && !empty($_REQUEST['preset']['file'])) { $f = $_REQUEST['preset']['file']; $_REQUEST['preset']['file'] = array($f); } $_REQUEST['preset']['file'][] = "vfs://default/apps/addressbook/".$GLOBALS['egw']->accounts->id2name($GLOBALS['egw_info']['user']['account_id'],'person_id')."/.entry"; } if (is_array($_REQUEST['preset'])) { //_debug_array($_REQUEST); if ($_REQUEST['preset']['mailto']) { // handle mailto strings such as // mailto:larry,dan?cc=mike&bcc=sue&subject=test&body=type+your&body=message+here // the above string may be htmlentyty encoded, then multiple body tags are supported // first, strip the mailto: string out of the mailto URL $tmp_send_to = trim(substr(html_entity_decode($_REQUEST['preset']['mailto']),7)); // check if there is more than the to address $mailtoArray = explode('?',$tmp_send_to,2); if ($mailtoArray[1]) { // check if there are more than one requests $addRequests = explode('&',$mailtoArray[1]); foreach ($addRequests as $key => $reqval) { // the additional requests should have a =, to separate key from value. $keyValuePair = explode('=',$reqval,2); $sessionData[$keyValuePair[0]] .= (strlen($sessionData[$keyValuePair[0]])>0 ? ' ':'') . $keyValuePair[1]; } } $sessionData['to']=$mailtoArray[0]; // if the mailto string is not htmlentity decoded the arguments are passed as simple requests foreach(array('cc','bcc','subject','body') as $name) { if ($_REQUEST[$name]) $sessionData[$name] .= (strlen($sessionData[$name])>0 ? ( $name == 'cc' || $name == 'bcc' ? ',' : ' ') : '') . $_REQUEST[$name]; } } if (isset($_REQUEST['preset']['file'])) { $names = (array)$_REQUEST['preset']['name']; $types = (array)$_REQUEST['preset']['type']; $files = (array)$_REQUEST['preset']['file']; foreach($files as $k => $path) { if (parse_url($path,PHP_URL_SCHEME == 'vfs')) { $type = egw_vfs::mime_content_type($path); // special handling for attaching vCard of iCal --> use their link-title as name if (substr($path,-7) != '/.entry' || !(list($app,$id) = array_slice(explode('/',$path),-3)) || !($name = egw_link::title($app, $id))) { $name = urldecode(egw_vfs::basename($path)); } else { $name .= '.'.mime_magic::mime2ext($type); } $formData = array( 'name' => $name, 'type' => $type, 'file' => $path, 'size' => filesize($path), ); if ($formData['type'] == egw_vfs::DIR_MIME_TYPE) continue; // ignore directories } elseif(is_readable($path)) { $formData = array( 'name' => isset($names[$k]) ? $names[$k] : basename($path), 'type' => isset($types[$k]) ? $types[$k] : (function_exists('mime_content_type') ? mime_content_type($path) : mime_magic::filename2mime($path)), 'file' => $path, 'size' => filesize($path), ); } else { continue; } $this->bocompose->addAttachment($formData,($alwaysAttachVCardAtCompose?true:false)); } $sessionData = $this->bocompose->getSessionData(); } foreach(array('to','cc','bcc','subject','body') as $name) { if ($_REQUEST['preset'][$name]) $sessionData[$name] = $_REQUEST['preset'][$name]; } } // is the to address set already? if (!empty($_REQUEST['send_to'])) { $sessionData['to'] = base64_decode($_REQUEST['send_to']); // first check if there is a questionmark or ampersand if (strpos($sessionData['to'],'?')!== false) list($sessionData['to'],$rest) = explode('?',$sessionData['to'],2); if (($at_pos = strpos($sessionData['to'],'@')) !== false) { if (($amp_pos = strpos(substr($sessionData['to'],$at_pos),'&')) !== false) { //list($email,$addoptions) = explode('&',$value,2); $email = substr($sessionData['to'],0,$amp_pos+$at_pos); $rest = substr($sessionData['to'], $amp_pos+$at_pos+1); //error_log(__METHOD__.__LINE__.$email.' '.$rest); $sessionData['to'] = $email; } } if (strpos($sessionData['to'],'%40')!== false) $sessionData['to'] = html::purify(str_replace('%40','@',$sessionData['to'])); $rarr = array(html::purify($rest)); if (isset($rest)&&!empty($rest) && strpos($rest,'&')!== false) $rarr = explode('&',$rest); //error_log(__METHOD__.__LINE__.$sessionData['to'].'->'.array2string($rarr)); $karr = array(); foreach ($rarr as $ri => $rval) { //must contain = if (strpos($rval,'=')!== false) { $k = $v = ''; list($k,$v) = explode('=',$rval,2); $karr[$k] = $v; } } //error_log(__METHOD__.__LINE__.$sessionData['to'].'->'.array2string($karr)); foreach(array('cc','bcc','subject','body') as $name) { if ($karr[$name]) $sessionData[$name] = $karr[$name]; } if (!empty($_REQUEST['subject'])) $sessionData['subject'] = html::purify(trim(html_entity_decode($_REQUEST['subject']))); } //is the MimeType set/requested if (!empty($_REQUEST['mimeType'])) { $sessionData['mimeType'] = $_REQUEST['mimeType']; } else { // try to enforce a mimeType on reply ( if type is not of the wanted type ) if ($isReply) { if (!empty($this->bocompose->preferencesArray['replyOptions']) && $this->bocompose->preferencesArray['replyOptions']=="text" && $sessionData['mimeType'] == 'html') { $sessionData['mimeType'] = 'plain'; $sessionData['body'] = $this->bocompose->convertHTMLToText(str_replace(array("\n\r","\n"),' ',$sessionData['body'])); } if (!empty($this->bocompose->preferencesArray['replyOptions']) && $this->bocompose->preferencesArray['replyOptions']=="html" && $sessionData['mimeType'] != 'html') { $sessionData['mimeType'] = 'html'; $sessionData['body'] = "
".$sessionData['body'].""; } } } if ($sessionData['mimeType'] == 'html' && html::htmlarea_availible()===false) { $sessionData['mimeType'] = 'plain'; $sessionData['body'] = $this->bocompose->convertHTMLToText($sessionData['body']); } // removal of possible script elements in HTML; getCleanHTML is the choice here, if not only for consistence // we use the preg of common_functions (slightly altered) to meet eGroupwares behavior on posted variables if ($sessionData['mimeType'] == 'html') { // this is now moved to egw_htmLawed (triggered by default config) which is called with ckeditor anyway //felamimail_bo::getCleanHTML($sessionData['body'],true); } // is a certain signature requested? // only the following values are supported (and make sense) // no => means -2 // system => means -1 // default => fetches the default, which is standard behavior if (!empty($_REQUEST['signature']) && (strtolower($_REQUEST['signature']) == 'no' || strtolower($_REQUEST['signature']) == 'system')) { $presetSig = (strtolower($_REQUEST['signature']) == 'no' ? -2 : -1); } if (($suppressSigOnTop || $sessionData['isDraft']) && !empty($sessionData['signatureID'])) $presetSig = (int)$sessionData['signatureID']; if (($suppressSigOnTop || $sessionData['isDraft']) && !empty($sessionData['stationeryID'])) $presetStationery = $sessionData['stationeryID']; $presetId = NULL; if (($suppressSigOnTop || $sessionData['isDraft']) && !empty($sessionData['identity'])) $presetId = (int)$sessionData['identity']; $this->display_app_header(); $this->t->set_file(array("composeForm" => "composeForm.tpl")); $this->t->set_block('composeForm','header','header'); $this->t->set_block('composeForm','body_input'); $this->t->set_block('composeForm','attachment','attachment'); $this->t->set_block('composeForm','attachment_row','attachment_row'); $this->t->set_block('composeForm','attachment_row_bold'); $this->t->set_block('composeForm','destination_row'); $this->t->set_block('composeForm','simple_text'); $this->translate(); // store the selected Signature $this->t->set_var("mySigID",($presetSig ? $presetSig : $sessionData['signatureID'])); if ($GLOBALS['egw_info']['user']['apps']['addressbook']) { $this->t->set_var("link_addressbook",egw::link('/index.php',array( 'menuaction' => 'addressbook.addressbook_ui.emailpopup', ))); } else { $this->t->set_var("link_addressbook",''); } $this->t->set_var("focusElement",$_focusElement); $linkData = array ( 'menuaction' => 'felamimail.uicompose.selectFolder', ); $this->t->set_var('folder_select_url',egw::link('/index.php',$linkData)); $linkData = array ( 'menuaction' => 'felamimail.uicompose.fileSelector', 'composeid' => $this->composeID ); $this->t->set_var('file_selector_url',egw::link('/index.php',$linkData)); $this->t->set_var('vfs_selector_url',egw::link('/index.php',array( 'menuaction' => 'filemanager.filemanager_select.select', 'mode' => 'open-multiple', 'method' => 'felamimail.uicompose.vfsSelector', 'id' => $this->composeID, 'label' => lang('Attach'), ))); if ($GLOBALS['egw_info']['user']['apps']['filemanager']) { $this->t->set_var('vfs_attach_button',' '); } else { $this->t->set_var('vfs_attach_button',''); } $linkData = array ( 'menuaction' => 'felamimail.uicompose.action', 'composeid' => $this->composeID ); $this->t->set_var("link_action",egw::link('/index.php',$linkData)); $this->t->set_var('folder_name',$this->bofelamimail->sessionData['mailbox']); $this->t->set_var('compose_id',$this->composeID); // the editorobject is needed all the time (since we use CKEDITOR3 //$editorObject = html::initCKEditor('400px','simple'); $this->t->set_var('ckeditorConfig', egw_ckeditor_config::get_ckeditor_config('simple-withimage'));//$editorObject->jsEncode($editorObject->config)); $this->t->set_var('refreshTimeOut', 3*60*1000); // 3 minutes till a compose messages will be saved as draft; // check for some error messages from last posting attempt $errorInfo = $this->bocompose->getErrorInfo(); if (isset($_REQUEST['preset']['msg'])) $errorInfo = html::purify($_REQUEST['preset']['msg']); if($errorInfo) { $this->t->set_var('errorInfo',"$errorInfo"); } else { $this->t->set_var('errorInfo',' '); } // header $allIdentities = $this->mailPreferences->getIdentity(); //_debug_array($allIdentities); $defaultIdentity = 0; $identities = array(); foreach($allIdentities as $key => $singleIdentity) { #$identities[$singleIdentity->id] = $singleIdentity->realName.' <'.$singleIdentity->emailAddress.'>'; if (array_search($singleIdentity->realName.' <'.$singleIdentity->emailAddress.'>',$identities)==false) $identities[$key] = $singleIdentity->realName.' <'.$singleIdentity->emailAddress.'>'; if(!empty($singleIdentity->default)) { #$defaultIdentity = $singleIdentity->id; $defaultIdentity = $key; $sessionData['signatureID'] = (!empty($singleIdentity->signature) ? $singleIdentity->signature : $sessionData['signatureID']); } } $selectFrom = html::select('identity', ($presetId ? $presetId : $defaultIdentity), $identities, true, "style='width:100%;' onchange='changeIdentity(this);'"); $this->t->set_var('select_from', $selectFrom); //error_log(__METHOD__.__LINE__.' DefaultIdentity:'.array2string($identities[($presetId ? $presetId : $defaultIdentity)])); // navbar(, kind of) $this->t->set_var('img_clear_left', common::image('felamimail','clear_left')); $this->t->set_var('img_fileopen', common::image('phpgwapi','fileopen')); $this->t->set_var('img_mail_send', common::image('felamimail','mail_send')); $this->t->set_var('img_attach_file', common::image('felamimail','attach')); $this->t->set_var('ajax-loader', common::image('felamimail','ajax-loader')); $this->t->set_var('img_fileexport', common::image('felamimail','fileexport')); // prepare print url/button $this->t->set_var('img_print_it', common::image('felamimail','print')); $this->t->set_var('lang_print_it', lang('print it')); $this->t->set_var('print_it', $printURL); // from, to, cc, replyto $destinationRows = 0; foreach(array('to','cc','bcc','replyto','folder') as $destination) { foreach((array)$sessionData[$destination] as $key => $value) { if ($value=="NIL@NIL") continue; if ($destination=='replyto' && str_replace('"','',$value) == str_replace('"','',$identities[($presetId ? $presetId : $defaultIdentity)])) continue; //error_log(__METHOD__.__LINE__.array2string(array('key'=>$key,'value'=>$value))); $selectDestination = html::select('destination[]', $destination, $this->destinations, false, "style='width: 100%;' onchange='fm_compose_changeInputType(this)'"); $this->t->set_var('select_destination', $selectDestination); $value = htmlspecialchars_decode($value,ENT_COMPAT); $value = str_replace("\"\"",'"',$value); $address_array = imap_rfc822_parse_adrlist((get_magic_quotes_gpc()?stripslashes($value):$value), ''); foreach((array)$address_array as $addressObject) { if ($addressObject->host == '.SYNTAX-ERROR.') continue; $address = imap_rfc822_write_address($addressObject->mailbox,$addressObject->host,$addressObject->personal); $address = felamimail_bo::htmlentities($address, $this->displayCharset); $this->t->set_var('address', ($destination=='folder'?$value:$address)); $this->t->parse('destinationRows','destination_row',True); $destinationRows++; } } } while($destinationRows < 3) { // and always add one empty row $selectDestination = html::select('destination[]', 'to', $this->destinations, false, "style='width: 100%;' onchange='fm_compose_changeInputType(this)'"); $this->t->set_var('select_destination', $selectDestination); $this->t->set_var('address', ''); $this->t->parse('destinationRows','destination_row',True); $destinationRows++; } // and always add one empty row $selectDestination = html::select('destination[]', 'to', $this->destinations, false, "style='width: 100%;' onchange='fm_compose_changeInputType(this)'"); $this->t->set_var('select_destination', $selectDestination); $this->t->set_var('address', ''); $this->t->parse('destinationRows','destination_row',True); // handle subject $subject = felamimail_bo::htmlentities($sessionData['subject'],$this->displayCharset); $this->t->set_var("subject",$subject); if ($GLOBALS['egw_info']['user']['apps']['addressbook']) { $this->t->set_var('addressbookButton',''); } else { $this->t->set_var('addressbookButton',''); } if ($GLOBALS['egw_info']['user']['apps']['infolog']) { $this->t->set_var('infologImage',html::image('felamimail','to_infolog',lang('Save as infolog'),'width="17px" height="17px" valign="middle"' )); $this->t->set_var('lang_save_as_infolog',lang('Save as infolog')); $this->t->set_var('infolog_checkbox',''); } else { $this->t->set_var('infologImage',''); $this->t->set_var('lang_save_as_infolog',''); $this->t->set_var('infolog_checkbox',''); } if ($GLOBALS['egw_info']['user']['apps']['tracker']) { $this->t->set_var('trackerImage',html::image('felamimail','to_tracker',lang('Save as tracker'),'width="17px" height="17px" valign="middle"' )); $this->t->set_var('lang_save_as_infolog',($GLOBALS['egw_info']['user']['apps']['infolog']?lang('Save:'):lang('Save as tracker'))); $this->t->set_var('tracker_checkbox',''); } else { $this->t->set_var('trackerImage',''); $this->t->set_var('tracker_checkbox',''); } $this->t->set_var('lang_no_recipient',lang('No recipient address given!')); $this->t->set_var('lang_no_subject',lang('No subject given!')); $this->t->set_var('lang_infolog_tracker_not_both',lang("You can either choose to save as infolog OR tracker, not both.")); $this->t->pparse("out","header"); // prepare signatures, the selected sig may be used on top of the body require_once(EGW_INCLUDE_ROOT.'/felamimail/inc/class.felamimail_bosignatures.inc.php'); $boSignatures = new felamimail_bosignatures(); $signatures = $boSignatures->getListOfSignatures(); if (empty($sessionData['signatureID'])) { if ($signatureData = $boSignatures->getDefaultSignature()) { if (is_array($signatureData)) { $sessionData['signatureID'] = $signatureData['signatureid']; } else { $sessionData['signatureID'] =$signatureData; } } } $selectSignatures = array( '-2' => lang('no signature') ); foreach($signatures as $signature) { $selectSignatures[$signature['fm_signatureid']] = lang('Signature').': '.$signature['fm_description']; } $disableRuler = false; $signature = $boSignatures->getSignature(($presetSig ? $presetSig : $sessionData['signatureID'])); if ((isset($this->bocompose->preferencesArray['disableRulerForSignatureSeparation']) && $this->bocompose->preferencesArray['disableRulerForSignatureSeparation']) || empty($signature->fm_signature) || trim($this->bocompose->convertHTMLToText($signature->fm_signature)) =='') { $disableRuler = true; } $insertSigOnTop = false; //error_log(__METHOD__.__LINE__.array2string($this->bocompose->preferencesArray)); if (isset($this->bocompose->preferencesArray['insertSignatureAtTopOfMessage']) && $this->bocompose->preferencesArray['insertSignatureAtTopOfMessage'] && !(isset($_POST['mySigID']) && !empty($_POST['mySigID']) ) && !$suppressSigOnTop ) { $insertSigOnTop = true; if($sessionData['mimeType'] == 'html') { $before = ($disableRuler ?'