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.
284 lines
7.4 KiB
284 lines
7.4 KiB
//---[ 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:
|
|
//
|
|
// <email pattern>[@<domain pattern>]
|
|
//
|
|
// The email pattern is expressed as follows:
|
|
//
|
|
// <email pattern> := { * | [*]<email name>[*] }
|
|
//
|
|
// 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:
|
|
//
|
|
// <domain pattern> := [*][<domain name>]
|
|
//
|
|
// 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);
|
|
}
|
|
|