| @@ -8,8 +8,9 @@ | ||
| 8 | 8 | |
| 9 | 9 | use BitCode\BitForm\Admin\Form\FrontEndScriptGenerator; |
| 10 | 10 | use BitCode\BitForm\Admin\Form\Helpers; |
| 11 | 11 | use BitCode\BitForm\Admin\Form\Template\TemplateProvider; |
| 12 | +use BitCode\BitForm\Core\Database\FormEntryLogModel; | |
| 12 | 13 | use BitCode\BitForm\Core\Database\FormEntryModel; |
| 13 | 14 | use BitCode\BitForm\Core\Database\FormModel; |
| 14 | 15 | use BitCode\BitForm\Core\Form\FormHandler; |
| 15 | 16 | use BitCode\BitForm\Core\Integration\IntegrationHandler; |
| @@ -16,8 +17,9 @@ | ||
| 16 | 17 | use BitCode\BitForm\Core\Integration\Integrations; |
| 17 | 18 | use BitCode\BitForm\Core\Util\IpTool; |
| 18 | 19 | use BitCode\BitForm\Core\Util\MailConfig; |
| 19 | 20 | use BitCode\BitForm\Core\Util\MetaBoxService; |
| 21 | +use BitCode\BitForm\Core\Util\Utilities; | |
| 20 | 22 | use BitCode\BitForm\Frontend\Form\FrontendFormManager; |
| 21 | 23 | use BitCode\BitForm\GlobalHelper; |
| 22 | 24 | use WP_Error; |
| 23 | 25 | |
| @@ -28,8 +30,10 @@ | ||
| 28 | 30 | add_action('wp_ajax_bitforms_integrations', [$this, 'integrations']); |
| 29 | 31 | add_action('wp_ajax_bitforms_save_connected_integration_apps', [$this, 'saveConnectedIntegrationApps']); |
| 30 | 32 | add_action('wp_ajax_bitforms_get_connected_integration_apps', [$this, 'getConnectedIntegrationApps']); |
| 31 | 33 | add_action('wp_ajax_bitforms_delete_connected_app', [$this, 'deleteConnectedApp']); |
| 34 | + add_action('wp_ajax_bitforms_update_connected_app', [$this, 'updateConnectedApp']); | |
| 35 | + add_action('wp_ajax_bitforms_integration_last_runs', [$this, 'integrationLastRuns']); | |
| 32 | 36 | add_action('wp_ajax_bitforms_update_form', [$this, 'updateForm']); |
| 33 | 37 | add_action('wp_ajax_bitforms_templates', [$this, 'templates']); |
| 34 | 38 | add_action('wp_ajax_bitforms_create_new_form', [$this, 'createNewForm']); |
| 35 | 39 | add_action('wp_ajax_bitforms_save_css', [$this, 'saveCss']); |
| @@ -51,8 +55,9 @@ | ||
| 51 | 55 | add_action('wp_ajax_bitforms_get_all_form', [$this, 'getAllForms']); |
| 52 | 56 | add_action('wp_ajax_bitforms_get_all_wp_pages', [$this, 'getAllWPPages']); |
| 53 | 57 | add_action('wp_ajax_bitforms_delete_success_messsage', [$this, 'deleteSuccessMessage']); |
| 54 | 58 | add_action('wp_ajax_bitforms_delete_integration', [$this, 'deleteAIntegration']); |
| 59 | + add_action('wp_ajax_bitforms_update_integration_status', [$this, 'updateIntegrationStatus']); | |
| 55 | 60 | add_action('wp_ajax_bitforms_delete_workflow', [$this, 'deleteAWorkflow']); |
| 56 | 61 | add_action('wp_ajax_bitforms_delete_mailtemplate', [$this, 'deleteAMailTemplate']); |
| 57 | 62 | add_action('wp_ajax_bitforms_duplicate_mailtemplate', [$this, 'duplicateAMailTemplate']); |
| 58 | 63 | add_action('wp_ajax_bitforms_save_allForm_report_prefs', [$this, 'setAllFormsReport']); |
| @@ -57,9 +62,8 @@ | ||
| 57 | 62 | add_action('wp_ajax_bitforms_duplicate_mailtemplate', [$this, 'duplicateAMailTemplate']); |
| 58 | 63 | add_action('wp_ajax_bitforms_save_allForm_report_prefs', [$this, 'setAllFormsReport']); |
| 59 | 64 | add_action('wp_ajax_bitforms_save_grecaptcha', [$this, 'savegReCaptcha']); |
| 60 | 65 | add_action('wp_ajax_bitforms_form_log_history', [$this, 'getLogHistory']); |
| 61 | - add_action('wp_ajax_bitforms_import_file_data', [$this, 'importFileData']); | |
| 62 | 66 | add_action('wp_ajax_bitforms_filter_export_data', [$this, 'filterExportEntry']); |
| 63 | 67 | add_action('wp_ajax_bitforms_api_key', [$this, 'saveApiKey']); |
| 64 | 68 | add_action('wp_ajax_bitforms_form_helpers_state', [$this, 'builerHelperState']); |
| 65 | 69 | add_action('wp_ajax_bitforms_icn_save_setting', [$this, 'iconUpload']); |
| @@ -110,9 +114,8 @@ | ||
| 110 | 114 | add_action('wp_ajax_bitforms_changelog_version', [$this, 'setChangelogVersion']); |
| 111 | 115 | |
| 112 | 116 | // Notice Options |
| 113 | 117 | add_action('wp_ajax_bitforms_handle_notice', [$this, 'handleNotice']); |
| 114 | - add_action('wp_ajax_bitforms_dismiss_pro_notice', [$this, 'dismissProUpgradeNotice']); | |
| 115 | 118 | |
| 116 | 119 | // conversational |
| 117 | 120 | add_action('wp_ajax_bitforms_save_conversational_css', [$this, 'saveConversationalCSS']); |
| 118 | 121 | |
| @@ -133,9 +136,15 @@ | ||
| 133 | 136 | $this->verifyAdminPermission(); |
| 134 | 137 | $formId = isset($_REQUEST['formID']) ? sanitize_text_field(wp_unslash($_REQUEST['formID'])) : ''; |
| 135 | 138 | |
| 136 | 139 | $FrontendFormManager = FrontendFormManager::getInstance($formId); |
| 140 | + if (!$FrontendFormManager->isExist()) { | |
| 141 | + wp_send_json_error(__('Form is not exists.', 'bit-form'), 404); | |
| 142 | + } | |
| 137 | 143 | $formContent = $FrontendFormManager->getFormContentWithValue(); |
| 144 | + if (!is_object($formContent) || !isset($formContent->fields, $formContent->layout)) { | |
| 145 | + wp_send_json_error(__('Form content is unavailable.', 'bit-form'), 404); | |
| 146 | + } | |
| 138 | 147 | $fields = $formContent->fields; |
| 139 | 148 | $layout = $formContent->layout; |
| 140 | 149 | $file = count($FrontendFormManager->getUploadFields()) > 0 ? $FrontendFormManager->getUploadFields() : false; |
| 141 | 150 | $html = $FrontendFormManager->formView($fields, $file); |
| @@ -290,11 +299,14 @@ | ||
| 290 | 299 | } catch (\InvalidArgumentException $e) { |
| 291 | 300 | wp_send_json_error($e->getMessage(), 400); |
| 292 | 301 | } |
| 293 | 302 | // Nonce verified at handler entry (wp_verify_nonce 'bitforms_save', line 273). |
| 294 | - $appId = isset($_REQUEST['appId']) && $_REQUEST['appId'] | |
| 303 | + $requestedAppId = isset($_REQUEST['appId']) | |
| 295 | 304 | ? sanitize_text_field(wp_unslash($_REQUEST['appId'])) |
| 296 | - : sanitize_text_field(wp_unslash((string) $input->appId)); | |
| 305 | + : ''; | |
| 306 | + $appId = $requestedAppId | |
| 307 | + ? $requestedAppId | |
| 308 | + : sanitize_text_field(wp_unslash((string) ($input->appId ?? ''))); | |
| 297 | 309 | $integrationHandler = Integrations::getInstance(); |
| 298 | 310 | $status = $integrationHandler->deleteConnectedApp($appId); |
| 299 | 311 | if (is_wp_error($status)) { |
| 300 | 312 | wp_send_json_error($status->get_error_message(), 411); |
| @@ -311,8 +323,89 @@ | ||
| 311 | 323 | ); |
| 312 | 324 | } |
| 313 | 325 | } |
| 314 | 326 | |
| 327 | + /** | |
| 328 | + * Renames a connected account (category connected_integration_apps, form_id 0). | |
| 329 | + * Only integration_name is writable; updateIntegration would overwrite the rest. | |
| 330 | + * | |
| 331 | + * @return void | |
| 332 | + */ | |
| 333 | + public function updateConnectedApp() | |
| 334 | + { | |
| 335 | + if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) { | |
| 336 | + $this->verifyAdminPermission(); | |
| 337 | + GlobalHelper::requirePostMethod(); | |
| 338 | + try { | |
| 339 | + $input = GlobalHelper::formatRequestData(); | |
| 340 | + } catch (\InvalidArgumentException $e) { | |
| 341 | + wp_send_json_error($e->getMessage(), 400); | |
| 342 | + } | |
| 343 | + $appId = !empty($input->appId) ? sanitize_text_field((string) $input->appId) : ''; | |
| 344 | + $name = isset($input->name) ? sanitize_text_field((string) $input->name) : ''; | |
| 345 | + if (empty($appId) || '' === trim($name)) { | |
| 346 | + wp_send_json_error(__('Invalid request', 'bit-form'), 400); | |
| 347 | + } | |
| 348 | + $integrations = Integrations::getInstance(); | |
| 349 | + $status = $integrations->renameConnectedApp($appId, $name); | |
| 350 | + if (is_wp_error($status)) { | |
| 351 | + wp_send_json_error($status->get_error_message(), 411); | |
| 352 | + } else { | |
| 353 | + wp_send_json_success($status, 200); | |
| 354 | + } | |
| 355 | + } else { | |
| 356 | + wp_send_json_error( | |
| 357 | + __( | |
| 358 | + 'Token expired', | |
| 359 | + 'bit-form' | |
| 360 | + ), | |
| 361 | + 401 | |
| 362 | + ); | |
| 363 | + } | |
| 364 | + } | |
| 365 | + | |
| 366 | + /** | |
| 367 | + * Last execution per integration of a form, for the integrations list Last Run column. | |
| 368 | + * | |
| 369 | + * @return void | |
| 370 | + */ | |
| 371 | + public function integrationLastRuns() | |
| 372 | + { | |
| 373 | + if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) { | |
| 374 | + $this->verifyAdminPermission(); | |
| 375 | + GlobalHelper::requirePostMethod(); | |
| 376 | + try { | |
| 377 | + $input = GlobalHelper::formatRequestData(); | |
| 378 | + } catch (\InvalidArgumentException $e) { | |
| 379 | + wp_send_json_error($e->getMessage(), 400); | |
| 380 | + } | |
| 381 | + $formID = !empty($input->formID) ? absint($input->formID) : 0; | |
| 382 | + if (empty($formID)) { | |
| 383 | + wp_send_json_error(__('Invalid request', 'bit-form'), 400); | |
| 384 | + } | |
| 385 | + $logModel = new FormEntryLogModel(); | |
| 386 | + $rows = $logModel->getIntegrationLastRuns($formID); | |
| 387 | + if (is_wp_error($rows)) { | |
| 388 | + // result_empty means nothing has run yet, which is a success. Any other | |
| 389 | + // error is a failed query — answering [] would paint every integration | |
| 390 | + // as never executed. Message stays generic: no DB detail to the browser. | |
| 391 | + if ('result_empty' !== $rows->get_error_code()) { | |
| 392 | + wp_send_json_error(__('Could not load integration run history', 'bit-form'), 500); | |
| 393 | + } | |
| 394 | + $rows = []; | |
| 395 | + } | |
| 396 | + wp_send_json_success($rows, 200); | |
| 397 | + } else { | |
| 398 | + wp_send_json_error( | |
| 399 | + __( | |
| 400 | + 'Token expired', | |
| 401 | + 'bit-form' | |
| 402 | + ), | |
| 403 | + 401 | |
| 404 | + ); | |
| 405 | + } | |
| 406 | + } | |
| 407 | + | |
| 315 | 408 | public function templates() |
| 316 | 409 | { |
| 317 | 410 | if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) { |
| 318 | 411 | $this->verifyAdminPermission(); |
| @@ -476,10 +569,14 @@ | ||
| 476 | 569 | // $input = json_decode($inputJSON); |
| 477 | 570 | $input = GlobalHelper::formatRequestData(); |
| 478 | 571 | $optionName = isset($input->optionName) ? $input->optionName : ''; |
| 479 | 572 | $optionValue = isset($input->optionValue) ? $input->optionValue : ''; |
| 480 | - update_option($optionName, $optionValue); | |
| 481 | - wp_send_json_success([$optionName, $optionValue], 200); | |
| 573 | + $allowedNoticeKeys = ['bitforms_hide_cashback', 'bitforms_hide_announcement']; | |
| 574 | + if (!in_array($optionName, $allowedNoticeKeys, true)) { | |
| 575 | + wp_send_json_error(__('Invalid option', 'bit-form'), 400); | |
| 576 | + } | |
| 577 | + update_option($optionName, (bool) $optionValue); | |
| 578 | + wp_send_json_success([$optionName, (bool) $optionValue], 200); | |
| 482 | 579 | } catch (\Exception | \InvalidArgumentException $e) { |
| 483 | 580 | wp_send_json_error($e->getMessage(), 400); |
| 484 | 581 | } |
| 485 | 582 | } else { |
| @@ -492,15 +589,8 @@ | ||
| 492 | 589 | ); |
| 493 | 590 | } |
| 494 | 591 | } |
| 495 | 592 | |
| 496 | - public function dismissProUpgradeNotice() | |
| 497 | - { | |
| 498 | - check_ajax_referer('bitforms_dismiss_pro_notice', 'nonce'); | |
| 499 | - update_user_meta(get_current_user_id(), 'bitforms_dismiss_pro_upgrade_notice', BITFORMS_REQUIRED_BITFORMPRO_VERSION); | |
| 500 | - wp_die(); | |
| 501 | - } | |
| 502 | - | |
| 503 | 593 | private function formatFormContentForUpdate($formContents) |
| 504 | 594 | { |
| 505 | 595 | $updatedFormContents = (object) []; |
| 506 | 596 | $updatedPaths = [ |
| @@ -544,9 +634,9 @@ | ||
| 544 | 634 | } |
| 545 | 635 | |
| 546 | 636 | public function getEmailConfig() |
| 547 | 637 | { |
| 548 | - \ignore_user_abort(); | |
| 638 | + Utilities::ignoreUserAbort(); | |
| 549 | 639 | |
| 550 | 640 | if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) { |
| 551 | 641 | $this->verifyAdminPermission(); |
| 552 | 642 | $ipTool = new IpTool(); |
| @@ -553,8 +643,11 @@ | ||
| 553 | 643 | $user_details = $ipTool->getUserDetail(); |
| 554 | 644 | $integrationHandler = new IntegrationHandler(0, $user_details); |
| 555 | 645 | $user_details = $ipTool->getUserDetail(); |
| 556 | 646 | $formIntegrations = $integrationHandler->getAllIntegration('mail', 'smtp'); |
| 647 | + if (is_wp_error($formIntegrations)) { | |
| 648 | + wp_send_json_error($formIntegrations->get_error_message(), 411); | |
| 649 | + } | |
| 557 | 650 | if (isset($formIntegrations[0]->integration_details) && is_string($formIntegrations[0]->integration_details)) { |
| 558 | 651 | $formIntegrations[0]->integration_details = wp_unslash($formIntegrations[0]->integration_details); |
| 559 | 652 | } |
| 560 | 653 | wp_send_json_success($formIntegrations, 200); |
| @@ -570,9 +663,9 @@ | ||
| 570 | 663 | } |
| 571 | 664 | |
| 572 | 665 | public function saveEmailConfig() |
| 573 | 666 | { |
| 574 | - \ignore_user_abort(); | |
| 667 | + Utilities::ignoreUserAbort(); | |
| 575 | 668 | if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) { |
| 576 | 669 | $this->verifyAdminPermission(); |
| 577 | 670 | GlobalHelper::requirePostMethod(); |
| 578 | 671 | $ipTool = new IpTool(); |
| @@ -808,9 +901,9 @@ | ||
| 808 | 901 | * @return void |
| 809 | 902 | */ |
| 810 | 903 | public function updateForm() |
| 811 | 904 | { |
| 812 | - \ignore_user_abort(); | |
| 905 | + Utilities::ignoreUserAbort(); | |
| 813 | 906 | if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) { |
| 814 | 907 | $this->verifyAdminPermission(); |
| 815 | 908 | GlobalHelper::requirePostMethod(); |
| 816 | 909 | try { |
| @@ -849,9 +942,12 @@ | ||
| 849 | 942 | } catch (\InvalidArgumentException $e) { |
| 850 | 943 | wp_send_json_error($e->getMessage(), 400); |
| 851 | 944 | } |
| 852 | 945 | |
| 853 | - $formId = $input->form_id; | |
| 946 | + $formId = isset($input->form_id) ? sanitize_text_field($input->form_id) : ''; | |
| 947 | + if (!filter_var($formId, FILTER_VALIDATE_INT)) { | |
| 948 | + wp_send_json_error(__('Invalid form id', 'bit-form'), 400); | |
| 949 | + } | |
| 854 | 950 | if (isset($input->atomicCssText)) { |
| 855 | 951 | $status = FrontEndScriptGenerator::saveCssFile($formId, $input->atomicCssText); |
| 856 | 952 | } |
| 857 | 953 | if (isset($input->atomicCssWithFormIdText)) { |
| @@ -1060,9 +1156,9 @@ | ||
| 1060 | 1156 | } |
| 1061 | 1157 | |
| 1062 | 1158 | public function duplicateAForm() |
| 1063 | 1159 | { |
| 1064 | - \ignore_user_abort(); | |
| 1160 | + Utilities::ignoreUserAbort(); | |
| 1065 | 1161 | if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) { |
| 1066 | 1162 | $this->verifyAdminPermission(); |
| 1067 | 1163 | GlobalHelper::requirePostMethod(); |
| 1068 | 1164 | try { |
| @@ -1092,9 +1188,9 @@ | ||
| 1092 | 1188 | } |
| 1093 | 1189 | |
| 1094 | 1190 | public function importAForm() |
| 1095 | 1191 | { |
| 1096 | - \ignore_user_abort(); | |
| 1192 | + Utilities::ignoreUserAbort(); | |
| 1097 | 1193 | if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) { |
| 1098 | 1194 | $this->verifyAdminPermission(); |
| 1099 | 1195 | GlobalHelper::requirePostMethod(); |
| 1100 | 1196 | try { |
| @@ -1373,9 +1469,9 @@ | ||
| 1373 | 1469 | } |
| 1374 | 1470 | |
| 1375 | 1471 | public function updateFormEntry() |
| 1376 | 1472 | { |
| 1377 | - \ignore_user_abort(); | |
| 1473 | + Utilities::ignoreUserAbort(); | |
| 1378 | 1474 | if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) { |
| 1379 | 1475 | $this->verifyAdminPermission(); |
| 1380 | 1476 | $formHandler = FormHandler::getInstance(); |
| 1381 | 1477 | $sanitized_request = [ |
| @@ -1505,8 +1601,36 @@ | ||
| 1505 | 1601 | ); |
| 1506 | 1602 | } |
| 1507 | 1603 | } |
| 1508 | 1604 | |
| 1605 | + public function updateIntegrationStatus() | |
| 1606 | + { | |
| 1607 | + if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) { | |
| 1608 | + $this->verifyAdminPermission(); | |
| 1609 | + GlobalHelper::requirePostMethod(); | |
| 1610 | + try { | |
| 1611 | + $input = GlobalHelper::formatRequestData(); | |
| 1612 | + } catch (\InvalidArgumentException $e) { | |
| 1613 | + wp_send_json_error($e->getMessage(), 400); | |
| 1614 | + } | |
| 1615 | + $formID = isset($input->formID) ? sanitize_text_field(wp_unslash($input->formID)) : ''; | |
| 1616 | + $integrationID = isset($input->id) ? absint($input->id) : 0; | |
| 1617 | + $status = isset($input->status) ? absint($input->status) : 0; | |
| 1618 | + if (empty($formID) || empty($integrationID)) { | |
| 1619 | + wp_send_json_error(__('Invalid request', 'bit-form'), 400); | |
| 1620 | + } | |
| 1621 | + $integrationHandler = new IntegrationHandler($formID); | |
| 1622 | + $result = $integrationHandler->updateIntegrationStatus($integrationID, $status); | |
| 1623 | + if (is_wp_error($result) && 'result_empty' !== $result->get_error_code()) { | |
| 1624 | + wp_send_json_error($result->get_error_message(), 411); | |
| 1625 | + } else { | |
| 1626 | + wp_send_json_success(['id' => $integrationID, 'status' => $status], 200); | |
| 1627 | + } | |
| 1628 | + } else { | |
| 1629 | + wp_send_json_error(__('Token expired', 'bit-form'), 401); | |
| 1630 | + } | |
| 1631 | + } | |
| 1632 | + | |
| 1509 | 1633 | public function deleteAWorkflow() |
| 1510 | 1634 | { |
| 1511 | 1635 | if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) { |
| 1512 | 1636 | $this->verifyAdminPermission(); |
| @@ -1702,9 +1826,13 @@ | ||
| 1702 | 1826 | update_option('bitform_secret_api_key', sanitize_text_field($input->api_key)); |
| 1703 | 1827 | $api_key = $input->api_key; |
| 1704 | 1828 | } |
| 1705 | 1829 | if (!$api_key) { |
| 1706 | - $api_key = hash('sha1', base64_encode(12345)); | |
| 1830 | + // The generated key authenticates the whole bitform/v1 data API. It was | |
| 1831 | + // previously a constant (sha1 of a fixed string), so every install that | |
| 1832 | + // never set one explicitly shared the same secret. Existing stored keys | |
| 1833 | + // are left untouched — only first-time generation changes. | |
| 1834 | + $api_key = wp_generate_password(64, false, false); | |
| 1707 | 1835 | update_option('bitform_secret_api_key', $api_key); |
| 1708 | 1836 | } |
| 1709 | 1837 | wp_send_json_success($api_key, 200); |
| 1710 | 1838 | } else { |
| @@ -1719,9 +1847,11 @@ | ||
| 1719 | 1847 | } |
| 1720 | 1848 | |
| 1721 | 1849 | private function checkExtensionWithURL($urlStr) |
| 1722 | 1850 | { |
| 1723 | - $pattern = '/^https?:\/\/.*(\.(svg|png|jpg|jpeg|gif))?$/i'; | |
| 1851 | + // Extension is mandatory (no optional group): the URL must end in a known image extension, | |
| 1852 | + // otherwise any http(s) URL would pass and be fetched. | |
| 1853 | + $pattern = '/^https?:\/\/.*\.(svg|png|jpg|jpeg|gif)$/i'; | |
| 1724 | 1854 | |
| 1725 | 1855 | return preg_match($pattern, $urlStr); |
| 1726 | 1856 | } |
| 1727 | 1857 | |
| @@ -1755,9 +1885,13 @@ | ||
| 1755 | 1885 | if (!is_dir($icnDir)) { |
| 1756 | 1886 | wp_mkdir_p($icnDir); |
| 1757 | 1887 | } |
| 1758 | 1888 | |
| 1759 | - $imageUrlData = file_get_contents($sanitize_url); | |
| 1889 | + $response = wp_safe_remote_get($sanitize_url); | |
| 1890 | + if (is_wp_error($response) || 200 !== (int) wp_remote_retrieve_response_code($response)) { | |
| 1891 | + wp_send_json_error(__('Unable to fetch icon', 'bit-form'), 400); | |
| 1892 | + } | |
| 1893 | + $imageUrlData = wp_remote_retrieve_body($response); | |
| 1760 | 1894 | |
| 1761 | 1895 | $filename = sanitize_file_name($input->id . '-' . basename($sanitize_url)); |
| 1762 | 1896 | |
| 1763 | 1897 | $validation = wp_check_filetype($filename); |
| @@ -1764,8 +1898,14 @@ | ||
| 1764 | 1898 | $type = $validation['type']; |
| 1765 | 1899 | $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); |
| 1766 | 1900 | $is_svg = 'svg' === $ext; // Check if the file is an SVG |
| 1767 | 1901 | if ($type && 0 === strpos($type, 'image/') || $is_svg) { |
| 1902 | + if ($is_svg) { | |
| 1903 | + $imageUrlData = (new \BitCode\BitForm\enshrined\svgSanitize\Sanitizer())->sanitize($imageUrlData); | |
| 1904 | + if (false === $imageUrlData) { | |
| 1905 | + wp_send_json_error(__('Invalid file type', 'bit-form'), 400); | |
| 1906 | + } | |
| 1907 | + } | |
| 1768 | 1908 | $uploaded = file_put_contents($icnDir . '/' . $filename, $imageUrlData); |
| 1769 | 1909 | |
| 1770 | 1910 | if ($uploaded) { |
| 1771 | 1911 | $uploadedFile = BITFORMS_UPLOAD_BASE_URL . '/' . 'icons' . '/' . $filename; |
| @@ -1956,9 +2096,9 @@ | ||
| 1956 | 2096 | public function getGenerelSettings() |
| 1957 | 2097 | { |
| 1958 | 2098 | if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) { |
| 1959 | 2099 | $this->verifyAdminPermission(); |
| 1960 | - $data = get_option('bitform_app_config', (object) ['cache_plugin' => 0, 'delete_table' => 0]); | |
| 2100 | + $data = get_option('bitform_app_config', (object) ['cache_plugin' => true, 'delete_table' => 0]); | |
| 1961 | 2101 | |
| 1962 | 2102 | if (is_wp_error($data)) { |
| 1963 | 2103 | wp_send_json_error($data->get_error_message(), 411); |
| 1964 | 2104 | } else { |