想知道是否有一种简单的方法可以在Objective C中执行简单的HTML转义/转义。我想要的是这样的伪代码:
NSString *string = @"<span>Foo</span>";
[string stringByUnescapingHTML];
哪个返回
<span>Foo</span>
希望也转义所有其他HTML实体,甚至ASCII码(例如Ӓ等)。
Cocoa Touch / UIKit中有什么方法可以做到这一点?
想知道是否有一种简单的方法可以在Objective C中执行简单的HTML转义/转义。我想要的是这样的伪代码:
NSString *string = @"<span>Foo</span>";
[string stringByUnescapingHTML];
哪个返回
<span>Foo</span>
希望也转义所有其他HTML实体,甚至ASCII码(例如Ӓ等)。
Cocoa Touch / UIKit中有什么方法可以做到这一点?
Answers:
此链接包含以下解决方案。可可CF具有CFXMLCreateStringByUnescapingEntities函数,但在iPhone上不可用。
@interface MREntitiesConverter : NSObject <NSXMLParserDelegate>{
NSMutableString* resultString;
}
@property (nonatomic, retain) NSMutableString* resultString;
- (NSString*)convertEntitiesInString:(NSString*)s;
@end
@implementation MREntitiesConverter
@synthesize resultString;
- (id)init
{
if([super init]) {
resultString = [[NSMutableString alloc] init];
}
return self;
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)s {
[self.resultString appendString:s];
}
- (NSString*)convertEntitiesInString:(NSString*)s {
if (!s) {
NSLog(@"ERROR : Parameter string is nil");
}
NSString* xmlStr = [NSString stringWithFormat:@"<d>%@</d>", s];
NSData *data = [xmlStr dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
NSXMLParser* xmlParse = [[[NSXMLParser alloc] initWithData:data] autorelease];
[xmlParse setDelegate:self];
[xmlParse parse];
return [NSString stringWithFormat:@"%@",resultString];
}
- (void)dealloc {
[resultString release];
[super dealloc];
}
@end
CFXMLCreateStringByUnescapingEntities
在iOS上不可用,您也可以从CFXMLParser.c(从Core Foundation源代码)复制其定义,然后在项目中使用它。我已经对其进行了测试,并且可以正常工作。
查看我的NSString类别中的XMLEntities。有以下方法可以解码XML实体(包括所有HTML字符引用),对XML实体进行编码,剥离标签并从字符串中删除换行符和空格:
- (NSString *)stringByStrippingTags;
- (NSString *)stringByDecodingXMLEntities; // Including all HTML character references
- (NSString *)stringByEncodingXMLEntities;
- (NSString *)stringWithNewLinesAsBRs;
- (NSString *)stringByRemovingNewLinesAndWhitespace;
pod "GTMNSStringHTMLAdditions"
。请参阅2015
Google Toolbox for Mac的另一个HTML NSString类别
尽管名称,但它也适用于iOS。
http://google-toolbox-for-mac.googlecode.com/svn/trunk/Foundation/GTMNSString+HTML.h
/// Get a string where internal characters that are escaped for HTML are unescaped
//
/// For example, '&' becomes '&'
/// Handles   and 2 cases as well
///
// Returns:
// Autoreleased NSString
//
- (NSString *)gtm_stringByUnescapingFromHTML;
而且我只需要在项目中包括三个文件:标头,实现和GTMDefines.h
。
'&'
变为'&'
,则该内容也将在- (NSString *)gtm_stringByEscapingForHTML;
文件的稍后定义中介绍。
GTMDefines.h
-fno-objc-arc
编译器标志也不会停止将该结构标记为Xcode中的错误。
这是我做过的一个骇人听闻的解决方案,但是如果您只想转义一个字符串而不必担心解析,请执行以下操作:
-(NSString *)htmlEntityDecode:(NSString *)string
{
string = [string stringByReplacingOccurrencesOfString:@""" withString:@"\""];
string = [string stringByReplacingOccurrencesOfString:@"'" withString:@"'"];
string = [string stringByReplacingOccurrencesOfString:@"<" withString:@"<"];
string = [string stringByReplacingOccurrencesOfString:@">" withString:@">"];
string = [string stringByReplacingOccurrencesOfString:@"&" withString:@"&"]; // Do this last so that, e.g. @"&lt;" goes to @"<" not @"<"
return string;
}
我知道这绝非优雅,但可以完成工作。然后,您可以通过调用以下内容来解码元素:
string = [self htmlEntityDecode:string];
就像我说的那样,它很笨拙,但是可以用。如果要编码字符串,只需反转stringByReplacingOccurencesOfString参数。
在iOS 7中,您可以使用NSAttributedString的导入HTML的功能将HTML实体转换为NSString。
例如:
@interface NSAttributedString (HTML)
+ (instancetype)attributedStringWithHTMLString:(NSString *)htmlString;
@end
@implementation NSAttributedString (HTML)
+ (instancetype)attributedStringWithHTMLString:(NSString *)htmlString
{
NSDictionary *options = @{ NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType,
NSCharacterEncodingDocumentAttribute :@(NSUTF8StringEncoding) };
NSData *data = [htmlString dataUsingEncoding:NSUTF8StringEncoding];
return [[NSAttributedString alloc] initWithData:data options:options documentAttributes:nil error:nil];
}
@end
然后在您要清理实体的代码中:
NSString *cleanString = [[NSAttributedString attributedStringWithHTMLString:question.title] string];
这可能是最简单的方法,但是我不知道它的性能如何。您应该非常确定“清洗”的内容中不包含任何<img>
标签或类似内容,因为此方法将在HTML到NSAttributedString转换期间下载这些图像。:)
this is test
从离开<b>this</b> is <a href='test'>test</a>
。
这是一个中和所有字符的解决方案(通过使它们成为所有Unicode值的HTML编码实体)...用于我的需要(确保来自用户但放置在webview内的字符串不能有任何字符) XSS攻击):
接口:
@interface NSString (escape)
- (NSString*)stringByEncodingHTMLEntities;
@end
实现方式:
@implementation NSString (escape)
- (NSString*)stringByEncodingHTMLEntities {
// Rather then mapping each individual entity and checking if it needs to be replaced, we simply replace every character with the hex entity
NSMutableString *resultString = [NSMutableString string];
for(int pos = 0; pos<[self length]; pos++)
[resultString appendFormat:@"&#x%x;",[self characterAtIndex:pos]];
return [NSString stringWithString:resultString];
}
@end
用法示例:
UIWebView *webView = [[UIWebView alloc] init];
NSString *userInput = @"<script>alert('This is an XSS ATTACK!');</script>";
NSString *safeInput = [userInput stringByEncodingHTMLEntities];
[webView loadHTMLString:safeInput baseURL:nil];
您的里程会有所不同。
@"&#x%04x;"
,除此之外,我还要添加一个简单的字母数字检测器并复制此类字符无需转义。
编码和解码HTML或XML字符串的侵入性最小,最轻便的方法是使用GTMNSStringHTMLAdditions CocoaPod。
它只是适用于Mac的Google Toolbox NSString类别GTMNSString+HTML
,去除了对的依赖GTMDefines.h
。因此,您只需添加一个.h和一个.m,您就可以开始了。
例:
#import "GTMNSString+HTML.h"
// Encoding a string with XML / HTML elements
NSString *stringToEncode = @"<TheBeat>Goes On</TheBeat>";
NSString *encodedString = [stringToEncode gtm_stringByEscapingForHTML];
// encodedString looks like this now:
// <TheBeat>Goes On</TheBeat>
// Decoding a string with XML / HTML encoded elements
NSString *stringToDecode = @"<TheBeat>Goes On</TheBeat>";
NSString *decodedString = [stringToDecode gtm_stringByUnescapingFromHTML];
// decodedString looks like this now:
// <TheBeat>Goes On</TheBeat>
这是一个易于使用的NSString类别实现:
它远未完成,但是您可以从此处添加一些缺少的实体:http : //code.google.com/p/statz/source/browse/trunk/NSString%2BHTML.m
用法:
#import "NSString+HTML.h"
NSString *raw = [NSString stringWithFormat:@"<div></div>"];
NSString *escaped = [raw htmlEscapedString];
上面的MREntitiesConverter是HTML剥离程序,不是编码器。
如果需要编码器,请转到此处:为XML / HTML编码NSString
MREntitiesConverter不适用于转义格式错误的xml。在简单的URL上将失败:
http://www.google.com/search?client=safari&rls=zh-CN&q=fail&ie=UTF-8&oe=UTF-8
如果您需要生成文字,则可以考虑使用如下工具:
http://www.freeformatter.com/java-dotnet-escape.html#ad-output
为您完成工作。
另请参阅此答案。
最简单的解决方案是创建如下类别:
这是类别的头文件:
#import <Foundation/Foundation.h>
@interface NSString (URLEncoding)
-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding;
@end
这是实现:
#import "NSString+URLEncoding.h"
@implementation NSString (URLEncoding)
-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding {
return (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)self,
NULL,
(CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ",
CFStringConvertNSStringEncodingToEncoding(encoding));
}
@end
现在我们可以简单地做到这一点:
NSString *raw = @"hell & brimstone + earthly/delight";
NSString *url = [NSString stringWithFormat:@"http://example.com/example?param=%@",
[raw urlEncodeUsingEncoding:NSUTF8Encoding]];
NSLog(url);
此答案的学分转到以下网站:
http://madebymany.com/blog/url-encoding-an-nsstring-on-ios
为什么不只是使用?
NSData *data = [s dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
NSString *result = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
return result;
菜鸟问题,但就我而言,它可行...
这是我几年前发布的旧答案。我的意图不是提供“好的”和“可敬的”解决方案,而是提供在某些情况下可能有用的“ hacky”解决方案。请不要使用此解决方案,除非其他方法无效。
实际上,它在很多情况下都可以很好地工作,而其他答案却没有,因为UIWebView可以完成所有工作。您甚至可以注入一些javascript(可能是危险的和/或有用的)。性能应该很糟糕,但实际上并不算差。
必须提及另一种解决方案。只需创建一个UIWebView
,加载编码后的字符串并取回文本即可。它转义了标签“ <>”,并且还解码了所有html实体(例如“&gt;”),并且可能在其他人不在的地方工作(例如,使用西里尔字母)。我认为这不是最好的解决方案,但是如果上述解决方案不起作用,它可能会很有用。
这是一个使用ARC的小例子:
@interface YourClass() <UIWebViewDelegate>
@property UIWebView *webView;
@end
@implementation YourClass
- (void)someMethodWhereYouGetTheHtmlString:(NSString *)htmlString {
self.webView = [[UIWebView alloc] init];
NSString *htmlString = [NSString stringWithFormat:@"<html><body>%@</body></html>", self.description];
[self.webView loadHTMLString:htmlString baseURL:nil];
self.webView.delegate = self;
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
self.webView = nil;
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
self.webView = nil;
NSString *escapedString = [self.webView stringByEvaluatingJavaScriptFromString:@"document.body.textContent;"];
}
- (void)webViewDidStartLoad:(UIWebView *)webView {
// Do Nothing
}
@end