/* Create a final range packet that follows all the data */ static HttpPacket *createFinalRangePacket(HttpStream *stream) { HttpPacket *packet; HttpTx *tx; tx = stream->tx; packet = httpCreatePacket(HTTP_RANGE_BUFSIZE); packet->flags |= HTTP_PACKET_RANGE | HTTP_PACKET_DATA; mprPutToBuf(packet->content, "\r\n--%s--\r\n", tx->rangeBoundary); return packet; }
/* Create a range boundary packet */ static HttpPacket *createRangePacket(HttpStream *stream, HttpRange *range) { HttpPacket *packet; HttpTx *tx; char *length; tx = stream->tx; length = (tx->entityLength >= 0) ? itos(tx->entityLength) : "*"; packet = httpCreatePacket(HTTP_RANGE_BUFSIZE); packet->flags |= HTTP_PACKET_RANGE | HTTP_PACKET_DATA; mprPutToBuf(packet->content, "\r\n--%s\r\n" "Content-Range: bytes %lld-%lld/%s\r\n\r\n", tx->rangeBoundary, range->start, range->end - 1, length); return packet; }
/* Process the content data. Returns < 0 on error == 0 when more data is needed == 1 when data successfully written */ static int processUploadData(HttpQueue *q) { HttpConn *conn; HttpPacket *packet; MprBuf *content; Upload *up; ssize size, dataLen; bool pureData; char *data, *bp, *key; conn = q->conn; up = q->queueData; content = q->first->content; packet = 0; size = mprGetBufLength(content); if (size < up->boundaryLen) { /* Incomplete boundary. Return and get more data */ return 0; } bp = getBoundary(mprGetBufStart(content), size, up->boundary, up->boundaryLen, &pureData); if (bp == 0) { if (up->clientFilename) { /* No signature found yet. probably more data to come. Must handle split boundaries. */ data = mprGetBufStart(content); dataLen = pureData ? size : (size - (up->boundaryLen - 1)); if (dataLen > 0) { if (writeToFile(q, mprGetBufStart(content), dataLen) < 0) { return MPR_ERR_CANT_WRITE; } } mprAdjustBufStart(content, dataLen); return 0; /* Get more data */ } } data = mprGetBufStart(content); dataLen = (bp) ? (bp - data) : mprGetBufLength(content); if (dataLen > 0) { mprAdjustBufStart(content, dataLen); /* This is the CRLF before the boundary */ if (dataLen >= 2 && data[dataLen - 2] == '\r' && data[dataLen - 1] == '\n') { dataLen -= 2; } if (up->clientFilename) { /* Write the last bit of file data and add to the list of files and define environment variables */ if (writeToFile(q, data, dataLen) < 0) { return MPR_ERR_CANT_WRITE; } defineFileFields(q, up); } else { /* Normal string form data variables */ data[dataLen] = '\0'; #if KEEP httpTrace(conn, "request.upload.variables", "context", "'%s':'%s'", up->name, data); #endif key = mprUriDecode(up->name); data = mprUriDecode(data); httpSetParam(conn, key, data); if (packet == 0) { packet = httpCreatePacket(ME_MAX_BUFFER); } if (httpGetPacketLength(packet) > 0) { /* Need to add www-form-urlencoding separators */ mprPutCharToBuf(packet->content, '&'); } else { conn->rx->mimeType = sclone("application/x-www-form-urlencoded"); } mprPutToBuf(packet->content, "%s=%s", up->name, data); } } if (up->clientFilename) { /* Now have all the data (we've seen the boundary) */ mprCloseFile(up->file); up->file = 0; up->clientFilename = 0; } if (packet) { httpPutPacketToNext(q, packet); } up->contentState = HTTP_UPLOAD_BOUNDARY; return 0; }