Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef mozilla_dom_HTMLFormSubmission_h
8 : #define mozilla_dom_HTMLFormSubmission_h
9 :
10 : #include "mozilla/Attributes.h"
11 : #include "nsCOMPtr.h"
12 : #include "nsIContent.h"
13 : #include "mozilla/Encoding.h"
14 : #include "nsString.h"
15 :
16 : class nsIURI;
17 : class nsIInputStream;
18 : class nsGenericHTMLElement;
19 : class nsIMultiplexInputStream;
20 :
21 : namespace mozilla {
22 : namespace dom {
23 :
24 : class Blob;
25 : class Directory;
26 :
27 : /**
28 : * Class for form submissions; encompasses the function to call to submit as
29 : * well as the form submission name/value pairs
30 : */
31 : class HTMLFormSubmission
32 : {
33 : public:
34 : /**
35 : * Get a submission object based on attributes in the form (ENCTYPE and
36 : * METHOD)
37 : *
38 : * @param aForm the form to get a submission object based on
39 : * @param aOriginatingElement the originating element (can be null)
40 : * @param aFormSubmission the form submission object (out param)
41 : */
42 : static nsresult
43 : GetFromForm(nsGenericHTMLElement* aForm,
44 : nsGenericHTMLElement* aOriginatingElement,
45 : HTMLFormSubmission** aFormSubmission);
46 :
47 0 : virtual ~HTMLFormSubmission()
48 0 : {
49 0 : MOZ_COUNT_DTOR(HTMLFormSubmission);
50 0 : }
51 :
52 : /**
53 : * Submit a name/value pair
54 : *
55 : * @param aName the name of the parameter
56 : * @param aValue the value of the parameter
57 : */
58 : virtual nsresult
59 : AddNameValuePair(const nsAString& aName, const nsAString& aValue) = 0;
60 :
61 : /**
62 : * Submit a name/blob pair
63 : *
64 : * @param aName the name of the parameter
65 : * @param aBlob the blob to submit. The file's name will be used if the Blob
66 : * is actually a File, otherwise 'blob' string is used instead if the aBlob is
67 : * not null.
68 : */
69 : virtual nsresult
70 : AddNameBlobOrNullPair(const nsAString& aName, Blob* aBlob) = 0;
71 :
72 : /**
73 : * Submit a name/directory pair
74 : *
75 : * @param aName the name of the parameter
76 : * @param aBlob the directory to submit.
77 : */
78 : virtual nsresult AddNameDirectoryPair(const nsAString& aName,
79 : Directory* aDirectory) = 0;
80 :
81 : /**
82 : * Reports whether the instance supports AddIsindex().
83 : *
84 : * @return true if supported.
85 : */
86 0 : virtual bool SupportsIsindexSubmission()
87 : {
88 0 : return false;
89 : }
90 :
91 : /**
92 : * Adds an isindex value to the submission.
93 : *
94 : * @param aValue the field value
95 : */
96 0 : virtual nsresult AddIsindex(const nsAString& aValue)
97 : {
98 0 : NS_NOTREACHED("AddIsindex called when not supported");
99 0 : return NS_ERROR_UNEXPECTED;
100 : }
101 :
102 : /**
103 : * Given a URI and the current submission, create the final URI and data
104 : * stream that will be submitted. Subclasses *must* implement this.
105 : *
106 : * @param aURI the URI being submitted to [INOUT]
107 : * @param aPostDataStream a data stream for POST data [OUT]
108 : */
109 : virtual nsresult
110 : GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream) = 0;
111 :
112 : /**
113 : * Get the charset that will be used for submission.
114 : */
115 0 : void GetCharset(nsACString& aCharset) { mEncoding->Name(aCharset); }
116 :
117 0 : nsIContent* GetOriginatingElement() const
118 : {
119 0 : return mOriginatingElement.get();
120 : }
121 :
122 : protected:
123 : /**
124 : * Can only be constructed by subclasses.
125 : *
126 : * @param aEncoding the character encoding of the form
127 : * @param aOriginatingElement the originating element (can be null)
128 : */
129 0 : HTMLFormSubmission(mozilla::NotNull<const mozilla::Encoding*> aEncoding,
130 : nsIContent* aOriginatingElement)
131 0 : : mEncoding(aEncoding)
132 0 : , mOriginatingElement(aOriginatingElement)
133 : {
134 0 : MOZ_COUNT_CTOR(HTMLFormSubmission);
135 0 : }
136 :
137 : // The character encoding of this form submission
138 : mozilla::NotNull<const mozilla::Encoding*> mEncoding;
139 :
140 : // Originating element.
141 : nsCOMPtr<nsIContent> mOriginatingElement;
142 : };
143 :
144 : class EncodingFormSubmission : public HTMLFormSubmission
145 : {
146 : public:
147 : EncodingFormSubmission(mozilla::NotNull<const mozilla::Encoding*> aEncoding,
148 : nsIContent* aOriginatingElement);
149 :
150 : virtual ~EncodingFormSubmission();
151 :
152 : /**
153 : * Encode a Unicode string to bytes using the encoder (or just copy the input
154 : * if there is no encoder).
155 : * @param aStr the string to encode
156 : * @param aResult the encoded string [OUT]
157 : * @param aHeaderEncode If true, turns all linebreaks into spaces and escapes
158 : * all quotes
159 : * @throws an error if UnicodeToNewBytes fails
160 : */
161 : nsresult EncodeVal(const nsAString& aStr, nsCString& aResult,
162 : bool aHeaderEncode);
163 : };
164 :
165 : /**
166 : * Handle multipart/form-data encoding, which does files as well as normal
167 : * inputs. This always does POST.
168 : */
169 : class FSMultipartFormData : public EncodingFormSubmission
170 : {
171 : public:
172 : /**
173 : * @param aEncoding the character encoding of the form
174 : */
175 : FSMultipartFormData(mozilla::NotNull<const mozilla::Encoding*> aEncoding,
176 : nsIContent* aOriginatingElement);
177 : ~FSMultipartFormData();
178 :
179 : virtual nsresult
180 : AddNameValuePair(const nsAString& aName, const nsAString& aValue) override;
181 :
182 : virtual nsresult
183 : AddNameBlobOrNullPair(const nsAString& aName, Blob* aBlob) override;
184 :
185 : virtual nsresult
186 : AddNameDirectoryPair(const nsAString& aName, Directory* aDirectory) override;
187 :
188 : virtual nsresult
189 : GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream) override;
190 :
191 0 : void GetContentType(nsACString& aContentType)
192 : {
193 : aContentType =
194 0 : NS_LITERAL_CSTRING("multipart/form-data; boundary=") + mBoundary;
195 0 : }
196 :
197 : nsIInputStream* GetSubmissionBody(uint64_t* aContentLength);
198 :
199 : protected:
200 :
201 : /**
202 : * Roll up the data we have so far and add it to the multiplexed data stream.
203 : */
204 : nsresult AddPostDataStream();
205 :
206 : private:
207 : void AddDataChunk(const nsACString& aName,
208 : const nsACString& aFilename,
209 : const nsACString& aContentType,
210 : nsIInputStream* aInputStream,
211 : uint64_t aInputStreamSize);
212 : /**
213 : * The post data stream as it is so far. This is a collection of smaller
214 : * chunks--string streams and file streams interleaved to make one big POST
215 : * stream.
216 : */
217 : nsCOMPtr<nsIMultiplexInputStream> mPostDataStream;
218 :
219 : /**
220 : * The current string chunk. When a file is hit, the string chunk gets
221 : * wrapped up into an input stream and put into mPostDataStream so that the
222 : * file input stream can then be appended and everything is in the right
223 : * order. Then the string chunk gets appended to again as we process more
224 : * name/value pairs.
225 : */
226 : nsCString mPostDataChunk;
227 :
228 : /**
229 : * The boundary string to use after each "part" (the boundary that marks the
230 : * end of a value). This is computed randomly and is different for each
231 : * submission.
232 : */
233 : nsCString mBoundary;
234 :
235 : /**
236 : * The total length in bytes of the streams that make up mPostDataStream
237 : */
238 : uint64_t mTotalLength;
239 : };
240 :
241 : } // namespace dom
242 : } // namespace mozilla
243 :
244 : #endif /* mozilla_dom_HTMLFormSubmission_h */
|