1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.html;
16
17 import java.io.File;
18 import java.net.URI;
19 import java.net.URISyntaxException;
20 import java.nio.charset.Charset;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.List;
24 import java.util.Map;
25
26 import org.apache.commons.io.FileUtils;
27 import org.htmlunit.BrowserVersion;
28 import org.htmlunit.SgmlPage;
29 import org.htmlunit.javascript.host.event.Event;
30 import org.htmlunit.util.KeyDataPair;
31 import org.htmlunit.util.MimeType;
32 import org.htmlunit.util.NameValuePair;
33 import org.htmlunit.util.StringUtils;
34
35
36
37
38
39
40
41
42
43
44
45
46 public class HtmlFileInput extends HtmlInput implements LabelableElement {
47
48 private String contentType_;
49 private byte[] data_;
50 private File[] files_ = new File[0];
51
52
53
54
55
56
57
58
59 HtmlFileInput(final String qualifiedName, final SgmlPage page,
60 final Map<String, DomAttr> attributes) {
61 super(qualifiedName, page, attributes);
62
63 final DomAttr valueAttrib = attributes.get(VALUE_ATTRIBUTE);
64 if (valueAttrib != null) {
65 setDefaultValue(valueAttrib.getNodeValue());
66 }
67 }
68
69
70
71
72
73 public final byte[] getData() {
74 return data_;
75 }
76
77
78
79
80
81
82
83
84
85
86
87 public final void setData(final byte[] data) {
88 data_ = data;
89 }
90
91
92
93
94 @Override
95 public void setDefaultChecked(final boolean defaultChecked) {
96
97 }
98
99
100
101
102 @Override
103 public NameValuePair[] getSubmitNameValuePairs() {
104 if (files_ == null || files_.length == 0) {
105 return new NameValuePair[] {new KeyDataPair(getNameAttribute(), null, null, null, (Charset) null)};
106 }
107
108 final List<NameValuePair> list = new ArrayList<>();
109 for (final File file : files_) {
110 final Charset charset = getPage().getCharset();
111
112 final KeyDataPair keyDataPair;
113 if (data_ == null) {
114 String contentType;
115 if (contentType_ == null) {
116 contentType = getPage().getWebClient().getBrowserVersion().getUploadMimeType(file);
117 if (StringUtils.isEmptyOrNull(contentType)) {
118 contentType = MimeType.APPLICATION_OCTET_STREAM;
119 }
120 }
121 else {
122 contentType = contentType_;
123 }
124
125 keyDataPair = new KeyDataPair(getNameAttribute(), file, null, contentType, charset);
126 }
127 else {
128 keyDataPair = new KeyDataPair(getNameAttribute(), null, file.getName(),
129 MimeType.APPLICATION_OCTET_STREAM, charset);
130 keyDataPair.setData(data_);
131 }
132 list.add(keyDataPair);
133 }
134 return list.toArray(new NameValuePair[0]);
135 }
136
137
138
139
140
141
142 public void setContentType(final String contentType) {
143 contentType_ = contentType;
144 }
145
146
147
148
149
150
151 public String getContentType() {
152 return contentType_;
153 }
154
155
156
157
158 @Override
159 public String getValue() {
160 final File[] files = getFiles();
161 if (files == null || files.length == 0) {
162 return ATTRIBUTE_NOT_DEFINED;
163 }
164 final File first = files[0];
165 final String name = first.getName();
166 if (name.isEmpty()) {
167 return name;
168 }
169 return "C:\\fakepath\\" + name;
170 }
171
172
173
174
175
176
177 @Override
178 public void setDefaultValue(final String defaultValue) {
179 final String oldDefaultValue = getDefaultValue();
180
181 super.setValueAttribute(defaultValue);
182
183 if (oldDefaultValue.equals(getValue())) {
184 setRawValue(defaultValue);
185 }
186 }
187
188
189
190
191 @Override
192 public void setValue(final String newValue) {
193 if (StringUtils.isEmptyOrNull(newValue)) {
194 setFiles();
195 return;
196 }
197
198 final File file = new File(newValue);
199 if (file.isDirectory()) {
200 setDirectory(file);
201 return;
202 }
203
204 setFiles(file);
205 }
206
207
208
209
210
211
212
213
214
215 public void setFiles(final File... files) {
216 if (files.length > 1 && ATTRIBUTE_NOT_DEFINED == getAttributeDirect("multiple")) {
217 throw new IllegalStateException("HtmlFileInput - 'multiple' is not set.");
218 }
219
220 for (int i = 0; i < files.length; i++) {
221 files[i] = normalizeFile(files[i]);
222 }
223 files_ = files;
224 fireEvent(Event.TYPE_CHANGE);
225 }
226
227
228
229
230
231
232 public void setDirectory(final File directory) {
233 if (directory == null) {
234 return;
235 }
236
237 if (ATTRIBUTE_NOT_DEFINED == getAttributeDirect("webkitdirectory")) {
238 throw new IllegalStateException("HtmlFileInput - 'webkitdirectory' is not set.");
239 }
240
241 if (ATTRIBUTE_NOT_DEFINED == getAttributeDirect("multiple")) {
242 throw new IllegalStateException("HtmlFileInput - 'multiple' is not set.");
243 }
244
245 if (!directory.isDirectory()) {
246 throw new IllegalStateException("HtmlFileInput - the provided directory '"
247 + directory.getAbsolutePath() + "' is not a directory.");
248 }
249
250 final Collection<File> fileColl = FileUtils.listFiles(directory, null, true);
251 final File[] files = new File[fileColl.size()];
252 int i = 0;
253 for (final File file : fileColl) {
254 files[i++] = normalizeFile(file);
255 }
256 files_ = files;
257 fireEvent(Event.TYPE_CHANGE);
258 }
259
260
261
262
263 private static File normalizeFile(final File file) {
264 File f = null;
265 String path = file.getPath().replace('\\', '/');
266 if (path.startsWith("file:/")) {
267 if (path.startsWith("file://") && !path.startsWith("file:///")) {
268 path = "file:///" + path.substring(7);
269 }
270 try {
271 f = new File(new URI(path));
272 }
273 catch (final URISyntaxException ignored) {
274
275 }
276 }
277 if (f == null) {
278 f = new File(path);
279 }
280 return f;
281 }
282
283
284
285
286
287 public File[] getFiles() {
288 return files_;
289 }
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305 @Override
306 public void reset() {
307 files_ = new File[0];
308 }
309
310
311
312
313
314 @Override
315 public boolean isValid() {
316 if (isDisabled()) {
317 return true;
318 }
319
320 return isCustomValidityValid()
321 && (!isRequiredSupported()
322 || ATTRIBUTE_NOT_DEFINED == getAttributeDirect("required")
323 || files_.length > 0);
324 }
325
326 @Override
327 protected void adjustValueAfterTypeChange(final HtmlInput oldInput, final BrowserVersion browserVersion) {
328 setValue("");
329 }
330 }