экранирование CRLF в типе содержимого HTTP multipart / form-data (iOS) - PullRequest
4 голосов
/ 20 января 2011

Я пытаюсь опубликовать файл, используя тип содержимого multipart / form-data, и у меня возник этот вопрос:
Разве я не должен избегать CRLF, когда пишу содержимое файла? У меня есть фрагмент кода в Интернете, и я думаю, что это может быть неправильно:

NSMutableURLRequest* req = [NSMutableURLRequest requestWithURL: url];
[req setHTTPMethod: @"POST"];

NSString* contentType = @"multipart/form-data, boundary=AaB03x";
[req setValue:contentType forHTTPHeaderField: @"Content-type"];

NSData* boundary = [@"\r\n--AaB03x\r\n" dataUsingEncoding:NSUTF8StringEncoding];
NSMutableData *postBody = [NSMutableData data];
[postBody appendData: boundary];
[postBody appendData: [@"Content-Disposition: form-data; name=\"datafile\"; filename=\"t.jpg\"" dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData: [@"Content-Type: image/jpeg\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData: imageData];
[postBody appendData: boundary];
[req setHTTPBody:postBody];

Это неправильно, потому что imageData может содержать последовательности \ r \ n, верно? Если так, есть ли способ избежать CRLF в необработанных данных? Или я что-то упустил?

Заранее спасибо!

Ответы [ 2 ]

3 голосов
/ 21 января 2011

Это интересный вопрос. Глядя на составной мультимедийный тип RFC , выясняется, что агенту-составителю необходимо убедиться, что граница не отображается в инкапсулированных данных. Кроме того, в нем говорится следующее:

ПРИМЕЧАНИЕ: поскольку ограничители границ не должны появляться в частях тела будучи инкапсулированным, пользовательский агент должен проявлять осторожность, чтобы выбрать уникальное значение граничного параметра. Значение граничного параметра в Пример выше мог бы быть результатом алгоритма, предназначенного для производить граничные разделители с очень низкой вероятностью уже существующие в данных, которые будут инкапсулированы без предварительного сканирования данные.

Я понимаю, что это означает, что для того, чтобы убедиться, что граничное значение не появляется в инкапсулированных данных, вам придется сканировать данные для граничного значения. Поскольку в большинстве случаев это недопустимо дорогая операция, ожидается, что пользовательские агенты просто выберут значение, вероятность появления которого в данных очень мала.

Рассмотрим вероятность того, что граница в вашем примере встречается в виде случайной строки байтов (которая в качестве аргумента, мы предположим, представляет собой изображение JPEG). Полная строка, которая должна соответствовать, чтобы досрочно завершить данные вашего изображения, будет "\ r \ n - AaB03x" - 10 байтов или 80 битов. Начиная с любого бита, вероятность того, что следующие 10 байтов будут этой последовательностью, равна 1 в 2 ^ 80. В файле JPEG размером 1 МБ содержится 2 ^ 23 бита. Это означает, что вероятность файла JPEG, содержащего последовательность, составляет менее 2 ^ 23/2 ^ 80 или один из 2 ^ 57 (более ста квадриллионов).

Итак, я думаю, что ответ заключается в том, что, чтобы быть на 100% уверенным, вам придется проверить данные для граничной последовательности, а затем использовать другую, если эта граничная последовательность существует в данных. Но на практике шансы возникновения граничной последовательности достаточно малы, так что это того не стоит.

0 голосов
/ 28 июня 2018

Технически говоря, это неправильно, поскольку конечный \r\n не должен быть частью границы, как указано в RFC2046 . Трейлинг \r\n должен быть частью transport-padding, но на практике это не должно иметь значения, потому что в любом случае вы поставите его после границы.

Также я понимаю, что следует избегать всей последовательности, а не подпоследовательностей.

...