|
|
//--------------------------------------------------------------------------//
// Application Header Files. //
//--------------------------------------------------------------------------//
#include "precomp.h"
#include "callto.h"
#include "calltoContext.h"
#include "calltoResolver.h"
//--------------------------------------------------------------------------//
// CCalltoResolver::CCalltoResolver. //
//--------------------------------------------------------------------------//
CCalltoResolver::CCalltoResolver(void): m_registeredResolvers( 0 ) {
addResolver( &m_phoneResolver ); addResolver( &m_emailResolver ); addResolver( &m_ipResolver ); addResolver( &m_computerResolver ); addResolver( &m_ilsResolver ); addResolver( &m_unrecognizedTypeResolver ); addResolver( &m_stringResolver );
} // End of CCalltoResolver::CCalltoResolver.
//--------------------------------------------------------------------------//
// CCalltoResolver::~CCalltoResolver. //
//--------------------------------------------------------------------------//
CCalltoResolver::~CCalltoResolver() { } // End of CCalltoResolver::~CCalltoResolver.
//--------------------------------------------------------------------------//
// CCalltoResolver::resolve. //
//--------------------------------------------------------------------------//
HRESULT CCalltoResolver::resolve ( ICalltoContext * const calltoContext, CCalltoProperties * const calltoProperties, CCalltoCollection * const resolvedCalltoCollection, const TCHAR * url, const bool strict ){ HRESULT result;
if( (calltoContext == NULL) || (calltoProperties == NULL) || (resolvedCalltoCollection == NULL) ) { result = E_POINTER; } else { TCHAR * params = StrStrI( url, TEXT( "phone:+" ) ); params = StrChr( (params != NULL)? params + strlen_literal( TEXT( "phone:+" ) ): url, '+' );
int paramsLength = (params == NULL)? 0: lstrlen( params ); int urlLength = lstrlen( url ) - paramsLength + 1; int prefixLength = 0;
if( !StrCmpNI_literal( url, TEXT( "callto:" ) ) ) { prefixLength = strlen_literal( TEXT( "callto:" ) ); } else if( StrCmpNI_literal( url, TEXT( "callto://" ) ) ) { prefixLength = strlen_literal( TEXT( "callto:" ) ); url += strlen_literal( TEXT( "callto://" ) ); urlLength -= strlen_literal( TEXT( "callto://" ) ) - strlen_literal( TEXT( "callto:" ) ); }
TCHAR * urlBuffer = NULL;
if( (urlBuffer = new TCHAR [ urlLength + prefixLength ]) == NULL ) { result = E_OUTOFMEMORY; } else { if( paramsLength > 0 ) { // Save params...
calltoProperties->set_params( params ); }
// Save original callto...
calltoProperties->set_callto( url, urlLength );
result = S_FALSE;
resolvedCalltoCollection->reset();
if( urlLength > 1 ) { bool strictChecked = !strict;
for( int nn = 0; nn < m_registeredResolvers; nn++ ) { if( prefixLength > 0 ) { lstrcpy( urlBuffer, TEXT( "callto:" ) ); // Prepend default of callto: ...
lstrcpyn( urlBuffer + strlen_literal( TEXT( "callto:" ) ), url, urlLength ); } else { lstrcpyn( urlBuffer, url, urlLength ); }
if( !strictChecked ) { if( !strictCheck( urlBuffer ) ) { result = E_INVALIDARG; break; }
strictChecked = true; }
HRESULT resolveResult = m_resolvers[ nn ]->resolve( resolvedCalltoCollection, urlBuffer );
if( FAILED( resolveResult ) && (!FAILED( result )) ) { result = resolveResult; } }
if( !FAILED( result ) ) { result = (resolvedCalltoCollection->get_count() > 0)? S_OK: S_FALSE; } } }
delete [] urlBuffer; }
return( result );
} // End of class CCalltoResolver::resolve.
//--------------------------------------------------------------------------//
// CCalltoResolver::addResolver. //
//--------------------------------------------------------------------------//
bool CCalltoResolver::addResolver ( IResolver * const resolver ){ //assert( resolver != NULL, TEXT( "attempted to add NULL resolver\r\n" ) );
//assert( m_registeredResolvers < elementsof( m_resolvers ), TEXT( "attempted to add to many resolvers: %d\r\n" ), m_registeredResolvers );
if( (resolver != NULL) && (m_registeredResolvers < elementsof( m_resolvers )) ) { m_resolvers[ m_registeredResolvers++ ] = resolver; }
return( (resolver != NULL) && (m_registeredResolvers <= elementsof( m_resolvers )) );
} // End of CCalltoResolver::addResolver.
//--------------------------------------------------------------------------//
// CCalltoResolver::strictCheck. //
//--------------------------------------------------------------------------//
const bool CCalltoResolver::strictCheck ( const TCHAR * const url ) const { //assert( url != NULL, TEXT( "attempted to strictCheck NULL url\r\n" ) );
return( (url != NULL) && (StrCmpNI_literal( url, TEXT( "callto:phone:" ) ) || StrCmpNI_literal( url, TEXT( "callto:email:" ) ) || StrCmpNI_literal( url, TEXT( "callto:ip:" ) ) || StrCmpNI_literal( url, TEXT( "callto:computer:" ) ) || StrCmpNI_literal( url, TEXT( "callto:ils:" ) ) || StrCmpNI_literal( url, TEXT( "callto:string:" ) ) || (StrStrI( url, TEXT( "|phone:" ) ) != NULL) || (StrStrI( url, TEXT( "|email:" ) ) != NULL) || (StrStrI( url, TEXT( "|ip:" ) ) != NULL) || (StrStrI( url, TEXT( "|computer:" ) ) != NULL) || (StrStrI( url, TEXT( "|ils:" ) ) != NULL) || (StrStrI( url, TEXT( "|string:" ) ) != NULL)) );
} // End of CCalltoResolver::strictCheck.
//--------------------------------------------------------------------------//
// CPhoneResolver::resolve. //
//--------------------------------------------------------------------------//
HRESULT CPhoneResolver::resolve ( IMutableCalltoCollection * const calltoCollection, TCHAR * const url ){ HRESULT result = E_INVALIDARG;
if( (calltoCollection != NULL) && (url != NULL) ) { TCHAR * phoneType; TCHAR * phoneNumber = NULL;
result = S_FALSE;
if( StrCmpNI_literal( url, TEXT( "callto:phone:" ) ) ) // Check for phone type without gateway...
{ phoneType = url; phoneNumber = url + strlen_literal( TEXT( "callto:phone:" ) ); } else if( (phoneType = StrStrI( url, TEXT( "|phone:" ) )) != NULL ) // Check for phone type with gateway...
{ phoneNumber = phoneType + strlen_literal( TEXT( "|phone:" ) ); }
if( phoneNumber != NULL ) { // phone: type was specified for this callto:...
if( CCalltoContext::toE164( phoneNumber, NULL, 0 ) ) { ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
if( resolvedCallto != NULL ) { CCalltoContext::toE164( phoneNumber, phoneNumber, lstrlen( phoneNumber ) ); resolvedCallto->set_qualifiedName( url ); resolvedCallto->set_confidence( S_CONFIDENCE_HIGH );
result = S_OK; } else { result = E_OUTOFMEMORY; } } } else { phoneNumber = url + strlen_literal( TEXT( "callto:" ) );
if( CCalltoContext::isPhoneNumber( phoneNumber ) ) { // It smells like E164...
result = E_OUTOFMEMORY;
CCalltoContext::toE164( phoneNumber, phoneNumber, lstrlen( phoneNumber ) );
TCHAR * buffer = new TCHAR [ lstrlen( phoneNumber ) + strlen_literal( TEXT( "callto:phone:%s" ) ) ];
if( buffer != NULL ) { ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
if( resolvedCallto != NULL ) { wsprintf( buffer, TEXT( "callto:phone:%s" ), phoneNumber ); resolvedCallto->set_qualifiedName( buffer ); resolvedCallto->set_confidence( S_CONFIDENCE_MEDIUM );
result = S_OK; }
delete [] buffer; } } } }
return( result );
} // End of CPhoneResolver::resolve.
//--------------------------------------------------------------------------//
// CEMailResolver::resolve. //
//--------------------------------------------------------------------------//
HRESULT CEMailResolver::resolve ( IMutableCalltoCollection * const calltoCollection, TCHAR * const url ){ HRESULT result = E_INVALIDARG;
if( (calltoCollection != NULL) && (url != NULL) ) { TCHAR * emailType; TCHAR * emailAddress = NULL;
result = S_FALSE;
if( StrCmpNI_literal( url, TEXT( "callto:email:" ) ) ) // Check for email type without gateway...
{ emailType = url; emailAddress = url + strlen_literal( TEXT( "callto:email:" ) ); } else if( (emailType = StrStrI( url, TEXT( "|email:" ) )) != NULL ) // Check for email type with gateway...
{ emailAddress = emailType + strlen_literal( TEXT( "|email:" ) ); }
if( emailAddress != NULL ) { // email: type was specified for this callto:...
ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
if( resolvedCallto != NULL ) { resolvedCallto->set_qualifiedName( url ); resolvedCallto->set_confidence( S_CONFIDENCE_HIGH ); result = S_OK; } else { result = E_OUTOFMEMORY; } } else { emailAddress = url + strlen_literal( TEXT( "callto:" ) );
if( (StrChr( emailAddress, ':' ) == NULL) && // isn't some other type:...
(StrChr( emailAddress, ' ' ) == NULL) && // doesn't contain spaces...
(StrChr( emailAddress, '|' ) == NULL) && // doesn't contain a bar (gateway)...
(StrChr( emailAddress, '/' ) == NULL) && // isn't an old style ilsserver/email...
((StrChr( emailAddress, '.' ) == NULL) || // doesn't have a dot unless it also
(StrChr( emailAddress, '@' ) != NULL)) ) // has a @ so it can't be an ip address...
{ // It smells like an email address...
result = E_OUTOFMEMORY;
TCHAR * buffer = new TCHAR [ lstrlen( emailAddress ) + strlen_literal( TEXT( "callto:email:%s" ) ) ];
if( buffer != NULL ) { ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
if( resolvedCallto != NULL ) { wsprintf( buffer, TEXT( "callto:email:%s" ), emailAddress ); resolvedCallto->set_qualifiedName( buffer ); resolvedCallto->set_confidence( S_CONFIDENCE_MEDIUM );
result = S_OK; }
delete [] buffer; } } } }
return( result );
} // End of CEMailResolver::resolve.
//--------------------------------------------------------------------------//
// CIPResolver::resolve. //
//--------------------------------------------------------------------------//
HRESULT CIPResolver::resolve ( IMutableCalltoCollection * const calltoCollection, TCHAR * const url ){ HRESULT result = E_INVALIDARG;
if( (calltoCollection != NULL) && (url != NULL) ) { TCHAR * ipType; TCHAR * ipAddress = NULL;
result = S_FALSE;
if( StrCmpNI_literal( url, TEXT( "callto:ip:" ) ) ) // Check for ip type without gateway...
{ ipType = url; ipAddress = url + strlen_literal( TEXT( "callto:ip:" ) ); } else if( (ipType = StrStrI( url, TEXT( "|ip:" ) )) != NULL ) // Check for ip type with gateway...
{ ipAddress = ipType + strlen_literal( TEXT( "|ip:" ) ); }
if( (ipAddress != NULL) && CCalltoContext::isIPAddress( ipAddress ) ) { // ip: type was specified for this callto:...
ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
if( resolvedCallto != NULL ) { resolvedCallto->set_qualifiedName( url ); resolvedCallto->set_confidence( S_CONFIDENCE_HIGH );
result = S_OK; } else { result = E_OUTOFMEMORY; } } else { ipAddress = url + strlen_literal( TEXT( "callto:" ) );
if( CCalltoContext::isIPAddress( ipAddress ) ) { // It smells like an ip address...
ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
if( resolvedCallto != NULL ) { TCHAR buffer[ MAX_PATH ];
wsprintf( buffer, TEXT( "callto:ip:%s" ), ipAddress ); resolvedCallto->set_qualifiedName( buffer ); resolvedCallto->set_confidence( S_CONFIDENCE_MEDIUM );
result = S_OK; } else { result = E_OUTOFMEMORY; } } } }
return( result );
} // End of CIPResolver::resolve.
//--------------------------------------------------------------------------//
// CComputerResolver::resolve. //
//--------------------------------------------------------------------------//
HRESULT CComputerResolver::resolve ( IMutableCalltoCollection * const calltoCollection, TCHAR * const url ){ HRESULT result = E_INVALIDARG;
if( (calltoCollection != NULL) && (url != NULL) ) { TCHAR * computerType; TCHAR * hostName = NULL;
result = S_FALSE;
if( StrCmpNI_literal( url, TEXT( "callto:computer:" ) ) ) // Check for computer type without gateway...
{ computerType = url; hostName = url + strlen_literal( TEXT( "callto:computer:" ) ); } else if( (computerType = StrStrI( url, TEXT( "|computer:" ) )) != NULL ) // Check for computer type with gateway...
{ hostName = computerType + strlen_literal( TEXT( "|computer:" ) ); }
if( hostName != NULL ) { // host: type was specified for this callto:...
ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
if( resolvedCallto != NULL ) { resolvedCallto->set_qualifiedName( url ); resolvedCallto->set_confidence( S_CONFIDENCE_HIGH );
result = S_OK; } else { result = E_OUTOFMEMORY; } } else { hostName = url + strlen_literal( TEXT( "callto:" ) );
TCHAR * slash = hostName;
// Remove any trailing /....
while( (slash = StrChr( slash, '/' )) != NULL ) { if( slash[ 1 ] == '\0' ) { slash[ 0 ] = '\0'; break; }
slash++; }
if( (StrChr( hostName, ':' ) == NULL) && // isn't some other type:...
(StrChr( hostName, ' ' ) == NULL) && // doesn't contain spaces...
(StrChr( hostName, '|' ) == NULL) && // doesn't contain a bar (gateway)...
(StrChr( hostName, '/' ) == NULL) && // doesn't contain a slash (ils)...
(StrChr( hostName, '@' ) == NULL) ) // doesn't contain an @...
{ // It smells like a dns host name...
result = E_OUTOFMEMORY;
TCHAR * buffer = new TCHAR [ lstrlen( hostName ) + strlen_literal( TEXT( "callto:computer:%s" ) ) ];
if( buffer != NULL ) { ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
if( resolvedCallto != NULL ) { wsprintf( buffer, TEXT( "callto:computer:%s" ), hostName ); resolvedCallto->set_qualifiedName( buffer ); resolvedCallto->set_confidence( StrCmpNI_literal( hostName, TEXT( "\\\\" ) )? S_CONFIDENCE_HIGH: S_CONFIDENCE_MEDIUM );
result = S_OK; }
delete [] buffer; } } } }
return( result );
} // End of CComputerResolver::resolve.
//--------------------------------------------------------------------------//
// CILSResolver::resolve. //
//--------------------------------------------------------------------------//
HRESULT CILSResolver::resolve ( IMutableCalltoCollection * const calltoCollection, TCHAR * const url ){ HRESULT result = E_INVALIDARG;
if( (calltoCollection != NULL) && (url != NULL) ) { const TCHAR * ilsType; const TCHAR * emailAddress = NULL;
result = S_FALSE;
if( StrCmpNI_literal( url, TEXT( "callto:ils:" ) ) ) // Check for ils type without gateway...
{ ilsType = url; emailAddress = url + strlen_literal( TEXT( "callto:ils:" ) ); } else if( (ilsType = StrStrI( url, TEXT( "|ils:" ) )) != NULL ) // Check for ils type with gateway...
{ emailAddress = ilsType + strlen_literal( TEXT( "|ils:" ) ); }
if( emailAddress != NULL ) { // ils: type was specified for this callto:...
ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
if( resolvedCallto != NULL ) { resolvedCallto->set_qualifiedName( url ); resolvedCallto->set_confidence( S_CONFIDENCE_HIGH );
result = S_OK; } else { result = E_OUTOFMEMORY; } } else { emailAddress = url + strlen_literal( TEXT( "callto:" ) );
if( (StrChr( emailAddress, ' ' ) == NULL) && // doesn't contain spaces...
(StrChr( emailAddress, '|' ) == NULL) && // doesn't contain a bar (gateway)...
(StrChr( emailAddress, '/' ) != NULL) ) // has a /...
{ // It smells like an ilsserver/emailaddress...
result = E_OUTOFMEMORY;
TCHAR * buffer = new TCHAR [ lstrlen( emailAddress ) + strlen_literal( TEXT( "callto:ils:%s" ) ) ];
if( buffer != NULL ) { ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
if( resolvedCallto != NULL ) { wsprintf( buffer, TEXT( "callto:ils:%s" ), emailAddress ); resolvedCallto->set_qualifiedName( buffer ); resolvedCallto->set_confidence( S_CONFIDENCE_MEDIUM );
result = S_OK; }
delete [] buffer; } } } }
return( result );
} // End of CILSResolver::resolve.
//--------------------------------------------------------------------------//
// CUnrecognizedTypeResolver::resolve. //
//--------------------------------------------------------------------------//
HRESULT CUnrecognizedTypeResolver::resolve ( IMutableCalltoCollection * const calltoCollection, TCHAR * const url ){ HRESULT result = E_INVALIDARG;
if( (calltoCollection != NULL) && (url != NULL) ) { TCHAR * type; TCHAR * unrecognized = url + strlen_literal( TEXT( "callto:" ) ); TCHAR * gateway = NULL; TCHAR * value = NULL;
result = S_FALSE;
if( ((type = StrChr( unrecognized, ':' )) != NULL) && // Check for a type, but not a known one...
(!StrCmpNI_literal( url, TEXT( "callto:phone:" ) )) && (StrStrI( url, TEXT( "|phone:" ) ) == NULL) && // isn't a phone: type...
(!StrCmpNI_literal( url, TEXT( "callto:email:" ) )) && (StrStrI( url, TEXT( "|email:" ) ) == NULL) && // isn't an email: type...
(!StrCmpNI_literal( url, TEXT( "callto:computer:" ) )) && (StrStrI( url, TEXT( "|computer:" ) ) == NULL) && // isn't a computer: type...
(!StrCmpNI_literal( url, TEXT( "callto:ils:" ) )) && (StrStrI( url, TEXT( "|ils:" ) ) == NULL) && // isn't an ils: type...
(!StrCmpNI_literal( url, TEXT( "callto:ip:" ) )) && (StrStrI( url, TEXT( "|ip:" ) ) == NULL) && // isn't an ip: type...
(!StrCmpNI_literal( url, TEXT( "callto:string:" ) )) && (StrStrI( url, TEXT( "|string:" ) ) == NULL) ) // isn't an string: type...
{ *type++ = NULL; value = type;
if( (gateway = StrChr( url, '|' )) != NULL ) // Check for a gateway...
{ *gateway++ = NULL; type = gateway; gateway = unrecognized; } }
if( value != NULL ) { // Some unrecognized type was specified...
result = E_OUTOFMEMORY;
int length = strlen_literal( TEXT( "callto:|%s" ) ) + lstrlen( value );
if( gateway == NULL ) { length += lstrlen( unrecognized ); } else { length += lstrlen( gateway ) + lstrlen( type ); }
TCHAR * buffer = new TCHAR [ length ];
if( buffer != NULL ) { ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
if( resolvedCallto != NULL ) { if( gateway == NULL ) { wsprintf( buffer, TEXT( "callto:%s:%s" ), unrecognized, value ); } else { wsprintf( buffer, TEXT( "callto:%s|%s:%s" ), gateway, type, value ); }
resolvedCallto->set_qualifiedName( buffer ); resolvedCallto->set_confidence( S_CONFIDENCE_LOW );
result = S_OK; }
delete [] buffer; } } }
return( result );
} // End of CUnrecognizedTypeResolver::resolve.
//--------------------------------------------------------------------------//
// CStringResolver::resolve. //
//--------------------------------------------------------------------------//
HRESULT CStringResolver::resolve ( IMutableCalltoCollection * const calltoCollection, TCHAR * const url ){ HRESULT result = E_INVALIDARG;
if( (calltoCollection != NULL) && (url != NULL) ) { TCHAR * stringType; TCHAR * string = NULL;
result = S_FALSE;
if( StrCmpNI_literal( url, TEXT( "callto:string:" ) ) ) // Check for string type without gateway...
{ stringType = url; string = url + strlen_literal( TEXT( "callto:string:" ) ); } else if( (stringType = StrStrI( url, TEXT( "|string:" ) )) != NULL ) // Check for string type with gateway...
{ string = stringType + strlen_literal( TEXT( "|string:" ) ); }
if( string != NULL ) { // string: type was specified for this callto:...
ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
if( resolvedCallto != NULL ) { resolvedCallto->set_qualifiedName( url ); resolvedCallto->set_confidence( S_CONFIDENCE_HIGH );
result = S_OK; } else { result = E_OUTOFMEMORY; } } else { string = url + strlen_literal( TEXT( "callto:" ) );
if( StrChr( string, ':' ) == NULL ) { // It doesn't have a type so set it to string...
result = E_OUTOFMEMORY; TCHAR * slash; TCHAR * buffer = new TCHAR [ lstrlen( string ) + strlen_literal( TEXT( "callto:%s|string:%s" ) ) ];
if( buffer != NULL ) { ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
if( resolvedCallto != NULL ) { if( (slash = StrChr( string, '|' )) == NULL ) // Check for a gateway...
{ wsprintf( buffer, TEXT( "callto:string:%s" ), string ); } else { *slash++ = NULL; wsprintf( buffer, TEXT( "callto:%s|string:%s" ), string, slash ); }
resolvedCallto->set_qualifiedName( buffer ); resolvedCallto->set_confidence( S_CONFIDENCE_LOW );
result = S_OK; }
delete [] buffer; } } } }
return( result );
} // End of CStringResolver::resolve.
|