Minimal check to validate relationship params.
authorMattias Michaux <mattias.michaux@gmail.com>
Wed, 20 Apr 2016 22:44:27 +0000 (00:44 +0200)
committerChris Burgess <chris@giantrobot.co.nz>
Fri, 22 Apr 2016 05:33:47 +0000 (17:33 +1200)
CRM/Contact/Page/AJAX.php
CRM/Core/Page/AJAX.php
CRM/Utils/Rule.php
CRM/Utils/Type.php

index 14336ac4d76684d093078bdd7849ae1ff0f347f3..cd9712308888b583715bb190121d757e30715157 100644 (file)
@@ -1019,23 +1019,7 @@ LIMIT {$offset}, {$rowCount}
       return CRM_Utils_System::permissionDenied();
     }
 
-    $sortMapper = array();
-    foreach ($_GET['columns'] as $key => $value) {
-      $sortMapper[$key] = $value['data'];
-    };
-
-    $offset = isset($_GET['start']) ? CRM_Utils_Type::escape($_GET['start'], 'Integer') : 0;
-    $rowCount = isset($_GET['length']) ? CRM_Utils_Type::escape($_GET['length'], 'Integer') : 25;
-    $sort = isset($_GET['order'][0]['column']) ? CRM_Utils_Array::value(CRM_Utils_Type::escape($_GET['order'][0]['column'], 'Integer'), $sortMapper) : NULL;
-    $sortOrder = isset($_GET['order'][0]['dir']) ? CRM_Utils_Type::escape($_GET['order'][0]['dir'], 'String') : 'asc';
-
-    $params = $_GET;
-    if ($sort && $sortOrder) {
-      $params['sortBy'] = $sort . ' ' . $sortOrder;
-    }
-
-    $params['page'] = ($offset / $rowCount) + 1;
-    $params['rp'] = $rowCount;
+    $params = CRM_Core_Page_AJAX::defaultSortAndPagerParams();
 
     $params['contact_id'] = $contactID;
     $params['context'] = $context;
index 09ca9d0cf1257813515d21a0291ccac343af1ccb..9777e8f5d177a2bc5ac103e347f12b59374e7ba7 100644 (file)
@@ -214,4 +214,28 @@ class CRM_Core_Page_AJAX {
     CRM_Utils_System::setHttpHeader('Cache-Control', "max-age=$ttl, public");
   }
 
+  public static function defaultSortAndPagerParams($defaultOffset = 0, $defaultRowCount = 25, $defaultSort = NULL, $defaultsortOrder = 'asc') {
+    $params = array();
+
+    $sortMapper = array();
+    foreach ($_GET['columns'] as $key => $value) {
+      $sortMapper[$key] = CRM_Utils_Type::escape($value['data'], 'MysqlColumnName');
+    };
+
+    $offset = isset($_GET['start']) ? CRM_Utils_Type::escape($_GET['start'], 'Integer') : $defaultOffset;
+    $rowCount = isset($_GET['length']) ? CRM_Utils_Type::escape($_GET['length'], 'Integer') : $defaultRowCount;
+    // Why is the number of order by columns limited to 1?
+    $sort = isset($_GET['order'][0]['column']) ? CRM_Utils_Array::value(CRM_Utils_Type::escape($_GET['order'][0]['column'], 'Integer'), $sortMapper) : $defaultSort;
+    $sortOrder = isset($_GET['order'][0]['dir']) ? CRM_Utils_Type::escape($_GET['order'][0]['dir'], 'MysqlOrderByDirection') : $defaultsortOrder;
+
+    if ($sort) {
+      $params['sortBy'] = "`{$sort}` {$sortOrder}";
+    }
+
+    $params['page'] = ($offset / $rowCount) + 1;
+    $params['rp'] = $rowCount;
+
+    return $params;
+  }
+
 }
index 97153c51db28fd7084a2e4d8e52f37bc0a9f7de8..d73785fdba293fd4686454b89029c3fed81e52ea 100644 (file)
@@ -87,6 +87,57 @@ class CRM_Utils_Rule {
     return TRUE;
   }
 
+  /**
+   * @param $str
+   *
+   * @return bool
+   */
+  public static function MysqlColumnName($str) {
+    //  check the length.
+    // This check can be incorrect for the <table>.<column> format, which can be
+    // a problem.
+    if (empty($str) || strlen($str) > 64) {
+      return FALSE;
+    }
+
+    return TRUE;
+  }
+
+  /**
+   * @param $str
+   *
+   * @return bool
+   */
+  public static function MysqlColumnNameStrict($str) {
+    //  check the length.
+    if (empty($str) || strlen($str) > 64) {
+      return FALSE;
+    }
+
+    // make sure it only contains valid characters (alphanumeric and underscores)
+    // This check doesn't support the <table>.<column> format, which can be
+    // a problem.
+    // @todo : check with the standards (http://dev.mysql.com/doc/refman/5.5/en/identifiers.html)
+    if (!preg_match('/^[\w_]+$/i', $str)) {
+      return FALSE;
+    }
+
+    return TRUE;
+  }
+
+  /**
+   * @param $str
+   *
+   * @return bool
+   */
+  public static function MysqlOrderByDirection($str) {
+    if (!preg_match('/^(asc|desc)$/i', $str)) {
+      return FALSE;
+    }
+
+    return TRUE;
+  }
+
   /**
    * @param $str
    *
index a7816f7dd2296fbaefc05f9fcd84842c37922ee7..fca08b7e5da63e4913bbc4a982503872e985e26e 100644 (file)
@@ -256,6 +256,24 @@ class CRM_Utils_Type {
         }
         break;
 
+      case 'MysqlColumnName':
+        if (CRM_Utils_Rule::MysqlColumnName($data)) {
+          return str_replace('`', '', $data);
+        }
+        break;
+
+      case 'MysqlColumnNameStrict':
+        if (CRM_Utils_Rule::MysqlColumnNameStrict($data)) {
+          return $data;
+        }
+        break;
+
+      case 'MysqlOrderByDirection':
+        if (CRM_Utils_Rule::MysqlOrderByDirection($data)) {
+          return $data;
+        }
+        break;
+
       default:
         CRM_Core_Error::fatal(
           $type . " is not a recognised (camel cased) data type."