]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - modules/Emails/EmailUI.php
Release 6.1.6
[Github/sugarcrm.git] / modules / Emails / EmailUI.php
1 <?php
2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4  * SugarCRM is a customer relationship management program developed by
5  * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc.
6  * 
7  * This program is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU Affero General Public License version 3 as published by the
9  * Free Software Foundation with the addition of the following permission added
10  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
13  * 
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
17  * details.
18  * 
19  * You should have received a copy of the GNU Affero General Public License along with
20  * this program; if not, see http://www.gnu.org/licenses or write to the Free
21  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  * 02110-1301 USA.
23  * 
24  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
26  * 
27  * The interactive user interfaces in modified source and object code versions
28  * of this program must display Appropriate Legal Notices, as required under
29  * Section 5 of the GNU Affero General Public License version 3.
30  * 
31  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32  * these Appropriate Legal Notices must retain the display of the "Powered by
33  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34  * technical reasons, the Appropriate Legal Notices must display the words
35  * "Powered by SugarCRM".
36  ********************************************************************************/
37
38 /*********************************************************************************
39
40  * Description:
41  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc. All Rights
42  * Reserved. Contributor(s): ______________________________________..
43  *********************************************************************************/
44
45 require_once("include/ytree/Tree.php");
46 require_once("include/ytree/ExtNode.php");
47 require_once("include/SugarFolders/SugarFolders.php");
48
49
50
51 class EmailUI {
52         var $db;
53         var $folder; // place holder for SugarFolder object
54         var $folderStates = array(); // array of folderPath names and their states (1/0)
55         var $smarty;
56         var $addressSeparators = array(";", ",");
57         var $rolloverStyle = "<style>div#rollover {position: relative;float: left;margin: none;text-decoration: none;}div#rollover a:hover {padding: 0;}div#rollover a span {display: none;}div#rollover a:hover span {text-decoration: none;display: block;width: 250px;margin-top: 5px;margin-left: 5px;position: absolute;padding: 10px;color: #333; border: 1px solid #ccc; background-color: #fff; font-size: 12px;z-index: 1000;}</style>\n";
58         var $groupCss = "<span class='groupInbox'>";
59         var $cacheTimeouts = array(
60                 'messages'              => 86400,       // 24 hours
61                 'folders'               => 300,         // 5 mins
62                 'attachments'   => 86400,       // 24 hours
63         );
64         var $userCacheDir = '';
65         var $coreDynamicFolderQuery = "SELECT emails.id polymorphic_id, 'Emails' polymorphic_module FROM emails
66                                                                    JOIN emails_text on emails.id = emails_text.email_id
67                                    WHERE (type = '::TYPE::' OR status = '::STATUS::') AND assigned_user_id = '::USER_ID::' AND emails.deleted = '0'";
68
69         /**
70          * Sole constructor
71          */
72         function EmailUI() {
73                 global $sugar_config;
74                 global $current_user;
75
76                 $folderStateSerial = $current_user->getPreference('folderOpenState', 'Emails');
77
78                 if(!empty($folderStateSerial)) {
79                         $this->folderStates = unserialize($folderStateSerial);
80                 }
81
82                 $this->smarty = new Sugar_Smarty();
83                 $this->folder = new SugarFolder();
84                 $this->userCacheDir = "{$sugar_config['cache_dir']}modules/Emails/{$current_user->id}";
85                 $this->db = DBManagerFactory::getInstance();
86         }
87
88
89         ///////////////////////////////////////////////////////////////////////////
90         ////    CORE
91         /**
92          * Renders the frame for emails
93          */
94         function displayEmailFrame() {
95
96                 require_once("include/OutboundEmail/OutboundEmail.php");
97
98                 global $app_strings, $app_list_strings;
99                 global $mod_strings;
100                 global $sugar_config;
101                 global $current_user;
102                 global $locale;
103                 global $timedate;
104                 global $theme;
105                 global $sugar_version;
106                 global $sugar_flavor;
107                 global $current_language;
108                 global $server_unique_key;
109
110                 $this->preflightUserCache();
111                 $ie = new InboundEmail();
112
113                 // focus listView
114                 $list = array(
115                         'mbox' => 'Home',
116                         'ieId' => '',
117                         'name' => 'Home',
118                         'unreadChecked' => 0,
119                         'out' => array(),
120                 );
121
122                 $this->_generateComposeConfigData('email_compose');
123
124
125         //Check quick create module access
126         $QCAvailibleModules = array();
127         $QCModules = array(
128         'Bugs',
129         'Cases',
130         'Contacts',
131         'Leads',
132         'Tasks'
133         );
134         foreach($QCModules as $module) {
135                 $class = substr($module, 0, strlen($module) - 1);
136             require_once("modules/{$module}/{$class}.php");
137
138             if($class=="Case") {
139                 $class = "aCase";
140             }
141
142             $seed = new $class();
143                 if ($seed->ACLAccess('edit')) {
144                         $QCAvailibleModules[] = $module;
145                 }
146         }
147
148         //Get the quickSearch js needed for assigned user id on Search Tab
149         require_once('include/QuickSearchDefaults.php');
150         $qsd = new QuickSearchDefaults();
151         $qsd->setFormName('advancedSearchForm');
152         $quicksearchAssignedUser = "if(typeof sqs_objects == 'undefined'){var sqs_objects = new Array;}";
153         $quicksearchAssignedUser .= "sqs_objects['advancedSearchForm_assigned_user_name']=" . json_encode($qsd->getQSUser()) . ";";
154         $qsd->setFormName('Distribute');
155         $quicksearchAssignedUser .= "sqs_objects['Distribute_assigned_user_name']=" . json_encode($qsd->getQSUser()) . ";";
156         $this->smarty->assign('quickSearchForAssignedUser', $quicksearchAssignedUser);
157
158
159                 ///////////////////////////////////////////////////////////////////////
160                 ////    BASIC ASSIGNS
161                 $this->smarty->assign("currentUserId",$current_user->id);
162                 $this->smarty->assign("CURRENT_USER_EMAIL",$current_user->email1);
163         $this->smarty->assign("currentUserName",$current_user->name);
164                 $this->smarty->assign('yuiPath', 'modules/Emails/javascript/yui-ext/');
165                 $this->smarty->assign('app_strings', $app_strings);
166                 $this->smarty->assign('mod_strings', $mod_strings);
167                 $this->smarty->assign('theme', $theme);
168                 $this->smarty->assign('sugar_config', $sugar_config);
169                 $this->smarty->assign('is_admin', $current_user->is_admin);
170                 $this->smarty->assign('sugar_version', $sugar_version);
171                 $this->smarty->assign('sugar_flavor', $sugar_flavor);
172                 $this->smarty->assign('current_language', $current_language);
173                 $this->smarty->assign('server_unique_key', $server_unique_key);
174                 $this->smarty->assign('qcModules', json_encode($QCAvailibleModules));
175                 $extAllDebugValue = "ext-all.js";
176                 $this->smarty->assign('extFileName', $extAllDebugValue);
177
178                 // settings: general
179                 $e2UserPreferences = $this->getUserPrefsJS();
180                 $emailSettings = $e2UserPreferences['emailSettings'];
181
182                 ///////////////////////////////////////////////////////////////////////
183                 ////    USER SETTINGS
184                 // settings: accounts
185
186                 $cuDatePref = $current_user->getUserDateTimePreferences();
187                 $this->smarty->assign('dateFormat', $cuDatePref['date']);
188                 $this->smarty->assign('dateFormatExample', str_replace(array("Y", "m", "d"), array("yyyy", "mm", "dd"), $cuDatePref['date']));
189                 $this->smarty->assign('calFormat', $timedate->get_cal_date_format());
190
191                 $ieAccounts = $ie->retrieveByGroupId($current_user->id);
192                 $ieAccountsOptions = "<option value=''>{$app_strings['LBL_NONE']}</option>\n";
193
194                 foreach($ieAccounts as $k => $v) {
195                         $disabled = (!$v->is_personal) ? "DISABLED" : "";
196                         $group = (!$v->is_personal) ? $app_strings['LBL_EMAIL_GROUP']."." : "";
197                         $ieAccountsOptions .= "<option value='{$v->id}' $disabled>{$group}{$v->name}</option>\n";
198                 }
199
200                 $this->smarty->assign('ieAccounts', $ieAccountsOptions);
201                 $this->smarty->assign('rollover', $this->rolloverStyle);
202
203                 $protocol = filterInboundEmailPopSelection($app_list_strings['dom_email_server_type']);
204                 $this->smarty->assign('PROTOCOL', get_select_options_with_id($protocol, ''));
205                 $this->smarty->assign('MAIL_SSL_OPTIONS', get_select_options_with_id($app_list_strings['email_settings_for_ssl'], ''));
206                 $this->smarty->assign('ie_mod_strings', return_module_language($current_language, 'InboundEmail'));
207
208                 $charsetSelectedValue = isset($emailSettings['defaultOutboundCharset']) ? $emailSettings['defaultOutboundCharset'] : false;
209                 if (!$charsetSelectedValue) {
210                         $charsetSelectedValue = $current_user->getPreference('default_export_charset', 'global');
211                         if (!$charsetSelectedValue) {
212                                 $charsetSelectedValue = $locale->getPrecedentPreference('default_email_charset');
213                         }
214                 }
215                 $charset = array(
216                         'options' => $locale->getCharsetSelect(),
217                         'selected' => $charsetSelectedValue,
218                 );
219                 $this->smarty->assign('charset', $charset);
220
221                 $emailCheckInterval = array('options' => $app_strings['LBL_EMAIL_CHECK_INTERVAL_DOM'], 'selected' => $emailSettings['emailCheckInterval']);
222                 $this->smarty->assign('emailCheckInterval', $emailCheckInterval);
223                 $this->smarty->assign('attachmentsSearchOptions', $app_list_strings['checkbox_dom']);
224                 $this->smarty->assign('sendPlainTextChecked', ($emailSettings['sendPlainText'] == 1) ? 'CHECKED' : '');
225                 $this->smarty->assign('showNumInList', get_select_options_with_id($app_list_strings['email_settings_num_dom'], $emailSettings['showNumInList']));
226
227                 ////    END USER SETTINGS
228                 ///////////////////////////////////////////////////////////////////////
229
230                 ///////////////////////////////////////////////////////////////////////
231                 ////    SIGNATURES
232                 $prependSignature = ($current_user->getPreference('signature_prepend')) ? 'true' : 'false';
233                 $defsigID = $current_user->getPreference('signature_default');
234                 $this->smarty->assign('signatures', $current_user->getSignatures(false, $defsigID));
235                 $this->smarty->assign('signaturesSettings', $current_user->getSignatures(false, $defsigID, false));
236                 $signatureButtons = $current_user->getSignatureButtons('SUGAR.email2.settings.createSignature', !empty($defsigID));
237                 if (!empty($defsigID)) {
238                         $signatureButtons = $signatureButtons . '<span name="delete_sig" id="delete_sig" style="visibility:inherit;"><input class="button" onclick="javascript:SUGAR.email2.settings.deleteSignature();" value="'.$app_strings['LBL_EMAIL_DELETE'].'" type="button" tabindex="392">&nbsp;
239                                         </span>';
240                 } else {
241                         $signatureButtons = $signatureButtons . '<span name="delete_sig" id="delete_sig" style="visibility:hidden;"><input class="button" onclick="javascript:SUGAR.email2.settings.deleteSignature();" value="'.$app_strings['LBL_EMAIL_DELETE'].'" type="button" tabindex="392">&nbsp;
242                                         </span>';
243                 }
244                 $this->smarty->assign('signatureButtons', $signatureButtons);
245                 $this->smarty->assign('signaturePrepend', $prependSignature == 'true' ? 'CHECKED' : '');
246                 ////    END SIGNATURES
247                 ///////////////////////////////////////////////////////////////////////
248
249                 ///////////////////////////////////////////////////////////////////////
250                 ////    EMAIL TEMPLATES
251                 $email_templates_arr = $this->getEmailTemplatesArray();
252                 natcasesort($email_templates_arr);
253                 $this->smarty->assign('EMAIL_TEMPLATE_OPTIONS', get_select_options_with_id($email_templates_arr, ''));
254                 ////    END EMAIL TEMPLATES
255                 ///////////////////////////////////////////////////////////////////////
256
257                 ///////////////////////////////////////////////////////////////////////
258                 ////    FOLDERS & TreeView
259                 $this->smarty->assign('groupUserOptions', $ie->getGroupsWithSelectOptions(array('' => $app_strings['LBL_EMAIL_CREATE_NEW'])));
260
261                 $tree = $this->getMailboxNodes();
262
263                 // preloaded folder
264                 $preloadFolder = 'lazyLoadFolder = ';
265                 $focusFolderSerial = $current_user->getPreference('focusFolder', 'Emails');
266                 if(!empty($focusFolderSerial)) {
267                         $focusFolder = unserialize($focusFolderSerial);
268                         //$focusFolder['ieId'], $focusFolder['folder']
269                         $preloadFolder .= json_encode($focusFolder).";";
270                 } else {
271                         $preloadFolder .= "new Object();";
272                 }
273                 ////    END FOLDERS
274                 ///////////////////////////////////////////////////////////////////////
275
276                 $out = "";
277                 $out .= $this->smarty->fetch("modules/Emails/templates/_baseEmail.tpl");
278                 $out .= $tree->generate_header();
279                 $out .= $tree->generateNodesNoInit(true, 'email2treeinit');
280                 $out .=<<<eoq
281                         <script type="text/javascript" language="javascript">
282
283                                 var loader = new YAHOO.util.YUILoader({
284                                     require : [
285                                         "layout", "element", "tabview", "menu",
286                                         "cookie", "sugarwidgets"
287                                     ],
288                                     loadOptional: true,
289                                     skin: { base: 'blank', defaultSkin: '' },
290                                     onSuccess: email2init,
291                                     allowRollup: true,
292                                     base: "include/javascript/yui/build/"
293                                 });
294                                 loader.addModule({
295                                     name :"sugarwidgets",
296                                     type : "js",
297                                     fullpath: "include/javascript/sugarwidgets/SugarYUIWidgets.js",
298                                     varName: "YAHOO.SUGAR",
299                                     requires: ["datatable", "dragdrop", "treeview", "tabview"]
300                                 });
301                                 loader.insert();
302
303                                 {$preloadFolder};
304                         </script>
305 eoq;
306
307
308                 return $out;
309         }
310
311         /**
312          * Generate the frame needed for the quick compose email UI.  This frame is loaded dynamically
313          * by an ajax call.
314          *
315          * @return JSON An object containing html markup and js script variables.
316          */
317         function displayQuickComposeEmailFrame()
318         {
319         $this->preflightUserCache();
320
321             $this->_generateComposeConfigData('email_compose_light');
322                 $javascriptOut = $this->smarty->fetch("modules/Emails/templates/_baseConfigData.tpl");
323
324         $divOut = $this->smarty->fetch("modules/Emails/templates/overlay.tpl");
325         $divOut .= $this->smarty->fetch("modules/Emails/templates/addressSearchContent.tpl");
326
327         $outData = array('jsData' => $javascriptOut,'divData'=> $divOut);
328         $out = json_encode($outData);
329         return $out;
330     }
331
332     /**
333      * Given an email link url (eg. index.php?action=Compose&parent_type=Contacts...) break up the
334      * request components and create a compose package that can be used by the quick compose UI. The
335      * result is typically passed into the js call SUGAR.quickCompose.init which initalizes the quick compose
336      * UI.
337      *
338      * @param String $emailLinkUrl
339      * @return JSON Object containing the composePackage and full link url
340      */
341     function generateComposePackageForQuickCreateFromComposeUrl($emailLinkUrl)
342     {
343         $composeData = explode("&",$emailLinkUrl);
344         $a_composeData = array();
345         foreach ($composeData as $singleRequest)
346         {
347                 $tmp = explode("=",$singleRequest);
348                 $a_composeData[$tmp[0]] = urldecode($tmp[1]);
349         }
350
351         return $this->generateComposePackageForQuickCreate($a_composeData,$emailLinkUrl);
352     }
353     /**
354      * Generate the composePackage for the quick compose email UI.  The package contains
355      * key/value pairs generated by the Compose.php file which are then set into the
356      * quick compose email UI (eg. to addr, parent id, parent type, etc)
357      *
358      * @param Array $composeData Associative array read and processed by generateComposeDataPackage.
359      * @param String $fullLinkUrl A link that contains all pertinant information so the user can be
360      *                              directed to the full compose screen if needed
361      * @return JSON Object containg composePackage and fullLinkUrl
362      */
363     function generateComposePackageForQuickCreate($composeData,$fullLinkUrl)
364     {
365         $_REQUEST['forQuickCreate'] = true;
366         require_once('modules/Emails/Compose.php');
367         $composePackage = generateComposeDataPackage($composeData,FALSE);
368
369         // JSON object is passed into the function defined within the a href onclick event
370         // which is delimeted by '.  Need to escape all single quotes and &, <, >
371         // but not double quotes since json would escape them
372         foreach ($composePackage as $key => $singleCompose)
373         {
374            if (is_string($singleCompose))
375                $composePackage[$key] = str_replace("&nbsp;", " ", from_html($singleCompose));
376         }
377
378         $quickComposeOptions = array('fullComposeUrl' => $fullLinkUrl,'composePackage' => $composePackage);
379         $json = new JSON();
380         $j_quickComposeOptions = $json->encode($quickComposeOptions, false, true);
381
382         return $j_quickComposeOptions;
383     }
384
385     /**
386      * Generate the config data needed for the Full Compose UI and the Quick Compose UI.  The set of config data
387      * returned is the minimum set needed by the quick compose UI.
388      *
389      * @param String $type Drives which tinyMCE options will be included.
390      */
391         function _generateComposeConfigData($type = "email_compose_light" )
392         {
393                 global $app_list_strings,$current_user, $app_strings, $mod_strings,$current_language,$locale;
394
395                 //Link drop-downs
396                 $parent_types = $app_list_strings['record_type_display'];
397                 $disabled_parent_types = ACLController::disabledModuleList($parent_types, false, 'list');
398
399                 foreach($disabled_parent_types as $disabled_parent_type) {
400                   unset($parent_types[$disabled_parent_type]);
401                 }
402                 asort($parent_types);
403                 $linkBeans = json_encode(get_select_options_with_id($parent_types, ''));
404
405                 //TinyMCE Config
406                 require_once("include/SugarTinyMCE.php");
407         $tiny = new SugarTinyMCE();
408         $tinyConf = $tiny->getConfig($type);
409
410         //Generate Language Packs
411                 $lang = "var app_strings = new Object();\n";
412                 foreach($app_strings as $k => $v) {
413                         if(strpos($k, 'LBL_EMAIL_') !== false) {
414                                 $lang .= "app_strings.{$k} = '{$v}';\n";
415                         }
416                 }
417                 //Get the email mod strings but don't use the global variable as this may be overridden by
418                 //other modules when the quick create is rendered.
419                 $email_mod_strings = return_module_language($current_language,'Emails');
420                 $modStrings = "var mod_strings = new Object();\n";
421                 foreach($email_mod_strings as $k => $v) {
422                         $v = str_replace("'", "\'", $v);
423                         $modStrings .= "mod_strings.{$k} = '{$v}';\n";
424                 }
425                 $lang .= "\n\n{$modStrings}\n";
426
427                 //Grab the Inboundemail language pack
428                 $ieModStrings = "var ie_mod_strings = new Object();\n";
429                 $ie_mod_strings = return_module_language($current_language,'InboundEmail');
430                 foreach($ie_mod_strings as $k => $v) {
431                         $v = str_replace("'", "\'", $v);
432                         $ieModStrings .= "ie_mod_strings.{$k} = '{$v}';\n";
433                 }
434                 $lang .= "\n\n{$ieModStrings}\n";
435
436                 $this->smarty->assign('linkBeans', $linkBeans);
437         $this->smarty->assign('linkBeansOptions', $parent_types);
438         $this->smarty->assign('tinyMCE', $tinyConf);
439         $this->smarty->assign('lang', $lang);
440         $this->smarty->assign('app_strings', $app_strings);
441                 $this->smarty->assign('mod_strings', $email_mod_strings);
442         $ie1 = new InboundEmail();
443
444         //Signatures
445         $defsigID = $current_user->getPreference('signature_default');
446                 $defaultSignature = $current_user->getDefaultSignature();
447                 $sigJson = !empty($defaultSignature) ? json_encode(array($defaultSignature['id'] => from_html($defaultSignature['signature_html']))) : "new Object()";
448                 $this->smarty->assign('defaultSignature', $sigJson);
449                 $this->smarty->assign('signatureDefaultId', (isset($defaultSignature['id'])) ? $defaultSignature['id'] : "");
450                 //User Preferences
451                 $this->smarty->assign('userPrefs', json_encode($this->getUserPrefsJS()));
452
453                 //Get the users default outbound id
454                 $defaultOutID = $ie1->getUsersDefaultOutboundServerId($current_user);
455                 $this->smarty->assign('defaultOutID', $defaultOutID);
456
457                 //Character Set
458                 $charsets = json_encode($locale->getCharsetSelect());
459                 $this->smarty->assign('emailCharsets', $charsets);
460
461                 //Relateable List of People for address book search
462                 //#20776 jchi
463                 $peopleTables = array("users",
464                                       "contacts",
465                                       "leads",
466                                       "prospects",
467                                       "accounts");
468                 $filterPeopleTables = array();
469                 global $app_list_strings, $app_strings;
470                 $filterPeopleTables['LBL_DROPDOWN_LIST_ALL'] = $app_strings['LBL_DROPDOWN_LIST_ALL'];
471                 foreach($peopleTables as $table) {
472                         $module = ucfirst($table);
473             $class = substr($module, 0, strlen($module) - 1);
474             require_once("modules/{$module}/{$class}.php");
475             $person = new $class();
476
477             if (!$person->ACLAccess('list')) continue;
478             $filterPeopleTables[$person->table_name] = $app_list_strings['moduleList'][$person->module_dir];
479                 }
480                 $this->smarty->assign('listOfPersons' , get_select_options_with_id($filterPeopleTables,''));
481
482         }
483
484
485
486         ////    END CORE
487         ///////////////////////////////////////////////////////////////////////////
488
489         ///////////////////////////////////////////////////////////////////////////
490         ////    ADDRESS BOOK
491         /**
492          * Retrieves all relationship metadata for a user's address book
493          * @return array
494          */
495         function getContacts() {
496                 global $current_user;
497
498                 $q = "SELECT * FROM address_book WHERE assigned_user_id = '{$current_user->id}' ORDER BY bean DESC";
499                 $r = $this->db->query($q);
500
501                 $ret = array();
502
503                 while($a = $this->db->fetchByAssoc($r)) {
504                         $ret[$a['bean_id']] = array(
505                                 'id'            => $a['bean_id'],
506                                 'module'        => $a['bean'],
507                         );
508                 }
509
510                 return $ret;
511         }
512
513         /**
514          * Saves changes to a user's address book
515          * @param array contacts
516          */
517         function setContacts($contacts) {
518                 global $current_user;
519
520                 $oldContacts = $this->getContacts();
521
522                 foreach($contacts as $cid => $contact) {
523                         if(!in_array($contact['id'], $oldContacts)) {
524                                 $q = "INSERT INTO address_book (assigned_user_id, bean, bean_id) VALUES ('{$current_user->id}', '{$contact['module']}', '{$contact['id']}')";
525                                 $r = $this->db->query($q, true);
526                         }
527                 }
528         }
529
530         /**
531          * Removes contacts from the user's address book
532          * @param array ids
533          */
534         function removeContacts($ids) {
535                 global $current_user;
536
537                 $concat = "";
538
539                 foreach($ids as $id) {
540                         if(!empty($concat))
541                                 $concat .= ", ";
542
543                         $concat .= "'{$id}'";
544                 }
545
546                 $q = "DELETE FROM address_book WHERE assigned_user_id = '{$current_user->id}' AND bean_id IN ({$concat})";
547                 $r = $this->db->query($q);
548         }
549
550         /**
551          * saves editted Contact info
552          * @param string $str JSON serialized object
553          */
554         function saveContactEdit($str) {
555
556                 $json = getJSONobj();
557
558                 $str = from_html($str);
559                 $obj = $json->decode($str);
560
561                 $contact = new Contact();
562                 $contact->retrieve($obj['contact_id']);
563                 $contact->first_name = $obj['contact_first_name'];
564                 $contact->last_name = $obj['contact_last_name'];
565                 $contact->save();
566
567                 // handle email address changes
568                 $addresses = array();
569
570                 foreach($obj as $k => $req) {
571                         if(strpos($k, 'emailAddress') !== false) {
572                                 $addresses[$k] = $req;
573                         }
574                 }
575
576                 // prefill some REQUEST vars for emailAddress save
577                 $_REQUEST['emailAddressOptOutFlag'] = $obj['optOut'];
578                 $_REQUEST['emailAddressInvalidFlag'] = $obj['invalid'];
579                 $contact->emailAddress->save($obj['contact_id'], 'Contacts', $addresses, $obj['primary'], '');
580         }
581
582         /**
583          * Prepares the Edit Contact mini-form via template assignment
584          * @param string id ID of contact in question
585          * @param string module Module in focus
586          * @return array
587          */
588         function getEditContact($id, $module) {
589                 global $app_strings;
590
591
592                 if(!class_exists("Contact")) {
593
594                 }
595
596                 $contact = new Contact();
597                 $contact->retrieve($_REQUEST['id']);
598                 $ret = array();
599
600                 if($contact->ACLAccess('edit')) {
601                         $contactMeta = array();
602                         $contactMeta['id'] = $contact->id;
603                         $contactMeta['module'] = $contact->module_dir;
604                         $contactMeta['first_name'] = $contact->first_name;
605                         $contactMeta['last_name'] = $contact->last_name;
606
607                         $this->smarty->assign("app_strings", $app_strings);
608                         $this->smarty->assign("contact_strings", return_module_language($_SESSION['authenticated_user_language'], 'Contacts'));
609                         $this->smarty->assign("contact", $contactMeta);
610
611                         $ea = new SugarEmailAddress();
612                         $newEmail = $ea->getEmailAddressWidgetEditView($id, $module, true);
613                         $this->smarty->assign("emailWidget", $newEmail['html']);
614
615                         $ret['form'] = $this->smarty->fetch("modules/Emails/templates/editContact.tpl");
616                         $ret['prefillData'] = $newEmail['prefillData'];
617                 } else {
618                         $id = "";
619                         $ret['form'] = $app_strings['LBL_EMAIL_ERROR_NO_ACCESS'];
620                         $ret['prefillData'] = '{}';
621                 }
622
623                 $ret['id'] = $id;
624                 $ret['contactName'] = $contact->full_name;
625
626                 return $ret;
627         }
628
629
630         /**
631          * Retrieves a concatenated list of contacts, those with assigned_user_id = user's id and those in the address_book
632          * table
633          * @param array $contacts Array of contact types -> IDs
634          * @param object $user User in focus
635          * @return array
636          */
637         function getUserContacts($contacts, $user=null) {
638
639                 global $current_user;
640                 global $locale;
641
642                 if(empty($user)) {
643                         $user = $current_user;
644                 }
645
646                 $emailAddress = new SugarEmailAddress();
647                 $ret = array();
648
649                 $union = '';
650
651                 $modules = array();
652                 foreach($contacts as $contact) {
653                         if(!isset($modules[$contact['module']])) {
654                                 $modules[$contact['module']] = array();
655                         }
656                         $modules[$contact['module']][] = $contact;
657                 }
658
659                 foreach($modules as $module => $contacts) {
660                         if(!empty($union)) {
661                                 $union .= " UNION ALL ";
662                         }
663
664                         $table = strtolower($module);
665                         $idsSerial = '';
666
667                         foreach($contacts as $contact) {
668                                 if(!empty($idsSerial)) {
669                                         $idsSerial .= ",";
670                                 }
671                                 $idsSerial .= "'{$contact['id']}'";
672                         }
673
674                         $union .= "(SELECT id, first_name, last_name, title, '{$module}' module FROM {$table} WHERE id IN({$idsSerial}) AND deleted = 0 )";
675                 }
676                 if(!empty($union)) {
677                         $union .= " ORDER BY last_name";
678                 }
679
680                 $r = $user->db->query($union);
681
682                 //_pp($union);
683
684                 while($a = $user->db->fetchByAssoc($r)) {
685                         $c = array();
686
687                         $c['name'] = $locale->getLocaleFormattedName($a['first_name'], "<b>{$a['last_name']}</b>", '', $a['title'], '', $user);
688                         $c['id'] = $a['id'];
689                         $c['module'] = $a['module'];
690                         $c['email'] = $emailAddress->getAddressesByGUID($a['id'], $a['module']);
691                         $ret[$a['id']] = $c;
692                 }
693
694                 return $ret;
695         }
696         ////    END ADDRESS BOOK
697         ///////////////////////////////////////////////////////////////////////////
698
699
700         ///////////////////////////////////////////////////////////////////////////
701         ////    EMAIL 2.0 Preferences
702         function getUserPrefsJS() {
703                 global $current_user;
704                 global $locale;
705
706                 // sort order per mailbox view
707                 $sortSerial = $current_user->getPreference('folderSortOrder', 'Emails');
708                 $sortArray = array();
709                 if(!empty($sortSerial)) {
710                         $sortArray = unserialize($sortSerial);
711                 }
712
713                 // treeview collapsed/open states
714                 $folderStateSerial = $current_user->getPreference('folderOpenState', 'Emails');
715                 $folderStates = array();
716                 if(!empty($folderStateSerial)) {
717                         $folderStates = unserialize($folderStateSerial);
718                 }
719
720                 // subscribed accounts
721                 $showFolders = unserialize(base64_decode($current_user->getPreference('showFolders', 'Emails')));
722
723                 // general settings
724                 $emailSettings = $current_user->getPreference('emailSettings', 'Emails');
725
726                 if(empty($emailSettings)) {
727                         $emailSettings = array();
728                         $emailSettings['emailCheckInterval'] = -1;
729                         $emailSettings['autoImport'] = '';
730                         $emailSettings['alwaysSaveOutbound'] = '1';
731                         $emailSettings['sendPlainText'] = '';
732                         $emailSettings['defaultOutboundCharset'] = $GLOBALS['sugar_config']['default_email_charset'];
733                         $emailSettings['showNumInList'] = 20;
734                 }
735
736                 // focus folder
737                 $focusFolder = $current_user->getPreference('focusFolder', 'Emails');
738                 $focusFolder = !empty($focusFolder) ? unserialize($focusFolder) : array();
739
740                 // unread only flag
741                 $showUnreadOnly = $current_user->getPreference('showUnreadOnly', 'Emails');
742
743                 $listViewSort = array(
744                         "sortBy" => 'date',
745                         "sortDirection" => 'DESC',
746                 );
747
748                 // signature prefs
749                 $signaturePrepend = $current_user->getPreference('signature_prepend') ? 'true' : 'false';
750                 $signatureDefault = $current_user->getPreference('signature_default');
751                 $signatures = array(
752                         'signature_prepend' => $signaturePrepend,
753                         'signature_default' => $signatureDefault
754                 );
755
756
757                 // current_user
758                 $user = array(
759                         'emailAddresses' => $current_user->emailAddress->getAddressesByGUID($current_user->id, 'Users'),
760                         'full_name' => from_html($current_user->full_name),
761                 );
762
763                 $userPreferences = array();
764                 $userPreferences['sort'] = $sortArray;
765                 $userPreferences['folderStates'] = $folderStates;
766                 $userPreferences['showFolders'] = $showFolders;
767                 $userPreferences['emailSettings'] = $emailSettings;
768                 $userPreferences['focusFolder'] = $focusFolder;
769                 $userPreferences['showUnreadOnly'] = $showUnreadOnly;
770                 $userPreferences['listViewSort'] = $listViewSort;
771                 $userPreferences['signatures'] = $signatures;
772                 $userPreferences['current_user'] = $user;
773                 return $userPreferences;
774         }
775
776
777
778         ///////////////////////////////////////////////////////////////////////////
779         ////    FOLDER FUNCTIONS
780
781         /**
782          * Creates a new Sugar folder
783          * @param string $nodeLabel New sugar folder name
784          * @param string $parentLabel Parent folder name
785          */
786         function saveNewFolder($nodeLabel, $parentId, $isGroup=0) {
787                 global $current_user;
788
789                 $this->folder->name = $nodeLabel;
790                 $this->folder->is_group = $isGroup;
791                 $this->folder->parent_folder = ($parentId == 'Home') ? "" : $parentId;
792                 $this->folder->has_child = 0;
793                 $this->folder->created_by = $current_user->id;
794                 $this->folder->modified_by = $current_user->id;
795                 $this->folder->date_created = date($GLOBALS['timedate']->get_db_date_time_format(), gmmktime());
796                 $this->folder->date_modified = date($GLOBALS['timedate']->get_db_date_time_format(), gmmktime());
797
798                 $this->folder->save();
799                 return array(
800                         'action' => 'newFolderSave',
801                         'id' => $this->folder->id,
802                         'name' => $this->folder->name,
803                         'is_group' => $this->folder->is_group,
804                         'is_dynamic' => $this->folder->is_dynamic
805                 );
806         }
807
808         /**
809          * Saves user sort prefernces
810          */
811         function saveListViewSortOrder($ieId, $focusFolder, $sortBy, $sortDir) {
812                 global $current_user;
813
814                 $sortArray = array();
815
816                 $sortSerial = $current_user->getPreference('folderSortOrder', 'Emails');
817                 if(!empty($sortSerial)) {
818                         $sortArray = unserialize($sortSerial);
819                 }
820
821                 $sortArray[$ieId][$focusFolder]['current']['sort'] = $sortBy;
822                 $sortArray[$ieId][$focusFolder]['current']['direction'] = $sortDir;
823                 $sortSerial = serialize($sortArray);
824                 $current_user->setPreference('folderSortOrder', $sortSerial, '', 'Emails');
825         }
826
827         /**
828          * Stickies folder collapse/open state
829          */
830         function saveFolderOpenState($focusFolder, $focusFolderOpen) {
831                 global $current_user;
832
833                 $folderStateSerial = $current_user->getPreference('folderOpenState', 'Emails');
834                 $folderStates = array();
835
836                 if(!empty($folderStateSerial)) {
837                         $folderStates = unserialize($folderStateSerial);
838                 }
839
840                 $folderStates[$focusFolder] = $focusFolderOpen;
841                 $newFolderStateSerial = serialize($folderStates);
842                 $current_user->setPreference('folderOpenState', $newFolderStateSerial, '', 'Emails');
843         }
844
845         /**
846          * saves a folder's view state
847          */
848         function saveListView($ieId, $folder) {
849                 global $current_user;
850
851                 $saveState = array();
852                 $saveState['ieId'] = $ieId;
853                 $saveState['folder'] = $folder;
854                 $saveStateSerial = serialize($saveState);
855                 $current_user->setPreference('focusFolder', $saveStateSerial, '', 'Emails');
856         }
857
858         /**
859          * Generates cache folder structure
860          */
861         function preflightEmailCache($cacheRoot) {
862                 // base
863                 if(!file_exists($cacheRoot))
864                         mkdir_recursive(clean_path($cacheRoot));
865
866                 // folders
867                 if(!file_exists($cacheRoot."/folders"))
868                         mkdir_recursive(clean_path("{$cacheRoot}/folders"));
869
870                 // messages
871                 if(!file_exists($cacheRoot."/messages"))
872                         mkdir_recursive(clean_path("{$cacheRoot}/messages"));
873
874                 // attachments
875                 if(!file_exists($cacheRoot."/attachments"))
876                         mkdir_recursive(clean_path("{$cacheRoot}/attachments"));
877         }
878
879         function deleteEmailCacheForFolders($cacheRoot) {
880                 $filePath = $cacheRoot."/folders/folders.php";
881                 if (file_exists($filePath)) {
882                         unlink($filePath);
883                 }
884         }
885         ///////////////////////////////////////////////////////////////////////////
886         ////    IMAP FUNCTIONS
887         /**
888          * Identifies subscribed mailboxes and empties the trash
889          * @param object $ie InboundEmail
890          */
891         function emptyTrash(&$ie) {
892                 global $current_user;
893
894                 $showFolders = unserialize(base64_decode($current_user->getPreference('showFolders', 'Emails')));
895
896                 if(is_array($showFolders)) {
897                         foreach($showFolders as $ieId) {
898                                 if(!empty($ieId)) {
899                                         $ie->retrieve($ieId);
900                                         $ie->emptyTrash();
901                                 }
902                         }
903                 }
904         }
905
906         /**
907          * returns an array of nodes that correspond to IMAP mailboxes.
908          * @param bool $forceRefresh
909          * @return object TreeView object
910          */
911         function getMailboxNodes() {
912                 global $sugar_config;
913                 global $current_user;
914                 global $app_strings;
915
916                 $tree = new Tree("frameFolders");
917                 $tree->tree_style= 'include/ytree/TreeView/css/check/tree.css';
918
919                 $nodes = array();
920                 $ie = new InboundEmail();
921                 $refreshOffset = $this->cacheTimeouts['folders']; // 5 mins.  this will be set via user prefs
922
923                 $rootNode = new ExtNode($app_strings['LBL_EMAIL_HOME_FOLDER'], $app_strings['LBL_EMAIL_HOME_FOLDER']);
924                 $rootNode->dynamicloadfunction = '';
925                 $rootNode->expanded = true;
926                 $rootNode->dynamic_load = true;
927                 $showFolders = unserialize(base64_decode($current_user->getPreference('showFolders', 'Emails')));
928
929                 if(empty($showFolders)) {
930                         $showFolders = array();
931                 }
932
933                 // INBOX NODES
934                 if($current_user->hasPersonalEmail()) {
935                         $personals = $ie->retrieveByGroupId($current_user->id);
936
937                         foreach($personals as $k => $personalAccount) {
938                                 if(in_array($personalAccount->id, $showFolders)) {
939                                         // check for cache value
940                                         $cacheRoot = "{$sugar_config['cache_dir']}modules/Emails/{$personalAccount->id}";
941                                         $this->preflightEmailCache($cacheRoot);
942
943                                         if($this->validCacheFileExists($personalAccount->id, 'folders', "folders.php")) {
944                                                 $mailboxes = $this->getMailBoxesFromCacheValue($personalAccount);
945                                         } else {
946                                                 $mailboxes = $personalAccount->getMailboxes();
947                                         }
948
949                                         $acctNode = new ExtNode('Home::' . $personalAccount->name, $personalAccount->name);
950                                         $acctNode->dynamicloadfunction = '';
951                                         $acctNode->expanded = false;
952                                         $acctNode->set_property('cls', 'ieFolder');
953                                         $acctNode->set_property('ieId', $personalAccount->id);
954                                 $acctNode->set_property('protocol', $personalAccount->protocol);
955
956                                         if(array_key_exists('Home::'.$personalAccount->name, $this->folderStates)) {
957                                                 if($this->folderStates['Home::'.$personalAccount->name] == 'open') {
958                                                         $acctNode->expanded = true;
959                                                 }
960                                         }
961                                         $acctNode->dynamic_load = true;
962
963                                         $nodePath = $acctNode->_properties['id'];
964
965                                         foreach($mailboxes as $k => $mbox) {
966                                                 $acctNode->add_node($this->buildTreeNode($k, $k, $mbox, $personalAccount->id,
967                                                     $nodePath, false, $personalAccount));
968                                         }
969
970                                         $rootNode->add_node($acctNode);
971                                 }
972                         }
973                 }
974
975                 // GROUP INBOX NODES
976                 $beans = $ie->retrieveAllByGroupId($current_user->id, false);
977                 foreach($beans as $k => $groupAccount) {
978                         if(in_array($groupAccount->id, $showFolders)) {
979                                 // check for cache value
980                                 $cacheRoot = "{$sugar_config['cache_dir']}modules/Emails/{$groupAccount->id}";
981                                 $this->preflightEmailCache($cacheRoot);
982                                 //$groupAccount->connectMailserver();
983
984                                 if($this->validCacheFileExists($groupAccount->id, 'folders', "folders.php")) {
985                                         $mailboxes = $this->getMailBoxesFromCacheValue($groupAccount);
986                                 } else {
987                                         $mailboxes = $groupAccount->getMailBoxesForGroupAccount();
988                                 }
989
990                                 $acctNode = new ExtNode($groupAccount->name, "group.{$groupAccount->name}");
991                                 $acctNode->dynamicloadfunction = '';
992                                 $acctNode->expanded = false;
993                         $acctNode->set_property('isGroup', 'true');
994                         $acctNode->set_property('ieId', $groupAccount->id);
995                         $acctNode->set_property('protocol', $groupAccount->protocol);
996
997                                 if(array_key_exists('Home::'.$groupAccount->name, $this->folderStates)) {
998                                         if($this->folderStates['Home::'.$groupAccount->name] == 'open') {
999                                                 $acctNode->expanded = true;
1000                                         }
1001                                 }
1002                                 $acctNode->dynamic_load = true;
1003                                 $nodePath = $rootNode->_properties['id']."::".$acctNode->_properties['id'];
1004
1005                                 foreach($mailboxes as $k => $mbox) {
1006                                         $acctNode->add_node($this->buildTreeNode($k, $k, $mbox, $groupAccount->id,
1007                                            $nodePath, true, $groupAccount));
1008                                 }
1009
1010                                 $rootNode->add_node($acctNode);
1011                         }
1012                 }
1013
1014                 // SugarFolder nodes
1015                 /* SugarFolders are built at onload when the UI renders */
1016
1017                 $tree->add_node($rootNode);
1018                 return $tree;
1019         }
1020
1021         function getMailBoxesFromCacheValue($mailAccount) {
1022                 $foldersCache = $this->getCacheValue($mailAccount->id, 'folders', "folders.php", 'foldersCache');
1023                 $mailboxes = $foldersCache['mailboxes'];
1024                 $mailboxesArray = $mailAccount->generateFlatArrayFromMultiDimArray($mailboxes, $mailAccount->retrieveDelimiter());
1025                 $mailAccount->saveMailBoxFolders($mailboxesArray);
1026                 $this->deleteEmailCacheForFolders($cacheRoot);
1027                 return $mailboxes;
1028         } // fn
1029
1030         /**
1031          * Builds up a TreeView Node object
1032          * @param mixed
1033          * @param mixed
1034          * @param string
1035          * @param string ID of InboundEmail instance
1036          * @param string nodePath Serialized path from root node to current node
1037          * @param bool isGroup
1038          * @param bool forceRefresh
1039          * @return mixed
1040          */
1041         function buildTreeNode($key, $label, $mbox, $ieId, $nodePath, $isGroup, $ie) {
1042                 global $sugar_config;
1043
1044                 // get unread counts
1045                 $exMbox = explode("::", $nodePath);
1046                 $unseen = 0;
1047                 $GLOBALS['log']->debug("$key --- $nodePath::$label");
1048
1049                 if(count($exMbox) >= 2) {
1050                         $mailbox = "";
1051                         for($i=2; $i<count($exMbox); $i++) {
1052                                 if($mailbox != "") {
1053                                         $mailbox .= ".";
1054                                 }
1055                                 $mailbox .= "{$exMbox[$i]}";
1056                         }
1057
1058                     $mailbox = substr($key, strpos($key, '.'));
1059
1060                         $unseen = $this->getUnreadCount($ie, $mailbox);
1061
1062                         if($unseen > 0) {
1063                                 //$label = " <span id='span{$ie->id}{$ie->mailbox}' style='font-weight:bold'>{$label} (<span id='span{$ie->id}{$ie->mailbox}nums'>{$unseen}</span>)</span>";
1064                         }
1065                 }
1066
1067                 $nodePath = $nodePath."::".$label;
1068         $node = new ExtNode($nodePath, $label);
1069         $node->dynamicloadfunction = '';
1070         $node->expanded = false;
1071         $node->set_property('labelStyle', "remoteFolder");
1072
1073
1074         if(array_key_exists($nodePath, $this->folderStates)) {
1075                 if($this->folderStates[$nodePath] == 'open') {
1076                         $node->expanded = true;
1077                 }
1078         }
1079
1080                 $group = ($isGroup) ? 'true' : 'false';
1081         $node->dynamic_load = true;
1082         //$node->set_property('href', " SUGAR.email2.listView.populateListFrame(YAHOO.namespace('frameFolders').selectednode, '{$ieId}', 'false');");
1083         $node->set_property('isGroup', $group);
1084         $node->set_property('isDynamic', 'false');
1085         $node->set_property('ieId', $ieId);
1086         $node->set_property('mbox', $key);
1087         $node->set_property('unseen', $unseen);
1088         $node->set_property('cls', 'ieFolder');
1089
1090         if(is_array($mbox)) {
1091                 foreach($mbox as $k => $v) {
1092                         $node->add_node($this->buildTreeNode("$key.$k", $k, $v, $ieId, $nodePath, $isGroup, $ie));
1093                 }
1094         }
1095
1096         return $node;
1097         }
1098
1099         /**
1100          * Totals the unread emails
1101          */
1102         function getUnreadCount(&$ie, $mailbox) {
1103                 global $sugar_config;
1104                 $unseen = 0;
1105
1106                 // use cache
1107                 return $ie->getCacheUnreadCount($mailbox);
1108         }
1109
1110         ///////////////////////////////////////////////////////////////////////////
1111         ////    DISPLAY CODE
1112         /**
1113          * Used exclusively by draft code.  Returns Notes and Documents as attachments.
1114          * @param array $ret
1115          * @return array
1116          */
1117         function getDraftAttachments($ret) {
1118                 global $db;
1119
1120                 // $ret['uid'] is the draft Email object's GUID
1121                 $ret['attachments'] = array();
1122
1123                 $q = "SELECT id, filename FROM notes WHERE parent_id = '{$ret['uid']}' AND deleted = 0";
1124                 $r = $db->query($q);
1125
1126                 while($a = $db->fetchByAssoc($r)) {
1127                         $ret['attachments'][$a['id']] = array(
1128                                 'id'            => $a['id'],
1129                                 'filename'      => $a['filename'],
1130                         );
1131                 }
1132
1133                 return $ret;
1134         }
1135
1136         function createCopyOfInboundAttachment($ie, $ret, $uid) {
1137                 global $sugar_config;
1138                 if ($ie->isPop3Protocol()) {
1139                         // get the UIDL from database;
1140                         $cachedUIDL = md5($uid);
1141                         $cache = "{$sugar_config['cache_dir']}modules/Emails/{$ie->id}/messages/{$ie->mailbox}{$cachedUIDL}.php";
1142                 } else {
1143                         $cache = "{$sugar_config['cache_dir']}modules/Emails/{$ie->id}/messages/{$ie->mailbox}{$uid}.php";
1144                 }
1145                 if(file_exists($cache)) {
1146                         include($cache); // profides $cacheFile
1147                         $metaOut = unserialize($cacheFile['out']);
1148                         $meta = $metaOut['meta']['email'];
1149                         if (isset($meta['attachments'])) {
1150                                 $attachmentHtmlData = $meta['attachments'];
1151                                 $actualAttachmentInfo = array();
1152                                 $this->parseAttachmentInfo($actualAttachmentInfo, $attachmentHtmlData);
1153                                 if (sizeof($actualAttachmentInfo) > 0) {
1154                                         foreach($actualAttachmentInfo as $key => $value) {
1155                                                 $attachmentid;
1156                                                 $fileName;
1157                                                 $datasplit = explode("&", $value);
1158                                                 $attachmentIdArray = explode("=", $datasplit[0]);
1159                                                 $attachmentid = $attachmentIdArray[1];
1160
1161                                                 $fileNameArray = explode("=", $datasplit[4]);
1162                                                 $fileName = $fileNameArray[1];
1163                                                 $guid = create_guid();
1164                                                 //$destination = clean_path("{$this->userCacheDir}/{$guid}{$fileName}");
1165                                                 $destination = clean_path("{$this->userCacheDir}/{$guid}");
1166
1167                                                 $attachmentFilePath = "{$sugar_config['cache_dir']}modules/Emails/{$ie->id}/attachments/{$attachmentid}";
1168                                                 copy($attachmentFilePath, $destination);
1169                                                 $ret['attachments'][$guid] = array();
1170                                                 $ret['attachments'][$guid]['id'] = $guid . $fileName;
1171                                                 $ret['attachments'][$guid]['filename'] = $fileName;
1172                                         } // for
1173                                 } // if
1174                         } // if
1175
1176                 } // if
1177                 return $ret;
1178
1179         } // fn
1180
1181         function parseAttachmentInfo(&$actualAttachmentInfo, $attachmentHtmlData) {
1182                 $downLoadPHP = strpos($attachmentHtmlData, "index.php?entryPoint=download&");
1183                 while ($downLoadPHP) {
1184                         $attachmentHtmlData = substr($attachmentHtmlData, $downLoadPHP+30);
1185                         $final = strpos($attachmentHtmlData, "\">");
1186                         $actualAttachmentInfo[] = substr($attachmentHtmlData, 0, $final);
1187                         $attachmentHtmlData = substr($attachmentHtmlData, $final);
1188                         $downLoadPHP = strpos($attachmentHtmlData, "index.php?entryPoint=download&");
1189                 } // while
1190         }
1191         /**
1192          * Renders the QuickCreate form from Smarty and returns HTML
1193          * @param array $vars request variable global
1194          * @param object $email Fetched email object
1195          * @param bool $addToAddressBook
1196          * @return array
1197          */
1198         function getQuickCreateForm($vars, $email, $addToAddressBookButton=false) {
1199                 require_once("include/EditView/EditView2.php");
1200                 global $app_strings;
1201                 global $mod_strings;
1202                 global $current_user;
1203                 global $beanList;
1204                 global $beanFiles;
1205                 global $current_language;
1206
1207                 //Setup the current module languge
1208                 $mod_strings = return_module_language($current_language, $_REQUEST['qc_module']);
1209
1210                 $bean = $beanList[$_REQUEST['qc_module']];
1211                 $class = $beanFiles[$bean];
1212                 require_once($class);
1213
1214                 $focus = new $bean();
1215
1216                 $people = array(
1217                 'Contact'
1218                 ,'Lead'
1219                 );
1220                 $emailAddress = array();
1221
1222                 // people
1223                 if(in_array($bean, $people)) {
1224                         // lead specific
1225                         $focus->lead_source = 'Email';
1226                         $focus->lead_source_description = trim($email->name);
1227
1228                         $from = (isset($email->from_name) && !empty($email->from_name)) ? $email->from_name : $email->from_addr;
1229
1230                         if(isset($_REQUEST['sugarEmail']) && !empty($_REQUEST['sugarEmail']))
1231                 $from = (isset($email->from_name) && !empty($email->from_name)) ? $email->from_name : $email->from_addr_name;
1232
1233
1234                         $name = explode(" ", trim($from));
1235
1236                         $address = trim(array_pop($name));
1237                         $address = str_replace(array("<",">","&lt;","&gt;"), "", $address);
1238
1239                         $emailAddress[] = array(
1240                                 'email_address'         => $address,
1241                                 'primary_address'       => 1,
1242                                 'invalid_email'         => 0,
1243                                 'opt_out'                       => 0,
1244                                 'reply_to_address'      => 1
1245                         );
1246
1247                         $focus->email1 = $address;
1248
1249                         if(!empty($name)) {
1250                                 $focus->last_name = trim(array_pop($name));
1251
1252                                 foreach($name as $first) {
1253                                         if(!empty($focus->first_name)) {
1254                                                 $focus->first_name .= " ";
1255                                         }
1256                                         $focus->first_name .= trim($first);
1257                                 }
1258                         }
1259                 } else {
1260                         // bugs, cases, tasks
1261                         $focus->name = trim($email->name);
1262                 }
1263
1264                 $focus->description = trim(strip_tags($email->description));
1265                 $focus->assigned_user_id = $current_user->id;
1266
1267
1268                 $EditView = new EditView();
1269                 $EditView->ss = new Sugar_Smarty();
1270                 //MFH BUG#20283 - checks for custom quickcreate fields
1271                 $EditView->setup($_REQUEST['qc_module'], $focus, 'custom/modules/'.$focus->module_dir.'/metadata/editviewdefs.php', 'include/EditView/EditView.tpl');
1272                 $EditView->process();
1273                 $EditView->render();
1274
1275                 $EditView->defs['templateMeta']['form']['buttons'] = array(
1276                         'email2save' => array(
1277                                 'id' => 'e2AjaxSave',
1278                                 'customCode' => '<input type="button" class="button" value="   '.$app_strings['LBL_SAVE_BUTTON_LABEL']
1279                                               . '   " onclick="SUGAR.email2.detailView.saveQuickCreate(false);" />'
1280                         ),
1281                         'email2saveandreply' => array(
1282                             'id' => 'e2SaveAndReply',
1283                             'customCode' => '<input type="button" class="button" value="   '.$app_strings['LBL_EMAIL_SAVE_AND_REPLY']
1284                                           . '   " onclick="SUGAR.email2.detailView.saveQuickCreate(\'reply\');" />'
1285                         ),
1286                         'email2cancel' => array(
1287                              'id' => 'e2cancel',
1288                              'customCode' => '<input type="button" class="button" value="   '.$app_strings['LBL_EMAIL_CANCEL']
1289                               . '   " onclick="SUGAR.email2.detailView.quickCreateDialog.hide();" />'
1290                         )
1291                 );
1292
1293
1294                 if($addToAddressBookButton) {
1295                         $EditView->defs['templateMeta']['form']['buttons']['email2saveAddToAddressBook'] = array(
1296                                 'id' => 'e2addToAddressBook',
1297                                 'customCode' => '<input type="button" class="button" value="   '.$app_strings['LBL_EMAIL_ADDRESS_BOOK_SAVE_AND_ADD']
1298                                               . '   " onclick="SUGAR.email2.detailView.saveQuickCreate(true);" />'
1299                         );
1300                 }
1301
1302                 //Get the module language for javascript
1303             if(!is_file($GLOBALS['sugar_config']['cache_dir'] . 'jsLanguage/' . $_REQUEST['qc_module'] . '/' . $GLOBALS['current_language'] . '.js')) {
1304             require_once('include/language/jsLanguage.php');
1305             jsLanguage::createModuleStringsCache($_REQUEST['qc_module'], $GLOBALS['current_language']);
1306         }
1307                 $jsLanguage = '<script type="text/javascript" src="' . $GLOBALS['sugar_config']['cache_dir'] . 'jsLanguage/'
1308                             . $_REQUEST['qc_module'] . '/' . $GLOBALS['current_language'] . '.js?s=' . $GLOBALS['sugar_version'] . '&c='
1309                             . $GLOBALS['sugar_config']['js_custom_version'] . '&j=' . $GLOBALS['sugar_config']['js_lang_version'] . '"></script>';
1310
1311
1312
1313                 $EditView->view = 'EmailQCView';
1314                 $EditView->defs['templateMeta']['form']['headerTpl'] = 'include/EditView/header.tpl';
1315                 $EditView->defs['templateMeta']['form']['footerTpl'] = 'include/EditView/footer.tpl';
1316                 $meta = array();
1317                 $meta['html'] = $jsLanguage . $EditView->display(false, true);
1318                 $meta['html'] = str_replace("src='include/SugarEmailAddress/SugarEmailAddress.js?s={$GLOBALS['js_version_key']}&c={$GLOBALS['sugar_config']['js_custom_version']}'", '', $meta['html']);
1319                 $meta['emailAddress'] = $emailAddress;
1320
1321                 $mod_strings = return_module_language($current_language, 'Emails');
1322
1323                 return $meta;
1324         }
1325
1326         /**
1327      * Renders the Import form from Smarty and returns HTML
1328      * @param array $vars request variable global
1329      * @param object $email Fetched email object
1330      * @param bool $addToAddressBook
1331      * @return array
1332      */
1333     function getImportForm($vars, $email, $formName = 'ImportEditView') {
1334                 require_once("include/EditView/EditView2.php");
1335         require_once("include/TemplateHandler/TemplateHandler.php");
1336                 require_once('include/QuickSearchDefaults.php');
1337                 $qsd = new QuickSearchDefaults();
1338                 $qsd->setFormName($formName);
1339
1340         global $app_strings;
1341         global $current_user;
1342         global $app_list_strings;
1343                 $sqs_objects = array(
1344                                      "{$formName}_parent_name" => $qsd->getQSParent(),
1345                 );
1346         $smarty = new Sugar_Smarty();
1347         $smarty->assign("APP",$app_strings);
1348         $smarty->assign('formName',$formName);
1349         $showAssignTo = false;
1350         if (!isset($vars['showAssignTo']) || $vars['showAssignTo'] == true) {
1351                 $showAssignTo = true;
1352                 } // if
1353                 if ($showAssignTo) {
1354                 if(empty($email->assigned_user_id) && empty($email->id))
1355                     $email->assigned_user_id = $current_user->id;
1356                 if(empty($email->assigned_name) && empty($email->id))
1357                     $email->assigned_user_name = $current_user->user_name;
1358                 $sqs_objects["{$formName}_assigned_user_name"] = $qsd->getQSUser();
1359                 }
1360                 $smarty->assign("showAssignedTo",$showAssignTo);
1361
1362         $showDelete = false;
1363         if (!isset($vars['showDelete']) || $vars['showDelete'] == true) {
1364             $showDelete = true;
1365         }
1366         $smarty->assign("showDelete",$showDelete);
1367
1368         $smarty->assign("userId",$email->assigned_user_id);
1369         $smarty->assign("userName",$email->assigned_user_name);
1370         $parent_types = $app_list_strings['record_type_display'];
1371         $smarty->assign('parentOptions', get_select_options_with_id($parent_types, $email->parent_type));
1372
1373                 $quicksearch_js = '<script type="text/javascript" language="javascript">sqs_objects = ' . json_encode($sqs_objects) . '</script>';
1374         $smarty->assign('SQS', $quicksearch_js);
1375
1376         $meta = array();
1377         $meta['html'] = $smarty->fetch("modules/Emails/templates/importRelate.tpl");
1378         return $meta;
1379     }
1380
1381     /**
1382      * This function returns the detail view for email in new 2.0 interface
1383      *
1384      */
1385     function getDetailViewForEmail2($emailId) {
1386
1387                 require_once('include/DetailView/DetailView.php');
1388                 global $app_strings, $app_list_strings;
1389                 global $mod_strings;
1390
1391         $smarty = new Sugar_Smarty();
1392
1393                 // SETTING DEFAULTS
1394                 $focus          = new Email();
1395                 $focus->retrieve($emailId);
1396                 $detailView->ss = new Sugar_Smarty();
1397                 $detailView     = new DetailView();
1398                 $title = "";
1399                 $offset         = 0;
1400                 if($focus->type == 'out') {
1401                         $title = get_module_title('Emails', $mod_strings['LBL_SENT_MODULE_NAME'].": ".$focus->name, true);
1402                 } elseif ($focus->type == 'draft') {
1403                         $title = get_module_title('Emails', $mod_strings['LBL_LIST_FORM_DRAFTS_TITLE'].": ".$focus->name, true);
1404                 } elseif($focus->type == 'inbound') {
1405                         $title = get_module_title('Emails', $mod_strings['LBL_INBOUND_TITLE'].": ".$focus->name, true);
1406                 }
1407                 $smarty->assign("emailTitle", $title);
1408
1409                 // DEFAULT TO TEXT IF NO HTML CONTENT:
1410                 $html = trim(from_html($focus->description_html));
1411                 if(empty($html)) {
1412                         $smarty->assign('SHOW_PLAINTEXT', 'true');
1413                         $description = nl2br($focus->description);
1414                 } else {
1415                         $smarty->assign('SHOW_PLAINTEXT', 'false');
1416                         $description = from_html($focus->description_html);
1417                 }
1418
1419                 //if not empty or set to test (from test campaigns)
1420                 if (!empty($focus->parent_type) && $focus->parent_type !='test') {
1421                         $smarty->assign('PARENT_MODULE', $focus->parent_type);
1422                         $smarty->assign('PARENT_TYPE', $app_list_strings['record_type_display'][$focus->parent_type] . ":");
1423                 }
1424
1425         global $gridline;
1426                 $smarty->assign('MOD', $mod_strings);
1427                 $smarty->assign('APP', $app_strings);
1428                 $smarty->assign('GRIDLINE', $gridline);
1429                 $smarty->assign('PRINT_URL', 'index.php?'.$GLOBALS['request_string']);
1430                 $smarty->assign('ID', $focus->id);
1431                 $smarty->assign('TYPE', $focus->type);
1432                 $smarty->assign('PARENT_NAME', $focus->parent_name);
1433                 $smarty->assign('PARENT_ID', $focus->parent_id);
1434                 $smarty->assign('NAME', $focus->name);
1435                 $smarty->assign('ASSIGNED_TO', $focus->assigned_user_name);
1436                 $smarty->assign('DATE_MODIFIED', $focus->date_modified);
1437                 $smarty->assign('DATE_ENTERED', $focus->date_entered);
1438                 $smarty->assign('DATE_START', $focus->date_start);
1439                 $smarty->assign('TIME_START', $focus->time_start);
1440                 $smarty->assign('FROM', $focus->from_addr);
1441                 $smarty->assign('TO', nl2br($focus->to_addrs));
1442                 $smarty->assign('CC', nl2br($focus->cc_addrs));
1443                 $smarty->assign('BCC', nl2br($focus->bcc_addrs));
1444                 $smarty->assign('CREATED_BY', $focus->created_by_name);
1445                 $smarty->assign('MODIFIED_BY', $focus->modified_by_name);
1446                 $smarty->assign('DESCRIPTION', nl2br($focus->description));
1447                 $smarty->assign('DESCRIPTION_HTML', from_html($focus->description_html));
1448                 $smarty->assign('DATE_SENT', $focus->date_entered);
1449                 $smarty->assign('EMAIL_NAME', 'RE: '.$focus->name);
1450                 $smarty->assign("TAG", $focus->listviewACLHelper());
1451                 $smarty->assign("SUGAR_VERSION", $GLOBALS['sugar_version']);
1452                 $smarty->assign("JS_CUSTOM_VERSION", $GLOBALS['sugar_config']['js_custom_version']);
1453                 if(!empty($focus->reply_to_email)) {
1454                         $replyTo = "
1455                                 <tr>
1456                         <td class=\"tabDetailViewDL\"><slot>".$mod_strings['LBL_REPLY_TO_NAME']."</slot></td>
1457                         <td colspan=3 class=\"tabDetailViewDF\"><slot>".$focus->reply_to_addr."</slot></td>
1458                         </tr>";
1459                         $smarty->assign("REPLY_TO", $replyTo);
1460                 }
1461                 ///////////////////////////////////////////////////////////////////////////////
1462                 ////    JAVASCRIPT VARS
1463                 $jsVars  = '';
1464                 $jsVars .= "var showRaw = '{$mod_strings['LBL_BUTTON_RAW_LABEL']}';";
1465                 $jsVars .= "var hideRaw = '{$mod_strings['LBL_BUTTON_RAW_LABEL_HIDE']}';";
1466                 $smarty->assign("JS_VARS", $jsVars);
1467                 ///////////////////////////////////////////////////////////////////////////////
1468                 ////    NOTES (attachements, etc.)
1469                 ///////////////////////////////////////////////////////////////////////////////
1470
1471                 $note = new Note();
1472                 $where = "notes.parent_id='{$focus->id}'";
1473                 //take in account if this is from campaign and the template id is stored in the macros.
1474
1475                 if(isset($macro_values) && isset($macro_values['email_template_id'])){
1476                     $where = "notes.parent_id='{$macro_values['email_template_id']}'";
1477                 }
1478                 $notes_list = $note->get_full_list("notes.name", $where, true);
1479
1480                 if(! isset($notes_list)) {
1481                         $notes_list = array();
1482                 }
1483
1484                 $attachments = '';
1485                 for($i=0; $i<count($notes_list); $i++) {
1486                         $the_note = $notes_list[$i];
1487                         //$attachments .= "<a href=\"".UploadFile::get_url($the_note->filename,$the_note->id)."\" target=\"_blank\">".$the_note->name.$the_note->description ."</a><br>";
1488                         $attachments .= "<a href=\"index.php?entryPoint=download&id=".$the_note->id."&type=Notes\">".$the_note->name."</a><br />";
1489                 }
1490                 $smarty->assign("ATTACHMENTS", $attachments);
1491                 ///////////////////////////////////////////////////////////////////////////////
1492                 ////    SUBPANELS
1493                 ///////////////////////////////////////////////////////////////////////////////
1494                 $show_subpanels = true;
1495                 if ($show_subpanels) {
1496                     require_once('include/SubPanel/SubPanelTiles.php');
1497                     $subpanel = new SubPanelTiles($focus, 'Emails');
1498                     $smarty->assign("SUBPANEL", $subpanel->display());
1499                 }
1500         $meta['html'] = $smarty->fetch("modules/Emails/templates/emailDetailView.tpl");
1501         return $meta;
1502
1503     } // fn
1504
1505         /**
1506          * Sets the "read" flag in the overview cache
1507          */
1508         function setReadFlag($ieId, $mbox, $uid) {
1509                 $this->markEmails('read', $ieId, $mbox, $uid);
1510         }
1511
1512         /**
1513          * Marks emails with the passed flag type.  This will be applied to local
1514          * cache files as well as remote emails.
1515          * @param string $type Flag type
1516          * @param string $ieId
1517          * @param string $folder IMAP folder structure or SugarFolder GUID
1518          * @param string $uids Comma sep list of UIDs or GUIDs
1519          */
1520         function markEmails($type, $ieId, $folder, $uids) {
1521
1522                 global $app_strings;
1523                 $uids = $this->_cleanUIDList($uids);
1524                 $exUids = explode($app_strings['LBL_EMAIL_DELIMITER'], $uids);
1525
1526                 if(strpos($folder, 'sugar::') !== false) {
1527                         // dealing with a sugar email object, uids are GUIDs
1528                         foreach($exUids as $id) {
1529                                 $email = new Email();
1530                                 $email->retrieve($id);
1531
1532                                 switch($type) {
1533                                         case "unread":
1534                                                 $email->status = 'unread';
1535                                                 $email->save();
1536                                         break;
1537
1538                                         case "read":
1539                                                 $email->status = 'read';
1540                                                 $email->save();
1541                                         break;
1542
1543                                         case "deleted":
1544                                                 $email->delete();
1545                                         break;
1546
1547                                         case "flagged":
1548                                                 $email->flagged = 1;
1549                                                 $email->save();
1550                                         break;
1551
1552                                         case "unflagged":
1553                                                 $email->flagged = 0;
1554                                                 $email->save();
1555                                         break;
1556
1557                                 }
1558                         }
1559                 } else {
1560                         /* dealing with IMAP email, uids are IMAP uids */
1561                         global $ie; // provided by EmailUIAjax.php
1562                         if(empty($ie)) {
1563
1564                                 $ie = new InboundEmail();
1565                         }
1566                         $ie->retrieve($ieId);
1567                         $ie->mailbox = $folder;
1568                         $ie->connectMailserver();
1569                         // mark cache files
1570                         if($type == 'deleted') {
1571                                 $ie->deleteMessageOnMailServer($uids);
1572                                 $ie->deleteMessageFromCache($uids);
1573                         } else {
1574                                 $overviews = $ie->getCacheValueForUIDs($ie->mailbox, $exUids);
1575                                 $manipulated = array();
1576
1577                                 foreach($overviews['retArr'] as $k => $overview) {
1578                                         if(in_array($overview->uid, $exUids)) {
1579                                                 switch($type) {
1580                                                         case "unread":
1581                                                                 $overview->seen = 0;
1582                                                         break;
1583
1584                                                         case "read":
1585                                                                 $overview->seen = 1;
1586                                                         break;
1587
1588                                                         case "flagged":
1589                                                                 $overview->flagged = 1;
1590                                                         break;
1591
1592                                                         case "unflagged":
1593                                                                 $overview->flagged = 0;
1594                                                         break;
1595                                                 }
1596                                                 $manipulated[] = $overview;
1597                                         }
1598                                 }
1599
1600                                 if(!empty($manipulated)) {
1601                                         $ie->setCacheValue($ie->mailbox, array(), $manipulated);
1602                                         /* now mark emails on email server */
1603                                         $ie->markEmails(implode(",", explode($app_strings['LBL_EMAIL_DELIMITER'], $uids)), $type);
1604                                 }
1605                         } // end not type == deleted
1606                 }
1607         }
1608
1609 function doAssignment($distributeMethod, $ieid, $folder, $uids, $users) {
1610         global $app_strings;
1611         $users = explode(",", $users);
1612         $emailIds = explode($app_strings['LBL_EMAIL_DELIMITER'], $uids);
1613         $out = "";
1614         if($folder != 'sugar::Emails') {
1615                 $emailIds = array();
1616                 $uids = explode($app_strings['LBL_EMAIL_DELIMITER'], $uids);
1617                 $ie = new InboundEmail();
1618                 $ie->retrieve($ieid);
1619                 $messageIndex = 1;
1620                 // dealing with an inbound email data so we need to import an email and then
1621                 foreach($uids as $uid) {
1622                         $ie->mailbox = $folder;
1623                         $ie->connectMailserver();
1624                         $msgNo = $uid;
1625                         if (!$ie->isPop3Protocol()) {
1626                                 $msgNo = imap_msgno($ie->conn, $uid);
1627                         } else {
1628                                 $msgNo = $ie->getCorrectMessageNoForPop3($uid);
1629                         }
1630
1631                         if(!empty($msgNo)) {
1632                                 if ($ie->importOneEmail($msgNo, $uid)) {
1633                                         $emailIds[] = $ie->email->id;
1634                                         $ie->deleteMessageOnMailServer($uid);
1635                                         //$ie->retrieve($ieid);
1636                                         //$ie->connectMailserver();
1637                                         $ie->mailbox = $folder;
1638                                         $ie->deleteMessageFromCache(($uids[] = $uid));
1639                                 } else {
1640                                         $out = $out . "Message No : " . $messageIndex . " failed. Reason : Message already imported \r\n";
1641                                 }
1642                         }
1643                         $messageIndex++;
1644                 } // for
1645         } // if
1646
1647         if (count($emailIds) > 0) {
1648                 $this->doDistributionWithMethod($users, $emailIds, $distributeMethod);
1649         } // if
1650         return $out;
1651 } // fn
1652
1653 /**
1654  * get team id and team set id from request
1655  * @return  array
1656  */
1657 function getTeams() {
1658 }
1659
1660 function doDistributionWithMethod($users, $emailIds, $distributionMethod) {
1661         // we have users and the items to distribute
1662         if($distributionMethod == 'roundRobin') {
1663                 $this->distRoundRobin($users, $emailIds);
1664         } elseif($distributionMethod == 'leastBusy') {
1665                 $this->distLeastBusy($users, $emailIds);
1666         } elseif($distributionMethod == 'direct') {
1667                 if(count($users) > 1) {
1668                         // only 1 user allowed in direct assignment
1669                         $error = 1;
1670                 } else {
1671                         $user = $users[0];
1672                         $this->distDirect($user, $emailIds);
1673                 } // else
1674         } // elseif
1675
1676 } // fn
1677
1678 /**
1679  * distributes emails to users on Round Robin basis
1680  * @param       $userIds        array of users to dist to
1681  * @param       $mailIds        array of email ids to push on those users
1682  * @return  boolean             true on success
1683  */
1684 function distRoundRobin($userIds, $mailIds) {
1685         // check if we have a 'lastRobin'
1686         $lastRobin = $userIds[0];
1687         foreach($mailIds as $k => $mailId) {
1688                 $userIdsKeys = array_flip($userIds); // now keys are values
1689                 $thisRobinKey = $userIdsKeys[$lastRobin] + 1;
1690                 if(!empty($userIds[$thisRobinKey])) {
1691                         $thisRobin = $userIds[$thisRobinKey];
1692                         $lastRobin = $userIds[$thisRobinKey];
1693                 } else {
1694                         $thisRobin = $userIds[0];
1695                         $lastRobin = $userIds[0];
1696                 }
1697
1698                 $email = new Email();
1699                 $email->retrieve($mailId);
1700                 $email->assigned_user_id = $thisRobin;
1701                 $email->status = 'unread';
1702                 $email->save();
1703         }
1704
1705         return true;
1706 }
1707
1708 /**
1709  * distributes emails to users on Least Busy basis
1710  * @param       $userIds        array of users to dist to
1711  * @param       $mailIds        array of email ids to push on those users
1712  * @return  boolean             true on success
1713  */
1714 function distLeastBusy($userIds, $mailIds) {
1715         foreach($mailIds as $k => $mailId) {
1716                 $email = new Email();
1717                 $email->retrieve($mailId);
1718                 foreach($userIds as $k => $id) {
1719                         $r = $this->db->query("SELECT count(*) AS c FROM emails WHERE assigned_user_id = '.$id.' AND status = 'unread'");
1720                         $a = $this->db->fetchByAssoc($r);
1721                         $counts[$id] = $a['c'];
1722                 }
1723                 asort($counts); // lowest to highest
1724                 $countsKeys = array_flip($counts); // keys now the 'count of items'
1725                 $leastBusy = array_shift($countsKeys); // user id of lowest item count
1726                 $email->assigned_user_id = $leastBusy;
1727                 $email->status = 'unread';
1728                 $email->save();
1729         }
1730         return true;
1731 }
1732
1733 /**
1734  * distributes emails to 1 user
1735  * @param       $user           users to dist to
1736  * @param       $mailIds        array of email ids to push
1737  * @return  boolean             true on success
1738  */
1739 function distDirect($user, $mailIds) {
1740         foreach($mailIds as $k => $mailId) {
1741                 $email = new Email();
1742                 $email->retrieve($mailId);
1743                 $email->assigned_user_id = $user;
1744                 $email->status = 'unread';
1745
1746                 $email->save();
1747         }
1748         return true;
1749 }
1750
1751 function getAssignedEmailsCountForUsers($userIds) {
1752         $counts = array();
1753         foreach($userIds as $id) {
1754                 $r = $this->db->query("SELECT count(*) AS c FROM emails WHERE assigned_user_id = '$id' AND status = 'unread'");
1755                 $a = $this->db->fetchByAssoc($r);
1756                 $counts[$id] = $a['c'];
1757         } // foreach
1758         return $counts;
1759 } // fn
1760
1761 function getLastRobin($ie) {
1762         $lastRobin = "";
1763         if($this->validCacheFileExists($ie->id, 'folders', "robin.cache.php")) {
1764                 $lastRobin = $this->getCacheValue($ie->id, 'folders', "robin.cache.php", 'robin');
1765         } // if
1766         return $lastRobin;
1767 } // fn
1768
1769 function setLastRobin($ie, $lastRobin) {
1770     global $sugar_config;
1771     $cacheFolderPath = clean_path("{$sugar_config['cache_dir']}modules/Emails/{$ie->id}/folders");
1772     if (!file_exists($cacheFolderPath)) {
1773         mkdir_recursive($cacheFolderPath);
1774     }
1775         $this->writeCacheFile('robin', $lastRobin, $ie->id, 'folders', "robin.cache.php");
1776 } // fn
1777
1778         /**
1779          * returns the metadata defining a single email message for display.  Uses cache file if it exists
1780          * @return array
1781          */
1782 function getSingleMessage($ie) {
1783
1784                 global $timedate;
1785                 global $app_strings,$mod_strings;
1786                 $ie->retrieve($_REQUEST['ieId']);
1787                 $noCache = true;
1788
1789                 $ie->mailbox = $_REQUEST['mbox'];
1790                 $filename = $_REQUEST['mbox'].$_REQUEST['uid'].".php";
1791                 $md5uidl = "";
1792                 if ($ie->isPop3Protocol()) {
1793                         $md5uidl = md5($_REQUEST['uid']);
1794                         $filename = $_REQUEST['mbox'].$md5uidl.".php";
1795                 } // if
1796
1797                 if($this->validCacheFileExists($_REQUEST['ieId'], 'messages', $filename)) {
1798                         $out = $this->getCacheValue($_REQUEST['ieId'], 'messages', $filename, 'out');
1799                         $noCache = false;
1800
1801                         // something fubar'd the cache?
1802                         if(empty($out['meta']['email']['name']) && empty($out['meta']['email']['description'])) {
1803                                 $noCache = true;
1804                         } else {
1805                                 // When sending data from cache, convert date into users preffered format
1806                                 $dateTimeInGMTFormat = $out['meta']['email']['date_start'];
1807                                 $out['meta']['email']['date_start'] = $timedate->to_display_date_time($dateTimeInGMTFormat);
1808                         } // else
1809                 }
1810
1811                 if($noCache) {
1812                         $writeToCacheFile = true;
1813                         if ($ie->isPop3Protocol()) {
1814                                 $status = $ie->setEmailForDisplay($_REQUEST['uid'], true, true, true);
1815                         } else {
1816                                 $status = $ie->setEmailForDisplay($_REQUEST['uid'], false, true, true);
1817                         }
1818                         $out = $ie->displayOneEmail($_REQUEST['uid'], $_REQUEST['mbox']);
1819                         // modify the out object to store date in GMT format on the local cache file
1820                         $dateTimeInUserFormat = $out['meta']['email']['date_start'];
1821                         $out['meta']['email']['date_start'] = $timedate->to_db_date($dateTimeInUserFormat) . " " . $timedate->to_db_time($dateTimeInUserFormat);
1822                         if ($status == 'error') {
1823                                 $writeToCacheFile = false;
1824                         }
1825                         if ($writeToCacheFile) {
1826                                 if ($ie->isPop3Protocol()) {
1827                                         $this->writeCacheFile('out', $out, $_REQUEST['ieId'], 'messages', "{$_REQUEST['mbox']}{$md5uidl}.php");
1828                                 } else {
1829                                         $this->writeCacheFile('out', $out, $_REQUEST['ieId'], 'messages', "{$_REQUEST['mbox']}{$_REQUEST['uid']}.php");
1830                                 } // else
1831                         // restore date in the users preferred format to be send on to UI for diaply
1832                         $out['meta']['email']['date_start'] = $dateTimeInUserFormat;
1833                         } // if
1834                 }
1835                 $out['meta']['email']['toaddrs'] = $this->generateExpandableAddrs($out['meta']['email']['toaddrs']);
1836                 if(!empty($out['meta']['email']['cc_addrs'])) {
1837             $ccs = $this->generateExpandableAddrs($out['meta']['email']['cc_addrs']);
1838                     $out['meta']['cc'] = <<<eoq
1839                                 <tr>
1840                                         <td NOWRAP valign="top" class="displayEmailLabel">
1841                                                 {$app_strings['LBL_EMAIL_CC']}:
1842                                         </td>
1843                                         <td class="displayEmailValue">
1844                                                 {$ccs}
1845                                         </td>
1846                                 </tr>
1847 eoq;
1848                 }
1849
1850                  if(empty($out['meta']['email']['description']))
1851                 $out['meta']['email']['description'] = $mod_strings['LBL_EMPTY_EMAIL_BODY'];
1852
1853                 if($noCache) {
1854                         $GLOBALS['log']->debug("EMAILUI: getSingleMessage() NOT using cache file");
1855                 } else {
1856                         $GLOBALS['log']->debug("EMAILUI: getSingleMessage() using cache file [ ".$_REQUEST['mbox'].$_REQUEST['uid'].".php ]");
1857                 }
1858
1859                 $this->setReadFlag($_REQUEST['ieId'], $_REQUEST['mbox'], $_REQUEST['uid']);
1860                 return $out;
1861         }
1862
1863
1864         /**
1865          * Returns the HTML for a list of emails in a given folder
1866          * @param GUID $ieId GUID to InboundEmail instance
1867          * @param string $mbox Mailbox path name in dot notation
1868          * @param int $folderListCacheOffset Seconds for valid cache file
1869          * @return string HTML render of list.
1870          */
1871         function getListEmails($ieId, $mbox, $folderListCacheOffset, $forceRefresh='false') {
1872                 global $sugar_config;
1873
1874
1875                 $ie = new InboundEmail();
1876                 $ie->retrieve($ieId);
1877                 $list = $ie->displayFolderContents($mbox, $forceRefresh);
1878
1879                 return $list;
1880         }
1881
1882         /**
1883          * Returns the templatized compose screen.  Used by reply, forwards and draft status messages.
1884          * @param object email Email bean in focus
1885          */
1886         function displayComposeEmail($email) {
1887                 global $locale;
1888                 global $current_user;
1889
1890
1891                 $ea = new SugarEmailAddress();
1892
1893                 if(!empty($email)) {
1894                         $description = (empty($email->description_html)) ? $email->description : $email->description_html;
1895                 }
1896
1897                 //Get the most complete address list availible for this email
1898                 $addresses = array('toAddresses' => 'to', 'ccAddresses' => 'cc', 'bccAddresses' => 'bcc');
1899                 foreach($addresses as $var => $type)
1900                 {
1901                         $$var = "";
1902                         foreach (array("{$type}_addrs_names", "{$type}addrs", "{$type}_addrs") as $emailVar)
1903                         {
1904                                 if (!empty($email->$emailVar)) {
1905                                         $$var = $email->$emailVar;
1906                                         break;
1907                                 }
1908                         }
1909                 }
1910
1911                 $ret = array();
1912                 $ret['type'] = $email->type;
1913                 $ret['name'] = $email->name;
1914                 $ret['description'] = $description;
1915                 $ret['from'] = (isset($_REQUEST['composeType']) && $_REQUEST['composeType'] == 'forward') ? "" : $email->from_addr;
1916                 $ret['to'] = from_html($toAddresses);
1917                 $ret['uid'] = $email->id;
1918                 $ret['parent_name'] = $email->parent_name;
1919                 $ret['parent_type'] = $email->parent_type;
1920                 $ret['parent_id'] = $email->parent_id;
1921
1922                 // reply all
1923                 if(isset($_REQUEST['composeType']) && $_REQUEST['composeType'] == 'replyAll') {
1924                     $ret['cc'] = from_html($ccAddresses);
1925                     $ret['bcc'] = $bccAddresses;
1926
1927                         $userEmails = array();
1928                         $userEmailsMeta = $ea->getAddressesByGUID($current_user->id, 'Users');
1929                         foreach($userEmailsMeta as $emailMeta) {
1930                                 $userEmails[] = from_html(strtolower(trim($emailMeta['email_address'])));
1931                         }
1932                         $userEmails[] = from_html(strtolower(trim($email->from_addr)));
1933
1934                         $ret['cc'] = from_html($email->cc_addrs);
1935                         $toAddresses = from_html($toAddresses);
1936                         $to = str_replace($this->addressSeparators, "::", $toAddresses);
1937                         $exTo = explode("::", $to);
1938
1939                         if(is_array($exTo)) {
1940                                 foreach($exTo as $addr) {
1941                                         $addr = strtolower(trim($addr));
1942                                         if(!in_array($addr, $userEmails)) {
1943                                                 if(!empty($ret['cc'])) {
1944                                                         $ret['cc'] = $ret['cc'].", ";
1945                                                 }
1946                                                 $ret['cc'] = $ret['cc'].trim($addr);
1947                                         }
1948                                 }
1949                         } elseif(!empty($exTo)) {
1950                                 $exTo = trim($exTo);
1951                                 if(!in_array($exTo, $userEmails)) {
1952                                         $ret['cc'] = $ret['cc'].", ".$exTo;
1953                                 }
1954                         }
1955                 }
1956                 return $ret;
1957         }
1958         /**
1959          * Formats email body on reply/forward
1960          * @param object email Email object in focus
1961          * @param string type
1962          * @return object email
1963          */
1964         function handleReplyType($email, $type) {
1965                 global $mod_strings;
1966                  $GLOBALS['log']->debug("****At Handle Reply Type: $type");
1967                 switch($type) {
1968                         case "reply":
1969                         case "replyAll":
1970                                 $header = $email->getReplyHeader();
1971                 if(!preg_match('/^(re:)+/i', $email->name)) {
1972                     $email->name = "{$mod_strings['LBL_RE']} {$email->name}";
1973                 }
1974                                 if ($type == "reply") {
1975                                         $email->cc_addrs = "";
1976                                         if (!empty($email->reply_to_addr)) {
1977                                                 $email->from_addr = $email->reply_to_addr;
1978                                         } // if
1979                                 } else {
1980                                         if (!empty($email->reply_to_addr)) {
1981                                                 $email->to_addrs = $email->to_addrs . "," . $email->reply_to_addr;
1982                                         } // if
1983                                 } // else
1984                         break;
1985
1986                         case "forward":
1987                                 $header = $email->getForwardHeader();
1988                                 if(!preg_match('/^(fw:)+/i', $email->name)) {
1989                     $email->name = "{$mod_strings['LBL_FW']} {$email->name}";
1990                 }
1991                                 $email->cc_addrs = "";
1992                         break;
1993
1994                         case "replyCase":
1995                                 $GLOBALS['log']->debug("EMAILUI: At reply case");
1996                                 $header = $email->getReplyHeader();
1997
1998                 $myCase = new aCase();
1999                 $myCase->retrieve($email->parent_id);
2000                 $myCaseMacro = $myCase->getEmailSubjectMacro();
2001                 $email->parent_name = $myCase->name;
2002                 $GLOBALS['log']->debug("****Case # : {$myCase->case_number} macro: $myCaseMacro");
2003                                 if(!strpos($email->name, str_replace('%1',$myCase->case_number,$myCaseMacro))) {
2004                                 $GLOBALS['log']->debug("Replacing");
2005                             $email->name = str_replace('%1',$myCase->case_number,$myCaseMacro) . ' '. $email->name;
2006                         }
2007                 $email->name = "{$mod_strings['LBL_RE']} {$email->name}";
2008             break;
2009                 }
2010
2011                 $html = trim($email->description_html);
2012                 $plain = trim($email->description);
2013
2014                 $desc = (!empty($html)) ? $html : $plain;
2015
2016                 $email->description = $header.$email->quoteHtmlEmailForNewEmailUI($desc);
2017                 return $email;
2018
2019         }
2020
2021         ///////////////////////////////////////////////////////////////////////////
2022         ////    PRIVATE HELPERS
2023         /**
2024          * Generates a UNION query to get one list of users, contacts, leads, and
2025          * prospects; used specifically for the addressBook
2026          */
2027         function _getPeopleUnionQuery($whereArr , $person) {
2028                 global $current_user , $app_strings;
2029                 global $db;
2030                 if(!isset($person) || $person === 'LBL_DROPDOWN_LIST_ALL'){
2031                         $peopleTables = array("users",
2032                                               "contacts",
2033                                               "leads",
2034                                               "prospects",
2035                                               "accounts"
2036                                              );
2037                 }else{
2038                         $peopleTables = array($person);
2039                 }
2040                 $q = '';
2041
2042                 $whereAdd = "";
2043
2044                 foreach($whereArr as $column => $clause) {
2045                         if(!empty($whereAdd)) {
2046                                 $whereAdd .= " AND ";
2047                         }
2048                         $clause = $current_user->db->helper->escape_quote($clause);
2049                         $whereAdd .= "{$column} LIKE '{$clause}%'";
2050                 }
2051
2052
2053                 foreach($peopleTables as $table) {
2054                         $module = ucfirst($table);
2055             $class = substr($module, 0, strlen($module) - 1);
2056             require_once("modules/{$module}/{$class}.php");
2057             $person = new $class();
2058                         if (!$person->ACLAccess('list')) {
2059                                 continue;
2060                         } // if
2061                         $where = "({$table}.deleted = 0 AND eabr.primary_address = 1 AND {$table}.id <> '{$current_user->id}')";
2062
2063             if (ACLController::requireOwner($module, 'list')) {
2064                 $where = $where . " AND ({$table}.assigned_user_id = '{$current_user->id}')";
2065             } // if
2066                         if(!empty($whereAdd)) {
2067                                 $where .= " AND ({$whereAdd})";
2068                         }
2069
2070                         if ($person === 'accounts') {
2071                                 $t = "SELECT {$table}.id, '' first_name, {$table}.name, eabr.primary_address, ea.email_address, '{$module}' module ";
2072                         } else {
2073                                 $t = "SELECT {$table}.id, {$table}.first_name, {$table}.last_name, eabr.primary_address, ea.email_address, '{$module}' module ";
2074                         }
2075                         $t .= "FROM {$table} ";
2076                         $t .= "JOIN email_addr_bean_rel eabr ON ({$table}.id = eabr.bean_id and eabr.deleted=0) ";
2077                         $t .= "JOIN email_addresses ea ON (eabr.email_address_id = ea.id) ";
2078                         $t .= " WHERE {$where}";
2079
2080                         if(!empty($q)) {
2081                                 $q .= "\n UNION ALL \n";
2082                         }
2083
2084                         $q .= "({$t})";
2085                 }
2086                 $countq = "SELECT count(people.id) c from ($q) people";
2087                 $q .= "ORDER BY last_name";
2088
2089                 return array('query' => $q, 'countQuery' => $countq);
2090     }
2091
2092     /**
2093      * get emails of related bean for a given bean id
2094      * @param $beanType
2095      * @param $condition array of conditions inclued bean id
2096      * @return array('query' => $q, 'countQuery' => $countq);
2097      */
2098     function getRelatedEmail($beanType, $whereArr, $relatedBeanInfoArr = ''){
2099         global $beanList, $current_user, $app_strings, $db;
2100         $finalQuery = '';
2101                 $searchBeans = null;
2102                 if($beanType === 'LBL_DROPDOWN_LIST_ALL')
2103                         $searchBeans = array("users",
2104                                              "contacts",
2105                                              "leads",
2106                                              "prospects",
2107                                              "accounts"
2108                                             );
2109
2110         if ($relatedBeanInfoArr == '' || empty($relatedBeanInfoArr['related_bean_type']) )
2111         {
2112                         if ($searchBeans != null)
2113                         {
2114                                 $q = array();
2115                                 foreach ($searchBeans as $searchBean)
2116                                 {
2117                                         $q[] = '('.$this->findEmailFromBeanIds('', $searchBean, $whereArr).')';
2118                                 }
2119                                 if (!empty($q))
2120                             $finalQuery .= implode("\n UNION ALL \n", $q);
2121                         }
2122                         else
2123                                 $finalQuery = $this->findEmailFromBeanIds('', $beanType, $whereArr);
2124         }
2125         else
2126         {
2127             $class = $beanList[$relatedBeanInfoArr['related_bean_type']];
2128             $focus = new $class();
2129             $focus->retrieve($relatedBeanInfoArr['related_bean_id']);
2130             if ($searchBeans != null)
2131             {
2132                 $q = array();
2133                 foreach ($searchBeans as $searchBean)
2134                 {
2135                     if ($focus->load_relationship($searchBean))
2136                     {
2137                         $data = $focus->$searchBean->get();
2138                         if (count($data) != 0)
2139                         $q[] = '('.$this->findEmailFromBeanIds($data, $searchBean, $whereArr).')';
2140                     }
2141                 }
2142                 if (!empty($q))
2143                 $finalQuery .= implode("\n UNION ALL \n", $q);
2144             }
2145             else
2146             {
2147                 if ($focus->load_relationship($beanType))
2148                 {
2149                     $data = $focus->$beanType->get();
2150                     if (count($data) != 0)
2151                     $finalQuery = $this->findEmailFromBeanIds($data, $beanType, $whereArr);
2152                 }
2153             }
2154         }
2155         $countq = "SELECT count(people.id) c from ($finalQuery) people";
2156                 return array('query' => $finalQuery, 'countQuery' => $countq);
2157     }
2158
2159     function findEmailFromBeanIds($beanIds, $beanType, $whereArr) {
2160         global $current_user;
2161                 $q = '';
2162                 $whereAdd = "";
2163                 $relatedIDs = '';
2164                 if ($beanIds != '') {
2165                         foreach ($beanIds as $key => $value) {
2166                                 $beanIds[$key] = '\''.$value.'\'';
2167                         }
2168                         $relatedIDs = implode(',', $beanIds);
2169                 }
2170
2171                 if ($beanType == 'accounts') {
2172                         if (isset($whereArr['first_name'])) {
2173                                 $whereArr['name'] = $whereArr['first_name'];
2174                         }
2175                         unset($whereArr['last_name']);
2176                         unset($whereArr['first_name']);
2177                 }
2178
2179                 foreach($whereArr as $column => $clause) {
2180                         if(!empty($whereAdd)) {
2181                                 $whereAdd .= " OR ";
2182                         }
2183                         $clause = $current_user->db->helper->escape_quote($clause);
2184                         $whereAdd .= "{$column} LIKE '{$clause}%'";
2185                 }
2186                 $table = $beanType;
2187                 $module = ucfirst($table);
2188             $class = substr($module, 0, strlen($module) - 1);
2189             require_once("modules/{$module}/{$class}.php");
2190             $person = new $class();
2191                 if ($person->ACLAccess('list')) {
2192                         if ($relatedIDs != '') {
2193                                 $where = "({$table}.deleted = 0 AND eabr.primary_address = 1 AND {$table}.id in ($relatedIDs))";
2194                         } else {
2195                                 $where = "({$table}.deleted = 0 AND eabr.primary_address = 1)";
2196                         }
2197
2198                         if (ACLController::requireOwner($module, 'list')) {
2199                                 $where = $where . " AND ({$table}.assigned_user_id = '{$current_user->id}')";
2200                         } // if
2201                         if(!empty($whereAdd)) {
2202                                 $where .= " AND ({$whereAdd})";
2203                         }
2204
2205                         if ($beanType === 'accounts') {
2206                                 $t = "SELECT {$table}.id, '' first_name, {$table}.name last_name, eabr.primary_address, ea.email_address, '{$module}' module ";
2207                         } else {
2208                                 $t = "SELECT {$table}.id, {$table}.first_name, {$table}.last_name, eabr.primary_address, ea.email_address, '{$module}' module ";
2209                         }
2210
2211                         $t .= "FROM {$table} ";
2212                         $t .= "JOIN email_addr_bean_rel eabr ON ({$table}.id = eabr.bean_id and eabr.deleted=0) ";
2213                         $t .= "JOIN email_addresses ea ON (eabr.email_address_id = ea.id) ";
2214                         $t .= " WHERE {$where}";
2215                 } // if
2216                 return $t;
2217     }
2218
2219         /**
2220          * Cleans UID lists
2221          * @param mixed $uids
2222          * @param bool $returnString False will return an array
2223          * @return mixed
2224          */
2225         function _cleanUIDList($uids, $returnString=false) {
2226                 global $app_strings;
2227                 $GLOBALS['log']->debug("_cleanUIDList: before - [ {$uids} ]");
2228
2229                 if(!is_array($uids)) {
2230                         $returnString = true;
2231
2232                         $exUids = explode($app_strings['LBL_EMAIL_DELIMITER'], $uids);
2233                         $uids = $exUids;
2234                 }
2235
2236                 $cleanUids = array();
2237                 foreach($uids as $uid) {
2238                         $cleanUids[$uid] = $uid;
2239                 }
2240
2241                 sort($cleanUids);
2242
2243                 if($returnString) {
2244                         $cleanImplode = implode($app_strings['LBL_EMAIL_DELIMITER'], $cleanUids);
2245                         $GLOBALS['log']->debug("_cleanUIDList: after - [ {$cleanImplode} ]");
2246                         return $cleanImplode;
2247                 }
2248
2249                 return $cleanUids;
2250         }
2251
2252         /**
2253          * Creates defaults for the User
2254          * @param object $user User in focus
2255          */
2256         function preflightUser(&$user) {
2257                 global $mod_strings;
2258
2259                 $goodToGo = $user->getPreference("email2Preflight", "Emails");
2260                         $q = "SELECT count(*) count FROM folders f where f.created_by = '{$user->id}' AND f.folder_type = 'inbound' AND f.deleted = 0";
2261                         $r = $user->db->query($q);
2262                         $a = $user->db->fetchByAssoc($r);
2263
2264                         if($a['count'] < 1) {
2265                                 require_once("include/SugarFolders/SugarFolders.php");
2266                                 // My Emails
2267                                 $folder = new SugarFolder();
2268                                 $folder->new_with_id = true;
2269                                 $folder->id = create_guid();
2270                                 $folder->name = $mod_strings['LNK_MY_INBOX'];
2271                                 $folder->has_child = 1;
2272                                 $folder->created_by = $user->id;
2273                                 $folder->modified_by = $user->id;
2274                                 $folder->is_dynamic = 1;
2275                                 $folder->folder_type = "inbound";
2276                                 $folder->dynamic_query = $this->generateDynamicFolderQuery('inbound', $user->id);
2277                                 $folder->save();
2278
2279                                 // My Drafts
2280                                 $drafts = new SugarFolder();
2281                                 $drafts->name = $mod_strings['LNK_MY_DRAFTS'];
2282                                 $drafts->has_child = 0;
2283                                 $drafts->parent_folder = $folder->id;
2284                                 $drafts->created_by = $user->id;
2285                                 $drafts->modified_by = $user->id;
2286                                 $drafts->is_dynamic = 1;
2287                                 $drafts->folder_type = "draft";
2288                                 $drafts->dynamic_query = $this->generateDynamicFolderQuery('draft', $user->id);
2289                                 $drafts->save();
2290
2291
2292                                 // Sent Emails
2293                                 $archived = new SugarFolder();
2294                                 $archived->name = $mod_strings['LNK_SENT_EMAIL_LIST'];
2295                                 $archived->has_child = 0;
2296                                 $archived->parent_folder = $folder->id;
2297                                 $archived->created_by = $user->id;
2298                                 $archived->modified_by = $user->id;
2299                                 $archived->is_dynamic = 1;
2300                                 $archived->folder_type = "sent";
2301                                 $archived->dynamic_query = $this->generateDynamicFolderQuery('sent', $user->id);
2302                                 $archived->save();
2303
2304                         // set flag to show that this was run
2305                         $user->setPreference("email2Preflight", true, 1, "Emails");
2306                 }
2307         }
2308
2309         /**
2310          * Parses the core dynamic folder query
2311          * @param string $type 'inbound', 'draft', etc.
2312          * @param string $userId
2313          * @return string
2314          */
2315         function generateDynamicFolderQuery($type, $userId) {
2316                 $q = $this->coreDynamicFolderQuery;
2317
2318                 $status = $type;
2319
2320                 if($type == "sent") {
2321                         $type = "out";
2322                 }
2323
2324                 $replacee = array("::TYPE::", "::STATUS::", "::USER_ID::");
2325                 $replacer = array($type, $status, $userId);
2326
2327                 $ret = str_replace($replacee, $replacer, $q);
2328
2329                 if($type == 'inbound') {
2330                         $ret .= " AND status NOT IN ('sent', 'archived', 'draft') AND type NOT IN ('out', 'archived', 'draft')";
2331                 } else {
2332                         $ret .= " AND status NOT IN ('archived') AND type NOT IN ('archived')";
2333                 }
2334
2335                 return $ret;
2336         }
2337
2338         /**
2339          * Preps the User's cache dir
2340          */
2341         function preflightUserCache() {
2342                 $path = clean_path($this->userCacheDir);
2343                 if(!file_exists($this->userCacheDir))
2344                         mkdir_recursive($path);
2345
2346                 $files = findAllFiles($path, array());
2347
2348                 foreach($files as $file) {
2349                         unlink($file);
2350                 }
2351         }
2352
2353         function clearInboundAccountCache($ieId) {
2354                 global $sugar_config;
2355                 $cacheRoot = getcwd()."/{$sugar_config['cache_dir']}modules/Emails/{$ieId}";
2356                 $files = findAllFiles($cacheRoot."/messages/", array());
2357                 foreach($files as $file) {
2358                         unlink($file);
2359                 } // fn
2360                 $files = findAllFiles($cacheRoot."/attachments/", array());
2361                 foreach($files as $file) {
2362                         unlink($file);
2363                 } // for
2364         } // fn
2365
2366         /**
2367          * returns an array of EmailTemplates that the user has access to for the compose email screen
2368          * @return array
2369          */
2370         function getEmailTemplatesArray() {
2371
2372                 global $app_strings;
2373
2374                 if(ACLController::checkAccess('EmailTemplates', 'list', true) && ACLController::checkAccess('EmailTemplates', 'view', true)) {
2375                         $et = new EmailTemplate();
2376                         $etResult = $et->db->query($et->create_new_list_query('','',array(),array(),''));
2377                         $email_templates_arr = array('' => $app_strings['LBL_NONE']);
2378                         while($etA = $et->db->fetchByAssoc($etResult)) {
2379                                 $email_templates_arr[$etA['id']] = $etA['name'];
2380                         }
2381                 } else {
2382                         $email_templates_arr = array('' => $app_strings['LBL_NONE']);
2383                 }
2384
2385                 return $email_templates_arr;
2386         }
2387
2388         function getFromAccountsArray($ie) {
2389         global $current_user;
2390         global $app_strings;
2391
2392         $ieAccountsFull = $ie->retrieveAllByGroupIdWithGroupAccounts($current_user->id);
2393         $ieAccountsFrom= array();
2394
2395         $oe = new OutboundEmail();
2396         $system = $oe->getSystemMailerSettings();
2397         $ret = $current_user->getUsersNameAndEmail();
2398                 $ret['name'] = from_html($ret['name']);
2399                 $useMyAccountString = true;
2400
2401         if(empty($ret['email'])) {
2402                 $systemReturn = $current_user->getSystemDefaultNameAndEmail();
2403                 $ret['email'] = $systemReturn['email'];
2404                 $ret['name'] = from_html($systemReturn['name']);
2405                 $useMyAccountString = false;
2406                 } // if
2407
2408                 $myAccountString = '';
2409                 if ($useMyAccountString) {
2410                         $myAccountString = " - {$app_strings['LBL_MY_ACCOUNT']}";
2411                 } // if
2412
2413                 //Check to make sure that the user has set the associated inbound email acount -> outbound acount is active.
2414                 $showFolders = unserialize(base64_decode($current_user->getPreference('showFolders', 'Emails')));
2415         $sf = new SugarFolder();
2416         $groupSubs = $sf->getSubscriptions($current_user);
2417
2418         foreach($ieAccountsFull as $k => $v)
2419         {
2420             $personalSelected = (!empty($showFolders) && in_array($v->id, $showFolders));
2421
2422             $allowOutboundGroupUsage = $v->get_stored_options('allow_outbound_group_usage',FALSE);
2423             $groupSelected = ( in_array($v->groupfolder_id, $groupSubs)  && $allowOutboundGroupUsage);
2424             $selected = ( $personalSelected || $groupSelected );
2425
2426             if(!$selected)
2427             {
2428                 $GLOBALS['log']->debug("Inbound Email {$v->name}, not selected and will not be available for selection within compose UI.");
2429                 continue;
2430             }
2431
2432                 $name = $v->get_stored_options('from_name');
2433                 $addr = $v->get_stored_options('from_addr');
2434                 if ($name != null && $addr != null) {
2435                         $name = from_html($name);
2436                         if (!$v->is_personal) {
2437                         $ieAccountsFrom[] = array("value" => $v->id, "text" => "{$name} ({$addr}) - {$app_strings['LBL_EMAIL_UPPER_CASE_GROUP']}");
2438                         } else {
2439                         $ieAccountsFrom[] = array("value" => $v->id, "text" => "{$name} ({$addr})");
2440                         } // else
2441                 } // if
2442         } // foreach
2443
2444
2445         $userSystemOverride = $oe->getUsersMailerForSystemOverride($current_user->id);
2446         //Substitute in the users system override if its available.
2447         if($userSystemOverride != null)
2448                     $system = $userSystemOverride;
2449
2450         if( !empty($system->mail_smtpserver) )
2451         {
2452             $admin = new Administration();
2453             $admin->retrieveSettings(); //retrieve all admin settings.
2454             $ieAccountsFrom[] = array("value" => $system->id, "text" =>
2455                 "{$ret['name']} ({$ret['email']}){$myAccountString}");
2456         }
2457
2458         return $ieAccountsFrom;
2459     } // fn
2460
2461     /**
2462      * This function will return all the accounts this user has access to based on the
2463      * match of the emailId passed in as a parameter
2464      *
2465      * @param unknown_type $ie
2466      * @return unknown
2467      */
2468         function getFromAllAccountsArray($ie, $ret) {
2469         global $current_user;
2470         global $app_strings;
2471
2472         $ret['fromAccounts'] = array();
2473         if (!isset($ret['to']) && !empty($ret['from'])) {
2474                 $ret['fromAccounts']['status'] = false;
2475                 return $ret;
2476         }
2477         $ieAccountsFull = $ie->retrieveAllByGroupIdWithGroupAccounts($current_user->id);
2478                 $foundInPersonalAccounts = false;
2479                 $foundInGroupAccounts = false;
2480                 $foundInSystemAccounts = false;
2481
2482                 //$toArray = array();
2483                 if ($ret['type'] == "draft") {
2484                         $toArray = explode(",", $ret['from']);
2485                 } else {
2486                         $toArray = $ie->email->email2ParseAddressesForAddressesOnly($ret['to']);
2487                 } // else
2488         foreach($ieAccountsFull as $k => $v) {
2489                 $storedOptions = unserialize(base64_decode($v->stored_options));
2490                         if (  array_search_insensitive($storedOptions['from_addr'], $toArray)) {
2491                         if ($v->is_personal) {
2492                                         $foundInPersonalAccounts = true;
2493                                         break;
2494                                 } else  {
2495                                         $foundInGroupAccounts = true;
2496                                 } // else
2497                         } // if
2498         } // foreach
2499
2500             $oe = new OutboundEmail();
2501         $system = $oe->getSystemMailerSettings();
2502
2503         $return = $current_user->getUsersNameAndEmail();
2504                 $return['name'] = from_html($return['name']);
2505                 $useMyAccountString = true;
2506
2507         if(empty($return['email'])) {
2508                 $systemReturn = $current_user->getSystemDefaultNameAndEmail();
2509                 $return['email'] = $systemReturn['email'];
2510                 $return['name'] = from_html($systemReturn['name']);
2511                 $useMyAccountString = false;
2512                 } // if
2513
2514                 $myAccountString = '';
2515                 if ($useMyAccountString) {
2516                         $myAccountString = " - {$app_strings['LBL_MY_ACCOUNT']}";
2517                 } // if
2518
2519         if(!empty($system->id)) {
2520
2521             $admin = new Administration();
2522             $admin->retrieveSettings(); //retrieve all admin settings.
2523             if (in_array(trim($return['email']), $toArray)) {
2524                 $foundInSystemAccounts = true;
2525             } // if
2526         } // if
2527
2528         if (!$foundInPersonalAccounts && !$foundInGroupAccounts && !$foundInSystemAccounts) {
2529                 $ret['fromAccounts']['status'] = false;
2530                 return $ret;
2531         } // if
2532
2533         $ieAccountsFrom= array();
2534         foreach($ieAccountsFull as $k => $v) {
2535                 $storedOptions = unserialize(base64_decode($v->stored_options));
2536                 $storedOptionsName = from_html($storedOptions['from_name']);
2537
2538                 $selected = false;
2539                         if (array_search_insensitive($storedOptions['from_addr'], $toArray)) {
2540                 //if ($ret['to'] == $storedOptions['from_addr']) {
2541                         $selected = true;
2542                         } // if
2543                 if ($foundInPersonalAccounts) {
2544                         if ($v->is_personal) {
2545                         $ieAccountsFrom[] = array("value" => $v->id, "selected" => $selected, "text" => "{$storedOptionsName} ({$storedOptions['from_addr']})");
2546                         } // if
2547                 } else {
2548                 $ieAccountsFrom[] = array("value" => $v->id, "selected" => $selected, "text" => "{$storedOptionsName} ({$storedOptions['from_addr']}) - {$app_strings['LBL_EMAIL_UPPER_CASE_GROUP']}");
2549                 } // else
2550         } // foreach
2551
2552         if(!empty($system->id)) {
2553             if (!$foundInPersonalAccounts && !$foundInGroupAccounts && $foundInSystemAccounts) {
2554             $ieAccountsFrom[] = array("value" => $system->id, "selected" => true, "text" =>
2555                 "{$return['name']} ({$return['email']}){$myAccountString}");
2556             } else {
2557             $ieAccountsFrom[] = array("value" => $system->id, "text" =>
2558                 "{$return['name']} ({$return['email']}){$myAccountString}");
2559             } // else
2560         } // if
2561
2562         $ret['fromAccounts']['status'] = ($foundInPersonalAccounts || $foundInGroupAccounts || $foundInSystemAccounts) ? true : false;
2563                 $ret['fromAccounts']['data'] = $ieAccountsFrom;
2564         return $ret;
2565     } // fn
2566
2567
2568         /**
2569          * takes an array and creates XML
2570          * @param array Array to convert
2571          * @param string Name to wrap highest level items in array
2572          * @return string XML
2573          */
2574         function arrayToXML($a, $paramName) {
2575                 if(!is_array($a))
2576                         return '';
2577
2578                 $bad = array("<",">","'",'"',"&");
2579                 $good = array("&lt;", "&gt;", "&#39;", "&quot;","&amp;");
2580
2581                 $ret = "";
2582
2583                 for($i=0; $i<count($a); $i++) {
2584                         $email = $a[$i];
2585                         $ret .= "\n<{$paramName}>";
2586
2587                         foreach($email as $k => $v) {
2588                                 $ret .= "\n\t<{$k}>".str_replace($bad, $good, $v)."</{$k}>";
2589                         }
2590                         $ret .= "\n</{$paramName}>";
2591                 }
2592                 return $ret;
2593         }
2594
2595         /**
2596          * Re-used option getter for Show Accounts multiselect pane
2597          */
2598         function getShowAccountsOptions(&$ie) {
2599                 global $current_user;
2600                 global $app_strings;
2601                 global $mod_strings;
2602
2603                 $ieAccountsFull = $ie->retrieveAllByGroupId($current_user->id);
2604                 $ieAccountsShowOptionsMeta = array();
2605                 $showFolders = unserialize(base64_decode($current_user->getPreference('showFolders', 'Emails')));
2606
2607                 $defaultIEAccount = $ie->getUsersDefaultOutboundServerId($current_user);
2608
2609                 foreach($ieAccountsFull as $k => $v) {
2610                         $selected = (!empty($showFolders) && in_array($v->id, $showFolders)) ? true : false;
2611                         $default = ($defaultIEAccount == $v->id) ? TRUE : FALSE;
2612                         $has_groupfolder = !empty($v->groupfolder_id) ? TRUE : FALSE;
2613                         $type = ($v->is_personal) ? $mod_strings['LBL_MAILBOX_TYPE_PERSONAL'] : $mod_strings['LBL_MAILBOX_TYPE_GROUP'];
2614
2615                         $ieAccountsShowOptionsMeta[] = array("id" => $v->id, "name" => $v->name, 'is_active' => $selected,
2616                                                                                                         'server_url' => $v->server_url, 'is_group' => !$v->is_personal,'group_id' => $v->group_id,
2617                                                                                                         'is_default' => $default, 'has_groupfolder' => $has_groupfolder,'type' => $type );
2618                 }
2619
2620                 //Retrieve the grou folders
2621                 $f = new SugarFolder();
2622                 $groupFolders = $f->getGroupFoldersForSettings($current_user);
2623
2624                 foreach ($groupFolders as $singleGroup)
2625                 {
2626                     //Retrieve the related IE accounts.
2627             $relatedIEAccounts = $ie->retrieveByGroupFolderId($singleGroup['id']);
2628
2629             if(count($relatedIEAccounts) == 0)
2630                 $server_url = $app_strings['LBL_EMAIL_MULT_GROUP_FOLDER_ACCOUNTS_EMPTY'];
2631             else if(count($relatedIEAccounts) == 1)
2632             {
2633                 if($relatedIEAccounts[0]->status != 'Active' || $relatedIEAccounts[0]->mailbox_type == 'bounce')
2634                     continue;
2635
2636                 $server_url = $relatedIEAccounts[0]->server_url;
2637             }
2638             else
2639                 $server_url = $app_strings['LBL_EMAIL_MULT_GROUP_FOLDER_ACCOUNTS'];
2640
2641             $type = $mod_strings['LBL_MAILBOX_TYPE_GROUP_FOLDER'];
2642                     $ieAccountsShowOptionsMeta[] = array("id" => $singleGroup['id'], "name" => $singleGroup['origName'], 'is_active' => $singleGroup['selected'],
2643                                                                                                         'server_url' => $server_url, 'is_group' => true,'group_id' => $singleGroup['id'],
2644                                                                                                         'is_default' => FALSE, 'has_groupfolder' => true,'type' => $type);
2645                 }
2646
2647
2648                 return $ieAccountsShowOptionsMeta;
2649         }
2650
2651         function getShowAccountsOptionsForSearch(&$ie) {
2652                 global $current_user;
2653                 global $app_strings;
2654
2655                 $ieAccountsFull = $ie->retrieveAllByGroupId($current_user->id);
2656                 //$ieAccountsShowOptions = "<option value=''>{$app_strings['LBL_NONE']}</option>\n";
2657                 $ieAccountsShowOptionsMeta = array();
2658                 $ieAccountsShowOptionsMeta[] = array("value" => "", "text" => $app_strings['LBL_NONE'], 'selected' => '');
2659                 $showFolders = unserialize(base64_decode($current_user->getPreference('showFolders', 'Emails')));
2660
2661                 foreach($ieAccountsFull as $k => $v) {
2662                         if(!in_array($v->id, $showFolders)) {
2663                                 continue;
2664                         }
2665                         $group = (!$v->is_personal) ? $app_strings['LBL_EMAIL_GROUP']."." : "";
2666                         $ieAccountsShowOptionsMeta[] = array("value" => $v->id, "text" => $group.$v->name, 'protocol' => $v->protocol);
2667                 }
2668
2669                 return $ieAccountsShowOptionsMeta;
2670         }
2671         /**
2672          * Formats a display message on successful async call
2673          * @param string $type Type of message to display
2674          */
2675         function displaySuccessMessage($type) {
2676                 global $app_strings;
2677
2678                 switch($type) {
2679                         case "delete":
2680                                 $message = $app_strings['LBL_EMAIL_DELETE_SUCCESS'];
2681                         break;
2682
2683                         default:
2684                                 $message = "NOOP: invalid type";
2685                         break;
2686                 }
2687
2688                 $this->smarty->assign('app_strings', $app_strings);
2689                 $this->smarty->assign('message', $message);
2690                 echo $this->smarty->fetch("modules/Emails/templates/successMessage.tpl");
2691         }
2692
2693         /**
2694          * Validates existence and expiration of a cache file
2695          * @param string $ieId
2696          * @param string $type Type of cache file: folders, messages, etc.
2697          * @param string $file The cachefile name
2698          * @param int refreshOffset Refresh time in secs.
2699          * @return mixed.
2700          */
2701         function validCacheFileExists($ieId, $type, $file, $refreshOffset=-1) {
2702                 global $sugar_config;
2703
2704                 if($refreshOffset == -1) {
2705                         $refreshOffset = $this->cacheTimeouts[$type]; // use defaults
2706                 }
2707
2708                 $cacheFilePath = getcwd()."/{$sugar_config['cache_dir']}modules/Emails/{$ieId}/{$type}/{$file}";
2709                 if(file_exists($cacheFilePath)) {
2710                         return true;
2711                 }
2712
2713                 return false;
2714         }
2715
2716         /**
2717          * retrieves the cached value
2718          * @param string $ieId
2719          * @param string $type Type of cache file: folders, messages, etc.
2720          * @param string $file The cachefile name
2721          * @param string $key name of cache value
2722          * @return mixed
2723          */
2724         function getCacheValue($ieId, $type, $file, $key) {
2725                 global $sugar_config;
2726
2727                 $cacheFilePath = "{$sugar_config['cache_dir']}modules/Emails/{$ieId}/{$type}/{$file}";
2728                 $cacheFile = array();
2729
2730                 if(file_exists($cacheFilePath)) {
2731                         include($cacheFilePath); // provides $cacheFile
2732
2733                         if(isset($cacheFile[$key])) {
2734                                 $ret = unserialize($cacheFile[$key]);
2735                                 return $ret;
2736                         }
2737                 } else {
2738                         $GLOBALS['log']->debug("EMAILUI: cache file not found [ {$cacheFilePath} ] - creating blank cache file");
2739                         $this->writeCacheFile('retArr', array(), $ieId, $type, $file);
2740                 }
2741
2742                 return null;
2743         }
2744
2745         /**
2746          * retrieves the cache file last touched time
2747          * @param string $ieId
2748          * @param string $type Type of cache file: folders, messages, etc.
2749          * @param string $file The cachefile name
2750          * @return string
2751          */
2752         function getCacheTimestamp($ieId, $type, $file) {
2753                 global $sugar_config;
2754
2755                 $cacheFilePath = "{$sugar_config['cache_dir']}modules/Emails/{$ieId}/{$type}/{$file}";
2756                 $cacheFile = array();
2757
2758                 if(file_exists($cacheFilePath)) {
2759                         include($cacheFilePath); // provides $cacheFile['timestamp']
2760
2761                         if(isset($cacheFile['timestamp'])) {
2762                                 $GLOBALS['log']->debug("EMAILUI: found timestamp [ {$cacheFile['timestamp']} ]");
2763                                 return $cacheFile['timestamp'];
2764                         }
2765                 }
2766
2767                 return '';
2768         }
2769
2770         /**
2771          * Updates the timestamp for a cache file - usually to mark a "check email"
2772          * process
2773          * @param string $ieId
2774          * @param string $type Type of cache file: folders, messages, etc.
2775          * @param string $file The cachefile name
2776          */
2777         function setCacheTimestamp($ieId, $type, $file) {
2778                 global $sugar_config;
2779
2780                 $cacheFilePath = "{$sugar_config['cache_dir']}modules/Emails/{$ieId}/{$type}/{$file}";
2781                 $cacheFile = array();
2782
2783                 if(file_exists($cacheFilePath)) {
2784                         include($cacheFilePath); // provides $cacheFile['timestamp']
2785
2786                         if(isset($cacheFile['timestamp'])) {
2787                                 $cacheFile['timestamp'] = strtotime('now');
2788                                 $GLOBALS['log']->debug("EMAILUI: setting updated timestamp [ {$cacheFile['timestamp']} ]");
2789                                 return $this->_writeCacheFile($cacheFile, $cacheFilePath);
2790                         }
2791                 }
2792         }
2793
2794
2795         /**
2796          * Writes caches to flat file in cache dir.
2797          * @param string $key Key to the main cache entry (not timestamp)
2798          * @param mixed $var Variable to be cached
2799          * @param string $ieId I-E focus ID
2800          * @param string $type Folder in cache
2801          * @param string $file Cache file name
2802          */
2803         function writeCacheFile($key, $var, $ieId, $type, $file) {
2804                 global $sugar_config;
2805
2806                 $the_file = clean_path("{$sugar_config['cache_dir']}/modules/Emails/{$ieId}/{$type}/{$file}");
2807                 $timestamp = strtotime('now');
2808                 $array = array();
2809                 $array['timestamp'] = $timestamp;
2810                 $array[$key] = serialize($var); // serialized since varexport_helper() can't handle PHP objects
2811
2812                 return $this->_writeCacheFile($array, $the_file);
2813         }
2814
2815         /**
2816          * Performs the actual file write.  Abstracted from writeCacheFile() for
2817          * flexibility
2818          * @param array $array The array to write to the cache
2819          * @param string $file Full path (relative) with cache file name
2820          * @return bool
2821          */
2822         function _writeCacheFile($array, $file) {
2823                 global $sugar_config;
2824
2825                 $arrayString = var_export_helper($array);
2826
2827                 $date = date("r");
2828             $the_string =<<<eoq
2829 <?php // created: {$date}
2830         \$cacheFile = {$arrayString};
2831 ?>
2832 eoq;
2833             if($fh = @sugar_fopen($file, "w")) {
2834                 fputs($fh, $the_string);
2835                 fclose($fh);
2836                 return true;
2837             } else {
2838                 $GLOBALS['log']->debug("EMAILUI: Could not write cache file [ {$file} ]");
2839                 return false;
2840             }
2841         }
2842
2843         /**
2844          * Generate JSON encoded data to be consumed by yui datatable.
2845          *
2846          * @param array $data
2847          * @param string $resultsParam The resultsList name
2848          * @return string
2849          */
2850         function jsonOuput($data, $resultsParam, $count=0, $fromCache=true, $unread=-1) {
2851             global $app_strings;
2852
2853                 $count = ($count > 0) ? $count : 0;
2854
2855                 if(isset($a['fromCache']))
2856                         $cached = ($a['fromCache'] == 1) ? 1 : 0;
2857                 else
2858                         $cached = ($fromCache) ? 1 : 0;
2859
2860                 if($data['mbox'] == 'undefined' || empty($data['mbox']))
2861                         $data['mbox'] = $app_strings['LBL_NONE'];
2862
2863                 $jsonOut = array('TotalCount' => $count, 'FromCache' => $cached, 'UnreadCount' => $unread, $resultsParam => $data['out']);
2864
2865                 return json_encode($jsonOut);
2866         }
2867         /**
2868          * generates XML output from an array
2869          * @param array
2870          * @param string master list Item
2871          * @return string
2872          */
2873         function xmlOutput($a, $paramName, $count=0, $fromCache=true, $unread=-1) {
2874                 global $app_strings;
2875                 $count = ($count > 0) ? $count : 0;
2876
2877                 if(isset($a['fromCache'])) {
2878                         $cached = ($a['fromCache'] == 1) ? 1 : 0;
2879                 } else {
2880                         $cached = ($fromCache) ? 1 : 0;
2881                 }
2882
2883                 if($a['mbox'] == 'undefined' || empty($a['mbox'])) {
2884                         $a['mbox'] = $app_strings['LBL_NONE'];
2885                 }
2886
2887                 $xml = $this->arrayToXML($a['out'], $paramName);
2888
2889                 $ret =<<<eoq
2890 <?xml version="1.0" encoding="UTF-8"?>
2891 <EmailPage>
2892 <TotalCount>{$count}</TotalCount>
2893 <UnreadCount>{$unread}</UnreadCount>
2894 <FromCache> {$cached} </FromCache>
2895 <{$paramName}s>
2896 {$xml}
2897 </{$paramName}s>
2898 </EmailPage>
2899 eoq;
2900                 return $ret;
2901         }
2902
2903     /**
2904      * Generate to/cc addresses string in email detailview.
2905      *
2906      * @param string $str
2907      * @param string $target values: to, cc
2908      * @param int $defaultNum
2909      * @return string $str
2910      */
2911         function generateExpandableAddrs($str) {
2912             global $mod_strings;
2913             $tempStr = $str.',';
2914         $tempStr = html_entity_decode($tempStr);
2915             $tempStr = $this->unifyEmailString($tempStr);
2916         $defaultNum = 2;
2917         $pattern = '/@.*,/U';
2918         preg_match_all($pattern, $tempStr, $matchs);
2919         $totalCount = count($matchs[0]);
2920
2921         if(!empty($matchs[0]) && $totalCount > $defaultNum) {
2922             $position = strpos($tempStr, $matchs[0][$defaultNum]);
2923             $hiddenCount = $totalCount - $defaultNum;
2924             $frontStr = substr($tempStr, 0, $position);
2925             $backStr = substr($tempStr, $position, -1);
2926             $str = htmlentities($frontStr) . '<a class="utilsLink" onclick="javascript: SUGAR.email2.detailView.displayAllAddrs(this);">...['.$mod_strings['LBL_EMAIL_DETAIL_VIEW_SHOW'].$hiddenCount.$mod_strings['LBL_EMAIL_DETAIL_VIEW_MORE'].']</a><span style="display: none;">' .htmlentities($backStr).'</span>';
2927         }
2928
2929         return $str;
2930     }
2931
2932     /**
2933      * Unify the seperator as ,
2934      *
2935      * @param String $str email address string
2936      * @return String converted string
2937      */
2938     function unifyEmailString($str) {
2939         preg_match_all('/@.*;/U', $str, $matches);
2940         if(!empty($matches[0])) {
2941             foreach($matches[0] as $key => $value) {
2942                 $new[] = str_replace(";",",",$value);
2943             }
2944             return str_replace($matches[0], $new, $str);
2945         }
2946         return $str;
2947     }
2948 } // end class def