PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 6.2.15
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v6.2.15
6.2.15 6.2.14 6.2.13 6.2.12 6.2.10 6.2.11 6.2.9 6.2.8 6.2.7 6.2.6 6.2.5 6.2.4 6.2.3 6.2.2 3.6.22 3.6.31 3.6.40 3.6.41 3.6.42 3.6.50 3.6.51 3.6.60 3.6.61 3.6.62 3.6.64 All 197 releases
← All changes | app/Services/Settings/SettingsService.php +108 -4 6.2.2 → 6.2.15 View file →
@@ -139,9 +139,9 @@
139 139 'samePageFormBehavior' => 'sanitize_text_field',
140 140 'customUrl' => 'sanitize_url',
141 141 'enabled' => 'rest_sanitize_boolean',
142 142 'numberOfEntries' => 'intval',
143 - 'period' => 'intval',
143 + 'period' => 'sanitize_text_field',
144 144 'limitReachedMsg' => 'sanitize_text_field',
145 145 'start' => 'sanitize_text_field',
146 146 'end' => 'sanitize_text_field',
147 147 'pendingMsg' => 'sanitize_text_field',
@@ -188,8 +188,26 @@
188 188 $valueArray = $value ? json_decode($value, true) : [];
189 189
190 190 $key = sanitize_text_field(Arr::get($attributes, 'meta_key'));
191 191
192 + // SECURITY (FINDING-14): this generic settings store accepted an arbitrary meta_key with no
193 + // allowlist, letting a forms_manager overwrite meta owned by dedicated, capability-gated
194 + // endpoints — most importantly the unfiltered_html-gated custom JS/CSS keys (bypassing the
195 + // boundary Customizer::store() enforces) and payment settings. Reject those keys here; each
196 + // has its own proper route. Filterable so first-party code can extend the protected set.
197 + $protectedKeys = apply_filters('fluentform/protected_form_meta_keys', [
198 + '_custom_form_js',
199 + '_custom_form_css',
200 + '_payment_settings',
201 + ]);
202 + if (in_array($key, $protectedKeys, true)) {
203 + throw new \FluentForm\Framework\Validator\ValidationException('', 422, null, [
204 + 'errors' => [
205 + 'meta_key' => [__('This settings key cannot be modified from this endpoint.', 'fluentform')],
206 + ],
207 + ]);
208 + }
209 +
192 210 if ('formSettings' == $key) {
193 211 Validator::validate(
194 212 'confirmations',
195 213 Arr::get(
@@ -249,11 +267,14 @@
249 267 {
250 268 $conversationalForm = new FluentConversational();
251 269
252 270 return [
253 - 'design_settings' => $conversationalForm->getDesignSettings($formId),
254 - 'meta_settings' => $conversationalForm->getMetaSettings($formId),
255 - 'has_pro' => defined('FLUENTFORMPRO'),
271 + 'design_settings' => $conversationalForm->getDesignSettings($formId),
272 + 'meta_settings' => $conversationalForm->getMetaSettings($formId),
273 + 'form_settings' => Form::getFormsDefaultSettings($formId),
274 + 'pretty_url' => $this->getPrettyUrlSettings($formId),
275 + 'has_pro' => defined('FLUENTFORMPRO'),
276 + 'has_pro_share_page' => $this->hasProSharePage(),
256 277 ];
257 278 }
258 279
259 280 public function storeConversationalDesign($attributes, $formId)
@@ -288,8 +309,15 @@
288 309 if ($meta) {
289 310 FormMeta::persist($formId, $metaKey . '_meta', $meta);
290 311 }
291 312
313 + $prettyUrl = $this->savePrettyUrlSettings(Arr::get($attributes, 'pretty_url'), $formId);
314 +
315 + $formSettings = Arr::get($attributes, 'form_settings');
316 + if (is_array($formSettings) && isset($formSettings['restrictions'])) {
317 + $this->saveFormRestrictions($formId, Arr::get($formSettings, 'restrictions', []));
318 + }
319 +
292 320 $params = [
293 321 'fluent-form' => $formId,
294 322 ];
295 323 if (isset($meta['share_key']) && !empty($meta['share_key'])) {
@@ -299,11 +327,29 @@
299 327 $shareUrl = add_query_arg($params, Helper::getFrontendFacingUrl());
300 328 return [
301 329 'message' => __('Settings successfully updated','fluentform'),
302 330 'share_url' => $shareUrl,
331 + 'pretty_url' => $prettyUrl,
303 332 ];
304 333 }
305 334
335 + public function saveFormRestrictions($formId, $restrictions)
336 + {
337 + $formId = intval($formId);
338 +
339 + if (!is_array($restrictions)) {
340 + return Form::getFormsDefaultSettings($formId);
341 + }
342 +
343 + $existingFormSettings = Form::getFormsDefaultSettings($formId);
344 + $existingFormSettings['restrictions'] = $restrictions;
345 + $existingFormSettings = $this->sanitizeData($existingFormSettings);
346 +
347 + FormMeta::persist($formId, 'formSettings', $existingFormSettings);
348 +
349 + return $existingFormSettings;
350 + }
351 +
306 352 public function getPreset($formId)
307 353 {
308 354 $formId = intval($formId);
309 355 $selectedPreset = Helper::getFormMeta($formId, '_ff_selected_style', 'ffs_default');
@@ -361,6 +407,64 @@
361 407 $clean = wp_strip_all_tags($clean);
362 408 $clean = sanitize_text_field($clean);
363 409
364 410 return trim($clean);
411 + }
412 +
413 + private function hasProSharePage()
414 + {
415 + return defined('FLUENTFORMPRO') && class_exists('\FluentFormPro\classes\SharePage\SharePage');
416 + }
417 +
418 + private function hasProPrettyUrl()
419 + {
420 + return defined('FLUENTFORMPRO') && class_exists('\FluentFormPro\classes\SharePage\FormPrettyUrlService');
421 + }
422 +
423 + private function getPrettyUrlSettings($formId)
424 + {
425 + if (!$this->hasProPrettyUrl()) {
426 + return [
427 + 'available' => false,
428 + 'slug' => '',
429 + 'enabled' => false,
430 + 'pretty_url' => '',
431 + 'base_slug' => 'form',
432 + ];
433 + }
434 +
435 + $service = '\FluentFormPro\classes\SharePage\FormPrettyUrlService';
436 + $slug = $service::getSlug($formId);
437 + if (!$slug) {
438 + $form = Form::find($formId);
439 + $slug = $form ? $service::generateSlug($form->title, $formId) : '';
440 + }
441 +
442 + return [
443 + 'available' => true,
444 + 'slug' => $slug,
445 + 'enabled' => $service::isEnabled($formId),
446 + 'pretty_url' => $service::getFormPrettyUrl($formId),
447 + 'base_slug' => $service::getBaseSlug(),
448 + ];
449 + }
450 +
451 + private function savePrettyUrlSettings($prettyUrl, $formId)
452 + {
453 + if (!is_array($prettyUrl) || !$this->hasProPrettyUrl()) {
454 + return $this->getPrettyUrlSettings($formId);
455 + }
456 +
457 + $service = '\FluentFormPro\classes\SharePage\FormPrettyUrlService';
458 + $slug = sanitize_text_field(Arr::get($prettyUrl, 'slug', ''));
459 + $enabled = Arr::isTrue($prettyUrl, 'enabled');
460 + $savedSlug = $service::saveSlug($formId, $slug, $enabled);
461 +
462 + return [
463 + 'available' => true,
464 + 'slug' => $savedSlug,
465 + 'enabled' => $service::isEnabled($formId),
466 + 'pretty_url' => $service::getFormPrettyUrl($formId),
467 + 'base_slug' => $service::getBaseSlug(),
468 + ];
365 469 }
366 470 }