Merge pull request #1597 from lcdservices/CRM-13341
[civicrm-core.git] / CRM / Utils / REST.php
index b97d023619401dc90375d481fecab7aa910929af..d09596fe1e6429e91aa9073efd0608e18e8de994 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 /*
    +--------------------------------------------------------------------+
-   | CiviCRM version 4.3                                                |
+   | CiviCRM version 4.4                                                |
    +--------------------------------------------------------------------+
    | Copyright CiviCRM LLC (c) 2004-2013                                |
    +--------------------------------------------------------------------+
@@ -94,6 +94,14 @@ class CRM_Utils_REST {
     return self::output($result);
   }
 
+  function bootAndRun() {
+    $response = $this->loadCMSBootstrap();
+    if (is_array($response)) {
+      return self::output($response);
+    }
+    return $this->run();
+  }
+
   static function output(&$result) {
     $hier = FALSE;
     if (is_scalar($result)) {
@@ -249,16 +257,19 @@ class CRM_Utils_REST {
         return self::error('Unknown function invocation.');
       }
       $store = NULL;
-      
+
       if ($args[1] == 'ping') {
         return self::ping();
       }
+    } else {
+      // or the new format (entity+action)
+      $args = array();
+      $args[0] = 'civicrm';
+      $args[1] = CRM_Utils_array::value('entity', $_REQUEST);
+      $args[2] = CRM_Utils_array::value('action', $_REQUEST);
     }
-    // or the new format (entity+action)
-    $args[1] = CRM_Utils_array::value('entity', $_REQUEST);
-    $args[2] = CRM_Utils_array::value('action', $_REQUEST);
-      
+
+
     // Everyone should be required to provide the server key, so the whole
     //  interface can be disabled in more change to the configuration file.
     // first check for civicrm site key
@@ -367,7 +378,7 @@ class CRM_Utils_REST {
 
     if (array_key_exists('json', $_REQUEST) &&  $_REQUEST['json'][0] == "{") {
       $params = json_decode($_REQUEST['json'], TRUE);
-      if(empty($params)) {
+      if($params === NULL) {
         echo json_encode(array('is_error' => 1, 'error_message', 'Unable to decode supplied JSON.'));
         CRM_Utils_System::civiExit();
       }
@@ -573,38 +584,42 @@ class CRM_Utils_REST {
     CRM_Utils_System::civiExit();
   }
 
+  /**
+   * @return array|NULL NULL if execution should proceed; array if the response is already known
+   */
   function loadCMSBootstrap() {
     $q = CRM_Utils_array::value('q', $_REQUEST);
     $args = explode('/', $q);
 
-    // If the function isn't in the civicrm namespace or request
-    // is for login or ping
-    if (empty($args) || $args[0] != 'civicrm' ||
-      ((count($args) != 3) && ($args[1] != 'login') && ($args[1] != 'ping')) ||
-      $args[1] == 'ping'
-    ) {
-      return;
+    // Proceed with bootstrap for "?entity=X&action=Y"
+    // Proceed with bootstrap for "?q=civicrm/X/Y" but not "?q=civicrm/ping"
+    if (!empty($q)) {
+      if (count($args) == 2 && $args[1] == 'ping') {
+        return NULL; // this is pretty wonky but maybe there's some reason I can't see
+      }
+      if (count($args) != 3) {
+        return self::error('ERROR: Malformed REST path');
+      }
+      if ($args[0] != 'civicrm') {
+        return self::error('ERROR: Malformed REST path');
+      }
+      // Therefore we have reasonably well-formed "?q=civicrm/X/Y"
     }
 
     if (!CRM_Utils_System::authenticateKey(FALSE)) {
-      return;
-    }
-
-    if ($args[1] == 'login') {
-      CRM_Utils_System::loadBootStrap(CRM_Core_DAO::$_nullArray, TRUE, FALSE);
-      return;
+      // FIXME: At time of writing, this doesn't actually do anything because
+      // authenticateKey abends, but that's a bad behavior which sends a
+      // malformed response.
+      return self::error('Failed to authenticate key');
     }
 
     $uid = NULL;
-    $session = CRM_Core_Session::singleton();
-
-    if ($session->get('PHPSESSID') && $session->get('cms_user_id')) {
-      $uid = $session->get('cms_user_id');
-    }
-
     if (!$uid) {
       $store      = NULL;
       $api_key    = CRM_Utils_Request::retrieve('api_key', 'String', $store, FALSE, NULL, 'REQUEST');
+      if (empty($api_key)) {
+        return self::error("FATAL: mandatory param 'api_key' (user key) missing");
+      }
       $contact_id = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $api_key, 'id', 'api_key');
       if ($contact_id) {
         $uid = CRM_Core_BAO_UFMatch::getUFId($contact_id);
@@ -613,11 +628,10 @@ class CRM_Utils_REST {
 
     if ($uid) {
       CRM_Utils_System::loadBootStrap(array('uid' => $uid), TRUE, FALSE);
+      return NULL;
     }
     else {
-      $err = array('error_message' => 'no CMS user associated with given api-key', 'is_error' => 1);
-      echo self::output($err);
-      CRM_Utils_System::civiExit();
+      return self::error('ERROR: No CMS user associated with given api-key');
     }
   }
 }