Squashed 'public/legacy/' changes from 52926f2943..c8ba0321c2

c8ba0321c2 Add support for PHP 8.3
9078c9fe6f SuiteCRM 7.14.7 Release
e8c0cdb428 Fix Email compose not sending without system outbound
f25f2793d5 Fix autocomplete not working fully on product number
899b8ce9cc Fix User Wizard Prompt
f378b226ca Update install page to remove smtp settings
bbbd5d60b9 Only allow external oauth to be the same type as email
5cf7a1198d Fix send test email on outbound
e92314e443 Add filter on external oauth connection on system
d242240a42 Add check for group type oauth on system outbound emails
d2cd059f62 Prevent calling set required on detail view on OutboundEmails
55f7a544b3 Properly reset fields when changing auth type on OutboundEmails
fd49ebccb2 Add from address validation to test function in OutboundEmails
0505626587 Fix SMTP OAuth in campaigns
c631df323a Remove save of system outbound email on email settings
4b76c94820 Allow using group OAuth Connections in bounce emails
d5a7868603 Add configurable timeout to test outbound email call
4c13b646b0 Remove mail_smtp_pass conditional display based on mail_smtpauth_req
2a3993bd52 Make OutboundEmailAccount from address and name required
d2a6c3a882 Add ExternalOAuthProvider default Authorize url options
61ddfc3594 Add error display view
50b8223148 Use OAuth authentication when sending emails
f692424805 Update SMTP test functionality to support OAuth
7a73365291 Update UI for configuring system email
9c4606bd81 Add support for auto-refreshing token in SMTP OAuth
8b1937e61a Minor fix in auth_type_fields_toggle.js
34fdf19497 Add support for OAuth in SugarPHPMailer
0fb6910698 Allow choosing different auth_types in OutboundEmailAccounts
6c22edadc5 Add auth_type and external_oauth_connection to OutboundEmailAccounts
2489d660f8 Fix importer progress bar uses incorrect values
bfcca9027f Fix notice messages prevent importing
5f14f96325 Add option to group on Reports field function
05f997dbaa Fix #10345 - Add toggle and field js files
01547c5fdf Fix #10345 - Add redirect uri type field
a5df5d3c84 Fix #10345 - Microsoft Azure OAuth Redirect URL
d32908885f Add support for EntryPoint /ep extension
978d912437 Fix #10532, #10377 - Display issues in global search
5d0ae0b756 Fix #10147, #10396 - Smarty unregistered function deprecated notice
50e4f3e182 Fix #10543 - Remove Security Groups button on subpanelsbased on EditView
06341925f5 Fix #10113 - Contracts / List Items table for services has bogus width
baecf4aba2 Allow End Users to use the PATCH verb for the V8 API
295ee2cec5 Fix #8632 - API V8 /meta/fields/{moduleName} endpoint output without field labels
e05795f930 Fix salesagility#10616 - Default values of DateTime always in English and value “first day of next month” gives an error
6a5d6e84b9 Fix #10285 - Fix non-countable error
2894d48110 Fix #10243 - studio not saving field properties correctly
33eb278141 Fix #10624 - Prevent Multiple Submissions on Survey Forms
5e1e966b95 Fix #10606 - Recently viewed items tooltip shows module name instead of full record name
c3a58cd1fb Fix - #10611 Subpanels don't show related records links when view permission is set to "group"
bebc66986c Fix #8280 - Fix Autocomplete search in line items
6ae6891ddc Fix #10475 - Rename the History subpanel by changing the label
a665c95d7f Fix #10264 - Smarty Error Assigned_user_name in SearchView.tpl
dcf72e04dc Fix #10637 - Local users gets Profile wizard on each login
026c014055 Fix #10660 - Email Template not saving in plain text
b82d9a76c6 Fix #10661 - Add check for preference before setting to default
77c50bb53f Fix #9809 - Incorrect parsing of 0 values in PDF templates
23a9953956 Fix #10400,#9823 Correctly find the id of related objects in search results
7bcd1f9dca Fix #10479 - Call LoggerManager's warn() method instead of warning()
f4d44b016a Fix #10502 - Remove duplicate line
afcf009a99 Fix #10549 - Variable name typo in getEmailInfo
ba11f93fb4 Fix salesagility#10564 - Thank you message in Surveys only in English
75d95fed99 Fix #10599 - Update Import Error
fe188ec0ee Fix #10599 - Update Import Error Styling
REVERT: 52926f2943 PHP 8.3 - Throw exception on Projects Gantt Table
REVERT: 7f5ad0158a PHP 8.3 - Fix PHP warning on import
REVERT: 282a1e0f89 PHP 8.3 - Fix currency formatting on listview
REVERT: dbed1d82cf PHP 8.3 - Fix PHP errors
REVERT: 07eaa3ff60 PHP 8.3 - Fix workflow date conversion error
REVERT: 13ccac1a3c PHP 8.3 - Fix Dates Error on calls
REVERT: 2b92f2cb15 Fix #10264 - Error `Assigned_user_name` `SearchView.tpl` (`{php}` tag now crashes Smarty 4)
REVERT: 660d546c2b Fix #10264 - Error Assigned_user_name SearchView.tpl ({php} tag now crashes Smarty 4)
REVERT: ecb6a6d89b PHP 8.3 - Fix report value not showing
REVERT: fece2fd35e PHP 8.3 - Fix PDF templates breaking detail view
REVERT: e9550a99a1 PHP 8.3 - Set same default as imap called function
REVERT: 17bde6e5a0 PHP 8.3 - Add default to cookie on susoap
REVERT: 01768fc962 PHP 8.3 - Remove deprecated param setting
REVERT: f3f62431fa PHP 8.3 - Remove deprecated ini setting
REVERT: 721fa93977 PHP 8.3 - Fix readability of if
REVERT: f9f7352a1a PHP 8.3 - Fix pdf template breaking listview
REVERT: 8bffb4d83a PHP 8.3 - Update null to -1 on preg split
REVERT: db663af17c PHP 8.3 - Remove unused time field on calls date start
REVERT: 32b6a6289b PHP 8.3 - don't show project task table if no tasks
REVERT: 04257e7663 PHP 8.3 - Fix Reports merge error
REVERT: 514319c6c9 PHP 8.3 - Add entry point variable to controller
REVERT: f37e6af3fb PHP 8.3 - Add quotes to array keys
REVERT: 955a6f8790 PHP 8.3 - Update deprecated use of self
REVERT: b81b1247ec PHP 8.3 - Fix invitee id on reminder
REVERT: 18375148b9 PHP 8.3 - Update OAuth searchdefs
REVERT: f5fdda17f5 PHP 8.3 - Fix margin reading as empty string
REVERT: ad144cb20a PHP 8.3 - Update function variable types
REVERT: f174ae27a8 PHP 8.3 - Update deprecated filter variable
REVERT: 29eb104ec5 PHP 8.3 - Update deprecated date functions
REVERT: 41ed417a94 PHP 8.3 - Update checks to not pass null
REVERT: 48169c4768 PHP 8.3 - Update Missing Labels
REVERT: b62e4a3d17 PHP 8.3 - Fix dashlet warnings and deprecations
REVERT: 5e745b6491 PHP 8.3 - Add and update variables on ListView
REVERT: b7dee66ccf PHP 8.3 - Update labels on tpl
REVERT: 2630420e9b PHP 8.3 - Add checks and defaults for editview field tpls
REVERT: 85aa7efd57 PHP 8.3 - Add checks for detailview field tpls
REVERT: 59d90f871e PHP 8.3 - Add extra checks on recurring message tpls
REVERT: 90fab9c2ac PHP 8.3 - Fix Duplicate variable init

git-subtree-dir: public/legacy
git-subtree-split: c8ba0321c2d89d66ed3c3a4ab175ef8cd590be84
This commit is contained in:
SAgility Dev 2025-08-05 22:39:30 +00:00
parent 8d824c79af
commit 989e304671
122 changed files with 3152 additions and 2017 deletions

View file

@ -1,7 +1,7 @@
<?php
// Swagger needs this, but should remove - CORS
header("Access-Control-Allow-Origin: *");
header('Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE');
header('Access-Control-Allow-Methods: POST, PATCH, GET, OPTIONS, PUT, DELETE');
header('Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With');
// @codingStandardsIgnoreStart

View file

@ -76,8 +76,9 @@ class MetaService
'default',
'len',
'precision',
'comments',
'comment',
'required',
'vname'
];
/**

View file

@ -90,7 +90,7 @@ class UserPreferencesService
$preferences = [];
while ($row = $db->fetchByAssoc($result)) {
$category = $row['category'];
$preferences[$category] = unserialize(base64_decode($row['contents']));
$preferences[$category] = unserialize(base64_decode($row['contents']), ['allowed_classes' => false]);
}
$dataResponse = new DataResponse('UserPreference', $params->getUserId());

View file

@ -916,7 +916,7 @@ class PackageManager
$installed->manifest = base64_encode(serialize($serial_manifest));
$installed->save();
} else {
$serial_manifest = unserialize(base64_decode($installed->manifest));
$serial_manifest = unserialize(base64_decode($installed->manifest), ['allowed_classes' => false]);
$manifest = $serial_manifest['manifest'];
}
if (($upgrades_installed==0 || $uh->UninstallAvailable($installeds, $installed))

View file

@ -2,7 +2,7 @@
<img width="180px" height="41px" src="https://suitecrm.com/wp-content/uploads/2017/12/logo.png" align="right" />
</a>
# SuiteCRM 7.14.6
# SuiteCRM 7.14.7
[![Build Status](https://travis-ci.org/salesagility/SuiteCRM.svg?branch=hotfix)](https://travis-ci.org/salesagility/SuiteCRM)
[![codecov](https://codecov.io/gh/salesagility/SuiteCRM/branch/hotfix/graph/badge.svg)](https://codecov.io/gh/salesagility/SuiteCRM/branch/hotfix)

View file

@ -1,20 +1,19 @@
{
"name": "salesagility/suitecrm",
"name": "suitecrm/suitecrm",
"description": "SuiteCRM",
"homepage": "https://suitecrm.com",
"type": "project",
"license": "GPL-3.0",
"authors": [
{
"name": "SalesAgility Ltd"
"name": "SuiteCRM Ltd"
}
],
"support": {
"issues": "https://github.com/salesagility/SuiteCRM/issues",
"issues": "https://github.com/suitecrm/SuiteCRM/issues",
"wiki": "https://docs.suitecrm.com",
"forum": "https://community.suitecrm.com",
"chat": "https://gitter.im/suitecrm/Lobby",
"source": "https://github.com/salesagility/SuiteCRM"
"source": "https://github.com/suitecrm/SuiteCRM"
},
"config": {
"vendor-dir": "vendor",
@ -39,10 +38,11 @@
"ext-json": "*",
"ext-openssl": "*",
"ext-zip": "*",
"ext-intl": "*",
"consolidation/robo": "^3.0",
"elasticsearch/elasticsearch": "^7.13",
"ezyang/htmlpurifier": "^4.10",
"google/apiclient": "^2.7",
"google/apiclient": "^2.14",
"google/recaptcha": "^1.1",
"gymadarasz/ace": "^1.2",
"gymadarasz/imagesloaded": "^4.1",
@ -60,13 +60,12 @@
"slim/slim": "^3.8",
"smarty/smarty": "^4",
"soundasleep/html2text": "~0.5",
"symfony/options-resolver": "^3.4",
"symfony/validator": "^3.4",
"symfony/options-resolver": "^5.4",
"symfony/validator": "^5.4",
"symfony/yaml": "^5.2",
"tecnickcom/tcpdf": "^6.4",
"tedivm/jshrink": "^1.3",
"tinymce/tinymce": "^5.10",
"vlucas/phpdotenv": "^3.5",
"voku/anti-xss": "^4.0",
"wikimedia/composer-merge-plugin": "^2.0",
"zbateson/mail-mime-parser": "^2.2",
@ -74,8 +73,7 @@
"zf1/zend-loader": "^1.12",
"zf1/zend-oauth": "^1.12",
"zf1/zend-registry": "^1.12",
"zf1/zend-search-lucene": "^1.12",
"ext-intl": "*"
"zf1/zend-search-lucene": "^1.12"
},
"require-dev": {
"browserstack/browserstack-local": "^1.1",
@ -95,7 +93,8 @@
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^9.5",
"rector/rector": "^0.16.0",
"scssphp/scssphp": "^1.5"
"scssphp/scssphp": "^1.5",
"vlucas/phpdotenv": "^5.5"
},
"autoload": {
"files": [

2425
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -57,7 +57,7 @@ if (!is_windows()) {
$cronUser = getRunningUser();
if ($cronUser == '') {
$GLOBALS['log']->warning('cron.php: can\'t determine running user. No cron user checks will occur.');
$GLOBALS['log']->warn('cron.php: can\'t determine running user. No cron user checks will occur.');
} elseif (array_key_exists('cron', $sugar_config) && array_key_exists('allowed_cron_users', $sugar_config['cron'])) {
if (!in_array($cronUser, $sugar_config['cron']['allowed_cron_users'])) {
$GLOBALS['log']->fatal("cron.php: running as $cronUser is not allowed in allowed_cron_users ".
@ -70,7 +70,7 @@ if (!is_windows()) {
sugar_die('cron.php running with user that is not in allowed_cron_users in config.php');
}
} else {
$GLOBALS['log']->warning('cron.php: missing expected allowed_cron_users entry in config.php. ' .
$GLOBALS['log']->warn('cron.php: missing expected allowed_cron_users entry in config.php. ' .
'No cron user checks will occur.');
}
}

View file

@ -1012,7 +1012,11 @@ class SugarController
require_once($this->entry_point_registry[$entryPoint]['file']);
$this->_processed = true;
$this->view = '';
} else {
$this->no_action();
}
} elseif (isset($_REQUEST['entryPoint'])) {
$this->no_action();
}
}

View file

@ -57,6 +57,7 @@ $action_view_map['modulelistmenu']= 'modulelistmenu';
$action_view_map['favorites']= 'favorites';
$action_view_map['ajaxui']= 'ajaxui';
$action_view_map['noaccess']= 'noaccess';
$action_view_map['errors']= 'errors';
// SugarPDF
$action_view_map['sugarpdf']= 'sugarpdf';

View file

@ -558,7 +558,7 @@ class SugarApplication
if ($dieIfInvalid) {
header("Cache-Control: no-cache, must-revalidate");
$ss = new Sugar_Smarty;
$ss->assign('host', $http_host[0]);
$ss->assign('host', securexss($http_host[0]));
$ss->assign('action', $this->controller->action);
$ss->assign('whiteListString', $whiteListString);
$ss->display('include/MVC/View/tpls/xsrf.tpl');
@ -577,7 +577,7 @@ class SugarApplication
$whiteListString = "'" . implode("', '", $whiteListActions) . "'";
$ss = new Sugar_Smarty;
$ss->assign('host', $http_ref['host']);
$ss->assign('host', securexss($http_ref['host']));
$ss->assign('action', $this->controller->action);
$ss->assign('whiteListString', $whiteListString);
$ss->display('include/MVC/View/tpls/xsrf.tpl');

View file

@ -0,0 +1,39 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SuiteCRM Ltd.
* Copyright (C) 2025 SuiteCRM Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUITECRM, SUITECRM DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
class ViewErrors extends SugarView
{
public $type = 'errors';
/**
* @see SugarView::display()
*/
public function display()
{
}
}

View file

@ -89,6 +89,8 @@ class OutboundEmail
public $mail_smtpssl; // bool
public $mail_smtpdisplay; // calculated value, not in DB
public $new_with_id = false;
public $auth_type; // no_auth, oauth2, external_oauth
public $external_oauth_connection_id; // no_auth, oauth2, external_oauth
/**
* Sole constructor
@ -389,6 +391,19 @@ class OutboundEmail
return $allowAccess;
}
public function getSystemEmail(): ?object
{
$q = "SELECT id FROM outbound_email WHERE type = 'system' AND deleted = 0";
$r = $this->db->query($q);
$a = $this->db->fetchByAssoc($r);
if (!empty($a)) {
return $this->retrieve($a['id']) ?? null;
}
return null;
}
/**
* Retrieves the system's Outbound options
*/

View file

@ -186,7 +186,7 @@ class SearchForm
$this->th->ss->assign('action', $this->action);
$this->th->ss->assign('displayView', $this->displayView);
$this->th->ss->assign('viewTab', $this->getViewTab());
$this->th->ss->assign('user_options', get_user_array(false)); // Fix https://github.com/salesagility/SuiteCRM/issues/10264
$this->th->ss->assign('user_options', get_user_array(false));
require_once('modules/MySettings/StoreQuery.php');
$storeQuery = new StoreQuery();

View file

@ -863,8 +863,6 @@ class SubPanelDefinitions
*/
public function get_hidden_subpanels()
{
global $moduleList;
//create variable as static to minimize queries
static $hidden_subpanels = null;
@ -879,25 +877,9 @@ class SubPanelDefinitions
$hidden_subpanels = $administration->settings['MySettings_hide_subpanels'];
$hidden_subpanels = trim($hidden_subpanels);
//make sure serialized string is not empty
if (!empty($hidden_subpanels)) {
//decode and unserialize to retrieve the array
$hidden_subpanels = base64_decode($hidden_subpanels);
$hidden_subpanels = unserialize($hidden_subpanels);
//Ensure modules saved in the preferences exist.
//get user preference
//unserialize and add to array if not empty
$pref_hidden = array();
foreach ($pref_hidden as $id => $pref_hidden_panel) {
$hidden_subpanels[] = $pref_hidden_panel;
}
} else {
//no settings found, return empty
return $hidden_subpanels;
$hidden_subpanels = unserialize(base64_decode($hidden_subpanels), ['allowed_classes' => false]);
}
} else { //no settings found, return empty
return $hidden_subpanels;
}
}

View file

@ -135,7 +135,7 @@ class SugarCacheFile extends SugarCacheAbstract
) {
// load up the external cache file
if (is_file($cachedfile = sugar_cached($this->_cacheFileName))) {
$this->localCache = unserialize(file_get_contents($cachedfile));
$this->localCache = unserialize(file_get_contents($cachedfile), ['allowed_classes' => false]);
}
if (isset($this->_localStore[$key])) {

View file

@ -141,7 +141,7 @@ class SugarCacheRedis extends SugarCacheAbstract
}
return is_string($returnValue) ?
unserialize($returnValue) :
unserialize($returnValue, ['allowed_classes' => false]) :
$returnValue;
}

View file

@ -86,7 +86,7 @@ class SugarCacheZend extends SugarCacheAbstract
return null;
}
return is_string($raw_cache_value) ?
unserialize($raw_cache_value) :
unserialize($raw_cache_value, ['allowed_classes' => false]) :
$raw_cache_value;
}

View file

@ -40,5 +40,4 @@
*}
{{capture name=display_size assign=size}}{{$displayParams.size|default:6}}{{/capture}}
{html_options name='{{$vardef.name}}[]' options=$user_options size="{{$size}}" style="width: 150px" {{if $size > 1}}multiple="1"{{/if}} selected={{sugarvar key='value' string=true}}}

View file

@ -132,23 +132,28 @@ class SugarPHPMailer extends PHPMailer
$this->Mailer = 'smtp';
$this->Host = $oe->mail_smtpserver;
$this->Port = $oe->mail_smtpport;
if ($oe->mail_smtpssl == 1) {
$this->SMTPSecure = 'ssl';
} // if
if ($oe->mail_smtpssl == 2) {
$this->SMTPSecure = 'tls';
} // if
if ($oe->mail_smtpauth_req) {
$this->SMTPAuth = true;
$this->Username = $oe->mail_smtpuser;
$this->Password = $oe->mail_smtppass;
}
$this->setSecureProtocol($oe->mail_smtpssl);
$this->initSMTPAuth(
$oe->auth_type ?? '',
$oe->external_oauth_connection_id ?? '',
$oe->mail_smtpuser ?? '',
$oe->mail_smtppass ?? '',
);
} else {
$this->Mailer = 'sendmail';
}
}
public function setSystemFromAddress(): void
{
require_once 'include/OutboundEmail/OutboundEmail.php';
$oe = new OutboundEmail();
$oe = $oe->getSystemMailerSettings();
$this->From = $oe->smtp_from_addr ?? '';
$this->FromName = $oe->smtp_from_name ?? '';
}
/**
* Prefills mailer for system
*/
@ -166,22 +171,81 @@ class SugarPHPMailer extends PHPMailer
$this->Mailer = 'smtp';
$this->Host = $oe->mail_smtpserver;
$this->Port = $oe->mail_smtpport;
if ($oe->mail_smtpssl == 1) {
$this->SMTPSecure = 'ssl';
} // if
if ($oe->mail_smtpssl == 2) {
$this->SMTPSecure = 'tls';
} // if
if ($oe->mail_smtpauth_req) {
$this->SMTPAuth = true;
$this->Username = $oe->mail_smtpuser;
$this->Password = $oe->mail_smtppass;
}
$this->setSecureProtocol($oe->mail_smtpssl);
$this->initSMTPAuth(
$oe->auth_type ?? '',
$oe->external_oauth_connection_id ?? '',
$oe->mail_smtpuser ?? '',
$oe->mail_smtppass ?? '',
);
} else {
$this->Mailer = 'sendmail';
}
}
public function initSMTPAuth(
string $authType,
string $externalOAuthConnectionId,
string $smtpUser,
string $smtpPass,
): void {
if ($authType === 'oauth') {
$this->initOAuth(
$authType,
$externalOAuthConnectionId,
$smtpUser,
);
return;
}
if ($authType === 'basic') {
$this->SMTPAuth = true;
$this->Username = $smtpUser;
$this->Password = $smtpPass;
}
}
public function initOAuth(
string $authType,
string $externalOAuthConnectionId,
string $smtpUser
): void
{
if ($authType !== 'oauth') {
return;
}
$this->isSMTP();
$this->SMTPAuth = true;
$this->AuthType = 'XOAUTH2';
$oAuthConnectionId = $externalOAuthConnectionId;
require_once 'modules/ExternalOAuthConnection/services/OAuthAuthorizationService.php';
$oAuth = new OAuthAuthorizationService();
$oAuth->refreshExpiredOAuthToken($oAuthConnectionId);
/** @var ExternalOAuthConnection $oauthConnection */
$oauthConnection = BeanFactory::getBean('ExternalOAuthConnection', $oAuthConnectionId);
$providerId = $oauthConnection->external_oauth_provider_id;
$oauthConfig = new \PHPMailer\PHPMailer\OAuth([
'provider' => $oAuth?->getProvider($providerId)?->getProvider($oauthConnection->client_id, $oauthConnection->client_secret),
'clientId' => $oauthConnection->client_id,
'refreshToken' => $oauthConnection->refresh_token,
'clientSecret' => $oauthConnection->client_secret,
'userName' => $smtpUser
]);
$this->setOAuth(
$oauthConfig
);
}
/**
* handles Charset translation for all visual parts of the email.
*/
@ -469,7 +533,7 @@ eoq;
$ret = parent::send();
$this->exceptions = $saveExceptionsState;
} catch (Exception $e) {
$phpMailerExceptionMsg=$e->errorMessage(); //Pretty error messages from PHPMailer
$phpMailerExceptionMsg =$e->getMessage(); //Pretty error messages from PHPMailer
if ($phpMailerExceptionMsg) {
$GLOBALS['log']->error("send: PHPMailer Exception: { $phpMailerExceptionMsg }");
}
@ -490,4 +554,18 @@ eoq;
*/
return $ret;
}
public function setSecureProtocol($smtpSsl): void
{
$this->protocol = ($smtpSsl) ? "ssl://" : "tcp://";
if ($smtpSsl == 1) {
$this->protocol = "ssl://";
$this->SMTPSecure = 'ssl';
}
if ($smtpSsl == 2) {
$this->protocol = "ssl://";
$this->SMTPSecure = 'tls';
}
}
} // end class definition

View file

@ -341,7 +341,7 @@ class SugarTheme
}
if (!inDeveloperMode()) {
if (is_file($cachedfile = sugar_cached($this->getFilePath().'/pathCache.php'))) {
$caches = unserialize(file_get_contents($cachedfile));
$caches = unserialize(file_get_contents($cachedfile), ['allowed_classes' => false]);
if (isset($caches['jsCache'])) {
$this->_jsCache = $caches['jsCache'];
}
@ -357,7 +357,7 @@ class SugarTheme
}
$cachedfile = sugar_cached($this->getFilePath().'/spriteCache.php');
if (!empty($GLOBALS['sugar_config']['use_sprites']) && is_file($cachedfile)) {
$this->_spriteCache = unserialize(sugar_file_get_contents($cachedfile));
$this->_spriteCache = unserialize(sugar_file_get_contents($cachedfile), ['allowed_classes' => false]);
}
}
$this->_initialCacheSize = array(

View file

@ -75,12 +75,25 @@ class Sugar_Smarty extends Smarty
mkdir_recursive(SUGAR_SMARTY_DIR . 'cache', true);
}
$this->template_dir = '.';
$this->compile_dir = SUGAR_SMARTY_DIR . 'templates_c';
$this->config_dir = SUGAR_SMARTY_DIR . 'configs';
$this->cache_dir = SUGAR_SMARTY_DIR . 'cache';
//$this->request_use_auto_globals = true; // to disable Smarty from using long arrays
$this->setTemplateDir('.');
$this->setCompileDir(SUGAR_SMARTY_DIR . 'templates_c');
$this->setCacheDir(SUGAR_SMARTY_DIR . 'cache');
$this->setConfigDir(SUGAR_SMARTY_DIR . 'configs');
$this->registerPHPFunctions([
'count',
'intval',
'is_string',
'key',
'preg_match',
'substr',
'strpos',
'strstr',
'strtoupper',
'strval',
'url2html'
]);
//TODO fix literals
$this->auto_literal = false;
@ -94,7 +107,16 @@ class Sugar_Smarty extends Smarty
$this->assign("VERSION_MARK", getVersionedPath(''));
}
public function registerPHPFunctions(array $functions): void
{
foreach ($functions as $function) {
try {
$this->registerPlugin(Smarty::PLUGIN_MODIFIER, $function, $function);
} catch (SmartyException $e) {
$GLOBALS['log']->fatal('Smarty: Failed to register PHP function' . $function . ': ' . $e->getMessage());
}
}
}
/**
* Override default _unlink method call to fix Bug 53010

View file

@ -125,10 +125,11 @@ class SugarWidgetSubPanelDetailViewLink extends SugarWidgetField
$detailView = $layout_def['DetailView'] ?? '';
$ownerId = $layout_def['owner_id'] ?? '';
$ownerModule = $layout_def['owner_module'] ?? '';
$groupAccessView = SecurityGroup::groupHasAccess($module,$record,'view');
if (!empty($record) &&
($detailView && !$layout_def['owner_module']
|| $detailView && !ACLController::moduleSupportsACL($layout_def['owner_module'])
|| ACLController::checkAccess($ownerModule, 'view', $ownerId == $current_user->id))) {
|| $detailView && !ACLController::moduleSupportsACL($layout_def['owner_module'])
|| ACLController::checkAccess($ownerModule, 'view', $ownerId == $current_user->id, 'module', $groupAccessView))) {
$link = ajaxLink("index.php?module=$module&action=$action&record={$record}{$parent}");
if ($module == 'EAPM') {
$link = "index.php?module=$module&action=$action&record={$record}{$parent}";

View file

@ -115,8 +115,7 @@ class SugarWidgetSubPanelRemoveButton extends SugarWidgetField
$hideremove = true;
}
//based on listview since that lets you select records
if ($layout_def['ListView'] && !$hideremove) {
if ($layout_def['EditView'] && !$hideremove) {
$retStr = "<a href=\"javascript:sub_p_rem('$subpanel', '$linked_field'"
. ", '$record', $refresh_page);\""
. ' class="listViewTdToolsS1"'

View file

@ -296,6 +296,12 @@ $app_list_strings = array(
'Dr.' => 'Dr.',
'Prof.' => 'Prof.',
),
'redirect_uri_type_dom' => [
'pretty_url' => 'Pretty URL (/ep/)',
'query_string' => 'Query String (index.php?entryPoint=)'
],
//time is in seconds; the greater the time the longer it takes;
'reminder_max_time' => 90000,
'reminder_time_options' => array(
@ -711,6 +717,12 @@ $app_list_strings = array(
'oauth' => 'OAuth',
],
'dom_outbound_email_auth_types' => [
'no_auth' => 'No Auth',
'basic' => 'Basic Auth',
'oauth' => 'OAuth',
],
'dom_external_oauth_connection_types' => [
'personal' => 'Personal',
'group' => 'Group',
@ -1399,6 +1411,7 @@ $app_strings = array(
'LBL_EMAIL_SETTINGS_CHECK_INTERVAL' => 'Check for New Mail',
'LBL_EMAIL_SETTINGS_FROM_ADDR' => 'From Address',
'LBL_EMAIL_SETTINGS_FROM_TO_EMAIL_ADDR' => 'Email Address For Test Notification:',
'LBL_EMAIL_SETTINGS_FROM_ADDR_NOT_SET' => 'From address and/or From name not set',
'LBL_EMAIL_SETTINGS_FROM_NAME' => 'From Name',
'LBL_EMAIL_SETTINGS_REPLY_TO_ADDR' => 'Reply to Address',
'LBL_EMAIL_SETTINGS_FULL_SYNC' => 'Synchronize All Mail Accounts',
@ -3950,6 +3963,8 @@ $app_strings['LBL_VALUE_SET_PLACEHOLDER'] = 'Value set. Enter new value to overr
$app_strings['ERR_IMAP_OAUTH_CONNECTION_ERROR'] = 'Not able to connect using OAuth login with Inbound Email server. For connection: ';
$app_strings['WARN_OAUTH_TOKEN_SESSION_EXPIRED'] = 'Your IMAP OAuth session has expired, please login again in the connection: ';
$app_strings['ERR_OAUTH_CONNECTION_ERROR'] = 'Not able to connect using OAuth login. For connection: ';
$app_strings['LBL_KEY'] = 'Key';
$app_strings['LBL_VALUE'] = 'Value';
$app_strings['LBL_OPTIONAL'] = 'Optional';

View file

@ -154,7 +154,7 @@ class nusoap_wsdlcache
$this->debug("$wsdl ($filename) not in cache (2)");
}
$this->releaseMutex($filename);
return (!is_null($s)) ? unserialize($s) : null;
return (!is_null($s)) ? unserialize($s, ['allowed_classes' => false]) : null;
}
$this->debug("Unable to obtain mutex for $filename in get");

View file

@ -2393,7 +2393,7 @@ function clean_xss($str, $cleanImg = true)
$sugar_config['email_xss'] = getDefaultXssTags();
}
$xsstags = unserialize(base64_decode($sugar_config['email_xss']));
$xsstags = unserialize(base64_decode($sugar_config['email_xss']), ['allowed_classes' => false]);
// cn: bug 13079 - "on\w" matched too many non-events (cONTact, strONG, etc.)
$jsEvents = 'onblur|onfocus|oncontextmenu|onresize|onscroll|onunload|ondblclick|onclick|';
@ -5978,7 +5978,7 @@ function sugar_unserialize($value)
return false;
}
return unserialize($value);
return unserialize($value, ['allowed_classes' => false]);
}
define('DEFAULT_UTIL_SUITE_ENCODING', 'UTF-8');

View file

@ -589,343 +589,6 @@ EOQ;
//--End of scenarios
//---------------
// SMTP Settings
//-------------------->
// smtp
// TODO-t: test it for all types
$MAIL_SSL_OPTIONS_GMAIL = get_select_options_with_id($app_list_strings['email_settings_for_ssl'], '2');
//$MAIL_SSL_OPTIONS_YAHOO = get_select_options_with_id($app_list_strings['email_settings_for_ssl'], '1');
$MAIL_SSL_OPTIONS_EXCHG = get_select_options_with_id($app_list_strings['email_settings_for_ssl'], 'none');
$MAIL_SSL_OPTIONS_OTHER = get_select_options_with_id($app_list_strings['email_settings_for_ssl'], 'none');
// set default notify_allow_default_outbound checkbox value
$notify_allow_default_outbound_checked = empty($_SESSION['notify_allow_default_outbound']) ? '' : ' checked="checked" ';
// set default smtp toggle buttons selected value
if (empty($_SESSION['smtp_tab_selected'])) {
$_SESSION['smtp_tab_selected'] = 'smtp_tab_other';
}
if (!isset($_SESSION['smtp_from_name']) || !$_SESSION['smtp_from_name']) {
$_SESSION['smtp_from_name'] = 'SuiteCRM';
}
if (!isset($_SESSION['smtp_from_addr']) || !$_SESSION['smtp_from_addr']) {
$_SESSION['smtp_from_addr'] = 'do_not_reply@example.com';
}
$out .= <<<EOQ
<div class="floatbox full" id="fb2">
<!-- smtp settings -->
<h3 onclick="$(this).next().toggle();" class="toggler">&raquo; {$mod_strings['LBL_MAIL_SMTP_SETTINGS']}</h3>
<div style="display: none;">
<br>
<!--
<p>{$mod_strings['LBL_WIZARD_SMTP_DESC']}</p>
-->
<!-- smtp types toggler buttons -->
<p style="display: inline;">
<div>
<div class="formrow">
<label>{$mod_strings['LBL_FROM_NAME']}</label>
<input type="text" name="smtp_from_name" value="{$_SESSION['smtp_from_name']}">
</div>
<div class="formrow">
<label>{$mod_strings['LBL_FROM_ADDR']}</label>
<input type="email" name="smtp_from_addr" value="{$_SESSION['smtp_from_addr']}">
</div>
</div>
<div class="clear"></div>
{$mod_strings['LBL_CHOOSE_EMAIL_PROVIDER']} </p><div class="tooltip-toggle"> <em>i</em> <div class="tooltip">{$mod_strings['LBL_WIZARD_SMTP_DESC']}</div></div>
<div class="clear"></div>
<div>
<input type="button" class="smtp_tab_toggler" id="smtp_tab_gmail_toggler" for="smtp_tab_gmail" value="{$mod_strings['LBL_SMTPTYPE_GMAIL']}" />
<input type="button" class="smtp_tab_toggler" id="smtp_tab_yahoo_toggler" for="smtp_tab_yahoo" value="{$mod_strings['LBL_SMTPTYPE_YAHOO']}" />
<input type="button" class="smtp_tab_toggler" id="smtp_tab_exchange_toggler" for="smtp_tab_exchange" value="{$mod_strings['LBL_SMTPTYPE_EXCHANGE']}" />
<input type="button" class="smtp_tab_toggler selected" id="smtp_tab_other_toggler" for="smtp_tab_other" value="{$mod_strings['LBL_SMTPTYPE_OTHER']}" />
<input type="hidden" name="smtp_tab_selected" value="{$_SESSION['smtp_tab_selected']}">
</div>
<!-- smtp / gmail tab -->
<div class="form_section smtp_tab" id="smtp_tab_gmail">
<div class="formrow">
<label>{$mod_strings['LBL_MAIL_SMTPSERVER']}</label>
<input type="text" name="smtp_tab_gmail[mail_smtpserver]" size="25" maxlength="255" value="smtp.gmail.com">
</div>
<div class="formrow">
<label>{$mod_strings['LBL_MAIL_SMTPPORT']}</label>
<input type="text" name="smtp_tab_gmail[mail_smtpport]" size="5" maxlength="5" value="587">
</div>
<div class="clear"></div>
<div class="formrow">
<label>{$mod_strings['LBL_MAIL_SMTPAUTH_REQ']}</label>
<input type="checkbox" name="smtp_tab_gmail[mail_smtpauth_req]" id="smtp_tab_gmail__mail_smtpauth_req" value="1" checked="checked" onclick="toggleSMTPAuthSettings(this, 'toggleArea_1');">
</div>
<div class="formrow">
<label>{$mod_strings['LBL_EMAIL_SMTP_SSL_OR_TLS']}</label>
<select name="smtp_tab_gmail[mail_smtpssl]">
{$MAIL_SSL_OPTIONS_GMAIL}
</select>
</div>
<div class="clear"></div>
<div class="toggleArea" id="toggleArea_1">
<div class="formrow">
<label>{$mod_strings['LBL_GMAIL_SMTPUSER']}</label>
<input type="text" name="smtp_tab_gmail[mail_smtpuser]" id="smtp_tab_gmail__mail_smtpuser" size="25" maxlength="255">
</div>
<div class="clear"></div>
<div class="formrow">
<label>{$mod_strings['LBL_GMAIL_SMTPPASS']}</label>
<input type="password" name="smtp_tab_gmail[mail_smtppass]" id="smtp_tab_gmail__mail_smtppass" size="25" maxlength="255" value="" tabindex="1">
</div>
<div class="clear"></div>
<div class="formrow">
<label>{$mod_strings['LBL_ALLOW_DEFAULT_SELECTION']} <i>i<div class="tooltip">{$mod_strings['LBL_ALLOW_DEFAULT_SELECTION_HELP']}</div></i></label>
<input name="smtp_tab_gmail[notify_allow_default_outbound]" id="smtp_tab_gmail__notify_allow_default_outbound" value="2" tabindex="1" class="checkbox" type="checkbox" {$notify_allow_default_outbound_checked}>
</div>
</div>
<div class="clear"></div>
</div>
<!-- smtp / yahoo! mail tab -->
<div class="form_section smtp_tab" id="smtp_tab_yahoo">
<input type="hidden" name="smtp_tab_yahoo[mail_smtpserver]" size="25" maxlength="255" value="smtp.mail.yahoo.com">
<input type="text" name="smtp_tab_yahoo[mail_smtpport]" size="5" maxlength="5" value="465">
<input type="hidden" name="smtp_tab_yahoo[mail_smtpssl]" value="1">
<div class="formrow">
<label>{$mod_strings['LBL_YAHOOMAIL_SMTPUSER']}</label>
<input type="text" name="smtp_tab_yahoo[mail_smtpuser]" size="25" maxlength="255">
</div>
<div class="clear"></div>
<div class="formrow">
<label>{$mod_strings['LBL_YAHOOMAIL_SMTPPASS']}</label>
<input type="password" name="smtp_tab_yahoo[mail_smtppass]" size="25" maxlength="255" value="" tabindex="1">
</div>
<div class="clear"></div>
<div class="formrow">
<label>{$mod_strings['LBL_ALLOW_DEFAULT_SELECTION']} <i>i<div class="tooltip">{$mod_strings['LBL_ALLOW_DEFAULT_SELECTION_HELP']}</div></i></label>
<input name="smtp_tab_yahoo[notify_allow_default_outbound]" value="2" tabindex="1" class="checkbox" type="checkbox" {$notify_allow_default_outbound_checked}>
</div>
<div class="clear"></div>
</div>
<!-- smtp / ms-exchange tab -->
<div class="form_section smtp_tab" id="smtp_tab_exchange">
<div class="formrow">
<label>{$mod_strings['LBL_EXCHANGE_SMTPSERVER']}</label>
<input type="text" name="smtp_tab_exchange[mail_smtpserver]" size="25" maxlength="255" value="">
</div>
<div class="formrow">
<label>{$mod_strings['LBL_EXCHANGE_SMTPPORT']}</label>
<input type="text" name="smtp_tab_exchange[mail_smtpport]" size="5" maxlength="5" value="25">
</div>
<div class="clear"></div>
<div class="formrow">
<label>{$mod_strings['LBL_MAIL_SMTPAUTH_REQ']}</label>
<input type="checkbox" name="smtp_tab_exchange[mail_smtpauth_req]" id="smtp_tab_exchange__mail_smtpauth_req" value="1" checked="checked" onclick="toggleSMTPAuthSettings(this, 'toggleArea_2');">
</div>
<div class="formrow">
<label>{$mod_strings['LBL_EMAIL_SMTP_SSL_OR_TLS']}</label>
<select name="smtp_tab_exchange[mail_smtpssl]" tabindex="501">
{$MAIL_SSL_OPTIONS_EXCHG}
</select>
</div>
<div class="clear"></div>
<div class="toggleArea" id="toggleArea_2">
<div class="formrow">
<label>{$mod_strings['LBL_EXCHANGE_SMTPUSER']}</label>
<input type="text" name="smtp_tab_exchange[mail_smtpuser]" id="smtp_tab_exchange__mail_smtpuser" size="25" maxlength="255">
</div>
<div class="clear"></div>
<div class="formrow">
<label>{$mod_strings['LBL_EXCHANGE_SMTPPASS']}</label>
<input type="password" name="smtp_tab_exchange[mail_smtppass]" id="smtp_tab_exchange__mail_smtppass" size="25" maxlength="255" value="" tabindex="1">
</div>
<div class="clear"></div>
<div class="formrow">
<label>{$mod_strings['LBL_ALLOW_DEFAULT_SELECTION']} <i>i<div class="tooltip">{$mod_strings['LBL_ALLOW_DEFAULT_SELECTION_HELP']}</div></i></label>
<input name="smtp_tab_exchange[notify_allow_default_outbound]" id="smtp_tab_exchange__notify_allow_default_outbound" value="2" tabindex="1" class="checkbox" type="checkbox" {$notify_allow_default_outbound_checked}>
</div>
</div>
<div class="clear"></div>
</div>
<!-- smtp / other tab-->
<div class="form_section smtp_tab" id="smtp_tab_other">
<div class="formrow">
<label>{$mod_strings['LBL_MAIL_SMTPSERVER']}</label>
<input type="text" name="smtp_tab_other[mail_smtpserver]" size="25" maxlength="255" value="">
</div>
<div class="formrow">
<label>{$mod_strings['LBL_MAIL_SMTPPORT']}</label>
<input type="text" name="smtp_tab_other[mail_smtpport]" size="5" maxlength="5" value="25">
</div>
<div class="clear"></div>
<div class="formrow">
<label>{$mod_strings['LBL_MAIL_SMTPAUTH_REQ']}</label>
<input type="hidden" name="smtp_tab_other[mail_smtpauth_req]" value="0">
<input type="checkbox" id="mail_smtpauth_req_chk" name="smtp_tab_other[mail_smtpauth_req]" value="1" checked="checked" onclick="toggleSMTPAuthSettings(this, 'toggleArea_3');">
</div>
<div class="formrow">
<label>{$mod_strings['LBL_EMAIL_SMTP_SSL_OR_TLS']}</label>
<select name="smtp_tab_other[mail_smtpssl]" tabindex="501">
{$MAIL_SSL_OPTIONS_OTHER}
</select>
</div>
<div class="clear"></div>
<div class="toggleArea" id="toggleArea_3">
<div class="formrow">
<label>{$mod_strings['LBL_MAIL_SMTPUSER']}</label>
<input type="text" name="smtp_tab_other[mail_smtpuser]" id="smtp_tab_other__mail_smtpuser" size="25" maxlength="255">
</div>
<div class="clear"></div>
<div class="formrow">
<label>{$mod_strings['LBL_MAIL_SMTPPASS']}</label>
<input type="password" name="smtp_tab_other[mail_smtppass]" id="smtp_tab_other__mail_smtppass" size="25" maxlength="255" value="" tabindex="1">
</div>
<div class="clear"></div>
<div class="formrow">
<label>{$mod_strings['LBL_ALLOW_DEFAULT_SELECTION']} <i>i<div class="tooltip">{$mod_strings['LBL_ALLOW_DEFAULT_SELECTION_HELP']}</div></i></label>
<input type="hidden" name="smtp_tab_other[notify_allow_default_outbound]" value="0">
<input id="notify_allow_default_outbound_chk" name="smtp_tab_other[notify_allow_default_outbound]" value="2" tabindex="1" class="checkbox" type="checkbox" {$notify_allow_default_outbound_checked}>
</div>
</div>
<div class="clear"></div>
<!-- </div> -->
<!-- smtp default values & tabs toggler js & tooltip help -->
<script>
var toggleSMTPAuthFields = {
toggleArea_1 : {
user: 'smtp_tab_gmail__mail_smtpuser',
pass: 'smtp_tab_gmail__mail_smtppass',
allow: 'smtp_tab_gmail__notify_allow_default_outbound'
},
toggleArea_2 : {
user: 'smtp_tab_exchange__mail_smtpuser',
pass: 'smtp_tab_exchange__mail_smtppass',
allow: 'smtp_tab_exchange__notify_allow_default_outbound'
},
toggleArea_3 : {
user: 'smtp_tab_other__mail_smtpuser',
pass: 'smtp_tab_other__mail_smtppass',
allow: 'notify_allow_default_outbound_chk'
}
};
var toggleSMTPAuthSettings = function(chkbox, elemID) {
if($(chkbox).prop('checked')) {
$('#' + elemID).show();
}
else {
$('#' + toggleSMTPAuthFields[elemID].user).val('');
$('#' + toggleSMTPAuthFields[elemID].pass).val('');
$('#' + toggleSMTPAuthFields[elemID].allow).prop('checked', false);
$('#' + elemID).hide();
}
};
$(function(){
$('.smtp_tab_toggler').click(function(){
$('.smtp_tab_toggler.selected').removeClass('selected');
$(this).addClass('selected');
$('.smtp_tab').hide();
$('#'+$(this).attr('for')).show();
$('input[name="smtp_tab_selected"]').val($(this).attr('for'));
});
// save last selected tab and set as default when form (re)load
$('#{$_SESSION['smtp_tab_selected']}_toggler').click();
$('select[name="smtp_tab_gmail[mail_smtpssl]"] option').each(function(){
if(!$(this).html()) {
$(this).html('-none-');
}
});
$('select[name="smtp_tab_yahoo[mail_smtpssl]"] option').each(function(){
if(!$(this).html()) {
$(this).html('-none-');
}
});
$('select[name="smtp_tab_exchange[mail_smtpssl]"] option').each(function(){
if(!$(this).html()) {
$(this).html('-none-');
}
});
$('select[name="smtp_tab_other[mail_smtpssl]"] option').each(function(){
if(!$(this).html()) {
$(this).html('-none-');
}
});
toggleSMTPAuthSettings(document.getElementById('smtp_tab_gmail__mail_smtpauth_req'), 'toggleArea_1');
toggleSMTPAuthSettings(document.getElementById('smtp_tab_exchange__mail_smtpauth_req'), 'toggleArea_2');
toggleSMTPAuthSettings(document.getElementById('mail_smtpauth_req_chk'), 'toggleArea_3');
});
</script>
</div> <!-- toggle hidden box end -->
EOQ;
// db setup (dbConfig_a.php)
$out2 =<<<EOQ2
<input type='hidden' name='setup_db_drop_tables' id='setup_db_drop_tables' value=''>
@ -956,8 +619,6 @@ EOQ2;
$out .= <<<EOQ
<!-- Branding -->
</div>
</div>
<div class="floatbox full" id="fb3">
<h3 onclick="$(this).next().toggle();" class="toggler">&raquo; {$mod_strings['LBL_WIZARD_SYSTEM_TITLE']}</h3>

View file

@ -1031,6 +1031,8 @@ EOQ;
RewriteBase {$basePath}
RewriteRule ^cache/jsLanguage/(.._..).js$ index.php?entryPoint=jslang&modulename=app_strings&lang=$1 [L,QSA]
RewriteRule ^cache/jsLanguage/(\w*)/(.._..).js$ index.php?entryPoint=jslang&modulename=$1&lang=$2 [L,QSA]
RewriteRule ^ep/(.*?)$ index.php?entryPoint=$1 [L,QSA]
# --------- DEPRECATED --------
RewriteRule ^api/(.*)$ - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

View file

@ -143,6 +143,7 @@ class SearchResults
$obj->load_relationships();
$fieldDefs = $obj->getFieldDefinitions();
$obj = $this->formatForDisplay($obj, $fieldDefs);
$parsed[$module][] = $this->updateFieldDefLinks($obj, $fieldDefs);
}
}
@ -150,6 +151,68 @@ class SearchResults
return $parsed;
}
/**
* Format data so it can be correctly displayed on search results
*
* @param SugarBean $obj
* @param array $fieldDefs
* @return SugarBean
*/
protected function formatForDisplay(SugarBean $obj, array $fieldDefs): SugarBean
{
global $app_list_strings, $locale;
foreach ($fieldDefs as $fieldDef) {
$value = $obj->{$fieldDef['name']};
if (isset($value)) {
switch ($fieldDef['type']){
case 'enum':
case 'dynamicenum':
if (isset($app_list_strings[$obj->field_name_map[$fieldDef['name']]['options']][$value]) &&
isset($obj->field_name_map[$fieldDef['name']]['options'])
) {
$obj->{$fieldDef['name']} = $app_list_strings[$obj->field_name_map[$fieldDef['name']]['options']][$value];
}
break;
case 'multienum':
if (isset($obj->field_name_map[$fieldDef['name']]['options']) &&
isset($app_list_strings[$obj->field_name_map[$fieldDef['name']]['options']])
) {
$multienumString = '';
$multienumValues = unencodeMultienum($value);
$arrayCount = count($multienumValues);
$i = 0;
foreach ($multienumValues as $multienumValue) {
$i++;
$multienumString .= $app_list_strings[$obj->field_name_map[$fieldDef['name']]['options']][$multienumValue];
if($i !== ($arrayCount)) $multienumString .= ", ";
}
$obj->{$fieldDef['name']} = $multienumString;
}
break;
case 'currency':
if (substr($fieldDef['name'], -9) !== '_usdollar') {
$params['currency_id'] = getCurrencyId($obj->module_dir, $obj->id);
$params['currency_symbol'] = $locale->currencies[$params['currency_id']]['symbol'];
} else {
$params['currency_id'] = $locale->getPrecedentPreference('currency');
$params['currency_symbol'] = $locale->getPrecedentPreference('default_currency_symbol');
$params['convert'] = true;
}
$obj->{$fieldDef['name']} = currency_format_number($value, $params);
break;
}
}
}
return $obj;
}
/**
*
* @param SugarBean $obj
@ -210,7 +273,12 @@ class SearchResults
{
$relField = $idName;
if (isset($obj->$link)) {
$relId = $obj->$link->getFocus()->$relField;
$linkedBeans = $obj->$link->getBeans();
if(count($linkedBeans) === 1){
$relId = array_keys($linkedBeans)[0];
} else {
$relId = $obj->$link->getFocus()->$relField;
}
if (is_object($relId)) {
if (method_exists($relId, "getFocus")) {
$relId = $relId->getFocus()->id;
@ -242,9 +310,9 @@ class SearchResults
*/
protected function getLink(string $label, string $module, string $record, string $action): string
{
global $sugar_config;
return "<a href=\"{$sugar_config['site_url']}/index.php?action={$action}&module={$module}&record={$record}&offset=1\"><span>{$label}</span></a>";
$link = ajaxLink("index.php?action={$action}&module={$module}&record={$record}");
return "<a href=\"{$link}\"><span>{$label}</span></a>";
}
/**

View file

@ -143,8 +143,15 @@ class SearchResultsController extends Controller
$smarty->assign('results', $this->results);
$smarty->assign('APP', $app_strings);
$smarty->assign('SITE_URL', $siteUrl);
$moduleName = [];
try {
$smarty->assign('resultsAsBean', $this->results->getHitsAsBeans());
$hitsAsBeans = $this->results->getHitsAsBeans();
foreach($hitsAsBeans as $bean){
$moduleName[$bean[0]->module_name] = translate('LBL_MODULE_NAME', $bean[0]->module_name);
}
$smarty->assign('moduleLabel', $moduleName);
$smarty->assign('resultsAsBean', $hitsAsBeans);
} catch (\SuiteCRM\Exception\Exception $e) {
LoggerManager::getLogger()->fatal("Failed to retrieve ElasticSearch options");
}

View file

@ -91,7 +91,7 @@
{/if}
{foreach from=$resultsAsBean item=beans key=module}
<h3>{$module}</h3>
<h3>{$moduleLabel[$module]}</h3>
<table class="list view">
<thead>
<tr>

View file

@ -406,7 +406,6 @@ EOF;
options: {
grouping:'$grouping',
backgroundGrid:false,
backgroundGrid:false,
gutterBottom: 150,
gutterTop:25,
gutterLeft:128,

View file

@ -56,10 +56,10 @@ function display_condition_lines($focus, $field, $value, $view)
while ($row = $focus->db->fetchByAssoc($result)) {
$condition_name = BeanFactory::newBean('AOR_Conditions');
$condition_name->retrieve($row['id']);
$condition_name->module_path = unserialize(base64_decode($condition_name->module_path));
$condition_name->module_path = unserialize(base64_decode($condition_name->module_path),['allowed_classes' => false]);
$html .= "report_fields = \"".trim(preg_replace('/\s+/', ' ', (string) getModuleFields(getRelatedModule($focus->report_module, $condition_name->module_path[0]))))."\";";
if ($condition_name->value_type == 'Date') {
$condition_name->value = unserialize(base64_decode($condition_name->value));
$condition_name->value = unserialize(base64_decode($condition_name->value),['allowed_classes' => false]);
}
$condition_item = json_encode($condition_name->toArray());
$html .= "loadConditionLine(".$condition_item.");";
@ -84,9 +84,9 @@ function display_condition_lines($focus, $field, $value, $view)
while ($row = $focus->db->fetchByAssoc($result)) {
$condition_name = BeanFactory::newBean('AOR_Conditions');
$condition_name->retrieve($row['id']);
$condition_name->module_path = unserialize(base64_decode($condition_name->module_path));
$condition_name->module_path = unserialize(base64_decode($condition_name->module_path),['allowed_classes' => false]);
if ($condition_name->value_type == 'Date') {
$condition_name->value = unserialize(base64_decode($condition_name->value));
$condition_name->value = unserialize(base64_decode($condition_name->value),['allowed_classes' => false]);
}
$condition_item = json_encode($condition_name->toArray());
$html .= "loadConditionLine(".$condition_item.");";

View file

@ -61,7 +61,7 @@ function display_field_lines($focus, $field, $value, $view)
while ($row = $focus->db->fetchByAssoc($result)) {
$field_name = BeanFactory::newBean('AOR_Fields');
$field_name->retrieve($row['id']);
$field_name->module_path = unserialize(base64_decode($field_name->module_path));
$field_name->module_path = unserialize(base64_decode($field_name->module_path),['allowed_classes' => false]);
$html .= "report_fields = \"".trim(preg_replace('/\s+/', ' ', (string) getModuleFields(getRelatedModule($focus->report_module, $field_name->module_path[0]))))."\";";
$field_item = json_encode($field_name->toArray());
$html .= "loadFieldLine(".$field_item.");";

View file

@ -204,8 +204,8 @@ class AOR_Report extends Basic
while ($row = $this->db->fetchByAssoc($result)) {
$field = BeanFactory::newBean('AOR_Fields');
$field->retrieve($row['id']);
$path = unserialize(base64_decode($field->module_path));
$path = unserialize(base64_decode($field->module_path),['allowed_classes' => false]);
$field_bean = new $beanList[$this->report_module]();
@ -311,7 +311,7 @@ class AOR_Report extends Basic
$GLOBALS['log']->fatal('ambiguous group display for report ' . $this->id);
} else {
if ($rowsCount == 1) {
$rows[0]['module_path'] = unserialize(base64_decode($rows[0]['module_path']));
$rows[0]['module_path'] = unserialize(base64_decode($rows[0]['module_path']),['allowed_classes' => false]);
if (!$rows[0]['module_path'][0]) {
$module = new $beanList[$this->report_module]();
$rows[0]['field_id_name'] = $module->field_defs[$rows[0]['field']]['id_name'] ? $module->field_defs[$rows[0]['field']]['id_name'] : $module->field_defs[$rows[0]['field']]['name'];
@ -440,7 +440,7 @@ class AOR_Report extends Basic
$field_label = str_replace(' ', '_', (string) $field->label);
$path = unserialize(base64_decode($field->module_path));
$path = unserialize(base64_decode($field->module_path),['allowed_classes' => false]);
$field_module = $module;
$table_alias = $field_module->table_name;
@ -670,7 +670,7 @@ class AOR_Report extends Basic
$field = BeanFactory::newBean('AOR_Fields');
$field->retrieve($row['id']);
$path = unserialize(base64_decode($field->module_path));
$path = unserialize(base64_decode($field->module_path),['allowed_classes' => false]);
$field_bean = new $beanList[$this->report_module]();
@ -905,7 +905,7 @@ class AOR_Report extends Basic
// End
}
$path = unserialize(base64_decode($field->module_path));
$path = unserialize(base64_decode($field->module_path),['allowed_classes' => false]);
$field_bean = new $beanList[$this->report_module]();
@ -1047,7 +1047,7 @@ class AOR_Report extends Basic
$field = BeanFactory::newBean('AOR_Fields');
$field->retrieve($row['id']);
$path = unserialize(base64_decode($field->module_path));
$path = unserialize(base64_decode($field->module_path),['allowed_classes' => false]);
$field_bean = new $beanList[$this->report_module]();
$field_module = $this->report_module;
$field_alias = $field_bean->table_name;
@ -1240,9 +1240,7 @@ class AOR_Report extends Basic
$field->label = str_replace(' ', '_', (string) $field->label) . $i;
$path = unserialize(base64_decode($field->module_path));
$data = $field_module->field_defs[$field->field] ?? [];
$path = unserialize(base64_decode($field->module_path),['allowed_classes' => false]);
$field_module = $module;
$table_alias = $field_module->table_name;
@ -1265,7 +1263,7 @@ class AOR_Report extends Basic
$field_module = $new_field_module;
}
}
$data = $field_module->field_defs[$field->field] ?? [];
if (!empty($data)){
if ($data['type'] == 'relate' && isset($data['id_name'])) {
@ -1340,10 +1338,11 @@ class AOR_Report extends Basic
unset($query['id_select'][$table_alias]);
}
if ($field->group_by == 1) {
if ($field->field_function != null) {
$unique = $field->group_by == 1 ? 'DISTINCT ' : '';
$select_field = $field->field_function . '(' . $unique . $select_field . ')';
} elseif ($field->group_by == 1) {
$query['group_by'][] = $select_field;
} elseif ($field->field_function != null) {
$select_field = $field->field_function . '(' . $select_field . ')';
} else {
$query['second_group_by'][] = $select_field;
}
@ -1490,14 +1489,14 @@ class AOR_Report extends Basic
$condition = BeanFactory::newBean('AOR_Conditions');
$condition->retrieve($row['id']);
$path = unserialize(base64_decode($condition->module_path));
$path = unserialize(base64_decode($condition->module_path),['allowed_classes' => false]);
$condition_module = $module;
$table_alias = $condition_module->table_name;
$oldAlias = $table_alias;
if (!empty($path[0]) && $path[0] != $module->module_dir) {
foreach ($path as $rel) {
if (empty($rel)) {
if (empty($rel) || !is_string($rel)) {
continue;
}
// Bug: Prevents relationships from loading.
@ -1629,7 +1628,7 @@ class AOR_Report extends Basic
break;
case 'Date':
$params = unserialize(base64_decode($condition->value));
$params = unserialize(base64_decode($condition->value),['allowed_classes' => false]);
// Fix for issue #1272 - AOR_Report module cannot update Date type parameter.
if ($params == false) {

View file

@ -185,7 +185,7 @@ function getConditionsAsParameters($report, $override = array())
continue;
}
$path = unserialize(base64_decode($condition->module_path));
$path = unserialize(base64_decode($condition->module_path),['allowed_classes' => false]);
$field_module = $report->report_module;
if ($path[0] != $report->report_module) {
foreach ($path as $rel) {
@ -196,7 +196,7 @@ function getConditionsAsParameters($report, $override = array())
}
}
$additionalConditions = unserialize(base64_decode($condition->value));
$additionalConditions = unserialize(base64_decode($condition->value),['allowed_classes' => false]);
$value = isset($override[$condition->id]['value']) ? $override[$condition->id]['value'] : $value = $condition->value;

View file

@ -38,9 +38,9 @@ class AOR_ReportsViewDetail extends ViewDetail
if (!$condition->parameter) {
continue;
}
$condition->module_path = implode(":", unserialize(base64_decode($condition->module_path)));
$condition->module_path = implode(":", unserialize(base64_decode($condition->module_path),['allowed_classes' => false]));
if ($condition->value_type == 'Date') {
$condition->value = unserialize(base64_decode($condition->value));
$condition->value = unserialize(base64_decode($condition->value),['allowed_classes' => false]);
}
$condition_item = $condition->toArray();
$display = getDisplayForField($condition->module_path, $condition->field, $this->bean->report_module);

View file

@ -82,10 +82,10 @@ class AOR_ReportsViewEdit extends ViewEdit
$condition_name = BeanFactory::newBean('AOR_Conditions');
$condition_name->retrieve($row['id']);
if (!$condition_name->parenthesis) {
$condition_name->module_path = implode(":", unserialize(base64_decode($condition_name->module_path)));
$condition_name->module_path = implode(":", unserialize(base64_decode($condition_name->module_path),['allowed_classes' => false]));
}
if ($condition_name->value_type == 'Date') {
$condition_name->value = unserialize(base64_decode($condition_name->value));
$condition_name->value = unserialize(base64_decode($condition_name->value),['allowed_classes' => false]);
}
$condition_item = $condition_name->toArray();
@ -115,7 +115,7 @@ class AOR_ReportsViewEdit extends ViewEdit
while ($row = $this->bean->db->fetchByAssoc($result)) {
$field_name = BeanFactory::newBean('AOR_Fields');
$field_name->retrieve($row['id']);
$field_name->module_path = implode(":", unserialize(base64_decode($field_name->module_path)));
$field_name->module_path = implode(":", unserialize(base64_decode($field_name->module_path),['allowed_classes' => false]));
$arr = $field_name->toArray();

View file

@ -91,7 +91,7 @@ class AOR_Scheduled_Reports extends basic
public function get_email_recipients()
{
$params = unserialize(base64_decode($this->email_recipients));
$params = unserialize(base64_decode($this->email_recipients),['allowed_classes' => false]);
$emails = array();
if (isset($params['email_target_type'])) {

View file

@ -42,7 +42,7 @@ function display_email_lines($focus, $field, $value, $view)
{
global $app_list_strings;
$aorEmailToList = $app_list_strings['aor_email_to_list'] ?? '';
$params = unserialize(base64_decode($value));
$params = unserialize(base64_decode($value),['allowed_classes' => false]);
if ($view == 'EditView') {
$html = '<script src="modules/AOR_Scheduled_Reports/emailRecipients.js"></script>';

View file

@ -67,7 +67,7 @@ class templateParser
if (isset($field_def['name']) && $field_def['name'] != '') {
$fieldName = $field_def['name'];
if (empty($focus->$fieldName)) {
if (!isset($focus->$fieldName) || $focus->$fieldName === '') {
$repl_arr[$key . '_' . $fieldName] = '';
continue;
}

View file

@ -184,7 +184,7 @@ function display_lines($focus, $field, $value, $view)
if ($serviceCount == 0) {
$service .= "<tr>";
$service .= "<td width='5%' class='tabDetailViewDL' style='text-align: left;padding:2px;' scope='row'>&nbsp;</td>";
$service .= "<td width='46%' class='dataLabel' style='text-align: left;padding:2px;' colspan='2' scope='row'>".$mod_strings['LBL_SERVICE_NAME']."</td>";
$service .= "<td width='22%' class='dataLabel' style='text-align: left;padding:2px;' colspan='2' scope='row'>".$mod_strings['LBL_SERVICE_NAME']."</td>";
$service .= "<td width='12%' class='dataLabel' style='text-align: right;padding:2px;' scope='row'>".$mod_strings['LBL_SERVICE_LIST_PRICE']."</td>";
$service .= "<td width='12%' class='dataLabel' style='text-align: right;padding:2px;' scope='row'>".$mod_strings['LBL_SERVICE_DISCOUNT']."</td>";
$service .= "<td width='12%' class='dataLabel' style='text-align: right;padding:2px;' scope='row'>".$mod_strings['LBL_SERVICE_PRICE']."</td>";

View file

@ -57,13 +57,13 @@ function display_condition_lines($focus, $field, $value, $view)
while ($row = $focus->db->fetchByAssoc($result)) {
$condition_name = BeanFactory::newBean('AOW_Conditions');
$condition_name->retrieve($row['id']);
$condition_name->module_path = unserialize(base64_decode($condition_name->module_path));
$condition_name->module_path = unserialize(base64_decode($condition_name->module_path), ['allowed_classes' => false]);
if ($condition_name->module_path == '') {
$condition_name->module_path = $focus->flow_module;
}
$html .= "flow_fields = \"".trim(preg_replace('/\s+/', ' ', (string) getModuleFields(getRelatedModule($focus->flow_module, $condition_name->module_path[0]))))."\";";
if ($condition_name->value_type == 'Date') {
$condition_name->value = unserialize(base64_decode($condition_name->value));
$condition_name->value = unserialize(base64_decode($condition_name->value), ['allowed_classes' => false]);
}
$condition_item = json_encode($condition_name->toArray());
$html .= "loadConditionLine(".$condition_item.");";
@ -88,13 +88,13 @@ function display_condition_lines($focus, $field, $value, $view)
while ($row = $focus->db->fetchByAssoc($result)) {
$condition_name = BeanFactory::newBean('AOW_Conditions');
$condition_name->retrieve($row['id']);
$condition_name->module_path = unserialize(base64_decode($condition_name->module_path));
$condition_name->module_path = unserialize(base64_decode($condition_name->module_path), ['allowed_classes' => false]);
if (empty($condition_name->module_path)) {
$condition_name->module_path[0] = $focus->flow_module;
}
$html .= "flow_fields = \"".trim(preg_replace('/\s+/', ' ', (string) getModuleFields(getRelatedModule($focus->flow_module, $condition_name->module_path[0]))))."\";";
if ($condition_name->value_type == 'Date') {
$condition_name->value = unserialize(base64_decode($condition_name->value));
$condition_name->value = unserialize(base64_decode($condition_name->value), ['allowed_classes' => false]);
}
$condition_item = json_encode($condition_name->toArray());
$html .= "loadConditionLine(".$condition_item.");";

View file

@ -389,7 +389,7 @@ class AOW_WorkFlow extends Basic
public function build_query_where(AOW_Condition $condition, $module, $query = array())
{
global $beanList, $app_list_strings, $sugar_config, $timedate;
$path = unserialize(base64_decode($condition->module_path));
$path = unserialize(base64_decode($condition->module_path), ['allowed_classes' => false]);
$condition_module = $module;
$table_alias = $condition_module->table_name;
@ -514,7 +514,7 @@ class AOW_WorkFlow extends Basic
return array();
case 'Date':
$params = @unserialize(base64_decode($condition->value));
$params = @unserialize(base64_decode($condition->value), ['allowed_classes' => false]);
if ($params === false) {
LoggerManager::getLogger()->error('Unserializable data given');
$params = [null];
@ -749,7 +749,7 @@ class AOW_WorkFlow extends Basic
$condition = BeanFactory::newBean('AOW_Conditions');
$condition->retrieve($row['id']);
$path = unserialize(base64_decode($condition->module_path));
$path = unserialize(base64_decode($condition->module_path), ['allowed_classes' => false]);
$condition_bean = $bean;
@ -815,7 +815,7 @@ class AOW_WorkFlow extends Basic
break;
case 'Date':
$params = unserialize(base64_decode($value));
$params = unserialize(base64_decode($value), ['allowed_classes' => false]);
$dateType = 'datetime';
if ($params[0] == 'now') {
$value = date('Y-m-d H:i:s');
@ -1055,7 +1055,7 @@ class AOW_WorkFlow extends Basic
$flow_action = new $action_name($action->id);
if (!$flow_action->run_action($bean, unserialize(base64_decode($action->parameters)), $in_save)) {
if (!$flow_action->run_action($bean, unserialize(base64_decode($action->parameters), ['allowed_classes' => false]), $in_save)) {
$pass = false;
$processed->aow_actions->add($action->id, array('status' => 'Failed'));
} else {

View file

@ -559,7 +559,7 @@ class AOW_WorkFlowController extends SugarController
$aow_action = BeanFactory::newBean('AOW_Actions');
$aow_action->retrieve($_REQUEST['id']);
$id = $aow_action->id;
$params = unserialize(base64_decode($aow_action->parameters ?? ''));
$params = unserialize(base64_decode($aow_action->parameters ?? ''), ['allowed_classes' => false]);
if ($params === false) {
$params = [];

View file

@ -203,7 +203,7 @@ if ($mail->Mailer == 'smtp' && $mail->Host == '') {
$focus = BeanFactory::newBean('InboundEmail');
$focus->checkImap();
$storedOptions = unserialize(base64_decode($focus->stored_options ?? ''));
$storedOptions = unserialize(base64_decode($focus->stored_options ?? ''), ['allowed_classes' => false]);
$email_templates_arr = get_bean_select_array(true, 'EmailTemplate', 'name', '', 'name', true);
$create_case_email_template = (isset($storedOptions['create_case_email_template'])) ? $storedOptions['create_case_email_template'] : "";
$TMPL_DRPDWN_LOST = get_select_options_with_id($email_templates_arr, $res['lostpasswordtmpl']);

View file

@ -66,7 +66,8 @@ class Controller extends AbstractController
*/
public function doSave(): void
{
$searchEngine = filter_input(INPUT_POST, 'search-engine');
$searchEngine = filter_input(INPUT_POST, 'search-engine', FILTER_SANITIZE_STRING);
$aod = $searchEngine === 'BasicAndAodEngine';
SearchConfigurator::make()
->setEngine($searchEngine)

View file

@ -98,7 +98,7 @@ $has_updates= false;
if (!empty($license->settings['license_latest_versions'])) {
$encodedVersions = $license->settings['license_latest_versions'];
$versions = unserialize(base64_decode($encodedVersions));
$versions = unserialize(base64_decode($encodedVersions), ['allowed_classes' => false]);
include('sugar_version.php');
if (!empty($versions)) {
foreach ($versions as $version) {

View file

@ -78,7 +78,7 @@ while ($row = $db->fetchByAssoc($result)) {
$prefs = array();
$newprefs = array();
$prefs = unserialize(base64_decode($row['user_preferences']));
$prefs = unserialize(base64_decode($row['user_preferences']), ['allowed_classes' => false]);
$setTo = '';
$alreadySet = '';
if (!empty($prefs)) {

View file

@ -196,7 +196,7 @@ function check_now($send_usage_info=true, $get_request_data=false, $response_dat
if ($response_data || !$sclient->getError()) {
$serializedResultData = sugarDecode($key, $encodedResult);
$resultData = unserialize($serializedResultData);
$resultData = unserialize($serializedResultData, ['allowed_classes' => false]);
if ($response_data && empty($resultData)) {
$resultData = array();
$resultData['validation'] = 'invalid validation key';

View file

@ -231,7 +231,7 @@ class CalendarDisplay
if (empty($activity)) {
$activity = $this->activity_colors;
}
$newActivities = unserialize(base64_decode($current_user->getPreference("CalendarActivities") ?? ''));
$newActivities = unserialize(base64_decode($current_user->getPreference("CalendarActivities") ?? ''), ['allowed_classes' => false]);
if ($newActivities) {
$activity = array_merge($activity, $newActivities);
}

View file

@ -135,7 +135,7 @@ function get_campaign_mailboxes_with_stored_options()
$r = $db->query($q);
while ($a = $db->fetchByAssoc($r)) {
$ret[$a['id']] = unserialize(base64_decode($a['stored_options']));
$ret[$a['id']] = unserialize(base64_decode($a['stored_options']), ['allowed_classes' => false]);
}
return $ret;
}

View file

@ -49,21 +49,28 @@ class TemplateDatetimecombo extends TemplateRange
{
public $type = 'datetimecombo';
public $len = '';
public $dateStrings = array(
'-none-' => '',
'today'=>'now',
'yesterday'=> '-1 day',
'tomorrow'=>'+1 day',
'next week'=> '+1 week',
'next monday'=>'next monday',
'next friday'=>'next friday',
'two weeks'=> '+2 weeks',
'next month'=> '+1 month',
'first day of next month'=> 'first of next month', // must handle this non-GNU date string in SugarBean->populateDefaultValues; if we don't this will evaluate to 1969...
'three months'=> '+3 months', //kbrill Bug #17023
'six months'=> '+6 months',
'next year'=> '+1 year',
);
public $dateStrings;
public function __construct()
{
parent::__construct();
global $app_strings;
$this->dateStrings = array(
$app_strings['LBL_NONE']=>'',
$app_strings['LBL_YESTERDAY']=> '-1 day',
$app_strings['LBL_TODAY']=>'now',
$app_strings['LBL_TOMORROW']=>'+1 day',
$app_strings['LBL_NEXT_WEEK']=> '+1 week',
$app_strings['LBL_NEXT_MONDAY']=>'next monday',
$app_strings['LBL_NEXT_FRIDAY']=>'next friday',
$app_strings['LBL_TWO_WEEKS']=> '+2 weeks',
$app_strings['LBL_NEXT_MONTH']=> '+1 month',
$app_strings['LBL_FIRST_DAY_OF_NEXT_MONTH']=> 'first day of next month', // must handle this non-GNU date string in SugarBean->populateDefaultValues; if we don't this will evaluate to 1969...
$app_strings['LBL_THREE_MONTHS']=> '+3 months', //kbrill Bug #17023
$app_strings['LBL_SIXMONTHS']=> '+6 months',
$app_strings['LBL_NEXT_YEAR']=> '+1 year',
);
}
public $hoursStrings = array(
'' => '',

View file

@ -153,7 +153,7 @@ class TemplateEnum extends TemplateText
$def['studio'] = 'visible';
// this class may be extended, so only do the unserialize for genuine TemplateEnums
if (get_class($this) == 'TemplateEnum' && empty($def['dependency'])) {
$def['dependency'] = $this->ext4 !== null? unserialize(html_entity_decode((string) $this->ext4)) : null ;
$def['dependency'] = $this->ext4 !== null? unserialize(html_entity_decode((string) $this->ext4), ['allowed_classes' => false]) : null ;
}
if (!empty($this->visibility_grid)) {
$def['visibility_grid'] = $this->visibility_grid;

View file

@ -128,7 +128,7 @@ class TemplateMultiEnum extends TemplateEnum
// turn off error reporting in case we are unpacking a value that hasn't been packed...
// this is kludgy, but unserialize doesn't throw exceptions correctly
if ($this->ext4[0] == 'a' && $this->ext4[1] == ':') {
$unpacked = @unserialize($this->ext4) ;
$unpacked = @unserialize($this->ext4, ['allowed_classes' => false]) ;
} else {
$unpacked = false;
}

View file

@ -50,7 +50,7 @@ require_once('modules/Notes/Note.php');
$note = BeanFactory::newBean('Notes');
//check if file is an email image
if (!$note->retrieve_by_string_fields(array('id' => $_REQUEST['id'], 'parent_type' => "Emails"))) {
//die("Not a Valid Entry Point");
die("Not a Valid Entry Point");
}
$location = $GLOBALS['sugar_config']['upload_dir']."/" . $_REQUEST['id'];

View file

@ -81,8 +81,7 @@ if (isset($admin->settings['massemailer_email_copy'])) {
$emailsPerSecond = 10;
$mail->setMailerForSystem();
$mail->From = "no-reply@example.com";
$mail->FromName = "no-reply";
$mail->setSystemFromAddress();
$mail->ContentType = "text/html";
$campaign_id = null;
@ -226,32 +225,29 @@ do {
$mail->Mailer = 'smtp';
$mail->Host = $outboundEmailAccount->mail_smtpserver;
$mail->Port = $outboundEmailAccount->mail_smtpport;
if ($outboundEmailAccount->mail_smtpssl == 1) {
$mail->SMTPSecure = 'ssl';
} elseif ($outboundEmailAccount->mail_smtpssl == 2) {
$mail->SMTPSecure = 'tls';
} else {
$mail->SMTPSecure = '';
}
if ($outboundEmailAccount->mail_smtpauth_req) {
$mail->SMTPAuth = true;
$mail->Username = $outboundEmailAccount->mail_smtpuser;
$mail->Password = $outboundEmailAccount->mail_smtppass;
} else {
$mail->SMTPAuth = false;
$mail->Username = '';
$mail->Password = '';
}
$mail->setSecureProtocol($ssltls ?? false);
$mail->initSMTPAuth(
$outboundEmailAccount->auth_type ?? '',
$outboundEmailAccount->external_oauth_connection_id ?? '',
$outboundEmailAccount->mail_smtpuser ?? '',
$outboundEmailAccount->mail_smtppass ?? '',
);
} else {
$mail->Mailer = 'sendmail';
}
$mail->oe->mail_smtpauth_req = $outboundEmailAccount->mail_smtpauth_req;
$mail->oe->mail_smtpuser = $outboundEmailAccount->mail_smtpuser;
$mail->oe->mail_smtppass = $outboundEmailAccount->mail_smtppass;
$mail->oe->mail_smtpserver = $outboundEmailAccount->mail_smtpserver;
$mail->oe->mail_smtpport = $outboundEmailAccount->mail_smtpport;
$mail->oe->mail_smtpssl = $outboundEmailAccount->mail_smtpssl;
$mail->oe->auth_type = $outboundEmailAccount->auth_type ?? '';
$mail->oe->external_oauth_connection_id = $outboundEmailAccount->external_oauth_connection_id ?? '';
$mail->oe->mail_smtpauth_req = $outboundEmailAccount->mail_smtpauth_req ?? '';
$mail->oe->mail_smtpuser = $outboundEmailAccount->mail_smtpuser ?? '';
$mail->oe->mail_smtppass = $outboundEmailAccount->mail_smtppass ?? '';
$mail->oe->mail_smtpserver = $outboundEmailAccount->mail_smtpserver ?? '';
$mail->oe->mail_smtpport = $outboundEmailAccount->mail_smtpport ?? '';
$mail->oe->mail_smtpssl = $outboundEmailAccount->mail_smtpssl ?? '';
$mail->FromName = $outboundEmailAccount->smtp_from_name ?? $outboundEmailAccount->mail_smtpuser;
$mail->From = $outboundEmailAccount->smtp_from_address ?? $outboundEmailAccount->mail_smtpuser;
}
if ((empty($row['related_confirm_opt_in']) || $row['related_confirm_opt_in'] == '0')) {

View file

@ -61,15 +61,6 @@ class EmailManController extends SugarController
$_REQUEST['mail_sendtype'] = "SMTP";
}
// save Outbound settings #Bug 20033 Ensure data for Outbound email exists before trying to update the system mailer.
if (isset($_REQUEST['mail_sendtype']) && empty($_REQUEST['campaignConfig'])) {
$oe = new OutboundEmail();
$oe->populateFromPost();
$oe->saveSystem();
}
$focus = BeanFactory::newBean('Administration');
if (isset($_POST['tracking_entities_location_type'])) {

View file

@ -139,6 +139,7 @@ $mod_strings = array(
'LBL_FROM_ADDRESS_HELP' => 'When enabled, the assigning user\\\'s name and email address will be included in the From field of the email. This feature might not work with SMTP servers that do not allow sending from a different email account than the server account.',
'LBL_HELP' => 'Help' /*for 508 compliance fix*/,
'LBL_OUTBOUND_EMAIL_ACCOUNT_VIEW' => 'View Outbound Email Accounts',
'LBL_SYSTEM_OUTBOUND_EMAIL_ACCOUNT' => 'System Outbound Email Account',
'LBL_ALLOW_SEND_AS_USER' => 'Users may send as themselves:',
'LBL_ALLOW_SEND_AS_USER_DESC' => 'When enabled, <b>all</b> users can send email using the outgoing mail server, using their own primary email address as the &quot;From:&quot; address.<br>This feature might not work with SMTP servers that do not allow sending from a different email account than the server account.',
);

View file

@ -52,9 +52,22 @@ global $mod_strings;
global $app_list_strings;
global $app_strings;
global $current_user;
global $sugar_config;
$testMaxTimeout = 30; // seconds
if (isset($sugar_config['outbound_email_test_max_timeout']) && is_numeric($sugar_config['outbound_email_test_max_timeout'])) {
$testMaxTimeout = (int)$sugar_config['outbound_email_test_max_timeout'];
}
ini_set('max_execution_time', $testMaxTimeout);
$json = getJSONobj();
$pass = '';
if (empty($_REQUEST['mail_smtppass'])) {
$_REQUEST['mail_smtppass'] = BeanFactory::getBean('OutboundEmailAccounts', $_REQUEST['record'])?->mail_smtppass ?? '';
}
if (!empty($_REQUEST['mail_smtppass'])) {
$pass = $_REQUEST['mail_smtppass'];
} elseif (isset($_REQUEST['mail_type'])) {
@ -73,13 +86,15 @@ $out = $email->sendEmailTest(
$_REQUEST['mail_smtpserver'],
$_REQUEST['mail_smtpport'],
$_REQUEST['mail_smtpssl'],
($_REQUEST['mail_smtpauth_req'] == 'true' ? 1 : 0),
(isTrue($_REQUEST['mail_smtpauth_req']) ? 1 : 0),
$_REQUEST['mail_smtpuser'],
$pass,
$_REQUEST['outboundtest_from_address'],
$_REQUEST['outboundtest_to_address'],
$_REQUEST['mail_sendtype'],
$_REQUEST['mail_from_name']
$_REQUEST['mail_from_name'],
$_REQUEST['mail_auth_type'] ?? 'no_auth',
$_REQUEST['mail_external_oauth_connection_id'] ?? '',
);
$out = $json->encode($out);

View file

@ -99,96 +99,39 @@ function change_state(radiobutton) {
{$MOD.LBL_OUTGOING_SECTION_HELP}
</td>
</tr>
<tr class="{$OUTBOUND_TYPE_CLASS}">
<td width="20%" scope="row">{$MOD.LBL_MAIL_SENDTYPE}</td>
<td width="30%">
<select id="mail_sendtype" name="mail_sendtype" onChange="notify_setrequired(document.ConfigureSettings); SUGAR.user.showHideGmailDefaultLink(this);" tabindex="1">{$mail_sendtype_options}</select>
</td>
<td scope="row">&nbsp;</td>
<td >&nbsp;</td>
</tr>
<tr>
<td width="25%" scope="row">
{$MOD.LBL_SYSTEM_OUTBOUND_EMAIL_ACCOUNT}
</td>
{if empty($system_outbound_email_id)}
<td width="30%">
{sugar_link
module="OutboundEmailAccounts"
label=$APP.LBL_CREATE_BUTTON_LABEL
action='Edit'
class="btn btn-sm btn-primary"
extraparams="type=system"
}
</td>
{/if}
{if !empty($system_outbound_email_id)}
<td width="30%">
{sugar_link
module="OutboundEmailAccounts"
record=$system_outbound_email_id
label=$system_outbound_email_name
action='DetailView'
}
</td>
{/if}
<td></td>
</tr>
<tr>
<td width="20%" scope="row">{$MOD.LBL_NOTIFY_FROMNAME} <span class="required">{$APP.LBL_REQUIRED_SYMBOL}</span></td>
<td width="30%" > <input id='notify_fromname' name='notify_fromname' tabindex='1' size='25' maxlength='128' type="text" value="{$notify_fromname}"></td>
</tr>
<tr>
<td width="20%" scope="row">{$MOD.LBL_NOTIFY_FROMADDRESS} <span class="required">{$APP.LBL_REQUIRED_SYMBOL}</span></td>
<td width="30%"><input id='notify_fromaddress' name='notify_fromaddress' tabindex='1' size='25' maxlength='128' type="text" value="{$notify_fromaddress}"></td>
</tr>
<tr>
<td align="left" scope="row" colspan="4">{$MOD.LBL_CHOOSE_EMAIL_PROVIDER}</td>
</tr>
<tr>
<td colspan="4">
<div id="smtpButtonGroup" class="yui-buttongroup">
<span id="gmail" class="yui-button yui-radio-button{if $mail_smtptype == 'gmail'} yui-button-checked{/if}">
<span class="first-child">
<button type="button" name="mail_smtptype" value="gmail" class="btn btn-danger">
&nbsp;&nbsp;&nbsp;&nbsp;{$APP.LBL_SMTPTYPE_GMAIL}&nbsp;&nbsp;&nbsp;&nbsp;
</button>
</span>
</span>
<span id="yahoomail" class="yui-button yui-radio-button{if $mail_smtptype == 'yahoomail'} yui-button-checked{/if}">
<span class="first-child">
<button type="button" name="mail_smtptype" value="yahoomail" class="btn btn-danger">
&nbsp;&nbsp;&nbsp;&nbsp;{$APP.LBL_SMTPTYPE_YAHOO}&nbsp;&nbsp;&nbsp;&nbsp;
</button>
</span>
</span>
<span id="exchange" class="yui-button yui-radio-button{if $mail_smtptype == 'exchange'} yui-button-checked{/if}">
<span class="first-child">
<button type="button" name="mail_smtptype" value="exchange" class="btn btn-danger">
&nbsp;&nbsp;&nbsp;&nbsp;{$APP.LBL_SMTPTYPE_EXCHANGE}&nbsp;&nbsp;&nbsp;&nbsp;
</button>
</span>
</span>
<span id="other" class="yui-button yui-radio-button{if $mail_smtptype == 'other' || empty($mail_smtptype)} yui-button-checked{/if}">
<span class="first-child">
<button type="button" name="mail_smtptype" value="other" class="btn btn-danger">
&nbsp;&nbsp;&nbsp;&nbsp;{$APP.LBL_SMTPTYPE_OTHER}&nbsp;&nbsp;&nbsp;&nbsp;
</button>
</span>
</span>
</div>
</td>
</tr>
<tr>
<td colspan="4">
<td colspan="2">
<div id="smtp_settings">
<table width="100%" cellpadding="0" cellspacing="0">
<tr id="mailsettings1">
<td width="20%" scope="row"><span id="mail_smtpserver_label">{$MOD.LBL_MAIL_SMTPSERVER}</span> <span class="required">{$APP.LBL_REQUIRED_SYMBOL}</span></td>
<td width="30%" ><input type="text" id="mail_smtpserver" name="mail_smtpserver" tabindex="1" size="25" maxlength="255" value="{$mail_smtpserver}"></td>
<td width="20%" scope="row"><span id="mail_smtpport_label">{$MOD.LBL_MAIL_SMTPPORT}</span> <span class="required">{$APP.LBL_REQUIRED_SYMBOL}</span></td>
<td width="30%" ><input type="text" id="mail_smtpport" name="mail_smtpport" tabindex="1" size="5" maxlength="5" value="{$mail_smtpport}"></td>
</tr>
<tr id="mailsettings2">
<td scope="row"><span id='mail_smtpauth_req_label'>{$MOD.LBL_MAIL_SMTPAUTH_REQ}</span></td>
<td >
<input id='mail_smtpauth_req' name='mail_smtpauth_req' type="checkbox" class="checkbox" value="1" tabindex='1'
onclick="notify_setrequired(document.ConfigureSettings);" {$mail_smtpauth_req}>
</td>
<td width="15%" scope="row"><span id="mail_smtpssl_label">{$APP.LBL_EMAIL_SMTP_SSL_OR_TLS}</span></td>
<td width="35%" >
<select id="mail_smtpssl" name="mail_smtpssl" tabindex="501" onchange="setDefaultSMTPPort();" >{$MAIL_SSL_OPTIONS}</select>
</td>
</tr>
<tr id="smtp_auth1">
<td width="20%" scope="row"><span id="mail_smtpuser_label">{$MOD.LBL_MAIL_SMTPUSER}</span> <span class="required">{$APP.LBL_REQUIRED_SYMBOL}</span></td>
<td width="30%" ><input type="text" id="mail_smtpuser" name="mail_smtpuser" size="25" maxlength="255" value="{$mail_smtpuser}" tabindex='1' ></td>
<td width="20%">&nbsp;</td>
<td width="30%">&nbsp;</td>
</tr>
<tr id="smtp_auth2">
<td width="20%" scope="row"><span id="mail_smtppass_label">{$MOD.LBL_MAIL_SMTPPASS}</span> <span class="required">{$APP.LBL_REQUIRED_SYMBOL}</span></td>
<td width="30%" >
<input type="password" id="mail_smtppass" name="mail_smtppass" size="25" maxlength="255" tabindex='1'>
<a href="javascript:void(0)" id='mail_smtppass_link' onClick="SUGAR.util.setEmailPasswordEdit('mail_smtppass')" style="display: none">{$APP.LBL_CHANGE_PASSWORD}</a>
</td>
<td width="20%">&nbsp;</td>
<td width="30%">&nbsp;</td>
</tr>
</table>
<table width="100%" cellpadding="0" cellspacing="0">
<tr id="mail_allow_user">
<td width="25%" scope="row">
@ -197,7 +140,7 @@ function change_state(radiobutton) {
</td>
<td width="30%">
<input type='hidden' id="notify_allow_default_outbound_hidden_input" name='notify_allow_default_outbound' value='0'>
<input id="notify_allow_default_outbound" name='notify_allow_default_outbound' value="2" tabindex='1' class="checkbox" type="checkbox" {$notify_allow_default_outbound_on}>
<input id="notify_allow_default_outbound" name='notify_allow_default_outbound' value="2" tabindex='1' class="checkbox" type="checkbox" style="margin-top: 10px;" {$notify_allow_default_outbound_on}>
</td>
</tr>
<tr class="legacy-compose-option" {if isset($legacyEmailConfigEnabled)}style="display:none"{/if}>
@ -216,13 +159,6 @@ function change_state(radiobutton) {
</div>
</td>
</tr>
<tr><td colspan="4">&nbsp;</tr>
<tr>
<td width="15%"><input type="button" class="btn btn-info" value="{$APP.LBL_EMAIL_TEST_OUTBOUND_SETTINGS}" onclick="testOutboundSettings();">&nbsp;</td>
<td width="15%">&nbsp;</td>
<td width="40%">&nbsp;</td>
<td width="40%">&nbsp;</td>
</tr>
</table>
</div>
</div>

View file

@ -182,8 +182,12 @@ class ViewConfig extends SugarView
LoggerManager::getLogger()->warn('EmailMan view display error: mail allow user send is not set for focus');
}
$oe = new OutboundEmail();
$oe = $oe->getSystemEmail();
$this->ss->assign("system_outbound_email_id", $oe->id);
$this->ss->assign("system_outbound_email_name", $oe->name);
$this->ss->assign("mail_smtptype", $mailSmtpType);
$this->ss->assign("mail_smtpserver", $mailSmtpServer);
$this->ss->assign("mail_smtpport", $mailSmtpPort);
$this->ss->assign("mail_smtpuser", $mailSmtpUser);
@ -277,7 +281,7 @@ class ViewConfig extends SugarView
$sugar_config['email_xss'] = getDefaultXssTags();
}
foreach (unserialize(base64_decode($sugar_config['email_xss'])) as $k => $v) {
foreach (unserialize(base64_decode($sugar_config['email_xss']), ['allowed_classes' => false]) as $k => $v) {
$this->ss->assign($k."Checked", 'CHECKED');
}

View file

@ -60,7 +60,7 @@ if (!$focus->ACLAccess('Delete')) {
$focus->mark_deleted($_REQUEST['record']);
if (isset($_REQUEST['record'])) {
$query = "DELETE FROM emailman WHERE marketing_id ='" . $_REQUEST['record'] ."'";
$query = "DELETE FROM emailman WHERE marketing_id ='" . $focus->db->quote($_REQUEST['record']) ."'";
$focus->db->query($query);
}

View file

@ -287,7 +287,7 @@ class EmailTemplate extends SugarBean
public function fill_in_additional_detail_fields()
{
if (empty($this->body) && !empty($this->body_html)) {
if (!empty($this->body_html)) {
global $sugar_config;
$bodyCleanup = $this->body_html;

View file

@ -812,7 +812,9 @@ class Email extends Basic
$fromaddress,
$toaddress,
$mail_sendtype = 'smtp',
$fromname = ''
$fromname = '',
$authType = 'no_auth',
$externalOAuthConnectionId = ''
) {
global $current_user, $app_strings;
$mod_strings = return_module_language($GLOBALS['current_language'], 'Emails'); //Called from EmailMan as well.
@ -821,22 +823,14 @@ class Email extends Basic
if ($mail->Mailer == 'smtp') {
$mail->Host = $mailserver_url;
$mail->Port = $port;
if (isset($ssltls) && !empty($ssltls)) {
$mail->protocol = "ssl://";
if ($ssltls == 1) {
$mail->SMTPSecure = 'ssl';
} // if
if ($ssltls == 2) {
$mail->SMTPSecure = 'tls';
} // if
} else {
$mail->protocol = "tcp://";
}
if ($smtp_auth_req) {
$mail->SMTPAuth = true;
$mail->Username = $smtp_username;
$mail->Password = $smtppassword;
}
$mail->setSecureProtocol($ssltls ?? false);
$mail->initSMTPAuth(
$authType ?? '',
$externalOAuthConnectionId ?? '',
$smtp_username ?? '',
$smtppassword ?? ''
);
} else {
$mail->Mailer = 'sendmail';
}
@ -2789,18 +2783,14 @@ class Email extends Basic
$mail->Mailer = "smtp";
$mail->Host = $oe->mail_smtpserver;
$mail->Port = $oe->mail_smtpport;
if ($oe->mail_smtpssl == 1) {
$mail->SMTPSecure = 'ssl';
} // if
if ($oe->mail_smtpssl == 2) {
$mail->SMTPSecure = 'tls';
} // if
if ($oe->mail_smtpauth_req) {
$mail->SMTPAuth = true;
$mail->Username = $oe->mail_smtpuser;
$mail->Password = $oe->mail_smtppass;
}
$mail->setSecureProtocol($oe->mail_smtpssl);
$mail->initSMTPAuth(
$oe->auth_type ?? '',
$oe->external_oauth_connection_id ?? '',
$oe->mail_smtpuser ?? '',
$oe->mail_smtppass ?? '',
);
} else {
$mail->Mailer = "sendmail";
}
@ -2842,18 +2832,14 @@ class Email extends Basic
$mail->Mailer = "smtp";
$mail->Host = $oe->mail_smtpserver;
$mail->Port = $oe->mail_smtpport;
if ($oe->mail_smtpssl == 1) {
$mail->SMTPSecure = 'ssl';
} // if
if ($oe->mail_smtpssl == 2) {
$mail->SMTPSecure = 'tls';
} // if
if ($oe->mail_smtpauth_req) {
$mail->SMTPAuth = true;
$mail->Username = $oe->mail_smtpuser;
$mail->Password = $oe->mail_smtppass;
}
$mail->setSecureProtocol($oe->mail_smtpssl);
$mail->initSMTPAuth(
$oe->auth_type ?? '',
$oe->external_oauth_connection_id ?? '',
$oe->mail_smtpuser ?? '',
$oe->mail_smtppass ?? '',
);
} else {
$mail->Mailer = "sendmail";
}
@ -3295,15 +3281,12 @@ class Email extends Basic
*/
public function getSystemDefaultEmail()
{
$email = array();
$r1 = $this->db->query('SELECT config.value FROM config WHERE name=\'fromaddress\'');
$r2 = $this->db->query('SELECT config.value FROM config WHERE name=\'fromname\'');
$a1 = $this->db->fetchByAssoc($r1);
$a2 = $this->db->fetchByAssoc($r2);
$oe = new OutboundEmail();
$oe = $oe->getSystemMailerSettings();
$email['email'] = $a1['value'];
$email['name'] = $a2['value'];
$email['email'] = $oe->smtp_from_addr ?? '';
$email['name'] = $oe->smtp_from_name ?? '';
return $email;
}
@ -3419,7 +3402,7 @@ class Email extends Basic
);
}
}
if (empty($this->contact_id) && !empty($this->parent_id) && !empty($this->parent_type) && $this->parent_type === 'Contacts' && !empty($this->parent_name)) {
$this->contact_id = $this->parent_id;
$this->contact_name = $this->parent_name;
@ -4438,14 +4421,16 @@ eoq;
// is from address in the request?
if (!isset($request['from_addr_name']) || !$request['from_addr_name']) {
$useDefaultFromAddressName = true;
}
if (!isset($request['from_addr'])) {
if (!isset($request['from_addr_name']) || !$request['from_addr_name']) {
$useDefaultFromAddressName = true;
}
// is from name in the request?
// is from name in the request?
if (!isset($request['from_addr_email']) || !$request['from_addr_email']) {
$useDefaultFromAddressEmail = true;
if (!isset($request['from_addr_email']) || !$request['from_addr_email']) {
$useDefaultFromAddressEmail = true;
}
}
// so, do we have to use any default data?

View file

@ -1561,7 +1561,7 @@ HTML;
}
if (file_exists($cache)) {
include($cache); // profides $cacheFile
$metaOut = unserialize($cacheFile['out']);
$metaOut = unserialize($cacheFile['out'], ['allowed_classes' => false]);
$meta = $metaOut['meta']['email'];
if (isset($meta['attachments'])) {
$attachmentHtmlData = $meta['attachments'];
@ -3391,9 +3391,7 @@ eoq;
include($cacheFilePath); // provides $cacheFile
if (isset($cacheFile[$key])) {
$ret = unserialize($cacheFile[$key]);
return $ret;
return unserialize($cacheFile[$key], ['allowed_classes' => false]);
}
} else {
$GLOBALS['log']->debug("EMAILUI: cache file not found [ {$cacheFilePath} ] - creating blank cache file");

View file

@ -1510,7 +1510,7 @@ eoq;
foreach ($ie->field_defs as $k => $v) {
if ($k == 'stored_options') {
$ie->$k = unserialize(base64_decode($ie->$k));
$ie->$k = unserialize(base64_decode($ie->$k), ['allowed_classes' => false]);
if (isset($ie->stored_options['from_name'])) {
$ie->stored_options['from_name'] = from_html($ie->stored_options['from_name']);
}

View file

@ -498,7 +498,7 @@ class ListViewDataEmails extends ListViewData
$ret = $emailHeader['flagged'];
break;
case 'name':
$ret = html_entity_decode((string) $inboundEmail->handleMimeHeaderDecode($emailHeader['subject'] ?? ''));
$ret = html_entity_decode(purify_html((string) $inboundEmail->handleMimeHeaderDecode($emailHeader['subject'] ?? '')));
break;
case 'date_entered':
$db = DBManagerFactory::getInstance();

View file

@ -42,6 +42,7 @@ if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
use League\OAuth2\Client\Provider\AbstractProvider;
use League\OAuth2\Client\Token\AccessTokenInterface;
interface ExternalOAuthProviderConnectorInterface
@ -142,4 +143,12 @@ interface ExternalOAuthProviderConnectorInterface
* @return string
*/
public function getAccessTokenRequestGrant(array $providerConfig): string;
/**
* Get Provider
* @param string $requestClientId
* @param string $requestClientSecret
* @return AbstractProvider|null
*/
public function getProvider(string $requestClientId, string $requestClientSecret): ?AbstractProvider;
}

View file

@ -268,6 +268,59 @@ class OAuthAuthorizationService
];
}
public function refreshExpiredOAuthToken(string $oAuthConnectionId): void
{
/** @var ExternalOAuthConnection $oauthConnection */
$oauthConnection = BeanFactory::getBean('ExternalOAuthConnection', $oAuthConnectionId);
$hasExpiredFeedback = $this->hasConnectionTokenExpired($oauthConnection);
$refreshToken = $hasExpiredFeedback['refreshToken'] ?? false;
if ($refreshToken === true) {
$refreshTokenFeedback = $this->refreshConnectionToken($oauthConnection);
if ($refreshTokenFeedback['success'] === false) {
$message = $this->getOAuthRefreshTokenErrorMessage(
$refreshTokenFeedback['reLogin'],
$oauthConnection,
$oAuthConnectionId
);
displayAdminError($message);
}
}
}
/**
* Get refersh token error messages
* @param $reLogin
* @param ExternalOAuthConnection $oauthConnection
* @param string $oAuthConnectionId
* @return string
*/
public function getOAuthRefreshTokenErrorMessage(
$reLogin,
ExternalOAuthConnection $oauthConnection,
string $oAuthConnectionId
): string {
$message = translate('ERR_OAUTH_CONNECTION_ERROR');
$linkAction = 'DetailView';
if ($reLogin === true) {
$linkAction = 'EditView';
$message = translate('WARN_OAUTH_TOKEN_SESSION_EXPIRED');
}
$oauthConnectionName = $oauthConnection->name;
$hasAccess = $oauthConnection->ACLAccess('edit') ?? false;
if ($hasAccess === true) {
$message .= " <a href=\"index.php?module=ExternalOAuthConnection&action=$linkAction&record=$oAuthConnectionId\">$oauthConnectionName</a>.";
} else {
$message .= $oauthConnectionName . '.';
}
return $message;
}
/**
* Map token to bean fields array
* @param string $providerId

View file

@ -73,6 +73,7 @@ class ExternalOAuthProvider extends Basic
public $expires_in_mapping;
public $refresh_token_mapping;
public $token_type_mapping;
public $redirect_uri_type;
/**
@ -322,10 +323,13 @@ class ExternalOAuthProvider extends Basic
global $sugar_config;
$siteUrl = $sugar_config['site_url'] ?? '';
$siteUrl = str_ireplace('index.php', '', (string) $siteUrl);
$siteUrl = rtrim($siteUrl, " \t\n\r\0\x0B\/");
if ($this->redirect_uri_type === 'pretty_url') {
return $siteUrl . '/ep/setExternalOAuthToken';
}
return $siteUrl . '/index.php?entryPoint=setExternalOAuthToken';
}

View file

@ -0,0 +1,196 @@
/**
* SuiteCRM is a customer relationship management program developed by SuiteCRM Ltd.
* Copyright (C) 2025 SuiteCRM Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUITECRM, SUITECRM DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
var externalOAuthProviderFields = function () {
var getDefaultFieldGetter = function () {
return function (field$) {
return (field$ && field$.val()) || '';
};
};
var getFunctionFieldGetter = function () {
return function (field$) {
field$ = field$[0];
if (!field$) {
return '';
}
return field$.innerText || field$.textContent || '';
};
};
var getDefaultFieldSetter = function () {
return function (field$, value) {
if (!field$) {
return;
}
field$.val(value);
field$.change();
};
};
var getFunctionFieldSetter = function () {
return function (field$, value) {
field$ = field$[0];
if (!field$) {
return;
}
field$.innerText = value || '';
};
};
return {
fields: {
'record': {
type: 'varchar',
getField$: function (field) {
return $('input[name=' + field + ']') || null;
}
},
'name': {
type: 'varchar'
},
'client_id': {
type: 'varchar'
},
'client_secret': {
type: 'varchar'
},
'redirect_uri_span': {
type: 'function'
},
'redirect_uri_type': {
type: 'enum'
},
},
getters: {
default: getDefaultFieldGetter(),
varchar: getDefaultFieldGetter(),
function: getFunctionFieldGetter(),
checkbox: function (field$) {
return (field$ && field$.prop('checked')) || false;
}
},
setters: {
default: getDefaultFieldSetter(),
varchar: getDefaultFieldSetter(),
function: getFunctionFieldSetter(),
checkbox: function (field$, value) {
if (!field$) {
return;
}
field$.prop('checked', !!value);
}
},
setValue: function (field, value) {
var field$ = this.getField$(field);
if (!field$) {
return null;
}
var setter = this.getValueSetter(field);
if (!setter) {
return null;
}
return setter(field$, value);
},
getValue: function (field) {
var field$ = this.getField$(field);
if (!field$) {
return null;
}
var getter = this.getValueGetter(field);
if (!getter) {
return null;
}
return getter(field$);
},
hide: function (field) {
var field$ = this.getFieldCell$(field);
if (!field$ || !field$.length) {
return;
}
field$.hide();
},
show: function (field) {
var field$ = this.getFieldCell$(field);
if (!field$ || !field$.length) {
return;
}
field$.show();
},
getField$: function (field) {
var handler = (this.fields[field] && this.fields[field].getField$) || null;
if (handler) {
return handler(field);
}
return $('#' + field) || null;
},
getFieldCell$: function (field) {
return $('[data-field="' + field + '"]') || null;
},
getFieldType: function (field) {
return (this.fields[field] && this.fields[field].type) || 'varchar';
},
getValueGetter: function (field) {
var type = this.getFieldType(field);
return this.getters[type] || this.getters['default'];
},
getValueSetter: function (field) {
var type = this.getFieldType(field);
return this.setters[type] || this.setters['default'];
}
};
}();

View file

@ -0,0 +1,57 @@
/**
* SuiteCRM is a customer relationship management program developed by SuiteCRM Ltd.
* Copyright (C) 2025 SuiteCRM Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUITECRM, SUITECRM DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
function toggleRedirectUri(type, url) {
var fieldValues = {
'query_string': {
'uri': 'index.php?entryPoint=setExternalOAuthToken'
},
'pretty_url': {
'uri': 'ep/setExternalOAuthToken'
}
}
var match = url.match(/^(.*?)(?:index\.php|ep)(?:\/|\?|$)/);
match = match ? match[1] : url;
var uri = fieldValues[type] ? fieldValues[type].uri : '';
externalOAuthProviderFields.setValue('redirect_uri_span', match + uri);
}
$(document).ready(function () {
var url = externalOAuthProviderFields.getValue('redirect_uri_span');
var type = externalOAuthProviderFields.getValue('redirect_uri_type');
toggleRedirectUri(type, url);
externalOAuthProviderFields.getField$('redirect_uri_type').change(function () {
url = externalOAuthProviderFields.getValue('redirect_uri_span');
type = externalOAuthProviderFields.getValue('redirect_uri_type');
toggleRedirectUri(type, url);
});
});

View file

@ -76,6 +76,7 @@ $mod_strings = [
'LBL_TYPE' => 'Type',
'LBL_CONNECTOR' => 'Connector',
'LBL_REDIRECT_URI' => 'Redirect URI',
'LBL_REDIRECT_URI_TYPE' => 'Redirect URI Type',
'LBL_CLIENT_ID' => 'Client Id',
'LBL_CLIENT_SECRET' => 'Client Secret',

View file

@ -95,7 +95,7 @@ $viewdefs[$module_name]['DetailView'] = [
],
[
'redirect_uri',
''
'redirect_uri_type'
],
],
'lbl_extra' => [

View file

@ -68,6 +68,13 @@ $viewdefs['ExternalOAuthProvider'] = [
'panelDefault' => 'expanded',
],
],
'javascript' => '
<script type="text/javascript">
{suite_combinescripts
files="modules/ExternalOAuthProvider/js/fields.js,
modules/ExternalOAuthProvider/js/redirect_uri_toggle.js"}
</script>
'
],
'panels' => [
'default' => [
@ -93,7 +100,7 @@ $viewdefs['ExternalOAuthProvider'] = [
],
[
'redirect_uri',
''
'redirect_uri_type'
],
],
'lbl_extra' => [

View file

@ -127,6 +127,21 @@ $dictionary['ExternalOAuthProvider'] = [
'exportable' => false,
'unified_search' => false,
],
'redirect_uri_type' => [
'name' => 'redirect_uri_type',
'vname' => 'LBL_REDIRECT_URI_TYPE',
'type' => 'enum',
'default' => 'pretty_url',
'options' => 'redirect_uri_type_dom',
'len' => 50,
'required' => false,
'reportable' => false,
'massupdate' => false,
'inline_edit' => false,
'importable' => false,
'exportable' => false,
'unified_search' => false,
],
'client_id' => [
'name' => 'client_id',
'vname' => 'LBL_CLIENT_ID',
@ -185,6 +200,7 @@ $dictionary['ExternalOAuthProvider'] = [
'vname' => 'LBL_AUTHORIZE_URL_OPTIONS',
'type' => 'stringmap',
'dbType' => 'text',
'default' => '{"prompt":"login"}',
'show_keys' => true,
'required' => false,
'reportable' => false,

View file

@ -52,7 +52,7 @@ require_once('modules/Import/ImportDuplicateCheck.php');
class Importer
{
/**
* @var ImportFieldSanitizer
* @var ImportFieldSanitize
*/
protected $ifs;
@ -62,27 +62,27 @@ class Importer
protected $defaultUserCurrency;
/**
* @var importColumns
* @var array
*/
protected $importColumns;
/**
* @var importSource
* @var ImportDataSource
*/
protected $importSource;
/**
* @var $isUpdateOnly
* @var bool
*/
protected $isUpdateOnly;
/**
* @var $bean
* @var SugarBean
*/
protected $bean;
/**
* @var sugarToExternalSourceFieldMap
* @var array
*/
protected $sugarToExternalSourceFieldMap = array();
@ -97,7 +97,7 @@ class Importer
$this->bean = $bean;
// use our own error handler
set_error_handler(array('Importer','handleImportErrors'), E_ALL);
set_error_handler(array('Importer','handleImportErrors'), E_ALL & ~E_DEPRECATED & ~E_STRICT & ~E_WARNING & ~E_NOTICE);
// Increase the max_execution_time since this step can take awhile
ini_set("max_execution_time", max($sugar_config['import_max_execution_time'], 3600));

View file

@ -130,7 +130,7 @@ abstract class ImportDataSource implements Iterator
* @return void
*/
abstract public function getHeaderColumns();
/**
* Set the source name.
*
@ -197,7 +197,7 @@ abstract class ImportDataSource implements Iterator
if ($module == 'Case') {
$module = 'aCase';
}
$last_import->bean_type = $module;
$last_import->bean_id = $id;
return $last_import->save();
@ -228,9 +228,9 @@ abstract class ImportDataSource implements Iterator
{
global $current_language;
$mod_strings = return_module_language($current_language, 'Import');
return "<b>{$mod_strings['LBL_ERROR']}</b> $error <br/>".
"<b>{$mod_strings['LBL_FIELD_NAME']}</b> $fieldName <br/>" .
"<b>{$mod_strings['LBL_VALUE']}</b> $fieldValue <br/>";
return "{$mod_strings['LBL_ERROR']}: $error. ".
"- {$mod_strings['LBL_FIELD_NAME']}: $fieldName. " .
"- {$mod_strings['LBL_VALUE']}: $fieldValue";
}
public function resetRowErrorCounter()
{
@ -330,7 +330,7 @@ abstract class ImportDataSource implements Iterator
//Add the error message to the first column
array_unshift($rowData, $errorMessage);
fputcsv($fp, $rowData);
fclose($fp);
fclose($fpNoErrors);
}

View file

@ -47,12 +47,11 @@
{
padding-left: 0px;
}
div.resultsTable {
overflow: auto;
width: 100%;
padding-top: 20px;
position: relative;
}
div.resultsTable {
overflow: auto;
padding-top: 20px;
position: relative;
}
</style>
{/literal}
@ -98,7 +97,7 @@
</form>
<br/>
<table width="100%" id="tabListContainerTable" cellpadding="0" cellspacing="0" border="0">
<tr>
<td nowrap id="tabListContainerTD">

View file

@ -80,7 +80,7 @@
{counter start=0 name="colCounter" print=false assign="colCounter"}
{foreach from=$rowData key=col item=params}
{strip}
<td align='left' valign="top">
<td align='left' valign="top" scope="record">
{$params}
</td>
{/strip}

View file

@ -128,7 +128,7 @@ class ImportListView
$this->ss->assign('navStrings', $navStrings);
$this->ss->assign('pageData', $this->generatePaginationData());
$this->ss->assign('tableID', $this->tableID);
$this->ss->assign('colCount', count($this->headerColumns));
$this->ss->assign('colCount', is_countable($this->headerColumns) ? count($this->headerColumns) : 0);
$this->ss->assign('APP', $app_strings);
$this->ss->assign('rowColor', array('oddListRow', 'evenListRow'));
$this->ss->assign('displayColumns', $this->headerColumns);

View file

@ -215,7 +215,7 @@ ProcessImport = new function()
+ "&import_module={$_REQUEST['import_module']}"
+ "&has_header=" + document.getElementById("importstepdup").has_header.value ;
if ( ProcessImport.fileCount >= ProcessImport.fileTotal ) {
YAHOO.SUGAR.MessageBox.updateProgress(1,'{$mod_strings['LBL_IMPORT_COMPLETED']}');
YAHOO.SUGAR.MessageBox.updateProgress(100,'{$mod_strings['LBL_IMPORT_COMPLETED']}');
SUGAR.util.hrefURL(locationStr);
}
else {
@ -238,7 +238,7 @@ ProcessImport = new function()
);
var move = 0;
if ( this.fileTotal > 0 ) {
move = this.fileCount/this.fileTotal;
move = (this.fileCount/this.fileTotal) * 100;
}
YAHOO.SUGAR.MessageBox.updateProgress( move,
"{$mod_strings['LBL_IMPORT_RECORDS']} " + ((this.fileCount * this.recordThreshold) + 1)

View file

@ -150,7 +150,7 @@ class AOPInboundEmail extends InboundEmail
$GLOBALS['log']->debug('InboundEmail created one case with number: '.$c->case_number);
$createCaseTemplateId = $this->get_stored_options('create_case_email_template', "");
if (!empty($this->stored_options)) {
$storedOptions = unserialize(base64_decode($this->stored_options));
$storedOptions = unserialize(base64_decode($this->stored_options), ['allowed_classes' => false]);
}
if (!empty($createCaseTemplateId)) {
$fromName = "";

View file

@ -1572,7 +1572,7 @@ class InboundEmail extends SugarBean
flush();
} // while
fclose($fh);
$diff = unserialize($data);
$diff = unserialize($data, ['allowed_classes' => false]);
if (!empty($diff)) {
if ((is_countable($diff) ? count($diff) : 0) > 50) {
$newDiff = array_slice($diff, 50, is_countable($diff) ? count($diff) : 0, true);
@ -2035,7 +2035,7 @@ class InboundEmail extends SugarBean
flush();
} // while
fclose($fh);
$results = unserialize($data);
$results = unserialize($data, ['allowed_classes' => false]);
} // if
} // if
if (!$cacheDataExists) {
@ -2964,7 +2964,7 @@ class InboundEmail extends SugarBean
$focusUser = BeanFactory::newBean('Users');
$focusUser->retrieve($groupId);
$mailerId = (isset($_REQUEST['outbound_email'])) ? $_REQUEST['outbound_email'] : "";
$mailerId = (isset($_REQUEST['outbound_email'])) ? $this->db->quote($_REQUEST['outbound_email']) : "";
$oe = new OutboundEmail();
if ($mailerId != "") {
@ -4144,14 +4144,14 @@ class InboundEmail extends SugarBean
$emailMessage = $this->mailParser->parse($emailBody, false)->getTextContent();
$emailMessage = $this->handleInlineImages($emailBody, $emailMessage);
$emailMessage = $this->customGetMessageText($emailMessage);
return SugarCleaner::cleanHtml($emailMessage, false);
return html_entity_decode(purify_html(SugarCleaner::cleanHtml($emailMessage, false)));
}
$emailMessage = $this->mailParser->parse($emailBody, false)->getHtmlContent();
$emailMessage = $this->handleInlineImages($emailBody, $emailMessage);
$emailMessage = $this->customGetMessageText($emailMessage);
$emailMessage = $this->customGetMessageText($emailMessage) ?? '';
return SugarCleaner::cleanHtml($emailMessage, $clean_email);
return html_entity_decode(purify_html(SugarCleaner::cleanHtml($emailMessage, $clean_email)));
}
/**
@ -5495,7 +5495,7 @@ class InboundEmail extends SugarBean
//// ASSIGN APPROPRIATE ATTRIBUTES TO NEW EMAIL OBJECT
// handle UTF-8/charset encoding in the ***headers***
$email->name = $this->handleMimeHeaderDecode($header->subject);
$email->name = purify_html($this->handleMimeHeaderDecode($parsedFullHeader->subject));
$email->type = 'inbound';
if (!empty($unixHeaderDate)) {
$email->date_sent_received = $timedate->asUser($unixHeaderDate);
@ -5713,7 +5713,7 @@ class InboundEmail extends SugarBean
$fullHeader = $this->getImap()->fetchHeader($uid, FT_UID);
$parsedFullHeader = $this->getImap()->rfc822ParseHeaders($fullHeader);
$email->name = $this->handleMimeHeaderDecode($parsedFullHeader->subject);
$email->name = purify_html($this->handleMimeHeaderDecode($parsedFullHeader->subject));
$email->type = 'inbound';
if (isset($request['metadata']['viewdefs'])) {
@ -7509,7 +7509,7 @@ class InboundEmail extends SugarBean
include($cache); // profides $cacheFile
/** @var $cacheFile array */
$metaOut = unserialize($cacheFile['out']);
$metaOut = unserialize($cacheFile['out'], ['allowed_classes' => false]);
$meta = $metaOut['meta']['email'];
$email = BeanFactory::newBean('Emails');
@ -8667,38 +8667,6 @@ eoq;
return 'imap2';
}
/**
* Get refersh token error messages
* @param $reLogin
* @param ExternalOAuthConnection $oauthConnection
* @param string $oAuthConnectionId
* @return string
*/
protected function getOAuthRefreshTokenErrorMessage(
$reLogin,
ExternalOAuthConnection $oauthConnection,
string $oAuthConnectionId
): string {
$message = translate('ERR_IMAP_OAUTH_CONNECTION_ERROR', 'InboundEmail');
$linkAction = 'DetailView';
if ($reLogin === true) {
$linkAction = 'EditView';
$message = translate('WARN_OAUTH_TOKEN_SESSION_EXPIRED', 'InboundEmail');
}
$oauthConnectionName = $oauthConnection->name;
$hasAccess = $oauthConnection->ACLAccess('edit') ?? false;
if ($hasAccess === true) {
$message .= " <a href=\"index.php?module=ExternalOAuthConnection&action=$linkAction&record=$oAuthConnectionId\">$oauthConnectionName</a>.";
} else {
$message .= $oauthConnectionName . '.';
}
return $message;
}
/**
* Get OAuthToken. Refresh if needed
* @param string $oAuthConnectionId
@ -8709,29 +8677,11 @@ eoq;
require_once __DIR__ . '/../ExternalOAuthConnection/services/OAuthAuthorizationService.php';
$oAuth = new OAuthAuthorizationService();
$oAuth->refreshExpiredOAuthToken($oAuthConnectionId);
/** @var ExternalOAuthConnection $oauthConnection */
$oauthConnection = BeanFactory::getBean('ExternalOAuthConnection', $oAuthConnectionId);
$password = $oauthConnection->access_token;
$hasExpiredFeedback = $oAuth->hasConnectionTokenExpired($oauthConnection);
$refreshToken = $hasExpiredFeedback['refreshToken'] ?? false;
if ($refreshToken === true) {
$refreshTokenFeedback = $oAuth->refreshConnectionToken($oauthConnection);
if ($refreshTokenFeedback['success'] === false) {
$message = $this->getOAuthRefreshTokenErrorMessage(
$refreshTokenFeedback['reLogin'],
$oauthConnection,
$oAuthConnectionId
);
displayAdminError($message);
return null;
}
return $oauthConnection->access_token;
}
return $password;
return $oauthConnection->access_token;
}
/**

View file

@ -167,7 +167,12 @@ if ($type === 'bounce') {
if (!empty($_REQUEST['external_oauth_connection_id'])) {
$externalOauthConnection = BeanFactory::getBean('ExternalOAuthConnection', $_REQUEST['external_oauth_connection_id']);
if ($externalOauthConnection->type !== $focus->type) {
$focusType = $focus->type ?? '';
if ($focusType === 'bounce') {
$focusType = 'group';
}
if ($externalOauthConnection->type !== $focusType) {
SugarApplication::appendErrorMessage($mod_strings['LBL_TYPE_DIFFERENT']);
SugarApplication::redirect('index.php?module=InboundEmail&action=EditView&is_personal=1&type=personal');
return;

View file

@ -37,7 +37,7 @@
* display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
function authTypetoggleFields(type) {
function authTypeToggleFields(type) {
var fieldsPerType = {
'basic': {
@ -81,10 +81,10 @@ function authTypetoggleFields(type) {
$(document).ready(function () {
var type = inboundEmailFields.getValue('auth_type');
authTypetoggleFields(type);
authTypeToggleFields(type);
inboundEmailFields.getField$('auth_type').change(function () {
type = inboundEmailFields.getValue('auth_type');
authTypetoggleFields(type);
authTypeToggleFields(type);
});
});

View file

@ -8,7 +8,7 @@ if (!defined('sugarEntry') || !sugarEntry) {
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 2018 SalesAgility Ltd.
* Copyright (C) 2011 - 2024 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
@ -119,17 +119,19 @@ class StandardField extends DynamicField
$this->baseField = get_widget($field->type) ;
foreach ($field->vardef_map as $property => $fmd_col) {
if ($property == "action" || $property == "label_value" || $property == "label"
|| ((substr((string) $property, 0, 3) == 'ext' && strlen((string) $property) == 4))
|| ((str_starts_with((string)$property, 'ext') && strlen((string) $property) == 4))
// possible bug here... $property is often the same as $fmd_col, but not always. Maybe we should also add:
// || ((str_starts_with((string)$fmd_col, 'ext') && strlen((string) $fmd_col) == 4))
// ... but a thorough analysis of the consequences of this would be required.
) {
continue;
}
// Bug 37043 - Avoid writing out vardef defintions that are the default value.
// Avoid writing out vardef definitions that are the default value, when possible.
// Since isDefaultvalue() is quite limited, and doesn't handle all cases well,
// sometimes we won't detect defaults and will store them anyway.
if (isset($newDef[$property]) &&
(
(!isset($currdef[$property]) && !$this->isDefaultValue($property, $newDef[$property], $this->baseField))
|| (isset($currdef[$property]) && $currdef[$property] != $newDef[$property])
)
!$this->isDefaultValue($property, $newDef[$property], $this->baseField)
) {
$this->custom_def[$property] =
is_string($newDef[$property]) ? htmlspecialchars_decode($newDef[$property], ENT_QUOTES) : $newDef[$property];

View file

@ -262,7 +262,7 @@ class ActivitiesRelationship extends OneToManyRelationship
'order' => 20 ,
'sort_order' => 'desc' ,
'sort_by' => 'date_modified' ,
'title_key' => 'LBL_HISTORY' ,
'title_key' => 'LBL_HISTORY_SUBPANEL_TITLE' ,
'type' => 'collection' ,
'subpanel_name' => 'history' , //this values is not associated with a physical file.
'module' => 'History' ,

View file

@ -463,7 +463,7 @@ abstract class AbstractMetaDataImplementation
// BEGIN ASSERTIONS
if ($type != MB_BASEMETADATALOCATION && $type != MB_HISTORYMETADATALOCATION) {
// just warn rather than die
$GLOBALS ['log']->warning(
$GLOBALS ['log']->warn(
"UndeployedMetaDataImplementation->getFileName(): view type $type is not recognized"
);
}

View file

@ -78,8 +78,7 @@ class TabController
$trimmed_tabs = trim($tabs);
//make sure serialized string is not empty
if (!empty($trimmed_tabs)) {
$tabs = base64_decode($tabs);
$tabs = unserialize($tabs);
$tabs = unserialize(base64_decode($tabs), ['allowed_classes' => false]);
//Ensure modules saved in the prefences exist.
foreach ($tabs as $id => $tab) {
if (!in_array($tab, $moduleList)) {

View file

@ -66,6 +66,13 @@ class OutboundEmailAccounts extends OutboundEmailAccounts_sugar
*/
public $mail_smtpuser;
public $mail_smtpauth_req;
public $mail_smtpssl;
public $mail_smtpport;
public $mail_smtpserver;
public $mail_smtptype;
public $mail_sendtype;
/**
* @var string
*/
@ -86,6 +93,9 @@ class OutboundEmailAccounts extends OutboundEmailAccounts_sugar
*/
public $reply_to_name;
public $auth_type = 'no_auth'; // 'no_auth', 'basic', 'oauth'
public $external_oauth_connection_id = '';
public function __construct()
{
parent::__construct();
@ -113,11 +123,34 @@ class OutboundEmailAccounts extends OutboundEmailAccounts_sugar
}
$this->mail_smtppass = $this->mail_smtppass ? blowfishEncode(blowfishGetKey('OutBoundEmail'), $this->mail_smtppass) : null;
if ($this->auth_type === 'basic') {
$this->mail_smtpauth_req = 1;
$this->external_oauth_connection_id = '';
}
if ($this->auth_type === 'no_auth') {
$this->mail_smtppass = '';
$this->mail_smtpauth_req = 0;
$this->external_oauth_connection_id = '';
}
if ($this->auth_type === 'oauth') {
$this->mail_smtppass = '';
$this->mail_smtpauth_req = 0;
}
$this->smtp_from_name = trim($this->smtp_from_name);
$this->smtp_from_addr = trim($this->smtp_from_addr);
$this->mail_smtpserver = trim($this->mail_smtpserver);
$this->mail_smtpuser = trim($this->mail_smtpuser);
if ($this->type === 'system') {
/** @var Administration $admin */
$admin = BeanFactory::newBean('Administration');
$admin->saveSetting('notify', 'fromname', $this->smtp_from_name);
$admin->saveSetting('notify', 'fromaddress', $this->smtp_from_addr);
}
$results = parent::save($check_notify);
return $results;
}
@ -134,6 +167,10 @@ class OutboundEmailAccounts extends OutboundEmailAccounts_sugar
return null;
}
if (isTrue($this->mail_smtpauth_req) && $this->auth_type === 'no_auth') {
$this->auth_type = 'basic';
}
$this->mail_smtppass = $this->mail_smtppass ? blowfishDecode(blowfishGetKey('OutBoundEmail'), $this->mail_smtppass) : null;
return $results;
}
@ -262,7 +299,9 @@ class OutboundEmailAccounts extends OutboundEmailAccounts_sugar
{
global $current_user;
$isNotAllowAction = $this->isNotAllowedAction($view);
$view = $view ?? '';
$isNotAllowAction = $this->isNotAllowedAction($view ?? '');
if ($isNotAllowAction === true) {
return false;
}
@ -406,6 +445,7 @@ HTML;
$adminNotifyFromAddress = $admin->settings['notify_fromaddress'];
isValidEmailAddress($adminNotifyFromAddress);
$adminNotifyFromName = $admin->settings['notify_fromname'];
$record = $_REQUEST['record'] ?? '';
$html = <<<HTML
<input id="sendTestOutboundEmailSettingsBtn" type="button" class="button" value="{$APP['LBL_EMAIL_TEST_OUTBOUND_SETTINGS']}" onclick="testOutboundSettings();">
<script type="text/javascript" src="cache/include/javascript/sugar_grp_yui_widgets.js"></script>
@ -431,6 +471,15 @@ HTML;
};
function testOutboundSettingsDialog() {
var notifyFromAddress = document.getElementById('smtp_from_addr') && document.getElementById('smtp_from_addr').value;
var notifyFromName = document.getElementById('smtp_from_name') && document.getElementById('smtp_from_name').value;
if (!notifyFromAddress || !notifyFromName) {
overlay("{$APP['ERR_INVALID_REQUIRED_FIELDS']}", "{$APP['LBL_EMAIL_SETTINGS_FROM_ADDR_NOT_SET']}", 'alert');
return;
}
// lazy load dialogue
if(!EmailMan.testOutboundDialog) {
EmailMan.testOutboundDialog = new YAHOO.widget.Dialog("testOutboundDialog", {
@ -507,7 +556,9 @@ HTML;
var smtpServer = document.getElementById('mail_smtpserver').value;
var smtpPort = document.getElementById('mail_smtpport').value;
var smtpssl = document.getElementById('mail_smtpssl').value;
var mailsmtpauthreq = document.getElementById('mail_smtpauth_req');
var authType = document.getElementById('auth_type').value || 'no_auth';
var externalOauthConnectionId = document.getElementById('external_oauth_connection_id').value || '';
var smtpPass = trim(document.getElementById('mail_smtppass').value);
var mail_sendtype = 'SMTP';
var adminNotifyFromAddress = document.getElementById('smtp_from_addr').value ? document.getElementById('smtp_from_addr').value :'$adminNotifyFromName';
var adminNotifyFromName = document.getElementById('smtp_from_name').value ? document.getElementById('smtp_from_name').value : '$adminNotifyFromAddress';
@ -516,9 +567,12 @@ HTML;
'mail_sendtype=' + mail_sendtype + '&' +
'mail_smtpserver=' + smtpServer + "&" +
"mail_smtpport=" + smtpPort + "&mail_smtpssl=" + smtpssl + "&" +
"mail_smtpauth_req=" + mailsmtpauthreq.checked + "&" +
"mail_auth_type=" + authType + "&" +
"mail_external_oauth_connection_id=" + externalOauthConnectionId + "&" +
"mail_smtpauth_req=" + (authType === 'basic' ? 1 : 0) + "&" +
"mail_smtpuser=" + trim(document.getElementById('mail_smtpuser').value) + "&" +
"mail_smtppass=" + trim(document.getElementById('mail_smtppass').value) + "&" +
"mail_smtppass=" + smtpPass + "&" +
"record=" + '$record' + "&" +
"outboundtest_to_address=" + toAddress + '&' +
'outboundtest_from_address=' + adminNotifyFromAddress + '&' +
'mail_from_name=' + adminNotifyFromName;

View file

@ -51,6 +51,32 @@ class OutboundEmailAccountsController extends SugarController
$this->bean->type = $type;
}
if (empty($this->bean) && $type === 'system' && !is_admin($GLOBALS['current_user'])) {
$this->hasAccess = false;
$this->view = 'noaccess';
return;
}
$oe = new OutboundEmail();
$oe = $oe->getSystemEmail();
if (empty($this->bean->id) && $type === 'system' && $oe !== null) {
$this->hasAccess = false;
$this->view = 'errors';
$this->errors = [
translate('LBL_ERROR_OUTBOUND_EMAIL_SYSTEM_EXISTS', 'OutboundEmailAccounts'),
];
return;
}
if ($type === 'system' && $oe !== null && $oe->id !== $this->bean->id) {
$this->hasAccess = false;
$this->view = 'errors';
$this->errors = [
translate('LBL_ERROR_OUTBOUND_EMAIL_SYSTEM_EXISTS', 'OutboundEmailAccounts'),
];
return;
}
if (empty($_REQUEST['record']) && $type === 'user') {
$this->hasAccess = true;
return;
@ -62,7 +88,7 @@ class OutboundEmailAccountsController extends SugarController
}
public function action_save() {
global $current_user;
global $current_user, $mod_strings;
$isNewRecord = (empty($this->bean->id) || $this->bean->new_with_id);
$this->bean->mail_sendtype = 'SMTP';
@ -84,6 +110,14 @@ class OutboundEmailAccountsController extends SugarController
}
}
$oe = new OutboundEmail();
$oe = $oe->getSystemEmail();
$type = $this->bean->type;
if ($type === 'user'){
$type = 'personal';
}
if ($isNewRecord && empty($this->bean->user_id)) {
$this->bean->user_id = $current_user->id;
$this->bean->assigned_user_id = $current_user->id;
@ -93,6 +127,34 @@ class OutboundEmailAccountsController extends SugarController
$this->bean->assigned_user_id = $this->bean->user_id;
}
$authType = $_REQUEST['auth_type'] ?? '';
$oauth = null;
if ($authType === 'oauth' || ($_REQUEST['auth_type'] ?? '') === 'oauth') {
$oauth = BeanFactory::getBean('ExternalOAuthConnection', $_REQUEST['external_oauth_connection_id']);
}
if ($type === 'system' && $oe !== null && $oe->id !== $this->bean->id) {
$this->hasAccess = false;
$this->view = 'errors';
$this->errors = [
translate('LBL_ERROR_OUTBOUND_EMAIL_SYSTEM_EXISTS', 'OutboundEmailAccounts'),
];
return;
}
if ($type === 'system' && $oauth !== null && $oauth->type !== 'group') {
SugarApplication::appendErrorMessage($mod_strings['LBL_ERROR_OUTBOUND_EMAIL_SYSTEM_IS_NOT_GROUP']);
SugarApplication::redirect('index.php?module=OutboundEmailAccounts&action=DetailView&record=' . $this->bean->id);
return;
}
if ($type !== 'system' && $oauth !== null && $oauth->type !== $type) {
SugarApplication::appendErrorMessage($mod_strings['LBL_ERROR_OUTBOUND_EMAIL_CONNECTION_TYPE_MISMATCH']);
SugarApplication::redirect('index.php?module=OutboundEmailAccounts&action=DetailView&record=' . $this->bean->id);
return;
}
parent::action_save();
}
}

View file

@ -0,0 +1,81 @@
/**
* SuiteCRM is a customer relationship management program developed by SuiteCRM Ltd.
* Copyright (C) 2025 SuiteCRM Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUITECRM, SUITECRM DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
function authTypeToggleFields(type) {
var fieldsPerType = {
'basic': {
'mail_smtppass': true,
'external_oauth_connection_name': false,
},
'no_auth': {
'mail_smtppass': false,
'external_oauth_connection_name': false,
},
'oauth': {
'mail_smtppass': false,
'external_oauth_connection_name': true,
},
};
var fieldType = {
'mail_smtppass': 'password',
'external_oauth_connection_name': 'relate',
};
var fieldDisplay = fieldsPerType[type] || fieldsPerType.personal;
Object.keys(fieldDisplay).forEach(function (fieldKey) {
var display = fieldDisplay[fieldKey];
var method = 'show';
var required = true;
if (!display) {
method = 'hide';
outboundEmailFields.setValue(fieldKey, '');
required = false;
}
var isValue = outboundEmailFields.getData(fieldKey, 'is-value-set');
if (isValue === true) {
required = false;
}
outboundEmailFields.setRequired(fieldKey, fieldType[fieldKey], 'EditView', required);
outboundEmailFields[method](fieldKey);
});
}
$(document).ready(function () {
var type = outboundEmailFields.getValue('auth_type');
authTypeToggleFields(type);
outboundEmailFields.getField$('auth_type').change(function () {
type = outboundEmailFields.getValue('auth_type');
authTypeToggleFields(type);
});
});

View file

@ -38,144 +38,256 @@
*/
var outboundEmailFields = function () {
var getDefaultFieldGetter = function () {
return function (field$) {
return (field$ && field$.val()) || '';
var requiredLabelTemplate = '<span class="required">*</span>';
var validationMessageTemplate = '<div class="required validation-message">Missing required field: $FIELD_NAME</div>';
var getValidationDefinition = function (formName, field) {
if (validate[formName]) {
for (i = 0; i < validate[formName].length; i++) {
if (validate[formName][i][nameIndex] == field) {
return validate[formName][i];
}
}
}
return null;
};
};
var getDefaultFieldSetter = function () {
return function (field$, value) {
if (!field$) {
return;
}
var configureValidation = function (formName, field, required) {
field$.val(value);
field$.change();
var definition = getValidationDefinition(formName, field);
if (!definition) {
return;
}
var isRequired = true;
if (!required) {
isRequired = false;
}
definition[requiredIndex] = isRequired;
};
};
return {
fields: {
'record': {
type: 'varchar',
var addRequiredIndicator = function ($label) {
var $indicator = $label.find('.required');
if ($indicator.length < 1) {
$label.append($(requiredLabelTemplate));
}
};
var removeRequiredIndicator = function ($label) {
var $indicator = $label.find('.required');
if ($indicator.length > 0) {
$indicator.remove();
}
};
var getDefaultFieldGetter = function () {
return function (field$) {
return (field$ && field$.val()) || '';
};
};
var getDefaultFieldSetter = function () {
return function (field$, value) {
if (!field$) {
return;
}
field$.val(value);
field$.change();
};
};
return {
fields: {
'record': {
type: 'varchar',
getField$: function (field) {
return $('input[name=' + field + ']') || null;
}
},
'mail_smtpssl': {
type: 'varchar'
},
'mail_smtppass': {
type: 'varchar',
},
'owner_name': {
type: 'varchar'
},
'type': {
type: 'varchar'
},
'mail_smtpport': {
type: 'varchar'
},
'mail_smtpauth_req': {
type: 'checkbox'
},
'auth_type': {
type: 'varchar'
},
'external_oauth_connection_name': {
type: 'varchar',
getField$: function (field) {
return $('input[name=' + field + ']') || null;
}
},
'external_oauth_connection_id': {
type: 'varchar',
getField$: function (field) {
return $('input[name=' + field + ']') || null;
}
},
},
getters: {
default: getDefaultFieldGetter(),
varchar: getDefaultFieldGetter(),
checkbox: function (field$) {
return (field$ && field$.prop('checked')) || false;
}
},
setters: {
default: getDefaultFieldSetter(),
varchar: getDefaultFieldSetter(),
checkbox: function (field$, value) {
if (!field$) {
return;
}
field$.prop('checked', !!value);
}
},
setValue: function (field, value) {
var field$ = this.getField$(field);
if (!field$) {
return null;
}
var setter = this.getValueSetter(field);
if (!setter) {
return null;
}
return setter(field$, value);
},
getValue: function (field) {
var field$ = this.getField$(field);
if (!field$) {
return null;
}
var getter = this.getValueGetter(field);
if (!getter) {
return null;
}
return getter(field$);
},
getData: function (field, dataKey) {
var field$ = this.getField$(field);
if (!field$) {
return null;
}
return field$.data(dataKey);
},
hide: function (field) {
var field$ = this.getFieldCell$(field);
if (!field$ || !field$.length) {
return;
}
field$.hide();
},
show: function (field) {
var field$ = this.getFieldCell$(field);
if (!field$ || !field$.length) {
return;
}
field$.show();
},
getField$: function (field) {
return $('input[name=' + field + ']') || null;
}
},
'mail_smtpssl': {
type: 'varchar'
},
'owner_name': {
type: 'varchar'
},
'type': {
type: 'varchar'
},
'mail_smtpport': {
type: 'varchar'
},
'mail_smtpauth_req': {
type: 'checkbox'
},
},
var handler = (this.fields[field] && this.fields[field].getField$) || null;
getters: {
default: getDefaultFieldGetter(),
varchar: getDefaultFieldGetter(),
checkbox: function (field$) {
return (field$ && field$.prop('checked')) || false;
}
},
if (handler) {
return handler(field);
}
setters: {
default: getDefaultFieldSetter(),
varchar: getDefaultFieldSetter(),
checkbox: function (field$, value) {
if (!field$) {
return;
}
return $('#' + field) || null;
},
field$.prop('checked', !!value);
}
},
getFieldCell$: function (field) {
return $('[data-field="' + field + '"]') || null;
},
setValue: function (field, value) {
var field$ = this.getField$(field);
if (!field$) {
return null;
}
getFieldType: function (field) {
return (this.fields[field] && this.fields[field].type) || 'varchar';
},
var setter = this.getValueSetter(field);
if (!setter) {
return null;
}
getValueGetter: function (field) {
var handler = (this.fields[field] && this.fields[field].getter) || null;
return setter(field$, value);
},
if (handler) {
return handler;
}
getValue: function (field) {
var field$ = this.getField$(field);
if (!field$) {
return null;
}
var type = this.getFieldType(field);
return this.getters[type] || this.getters['default'];
},
var getter = this.getValueGetter(field);
if (!getter) {
return null;
}
getValueSetter: function (field) {
var handler = (this.fields[field] && this.fields[field].setter) || null;
return getter(field$);
},
if (handler) {
return handler;
}
hide: function (field) {
var field$ = this.getFieldCell$(field);
var type = this.getFieldType(field);
return this.setters[type] || this.setters['default'];
},
if (!field$ || !field$.length) {
return;
}
setRequired: function (field, fieldType, formName, required) {
field$.hide();
},
var $editView = $('#EditView');
if (!$editView || !$editView.length) {
return;
}
configureValidation(this.formName, this.name, required);
show: function (field) {
var field$ = this.getFieldCell$(field);
this.setRequiredIndicator(field, required);
if (!field$ || !field$.length) {
return;
}
if (required) {
addToValidate(formName, field, fieldType, true, SUGAR.language.get('OutboundEmailAccounts', "LBL_" + field.toUpperCase()));
} else {
removeFromValidate(formName, field);
}
field$.show();
},
},
setRequiredIndicator: function (field, required) {
var $label = this.getFieldCell$(field).find('.label');
if (required) {
addRequiredIndicator($label);
} else {
removeRequiredIndicator($label);
}
},
getField$: function (field) {
var handler = (this.fields[field] && this.fields[field].getField$) || null;
if (handler) {
return handler(field);
}
return $('#' + field) || null;
},
getFieldCell$: function (field) {
return $('[data-field="' + field + '"]') || null;
},
getFieldType: function (field) {
return (this.fields[field] && this.fields[field].type) || 'varchar';
},
getValueGetter: function (field) {
var type = this.getFieldType(field);
return this.getters[type] || this.getters['default'];
},
getValueSetter: function (field) {
var type = this.getFieldType(field);
return this.setters[type] || this.setters['default'];
}
};
};
}();

View file

@ -1,76 +0,0 @@
/**
*
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 2022 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along with
* this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "Powered by
* SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not
* reasonably feasible for technical reasons, the Appropriate Legal Notices must
* display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
function toggleAuthFields(authEnabled) {
var status = 'disabled';
if (authEnabled) {
status = 'enabled';
}
var fieldsPerStatus = {
'enabled': {
'mail_smtppass': true,
},
'disabled': {
'mail_smtppass': false,
},
};
var fieldDisplay = fieldsPerStatus[status] || fieldsPerStatus.disabled;
Object.keys(fieldDisplay).forEach(function (fieldKey) {
var display = fieldDisplay[fieldKey];
var method = 'show';
if(!display) {
method = 'hide';
}
outboundEmailFields[method](fieldKey);
});
}
$(document).ready(function () {
var authEnabled = outboundEmailFields.getValue('mail_smtpauth_req');
toggleAuthFields(authEnabled);
$('#mail_smtpauth_req').change(function () {
var authEnabled = outboundEmailFields.getValue('mail_smtpauth_req');
toggleAuthFields(authEnabled);
});
});

View file

@ -118,5 +118,14 @@ $mod_strings = array(
'LBL_OWNER' => 'Owner',
'LBL_OWNER_NAME' => 'Owner',
'LNK_EXTERNAL_OAUTH_CONNECTIONS' => 'External OAuth Connections'
'LBL_AUTH_TYPE' => 'Auth Type',
'LBL_EXTERNAL_OAUTH_CONNECTION' => 'External OAuth Connection',
'LBL_EXTERNAL_OAUTH_CONNECTION_ID' => 'External OAuth Connection id',
'LBL_EXTERNAL_OAUTH_CONNECTION_NAME' => 'External OAuth Connection',
'LNK_EXTERNAL_OAUTH_CONNECTIONS' => 'External OAuth Connections',
'LBL_ERROR_OUTBOUND_EMAIL_SYSTEM_EXISTS' => 'System Outbound Email Account already exists. Please remove it before creating a new one.',
'LBL_ERROR_OUTBOUND_EMAIL_SYSTEM_IS_NOT_GROUP' => 'When configuring the System Outbound account using OAuth, you must select a Group-Type External Oauth Connection',
'LBL_ERROR_OUTBOUND_EMAIL_CONNECTION_TYPE_MISMATCH' => 'When configuring the Outbound account using OAuth, you must select a External Oauth Connection the same type as the Outbound Email Account (Group or Personal)',
);

View file

@ -37,7 +37,7 @@ $viewdefs ['OutboundEmailAccounts'] = [
files="modules/OutboundEmailAccounts/js/fields.js,
modules/OutboundEmailAccounts/js/owner_toggle.js,
modules/OutboundEmailAccounts/js/panel_toggle.js,
modules/OutboundEmailAccounts/js/smtp_auth_toggle.js"}
modules/OutboundEmailAccounts/js/auth_type_fields_toggle.js"}
</script>
',
],
@ -57,17 +57,21 @@ $viewdefs ['OutboundEmailAccounts'] = [
],
'lbl_connection_configuration' => [
[
'mail_smtpserver',
'mail_smtpauth_req',
],
[
'mail_smtpssl',
'auth_type',
'mail_smtpuser',
],
[
'mail_smtpport',
'mail_smtpserver',
'external_oauth_connection_name',
],
[
'mail_smtpssl',
'',
],
[
'mail_smtpport',
''
],
],
'lbl_outbound_configuration' => [
[

View file

@ -40,7 +40,7 @@ $viewdefs ['OutboundEmailAccounts'] = [
modules/OutboundEmailAccounts/js/ssl_port_set.js,
modules/OutboundEmailAccounts/js/panel_toggle.js,
modules/OutboundEmailAccounts/js/owner_toggle.js,
modules/OutboundEmailAccounts/js/smtp_auth_toggle.js"}
modules/OutboundEmailAccounts/js/auth_type_fields_toggle.js"}
</script>
',
],
@ -60,17 +60,26 @@ $viewdefs ['OutboundEmailAccounts'] = [
],
'lbl_connection_configuration' => [
[
'mail_smtpserver',
'mail_smtpauth_req',
],
[
'mail_smtpssl',
'auth_type',
'mail_smtpuser',
],
[
'mail_smtpport',
'mail_smtpserver',
'mail_smtppass',
],
[
'mail_smtpssl',
[
'name' => 'external_oauth_connection_name',
'displayParams' => [
'initial_filter' => '{if $fields.type.value === "system"}&type="+"group"+"{/if}',
],
],
],
[
'mail_smtpport',
'',
],
[
[
'name' => 'sent_test_email_btn',

Some files were not shown because too many files have changed in this diff Show more