2016-09-29 8 views
1

ソリューションのない約1週間の調査の後、私はあきらめて、皆さんに提案をお願いします。iOS - 目的C - POST文字列のエスケープ/エンコードの問題

POSTリクエストを処理するのと同じ方法で、簡単なHTMLフォームまたはiOSアプリケーションのいずれかの起源にかかわらず同じPHPスクリプトが必要です。 JSONは関係ありません。

問題: POST送信者がiOSアプリケーションの場合、一部の文字が失われます。この時点で、私はなぜそれがそのように振る舞うのかわかりません。どうやら、私のobj-cコードはPOST要求のビルド時に、Webブラウザがすべての文字を正しくエスケープしているようです。

objective-cコードでは、私がやった試行錯誤のうち5つを見て、何が間違っているのかを少し注意してください。

私は本当にあなたが

tester.phpをファイル役立つことを願っ:私は(正確に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]; 

結果:

<?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の実行を私がフォームに入力したもの):

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

私は(一部の文字が消える)、最後のテストの1 Objective 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にテスト済み)。