web-dev-qa-db-fra.com

Objective C HTML escape/unescape

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?

73
Alex Wayne

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
30
Andrew Grant

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;
90

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, '&amp;' becomes '&'
///  Handles &#32; and &#x32; 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.

35
Nikita Rybak

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:@"&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;
    }

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.

28
Andrew Kozlik

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. :)

11
orj

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.

5
BadPirate

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:
// &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>
4
T Blank

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];
2
Blago

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

1
Brain2000

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

0
richcollins

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 .

0
diadyne

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
0
Hashim Akhtar