Nice programing

Objective C HTML 이스케이프 / 이스케이프 해제

nicepro 2020. 10. 20. 08:08
반응형

Objective C HTML 이스케이프 / 이스케이프 해제


Objective C에서 간단한 HTML 이스케이프 / 이스케이프 해제를 수행하는 쉬운 방법이 있는지 궁금합니다. 내가 원하는 것은 다음과 같은 의사 코드입니다.

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

어떤 반환

<span>Foo</span>

다른 모든 HTML 엔티티와 Ӓ 등과 같은 ASCII 코드도 이스케이프 해제되기를 바랍니다.

Cocoa Touch / UIKit에이 작업을 수행하는 방법이 있습니까?


링크 에는 아래 솔루션 포함되어 있습니다. 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

XMLEntities에 대한NSString 카테고리를 확인하십시오 . XML 엔티티 (모든 HTML 문자 참조 포함)를 디코딩하고, XML 엔티티를 인코딩하고, 태그를 제거하고, 문자열에서 줄 바꿈과 공백을 제거하는 방법이 있습니다.

- (NSString *)stringByStrippingTags;
- (NSString *)stringByDecodingXMLEntities; // Including all HTML character references
- (NSString *)stringByEncodingXMLEntities;
- (NSString *)stringWithNewLinesAsBRs;
- (NSString *)stringByRemovingNewLinesAndWhitespace;

Mac 용 Google Toolbox의 또 다른 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, '&amp;' becomes '&'
///  Handles &#32; and &#x32; cases as well
///
//  Returns:
//    Autoreleased NSString
//
- (NSString *)gtm_stringByUnescapingFromHTML;

그리고 프로젝트에 헤더, 구현 및 GTMDefines.h.


이것은 내가 한 엄청나게 해킹 된 솔루션이지만 구문 분석에 대해 걱정하지 않고 단순히 문자열을 이스케이프하려면 다음을 수행하십시오.

-(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 매개 변수를 반대로하면됩니다.


iOS 7에서는 HTML을 가져 오는 NSAttributedString의 기능을 사용하여 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으로 변환하는 동안 해당 이미지를 다운로드하기 때문에 "정리"하는 콘텐츠에 이와 같은 태그 나 항목이 포함되어 있지 않다는 것을 확신 할 수 있습니다 . :)


여기에 모든 문자를 무력화하는 솔루션이 있습니다 (유니 코드 값에 대해 모든 HTML로 인코딩 된 엔티티를 만들어서) ... 내 필요를 위해 이것을 사용했습니다 (사용자에게서 왔지만 웹뷰 안에 배치 된 문자열이 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];

귀하의 마일리지는 다양합니다.


HTML 또는 XML 문자열을 인코딩하고 디코딩하는 가장 덜 침습적이고 가장 가벼운 방법은 GTMNSStringHTMLAdditions CocoaPod 를 사용하는 것입니다 .

이것은 단순히 .NET Core GTMNSString+HTML에 대한 종속성을 제거한 Mac 용 Google Toolbox NSString 범주 입니다 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>

이것은 사용하기 쉬운 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 스트리퍼입니다.

If you need an encoder, go here: Encode NSString for XML/HTML


MREntitiesConverter doesn't work for escaping malformed xml. It will fail on a simple URL:

http://www.google.com/search?client=safari&rls=en&q=fail&ie=UTF-8&oe=UTF-8


If you need to generate a literal you might consider using a tool like this:

http://www.freeformatter.com/java-dotnet-escape.html#ad-output

to accomplish the work for you.

See also this answer.


This easiest solution is to create a category as below:

Here’s the category’s header file:

#import <Foundation/Foundation.h>
@interface NSString (URLEncoding)
-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding;
@end

And here’s the implementation:

#import "NSString+URLEncoding.h"
@implementation NSString (URLEncoding)
-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding {
    return (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
               (CFStringRef)self,
               NULL,
               (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ",
               CFStringConvertNSStringEncodingToEncoding(encoding));
}
@end

And now we can simply do this:

NSString *raw = @"hell & brimstone + earthly/delight";
NSString *url = [NSString stringWithFormat:@"http://example.com/example?param=%@",
            [raw urlEncodeUsingEncoding:NSUTF8Encoding]];
NSLog(url);

The credits for this answer goes to the website below:-

http://madebymany.com/blog/url-encoding-an-nsstring-on-ios

Why not just using ?

NSData *data = [s dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
NSString *result = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
return result;

Noob question but in my case it works...


This is an old answer that I posted some years ago. My intention was not to provide a "good" and "respectable" solution, but a "hacky" one that might be useful under some circunstances. Please, don't use this solution unless nothing else works.

Actually, it works perfectly fine in many situations that other answers don't because the UIWebView is doing all the work. And you can even inject some javascript (which can be dangerous and/or useful). The performance should be horrible, but actually is not that bad.

There is another solution that has to be mentioned. Just create a UIWebView, load the encoded string and get the text back. It escapes tags "<>", and also decodes all html entities (e.g. "&gt;") and it might work where other's don't (e.g. using cyrillics). I don't think it's the best solution, but it can be useful if the above solutions doesn't work.

Here is a small example using 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

참고URL : https://stackoverflow.com/questions/659602/objective-c-html-escape-unescape

반응형