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.
 
 
 
 
 
 

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);
}