    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017
    018package org.apache.commons.fileupload2.javax;
    019
    020import static org.junit.jupiter.api.Assertions.assertEquals;
    021import static org.junit.jupiter.api.Assertions.assertTrue;
    022
    023import java.io.ByteArrayOutputStream;
    024import java.io.IOException;
    025import java.nio.charset.StandardCharsets;
    026import java.util.List;
    027
    028import javax.servlet.http.HttpServletRequest;
    029
    030import org.apache.commons.fileupload2.core.AbstractFileUploadTest;
    031import org.apache.commons.fileupload2.core.Constants;
    032import org.apache.commons.fileupload2.core.DiskFileItem;
    033import org.apache.commons.fileupload2.core.DiskFileItemFactory;
    034import org.apache.commons.fileupload2.core.FileUploadException;
    035import org.junit.jupiter.api.Test;
    036
    037/**
    038 * Tests {@link JavaxServletFileUpload}.
    039 *
    040 * @see AbstractFileUploadTest
    041 */
    042public class JavaxServletFileUploadTest
    043        extends AbstractFileUploadTest<JavaxServletFileUpload<DiskFileItem, DiskFileItemFactory>, HttpServletRequest, DiskFileItem, DiskFileItemFactory> {
    044
    045    public JavaxServletFileUploadTest() {
    046        super(new JavaxServletFileUpload<>(DiskFileItemFactory.builder().get()));
    047    }
    048
    049    @Override
    050    public List<DiskFileItem> parseUpload(final JavaxServletFileUpload<DiskFileItem, DiskFileItemFactory> upload, final byte[] bytes, final String contentType)
    051            throws FileUploadException {
    052        final HttpServletRequest request = new JavaxMockHttpServletRequest(bytes, contentType);
    053        return upload.parseRequest(new JavaxServletRequestContext(request));
    054    }
    055
    056    /**
    057     * Runs a test with varying file sizes.
    058     */
    059    @Override
    060    @Test
    061    public void testFileUpload() throws IOException, FileUploadException {
    062        final var baos = new ByteArrayOutputStream();
    063        var add = 16;
    064        var num = 0;
    065        for (var i = 0; i < 16384; i += add) {
    066            if (++add == 32) {
    067                add = 16;
    068            }
    069            final var header = "-----1234\r\n" + "Content-Disposition: form-data; name=\"field" + num++ + "\"\r\n" + "\r\n";
    070            baos.write(header.getBytes(StandardCharsets.US_ASCII));
    071            for (var j = 0; j < i; j++) {
    072                baos.write((byte) j);
    073            }
    074            baos.write("\r\n".getBytes(StandardCharsets.US_ASCII));
    075        }
    076        baos.write("-----1234--\r\n".getBytes(StandardCharsets.US_ASCII));
    077
    078        final var fileItems = parseUpload(new JavaxServletFileUpload<>(DiskFileItemFactory.builder().get()), baos.toByteArray());
    079        final var fileIter = fileItems.iterator();
    080        add = 16;
    081        num = 0;
    082        for (var i = 0; i < 16384; i += add) {
    083            if (++add == 32) {
    084                add = 16;
    085            }
    086            final var item = fileIter.next();
    087            assertEquals("field" + num++, item.getFieldName());
    088            final var bytes = item.get();
    089            assertEquals(i, bytes.length);
    090            for (var j = 0; j < i; j++) {
    091                assertEquals((byte) j, bytes[j]);
    092            }
    093        }
    094        assertTrue(!fileIter.hasNext());
    095    }
    096
    097    @Test
    098    public void testParseImpliedUtf8() throws Exception {
    099        // utf8 encoded form-data without explicit content-type encoding
    100        // @formatter:off
    101        final var text = "-----1234\r\n" +
    102                "Content-Disposition: form-data; name=\"utf8Html\"\r\n" +
    103                "\r\n" +
    104                "Thís ís the coñteñt of the fíle\n" +
    105                "\r\n" +
    106                "-----1234--\r\n";
    107        // @formatter:on
    108
    109        final var bytes = text.getBytes(StandardCharsets.UTF_8);
    110        final HttpServletRequest request = new JavaxMockHttpServletRequest(bytes, Constants.CONTENT_TYPE);
    111        // @formatter:off
    112        final var fileItemFactory = DiskFileItemFactory.builder()
    113                .setCharset(StandardCharsets.UTF_8)
    114                .get();
    115        // @formatter:on
    116        final var upload = new JavaxServletFileUpload<>(fileItemFactory);
    117        final var fileItems = upload.parseRequest(request);
    118        final var fileItem = fileItems.get(0);
    119        assertTrue(fileItem.getString().contains("coñteñt"), fileItem.getString());
    120    }
    121
    122    /*
    123     * Test case for <a href="https://issues.apache.org/jira/browse/FILEUPLOAD-210">
    124     */
    125    @Test
    126    public void testParseParameterMap() throws Exception {
    127        // @formatter:off
    128        final var text = "-----1234\r\n" +
    129                      "Content-Disposition: form-data; name=\"file\"; filename=\"foo.tab\"\r\n" +
    130                      "Content-Type: text/whatever\r\n" +
    131                      "\r\n" +
    132                      "This is the content of the file\n" +
    133                      "\r\n" +
    134                      "-----1234\r\n" +
    135                      "Content-Disposition: form-data; name=\"field\"\r\n" +
    136                      "\r\n" +
    137                      "fieldValue\r\n" +
    138                      "-----1234\r\n" +
    139                      "Content-Disposition: form-data; name=\"multi\"\r\n" +
    140                      "\r\n" +
    141                      "value1\r\n" +
    142                      "-----1234\r\n" +
    143                      "Content-Disposition: form-data; name=\"multi\"\r\n" +
    144                      "\r\n" +
    145                      "value2\r\n" +
    146                      "-----1234--\r\n";
    147        // @formatter:on
    148        final var bytes = text.getBytes(StandardCharsets.US_ASCII);
    149        final HttpServletRequest request = new JavaxMockHttpServletRequest(bytes, Constants.CONTENT_TYPE);
    150
    151        final var upload = new JavaxServletFileUpload<>(DiskFileItemFactory.builder().get());
    152        final var mappedParameters = upload.parseParameterMap(request);
    153        assertTrue(mappedParameters.containsKey("file"));
    154        assertEquals(1, mappedParameters.get("file").size());
    155
    156        assertTrue(mappedParameters.containsKey("field"));
    157        assertEquals(1, mappedParameters.get("field").size());
    158
    159        assertTrue(mappedParameters.containsKey("multi"));
    160        assertEquals(2, mappedParameters.get("multi").size());
    161    }
    162
    163}