CRM-21264 - Fix broken regular expression
authorSean Madsen <sean@seanmadsen.com>
Thu, 15 Mar 2018 14:58:33 +0000 (10:58 -0400)
committerSean Madsen <sean@seanmadsen.com>
Thu, 15 Mar 2018 14:58:33 +0000 (10:58 -0400)
* Escape dot in token since it will be used in a regex (for good
  measure)
* Add `(?![\w-])` to ensure that `td` is not followed by other
  characters that would make it a different element.
* Instead of the first `.+?`, use `((?!</td>).)*` which matches zero or
  more characters but refuses to consume if it encounters `</td>`
* Escape curly braces (for good measure)
* Instead of the second `.+?`, use `.*?` so that it will match if there
  are zero characters. (Note: this change is really the crux of the
  issue, as described in CRM-21264).
* Complete then closing `</td>` (for good measure)

CRM/Contribute/Form/Task/PDFLetterCommon.php

index 321ef460863d94d59cb2487513b456cab1ec509e..f5fdb968c9a63490de6607418340fd1d21ef3aed 100644 (file)
@@ -195,8 +195,8 @@ class CRM_Contribute_Form_Task_PDFLetterCommon extends CRM_Contact_Form_Task_PDF
    * @return bool
    */
   public static function isHtmlTokenInTableCell($token, $entity, $textToSearch) {
-    $tokenToMatch = $entity . '.' . $token;
-    $pattern = '|<td.+?{' . $tokenToMatch . '}.+?</td|si';
+    $tokenToMatch = $entity . '\.' . $token;
+    $pattern = '|<td(?![\w-])((?!</td>).)*\{' . $tokenToMatch . '\}.*?</td>|si';
     $within = preg_match_all($pattern, $textToSearch);
     $total = preg_match_all("|{" . $tokenToMatch . "}|", $textToSearch);
     return ($within == $total);