diff --git a/data/CRMEntity.php b/data/CRMEntity.php index a2bde35da4647c7f65e02a0b6054366493696cb4..469dae8ed1fd3737b7f81364e380934dd1415e1b 100644 --- a/data/CRMEntity.php +++ b/data/CRMEntity.php @@ -571,7 +571,7 @@ class CRMEntity { } else { $fldvalue = $this->column_fields[$fieldname]; } - } elseif ($uitype == 7) { + } elseif ($uitype == 7 || $uitype == 9) { //strip out the spaces and commas in numbers if given ie., in amounts there may be , $fldvalue = str_replace(",", "", $this->column_fields[$fieldname]); //trim($this->column_fields[$fieldname],","); if (in_array($datatype, array('N', 'NN'))) { @@ -2999,9 +2999,10 @@ class CRMEntity { * @param <String> $selectedColumns * @param <Boolean> $ignoreEmpty * @param <Array> $requiredTables + * @param <Array> $columnTypes * @return string */ - function getQueryForDuplicates($module, $tableColumns, $selectedColumns = '', $ignoreEmpty = false,$requiredTables = array()) { + function getQueryForDuplicates($module, $tableColumns, $selectedColumns = '', $ignoreEmpty = false,$requiredTables = array(),$columnTypes = null) { if(is_array($tableColumns)) { $tableColumnsString = implode(',', $tableColumns); } @@ -3031,7 +3032,11 @@ class CRMEntity { if($ignoreEmpty) { foreach($tableColumns as $tableColumn){ - $whereClause .= " AND ($tableColumn IS NOT NULL AND $tableColumn != '') "; + if ($columnTypes && ($columnTypes[$tableColumn] == "date" || $columnTypes[$tableColumn] == "datetime")) { + $whereClause .= " AND ($tableColumn IS NOT NULL) "; + } else { + $whereClause .= " AND ($tableColumn IS NOT NULL AND $tableColumn != '') "; + } } } diff --git a/include/database/PearDatabase.php b/include/database/PearDatabase.php index 1fae20c8b7910808a69ad3a1d3e5fc9793fb2f67..dee0f71f797f8ab0029cc8eae040841c5a4215ea 100644 --- a/include/database/PearDatabase.php +++ b/include/database/PearDatabase.php @@ -357,8 +357,20 @@ class PearDatabase{ $this->executeSetNamesUTF8SQL(); $sql_start_time = microtime(true); - $params = $this->flatten_array($params); - if (is_array($params) && count($params) > 0) { + + // flatten only when params has array inside. + $flatten_params = false; + foreach ($params as $val) { + if (is_array($val)) { + $flatten_params = true; + break; + } + } + if ($flatten_params) { + $params = $this->flatten_array($params); + } + + if ($log->isDebugEnabled() && is_array($params) && count($params) > 0) { $log->debug('Prepared sql query parameters : [' . implode(",", $params) . ']'); } diff --git a/include/utils/VtlibUtils.php b/include/utils/VtlibUtils.php index 41733b7136f3e29ea71555582ec828dec851e4b3..06e20bfd7f3cb323625a51db7dd988e76c295fc5 100644 --- a/include/utils/VtlibUtils.php +++ b/include/utils/VtlibUtils.php @@ -735,6 +735,37 @@ function vtlib_purify($input, $ignore = false) { return $value; } +/** + * Remove content within quotes (single/double/unbalanced) + * Helpful to keep away quote-injection xss attacks in the templates. + */ +function vtlib_strip_quoted($input) { + if (is_null($input)) return $input; + + $output = $input; + /* + * Discard anything in "double quoted until'you find next double quote" + * or discard anything in 'single quoted until "you" find next single quote" + */ + $qchar = '"'; + $idx = strpos($input, $qchar); + if ($idx === false) { // no double-quote, find single-quote + $qchar = "'"; + $idx = strpos($input, $qchar); + } + if ($idx !== false) { + $output = substr($input,0, $idx); + $idx = strpos($input, $qchar, $idx+1); + if ($idx === false) { + // unbalanced - eat all. + $idx = strlen($input)-1; + } + $input = substr($input, $idx+1); + $output .= vtlib_strip_quoted($input); + } + return $output; +} + /** * Function to replace values in multi dimentional array (str_replace will support only one level of array) * @param type $search @@ -785,32 +816,13 @@ function strcasecmp_accents_callback() { */ function purifyHtmlEventAttributes($value,$replaceAll = false){ -$tmp_markers = $office365ImageMarkers = array(); -$value = Vtiger_Functions::strip_base64_data($value,true,$tmp_markers); -$value = Vtiger_Functions::stripInlineOffice365Image($value,true,$office365ImageMarkers); -$tmp_markers = array_merge($tmp_markers, $office365ImageMarkers); - -$htmlEventAttributes = "onerror|onblur|onchange|oncontextmenu|onfocus|oninput|oninvalid|onresize|onauxclick|oncancel|oncanplay|oncanplaythrough|". - "onreset|onsearch|onselect|onsubmit|onkeydown|onkeypress|onkeyup|onclose|oncuechange|ondurationchange|onemptied|onended|". - "onclick|ondblclick|ondrag|ondragend|ondragenter|ondragleave|ondragover|ondragexit|onformdata|onloadeddata|onloadedmetadata|". - "ondragstart|ondrop|onmousedown|onmousemove|onmouseout|onmouseover|onmouseenter|onmouseleave|onpause|onplay|onplaying|". - "onmouseup|onmousewheel|onscroll|onwheel|oncopy|oncut|onpaste|onload|onprogress|onratechange|onsecuritypolicyviolation|". - "onselectionchange|onabort|onselectstart|onstart|onfinish|onloadstart|onshow|onreadystatechange|onseeked|onslotchange|". - "onseeking|onstalled|onsubmit|onsuspend|ontimeupdate|ontoggle|onvolumechange|onwaiting|onwebkitanimationend|onstorage|". - "onwebkitanimationiteration|onwebkitanimationstart|onwebkittransitionend|onafterprint|onbeforeprint|onbeforeunload|". - "onhashchange|onlanguagechange|onmessage|onmessageerror|onoffline|ononline|onpagehide|onpageshow|onpopstate|onunload|". - "onrejectionhandled|onunhandledrejection|onloadend|onpointerenter|ongotpointercapture|onlostpointercapture|onpointerdown|". - "onpointermove|onpointerup|onpointercancel|onpointerover|onpointerout|onpointerleave|onactivate|onafterscriptexecute|". - "onanimationcancel|onanimationend|onanimationiteration|onanimationstart|onbeforeactivate|onbeforedeactivate|onbeforescriptexecute|". - "onbegin|onbounce|ondeactivate|onend|onfocusin|onfocusout|onrepeat|ontransitioncancel|ontransitionend|ontransitionrun|". - "ontransitionstart|onbeforecopy|onbeforecut|onbeforepaste|onfullscreenchange|onmozfullscreenchange|onpointerrawupdate|". - "ontouchend|ontouchmove|ontouchstart"; - + $tmp_markers = $office365ImageMarkers = array(); + $value = Vtiger_Functions::strip_base64_data($value,true,$tmp_markers); + $value = Vtiger_Functions::stripInlineOffice365Image($value,true,$office365ImageMarkers); + $tmp_markers = array_merge($tmp_markers, $office365ImageMarkers); // remove malicious html attributes with its value. if ($replaceAll) { - $regex = '\s*[=&%#]\s*(?:"[^"]*"[\'"]*|\'[^\']*\'[\'"]*|[^]*[\s\/>])*/i'; - $value = preg_replace("/\s*(" . $htmlEventAttributes . ")" . $regex, '', $value); - + $value = preg_replace('/\b(alert|on\w+)\s*\([^)]*\)|\s*(?:on\w+)=(".*?"|\'.*?\'|[^\'">\s]+)\s*/', '', $value); //remove script tag with contents $value = purifyScript($value); //purify javascript alert from the tag contents diff --git a/layouts/v7/modules/Inventory/partials/LineItemsContent.tpl b/layouts/v7/modules/Inventory/partials/LineItemsContent.tpl index a1bd2b88490dbc52b620ed78fbfe17a715231e31..7f8a3dff92e6cb1388f8139a643b54405c14f7af 100644 --- a/layouts/v7/modules/Inventory/partials/LineItemsContent.tpl +++ b/layouts/v7/modules/Inventory/partials/LineItemsContent.tpl @@ -46,7 +46,7 @@ {assign var="listPriceValues" value=Products_Record_Model::getListPriceValues($productId)} {if $MODULE eq 'PurchaseOrder'} {assign var="listPriceValues" value=array()} - {assign var="purchaseCost" value="{if $data.$purchaseCost && $RECORD_CURRENCY_RATE}{((float)$data.$purchaseCost) / ((float)$data.$qty * (float){$RECORD_CURRENCY_RATE})}{else}0{/if}"} + {assign var="purchaseCost" value="{if $data.$purchaseCost && $RECORD_CURRENCY_RATE && $data.$qty}{((float)$data.$purchaseCost) / ((float)$data.$qty * (float){$RECORD_CURRENCY_RATE})}{else}0{/if}"} {foreach item=currency_details from=$CURRENCIES} {append var='listPriceValues' value=$currency_details.conversionrate * $purchaseCost index=$currency_details.currency_id} {/foreach} @@ -298,4 +298,4 @@ <td> <span id="netPrice{$row_no}" class="pull-right netPrice">{if $data.$netPrice}{$data.$netPrice}{else}0{/if}</span> </td> -{/strip} \ No newline at end of file +{/strip} diff --git a/layouts/v7/modules/Vtiger/Header.tpl b/layouts/v7/modules/Vtiger/Header.tpl index 6e5e79f46fb100dc4c3ea3e08236e516e23019af..cd72c18daa43c2b5a01c4e5733f99f1780c9e42b 100644 --- a/layouts/v7/modules/Vtiger/Header.tpl +++ b/layouts/v7/modules/Vtiger/Header.tpl @@ -61,7 +61,7 @@ {if $CURRENT_USER_MODEL} _USERMETA = { 'id' : "{$CURRENT_USER_MODEL->get('id')}", 'menustatus' : "{$CURRENT_USER_MODEL->get('leftpanelhide')}", 'currency' : "{decode_html($USER_CURRENCY_SYMBOL)}", 'currencySymbolPlacement' : "{$CURRENT_USER_MODEL->get('currency_symbol_placement')}", - 'currencyGroupingPattern' : "{$CURRENT_USER_MODEL->get('currency_grouping_pattern')}", 'truncateTrailingZeros' : "{$CURRENT_USER_MODEL->get('truncate_trailing_zeros')}",'userlabel':"{vtlib_purify(decode_html($CURRENT_USER_MODEL->get('userlabel')))}",}; + 'currencyGroupingPattern' : "{$CURRENT_USER_MODEL->get('currency_grouping_pattern')}", 'truncateTrailingZeros' : "{$CURRENT_USER_MODEL->get('truncate_trailing_zeros')}",'userlabel':"{($CURRENT_USER_MODEL->get('userlabel'))|escape:html}",}; {/if} </script> </head> diff --git a/layouts/v7/modules/Vtiger/resources/validation.js b/layouts/v7/modules/Vtiger/resources/validation.js index 16d59a3bb71da07477c3f4570ae6c07eeb4a1e3b..240ea286cda1ef3f7c9eca1cd2b50571aea4ee09 100644 --- a/layouts/v7/modules/Vtiger/resources/validation.js +++ b/layouts/v7/modules/Vtiger/resources/validation.js @@ -700,7 +700,7 @@ jQuery.validator.addMethod("PositiveNumber",function(value,element,params){ jQuery.validator.addMethod("percentage", function(value, element, params){ var decimalSeparator = app.getDecimalSeparator(); - var strippedValue = value.replace(/[^\d,]/g, ''); + var strippedValue = value.replace(decimalSeparator, ''); var spacePattern = /\s/; if(spacePattern.test(decimalSeparator)) { strippedValue = strippedValue.replace(/ /g, ''); diff --git a/modules/Emails/models/Record.php b/modules/Emails/models/Record.php index 7f5e1d99ec23cdc7cc82cc8deb6a321772502065..5595d222b624a79ebc5c5060a1f71aa8dda327ce 100644 --- a/modules/Emails/models/Record.php +++ b/modules/Emails/models/Record.php @@ -36,7 +36,7 @@ class Emails_Record_Model extends Vtiger_Record_Model { //$this->set('assigned_user_id', $currentUserModel->getId()); $this->getModule()->saveRecord($this); $documentIds = $this->get('documentids'); - if (!empty ($documentIds)) { + if (!empty ($documentIds) && $documentIds != "[]") { /* json_encoded check for empty */ $this->deleteDocumentLink(); $this->saveDocumentDetails(); } diff --git a/modules/Leads/Leads.php b/modules/Leads/Leads.php index 0d366b3224572dfbcbeab4aa4725e1d05e3f1603..442145a3f8d5b26d48d945d3b843ab87e021596e 100755 --- a/modules/Leads/Leads.php +++ b/modules/Leads/Leads.php @@ -681,7 +681,7 @@ class Leads extends CRMEntity { } } - function getQueryForDuplicates($module, $tableColumns, $selectedColumns = '', $ignoreEmpty = false, $requiredTables = array()) { + function getQueryForDuplicates($module, $tableColumns, $selectedColumns = '', $ignoreEmpty = false, $requiredTables = array(), $columnTypes = null) { if(is_array($tableColumns)) { $tableColumnsString = implode(',', $tableColumns); } @@ -711,7 +711,11 @@ class Leads extends CRMEntity { if($ignoreEmpty) { foreach($tableColumns as $tableColumn){ - $whereClause .= " AND ($tableColumn IS NOT NULL AND $tableColumn != '') "; + if ($columnTypes && ($columnTypes[$tableColumn] == "date" || $columnTypes[$tableColumn] == "datetime")) { + $whereClause .= " AND ($tableColumn IS NOT NULL) "; + } else { + $whereClause .= " AND ($tableColumn IS NOT NULL AND $tableColumn != '') "; + } } } @@ -759,4 +763,4 @@ class Leads extends CRMEntity { } } -?> \ No newline at end of file +?> diff --git a/modules/Migration/schema/650_to_660.php b/modules/Migration/schema/650_to_660.php index 2edbe3f3ca0e971073cf975d9eea902e739c4007..6e6faf8384027a64d75acabf1b790a561e92efb0 100644 --- a/modules/Migration/schema/650_to_660.php +++ b/modules/Migration/schema/650_to_660.php @@ -17,6 +17,7 @@ if(defined('VTIGER_UPGRADE')) { $adb->pquery('INSERT INTO vtiger_actionmapping VALUES(?, ?, ?)', array(7, 'CreateView', 0)); } + // take reference of operation (1) and make entries similarly to operation (7) - skip over duplicates. $createActionResult = $adb->pquery('SELECT * FROM vtiger_profile2standardpermissions WHERE operation=?', array(1)); $query = 'INSERT INTO vtiger_profile2standardpermissions VALUES'; while($rowData = $adb->fetch_array($createActionResult)) { @@ -25,7 +26,8 @@ if(defined('VTIGER_UPGRADE')) { $permissions = $rowData['permissions']; $query .= "('$profileId', '$tabId', '7', '$permissions'),"; } - $adb->pquery(trim($query, ','), array()); + $query = trim($query, ',') . " on duplicate key update permissions=permissions"; /* mute update to avoid insert failure on duplicate entries */ + $adb->pquery($query, array()); require_once 'modules/Users/CreateUserPrivilegeFile.php'; $usersResult = $adb->pquery('SELECT id FROM vtiger_users', array()); diff --git a/modules/SalesOrder/SalesOrder.php b/modules/SalesOrder/SalesOrder.php index c7ca1a6d94c296ae3b9621e05cbfdcfed8a5cdd5..3ad88894f0483866f34a834aaf9857e1e40db586 100644 --- a/modules/SalesOrder/SalesOrder.php +++ b/modules/SalesOrder/SalesOrder.php @@ -540,7 +540,7 @@ class SalesOrder extends CRMEntity { * @return string */ // Note : remove getDuplicatesQuery API once vtiger5 code is removed - function getQueryForDuplicates($module, $tableColumns, $selectedColumns = '', $ignoreEmpty = false,$requiredTables = array()) { + function getQueryForDuplicates($module, $tableColumns, $selectedColumns = '', $ignoreEmpty = false,$requiredTables = array(), $columnTypes = null) { if(is_array($tableColumns)) { $tableColumnsString = implode(',', $tableColumns); } @@ -575,7 +575,11 @@ class SalesOrder extends CRMEntity { if($ignoreEmpty) { foreach($tableColumns as $tableColumn){ - $whereClause .= " AND ($tableColumn IS NOT NULL AND $tableColumn != '') "; + if ($columnTypes && ($columnTypes[$tableColumn] == "date" || $columnTypes[$tableColumn] == "datetime")) { + $whereClause .= " AND ($tableColumn IS NOT NULL) "; + } else { + $whereClause .= " AND ($tableColumn IS NOT NULL AND $tableColumn != '') "; + } } } diff --git a/modules/Users/Users.php b/modules/Users/Users.php index b0ad5bd58992e3ea6253da2f59808d1ae4b4b36b..b88c9f8dc80954a434a3bfd912e5f44acd5a69dd 100755 --- a/modules/Users/Users.php +++ b/modules/Users/Users.php @@ -779,7 +779,7 @@ class Users extends CRMEntity { } $userlabel = trim(decode_html($userlabel)); - $this->column_fields['userlabel'] = strip_tags($userlabel); + $this->column_fields['userlabel'] = vtlib_strip_quoted(strip_tags($userlabel)); } if($insertion_mode == 'edit') { diff --git a/modules/Users/actions/Save.php b/modules/Users/actions/Save.php index 378a09d58eaf8923993576419f9493ce076380fd..5c5c7aecd5038c8603c3cb48614ef306f965bd3f 100644 --- a/modules/Users/actions/Save.php +++ b/modules/Users/actions/Save.php @@ -109,6 +109,27 @@ class Users_Save_Action extends Vtiger_Save_Action { return $recordModel; } + protected function checkRestrictedValueChange(Vtiger_Request $request) { + // NOTE: to be repeated in SaveAjax.php + + if ($request->has('user_name') || $request->has('user_password') || $request->has('accesskey') ) { + // should use separate actions. + throw new AppException(vtranslate('LBL_PERMISSION_DENIED', 'Vtiger')); + } + + if ($request->get('field', "") == "status" || $request->has("status")) { + $currentUserModel = Users_Record_Model::getCurrentUserModel(); + // only admin (not self) can change status. + if (!$currentUserModel->isAdminUser()) { + throw new AppException(vtranslate('LBL_PERMISSION_DENIED', 'Vtiger')); + } + $recordId = $request->get('record'); + if ($recordId == $currentUserModel->getId()) { + throw new AppException(vtranslate('LBL_PERMISSION_DENIED', 'Vtiger')); + } + } + } + public function process(Vtiger_Request $request) { $result = Vtiger_Util_Helper::transformUploadedFiles($_FILES, true); $_FILES = $result['imagename']; @@ -123,10 +144,7 @@ class Users_Save_Action extends Vtiger_Save_Action { throw new AppException(vtranslate('LBL_DUPLICATE_USER_EXISTS', $module)); } } else { - if ($request->has('user_name') || $request->has('user_password') || $request->has('accesskey') ) { - // should use separate actions. - throw new AppException(vtranslate('LBL_PERMISSION_DENIED', $module)); - } + $this->checkRestrictedValueChange($request); } $recordModel = $this->saveRecord($request); diff --git a/modules/Users/actions/SaveAjax.php b/modules/Users/actions/SaveAjax.php index 4c242a0293d6bc51a99bd097f117648acc1a9cce..485a092d34a9e622802b1122d23919178f3ce2f1 100644 --- a/modules/Users/actions/SaveAjax.php +++ b/modules/Users/actions/SaveAjax.php @@ -43,12 +43,40 @@ class Users_SaveAjax_Action extends Vtiger_SaveAjax_Action { } } + protected function checkRestrictedValueChange(Vtiger_Request $request) { + // NOTE: to be repeated in Save.php + + if ($request->has('user_name') || $request->has('user_password') || $request->has('accesskey') ) { + // should use separate actions. + throw new AppException(vtranslate('LBL_PERMISSION_DENIED', 'Vtiger')); + } + if ($request->has('field') && in_array($request->get('field'), array('user_name', 'user_password', 'accesskey'))) { + // should use separate actions. + throw new AppException(vtranslate('LBL_PERMISSION_DENIED', 'Vtiger')); + } + + if ($request->get('field', "") == "status" || $request->has("status")) { + $currentUserModel = Users_Record_Model::getCurrentUserModel(); + // only admin (not self) can change status. + if (!$currentUserModel->isAdminUser()) { + throw new AppException(vtranslate('LBL_PERMISSION_DENIED', 'Vtiger')); + } + $recordId = $request->get('record'); + if ($recordId == $currentUserModel->getId()) { + throw new AppException(vtranslate('LBL_PERMISSION_DENIED', 'Vtiger')); + } + } + + } + public function process(Vtiger_Request $request) { $mode = $request->get('mode'); if (!empty($mode)) { $this->invokeExposedMethod($mode, $request); return; + } else { + $this->checkRestrictedValueChange($request); } $recordModel = $this->saveRecord($request); diff --git a/modules/Users/models/Record.php b/modules/Users/models/Record.php index 1cc0d3633b1564d82d90f096ff7bc65525cb2a13..035e2b4990be62507b3a31fb8de01ca99ddab0d5 100644 --- a/modules/Users/models/Record.php +++ b/modules/Users/models/Record.php @@ -882,11 +882,17 @@ class Users_Record_Model extends Vtiger_Record_Model { */ public static function changeUsername($newUsername,$newpassword,$oldPassword,$forUserId) { $response = array('success'=> false,'message' => 'error'); - $record = self::getInstanceFromPreferenceFile($forUserId); - $moduleName = $record->getModuleName(); + $moduleName = "Users"; $currentUserModel = static::getCurrentUserModel(); - if($currentUserModel->getId() == $forUserId || !Users_Privileges_Model::isPermittedToChangeUsername($forUserId)) { + if (empty($newpassword) || empty($forUserId)) { + $response['message'] = vtranslate('ERROR_CHANGE_USERNAME', $moduleName); + return $response; + } + + $record = self::getInstanceFromPreferenceFile($forUserId); + + if(!Users_Privileges_Model::isPermittedToChangeUsername($forUserId)) { $response['message'] = vtranslate('LBL_PERMISSION_DENIED', $moduleName); return $response; } diff --git a/modules/Vtiger/helpers/Logger.php b/modules/Vtiger/helpers/Logger.php index f9a61ef77bbd1fcc9f1efb6f511392474c7a60d7..0198dc142fc2931643fc30b36e27b644a37cff70 100644 --- a/modules/Vtiger/helpers/Logger.php +++ b/modules/Vtiger/helpers/Logger.php @@ -76,6 +76,10 @@ class Logger { public function warn($message) {} public function error($message) {} + public function isDebugEnabled() { + return self::$logLevel == 100; + } + } // Define extended version of Monolog Logger to support functions @@ -83,6 +87,16 @@ class MonologLoggerEx extends MonologLogger { function fatal($message, $context = array()) { $this->error($message, $context); } + function isDebugEnabled() { + $debugLevel = false; + foreach ($this->getHandlers() as $handler) { + if ($handler->getLogLevel() == static::DEBUG) { + $debugLevel = true; + break; + } + } + return $debugLevel; + } } // Define a custom log formatter diff --git a/modules/Vtiger/models/FindDuplicate.php b/modules/Vtiger/models/FindDuplicate.php index 892cb538d6da2c94d9a98662344f2a8ab62de21a..d4889a24322777ce0e55ae66ce4d3c49882cb59b 100644 --- a/modules/Vtiger/models/FindDuplicate.php +++ b/modules/Vtiger/models/FindDuplicate.php @@ -42,11 +42,13 @@ class Vtiger_FindDuplicate_Model extends Vtiger_Base_Model { $fields = $this->get('fields'); $fieldModels = $moduleModel->getFields(); $requiredTables = array(); + $columnTypes = array(); if(is_array($fields)) { foreach($fields as $fieldName) { $fieldModel = $fieldModels[$fieldName]; $requiredTables[] = $fieldModel->get('table'); $tableColumns[] = $fieldModel->get('table').'.'.$fieldModel->get('column'); + $columnTypes[$fieldModel->get('table').'.'.$fieldModel->get('column')] = $fieldModel->getFieldDataType(); } } @@ -55,7 +57,7 @@ class Vtiger_FindDuplicate_Model extends Vtiger_Base_Model { $ignoreEmpty = $this->get('ignoreEmpty'); $focus = CRMEntity::getInstance($module); - $query = $focus->getQueryForDuplicates($module, $tableColumns, '', $ignoreEmpty,$requiredTables); + $query = $focus->getQueryForDuplicates($module, $tableColumns, '', $ignoreEmpty,$requiredTables,$columnTypes); self::$query = $query; $query .= " LIMIT $startIndex, ". ($pageLimit+1); @@ -134,16 +136,18 @@ class Vtiger_FindDuplicate_Model extends Vtiger_Base_Model { $module = $moduleModel->getName(); $fields = $this->get('fields'); $fieldModels = $moduleModel->getFields(); + $columnTypes = array(); if(is_array($fields)) { foreach($fields as $fieldName) { $fieldModel = $fieldModels[$fieldName]; $requiredTables[] = $fieldModel->get('table'); $tableColumns[] = $fieldModel->get('table').'.'.$fieldModel->get('column'); + $columnTypes[$fieldModel->get('table').'.'.$fieldModel->get('column')] = $fieldModel->getFieldDataType(); } } $focus = CRMEntity::getInstance($module); $ignoreEmpty = $this->get('ignoreEmpty'); - self::$query = $focus->getQueryForDuplicates($module, $tableColumns, '', $ignoreEmpty,$requiredTables); + self::$query = $focus->getQueryForDuplicates($module, $tableColumns, '', $ignoreEmpty,$requiredTables,$columnTypes); } $query = self::$query; $position = stripos($query, 'from'); @@ -174,15 +178,19 @@ class Vtiger_FindDuplicate_Model extends Vtiger_Base_Model { $ignoreEmptyValue = true; $fieldModels = $moduleModel->getFields(); + $requiredTables = array(); + $columnTypes = array(); if(is_array($fields)) { foreach($fields as $fieldName) { $fieldModel = $fieldModels[$fieldName]; $tableColumns[] = $fieldModel->get('table').'.'.$fieldModel->get('column'); + $requiredTables[] = $fieldModel->get('table'); + $columnTypes[$fieldModel->get('table').'.'.$fieldModel->get('column')] = $fieldModel->getFieldDataType(); } } $focus = CRMEntity::getInstance($module); - $query = $focus->getQueryForDuplicates($module, $tableColumns, '', $ignoreEmpty); + $query = $focus->getQueryForDuplicates($module, $tableColumns, '', $ignoreEmpty, $requiredTables, $columnTypes); $result = $db->pquery($query, array()); $recordIds = array(); diff --git a/modules/Vtiger/uitypes/Percentage.php b/modules/Vtiger/uitypes/Percentage.php index 93815bc501f969d5c404dbdcc3955c1d6a56186f..b046afe29167b9b98168315926e5258d1e81fffd 100644 --- a/modules/Vtiger/uitypes/Percentage.php +++ b/modules/Vtiger/uitypes/Percentage.php @@ -21,7 +21,7 @@ class Vtiger_Percentage_UIType extends Vtiger_Base_UIType { public function getDisplayValue($value, $record = false, $recordInstance = false) { $fldvalue = str_replace(",", ".", $value); $value = (is_numeric($fldvalue)) ? $fldvalue : null; - return Vtiger_Percentage_UIType::convertToUserFormat($value, null, true); + return static::convertToUserFormat($value, null, true); } public static function convertToUserFormat($value, $user = null, $skipConversion = false, $skipFormatting = false) { @@ -32,19 +32,17 @@ class Vtiger_Percentage_UIType extends Vtiger_Base_UIType { if (empty($user)) { $user = Users_Record_Model::getCurrentUserModel(); } - $old_no_of_currency_decimals = $user->no_of_currency_decimals; - // If decimal separator is "," and no.of decimals is "0" then if we give 8,8 (value:8.8) - // which is becoming round of value i,e "9". - // so by default we are setting no_of_currency_decimals to max value. - $user->no_of_currency_decimals = 5; - $currencyField = new CurrencyField($value); $display_value = $currencyField->getDisplayValue($user, $skipConversion, $skipFormatting); - $user->no_of_currency_decimals = $old_no_of_currency_decimals; return $display_value; } public function getEditViewDisplayValue($value) { return $this->getDisplayValue($value); } + + public function getDBInsertValue($value) { + $value = CurrencyField::convertToDBFormat($value, null, true); + return $value; + } } diff --git a/packages/vtiger/mandatory/Import.zip b/packages/vtiger/mandatory/Import.zip index 75a95984566ceea8da35811ee8da3a52c18b16c3..8b879521d565b697cd6196ad5ac80a398b8b1797 100644 Binary files a/packages/vtiger/mandatory/Import.zip and b/packages/vtiger/mandatory/Import.zip differ diff --git a/packages/vtiger/mandatory/MailManager.zip b/packages/vtiger/mandatory/MailManager.zip index 66335f6a3c60151d63a2b6bfa545319194593b2b..1a91b4ecaa8d32372d31173080a906d87750ead0 100644 Binary files a/packages/vtiger/mandatory/MailManager.zip and b/packages/vtiger/mandatory/MailManager.zip differ diff --git a/packages/vtiger/mandatory/Mobile.zip b/packages/vtiger/mandatory/Mobile.zip index 1d5994b951e697d0f55ac13392cc7e17e626198e..314d6615e333475f3df901946e9ab7cbc65e03b2 100644 Binary files a/packages/vtiger/mandatory/Mobile.zip and b/packages/vtiger/mandatory/Mobile.zip differ diff --git a/packages/vtiger/mandatory/ModTracker.zip b/packages/vtiger/mandatory/ModTracker.zip index e26bd9e772d96fd2df99a601d342d0b999447e42..f4ab5d282b2dcdef07f59f7e48bcc0d7ae116b2a 100644 Binary files a/packages/vtiger/mandatory/ModTracker.zip and b/packages/vtiger/mandatory/ModTracker.zip differ diff --git a/packages/vtiger/mandatory/PBXManager.zip b/packages/vtiger/mandatory/PBXManager.zip index 570a8acf91ca00b48877d2d9ea345df8c97385a6..603660f72f8d605a82390cd91e0872d4de00340c 100644 Binary files a/packages/vtiger/mandatory/PBXManager.zip and b/packages/vtiger/mandatory/PBXManager.zip differ diff --git a/packages/vtiger/mandatory/ServiceContracts.zip b/packages/vtiger/mandatory/ServiceContracts.zip index 78361db20a82a1a4423e36132a103aa3dd98bb7b..bb9081390d3787eba29b37b2f247e7e7143e33fd 100644 Binary files a/packages/vtiger/mandatory/ServiceContracts.zip and b/packages/vtiger/mandatory/ServiceContracts.zip differ diff --git a/packages/vtiger/mandatory/Services.zip b/packages/vtiger/mandatory/Services.zip index 846ae8626643b14417dcab29cfffae39767ef611..74f2fa669a88929bb070f990d2c02b30ea4fbee8 100644 Binary files a/packages/vtiger/mandatory/Services.zip and b/packages/vtiger/mandatory/Services.zip differ diff --git a/packages/vtiger/mandatory/WSAPP.zip b/packages/vtiger/mandatory/WSAPP.zip index b98e0378aebea233cbd9be25050c80d3035539d2..e80ccf4192f425e8dcb93c459e6c70d5494fa39c 100644 Binary files a/packages/vtiger/mandatory/WSAPP.zip and b/packages/vtiger/mandatory/WSAPP.zip differ diff --git a/packages/vtiger/marketplace/ExtensionStore.zip b/packages/vtiger/marketplace/ExtensionStore.zip index 8e365d1593bc4cb5296af28a227a1fa8077a7b33..421f1f37e5857e0970abded28b78f5c5aead54ff 100644 Binary files a/packages/vtiger/marketplace/ExtensionStore.zip and b/packages/vtiger/marketplace/ExtensionStore.zip differ diff --git a/packages/vtiger/optional/Arabic_ar_ae.zip b/packages/vtiger/optional/Arabic_ar_ae.zip index b553579d6848903e544efa3e35ab309f7d6c0b57..f66e6328829d396f62fd840f827c5ef319d1f59a 100644 Binary files a/packages/vtiger/optional/Arabic_ar_ae.zip and b/packages/vtiger/optional/Arabic_ar_ae.zip differ diff --git a/packages/vtiger/optional/Assets.zip b/packages/vtiger/optional/Assets.zip index 97fc3899c1b896561d00c3cc77961db0d6f078ab..e58e3b846f2782d971a2a4bca93f96e761b13690 100644 Binary files a/packages/vtiger/optional/Assets.zip and b/packages/vtiger/optional/Assets.zip differ diff --git a/packages/vtiger/optional/BrazilianLanguagePack_bz_bz.zip b/packages/vtiger/optional/BrazilianLanguagePack_bz_bz.zip index 1312c392ae04a7d2132dd8dc5d4666c77a26d6c8..0c607aeec1e40debe87f8c51ade67ec5aa5041e1 100644 Binary files a/packages/vtiger/optional/BrazilianLanguagePack_bz_bz.zip and b/packages/vtiger/optional/BrazilianLanguagePack_bz_bz.zip differ diff --git a/packages/vtiger/optional/BritishLanguagePack_br_br.zip b/packages/vtiger/optional/BritishLanguagePack_br_br.zip index 107a1147edf8c3bd49ce4e528f2e5921d38f88e3..28f6e07acbc2298bce12106e66242c1c1688d11f 100644 Binary files a/packages/vtiger/optional/BritishLanguagePack_br_br.zip and b/packages/vtiger/optional/BritishLanguagePack_br_br.zip differ diff --git a/packages/vtiger/optional/CustomerPortal.zip b/packages/vtiger/optional/CustomerPortal.zip index 76cd0728acdfa4f5b248ab0b492cea002bd1dda6..f8f25e769373f85cef3e90adbab159cadbd1c8ac 100644 Binary files a/packages/vtiger/optional/CustomerPortal.zip and b/packages/vtiger/optional/CustomerPortal.zip differ diff --git a/packages/vtiger/optional/Deutsch.zip b/packages/vtiger/optional/Deutsch.zip index d51dd011309f4caac1a1ce4263a56365e4152a7e..0d7a6f0c0ce0e886e3ff095012f7714d3307f8ef 100644 Binary files a/packages/vtiger/optional/Deutsch.zip and b/packages/vtiger/optional/Deutsch.zip differ diff --git a/packages/vtiger/optional/Dutch.zip b/packages/vtiger/optional/Dutch.zip index d2b30129267ac79f9eec2e8c4623f04c55ada373..23679a435825cda05d6d36df1cb49ccdd0752b53 100644 Binary files a/packages/vtiger/optional/Dutch.zip and b/packages/vtiger/optional/Dutch.zip differ diff --git a/packages/vtiger/optional/EmailTemplates.zip b/packages/vtiger/optional/EmailTemplates.zip index 0a33497c04920753402ec5292660a19b208fb7db..8c96595e409849548a5858853dc8460fbadb1ea3 100644 Binary files a/packages/vtiger/optional/EmailTemplates.zip and b/packages/vtiger/optional/EmailTemplates.zip differ diff --git a/packages/vtiger/optional/French.zip b/packages/vtiger/optional/French.zip index 0040e8b751f02420dff7b0654bed1327c5ab2219..a30379660cf4815ee102e23f2432ddc96236229c 100644 Binary files a/packages/vtiger/optional/French.zip and b/packages/vtiger/optional/French.zip differ diff --git a/packages/vtiger/optional/Google.zip b/packages/vtiger/optional/Google.zip index c042d5978b0de52596228f1c43af29d84da04533..7d7f342af67ae7b525a0b2fe309c7a486390add5 100644 Binary files a/packages/vtiger/optional/Google.zip and b/packages/vtiger/optional/Google.zip differ diff --git a/packages/vtiger/optional/Hungarian.zip b/packages/vtiger/optional/Hungarian.zip index cfa6994d260fccfbc0e1bba90d04473974375b35..283897d0e4fbadc08d2775baf634d02129cad25a 100644 Binary files a/packages/vtiger/optional/Hungarian.zip and b/packages/vtiger/optional/Hungarian.zip differ diff --git a/packages/vtiger/optional/ItalianLanguagePack_it_it.zip b/packages/vtiger/optional/ItalianLanguagePack_it_it.zip index 0c9e64052464759802642bfa1816cee7921de5a2..543a8b516fa43ef9c33087eadb46ffe4a966a889 100644 Binary files a/packages/vtiger/optional/ItalianLanguagePack_it_it.zip and b/packages/vtiger/optional/ItalianLanguagePack_it_it.zip differ diff --git a/packages/vtiger/optional/MexicanSpanishLanguagePack_es_mx.zip b/packages/vtiger/optional/MexicanSpanishLanguagePack_es_mx.zip index 698045e178a1b67c0b280ec625d8c0e9e060cba9..816d870cede50c73b7c885223239a552a1ed39c7 100644 Binary files a/packages/vtiger/optional/MexicanSpanishLanguagePack_es_mx.zip and b/packages/vtiger/optional/MexicanSpanishLanguagePack_es_mx.zip differ diff --git a/packages/vtiger/optional/ModComments.zip b/packages/vtiger/optional/ModComments.zip index f6737fe71ad172d4828328a64beb6af21b87009a..d4dd7cbab25aef623993324db9131ca904261f51 100644 Binary files a/packages/vtiger/optional/ModComments.zip and b/packages/vtiger/optional/ModComments.zip differ diff --git a/packages/vtiger/optional/PolishLanguagePack_pl_pl.zip b/packages/vtiger/optional/PolishLanguagePack_pl_pl.zip index 4981faa6d9444da08360cfd72f5682cf73f6e116..41acff3ae33b8af7a77524d17cdd99e356e870a8 100644 Binary files a/packages/vtiger/optional/PolishLanguagePack_pl_pl.zip and b/packages/vtiger/optional/PolishLanguagePack_pl_pl.zip differ diff --git a/packages/vtiger/optional/Projects.zip b/packages/vtiger/optional/Projects.zip index 083ca969a143e672f1fcde63c4fa545af57a3fb0..4baac1894023af01af4ba23c4f3046a05f73fd11 100644 Binary files a/packages/vtiger/optional/Projects.zip and b/packages/vtiger/optional/Projects.zip differ diff --git a/packages/vtiger/optional/RecycleBin.zip b/packages/vtiger/optional/RecycleBin.zip index 6ec83e0d03d1dd11d5e903cff930d8ce079964f6..9a700f08b2327e87430659b72426ca48db2bcdb7 100644 Binary files a/packages/vtiger/optional/RecycleBin.zip and b/packages/vtiger/optional/RecycleBin.zip differ diff --git a/packages/vtiger/optional/RomanianLanguagePack_rm_rm.zip b/packages/vtiger/optional/RomanianLanguagePack_rm_rm.zip index 72ab095d121d9b1a052789b60d4d97f199e950a7..043f62ffdd1d6b3f3cc5183f2841a89fe83d8a95 100644 Binary files a/packages/vtiger/optional/RomanianLanguagePack_rm_rm.zip and b/packages/vtiger/optional/RomanianLanguagePack_rm_rm.zip differ diff --git a/packages/vtiger/optional/Russian.zip b/packages/vtiger/optional/Russian.zip index 4ba81546d81b6a10ba7c0404d91641497a16b50b..03222f1405420b5b6a7c39388534ffe19ed087fc 100644 Binary files a/packages/vtiger/optional/Russian.zip and b/packages/vtiger/optional/Russian.zip differ diff --git a/packages/vtiger/optional/SMSNotifier.zip b/packages/vtiger/optional/SMSNotifier.zip index c76cbd945ccb5dd84bffeb040ace02a7f77e3365..7c0fab9939e36be5780f9813f46522aae183670b 100644 Binary files a/packages/vtiger/optional/SMSNotifier.zip and b/packages/vtiger/optional/SMSNotifier.zip differ diff --git a/packages/vtiger/optional/Spanish.zip b/packages/vtiger/optional/Spanish.zip index c44ef0815ef1a4054f0f97bc0b7c5104ba85f759..92e8c42fcb770f26ae9007399803bffdfa660da7 100644 Binary files a/packages/vtiger/optional/Spanish.zip and b/packages/vtiger/optional/Spanish.zip differ diff --git a/packages/vtiger/optional/Sweden_sv_se.zip b/packages/vtiger/optional/Sweden_sv_se.zip index c6944675106d32695645f109d5bc6ff5e47f552f..2a703890a409453b3072e43e5caaeba4ac8eb909 100644 Binary files a/packages/vtiger/optional/Sweden_sv_se.zip and b/packages/vtiger/optional/Sweden_sv_se.zip differ diff --git a/packages/vtiger/optional/TurkishLanguagePack_tr_tr.zip b/packages/vtiger/optional/TurkishLanguagePack_tr_tr.zip index bdb8c342997f247217e216cc576a498cf2ad1ede..791d336c34c5e334ccdebc41615cb713efc9eb79 100644 Binary files a/packages/vtiger/optional/TurkishLanguagePack_tr_tr.zip and b/packages/vtiger/optional/TurkishLanguagePack_tr_tr.zip differ diff --git a/packages/vtiger/optional/Webforms.zip b/packages/vtiger/optional/Webforms.zip index 07149559dbb64a38de52420f08ebc5c9bbc4c5f2..4e94d0dbee48f9ac426c9fd1f40d5b0e72d4d86a 100644 Binary files a/packages/vtiger/optional/Webforms.zip and b/packages/vtiger/optional/Webforms.zip differ diff --git a/pkg/vtiger/modules/MailManager/modules/MailManager/connectors/Connector.php b/pkg/vtiger/modules/MailManager/modules/MailManager/connectors/Connector.php index 5bcb44ac00ce3876a0cc146d9b4e476b3d907c73..44c17d573f9e6e066fc7f78909edaa5dd788a24b 100644 --- a/pkg/vtiger/modules/MailManager/modules/MailManager/connectors/Connector.php +++ b/pkg/vtiger/modules/MailManager/modules/MailManager/connectors/Connector.php @@ -389,6 +389,7 @@ class MailManager_Connector_Connector { $mbox = $this->mBox; } + $mailnos = array(); foreach($records as $result) { $message = MailManager_Message_Model::parseOverview($result,$mbox); array_unshift($mails, $message); diff --git a/pkg/vtiger/modules/Webforms/settings/actions/Save.php b/pkg/vtiger/modules/Webforms/settings/actions/Save.php index 7ae864e1c61a60e25c5c03b8d88afa3e65d4ee2e..15fd2421ec4cbcbcb95516264aa807b07c957870 100644 --- a/pkg/vtiger/modules/Webforms/settings/actions/Save.php +++ b/pkg/vtiger/modules/Webforms/settings/actions/Save.php @@ -41,10 +41,12 @@ class Settings_Webforms_Save_Action extends Settings_Vtiger_Index_Action { if (!$fieldValue) { $fieldValue = $fieldModel->get('defaultvalue'); } - if($fieldModel->isMandatory() && empty(trim($fieldValue))) { - throw new AppException(vtranslate('LBL_MANDATORY_FIELD_MISSING')); - }else if($fieldName == 'targetmodule' && !array_key_exists($fieldValue,$supportedModules)){ - throw new Exception('Target module is not supported to create webform'); + $isValueEmpty = is_array($fieldValue) ? false : empty(trim($fieldValue)); /* array in-case of round-robin user list */ + if($fieldModel->isMandatory() && $isValueEmpty){ + $label = vtranslate($fieldModel->get('label'), $qualifiedModuleName); + throw new AppException(vtranslate('LBL_MANDATORY_FIELD_MISSING', 'Vtiger', $label)); + } else if($fieldName == 'targetmodule' && !array_key_exists($fieldValue, $supportedModules)){ + throw new Exception(vtranslate('LBL_TARGET_MODULE_IS_NOT_SUPPORTED_TO_CREATE_WEBFORM', 'Vtiger')); } $recordModel->set($fieldName, $fieldValue); } @@ -57,6 +59,10 @@ class Settings_Webforms_Save_Action extends Settings_Vtiger_Index_Action { $returnUrl = $recordModel->getModule()->getListViewUrl(); $recordModel->set('selectedFieldsData', $request->get('selectedFieldsData')); + $selectedFieldsData = $request->get('selectedFieldsData'); + if (empty($selectedFieldsData)) { + throw new AppException(vtranslate('LBL_MANDATORY_FIELDS_MISSING', 'Vtiger')); + } if (!$recordModel->checkDuplicate()) { $recordModel->save(); $returnUrl = $recordModel->getDetailViewUrl(); @@ -67,4 +73,4 @@ class Settings_Webforms_Save_Action extends Settings_Vtiger_Index_Action { public function validateRequest(Vtiger_Request $request) { $request->validateWriteAccess(); } -} \ No newline at end of file +} diff --git a/vtigerversion.php b/vtigerversion.php index afd5efe912a39f58246b245b6efb80a8850cae8b..576391f7f6a5ef3b7139d0ee09be567ccf4edbd6 100644 --- a/vtigerversion.php +++ b/vtigerversion.php @@ -8,9 +8,9 @@ * All Rights Reserved. ************************************************************************************/ -$patch_version = '20240125'; // -ve timestamp before release, +ve timestamp after release. +$patch_version = '-20240505'; // -ve timestamp before release, +ve timestamp after release. $modified_database = ''; -$vtiger_current_version = '8.1.0'; +$vtiger_current_version = '8.2.0'; $_SESSION['vtiger_version'] = $vtiger_current_version; ?>