Удивление, если есть простой способ сделать простой escape/unescape HTML в Objective C. То, что я хочу, это что-то вроде этого psuedo-кода:
NSString *string = @"<span>Foo</span>";
[string stringByUnescapingHTML];
Что возвращает
<span>Foo</span>
Надеемся, что все другие HTML-объекты также будут сохранены и даже ASCII-коды, такие как Ӓ и т.д.
Существуют ли какие-либо методы в Cocoa Touch/UIKit для этого?
Ответ 1
Эта ссылка содержит приведенное ниже решение. Cocoa 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
Ответ 2
Ознакомьтесь с моей категорией NSString для XMLEntities. Существуют методы для декодирования объектов XML (включая все ссылки на HTML-символы), кодирования объектов XML, удаления дескрипторов и удаления строк и пробелов из строки:
- (NSString *)stringByStrippingTags;
- (NSString *)stringByDecodingXMLEntities; // Including all HTML character references
- (NSString *)stringByEncodingXMLEntities;
- (NSString *)stringWithNewLinesAsBRs;
- (NSString *)stringByRemovingNewLinesAndWhitespace;
Ответ 3
Еще одна категория HTML NSString из Google Toolbox для Mac
Несмотря на название, это работает и на 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
.
Ответ 4
Это невероятно взломанное решение, которое я сделал, но если вы хотите просто избежать строки, не беспокоясь о разборе, сделайте следующее:
-(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.
Ответ 5
В 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.:)
Ответ 6
Здесь решение, которое нейтрализует все символы (делая их все закодированные HTML-объекты сущностями для их значения в unicode)... Используется для моей потребности (убедитесь, что строка, которая пришла от пользователя, но была помещена внутри webview cann ' t есть любые атаки 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];
Ваш пробег будет отличаться.
Ответ 7
Наименее инвазивный и самый легкий способ кодирования и декодирования строк HTML или XML состоит в использовании GTMNSStringHTMLAdditions CocoaPod.
Это просто категория инструментов Google Toolbox для Mac 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>
Ответ 8
Это простая в использовании реализация категории 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];
Ответ 9
MREntitiesConverter выше - стриппер для HTML, а не кодировщик.
Если вам нужен кодер, перейдите сюда: Кодировать NSString для XML/HTML
Ответ 10
MREntitiesConverter не работает для экранирования искаженного xml. Он провалится по простому URL-адресу:
http://www.google.com/search?client=safari&rls=en&q=fail&ie=UTF-8&oe=UTF-8
Ответ 11
Если вам нужно создать литерал, вы можете использовать такой инструмент:
http://www.freeformatter.com/java-dotnet-escape.html#ad-output
чтобы выполнить эту работу для вас.
См. также этот ответ.
Ответ 12
Это самое простое решение - создать категорию, как показано ниже:
Вот заголовок файла категорий:
#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
Ответ 13
Почему бы просто не использовать?
NSData *data = [s dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
NSString *result = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
return result;
Вопрос Noob, но в моем случае это работает...
Ответ 14
Это старый ответ, который я опубликовал несколько лет назад. Мое намерение было не предоставлять "хорошее" и "респектабельное" решение, а "хакерское" которые могут быть полезны при некоторых мероприятиях. Пожалуйста, не используйте это решение, если ничего не работает.
Вообще-то, во многих ситуациях он отлично работает, ответы не связаны с тем, что 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