Ticket #342: patch-SelectorUtils-preg_match.patch

File patch-SelectorUtils-preg_match.patch, 10.6 KB (added by uwe@…, 3 years ago)
  • classes/phing/types/selectors/SelectorUtils.php

    diff --git a/classes/phing/types/selectors/SelectorUtils.php b/classes/phing/types/selectors/SelectorUtils.php
    index b77dcbf..e1772de 100755
    a b class SelectorUtils { 
    128128     */ 
    129129    public static function matchPath($pattern, $str, $isCaseSensitive = true) { 
    130130     
    131         // When str starts with a DIRECTORY_SEPARATOR, pattern has to start with a 
    132         // DIRECTORY_SEPARATOR. 
    133         // When pattern starts with a DIRECTORY_SEPARATOR, str has to start with a 
    134         // DIRECTORY_SEPARATOR. 
    135         if (StringHelper::startsWith(DIRECTORY_SEPARATOR, $str) !== 
    136             StringHelper::startsWith(DIRECTORY_SEPARATOR, $pattern)) { 
    137             return false; 
    138         } 
    139  
    140         $patDirs = explode(DIRECTORY_SEPARATOR, $pattern); 
    141         $strDirs = explode(DIRECTORY_SEPARATOR, $str); 
    142  
    143         $patIdxStart = 0; 
    144         $patIdxEnd   = count($patDirs)-1; 
    145         $strIdxStart = 0; 
    146         $strIdxEnd   = count($strDirs)-1; 
    147          
    148         // up to first '**' 
    149         while ($patIdxStart <= $patIdxEnd && $strIdxStart <= $strIdxEnd) { 
    150             $patDir = $patDirs[$patIdxStart]; 
    151             if ($patDir == "**") { 
    152                 break; 
    153             } 
    154             if (!self::match($patDir, $strDirs[$strIdxStart], $isCaseSensitive)) { 
    155                 return false; 
    156             } 
    157             $patIdxStart++; 
    158             $strIdxStart++; 
    159         } 
    160         if ($strIdxStart > $strIdxEnd) { 
    161             // String is exhausted 
    162             for ($i=$patIdxStart; $i <= $patIdxEnd; $i++) { 
    163                 if ($patDirs[$i] != "**") { 
    164                     return false; 
    165                 } 
    166             } 
    167             return true; 
    168         } elseif ($patIdxStart > $patIdxEnd) { 
    169             // String not exhausted, but pattern is. Failure. 
    170             return false; 
    171         } 
    172  
    173         // up to last '**' 
    174         while ($patIdxStart <= $patIdxEnd && $strIdxStart <= $strIdxEnd) { 
    175             $patDir = $patDirs[$patIdxEnd]; 
    176             if ($patDir == "**") { 
    177                 break; 
    178             } 
    179             if (!self::match($patDir, $strDirs[$strIdxEnd], $isCaseSensitive)) { 
    180                 return false; 
    181             } 
    182             $patIdxEnd--; 
    183             $strIdxEnd--; 
    184         } 
    185          
    186         if ($strIdxStart > $strIdxEnd) { 
    187             // String is exhausted 
    188             for ($i = $patIdxStart; $i <= $patIdxEnd; $i++) { 
    189                 if ($patDirs[$i] != "**") { 
    190                     return false; 
    191                 } 
    192             } 
    193             return true; 
    194         } 
    195  
    196         while ($patIdxStart != $patIdxEnd && $strIdxStart <= $strIdxEnd) { 
    197             $patIdxTmp = -1; 
    198             for ($i = $patIdxStart+1; $i <= $patIdxEnd; $i++) { 
    199                 if ($patDirs[$i] == "**") { 
    200                     $patIdxTmp = $i; 
    201                     break; 
    202                 } 
    203             } 
    204             if ($patIdxTmp == $patIdxStart+1) { 
    205                 // '**/**' situation, so skip one 
    206                 $patIdxStart++; 
    207                 continue; 
    208             } 
    209             // Find the pattern between padIdxStart & padIdxTmp in str between 
    210             // strIdxStart & strIdxEnd 
    211             $patLength = ($patIdxTmp-$patIdxStart-1); 
    212             $strLength = ($strIdxEnd-$strIdxStart+1); 
    213             $foundIdx  = -1; 
    214  
    215             //strLoop:    (start of outer loop) 
    216             for ($i=0; $i <= $strLength - $patLength; $i++) {                 
    217                 for ($j = 0; $j < $patLength; $j++) { 
    218                     $subPat = $patDirs[$patIdxStart+$j+1]; 
    219                     $subStr = $strDirs[$strIdxStart+$i+$j]; 
    220                     if (!self::match($subPat, $subStr, $isCaseSensitive)) { 
    221                         continue 2; // continue up two levels (to strLoop:) 
    222                     } 
    223                 }                                 
    224                 $foundIdx = $strIdxStart+$i; // only reached if all sub patterns matched 
    225                 break; 
    226             } 
    227  
    228             if ($foundIdx == -1) { 
    229                 return false; 
    230             } 
    231  
    232             $patIdxStart = $patIdxTmp; 
    233             $strIdxStart = $foundIdx + $patLength; 
    234         } 
    235  
    236         for ($i = $patIdxStart; $i <= $patIdxEnd; $i++) { 
    237             if ($patDirs[$i] != "**") { 
    238                 return false; 
    239             } 
    240         } 
    241  
    242         return true; 
     131        $rePattern = preg_quote($pattern, '/'); 
     132        $dirSep = preg_quote(DIRECTORY_SEPARATOR, '/'); 
     133        $rePattern = str_replace(array("\*\*", "\*", "\?"), array('.*', '[^'.$dirSep.']*', '[^'.$dirSep.']'), $rePattern); 
     134        $rePattern = '/^'.$rePattern.'$/'.($isCaseSensitive ? '' : 'i'); 
     135        return preg_match($rePattern, $str); 
    243136    } 
    244137 
    245138    /** 
    class SelectorUtils { 
    261154     */ 
    262155    public static function match($pattern, $str, $isCaseSensitive = true) { 
    263156     
    264         $patArr = StringHelper::toCharArray($pattern); 
    265         $strArr = StringHelper::toCharArray($str); 
    266         $patIdxStart = 0; 
    267         $patIdxEnd   = count($patArr)-1; 
    268         $strIdxStart = 0; 
    269         $strIdxEnd   = count($strArr)-1; 
    270          
    271         $containsStar = false; 
    272         for ($i = 0, $size=count($patArr); $i < $size; $i++) { 
    273             if ($patArr[$i] == '*') { 
    274                 $containsStar = true; 
    275                 break; 
    276             } 
    277         } 
    278  
    279         if (!$containsStar) { 
    280             // No '*'s, so we make a shortcut 
    281             if ($patIdxEnd != $strIdxEnd) { 
    282                 return false; // Pattern and string do not have the same size 
    283             } 
    284             for ($i = 0; $i <= $patIdxEnd; $i++) { 
    285                 $ch = $patArr[$i]; 
    286                 if ($ch != '?') { 
    287                     if ($isCaseSensitive && $ch !== $strArr[$i]) { 
    288                         return false;// Character mismatch 
    289                     } 
    290                     if (!$isCaseSensitive && strtoupper($ch) !== 
    291                         strtoupper($strArr[$i])) { 
    292                         return false; // Character mismatch 
    293                     } 
    294                 } 
    295             } 
    296             return true; // String matches against pattern 
    297         } 
    298  
    299         if ($patIdxEnd == 0) { 
    300             return true; // Pattern contains only '*', which matches anything 
    301         } 
    302  
    303         // Process characters before first star 
    304         while(($ch = $patArr[$patIdxStart]) != '*' && $strIdxStart <= $strIdxEnd) { 
    305             if ($ch != '?') { 
    306                 if ($isCaseSensitive && $ch !== $strArr[$strIdxStart]) { 
    307                     return false;// Character mismatch 
    308                 } 
    309                 if (!$isCaseSensitive && strtoupper($ch) !== 
    310                     strtoupper($strArr[$strIdxStart])) { 
    311                     return false;// Character mismatch 
    312                 } 
    313             } 
    314             $patIdxStart++; 
    315             $strIdxStart++; 
    316         } 
    317          
    318         if ($strIdxStart > $strIdxEnd) { 
    319             // All characters in the string are used. Check if only '*'s are 
    320             // left in the pattern. If so, we succeeded. Otherwise failure. 
    321             for ($i = $patIdxStart; $i <= $patIdxEnd; $i++) { 
    322                 if ($patArr[$i] != '*') { 
    323                     return false; 
    324                 } 
    325             } 
    326             return true; 
    327         } 
    328  
    329         // Process characters after last star 
    330         while(($ch = $patArr[$patIdxEnd]) != '*' && $strIdxStart <= $strIdxEnd) { 
    331             if ($ch != '?') { 
    332                 if ($isCaseSensitive && $ch !== $strArr[$strIdxEnd]) { 
    333                     return false;// Character mismatch 
    334                 } 
    335                 if (!$isCaseSensitive && strtoupper($ch) !== 
    336                     strtoupper($strArr[$strIdxEnd])) { 
    337                     return false;// Character mismatch 
    338                 } 
    339             } 
    340             $patIdxEnd--; 
    341             $strIdxEnd--; 
    342         } 
    343         if ($strIdxStart > $strIdxEnd) { 
    344             // All characters in the string are used. Check if only '*'s are 
    345             // left in the pattern. If so, we succeeded. Otherwise failure. 
    346             for ($i = $patIdxStart; $i <= $patIdxEnd; $i++) { 
    347                 if ($patArr[$i] != '*') { 
    348                     return false; 
    349                 } 
    350             } 
    351             return true; 
    352         } 
    353  
    354         // process pattern between stars. padIdxStart and patIdxEnd point 
    355         // always to a '*'. 
    356         while ($patIdxStart !== $patIdxEnd && $strIdxStart <= $strIdxEnd) { 
    357             $patIdxTmp = -1; 
    358             for ($i = $patIdxStart+1; $i <= $patIdxEnd; $i++) { 
    359                 if ($patArr[$i] == '*') { 
    360                     $patIdxTmp = $i; 
    361                     break; 
    362                 } 
    363             } 
    364             if ($patIdxTmp === $patIdxStart + 1) { 
    365                 // Two stars next to each other, skip the first one. 
    366                 $patIdxStart++; 
    367                 continue; 
    368             } 
    369             // Find the pattern between padIdxStart & padIdxTmp in str between 
    370             // strIdxStart & strIdxEnd 
    371             $patLength = ($patIdxTmp - $patIdxStart - 1); 
    372             $strLength = ($strIdxEnd - $strIdxStart + 1); 
    373             $foundIdx  = -1; 
    374              
    375             //strLoop: 
    376             for ($i = 0; $i <= $strLength - $patLength; $i++) { 
    377                 for ($j = 0; $j < $patLength; $j++) { 
    378                     $ch = $patArr[$patIdxStart+$j+1]; 
    379                     if ($ch != '?') { 
    380                         if ($isCaseSensitive && $ch !== $strArr[$strIdxStart+$i+$j]) { 
    381                                continue 2; //continue to strLoop: 
    382                         } 
    383                         if (!$isCaseSensitive && strtoupper($ch) !== 
    384                             strtoupper($strArr[$strIdxStart+$i+$j])) { 
    385                                continue 2; //continue to strLoop: 
    386                         } 
    387                     } 
    388                 } 
    389                 // only reached if sub loop completed w/o invoking continue 2 
    390                 $foundIdx = $strIdxStart + $i; 
    391                 break; 
    392             } 
    393  
    394             if ($foundIdx == -1) { 
    395                 return false; 
    396             } 
    397  
    398             $patIdxStart = $patIdxTmp; 
    399             $strIdxStart = $foundIdx + $patLength; 
    400         } 
    401  
    402         // All characters in the string are used. Check if only '*'s are left 
    403         // in the pattern. If so, we succeeded. Otherwise failure. 
    404         for ($i = $patIdxStart; $i <= $patIdxEnd; $i++) { 
    405             if ($patArr[$i] != '*') { 
    406                 return false; 
    407             } 
    408         } 
    409         return true; 
     157        $rePattern = preg_quote($pattern, '/'); 
     158        $rePattern = str_replace(array("\*", "\?"), array('.*', '.'), $rePattern); 
     159        $rePattern = '/^'.$rePattern.'$/'.($isCaseSensitive ? '' : 'i'); 
     160        return preg_match($rePattern, $str); 
    410161    } 
    411162 
    412163    /**