为JavaScript输入转义NSString

时间:2011-04-06 16:26:27

标签: javascript iphone objective-c escaping ascii

我有一串ASCII字符(由[NSString stringWithFormat:@“%c”,someNumber]随机创建),我想使用该字符串作为javascript方法的输入。类似的东西:

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

如何逃避NSString?我试着查看encodeURI和decodeURI,但还没有找到任何解决方案。

8 个答案:

答案 0 :(得分:13)

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

答案 1 :(得分:9)

经过无数个小时研究解决方案后,我想出了什么。结果我遇到了一个问题,我没有逃过回车\ r \ n这个功能解决了我的问题。

-(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

答案 2 :(得分:5)

通过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];

答案 3 :(得分:1)

Here's the relevant part of the ES5 specification

  

除了结束引号字符,反斜杠,回车符,行分隔符,段落分隔符和换行符之外,所有字符都可以按字面意思显示在字符串文字中。任何字符都可能以转义序列的形式出现。

某些字符存在反斜杠转义(您可以找到几页),任何字符都可以用十六进制表示为\uXXXX。它们(在示例中)在规范中向下解释了几页。

答案 4 :(得分:1)

如果您需要一个可以使用扩展ASCII符号(例如拉丁符号)和/或unicode的解决方案,您可以使用:

- (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表示。

答案 5 :(得分:0)

你有没有尝试过类似的东西:

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

将转义函数放入字符串调用可能对您有用。这真的取决于你想要逃脱的原因

答案 6 :(得分:0)

以上是@ zetachang的回答。你必须在javascript函数的参数中使用双引号。如,

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

答案 7 :(得分:0)

我使用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