将 UITextView / UITextField 中的空格编码为 URL 格式

发布于 2024-07-22 20:43:06 字数 1124 浏览 6 评论 0原文

我正在尝试将 UITextView 或 UITextField 的内容作为参数发送到 php 文件

NSString *urlstr = [[NSString alloc] initWithFormat:@"http://server.com/file.php?name=%@&tags=%@&entry=%@",nameField.text, tagsField.text, dreamEntry.text];

当我记录 urlstr 时,只要 UITextView 或 UITextField 不包含空格,url 格式就可以。 我该如何将空格转换为 %20 ?

这里编辑

的是目前的代码,它不仅崩溃而且没有正确编码 url。

name=John Doe&tags=recurring night&entry=Testing 测试测试

转换为

name=John -1844684964oe&tags=recurringightmare&entry=Testing 4.214929e-307sting -1.992836e+00sting

- (IBAction)sendButtonPressed:(id)sender
{

    NSString *urlString = [[NSString alloc] initWithFormat:@"http://server.com/file.php?name=%@&tags=%@&entry=%@", nameField.text, tagsField.text, dreamEntry.text];

    NSString *encodedString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

    NSURL *url = [[NSURL alloc] initWithString:encodedString];

    NSLog(encodedString);

    NSLog(urlString);

    [urlString release];
    [url release];
    [encodedString release];


}

I'm trying to send the contents of UITextView or UITextField as parameters to a php file

NSString *urlstr = [[NSString alloc] initWithFormat:@"http://server.com/file.php?name=%@&tags=%@&entry=%@",nameField.text, tagsField.text, dreamEntry.text];

When i log urlstr, the url format is ok just as long as the UITextView or UITextField don't contain spaces. How would i go about converting the spaces to %20 ?

edit

here is the code at present, which not only crashes but isn't encoding the url properly.

name=John Doe&tags=recurring nightmare&entry=Testing testing testing

is converted to

name=John -1844684964oe&tags=recurringightmare&entry=Testing 4.214929e-307sting -1.992836e+00sting

- (IBAction)sendButtonPressed:(id)sender
{

    NSString *urlString = [[NSString alloc] initWithFormat:@"http://server.com/file.php?name=%@&tags=%@&entry=%@", nameField.text, tagsField.text, dreamEntry.text];

    NSString *encodedString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

    NSURL *url = [[NSURL alloc] initWithString:encodedString];

    NSLog(encodedString);

    NSLog(urlString);

    [urlString release];
    [url release];
    [encodedString release];


}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

蔚蓝源自深海 2024-07-29 20:43:06

实际上,之前的所有答案都至少包含一些不准确之处,对于用户在 TextFields 中提供的文本的许多常见值来说,这些值将无法与服务器正确通信

stringByAddingPercentEscapesUsingEncoding: 百分比转义所有不是有效 URL 的字符人物。 此方法应该对整个 URL 应用一次。

之前的答案声称 stringByAddingPercentEscapesUsingEncoding: 的工作方式类似于许多脚本语言中的 URL 构建类,您不应将其应用于整个 URL 字符串,但事实并非如此。 任何人都可以通过检查其输出中是否有未转义的 &? 来轻松验证这一点。 因此,应用于整个字符串是可以的,但应用于“动态”url 内容是不够的。

前面的答案是正确的,因为您必须对 CGI 查询字符串中的名称和值做更多的工作。 由于 CGI 由 RFC3875 指定,因此这通常称为 RFC3875 百分比转义。 它确保您的名称和值不包含属于有效 URL 字符但在 URL 的其他部分中很重要的字符(;?@&=$+ >、{}<>,

然而,最后对整个字符串进行纯 URL 百分比转义以确保字符串中的所有字符都是有效的 URL 字符也非常重要。 虽然您在示例中没有这样做,但一般来说,字符串的“静态”部分中可能存在不是有效 URL 字符的字符,因此您也需要对这些字符进行转义。

不幸的是,NSString 无法让我们转义 RFC3875 重要字符,因此我们必须深入研究 CFString 才能做到这一点。 显然使用 CFString 很痛苦,所以我通常将 Category 添加到 NSString 上,如下所示:

@interface NSString (RFC3875)
- (NSString *)stringByAddingRFC3875PercentEscapesUsingEncoding:(NSStringEncoding)encoding;
@end

@implementation NSString (RFC3875)
- (NSString *)stringByAddingRFC3875PercentEscapesUsingEncoding:(NSStringEncoding)encoding {
    CFStringEncoding cfEncoding = CFStringConvertNSStringEncodingToEncoding(encoding);
    NSString *rfcEscaped = (NSString *)CFURLCreateStringByAddingPercentEscapes(
                                                NULL, 
                                                (CFStringRef)self,
                                                NULL, 
                                                (CFStringRef)@";/?:@&=$+{}<>,",
                                                cfEncoding);
    return [rfcEscaped autorelease];
}
@end

有了这个 Category ,原来的问题可以通过以下方法正确解决:

NSString *urlEscapedBase = [@"http://server.com/file.php" stringByAddingPercentEscapesUsingEncoding:
                                            NSUTF8StringEncoding];
NSString *rfcEscapedName = [nameField.text stringByAddingRFC3875PercentEscapesUsingEncoding:
                                                NSUTF8StringEncoding];
NSString *rfcEscapedTags = [tagsField.text stringByAddingRFC3875PercentEscapesUsingEncoding:
                                                NSUTF8StringEncoding];
NSString *rfcEscapedEntry = [dreamEntry.text stringByAddingRFC3875PercentEscapesUsingEncoding:
                                                NSUTF8StringEncoding];

NSString *urlStr = [NSString stringWithFormat:@"%@?name=%@&tags=%@&entry=%@",
                                urlEscapedBase,
                                rfcEscapedName,
                                rfcEscapedTags,
                                rfcEscapedEntry];

NSURL *url = [NSURL URLWithString:urlStr];

这是一个有点变量重的问题,只是更清楚一点。 另请注意,提供给 stringWithFormat: 的变量列表不应以 nil 结尾。 格式字符串描述了其后应包含的变量的精确数量。 另外,从技术上讲,查询字符串名称(名称、标签、条目等)的字符串当然应该通过 stringByAddingPercentEscapesUsingEncoding: 运行,但在这个小示例中,我们可以很容易地看到它们不包含无效的 URL 字符。

要了解为什么以前的解决方案不正确,请假设 dreamEntry.text 中的用户输入文本包含 &,这并非不可能。 使用以前的解决方案,当服务器获取该文本时,该字符后面的所有文本都将丢失,因为未转义的“&”符号将被服务器解释为结束该查询字符串对的值部分。

Actually, all of the previous answers contain at least some inaccuracies, which for many common values of user provided text in the TextFields would not correctly communicate with the server

stringByAddingPercentEscapesUsingEncoding: percent escapes all characters which are not valid URL characters. This method should applied once to the entire URL.

A previous answer claims that stringByAddingPercentEscapesUsingEncoding: works like the URL building classes in many scripting languages, where you should not apply it to the entire URL string, but it doesn't. Anyone can easily verify this by checking its output for unescaped &s and ?s. So it is fine to apply to the entire string, but it is not enough to apply to your 'dynamic' url content.

The previous answer is right in that you have to do some more work to the names and values that go into your CGI query string. Since CGI is specified by RFC3875, this is often referred to as RFC3875 percent escaping. It makes sure that your names and values don't contain characters that are valid URL characters but which are significant in other parts of the URL (;, ?, :, @, &, =, $, +, {, }, <, >, and ,)

However, it is very important to also finish by doing plain URL percent escapes on the full string to make sure that all characters in the string are valid URL characters. While you don't in your example, in general there could be characters in a 'static' part of the string which are not valid URL characters, so you do need to escape those as well.

Unfortunately, NSString doesn't give us the power to escape the RFC3875 significant characters so we have to dip down into CFString to do so. Obviously using CFString is a pain so I generally add a Category onto NSString like so:

@interface NSString (RFC3875)
- (NSString *)stringByAddingRFC3875PercentEscapesUsingEncoding:(NSStringEncoding)encoding;
@end

@implementation NSString (RFC3875)
- (NSString *)stringByAddingRFC3875PercentEscapesUsingEncoding:(NSStringEncoding)encoding {
    CFStringEncoding cfEncoding = CFStringConvertNSStringEncodingToEncoding(encoding);
    NSString *rfcEscaped = (NSString *)CFURLCreateStringByAddingPercentEscapes(
                                                NULL, 
                                                (CFStringRef)self,
                                                NULL, 
                                                (CFStringRef)@";/?:@&=$+{}<>,",
                                                cfEncoding);
    return [rfcEscaped autorelease];
}
@end

With this Category in place, the original problem could be correctly solved with the following:

NSString *urlEscapedBase = [@"http://server.com/file.php" stringByAddingPercentEscapesUsingEncoding:
                                            NSUTF8StringEncoding];
NSString *rfcEscapedName = [nameField.text stringByAddingRFC3875PercentEscapesUsingEncoding:
                                                NSUTF8StringEncoding];
NSString *rfcEscapedTags = [tagsField.text stringByAddingRFC3875PercentEscapesUsingEncoding:
                                                NSUTF8StringEncoding];
NSString *rfcEscapedEntry = [dreamEntry.text stringByAddingRFC3875PercentEscapesUsingEncoding:
                                                NSUTF8StringEncoding];

NSString *urlStr = [NSString stringWithFormat:@"%@?name=%@&tags=%@&entry=%@",
                                urlEscapedBase,
                                rfcEscapedName,
                                rfcEscapedTags,
                                rfcEscapedEntry];

NSURL *url = [NSURL URLWithString:urlStr];

This is a little variable heavy just be more clear. Also note that the variable list provided to stringWithFormat: should not be nil terminated. The format string describes the precise number of variables that should follow it. Also, technically the strings for query string names (name, tags, entry,..) should be run through stringByAddingPercentEscapesUsingEncoding: as a matter of course but in this small example we can easily see that they contain no invalid URL characters.

To see why the previous solutions are incorrect, imagine that the user input text in dreamEntry.text contains an &, which is not unlikely. With the previous solutions, all text following that character would be lost by the time the server got that text, since the unescaped ampersand would be interpreted by the server as ending the value portion of that query string pair.

℉絮湮 2024-07-29 20:43:06

您可以获取您的 URL 并使用:

NSString *urlStr = [[NSString alloc] initWithFormat:@"http://server.com/file.php?name=%@&tags=%@&entry=%@",nameField.text, tagsField.text, dreamEntry.text];

NSString *encStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

You can take your URL and use:

NSString *urlStr = [[NSString alloc] initWithFormat:@"http://server.com/file.php?name=%@&tags=%@&entry=%@",nameField.text, tagsField.text, dreamEntry.text];

NSString *encStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
滴情不沾 2024-07-29 20:43:06

您不应该对整个字符串进行 URL 转义,而应该对动态组件进行 URL 转义。 尝试

NSString *urlStr = [NSString stringWithFormat:@"http://server.com/file.php?name=%@&tags=%@&entry=%@",
                        [nameField.text stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
                        [tagsField.text stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
                        [dreamEntry.text stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
                        nil];
NSURL *url = [NSURL URLWithString:urlStr];

代码的第二个问题(无疑是奇怪打印的原因)是您将字符串直接传递给 NSLog,因此它被视为格式字符串。 你需要用它

NSLog(@"%@", encodedString);

来代替。 这将使其按预期打印。

编辑:代码的第三个问题是您混合了自动释放和拥有的对象,然后在最后释放它们。 看看您创建的 3 个对象,以及随后释放的对象。 其中一个不应稍后发布,因为它是由不以 alloc、copy 或 new 开头的方法生成的。 识别所讨论的对象是留给读者的练习。

You're not supposed to URL-escape the entire string, you're supposed to URL-escape the dynamic components. Try

NSString *urlStr = [NSString stringWithFormat:@"http://server.com/file.php?name=%@&tags=%@&entry=%@",
                        [nameField.text stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
                        [tagsField.text stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
                        [dreamEntry.text stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
                        nil];
NSURL *url = [NSURL URLWithString:urlStr];

The second issue with your code (and undoubtedly the reason for the odd printing) is you're passing the string directly to NSLog, so it's being treated as a format string. You need to use

NSLog(@"%@", encodedString);

instead. That will make it print as expected.

Edit: A third issue with your code is you're mixing autoreleased and owned objects, then releasing them all at the end. Go look at the 3 objects you create, and which you subsequently release later. One of them shouldn't be released later because it was produced by a method that did not start with the words alloc, copy, or new. Identifying the object in question is an exercise left to the reader.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文