first commit
This commit is contained in:
commit
4d332ef662
27586 changed files with 3281783 additions and 0 deletions
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed 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.
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
Manifest-Version: 1.0
|
||||
Implementation-Build: trunk@r1565338; 2014-02-06 17:03:20+0000
|
||||
Built-By: Administrator
|
||||
X-Compile-Source-JDK: 1.5
|
||||
Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
Import-Package: javax.servlet,javax.servlet.http,org.apache.commons.io
|
||||
,org.apache.commons.io.output
|
||||
Include-Resource: META-INF/LICENSE.txt=LICENSE.txt,META-INF/NOTICE.txt
|
||||
=NOTICE.txt
|
||||
Implementation-Vendor-Id: org.apache
|
||||
Bnd-LastModified: 1391706206354
|
||||
Bundle-Version: 1.3.1
|
||||
Bundle-Description: The Apache Commons FileUpload component provides a
|
||||
simple yet flexible means of adding support for multipart file up
|
||||
load functionality to servlets and web applications.
|
||||
Bundle-Name: Apache Commons FileUpload
|
||||
Build-Jdk: 1.5.0_22
|
||||
Bundle-ManifestVersion: 2
|
||||
Tool: Bnd-2.1.0.20130426-122213
|
||||
Specification-Vendor: The Apache Software Foundation
|
||||
Implementation-Version: 1.3.1
|
||||
DynamicImport-Package: javax.portlet
|
||||
Implementation-Vendor: The Apache Software Foundation
|
||||
Specification-Title: Apache Commons FileUpload
|
||||
Archiver-Version: Plexus Archiver
|
||||
Created-By: Apache Maven Bundle Plugin
|
||||
Specification-Version: 1.3.1
|
||||
Export-Package: org.apache.commons.fileupload;version="1.3.1",org.apac
|
||||
he.commons.fileupload.disk;version="1.3.1",org.apache.commons.fileupl
|
||||
oad.portlet;version="1.3.1",org.apache.commons.fileupload.servlet;ver
|
||||
sion="1.3.1",org.apache.commons.fileupload.util;version="1.3.1"
|
||||
X-Compile-Target-JDK: 1.5
|
||||
Private-Package: org.apache.commons.fileupload.util.mime
|
||||
Bundle-DocURL: http://commons.apache.org/proper/commons-fileupload/
|
||||
Bundle-Vendor: The Apache Software Foundation
|
||||
Bundle-SymbolicName: org.apache.commons.fileupload
|
||||
Implementation-Title: Apache Commons FileUpload
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
Apache Commons FileUpload
|
||||
Copyright 2002-2014 The Apache Software Foundation
|
||||
|
||||
This product includes software developed at
|
||||
The Apache Software Foundation (http://www.apache.org/).
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
#Generated by Maven
|
||||
#Thu Feb 06 17:03:33 GMT 2014
|
||||
version=1.3.1
|
||||
groupId=commons-fileupload
|
||||
artifactId=commons-fileupload
|
||||
|
|
@ -0,0 +1,298 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-parent</artifactId>
|
||||
<version>32</version>
|
||||
</parent>
|
||||
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
<version>1.3.1</version>
|
||||
|
||||
<name>Apache Commons FileUpload</name>
|
||||
<description>
|
||||
The Apache Commons FileUpload component provides a simple yet flexible means of adding support for multipart
|
||||
file upload functionality to servlets and web applications.
|
||||
</description>
|
||||
<url>http://commons.apache.org/proper/commons-fileupload/</url>
|
||||
<inceptionYear>2002</inceptionYear>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<name>Martin Cooper</name>
|
||||
<id>martinc</id>
|
||||
<email>martinc@apache.org</email>
|
||||
<organization>Yahoo!</organization>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>dIon Gillard</name>
|
||||
<id>dion</id>
|
||||
<email>dion@apache.org</email>
|
||||
<organization>Multitask Consulting</organization>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>John McNally</name>
|
||||
<id>jmcnally</id>
|
||||
<email>jmcnally@collab.net</email>
|
||||
<organization>CollabNet</organization>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Daniel Rall</name>
|
||||
<id>dlr</id>
|
||||
<email>dlr@finemaltcoding.com</email>
|
||||
<organization>CollabNet</organization>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Jason van Zyl</name>
|
||||
<id>jvanzyl</id>
|
||||
<email>jason@zenplex.com</email>
|
||||
<organization>Zenplex</organization>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Robert Burrell Donkin</name>
|
||||
<id>rdonkin</id>
|
||||
<email>rdonkin@apache.org</email>
|
||||
<organization />
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Sean C. Sullivan</name>
|
||||
<id>sullis</id>
|
||||
<email>sean |at| seansullivan |dot| com</email>
|
||||
<organization />
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Jochen Wiedmann</name>
|
||||
<id>jochen</id>
|
||||
<email>jochen.wiedmann@gmail.com</email>
|
||||
<organization />
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Simone Tripodi</name>
|
||||
<id>simonetripodi</id>
|
||||
<email>simonetripodi@apache.org</email>
|
||||
<organization>Adobe</organization>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Gary Gregory</name>
|
||||
<id>ggregory</id>
|
||||
<email>ggregory@apache.org</email>
|
||||
<organization />
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<contributors>
|
||||
<contributor>
|
||||
<name>Aaron Freeman</name>
|
||||
<email>aaron@sendthisfile.com</email>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Daniel Fabian</name>
|
||||
<email>dfabian@google.com</email>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Jörg Heinicke</name>
|
||||
<email>joerg.heinicke@gmx.de</email>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Stepan Koltsov</name>
|
||||
<email>yozh@mx1.ru</email>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Michael Macaluso</name>
|
||||
<email>michael.public@wavecorp.com</email>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Amichai Rothman</name>
|
||||
<email>amichai2@amichais.net</email>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Alexander Sova</name>
|
||||
<email>bird@noir.crocodile.org</email>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Paul Spurr</name>
|
||||
<email>pspurr@gmail.com</email>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Thomas Vandahl</name>
|
||||
<email>tv@apache.org</email>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Henry Yandell</name>
|
||||
<email>bayard@apache.org</email>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Jan Novotný</name>
|
||||
<email>novotnaci@gmail.com</email>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>frank</name>
|
||||
<email>mailsurfie@gmail.com</email>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Rafal Krzewski</name>
|
||||
<email>Rafal.Krzewski@e-point.pl</email>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Sean Legassick</name>
|
||||
<email>sean@informage.net</email>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Oleg Kalnichevski</name>
|
||||
<email>oleg@ural.ru</email>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>David Sean Taylor</name>
|
||||
<email>taylor@apache.org</email>
|
||||
</contributor>
|
||||
</contributors>
|
||||
|
||||
<scm>
|
||||
<connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/fileupload/trunk</connection>
|
||||
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/fileupload/trunk</developerConnection>
|
||||
<url>http://svn.apache.org/viewvc/commons/proper/fileupload/trunk</url>
|
||||
</scm>
|
||||
<issueManagement>
|
||||
<system>jira</system>
|
||||
<url>http://issues.apache.org/jira/browse/FILEUPLOAD</url>
|
||||
</issueManagement>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>1.5</maven.compiler.source>
|
||||
<maven.compiler.target>1.5</maven.compiler.target>
|
||||
<maven.compile.encoding>ISO-8859-1</maven.compile.encoding>
|
||||
<commons.componentid>fileupload</commons.componentid>
|
||||
<commons.release.version>1.3.1</commons.release.version>
|
||||
<commons.rc.version>RC1</commons.rc.version>
|
||||
<commons.jira.id>FILEUPLOAD</commons.jira.id>
|
||||
<commons.jira.pid>12310476</commons.jira.pid>
|
||||
<commons.osgi.export>!org.apache.commons.fileupload.util.mime,org.apache.commons.*;version=${project.version};-noimport:=true</commons.osgi.export>
|
||||
<commons.osgi.import>!javax.portlet,*</commons.osgi.import>
|
||||
<commons.osgi.dynamicImport>javax.portlet</commons.osgi.dynamicImport>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<version>2.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>portlet-api</groupId>
|
||||
<artifactId>portlet-api</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>${basedir}/src/main/assembly/bin.xml</descriptor>
|
||||
<descriptor>${basedir}/src/main/assembly/src.xml</descriptor>
|
||||
</descriptors>
|
||||
<tarLongFileMode>gnu</tarLongFileMode>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<configuration>
|
||||
<preparationGoals>clean site verify</preparationGoals>
|
||||
<goals>deploy</goals>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-changes-plugin</artifactId>
|
||||
<version>${commons.changes.version}</version>
|
||||
<configuration>
|
||||
<issueLinkTemplate>%URL%/../%ISSUE%</issueLinkTemplate>
|
||||
</configuration>
|
||||
<reportSets>
|
||||
<reportSet>
|
||||
<reports>
|
||||
<report>changes-report</report>
|
||||
<!-- NPE, retry from time to time <report>jira-report</report> -->
|
||||
</reports>
|
||||
</reportSet>
|
||||
</reportSets>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>2.10</version>
|
||||
<configuration>
|
||||
<configLocation>${basedir}/src/checkstyle/fileupload_checks.xml</configLocation>
|
||||
<suppressionsLocation>${basedir}/src/checkstyle/checkstyle-suppressions.xml</suppressionsLocation>
|
||||
<enableRulesSummary>false</enableRulesSummary>
|
||||
<headerLocation>${basedir}/src/checkstyle/license-header.txt</headerLocation>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-pmd-plugin</artifactId>
|
||||
<version>2.7.1</version>
|
||||
<configuration>
|
||||
<targetJdk>${maven.compiler.target}</targetJdk>
|
||||
<rulesets>
|
||||
<ruleset>${basedir}/src/checkstyle/fileupload_basic.xml</ruleset>
|
||||
</rulesets>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>clirr-maven-plugin</artifactId>
|
||||
<version>${commons.clirr.version}</version>
|
||||
<configuration>
|
||||
<comparisonArtifacts>
|
||||
<comparisonArtifact>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
<version>1.3</version>
|
||||
</comparisonArtifact>
|
||||
</comparisonArtifacts>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
|
||||
</project>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package org.apache.commons.fileupload;
|
||||
|
||||
import java.io.File;
|
||||
import org.apache.commons.fileupload.disk.DiskFileItem;
|
||||
|
||||
@Deprecated
|
||||
public class DefaultFileItem extends DiskFileItem {
|
||||
private static final long serialVersionUID = 4088572813833518255L;
|
||||
|
||||
@Deprecated
|
||||
public DefaultFileItem(String fieldName, String contentType, boolean isFormField, String fileName, int sizeThreshold, File repository) {
|
||||
super(fieldName, contentType, isFormField, fileName, sizeThreshold, repository);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package org.apache.commons.fileupload;
|
||||
|
||||
import java.io.File;
|
||||
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
|
||||
|
||||
@Deprecated
|
||||
public class DefaultFileItemFactory extends DiskFileItemFactory {
|
||||
@Deprecated
|
||||
public DefaultFileItemFactory() {}
|
||||
|
||||
@Deprecated
|
||||
public DefaultFileItemFactory(int sizeThreshold, File repository) {
|
||||
super(sizeThreshold, repository);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public FileItem createItem(String fieldName, String contentType, boolean isFormField, String fileName) {
|
||||
return new DefaultFileItem(fieldName, contentType, isFormField, fileName, getSizeThreshold(), getRepository());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package org.apache.commons.fileupload;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@Deprecated
|
||||
public class DiskFileUpload extends FileUploadBase {
|
||||
private DefaultFileItemFactory fileItemFactory;
|
||||
|
||||
@Deprecated
|
||||
public DiskFileUpload() {
|
||||
this.fileItemFactory = new DefaultFileItemFactory();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public DiskFileUpload(DefaultFileItemFactory fileItemFactory) {
|
||||
this.fileItemFactory = fileItemFactory;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public FileItemFactory getFileItemFactory() {
|
||||
return this.fileItemFactory;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setFileItemFactory(FileItemFactory factory) {
|
||||
this.fileItemFactory = (DefaultFileItemFactory)factory;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public int getSizeThreshold() {
|
||||
return this.fileItemFactory.getSizeThreshold();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setSizeThreshold(int sizeThreshold) {
|
||||
this.fileItemFactory.setSizeThreshold(sizeThreshold);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getRepositoryPath() {
|
||||
return this.fileItemFactory.getRepository().getPath();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setRepositoryPath(String repositoryPath) {
|
||||
this.fileItemFactory.setRepository(new File(repositoryPath));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public List<FileItem> parseRequest(HttpServletRequest req, int sizeThreshold, long sizeMax, String path) throws FileUploadException {
|
||||
setSizeThreshold(sizeThreshold);
|
||||
setSizeMax(sizeMax);
|
||||
setRepositoryPath(path);
|
||||
return parseRequest(req);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package org.apache.commons.fileupload;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
public interface FileItem extends Serializable, FileItemHeadersSupport {
|
||||
InputStream getInputStream() throws IOException;
|
||||
|
||||
String getContentType();
|
||||
|
||||
String getName();
|
||||
|
||||
boolean isInMemory();
|
||||
|
||||
long getSize();
|
||||
|
||||
byte[] get();
|
||||
|
||||
String getString(String paramString) throws UnsupportedEncodingException;
|
||||
|
||||
String getString();
|
||||
|
||||
void write(File paramFile) throws Exception;
|
||||
|
||||
void delete();
|
||||
|
||||
String getFieldName();
|
||||
|
||||
void setFieldName(String paramString);
|
||||
|
||||
boolean isFormField();
|
||||
|
||||
void setFormField(boolean paramBoolean);
|
||||
|
||||
OutputStream getOutputStream() throws IOException;
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package org.apache.commons.fileupload;
|
||||
|
||||
public interface FileItemFactory {
|
||||
FileItem createItem(String paramString1, String paramString2, boolean paramBoolean, String paramString3);
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package org.apache.commons.fileupload;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
public interface FileItemHeaders {
|
||||
String getHeader(String paramString);
|
||||
|
||||
Iterator<String> getHeaders(String paramString);
|
||||
|
||||
Iterator<String> getHeaderNames();
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package org.apache.commons.fileupload;
|
||||
|
||||
public interface FileItemHeadersSupport {
|
||||
FileItemHeaders getHeaders();
|
||||
|
||||
void setHeaders(FileItemHeaders paramFileItemHeaders);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package org.apache.commons.fileupload;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface FileItemIterator {
|
||||
boolean hasNext() throws FileUploadException, IOException;
|
||||
|
||||
FileItemStream next() throws FileUploadException, IOException;
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package org.apache.commons.fileupload;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public interface FileItemStream extends FileItemHeadersSupport {
|
||||
InputStream openStream() throws IOException;
|
||||
|
||||
String getContentType();
|
||||
|
||||
String getName();
|
||||
|
||||
String getFieldName();
|
||||
|
||||
boolean isFormField();
|
||||
|
||||
public static class ItemSkippedException extends IOException {
|
||||
private static final long serialVersionUID = -7280778431581963740L;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package org.apache.commons.fileupload;
|
||||
|
||||
public class FileUpload extends FileUploadBase {
|
||||
private FileItemFactory fileItemFactory;
|
||||
|
||||
public FileUpload() {}
|
||||
|
||||
public FileUpload(FileItemFactory fileItemFactory) {
|
||||
this.fileItemFactory = fileItemFactory;
|
||||
}
|
||||
|
||||
public FileItemFactory getFileItemFactory() {
|
||||
return this.fileItemFactory;
|
||||
}
|
||||
|
||||
public void setFileItemFactory(FileItemFactory factory) {
|
||||
this.fileItemFactory = factory;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,650 @@
|
|||
package org.apache.commons.fileupload;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.apache.commons.fileupload.servlet.ServletFileUpload;
|
||||
import org.apache.commons.fileupload.servlet.ServletRequestContext;
|
||||
import org.apache.commons.fileupload.util.Closeable;
|
||||
import org.apache.commons.fileupload.util.FileItemHeadersImpl;
|
||||
import org.apache.commons.fileupload.util.LimitedInputStream;
|
||||
import org.apache.commons.fileupload.util.Streams;
|
||||
|
||||
public abstract class FileUploadBase {
|
||||
public static final String CONTENT_TYPE = "Content-type";
|
||||
|
||||
public static final String CONTENT_DISPOSITION = "Content-disposition";
|
||||
|
||||
public static final String CONTENT_LENGTH = "Content-length";
|
||||
|
||||
public static final String FORM_DATA = "form-data";
|
||||
|
||||
public static final String ATTACHMENT = "attachment";
|
||||
|
||||
public static final String MULTIPART = "multipart/";
|
||||
|
||||
public static final String MULTIPART_FORM_DATA = "multipart/form-data";
|
||||
|
||||
public static final String MULTIPART_MIXED = "multipart/mixed";
|
||||
|
||||
@Deprecated
|
||||
public static final int MAX_HEADER_SIZE = 1024;
|
||||
|
||||
public static final boolean isMultipartContent(RequestContext ctx) {
|
||||
String contentType = ctx.getContentType();
|
||||
if (contentType == null)
|
||||
return false;
|
||||
if (contentType.toLowerCase(Locale.ENGLISH).startsWith("multipart/"))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static boolean isMultipartContent(HttpServletRequest req) {
|
||||
return ServletFileUpload.isMultipartContent(req);
|
||||
}
|
||||
|
||||
private long sizeMax = -1L;
|
||||
|
||||
private long fileSizeMax = -1L;
|
||||
|
||||
private String headerEncoding;
|
||||
|
||||
private ProgressListener listener;
|
||||
|
||||
public long getSizeMax() {
|
||||
return this.sizeMax;
|
||||
}
|
||||
|
||||
public void setSizeMax(long sizeMax) {
|
||||
this.sizeMax = sizeMax;
|
||||
}
|
||||
|
||||
public long getFileSizeMax() {
|
||||
return this.fileSizeMax;
|
||||
}
|
||||
|
||||
public void setFileSizeMax(long fileSizeMax) {
|
||||
this.fileSizeMax = fileSizeMax;
|
||||
}
|
||||
|
||||
public String getHeaderEncoding() {
|
||||
return this.headerEncoding;
|
||||
}
|
||||
|
||||
public void setHeaderEncoding(String encoding) {
|
||||
this.headerEncoding = encoding;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public List<FileItem> parseRequest(HttpServletRequest req) throws FileUploadException {
|
||||
return parseRequest(new ServletRequestContext(req));
|
||||
}
|
||||
|
||||
public FileItemIterator getItemIterator(RequestContext ctx) throws FileUploadException, IOException {
|
||||
try {
|
||||
return new FileItemIteratorImpl(ctx);
|
||||
} catch (FileUploadIOException e) {
|
||||
throw (FileUploadException)e.getCause();
|
||||
}
|
||||
}
|
||||
|
||||
public List<FileItem> parseRequest(RequestContext ctx) throws FileUploadException {
|
||||
List<FileItem> items = new ArrayList<FileItem>();
|
||||
boolean successful = false;
|
||||
try {
|
||||
FileItemIterator iter = getItemIterator(ctx);
|
||||
FileItemFactory fac = getFileItemFactory();
|
||||
if (fac == null)
|
||||
throw new NullPointerException("No FileItemFactory has been set.");
|
||||
while (iter.hasNext()) {
|
||||
FileItemStream item = iter.next();
|
||||
String fileName = ((FileItemIteratorImpl.FileItemStreamImpl)item).name;
|
||||
FileItem fileItem = fac.createItem(item.getFieldName(), item.getContentType(), item.isFormField(), fileName);
|
||||
items.add(fileItem);
|
||||
try {
|
||||
Streams.copy(item.openStream(), fileItem.getOutputStream(), true);
|
||||
} catch (FileUploadIOException e) {
|
||||
throw (FileUploadException)e.getCause();
|
||||
} catch (IOException e) {
|
||||
throw new IOFileUploadException(String.format("Processing of %s request failed. %s", "multipart/form-data", e.getMessage()), e);
|
||||
}
|
||||
FileItemHeaders fih = item.getHeaders();
|
||||
fileItem.setHeaders(fih);
|
||||
}
|
||||
successful = true;
|
||||
return items;
|
||||
} catch (FileUploadIOException e) {
|
||||
throw (FileUploadException)e.getCause();
|
||||
} catch (IOException e) {
|
||||
throw new FileUploadException(e.getMessage(), e);
|
||||
} finally {
|
||||
if (!successful)
|
||||
for (FileItem fileItem : items) {
|
||||
try {
|
||||
fileItem.delete();
|
||||
} catch (Throwable e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, List<FileItem>> parseParameterMap(RequestContext ctx) throws FileUploadException {
|
||||
List<FileItem> items = parseRequest(ctx);
|
||||
Map<String, List<FileItem>> itemsMap = new HashMap<String, List<FileItem>>(items.size());
|
||||
for (FileItem fileItem : items) {
|
||||
String fieldName = fileItem.getFieldName();
|
||||
List<FileItem> mappedItems = itemsMap.get(fieldName);
|
||||
if (mappedItems == null) {
|
||||
mappedItems = new ArrayList<FileItem>();
|
||||
itemsMap.put(fieldName, mappedItems);
|
||||
}
|
||||
mappedItems.add(fileItem);
|
||||
}
|
||||
return itemsMap;
|
||||
}
|
||||
|
||||
protected byte[] getBoundary(String contentType) {
|
||||
byte[] arrayOfByte;
|
||||
ParameterParser parser = new ParameterParser();
|
||||
parser.setLowerCaseNames(true);
|
||||
Map<String, String> params = parser.parse(contentType, new char[] { ';', ',' });
|
||||
String boundaryStr = params.get("boundary");
|
||||
if (boundaryStr == null)
|
||||
return null;
|
||||
try {
|
||||
arrayOfByte = boundaryStr.getBytes("ISO-8859-1");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
arrayOfByte = boundaryStr.getBytes();
|
||||
}
|
||||
return arrayOfByte;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
protected String getFileName(Map<String, String> headers) {
|
||||
return getFileName(getHeader(headers, "Content-disposition"));
|
||||
}
|
||||
|
||||
protected String getFileName(FileItemHeaders headers) {
|
||||
return getFileName(headers.getHeader("Content-disposition"));
|
||||
}
|
||||
|
||||
private String getFileName(String pContentDisposition) {
|
||||
String fileName = null;
|
||||
if (pContentDisposition != null) {
|
||||
String cdl = pContentDisposition.toLowerCase(Locale.ENGLISH);
|
||||
if (cdl.startsWith("form-data") || cdl.startsWith("attachment")) {
|
||||
ParameterParser parser = new ParameterParser();
|
||||
parser.setLowerCaseNames(true);
|
||||
Map<String, String> params = parser.parse(pContentDisposition, ';');
|
||||
if (params.containsKey("filename")) {
|
||||
fileName = params.get("filename");
|
||||
if (fileName != null) {
|
||||
fileName = fileName.trim();
|
||||
} else {
|
||||
fileName = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
|
||||
protected String getFieldName(FileItemHeaders headers) {
|
||||
return getFieldName(headers.getHeader("Content-disposition"));
|
||||
}
|
||||
|
||||
private String getFieldName(String pContentDisposition) {
|
||||
String fieldName = null;
|
||||
if (pContentDisposition != null && pContentDisposition.toLowerCase(Locale.ENGLISH).startsWith("form-data")) {
|
||||
ParameterParser parser = new ParameterParser();
|
||||
parser.setLowerCaseNames(true);
|
||||
Map<String, String> params = parser.parse(pContentDisposition, ';');
|
||||
fieldName = params.get("name");
|
||||
if (fieldName != null)
|
||||
fieldName = fieldName.trim();
|
||||
}
|
||||
return fieldName;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
protected String getFieldName(Map<String, String> headers) {
|
||||
return getFieldName(getHeader(headers, "Content-disposition"));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
protected FileItem createItem(Map<String, String> headers, boolean isFormField) throws FileUploadException {
|
||||
return getFileItemFactory().createItem(getFieldName(headers), getHeader(headers, "Content-type"), isFormField, getFileName(headers));
|
||||
}
|
||||
|
||||
protected FileItemHeaders getParsedHeaders(String headerPart) {
|
||||
int len = headerPart.length();
|
||||
FileItemHeadersImpl headers = newFileItemHeaders();
|
||||
int start = 0;
|
||||
while (true) {
|
||||
int end = parseEndOfLine(headerPart, start);
|
||||
if (start == end)
|
||||
break;
|
||||
StringBuilder header = new StringBuilder(headerPart.substring(start, end));
|
||||
start = end + 2;
|
||||
while (start < len) {
|
||||
int nonWs = start;
|
||||
while (nonWs < len) {
|
||||
char c = headerPart.charAt(nonWs);
|
||||
if (c != ' ' && c != '\t')
|
||||
break;
|
||||
nonWs++;
|
||||
}
|
||||
if (nonWs == start)
|
||||
break;
|
||||
end = parseEndOfLine(headerPart, nonWs);
|
||||
header.append(" ").append(headerPart.substring(nonWs, end));
|
||||
start = end + 2;
|
||||
}
|
||||
parseHeaderLine(headers, header.toString());
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
protected FileItemHeadersImpl newFileItemHeaders() {
|
||||
return new FileItemHeadersImpl();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
protected Map<String, String> parseHeaders(String headerPart) {
|
||||
FileItemHeaders headers = getParsedHeaders(headerPart);
|
||||
Map<String, String> result = new HashMap<String, String>();
|
||||
for (Iterator<String> iter = headers.getHeaderNames(); iter.hasNext(); ) {
|
||||
String headerName = iter.next();
|
||||
Iterator<String> iter2 = headers.getHeaders(headerName);
|
||||
StringBuilder headerValue = new StringBuilder(iter2.next());
|
||||
while (iter2.hasNext())
|
||||
headerValue.append(",").append(iter2.next());
|
||||
result.put(headerName, headerValue.toString());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private int parseEndOfLine(String headerPart, int end) {
|
||||
int index = end;
|
||||
while (true) {
|
||||
int offset = headerPart.indexOf('\r', index);
|
||||
if (offset == -1 || offset + 1 >= headerPart.length())
|
||||
throw new IllegalStateException("Expected headers to be terminated by an empty line.");
|
||||
if (headerPart.charAt(offset + 1) == '\n')
|
||||
return offset;
|
||||
index = offset + 1;
|
||||
}
|
||||
}
|
||||
|
||||
private void parseHeaderLine(FileItemHeadersImpl headers, String header) {
|
||||
int colonOffset = header.indexOf(':');
|
||||
if (colonOffset == -1)
|
||||
return;
|
||||
String headerName = header.substring(0, colonOffset).trim();
|
||||
String headerValue = header.substring(header.indexOf(':') + 1).trim();
|
||||
headers.addHeader(headerName, headerValue);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
protected final String getHeader(Map<String, String> headers, String name) {
|
||||
return headers.get(name.toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
|
||||
private class FileItemIteratorImpl implements FileItemIterator {
|
||||
private final MultipartStream multi;
|
||||
|
||||
private final MultipartStream.ProgressNotifier notifier;
|
||||
|
||||
private final byte[] boundary;
|
||||
|
||||
private FileItemStreamImpl currentItem;
|
||||
|
||||
private String currentFieldName;
|
||||
|
||||
private boolean skipPreamble;
|
||||
|
||||
private boolean itemValid;
|
||||
|
||||
private boolean eof;
|
||||
|
||||
class FileItemStreamImpl implements FileItemStream {
|
||||
private final String contentType;
|
||||
|
||||
private final String fieldName;
|
||||
|
||||
private final String name;
|
||||
|
||||
private final boolean formField;
|
||||
|
||||
private final InputStream stream;
|
||||
|
||||
private boolean opened;
|
||||
|
||||
private FileItemHeaders headers;
|
||||
|
||||
FileItemStreamImpl(String pName, String pFieldName, String pContentType, boolean pFormField, long pContentLength) throws IOException {
|
||||
this.name = pName;
|
||||
this.fieldName = pFieldName;
|
||||
this.contentType = pContentType;
|
||||
this.formField = pFormField;
|
||||
final MultipartStream.ItemInputStream itemStream = this$0.multi.newInputStream();
|
||||
InputStream istream = itemStream;
|
||||
if (FileUploadBase.this.fileSizeMax != -1L) {
|
||||
if (pContentLength != -1L && pContentLength > FileUploadBase.this.fileSizeMax) {
|
||||
FileUploadBase.FileSizeLimitExceededException e = new FileUploadBase.FileSizeLimitExceededException(String.format("The field %s exceeds its maximum permitted size of %s bytes.", this.fieldName, FileUploadBase.this.fileSizeMax), pContentLength, FileUploadBase.this.fileSizeMax);
|
||||
e.setFileName(pName);
|
||||
e.setFieldName(pFieldName);
|
||||
throw new FileUploadBase.FileUploadIOException(e);
|
||||
}
|
||||
istream = new LimitedInputStream(istream, FileUploadBase.this.fileSizeMax) {
|
||||
protected void raiseError(long pSizeMax, long pCount) throws IOException {
|
||||
itemStream.close(true);
|
||||
FileUploadBase.FileSizeLimitExceededException e = new FileUploadBase.FileSizeLimitExceededException(String.format("The field %s exceeds its maximum permitted size of %s bytes.", FileItemStreamImpl.this.fieldName, pSizeMax), pCount, pSizeMax);
|
||||
e.setFieldName(FileItemStreamImpl.this.fieldName);
|
||||
e.setFileName(FileItemStreamImpl.this.name);
|
||||
throw new FileUploadBase.FileUploadIOException(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
this.stream = istream;
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return this.contentType;
|
||||
}
|
||||
|
||||
public String getFieldName() {
|
||||
return this.fieldName;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return Streams.checkFileName(this.name);
|
||||
}
|
||||
|
||||
public boolean isFormField() {
|
||||
return this.formField;
|
||||
}
|
||||
|
||||
public InputStream openStream() throws IOException {
|
||||
if (this.opened)
|
||||
throw new IllegalStateException("The stream was already opened.");
|
||||
if (((Closeable)this.stream).isClosed())
|
||||
throw new FileItemStream.ItemSkippedException();
|
||||
return this.stream;
|
||||
}
|
||||
|
||||
void close() throws IOException {
|
||||
this.stream.close();
|
||||
}
|
||||
|
||||
public FileItemHeaders getHeaders() {
|
||||
return this.headers;
|
||||
}
|
||||
|
||||
public void setHeaders(FileItemHeaders pHeaders) {
|
||||
this.headers = pHeaders;
|
||||
}
|
||||
}
|
||||
|
||||
FileItemIteratorImpl(RequestContext ctx) throws FileUploadException, IOException {
|
||||
if (ctx == null)
|
||||
throw new NullPointerException("ctx parameter");
|
||||
String contentType = ctx.getContentType();
|
||||
if (null == contentType || !contentType.toLowerCase(Locale.ENGLISH).startsWith("multipart/"))
|
||||
throw new FileUploadBase.InvalidContentTypeException(String.format("the request doesn't contain a %s or %s stream, content type header is %s", "multipart/form-data", "multipart/mixed", contentType));
|
||||
InputStream input = ctx.getInputStream();
|
||||
int contentLengthInt = ctx.getContentLength();
|
||||
long requestSize = UploadContext.class.isAssignableFrom(ctx.getClass()) ? ((UploadContext)ctx).contentLength() : (long)contentLengthInt;
|
||||
if (FileUploadBase.this.sizeMax >= 0L) {
|
||||
if (requestSize != -1L && requestSize > FileUploadBase.this.sizeMax)
|
||||
throw new FileUploadBase.SizeLimitExceededException(String.format("the request was rejected because its size (%s) exceeds the configured maximum (%s)", requestSize, FileUploadBase.this.sizeMax), requestSize, FileUploadBase.this.sizeMax);
|
||||
input = new LimitedInputStream(input, FileUploadBase.this.sizeMax) {
|
||||
protected void raiseError(long pSizeMax, long pCount) throws IOException {
|
||||
FileUploadException ex = new FileUploadBase.SizeLimitExceededException(String.format("the request was rejected because its size (%s) exceeds the configured maximum (%s)", pCount, pSizeMax), pCount, pSizeMax);
|
||||
throw new FileUploadBase.FileUploadIOException(ex);
|
||||
}
|
||||
};
|
||||
}
|
||||
String charEncoding = this$0.headerEncoding;
|
||||
if (charEncoding == null)
|
||||
charEncoding = ctx.getCharacterEncoding();
|
||||
this.boundary = this$0.getBoundary(contentType);
|
||||
if (this.boundary == null)
|
||||
throw new FileUploadException("the request was rejected because no multipart boundary was found");
|
||||
this.notifier = new MultipartStream.ProgressNotifier(this$0.listener, requestSize);
|
||||
try {
|
||||
this.multi = new MultipartStream(input, this.boundary, this.notifier);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
throw new FileUploadBase.InvalidContentTypeException(String.format("The boundary specified in the %s header is too long", "Content-type"), iae);
|
||||
}
|
||||
this.multi.setHeaderEncoding(charEncoding);
|
||||
this.skipPreamble = true;
|
||||
findNextItem();
|
||||
}
|
||||
|
||||
private boolean findNextItem() throws IOException {
|
||||
if (this.eof)
|
||||
return false;
|
||||
if (this.currentItem != null) {
|
||||
this.currentItem.close();
|
||||
this.currentItem = null;
|
||||
}
|
||||
while (true) {
|
||||
boolean nextPart;
|
||||
if (this.skipPreamble) {
|
||||
nextPart = this.multi.skipPreamble();
|
||||
} else {
|
||||
nextPart = this.multi.readBoundary();
|
||||
}
|
||||
if (!nextPart) {
|
||||
if (this.currentFieldName == null) {
|
||||
this.eof = true;
|
||||
return false;
|
||||
}
|
||||
this.multi.setBoundary(this.boundary);
|
||||
this.currentFieldName = null;
|
||||
continue;
|
||||
}
|
||||
FileItemHeaders headers = FileUploadBase.this.getParsedHeaders(this.multi.readHeaders());
|
||||
if (this.currentFieldName == null) {
|
||||
String fieldName = FileUploadBase.this.getFieldName(headers);
|
||||
if (fieldName != null) {
|
||||
String subContentType = headers.getHeader("Content-type");
|
||||
if (subContentType != null && subContentType.toLowerCase(Locale.ENGLISH).startsWith("multipart/mixed")) {
|
||||
this.currentFieldName = fieldName;
|
||||
byte[] subBoundary = FileUploadBase.this.getBoundary(subContentType);
|
||||
this.multi.setBoundary(subBoundary);
|
||||
this.skipPreamble = true;
|
||||
continue;
|
||||
}
|
||||
String fileName = FileUploadBase.this.getFileName(headers);
|
||||
this.currentItem = new FileItemStreamImpl(fileName, fieldName, headers.getHeader("Content-type"), (fileName == null), getContentLength(headers));
|
||||
this.currentItem.setHeaders(headers);
|
||||
this.notifier.noteItem();
|
||||
this.itemValid = true;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
String fileName = FileUploadBase.this.getFileName(headers);
|
||||
if (fileName != null) {
|
||||
this.currentItem = new FileItemStreamImpl(fileName, this.currentFieldName, headers.getHeader("Content-type"), false, getContentLength(headers));
|
||||
this.currentItem.setHeaders(headers);
|
||||
this.notifier.noteItem();
|
||||
this.itemValid = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
this.multi.discardBodyData();
|
||||
}
|
||||
}
|
||||
|
||||
private long getContentLength(FileItemHeaders pHeaders) {
|
||||
try {
|
||||
return Long.parseLong(pHeaders.getHeader("Content-length"));
|
||||
} catch (Exception e) {
|
||||
return -1L;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasNext() throws FileUploadException, IOException {
|
||||
if (this.eof)
|
||||
return false;
|
||||
if (this.itemValid)
|
||||
return true;
|
||||
try {
|
||||
return findNextItem();
|
||||
} catch (FileUploadBase.FileUploadIOException e) {
|
||||
throw (FileUploadException)e.getCause();
|
||||
}
|
||||
}
|
||||
|
||||
public FileItemStream next() throws FileUploadException, IOException {
|
||||
if (this.eof || (!this.itemValid && !hasNext()))
|
||||
throw new NoSuchElementException();
|
||||
this.itemValid = false;
|
||||
return this.currentItem;
|
||||
}
|
||||
}
|
||||
|
||||
public static class FileUploadIOException extends IOException {
|
||||
private static final long serialVersionUID = -7047616958165584154L;
|
||||
|
||||
private final FileUploadException cause;
|
||||
|
||||
public FileUploadIOException(FileUploadException pCause) {
|
||||
this.cause = pCause;
|
||||
}
|
||||
|
||||
public Throwable getCause() {
|
||||
return this.cause;
|
||||
}
|
||||
}
|
||||
|
||||
public static class InvalidContentTypeException extends FileUploadException {
|
||||
private static final long serialVersionUID = -9073026332015646668L;
|
||||
|
||||
public InvalidContentTypeException() {}
|
||||
|
||||
public InvalidContentTypeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public InvalidContentTypeException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
}
|
||||
|
||||
public static class IOFileUploadException extends FileUploadException {
|
||||
private static final long serialVersionUID = 1749796615868477269L;
|
||||
|
||||
private final IOException cause;
|
||||
|
||||
public IOFileUploadException(String pMsg, IOException pException) {
|
||||
super(pMsg);
|
||||
this.cause = pException;
|
||||
}
|
||||
|
||||
public Throwable getCause() {
|
||||
return this.cause;
|
||||
}
|
||||
}
|
||||
|
||||
protected static abstract class SizeException extends FileUploadException {
|
||||
private static final long serialVersionUID = -8776225574705254126L;
|
||||
|
||||
private final long actual;
|
||||
|
||||
private final long permitted;
|
||||
|
||||
protected SizeException(String message, long actual, long permitted) {
|
||||
super(message);
|
||||
this.actual = actual;
|
||||
this.permitted = permitted;
|
||||
}
|
||||
|
||||
public long getActualSize() {
|
||||
return this.actual;
|
||||
}
|
||||
|
||||
public long getPermittedSize() {
|
||||
return this.permitted;
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static class UnknownSizeException extends FileUploadException {
|
||||
private static final long serialVersionUID = 7062279004812015273L;
|
||||
|
||||
public UnknownSizeException() {}
|
||||
|
||||
public UnknownSizeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SizeLimitExceededException extends SizeException {
|
||||
private static final long serialVersionUID = -2474893167098052828L;
|
||||
|
||||
@Deprecated
|
||||
public SizeLimitExceededException() {
|
||||
this(null, 0L, 0L);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public SizeLimitExceededException(String message) {
|
||||
this(message, 0L, 0L);
|
||||
}
|
||||
|
||||
public SizeLimitExceededException(String message, long actual, long permitted) {
|
||||
super(message, actual, permitted);
|
||||
}
|
||||
}
|
||||
|
||||
public static class FileSizeLimitExceededException extends SizeException {
|
||||
private static final long serialVersionUID = 8150776562029630058L;
|
||||
|
||||
private String fileName;
|
||||
|
||||
private String fieldName;
|
||||
|
||||
public FileSizeLimitExceededException(String message, long actual, long permitted) {
|
||||
super(message, actual, permitted);
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return this.fileName;
|
||||
}
|
||||
|
||||
public void setFileName(String pFileName) {
|
||||
this.fileName = pFileName;
|
||||
}
|
||||
|
||||
public String getFieldName() {
|
||||
return this.fieldName;
|
||||
}
|
||||
|
||||
public void setFieldName(String pFieldName) {
|
||||
this.fieldName = pFieldName;
|
||||
}
|
||||
}
|
||||
|
||||
public ProgressListener getProgressListener() {
|
||||
return this.listener;
|
||||
}
|
||||
|
||||
public void setProgressListener(ProgressListener pListener) {
|
||||
this.listener = pListener;
|
||||
}
|
||||
|
||||
public abstract FileItemFactory getFileItemFactory();
|
||||
|
||||
public abstract void setFileItemFactory(FileItemFactory paramFileItemFactory);
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package org.apache.commons.fileupload;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
public class FileUploadException extends Exception {
|
||||
private static final long serialVersionUID = 8881893724388807504L;
|
||||
|
||||
private final Throwable cause;
|
||||
|
||||
public FileUploadException() {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
public FileUploadException(String msg) {
|
||||
this(msg, null);
|
||||
}
|
||||
|
||||
public FileUploadException(String msg, Throwable cause) {
|
||||
super(msg);
|
||||
this.cause = cause;
|
||||
}
|
||||
|
||||
public void printStackTrace(PrintStream stream) {
|
||||
super.printStackTrace(stream);
|
||||
if (this.cause != null) {
|
||||
stream.println("Caused by:");
|
||||
this.cause.printStackTrace(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public void printStackTrace(PrintWriter writer) {
|
||||
super.printStackTrace(writer);
|
||||
if (this.cause != null) {
|
||||
writer.println("Caused by:");
|
||||
this.cause.printStackTrace(writer);
|
||||
}
|
||||
}
|
||||
|
||||
public Throwable getCause() {
|
||||
return this.cause;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package org.apache.commons.fileupload;
|
||||
|
||||
public class InvalidFileNameException extends RuntimeException {
|
||||
private static final long serialVersionUID = 7922042602454350470L;
|
||||
|
||||
private final String name;
|
||||
|
||||
public InvalidFileNameException(String pName, String pMessage) {
|
||||
super(pMessage);
|
||||
this.name = pName;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,413 @@
|
|||
package org.apache.commons.fileupload;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import org.apache.commons.fileupload.util.Closeable;
|
||||
import org.apache.commons.fileupload.util.Streams;
|
||||
|
||||
public class MultipartStream {
|
||||
public static final byte CR = 13;
|
||||
|
||||
public static final byte LF = 10;
|
||||
|
||||
public static final byte DASH = 45;
|
||||
|
||||
public static final int HEADER_PART_SIZE_MAX = 10240;
|
||||
|
||||
protected static final int DEFAULT_BUFSIZE = 4096;
|
||||
|
||||
public static class ProgressNotifier {
|
||||
private final ProgressListener listener;
|
||||
|
||||
private final long contentLength;
|
||||
|
||||
private long bytesRead;
|
||||
|
||||
private int items;
|
||||
|
||||
ProgressNotifier(ProgressListener pListener, long pContentLength) {
|
||||
this.listener = pListener;
|
||||
this.contentLength = pContentLength;
|
||||
}
|
||||
|
||||
void noteBytesRead(int pBytes) {
|
||||
this.bytesRead += (long)pBytes;
|
||||
notifyListener();
|
||||
}
|
||||
|
||||
void noteItem() {
|
||||
this.items++;
|
||||
notifyListener();
|
||||
}
|
||||
|
||||
private void notifyListener() {
|
||||
if (this.listener != null)
|
||||
this.listener.update(this.bytesRead, this.contentLength, this.items);
|
||||
}
|
||||
}
|
||||
|
||||
protected static final byte[] HEADER_SEPARATOR = new byte[] { 13, 10, 13, 10 };
|
||||
|
||||
protected static final byte[] FIELD_SEPARATOR = new byte[] { 13, 10 };
|
||||
|
||||
protected static final byte[] STREAM_TERMINATOR = new byte[] { 45, 45 };
|
||||
|
||||
protected static final byte[] BOUNDARY_PREFIX = new byte[] { 13, 10, 45, 45 };
|
||||
|
||||
private final InputStream input;
|
||||
|
||||
private int boundaryLength;
|
||||
|
||||
private int keepRegion;
|
||||
|
||||
private byte[] boundary;
|
||||
|
||||
private final int bufSize;
|
||||
|
||||
private final byte[] buffer;
|
||||
|
||||
private int head;
|
||||
|
||||
private int tail;
|
||||
|
||||
private String headerEncoding;
|
||||
|
||||
private final ProgressNotifier notifier;
|
||||
|
||||
@Deprecated
|
||||
public MultipartStream() {
|
||||
this(null, null, null);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public MultipartStream(InputStream input, byte[] boundary, int bufSize) {
|
||||
this(input, boundary, bufSize, null);
|
||||
}
|
||||
|
||||
public MultipartStream(InputStream input, byte[] boundary, int bufSize, ProgressNotifier pNotifier) {
|
||||
if (boundary == null)
|
||||
throw new IllegalArgumentException("boundary may not be null");
|
||||
this.input = input;
|
||||
this.bufSize = bufSize;
|
||||
this.buffer = new byte[bufSize];
|
||||
this.notifier = pNotifier;
|
||||
this.boundaryLength = boundary.length + BOUNDARY_PREFIX.length;
|
||||
if (bufSize < this.boundaryLength + 1)
|
||||
throw new IllegalArgumentException("The buffer size specified for the MultipartStream is too small");
|
||||
this.boundary = new byte[this.boundaryLength];
|
||||
this.keepRegion = this.boundary.length;
|
||||
System.arraycopy(BOUNDARY_PREFIX, 0, this.boundary, 0, BOUNDARY_PREFIX.length);
|
||||
System.arraycopy(boundary, 0, this.boundary, BOUNDARY_PREFIX.length, boundary.length);
|
||||
this.head = 0;
|
||||
this.tail = 0;
|
||||
}
|
||||
|
||||
MultipartStream(InputStream input, byte[] boundary, ProgressNotifier pNotifier) {
|
||||
this(input, boundary, 4096, pNotifier);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public MultipartStream(InputStream input, byte[] boundary) {
|
||||
this(input, boundary, 4096, null);
|
||||
}
|
||||
|
||||
public String getHeaderEncoding() {
|
||||
return this.headerEncoding;
|
||||
}
|
||||
|
||||
public void setHeaderEncoding(String encoding) {
|
||||
this.headerEncoding = encoding;
|
||||
}
|
||||
|
||||
public byte readByte() throws IOException {
|
||||
if (this.head == this.tail) {
|
||||
this.head = 0;
|
||||
this.tail = this.input.read(this.buffer, this.head, this.bufSize);
|
||||
if (this.tail == -1)
|
||||
throw new IOException("No more data is available");
|
||||
if (this.notifier != null)
|
||||
this.notifier.noteBytesRead(this.tail);
|
||||
}
|
||||
return this.buffer[this.head++];
|
||||
}
|
||||
|
||||
public boolean readBoundary() throws FileUploadBase.FileUploadIOException, MalformedStreamException {
|
||||
byte[] marker = new byte[2];
|
||||
boolean nextChunk = false;
|
||||
this.head += this.boundaryLength;
|
||||
try {
|
||||
marker[0] = readByte();
|
||||
if (marker[0] == 10)
|
||||
return true;
|
||||
marker[1] = readByte();
|
||||
if (arrayequals(marker, STREAM_TERMINATOR, 2)) {
|
||||
nextChunk = false;
|
||||
} else if (arrayequals(marker, FIELD_SEPARATOR, 2)) {
|
||||
nextChunk = true;
|
||||
} else {
|
||||
throw new MalformedStreamException("Unexpected characters follow a boundary");
|
||||
}
|
||||
} catch (FileUploadBase.FileUploadIOException e) {
|
||||
throw e;
|
||||
} catch (IOException e) {
|
||||
throw new MalformedStreamException("Stream ended unexpectedly");
|
||||
}
|
||||
return nextChunk;
|
||||
}
|
||||
|
||||
public void setBoundary(byte[] boundary) throws IllegalBoundaryException {
|
||||
if (boundary.length != this.boundaryLength - BOUNDARY_PREFIX.length)
|
||||
throw new IllegalBoundaryException("The length of a boundary token can not be changed");
|
||||
System.arraycopy(boundary, 0, this.boundary, BOUNDARY_PREFIX.length, boundary.length);
|
||||
}
|
||||
|
||||
public String readHeaders() throws FileUploadBase.FileUploadIOException, MalformedStreamException {
|
||||
int i = 0;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
int size = 0;
|
||||
while (i < HEADER_SEPARATOR.length) {
|
||||
byte b;
|
||||
try {
|
||||
b = readByte();
|
||||
} catch (FileUploadBase.FileUploadIOException e) {
|
||||
throw e;
|
||||
} catch (IOException e) {
|
||||
throw new MalformedStreamException("Stream ended unexpectedly");
|
||||
}
|
||||
if (++size > 10240)
|
||||
throw new MalformedStreamException(String.format("Header section has more than %s bytes (maybe it is not properly terminated)", 10240));
|
||||
if (b == HEADER_SEPARATOR[i]) {
|
||||
i++;
|
||||
} else {
|
||||
i = 0;
|
||||
}
|
||||
baos.write(b);
|
||||
}
|
||||
String headers = null;
|
||||
if (this.headerEncoding != null) {
|
||||
try {
|
||||
headers = baos.toString(this.headerEncoding);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
headers = baos.toString();
|
||||
}
|
||||
} else {
|
||||
headers = baos.toString();
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
public int readBodyData(OutputStream output) throws MalformedStreamException, IOException {
|
||||
InputStream istream = newInputStream();
|
||||
return (int)Streams.copy(istream, output, false);
|
||||
}
|
||||
|
||||
ItemInputStream newInputStream() {
|
||||
return new ItemInputStream();
|
||||
}
|
||||
|
||||
public int discardBodyData() throws MalformedStreamException, IOException {
|
||||
return readBodyData(null);
|
||||
}
|
||||
|
||||
public boolean skipPreamble() throws IOException {
|
||||
System.arraycopy(this.boundary, 2, this.boundary, 0, this.boundary.length - 2);
|
||||
this.boundaryLength = this.boundary.length - 2;
|
||||
try {
|
||||
discardBodyData();
|
||||
return readBoundary();
|
||||
} catch (MalformedStreamException e) {
|
||||
return false;
|
||||
} finally {
|
||||
System.arraycopy(this.boundary, 0, this.boundary, 2, this.boundary.length - 2);
|
||||
this.boundaryLength = this.boundary.length;
|
||||
this.boundary[0] = 13;
|
||||
this.boundary[1] = 10;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean arrayequals(byte[] a, byte[] b, int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (a[i] != b[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected int findByte(byte value, int pos) {
|
||||
for (int i = pos; i < this.tail; i++) {
|
||||
if (this.buffer[i] == value)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
protected int findSeparator() {
|
||||
int match = 0;
|
||||
int maxpos = this.tail - this.boundaryLength;
|
||||
int first;
|
||||
for (first = this.head; first <= maxpos && match != this.boundaryLength; first++) {
|
||||
first = findByte(this.boundary[0], first);
|
||||
if (first == -1 || first > maxpos)
|
||||
return -1;
|
||||
for (int i = 1; i < this.boundaryLength &&
|
||||
this.buffer[first + i] == this.boundary[i]; i++);
|
||||
}
|
||||
if (match == this.boundaryLength)
|
||||
return first - 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static class MalformedStreamException extends IOException {
|
||||
private static final long serialVersionUID = 6466926458059796677L;
|
||||
|
||||
public MalformedStreamException() {}
|
||||
|
||||
public MalformedStreamException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
public static class IllegalBoundaryException extends IOException {
|
||||
private static final long serialVersionUID = -161533165102632918L;
|
||||
|
||||
public IllegalBoundaryException() {}
|
||||
|
||||
public IllegalBoundaryException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
public class ItemInputStream extends InputStream implements Closeable {
|
||||
private long total;
|
||||
|
||||
private int pad;
|
||||
|
||||
private int pos;
|
||||
|
||||
private boolean closed;
|
||||
|
||||
private static final int BYTE_POSITIVE_OFFSET = 256;
|
||||
|
||||
ItemInputStream() {
|
||||
findSeparator();
|
||||
}
|
||||
|
||||
private void findSeparator() {
|
||||
this.pos = MultipartStream.this.findSeparator();
|
||||
if (this.pos == -1)
|
||||
if (MultipartStream.this.tail - MultipartStream.this.head > MultipartStream.this.keepRegion) {
|
||||
this.pad = MultipartStream.this.keepRegion;
|
||||
} else {
|
||||
this.pad = MultipartStream.this.tail - MultipartStream.this.head;
|
||||
}
|
||||
}
|
||||
|
||||
public long getBytesRead() {
|
||||
return this.total;
|
||||
}
|
||||
|
||||
public int available() throws IOException {
|
||||
if (this.pos == -1)
|
||||
return MultipartStream.this.tail - MultipartStream.this.head - this.pad;
|
||||
return this.pos - MultipartStream.this.head;
|
||||
}
|
||||
|
||||
public int read() throws IOException {
|
||||
if (this.closed)
|
||||
throw new FileItemStream.ItemSkippedException();
|
||||
if (available() == 0 && makeAvailable() == 0)
|
||||
return -1;
|
||||
this.total++;
|
||||
int b = MultipartStream.this.buffer[MultipartStream.this.head++];
|
||||
if (b >= 0)
|
||||
return b;
|
||||
return b + 256;
|
||||
}
|
||||
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
if (this.closed)
|
||||
throw new FileItemStream.ItemSkippedException();
|
||||
if (len == 0)
|
||||
return 0;
|
||||
int res = available();
|
||||
if (res == 0) {
|
||||
res = makeAvailable();
|
||||
if (res == 0)
|
||||
return -1;
|
||||
}
|
||||
res = Math.min(res, len);
|
||||
System.arraycopy(MultipartStream.this.buffer, MultipartStream.this.head, b, off, res);
|
||||
MultipartStream.this.head += res;
|
||||
this.total += (long)res;
|
||||
return res;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
close(false);
|
||||
}
|
||||
|
||||
public void close(boolean pCloseUnderlying) throws IOException {
|
||||
if (this.closed)
|
||||
return;
|
||||
if (pCloseUnderlying) {
|
||||
this.closed = true;
|
||||
MultipartStream.this.input.close();
|
||||
} else {
|
||||
while (true) {
|
||||
int av = available();
|
||||
if (av == 0) {
|
||||
av = makeAvailable();
|
||||
if (av == 0)
|
||||
break;
|
||||
}
|
||||
skip((long)av);
|
||||
}
|
||||
}
|
||||
this.closed = true;
|
||||
}
|
||||
|
||||
public long skip(long bytes) throws IOException {
|
||||
if (this.closed)
|
||||
throw new FileItemStream.ItemSkippedException();
|
||||
int av = available();
|
||||
if (av == 0) {
|
||||
av = makeAvailable();
|
||||
if (av == 0)
|
||||
return 0L;
|
||||
}
|
||||
long res = Math.min((long)av, bytes);
|
||||
MultipartStream.access$114(MultipartStream.this, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
private int makeAvailable() throws IOException {
|
||||
int av;
|
||||
if (this.pos != -1)
|
||||
return 0;
|
||||
this.total += (long)(MultipartStream.this.tail - MultipartStream.this.head - this.pad);
|
||||
System.arraycopy(MultipartStream.this.buffer, MultipartStream.this.tail - this.pad, MultipartStream.this.buffer, 0, this.pad);
|
||||
MultipartStream.this.head = 0;
|
||||
MultipartStream.this.tail = this.pad;
|
||||
do {
|
||||
int bytesRead = MultipartStream.this.input.read(MultipartStream.this.buffer, MultipartStream.this.tail, MultipartStream.this.bufSize - MultipartStream.this.tail);
|
||||
if (bytesRead == -1) {
|
||||
String msg = "Stream ended unexpectedly";
|
||||
throw new MultipartStream.MalformedStreamException("Stream ended unexpectedly");
|
||||
}
|
||||
if (MultipartStream.this.notifier != null)
|
||||
MultipartStream.this.notifier.noteBytesRead(bytesRead);
|
||||
MultipartStream.this.tail += bytesRead;
|
||||
findSeparator();
|
||||
av = available();
|
||||
} while (av <= 0 && this.pos == -1);
|
||||
return av;
|
||||
}
|
||||
|
||||
public boolean isClosed() {
|
||||
return this.closed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
package org.apache.commons.fileupload;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import org.apache.commons.fileupload.util.mime.MimeUtility;
|
||||
|
||||
public class ParameterParser {
|
||||
private char[] chars = null;
|
||||
|
||||
private int pos = 0;
|
||||
|
||||
private int len = 0;
|
||||
|
||||
private int i1 = 0;
|
||||
|
||||
private int i2 = 0;
|
||||
|
||||
private boolean lowerCaseNames = false;
|
||||
|
||||
private boolean hasChar() {
|
||||
return (this.pos < this.len);
|
||||
}
|
||||
|
||||
private String getToken(boolean quoted) {
|
||||
while (this.i1 < this.i2 && Character.isWhitespace(this.chars[this.i1]))
|
||||
this.i1++;
|
||||
while (this.i2 > this.i1 && Character.isWhitespace(this.chars[this.i2 - 1]))
|
||||
this.i2--;
|
||||
if (quoted && this.i2 - this.i1 >= 2 && this.chars[this.i1] == '"' && this.chars[this.i2 - 1] == '"') {
|
||||
this.i1++;
|
||||
this.i2--;
|
||||
}
|
||||
String result = null;
|
||||
if (this.i2 > this.i1)
|
||||
result = new String(this.chars, this.i1, this.i2 - this.i1);
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isOneOf(char ch, char[] charray) {
|
||||
boolean result = false;
|
||||
for (char element : charray) {
|
||||
if (ch == element) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String parseToken(char[] terminators) {
|
||||
this.i1 = this.pos;
|
||||
this.i2 = this.pos;
|
||||
while (hasChar()) {
|
||||
char ch = this.chars[this.pos];
|
||||
if (isOneOf(ch, terminators))
|
||||
break;
|
||||
this.i2++;
|
||||
this.pos++;
|
||||
}
|
||||
return getToken(false);
|
||||
}
|
||||
|
||||
private String parseQuotedToken(char[] terminators) {
|
||||
this.i1 = this.pos;
|
||||
this.i2 = this.pos;
|
||||
boolean quoted = false;
|
||||
boolean charEscaped = false;
|
||||
while (hasChar()) {
|
||||
char ch = this.chars[this.pos];
|
||||
if (!quoted && isOneOf(ch, terminators))
|
||||
break;
|
||||
if (!charEscaped && ch == '"')
|
||||
quoted = !quoted;
|
||||
charEscaped = (!charEscaped && ch == '\\');
|
||||
this.i2++;
|
||||
this.pos++;
|
||||
}
|
||||
return getToken(true);
|
||||
}
|
||||
|
||||
public boolean isLowerCaseNames() {
|
||||
return this.lowerCaseNames;
|
||||
}
|
||||
|
||||
public void setLowerCaseNames(boolean b) {
|
||||
this.lowerCaseNames = b;
|
||||
}
|
||||
|
||||
public Map<String, String> parse(String str, char[] separators) {
|
||||
if (separators == null || separators.length == 0)
|
||||
return new HashMap<String, String>();
|
||||
char separator = separators[0];
|
||||
if (str != null) {
|
||||
int idx = str.length();
|
||||
for (char separator2 : separators) {
|
||||
int tmp = str.indexOf(separator2);
|
||||
if (tmp != -1 && tmp < idx) {
|
||||
idx = tmp;
|
||||
separator = separator2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return parse(str, separator);
|
||||
}
|
||||
|
||||
public Map<String, String> parse(String str, char separator) {
|
||||
if (str == null)
|
||||
return new HashMap<String, String>();
|
||||
return parse(str.toCharArray(), separator);
|
||||
}
|
||||
|
||||
public Map<String, String> parse(char[] charArray, char separator) {
|
||||
if (charArray == null)
|
||||
return new HashMap<String, String>();
|
||||
return parse(charArray, 0, charArray.length, separator);
|
||||
}
|
||||
|
||||
public Map<String, String> parse(char[] charArray, int offset, int length, char separator) {
|
||||
if (charArray == null)
|
||||
return new HashMap<String, String>();
|
||||
HashMap<String, String> params = new HashMap<String, String>();
|
||||
this.chars = charArray;
|
||||
this.pos = offset;
|
||||
this.len = length;
|
||||
String paramName = null;
|
||||
String paramValue = null;
|
||||
while (hasChar()) {
|
||||
paramName = parseToken(new char[] { '=', separator });
|
||||
paramValue = null;
|
||||
if (hasChar() && charArray[this.pos] == '=') {
|
||||
this.pos++;
|
||||
paramValue = parseQuotedToken(new char[] { separator });
|
||||
if (paramValue != null)
|
||||
try {
|
||||
paramValue = MimeUtility.decodeText(paramValue);
|
||||
} catch (UnsupportedEncodingException e) {}
|
||||
}
|
||||
if (hasChar() && charArray[this.pos] == separator)
|
||||
this.pos++;
|
||||
if (paramName != null && paramName.length() > 0) {
|
||||
if (this.lowerCaseNames)
|
||||
paramName = paramName.toLowerCase(Locale.ENGLISH);
|
||||
params.put(paramName, paramValue);
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package org.apache.commons.fileupload;
|
||||
|
||||
public interface ProgressListener {
|
||||
void update(long paramLong1, long paramLong2, int paramInt);
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package org.apache.commons.fileupload;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public interface RequestContext {
|
||||
String getCharacterEncoding();
|
||||
|
||||
String getContentType();
|
||||
|
||||
@Deprecated
|
||||
int getContentLength();
|
||||
|
||||
InputStream getInputStream() throws IOException;
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package org.apache.commons.fileupload;
|
||||
|
||||
public interface UploadContext extends RequestContext {
|
||||
long contentLength();
|
||||
}
|
||||
|
|
@ -0,0 +1,289 @@
|
|||
package org.apache.commons.fileupload.disk;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import org.apache.commons.fileupload.FileItem;
|
||||
import org.apache.commons.fileupload.FileItemHeaders;
|
||||
import org.apache.commons.fileupload.FileUploadException;
|
||||
import org.apache.commons.fileupload.ParameterParser;
|
||||
import org.apache.commons.fileupload.util.Streams;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.io.output.DeferredFileOutputStream;
|
||||
|
||||
public class DiskFileItem implements FileItem {
|
||||
private static final long serialVersionUID = 2237570099615271025L;
|
||||
|
||||
public static final String DEFAULT_CHARSET = "ISO-8859-1";
|
||||
|
||||
private static final String UID = UUID.randomUUID().toString().replace('-', '_');
|
||||
|
||||
private static final AtomicInteger COUNTER = new AtomicInteger(0);
|
||||
|
||||
private String fieldName;
|
||||
|
||||
private final String contentType;
|
||||
|
||||
private boolean isFormField;
|
||||
|
||||
private final String fileName;
|
||||
|
||||
private long size = -1L;
|
||||
|
||||
private final int sizeThreshold;
|
||||
|
||||
private final File repository;
|
||||
|
||||
private byte[] cachedContent;
|
||||
|
||||
private transient DeferredFileOutputStream dfos;
|
||||
|
||||
private transient File tempFile;
|
||||
|
||||
private File dfosFile;
|
||||
|
||||
private FileItemHeaders headers;
|
||||
|
||||
public DiskFileItem(String fieldName, String contentType, boolean isFormField, String fileName, int sizeThreshold, File repository) {
|
||||
this.fieldName = fieldName;
|
||||
this.contentType = contentType;
|
||||
this.isFormField = isFormField;
|
||||
this.fileName = fileName;
|
||||
this.sizeThreshold = sizeThreshold;
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() throws IOException {
|
||||
if (!isInMemory())
|
||||
return new FileInputStream(this.dfos.getFile());
|
||||
if (this.cachedContent == null)
|
||||
this.cachedContent = this.dfos.getData();
|
||||
return new ByteArrayInputStream(this.cachedContent);
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return this.contentType;
|
||||
}
|
||||
|
||||
public String getCharSet() {
|
||||
ParameterParser parser = new ParameterParser();
|
||||
parser.setLowerCaseNames(true);
|
||||
Map<String, String> params = parser.parse(getContentType(), ';');
|
||||
return params.get("charset");
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return Streams.checkFileName(this.fileName);
|
||||
}
|
||||
|
||||
public boolean isInMemory() {
|
||||
if (this.cachedContent != null)
|
||||
return true;
|
||||
return this.dfos.isInMemory();
|
||||
}
|
||||
|
||||
public long getSize() {
|
||||
if (this.size >= 0L)
|
||||
return this.size;
|
||||
if (this.cachedContent != null)
|
||||
return (long)this.cachedContent.length;
|
||||
if (this.dfos.isInMemory())
|
||||
return (long)(this.dfos.getData()).length;
|
||||
return this.dfos.getFile().length();
|
||||
}
|
||||
|
||||
public byte[] get() {
|
||||
if (isInMemory()) {
|
||||
if (this.cachedContent == null)
|
||||
this.cachedContent = this.dfos.getData();
|
||||
return this.cachedContent;
|
||||
}
|
||||
byte[] fileData = new byte[(int)getSize()];
|
||||
InputStream fis = null;
|
||||
try {
|
||||
fis = new BufferedInputStream(new FileInputStream(this.dfos.getFile()));
|
||||
fis.read(fileData);
|
||||
} catch (IOException e) {
|
||||
fileData = null;
|
||||
} finally {
|
||||
if (fis != null)
|
||||
try {
|
||||
fis.close();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
return fileData;
|
||||
}
|
||||
|
||||
public String getString(String charset) throws UnsupportedEncodingException {
|
||||
return new String(get(), charset);
|
||||
}
|
||||
|
||||
public String getString() {
|
||||
byte[] rawdata = get();
|
||||
String charset = getCharSet();
|
||||
if (charset == null)
|
||||
charset = "ISO-8859-1";
|
||||
try {
|
||||
return new String(rawdata, charset);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return new String(rawdata);
|
||||
}
|
||||
}
|
||||
|
||||
public void write(File file) throws Exception {
|
||||
if (isInMemory()) {
|
||||
FileOutputStream fout = null;
|
||||
try {
|
||||
fout = new FileOutputStream(file);
|
||||
fout.write(get());
|
||||
} finally {
|
||||
if (fout != null)
|
||||
fout.close();
|
||||
}
|
||||
} else {
|
||||
File outputFile = getStoreLocation();
|
||||
if (outputFile != null) {
|
||||
this.size = outputFile.length();
|
||||
if (!outputFile.renameTo(file)) {
|
||||
BufferedInputStream in = null;
|
||||
BufferedOutputStream out = null;
|
||||
try {
|
||||
in = new BufferedInputStream(new FileInputStream(outputFile));
|
||||
out = new BufferedOutputStream(new FileOutputStream(file));
|
||||
IOUtils.copy(in, out);
|
||||
} finally {
|
||||
if (in != null)
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException e) {}
|
||||
if (out != null)
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new FileUploadException("Cannot write uploaded file to disk!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
this.cachedContent = null;
|
||||
File outputFile = getStoreLocation();
|
||||
if (outputFile != null && outputFile.exists())
|
||||
outputFile.delete();
|
||||
}
|
||||
|
||||
public String getFieldName() {
|
||||
return this.fieldName;
|
||||
}
|
||||
|
||||
public void setFieldName(String fieldName) {
|
||||
this.fieldName = fieldName;
|
||||
}
|
||||
|
||||
public boolean isFormField() {
|
||||
return this.isFormField;
|
||||
}
|
||||
|
||||
public void setFormField(boolean state) {
|
||||
this.isFormField = state;
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() throws IOException {
|
||||
if (this.dfos == null) {
|
||||
File outputFile = getTempFile();
|
||||
this.dfos = new DeferredFileOutputStream(this.sizeThreshold, outputFile);
|
||||
}
|
||||
return this.dfos;
|
||||
}
|
||||
|
||||
public File getStoreLocation() {
|
||||
if (this.dfos == null)
|
||||
return null;
|
||||
return this.dfos.getFile();
|
||||
}
|
||||
|
||||
protected void finalize() {
|
||||
File outputFile = this.dfos.getFile();
|
||||
if (outputFile != null && outputFile.exists())
|
||||
outputFile.delete();
|
||||
}
|
||||
|
||||
protected File getTempFile() {
|
||||
if (this.tempFile == null) {
|
||||
File tempDir = this.repository;
|
||||
if (tempDir == null)
|
||||
tempDir = new File(System.getProperty("java.io.tmpdir"));
|
||||
String tempFileName = String.format("upload_%s_%s.tmp", UID, getUniqueId());
|
||||
this.tempFile = new File(tempDir, tempFileName);
|
||||
}
|
||||
return this.tempFile;
|
||||
}
|
||||
|
||||
private static String getUniqueId() {
|
||||
int limit = 100000000;
|
||||
int current = COUNTER.getAndIncrement();
|
||||
String id = Integer.toString(current);
|
||||
if (current < 100000000)
|
||||
id = ("00000000" + id).substring(id.length());
|
||||
return id;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return String.format("name=%s, StoreLocation=%s, size=%s bytes, isFormField=%s, FieldName=%s", getName(), getStoreLocation(), getSize(), isFormField(), getFieldName());
|
||||
}
|
||||
|
||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||
if (this.dfos.isInMemory()) {
|
||||
this.cachedContent = get();
|
||||
} else {
|
||||
this.cachedContent = null;
|
||||
this.dfosFile = this.dfos.getFile();
|
||||
}
|
||||
out.defaultWriteObject();
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
in.defaultReadObject();
|
||||
if (this.repository != null)
|
||||
if (this.repository.isDirectory()) {
|
||||
if (this.repository.getPath().contains("\000"))
|
||||
throw new IOException(String.format("The repository [%s] contains a null character", this.repository.getPath()));
|
||||
} else {
|
||||
throw new IOException(String.format("The repository [%s] is not a directory", this.repository.getAbsolutePath()));
|
||||
}
|
||||
OutputStream output = getOutputStream();
|
||||
if (this.cachedContent != null) {
|
||||
output.write(this.cachedContent);
|
||||
} else {
|
||||
FileInputStream input = new FileInputStream(this.dfosFile);
|
||||
IOUtils.copy(input, output);
|
||||
this.dfosFile.delete();
|
||||
this.dfosFile = null;
|
||||
}
|
||||
output.close();
|
||||
this.cachedContent = null;
|
||||
}
|
||||
|
||||
public FileItemHeaders getHeaders() {
|
||||
return this.headers;
|
||||
}
|
||||
|
||||
public void setHeaders(FileItemHeaders pHeaders) {
|
||||
this.headers = pHeaders;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
package org.apache.commons.fileupload.disk;
|
||||
|
||||
import java.io.File;
|
||||
import org.apache.commons.fileupload.FileItem;
|
||||
import org.apache.commons.fileupload.FileItemFactory;
|
||||
import org.apache.commons.io.FileCleaningTracker;
|
||||
|
||||
public class DiskFileItemFactory implements FileItemFactory {
|
||||
public static final int DEFAULT_SIZE_THRESHOLD = 10240;
|
||||
|
||||
private File repository;
|
||||
|
||||
private int sizeThreshold = 10240;
|
||||
|
||||
private FileCleaningTracker fileCleaningTracker;
|
||||
|
||||
public DiskFileItemFactory() {
|
||||
this(10240, null);
|
||||
}
|
||||
|
||||
public DiskFileItemFactory(int sizeThreshold, File repository) {
|
||||
this.sizeThreshold = sizeThreshold;
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
public File getRepository() {
|
||||
return this.repository;
|
||||
}
|
||||
|
||||
public void setRepository(File repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
public int getSizeThreshold() {
|
||||
return this.sizeThreshold;
|
||||
}
|
||||
|
||||
public void setSizeThreshold(int sizeThreshold) {
|
||||
this.sizeThreshold = sizeThreshold;
|
||||
}
|
||||
|
||||
public FileItem createItem(String fieldName, String contentType, boolean isFormField, String fileName) {
|
||||
DiskFileItem result = new DiskFileItem(fieldName, contentType, isFormField, fileName, this.sizeThreshold, this.repository);
|
||||
FileCleaningTracker tracker = getFileCleaningTracker();
|
||||
if (tracker != null)
|
||||
tracker.track(result.getTempFile(), result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public FileCleaningTracker getFileCleaningTracker() {
|
||||
return this.fileCleaningTracker;
|
||||
}
|
||||
|
||||
public void setFileCleaningTracker(FileCleaningTracker pTracker) {
|
||||
this.fileCleaningTracker = pTracker;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
package org.apache.commons.fileupload.portlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.portlet.ActionRequest;
|
||||
import org.apache.commons.fileupload.FileItem;
|
||||
import org.apache.commons.fileupload.FileItemFactory;
|
||||
import org.apache.commons.fileupload.FileItemIterator;
|
||||
import org.apache.commons.fileupload.FileUpload;
|
||||
import org.apache.commons.fileupload.FileUploadBase;
|
||||
import org.apache.commons.fileupload.FileUploadException;
|
||||
|
||||
public class PortletFileUpload extends FileUpload {
|
||||
public static final boolean isMultipartContent(ActionRequest request) {
|
||||
return FileUploadBase.isMultipartContent(new PortletRequestContext(request));
|
||||
}
|
||||
|
||||
public PortletFileUpload() {}
|
||||
|
||||
public PortletFileUpload(FileItemFactory fileItemFactory) {
|
||||
super(fileItemFactory);
|
||||
}
|
||||
|
||||
public List<FileItem> parseRequest(ActionRequest request) throws FileUploadException {
|
||||
return parseRequest(new PortletRequestContext(request));
|
||||
}
|
||||
|
||||
public Map<String, List<FileItem>> parseParameterMap(ActionRequest request) throws FileUploadException {
|
||||
return parseParameterMap(new PortletRequestContext(request));
|
||||
}
|
||||
|
||||
public FileItemIterator getItemIterator(ActionRequest request) throws FileUploadException, IOException {
|
||||
return getItemIterator(new PortletRequestContext(request));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package org.apache.commons.fileupload.portlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import javax.portlet.ActionRequest;
|
||||
import org.apache.commons.fileupload.UploadContext;
|
||||
|
||||
public class PortletRequestContext implements UploadContext {
|
||||
private final ActionRequest request;
|
||||
|
||||
public PortletRequestContext(ActionRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
public String getCharacterEncoding() {
|
||||
return this.request.getCharacterEncoding();
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return this.request.getContentType();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public int getContentLength() {
|
||||
return this.request.getContentLength();
|
||||
}
|
||||
|
||||
public long contentLength() {
|
||||
long l;
|
||||
try {
|
||||
l = Long.parseLong(this.request.getProperty("Content-length"));
|
||||
} catch (NumberFormatException e) {
|
||||
l = (long)this.request.getContentLength();
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return this.request.getPortletInputStream();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return String.format("ContentLength=%s, ContentType=%s", contentLength(), getContentType());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package org.apache.commons.fileupload.servlet;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
import org.apache.commons.io.FileCleaningTracker;
|
||||
|
||||
public class FileCleanerCleanup implements ServletContextListener {
|
||||
public static final String FILE_CLEANING_TRACKER_ATTRIBUTE = FileCleanerCleanup.class.getName() + ".FileCleaningTracker";
|
||||
|
||||
public static FileCleaningTracker getFileCleaningTracker(ServletContext pServletContext) {
|
||||
return (FileCleaningTracker)pServletContext.getAttribute(FILE_CLEANING_TRACKER_ATTRIBUTE);
|
||||
}
|
||||
|
||||
public static void setFileCleaningTracker(ServletContext pServletContext, FileCleaningTracker pTracker) {
|
||||
pServletContext.setAttribute(FILE_CLEANING_TRACKER_ATTRIBUTE, pTracker);
|
||||
}
|
||||
|
||||
public void contextInitialized(ServletContextEvent sce) {
|
||||
setFileCleaningTracker(sce.getServletContext(), new FileCleaningTracker());
|
||||
}
|
||||
|
||||
public void contextDestroyed(ServletContextEvent sce) {
|
||||
getFileCleaningTracker(sce.getServletContext()).exitWhenFinished();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package org.apache.commons.fileupload.servlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.apache.commons.fileupload.FileItem;
|
||||
import org.apache.commons.fileupload.FileItemFactory;
|
||||
import org.apache.commons.fileupload.FileItemIterator;
|
||||
import org.apache.commons.fileupload.FileUpload;
|
||||
import org.apache.commons.fileupload.FileUploadBase;
|
||||
import org.apache.commons.fileupload.FileUploadException;
|
||||
|
||||
public class ServletFileUpload extends FileUpload {
|
||||
private static final String POST_METHOD = "POST";
|
||||
|
||||
public static final boolean isMultipartContent(HttpServletRequest request) {
|
||||
if (!"POST".equalsIgnoreCase(request.getMethod()))
|
||||
return false;
|
||||
return FileUploadBase.isMultipartContent(new ServletRequestContext(request));
|
||||
}
|
||||
|
||||
public ServletFileUpload() {}
|
||||
|
||||
public ServletFileUpload(FileItemFactory fileItemFactory) {
|
||||
super(fileItemFactory);
|
||||
}
|
||||
|
||||
public List<FileItem> parseRequest(HttpServletRequest request) throws FileUploadException {
|
||||
return parseRequest(new ServletRequestContext(request));
|
||||
}
|
||||
|
||||
public Map<String, List<FileItem>> parseParameterMap(HttpServletRequest request) throws FileUploadException {
|
||||
return parseParameterMap(new ServletRequestContext(request));
|
||||
}
|
||||
|
||||
public FileItemIterator getItemIterator(HttpServletRequest request) throws FileUploadException, IOException {
|
||||
return getItemIterator(new ServletRequestContext(request));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package org.apache.commons.fileupload.servlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.apache.commons.fileupload.UploadContext;
|
||||
|
||||
public class ServletRequestContext implements UploadContext {
|
||||
private final HttpServletRequest request;
|
||||
|
||||
public ServletRequestContext(HttpServletRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
public String getCharacterEncoding() {
|
||||
return this.request.getCharacterEncoding();
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return this.request.getContentType();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public int getContentLength() {
|
||||
return this.request.getContentLength();
|
||||
}
|
||||
|
||||
public long contentLength() {
|
||||
long l;
|
||||
try {
|
||||
l = Long.parseLong(this.request.getHeader("Content-length"));
|
||||
} catch (NumberFormatException e) {
|
||||
l = (long)this.request.getContentLength();
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return (InputStream)this.request.getInputStream();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return String.format("ContentLength=%s, ContentType=%s", contentLength(), getContentType());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package org.apache.commons.fileupload.util;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface Closeable {
|
||||
void close() throws IOException;
|
||||
|
||||
boolean isClosed() throws IOException;
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
package org.apache.commons.fileupload.util;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import org.apache.commons.fileupload.FileItemHeaders;
|
||||
|
||||
public class FileItemHeadersImpl implements FileItemHeaders, Serializable {
|
||||
private static final long serialVersionUID = -4455695752627032559L;
|
||||
|
||||
private final Map<String, List<String>> headerNameToValueListMap = new LinkedHashMap<String, List<String>>();
|
||||
|
||||
public String getHeader(String name) {
|
||||
String nameLower = name.toLowerCase(Locale.ENGLISH);
|
||||
List<String> headerValueList = this.headerNameToValueListMap.get(nameLower);
|
||||
if (null == headerValueList)
|
||||
return null;
|
||||
return headerValueList.get(0);
|
||||
}
|
||||
|
||||
public Iterator<String> getHeaderNames() {
|
||||
return this.headerNameToValueListMap.keySet().iterator();
|
||||
}
|
||||
|
||||
public Iterator<String> getHeaders(String name) {
|
||||
String nameLower = name.toLowerCase(Locale.ENGLISH);
|
||||
List<String> headerValueList = this.headerNameToValueListMap.get(nameLower);
|
||||
if (null == headerValueList)
|
||||
headerValueList = Collections.<String>emptyList();
|
||||
return headerValueList.iterator();
|
||||
}
|
||||
|
||||
public synchronized void addHeader(String name, String value) {
|
||||
String nameLower = name.toLowerCase(Locale.ENGLISH);
|
||||
List<String> headerValueList = this.headerNameToValueListMap.get(nameLower);
|
||||
if (null == headerValueList) {
|
||||
headerValueList = new ArrayList<String>();
|
||||
this.headerNameToValueListMap.put(nameLower, headerValueList);
|
||||
}
|
||||
headerValueList.add(value);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package org.apache.commons.fileupload.util;
|
||||
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public abstract class LimitedInputStream extends FilterInputStream implements Closeable {
|
||||
private final long sizeMax;
|
||||
|
||||
private long count;
|
||||
|
||||
private boolean closed;
|
||||
|
||||
public LimitedInputStream(InputStream inputStream, long pSizeMax) {
|
||||
super(inputStream);
|
||||
this.sizeMax = pSizeMax;
|
||||
}
|
||||
|
||||
protected abstract void raiseError(long paramLong1, long paramLong2) throws IOException;
|
||||
|
||||
private void checkLimit() throws IOException {
|
||||
if (this.count > this.sizeMax)
|
||||
raiseError(this.sizeMax, this.count);
|
||||
}
|
||||
|
||||
public int read() throws IOException {
|
||||
int res = super.read();
|
||||
if (res != -1) {
|
||||
this.count++;
|
||||
checkLimit();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
int res = super.read(b, off, len);
|
||||
if (res > 0) {
|
||||
this.count += (long)res;
|
||||
checkLimit();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public boolean isClosed() throws IOException {
|
||||
return this.closed;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
this.closed = true;
|
||||
super.close();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
package org.apache.commons.fileupload.util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import org.apache.commons.fileupload.InvalidFileNameException;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
public final class Streams {
|
||||
private static final int DEFAULT_BUFFER_SIZE = 8192;
|
||||
|
||||
public static long copy(InputStream inputStream, OutputStream outputStream, boolean closeOutputStream) throws IOException {
|
||||
return copy(inputStream, outputStream, closeOutputStream, new byte[8192]);
|
||||
}
|
||||
|
||||
public static long copy(InputStream inputStream, OutputStream outputStream, boolean closeOutputStream, byte[] buffer) throws IOException {
|
||||
OutputStream out = outputStream;
|
||||
InputStream in = inputStream;
|
||||
try {
|
||||
long total = 0L;
|
||||
while (true) {
|
||||
int res = in.read(buffer);
|
||||
if (res == -1)
|
||||
break;
|
||||
if (res > 0) {
|
||||
total += (long)res;
|
||||
if (out != null)
|
||||
out.write(buffer, 0, res);
|
||||
}
|
||||
}
|
||||
if (out != null) {
|
||||
if (closeOutputStream) {
|
||||
out.close();
|
||||
} else {
|
||||
out.flush();
|
||||
}
|
||||
out = null;
|
||||
}
|
||||
in.close();
|
||||
in = null;
|
||||
return total;
|
||||
} finally {
|
||||
IOUtils.closeQuietly(in);
|
||||
if (closeOutputStream)
|
||||
IOUtils.closeQuietly(out);
|
||||
}
|
||||
}
|
||||
|
||||
public static String asString(InputStream inputStream) throws IOException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
copy(inputStream, baos, true);
|
||||
return baos.toString();
|
||||
}
|
||||
|
||||
public static String asString(InputStream inputStream, String encoding) throws IOException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
copy(inputStream, baos, true);
|
||||
return baos.toString(encoding);
|
||||
}
|
||||
|
||||
public static String checkFileName(String fileName) {
|
||||
if (fileName != null && fileName.indexOf('\000') != -1) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < fileName.length(); i++) {
|
||||
char c = fileName.charAt(i);
|
||||
switch (c) {
|
||||
case '\000':
|
||||
sb.append("\\0");
|
||||
break;
|
||||
default:
|
||||
sb.append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
throw new InvalidFileNameException(fileName, "Invalid file name: " + sb);
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
package org.apache.commons.fileupload.util.mime;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
final class Base64Decoder {
|
||||
private static final int INVALID_BYTE = -1;
|
||||
|
||||
private static final int PAD_BYTE = -2;
|
||||
|
||||
private static final int MASK_BYTE_UNSIGNED = 255;
|
||||
|
||||
private static final int INPUT_BYTES_PER_CHUNK = 4;
|
||||
|
||||
private static final byte[] ENCODING_TABLE = new byte[] {
|
||||
65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
|
||||
75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
|
||||
85, 86, 87, 88, 89, 90, 97, 98, 99, 100,
|
||||
101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
|
||||
111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
|
||||
121, 122, 48, 49, 50, 51, 52, 53, 54, 55,
|
||||
56, 57, 43, 47 };
|
||||
|
||||
private static final byte PADDING = 61;
|
||||
|
||||
private static final byte[] DECODING_TABLE = new byte[256];
|
||||
|
||||
static {
|
||||
for (int j = 0; j < DECODING_TABLE.length; j++)
|
||||
DECODING_TABLE[j] = -1;
|
||||
for (int i = 0; i < ENCODING_TABLE.length; i++)
|
||||
DECODING_TABLE[ENCODING_TABLE[i]] = (byte)i;
|
||||
DECODING_TABLE[61] = -2;
|
||||
}
|
||||
|
||||
public static int decode(byte[] data, OutputStream out) throws IOException {
|
||||
int outLen = 0;
|
||||
byte[] cache = new byte[4];
|
||||
int cachedBytes = 0;
|
||||
for (byte b : data) {
|
||||
byte d = DECODING_TABLE[0xFF & b];
|
||||
if (d != -1) {
|
||||
cache[cachedBytes++] = d;
|
||||
if (cachedBytes == 4) {
|
||||
byte b1 = cache[0];
|
||||
byte b2 = cache[1];
|
||||
byte b3 = cache[2];
|
||||
byte b4 = cache[3];
|
||||
if (b1 == -2 || b2 == -2)
|
||||
throw new IOException("Invalid Base64 input: incorrect padding, first two bytes cannot be padding");
|
||||
out.write(b1 << 2 | b2 >> 4);
|
||||
outLen++;
|
||||
if (b3 != -2) {
|
||||
out.write(b2 << 4 | b3 >> 2);
|
||||
outLen++;
|
||||
if (b4 != -2) {
|
||||
out.write(b3 << 6 | b4);
|
||||
outLen++;
|
||||
}
|
||||
} else if (b4 != -2) {
|
||||
throw new IOException("Invalid Base64 input: incorrect padding, 4th byte must be padding if 3rd byte is");
|
||||
}
|
||||
cachedBytes = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cachedBytes != 0)
|
||||
throw new IOException("Invalid Base64 input: truncated");
|
||||
return outLen;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
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;
|
||||
|
||||
public final class MimeUtility {
|
||||
private static final String US_ASCII_CHARSET = "US-ASCII";
|
||||
|
||||
private static final String BASE64_ENCODING_MARKER = "B";
|
||||
|
||||
private static final String QUOTEDPRINTABLE_ENCODING_MARKER = "Q";
|
||||
|
||||
private static final String ENCODED_TOKEN_MARKER = "=?";
|
||||
|
||||
private static final String ENCODED_TOKEN_FINISHER = "?=";
|
||||
|
||||
private static final String LINEAR_WHITESPACE = " \t\r\n";
|
||||
|
||||
private static final Map<String, String> MIME2JAVA = new HashMap<String, String>();
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
public static String decodeText(String text) throws UnsupportedEncodingException {
|
||||
if (text.indexOf("=?") < 0)
|
||||
return text;
|
||||
int offset = 0;
|
||||
int endOffset = text.length();
|
||||
int startWhiteSpace = -1;
|
||||
int endWhiteSpace = -1;
|
||||
StringBuilder decodedText = new StringBuilder(text.length());
|
||||
boolean previousTokenEncoded = false;
|
||||
while (offset < endOffset) {
|
||||
char ch = text.charAt(offset);
|
||||
if (" \t\r\n".indexOf(ch) != -1) {
|
||||
startWhiteSpace = offset;
|
||||
while (offset < endOffset) {
|
||||
ch = text.charAt(offset);
|
||||
if (" \t\r\n".indexOf(ch) != -1) {
|
||||
offset++;
|
||||
continue;
|
||||
}
|
||||
endWhiteSpace = offset;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
int wordStart = offset;
|
||||
while (offset < endOffset) {
|
||||
ch = text.charAt(offset);
|
||||
if (" \t\r\n".indexOf(ch) == -1) {
|
||||
offset++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
String word = text.substring(wordStart, offset);
|
||||
if (word.startsWith("=?"))
|
||||
try {
|
||||
String decodedWord = decodeWord(word);
|
||||
if (!previousTokenEncoded && startWhiteSpace != -1) {
|
||||
decodedText.append(text.substring(startWhiteSpace, endWhiteSpace));
|
||||
startWhiteSpace = -1;
|
||||
}
|
||||
previousTokenEncoded = true;
|
||||
decodedText.append(decodedWord);
|
||||
continue;
|
||||
} catch (ParseException e) {}
|
||||
if (startWhiteSpace != -1) {
|
||||
decodedText.append(text.substring(startWhiteSpace, endWhiteSpace));
|
||||
startWhiteSpace = -1;
|
||||
}
|
||||
previousTokenEncoded = false;
|
||||
decodedText.append(word);
|
||||
}
|
||||
return decodedText.toString();
|
||||
}
|
||||
|
||||
private static String decodeWord(String word) throws ParseException, UnsupportedEncodingException {
|
||||
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);
|
||||
String charset = word.substring(2, charsetPos).toLowerCase();
|
||||
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);
|
||||
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);
|
||||
if (encodedText.length() == 0)
|
||||
return "";
|
||||
try {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(encodedText.length());
|
||||
byte[] encodedData = encodedText.getBytes("US-ASCII");
|
||||
if (encoding.equals("B")) {
|
||||
Base64Decoder.decode(encodedData, out);
|
||||
} else if (encoding.equals("Q")) {
|
||||
QuotedPrintableDecoder.decode(encodedData, out);
|
||||
} else {
|
||||
throw new UnsupportedEncodingException("Unknown RFC 2047 encoding: " + encoding);
|
||||
}
|
||||
byte[] decodedData = out.toByteArray();
|
||||
return new String(decodedData, javaCharset(charset));
|
||||
} catch (IOException e) {
|
||||
throw new UnsupportedEncodingException("Invalid RFC 2047 encoding");
|
||||
}
|
||||
}
|
||||
|
||||
private static String javaCharset(String charset) {
|
||||
if (charset == null)
|
||||
return null;
|
||||
String mappedCharset = MIME2JAVA.get(charset.toLowerCase(Locale.ENGLISH));
|
||||
if (mappedCharset == null)
|
||||
return charset;
|
||||
return mappedCharset;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package org.apache.commons.fileupload.util.mime;
|
||||
|
||||
final class ParseException extends Exception {
|
||||
private static final long serialVersionUID = 5355281266579392077L;
|
||||
|
||||
public ParseException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package org.apache.commons.fileupload.util.mime;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
final class QuotedPrintableDecoder {
|
||||
private static final int UPPER_NIBBLE_SHIFT = 4;
|
||||
|
||||
public static int decode(byte[] data, OutputStream out) throws IOException {
|
||||
int off = 0;
|
||||
int length = data.length;
|
||||
int endOffset = off + length;
|
||||
int bytesWritten = 0;
|
||||
while (off < endOffset) {
|
||||
byte ch = data[off++];
|
||||
if (ch == 95) {
|
||||
out.write(32);
|
||||
continue;
|
||||
}
|
||||
if (ch == 61) {
|
||||
if (off + 1 >= endOffset)
|
||||
throw new IOException("Invalid quoted printable encoding; truncated escape sequence");
|
||||
byte b1 = data[off++];
|
||||
byte b2 = data[off++];
|
||||
if (b1 == 13) {
|
||||
if (b2 != 10)
|
||||
throw new IOException("Invalid quoted printable encoding; CR must be followed by LF");
|
||||
continue;
|
||||
}
|
||||
int c1 = hexToBinary(b1);
|
||||
int c2 = hexToBinary(b2);
|
||||
out.write(c1 << 4 | c2);
|
||||
bytesWritten++;
|
||||
continue;
|
||||
}
|
||||
out.write(ch);
|
||||
bytesWritten++;
|
||||
}
|
||||
return bytesWritten;
|
||||
}
|
||||
|
||||
private static int hexToBinary(byte b) throws IOException {
|
||||
int i = Character.digit((char)b, 16);
|
||||
if (i == -1)
|
||||
throw new IOException("Invalid quoted printable encoding: not a valid hex digit: " + b);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue