Кодирование сущности HTML (конвертировать '<' в '&lt;') на iPhone в objective-c

Я разрабатываю приложение для iPhone, у которого есть возможности отправки сообщений вApp. Пока что так хорошо, но теперь я хочу избежать html-инъекций, поскольку некоторые части почты - это созданные пользователем тексты.

В основном я ищу что-то вроде этого:

// inits
NSString *sourceString = [NSString stringWithString:@"Hello world! Grüße dich Welt <-- This is in German."];

//                                          -----   THAT WHAT I'M LOOKING FOR
// pseudo-code                              |
//                                          V
NSString *htmlEncodedString = [sourceString htmlEncode];

// log
NSLog(@"source string: %@", sourceString);
NSLog(@"encoded string: %@", htmlEncodedString);

Ожидаемый результат
source string: Hello world! Grüße dich Welt <-- This is in German.
encoded string: Hello world! Gr&#252;&#223;e dich Welt &lt;-- This is in German.

Я уже googled и просмотрел несколько вопросов и ответов SO, но все они, похоже, связаны с кодировкой URL, и это не то, что мне действительно нужно (я пробовал stringByAddingPercentEscapesUsingEncoding без везения - он создает% C3% BC из "ü", который должен быть ü).

Образец кода будет действительно большим (исправление моей?)...

- Страница Спасибо заранее,
Маркус

Ответ 1

Ознакомьтесь с моей категорией NSString для HTML. Вот доступные методы:

- (NSString *)stringByConvertingHTMLToPlainText;
- (NSString *)stringByDecodingHTMLEntities;
- (NSString *)stringByEncodingHTMLEntities;
- (NSString *)stringWithNewLinesAsBRs;
- (NSString *)stringByRemovingNewLinesAndWhitespace;

Ответ 2

Спасибо @all. В итоге я использовал свою собственную реализацию:

//
// _________________________________________
//
// textToHtml
// _________________________________________
//
- (NSString*)textToHtml:(NSString*)htmlString {
    htmlString = [htmlString stringByReplacingOccurrencesOfString:@"&"  withString:@"&amp;"];
    htmlString = [htmlString stringByReplacingOccurrencesOfString:@"<"  withString:@"&lt;"];
    htmlString = [htmlString stringByReplacingOccurrencesOfString:@">"  withString:@"&gt;"];
    htmlString = [htmlString stringByReplacingOccurrencesOfString:@"""" withString:@"&quot;"];    
    htmlString = [htmlString stringByReplacingOccurrencesOfString:@"'"  withString:@"&#039;"];
    htmlString = [htmlString stringByReplacingOccurrencesOfString:@"\n" withString:@"<br>"];
    return htmlString;
}

Ответ 3

Небольшое улучшение кода @Markus [Изменить < br/ > до </p> , избегать нескольких пространств]

- (NSString*)textToHtml:(NSString*)htmlString {
    htmlString = [htmlString stringByReplacingOccurrencesOfString:@"&"  withString:@"&amp;"];
    htmlString = [htmlString stringByReplacingOccurrencesOfString:@"<"  withString:@"&lt;"];
    htmlString = [htmlString stringByReplacingOccurrencesOfString:@">"  withString:@"&gt;"];
    htmlString = [htmlString stringByReplacingOccurrencesOfString:@"""" withString:@"&quot;"];
    htmlString = [htmlString stringByReplacingOccurrencesOfString:@"'"  withString:@"&#039;"];

    htmlString = [@"<p>" stringByAppendingString:htmlString];
    htmlString = [htmlString stringByAppendingString:@"</p>"];
    htmlString = [htmlString stringByReplacingOccurrencesOfString:@"\n" withString:@"</p><p>"];
//  htmlString = [htmlString stringByReplacingOccurrencesOfString:@"\n" withString:@"<br />"];
    while ([htmlString rangeOfString:@"  "].length > 0) {
        htmlString = [htmlString stringByReplacingOccurrencesOfString:@"  " withString:@"&nbsp;&nbsp;"];
    }
    return htmlString;
}

Ответ 4

Я искал подобное решение, и это помогло мне

NSString* value = @"<&>";
const void* keys[1] = {CFSTR("somekey")};
const void* values[1] = {value};    
CFDictionaryRef dicRef =  CFDictionaryCreate(kCFAllocatorDefault, keys, values, 1, nil, nil);    
CFDataRef dataRef = CFPropertyListCreateData(kCFAllocatorDefault, dicRef, kCFPropertyListXMLFormat_v1_0, 0, NULL);    
NSString *str = [[NSString alloc]initWithData:(NSData *)dataRef encoding:NSUTF8StringEncoding];    
NSRange start =[str rangeOfString:@"string>"];
NSRange end =[str rangeOfString:@"</string"];    
NSString *substr = [str substringWithRange:NSMakeRange(start.location+start.length, end.location-(start.location+start.length))];
[str release];
CFRelease(dicRef);
CFRelease(dataRef);    

//Подстрока теперь кодируется html-объектом

Я использую некоторые функции, которые используются при сохранении файлов plist. Надеюсь, это поможет.

Ответ 5

Предполагая, что кодировка символа электронной почты поддерживает Unicode - скажем, UTF-8 - не могли бы вы просто найти и заменить вхождения <, > и & с помощью &lt, &gt и &amp;?

Ответ 6

Я расширяю ответ @Markus, потому что в моем случае я отправляю строку JSON, поэтому мне нужно добавить некоторый escape, это моя функция:

Примечание: ссылка на исключение из w3schools. https://www.w3schools.com/tags/ref_urlencode.asp

- (NSString*)convertStringToHTMLEscape:(NSString*)stringContent
{
    stringContent = [stringContent stringByReplacingOccurrencesOfString:@"{" withString:@"%7B"];
    stringContent = [stringContent stringByReplacingOccurrencesOfString:@"}" withString:@"%7D"];
    stringContent = [stringContent stringByReplacingOccurrencesOfString:@"[" withString:@"%5B"];
    stringContent = [stringContent stringByReplacingOccurrencesOfString:@"]" withString:@"%5D"];
    stringContent = [stringContent stringByReplacingOccurrencesOfString:@" " withString:@"%20"];
    stringContent = [stringContent stringByReplacingOccurrencesOfString:@"\"" withString:@"%22"];
    stringContent = [stringContent stringByReplacingOccurrencesOfString:@"\\" withString:@"%5C"];
    stringContent = [stringContent stringByReplacingOccurrencesOfString:@"/" withString:@"%2F"];

    return stringContent;
}