Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

499 lines
15 KiB

  1. #include "wildcard.h" /* prototype verification */
  2. #ifndef TRUE
  3. #define TRUE (1)
  4. #endif
  5. #ifndef FALSE
  6. #define FALSE (0)
  7. #endif
  8. #define WILDCARD '*' /* zero or more of any character */
  9. #define WILDCHAR '?' /* one of any character (does not match END) */
  10. #define END '\0' /* terminal character */
  11. #define DOT '.' /* may be implied at end ("hosts" matches "*.") */
  12. #ifdef STANDALONE
  13. #include <stdio.h>
  14. #include <windows.h>
  15. struct
  16. {
  17. char *String;
  18. char *Pattern;
  19. int Expected;
  20. int ExpectedWithImpliedDots;
  21. }
  22. testcase[] =
  23. {
  24. //
  25. // empty patterns
  26. //
  27. { "", "", TRUE, TRUE },
  28. { "a", "", FALSE, FALSE },
  29. //
  30. // single character patterns
  31. //
  32. { "", "a", FALSE, FALSE },
  33. { "a", "a", TRUE, TRUE },
  34. { "b", "a", FALSE, FALSE },
  35. { "aa", "a", FALSE, FALSE },
  36. { "ab", "a", FALSE, FALSE },
  37. //
  38. // multiple character patterns
  39. //
  40. { "", "aa", FALSE, FALSE },
  41. { "b", "aa", FALSE, FALSE },
  42. { "a", "aa", FALSE, FALSE },
  43. { "ab", "aa", FALSE, FALSE },
  44. { "aa", "aa", TRUE, TRUE },
  45. { "b", "ab", FALSE, FALSE },
  46. { "a", "ab", FALSE, FALSE },
  47. { "ab", "ab", TRUE, TRUE },
  48. { "abc", "ab", FALSE, FALSE },
  49. { "acb", "ab", FALSE, FALSE },
  50. //
  51. // wildchar patterns
  52. //
  53. { "", "?", FALSE, TRUE },
  54. { "a", "?", TRUE, TRUE },
  55. { "", "?a", FALSE, FALSE },
  56. { "a", "?a", FALSE, FALSE },
  57. { "aa", "?a", TRUE, TRUE },
  58. { "ab", "?a", FALSE, FALSE },
  59. { "ba", "?a", TRUE, TRUE },
  60. { "bb", "?a", FALSE, FALSE },
  61. { "aac", "?a", FALSE, FALSE },
  62. { "aba", "?a", FALSE, FALSE },
  63. { "bac", "?a", FALSE, FALSE },
  64. { "bbc", "?a", FALSE, FALSE },
  65. { "", "a?", FALSE, FALSE },
  66. { "a", "a?", FALSE, TRUE },
  67. { "aa", "a?", TRUE, TRUE },
  68. { "ab", "a?", TRUE, TRUE },
  69. { "ba", "a?", FALSE, FALSE },
  70. { "bb", "a?", FALSE, FALSE },
  71. { "aac", "a?", FALSE, FALSE },
  72. { "aba", "a?", FALSE, FALSE },
  73. { "", "a?b", FALSE, FALSE },
  74. { "a", "a?b", FALSE, FALSE },
  75. { "aa", "a?b", FALSE, FALSE },
  76. { "ab", "a?b", FALSE, FALSE },
  77. { "baa", "a?b", FALSE, FALSE },
  78. { "abb", "a?b", TRUE, TRUE },
  79. { "aab", "a?b", TRUE, TRUE },
  80. { "aabc", "a?b", FALSE, FALSE },
  81. { "abc", "a?b", FALSE, FALSE },
  82. { "bab", "a?b", FALSE, FALSE },
  83. { "bbb", "a?b", FALSE, FALSE },
  84. //
  85. // wildcard patterns
  86. //
  87. { "", "*a", FALSE, FALSE },
  88. { "a", "*a", TRUE, TRUE },
  89. { "ba", "*a", TRUE, TRUE },
  90. { "bab", "*ab", TRUE, TRUE },
  91. { "baa", "*ab", FALSE, FALSE },
  92. { "bac", "*ab", FALSE, FALSE },
  93. { "ab", "*ab", TRUE, TRUE },
  94. { "aa", "*ab", FALSE, FALSE },
  95. { "aa", "*ab", FALSE, FALSE },
  96. { "aab", "*ab", TRUE, TRUE },
  97. { "b", "*a", FALSE, FALSE },
  98. { "", "a*", FALSE, FALSE },
  99. { "a", "a*", TRUE, TRUE },
  100. { "ba", "a*", FALSE, FALSE },
  101. { "bab", "a*b", FALSE, FALSE },
  102. { "baa", "a*b", FALSE, FALSE },
  103. { "bac", "a*b", FALSE, FALSE },
  104. { "ab", "a*b", TRUE, TRUE },
  105. { "aa", "a*b", FALSE, FALSE },
  106. { "aa", "a*b", FALSE, FALSE },
  107. { "aab", "a*b", TRUE, TRUE },
  108. { "b", "a*", FALSE, FALSE },
  109. //
  110. // wildcards with false matches
  111. //
  112. { "ab", "*a", FALSE, FALSE },
  113. { "aa", "*a", TRUE, TRUE },
  114. { "baa", "*a", TRUE, TRUE },
  115. //
  116. // mixed wildcard patterns
  117. //
  118. { "", "*?", FALSE, TRUE },
  119. { "a", "*?", TRUE, TRUE },
  120. { "a", "*?a", FALSE, FALSE },
  121. { "aba", "*?a", TRUE, TRUE },
  122. { "ba", "*?a", TRUE, TRUE },
  123. { "ab", "*?b", TRUE, TRUE },
  124. { "", "*", TRUE, TRUE },
  125. { "a", "*", TRUE, TRUE },
  126. { "a", "**", TRUE, TRUE },
  127. { "a", "*?*?", FALSE, TRUE },
  128. { "aa", "*?*?", TRUE, TRUE },
  129. { "aaa", "*?*?", TRUE, TRUE },
  130. { "abbbc", "a*?c", TRUE, TRUE },
  131. //
  132. // Tom's
  133. //
  134. { "abc", "abc", TRUE, TRUE },
  135. { "abcd", "abc", FALSE, FALSE },
  136. { "ab", "abc", FALSE, FALSE },
  137. { "abc", "a?c", TRUE, TRUE },
  138. { "ac", "a?c", FALSE, FALSE },
  139. { "abc", "ab?", TRUE, TRUE },
  140. { "ab", "ab?", FALSE, TRUE },
  141. { "az", "a*z", TRUE, TRUE },
  142. { "abcdefz", "a*z", TRUE, TRUE },
  143. { "ab", "ab*", TRUE, TRUE },
  144. { "abcdefg", "ab*", TRUE, TRUE },
  145. { "ab", "*ab", TRUE, TRUE },
  146. { "abc", "*ab", FALSE, FALSE },
  147. { "123ab", "*ab", TRUE, TRUE },
  148. { "a", "*a*", TRUE, TRUE },
  149. { "123abc", "*a*", TRUE, TRUE },
  150. { "abcdef", "abc*?def", FALSE, FALSE },
  151. { "abcxdef", "abc*?def", TRUE, TRUE },
  152. { "abcxyzdef", "abc*?def", TRUE, TRUE },
  153. { "abc123", "*ab?12*", TRUE, TRUE },
  154. { "abcabc123", "*ab?12*", TRUE, TRUE },
  155. //
  156. // filename handling
  157. //
  158. { "host", "*.", FALSE, TRUE },
  159. { "host.", "*.", TRUE, TRUE },
  160. { "host.s", "*.", FALSE, FALSE },
  161. { "a", "**", TRUE, TRUE },
  162. { "a", "*.", FALSE, TRUE },
  163. { "a", "*?.", FALSE, TRUE },
  164. { "a", "?*.", FALSE, TRUE },
  165. { "a", "*.*", FALSE, TRUE },
  166. { "a", "*.**", FALSE, TRUE },
  167. { "a", "*.*.*", FALSE, FALSE },
  168. { "a.b", "*.*.*", FALSE, FALSE }
  169. };
  170. #define COUNT(a) (sizeof(a) / sizeof(a[0]))
  171. int __cdecl main(int argc, char *argv[])
  172. {
  173. int iCase, iResult;
  174. int fAllowImpliedDot;
  175. char *psz;
  176. //
  177. // run test cases
  178. //
  179. for (iCase = 0; iCase < COUNT(testcase); iCase++)
  180. {
  181. fAllowImpliedDot = TRUE;
  182. for (psz = testcase[iCase].String; *psz != END; psz++)
  183. {
  184. if (*psz == DOT)
  185. {
  186. fAllowImpliedDot = FALSE;
  187. break;
  188. }
  189. }
  190. if (PatternMatch(testcase[iCase].String, testcase[iCase].Pattern, FALSE) !=
  191. testcase[iCase].Expected)
  192. {
  193. printf("PatternMatch() failed: string \"%s\", pattern \"%s\" expected %s (implied=FALSE)\n",
  194. testcase[iCase].String,
  195. testcase[iCase].Pattern,
  196. testcase[iCase].Expected ? "TRUE" : "FALSE");
  197. }
  198. if (PatternMatch(testcase[iCase].String, testcase[iCase].Pattern, fAllowImpliedDot) !=
  199. testcase[iCase].ExpectedWithImpliedDots)
  200. {
  201. printf("PatternMatch() failed: string \"%s\", pattern \"%s\" expected %s (implied=TRUE)\n",
  202. testcase[iCase].String,
  203. testcase[iCase].Pattern,
  204. testcase[iCase].ExpectedWithImpliedDots ? "TRUE" : "FALSE");
  205. }
  206. }
  207. //
  208. // run user cases
  209. //
  210. if (argc > 1)
  211. {
  212. fAllowImpliedDot = TRUE;
  213. for (psz = argv[1]; *psz != END; psz++)
  214. {
  215. if (*psz == DOT)
  216. {
  217. fAllowImpliedDot = FALSE;
  218. break;
  219. }
  220. }
  221. for (iCase = 2; iCase < argc; iCase++)
  222. {
  223. iResult = PatternMatch(argv[1], argv[iCase], FALSE);
  224. printf("string \"%s\", pattern \"%s\" -> %s (implied=FALSE)\n",
  225. argv[1],
  226. argv[iCase],
  227. iResult ? "TRUE" : "FALSE");
  228. if (fAllowImpliedDot)
  229. {
  230. iResult = PatternMatch(argv[1], argv[iCase], fAllowImpliedDot);
  231. printf("string \"%s\", pattern \"%s\" -> %s (implied=TRUE)\n",
  232. argv[1],
  233. argv[iCase],
  234. iResult ? "TRUE" : "FALSE");
  235. }
  236. }
  237. }
  238. return(0);
  239. }
  240. #endif
  241. static int __inline Lower(c)
  242. {
  243. if ((c >= 'A') && (c <= 'Z'))
  244. {
  245. return(c + ('a' - 'A'));
  246. }
  247. else
  248. {
  249. return(c);
  250. }
  251. }
  252. static int __inline CharacterMatch(char chCharacter, char chPattern)
  253. {
  254. if (Lower(chCharacter) == Lower(chPattern))
  255. {
  256. return(TRUE);
  257. }
  258. else
  259. {
  260. return(FALSE);
  261. }
  262. }
  263. int __stdcall PatternMatch(const char *pszString,const char *pszPattern,int fImplyDotAtEnd)
  264. {
  265. /* RECURSIVE */
  266. //
  267. // This function does not deal with 8.3 conventions which might
  268. // be expected for filename comparisons. (In an 8.3 environment,
  269. // "alongfilename.html" would match "alongfil.htm")
  270. //
  271. // This code is NOT MBCS-enabled
  272. //
  273. for ( ; ; )
  274. {
  275. switch (*pszPattern)
  276. {
  277. case END:
  278. //
  279. // Reached end of pattern, so we're done. Matched if
  280. // end of string, no match if more string remains.
  281. //
  282. return(*pszString == END);
  283. case WILDCHAR:
  284. //
  285. // Next in pattern is a wild character, which matches
  286. // anything except end of string. If we reach the end
  287. // of the string, the implied DOT would also match.
  288. //
  289. if (*pszString == END)
  290. {
  291. if (fImplyDotAtEnd == TRUE)
  292. {
  293. fImplyDotAtEnd = FALSE;
  294. }
  295. else
  296. {
  297. return(FALSE);
  298. }
  299. }
  300. else
  301. {
  302. pszString++;
  303. }
  304. pszPattern++;
  305. break;
  306. case WILDCARD:
  307. //
  308. // Next in pattern is a wildcard, which matches anything.
  309. // Find the required character that follows the wildcard,
  310. // and search the string for it. At each occurence of the
  311. // required character, try to match the remaining pattern.
  312. //
  313. // There are numerous equivalent patterns in which multiple
  314. // WILDCARD and WILDCHAR are adjacent. We deal with these
  315. // before our search for the required character.
  316. //
  317. // Each WILDCHAR burns one non-END from the string. An END
  318. // means we have a match. Additional WILDCARDs are ignored.
  319. //
  320. for ( ; ; )
  321. {
  322. pszPattern++;
  323. if (*pszPattern == END)
  324. {
  325. return(TRUE);
  326. }
  327. else if (*pszPattern == WILDCHAR)
  328. {
  329. if (*pszString == END)
  330. {
  331. if (fImplyDotAtEnd == TRUE)
  332. {
  333. fImplyDotAtEnd = FALSE;
  334. }
  335. else
  336. {
  337. return(FALSE);
  338. }
  339. }
  340. else
  341. {
  342. pszString++;
  343. }
  344. }
  345. else if (*pszPattern != WILDCARD)
  346. {
  347. break;
  348. }
  349. }
  350. //
  351. // Now we have a regular character to search the string for.
  352. //
  353. while (*pszString != END)
  354. {
  355. //
  356. // For each match, use recursion to see if the remainder
  357. // of the pattern accepts the remainder of the string.
  358. // If it does not, continue looking for other matches.
  359. //
  360. if (CharacterMatch(*pszString, *pszPattern) == TRUE)
  361. {
  362. if (PatternMatch(pszString + 1, pszPattern + 1, fImplyDotAtEnd) == TRUE)
  363. {
  364. return(TRUE);
  365. }
  366. }
  367. pszString++;
  368. }
  369. //
  370. // Reached end of string without finding required character
  371. // which followed the WILDCARD. If the required character
  372. // is a DOT, consider matching the implied DOT.
  373. //
  374. // Since the remaining string is empty, the only pattern which
  375. // could match after the DOT would be zero or more WILDCARDs,
  376. // so don't bother with recursion.
  377. //
  378. if ((*pszPattern == DOT) && (fImplyDotAtEnd == TRUE))
  379. {
  380. pszPattern++;
  381. while (*pszPattern != END)
  382. {
  383. if (*pszPattern != WILDCARD)
  384. {
  385. return(FALSE);
  386. }
  387. pszPattern++;
  388. }
  389. return(TRUE);
  390. }
  391. //
  392. // Reached end of the string without finding required character.
  393. //
  394. return(FALSE);
  395. break;
  396. default:
  397. //
  398. // Nothing special about the pattern character, so it
  399. // must match source character.
  400. //
  401. if (CharacterMatch(*pszString, *pszPattern) == FALSE)
  402. {
  403. if ((*pszPattern == DOT) &&
  404. (*pszString == END) &&
  405. (fImplyDotAtEnd == TRUE))
  406. {
  407. fImplyDotAtEnd = FALSE;
  408. }
  409. else
  410. {
  411. return(FALSE);
  412. }
  413. }
  414. if (*pszString != END)
  415. {
  416. pszString++;
  417. }
  418. pszPattern++;
  419. }
  420. }
  421. }