/** NSString+HTML.m - GSWeb: NSString / HTML Copyright (C) 1999-2003 Free Software Foundation, Inc. Written by: Manuel Guesdon Date: Jan 1999 $Revision$ $Date$ $Id$ This file is part of the GNUstep Web Library. 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. **/ #include "config.h" RCS_ID("$Id$") #include "GSWeb.h" #include static NSArray* normalChars=nil; static NSArray* htmlChars=nil; /* */ void initHtmlChars() { if (!normalChars) { normalChars=[[NSArray arrayWithObjects: @"&", @">", @"<", @"\"", @"£", @"|", @"°", @"é", @"ç", @"à", @"â", @"ã", @"è", @"ê", @"ì", @"î", @"ñ", @"ô", @"õ", @"ù", @"û", nil ] retain]; }; if (!htmlChars) { htmlChars=[[NSArray arrayWithObjects: @"&", @">", @"<", @""", @"£", @"¦", @"°", @"é", @"ç", @"à", @"â", @"ã", @"è", @"ê", @"ì", @"î", @"ñ", @"ô", @"õ", @"ù", @"û", nil ] retain]; }; }; //==================================================================== @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*)decodeURL { //TODO speed unichar* unichars=NULL; unichar uniChar=0; NSString* voidString=nil; NSString* temp=nil; const char* p=NULL; int uniCharsIndex=0; NSDebugMLLog(@"low",@"self=%@",self); voidString=[self htmlPlus2Space]; NSDebugMLLog(@"low",@"voidString=%@",voidString); unichars=GSAutoreleasedBuffer(sizeof(unichar)*([voidString length]+1)); NSDebugMLLog(@"low",@"[voidString cString]=%s",[voidString cString]); for (p=[voidString cString];p && *p;p++) { if (*p == '%') { // // 2 hex digits follow... // int i=0; uniChar=0; for (i=0;p[1] && i<2;i++) { p++; NSDebugMLLog(@"low",@"*p=%c %u",(char)*p,(unsigned int)*p); uniChar <<= 4; NSDebugMLLog(@"low",@"uniChar=%x",(unsigned int)uniChar); if (isdigit(*p)) uniChar+=*p-'0'; else uniChar+=toupper(*p)-'A'+10; NSDebugMLLog(@"low",@"uniChar=%x",(unsigned int)uniChar); }; } else uniChar=(unsigned char)*p; unichars[uniCharsIndex]=uniChar; uniCharsIndex++; }; temp=[NSString stringWithCharacters:unichars length:uniCharsIndex]; NSDebugMLLog(@"low",@"temp=%@",temp); NSDebugMLLog(@"low",@"temp data=%@",[temp dataUsingEncoding:NSISOLatin1StringEncoding]); return temp; }; //-------------------------------------------------------------------- // 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 cString]; static char *digits = "0123456789ABCDEF"; for (p =[self cString]; 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*)dictionaryQueryString { return [self dictionaryWithSep1:@"&" withSep2:@"=" withOptionUnescape:YES forceArray:YES]; }; //-------------------------------------------------------------------- -(NSDictionary*)dictionaryWithSep1:(NSString*)sep1 withSep2:(NSString*)sep2 withOptionUnescape:(BOOL)unescape { return [self dictionaryWithSep1:sep1 withSep2:sep2 withOptionUnescape:unescape forceArray:NO]; }; //-------------------------------------------------------------------- -(NSDictionary*)dictionaryWithSep1:(NSString*)sep1 withSep2:(NSString*)sep2 withOptionUnescape:(BOOL)unescape forceArray:(BOOL)forceArray// Put value in array even if there's only one value { NSMutableDictionary* pDico=nil; if ([self length]>0) { NSArray* listItems = [self componentsSeparatedByString:sep1]; int iCount=0; pDico=(NSMutableDictionary*)[NSMutableDictionary dictionary]; for(iCount=0;iCount<[listItems count];iCount++) { if ([[listItems objectAtIndex: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 decodeURL]; } else if ([listParam count]==2) { key=[listParam objectAtIndex:0]; value=[listParam objectAtIndex:1]; if (unescape) { key=[key decodeURL]; value=[value decodeURL]; }; }; 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:(int*)x y:(int*)y { BOOL ok=NO; NSScanner* scanner=[NSScanner scannerWithString:self]; if ([scanner scanInt:x]) { if (x) { NSDebugMLLog(@"low",@"x=%d",*x); }; if ([scanner scanString:@"," intoString:NULL]) { if ([scanner scanInt: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 { //TODO speed NSString* str=nil; if ([self length]>0) { NSMutableString* tmp=[self mutableCopy]; [tmp replaceString:@"&" withString:@"&"]; [tmp replaceString:@"\"" withString:@"""]; [tmp replaceString:@"<" withString:@"<"]; [tmp replaceString:@">" withString:@">"]; str = AUTORELEASE([tmp copy]); RELEASE(tmp); }; return str; }; //-------------------------------------------------------------------- -(NSString*)stringByEscapingHTMLAttributeValue { //TODO speed NSString* str=nil; if ([self length]>0) { NSMutableString* tmp=[self mutableCopy]; [tmp replaceString:@"&" withString:@"&"]; [tmp replaceString:@"\"" withString:@"""]; [tmp replaceString:@"<" withString:@"<"]; [tmp replaceString:@">" withString:@">"]; [tmp replaceString:@"\t" withString:@" "]; [tmp replaceString:@"\n" withString:@" "]; [tmp replaceString:@"\r" withString:@" "]; str = AUTORELEASE([tmp copy]); RELEASE(tmp); }; return str; }; //-------------------------------------------------------------------- -(NSString*)stringByConvertingToHTMLEntities { //TODO speed NSString* str=nil; if ([self length]>0) { int i=0; NSMutableString* tmp=[self mutableCopy]; if (!normalChars) initHtmlChars(); for(i=0;i<[normalChars count];i++) { [tmp replaceString:[normalChars objectAtIndex:i] withString:[htmlChars objectAtIndex:i]]; }; str = AUTORELEASE([tmp copy]); RELEASE(tmp); }; return str; }; //-------------------------------------------------------------------- -(NSString*)stringByConvertingFromHTMLEntities { NSString* str=nil; if ([self length]>0) { int i=0; NSMutableString* tmp=[self mutableCopy]; if (!normalChars) initHtmlChars(); for(i=0;i<[normalChars count];i++) { [tmp replaceString:[htmlChars objectAtIndex:i] withString:[normalChars objectAtIndex:i]]; }; str = AUTORELEASE([tmp copy]); RELEASE(tmp); }; return str; }; //-------------------------------------------------------------------- -(NSString*)stringByConvertingToHTML { NSString* str=nil; if ([self length]>0) { //TODO speed NSMutableString* tmp=[[self stringByConvertingToHTMLEntities] mutableCopy]; [tmp replaceString:@"\r\n" withString:@"
"]; [tmp replaceString:@"\r" withString:@"
"]; [tmp replaceString:@"\n" withString:@"
"]; str = AUTORELEASE([tmp copy]); RELEASE(tmp); }; return str; }; //-------------------------------------------------------------------- -(NSString*)stringByConvertingFromHTML { NSString* str=nil; if ([self length]>0) { //TODO speed NSMutableString* tmp=[[self stringByConvertingFromHTMLEntities] mutableCopy]; [tmp replaceString:@"
" withString:@"\n"]; str = AUTORELEASE([tmp copy]); RELEASE(tmp); }; return str; }; @end