1/*
2 * Copyright (C) 2004, 2006, 2008, 2011 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#ifndef FormData_h
21#define FormData_h
22
23#include "KURL.h"
24#include <wtf/Forward.h>
25#include <wtf/RefCounted.h>
26#include <wtf/Vector.h>
27#include <wtf/text/WTFString.h>
28
29namespace WebCore {
30
31class Document;
32class FormDataList;
33class TextEncoding;
34
35class FormDataElement {
36public:
37    FormDataElement() : m_type(data) { }
38    explicit FormDataElement(const Vector<char>& array) : m_type(data), m_data(array) { }
39
40#if ENABLE(BLOB)
41    FormDataElement(const String& filename, long long fileStart, long long fileLength, double expectedFileModificationTime, bool shouldGenerateFile) : m_type(encodedFile), m_filename(filename), m_fileStart(fileStart), m_fileLength(fileLength), m_expectedFileModificationTime(expectedFileModificationTime), m_shouldGenerateFile(shouldGenerateFile) { }
42    explicit FormDataElement(const KURL& blobURL) : m_type(encodedBlob), m_url(blobURL) { }
43#else
44    FormDataElement(const String& filename, bool shouldGenerateFile) : m_type(encodedFile), m_filename(filename), m_shouldGenerateFile(shouldGenerateFile) { }
45#endif
46#if ENABLE(FILE_SYSTEM)
47    FormDataElement(const KURL& url, long long start, long long length, double expectedFileModificationTime) : m_type(encodedURL), m_url(url), m_fileStart(start), m_fileLength(length), m_expectedFileModificationTime(expectedFileModificationTime), m_shouldGenerateFile(false) { }
48#endif
49
50    enum Type {
51        data,
52        encodedFile
53#if ENABLE(BLOB)
54        , encodedBlob
55#endif
56#if ENABLE(FILE_SYSTEM)
57        , encodedURL
58#endif
59    } m_type;
60    Vector<char> m_data;
61    String m_filename;
62#if ENABLE(BLOB)
63    KURL m_url; // For Blob or URL.
64    long long m_fileStart;
65    long long m_fileLength;
66    double m_expectedFileModificationTime;
67#endif
68    String m_generatedFilename;
69    bool m_shouldGenerateFile;
70};
71
72inline bool operator==(const FormDataElement& a, const FormDataElement& b)
73{
74    if (&a == &b)
75        return true;
76
77    if (a.m_type != b.m_type)
78        return false;
79    if (a.m_type == FormDataElement::data)
80        return a.m_data == b.m_data;
81    if (a.m_type == FormDataElement::encodedFile)
82#if ENABLE(BLOB)
83        return a.m_filename == b.m_filename && a.m_fileStart == b.m_fileStart && a.m_fileLength == b.m_fileLength && a.m_expectedFileModificationTime == b.m_expectedFileModificationTime;
84    if (a.m_type == FormDataElement::encodedBlob)
85        return a.m_url == b.m_url;
86#else
87        return a.m_filename == b.m_filename;
88#endif
89#if ENABLE(FILE_SYSTEM)
90    if (a.m_type == FormDataElement::encodedURL)
91        return a.m_url == b.m_url;
92#endif
93
94    return true;
95}
96
97inline bool operator!=(const FormDataElement& a, const FormDataElement& b)
98{
99    return !(a == b);
100}
101
102class FormData : public RefCounted<FormData> {
103public:
104    enum EncodingType {
105        FormURLEncoded, // for application/x-www-form-urlencoded
106        TextPlain, // for text/plain
107        MultipartFormData // for multipart/form-data
108    };
109
110    static PassRefPtr<FormData> create();
111    static PassRefPtr<FormData> create(const void*, size_t);
112    static PassRefPtr<FormData> create(const CString&);
113    static PassRefPtr<FormData> create(const Vector<char>&);
114    static PassRefPtr<FormData> create(const FormDataList&, const TextEncoding&, EncodingType = FormURLEncoded);
115    static PassRefPtr<FormData> createMultiPart(const FormDataList&, const TextEncoding&, Document*);
116    PassRefPtr<FormData> copy() const;
117    PassRefPtr<FormData> deepCopy() const;
118    ~FormData();
119
120    void encode(Encoder&) const;
121    static PassRefPtr<FormData> decode(Decoder&);
122
123    void appendData(const void* data, size_t);
124    void appendFile(const String& filePath, bool shouldGenerateFile = false);
125#if ENABLE(BLOB)
126    void appendFileRange(const String& filename, long long start, long long length, double expectedModificationTime, bool shouldGenerateFile = false);
127    void appendBlob(const KURL& blobURL);
128#endif
129#if ENABLE(FILE_SYSTEM)
130    void appendURL(const KURL&);
131    void appendURLRange(const KURL&, long long start, long long length, double expectedModificationTime);
132#endif
133
134    void flatten(Vector<char>&) const; // omits files
135    String flattenToString() const; // omits files
136
137#if ENABLE(BLOB)
138    // Resolve all blob references so we only have file and data.
139    // If the FormData has no blob references to resolve, this is returned.
140    PassRefPtr<FormData> resolveBlobReferences();
141#endif
142
143    bool isEmpty() const { return m_elements.isEmpty(); }
144    const Vector<FormDataElement>& elements() const { return m_elements; }
145    const Vector<char>& boundary() const { return m_boundary; }
146
147    void generateFiles(Document*);
148    void removeGeneratedFilesIfNeeded();
149
150    bool alwaysStream() const { return m_alwaysStream; }
151    void setAlwaysStream(bool alwaysStream) { m_alwaysStream = alwaysStream; }
152
153    // Identifies a particular form submission instance.  A value of 0 is used
154    // to indicate an unspecified identifier.
155    void setIdentifier(int64_t identifier) { m_identifier = identifier; }
156    int64_t identifier() const { return m_identifier; }
157
158    bool containsPasswordData() const { return m_containsPasswordData; }
159    void setContainsPasswordData(bool containsPasswordData) { m_containsPasswordData = containsPasswordData; }
160
161    static EncodingType parseEncodingType(const String& type)
162    {
163        if (equalIgnoringCase(type, "text/plain"))
164            return TextPlain;
165        if (equalIgnoringCase(type, "multipart/form-data"))
166            return MultipartFormData;
167        return FormURLEncoded;
168    }
169
170private:
171    FormData();
172    FormData(const FormData&);
173
174    void appendKeyValuePairItems(const FormDataList&, const TextEncoding&, bool isMultiPartForm, Document*, EncodingType = FormURLEncoded);
175
176    Vector<FormDataElement> m_elements;
177
178    int64_t m_identifier;
179    bool m_hasGeneratedFiles;
180    bool m_alwaysStream;
181    Vector<char> m_boundary;
182    bool m_containsPasswordData;
183};
184
185inline bool operator==(const FormData& a, const FormData& b)
186{
187    return a.elements() == b.elements();
188}
189
190inline bool operator!=(const FormData& a, const FormData& b)
191{
192    return !(a == b);
193}
194
195} // namespace WebCore
196
197#endif
198