@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Conduit accept int/bool parameters as strings

Summary: Accept Conduit parameter values as strings (e.g. from `curl`) and convert to required type.

Test Plan:
Call conduit method with int/bool parameter iusing `curl` and make sure it does not result in validation error, e.g.
```
$ curl http://$PHABRICATOR_HOST/api/maniphest.search -d api.token=$CONDUIT_TOKEN -d constraints[modifiedEnd]=$(date +%s) -d constraints[hasParents]=true -d limit=1
```

Fixes T10456.

Reviewers: epriestley, #blessed_reviewers

Reviewed By: epriestley, #blessed_reviewers

Subscribers: Korvin

Maniphest Tasks: T10456

Differential Revision: https://secure.phabricator.com/D16694

authored by

Giedrius Dubinskas and committed by
gd
c71bb055 636eaf23

+127 -100
+2 -2
src/applications/conduit/call/ConduitCall.php
··· 15 15 private $request; 16 16 private $user; 17 17 18 - public function __construct($method, array $params) { 18 + public function __construct($method, array $params, $strictly_typed = true) { 19 19 $this->method = $method; 20 20 $this->handler = $this->buildMethodHandler($method); 21 21 ··· 41 41 "'".implode("', '", array_keys($invalid_params))."'")); 42 42 } 43 43 44 - $this->request = new ConduitAPIRequest($params); 44 + $this->request = new ConduitAPIRequest($params, $strictly_typed); 45 45 } 46 46 47 47 public function getAPIRequest() {
+7 -5
src/applications/conduit/controller/PhabricatorConduitAPIController.php
··· 25 25 26 26 try { 27 27 28 - list($metadata, $params) = $this->decodeConduitParams($request, $method); 28 + list($metadata, $params, $strictly_typed) = $this->decodeConduitParams( 29 + $request, 30 + $method); 29 31 30 - $call = new ConduitCall($method, $params); 32 + $call = new ConduitCall($method, $params, $strictly_typed); 31 33 $method_implementation = $call->getMethodImplementation(); 32 34 33 35 $result = null; ··· 638 640 $metadata = idx($params, '__conduit__', array()); 639 641 unset($params['__conduit__']); 640 642 641 - return array($metadata, $params); 643 + return array($metadata, $params, true); 642 644 } 643 645 644 646 // Otherwise, look for a single parameter called 'params' which has the ··· 659 661 $metadata = idx($params, '__conduit__', array()); 660 662 unset($params['__conduit__']); 661 663 662 - return array($metadata, $params); 664 + return array($metadata, $params, true); 663 665 } 664 666 665 667 // If we do not have `params`, assume this is a simple HTTP request with ··· 675 677 } 676 678 } 677 679 678 - return array($metadata, $params); 680 + return array($metadata, $params, false); 679 681 } 680 682 681 683 private function authorizeOAuthMethodAccess(
+3 -11
src/applications/conduit/parametertype/ConduitBoolParameterType.php
··· 3 3 final class ConduitBoolParameterType 4 4 extends ConduitParameterType { 5 5 6 - protected function getParameterValue(array $request, $key) { 7 - $value = parent::getParameterValue($request, $key); 8 - 9 - if (!is_bool($value)) { 10 - $this->raiseValidationException( 11 - $request, 12 - $key, 13 - pht('Expected boolean (true or false), got something else.')); 14 - } 15 - 16 - return $value; 6 + protected function getParameterValue(array $request, $key, $strict) { 7 + $value = parent::getParameterValue($request, $key, $strict); 8 + return $this->parseBoolValue($request, $key, $value, $strict); 17 9 } 18 10 19 11 protected function getParameterTypeName() {
+2 -2
src/applications/conduit/parametertype/ConduitColumnsParameterType.php
··· 3 3 final class ConduitColumnsParameterType 4 4 extends ConduitParameterType { 5 5 6 - protected function getParameterValue(array $request, $key) { 6 + protected function getParameterValue(array $request, $key, $strict) { 7 7 // We don't do any meaningful validation here because the transaction 8 8 // itself validates everything and the input format is flexible. 9 - return parent::getParameterValue($request, $key); 9 + return parent::getParameterValue($request, $key, $strict); 10 10 } 11 11 12 12 protected function getParameterTypeName() {
+3 -9
src/applications/conduit/parametertype/ConduitEpochParameterType.php
··· 3 3 final class ConduitEpochParameterType 4 4 extends ConduitParameterType { 5 5 6 - protected function getParameterValue(array $request, $key) { 7 - $value = parent::getParameterValue($request, $key); 8 - 9 - if (!is_int($value)) { 10 - $this->raiseValidationException( 11 - $request, 12 - $key, 13 - pht('Expected epoch timestamp as integer, got something else.')); 14 - } 6 + protected function getParameterValue(array $request, $key, $strict) { 7 + $value = parent::getParameterValue($request, $key, $strict); 8 + $value = $this->parseIntValue($request, $key, $value, $strict); 15 9 16 10 if ($value <= 0) { 17 11 $this->raiseValidationException(
+3 -11
src/applications/conduit/parametertype/ConduitIntListParameterType.php
··· 3 3 final class ConduitIntListParameterType 4 4 extends ConduitListParameterType { 5 5 6 - protected function getParameterValue(array $request, $key) { 7 - $list = parent::getParameterValue($request, $key); 6 + protected function getParameterValue(array $request, $key, $strict) { 7 + $list = parent::getParameterValue($request, $key, $strict); 8 8 9 9 foreach ($list as $idx => $item) { 10 - if (!is_int($item)) { 11 - $this->raiseValidationException( 12 - $request, 13 - $key, 14 - pht( 15 - 'Expected a list of integers, but item with index "%s" is '. 16 - 'not an integer.', 17 - $idx)); 18 - } 10 + $list[$idx] = $this->parseIntValue($request, $key.'['.$idx.']', $item); 19 11 } 20 12 21 13 return $list;
+3 -11
src/applications/conduit/parametertype/ConduitIntParameterType.php
··· 3 3 final class ConduitIntParameterType 4 4 extends ConduitParameterType { 5 5 6 - protected function getParameterValue(array $request, $key) { 7 - $value = parent::getParameterValue($request, $key); 8 - 9 - if (!is_int($value)) { 10 - $this->raiseValidationException( 11 - $request, 12 - $key, 13 - pht('Expected integer, got something else.')); 14 - } 15 - 16 - return $value; 6 + protected function getParameterValue(array $request, $key, $strict) { 7 + $value = parent::getParameterValue($request, $key, $strict); 8 + return $this->parseIntValue($request, $key, $value, $strict); 17 9 } 18 10 19 11 protected function getParameterTypeName() {
+13 -12
src/applications/conduit/parametertype/ConduitListParameterType.php
··· 14 14 return $this->allowEmptyList; 15 15 } 16 16 17 - protected function getParameterValue(array $request, $key) { 18 - $value = parent::getParameterValue($request, $key); 17 + protected function getParameterValue(array $request, $key, $strict) { 18 + $value = parent::getParameterValue($request, $key, $strict); 19 19 20 20 if (!is_array($value)) { 21 21 $this->raiseValidationException( ··· 48 48 return $value; 49 49 } 50 50 51 - protected function validateStringList(array $request, $key, array $list) { 51 + protected function parseStringList( 52 + array $request, 53 + $key, 54 + array $list, 55 + $strict) { 56 + 52 57 foreach ($list as $idx => $item) { 53 - if (!is_string($item)) { 54 - $this->raiseValidationException( 55 - $request, 56 - $key, 57 - pht( 58 - 'Expected a list of strings, but item with index "%s" is '. 59 - 'not a string.', 60 - $idx)); 61 - } 58 + $list[$idx] = $this->parseStringValue( 59 + $request, 60 + $key.'['.$idx.']', 61 + $item, 62 + $strict); 62 63 } 63 64 64 65 return $list;
+3 -3
src/applications/conduit/parametertype/ConduitPHIDListParameterType.php
··· 3 3 final class ConduitPHIDListParameterType 4 4 extends ConduitListParameterType { 5 5 6 - protected function getParameterValue(array $request, $key) { 7 - $list = parent::getParameterValue($request, $key); 8 - return $this->validateStringList($request, $key, $list); 6 + protected function getParameterValue(array $request, $key, $strict) { 7 + $list = parent::getParameterValue($request, $key, $strict); 8 + return $this->parseStringList($request, $key, $list, $strict); 9 9 } 10 10 11 11 protected function getParameterTypeName() {
+2 -2
src/applications/conduit/parametertype/ConduitPHIDParameterType.php
··· 3 3 final class ConduitPHIDParameterType 4 4 extends ConduitParameterType { 5 5 6 - protected function getParameterValue(array $request, $key) { 7 - $value = parent::getParameterValue($request, $key); 6 + protected function getParameterValue(array $request, $key, $strict) { 7 + $value = parent::getParameterValue($request, $key, $strict); 8 8 9 9 if (!is_string($value)) { 10 10 $this->raiseValidationException(
+50 -3
src/applications/conduit/parametertype/ConduitParameterType.php
··· 30 30 } 31 31 32 32 33 - final public function getValue(array $request, $key) { 33 + final public function getValue(array $request, $key, $strict = true) { 34 34 if (!$this->getExists($request, $key)) { 35 35 return $this->getParameterDefault(); 36 36 } 37 37 38 - return $this->getParameterValue($request, $key); 38 + return $this->getParameterValue($request, $key, $strict); 39 39 } 40 40 41 41 final public function getKeys($key) { ··· 85 85 return array_key_exists($key, $request); 86 86 } 87 87 88 - protected function getParameterValue(array $request, $key) { 88 + protected function getParameterValue(array $request, $key, $strict) { 89 89 return $request[$key]; 90 90 } 91 91 92 92 protected function getParameterKeys($key) { 93 93 return array($key); 94 + } 95 + 96 + protected function parseStringValue(array $request, $key, $value, $strict) { 97 + if (!is_string($value)) { 98 + $this->raiseValidationException( 99 + $request, 100 + $key, 101 + pht('Expected string, got something else.')); 102 + } 103 + return $value; 104 + } 105 + 106 + protected function parseIntValue(array $request, $key, $value, $strict) { 107 + if (!$strict && is_string($value) && ctype_digit($value)) { 108 + $value = $value + 0; 109 + if (!is_int($value)) { 110 + $this->raiseValidationException( 111 + $request, 112 + $key, 113 + pht('Integer overflow.')); 114 + } 115 + } else if (!is_int($value)) { 116 + $this->raiseValidationException( 117 + $request, 118 + $key, 119 + pht('Expected integer, got something else.')); 120 + } 121 + return $value; 122 + } 123 + 124 + protected function parseBoolValue(array $request, $key, $value, $strict) { 125 + $bool_strings = array( 126 + '0' => false, 127 + '1' => true, 128 + 'false' => false, 129 + 'true' => true, 130 + ); 131 + 132 + if (!$strict && is_string($value) && isset($bool_strings[$value])) { 133 + $value = $bool_strings[$value]; 134 + } else if (!is_bool($value)) { 135 + $this->raiseValidationException( 136 + $request, 137 + $key, 138 + pht('Expected boolean (true or false), got something else.')); 139 + } 140 + return $value; 94 141 } 95 142 96 143 abstract protected function getParameterTypeName();
+2 -2
src/applications/conduit/parametertype/ConduitPointsParameterType.php
··· 3 3 final class ConduitPointsParameterType 4 4 extends ConduitParameterType { 5 5 6 - protected function getParameterValue(array $request, $key) { 7 - $value = parent::getParameterValue($request, $key); 6 + protected function getParameterValue(array $request, $key, $strict) { 7 + $value = parent::getParameterValue($request, $key, $strict); 8 8 9 9 if (($value !== null) && !is_numeric($value)) { 10 10 $this->raiseValidationException(
+3 -3
src/applications/conduit/parametertype/ConduitProjectListParameterType.php
··· 3 3 final class ConduitProjectListParameterType 4 4 extends ConduitListParameterType { 5 5 6 - protected function getParameterValue(array $request, $key) { 7 - $list = parent::getParameterValue($request, $key); 8 - $list = $this->validateStringList($request, $key, $list); 6 + protected function getParameterValue(array $request, $key, $strict) { 7 + $list = parent::getParameterValue($request, $key, $strict); 8 + $list = $this->parseStringList($request, $key, $list, $strict); 9 9 return id(new PhabricatorProjectPHIDResolver()) 10 10 ->setViewer($this->getViewer()) 11 11 ->resolvePHIDs($list);
+3 -3
src/applications/conduit/parametertype/ConduitStringListParameterType.php
··· 3 3 final class ConduitStringListParameterType 4 4 extends ConduitListParameterType { 5 5 6 - protected function getParameterValue(array $request, $key) { 7 - $list = parent::getParameterValue($request, $key); 8 - return $this->validateStringList($request, $key, $list); 6 + protected function getParameterValue(array $request, $key, $strict) { 7 + $list = parent::getParameterValue($request, $key, $strict); 8 + return $this->parseStringList($request, $key, $list, $strict); 9 9 } 10 10 11 11 protected function getParameterTypeName() {
+3 -11
src/applications/conduit/parametertype/ConduitStringParameterType.php
··· 3 3 final class ConduitStringParameterType 4 4 extends ConduitParameterType { 5 5 6 - protected function getParameterValue(array $request, $key) { 7 - $value = parent::getParameterValue($request, $key); 8 - 9 - if (!is_string($value)) { 10 - $this->raiseValidationException( 11 - $request, 12 - $key, 13 - pht('Expected string, got something else.')); 14 - } 15 - 16 - return $value; 6 + protected function getParameterValue(array $request, $key, $strict) { 7 + $value = parent::getParameterValue($request, $key, $strict); 8 + return $this->parseStringValue($request, $key, $value, $strict); 17 9 } 18 10 19 11 protected function getParameterTypeName() {
+3 -3
src/applications/conduit/parametertype/ConduitUserListParameterType.php
··· 3 3 final class ConduitUserListParameterType 4 4 extends ConduitListParameterType { 5 5 6 - protected function getParameterValue(array $request, $key) { 7 - $list = parent::getParameterValue($request, $key); 8 - $list = $this->validateStringList($request, $key, $list); 6 + protected function getParameterValue(array $request, $key, $strict) { 7 + $list = parent::getParameterValue($request, $key, $strict); 8 + $list = $this->parseStringList($request, $key, $list, $strict); 9 9 return id(new PhabricatorUserPHIDResolver()) 10 10 ->setViewer($this->getViewer()) 11 11 ->resolvePHIDs($list);
+2 -2
src/applications/conduit/parametertype/ConduitUserParameterType.php
··· 3 3 final class ConduitUserParameterType 4 4 extends ConduitParameterType { 5 5 6 - protected function getParameterValue(array $request, $key) { 7 - $value = parent::getParameterValue($request, $key); 6 + protected function getParameterValue(array $request, $key, $strict) { 7 + $value = parent::getParameterValue($request, $key, $strict); 8 8 9 9 if ($value === null) { 10 10 return null;
+7 -1
src/applications/conduit/protocol/ConduitAPIRequest.php
··· 6 6 private $user; 7 7 private $isClusterRequest = false; 8 8 private $oauthToken; 9 + private $isStrictlyTyped = true; 9 10 10 - public function __construct(array $params) { 11 + public function __construct(array $params, $strictly_typed) { 11 12 $this->params = $params; 13 + $this->isStrictlyTyped = $strictly_typed; 12 14 } 13 15 14 16 public function getValue($key, $default = null) { ··· 66 68 67 69 public function getIsClusterRequest() { 68 70 return $this->isClusterRequest; 71 + } 72 + 73 + public function getIsStrictlyTyped() { 74 + return $this->isStrictlyTyped; 69 75 } 70 76 71 77 public function newContentSource() {
+3 -1
src/applications/search/engine/PhabricatorApplicationSearchEngine.php
··· 1115 1115 continue; 1116 1116 } 1117 1117 1118 - $value = $field->readValueFromConduitRequest($constraints); 1118 + $value = $field->readValueFromConduitRequest( 1119 + $constraints, 1120 + $request->getIsStrictlyTyped()); 1119 1121 $saved_query->setParameter($field->getKey(), $value); 1120 1122 } 1121 1123
+6 -2
src/applications/search/field/PhabricatorSearchField.php
··· 323 323 $this->getConduitKey()); 324 324 } 325 325 326 - public function readValueFromConduitRequest(array $constraints) { 326 + public function readValueFromConduitRequest( 327 + array $constraints, 328 + $strict = true) { 329 + 327 330 return $this->getConduitParameterType()->getValue( 328 331 $constraints, 329 - $this->getConduitKey()); 332 + $this->getConduitKey(), 333 + $strict); 330 334 } 331 335 332 336 public function getValidConstraintKeys() {
+4 -1
src/applications/transactions/editengine/PhabricatorEditEngine.php
··· 1903 1903 $parameter_type->setViewer($viewer); 1904 1904 1905 1905 try { 1906 - $xaction['value'] = $parameter_type->getValue($xaction, 'value'); 1906 + $xaction['value'] = $parameter_type->getValue( 1907 + $xaction, 1908 + 'value', 1909 + $request->getIsStrictlyTyped()); 1907 1910 } catch (Exception $ex) { 1908 1911 throw new PhutilProxyException( 1909 1912 pht(