X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=api%2Fv3%2Futils.php;h=f810fcbf42505af0f47c9e5b031f98fe701b0ada;hb=5ba3bfc895f1350346533fd6f0c0087a59dea7ee;hp=93688697c70983bf5df1c852e7780299e0103f90;hpb=9ed4c3c05a8b3d0932a18eabe3be878121cb8d19;p=civicrm-core.git diff --git a/api/v3/utils.php b/api/v3/utils.php index 93688697c7..f810fcbf42 100644 --- a/api/v3/utils.php +++ b/api/v3/utils.php @@ -116,7 +116,9 @@ function civicrm_api3_verify_mandatory($params, $daoName = NULL, $keys = array( } } else { - if (!array_key_exists($key, $params) || empty($params[$key])) { + // Disallow empty values except for the number zero. + // TODO: create a utility for this since it's needed in many places + if (!array_key_exists($key, $params) || (empty($params[$key]) && $params[$key] !== 0 && $params[$key] !== '0')) { $unmatched[] = $key; } } @@ -307,8 +309,13 @@ function _civicrm_api3_get_DAO($name) { */ function _civicrm_api3_get_BAO($name) { $dao = _civicrm_api3_get_DAO($name); - $dao = str_replace("DAO", "BAO", $dao); - return $dao; + if (!$dao) { + return NULL; + } + $bao = str_replace("DAO", "BAO", $dao); + $file = strtr($bao, '_', '/') . '.php'; + // Check if this entity actually has a BAO. Fall back on the DAO if not. + return stream_resolve_include_path($file) ? $bao : $dao; } /** @@ -626,8 +633,8 @@ function _civicrm_api3_get_options_from_params(&$params, $queryObject = FALSE, $ $returnProperties = array_fill_keys($returnProperties, 1); } } - if($entity && $action =='get' ){ - if(CRM_Utils_Array::value('id',$returnProperties)){ + if ($entity && $action =='get') { + if (CRM_Utils_Array::value('id',$returnProperties)) { $returnProperties[$entity . '_id'] = 1; unset($returnProperties['id']); } @@ -639,15 +646,18 @@ function _civicrm_api3_get_options_from_params(&$params, $queryObject = FALSE, $ } } - $options = array( - 'offset' => $offset, - 'sort' => $sort, - 'limit' => $limit, + 'offset' => CRM_Utils_Rule::integer($offset) ? $offset : NULL, + 'sort' => CRM_Utils_Rule::string($sort) ? $sort : NULL, + 'limit' => CRM_Utils_Rule::integer($limit) ? $limit : NULL, 'is_count' => $is_count, 'return' => !empty($returnProperties) ? $returnProperties : NULL, ); + if ($options['sort'] && stristr($options['sort'], 'SELECT')) { + throw new API_Exception('invalid string in sort options'); + } + if (!$queryObject) { return $options; } @@ -662,12 +672,15 @@ function _civicrm_api3_get_options_from_params(&$params, $queryObject = FALSE, $ if (substr($n, 0, 7) == 'return.') { $legacyreturnProperties[substr($n, 7)] = $v; } - elseif($n == 'id'){ + elseif ($n == 'id') { $inputParams[$entity. '_id'] = $v; } elseif (in_array($n, $otherVars)) {} - else{ + else { $inputParams[$n] = $v; + if ($v && !is_array($v) && stristr($v, 'SELECT')) { + throw new API_Exception('invalid string'); + } } } $options['return'] = array_merge($returnProperties, $legacyreturnProperties); @@ -904,7 +917,7 @@ function _civicrm_api3_check_required_fields($params, $daoName, $return = FALSE) * @param $entity string API entity being accessed * @param $action string API action being performed * @param $params array params of the API call - * @param $throw bool whether to throw exception instead of returning false + * @param $throw deprecated bool whether to throw exception instead of returning false * * @throws Exception * @return bool whether the current API user has the permission to make the call @@ -923,16 +936,20 @@ function _civicrm_api3_api_check_permission($entity, $action, &$params, $throw = return TRUE; } - foreach ($permissions as $perm) { - if (!CRM_Core_Permission::check($perm)) { - if ($throw) { - throw new Exception("API permission check failed for $entity/$action call; missing permission: $perm."); - } - else { - return FALSE; + if (!CRM_Core_Permission::check($permissions)) { + if ($throw) { + if(is_array($permissions)) { + $permissions = implode(' and ', $permissions); } + throw new Exception("API permission check failed for $entity/$action call; insufficient permission: require $permissions"); + } + else { + //@todo remove this - this is an internal api function called with $throw set to TRUE. It is only called with false + // in tests & that should be tidied up + return FALSE; } } + return TRUE; } @@ -990,6 +1007,16 @@ function _civicrm_api3_basic_create($bao_name, &$params, $entity = NULL) { if (is_null($bao)) { return civicrm_api3_create_error('Entity not created (' . $fct_name . ')'); } + elseif (is_a($bao, 'CRM_Core_Error')) { + //some wierd circular thing means the error takes itself as an argument + $msg = $bao->getMessages($bao); + // the api deals with entities on a one-by-one basis. However, the contribution bao pushes entities + // onto the error object - presumably because the contribution import is not handling multiple errors correctly + // so we need to reset the error object here to avoid getting concatenated errors + //@todo - the mulitple error handling should be moved out of the contribution object to the import / multiple entity processes + CRM_Core_Error::singleton()->reset(); + throw new API_Exception($msg); + } else { $values = array(); _civicrm_api3_object_to_array($bao, $values[$bao->id]);