status check for external case xml files
[civicrm-core.git] / CRM / Utils / String.php
index 8099f23180b20a5666d80f637fec59ad55e24dae..6e53d007768aa88eb6494b239722fc28629f6dd5 100644 (file)
@@ -31,6 +31,9 @@
  * @copyright CiviCRM LLC (c) 2004-2019
  */
 
+use function xKerman\Restricted\unserialize;
+use xKerman\Restricted\UnserializeFailedException;
+
 require_once 'HTML/QuickForm/Rule/Email.php';
 
 /**
@@ -107,12 +110,12 @@ class CRM_Utils_String {
    * @return string
    */
   public static function convertStringToCamel($string) {
-    $map = array(
+    $map = [
       'acl' => 'Acl',
       'ACL' => 'Acl',
       'im' => 'Im',
       'IM' => 'Im',
-    );
+    ];
     if (isset($map[$string])) {
       return $map[$string];
     }
@@ -162,7 +165,7 @@ class CRM_Utils_String {
    *   The last component
    */
   public static function getClassName($string, $char = '_') {
-    $names = array();
+    $names = [];
     if (!is_array($string)) {
       $names = explode($char, $string);
     }
@@ -245,7 +248,7 @@ class CRM_Utils_String {
       return TRUE;
     }
     else {
-      $order = array('ASCII');
+      $order = ['ASCII'];
       if ($utf8) {
         $order[] = 'UTF-8';
       }
@@ -269,7 +272,7 @@ class CRM_Utils_String {
   public static function regex($str, $regexRules) {
     // redact the regular expressions
     if (!empty($regexRules) && isset($str)) {
-      static $matches, $totalMatches, $match = array();
+      static $matches, $totalMatches, $match = [];
       foreach ($regexRules as $pattern => $replacement) {
         preg_match_all($pattern, $str, $matches);
         if (!empty($matches[0])) {
@@ -295,7 +298,7 @@ class CRM_Utils_String {
       }
       return $match;
     }
-    return CRM_Core_DAO::$_nullArray;
+    return [];
   }
 
   /**
@@ -337,7 +340,7 @@ class CRM_Utils_String {
       // iconv('ISO-8859-1', 'UTF-8', $str);
     }
     else {
-      $enc = mb_detect_encoding($str, array('UTF-8'), TRUE);
+      $enc = mb_detect_encoding($str, ['UTF-8'], TRUE);
       return ($enc !== FALSE);
     }
   }
@@ -517,7 +520,7 @@ class CRM_Utils_String {
     $string = trim($string);
 
     $values = explode("\n", $string);
-    $result = array();
+    $result = [];
     foreach ($values as $value) {
       list($n, $v) = CRM_Utils_System::explode('=', $value, 2);
       if (!empty($v)) {
@@ -538,7 +541,7 @@ class CRM_Utils_String {
    *   only the first alternative found (or the text without alternatives)
    */
   public static function stripAlternatives($full) {
-    $matches = array();
+    $matches = [];
     preg_match('/-ALTERNATIVE ITEM 0-(.*?)-ALTERNATIVE ITEM 1-.*-ALTERNATIVE END-/s', $full, $matches);
 
     if (isset($matches[1]) &&
@@ -592,7 +595,7 @@ class CRM_Utils_String {
     }
 
     if ($_searchChars == NULL) {
-      $_searchChars = array(
+      $_searchChars = [
         '&',
         ';',
         ',',
@@ -610,7 +613,7 @@ class CRM_Utils_String {
         "\r\n",
         "\n",
         "\t",
-      );
+      ];
       $_replaceChar = '_';
     }
 
@@ -625,7 +628,6 @@ class CRM_Utils_String {
     return str_replace($search, $replace, $string);
   }
 
-
   /**
    * Use HTMLPurifier to clean up a text string and remove any potential
    * xss attacks. This is primarily used in public facing pages which
@@ -642,6 +644,7 @@ class CRM_Utils_String {
     if (!$_filter) {
       $config = HTMLPurifier_Config::createDefault();
       $config->set('Core.Encoding', 'UTF-8');
+      $config->set('Attr.AllowedFrameTargets', ['_blank', '_self', '_parent', '_top']);
 
       // Disable the cache entirely
       $config->set('Cache.DefinitionImpl', NULL);
@@ -699,10 +702,10 @@ class CRM_Utils_String {
   public static function parsePrefix($delim, $string, $defaultPrefix = NULL) {
     $pos = strpos($string, $delim);
     if ($pos === FALSE) {
-      return array($defaultPrefix, $string);
+      return [$defaultPrefix, $string];
     }
     else {
-      return array(substr($string, 0, $pos), substr($string, 1 + $pos));
+      return [substr($string, 0, $pos), substr($string, 1 + $pos)];
     }
   }
 
@@ -853,10 +856,10 @@ class CRM_Utils_String {
     $port = isset($parts['port']) ? ':' . $parts['port'] : '';
     $path = isset($parts['path']) ? $parts['path'] : '';
     $query = isset($parts['query']) ? '?' . $parts['query'] : '';
-    return array(
+    return [
       'host+port' => "$host$port",
       'path+query' => "$path$query",
-    );
+    ];
   }
 
   /**
@@ -917,7 +920,7 @@ class CRM_Utils_String {
    */
   public static function filterByWildcards($patterns, $allStrings, $allowNew = FALSE) {
     $patterns = (array) $patterns;
-    $result = array();
+    $result = [];
     foreach ($patterns as $pattern) {
       if (!\CRM_Utils_String::endsWith($pattern, '*')) {
         if ($allowNew || in_array($pattern, $allStrings)) {
@@ -936,4 +939,33 @@ class CRM_Utils_String {
     return array_values(array_unique($result));
   }
 
+  /**
+   * Safely unserialize a string of scalar or array values (but not objects!)
+   *
+   * Use `xkerman/restricted-unserialize` to unserialize strings using PHP's
+   * serialization format. `restricted-unserialize` works like PHP's built-in
+   * `unserialize` function except that it does not deserialize object instances,
+   * making it immune to PHP Object Injection {@see https://www.owasp.org/index.php/PHP_Object_Injection}
+   * vulnerabilities.
+   *
+   * Note: When dealing with user inputs, it is generally recommended to use
+   * safe, standard data interchange formats such as JSON rather than PHP's
+   * serialization format when dealing with user input.
+   *
+   * @param string|NULL $string
+   *
+   * @return mixed
+   */
+  public static function unserialize($string) {
+    if (!is_string($string)) {
+      return FALSE;
+    }
+    try {
+      return unserialize($string);
+    }
+    catch (UnserializeFailedException $e) {
+      return FALSE;
+    }
+  }
+
 }