1/* 2 * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved. 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public License 15 * along with this library; see the file COPYING.LIB. If not, write to 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 * 19 */ 20 21#include "config.h" 22#include "core/html/FormDataList.h" 23 24#include "core/fileapi/File.h" 25#include "platform/network/FormDataBuilder.h" 26#include "platform/text/LineEnding.h" 27 28namespace blink { 29 30DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(FormDataList); 31 32FormDataList::FormDataList(const WTF::TextEncoding& c) 33 : m_encoding(c) 34{ 35} 36 37void FormDataList::appendString(const String& string) 38{ 39 CString encodedString = m_encoding.encode(string, WTF::EntitiesForUnencodables); 40 m_items.append(normalizeLineEndingsToCRLF(encodedString)); 41} 42 43void FormDataList::appendString(const CString& string) 44{ 45 m_items.append(string); 46} 47 48void FormDataList::appendBlob(PassRefPtrWillBeRawPtr<Blob> blob, const String& filename) 49{ 50 m_items.append(Item(blob, filename)); 51} 52 53PassRefPtr<FormData> FormDataList::createFormData(FormData::EncodingType encodingType) 54{ 55 RefPtr<FormData> result = FormData::create(); 56 appendKeyValuePairItemsTo(result.get(), m_encoding, false, encodingType); 57 return result.release(); 58} 59 60PassRefPtr<FormData> FormDataList::createMultiPartFormData() 61{ 62 RefPtr<FormData> result = FormData::create(); 63 appendKeyValuePairItemsTo(result.get(), m_encoding, true); 64 return result.release(); 65} 66 67void FormDataList::appendKeyValuePairItemsTo(FormData* formData, const WTF::TextEncoding& encoding, bool isMultiPartForm, FormData::EncodingType encodingType) 68{ 69 if (isMultiPartForm) 70 formData->setBoundary(FormDataBuilder::generateUniqueBoundaryString()); 71 72 Vector<char> encodedData; 73 74 const WillBeHeapVector<Item>& items = this->items(); 75 size_t formDataListSize = items.size(); 76 ASSERT(!(formDataListSize % 2)); 77 for (size_t i = 0; i < formDataListSize; i += 2) { 78 const FormDataList::Item& key = items[i]; 79 const FormDataList::Item& value = items[i + 1]; 80 if (isMultiPartForm) { 81 Vector<char> header; 82 FormDataBuilder::beginMultiPartHeader(header, formData->boundary().data(), key.data()); 83 84 // If the current type is blob, then we also need to include the filename 85 if (value.blob()) { 86 String name; 87 if (value.blob()->isFile()) { 88 File* file = toFile(value.blob()); 89 // For file blob, use the filename (or relative path if it is present) as the name. 90 name = file->webkitRelativePath().isEmpty() ? file->name() : file->webkitRelativePath(); 91 92 // If a filename is passed in FormData.append(), use it instead of the file blob's name. 93 if (!value.filename().isNull()) 94 name = value.filename(); 95 } else { 96 // For non-file blob, use the filename if it is passed in FormData.append(). 97 if (!value.filename().isNull()) 98 name = value.filename(); 99 else 100 name = "blob"; 101 } 102 103 // We have to include the filename=".." part in the header, even if the filename is empty 104 FormDataBuilder::addFilenameToMultiPartHeader(header, encoding, name); 105 106 // Add the content type if available, or "application/octet-stream" otherwise (RFC 1867). 107 String contentType; 108 if (value.blob()->type().isEmpty()) 109 contentType = "application/octet-stream"; 110 else 111 contentType = value.blob()->type(); 112 FormDataBuilder::addContentTypeToMultiPartHeader(header, contentType.latin1()); 113 } 114 115 FormDataBuilder::finishMultiPartHeader(header); 116 117 // Append body 118 formData->appendData(header.data(), header.size()); 119 if (value.blob()) { 120 if (value.blob()->hasBackingFile()) { 121 File* file = toFile(value.blob()); 122 // Do not add the file if the path is empty. 123 if (!file->path().isEmpty()) 124 formData->appendFile(file->path()); 125 if (!file->fileSystemURL().isEmpty()) 126 formData->appendFileSystemURL(file->fileSystemURL()); 127 } else { 128 formData->appendBlob(value.blob()->uuid(), value.blob()->blobDataHandle()); 129 } 130 } else { 131 formData->appendData(value.data().data(), value.data().length()); 132 } 133 formData->appendData("\r\n", 2); 134 } else { 135 FormDataBuilder::addKeyValuePairAsFormData(encodedData, key.data(), value.data(), encodingType); 136 } 137 } 138 139 if (isMultiPartForm) 140 FormDataBuilder::addBoundaryToMultiPartHeader(encodedData, formData->boundary().data(), true); 141 142 formData->appendData(encodedData.data(), encodedData.size()); 143} 144 145void FormDataList::trace(Visitor* visitor) 146{ 147 visitor->trace(m_items); 148} 149 150void FormDataList::Item::trace(Visitor* visitor) 151{ 152 visitor->trace(m_blob); 153} 154 155} // namespace 156