[FILEUPLOAD-199] shaded javax.mail dependencies class replaced by retailed classes from geronimo-javamail_1.4_spec-1.4, which are licensed under ALv2.0

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/fileupload/trunk@1456515 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Simone Tripodi 2013-03-14 16:37:17 +00:00
parent ce463cc55b
commit 4c32be03e2
8 changed files with 615 additions and 92 deletions

View File

@ -200,53 +200,3 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
APACHE COMMONS FILEUPLOAD SUBCOMPONENTS:
The Apache Commons FileUpload jar includes a number of subcomponents with
separate copyright notices and license terms. Your use of the source
code for the these subcomponents is subject to the terms and
conditions of the following licenses.
=
For the javax.mail component (http://www.oracle.com/technetwork/java/javamail/index.html)
This is licensed under the Common Development and Distribution License("CDDL"), see below
Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 2 only ("GPL") or the Common Development
and Distribution License("CDDL") (collectively, the "License"). You
may not use this file except in compliance with the License. You can
obtain a copy of the License at
https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
or packager/legal/LICENSE.txt. See the License for the specific
language governing permissions and limitations under the License.
When distributing the software, include this License Header Notice in each
file and include the License file at packager/legal/LICENSE.txt.
GPL Classpath Exception:
Oracle designates this particular file as subject to the "Classpath"
exception as provided by Oracle in the GPL Version 2 section of the License
file that accompanied this code.
Modifications:
If applicable, add the following below the License Header, with the fields
enclosed by brackets [] replaced by your own identifying information:
"Portions Copyright [year] [name of copyright owner]"
Contributor(s):
If you wish your version of this file to be governed by only the CDDL or
only the GPL Version 2, indicate your decision by adding "[Contributor]
elects to include this software in this distribution under the [CDDL or GPL
Version 2] license." If you don't indicate a single choice of license, a
recipient has the option to distribute your version of this file under
either the CDDL, the GPL Version 2 or to extend the choice of license to
its licensees as provided above. However, if you add GPL Version 2 code
and therefore, elected the GPL Version 2 license, then the option applies
only if the new code is made subject to such option by the copyright
holder.
=

41
pom.xml
View File

@ -210,12 +210,6 @@
<artifactId>commons-io</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.5</version>
<optional>true</optional>
</dependency>
</dependencies>
<build>
@ -237,41 +231,6 @@
<goals>deploy</goals>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>javax.mail:mail</include>
</includes>
</artifactSet>
<filters>
<filter>
<artifact>javax.mail:mail</artifact>
<includes>
<include>javax/mail/MessagingException*</include>
<include>javax/mail/internet/MimeUtility*</include>
</includes>
</filter>
</filters>
<relocations>
<relocation>
<pattern>javax.mail</pattern>
<shadedPattern>org.apache.commons.fileupload.util.javax.mail</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

View File

@ -21,7 +21,7 @@ import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.mail.internet.MimeUtility;
import org.apache.commons.fileupload.util.mime.MimeUtility;
/**
* A simple parser intended to parse sequences of name/value pairs.

View File

@ -0,0 +1,156 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.fileupload.util.mime;
import java.io.IOException;
import java.io.OutputStream;
/**
* @since 1.3
*/
final class Base64Decoder {
protected final byte[] encodingTable = {
(byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
(byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
(byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
(byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
(byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
(byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
(byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
(byte)'v',
(byte)'w', (byte)'x', (byte)'y', (byte)'z',
(byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6',
(byte)'7', (byte)'8', (byte)'9',
(byte)'+', (byte)'/'
};
protected byte padding = (byte)'=';
/*
* set up the decoding table.
*/
protected final byte[] decodingTable = new byte[256];
protected void initialiseDecodingTable() {
for (int i = 0; i < encodingTable.length; i++) {
decodingTable[encodingTable[i]] = (byte)i;
}
}
public Base64Decoder() {
initialiseDecodingTable();
}
private boolean ignore(
char c) {
return (c == '\n' || c =='\r' || c == '\t' || c == ' ');
}
/**
* decode the base 64 encoded byte data writing it to the given output stream,
* whitespace characters will be ignored.
*
* @return the number of bytes produced.
*/
public int decode(
byte[] data,
int off,
int length,
OutputStream out)
throws IOException {
byte b1, b2, b3, b4;
int outLen = 0;
int end = off + length;
while (end > 0) {
if (!ignore((char)data[end - 1])) {
break;
}
end--;
}
int i = off;
int finish = end - 4;
while (i < finish) {
while ((i < finish) && ignore((char)data[i])) {
i++;
}
b1 = decodingTable[data[i++]];
while ((i < finish) && ignore((char)data[i])) {
i++;
}
b2 = decodingTable[data[i++]];
while ((i < finish) && ignore((char)data[i])) {
i++;
}
b3 = decodingTable[data[i++]];
while ((i < finish) && ignore((char)data[i])) {
i++;
}
b4 = decodingTable[data[i++]];
out.write((b1 << 2) | (b2 >> 4));
out.write((b2 << 4) | (b3 >> 2));
out.write((b3 << 6) | b4);
outLen += 3;
}
if (data[end - 2] == padding) {
b1 = decodingTable[data[end - 4]];
b2 = decodingTable[data[end - 3]];
out.write((b1 << 2) | (b2 >> 4));
outLen += 1;
} else if (data[end - 1] == padding) {
b1 = decodingTable[data[end - 4]];
b2 = decodingTable[data[end - 3]];
b3 = decodingTable[data[end - 2]];
out.write((b1 << 2) | (b2 >> 4));
out.write((b2 << 4) | (b3 >> 2));
outLen += 2;
} else {
b1 = decodingTable[data[end - 4]];
b2 = decodingTable[data[end - 3]];
b3 = decodingTable[data[end - 2]];
b4 = decodingTable[data[end - 1]];
out.write((b1 << 2) | (b2 >> 4));
out.write((b2 << 4) | (b3 >> 2));
out.write((b3 << 6) | b4);
outLen += 3;
}
return outLen;
}
}

View File

@ -0,0 +1,257 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.fileupload.util.mime;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
/**
* Utility class to decode MIME texts.
*
* Imported and retailed from <a href="http://svn.apache.org/repos/asf/geronimo/specs/tags/geronimo-javamail_1.4_spec-1.4/src/main/java/javax/mail/internet/MimeUtility.java">Apache Geronimo</a>
*
* @since 1.3
*/
public final class MimeUtility {
private static final String LINEAR_WHITESPACE = " \t\r\n";
private static final Map<String, String> MIME2JAVA = new HashMap<String, String>();
private static final Base64Decoder BASE64_DECODER = new Base64Decoder();
static {
MIME2JAVA.put("iso-2022-cn", "ISO2022CN");
MIME2JAVA.put("iso-2022-kr", "ISO2022KR");
MIME2JAVA.put("utf-8", "UTF8");
MIME2JAVA.put("utf8", "UTF8");
MIME2JAVA.put("ja_jp.iso2022-7", "ISO2022JP");
MIME2JAVA.put("ja_jp.eucjp", "EUCJIS");
MIME2JAVA.put("euc-kr", "KSC5601");
MIME2JAVA.put("euckr", "KSC5601");
MIME2JAVA.put("us-ascii", "ISO-8859-1");
MIME2JAVA.put("x-us-ascii", "ISO-8859-1");
}
/**
* Hidden constructor, this class must not be instantiated.
*/
private MimeUtility() {
// do nothing
}
/**
* Decode a string of text obtained from a mail header into
* it's proper form. The text generally will consist of a
* string of tokens, some of which may be encoded using
* base64 encoding.
*
* @param text The text to decode.
*
* @return The decoded test string.
* @exception UnsupportedEncodingException
*/
public static String decodeText(String text) throws UnsupportedEncodingException {
// if the text contains any encoded tokens, those tokens will be marked with "=?". If the
// source string doesn't contain that sequent, no decoding is required.
if (text.indexOf("=?") < 0) {
return text;
}
int offset = 0;
int endOffset = text.length();
int startWhiteSpace = -1;
int endWhiteSpace = -1;
StringBuffer decodedText = new StringBuffer(text.length());
boolean previousTokenEncoded = false;
while (offset < endOffset) {
char ch = text.charAt(offset);
// is this a whitespace character?
if (LINEAR_WHITESPACE.indexOf(ch) != -1) {
startWhiteSpace = offset;
while (offset < endOffset) {
// step over the white space characters.
ch = text.charAt(offset);
if (LINEAR_WHITESPACE.indexOf(ch) != -1) {
offset++;
}
else {
// record the location of the first non lwsp and drop down to process the
// token characters.
endWhiteSpace = offset;
break;
}
}
} else {
// we have a word token. We need to scan over the word and then try to parse it.
int wordStart = offset;
while (offset < endOffset) {
// step over the white space characters.
ch = text.charAt(offset);
if (LINEAR_WHITESPACE.indexOf(ch) == -1) {
offset++;
}
else {
break;
}
//NB: Trailing whitespace on these header strings will just be discarded.
}
// pull out the word token.
String word = text.substring(wordStart, offset);
// is the token encoded? decode the word
if (word.startsWith("=?")) {
try {
// if this gives a parsing failure, treat it like a non-encoded word.
String decodedWord = decodeWord(word);
// are any whitespace characters significant? Append 'em if we've got 'em.
if (!previousTokenEncoded) {
if (startWhiteSpace != -1) {
decodedText.append(text.substring(startWhiteSpace, endWhiteSpace));
startWhiteSpace = -1;
}
}
// this is definitely a decoded token.
previousTokenEncoded = true;
// and add this to the text.
decodedText.append(decodedWord);
// we continue parsing from here...we allow parsing errors to fall through
// and get handled as normal text.
continue;
} catch (ParseException e) {
}
}
// this is a normal token, so it doesn't matter what the previous token was. Add the white space
// if we have it.
if (startWhiteSpace != -1) {
decodedText.append(text.substring(startWhiteSpace, endWhiteSpace));
startWhiteSpace = -1;
}
// this is not a decoded token.
previousTokenEncoded = false;
decodedText.append(word);
}
}
return decodedText.toString();
}
/**
* Parse a string using the RFC 2047 rules for an "encoded-word"
* type. This encoding has the syntax:
*
* encoded-word = "=?" charset "?" encoding "?" encoded-text "?="
*
* @param word The possibly encoded word value.
*
* @return The decoded word.
* @exception ParseException
* @exception UnsupportedEncodingException
*/
private static String decodeWord(String word) throws ParseException, UnsupportedEncodingException {
// encoded words start with the characters "=?". If this not an encoded word, we throw a
// ParseException for the caller.
if (!word.startsWith("=?")) {
throw new ParseException("Invalid RFC 2047 encoded-word: " + word);
}
int charsetPos = word.indexOf('?', 2);
if (charsetPos == -1) {
throw new ParseException("Missing charset in RFC 2047 encoded-word: " + word);
}
// pull out the character set information (this is the MIME name at this point).
String charset = word.substring(2, charsetPos).toLowerCase();
// now pull out the encoding token the same way.
int encodingPos = word.indexOf('?', charsetPos + 1);
if (encodingPos == -1) {
throw new ParseException("Missing encoding in RFC 2047 encoded-word: " + word);
}
String encoding = word.substring(charsetPos + 1, encodingPos);
// and finally the encoded text.
int encodedTextPos = word.indexOf("?=", encodingPos + 1);
if (encodedTextPos == -1) {
throw new ParseException("Missing encoded text in RFC 2047 encoded-word: " + word);
}
String encodedText = word.substring(encodingPos + 1, encodedTextPos);
// seems a bit silly to encode a null string, but easy to deal with.
if (encodedText.length() == 0) {
return "";
}
try {
// the decoder writes directly to an output stream.
ByteArrayOutputStream out = new ByteArrayOutputStream(encodedText.length());
byte[] encodedData = encodedText.getBytes("US-ASCII");
// Base64 encoded?
if (encoding.equals("B")) {
BASE64_DECODER.decode(encodedData, 0, encodedData.length, out);
} else if (encoding.equals("Q")) { // maybe quoted printable.
QuotedPrintableDecoder dataEncoder = new QuotedPrintableDecoder();
dataEncoder.decodeWord(encodedData, 0, encodedData.length, out);
} else {
throw new UnsupportedEncodingException("Unknown RFC 2047 encoding: " + encoding);
}
// get the decoded byte data and convert into a string.
byte[] decodedData = out.toByteArray();
return new String(decodedData, javaCharset(charset));
} catch (IOException e) {
throw new UnsupportedEncodingException("Invalid RFC 2047 encoding");
}
}
/**
* Translate a MIME standard character set name into the Java
* equivalent.
*
* @param charset The MIME standard name.
*
* @return The Java equivalent for this name.
*/
private static String javaCharset(String charset) {
// nothing in, nothing out.
if (charset == null) {
return null;
}
String mappedCharset = MIME2JAVA.get(charset.toLowerCase(Locale.ENGLISH));
// if there is no mapping, then the original name is used. Many of the MIME character set
// names map directly back into Java. The reverse isn't necessarily true.
return mappedCharset == null ? charset : mappedCharset;
}
}

View File

@ -0,0 +1,33 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.fileupload.util.mime;
/**
* @since 1.3
*/
public final class ParseException extends Exception {
/**
*
*/
private static final long serialVersionUID = 5355281266579392077L;
public ParseException(String message) {
super(message);
}
}

View File

@ -0,0 +1,146 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.fileupload.util.mime;
import java.io.IOException;
import java.io.OutputStream;
/**
* @since 1.3
*/
final class QuotedPrintableDecoder {
/**
* set up the encoding table.
*/
static protected final byte[] ENCODING_TABLE =
{
(byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
(byte)'8', (byte)'9', (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F'
};
/**
* set up the decoding table.
*/
static protected final byte[] DECODING_TABLE = new byte[128];
static {
// initialize the decoding table
for (int i = 0; i < ENCODING_TABLE.length; i++) {
DECODING_TABLE[ENCODING_TABLE[i]] = (byte)i;
}
}
// default number of characters we will write per line.
static private final int DEFAULT_CHARS_PER_LINE = 76;
// the output stream we're wrapped around
protected OutputStream out;
// the number of bytes written;
protected int bytesWritten = 0;
// number of bytes written on the current line
protected int lineCount = 0;
// line length we're dealing with
protected int lineLength;
// number of deferred whitespace characters in decode mode.
protected int deferredWhitespace = 0;
protected int cachedCharacter = -1;
// indicates whether the last character was a '\r', potentially part of a CRLF sequence.
protected boolean lastCR = false;
// remember whether last character was a white space.
protected boolean lastWhitespace = false;
public QuotedPrintableDecoder() {
this(null, DEFAULT_CHARS_PER_LINE);
}
public QuotedPrintableDecoder(OutputStream out) {
this(out, DEFAULT_CHARS_PER_LINE);
}
public QuotedPrintableDecoder(OutputStream out, int lineLength) {
this.out = out;
this.lineLength = lineLength;
}
/**
* decode the uuencoded byte data writing it to the given output stream
*
* @param data The array of byte data to decode.
* @param off Starting offset within the array.
* @param length The length of data to encode.
* @param out The output stream used to return the decoded data.
*
* @return the number of bytes produced.
* @exception IOException
*/
public int decodeWord(byte[] data, int off, int length, OutputStream out) throws IOException {
// make sure we're writing to the correct stream
this.out = out;
int endOffset = off + length;
int bytesWritten = 0;
while (off < endOffset) {
byte ch = data[off++];
// space characters were translated to '_' on encode, so we need to translate them back.
if (ch == '_') {
out.write(' ');
} else if (ch == '=') {
// we found an encoded character. Reduce the 3 char sequence to one.
// but first, make sure we have two characters to work with.
if (off + 1 >= endOffset) {
throw new IOException("Invalid quoted printable encoding");
}
// convert the two bytes back from hex.
byte b1 = data[off++];
byte b2 = data[off++];
// we've found an encoded carriage return. The next char needs to be a newline
if (b1 == '\r') {
if (b2 != '\n') {
throw new IOException("Invalid quoted printable encoding");
}
// this was a soft linebreak inserted by the encoding. We just toss this away
// on decode.
} else {
// this is a hex pair we need to convert back to a single byte.
byte c1 = DECODING_TABLE[b1];
byte c2 = DECODING_TABLE[b2];
out.write((c1 << 4) | c2);
// 3 bytes in, one byte out
bytesWritten++;
}
} else {
// simple character, just write it out.
out.write(ch);
bytesWritten++;
}
}
return bytesWritten;
}
}

View File

@ -0,0 +1,22 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* MIME decoder implementation, imported and retailed from
* <a href="http://svn.apache.org/repos/asf/geronimo/specs/tags/geronimo-javamail_1.4_spec-1.4/">Apache Geronimo</a>.
*/
package org.apache.commons.fileupload.util.mime;