windows-nt/Source/XPSP1/NT/enduser/netmeeting/ui/conf/callto.cpp
2020-09-26 16:20:57 +08:00

1648 lines
43 KiB
C++

#include "precomp.h"
#include "call.h"
#include "callto.h"
#include "conf.h"
#include "confroom.h"
#include "confpolicies.h"
#include "confutil.h"
#include "nmldap.h"
const int CCallto::s_iMaxCalltoLength = 255;
const int CCallto::s_iMaxAddressLength = 255;
//--------------------------------------------------------------------------//
// CCallto::CCallto. //
//--------------------------------------------------------------------------//
CCallto::CCallto(void):
m_bUnescapedAddressOnly( false ),
m_ulDestination( INADDR_NONE ),
m_bGatekeeperEnabled( false ),
m_pszGatekeeperName( NULL ),
m_ulGatekeeperAddress( INADDR_NONE ),
m_bGatewayEnabled( false ),
m_pszGatewayName( NULL ),
m_ulGatewayAddress( INADDR_NONE ),
m_pszDefaultIlsServerName( NULL ),
m_pszCalltoBuffer( NULL ),
m_pszDisplayName( NULL )
{
} // End of CCallto::CCallto.
//--------------------------------------------------------------------------//
// CCallto::~CCallto. //
//--------------------------------------------------------------------------//
CCallto::~CCallto(void)
{
delete [] m_pszGatekeeperName;
delete [] m_pszGatewayName;
delete [] m_pszDefaultIlsServerName;
delete [] m_pszCalltoBuffer;
delete [] m_pszDisplayName;
} // End of CCallto::~CCallto.
//--------------------------------------------------------------------------//
// CCallto::Callto. //
//--------------------------------------------------------------------------//
HRESULT CCallto::Callto
(
const TCHAR * const pszCallto, // pointer to the callto url to try to place the call with...
const TCHAR * const pszDisplayName, // pointer to the display name to use...
const NM_ADDR_TYPE nmType, // callto type to resolve this callto as...
const bool bAddressOnly, // the pszCallto parameter is to be interpreted as a pre-unescaped addressing component vs a full callto...
const bool * const pbSecurityPreference, // pointer to security preference, NULL for none. must be "compatible" with secure param if present...
const bool bAddToMru, // whether or not save in mru...
const bool bUIEnabled, // whether or not to perform user interaction on errors...
const HWND hwndParent, // if bUIEnabled is true this is the window to parent error/status windows to...
INmCall ** const ppInternalCall // out pointer to INmCall * to receive INmCall * generated by placing call...
){
ASSERT( pszCallto != NULL );
ASSERT( (hwndParent == NULL) || IsWindow( hwndParent ) );
HRESULT hrResult;
// These members need to be reset at the beginning of every call...
m_bUIEnabled = bUIEnabled;
m_hwndParent = hwndParent;
m_ulDestination = INADDR_NONE;
m_bUnescapedAddressOnly = bAddressOnly;
m_pszDisplayName = PszAlloc( pszDisplayName );
m_Parameters.SetParams( NULL ); // Need to reset all parameter settings too...
// Process the callto...
if( (hrResult = Parse( pszCallto )) == S_OK )
{
// Validate that the security specified (if any) is compatible with current NM state.
bool bValidatedSecurity;
if( (hrResult = GetValidatedSecurity( pbSecurityPreference, bValidatedSecurity )) == S_OK )
{
if( (hrResult = Resolve( nmType )) == S_OK )
{
hrResult = PlaceCall( pszCallto, bAddToMru, bValidatedSecurity, ppInternalCall );
}
}
}
if( FAILED( hrResult ) && m_bUIEnabled )
{
DisplayCallError( hrResult, (pszDisplayName != NULL)? pszDisplayName: pszCallto );
}
delete [] m_pszCalltoBuffer;
delete [] m_pszDisplayName;
m_pszCalltoBuffer = NULL;
m_pszDisplayName = NULL;
return( hrResult );
} // End of CCallto::Callto.
//--------------------------------------------------------------------------//
// CCallto::Parse. //
//--------------------------------------------------------------------------//
HRESULT CCallto::Parse
(
const TCHAR * const pszCallto // pointer to the callto url to parse...
){
ASSERT( pszCallto != NULL );
ASSERT( m_ulDestination == INADDR_NONE );
HRESULT hrResult;
if( (m_pszCalltoBuffer = PszAlloc( pszCallto )) == NULL ) // Make a copy that we can modify in place...
{
hrResult = E_OUTOFMEMORY;
}
else if( TrimSzCallto( m_pszCalltoBuffer ) == 0 ) // Remove any leading/trailing blanks...
{
hrResult = NM_CALLERR_PARAM_ERROR; // Entire string was blanks...
}
else
{
hrResult = S_OK;
m_pszParsePos = m_pszCalltoBuffer;
if( !m_bUnescapedAddressOnly )
{
// Skip over "callto:" or "callto://" which mean nothing to us now...
static const TCHAR pszCallto[] = TEXT( "callto:" );
static const TCHAR pszDoubleSlash[] = TEXT( "//" );
if( StrCmpNI_literal( m_pszCalltoBuffer, pszCallto ) )
{
m_pszParsePos = m_pszCalltoBuffer + strlen_literal( pszCallto );
if( StrCmpNI_literal( m_pszParsePos, pszDoubleSlash ) )
{
m_pszParsePos += strlen_literal( pszDoubleSlash );
}
}
int iLength = lstrlen( m_pszCalltoBuffer );
if( m_pszCalltoBuffer[ iLength - 1 ] == '/' )
{
m_pszCalltoBuffer[ iLength - 1 ] = '\0'; // The shell seems to add a trailing slash before calling us...
}
}
// Break the callto into two pieces at the start of the parameters (if any)...
m_pszParameters = StrChr( m_pszCalltoBuffer, '+' );
if( m_pszParameters != NULL )
{
if( m_bUnescapedAddressOnly )
{
// Sorry but '+' not allowed in addressing component...
hrResult = NM_CALLERR_INVALID_ADDRESS;
}
else
{
*m_pszParameters++ = '\0';
}
}
if( hrResult == S_OK )
{
// Make sure we have something left before going on...
if( m_pszParsePos[ 0 ] == '\0' )
{
hrResult = NM_CALLERR_NO_ADDRESS;
}
else
{
// Not really a parsing thing but what we have at this point is conveiniently
// exactly what we want to use for a display name if one wasn't specified so
// save a copy of it before ParseAddress breaks it up into pieces...
if( m_pszDisplayName == NULL )
{
m_pszDisplayName = PszAlloc( m_pszParsePos );
}
if( m_pszParameters != NULL )
{
// Send the parameters off to be parsed...
hrResult = m_Parameters.SetParams( m_pszParameters );
}
if( hrResult == S_OK )
{
// Go parse the addressing component...
hrResult = ParseAddress();
}
}
}
}
return( hrResult );
} // End of CCallto::Parse.
//--------------------------------------------------------------------------//
// CCallto::ParseAddress. //
//--------------------------------------------------------------------------//
HRESULT CCallto::ParseAddress(void)
{
ASSERT( m_pszCalltoBuffer != NULL );
HRESULT hrResult = NM_CALLERR_INVALID_ADDRESS;
if( m_Parameters.GetBooleanParam( TEXT( "h323" ), true ) && inGatekeeperMode() )
{
m_pszAddress = m_pszParsePos;
hrResult = S_OK; // Bless you gatekeeper...
}
else if( StrChr( m_pszParsePos, '=' ) == NULL ) // We're not going to allow the address component to contain an '='...
{
// The address is allowed to be one of these formats...
// (1) string
// (2) server/email
// (3) server:port/email
// This means it may contain at most one ':', at most one '/',
// and given a ':', there must be a following '/'...
TCHAR * const pszColon = StrChr( m_pszParsePos, ':' );
TCHAR * const pszSlash = StrChr( m_pszParsePos, '/' );
if( (pszSlash == NULL) && (pszColon == NULL) )
{
// It's a valid simple (1) string format...
m_pszAddress = m_pszParsePos;
m_pszIlsServer = NULL;
m_uiIlsPort = DEFAULT_LDAP_PORT;
m_pszEmail = m_pszParsePos;
if( m_bUnescapedAddressOnly )
{
hrResult = S_OK; // Done...
}
else
{
// Need to unescape m_pszAddress but not m_pszEmail because it points to the same place...
hrResult = Unescape( m_pszAddress );
}
}
else if( (pszSlash != NULL) && (pszColon == NULL) )
{
if( StrChr( pszSlash + 1, '/' ) == NULL )
{
// No colon and only one slash so it's a valid (2) format
// as long as each side is non zero length...
if( (pszSlash > m_pszParsePos) && (lstrlen( pszSlash ) > 1) )
{
m_pszAddress = TEXT( "" );
m_pszIlsServer = m_pszParsePos;
m_uiIlsPort = DEFAULT_LDAP_PORT;
m_pszEmail = pszSlash + 1;
*pszSlash = '\0';
if( m_bUnescapedAddressOnly )
{
hrResult = S_OK; // Done...
}
else
{
if( (hrResult = Unescape( m_pszIlsServer )) == S_OK )
{
hrResult = Unescape( m_pszEmail );
}
}
}
}
}
else if( (pszSlash != NULL) && (pszColon != NULL) )
{
// Make sure the ':' preceeds the '/' and there's only one of each...
if( (pszColon < pszSlash) && (StrChr( pszSlash + 1, '/') == NULL) && (StrChr( pszColon + 1, ':' ) == NULL) )
{
// One colon and one slash in the correct order so it's a valid (3) format as long
// as all three pieces are non zero length and the port piece is a number...
if( (pszColon > m_pszParsePos) && (pszSlash > pszColon + 1) && (lstrlen( pszSlash ) > 1) )
{
// We're not in gatekeeper mode so break it up into server, port, and email...
m_pszAddress = TEXT( "" );
m_pszIlsServer = m_pszParsePos;
m_pszEmail = pszSlash + 1;
*pszColon = '\0';
*pszSlash = '\0';
if( m_bUnescapedAddressOnly )
{
hrResult = DecimalStringToUINT( pszColon + 1, m_uiIlsPort );
}
else
{
if( (hrResult = Unescape( m_pszIlsServer )) == S_OK )
{
if( (hrResult = Unescape( m_pszEmail )) == S_OK )
{
if( (hrResult = Unescape( pszColon + 1 )) == S_OK )
{
hrResult = DecimalStringToUINT( pszColon + 1, m_uiIlsPort );
}
}
}
}
}
}
}
}
return( hrResult );
} // End of CCallto::ParseAddress.
//--------------------------------------------------------------------------//
// CCallto::Resolve. //
//--------------------------------------------------------------------------//
HRESULT CCallto::Resolve
(
const NM_ADDR_TYPE nmType // callto type to resolve this callto as...
){
HRESULT hrResult;
// First set our address type...
if( (nmType != NM_ADDR_UNKNOWN) && (nmType != NM_ADDR_CALLTO) )
{
m_nmAddressType = nmType;
}
else
{
const TCHAR * const pszType = m_Parameters.GetParam( TEXT( "type" ), NULL );
if( lstrcmpi( pszType, TEXT( "phone" ) ) == 0 )
{
m_nmAddressType = NM_ADDR_ALIAS_E164;
}
else if( lstrcmpi( pszType, TEXT( "ip" ) ) == 0 )
{
m_nmAddressType = NM_ADDR_IP;
}
else if( lstrcmpi( pszType, TEXT( "host" ) ) == 0 )
{
m_nmAddressType = NM_ADDR_MACHINENAME;
}
else if( lstrcmpi( pszType, TEXT( "directory" ) ) == 0 )
{
m_nmAddressType = NM_ADDR_ULS;
}
else
{
m_nmAddressType = NM_ADDR_UNKNOWN;
}
}
// Then see what we should do with it...
if( m_Parameters.GetBooleanParam( TEXT( "h323" ), true ) && inGatekeeperMode() )
{
if (!IsGatekeeperLoggedOn() && !IsGatekeeperLoggingOn())
{
hrResult = NM_CALLERR_NOT_REGISTERED;
}
else
{
// We can always send anything to the gatekeeper for actual resolution...
if( (hrResult = GetGatekeeperIpAddress( m_ulDestination )) == S_OK )
{
if( m_nmAddressType == NM_ADDR_ALIAS_E164 ) // should this also check for NM_ADDR_H323_GATEWAY???
{
CleanupE164StringEx( m_pszAddress );
}
else
{
m_nmAddressType = NM_ADDR_ALIAS_ID;
}
}
}
}
else
{
switch( m_nmAddressType )
{
case NM_ADDR_ALIAS_ID:
{
hrResult = NM_CALLERR_NO_GATEKEEPER;
}
break;
case NM_ADDR_ALIAS_E164:
case NM_ADDR_H323_GATEWAY:
{
if( inGatewayMode() )
{
if( (hrResult = GetGatewayIpAddress( m_ulDestination )) == S_OK )
{
// Explicit phone types are also still resolvable in gateway mode...
CleanupE164StringEx( m_pszAddress );
}
}
else
{
hrResult = NM_CALLERR_NO_PHONE_SUPPORT;
}
}
break;
case NM_ADDR_IP:
{
if( (hrResult = GetIpAddress( m_pszAddress, m_ulDestination )) != S_OK )
{
hrResult = NM_CALLERR_INVALID_IPADDRESS;
}
}
break;
case NM_ADDR_MACHINENAME:
{
if( (hrResult = GetIpAddressFromHostName( m_pszAddress, m_ulDestination )) != S_OK )
{
hrResult = NM_CALLERR_HOST_RESOLUTION_FAILED;
}
}
break;
case NM_ADDR_ULS:
{
// Ils types need to be resolved against an ils...
hrResult = GetIpAddressFromIls( m_ulDestination );
}
break;
default:
{
// If we get here the type was unspecified (Automatic or 2.xx)...
// Our order of precedence is ipaddress,hostname,ils,fail...
// We will not try phone since it didn't explicitly have a phone type...
if( (hrResult = GetIpAddress( m_pszAddress, m_ulDestination )) == S_OK )
{
m_nmAddressType = NM_ADDR_IP;
}
else
{
// It's not a valid ip address so try it next as a host name...
if( (hrResult = GetIpAddressFromHostName( m_pszAddress, m_ulDestination )) == S_OK )
{
m_nmAddressType = NM_ADDR_MACHINENAME;
}
else
{
// It's not a valid host name either so try it finally as an ils lookup...
if ( (hrResult = GetIpAddressFromIls( m_ulDestination )) == S_OK )
{
m_nmAddressType = NM_ADDR_ULS;
}
}
}
}
}
}
return( hrResult );
} // End of CCallto::Resolve.
//--------------------------------------------------------------------------//
// CCallto::PlaceCall. //
//--------------------------------------------------------------------------//
HRESULT CCallto::PlaceCall
(
const TCHAR * const pszCallto, // pointer to the original callto...
const bool bAddToMru, // whether or not save in mru...
const bool bSecure, // whether or not to place the call securely...
INmCall ** const ppInternalCall // out pointer to INmCall * to receive INmCall * generated by placing call...
){
ASSERT( m_ulDestination != INADDR_NONE );
const TCHAR * const pszConferenceName = m_Parameters.GetParam( TEXT( "conference" ), NULL );
const TCHAR * const pszPassword = m_Parameters.GetParam( TEXT( "password" ), NULL );
const bool bH323 = m_Parameters.GetBooleanParam( TEXT( "h323" ), true );
const bool bAV = m_Parameters.GetBooleanParam( TEXT( "av" ), true );
const bool bData = m_Parameters.GetBooleanParam( TEXT( "data" ), true );
const TCHAR * const pszAlias = NULL;
const TCHAR * const pszE164 = NULL;
HRESULT hrResult;
if( IsLocalIpAddress( m_ulDestination ) )
{
// We don't want to go any further if we are attempting to call ourselves...
hrResult = NM_CALLERR_LOOPBACK;
}
else
{
// Map to old style call flags...
DWORD dwCallFlags = 0;
if( pszConferenceName != NULL )
{
dwCallFlags |= CRPCF_JOIN;
}
if( bH323 )
{
dwCallFlags |= CRPCF_H323CC;
}
if( bSecure )
{
dwCallFlags |= CRPCF_SECURE;
}
else if( bAV )
{
if( g_uMediaCaps & (CAPFLAG_RECV_AUDIO | CAPFLAG_SEND_AUDIO) )
{
dwCallFlags |= CRPCF_AUDIO;
}
if( g_uMediaCaps & (CAPFLAG_RECV_VIDEO | CAPFLAG_SEND_VIDEO) )
{
dwCallFlags |= CRPCF_VIDEO;
}
}
if( bData )
{
dwCallFlags |= CRPCF_DATA | CRPCF_T120;
}
if (((CRPCF_T120 | CRPCF_DATA) != (dwCallFlags & (CRPCF_T120 | CRPCF_DATA))) &&
((CRPCF_H323CC | CRPCF_AUDIO) != ( dwCallFlags & (CRPCF_H323CC | CRPCF_AUDIO))) &&
((CRPCF_H323CC | CRPCF_VIDEO) != ( dwCallFlags & (CRPCF_H323CC | CRPCF_VIDEO))))
{
hrResult = NM_CALLERR_UNKNOWN;
}
CConfRoom * pConfRoom = ::GetConfRoom();
ASSERT(pConfRoom);
if (_Module.IsUIActive())
{
pConfRoom->BringToFront();
}
if( !(pConfRoom->GetMeetingPermissions() & NM_PERMIT_OUTGOINGCALLS) )
{
ERROR_OUT( ("CCallto::PlaceCall: meeting setting permissions do not permit outgoing calls...") );
}
else
{
CCall * pCall = new CCall( pszCallto, m_pszDisplayName, m_nmAddressType, bAddToMru, FALSE );
if( pCall == NULL )
{
ERROR_OUT( ("CCallto::PlaceCall: CCall object not created...") );
hrResult = E_OUTOFMEMORY;
}
else
{
pCall->AddRef(); // Protect against another thread canceling this call
IncrementBusyOperations();
{
const TCHAR * pszCallAlias = (m_nmAddressType == NM_ADDR_ULS)? m_pszEmail: m_pszAddress;
const char * const pszDestination = inet_ntoa( *reinterpret_cast<in_addr *>(&m_ulDestination) );
hrResult = pCall->PlaceCall( dwCallFlags, // call flags bit mask, is there a good reason why they're not named?
m_nmAddressType, // address type.
pszDestination, // setup address.
pszDestination, // destination address.
pszCallAlias, // alias.
NULL, // callto url.
pszConferenceName, // conference name.
pszPassword, // conference password.
NULL ); // user data.
}
DecrementBusyOperations();
if( FAILED( hrResult ) && (pCall->GetState() == NM_CALL_INVALID) )
{
// just release the call to free the data
// otherwise wait for the call state to be changed
pCall->Release();
}
if( ppInternalCall )
{
*ppInternalCall = pCall->GetINmCall();
(*ppInternalCall)->AddRef();
}
pCall->Release();
}
}
}
return( hrResult );
} // End of CCallto::PlaceCall.
//--------------------------------------------------------------------------//
// CCallto::GetValidatedSecurity. //
//--------------------------------------------------------------------------//
HRESULT CCallto::GetValidatedSecurity
(
const bool * const pbSecurityPreference, // pointer to security preference, NULL for none. must be "compatible" with secure param if present...
bool & bValidatedSecurity // out bool reference to recieve validated security setting
){
HRESULT hrResult;
// First figure out what security setting is desired...
if( pbSecurityPreference != NULL )
{
// A preference was specified so use it.
bValidatedSecurity = *pbSecurityPreference;
}
else
{
// No preference was specified either so check for secure param
// passing the current system settings to use as the default.
bool bUserAlterable;
bool bDefaultSecurity;
CConfRoom::get_securitySettings( bUserAlterable, bDefaultSecurity );
bValidatedSecurity = m_Parameters.GetBooleanParam( TEXT( "secure" ), bDefaultSecurity );
}
// And then validate that the desired setting is allowed...
int iSecurityPolicy = ConfPolicies::GetSecurityLevel();
if( (bValidatedSecurity && (iSecurityPolicy == DISABLED_POL_SECURITY)) ||
((!bValidatedSecurity) && (iSecurityPolicy == REQUIRED_POL_SECURITY)) )
{
// There was a mismatch between what they want and what they can have...
// Set security to what they can have and return mismatch error...
bValidatedSecurity = (iSecurityPolicy == REQUIRED_POL_SECURITY);
hrResult = NM_CALLERR_SECURITY_MISMATCH;
}
else
{
hrResult = S_OK;
}
return( hrResult );
} // End of CCallto::GetValidatedSecurity.
//--------------------------------------------------------------------------//
// CCallto::inGatekeeperMode. //
//--------------------------------------------------------------------------//
bool CCallto::inGatekeeperMode(void)
{
return(ConfPolicies::CallingMode_GateKeeper == ConfPolicies::GetCallingMode() );
} // End of CCallto::inGatekeeperMode.
//--------------------------------------------------------------------------//
// CCallto::SetGatekeeperEnabled. //
//--------------------------------------------------------------------------//
void CCallto::SetGatekeeperEnabled
(
const bool bEnabled // new Gatekeeper state
){
m_bGatekeeperEnabled = bEnabled;
} // End of CCallto::SetGatekeeperEnabled.
//--------------------------------------------------------------------------//
// CCallto::SetGatekeeperName. //
//--------------------------------------------------------------------------//
HRESULT CCallto::SetGatekeeperName
(
const TCHAR * const pszGatekeeperName // pointer to new Gatekeeper name
){
if( lstrcmpi( pszGatekeeperName, m_pszGatekeeperName ) != 0 )
{
delete [] m_pszGatekeeperName;
m_pszGatekeeperName = PszAlloc( pszGatekeeperName );
m_ulGatekeeperAddress = INADDR_NONE; // We reset this cached value when the name changes...
}
ASSERT( (m_pszGatekeeperName != NULL) || (pszGatekeeperName == NULL) );
return( ((pszGatekeeperName != NULL) && (m_pszGatekeeperName == NULL))? E_OUTOFMEMORY: S_OK );
} // End of CCallto::SetGatekeeperName.
//--------------------------------------------------------------------------//
// CCallto::GetGatekeeperIpAddress. //
//--------------------------------------------------------------------------//
HRESULT CCallto::GetGatekeeperIpAddress
(
unsigned long & ulIpAddress // out unsigned long reference to receive gatekeeper IP address
){
ASSERT( m_pszGatekeeperName != NULL );
if( m_ulGatekeeperAddress == INADDR_NONE )
{
GetIpAddressFromHostName( m_pszGatekeeperName, m_ulGatekeeperAddress );
}
ulIpAddress = m_ulGatekeeperAddress;
return( (m_ulGatekeeperAddress != INADDR_NONE)? S_OK: NM_CALLERR_NO_GATEKEEPER );
} // End of CCallto::GetGatekeeperIpAddress.
//--------------------------------------------------------------------------//
// CCallto::inGatewayMode. //
//--------------------------------------------------------------------------//
bool CCallto::inGatewayMode(void)
{
return( (m_bGatewayEnabled && (m_pszGatewayName != NULL)) || (m_Parameters.GetParam( TEXT( "gateway" ), NULL ) != NULL) );
} // End of CCallto::inGatewayMode.
//--------------------------------------------------------------------------//
// CCallto::SetGatewayEnabled. //
//--------------------------------------------------------------------------//
void CCallto::SetGatewayEnabled
(
const bool bEnabled // new Gateway state
){
m_bGatewayEnabled = bEnabled;
} // End of CCallto::SetGatewayEnabled.
//--------------------------------------------------------------------------//
// CCallto::SetGatewayName. //
//--------------------------------------------------------------------------//
HRESULT CCallto::SetGatewayName
(
const TCHAR * const pszGatewayName // pointer to new Gateway name
){
if( lstrcmpi( pszGatewayName, m_pszGatewayName ) != 0 )
{
delete [] m_pszGatewayName;
m_pszGatewayName = PszAlloc( pszGatewayName );
m_ulGatewayAddress = INADDR_NONE; // We reset this cached value when the name changes...
}
ASSERT( (m_pszGatewayName != NULL) || (pszGatewayName == NULL) );
return( ((pszGatewayName != NULL) && (m_pszGatewayName == NULL))? E_OUTOFMEMORY: S_OK );
} // End of CCallto::SetGatewayName.
//--------------------------------------------------------------------------//
// CCallto::GetGatewayIpAddress. //
//--------------------------------------------------------------------------//
HRESULT CCallto::GetGatewayIpAddress
(
unsigned long & ulIpAddress // out unsigned long reference to receive gateway IP address
){
const TCHAR * const pszGateway = m_Parameters.GetParam( TEXT( "gateway" ), NULL );
if( pszGateway != NULL )
{
// A non-default gateway was specified with this callto...
GetIpAddressFromHostName( pszGateway, ulIpAddress );
}
else
{
if( m_ulGatewayAddress == INADDR_NONE )
{
GetIpAddressFromHostName( m_pszGatewayName, m_ulGatewayAddress );
}
ulIpAddress = m_ulGatewayAddress;
}
return( (ulIpAddress != INADDR_NONE)? S_OK: NM_CALLERR_NO_GATEWAY );
} // End of CCallto::GetGatewayIpAddress.
//--------------------------------------------------------------------------//
// CCallto::SetIlsServerName. //
//--------------------------------------------------------------------------//
HRESULT CCallto::SetIlsServerName
(
const TCHAR * const pszServerName // pointer to new default Ils server name
){
delete [] m_pszDefaultIlsServerName;
m_pszDefaultIlsServerName = PszAlloc( pszServerName );
ASSERT( (m_pszDefaultIlsServerName != NULL) || (pszServerName == NULL) );
return( ((pszServerName != NULL) && (m_pszDefaultIlsServerName == NULL))? E_OUTOFMEMORY: S_OK );
} // End of CCallto::SetIlsServerName.
//--------------------------------------------------------------------------//
// CCallto::GetIpAddressFromIls. //
//--------------------------------------------------------------------------//
HRESULT CCallto::GetIpAddressFromIls
(
unsigned long & ulIpAddress // out unsigned long reference to receive IP address
){
ASSERT( m_pszEmail != NULL );
HRESULT hrResult;
const TCHAR * const pszActiveIlsServer = (m_pszIlsServer != NULL)? m_pszIlsServer: m_pszDefaultIlsServerName;
if( pszActiveIlsServer == NULL )
{
hrResult = NM_CALLERR_NO_ILS;
}
if( g_pLDAP == NULL )
{
g_pLDAP = new CNmLDAP;
}
ASSERT( g_pLDAP != NULL );
if( g_pLDAP == NULL )
{
hrResult = E_OUTOFMEMORY;
}
else
{
TCHAR szIpAddress[ 64 ];
hrResult = g_pLDAP->ResolveUser( m_pszEmail, pszActiveIlsServer, szIpAddress, ARRAY_ELEMENTS( szIpAddress ), m_uiIlsPort );
if( hrResult == S_OK )
{
// Verify that it gave back a good IP address...
hrResult = GetIpAddress( szIpAddress, ulIpAddress );
}
if( hrResult != S_OK )
{
hrResult = NM_CALLERR_ILS_RESOLUTION_FAILED;
}
}
return( hrResult );
} // End of CCallto::GetIpAddressFromIls.
//--------------------------------------------------------------------------//
// CCallto::DoUserValidation //
//--------------------------------------------------------------------------//
bool CCallto::DoUserValidation(const TCHAR * const pszCallto)
{
bool bRet = false;
CCallto callto;
TCHAR szCaption[MAX_PATH];
TCHAR *pszText = NULL;
// Parse input string to retrieve display name
if(FAILED(callto.Parse(pszCallto)))
goto Exit;
// Verify we have a valid display name
if(NULL == callto.m_pszDisplayName)
goto Exit;
// Allocate message buffer. MAX_PATH represents max format string size
pszText = new TCHAR[_tcslen(callto.m_pszDisplayName) + MAX_PATH];
if(NULL == pszText)
goto Exit;
// Compose message string
if(!FLoadString1(IDS_JOIN_PERMISSION, pszText, callto.m_pszDisplayName))
goto Exit;
if(!FLoadString(IDS_MSGBOX_TITLE, szCaption, CCHMAX(szCaption)))
goto Exit;
// Display message box
if(IDOK != MessageBox(NULL, pszText, szCaption, MB_ICONWARNING | MB_OKCANCEL | MB_TOPMOST))
goto Exit;
bRet = true;
Exit:
// Free allocated buffer
if(NULL != pszText)
{
delete [] pszText;
}
return bRet;
}
//--------------------------------------------------------------------------//
// CCalltoParams::CCalltoParams. //
//--------------------------------------------------------------------------//
CCalltoParams::CCalltoParams(void):
m_chNameDelimiter( '+' ),
m_chValueDelimiter( '=' ),
m_pszParams( NULL ),
m_iCount( 0 )
{
} // End of CCalltoParams::CCalltoParams.
//--------------------------------------------------------------------------//
// CCalltoParams::CCalltoParams. //
//--------------------------------------------------------------------------//
CCalltoParams::~CCalltoParams()
{
delete [] m_pszParams;
} // End of CCalltoParams::~CCalltoParams.
//--------------------------------------------------------------------------//
// CCalltoParams::SetParams. //
//--------------------------------------------------------------------------//
HRESULT
CCalltoParams::SetParams
(
const TCHAR * const pszParams
){
HRESULT hrResult;
delete [] m_pszParams;
m_pszParams = NULL;
m_iCount = 0;
if( pszParams == NULL )
{
hrResult = S_OK;
}
else if( (m_pszParams = new TCHAR [ lstrlen( pszParams ) + 1 ]) == NULL )
{
hrResult = E_OUTOFMEMORY;
}
else
{
hrResult = S_OK;
lstrcpy( m_pszParams, pszParams );
TCHAR * pszPos = m_pszParams;
TCHAR * pszEnd;
while( (*pszPos != '\0') && (m_iCount < ARRAY_ELEMENTS( m_pszNames )) )
{
m_pszNames[ m_iCount ] = pszPos;
m_pszValues[ m_iCount ] = NULL;
while( *pszPos != '\0' )
{
if( (*pszPos == '+') || (*pszPos == '=') )
{
break;
}
pszPos = CharNext( pszPos );
}
if( *pszPos != '=' )
{
// Valueless param...
if( m_pszNames[ m_iCount ] == pszPos )
{
hrResult = NM_CALLERR_PARAM_ERROR; // Can't have zero length param names...
break;
}
pszEnd = pszPos;
pszPos = CharNext( pszPos );
if( (pszPos != pszEnd) && (*pszPos == '\0') )
{
hrResult = NM_CALLERR_PARAM_ERROR; // Can't have trailing + or =...
break;
}
*pszEnd = '\0';
m_iCount++;
}
else
{
// Value follows...
pszEnd = pszPos;
pszPos = CharNext( pszPos );
*pszEnd = '\0';
m_pszValues[ m_iCount ] = pszPos;
while( *pszPos != '\0' )
{
if( (*pszPos == '+') || (*pszPos == '=') )
{
break;
}
pszPos = CharNext( pszPos );
}
if( (*pszPos == '=') || (m_pszValues[ m_iCount ] == pszPos) )
{
hrResult = NM_CALLERR_PARAM_ERROR; // Can't have '=' or zero length param names...
break;
}
pszEnd = pszPos;
pszPos = CharNext( pszPos );
if( (pszPos != pszEnd) && (*pszPos == '\0') )
{
hrResult = NM_CALLERR_PARAM_ERROR; // Can't have trailing + or =...
break;
}
*pszEnd = '\0';
m_iCount++;
}
}
if( hrResult == S_OK )
{
if( m_iCount == ARRAY_ELEMENTS( m_pszNames ) )
{
hrResult = NM_CALLERR_PARAM_ERROR; // Too many params...
}
else
{
for( int nn = 0; nn < m_iCount; nn++ )
{
if( (hrResult = Unescape( m_pszNames[ nn ] )) != S_OK )
{
break;
}
if( m_pszValues[ nn ] != NULL )
{
if( (hrResult = Unescape( m_pszValues[ nn ] )) != S_OK )
{
break;
}
}
}
}
}
}
return( hrResult );
} // End of CCalltoParams::SetParams.
//--------------------------------------------------------------------------//
// CCalltoParams::GetParam. //
//--------------------------------------------------------------------------//
const TCHAR * const
CCalltoParams::GetParam
(
const TCHAR * const pszName,
const TCHAR * const pszDefaultValue
) const
{
ASSERT( pszName != NULL );
TCHAR * pszValue = NULL;
if( m_pszParams != NULL )
{
for( int nn = 0; nn < m_iCount; nn++ )
{
if( lstrcmpi( pszName, m_pszNames[ nn ] ) == 0 )
{
pszValue = m_pszValues[ nn ];
break;
}
}
}
return( (pszValue == NULL)? pszDefaultValue: pszValue );
} // End of CCalltoParams::GetParam.
//--------------------------------------------------------------------------//
// CCalltoParams::GetBooleanParam. //
//--------------------------------------------------------------------------//
bool
CCalltoParams::GetBooleanParam
(
const TCHAR * const pszParamName,
const bool bDefaultValue
) const
{
ASSERT( pszParamName != NULL );
const TCHAR * const pszValue = GetParam( pszParamName, NULL );
bool bResult;
if( pszValue == NULL ) // this parameter wasn't specified...
{
bResult = bDefaultValue;
}
else if( *pszValue == 0 ) // this parameter was specified but with no value...
{
bResult = true;
}
else if( (lstrcmpi( pszValue, TEXT( "1" ) ) == 0) ||
(lstrcmpi( pszValue, TEXT( "true" ) ) == 0) ||
(lstrcmpi( pszValue, TEXT( "y" ) ) == 0) ||
(lstrcmpi( pszValue, TEXT( "yes" ) ) == 0) ||
(lstrcmpi( pszValue, TEXT( "on" ) ) == 0) )
{
bResult = true;
}
else if( (lstrcmpi( pszValue, TEXT( "0" ) ) == 0) ||
(lstrcmpi( pszValue, TEXT( "false" ) ) == 0) ||
(lstrcmpi( pszValue, TEXT( "n" ) ) == 0) ||
(lstrcmpi( pszValue, TEXT( "no" ) ) == 0) ||
(lstrcmpi( pszValue, TEXT( "off" ) ) == 0) )
{
bResult = false;
}
else
{
bResult = bDefaultValue;
}
return( bResult );
} // End of CCalltoParams::GetBooleanParam.
//--------------------------------------------------------------------------//
// IsLocalIpAddress. //
//--------------------------------------------------------------------------//
bool IsLocalIpAddress
(
const unsigned long ulIpAddress // IP Address to verify is not local
){
bool bResult = (ulIpAddress == INADDR_LOOPBACK); // First check right away if it's the prefined loop back ip address...
if( !bResult )
{
char szHostName[ MAX_PATH ];
// Get our own local hostname...
if( gethostname( szHostName, ARRAY_ELEMENTS( szHostName ) ) == SOCKET_ERROR )
{
WARNING_OUT( ("IsLocalIpAddress: gethostname() failed with error=%s", PszWSALastError()) );
}
else
{
// Now find out which IP addresses are associated with it...
HOSTENT * pHostEnt = gethostbyname( szHostName );
if( pHostEnt == NULL )
{
WARNING_OUT( ("IsLocalIpAddress: gethostbyname() failed with error=%s", PszWSALastError()) );
}
else if( (pHostEnt->h_addrtype != AF_INET) || (pHostEnt->h_length != sizeof( ulIpAddress )) )
{
WARNING_OUT( ("IsLocalIpAddress: gethostbyname() returned unexpected address type: 0x%08X (%d)", pHostEnt->h_addrtype, pHostEnt->h_addrtype) );
}
else
{
ASSERT( reinterpret_cast<unsigned long **>(pHostEnt->h_addr_list) != NULL );
// Compare all the IP addresses associated with this machine to see if any of them match the one specified...
for( unsigned long ** ppIpAddress = reinterpret_cast<unsigned long **>(pHostEnt->h_addr_list); *ppIpAddress != NULL; ppIpAddress++ )
{
if( **ppIpAddress == ulIpAddress )
{
bResult = true;
break;
}
}
}
}
}
return( bResult );
} // End of IsLocalIpAddress.
//--------------------------------------------------------------------------//
// DecimalStringToUINT. //
//--------------------------------------------------------------------------//
HRESULT DecimalStringToUINT
(
const TCHAR * const pszDecimalString, // Pointer to string to convert...
unsigned int & uiValue // out unsigned int reference to receive converted value...
){
ASSERT( pszDecimalString != NULL );
HRESULT hrResult;
if( lstrlen( pszDecimalString ) > 10 )
{
hrResult = E_INVALIDARG; // Limit it to billions....
}
else
{
hrResult = S_OK;
const TCHAR * pszDigit;
for( pszDigit = pszDecimalString, uiValue = 0; *pszDigit != '\0'; pszDigit = CharNext( pszDigit ) )
{
if( (*pszDigit < '0') || (*pszDigit > '9') )
{
// There's a non digit character in the string so fail...
hrResult = E_INVALIDARG;
break;
}
uiValue = (uiValue * 10) + *pszDigit - '0';
}
}
return( hrResult );
} // End of DecimalStringToUINT.
//--------------------------------------------------------------------------//
// TrimSzCallto. //
//--------------------------------------------------------------------------//
int TrimSzCallto
(
TCHAR * const pszSrc // Pointer to string to trim blanks from in place...
){
ASSERT( pszSrc != NULL );
TCHAR * pszFirst;
int iResult;
for( pszFirst = pszSrc; *pszFirst == ' '; pszFirst = CharNext( pszFirst ) ){};
if( *pszFirst == '\0' )
{
*pszSrc = '\0';
iResult = 0;
}
else
{
TCHAR * pszLast;
TCHAR * psz;
for( pszLast = pszFirst, psz = pszFirst; *psz != '\0'; psz = CharNext( psz ) )
{
if( *psz != ' ' )
{
pszLast = psz;
}
}
pszLast = CharNext( pszLast );
*pszLast = '\0';
lstrcpy( pszSrc, pszFirst );
iResult = lstrlen( pszSrc );
}
return( iResult );
} // End of TrimSzCallto.
//--------------------------------------------------------------------------//
// GetIpAddress. //
//--------------------------------------------------------------------------//
HRESULT GetIpAddress
(
const TCHAR * const pszIpAddress, // pointer to dotted IP address string
unsigned long & ulIpAddress // out unsigned long reference to receive IP address
){
ASSERT( pszIpAddress != NULL );
ulIpAddress = INADDR_NONE;
int ipByte = 0;
int parts = 0;
const TCHAR * ptr = pszIpAddress;
bool newPart = true;
bool result = true;
while( result && (*ptr != NULL) && (parts <= 4) )
{
if( (*ptr >= '0') && (*ptr <= '9') )
{
if( newPart )
{
parts++;
newPart = false;
}
ipByte = (ipByte * 10) + (*ptr - '0');
if( ipByte > 255 )
{
result = false;
}
}
else if( *ptr == '.' )
{
newPart = true;
ipByte = 0;
}
else
{
result = false;
}
ptr++;
}
if( result && (parts == 4) )
{
#if !defined( UNICODE )
ulIpAddress = inet_addr( pszIpAddress );
#else
char * ansiIPAddress;
int size;
size = WideCharToMultiByte( CP_ACP, // code page
0, // performance and mapping flags
ipAddress, // address of wide-character string
-1, // number of characters in string
NULL, // address of buffer for new string
0, // size of buffer
NULL, // address of default for unmappable characters
NULL ); // address of flag set when default char. used
if( (ansiIPAddress = new char [ size ]) != NULL )
{
size = WideCharToMultiByte( CP_ACP, // code page
0, // performance and mapping flags
pszIpAddress, // address of wide-character string
-1, // number of characters in string
ansiIPAddress, // address of buffer for new string
size, // size of buffer
NULL, // address of default for unmappable characters
NULL ); // address of flag set when default char. used
if( size != 0 )
{
ulIpAddress = inet_addr( ansiIPAddress );
}
delete [] ansiIPAddress;
}
#endif // !defined( UNICODE )
}
return( (ulIpAddress != INADDR_NONE)? S_OK: E_FAIL );
} // End of GetIpAddress.
//--------------------------------------------------------------------------//
// GetIpAddressFromHostName. //
//--------------------------------------------------------------------------//
HRESULT GetIpAddressFromHostName
(
const TCHAR * const pszName, // pointer to host name to get IP address of
unsigned long & ulIpAddress // out unsigned long reference to receive IP address
){
ASSERT( pszName != NULL );
HRESULT hrResult = E_FAIL;
if( pszName[ 0 ] == '\0' )
{
ulIpAddress = INADDR_NONE;
}
else if( (hrResult = GetIpAddress( pszName, ulIpAddress )) != S_OK )
{
// Wasn't already in dotted IP address form...
HOSTENT * pHostEnt;
#if !defined( UNICODE )
TCHAR * pszOemName = new TCHAR [ lstrlen( pszName ) + 1 ];
if( pszOemName == NULL )
{
hrResult = E_OUTOFMEMORY;
}
else
{
lstrcpy( pszOemName, pszName );
CharUpper ( pszOemName );
CharToOem( pszOemName, pszOemName );
pHostEnt = gethostbyname( pszOemName );
if( pHostEnt == NULL )
{
WARNING_OUT( ("GetIpAddressFromHostName: gethostbyname() failed with error=%s", PszWSALastError()) );
}
else if( (pHostEnt->h_addrtype != AF_INET) || (pHostEnt->h_length != sizeof( ulIpAddress )) )
{
WARNING_OUT( ("GetIpAddressFromHostName: gethostbyname() returned unexpected address type: 0x%08X (%d)", pHostEnt->h_addrtype, pHostEnt->h_addrtype) );
}
else
{
if( pHostEnt->h_addr_list[ 0 ] != NULL )
{
ulIpAddress = *reinterpret_cast<unsigned long *>(pHostEnt->h_addr_list[ 0 ]); // Just use the first IP address
hrResult = S_OK;
}
}
delete [] pszOemName;
}
#else
// Need to figure out OEM'ing the name...
char * pszMultiByteName;
int iSize;
iSize = WideCharToMultiByte( CP_ACP, // code page
0, // performance and mapping flags
pszName, // address of wide-character string
-1, // number of characters in string
NULL, // address of buffer for new string
0, // size of buffer
NULL, // address of default for unmappable characters
NULL ); // address of flag set when default char. used
if( (pszMultiByteName = new char [ iSize ]) == NULL )
{
hrResult = E_OUTOFMEMORY;
}
else
{
iSize = WideCharToMultiByte( CP_ACP, // code page
0, // performance and mapping flags
pszName, // address of wide-character string
-1, // number of characters in string
pszMultiByteName, // address of buffer for new string
iSize, // size of buffer
NULL, // address of default for unmappable characters
NULL ); // address of flag set when default char. used
if( iSize != 0 )
{
pHostEnt = gethostbyname( ansiHost );
if( pHostEnt == NULL )
{
WARNING_OUT( ("GetIpAddressFromHostName: gethostbyname() failed with error=%s", PszWSALastError()) );
}
else if( (pHostEnt->h_addrtype != AF_INET) || (pHostEnt->h_length != sizeof( ulIpAddress )) )
{
WARNING_OUT( ("GetIpAddressFromHostName: gethostbyname() returned unexpected address type: 0x%08X (%d)", pHostEnt->h_addrtype, pHostEnt->h_addrtype) );
}
else
{
if( pHostEnt->h_addr_list[ 0 ] != NULL )
{
ulIpAddress = *reinterpret_cast<unsigned long *>(pHostEnt->h_addr_list[ 0 ]); // Just use the first IP address
hrResult = S_OK;
}
}
}
delete [] pszMultiByteName;
}
#endif // !defined( UNICODE )
}
return( hrResult );
} // End of GetIpAddressFromHostName.
//--------------------------------------------------------------------------//
// IsPhoneNumber. //
//--------------------------------------------------------------------------//
bool IsPhoneNumber
(
const TCHAR * pszPhone // string to check for invalid phone number characters
){
ASSERT( pszPhone != NULL );
ASSERT( pszPhone[ 0 ] != '\0' );
bool bResult = true;
while( pszPhone[ 0 ] != '\0' )
{
switch( pszPhone[ 0 ] )
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '(':
case ')':
case '#':
case '*':
case '-':
case ',':
case ' ':
break;
default:
bResult = false;
break;
}
pszPhone++;
}
return( bResult );
} // End of IsPhoneNumber.
//--------------------------------------------------------------------------//
// bCanCallAsPhoneNumber. //
//--------------------------------------------------------------------------//
bool bCanCallAsPhoneNumber
(
const TCHAR * const pszPhone
){
ASSERT( pszPhone != NULL );
ASSERT( pszPhone[ 0 ] != '\0' );
bool bResult = FALSE;
if( IsPhoneNumber( pszPhone ) )
{
if( ConfPolicies::CallingMode_GateKeeper == ConfPolicies::GetCallingMode() )
{
bResult = true;
}
else
{
RegEntry reConf( CONFERENCING_KEY, HKEY_CURRENT_USER );
bResult = (reConf.GetNumber( REGVAL_USE_H323_GATEWAY ) != 0);
}
}
return( bResult );
} // End of bCanCallAsPhoneNumber.
//--------------------------------------------------------------------------//
// unescape. //
//--------------------------------------------------------------------------//
HRESULT Unescape
(
TCHAR * const pszSrc // pointer to string to unescape in place
){
ASSERT( pszSrc != NULL );
TCHAR * pszPercentSign;
HRESULT hrResult;
for( hrResult = S_OK, pszPercentSign = pszSrc; pszPercentSign != NULL; )
{
if( (pszPercentSign = StrChr( pszPercentSign, '%' )) != NULL )
{
TCHAR chHighNibble = pszPercentSign[ 1 ];
if( ((chHighNibble >= '0') && (chHighNibble <= '9')) ||
((chHighNibble >= 'a') && (chHighNibble <= 'f')) ||
((chHighNibble >= 'A') && (chHighNibble <= 'F')) )
{
TCHAR chLowNibble = pszPercentSign[ 2 ];
if( ((chLowNibble >= '0') && (chLowNibble <= '9')) ||
((chLowNibble >= 'a') && (chLowNibble <= 'f')) ||
((chLowNibble >= 'A') && (chLowNibble <= 'F')) )
{
chHighNibble = ((chHighNibble >= '0') && (chHighNibble <= '9'))? chHighNibble - '0':
((chHighNibble >= 'a') && (chHighNibble <= 'f'))? chHighNibble - 'a' + 10: chHighNibble - 'A' + 10;
chLowNibble = ((chLowNibble >= '0') && (chLowNibble <= '9'))? chLowNibble - '0':
((chLowNibble >= 'a') && (chLowNibble <= 'f'))? chLowNibble - 'a' + 10: chLowNibble - 'A' + 10;
*pszPercentSign++ = (chHighNibble << 4) | chLowNibble;
lstrcpy( pszPercentSign, &pszPercentSign[ 2 ] );
}
else
{
hrResult = NM_CALLERR_UNESCAPE_ERROR;
break;
}
}
else
{
hrResult = NM_CALLERR_UNESCAPE_ERROR;
break;
}
}
}
return( hrResult );
} // End of Unescape.