Je me demandais s’il existait un moyen simple d’échapper/dévier HTML dans Objective C. Ce que je veux, c’est quelque chose comme ce code psuedo:
NSString *string = @"<span>Foo</span>";
[string stringByUnescapingHTML];
Qui retourne
<span>Foo</span>
Espérons que toutes les autres entités HTML et les codes ASCII tels que, etc.
Y a-t-il des méthodes dans Cocoa Touch/UIKit pour le faire?
Ce link contient la solution ci-dessous. Cocoa CF possède la fonction CFXMLCreateStringByUnescapingEntities mais n’est pas disponible sur l’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
Découvrez ma catégorie NSString pour XMLEntities . Il existe des méthodes pour décoder les entités XML (y compris toutes les références de caractères HTML), coder les entités XML, supprimer les balises et supprimer les nouvelles lignes et les espaces d'une chaîne
- (NSString *)stringByStrippingTags;
- (NSString *)stringByDecodingXMLEntities; // Including all HTML character references
- (NSString *)stringByEncodingXMLEntities;
- (NSString *)stringWithNewLinesAsBRs;
- (NSString *)stringByRemovingNewLinesAndWhitespace;
Une autre catégorie HTML NSString de Google Toolbox for Mac
Malgré son nom, cela fonctionne aussi sur 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;
Et je ne devais inclure que trois fichiers dans le projet: en-tête, implémentation et GTMDefines.h
.
C'est une solution incroyablement complexe que j'ai faite, mais si vous voulez simplement échapper à une chaîne sans vous soucier de l'analyse, procédez comme suit:
-(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;
}
Je sais que ce n'est pas du tout élégant, mais le travail est fait. Vous pouvez ensuite décoder un élément en appelant:
string = [self htmlEntityDecode:string];
Comme je l'ai dit, c'est hacky mais ça marche. SI vous voulez encoder une chaîne, il suffit d’inverser les paramètres stringByReplacingOccurencesOfString.
Dans iOS 7, vous pouvez utiliser la capacité de NSAttributedString à importer du HTML pour convertir des entités HTML en NSString.
Par exemple:
@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
Puis dans votre code lorsque vous souhaitez nettoyer les entités:
NSString *cleanString = [[NSAttributedString attributedStringWithHTMLString:question.title] string];
C’est probablement le moyen le plus simple, mais je ne sais pas à quel point il est performant. Vous devriez probablement vous assurer que le contenu de votre "nettoyage" ne contient aucune balise <img>
ou quelque chose du genre, car cette méthode téléchargera ces images lors de la conversion HTML à NSAttributedString. :)
Voici une solution qui neutralise tous les caractères (en leur faisant toutes les entités codées HTML pour leur valeur unicode) ... Utilisée pour mon besoin Attaques XSS):
Interface:
@interface NSString (escape)
- (NSString*)stringByEncodingHTMLEntities;
@end
La mise en oeuvre:
@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
Exemple d'utilisation:
UIWebView *webView = [[UIWebView alloc] init];
NSString *userInput = @"<script>alert('This is an XSS ATTACK!');</script>";
NSString *safeInput = [userInput stringByEncodingHTMLEntities];
[webView loadHTMLString:safeInput baseURL:nil];
Votre kilométrage variera.
Le moyen le moins invasif et le plus léger de coder et de décoder des chaînes HTML ou XML consiste à utiliser le fichier GTMNSStringHTMLAdditions CocoaPod .
Il s’agit simplement de la catégorie GTMNSString+HTML
de la boîte à outils Google pour la boîte à outils Mac pour Mac, dépourvue de la dépendance sur GTMDefines.h
. Donc, tout ce que vous devez ajouter est un .h et un .m, et vous êtes prêt à partir.
Exemple:
#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>
Ceci est une implémentation de catégorie NSString facile à utiliser:
Il est loin d’être complet mais vous pouvez ajouter des entités manquantes à partir d’ici: http://code.google.com/p/statz/source/browse/trunk/NSString%2BHTML.m
Usage:
#import "NSString+HTML.h"
NSString *raw = [NSString stringWithFormat:@"<div></div>"];
NSString *escaped = [raw htmlEscapedString];
Le convertisseur MREntitiesConverter ci-dessus est un outil de suppression HTML, pas un encodeur.
Si vous avez besoin d'un encodeur, allez ici: Encode NSString pour XML/HTML
MREntitiesConverter ne fonctionne pas pour échapper à XML malformé. Cela échouera sur une simple URL:
http://www.google.com/search?client=safari&rls=en&q=fail&ie=UTF-8&oe=UTF-8
Si vous devez générer un littéral, vous pouvez envisager d'utiliser un outil comme celui-ci:
http://www.freeformatter.com/Java-dotnet-escape.html#ad-output
d'accomplir le travail pour vous.
Voir aussi cette réponse .
Cette solution la plus simple consiste à créer une catégorie comme ci-dessous:
Voici le fichier d’en-tête de la catégorie:
#import <Foundation/Foundation.h>
@interface NSString (URLEncoding)
-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding;
@end
Et voici la mise en œuvre:
#import "NSString+URLEncoding.h"
@implementation NSString (URLEncoding)
-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding {
return (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)self,
NULL,
(CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ",
CFStringConvertNSStringEncodingToEncoding(encoding));
}
@end
Et maintenant, nous pouvons simplement faire ceci:
NSString *raw = @"hell & brimstone + earthly/delight";
NSString *url = [NSString stringWithFormat:@"http://example.com/example?param=%@",
[raw urlEncodeUsingEncoding:NSUTF8Encoding]];
NSLog(url);
Les crédits pour cette réponse vont au site web ci-dessous: -
http://madebymany.com/blog/url-encoding-an-nsstring-on-ios