Objective Cで簡単なHTMLエスケープ/エスケープを行う簡単な方法があるかどうか疑問に思います。私が欲しいのは、この擬似コードのようなものです:
NSString *string = @"<span>Foo</span>";
[string stringByUnescapingHTML];
どっちが
<span>Foo</span>
うまくいけば、他のすべてのHTMLエンティティのエスケープを解除し、ASCII likeなどのコードも).
Cocoa Touch/UIKitにこれを行う方法はありますか?
この link には以下のソリューションが含まれています。 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ツールボックス の別の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 *)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への変換中にこれらの画像をダウンロードするためです。 :)
すべての文字を中和するソリューションです(すべてのHTMLエンコードされたエンティティをUnicode値にする)...これを私のニーズに使用しました(ユーザーから来たが、Webビュー内に配置された文字列が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 を使用することです。
これは、Mac Toolbox for MacのNSStringカテゴリGTMNSString+HTML
であり、GTMDefines.h
への依存関係が取り除かれています。追加する必要があるのは、1つの.hと1つの.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=en&q=fail&ie=UTF-8&oe=UTF-8
リテラルを生成する必要がある場合は、次のようなツールの使用を検討してください。
http://www.freeformatter.com/Java-dotnet-escape.html#ad-output
あなたのために仕事を達成するために。
this answer も参照してください。
この最も簡単な解決策は、次のようにカテゴリを作成することです。
カテゴリのヘッダーファイルは次のとおりです。
#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