#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <Carbon/Carbon.h>
#include "URLUtilities.h"
#if TARGET_CARBON
#define charisalpha(c) ( ((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z') )
#define charisdigit(c) ( (c) >= '0' && (c) <= '9' )
#define charisprint(c) ( (c) >= ' ' )
#define charisxdigit(c) ( charisdigit((c)) || ( (c) >= 'a' && (c) <= 'f' ) || ( (c) >= 'A' && (c) <= 'F' ) )
#else
#define charisalpha isalpha
#define charisdigit isdigit
#define charisprint isprint
#define charisxdigit isxdigit
#endif
Boolean IsURL( const char* theString, UInt32 theURLLength, char** svcTypeOffset )
{
Boolean foundURL=false;
if ( AllLegalURLChars(theString, theURLLength) )
{
*svcTypeOffset = strstr(theString, ":/"); if ( *svcTypeOffset != NULL)
foundURL = true;
}
return foundURL;
}
Boolean AllLegalURLChars( const char* theString, UInt32 theURLLength )
{
Boolean isLegal = true;
if ( theString ) {
for (SInt32 i = theURLLength - 1; i>=0 && isLegal; i--)
isLegal = IsLegalURLChar( theString[i] );
}
else
isLegal = false;
return isLegal;
}
Boolean IsLegalURLChar( const char theChar )
{
return ( charisprint( theChar ) && ( theChar != ' ' && theChar != '\"' && theChar != '<' && theChar != '>' ) );
}
void GetServiceTypeFromURL( const char* readPtr,
UInt32 theURLLength,
char* URLType )
{
char* curOffset;
UInt16 typeLen;
if ( IsURL( readPtr, theURLLength, &curOffset))
{
typeLen = curOffset - readPtr;
::memcpy(URLType, (unsigned char*)readPtr, typeLen);
URLType[typeLen] = '\0';
}
else
{
URLType[0] = '\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;
}
char DecodeHexToChar( const char* oldHexTriplet, Boolean* wasHexTriplet )
{
char c, c1, c2;
*wasHexTriplet = false;
c = *oldHexTriplet;
if ( c == '%' )
{
c1 = tolower(oldHexTriplet[1]);
c2 = tolower(oldHexTriplet[2]);
if (charisxdigit(c1) && charisxdigit(c2))
{
c1 = charisdigit(c1) ? c1 - '0' : c1 - 'a' + 10;
c2 = charisdigit(c2) ? c2 - '0' : c2 - 'a' + 10;
c = (c1 << 4) | c2;
*wasHexTriplet = true;
}
}
return c;
}
Boolean EncodeHTTPString( string& text )
{
string temp, theString = text.c_str();
short i=0;
short len = theString.size();
char c, c1, c2;
Boolean encodedTheString = false;
if ( *(text.c_str()) == '.' && text.size() == 1 )
{
text = "%2E";
encodedTheString = true;
}
else
{
temp.reserve(len);
while (i < len)
{
c = theString[i];
if ( c == '>' )
{
temp += "%3E";
encodedTheString = true;
}
else if ( c == '<' )
{
temp += "%3C";
encodedTheString = true;
}
else if ( c == '?' )
{
temp += "%3F";
encodedTheString = true;
}
else if ( c == '/' )
{
temp += "%2F"; encodedTheString = true;
}
else if ((c < 0x2C) || (c > 'z')) {
div_t result;
short hexValue = c;
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;
temp += '%';
temp += c1;
temp += c2;
encodedTheString = true;
}
else
{
temp += c;
}
i = i + 1;
}
text = temp.c_str();
}
return encodedTheString;
}
void DecodeHTTPString( string& theString )
{
short i=0;
short len = theString.size();
char c, c1, c2;
string temp;
temp.reserve(len);
while (i < len)
{
c = theString[i];
if ((c == '%') & (i+2 < len))
{
c1 = tolower(theString[i+1]);
c2 = tolower(theString[i+2]);
if (charisxdigit(c1) && charisxdigit(c2))
{
c1 = charisdigit(c1) ? c1 - '0' : c1 - 'a' + 10;
c2 = charisdigit(c2) ? c2 - '0' : c2 - 'a' + 10;
c = (c1 << 4) | c2;
temp += c;
}
i = i + 3;
}
else
{
temp += c;
i = i + 1;
}
}
theString = temp;
}