Skip to content

Commit

Permalink
SuiteCRM 7.12.9 Release
Browse files Browse the repository at this point in the history
  • Loading branch information
jack7anderson7 committed Jan 25, 2023
1 parent ba20ee5 commit c19f221
Show file tree
Hide file tree
Showing 21 changed files with 339 additions and 95 deletions.
22 changes: 20 additions & 2 deletions Api/V8/JsonApi/Helper/AttributeObjectHelper.php
Expand Up @@ -29,6 +29,24 @@ public function getAttributes(\SugarBean $bean, $fields = null)
{
$bean->fixUpFormatting();

$allowedField = [];

$fieldsToParse = $fields;
if (empty($fields)) {
$fieldsToParse = array_keys($bean->field_defs);
}

foreach ($fieldsToParse ?? [] as $index => $field) {
$isSensitive = isTrue($bean->field_defs[$field]['sensitive'] ?? false);
$notApiVisible = isFalse($bean->field_defs[$field]['api-visible'] ?? true);

if ($isSensitive || $notApiVisible){
continue;
}

$allowedField[$index] = $field;
}

// using the ISO 8601 format for dates
$attributes = array_map(function ($value) {
return is_string($value)
Expand All @@ -38,8 +56,8 @@ public function getAttributes(\SugarBean $bean, $fields = null)
: $value;
}, $bean->toArray());

if ($fields !== null) {
$attributes = array_intersect_key($attributes, array_flip($fields));
if ($allowedField !== null) {
$attributes = array_intersect_key($attributes, array_flip($allowedField));
}

unset($attributes['id']);
Expand Down
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -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.12.8
# SuiteCRM 7.12.9

[![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)
Expand Down
45 changes: 45 additions & 0 deletions data/BeanFactory.php
Expand Up @@ -151,6 +151,51 @@ public static function getBean($module, $id = null, $params = [], $deleted = tru
return $bean;
}

/**
* Returns a SugarBean object by id.
*
* @static
*
* @param string $module
* @param string $id
* @param array $params
* A name/value array of parameters. Names: encode, deleted.
* If $params is boolean we revert to the old arguments (encode, deleted), and use $params as $encode.
* This will be changed to using only $params in later versions.
* @param bool $deleted
* @see SugarBean::retrieve
*
* @return SugarBean|bool
*/
public static function getReloadedBean($module, $id = null, $params = [], $deleted = true)
{
$params = self::convertParams($params);
$encode = self::hasEncodeFlag($params);
$deleted = self::hasDeletedFlag($params, $deleted);

$beanClass = self::getBeanClass($module);

if (!self::loadBeanFile($module)) {
return false;
}

if (empty($id)) {
return new $beanClass();
}

/* @var SugarBean $bean */
$bean = new $beanClass();

$result = $bean->retrieve($id, $encode, $deleted);

if ($result === null) {
return false;
}

return $bean;
}


/**
* Shallow beans are created by SugarBean during the fill_in_relationship_fields method, and they differ from
* 'complete' bean in that they do not have their own relate fields completed.
Expand Down
72 changes: 36 additions & 36 deletions files.md5

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion include/InlineEditing/InlineEditing.php
Expand Up @@ -52,6 +52,11 @@ function getEditFieldHTML($module, $fieldname, $aow_field, $view = 'EditView', $
return false;
}

$vardef = $bean->getFieldDefinition($fieldname);

if (isTrue($vardef['sensitive'] ?? false) || isFalse($vardef['api-visible'] ?? true)){
return false;
}

$value = getFieldValueFromModule($fieldname, $module, $id);
// use the mod_strings for this module
Expand Down Expand Up @@ -126,7 +131,7 @@ function getEditFieldHTML($module, $fieldname, $aow_field, $view = 'EditView', $
if (isset($vardef['name']) && ($vardef['name'] == 'date_modified')) {
$vardef['name'] = 'aow_temp_date';
}

if (isset($vardef['help'])) {
$vardef['help'] = htmlspecialchars($vardef['help'],ENT_QUOTES);
}
Expand Down
5 changes: 5 additions & 0 deletions include/MySugar/MySugar.php
Expand Up @@ -95,6 +95,11 @@ public function addDashlet()

$dashlets = $current_user->getPreference('dashlets', $this->type);

if (!empty($_POST['type_module']) && stripos($_POST['type_module'], 'phar://') !== false) {
LoggerManager::getLogger()->security('MySugar:addDashlet unsecure type_module received: ' . $_POST['type_module']);
throw new RuntimeException('Invalid type_module');
}

$guid = create_guid();
$options = array();
if (isset($_POST['type'], $_POST['type_module']) && $_POST['type'] == 'web') {
Expand Down
30 changes: 28 additions & 2 deletions include/utils.php
Expand Up @@ -206,6 +206,9 @@ function make_sugar_config(&$sugar_config)
'php3',
'php4',
'php5',
'php6',
'php7',
'php8',
'pl',
'cgi',
'py',
Expand Down Expand Up @@ -468,6 +471,9 @@ function get_sugar_config_defaults(): array
'php3',
'php4',
'php5',
'php6',
'php7',
'php8',
'pl',
'cgi',
'py',
Expand All @@ -485,7 +491,8 @@ function get_sugar_config_defaults(): array
'png',
'jpg',
'jpeg',
'svg'
'svg',
'bmp'
],
'allowed_preview' => [
'pdf',
Expand Down Expand Up @@ -1351,7 +1358,7 @@ function return_module_language($language, $module, $refresh = false)
global $currentModule;

// Jenny - Bug 8119: Need to check if $module is not empty
if (empty($module)) {
if (empty($module) || !isAllowedModuleName($module)) {
$GLOBALS['log']->warn('Variable module is not in return_module_language, see more info: debug_backtrace()');

return array();
Expand Down Expand Up @@ -6025,3 +6032,22 @@ function get_id_validation_pattern(): string {

return $pattern;
}

/**
* Check if is string is an allowed module name
* @param string $value
* @return bool
*/
function isAllowedModuleName(string $value): bool {
if (empty($value)) {
return false;
}

$result = preg_match("/^[\w\-\_\.]+$/", $value);

if (!empty($result)) {
return true;
}

return false;
}
6 changes: 3 additions & 3 deletions install/install_utils.php
Expand Up @@ -994,7 +994,7 @@ function handleHtaccess()
$restrict_str .= <<<EOQ
RedirectMatch 403 {$ignoreCase}.*\.log$
RedirectMatch 403 {$ignoreCase}/+not_imported_.*\.txt
RedirectMatch 403 {$ignoreCase}/+(soap|cache|xtemplate|data|examples|include|log4php|metadata|modules|vendor)/+.*\.(php|tpl)
RedirectMatch 403 {$ignoreCase}/+(soap|cache|xtemplate|data|examples|include|log4php|metadata|modules|vendor)/+.*\.(php|tpl|phar)
RedirectMatch 403 {$ignoreCase}/+emailmandelivery\.php
RedirectMatch 403 {$ignoreCase}/+.git
RedirectMatch 403 {$ignoreCase}/+.{$cacheDir}
Expand Down Expand Up @@ -1043,7 +1043,7 @@ function handleHtaccess()
# CSS
ExpiresByType text/css "access plus 1 year"
# Data
ExpiresByType application/atom+xml "access plus 1 hour"
ExpiresByType application/rdf+xml "access plus 1 hour"
Expand Down Expand Up @@ -1296,7 +1296,7 @@ function create_default_users()
global $sugar_config;

require_once('install/UserDemoData.php');

//Create default admin user
$user = BeanFactory::newBean('Users');
$user->id = 1;
Expand Down
7 changes: 7 additions & 0 deletions lib/API/JsonApi/v1/Resource/SuiteBeanResource.php
Expand Up @@ -115,6 +115,13 @@ public function fromSugarBean($sugarBean, $source = ResourceEnum::DEFAULT_SOURCE
throw $exception;
}

$isSensitive = isTrue($definition['sensitive'] ?? false);
$notApiVisible = isFalse($definition['api-visible'] ?? true);

if ($isSensitive || $notApiVisible){
continue;
}

if ($definition['type'] === 'datetime' && isset($sugarBean->$fieldName)) {
// Convert to DB date
$datetime = $dateTimeConverter->fromUser($sugarBean->$fieldName);
Expand Down
6 changes: 6 additions & 0 deletions modules/AOS_Products/AOS_Products.php
Expand Up @@ -64,6 +64,12 @@ public function save($check_notify = false)
require_once('include/upload_file.php');
$GLOBALS['log']->debug('UPLOADING PRODUCT IMAGE');

$imageFileName = $_FILES['uploadimage']['name'] ?? '';
if (!has_valid_image_extension('AOS_Products Uploaded image file: ' . $imageFileName , $imageFileName)) {

This comment has been minimized.

Copy link
@lazka

lazka Jan 26, 2023

Contributor

this broke the unit tests

LoggerManager::getLogger()->fatal("AOS_Products save - Invalid image file ext : '$imageFileName'.");
throw new RuntimeException('Invalid request');
}

if (!empty($_FILES['uploadimage']['tmp_name']) && verify_uploaded_image($_FILES['uploadimage']['tmp_name'])) {
if ($_FILES['uploadimage']['size'] > $sugar_config['upload_maxsize']) {
die($mod_strings['LBL_IMAGE_UPLOAD_FAIL'] . $sugar_config['upload_maxsize']);
Expand Down
12 changes: 9 additions & 3 deletions modules/Administration/UpgradeWizard.php
Expand Up @@ -106,9 +106,15 @@ function unlinkTempFiles()
$perform = true;
$base_filename = urldecode($tempFile);
} elseif (!empty($_REQUEST['load_module_from_dir'])) {
$moduleDir = $_REQUEST['load_module_from_dir'];
if (strpos($moduleDir, 'phar://') !== false) {
die();
$moduleDir = $_REQUEST['load_module_from_dir'] ?? '';
if (stripos($moduleDir, 'phar://') !== false) {
LoggerManager::getLogger()->fatal("UpgradeWizard - invalid load_module_from_dir: " . $moduleDir);
throw new RuntimeException('Invalid request');
}

if (strtolower(pathinfo(urldecode($_REQUEST['upgrade_zip_escaped'] ?? ''), PATHINFO_EXTENSION)) !== 'zip'){
LoggerManager::getLogger()->fatal("UpgradeWizard - invalid upgrade_zip_escaped: " . $_REQUEST['upgrade_zip_escaped'] ?? '');
throw new RuntimeException("Invalid request");
}
//copy file to proper location then call performSetup
copy($moduleDir . '/' . $_REQUEST['upgrade_zip_escaped'], "upload://" . $_REQUEST['upgrade_zip_escaped']);
Expand Down
13 changes: 9 additions & 4 deletions modules/Campaigns/WebToPersonCapture.php
Expand Up @@ -54,6 +54,11 @@
die('Not a valid module directory');
}

if (!isValidWebToPersonModule($moduleDir)) {
LoggerManager::getLogger()->fatal('Trying to run WepToPersonCapture for invalid module: ' . $moduleDir);
throw new RuntimeException('Not a valid module');
}

global $app_strings, $sugar_config, $timedate, $current_user;

$mod_strings = return_module_language($sugar_config['default_language'], $moduleDir);
Expand Down Expand Up @@ -120,7 +125,7 @@

//As form base items are not necessarily in place for the custom classes that extend Person, cannot use
//the hendleSave method of the formbase

$optInEmailFields = array();
$optInPrefix = 'opt_in_';

Expand Down Expand Up @@ -209,8 +214,8 @@
$sea->AddUpdateEmailAddress($person->email2, 0, 1);
}
}


if (!empty($optInEmailFields)) {
// Look for opted out
$optedOut = array();
Expand Down Expand Up @@ -342,7 +347,7 @@
$log = LoggerManager::getLogger();
$log->error('Success but some error occurred: ' . implode(', ', $errors));
}

//If the custom module does not have a LBL_THANKS_FOR_SUBMITTING label, default to this general one
echo $app_strings['LBL_THANKS_FOR_SUBMITTING'];
}
Expand Down
46 changes: 38 additions & 8 deletions modules/Campaigns/utils.php
Expand Up @@ -54,7 +54,7 @@
*name and list of all prospects associated with this campaign..
*
*/
function get_message_scope_dom($campaign_id, $campaign_name, $db=null, $mod_strings=array())
function get_message_scope_dom($campaign_id, $campaign_name, $db = null, $mod_strings = array())
{
if (empty($db)) {
$db = DBManagerFactory::getInstance();
Expand All @@ -65,7 +65,7 @@ function get_message_scope_dom($campaign_id, $campaign_name, $db=null, $mod_stri
}

//find prospect list attached to this campaign..
$query = "SELECT prospect_list_id, prospect_lists.name ";
$query = "SELECT prospect_list_id, prospect_lists.name ";
$query .= "FROM prospect_list_campaigns ";
$query .= "INNER join prospect_lists on prospect_lists.id = prospect_list_campaigns.prospect_list_id ";
$query .= "WHERE prospect_lists.deleted = 0 ";
Expand Down Expand Up @@ -297,21 +297,21 @@ function log_campaign_activity($identifier, $activity, $update = true, $clicked_
//values for return array..
$return_array['target_id'] = $row['target_id'];
$return_array['target_type'] = $row['target_type'];

// quote variable first
$dataArrayKeys = array_keys($data);
$dataArrayKeysQuoted = array();
foreach ($dataArrayKeys as $dataArrayKey) {
$dataArrayKeysQuoted[] = $db->quote($dataArrayKey);
}
$dataArrayKeysQuotedImplode = implode(', ', $dataArrayKeysQuoted);

$insert_query = "INSERT into campaign_log (" . $dataArrayKeysQuotedImplode . ")";

$dataArrayValuesQuotedImplode = implode(', ', array_values($data));

$insert_query .= " VALUES (" . $dataArrayValuesQuotedImplode . ")";

$db->query($insert_query);
}
} else {
Expand All @@ -331,7 +331,7 @@ function log_campaign_activity($identifier, $activity, $update = true, $clicked_
$rowCampaignIdQuoted = $db->quote($row['campaign_id']);
$query = "SELECT campaigns.* FROM campaigns WHERE campaigns.id = '" . $rowCampaignIdQuoted . "' ";
$result = $db->query($query);

if (!empty($result)) {
$c_row = $db->fetchByAssoc($result);

Expand Down Expand Up @@ -1160,3 +1160,33 @@ function filterFieldsFromBeans($beans)
}
return $formattedBeans;
}

/**
* Get valid web to person modules
* @return array
*/
function getValidWebToPersonModules(): array
{
$superclass = 'Person';
$modules = [];
foreach ($GLOBALS['moduleList'] as $mod) {
$item = BeanFactory::getBean($mod);
if ($item && is_subclass_of($item, $superclass)) {
$modules[] = $item->module_name;
}
}

return $modules;
}

/**
* Check if it is a valid WebToPerson module
* @param string $module
* @return bool
*/
function isValidWebToPersonModule(string $module): bool
{
$validModules = getValidWebToPersonModules();

return in_array($module, $validModules, true);
}

0 comments on commit c19f221

Please sign in to comment.