Подтвердить что ты не робот

Объект C HTML escape/unescape

Удивление, если есть простой способ сделать простой escape/unescape HTML в Objective C. То, что я хочу, это что-то вроде этого psuedo-кода:

NSString *string = @"<span>Foo</span>";
[string stringByUnescapingHTML];

Что возвращает

<span>Foo</span>

Надеемся, что все другие HTML-объекты также будут сохранены и даже ASCII-коды, такие как Ӓ и т.д.

Существуют ли какие-либо методы в Cocoa Touch/UIKit для этого?

4b9b3361

Ответ 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, '&amp;' becomes '&'
///  Handles &#32; and &#x32; cases as well
///
//  Returns:
//    Autoreleased NSString
//
- (NSString *)gtm_stringByUnescapingFromHTML;

И мне пришлось включить только три файла в проект: заголовок, реализация и GTMDefines.h.

Ответ 4

Это невероятно взломанное решение, которое я сделал, но если вы хотите просто избежать строки, не беспокоясь о разборе, сделайте следующее:

-(NSString *)htmlEntityDecode:(NSString *)string
    {
        string = [string stringByReplacingOccurrencesOfString:@"&quot;" withString:@"\""];
        string = [string stringByReplacingOccurrencesOfString:@"&apos;" withString:@"'"];
        string = [string stringByReplacingOccurrencesOfString:@"&lt;" withString:@"<"];
        string = [string stringByReplacingOccurrencesOfString:@"&gt;" withString:@">"];
        string = [string stringByReplacingOccurrencesOfString:@"&amp;" withString:@"&"]; // Do this last so that, e.g. @"&amp;lt;" goes to @"&lt;" 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:
// &lt;TheBeat&gt;Goes On&lt;/TheBeat&gt;

// Decoding a string with XML / HTML encoded elements
NSString *stringToDecode = @"&lt;TheBeat&gt;Goes On&lt;/TheBeat&gt;";
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];

Ответ 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