2016-09-29 20 views
1

经过大约一周的研究,没有解决方案后,我放弃了,我问你们有什么建议。iOS - Objective C - POST字符串转义/编码问题

我需要相同的PHP脚本来以相同的方式处理POST请求,无论它们的来源是简单的HTML表单还是iOS应用程序。没有涉及JSON。

问题:当POST发件人是iOS应用程序时,有些字符会丢失。在这一点上,我会说我不知道​​为什么它的行为如此。显然,Web浏览器在构建POST请求时正确地转义了所有的字符,而我的obj-c代码却没有。

在Objective-C代码中,您可以看到我所做的5个试验,并记录了出错的一些细节。

我真的希望你能帮助

tester.php文件:

<?php 
header('Content-Type: text/html; charset=utf-8'); 

if (isset($_POST['email'])) 
{ 
    echo "email: " . $_POST['email']; 
    echo "\n"; 
    echo "password: " . $_POST['password']; 
} 
else 
{ 
?> 

<form method="post"> 
    <input type="text" id="email" name="email" value="切换到中文@gmail.com" /> 
    <br> 
    <input type="text" id="password" name="password" value="&+=/切/().%&" /> 
    <br> 
    <input type="submit" /> 

</form> 

<?php 
} 

Objectice-C HTTP POST执行:

如果我使用的HTML表单(正好
// Get values 
NSString *email = @"切换到中文@gmail.com"; 
NSString *password = @"&+=/切/().%&"; 

NSLog(@"Before: %@ and %@", email, password); 

// Escape tentative 1: fails: % disappears 
//email = [email stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet alphanumericCharacterSet]]; 
//password = [password stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet alphanumericCharacterSet]]; 

// Escape tentative 2: failed: % disappears, + becomes a space, who knows what else 
// email = [email stringByReplacingOccurrencesOfString: @"&" withString: @"%26"]; 
// password = [password stringByReplacingOccurrencesOfString: @"&" withString: @"%26"]; 

// Escape tentative 3: % disappears 
// NSString *charactersToEscape = @"!*'();:@&=+$,/?%#[]\" "; 
// NSCharacterSet *allowedCharacters = [[NSCharacterSet characterSetWithCharactersInString:charactersToEscape] invertedSet]; 
// email = [email stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters]; 
// password = [password stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters]; 

// Escape tentative 4: % disappears 
/*CFStringRef cf_email = (__bridge CFStringRef)(email); 
CFStringRef cf_password = (__bridge CFStringRef)(password); 

email = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, 
                    cf_email, 
                    NULL, 
                    CFSTR("%:/?#[]@!$&'()*+,;="), 
                    kCFStringEncodingUTF8)); 
password = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, 
                    cf_password, 
                    NULL, 
                    CFSTR("%:/?#[]@!$&'()*+,;="), 
                    kCFStringEncodingUTF8));*/ 

// Escape tentative 5: password becomes "(null)" 
/*email = [email stringByReplacingOccurrencesOfString: @"%" withString: @"%25"]; 
email = [email stringByReplacingOccurrencesOfString: @"&" withString: @"%26"]; 
email = [email stringByReplacingOccurrencesOfString: @"+" withString: @"%2b"]; 


password = [password stringByReplacingOccurrencesOfString: @"%" withString: @"%25"]; 
password = [password stringByReplacingOccurrencesOfString: @"&" withString: @"%26"]; 
password = [password stringByReplacingOccurrencesOfString: @"+" withString: @"%2b"];*/ 



// Execute HTTP request 
NSString *postData = [NSString stringWithFormat:@"email=%@&password=%@", email, password]; 

NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; 
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration]; 

NSURL *url = [NSURL URLWithString:@"http://localhost:8080/tester.php"]; 

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; 

request.HTTPBody = [postData dataUsingEncoding:NSUTF8StringEncoding]; 
request.HTTPMethod = @"POST"; 

NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 
    // Print response 
    NSLog([[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); 
}]; 
[postDataTask resume]; 

结果我在表格中输入的内容):

email: 切换到中文@gmail.com password: &+=/切/().%& 

我从客观的C代码得到什么(一些字符消失),最后的测试之一:

2016-09-29 21:28:59.519 test[44752:2438179] Before: 切换到中文@gmail.com (15) and &+=/切/().%& (11) 
2016-09-29 21:28:59.705 test[44752:2438721] email: 切换到中文@gmail.com password: &+=/切/().& 

回答

0

这是我做的方式。它在我尝试的所有方面都非常有效。首先,你需要的是功能添加到的NSString:

@implementation NSString (NSStringWebStructure) 
-(NSString*)stringToWebStructure 
{ 
    NSString* webString = [self stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 

    webString = [webString stringByReplacingOccurrencesOfString:@"&" withString:@"%26"]; 
    webString = [webString stringByReplacingOccurrencesOfString:@"?" withString:@"%3F"]; 

    return webString; 
} 
@end 

现在,您需要请求功能:

-(NSString*)launchURL:(NSURL*)url withPostString:(NSString*)post 
{ 
    NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; 
    NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)[postData length]]; 

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; 
    [request setURL:url]; 
    [request setHTTPMethod:@"POST"]; 
    [request setValue:postLength forHTTPHeaderField:@"Content-Length"]; 
    [request setHTTPBody:postData]; 

    NSError *error = nil; 
    NSHTTPURLResponse *response = nil; 
    NSData *urlData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; 

    if (response.statusCode >= 200 && response.statusCode < 300) 
    { 
     NSString *responseData = [[NSString alloc] initWithData:urlData encoding:NSUTF8StringEncoding]; 
     if (responseData.length > 0) return responseData; 
    } 
    else if (error) return [error description]; 

    return nil; 
} 
-(NSString*)launchURL:(NSURL*)url withPostValues:(NSDictionary*)postDict 
{ 
    NSArray* postKeys = postDict.allKeys; 
    NSMutableArray* postLines = [[NSMutableArray alloc] init]; 

    for (NSString* key in postKeys) 
    { 
     [postLines addObject:[NSString stringWithFormat:@"%@=%@",key,[postDict[key] stringToWebStructure]]]; 
    } 

    return [self launchURL:url withPostString:[postLines componentsJoinedByString:@"&"]]; 
} 

并考虑你的榜样,你需要做的仅仅是:

NSString *email = @"切换到中文@gmail.com"; 
NSString *password = @"&+=/切/().%&"; 

NSURL *url = [NSURL URLWithString:@"http://localhost:8080/tester.php"]; 
NSDictionary* postValues = @{@"email":email, @"password": password}; 

NSString* response = [self launchURL:url withPostValues: postValues]; 
NSLog(@"%@",response); 

stringByAddingPercentEscapesUsingEncoding:在macOS 10.11中已弃用,但如果您要支持旧版macOS,就像我一样,这是一种功能方法(从macOS 10.6到macOS 10.12进行测试)。