• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hazendaz / httpunit / 755

14 Feb 2026 07:14PM UTC coverage: 80.526%. Remained the same
755

push

github

hazendaz
[ci] Fix badge

3213 of 4105 branches covered (78.27%)

Branch coverage included in aggregate %.

8245 of 10124 relevant lines covered (81.44%)

0.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.16
/src/main/java/com/meterware/httpunit/protocol/MimeEncodedMessageBody.java
1
/*
2
 * SPDX-License-Identifier: MIT
3
 * See LICENSE file for details.
4
 *
5
 * Copyright 2000-2026 Russell Gold
6
 * Copyright 2021-2000 hazendaz
7
 */
8
package com.meterware.httpunit.protocol;
9

10
import java.io.IOException;
11
import java.io.InputStream;
12
import java.io.OutputStream;
13
import java.nio.charset.Charset;
14

15
/**
16
 * A POST-method message body which is MIME-encoded. This is used when uploading files, and is selected when the enctype
17
 * parameter of a form is set to "multi-part/form-data".
18
 **/
19
class MimeEncodedMessageBody extends MessageBody {
20

21
    /**
22
     * Instantiates a new mime encoded message body.
23
     *
24
     * @param characterSet
25
     *            the character set
26
     */
27
    MimeEncodedMessageBody(String characterSet) {
28
        super(characterSet);
1✔
29
    }
1✔
30

31
    /**
32
     * Returns the content type of this message body.
33
     **/
34
    @Override
35
    public String getContentType() {
36
        return "multipart/form-data; boundary=" + BOUNDARY;
1✔
37
    }
38

39
    /**
40
     * Transmits the body of this request as a sequence of bytes.
41
     **/
42
    @Override
43
    public void writeTo(OutputStream outputStream, ParameterCollection parameters) throws IOException {
44
        MimeEncoding encoding = new MimeEncoding(outputStream);
1✔
45
        parameters.recordParameters(encoding);
1✔
46
        encoding.sendClose();
1✔
47
    }
1✔
48

49
    /** The Constant BOUNDARY. */
50
    private static final String BOUNDARY = "--HttpUnit-part0-aSgQ2M";
51

52
    /** The Constant CRLF. */
53
    private static final byte[] CRLF = { 0x0d, 0x0A };
1✔
54

55
    /**
56
     * Encode.
57
     *
58
     * @param string
59
     *            the string
60
     *
61
     * @return the string
62
     */
63
    private String encode(String string) {
64
        char[] chars = string.toCharArray();
1✔
65
        StringBuilder sb = new StringBuilder(chars.length + 20);
1✔
66
        for (char element : chars) {
1✔
67
            if (element == '\\') {
1!
68
                sb.append("\\\\"); // accomodate MS-DOS file paths ??? is this safe??
×
69
            } else {
70
                sb.append(element);
1✔
71
            }
72
        }
73
        return sb.toString();
1✔
74
    }
75

76
    /**
77
     * Write ln.
78
     *
79
     * @param os
80
     *            the os
81
     * @param value
82
     *            the value
83
     * @param encoding
84
     *            the encoding
85
     *
86
     * @throws IOException
87
     *             Signals that an I/O exception has occurred.
88
     */
89
    private void writeLn(OutputStream os, String value, String encoding) throws IOException {
90
        os.write(value.getBytes(Charset.forName(encoding)));
1✔
91
        os.write(CRLF);
1✔
92
    }
1✔
93

94
    /**
95
     * Write ln.
96
     *
97
     * @param os
98
     *            the os
99
     * @param value
100
     *            the value
101
     *
102
     * @throws IOException
103
     *             Signals that an I/O exception has occurred.
104
     */
105
    private void writeLn(OutputStream os, String value) throws IOException {
106
        writeLn(os, value, getCharacterSet());
1✔
107
    }
1✔
108

109
    /**
110
     * The Class MimeEncoding.
111
     */
112
    class MimeEncoding implements ParameterProcessor {
113

114
        /**
115
         * Instantiates a new mime encoding.
116
         *
117
         * @param outputStream
118
         *            the output stream
119
         */
120
        public MimeEncoding(OutputStream outputStream) {
1✔
121
            _outputStream = outputStream;
1✔
122
        }
1✔
123

124
        /**
125
         * Send close.
126
         *
127
         * @throws IOException
128
         *             Signals that an I/O exception has occurred.
129
         */
130
        public void sendClose() throws IOException {
131
            writeLn(_outputStream, "--" + BOUNDARY + "--");
1✔
132
        }
1✔
133

134
        /**
135
         * add the parameter with the given name value and characterSet
136
         *
137
         * @param name
138
         *            - the name
139
         * @param value
140
         *            - the value to set
141
         * @param characterSet
142
         *            - the name of the characterSet to use
143
         */
144
        @Override
145
        public void addParameter(String name, String value, String characterSet) throws IOException {
146
            if (name == null || name.isEmpty() || value == null) {
1!
147
                return;
×
148
            }
149
            writeLn(_outputStream, "--" + BOUNDARY);
1✔
150
            writeLn(_outputStream, "Content-Disposition: form-data; name=\"" + name + '"'); // XXX need to handle
1✔
151
            // non-ascii names here
152
            writeLn(_outputStream, "Content-Type: text/plain; charset=" + getCharacterSet());
1✔
153
            writeLn(_outputStream, "");
1✔
154
            writeLn(_outputStream, fixLineEndings(value), getCharacterSet());
1✔
155
        }
1✔
156

157
        /** The Constant CR. */
158
        private static final char CR = 0x0D;
159

160
        /** The Constant LF. */
161
        private static final char LF = 0x0A;
162

163
        /**
164
         * Fix line endings.
165
         *
166
         * @param value
167
         *            the value
168
         *
169
         * @return the string
170
         */
171
        private String fixLineEndings(String value) {
172
            StringBuilder sb = new StringBuilder();
1✔
173
            char[] chars = value.toCharArray();
1✔
174
            for (int i = 0; i < chars.length; i++) {
1✔
175
                if (chars[i] == CR || chars[i] == LF && (i == 0 || chars[i - 1] != CR)) {
1!
176
                    sb.append(CR).append(LF);
1✔
177
                } else {
178
                    sb.append(chars[i]);
1✔
179
                }
180
            }
181
            return sb.toString();
1✔
182
        }
183

184
        @Override
185
        public void addFile(String name, UploadFileSpec spec) throws IOException {
186
            byte[] buffer = new byte[8 * 1024];
1✔
187

188
            writeLn(_outputStream, "--" + BOUNDARY);
1✔
189
            writeLn(_outputStream, "Content-Disposition: form-data; name=\"" + encode(name) + "\"; filename=\""
1✔
190
                    + encode(spec.getFileName()) + '"'); // XXX need to handle non-ascii names here
1✔
191
            writeLn(_outputStream, "Content-Type: " + spec.getContentType());
1✔
192
            writeLn(_outputStream, "");
1✔
193

194
            InputStream in = spec.getInputStream();
1✔
195
            int count = 0;
1✔
196
            do {
197
                _outputStream.write(buffer, 0, count);
1✔
198
                count = in.read(buffer, 0, buffer.length);
1✔
199
            } while (count != -1);
1✔
200

201
            in.close();
1✔
202
            writeLn(_outputStream, "");
1✔
203
        }
1✔
204

205
        /** The output stream. */
206
        private OutputStream _outputStream;
207
    }
208

209
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc