Flexible.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. <?php
  2. /**
  3. * Performs safe variable parsing based on types which can be used by
  4. * users. This may not be able to represent all possible data inputs,
  5. * however.
  6. */
  7. class HTMLPurifier_VarParser_Flexible extends HTMLPurifier_VarParser
  8. {
  9. /**
  10. * @param mixed $var
  11. * @param int $type
  12. * @param bool $allow_null
  13. * @return array|bool|float|int|mixed|null|string
  14. * @throws HTMLPurifier_VarParserException
  15. */
  16. protected function parseImplementation($var, $type, $allow_null)
  17. {
  18. if ($allow_null && $var === null) {
  19. return null;
  20. }
  21. switch ($type) {
  22. // Note: if code "breaks" from the switch, it triggers a generic
  23. // exception to be thrown. Specific errors can be specifically
  24. // done here.
  25. case self::C_MIXED:
  26. case self::ISTRING:
  27. case self::C_STRING:
  28. case self::TEXT:
  29. case self::ITEXT:
  30. return $var;
  31. case self::C_INT:
  32. if (is_string($var) && ctype_digit($var)) {
  33. $var = (int)$var;
  34. }
  35. return $var;
  36. case self::C_FLOAT:
  37. if ((is_string($var) && is_numeric($var)) || is_int($var)) {
  38. $var = (float)$var;
  39. }
  40. return $var;
  41. case self::C_BOOL:
  42. if (is_int($var) && ($var === 0 || $var === 1)) {
  43. $var = (bool)$var;
  44. } elseif (is_string($var)) {
  45. if ($var == 'on' || $var == 'true' || $var == '1') {
  46. $var = true;
  47. } elseif ($var == 'off' || $var == 'false' || $var == '0') {
  48. $var = false;
  49. } else {
  50. throw new HTMLPurifier_VarParserException("Unrecognized value '$var' for $type");
  51. }
  52. }
  53. return $var;
  54. case self::ALIST:
  55. case self::HASH:
  56. case self::LOOKUP:
  57. if (is_string($var)) {
  58. // special case: technically, this is an array with
  59. // a single empty string item, but having an empty
  60. // array is more intuitive
  61. if ($var == '') {
  62. return array();
  63. }
  64. if (strpos($var, "\n") === false && strpos($var, "\r") === false) {
  65. // simplistic string to array method that only works
  66. // for simple lists of tag names or alphanumeric characters
  67. $var = explode(',', $var);
  68. } else {
  69. $var = preg_split('/(,|[\n\r]+)/', $var);
  70. }
  71. // remove spaces
  72. foreach ($var as $i => $j) {
  73. $var[$i] = trim($j);
  74. }
  75. if ($type === self::HASH) {
  76. // key:value,key2:value2
  77. $nvar = array();
  78. foreach ($var as $keypair) {
  79. $c = explode(':', $keypair, 2);
  80. if (!isset($c[1])) {
  81. continue;
  82. }
  83. $nvar[trim($c[0])] = trim($c[1]);
  84. }
  85. $var = $nvar;
  86. }
  87. }
  88. if (!is_array($var)) {
  89. break;
  90. }
  91. $keys = array_keys($var);
  92. if ($keys === array_keys($keys)) {
  93. if ($type == self::ALIST) {
  94. return $var;
  95. } elseif ($type == self::LOOKUP) {
  96. $new = array();
  97. foreach ($var as $key) {
  98. $new[$key] = true;
  99. }
  100. return $new;
  101. } else {
  102. break;
  103. }
  104. }
  105. if ($type === self::ALIST) {
  106. trigger_error("Array list did not have consecutive integer indexes", E_USER_WARNING);
  107. return array_values($var);
  108. }
  109. if ($type === self::LOOKUP) {
  110. foreach ($var as $key => $value) {
  111. if ($value !== true) {
  112. trigger_error(
  113. "Lookup array has non-true value at key '$key'; " .
  114. "maybe your input array was not indexed numerically",
  115. E_USER_WARNING
  116. );
  117. }
  118. $var[$key] = true;
  119. }
  120. }
  121. return $var;
  122. default:
  123. $this->errorInconsistent(__CLASS__, $type);
  124. }
  125. $this->errorGeneric($var, $type);
  126. }
  127. }
  128. // vim: et sw=4 sts=4