2008-10-14 Darin Adler <darin@apple.com>
Reviewed by Sam Weinig (all but the FormDataListItem rename).
- https://bugs.webkit.org/show_bug.cgi?id=21593
Bug 21593: add multiple-file support to HTMLFormElement
* html/FormDataList.cpp: Removed appendFile since it's now inline.
Also took incorrect old copyrights off of this file that are left
over from when it was split.
* html/FormDataList.h: Ditto. Renamed FormDataListItem to Item and
made it a member of FormDataList. Changed it to hold a File object
instead of a path. And made its data members private. Changed
FormDataList::appendFile accordingly.
* html/HTMLFormElement.cpp:
(WebCore::HTMLFormElement::formData): Updated for above changes.
Removed the code that special-cases HTMLInputElement, because now
the FormDataListItem has everything we need. And if there are
multiple files, we'll get multiple list items for them.
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::appendFormData): Changed the code for
<input type=file> to use File objects instead of path strings and
also to append multiple files if the file list has them.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@37589 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index c3a5fcd..a096ab4 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,29 @@
+2008-10-14 Darin Adler <darin@apple.com>
+
+ Reviewed by Sam Weinig (all but the FormDataListItem rename).
+
+ - https://bugs.webkit.org/show_bug.cgi?id=21593
+ Bug 21593: add multiple-file support to HTMLFormElement
+
+ * html/FormDataList.cpp: Removed appendFile since it's now inline.
+ Also took incorrect old copyrights off of this file that are left
+ over from when it was split.
+ * html/FormDataList.h: Ditto. Renamed FormDataListItem to Item and
+ made it a member of FormDataList. Changed it to hold a File object
+ instead of a path. And made its data members private. Changed
+ FormDataList::appendFile accordingly.
+
+ * html/HTMLFormElement.cpp:
+ (WebCore::HTMLFormElement::formData): Updated for above changes.
+ Removed the code that special-cases HTMLInputElement, because now
+ the FormDataListItem has everything we need. And if there are
+ multiple files, we'll get multiple list items for them.
+
+ * html/HTMLInputElement.cpp:
+ (WebCore::HTMLInputElement::appendFormData): Changed the code for
+ <input type=file> to use File objects instead of path strings and
+ also to append multiple files if the file list has them.
+
2008-10-14 Tor Arne Vestbø <tavestbo@trolltech.com>
Reviewed by Simon.
diff --git a/WebCore/html/FormDataList.cpp b/WebCore/html/FormDataList.cpp
index 15ca9a8..281c9fe 100644
--- a/WebCore/html/FormDataList.cpp
+++ b/WebCore/html/FormDataList.cpp
@@ -1,11 +1,5 @@
/*
- * This file is part of the DOM implementation for KDE.
- *
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2001 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
- * (C) 2006 Alexey Proskuryakov (ap@nypop.com)
+ * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -40,11 +34,11 @@
}
// Change plain CR and plain LF to CRLF pairs.
-static CString fixLineBreaks(const CString &s)
+static CString fixLineBreaks(const CString& s)
{
// Compute the length.
unsigned newLen = 0;
- const char *p = s.data();
+ const char* p = s.data();
while (char c = *p++) {
if (c == '\r') {
// Safe to look ahead because of trailing '\0'.
@@ -66,7 +60,7 @@
// Make a copy of the string.
p = s.data();
- char *q;
+ char* q;
CString result = CString::newUninitialized(newLen, q);
while (char c = *p++) {
if (c == '\r') {
@@ -94,10 +88,4 @@
m_list.append(cstr);
}
-void FormDataList::appendFile(const String& key, const String& filename)
-{
- appendString(key);
- m_list.append(filename);
-}
-
} // namespace
diff --git a/WebCore/html/FormDataList.h b/WebCore/html/FormDataList.h
index cdff8f7..aec1a52 100644
--- a/WebCore/html/FormDataList.h
+++ b/WebCore/html/FormDataList.h
@@ -1,11 +1,5 @@
/*
- * This file is part of the DOM implementation for KDE.
- *
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2001 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
- * (C) 2006 Alexey Proskuryakov (ap@nypop.com)
+ * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -28,21 +22,11 @@
#define FormDataList_h
#include "CString.h"
-#include "PlatformString.h"
+#include "File.h"
#include "TextEncoding.h"
-#include <wtf/Vector.h>
namespace WebCore {
-struct FormDataListItem {
- FormDataListItem() { }
- FormDataListItem(const CString& data) : m_data(data) { }
- FormDataListItem(const String& path) : m_path(path) { }
-
- String m_path;
- CString m_data;
-};
-
class FormDataList {
public:
FormDataList(const TextEncoding&);
@@ -53,16 +37,31 @@
{ appendString(key); appendString(value); }
void appendData(const String& key, int value)
{ appendString(key); appendString(String::number(value)); }
- void appendFile(const String& key, const String& filename);
+ void appendFile(const String& key, PassRefPtr<File> file)
+ { appendString(key); m_list.append(file); }
- const Vector<FormDataListItem>& list() const { return m_list; }
+ class Item {
+ public:
+ Item() { }
+ Item(const CString& data) : m_data(data) { }
+ Item(PassRefPtr<File> file) : m_file(file) { }
+
+ const CString& data() const { return m_data; }
+ File* file() const { return m_file.get(); }
+
+ private:
+ CString m_data;
+ RefPtr<File> m_file;
+ };
+
+ const Vector<Item>& list() const { return m_list; }
private:
void appendString(const CString&);
void appendString(const String&);
TextEncoding m_encoding;
- Vector<FormDataListItem> m_list;
+ Vector<Item> m_list;
};
} // namespace WebCore
diff --git a/WebCore/html/HTMLFormElement.cpp b/WebCore/html/HTMLFormElement.cpp
index 1a83d3a..a691d7f 100644
--- a/WebCore/html/HTMLFormElement.cpp
+++ b/WebCore/html/HTMLFormElement.cpp
@@ -248,18 +248,18 @@
if (!control->disabled() && control->appendFormData(list, m_multipart)) {
size_t ln = list.list().size();
for (size_t j = 0; j < ln; ++j) {
- const FormDataListItem& item = list.list()[j];
+ const FormDataList::Item& item = list.list()[j];
if (!m_multipart) {
// 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() && item.m_data == "isindex")
- appendEncodedString(encodedData, list.list()[++j].m_data);
+ if (encodedData.isEmpty() && item.data() == "isindex")
+ appendEncodedString(encodedData, list.list()[++j].data());
else {
if (!encodedData.isEmpty())
encodedData.append('&');
- appendEncodedString(encodedData, item.m_data);
+ appendEncodedString(encodedData, item.data());
encodedData.append('=');
- appendEncodedString(encodedData, list.list()[++j].m_data);
+ appendEncodedString(encodedData, list.list()[++j].data());
}
} else {
Vector<char> header;
@@ -267,30 +267,24 @@
appendString(header, boundary);
appendString(header, "\r\n");
appendString(header, "Content-Disposition: form-data; name=\"");
- header.append(item.m_data.data(), item.m_data.length());
+ header.append(item.data().data(), item.data().length());
header.append('"');
bool shouldGenerateFile = false;
// if the current type is FILE, then we also need to
// include the filename
- if (control->hasLocalName(inputTag)
- && static_cast<HTMLInputElement*>(control)->inputType() == HTMLInputElement::FILE) {
- String path;
- String filename;
- const FileList* files = static_cast<HTMLInputElement*>(control)->files();
- if (!files->isEmpty()) {
- // NOTE: We currently only handle one file; some day we'll add multiple file support.
- const File* file = files->item(0);
- path = file->path();
- filename = file->fileName();
- }
+ if (item.file()) {
+ const String& path = item.file()->path();
+ String filename = item.file()->fileName();
// 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(path, generatedFilename);
- if (shouldGenerateFile)
- filename = generatedFilename;
+ if (!path.isEmpty()) {
+ if (Page* page = document()->page()) {
+ String generatedFilename;
+ shouldGenerateFile = page->chrome()->client()->shouldReplaceWithGeneratedFileForUpload(path, generatedFilename);
+ if (shouldGenerateFile)
+ filename = generatedFilename;
+ }
}
// FIXME: This won't work if the filename includes a " mark,
@@ -302,9 +296,10 @@
header.append('"');
if (!filename.isEmpty()) {
- // FIXME: This function's name makes it sound like it takes a path, not just a basename.
- // But filename is not the path. But note, that it's not safe to just use path, instead
- // since in the generated-file case it will not reflect the MIME type of the generated file.
+ // FIXME: The MIMETypeRegistry function's name makes it sound like it takes a path,
+ // not just a basename. But filename is not the path. But note that it's not safe to
+ // just use path instead since in the generated-file case it will not reflect the
+ // MIME type of the generated file.
String mimeType = MIMETypeRegistry::getMIMETypeForPath(filename);
if (!mimeType.isEmpty()) {
appendString(header, "\r\nContent-Type: ");
@@ -317,11 +312,11 @@
// append body
result->appendData(header.data(), header.size());
- const FormDataListItem& item = list.list()[j + 1];
- if (size_t dataSize = item.m_data.length())
- result->appendData(item.m_data.data(), dataSize);
- else if (!item.m_path.isEmpty())
- result->appendFile(item.m_path, shouldGenerateFile);
+ const FormDataList::Item& item = list.list()[j + 1];
+ if (size_t dataSize = item.data().length())
+ result->appendData(item.data().data(), dataSize);
+ else if (item.file() && !item.file()->path().isEmpty())
+ result->appendFile(item.file()->path(), shouldGenerateFile);
result->appendData("\r\n", 2);
++j;
diff --git a/WebCore/html/HTMLInputElement.cpp b/WebCore/html/HTMLInputElement.cpp
index 4963b83..93791a2 100644
--- a/WebCore/html/HTMLInputElement.cpp
+++ b/WebCore/html/HTMLInputElement.cpp
@@ -2,7 +2,7 @@
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* (C) 2001 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
* (C) 2006 Alexey Proskuryakov (ap@nypop.com)
* Copyright (C) 2007 Samuel Weinig (sam@webkit.org)
*
@@ -868,20 +868,23 @@
}
break;
- case FILE:
+ case FILE: {
// Can't submit file on GET.
if (!multipart)
return false;
// If no filename at all is entered, return successful but empty.
// Null would be more logical, but Netscape posts an empty file. Argh.
- if (m_fileList->isEmpty()) {
- encoding.appendData(name(), String(""));
+ unsigned numFiles = m_fileList->length();
+ if (!numFiles) {
+ encoding.appendFile(name(), File::create(""));
return true;
}
- encoding.appendFile(name(), m_fileList->item(0)->path());
+ for (unsigned i = 0; i < numFiles; ++i)
+ encoding.appendFile(name(), m_fileList->item(i));
return true;
+ }
}
return false;
}