mirror of
https://github.com/gnustep/libs-gsweb.git
synced 2025-02-21 10:51:23 +00:00
get rid of RCS_ID as shortly discussed with David and Manuel git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gsweb/trunk@37929 72102866-910b-0410-8b05-ffd578937521
861 lines
29 KiB
Objective-C
861 lines
29 KiB
Objective-C
/** NSString+HTML.m - <title>GSWeb: NSString / HTML</title>
|
|
|
|
Copyright (C) 1999-2005 Free Software Foundation, Inc.
|
|
|
|
Written by: Manuel Guesdon <mguesdon@orange-concept.com>
|
|
Date: Jan 1999
|
|
|
|
$Revision$
|
|
$Date$
|
|
$Id$
|
|
|
|
This file is part of the GNUstep Web Library.
|
|
|
|
<license>
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
License along with this library; if not, write to the Free
|
|
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
</license>
|
|
**/
|
|
|
|
#include "config.h"
|
|
|
|
#include "GSWeb.h"
|
|
#include "GSWPrivate.h"
|
|
|
|
#ifndef GNUSTEP
|
|
#include <GNUstepBase/GSObjCRuntime.h>
|
|
#endif
|
|
#include <GNUstepBase/NSString+GNUstepBase.h>
|
|
|
|
|
|
#include <limits.h>
|
|
|
|
/*
|
|
<!ENTITY amp CDATA "&" -- ampersand -->
|
|
<!ENTITY gt CDATA ">" -- greater than -->
|
|
<!ENTITY lt CDATA "<" -- less than -->
|
|
<!ENTITY quot CDATA """ -- double quote -->
|
|
<!ENTITY nbsp CDATA " " -- no-break space -->
|
|
<!ENTITY iexcl CDATA "¡" -- inverted exclamation mark -->
|
|
<!ENTITY cent CDATA "¢" -- cent sign -->
|
|
<!ENTITY pound CDATA "£" -- pound sterling sign -->
|
|
<!ENTITY curren CDATA "¤" -- general currency sign -->
|
|
<!ENTITY yen CDATA "¥" -- yen sign -->
|
|
<!ENTITY brvbar CDATA "¦" -- broken (vertical) bar -->
|
|
<!ENTITY sect CDATA "§" -- section sign -->
|
|
<!ENTITY uml CDATA "¨" -- umlaut (dieresis) -->
|
|
<!ENTITY copy CDATA "©" -- copyright sign -->
|
|
<!ENTITY ordf CDATA "ª" -- ordinal indicator, feminine -->
|
|
<!ENTITY laquo CDATA "«" -- angle quotation mark, left -->
|
|
<!ENTITY not CDATA "¬" -- not sign -->
|
|
<!ENTITY shy CDATA "­" -- soft hyphen -->
|
|
<!ENTITY reg CDATA "®" -- registered sign -->
|
|
<!ENTITY macr CDATA "¯" -- macron -->
|
|
<!ENTITY deg CDATA "°" -- degree sign -->
|
|
<!ENTITY plusmn CDATA "±" -- plus-or-minus sign -->
|
|
<!ENTITY sup2 CDATA "²" -- superscript two -->
|
|
<!ENTITY sup3 CDATA "³" -- superscript three -->
|
|
<!ENTITY acute CDATA "´" -- acute accent -->
|
|
<!ENTITY micro CDATA "µ" -- micro sign -->
|
|
<!ENTITY para CDATA "¶" -- pilcrow (paragraph sign) -->
|
|
<!ENTITY middot CDATA "·" -- middle dot -->
|
|
<!ENTITY cedil CDATA "¸" -- cedilla -->
|
|
<!ENTITY sup1 CDATA "¹" -- superscript one -->
|
|
<!ENTITY ordm CDATA "º" -- ordinal indicator, masculine -->
|
|
<!ENTITY raquo CDATA "»" -- angle quotation mark, right -->
|
|
<!ENTITY frac14 CDATA "¼" -- fraction one-quarter -->
|
|
<!ENTITY frac12 CDATA "½" -- fraction one-half -->
|
|
<!ENTITY frac34 CDATA "¾" -- fraction three-quarters -->
|
|
<!ENTITY iquest CDATA "¿" -- inverted question mark -->
|
|
<!ENTITY Agrave CDATA "À" -- capital A, grave accent -->
|
|
<!ENTITY Aacute CDATA "Á" -- capital A, acute accent -->
|
|
<!ENTITY Acirc CDATA "Â" -- capital A, circumflex accent -->
|
|
<!ENTITY Atilde CDATA "Ã" -- capital A, tilde -->
|
|
<!ENTITY Auml CDATA "Ä" -- capital A, dieresis or umlaut -->
|
|
<!ENTITY Aring CDATA "Å" -- capital A, ring -->
|
|
<!ENTITY AElig CDATA "Æ" -- capital AE diphthong (ligature) -->
|
|
<!ENTITY Ccedil CDATA "Ç" -- capital C, cedilla -->
|
|
<!ENTITY Egrave CDATA "È" -- capital E, grave accent -->
|
|
<!ENTITY Eacute CDATA "É" -- capital E, acute accent -->
|
|
<!ENTITY Ecirc CDATA "Ê" -- capital E, circumflex accent -->
|
|
<!ENTITY Euml CDATA "Ë" -- capital E, dieresis or umlaut -->
|
|
<!ENTITY Igrave CDATA "Ì" -- capital I, grave accent -->
|
|
<!ENTITY Iacute CDATA "Í" -- capital I, acute accent -->
|
|
<!ENTITY Icirc CDATA "Î" -- capital I, circumflex accent -->
|
|
<!ENTITY Iuml CDATA "Ï" -- capital I, dieresis or umlaut -->
|
|
<!ENTITY ETH CDATA "Ð" -- capital Eth, Icelandic -->
|
|
<!ENTITY Ntilde CDATA "Ñ" -- capital N, tilde -->
|
|
<!ENTITY Ograve CDATA "Ò" -- capital O, grave accent -->
|
|
<!ENTITY Oacute CDATA "Ó" -- capital O, acute accent -->
|
|
<!ENTITY Ocirc CDATA "Ô" -- capital O, circumflex accent -->
|
|
<!ENTITY Otilde CDATA "Õ" -- capital O, tilde -->
|
|
<!ENTITY Ouml CDATA "Ö" -- capital O, dieresis or umlaut -->
|
|
<!ENTITY times CDATA "×" -- multiply sign -->
|
|
<!ENTITY Oslash CDATA "Ø" -- capital O, slash -->
|
|
<!ENTITY Ugrave CDATA "Ù" -- capital U, grave accent -->
|
|
<!ENTITY Uacute CDATA "Ú" -- capital U, acute accent -->
|
|
<!ENTITY Ucirc CDATA "Û" -- capital U, circumflex accent -->
|
|
<!ENTITY Uuml CDATA "Ü" -- capital U, dieresis or umlaut -->
|
|
<!ENTITY Yacute CDATA "Ý" -- capital Y, acute accent -->
|
|
<!ENTITY THORN CDATA "Þ" -- capital Thorn, Icelandic -->
|
|
<!ENTITY szlig CDATA "ß" -- small sharp s, German (sz ligature) -->
|
|
<!ENTITY agrave CDATA "à" -- small a, grave accent -->
|
|
<!ENTITY aacute CDATA "á" -- small a, acute accent -->
|
|
<!ENTITY acirc CDATA "â" -- small a, circumflex accent -->
|
|
<!ENTITY atilde CDATA "ã" -- small a, tilde -->
|
|
<!ENTITY auml CDATA "ä" -- small a, dieresis or umlaut -->
|
|
<!ENTITY aring CDATA "å" -- small a, ring -->
|
|
<!ENTITY aelig CDATA "æ" -- small ae diphthong (ligature) -->
|
|
<!ENTITY ccedil CDATA "ç" -- small c, cedilla -->
|
|
<!ENTITY egrave CDATA "è" -- small e, grave accent -->
|
|
<!ENTITY eacute CDATA "é" -- small e, acute accent -->
|
|
<!ENTITY ecirc CDATA "ê" -- small e, circumflex accent -->
|
|
<!ENTITY euml CDATA "ë" -- small e, dieresis or umlaut -->
|
|
<!ENTITY igrave CDATA "ì" -- small i, grave accent -->
|
|
<!ENTITY iacute CDATA "í" -- small i, acute accent -->
|
|
<!ENTITY icirc CDATA "î" -- small i, circumflex accent -->
|
|
<!ENTITY iuml CDATA "ï" -- small i, dieresis or umlaut -->
|
|
<!ENTITY eth CDATA "ð" -- small eth, Icelandic -->
|
|
<!ENTITY ntilde CDATA "ñ" -- small n, tilde -->
|
|
<!ENTITY ograve CDATA "ò" -- small o, grave accent -->
|
|
<!ENTITY oacute CDATA "ó" -- small o, acute accent -->
|
|
<!ENTITY ocirc CDATA "ô" -- small o, circumflex accent -->
|
|
<!ENTITY otilde CDATA "õ" -- small o, tilde -->
|
|
<!ENTITY ouml CDATA "ö" -- small o, dieresis or umlaut -->
|
|
<!ENTITY divide CDATA "÷" -- divide sign -->
|
|
<!ENTITY oslash CDATA "ø" -- small o, slash -->
|
|
<!ENTITY ugrave CDATA "ù" -- small u, grave accent -->
|
|
<!ENTITY uacute CDATA "ú" -- small u, acute accent -->
|
|
<!ENTITY ucirc CDATA "û" -- small u, circumflex accent -->
|
|
<!ENTITY uuml CDATA "ü" -- small u, dieresis or umlaut -->
|
|
<!ENTITY yacute CDATA "ý" -- small y, acute accent -->
|
|
<!ENTITY thorn CDATA "þ" -- small thorn, Icelandic -->
|
|
<!ENTITY yuml CDATA "ÿ" -- small y, dieresis or umlaut -->
|
|
*/
|
|
|
|
#define NORMAL_CHARS @"(\"&\", \
|
|
\">\", \
|
|
\"<\", \
|
|
\"\\\"\", \
|
|
\"\\U00A3\", \
|
|
\"|\", \
|
|
\"\\U00B0\", \
|
|
\"\\U00E9\", \
|
|
\"\\U00E7\", \
|
|
\"\\U00E0\", \
|
|
\"\\U00E2\", \
|
|
\"\\U00E3\", \
|
|
\"\\U00E8\", \
|
|
\"\\U00EA\", \
|
|
\"\\U00EC\", \
|
|
\"\\U00EE\", \
|
|
\"\\U00F1\", \
|
|
\"\\U00F4\", \
|
|
\"\\U00F5\", \
|
|
\"\\U00F9\", \
|
|
\"\\U00FB\")"
|
|
|
|
#define HTML_CHARS @"( \"&\", \
|
|
\">\", \
|
|
\"<\", \
|
|
\""\", \
|
|
\"£\", \
|
|
\"¦\", \
|
|
\"°\", \
|
|
\"é\", \
|
|
\"ç\", \
|
|
\"à\", \
|
|
\"â\", \
|
|
\"ã\", \
|
|
\"è\", \
|
|
\"ê\", \
|
|
\"ì\", \
|
|
\"î\", \
|
|
\"ñ\", \
|
|
\"ô\", \
|
|
\"õ\", \
|
|
\"ù\", \
|
|
\"û\")"
|
|
|
|
#define ESCAPING_HTML_ATTRIBUTE_VALUE_NORMAL_CHARS @"( \
|
|
\"&\", \
|
|
\"\\\"\", \
|
|
\"<\", \
|
|
\">\", \
|
|
\"\t\", \
|
|
\"\n\", \
|
|
\"\r\" )"
|
|
|
|
#define ESCAPING_HTML_ATTRIBUTE_VALUE_HTML_CHARS @"( \
|
|
\"&\", \
|
|
\""\", \
|
|
\"<\", \
|
|
\">\", \
|
|
\"	\", \
|
|
\" \",\
|
|
\" \" )"
|
|
|
|
#define ESCAPING_HTML_STRING_NORMAL_CHARS @"( \
|
|
\"&\", \
|
|
\"\\\"\", \
|
|
\"<\", \
|
|
\">\" )"
|
|
|
|
#define ESCAPING_HTML_STRING_HTML_CHARS @"( \
|
|
\"&\", \
|
|
\""\", \
|
|
\"<\", \
|
|
\">\" )"
|
|
|
|
GSWHTMLConvertingStruct htmlConvertStruct;
|
|
GSWHTMLConvertingStruct htmlConvertAttributeValueStruct;
|
|
GSWHTMLConvertingStruct htmlConvertHTMLString;
|
|
|
|
static unichar unicodeBR[5];
|
|
static NSUInteger unicodeBRLen=4;
|
|
#define htmlCharsMaxLength 9
|
|
#define htmlCharsAtIndex(convStructPtr,i) (((convStructPtr)->htmlChars)+((i)*(htmlCharsMaxLength+1)))
|
|
|
|
|
|
static Class mutableStringClass = Nil;
|
|
static Class stringClass=Nil;
|
|
static SEL stringWithCharactersSEL=NULL;
|
|
static SEL stringWithStringSEL=NULL;
|
|
static IMP stringClass_stringWithCharactersIMP=NULL;
|
|
static IMP stringClass_stringWithStringIMP=NULL;
|
|
|
|
static void initNormalHTMLChars(GSWHTMLConvertingStruct* htmlConvertStruct,
|
|
NSString* normalCharsPropertyListString,
|
|
NSString* htmlCharsPropertyListString)
|
|
{
|
|
NSArray* normalCharsStringArray=[normalCharsPropertyListString propertyList];
|
|
NSArray* htmlCharsStringArray=[htmlCharsPropertyListString propertyList];
|
|
NSUInteger i=0;
|
|
htmlConvertStruct->charsCount=[normalCharsStringArray count];
|
|
NSCAssert([htmlCharsStringArray count]==htmlConvertStruct->charsCount,
|
|
@"html and normal characters array have not the same count of elements");
|
|
htmlConvertStruct->normalChars=NSZoneMalloc(NSDefaultMallocZone(),sizeof(unichar)*(htmlConvertStruct->charsCount));
|
|
htmlConvertStruct->htmlChars=NSZoneMalloc(NSDefaultMallocZone(),sizeof(unichar)*(htmlCharsMaxLength+1)*(htmlConvertStruct->charsCount));
|
|
htmlConvertStruct->htmlCharsLen=NSZoneMalloc(NSDefaultMallocZone(),sizeof(NSUInteger)*(htmlConvertStruct->charsCount));
|
|
|
|
for(i=0;i<(htmlConvertStruct->charsCount);i++)
|
|
{
|
|
NSString* htmlString=[htmlCharsStringArray objectAtIndex:i];
|
|
htmlConvertStruct->htmlCharsLen[i]=[htmlString length];
|
|
NSCAssert1(htmlConvertStruct->htmlCharsLen[i]<=htmlCharsMaxLength,
|
|
@"html character at inde i is too long",i);
|
|
|
|
htmlConvertStruct->normalChars[i]=[[normalCharsStringArray objectAtIndex:i]characterAtIndex:0];
|
|
[htmlString getCharacters:htmlCharsAtIndex(htmlConvertStruct,i)];
|
|
};
|
|
}
|
|
|
|
//static void testStringByConvertingHTML();
|
|
|
|
void NSStringHTML_Initialize()
|
|
{
|
|
static BOOL initialized=NO;
|
|
if (!initialized)
|
|
{
|
|
initialized=YES;
|
|
|
|
initNormalHTMLChars(&htmlConvertStruct,
|
|
NORMAL_CHARS,
|
|
HTML_CHARS);
|
|
|
|
initNormalHTMLChars(&htmlConvertAttributeValueStruct,
|
|
ESCAPING_HTML_ATTRIBUTE_VALUE_NORMAL_CHARS,
|
|
ESCAPING_HTML_ATTRIBUTE_VALUE_HTML_CHARS);
|
|
|
|
initNormalHTMLChars(&htmlConvertHTMLString,
|
|
ESCAPING_HTML_STRING_NORMAL_CHARS,
|
|
ESCAPING_HTML_STRING_HTML_CHARS);
|
|
|
|
[@"<BR>" getCharacters:unicodeBR];
|
|
|
|
ASSIGN(mutableStringClass,[NSMutableString class]);
|
|
ASSIGN(stringClass,[NSString class]);
|
|
|
|
stringWithCharactersSEL=@selector(stringWithCharacters:length:);
|
|
stringWithStringSEL=@selector(stringWithString:);
|
|
stringClass_stringWithCharactersIMP=[stringClass methodForSelector:stringWithCharactersSEL];
|
|
stringClass_stringWithStringIMP=[stringClass methodForSelector:stringWithStringSEL];
|
|
|
|
//testStringByConvertingHTML();
|
|
};
|
|
};
|
|
|
|
//====================================================================
|
|
#define GSWMemMove(dst, src, size); \
|
|
{ \
|
|
memmove(dst, src, size); \
|
|
};
|
|
|
|
#define HTML_TEST_STRINGS @"(\"\", \
|
|
\"ABCDEF\", \
|
|
\"&12\\U00E9\", \
|
|
\"&\n1\", \
|
|
\"&\r\n2\\U00E8\", \
|
|
\"<ee>\")"
|
|
|
|
|
|
void allocOrReallocUnicharString(unichar** ptrPtr,NSUInteger* capacityPtr,NSUInteger length,NSUInteger newCapacity)
|
|
{
|
|
//Really need ?
|
|
if (newCapacity>*capacityPtr)
|
|
{
|
|
NSUInteger allocSize=newCapacity*sizeof(unichar);
|
|
unichar* newPtr=GSAutoreleasedBuffer(allocSize);
|
|
|
|
NSCAssert1(newPtr,@"Can't alloc %"PRIuPTR" allocSize bytes",
|
|
allocSize);
|
|
|
|
if (length>0)
|
|
{
|
|
// Copy previous parts
|
|
GSWMemMove(newPtr,
|
|
*ptrPtr,
|
|
length*sizeof(unichar));
|
|
};
|
|
|
|
*capacityPtr=newCapacity;
|
|
*ptrPtr=newPtr;
|
|
};
|
|
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
NSString* baseStringByConvertingToHTML(NSString* string,GSWHTMLConvertingStruct* convStructPtr,BOOL includeCRLF)
|
|
{
|
|
NSString* str=nil;
|
|
NSUInteger length=[string length];
|
|
NSCAssert(convStructPtr->charsCount>0,@"normalChars not initialized");
|
|
if (length>0)
|
|
{
|
|
BOOL changed=NO;
|
|
NSUInteger srcLen=0;
|
|
NSUInteger dstLen=0;
|
|
unichar* dstChars=NULL;
|
|
NSUInteger capacity=0;
|
|
unichar* pString=NULL;
|
|
NSUInteger i=0;
|
|
NSUInteger j=0;
|
|
NSUInteger allocMargin=max(128,length/2);
|
|
allocOrReallocUnicharString(&pString,&capacity,0,length+1+allocMargin);
|
|
[string getCharacters:pString];
|
|
//NSDebugFLog(@"string=%@",string);
|
|
while(i<length)
|
|
{
|
|
srcLen=0;
|
|
unichar c=pString[i];
|
|
//NSDebugFLog(@"i=%d: c=%c",i,(char)c);
|
|
if (includeCRLF && c=='\r')
|
|
{
|
|
if (i<(length-1)
|
|
&& pString[i+1]=='\n')
|
|
{
|
|
srcLen=2;
|
|
dstLen=unicodeBRLen;
|
|
dstChars=unicodeBR;
|
|
}
|
|
else
|
|
{
|
|
srcLen=1;
|
|
dstLen=unicodeBRLen;
|
|
dstChars=unicodeBR;
|
|
};
|
|
}
|
|
else if (c=='\n' && includeCRLF)
|
|
{
|
|
srcLen=1;
|
|
dstLen=4;
|
|
dstChars=unicodeBR;
|
|
}
|
|
else
|
|
{
|
|
for(j=0;j<convStructPtr->charsCount;j++)
|
|
{
|
|
if (c==convStructPtr->normalChars[j])
|
|
{
|
|
srcLen=1;
|
|
dstLen=convStructPtr->htmlCharsLen[j];
|
|
dstChars=htmlCharsAtIndex(convStructPtr,j);
|
|
break;
|
|
};
|
|
};
|
|
};
|
|
if (srcLen>0)
|
|
{
|
|
changed=YES;
|
|
if (length+1+dstLen-srcLen>capacity)
|
|
allocOrReallocUnicharString(&pString,&capacity,length,capacity+allocMargin);
|
|
GSWMemMove(pString+i+dstLen,pString+i+srcLen,sizeof(unichar)*(length-i-srcLen));
|
|
GSWMemMove(pString+i,dstChars,sizeof(unichar)*dstLen);
|
|
i+=dstLen;
|
|
length+=dstLen-srcLen;
|
|
}
|
|
else
|
|
i++;
|
|
};
|
|
if (changed)
|
|
str=(*stringClass_stringWithCharactersIMP)(stringClass,stringWithCharactersSEL,pString,length);
|
|
else if ([string isKindOfClass:mutableStringClass])
|
|
str=(*stringClass_stringWithStringIMP)(stringClass,stringWithStringSEL,string);
|
|
else
|
|
str=string;
|
|
}
|
|
else if ([string isKindOfClass:mutableStringClass])
|
|
str=@"";
|
|
else
|
|
str=AUTORELEASE(RETAIN(string));
|
|
return str;
|
|
};
|
|
|
|
static inline BOOL areUnicharEquals(unichar* p1,unichar* p2,NSUInteger len)
|
|
{
|
|
switch(len)
|
|
{
|
|
case 0:
|
|
NSCAssert(NO,@"Too short comparaison");
|
|
return NO;
|
|
case 1:
|
|
return *p1==*p2;
|
|
case 2:
|
|
return (*p1==*p2
|
|
&& *(p1+1)==*(p2+1));
|
|
case 3:
|
|
return (*p1==*p2
|
|
&& *(p1+1)==*(p2+1)
|
|
&& *(p1+2)==*(p2+2));
|
|
case 4:
|
|
return (*p1==*p2
|
|
&& *(p1+1)==*(p2+1)
|
|
&& *(p1+2)==*(p2+2)
|
|
&& *(p1+3)==*(p2+3));
|
|
case 5:
|
|
return (*p1==*p2
|
|
&& *(p1+1)==*(p2+1)
|
|
&& *(p1+2)==*(p2+2)
|
|
&& *(p1+3)==*(p2+3)
|
|
&& *(p1+4)==*(p2+4));
|
|
case 6:
|
|
return (*p1==*p2
|
|
&& *(p1+1)==*(p2+1)
|
|
&& *(p1+2)==*(p2+2)
|
|
&& *(p1+3)==*(p2+3)
|
|
&& *(p1+4)==*(p2+4)
|
|
&& *(p1+5)==*(p2+5));
|
|
case 7:
|
|
return (*p1==*p2
|
|
&& *(p1+1)==*(p2+1)
|
|
&& *(p1+2)==*(p2+2)
|
|
&& *(p1+3)==*(p2+3)
|
|
&& *(p1+4)==*(p2+4)
|
|
&& *(p1+5)==*(p2+5)
|
|
&& *(p1+6)==*(p2+6));
|
|
case 8:
|
|
return (*p1==*p2
|
|
&& *(p1+1)==*(p2+1)
|
|
&& *(p1+2)==*(p2+2)
|
|
&& *(p1+3)==*(p2+3)
|
|
&& *(p1+4)==*(p2+4)
|
|
&& *(p1+5)==*(p2+5)
|
|
&& *(p1+6)==*(p2+6)
|
|
&& *(p1+7)==*(p2+7));
|
|
case 9:
|
|
return (*p1==*p2
|
|
&& *(p1+1)==*(p2+1)
|
|
&& *(p1+2)==*(p2+2)
|
|
&& *(p1+3)==*(p2+3)
|
|
&& *(p1+4)==*(p2+4)
|
|
&& *(p1+5)==*(p2+5)
|
|
&& *(p1+6)==*(p2+6)
|
|
&& *(p1+7)==*(p2+7)
|
|
&& *(p1+8)==*(p2+8));
|
|
default:
|
|
NSCAssert(NO,@"Compraison too long");
|
|
return NO;
|
|
};
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
NSString* baseStringByConvertingFromHTML(NSString* string,GSWHTMLConvertingStruct* convStructPtr,BOOL includeBR)
|
|
{
|
|
NSString* str=nil;
|
|
NSUInteger length=[string length];
|
|
NSCAssert(convStructPtr->charsCount>0,@"normalChars not initialized");
|
|
if (length>0)
|
|
{
|
|
BOOL changed=NO;
|
|
NSUInteger srcLen=0;
|
|
NSUInteger dstLen=0;
|
|
unichar dstUnichar;
|
|
unichar* pString=NSZoneMalloc(NSDefaultMallocZone(),(length+1)*sizeof(unichar));
|
|
NSUInteger i=0;
|
|
NSUInteger j=0;
|
|
[string getCharacters:pString];
|
|
|
|
while(i<(length-2)) // at least 2 characters for html coded
|
|
{
|
|
srcLen=0;
|
|
if (includeBR
|
|
&& length-i>=unicodeBRLen
|
|
&& areUnicharEquals(pString+i,unicodeBR,unicodeBRLen))
|
|
{
|
|
srcLen=unicodeBRLen;
|
|
dstLen=1;
|
|
dstUnichar='\n';
|
|
}
|
|
else
|
|
{
|
|
for(j=0;j<convStructPtr->charsCount;j++)
|
|
{
|
|
if (length-i>=convStructPtr->htmlCharsLen[j]
|
|
&& areUnicharEquals(pString+i,htmlCharsAtIndex(convStructPtr,j),convStructPtr->htmlCharsLen[j]))
|
|
{
|
|
srcLen=convStructPtr->htmlCharsLen[j];
|
|
dstLen=1;
|
|
dstUnichar=convStructPtr->normalChars[j];
|
|
break;
|
|
}
|
|
};
|
|
};
|
|
if (srcLen>0)
|
|
{
|
|
changed=YES;
|
|
GSWMemMove(pString+i+dstLen,pString+i+srcLen,sizeof(unichar)*(length-i-srcLen));
|
|
GSWMemMove(pString+i,&dstUnichar,sizeof(unichar)*dstLen);
|
|
i+=dstLen;
|
|
length+=dstLen-srcLen;
|
|
};
|
|
if (srcLen==0)
|
|
i++;
|
|
};
|
|
if (changed)
|
|
str=(*stringClass_stringWithCharactersIMP)(stringClass,stringWithCharactersSEL,pString,length);
|
|
else if ([string isKindOfClass:mutableStringClass])
|
|
str=(*stringClass_stringWithStringIMP)(stringClass,stringWithStringSEL,string);
|
|
else
|
|
str=string;
|
|
NSZoneFree(NSDefaultMallocZone(), pString);
|
|
|
|
}
|
|
else if ([string isKindOfClass:mutableStringClass])
|
|
str=@"";
|
|
else
|
|
str=AUTORELEASE(RETAIN(string));
|
|
|
|
|
|
return str;
|
|
};
|
|
|
|
//====================================================================
|
|
@implementation NSString (HTMLString)
|
|
|
|
//--------------------------------------------------------------------
|
|
-(NSString*)htmlPlus2Space
|
|
{
|
|
return [self stringByReplacingString:@"+"
|
|
withString:@" "];
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
// void decodeURL(String &str)
|
|
// Convert the given URL string to a normal string. This means that
|
|
// all escaped characters are converted to their normal values. The
|
|
// escape character is '%' and is followed by 2 hex digits
|
|
// representing the octet.
|
|
//
|
|
-(NSString*) decodeURLEncoding:(NSStringEncoding) encoding
|
|
{
|
|
NSUInteger orglen = [self length];
|
|
NSMutableData *new = [NSMutableData dataWithLength: orglen];
|
|
const char *read;
|
|
char *write;
|
|
NSUInteger i,n,l;
|
|
|
|
read = [self UTF8String];
|
|
write = [new mutableBytes];
|
|
for (l=0,i=0,n=orglen;i<n;i++,l++)
|
|
{
|
|
switch (read[i])
|
|
{
|
|
case '%':
|
|
{
|
|
unsigned char chh, chl;
|
|
|
|
chh = read[++i];
|
|
chh = isdigit(chh) ? chh - '0' : (toupper(chh) - 'A') + 10;
|
|
|
|
chl = read[++i];
|
|
chl = isdigit(chl) ? chl - '0' : (toupper(chl) - 'A') + 10;
|
|
|
|
*write++ = (chh << 4)|chl;
|
|
break;
|
|
}
|
|
case '+':
|
|
{
|
|
*write++ = ' ';
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
*write++ = read[i];
|
|
}
|
|
}
|
|
}
|
|
[new setLength: l];
|
|
|
|
return AUTORELEASE([[NSString alloc] initWithData: new
|
|
encoding: encoding]);
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// void encodeURL(String &str, char *valid)
|
|
// Convert a normal string to a URL 'safe' string. This means that
|
|
// all characters not explicitly mentioned in the URL BNF will be
|
|
// escaped. The escape character is '%' and is followed by 2 hex
|
|
// digits representing the octet.
|
|
//
|
|
-(NSString*)encodeURL
|
|
{
|
|
return [self encodeURLWithValid:nil];
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(NSString*)encodeURLWithValid:(NSString*)validString
|
|
{
|
|
NSMutableString* temp=[NSMutableString stringWithCapacity:[self length]];
|
|
const char* p=NULL;
|
|
const char* valid=[validString cStringUsingEncoding:NSUTF8StringEncoding];
|
|
static char *digits = "0123456789ABCDEF";
|
|
for (p =[self cStringUsingEncoding:NSUTF8StringEncoding]; p && *p; p++)
|
|
{
|
|
if (isdigit(*p) || isalpha(*p) || (valid && strchr(valid, *p)))
|
|
[temp appendFormat:@"%c",*p];
|
|
else
|
|
[temp appendFormat:@"%%%c%c",digits[(*p >> 4) & 0x0f],digits[*p & 0x0f]];
|
|
};
|
|
return [NSString stringWithString:temp];
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
-(NSDictionary*) dictionaryQueryStringWithEncoding: (NSStringEncoding) encoding
|
|
{
|
|
return [self dictionaryWithSep1:@"&"
|
|
withSep2:@"="
|
|
withOptionUnescape:YES
|
|
forceArray:YES
|
|
encoding: encoding];
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(NSDictionary*)dictionaryWithSep1:(NSString*)sep1
|
|
withSep2:(NSString*)sep2
|
|
withOptionUnescape:(BOOL)unescape
|
|
{
|
|
return [self dictionaryWithSep1:sep1
|
|
withSep2:sep2
|
|
withOptionUnescape:unescape
|
|
forceArray:NO
|
|
encoding:[GSWMessage defaultEncoding]];
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(NSDictionary*)dictionaryWithSep1:(NSString*)sep1
|
|
withSep2:(NSString*)sep2
|
|
withOptionUnescape:(BOOL)unescape
|
|
forceArray:(BOOL)forceArray// Put value in array even if there's only one value
|
|
encoding:(NSStringEncoding) encoding
|
|
{
|
|
NSMutableDictionary* pDico=nil;
|
|
if ([self length]>0)
|
|
{
|
|
NSArray* listItems = [self componentsSeparatedByString:sep1];
|
|
NSUInteger iCount=0;
|
|
NSUInteger itemsCount=[listItems count];
|
|
IMP oaiIMP=NULL;
|
|
|
|
pDico=(NSMutableDictionary*)[NSMutableDictionary dictionary];
|
|
|
|
for(iCount=0;iCount<itemsCount;iCount++)
|
|
{
|
|
if ([GSWeb_objectAtIndexWithImpPtr(listItems,&oaiIMP,iCount) length]>0)
|
|
{
|
|
NSArray* listParam = [[listItems objectAtIndex:iCount] componentsSeparatedByString:sep2];
|
|
id key=nil;
|
|
id value=nil;
|
|
if ([listParam count]==1)
|
|
{
|
|
key=[listParam objectAtIndex:0];
|
|
if (unescape)
|
|
key=[key decodeURLEncoding: encoding];
|
|
}
|
|
else if ([listParam count]==2)
|
|
{
|
|
key=[listParam objectAtIndex:0];
|
|
value=[listParam objectAtIndex:1];
|
|
if (unescape)
|
|
{
|
|
key=[key decodeURLEncoding: encoding];
|
|
value= [value decodeURLEncoding: encoding];
|
|
};
|
|
};
|
|
if (key)
|
|
{
|
|
id newValue=nil;
|
|
id prevValue=[pDico objectForKey:key];
|
|
if (!value)
|
|
value=[NSString string];
|
|
if (prevValue)
|
|
{
|
|
if (!forceArray || [prevValue isKindOfClass:[NSArray class]])
|
|
newValue=[prevValue arrayByAddingObject:value];
|
|
else
|
|
newValue=[NSArray arrayWithObjects:prevValue,value,nil];
|
|
}
|
|
else
|
|
{
|
|
if (forceArray)
|
|
newValue=[NSArray arrayWithObject:value];
|
|
else
|
|
newValue=value;
|
|
};
|
|
[pDico setObject:newValue
|
|
forKey: key];
|
|
};
|
|
};
|
|
};
|
|
pDico=[NSDictionary dictionaryWithDictionary:pDico];
|
|
};
|
|
return pDico;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(BOOL)ismapCoordx:(NSInteger*)x
|
|
y:(NSInteger*)y
|
|
{
|
|
BOOL ok=NO;
|
|
NSScanner* scanner=[NSScanner scannerWithString:self];
|
|
if ([scanner scanInteger:x])
|
|
{
|
|
// if (x)
|
|
// {
|
|
// NSDebugMLLog(@"low",@"x=%d",*x);
|
|
// };
|
|
if ([scanner scanString:@","
|
|
intoString:NULL])
|
|
{
|
|
if ([scanner scanInteger:y])
|
|
{
|
|
// if (y)
|
|
// {
|
|
// NSDebugMLLog(@"low",@"y=%d",*y);
|
|
// };
|
|
// NSDebugMLLog(@"low",@"[scanner isAtEnd]=%d",(int)[scanner isAtEnd]);
|
|
if ([scanner isAtEnd])
|
|
{
|
|
ok=YES;
|
|
};
|
|
};
|
|
};
|
|
};
|
|
if (!ok)
|
|
{
|
|
if (x)
|
|
*x=INT_MAX;
|
|
if (y)
|
|
*y=INT_MAX;
|
|
};
|
|
return ok;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(NSString*)stringByEscapingHTMLString
|
|
{
|
|
return stringByEscapingHTMLString(self);
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(NSString*)stringByEscapingHTMLAttributeValue
|
|
{
|
|
return stringByEscapingHTMLAttributeValue(self);
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(NSString*)stringByConvertingToHTMLEntities
|
|
{
|
|
return stringByConvertingToHTMLEntities(self);
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(NSString*)stringByConvertingFromHTMLEntities
|
|
{
|
|
return stringByConvertingFromHTMLEntities(self);
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(NSString*)stringByConvertingToHTML
|
|
{
|
|
return stringByConvertingToHTML(self);
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(NSString*)stringByConvertingFromHTML
|
|
{
|
|
return stringByConvertingFromHTML(self);
|
|
};
|
|
|
|
// some hacks for use in dynamic elements
|
|
|
|
- (BOOL) isRelativeURL
|
|
{
|
|
NSRange myRange;
|
|
NSUInteger i = 0;
|
|
NSUInteger j = 0;
|
|
BOOL flag = YES;
|
|
|
|
if ([self hasPrefix:@"#"]) {
|
|
return YES;
|
|
} else {
|
|
myRange = [self rangeOfString:@"/"];
|
|
i = myRange.location;
|
|
|
|
if (i == 0) {
|
|
return NO;
|
|
}
|
|
myRange = [self rangeOfString:@":"];
|
|
j = myRange.location;
|
|
|
|
if (j == NSNotFound) {
|
|
flag = YES;
|
|
} else {
|
|
if (i != NSNotFound && i < j) {
|
|
flag = YES;
|
|
} else {
|
|
flag = NO;
|
|
}
|
|
}
|
|
}
|
|
return flag;
|
|
}
|
|
|
|
- (BOOL) isFragmentURL
|
|
{
|
|
return [self hasPrefix:@"#"];
|
|
}
|
|
|
|
@end
|
|
|