Convert existing `X-Requested-With:` guards to `isWebServiceRequest()`
authorTim Otten <totten@civicrm.org>
Fri, 4 Feb 2022 23:34:39 +0000 (15:34 -0800)
committerTim Otten <totten@civicrm.org>
Fri, 4 Feb 2022 23:46:00 +0000 (15:46 -0800)
_Overview_:  `civicrm/ajax/api4` and `returnJsonResponse()` inspect the
web-request to see if it comes via AJAX/REST. If so, the call is
allowed and formatted as JSON. The patch refines the test.

_Before_: `X-Requested-With:` signals that a call is AJAX/REST.

_After_: `X-Requested-With:` still signals that a call is AJAX/REST.
Additionally, if `authx` is enabled, then some requests will be treated as
AJAX/REST based on how they are authenticated (ie `xheader`/`X-Civi-Auth:`
and `param`/`?_authx=` are AJAX/REST).

CRM/Api4/Page/AJAX.php
CRM/Core/Page/AJAX.php

index a368b20c4c8382c54ba3f0818e2393412048e36f..64edf46f44f8039e1dab45fecacc46d6aff23373 100644 (file)
@@ -22,10 +22,7 @@ class CRM_Api4_Page_AJAX extends CRM_Core_Page {
    */
   public function run() {
     $config = CRM_Core_Config::singleton();
-    if (!$config->debug && (!array_key_exists('HTTP_X_REQUESTED_WITH', $_SERVER) ||
-        $_SERVER['HTTP_X_REQUESTED_WITH'] != "XMLHttpRequest"
-      )
-    ) {
+    if (!$config->debug && !CRM_Utils_REST::isWebServiceRequest()) {
       $response = [
         'error_code' => 401,
         'error_message' => "SECURITY ALERT: Ajax requests can only be issued by javascript clients, eg. CRM.api4().",
index 17a0fe8f6ef9e6c86aad5c266646c0cfac6bff29..4f1fd1b6407b1584e0b02bc7baae4977ca3e9dc1 100644 (file)
@@ -167,7 +167,9 @@ class CRM_Core_Page_AJAX {
     $output = json_encode($response);
 
     // CRM-11831 @see http://www.malsup.com/jquery/form/#file-upload
-    if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
+    // COMMENT: Wouldn't the `Accept:` header be more appropriate? Only use `X-Requested-With:` as a
+    // fallback where `Accept:` is missing?
+    if (CRM_Utils_REST::isWebServiceRequest()) {
       CRM_Utils_System::setHttpHeader('Content-Type', 'application/json');
     }
     else {