void FormData::appendKeyValuePairItems(const FormDataList& list, const WTF::TextEncoding& encoding, bool isMultiPartForm, Document* document, EncodingType encodingType) { if (isMultiPartForm) m_boundary = FormDataBuilder::generateUniqueBoundaryString(); Vector<char> encodedData; const Vector<FormDataList::Item>& items = list.items(); size_t formDataListSize = items.size(); ASSERT(!(formDataListSize % 2)); for (size_t i = 0; i < formDataListSize; i += 2) { const FormDataList::Item& key = items[i]; const FormDataList::Item& value = items[i + 1]; if (isMultiPartForm) { Vector<char> header; FormDataBuilder::beginMultiPartHeader(header, m_boundary.data(), key.data()); // If the current type is blob, then we also need to include the filename if (value.blob()) { String name; if (value.blob()->isFile()) { File* file = toFile(value.blob()); // For file blob, use the filename (or relative path if it is present) as the name. name = file->webkitRelativePath().isEmpty() ? file->name() : file->webkitRelativePath(); // If a filename is passed in FormData.append(), use it instead of the file blob's name. if (!value.filename().isNull()) name = value.filename(); } else { // For non-file blob, use the filename if it is passed in FormData.append(). if (!value.filename().isNull()) name = value.filename(); else name = "blob"; } // We have to include the filename=".." part in the header, even if the filename is empty FormDataBuilder::addFilenameToMultiPartHeader(header, encoding, name); // Add the content type if available, or "application/octet-stream" otherwise (RFC 1867). String contentType; if (value.blob()->type().isEmpty()) contentType = "application/octet-stream"; else contentType = value.blob()->type(); FormDataBuilder::addContentTypeToMultiPartHeader(header, contentType.latin1()); } FormDataBuilder::finishMultiPartHeader(header); // Append body appendData(header.data(), header.size()); if (value.blob()) { if (value.blob()->isFile()) { File* file = toFile(value.blob()); // Do not add the file if the path is empty. if (!file->path().isEmpty()) appendFile(file->path()); if (!file->fileSystemURL().isEmpty()) appendURL(file->fileSystemURL()); } else appendBlob(value.blob()->url()); } else appendData(value.data().data(), value.data().length()); appendData("\r\n", 2); } else { // Omit the name "isindex" if it's the first form data element. // FIXME: Why is this a good rule? Is this obsolete now? if (encodedData.isEmpty() && key.data() == "isindex") FormDataBuilder::encodeStringAsFormData(encodedData, value.data()); else FormDataBuilder::addKeyValuePairAsFormData(encodedData, key.data(), value.data(), encodingType); } } if (isMultiPartForm) FormDataBuilder::addBoundaryToMultiPartHeader(encodedData, m_boundary.data(), true); appendData(encodedData.data(), encodedData.size()); }
void FormData::appendKeyValuePairItems(const FormDataList& list, const TextEncoding& encoding, bool isMultiPartForm, Document* document, EncodingType encodingType) { if (isMultiPartForm) m_boundary = FormDataBuilder::generateUniqueBoundaryString(); Vector<char> encodedData; const Vector<FormDataList::Item>& items = list.items(); size_t formDataListSize = items.size(); ASSERT(!(formDataListSize % 2)); for (size_t i = 0; i < formDataListSize; i += 2) { const FormDataList::Item& key = items[i]; const FormDataList::Item& value = items[i + 1]; if (isMultiPartForm) { Vector<char> header; FormDataBuilder::beginMultiPartHeader(header, m_boundary.data(), key.data()); bool shouldGenerateFile = false; // If the current type is blob, then we also need to include the filename if (value.blob()) { String name; if (value.blob()->isFile()) { File* file = toFile(value.blob()); name = file->name(); // Let the application specify a filename if it's going to generate a replacement file for the upload. const String& path = file->path(); if (!path.isEmpty()) { if (Page* page = document->page()) { String generatedFileName; shouldGenerateFile = page->chrome().client().shouldReplaceWithGeneratedFileForUpload(path, generatedFileName); if (shouldGenerateFile) name = generatedFileName; } } // If a filename is passed in FormData.append(), use it instead of the file blob's name. if (!value.filename().isNull()) name = value.filename(); } else { // For non-file blob, use the filename if it is passed in FormData.append(). if (!value.filename().isNull()) name = value.filename(); else name = "blob"; } // We have to include the filename=".." part in the header, even if the filename is empty FormDataBuilder::addFilenameToMultiPartHeader(header, encoding, name); // Add the content type if available, or "application/octet-stream" otherwise (RFC 1867). String contentType = value.blob()->type(); if (contentType.isEmpty()) contentType = "application/octet-stream"; ASSERT(Blob::isNormalizedContentType(contentType)); FormDataBuilder::addContentTypeToMultiPartHeader(header, contentType.ascii()); } FormDataBuilder::finishMultiPartHeader(header); // Append body appendData(header.data(), header.size()); if (value.blob()) { if (value.blob()->isFile()) { File* file = toFile(value.blob()); // Do not add the file if the path is empty. if (!file->path().isEmpty()) appendFile(file->path(), shouldGenerateFile); } else appendBlob(value.blob()->url()); } else appendData(value.data().data(), value.data().length()); appendData("\r\n", 2); } else { // Omit the name "isindex" if it's the first form data element. // FIXME: Why is this a good rule? Is this obsolete now? if (encodedData.isEmpty() && key.data() == "isindex") FormDataBuilder::encodeStringAsFormData(encodedData, value.data()); else FormDataBuilder::addKeyValuePairAsFormData(encodedData, key.data(), value.data(), encodingType); } } if (isMultiPartForm) FormDataBuilder::addBoundaryToMultiPartHeader(encodedData, m_boundary.data(), true); appendData(encodedData.data(), encodedData.size()); }
void FormData::appendKeyValuePairItems(const FormDataList& list, const TextEncoding& encoding, bool isMultiPartForm, Document* document) { if (isMultiPartForm) m_boundary = FormDataBuilder::generateUniqueBoundaryString(); Vector<char> encodedData; const Vector<FormDataList::Item>& items = list.items(); size_t formDataListSize = items.size(); ASSERT(!(formDataListSize % 2)); for (size_t i = 0; i < formDataListSize; i += 2) { const FormDataList::Item& key = items[i]; const FormDataList::Item& value = items[i + 1]; if (isMultiPartForm) { Vector<char> header; FormDataBuilder::beginMultiPartHeader(header, m_boundary.data(), key.data()); bool shouldGenerateFile = false; // If the current type is blob, then we also need to include the filename if (value.blob()) { String name; if (value.blob()->isFile()) { // For file blob, use the filename (or relative path if it is present) as the name. File* file = static_cast<File*>(value.blob()); #if ENABLE(DIRECTORY_UPLOAD) name = file->webkitRelativePath().isEmpty() ? file->name() : file->webkitRelativePath(); #else name = file->name(); #endif // Let the application specify a filename if it's going to generate a replacement file for the upload. if (Page* page = document->page()) { String generatedFileName; shouldGenerateFile = page->chrome()->client()->shouldReplaceWithGeneratedFileForUpload(file->path(), generatedFileName); if (shouldGenerateFile) name = generatedFileName; } } else { // For non-file blob, use the identifier part of the URL as the name. name = "Blob" + BlobURL::getIdentifier(value.blob()->url()); name = name.replace("-", ""); // For safety, remove '-' from the filename since some servers may not like it. } // We have to include the filename=".." part in the header, even if the filename is empty FormDataBuilder::addFilenameToMultiPartHeader(header, encoding, name); // Add the content type if available, or "application/octet-stream" otherwise (RFC 1867). String contentType; if (value.blob()->type().isEmpty()) contentType = "application/octet-stream"; else contentType = value.blob()->type(); FormDataBuilder::addContentTypeToMultiPartHeader(header, contentType.latin1()); } FormDataBuilder::finishMultiPartHeader(header); // Append body appendData(header.data(), header.size()); if (value.blob()) { if (value.blob()->isFile()) { // Do not add the file if the path is empty. if (!static_cast<File*>(value.blob())->path().isEmpty()) appendFile(static_cast<File*>(value.blob())->path(), shouldGenerateFile); } #if ENABLE(BLOB) else appendBlob(value.blob()->url()); #endif } else appendData(value.data().data(), value.data().length()); appendData("\r\n", 2); } else { // Omit the name "isindex" if it's the first form data element. // FIXME: Why is this a good rule? Is this obsolete now? if (encodedData.isEmpty() && key.data() == "isindex") FormDataBuilder::encodeStringAsFormData(encodedData, value.data()); else FormDataBuilder::addKeyValuePairAsFormData(encodedData, key.data(), value.data()); } } if (isMultiPartForm) FormDataBuilder::addBoundaryToMultiPartHeader(encodedData, m_boundary.data(), true); appendData(encodedData.data(), encodedData.size()); }