Escape NSString для ввода JavaScript - PullRequest
6 голосов
/ 06 апреля 2011

У меня есть строка символов ASCII (созданная случайным образом [NSString stringWithFormat: @ "% c", someNumber]), и я хочу использовать эту строку в качестве входных данных для метода javascript. Что-то вроде:

[webView_ stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"my_javascript_method(\"%@\")", myASCIIString]];

Как мне избежать NSString? Я пытался заглянуть в encodeURI и decodeURI, но пока не нашел решения.

Ответы [ 8 ]

13 голосов
/ 26 ноября 2012

NSJSONSerialization прямо в углу.Для перехода от NSString к Javascript строковый литерал является сложным и может быть легко сделан неправильно.(JSONKit используйте строки кода, чтобы справиться с этим https://github.com/johnezang/JSONKit/blob/82157634ca0ca5b6a4a67a194dd11f15d9b72835/JSONKit.m#L1423)

Ниже приведен метод небольшой категории для экранирования объекта NSString.

#import "NSString+JavascriptEscape.h"

@implementation NSString (JavascriptEscape)

- (NSString *)stringEscapedForJavasacript {
    // valid JSON object need to be an array or dictionary
    NSArray* arrayForEncoding = @[self];
    NSString* jsonString = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:arrayForEncoding options:0 error:nil] encoding:NSUTF8StringEncoding];

    NSString* escapedString = [jsonString substringWithRange:NSMakeRange(2, jsonString.length - 4)];
    return escapedString;
}

@end

Также следует обратить внимание на одну вещьВы должны использовать двойные кавычки в аргументе функции javascript. Например,

NSString *javascriptCall = 
    [NSString stringWithFormat:@"MyJavascriptFunction(\"%@\")", escapedString];

[self.webView stringByEvaluatingJavaScriptFromString:javascriptCall];
10 голосов
/ 29 марта 2012

После бесчисленных часов поиска решения, вот что я придумала. Оказывается, у меня возникла проблема, когда я не избежал возврата каретки, поэтому эта функция решила мои проблемы.

-(NSString *)addBackslashes:(NSString *)string {
    /*

     Escape characters so we can pass a string via stringByEvaluatingJavaScriptFromString

     */

    // Escape the characters
    string = [string stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"];
    string = [string stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""];
    string = [string stringByReplacingOccurrencesOfString:@"\'" withString:@"\\\'"];
    string = [string stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"];
    string = [string stringByReplacingOccurrencesOfString:@"\r" withString:@"\\r"];
    string = [string stringByReplacingOccurrencesOfString:@"\f" withString:@"\\f"];
    return string;
}

Вот отличный веб-сайт, который я нашел и который привел меня к этому решению. http://www.wilsonmar.com/1eschars.htm

5 голосов
/ 06 апреля 2011

Под ASCII я полагаю, вы имеете в виду, что это байт в диапазоне от 0x00 до 0x7F. В этом диапазоне, согласно http://www.json.org, вам необходимо выбрать только символы \, " и контрольные символы: 0x00-0x1F и 0x7F. Управляющие символы становятся немного хитрыми, если вы делаете простые замены, поэтому я бы проходил через символ за символом для экранирования строки, может быть, что-то вроде этого (совсем не тестировалось):

const char *chars = [myASCIIString UTF8String];
NSMutableString *escapedString = [NSMutableString string];
while (*chars)
{
    if (*chars == '\\')
        [escapedString appendString:@"\\\\"];
    else if (*chars == '"')
        [escapedString appendString:@"\\\""];
    else if (*chars < 0x1F || *chars == 0x7F)
        [escapedString appendFormat:@"\\u%04X", (int)*chars];
    else
        [escapedString appendFormat:@"%c", *chars];
    ++chars;
}
NSString *js = [NSString stringWithFormat:@"my_js_function(\"%@\")", escapedString];
1 голос
/ 29 января 2014

Если вам нужно решение, которое будет работать с расширенными символами ASCII (например, латинскими символами) и / или юникодом, вы можете использовать это:

- (NSString*) escapeStringForJavascript:(NSString*)input
{
    NSMutableString* ret = [NSMutableString string];
    int i;
    for (i = 0; i < input.length; i++)
    {
        unichar c = [input characterAtIndex:i];
        if (c == '\\')
        {
            // escape backslash
            [ret appendFormat:@"\\\\"];
        }
        else if (c == '"')
        {
            // escape double quotes
            [ret appendFormat:@"\\\""];
        }
        else if (c >= 0x20 && c <= 0x7E)
        {
            // if it is a printable ASCII character (other than \ and "), append directly
            [ret appendFormat:@"%c", c];
        }
        else
        {
            // if it is not printable standard ASCII, append as a unicode escape sequence
            [ret appendFormat:@"\\u%04X", c];
        }
    }
    return ret;
}

Я не знаю, как это происходит с кодовыми точкамивыше этого представимого unichar.Похоже, что такие символы также не могут быть представлены в javascript.

1 голос
/ 06 апреля 2011

Вот соответствующая часть спецификации ES5 :

Все символы могут появляться буквально в строковом литерале, кроме символа закрывающей кавычки, обратной косой черты, возврата каретки, разделителя строк, разделителя абзацев и перевода строки. Любой символ может появиться в виде escape-последовательности.

Для некоторых символов есть экранирование с обратной косой чертой (вы можете найти пару страниц внизу), и любой символ может быть представлен в шестнадцатеричном виде как \uXXXX. Они объяснены (с примерами) на нескольких страницах в спецификации.

0 голосов
/ 27 сентября 2015

Я бы использовал NSJSONSerialization для преобразования строки в массив JSON, а затем вставил полученную строку JSON в параметр функции JavaScript.Таким образом, мне не нужно беспокоиться о том, содержится ли строка JSON в одинарных или двойных кавычках.

NSString* inputString = ... // your raw string to escape
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:@[inputString] options:0 error:nil];
NSString* jsString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSString* jsScript = [NSString stringWithFormat:@"yourFunction(%@[0])",jsString];
// then pass jsScript to a JavaScript interpreter
0 голосов
/ 14 августа 2014

Это продолжение ответа @ zetachang выше.Вы должны использовать двойные кавычки в аргументе функции javascript.Например,

NSString *javascriptCall = 
    [NSString stringWithFormat:@"MyJavascriptFunction(\"%@\")", escapedString];
[self.webView stringByEvaluatingJavaScriptFromString:javascriptCall];
0 голосов
/ 06 апреля 2011

Вы пробовали что-нибудь похожее на:

[webView_ stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"my_javascript_method(escape(\"%@\"))", myASCIIString]];

Простое добавление функции escape в строковый вызов может работать для вас.Это действительно зависит, ПОЧЕМУ вы хотите, чтобы это сбежало

...