|
|
#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 pszCallto2[] = TEXT( "callto:" ); static const TCHAR pszDoubleSlash[] = TEXT( "//" );
if( StrCmpNI_literal( m_pszCalltoBuffer, pszCallto2 ) ) { m_pszParsePos = m_pszCalltoBuffer + strlen_literal( pszCallto2 );
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(NULL != pszType) { 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; } } 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.
|