#include <stdio.h>
#include <string.h>
#include <CoreFoundation/CoreFoundation.h>
#include <DirectoryService/DirServicesTypes.h>
#include "GenericNBPURL.h"
#include "NSLDebugLog.h"
OSStatus HexEncodeText( const char* rawText, UInt16 rawTextLen, char* newTextBuffer, UInt16* newTextBufferLen, Boolean* textChanged );
void MakeGenericNBPURL(const char *entityType, const char *zoneName, const char *name, char* returnBuffer, UInt16* returnBufferLen )
{
char safeEntityType[256*3];
char safeZoneName[32*3], safeName[32*3];
Size urlLength = 0;
if ( entityType && zoneName && name )
{
{
char tempBuf[256];
UInt16 bufLen = 256;
Boolean textChanged;
OSStatus status;
UInt16 entityTypeLen = strlen(entityType);
status = HexEncodeText( entityType, entityTypeLen, tempBuf, &bufLen, &textChanged );
if ( !status )
{
tempBuf[bufLen] = '\0';
strcpy( safeEntityType, tempBuf );
}
else
{
safeEntityType[0] = '\0';
DBGLOG( "HexEncodeText failed for entityType, status = %ld\n", status );
}
UInt16 zoneNameLen = strlen(zoneName);
bufLen = 256;
status = HexEncodeText( zoneName, zoneNameLen, tempBuf, &bufLen, &textChanged );
if ( !status )
{
tempBuf[bufLen] = '\0';
strcpy( safeZoneName, tempBuf );
}
else
DBGLOG( "HexEncodeText failed, status = %ld\n", status );
UInt16 nameLen = strlen(name);
bufLen = 256;
status = HexEncodeText( (char*)name, nameLen, tempBuf, &bufLen, &textChanged );
if ( !status )
{
tempBuf[bufLen] = '\0';
strcpy( safeName, tempBuf );
}
else
DBGLOG( "HexEncodeText failed, status = %ld\n", status );
}
urlLength = strlen( safeEntityType )
+ strlen( kNBPDivider )
+ strlen( safeZoneName )
+ strlen( kEntityZoneDelimiter )
+ strlen( safeName )
+ 1;
if ( urlLength <= *returnBufferLen )
{
strcpy( returnBuffer, safeEntityType );
strcat( returnBuffer, kNBPDivider );
strcat( returnBuffer, safeName );
strcat( returnBuffer, kEntityZoneDelimiter );
strcat( returnBuffer, safeZoneName );
*returnBufferLen = urlLength;
}
else
*returnBufferLen = 0;
}
}
Boolean IsCharURLReservedOrIllegal( const char c )
{
Boolean isIllegal = false;
if ( c <= 0x1F || c == 0x7F || (unsigned char)c >= 0x80 )
isIllegal = true;
else
{
switch (c)
{
case '<':
case '>':
case 0x22: case 0x5c: case '#':
case '{':
case '}':
case '|':
case '^':
case '~':
case '[':
case ']':
case '`':
case ';':
case '/':
case '?':
case ':':
case '@':
case '=':
case '&':
case ' ':
case ',':
case '%':
isIllegal = true;
break;
}
}
return isIllegal;
}
void EncodeCharToHex( const char c, char* newHexChar )
{
div_t result;
short hexValue = c;
char c1, c2;
if ( hexValue < 0 )
hexValue -= 0xFF00;
result = div( hexValue, 16 );
if ( result.quot < 0xA )
c1 = (char)result.quot + '0';
else
c1 = (char)result.quot + 'a' - 10;
if ( result.rem < 0xA )
c2 = (char)result.rem + '0';
else
c2 = (char)result.rem + 'a' - 10;
newHexChar[0] = '%';
newHexChar[1] = c1;
newHexChar[2] = c2;
}
OSStatus HexEncodeText( const char* rawText, UInt16 rawTextLen, char* newTextBuffer, UInt16* newTextBufferLen, Boolean* textChanged )
{
OSStatus status = noErr;
char* curWritePtr = newTextBuffer;
UInt16 writeBufferMaxLen;
if ( !rawText || !newTextBuffer || !newTextBufferLen || !textChanged )
status = eDSNullParameter;
writeBufferMaxLen = *newTextBufferLen;
*textChanged = false;
for ( UInt16 i=0; !status && i<rawTextLen; i++ )
{
if ( IsCharURLReservedOrIllegal( rawText[i] ) )
{
if ( curWritePtr > newTextBuffer + writeBufferMaxLen + 2 ) {
status = eDSBufferTooSmall;
break;
}
EncodeCharToHex( rawText[i], curWritePtr );
curWritePtr += 3;
*textChanged = true;
}
else
{
if ( curWritePtr > newTextBuffer + writeBufferMaxLen )
{
status = eDSBufferTooSmall;
break;
}
*curWritePtr = rawText[i];
curWritePtr++;
}
}
if ( !status )
*newTextBufferLen = (curWritePtr - newTextBuffer);
else
{
*newTextBufferLen = 0;
*textChanged = false;
}
return status;
}