//---[ wildmat.cpp ]------------------------------------------------------------- // // Description: // Provides support for a simple wildcard matching mechanism for // matching email addresses. // // Copyright (C) Microsoft Corp. 1997. All Rights Reserved. // // --------------------------------------------------------------------------- // // This stuff is isolated out to simplify unit-testing ... // #include "windows.h" #include "abtype.h" #include "dbgtrace.h" static void pStringLower(LPSTR szString, LPSTR szLowerString) { while (*szString) *szLowerString++ = (CHAR)tolower(*szString++); *szLowerString = '\0'; } // This stuff is from address.hxx #define MAX_EMAIL_NAME 64 #define MAX_DOMAIN_NAME 250 #define MAX_INTERNET_NAME (MAX_EMAIL_NAME + MAX_DOMAIN_NAME + 2) // 2 for @ and \0 // // This is a quick and dirty function to do wildcard matching for email // names. The match is case-insensitive, and the pattern can be expressed as: // // [@] // // The email pattern is expressed as follows: // // := { * | [*][*] } // // Which becomes one of the below: // * - Any email name // foo - Exact match for "foo" // *foo - Any email name ending with "foo", including "foo" // foo* - Any email name beginning with "foo", including "foo" // *foo* - Any email name that contains the string "foo", including "foo" // // If a domain is not specified, the pattern matches against any domain. Both the // email pattern and the domain pattern (if specified) must be matched for the // rule to fire. Domain patterns are expressed as: // // := [*][] // // Which are: // * - Any domain // bar.com - Exact match for "bar.com" // *bar.com - Any domain ending with "bar.com", including "bar.com" // // szEmail must be a string to the email alias (clean without comments, etc.) // szEmailDomain must be a string to the email domain. NULL means no domain // is specified. The domain must be clean without comments, etc. // // typedef enum _WILDMAT_MODES { WMOD_INVALID = 0, WMOD_WILDCARD_LEFT, // Wildcard on the left WMOD_WILDCARD_RIGHT, // Wildcard on the right WMOD_WILDCARD_BOTH, // Wildcard on both sides WMOD_WILDCARD_MAX } WILDMAT_MODES; HRESULT MatchEmailOrDomainName(LPSTR szEmail, LPSTR szEmailDomain, LPSTR szPattern, BOOL fIsEmail) { LPSTR pszPatternDomain; BOOL fEmailWildMat = FALSE; BOOL fDomainWildMat = FALSE; DWORD wmEmailWildMatMode = WMOD_INVALID; DWORD dwEmailLen = 0, dwDomainLen = 0; DWORD dwEmailStemLen = 0, dwDomainStemLen = 0; DWORD i; HRESULT hrRes = S_OK; CHAR szDomainMat[MAX_INTERNET_NAME + 1]; TraceFunctEnterEx((LPARAM)NULL, "MatchEmailOrDomainName"); // This validates that it is a good email name lstrcpyn(szDomainMat, szPattern, MAX_INTERNET_NAME + 1); szPattern = szDomainMat; pszPatternDomain = strchr(szDomainMat, '@'); // See if we have an email wildcard at the left if (*szPattern == '*') { DebugTrace((LPARAM)NULL, "We have a left wildcard"); fEmailWildMat = TRUE; szPattern++; wmEmailWildMatMode = WMOD_WILDCARD_LEFT; } // Get the domain pointer if (szEmailDomain) { dwEmailLen = (DWORD)(szEmailDomain - szEmail); *szEmailDomain++ = '\0'; dwDomainLen = lstrlen(szEmailDomain); } else dwEmailLen = lstrlen(szEmail); // Validate that the lengths of szEmail and szEmailDomain will not // overflow our buffers if (dwEmailLen > MAX_INTERNET_NAME || dwDomainLen > MAX_INTERNET_NAME) { hrRes = E_INVALIDARG; goto Cleanup; } if (pszPatternDomain) { dwEmailStemLen = (DWORD)(pszPatternDomain - szPattern); *pszPatternDomain++ = '\0'; dwDomainStemLen = lstrlen(pszPatternDomain); if (*pszPatternDomain == '*') { fDomainWildMat = TRUE; dwDomainStemLen--; pszPatternDomain++; } } else dwEmailStemLen = lstrlen(szPattern); // See if we have an email wildcard at the right if (dwEmailStemLen && *(szPattern + dwEmailStemLen - 1) == '*') { DebugTrace((LPARAM)NULL, "We have a right wildcard"); szPattern[--dwEmailStemLen] = '\0'; if (!fEmailWildMat) { // It has no left wildcard, so it is a right-only wildcard fEmailWildMat = TRUE; wmEmailWildMatMode = WMOD_WILDCARD_RIGHT; } else wmEmailWildMatMode = WMOD_WILDCARD_BOTH; } // Make sure there are no more wildcards embedded for (i = 0; i < dwEmailStemLen; i++) if (szPattern[i] == '*') { hrRes = ERROR_INVALID_PARAMETER; goto Cleanup; } for (i = 0; i < dwDomainStemLen; i++) if (pszPatternDomain[i] == '*') { hrRes = ERROR_INVALID_PARAMETER; goto Cleanup; } DebugTrace((LPARAM)NULL, "Email = <%s>, Domain = <%s>", szEmail, szEmailDomain?szEmailDomain:"none"); DebugTrace((LPARAM)NULL, "Email = <%s>, Domain = <%s>", szPattern, pszPatternDomain?pszPatternDomain:"none"); // OK, now eliminate by length if (dwEmailLen < dwEmailStemLen) { DebugTrace((LPARAM)NULL, "Email too short to match"); hrRes = S_FALSE; goto Cleanup; } else { if (fEmailWildMat) { CHAR szPatternLower[MAX_INTERNET_NAME + 1]; CHAR szEmailLower[MAX_INTERNET_NAME + 1]; _ASSERT(wmEmailWildMatMode != WMOD_INVALID); _ASSERT(wmEmailWildMatMode < WMOD_WILDCARD_MAX); // Do the right thing based on the wildcard mode switch (wmEmailWildMatMode) { case WMOD_WILDCARD_LEFT: if (lstrcmpi(szPattern, szEmail + (dwEmailLen - dwEmailStemLen))) { DebugTrace((LPARAM)NULL, "Left email wildcard mismatch"); hrRes = S_FALSE; goto Cleanup; } break; case WMOD_WILDCARD_RIGHT: pStringLower(szEmail, szEmailLower); pStringLower(szPattern, szPatternLower); if (strstr(szEmail, szPattern) != szEmail) { DebugTrace((LPARAM)NULL, "Right email wildcard mismatch"); hrRes = S_FALSE; goto Cleanup; } break; case WMOD_WILDCARD_BOTH: pStringLower(szEmail, szEmailLower); pStringLower(szPattern, szPatternLower); if (strstr(szEmail, szPattern) == NULL) { DebugTrace((LPARAM)NULL, "Left and Right email wildcard mismatch"); hrRes = S_FALSE; goto Cleanup; } break; } } else { if ((dwEmailLen != dwEmailStemLen) || (lstrcmpi(szPattern, szEmail))) { DebugTrace((LPARAM)NULL, "Exact email match failed"); hrRes = S_FALSE; goto Cleanup; } } } // We are matching the domain pattern if (pszPatternDomain) { if (!szEmailDomain) { DebugTrace((LPARAM)NULL, "No email domain"); hrRes = S_FALSE; goto Cleanup; } if (dwDomainLen < dwDomainStemLen) { DebugTrace((LPARAM)NULL, "Domain too short to match"); hrRes = S_FALSE; goto Cleanup; } else { if (fDomainWildMat) { if (lstrcmpi(pszPatternDomain, szEmailDomain + (dwDomainLen - dwDomainStemLen))) { DebugTrace((LPARAM)NULL, "Left domain wildcard mismatch"); hrRes = S_FALSE; goto Cleanup; } } else { if ((dwDomainLen != dwDomainStemLen) || (lstrcmpi(pszPatternDomain, szEmailDomain))) { DebugTrace((LPARAM)NULL, "Exact domain match failed"); hrRes = S_FALSE; goto Cleanup; } } } } else hrRes = S_OK; Cleanup: TraceFunctLeaveEx((LPARAM)NULL); return(hrRes); }