Line data Source code
1 : /* 2 : Unix SMB/CIFS implementation. 3 : Samba utility functions 4 : Copyright (C) Jeremy Allison 2001 5 : 6 : This program is free software; you can redistribute it and/or modify 7 : it under the terms of the GNU General Public License as published by 8 : the Free Software Foundation; either version 3 of the License, or 9 : (at your option) any later version. 10 : 11 : This program is distributed in the hope that it will be useful, 12 : but WITHOUT ANY WARRANTY; without even the implied warranty of 13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 : GNU General Public License for more details. 15 : 16 : You should have received a copy of the GNU General Public License 17 : along with this program. If not, see <http://www.gnu.org/licenses/>. 18 : */ 19 : 20 : #include "replace.h" 21 : #include <talloc.h> 22 : #include "lib/util/talloc_stack.h" 23 : #include "lib/util/charset/charset.h" 24 : #include "lib/util/unix_match.h" 25 : 26 : /********************************************************* 27 : Recursive routine that is called by unix_wild_match. 28 : *********************************************************/ 29 : 30 8 : static bool unix_do_match(const char *regexp, const char *str) 31 : { 32 0 : const char *p; 33 : 34 48 : for( p = regexp; *p && *str; ) { 35 : 36 44 : switch(*p) { 37 0 : case '?': 38 0 : str++; 39 0 : p++; 40 0 : break; 41 : 42 4 : case '*': 43 : 44 : /* 45 : * Look for a character matching 46 : * the one after the '*'. 47 : */ 48 4 : p++; 49 4 : if(!*p) { 50 0 : return true; /* Automatic match */ 51 : } 52 4 : while(*str) { 53 : 54 40 : while(*str && (*p != *str)) { 55 36 : str++; 56 : } 57 : 58 : /* 59 : * Patch from weidel@multichart.de. 60 : * In the case of the regexp 61 : * '*XX*' we want to ensure there are 62 : * at least 2 'X' characters in the 63 : * string after the '*' for a match to 64 : * be made. 65 : */ 66 : 67 : { 68 4 : int matchcount=0; 69 : 70 : /* 71 : * Eat all the characters that 72 : * match, but count how many 73 : * there were. 74 : */ 75 : 76 6 : while(*str && (*p == *str)) { 77 2 : str++; 78 2 : matchcount++; 79 : } 80 : 81 : /* 82 : * Now check that if the regexp 83 : * had n identical characters 84 : * that matchcount had at least 85 : * that many matches. 86 : */ 87 : 88 4 : while (*(p+1) && (*(p+1)==*p)) { 89 0 : p++; 90 0 : matchcount--; 91 : } 92 : 93 4 : if ( matchcount <= 0 ) { 94 2 : return false; 95 : } 96 : } 97 : 98 : /* 99 : * We've eaten the match char 100 : * after the '*' 101 : */ 102 2 : str--; 103 : 104 2 : if(unix_do_match(p, str)) { 105 2 : return true; 106 : } 107 : 108 0 : if(!*str) { 109 0 : return false; 110 : } else { 111 0 : str++; 112 : } 113 : } 114 0 : return false; 115 : 116 40 : default: 117 40 : if(*str != *p) { 118 0 : return false; 119 : } 120 40 : str++; 121 40 : p++; 122 40 : break; 123 : } 124 : } 125 : 126 4 : if(!*p && !*str) { 127 4 : return true; 128 : } 129 : 130 0 : if (!*p && str[0] == '.' && str[1] == 0) { 131 0 : return true; 132 : } 133 : 134 0 : if (!*str && *p == '?') { 135 0 : while (*p == '?') { 136 0 : p++; 137 : } 138 0 : return(!*p); 139 : } 140 : 141 0 : if(!*str && (*p == '*' && p[1] == '\0')) { 142 0 : return true; 143 : } 144 : 145 0 : return false; 146 : } 147 : 148 : /******************************************************************* 149 : Simple case insensitive interface to a UNIX wildcard matcher. 150 : Returns True if match, False if not. 151 : *******************************************************************/ 152 : 153 6 : bool unix_wild_match(const char *pattern, const char *string) 154 : { 155 6 : TALLOC_CTX *ctx = talloc_stackframe(); 156 0 : char *p2; 157 0 : char *s2; 158 0 : char *p; 159 6 : bool ret = false; 160 : 161 6 : p2 = strlower_talloc(ctx, pattern); 162 6 : s2 = strlower_talloc(ctx, string); 163 6 : if (!p2 || !s2) { 164 0 : TALLOC_FREE(ctx); 165 0 : return false; 166 : } 167 : 168 : /* Remove any *? and ** from the pattern as they are meaningless */ 169 58 : for(p = p2; *p; p++) { 170 52 : while( *p == '*' && (p[1] == '?' ||p[1] == '*')) { 171 0 : memmove(&p[1], &p[2], strlen(&p[2])+1); 172 : } 173 : } 174 : 175 6 : if (p2[0] == '*' && p2[1] == '\0') { 176 0 : TALLOC_FREE(ctx); 177 0 : return true; 178 : } 179 : 180 6 : ret = unix_do_match(p2, s2); 181 6 : TALLOC_FREE(ctx); 182 6 : return ret; 183 : }