| @@ -121,8 +121,32 @@ | ||
| 121 | 121 | { |
| 122 | 122 | return is_scalar($value) ? sanitize_title($value) : ''; |
| 123 | 123 | } |
| 124 | 124 | |
| 125 | + /** | |
| 126 | + * A key is unsafe when it opens a handler, or when it carries a character that | |
| 127 | + * ENDS an attribute name in the HTML tokeniser -- whitespace, quote, slash, | |
| 128 | + * equals or angle bracket. `esc_attr()` leaves those intact, so `x onclick` | |
| 129 | + * renders as two attributes and the second one is live. | |
| 130 | + * | |
| 131 | + * Deny those characters rather than allow-list a charset: an allow-list also | |
| 132 | + * rejects the legal-but-unusual keys real sites carry (leading underscore, | |
| 133 | + * non-Latin names, framework prefixes) and silently drops working markup. | |
| 134 | + * | |
| 135 | + * @param string|int $key | |
| 136 | + * @return bool | |
| 137 | + */ | |
| 138 | + public static function isSafeAttributeKey($key) | |
| 139 | + { | |
| 140 | + $key = (string) $key; | |
| 141 | + | |
| 142 | + if ('' === $key || preg_match('/^on[a-z]/i', $key)) { | |
| 143 | + return false; | |
| 144 | + } | |
| 145 | + | |
| 146 | + return !preg_match('/[\s"\'\/=<>`]|[\x00-\x1F\x7F]/', $key); | |
| 147 | + } | |
| 148 | + | |
| 125 | 149 | /* |
| 126 | 150 | * Keys the whitelist above drops but the editor and Pro Inventory need back. |
| 127 | 151 | * They are sanitized rather than passed through, since preserving unknown |
| 128 | 152 | * keys verbatim would defeat the whitelist for exactly the users this path |
| @@ -329,8 +353,14 @@ | ||
| 329 | 353 | |
| 330 | 354 | return $statuses; |
| 331 | 355 | } |
| 332 | 356 | |
| 357 | + // Statuses a caller may write by hand; add-ons withhold the ones they own as workflow steps. | |
| 358 | + public static function getMutableEntryStatuses($form_id = false, $submission_id = null) | |
| 359 | + { | |
| 360 | + return apply_filters('fluentform/entry_statuses_for_mutation', static::getEntryStatuses($form_id), $form_id, $submission_id); | |
| 361 | + } | |
| 362 | + | |
| 333 | 363 | public static function getReportableInputs() |
| 334 | 364 | { |
| 335 | 365 | $data = [ |
| 336 | 366 | 'select', |
| @@ -1340,9 +1370,9 @@ | ||
| 1340 | 1370 | } |
| 1341 | 1371 | } elseif ('dynamic_field' == $fieldType) { |
| 1342 | 1372 | $dynamicFetchValue = 'yes' == ArrayHelper::get($rawField, 'settings.dynamic_fetch'); |
| 1343 | 1373 | if ($dynamicFetchValue) { |
| 1344 | - $rawField = apply_filters('fluentform/dynamic_field_re_fetch_result_and_resolve_value', $rawField); | |
| 1374 | + $rawField = apply_filters('fluentform/dynamic_field_re_fetch_result_and_resolve_value', $rawField, $form->id); | |
| 1345 | 1375 | } |
| 1346 | 1376 | $dfElementType = ArrayHelper::get($rawField, 'attributes.type'); |
| 1347 | 1377 | if (in_array($dfElementType, ['radio', 'select', 'checkbox'])) { |
| 1348 | 1378 | $fieldType = 'dynamic_field_options'; |