18 #include "multipartformdataparser_p.h" 27 if (body->isSequential()) {
28 qCWarning(CUTELYST_MULTIPART) <<
"Parsing sequential body is not supported" << body;
34 qCWarning(CUTELYST_MULTIPART) <<
"No boudary match" << contentType;
40 const int len = contentType.length();
41 boundary.reserve(contentType.length() - start + 2);
43 for (
int i = start, quotes = 0; i < len; ++i) {
44 const QChar ch = contentType.at(i);
46 if ((quotes == 0 && i > start) || ++quotes == 2) {
52 boundary.append(ch.toLatin1());
56 if (boundary.isEmpty()) {
57 qCWarning(CUTELYST_MULTIPART) <<
"Boudary match was empty" << contentType;
60 boundary.prepend(
"--", 2);
62 if (bufferSize < 1024) {
65 char *buffer =
new char[bufferSize];
67 ret = MultiPartFormDataParserPrivate::execute(buffer, bufferSize, body, boundary);
74 Uploads MultiPartFormDataParserPrivate::execute(
char *buffer,
int bufferSize, QIODevice *body,
const QByteArray &boundary)
77 QByteArray headerLine;
81 qint64 contentLength = body->size();
83 int boundarySize = boundary.size();
84 ParserState state = FindBoundary;
85 QByteArrayMatcher matcher(boundary);
87 while (pos < contentLength) {
88 qint64 len = body->read(buffer + bufferSkip, bufferSize - bufferSkip);
90 qCWarning(CUTELYST_MULTIPART) <<
"Error while reading POST body" << body->errorString();
101 i += findBoundary(buffer + i, len - i, matcher, boundarySize, state);
105 if (buffer[i] !=
'\r') {
109 state = EndBoundaryLF;
112 if (buffer[i] !=
'\n') {
116 state = StartHeaders;
119 if (headerLine.isEmpty() && buffer[i] ==
'\r') {
123 char *pch = static_cast<char *>(memchr(buffer + i,
'\r', len - i));
125 headerLine.append(buffer + i, len - i);
128 headerLine.append(buffer + i, pch - buffer - i);
130 state = FinishHeader;
135 if (buffer[i] ==
'\n') {
136 int dotdot = headerLine.indexOf(
':');
137 headers.
setHeader(QString::fromLatin1(headerLine.left(dotdot)),
138 QString::fromLatin1(headerLine.mid(dotdot + 1).trimmed()));
139 headerLine = QByteArray();
140 state = StartHeaders;
147 if (buffer[i] ==
'\n') {
156 startOffset = pos - len + i;
159 i += findBoundary(buffer + i, len - i, matcher, boundarySize, state);
161 if (state == EndBoundaryCR) {
163 const qint64 endOffset = pos - len + i - boundarySize - 1;
164 auto upload =
new Upload(
new UploadPrivate(body, headers, startOffset, endOffset));
171 bufferSkip = boundarySize - 1;
172 memmove(buffer, buffer + len - bufferSkip, bufferSkip);
184 int MultiPartFormDataParserPrivate::findBoundary(
char *buffer,
int len,
const QByteArrayMatcher &matcher,
int boundarySize, MultiPartFormDataParserPrivate::ParserState &state)
186 int i = matcher.indexIn(buffer, len);
190 state = EndBoundaryCR;
191 return i + boundarySize - 1;
196 #include "moc_multipartformdataparser_p.cpp"
Cutelyst Upload handles file upload request
The Cutelyst namespace holds all public Cutelyst API.
QVector< Upload * > Uploads