Issues (4069)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

include/SugarEmailAddress/SugarEmailAddress.php (12 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3
/*********************************************************************************
4
 * SugarCRM Community Edition is a customer relationship management program developed by
5
 * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
6
7
 * SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd.
8
 * Copyright (C) 2011 - 2014 Salesagility Ltd.
9
 *
10
 * This program is free software; you can redistribute it and/or modify it under
11
 * the terms of the GNU Affero General Public License version 3 as published by the
12
 * Free Software Foundation with the addition of the following permission added
13
 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
14
 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
15
 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
16
 *
17
 * This program is distributed in the hope that it will be useful, but WITHOUT
18
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19
 * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
20
 * details.
21
 *
22
 * You should have received a copy of the GNU Affero General Public License along with
23
 * this program; if not, see http://www.gnu.org/licenses or write to the Free
24
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25
 * 02110-1301 USA.
26
 *
27
 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
28
 * SW2-130, Cupertino, CA 95014, USA. or at email address [email protected].
29
 *
30
 * The interactive user interfaces in modified source and object code versions
31
 * of this program must display Appropriate Legal Notices, as required under
32
 * Section 5 of the GNU Affero General Public License version 3.
33
 *
34
 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
35
 * these Appropriate Legal Notices must retain the display of the "Powered by
36
 * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not
37
 * reasonably feasible for  technical reasons, the Appropriate Legal Notices must
38
 * display the words  "Powered by SugarCRM" and "Supercharged by SuiteCRM".
39
 ********************************************************************************/
40
41
/*********************************************************************************
42
43
 * Description:
44
 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc. All Rights
45
 * Reserved. Contributor(s): ______________________________________..
46
 *********************************************************************************/
47
48
49
require_once("include/JSON.php");
50
51
52
class SugarEmailAddress extends SugarBean {
53
    var $table_name = 'email_addresses';
54
    var $module_name = "EmailAddresses";
55
    var $module_dir = 'EmailAddresses';
56
    var $object_name = 'EmailAddress';
57
58
    //bug 40068, According to rules in page 6 of http://www.apps.ietf.org/rfc/rfc3696.html#sec-3,
59
	//allowed special characters ! # $ % & ' * + - / = ?  ^ _ ` . { | } ~ in local part
60
    var $regex = "/^(?:['\.\-\+&#!\$\*=\?\^_`\{\}~\/\w]+)@(?:(?:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|\w+(?:[\.-]*\w+)*(?:\.[\w-]{2,})+)\$/";
61
    var $disable_custom_fields = true;
62
    var $db;
63
    var $smarty;
64
    var $addresses = array(); // array of emails
65
    var $view = '';
66
    private $stateBeforeWorkflow;
67
68
    public $email_address;
69
70
    static $count = 0;
71
72
    /**
73
     * Sole constructor
74
     */
75 330
    public function __construct() {
76 330
        parent::__construct();
77 330
        $this->index = self::$count;
78 330
        self::$count++;
79 330
    }
80
81
    /**
82
     * @deprecated deprecated since version 7.6, PHP4 Style Constructors are deprecated and will be remove in 7.8, please update your code, use __construct instead
83
     */
84
    public function SugarEmailAddress(){
85
        $deprecatedMessage = 'PHP4 Style Constructors are deprecated and will be remove in 7.8, please update your code';
86
        if(isset($GLOBALS['log'])) {
87
            $GLOBALS['log']->deprecated($deprecatedMessage);
88
        }
89
        else {
90
            trigger_error($deprecatedMessage, E_USER_DEPRECATED);
91
        }
92
        self::__construct();
93
    }
94
95
96
    /**
97
     * Legacy email address handling.  This is to allow support for SOAP or customizations
98
     * @param string $id
0 ignored issues
show
There is no parameter named $id. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
99
     * @param string $module
0 ignored issues
show
There is no parameter named $module. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
100
     */
101 3
    function handleLegacySave($bean, $prefix = "") {
102 3
        if(!isset($_REQUEST) || !isset($_REQUEST['useEmailWidget'])) {
103 3
            if (empty($this->addresses) || !isset($_REQUEST['massupdate'])) {
104 3
                $this->addresses = array();
105 3
                $optOut = (isset($bean->email_opt_out) && $bean->email_opt_out == "1") ? true : false;
106 3
                $invalid = (isset($bean->invalid_email) && $bean->invalid_email == "1") ? true : false;
107
108 3
                $isPrimary = true;
109 3
                for($i = 1; $i <= 10; $i++){
110 3
                    $email = 'email'.$i;
111 3
                    if(isset($bean->$email) && !empty($bean->$email)){
112 1
                        $opt_out_field = $email.'_opt_out';
113 1
                        $invalid_field = $email.'_invalid';
114 1
                        $field_optOut = (isset($bean->$opt_out_field)) ? $bean->$opt_out_field : $optOut;
115 1
                        $field_invalid = (isset($bean->$invalid_field)) ? $bean->$invalid_field : $invalid;
116 1
                        $this->addAddress($bean->$email, $isPrimary, false, $field_invalid, $field_optOut);
117 1
                        $isPrimary = false;
118
                    }
119
                }
120
            }
121
        }
122 3
        $this->populateAddresses($bean->id, $bean->module_dir, array(),'');
123 3
        if(isset($_REQUEST) && isset($_REQUEST['useEmailWidget'])) {
124
            $this->populateLegacyFields($bean);
125
        }
126 3
    }
127
128
    /**
129
     * Fills standard email1 legacy fields
130
     * @param string id
131
     * @param string module
132
     * @return object
133
     */
134 51
    function handleLegacyRetrieve(&$bean) {
135 51
        $module_dir = $this->getCorrectedModule($bean->module_dir);
136 51
        $this->addresses = $this->getAddressesByGUID($bean->id, $module_dir);
137 51
        $this->populateLegacyFields($bean);
138 51
        if (isset($bean->email1) && !isset($bean->fetched_row['email1'])) {
139 50
            $bean->fetched_row['email1'] = $bean->email1;
140
        }
141
142 51
        return;
143
    }
144
145 51
    function populateLegacyFields(&$bean){
146 51
        $primary_found = false;
147 51
        $alternate_found = false;
148 51
        $alternate2_found = false;
149 51
        foreach($this->addresses as $k=>$address) {
150 1
            if ($primary_found && $alternate_found)
151
                break;
152 1
            if ($address['primary_address'] == 1 && !$primary_found) {
153 1
                $primary_index = $k;
154 1
                $primary_found = true;
155 1
            } elseif (!$alternate_found) {
156 1
                $alternate_index = $k;
157 1
                $alternate_found = true;
158
            } elseif (!$alternate2_found){
159
                $alternate2_index = $k;
160 1
                $alternate2_found = true;
161
            }
162
        }
163
164 51
        if ($primary_found) {
165 1
            $bean->email1 = $this->addresses[$primary_index]['email_address'];
166 1
            $bean->email_opt_out = $this->addresses[$primary_index]['opt_out'];
167 1
            $bean->invalid_email = $this->addresses[$primary_index]['invalid_email'];
168 1
            if ($alternate_found) {
169 1
                $bean->email2 = $this->addresses[$alternate_index]['email_address'];
170
            }
171 50
        } elseif ($alternate_found) {
172
            // Use the first found alternate as email1.
173
            $bean->email1 = $this->addresses[$alternate_index]['email_address'];
174
            $bean->email_opt_out = $this->addresses[$alternate_index]['opt_out'];
175
            $bean->invalid_email = $this->addresses[$alternate_index]['invalid_email'];
176
            if ($alternate2_found) {
177
                $bean->email2 = $this->addresses[$alternate2_index]['email_address'];
178
            }
179
        }
180 51
    }
181
182
    /**
183
     * Saves email addresses for a parent bean
184
     * @param string $id Parent bean ID
0 ignored issues
show
There is no parameter named $id. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
185
     * @param string $module Parent bean's module
0 ignored issues
show
There is no parameter named $module. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
186
     * @param array $addresses Override of $_REQUEST vars, used to handle non-standard bean saves
0 ignored issues
show
There is no parameter named $addresses. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
187
     * @param string $primary GUID of primary address
0 ignored issues
show
There is no parameter named $primary. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
188
     * @param string $replyTo GUID of reply-to address
0 ignored issues
show
There is no parameter named $replyTo. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
189
     * @param string $invalid GUID of invalid address
0 ignored issues
show
There is no parameter named $invalid. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
190
     */
191 3
    public function save($check_notify = FALSE) {
192 3
        $args = func_get_args();
193 3
        return call_user_func_array(array($this, '_save'), $args);
194
    }
195 3
    private function _save($id, $module, $new_addrs=array(), $primary='', $replyTo='', $invalid='', $optOut='', $in_workflow=false) {
196 3
        if(empty($this->addresses) || $in_workflow){
197 2
            $this->populateAddresses($id, $module, $new_addrs,$primary);
198
        }
199
200
        //find all email addresses..
201 3
        $current_links=array();
202
        // Need to correct this to handle the Employee/User split
203 3
        $module = $this->getCorrectedModule($module);
204 3
        $q2="select *  from email_addr_bean_rel eabr WHERE eabr.bean_id = '".$this->db->quote($id)."' AND eabr.bean_module = '".$this->db->quote($module)."' and eabr.deleted=0";
205 3
        $r2 = $this->db->query($q2);
206 3
        while(($row2=$this->db->fetchByAssoc($r2)) != null ) {
207 1
            $current_links[$row2['email_address_id']]=$row2;
208
        }
209
210 3
        $isConversion = (isset($_REQUEST) && isset($_REQUEST['action']) && $_REQUEST['action'] == 'ConvertLead') ? true : false;
211
212 3
        if (!empty($this->addresses)) {
213
            // insert new relationships and create email address record, if they don't exist
214 1
            foreach($this->addresses as $address) {
215 1
                if(!empty($address['email_address'])) {
216 1
                    $guid = create_guid();
217 1
                    $emailId = isset($address['email_address_id'])
218 1
                        && isset($current_links[$address['email_address_id']])
219 1
                        ? $address['email_address_id'] : null;
220 1
                    $emailId = $this->AddUpdateEmailAddress($address['email_address'],
221 1
                                                            $address['invalid_email'],
222 1
                                                            $address['opt_out'],
223
                                                            $emailId);// this will save the email address if not found
224
225
                    //verify linkage and flags.
226 1
                    $upd_eabr="";
227 1
                    if (isset($current_links[$emailId])) {
228 1
                        if (!$isConversion) { // do not update anything if this is for lead conversion
229 1
                        if ($address['primary_address'] != $current_links[$emailId]['primary_address'] or $address['reply_to_address'] != $current_links[$emailId]['reply_to_address'] ) {
230
                            $upd_eabr="UPDATE email_addr_bean_rel SET primary_address='".$this->db->quote($address['primary_address'])."', reply_to_address='".$this->db->quote($address['reply_to_address'])."' WHERE id='".$this->db->quote($current_links[$emailId]['id'])."'";
231
                        }
232
233 1
                        unset($current_links[$emailId]);
234
                        }
235
                    } else {
236 1
                        $primary = $address['primary_address'];
237 1
                        if (!empty($current_links) && $isConversion) {
238
                            foreach ($current_links as $eabr) {
239
                                if ($eabr['primary_address'] == 1) {
240
                                    // for lead conversion, if there is already a primary email, do not insert another primary email
241
                                    $primary = 0;
242
                                    break;
243
                                }
244
                            }
245
                        }
246 1
                        $now = $this->db->now();
247 1
                        $upd_eabr = "INSERT INTO email_addr_bean_rel (id, email_address_id,bean_id, bean_module,primary_address,reply_to_address,date_created,date_modified,deleted) VALUES('".$this->db->quote($guid)."', '".$this->db->quote($emailId)."', '".$this->db->quote($id)."', '".$this->db->quote($module)."', ".intval($primary).", ".intval($address['reply_to_address']).", $now, $now, 0)";
248
                    }
249
250 1
                    if (!empty($upd_eabr)) {
251 1
                        $r2 = $this->db->query($upd_eabr);
252
                    }
253
                }
254
            }
255
        }
256
257
        //delete link to dropped email address.
258
        // for lead conversion, do not delete email addresses
259 3
        if (!empty($current_links) && !$isConversion) {
260
261
            $delete="";
262
            foreach ($current_links as $eabr) {
263
264
                $delete.=empty($delete) ? "'".$this->db->quote($eabr['id']) . "' " : ",'" . $this->db->quote($eabr['id']) . "'";
265
            }
266
267
            $eabr_unlink="update email_addr_bean_rel set deleted=1 where id in ({$delete})";
268
            $this->db->query($eabr_unlink);
269
        }
270 3
        $this->stateBeforeWorkflow = null;
271 3
        return;
272
    }
273
274
    /**
275
     * returns the number of email addresses found for a specifed bean
276
     *
277
     * @param  string $email       Address to match
278
     * @param  object $bean        Bean to query against
279
     * @param  string $addresstype Optional, pass a 1 to query against the primary address, 0 for the other addresses
280
     * @return int                 Count of records found
281
     */
282
    function getCountEmailAddressByBean(
283
        $email,
284
        $bean,
285
        $addresstype
286
        )
287
    {
288
        $emailCaps = strtoupper(trim($email));
289
        if(empty($emailCaps))
290
            return 0;
291
292
        $q = "SELECT *
293
                FROM email_addr_bean_rel eabl JOIN email_addresses ea
294
                        ON (ea.id = eabl.email_address_id)
295
                    JOIN {$bean->table_name} bean
296
                        ON (eabl.bean_id = bean.id)
297
                WHERE ea.email_address_caps = '".$this->db->quote($emailCaps)."'
298
                    and eabl.bean_module = '".$this->db->quote($bean->module_dir)."'
299
                    and eabl.primary_address = '".$this->db->quote($addresstype)."'
300
                    and eabl.deleted=0 ";
301
302
        $r = $this->db->query($q);
303
304
        // do it this way to make the count accurate in oracle
305
        $i = 0;
306
        while ($this->db->fetchByAssoc($r)) ++$i;
307
308
        return $i;
309
    }
310
311
    /**
312
     * This function returns a contact or user ID if a matching email is found
313
     * @param   $email      the email address to match
314
     * @param   $table      which table to query
315
     */
316
    function getRelatedId($email, $module) {
317
        $email = $this->db->quote(trim(strtoupper($email)));
318
        $module = $this->db->quote(ucfirst($module));
319
320
        $q = "SELECT bean_id FROM email_addr_bean_rel eabr
321
                JOIN email_addresses ea ON (eabr.email_address_id = ea.id)
322
                WHERE bean_module = '$module' AND ea.email_address_caps = '$email' AND eabr.deleted=0";
323
324
        $r = $this->db->query($q, true);
325
326
        $retArr = array();
327
        while($a = $this->db->fetchByAssoc($r)) {
328
            $retArr[] = $a['bean_id'];
329
        }
330
        if(count($retArr) > 0) {
331
            return $retArr;
332
        } else {
333
            return false;
334
        }
335
    }
336
337
    /**
338
     * returns a collection of beans matching the email address
339
     * @param string $email Address to match
340
     * @return array
341
     */
342
    function getBeansByEmailAddress($email) {
343
        global $beanList;
344
        global $beanFiles;
345
346
        $ret = array();
347
348
        $email = trim($email);
349
350
        if(empty($email)) {
351
            return array();
352
        }
353
354
        $emailCaps = "'".$this->db->quote(strtoupper($email))."'";
355
        $q = "SELECT * FROM email_addr_bean_rel eabl JOIN email_addresses ea ON (ea.id = eabl.email_address_id)
356
                WHERE ea.email_address_caps = $emailCaps and eabl.deleted=0 ";
357
        $r = $this->db->query($q);
358
359
        while($a = $this->db->fetchByAssoc($r)) {
360
            if(isset($beanList[$a['bean_module']]) && !empty($beanList[$a['bean_module']])) {
361
                $className = $beanList[$a['bean_module']];
362
363
                if(isset($beanFiles[$className]) && !empty($beanFiles[$className])) {
364
                    if(!class_exists($className)) {
365
                        require_once($beanFiles[$className]);
366
                    }
367
368
                    $bean = new $className();
369
                    $bean->retrieve($a['bean_id']);
370
371
                    $ret[] = $bean;
372
                } else {
373
                    $GLOBALS['log']->fatal("SUGAREMAILADDRESS: could not find valid class file for [ {$className} ]");
374
                }
375
            } else {
376
                $GLOBALS['log']->fatal("SUGAREMAILADDRESS: could not find valid class [ {$a['bean_module']} ]");
377
            }
378
        }
379
380
        return $ret;
381
    }
382
383
    /**
384
     * Saves email addresses for a parent bean
385
     * @param string $id Parent bean ID
386
     * @param string $module Parent bean's module
387
     * @param array $addresses Override of $_REQUEST vars, used to handle non-standard bean saves
0 ignored issues
show
There is no parameter named $addresses. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
388
     * @param string $primary GUID of primary address
389
     * @param string $replyTo GUID of reply-to address
390
     * @param string $invalid GUID of invalid address
391
     */
392 3
    function populateAddresses($id, $module, $new_addrs=array(), $primary='', $replyTo='', $invalid='', $optOut='') {
393 3
        $module = $this->getCorrectedModule($module);
394
        //One last check for the ConvertLead action in which case we need to change $module to 'Leads'
395 3
        $module = (isset($_REQUEST) && isset($_REQUEST['action']) && $_REQUEST['action'] == 'ConvertLead') ? 'Leads' : $module;
396
397 3
        $post_from_email_address_widget = (isset($_REQUEST) && isset($_REQUEST['emailAddressWidget'])) ? true : false;
398 3
        $primaryValue = $primary;
399 3
        $widgetCount = 0;
400 3
        $hasEmailValue = false;
401 3
        $email_ids = array();
402
403 3
        if (isset($_REQUEST) && isset($_REQUEST[$module .'_email_widget_id'])) {
404
405
            $fromRequest = false;
406
            // determine which array to process
407
            foreach($_REQUEST as $k => $v) {
408
                if(strpos($k, 'emailAddress') !== false) {
409
                   $fromRequest = true;
410
                   break;
411
                }
412
            $widget_id = $_REQUEST[$module .'_email_widget_id'];
413
    }
414
415
            //Iterate over the widgets for this module, in case there are multiple email widgets for this module
416
            while(isset($_REQUEST[$module . $widget_id . "emailAddress" . $widgetCount]))
417
            {
418
                if (empty($_REQUEST[$module . $widget_id . "emailAddress" . $widgetCount])) {
419
                    $widgetCount++;
420
                    continue;
421
                }
422
423
                $hasEmailValue = true;
424
425
                $eId = $module . $widget_id;
426
                if(isset($_REQUEST[$eId . 'emailAddressPrimaryFlag'])) {
427
                   $primaryValue = $_REQUEST[$eId . 'emailAddressPrimaryFlag'];
428
                } else if(isset($_REQUEST[$module . 'emailAddressPrimaryFlag'])) {
429
                   $primaryValue = $_REQUEST[$module . 'emailAddressPrimaryFlag'];
430
                }
431
432
                $optOutValues = array();
433
                if(isset($_REQUEST[$eId .'emailAddressOptOutFlag'])) {
434
                   $optOutValues = $_REQUEST[$eId .'emailAddressOptOutFlag'];
435
                } else if(isset($_REQUEST[$module . 'emailAddressOptOutFlag'])) {
436
                   $optOutValues = $_REQUEST[$module . 'emailAddressOptOutFlag'];
437
                }
438
439
                $invalidValues = array();
440
                if(isset($_REQUEST[$eId .'emailAddressInvalidFlag'])) {
441
                   $invalidValues = $_REQUEST[$eId .'emailAddressInvalidFlag'];
442
                } else if(isset($_REQUEST[$module . 'emailAddressInvalidFlag'])) {
443
                   $invalidValues = $_REQUEST[$module . 'emailAddressInvalidFlag'];
444
                }
445
446
                $deleteValues = array();
447
                if(isset($_REQUEST[$eId .'emailAddressDeleteFlag'])) {
448
                   $deleteValues = $_REQUEST[$eId .'emailAddressDeleteFlag'];
449
                } else if(isset($_REQUEST[$module . 'emailAddressDeleteFlag'])) {
450
                   $deleteValues = $_REQUEST[$module . 'emailAddressDeleteFlag'];
451
                }
452
453
                // prep from form save
454
                $primaryField = $primary;
455
                $replyToField = '';
456
                $invalidField = '';
457
                $optOutField = '';
458
                if($fromRequest && empty($primary) && isset($primaryValue)) {
459
                    $primaryField = $primaryValue;
460
                }
461
462
                if($fromRequest && empty($replyTo)) {
463
                    if(isset($_REQUEST[$eId .'emailAddressReplyToFlag'])) {
464
                       $replyToField = $_REQUEST[$eId .'emailAddressReplyToFlag'];
465
                    } else if(isset($_REQUEST[$module . 'emailAddressReplyToFlag'])) {
466
                       $replyToField = $_REQUEST[$module . 'emailAddressReplyToFlag'];
467
                    }
468
                }
469
                if($fromRequest && empty($new_addrs)) {
470
                    foreach($_REQUEST as $k => $v) {
471
                        if(preg_match('/'.$eId.'emailAddress[0-9]+$/i', $k) && !empty($v)) {
472
                            $new_addrs[$k] = $v;
473
                        }
474
                    }
475
                }
476
                if($fromRequest && empty($email_ids)) {
477
                    foreach($_REQUEST as $k => $v) {
478
                        if(preg_match('/'.$eId.'emailAddressId[0-9]+$/i', $k) && !empty($v)) {
479
                            $key = str_replace('emailAddressId', 'emailAddress', $k);
480
                            $email_ids[$key] = $v;
481
                        }
482
                    }
483
                }
484
485
                if($fromRequest && empty($new_addrs)) {
486
                    foreach($_REQUEST as $k => $v) {
487
                        if(preg_match('/'.$eId.'emailAddressVerifiedValue[0-9]+$/i', $k) && !empty($v)) {
488
                            $validateFlag = str_replace("Value", "Flag", $k);
489
                            if (isset($_REQUEST[$validateFlag]) && $_REQUEST[$validateFlag] == "true")
490
                              $new_addrs[$k] = $v;
491
                        }
492
                    }
493
                }
494
495
                //empty the addresses array if the post happened from email address widget.
496
                if($post_from_email_address_widget) {
497
                    $this->addresses=array();  //this gets populated during retrieve of the contact bean.
498
                } else {
499
                    $optOutValues = array();
500
                    $invalidValues = array();
501
                    foreach($new_addrs as $k=>$email) {
502
                       preg_match('/emailAddress([0-9])+$/', $k, $matches);
503
                       $count = $matches[1];
504
                       $result = $this->db->query("SELECT opt_out, invalid_email from email_addresses where email_address_caps = '" . $this->db->quote(strtoupper($email)) . "'");
505
                       if(!empty($result)) {
506
                          $row=$this->db->fetchByAssoc($result);
507
                          if(!empty($row['opt_out'])) {
508
                             $optOutValues[$k] = "emailAddress$count";
509
                          }
510
                          if(!empty($row['invalid_email'])) {
511
                             $invalidValues[$k] = "emailAddress$count";
512
                          }
513
                       }
514
                    }
515
                }
516
                // Re-populate the addresses class variable if we have new address(es).
517
                if (!empty($new_addrs)) {
518
                    foreach($new_addrs as $k => $reqVar) {
519
                        //$key = preg_match("/^$eId/s", $k) ? substr($k, strlen($eId)) : $k;
520
                        $reqVar = trim($reqVar);
521
                        if(strpos($k, 'emailAddress') !== false) {
522
                            if(!empty($reqVar) && !in_array($k, $deleteValues)) {
523
                                $email_id   = (array_key_exists($k, $email_ids)) ? $email_ids[$k] : null;
524
                                $primary    = ($k == $primaryValue) ? true : false;
525
                                $replyTo    = ($k == $replyToField) ? true : false;
526
                                $invalid    = (in_array($k, $invalidValues)) ? true : false;
527
                                $optOut     = (in_array($k, $optOutValues)) ? true : false;
528
                                $this->addAddress(trim($new_addrs[$k]), $primary, $replyTo, $invalid, $optOut, $email_id);
529
                            }
530
                        }
531
                    } //foreach
532
                }
533
534
                $widgetCount++;
535
            }//End of Widget for loop
536
        }
537
538
        //If no widgets, set addresses array to empty
539 3
        if($post_from_email_address_widget && !$hasEmailValue) {
540
           $this->addresses = array();
541
        }
542 3
    }
543
544
    /**
545
     * Preps internal array structure for email addresses
546
     * @param string $addr Email address
547
     * @param bool $primary Default false
548
     * @param bool $replyTo Default false
549
     */
550 1
    function addAddress($addr, $primary=false, $replyTo=false, $invalid=false, $optOut=false, $email_id = null) {
551 1
        $addr = html_entity_decode($addr, ENT_QUOTES);
552 1
        if(preg_match($this->regex, $addr)) {
553 1
            $primaryFlag = ($primary) ? '1' : '0';
554 1
            $replyToFlag = ($replyTo) ? '1' : '0';
555 1
            $invalidFlag = ($invalid) ? '1' : '0';
556 1
            $optOutFlag = ($optOut) ? '1' : '0';
557
558 1
            $addr = trim($addr);
559
560
            // If we have such address already, remove it and add new one in.
561 1
            foreach ($this->addresses as $k=>$address) {
562 1
                if ($address['email_address'] == $addr) {
563
                    unset($this->addresses[$k]);
564 1
                } elseif ($primary && $address['primary_address'] == '1') {
565
                    // We should only have one primary. If we are adding a primary but
566
                    // we find an existing primary, reset this one's primary flag.
567 1
                    $address['primary_address'] = '0';
568
                }
569
            }
570
571 1
            $this->addresses[] = array(
572 1
                'email_address' => $addr,
573 1
                'primary_address' => $primaryFlag,
574 1
                'reply_to_address' => $replyToFlag,
575 1
                'invalid_email' => $invalidFlag,
576 1
                'opt_out' => $optOutFlag,
577 1
                'email_address_id' => $email_id,
578
            );
579
        } else {
580
            $GLOBALS['log']->fatal("SUGAREMAILADDRESS: address did not validate [ {$addr} ]");
581
        }
582 1
    }
583
584
    /**
585
     * Updates invalid_email and opt_out flags for each address
586
     */
587
    function updateFlags() {
588
        if(!empty($this->addresses)) {
589
            foreach($this->addresses as $addressMeta) {
590
                if(isset($addressMeta['email_address']) && !empty($addressMeta['email_address'])) {
591
                    $address = $this->db->quote($this->_cleanAddress($addressMeta['email_address']));
592
593
                    $q = "SELECT * FROM email_addresses WHERE email_address = '{$address}'";
594
                    $r = $this->db->query($q);
595
                    $a = $this->db->fetchByAssoc($r);
596
597
                    if(!empty($a)) {
598
                        if(isset($a['invalid_email']) && isset($addressMeta['invalid_email']) && isset($addressMeta['opt_out']) && $a['invalid_email'] != $addressMeta['invalid_email'] || $a['opt_out'] != $addressMeta['opt_out']) {
599
                            $qUpdate = "UPDATE email_addresses SET invalid_email = ".intval($addressMeta['invalid_email']).", opt_out = ".intval($addressMeta['opt_out']).", date_modified = '".TimeDate::getInstance()->nowDb()."' WHERE id = '".$this->db->quote($a['id'])."'";
600
                            $rUpdate = $this->db->query($qUpdate);
601
                        }
602
                    }
603
                }
604
            }
605
        }
606
    }
607
608 4
    public function splitEmailAddress($addr)
609
    {
610 4
        $email = $this->_cleanAddress($addr);
611 4
        if(!preg_match($this->regex, $email)) {
612 3
            $email = ''; // remove bad email addr
613
        }
614 4
        $name = trim(str_replace(array($email, '<', '>', '"', "'"), '', $addr));
615 4
        return array("name" => $name, "email" => strtolower($email));
616
    }
617
618
    /**
619
     * PRIVATE UTIL
620
     * Normalizes an RFC-clean email address, returns a string that is the email address only
621
     * @param string $addr Dirty email address
622
     * @return string clean email address
623
     */
624 5
    function _cleanAddress($addr) {
625 5
        $addr = trim(from_html($addr));
626
627 5
        if(strpos($addr, "<") !== false && strpos($addr, ">") !== false) {
628 2
            $address = trim(substr($addr, strrpos($addr, "<") +1, strrpos($addr, ">") - strrpos($addr, "<") -1));
629
        } else {
630 5
            $address = trim($addr);
631
        }
632
633 5
        return $address;
634
    }
635
636
    /**
637
     * preps a passed email address for email address storage
638
     * @param array $addr Address in focus, must be RFC compliant
639
     * @return string $id email_addresses ID
640
     */
641 3
    function getEmailGUID($addr) {
642 3
        $address = $this->db->quote($this->_cleanAddress($addr));
643 3
        $addressCaps = strtoupper($address);
644
645 3
        $q = "SELECT id FROM email_addresses WHERE email_address_caps = '{$addressCaps}'";
646 3
        $r = $this->db->query($q);
647 3
        $a = $this->db->fetchByAssoc($r);
648
649 3
        if(!empty($a) && !empty($a['id'])) {
650 2
            return $a['id'];
651
        } else {
652 2
            $guid = '';
653 2
            if(!empty($address)){
654 2
                $guid = create_guid();
655 2
                $now = TimeDate::getInstance()->nowDb();
656
                $qa = "INSERT INTO email_addresses (id, email_address, email_address_caps, date_created, date_modified, deleted)
657 2
                        VALUES('{$guid}', '{$address}', '{$addressCaps}', '$now', '$now', 0)";
658 2
                $ra = $this->db->query($qa);
659
            }
660 2
            return $guid;
661
        }
662
    }
663
664
    /**
665
     * Creates or Updates an entry in the email_addresses table, depending
666
     * on if the email address submitted matches a previous entry (case-insensitive)
667
     * @param String $addr - email address
668
     * @param int $invalid - is the email address marked as Invalid?
669
     * @param int $opt_out - is the email address marked as Opt-Out?
670
     * @param String $id - the GUID of the original SugarEmailAddress bean,
671
     *        in case a "email has changed" WorkFlow has triggered - hack to allow workflow-induced changes
672
     *        to propagate to the new SugarEmailAddress - see bug 39188
673
     * @return String GUID of Email Address or '' if cleaned address was empty.
674
     */
675 1
    public function AddUpdateEmailAddress($addr,$invalid=0,$opt_out=0,$id=null)
676
    {
677
        // sanity checks to avoid SQL injection.
678 1
        $invalid = intval($invalid);
679 1
        $opt_out = intval($opt_out);
680
681 1
        $address = $this->db->quote($this->_cleanAddress($addr));
682 1
        $addressCaps = strtoupper($address);
683
684
        // determine if we have a matching email address
685 1
        $q = "SELECT * FROM email_addresses WHERE email_address_caps = '{$addressCaps}' and deleted=0";
686 1
        $r = $this->db->query($q);
687 1
        $duplicate_email = $this->db->fetchByAssoc($r);
688
689
        // check if we are changing an email address, where workflow might be in play
690 1
        if ($id) {
691
            $r = $this->db->query("SELECT * FROM email_addresses WHERE id='".$this->db->quote($id)."'");
692
            $current_email = $this->db->fetchByAssoc($r);
693
        }
694
        else {
695 1
            $current_email = null;
696
        }
697
698
        // unless workflow made changes, assume parameters are what to use.
699 1
        $new_opt_out = $opt_out;
700 1
        $new_invalid = $invalid;
701 1
        if (!empty($current_email['id']) && isset($this->stateBeforeWorkflow[$current_email['id']])) {
702
            if ($current_email['invalid_email'] != $invalid ||
703
                $current_email['opt_out'] != $opt_out) {
704
705
                // workflow could be in play
706
                $before_email = $this->stateBeforeWorkflow[$current_email['id']];
707
708
                // our logic is as follows: choose from parameter, unless workflow made a change to the value, then choose final value
709
                if (intval($before_email['opt_out']) != intval($current_email['opt_out'])) {
710
                    $new_opt_out = intval($current_email['opt_out']);
711
                }
712
                if (intval($before_email['invalid_email']) != intval($current_email['invalid_email'])) {
713
                    $new_invalid = intval($current_email['invalid_email']);
714
                }
715
            }
716
        }
717
718
        // determine how we are going to put in this address - UPDATE or INSERT
719 1
        if (!empty($duplicate_email['id'])) {
720
721
            // address_caps matches - see if we're changing fields
722 1
            if ($duplicate_email['invalid_email'] != $new_invalid ||
723 1
                $duplicate_email['opt_out'] != $new_opt_out ||
724 1
                (trim($duplicate_email['email_address']) != $address)) {
725
                $upd_q = 'UPDATE ' . $this->table_name . ' ' .
726
                    'SET email_address=\'' . $address . '\', ' .
727
                    'invalid_email=' . $new_invalid . ', ' .
728
                    'opt_out=' . $new_opt_out . ', ' .
729
                    'date_modified=' . $this->db->now() . ' ' .
730
                    'WHERE id=\'' . $this->db->quote($duplicate_email['id']) . '\'';
731
                $upd_r = $this->db->query($upd_q);
732
            }
733 1
            return $duplicate_email['id'];
734
        }
735
        else {
736
            // no case-insensitive address match - it's new, or undeleted.
737 1
            $guid = '';
738 1
            if(!empty($address)){
739 1
                $guid = create_guid();
740 1
                $now = TimeDate::getInstance()->nowDb();
741
                $qa = "INSERT INTO email_addresses (id, email_address, email_address_caps, date_created, date_modified, deleted, invalid_email, opt_out)
742 1
                        VALUES('{$guid}', '{$address}', '{$addressCaps}', '$now', '$now', 0 , $new_invalid, $new_opt_out)";
743 1
                $this->db->query($qa);
744
            }
745 1
            return $guid;
746
        }
747
    }
748
749
    /**
750
     * Returns Primary or newest email address
751
     * @param object $focus Object in focus
752
     * @return string email
753
     */
754 13
    function getPrimaryAddress($focus,$parent_id=null,$parent_type=null) {
755
756 13
        $parent_type=empty($parent_type) ? $focus->module_dir : $parent_type;
757
        // Bug63174: Email address is not shown in the list view for employees
758 13
        $parent_type = $this->getCorrectedModule($parent_type);
759 13
        $parent_id=empty($parent_id) ? $focus->id : $parent_id;
760
761
        $q = "SELECT ea.email_address FROM email_addresses ea
762
                LEFT JOIN email_addr_bean_rel ear ON ea.id = ear.email_address_id
763 13
                WHERE ear.bean_module = '".$this->db->quote($parent_type)."'
764 13
                AND ear.bean_id = '".$this->db->quote($parent_id)."'
765
                AND ear.deleted = 0
766
                AND ea.invalid_email = 0
767 13
                ORDER BY ear.primary_address DESC";
768 13
        $r = $this->db->limitQuery($q, 0, 1);
769 13
        $a = $this->db->fetchByAssoc($r);
770
771 13
        if(isset($a['email_address'])) {
772 1
            return $a['email_address'];
773
        }
774 12
        return '';
775
    }
776
777
    /**
778
     * As long as this function is used not only to retrieve user's Reply-To
779
     * address, but also notification address and so on, there were added
780
     * $replyToOnly optional parameter used to retrieve only address marked as
781
     * Reply-To (bug #43643).
782
     *
783
     * @param SugarBean $focus
784
     * @param bool $replyToOnly
785
     * @return string
786
     */
787
    function getReplyToAddress($focus, $replyToOnly = false) {
788
        $q = "SELECT ea.email_address FROM email_addresses ea
789
                LEFT JOIN email_addr_bean_rel ear ON ea.id = ear.email_address_id
790
                WHERE ear.bean_module = '".$this->db->quote($focus->module_dir)."'
791
                AND ear.bean_id = '".$this->db->quote($focus->id)."'
792
                AND ear.deleted = 0
793
                AND ea.invalid_email = 0";
794
795
        if (!$replyToOnly)
796
        {
797
            // retrieve reply-to address if it exists or any other address
798
            // otherwise
799
            $q .= "
800
                ORDER BY ear.reply_to_address DESC";
801
        }
802
        else
803
        {
804
            // retrieve reply-to address only
805
            $q .= "
806
                AND ear.reply_to_address = 1";
807
        }
808
809
        $r = $this->db->query($q);
810
        $a = $this->db->fetchByAssoc($r);
811
812
        if(isset($a['email_address'])) {
813
            return $a['email_address'];
814
        }
815
        return '';
816
    }
817
818
    /**
819
     * Returns all email addresses by parent's GUID
820
     * @param string $id Parent's GUID
821
     * @param string $module Parent's module
822
     * @return array
823
     */
824 53
    function getAddressesByGUID($id, $module) {
825 53
        $return = array();
826 53
        $module = $this->getCorrectedModule($module);
827
828
        $q = "SELECT ea.email_address, ea.email_address_caps, ea.invalid_email, ea.opt_out, ea.date_created, ea.date_modified,
829
                ear.id, ear.email_address_id, ear.bean_id, ear.bean_module, ear.primary_address, ear.reply_to_address, ear.deleted
830
                FROM email_addresses ea LEFT JOIN email_addr_bean_rel ear ON ea.id = ear.email_address_id
831 53
                WHERE ear.bean_module = '".$this->db->quote($module)."'
832 53
                AND ear.bean_id = '".$this->db->quote($id)."'
833
                AND ear.deleted = 0
834 53
                ORDER BY ear.reply_to_address, ear.primary_address DESC";
835 53
        $r = $this->db->query($q);
836
837 53
        while($a = $this->db->fetchByAssoc($r, FALSE)) {
838 1
            $return[] = $a;
839
        }
840
841 53
        return $return;
842
    }
843
844
    /**
845
     * Returns the HTML/JS for the EmailAddress widget
846
     * @param string $parent_id ID of parent bean, generally $focus
0 ignored issues
show
There is no parameter named $parent_id. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
847
     * @param string $module $focus' module
848
     * @param bool asMetadata Default false
849
     * @return string HTML/JS for widget
850
     */
851 4
    function getEmailAddressWidgetEditView($id, $module, $asMetadata=false, $tpl='',$tabindex='0')
852
    {
853 4
        if ( !($this->smarty instanceOf Sugar_Smarty ) )
854 4
            $this->smarty = new Sugar_Smarty();
855
856 4
        global $app_strings, $dictionary, $beanList;
857
858 4
        $prefill = 'false';
859
860 4
        $prefillData = 'new Object()';
861 4
        $passedModule = $module;
862 4
        $module = $this->getCorrectedModule($module);
863 4
        $saveModule = $module;
864 4
        if(isset($_POST['is_converted']) && $_POST['is_converted']==true){
865
            $id=$_POST['return_id'];
866
            $module=$_POST['return_module'];
867
        }
868 4
        $prefillDataArr = array();
869 4
        if(!empty($id)) {
870
            $prefillDataArr = $this->getAddressesByGUID($id, $module);
871
            //When coming from convert leads, sometimes module is Contacts while the id is for a lead.
872
            if (empty($prefillDataArr) && $module == "Contacts")
873
                $prefillDataArr = $this->getAddressesByGUID($id, "Leads");
874 4
        } else if(isset($_REQUEST['full_form']) && !empty($_REQUEST['emailAddressWidget'])){
875
            $widget_id = isset($_REQUEST[$module . '_email_widget_id']) ? $_REQUEST[$module . '_email_widget_id'] : '0';
876
            $count = 0;
877
            $key = $module . $widget_id . 'emailAddress'.$count;
878
            while(isset($_REQUEST[$key])) {
879
                   $email = $_REQUEST[$key];
880
                   $prefillDataArr[] =  array('email_address'=>$email,
881
                                             'primary_address'=>isset($_REQUEST['emailAddressPrimaryFlag']) && $_REQUEST['emailAddressPrimaryFlag'] == $key,
882
                                             'invalid_email'=>isset($_REQUEST['emailAddressInvalidFlag']) && in_array($key, $_REQUEST['emailAddressInvalidFlag']),
883
                                             'opt_out'=>isset($_REQUEST['emailAddressOptOutFlag']) && in_array($key, $_REQUEST['emailAddressOptOutFlag']),
884
                                             'reply_to_address'=>false
885
                                        );
886
                   $key = $module . $widget_id . 'emailAddress' . ++$count;
887
            } //while
888
        }
889
890 4
        if(!empty($prefillDataArr)) {
891
            $json = new JSON(JSON_LOOSE_TYPE);
0 ignored issues
show
The call to JSON::__construct() has too many arguments starting with JSON_LOOSE_TYPE.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
892
            $prefillData = $json->encode($prefillDataArr);
893
            $prefill = !empty($prefillDataArr) ? 'true' : 'false';
894
        }
895
896 4
        $required = false;
897 4
        $vardefs = $dictionary[$beanList[$passedModule]]['fields'];
898 4
        if (!empty($vardefs['email1']) && isset($vardefs['email1']['required']) && $vardefs['email1']['required'])
899 1
            $required = true;
900 4
        $this->smarty->assign('required', $required);
901
902 4
        $this->smarty->assign('module', $saveModule);
903 4
        $this->smarty->assign('index', $this->index);
904 4
        $this->smarty->assign('app_strings', $app_strings);
905 4
        $this->smarty->assign('prefillEmailAddresses', $prefill);
906 4
        $this->smarty->assign('prefillData', $prefillData);
907 4
        $this->smarty->assign('tabindex', $tabindex);
908
        //Set addDefaultAddress flag (do not add if it's from the Email module)
909 4
        $this->smarty->assign('addDefaultAddress', (isset($_REQUEST['module']) && $_REQUEST['module'] == 'Emails') ? 'false' : 'true');
910 4
        $form = $this->view;
911
912
        //determine if this should be a quickcreate form, or a quick create form under subpanels
913 4
        if ($this->view == "QuickCreate"){
914 3
            $form = 'form_DC'.$this->view .'_'.$module;
915 3
            if(isset($_REQUEST['action']) && $_REQUEST['action']=='SubpanelCreates' ||  $_REQUEST['action']=='SubpanelEdits'){
916 1
                $form = 'form_Subpanel'.$this->view .'_'.$module;
917
            }
918
        }
919
920 4
        $this->smarty->assign('emailView', $form);
921
922 4
        if($module == 'Users') {
923 1
            $this->smarty->assign('useReplyTo', true);
924
        } else {
925 3
            $this->smarty->assign('useOptOut', true);
926 3
            $this->smarty->assign('useInvalid', true);
927
        }
928
929 4
        $template = empty($tpl) ? "include/SugarEmailAddress/templates/forEditView.tpl" : $tpl;
930 4
        $newEmail = $this->smarty->fetch($template);
931
932
933 4
        if($asMetadata) {
934
            // used by Email 2.0
935
            $ret = array();
936
            $ret['prefillData'] = $prefillDataArr;
937
            $ret['html'] = $newEmail;
938
939
            return $ret;
940
        }
941
942 4
        return $newEmail;
943
    }
944
945
946
    /**
947
     * Returns the HTML/JS for the EmailAddress widget
948
     * @param object $focus Bean in focus
949
     * @return string HTML/JS for widget
950
     */
951 6
    function getEmailAddressWidgetDetailView($focus, $tpl='')
952
    {
953 6
        if ( !($this->smarty instanceOf Sugar_Smarty ) )
954 6
            $this->smarty = new Sugar_Smarty();
955
956 6
        global $app_strings;
957 6
        global $current_user;
958 6
        $assign = array();
959 6
        if(empty($focus->id))return '';
960 2
        $prefillData = $this->getAddressesByGUID($focus->id, $focus->module_dir);
961
962 2
        foreach($prefillData as $addressItem) {
963
            $key = ($addressItem['primary_address'] == 1) ? 'primary' : "";
964
            $key = ($addressItem['reply_to_address'] == 1) ? 'reply_to' : $key;
965
            $key = ($addressItem['opt_out'] == 1) ? 'opt_out' : $key;
966
            $key = ($addressItem['invalid_email'] == 1) ? 'invalid' : $key;
967
            $key = ($addressItem['opt_out'] == 1) && ($addressItem['invalid_email'] == 1) ? 'opt_out_invalid' : $key;
968
969
            $assign[] = array('key' => $key, 'address' => $current_user->getEmailLink2($addressItem['email_address'], $focus).$addressItem['email_address']."</a>");
970
        }
971
972
973 2
        $this->smarty->assign('app_strings', $app_strings);
974 2
        $this->smarty->assign('emailAddresses', $assign);
975 2
        $templateFile = empty($tpl) ? "include/SugarEmailAddress/templates/forDetailView.tpl" : $tpl;
976 2
        $return = $this->smarty->fetch($templateFile);
977 2
        return $return;
978
    }
979
980
981
    /**
982
     * getEmailAddressWidgetDuplicatesView($focus)
983
     * @param object $focus Bean in focus
984
     * @return string HTML that contains hidden input values based off of HTML request
985
     */
986
    function getEmailAddressWidgetDuplicatesView($focus)
987
    {
988
        if ( !($this->smarty instanceOf Sugar_Smarty ) )
989
            $this->smarty = new Sugar_Smarty();
990
991
        $count = 0;
992
        $emails = array();
993
        $primary = null;
994
        $optOut = array();
995
        $invalid = array();
996
        $mod = isset($focus) ? $focus->module_dir : "";
997
998
        $widget_id = $_POST[$mod .'_email_widget_id'];
999
        $this->smarty->assign('email_widget_id',$widget_id);
1000
        $this->smarty->assign('emailAddressWidget',$_POST['emailAddressWidget']);
1001
1002
        if(isset($_POST[$mod . $widget_id . 'emailAddressPrimaryFlag'])) {
1003
           $primary = $_POST[$mod . $widget_id . 'emailAddressPrimaryFlag'];
1004
        }
1005
1006
        while(isset($_POST[$mod . $widget_id . "emailAddress" . $count])) {
1007
            $emails[] = $_POST[$mod . $widget_id . 'emailAddress' . $count];
1008
            $count++;
1009
        }
1010
1011
        if($count == 0) {
1012
           return "";
1013
        }
1014
1015
        if(isset($_POST[$mod . $widget_id . 'emailAddressOptOutFlag'])) {
1016
           foreach($_POST[$mod . $widget_id . 'emailAddressOptOutFlag'] as $v) {
1017
              $optOut[] = $v;
1018
           }
1019
        }
1020
1021
        if(isset($_POST[$mod . $widget_id . 'emailAddressInvalidFlag'])) {
1022
           foreach($_POST[$mod . $widget_id . 'emailAddressInvalidFlag'] as $v) {
1023
              $invalid[] = $v;
1024
           }
1025
        }
1026
1027
        if(isset($_POST[$mod . $widget_id . 'emailAddressReplyToFlag'])) {
1028
           foreach($_POST[$mod . $widget_id . 'emailAddressReplyToFlag'] as $v) {
1029
              $replyTo[] = $v;
1030
           }
1031
        }
1032
1033
        if(isset($_POST[$mod . $widget_id . 'emailAddressDeleteFlag'])) {
1034
           foreach($_POST[$mod . $widget_id . 'emailAddressDeleteFlag'] as $v) {
1035
              $delete[] = $v;
1036
           }
1037
        }
1038
1039
        while(isset($_POST[$mod . $widget_id . "emailAddressVerifiedValue" . $count])) {
1040
            $verified[] = $_POST[$mod . $widget_id . 'emailAddressVerifiedValue' . $count];
1041
            $count++;
1042
        }
1043
1044
        $this->smarty->assign('emails', $emails);
1045
        $this->smarty->assign('primary', $primary);
1046
        $this->smarty->assign('optOut', $optOut);
1047
        $this->smarty->assign('invalid', $invalid);
1048
        $this->smarty->assign('replyTo', $invalid);
1049
        $this->smarty->assign('delete', $invalid);
1050
        $this->smarty->assign('verified', $invalid);
1051
        $this->smarty->assign('moduleDir', $mod);
1052
1053
        return $this->smarty->fetch("include/SugarEmailAddress/templates/forDuplicatesView.tpl");
1054
    }
1055
1056
    /**
1057
     * getFormBaseURL
1058
     *
1059
     */
1060
    function getFormBaseURL($focus) {
1061
        $get = "";
1062
        $count = 0;
1063
        $mod = isset($focus) ? $focus->module_dir : "";
1064
1065
        $widget_id = $_POST[$mod .'_email_widget_id'];
1066
        $get .= '&' . $mod . '_email_widget_id='. $widget_id;
1067
        $get .= '&emailAddressWidget='.$_POST['emailAddressWidget'];
1068
1069
        while(isset($_REQUEST[$mod . $widget_id . 'emailAddress' . $count])) {
1070
              $get .= "&" . $mod . $widget_id . "emailAddress" . $count . "=" . urlencode($_REQUEST[$mod . $widget_id . 'emailAddress' . $count]);
1071
              $count++;
1072
        } //while
1073
1074
        while(isset($_REQUEST[$mod . $widget_id . 'emailAddressVerifiedValue' . $count])) {
1075
              $get .= "&" . $mod . $widget_id . "emailAddressVerifiedValue" . $count . "=" . urlencode($_REQUEST[$mod . $widget_id . 'emailAddressVerifiedValue' . $count]);
1076
              $count++;
1077
        } //while
1078
1079
        $options = array('emailAddressPrimaryFlag', 'emailAddressOptOutFlag', 'emailAddressInvalidFlag', 'emailAddressDeleteFlag', 'emailAddressReplyToFlag');
1080
1081
        foreach($options as $option) {
1082
            $count = 0;
1083
            $optionIdentifier = $mod.$widget_id.$option;
1084
            if(isset($_REQUEST[$optionIdentifier])) {
1085
               if(is_array($_REQUEST[$optionIdentifier])) {
1086
                   foreach($_REQUEST[$optionIdentifier] as $optOut) {
1087
                      $get .= "&" . $optionIdentifier . "[" . $count . "]=" . $optOut;
1088
                      $count++;
1089
                   } //foreach
1090
               } else {
1091
                   $get .= "&" . $optionIdentifier . "=" . $_REQUEST[$optionIdentifier];
1092
               }
1093
            } //if
1094
        } //foreach
1095
        return $get;
1096
1097
    }
1098
1099 9
    function setView($view) {
1100 9
       $this->view = $view;
1101 9
    }
1102
1103
/**
1104
 * This function is here so the Employees/Users division can be handled cleanly in one place
1105
 * @param object $focus SugarBean
0 ignored issues
show
There is no parameter named $focus. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1106
 * @return string The value for the bean_module column in the email_addr_bean_rel table
1107
 */
1108 69
    function getCorrectedModule(&$module) {
1109 69
        return ($module == "Employees")? "Users" : $module;
1110
    }
1111
1112 3
    public function stash($parentBeanId, $moduleName)
1113
    {
1114 3
        $result = $this->db->query("select email_address_id from email_addr_bean_rel eabr WHERE eabr.bean_id = '".$this->db->quote($parentBeanId)."' AND eabr.bean_module = '".$this->db->quote($moduleName)."' and eabr.deleted=0");
1115 3
        $this->stateBeforeWorkflow = array();
1116 3
        $ids = array();
1117 3
        while ($row = $this->db->fetchByAssoc($result, false))
1118
        {
1119 1
            $ids[] =$this->db->quote($row['email_address_id']); // avoid 2nd order SQL Injection
1120
        }
1121 3
        if (!empty($ids))
1122
        {
1123 1
            $ids = implode("', '", $ids);
1124 1
            $queryEmailData = "SELECT id, email_address, invalid_email, opt_out FROM {$this->table_name} WHERE id IN ('$ids') AND deleted=0";
1125 1
            $result = $this->db->query($queryEmailData);
1126 1
            while ($row = $this->db->fetchByAssoc($result, false))
1127
            {
1128 1
                $this->stateBeforeWorkflow[$row['id']] = array_diff_key($row, array('id' => null));
1129
            }
1130
        }
1131 3
    }
1132
} // end class def
1133
1134
1135
/**
1136
 * Convenience function for MVC (Mystique)
1137
 * @param object $focus SugarBean
1138
 * @param string $field unused
1139
 * @param string $value unused
1140
 * @param string $view DetailView or EditView
1141
 * @return string
1142
 */
1143
function getEmailAddressWidget($focus, $field, $value, $view, $tabindex='0') {
1144 9
    $sea = new SugarEmailAddress();
1145 9
    $sea->setView($view);
1146
1147 9
        if($view == 'EditView' || $view == 'QuickCreate' || $view == 'ConvertLead') {
1148 4
            $module = $focus->module_dir;
1149 4
            if ($view == 'ConvertLead' && $module == "Contacts")  $module = "Leads";
1150
1151 4
            return $sea->getEmailAddressWidgetEditView($focus->id, $module, false,'',$tabindex);
1152
        }
1153
1154 6
    return $sea->getEmailAddressWidgetDetailView($focus);
1155
}
1156