6

Objective-C で torrent スクレーパーを作成しており、HTTP リクエストにAFNetworkingを使用しています。トラッカー リクエストのメタ情報の一部の sha1 ハッシュを送信する必要があります。ハッシュの作成に成功し、それが正しいことを確認しました。バイナリデータをエンコードしないため、ハッシュを NSString に入れることはできません。そのため、ハッシュを NSData オブジェクトに入れてから、送信するパラメーターに入れました。これは私が現在持っているものですが、常にエラーが返されます。ハッシュを送信するために使用しているメソッドにあると思います。また、ハッシュをURLエンコードしてから、それをNSStringに入れてみましたが、役に立ちませんでした

 NSMutableDictionary *parameters = [NSMutableDictionary dictionary];

 unsigned char infoHash[20];
 [self.tracker generateTorrentInfoHash:infoHash];

 const char peer_id[20] = "randomstringfornow";

[parameters setObject:[NSData dataWithBytes:&infoHash length:20] forKey:@"info_hash"];    
[parameters setObject:[NSData dataWithBytes:&peer_id length:20] forKey:@"peer_id"];
[parameters setObject:@(8080) forKey:@"port"];
[parameters setObject:@(0) forKey:@"uploaded"];
[parameters setObject:@(self.tracker.metaInfo.totalFileSize) forKey:@"left"];
[parameters setObject:@(0) forKey:@"downloaded"];
[parameters setObject:@(0) forKey:@"compact"];
[parameters setObject:@"stopped" forKey:@"event"];


[self getPath:@"" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSLog(@"%@",operation.responseString);


   } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"%@",operation.responseString);
}];

AFNetworkingでこれを行う方法があるかどうかは誰にもわかりませんか、それとも単純なものが欠けていることを願っています。

4

1 に答える 1

5

わかりました、私は急流の専門家ではありませんが、あなたが抱えている課題は、あなたが引き出しているベンコードされたデータ表現がSHA1ハッシュを20バイトのデータとしてエンコードすることだと思います.

HTTP リクエストの GET 部分でそのような生データを送信することはできないため、エンコードする必要があります。仕様に基づいて、生データのurlencodingが公式の方法であるようです。(他のオプションは、たとえば、人間が読める16進文字列に変換することです)。

この代替 Bittorrent 仕様から:

トラッカーは、HTTP GET リクエストに応答する HTTP/HTTPS サービスです。リクエストには、トラッカーが torrent に関する全体的な統計を保持するのに役立つクライアントからのメトリックが含まれます。応答には、クライアントが torrent に参加するのに役立つピア リストが含まれます。ベース URL は、メタ情報 (.torrent) ファイルで定義されている「アナウンス URL」で構成されます。パラメータは、標準の CGI メソッドを使用してこの URL に追加されます (つまり、アナウンス URL の後に '?' が続き、その後に '&' で区切られた 'param=value' シーケンスが続きます)。

URL 内のすべてのバイナリ データ (特に info_hash と peer_id) は適切にエスケープする必要があることに注意してください。これは、0 ~ 9、az、AZ、'.'、'-'、'_'、および '~' のセットにないバイトは、「%nn」形式を使用してエンコードする必要があることを意味します。バイト。(詳細については、RFC1738 を参照してください。)

の 20 バイトのハッシュの場合\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a

正しいエンコード形式は%124Vx%9A%BC%DE%F1%23Eg%89%AB%CD%EF%124Vx%9A

生の 20 文字の C 配列から始めて、 URLEncoded に到達する必要がありますNSString

残念ながら、特にこのタイプのデータでは、ループで使用する単純な方法stringByAddingPercentEscapesUsingEncodingは機能しません。これは、GET パラメーターとして送信する安全なエンコーディングにならないためです。

少しの SO ヘルプ (文字列を URL エンコードするにはどうすればよいですか) を使用して、最終製品に成形できるコードの一部を次に示しますが、正しい出力の仕様ドキュメントを満たしています。

const char source[20] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf1, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x9a};

NSMutableString *output = [NSMutableString string];

NSLog(@"Raw Data: %@", [NSData dataWithBytes:source length:20]);

int sourceLen = sizeof(source);

for (int i = 0; i < sourceLen; ++i) {
    const unsigned char thisChar = source[i];
    if (thisChar == ' '){
        [output appendString:@"+"];
    } else if (thisChar == '.' || thisChar == '-' || thisChar == '_' || thisChar == '~' || 
               (thisChar >= 'a' && thisChar <= 'z') ||
               (thisChar >= 'A' && thisChar <= 'Z') ||
               (thisChar >= '0' && thisChar <= '9')) {
        [output appendFormat:@"%c", thisChar];
    } else {
        [output appendFormat:@"%%%02X", thisChar];
    }
}

NSLog(@"Encoded:  %@", output);

出力は次のとおりです。

Raw Data: <12345678 9abcdef1 23456789 abcdef12 3456789a>
Encoded:  %124Vx%9A%BC%DE%F1%23Eg%89%AB%CD%EF%124Vx%9A

幸運を!

于 2012-08-12T05:56:13.487 に答える