1648 lines
43 KiB
C++
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.
|