001/****************************************************************
002 * Licensed to the Apache Software Foundation (ASF) under one   *
003 * or more contributor license agreements.  See the NOTICE file *
004 * distributed with this work for additional information        *
005 * regarding copyright ownership.  The ASF licenses this file   *
006 * to you under the Apache License, Version 2.0 (the            *
007 * "License"); you may not use this file except in compliance   *
008 * with the License.  You may obtain a copy of the License at   *
009 *                                                              *
010 *   http://www.apache.org/licenses/LICENSE-2.0                 *
011 *                                                              *
012 * Unless required by applicable law or agreed to in writing,   *
013 * software distributed under the License is distributed on an  *
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
015 * KIND, either express or implied.  See the License for the    *
016 * specific language governing permissions and limitations      *
017 * under the License.                                           *
018 ****************************************************************/
019
020package org.apache.james.mime4j.stream;
021
022import org.apache.james.mime4j.MimeException;
023
024/**
025 * Properties used to configure the behavior of MIME stream parsers.
026 */
027public final class MimeConfig implements Cloneable {
028
029    private boolean strictParsing;
030    private int maxLineLen;
031    private int maxHeaderCount;
032    private int maxHeaderLen;
033    private long maxContentLen;
034    private boolean countLineNumbers;
035    private String headlessParsing;
036    private boolean malformedHeaderStartsBody;
037
038    public MimeConfig() {
039        this.strictParsing = false;
040        this.countLineNumbers = false;
041        this.malformedHeaderStartsBody = false;
042        this.maxLineLen = 1000;
043        this.maxHeaderCount = 1000;
044        this.maxHeaderLen = 10000;
045        this.maxContentLen = -1;
046        this.headlessParsing = null;
047    }
048
049    /**
050     * @see #setMalformedHeaderStartsBody(boolean)
051     *
052     * @return true if malformed header should "end" the headers and be part of
053     *         the body
054     */
055    public boolean isMalformedHeaderStartsBody() {
056        return malformedHeaderStartsBody;
057    }
058
059    /**
060     * Define the behaviour for dealing with malformed headers while in lenient
061     * mode
062     *
063     * @param malformedHeaderStartsBody
064     *            <code>true</code> to make the parser interpret a malformed
065     *            header as end of the headers and as part of the body (as if
066     *            the CRLF separator was missing). <code>false</code> to simply
067     *            ignore malformed headers and continue parsing headers from the
068     *            following line.
069     */
070    public void setMalformedHeaderStartsBody(boolean malformedHeaderStartsBody) {
071        this.malformedHeaderStartsBody = malformedHeaderStartsBody;
072    }
073
074    /**
075     * Returns the value of the strict parsing mode
076     *
077     * @see #setStrictParsing(boolean)
078     *
079     * @return value of the strict parsing mode
080     */
081    public boolean isStrictParsing() {
082        return this.strictParsing;
083    }
084
085    /**
086     * Defines whether minor violations of the MIME specification should be
087     * tolerated or should result in a {@link MimeException}. If this parameter
088     * is set to <code>true</code>, a strict interpretation of the MIME
089     * specification will be enforced, If this parameter is set to
090     * <code>false</code> minor violations will result in a warning in the log.
091     * <p>
092     * Default value: <code>false</code>
093     *
094     * @param strictParsing
095     *            value of the strict parsing mode
096     */
097    public void setStrictParsing(boolean strictParsing) {
098        this.strictParsing = strictParsing;
099    }
100
101    /**
102     * Returns the maximum line length limit
103     *
104     * @see #setMaxLineLen(int)
105     *
106     * @return value of the the maximum line length limit
107     */
108    public int getMaxLineLen() {
109        return this.maxLineLen;
110    }
111
112    /**
113     * Sets the maximum line length limit. Parsing of a MIME entity will be
114     * terminated with a {@link MimeException} if a line is encountered that
115     * exceeds the maximum length limit. If this parameter is set to a non
116     * positive value the line length check will be disabled.
117     * <p>
118     * Default value: <code>1000</code>
119     *
120     * @param maxLineLen
121     *            maximum line length limit
122     */
123    public void setMaxLineLen(int maxLineLen) {
124        this.maxLineLen = maxLineLen;
125    }
126
127    /**
128     * Returns the maximum header limit
129     *
130     * @see #setMaxHeaderCount(int)
131     *
132     * @return value of the the maximum header limit
133     */
134    public int getMaxHeaderCount() {
135        return this.maxHeaderCount;
136    }
137
138    /**
139     * Sets the maximum header limit. Parsing of a MIME entity will be
140     * terminated with a {@link MimeException} if the number of headers exceeds
141     * the maximum limit. If this parameter is set to a non positive value the
142     * header limit check will be disabled.
143     * <p>
144     * Default value: <code>1000</code>
145     *
146     * @param maxHeaderCount
147     *            maximum header limit
148     */
149    public void setMaxHeaderCount(int maxHeaderCount) {
150        this.maxHeaderCount = maxHeaderCount;
151    }
152
153    /**
154     * Returns the maximum header length limit
155     *
156     * @see #setMaxHeaderLen(int)
157     *
158     * @return value of the maximum header length limit
159     */
160    public int getMaxHeaderLen() {
161        return maxHeaderLen;
162    }
163
164    /**
165     * Sets the maximum header length limit. Parsing of a MIME entity will be
166     * terminated with a {@link MimeException} if the total length of a header
167     * exceeds this limit. If this parameter is set to a non positive value the
168     * header length check will be disabled.
169     * <p>
170     * A message header may be folded across multiple lines. This configuration
171     * parameter is used to limit the total length of a header, i.e. the sum of
172     * the length of all lines the header spans across (including line
173     * terminators).
174     * <p>
175     * Default value: <code>10000</code>
176     *
177     * @param maxHeaderLen
178     *            maximum header length limit
179     */
180    public void setMaxHeaderLen(int maxHeaderLen) {
181        this.maxHeaderLen = maxHeaderLen;
182    }
183
184    /**
185     * Returns the maximum content length limit
186     *
187     * @see #setMaxContentLen(long)
188     *
189     * @return value of the the maximum content length limit
190     */
191    public long getMaxContentLen() {
192        return maxContentLen;
193    }
194
195    /**
196     * Sets the maximum content length limit. Parsing of a MIME entity will be
197     * terminated with a {@link MimeException} if a content body exceeds the
198     * maximum length limit. If this parameter is set to a non positive value
199     * the content length check will be disabled.
200     * <p>
201     * Default value: <code>-1</code>
202     *
203     * @param maxContentLen
204     *            maximum content length limit
205     */
206    public void setMaxContentLen(long maxContentLen) {
207        this.maxContentLen = maxContentLen;
208    }
209
210    /**
211     * Returns the value of the line number counting mode.
212     *
213     * @return value of the line number counting mode.
214     */
215    public boolean isCountLineNumbers() {
216        return countLineNumbers;
217    }
218
219    /**
220     * Defines whether the parser should count line numbers. If enabled line
221     * numbers are included in the debug output.
222     * <p>
223     * Default value: <code>false</code>
224     *
225     * @param countLineNumbers
226     *            value of the line number counting mode.
227     */
228    public void setCountLineNumbers(boolean countLineNumbers) {
229        this.countLineNumbers = countLineNumbers;
230    }
231
232    /**
233     * Returns the value of the default content type. When not null, indicates
234     * that the parsing should be headless.
235     *
236     * @return default content type when parsing headless, null otherwise
237     * @see org.apache.james.mime4j.parser.MimeStreamParser#parse(java.io.InputStream)
238     */
239    public String getHeadlessParsing() {
240        return headlessParsing;
241    }
242
243    /**
244     * Defines a default content type. When not null, indicates that the parsing
245     * should be headless.
246     * <p>
247     * Default value: <code>null</code>
248     *
249     * @param contentType
250     *            value of the default content type when parsing headless, null
251     *            otherwise
252     * @see org.apache.james.mime4j.parser.MimeStreamParser#parse(java.io.InputStream)
253     */
254    public void setHeadlessParsing(String contentType) {
255        this.headlessParsing = contentType;
256    }
257
258    @Override
259    public MimeConfig clone() {
260        try {
261            return (MimeConfig) super.clone();
262        } catch (CloneNotSupportedException e) {
263            // this shouldn't happen, since we are Cloneable
264            throw new InternalError();
265        }
266    }
267
268    @Override
269    public String toString() {
270        return "[strict parsing: " + strictParsing + ", max line length: " + maxLineLen + ", max header count: " + maxHeaderCount + ", max content length: " + maxContentLen + ", count line numbers: " + countLineNumbers + "]";
271    }
272
273}