Merge pull request #60 from sgdc3/master
Maven stuff + Updated dependencies
This commit is contained in:
commit
17bfb57a97
129
.gitignore
vendored
129
.gitignore
vendored
@ -1,6 +1,125 @@
|
|||||||
/target/
|
# Created by https://www.gitignore.io
|
||||||
/bin/
|
|
||||||
/.settings/
|
### Java ###
|
||||||
.classpath
|
*.class
|
||||||
|
|
||||||
|
# Mobile Tools for Java (J2ME)
|
||||||
|
.mtj.tmp/
|
||||||
|
|
||||||
|
# Package Files #
|
||||||
|
#*.jar
|
||||||
|
*.war
|
||||||
|
*.ear
|
||||||
|
|
||||||
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
|
hs_err_pid*
|
||||||
|
|
||||||
|
|
||||||
|
### Intellij ###
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
|
||||||
|
|
||||||
|
*.iml
|
||||||
|
|
||||||
|
## Directory-based project format:
|
||||||
|
.idea/
|
||||||
|
# if you remove the above rule, at least ignore the following:
|
||||||
|
|
||||||
|
# User-specific stuff:
|
||||||
|
# .idea/workspace.xml
|
||||||
|
# .idea/tasks.xml
|
||||||
|
# .idea/dictionaries
|
||||||
|
|
||||||
|
# Sensitive or high-churn files:
|
||||||
|
# .idea/dataSources.ids
|
||||||
|
# .idea/dataSources.xml
|
||||||
|
# .idea/sqlDataSources.xml
|
||||||
|
# .idea/dynamic.xml
|
||||||
|
# .idea/uiDesigner.xml
|
||||||
|
|
||||||
|
# Gradle:
|
||||||
|
# .idea/gradle.xml
|
||||||
|
# .idea/libraries
|
||||||
|
|
||||||
|
# Mongo Explorer plugin:
|
||||||
|
# .idea/mongoSettings.xml
|
||||||
|
|
||||||
|
## File-based project format:
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
## Plugin-specific files:
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
|
||||||
|
|
||||||
|
### Eclipse ###
|
||||||
|
*.pydevproject
|
||||||
|
.metadata
|
||||||
|
.gradle
|
||||||
|
bin/
|
||||||
|
tmp/
|
||||||
|
*.tmp
|
||||||
|
*.bak
|
||||||
|
*.swp
|
||||||
|
*~.nib
|
||||||
|
local.properties
|
||||||
|
.settings/
|
||||||
|
.loadpath
|
||||||
|
|
||||||
|
# Eclipse Core
|
||||||
.project
|
.project
|
||||||
/target/
|
|
||||||
|
# External tool builders
|
||||||
|
.externalToolBuilders/
|
||||||
|
|
||||||
|
# Locally stored "Eclipse launch configurations"
|
||||||
|
*.launch
|
||||||
|
|
||||||
|
# CDT-specific
|
||||||
|
.cproject
|
||||||
|
|
||||||
|
# JDT-specific (Eclipse Java Development Tools)
|
||||||
|
.classpath
|
||||||
|
|
||||||
|
# PDT-specific
|
||||||
|
.buildpath
|
||||||
|
|
||||||
|
# sbteclipse plugin
|
||||||
|
.target
|
||||||
|
|
||||||
|
# TeXlipse plugin
|
||||||
|
.texlipse
|
||||||
|
|
||||||
|
|
||||||
|
### Maven ###
|
||||||
|
target/
|
||||||
|
pom.xml.tag
|
||||||
|
pom.xml.releaseBackup
|
||||||
|
pom.xml.versionsBackup
|
||||||
|
pom.xml.next
|
||||||
|
release.properties
|
||||||
|
dependency-reduced-pom.xml
|
||||||
|
buildNumber.properties
|
||||||
|
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
nbproject/private/
|
||||||
|
build/
|
||||||
|
nbbuild/
|
||||||
|
dist/
|
||||||
|
nbdist/
|
||||||
|
nbactions.xml
|
||||||
|
nb-configuration.xml
|
||||||
|
.nb-gradle/
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
language: java
|
language: java
|
||||||
jdk:
|
jdk:
|
||||||
- openjdk6
|
- oraclejdk7
|
||||||
script: "mvn clean install"
|
script: "mvn clean install"
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
lib/Spigot.jar
BIN
lib/Spigot.jar
Binary file not shown.
Binary file not shown.
BIN
lib/Vault.jar
BIN
lib/Vault.jar
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
libs/ChestShop.jar
Normal file
BIN
libs/ChestShop.jar
Normal file
Binary file not shown.
Binary file not shown.
402
pom.xml
402
pom.xml
@ -1,138 +1,288 @@
|
|||||||
<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/xsd/maven-4.0.0.xsd">
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<groupId>fr.xephi.authme.AuthMe</groupId>
|
<groupId>fr.xephi.authme.AuthMe</groupId>
|
||||||
<artifactId>AuthMe</artifactId>
|
<artifactId>AuthMe</artifactId>
|
||||||
<packaging>jar</packaging>
|
|
||||||
<name>AuthMe</name>
|
|
||||||
<properties>
|
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
|
||||||
</properties>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
|
||||||
<version>2.5</version>
|
|
||||||
<configuration>
|
|
||||||
<archive>
|
|
||||||
<manifestFile>${manifest.file}</manifestFile>
|
|
||||||
</archive>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
<version>5.0-SNAPSHOT</version>
|
<version>5.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<name>AuthMeReloaded</name>
|
||||||
|
<description>Authentication plugin for CraftBukkit/Spigot!</description>
|
||||||
|
<url>http://dev.bukkit.org/bukkit-plugins/authme-reloaded/</url>
|
||||||
|
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
|
||||||
|
<!-- Change Compiler Version (JDK) HERE! -->
|
||||||
|
<maven.compiler.source>1.7</maven.compiler.source>
|
||||||
|
<maven.compiler.target>1.7</maven.compiler.target>
|
||||||
|
|
||||||
|
<!-- Change MC Version HERE! -->
|
||||||
|
<bukkitVersion>1.8.7-R0.1-SNAPSHOT</bukkitVersion>
|
||||||
|
|
||||||
|
<mainClass>${project.groupId}.${project.artifactId}</mainClass>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<!-- Official Build Server
|
||||||
|
ALLERT: sometimes jenkins is offline, no panic! -->
|
||||||
|
<ciManagement>
|
||||||
|
<system>jenkins</system>
|
||||||
|
<url>http://ci.xephi.fr</url>
|
||||||
|
</ciManagement>
|
||||||
|
|
||||||
|
<issueManagement>
|
||||||
|
<system>GitHub</system>
|
||||||
|
<url>https://github.com/Xephi/AuthMeReloaded/issues</url>
|
||||||
|
</issueManagement>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>2.5</version>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<manifestFile>${manifest.file}</manifestFile>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
|
||||||
|
<!-- SpigotMC Repo (Bukkit and SpigotAPI) -->
|
||||||
|
<repository>
|
||||||
|
<id>spigot-repo</id>
|
||||||
|
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
|
||||||
|
</repository>
|
||||||
|
|
||||||
|
<!-- Vault Repo -->
|
||||||
|
<repository>
|
||||||
|
<id>vault-repo</id>
|
||||||
|
<url>http://nexus.theyeticave.net/content/repositories/pub_releases</url>
|
||||||
|
</repository>
|
||||||
|
|
||||||
|
<!-- Citizens 2.X Repo -->
|
||||||
|
<repository>
|
||||||
|
<id>everything</id>
|
||||||
|
<url>http://repo.citizensnpcs.co</url>
|
||||||
|
</repository>
|
||||||
|
|
||||||
|
<!-- Multiverse Repo -->
|
||||||
|
<repository>
|
||||||
|
<id>onarandombox</id>
|
||||||
|
<url>http://repo.onarandombox.com/content/groups/public</url>
|
||||||
|
</repository>
|
||||||
|
|
||||||
|
<!-- EssentialsX Repo -->
|
||||||
|
<repository>
|
||||||
|
<id>ess-repo</id>
|
||||||
|
<url>https://ci.drtshock.net/plugin/repository/everything/</url>
|
||||||
|
</repository>
|
||||||
|
|
||||||
|
<!-- CombatTagPlus Repo -->
|
||||||
|
<repository>
|
||||||
|
<id>minelink-thirdparty</id>
|
||||||
|
<url>http://repo.minelink.net/content/repositories/public</url>
|
||||||
|
</repository>
|
||||||
|
|
||||||
|
<!-- CombatTag Repo, Unofficial (needs replacement) -->
|
||||||
|
<repository>
|
||||||
|
<id>techcable-repo</id>
|
||||||
|
<url>http://repo.techcable.net/content/repositories/snapshots/</url>
|
||||||
|
</repository>
|
||||||
|
|
||||||
|
<!-- XAuth Repo -->
|
||||||
|
<repository>
|
||||||
|
<id>bukkit-plugins-releases</id>
|
||||||
|
<name>repo.luricos.de releases</name>
|
||||||
|
<url>http://repo.luricos.de/content/repositories/releases/</url>
|
||||||
|
</repository>
|
||||||
|
|
||||||
|
<!-- SpoutCraft Repo -->
|
||||||
|
<repository>
|
||||||
|
<id>sonatype-nexus-releases</id>
|
||||||
|
<url>https://oss.sonatype.org/content/repositories/releases</url>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>sonatype-nexus-snapshots</id>
|
||||||
|
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
<updatePolicy>always</updatePolicy>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
<!-- End of Spout Repo -->
|
||||||
|
|
||||||
|
<!-- Attribute Repo
|
||||||
|
<repository>
|
||||||
|
<id>comphenix-snapshots</id>
|
||||||
|
<name>Comphenix Maven Snapshots</name>
|
||||||
|
<url>http://repo.comphenix.net/content/repositories/snapshots/</url>
|
||||||
|
</repository> -->
|
||||||
|
|
||||||
|
</repositories>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>org.spigotmc</groupId>
|
<!-- Maven Dependencies -->
|
||||||
<artifactId>spigot</artifactId>
|
|
||||||
<version>1.8.3</version>
|
<!-- MySql Library -->
|
||||||
<scope>system</scope>
|
<dependency>
|
||||||
<systemPath>${project.basedir}/lib/Spigot.jar</systemPath>
|
<groupId>mysql</groupId>
|
||||||
</dependency>
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
<dependency>
|
<version>5.1.35</version>
|
||||||
<groupId>net.milkbowl.vault</groupId>
|
</dependency>
|
||||||
<artifactId>Vault</artifactId>
|
|
||||||
<version>1.5.3</version>
|
<!-- SQLite Library -->
|
||||||
<scope>system</scope>
|
<dependency>
|
||||||
<systemPath>${project.basedir}/lib/Vault.jar</systemPath>
|
<groupId>org.xerial</groupId>
|
||||||
</dependency>
|
<artifactId>sqlite-jdbc</artifactId>
|
||||||
<dependency>
|
<version>3.8.10.1</version>
|
||||||
<groupId>net.citizensnpcs</groupId>
|
</dependency>
|
||||||
<artifactId>citizensapi</artifactId>
|
|
||||||
<version>2.0.13-SNAPSHOT</version>
|
<!-- Database Library -->
|
||||||
<scope>system</scope>
|
|
||||||
<systemPath>${project.basedir}/lib/citizensapi-2.0.13-SNAPSHOT.jar</systemPath>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.citizensnpcs</groupId>
|
|
||||||
<artifactId>Citizens</artifactId>
|
|
||||||
<version>1.2.1</version>
|
|
||||||
<scope>system</scope>
|
|
||||||
<systemPath>${project.basedir}/lib/Citizens.jar</systemPath>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.getspout</groupId>
|
|
||||||
<artifactId>spoutapi</artifactId>
|
|
||||||
<version>1.6.4-SNAPSHOT</version>
|
|
||||||
<scope>system</scope>
|
|
||||||
<systemPath>${project.basedir}/lib/SpoutPlugin.jar</systemPath>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.trc202</groupId>
|
|
||||||
<artifactId>CombatTag</artifactId>
|
|
||||||
<version>5.4</version>
|
|
||||||
<scope>system</scope>
|
|
||||||
<systemPath>${project.basedir}/lib/CombatTag-5.4.jar</systemPath>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>mysql</groupId>
|
|
||||||
<artifactId>mysql-connector-java</artifactId>
|
|
||||||
<version>5.1.6</version>
|
|
||||||
<scope>system</scope>
|
|
||||||
<systemPath>${project.basedir}/lib/mysql-connector-java.jar</systemPath>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.xerial</groupId>
|
|
||||||
<artifactId>sqlite-jdbc</artifactId>
|
|
||||||
<version>3.7.2</version>
|
|
||||||
<scope>system</scope>
|
|
||||||
<systemPath>${project.basedir}/lib/sqlite-jdbc.jar</systemPath>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>me.muizers</groupId>
|
<groupId>com.h2database</groupId>
|
||||||
<artifactId>Notifications</artifactId>
|
<artifactId>h2</artifactId>
|
||||||
<version>1.6</version>
|
<version>1.4.187</version>
|
||||||
<scope>system</scope>
|
</dependency>
|
||||||
<systemPath>${project.basedir}/lib/Notifications.jar</systemPath>
|
|
||||||
</dependency>
|
<!-- Java Email API -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.Acrobot</groupId>
|
<groupId>com.sun.mail</groupId>
|
||||||
<artifactId>ChestShop</artifactId>
|
<artifactId>javax.mail</artifactId>
|
||||||
<version>3.7.9</version>
|
<version>1.5.3</version>
|
||||||
<scope>system</scope>
|
</dependency>
|
||||||
<systemPath>${project.basedir}/lib/ChestShop.jar</systemPath>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.h2</groupId>
|
<groupId>javax.mail</groupId>
|
||||||
<artifactId>h2</artifactId>
|
<artifactId>mail</artifactId>
|
||||||
<version>1.3.164</version>
|
<version>1.5.0-b01</version>
|
||||||
<scope>system</scope>
|
</dependency>
|
||||||
<systemPath>${project.basedir}/lib/h2-1.3.164.jar</systemPath>
|
|
||||||
</dependency>
|
<!-- Attribute, THIS DOESN?T WORK BECAUSE XEPHI USED A MODIFIED VERSION
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.cypherx</groupId>
|
<groupId>com.comphenix.attribute</groupId>
|
||||||
<artifactId>xauth</artifactId>
|
<artifactId>AttributeStorage</artifactId>
|
||||||
<version>2.0.26</version>
|
<version>0.0.2-SNAPSHOT</version>
|
||||||
<scope>system</scope>
|
</dependency> -->
|
||||||
<systemPath>${project.basedir}/lib/xAuth.jar</systemPath>
|
|
||||||
</dependency>
|
<!-- Maxmind GeoIp API -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>de.luricos.bukkit</groupId>
|
<groupId>com.maxmind.geoip</groupId>
|
||||||
<artifactId>xAuth</artifactId>
|
<artifactId>geoip-api</artifactId>
|
||||||
<version>2.4.4</version>
|
<version>1.2.14</version>
|
||||||
<scope>system</scope>
|
</dependency>
|
||||||
<systemPath>${project.basedir}/lib/xAuth-2.4.4.jar</systemPath>
|
|
||||||
</dependency>
|
<!-- Spigot-Api, http://www.spigotmc.org/
|
||||||
|
Based on the Bukkit project, http://bukkit.org/ -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.spigotmc</groupId>
|
||||||
|
<artifactId>spigot-api</artifactId>
|
||||||
|
<version>${bukkitVersion}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Vault, http://dev.bukkit.org/bukkit-plugins/vault/ -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.milkbowl.vault</groupId>
|
||||||
|
<artifactId>Vault</artifactId>
|
||||||
|
<version>1.5.4</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Citizens 2.X, NPC plugin, http://dev.bukkit.org/bukkit-plugins/citizens/ -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.citizensnpcs</groupId>
|
||||||
|
<artifactId>citizensapi</artifactId>
|
||||||
|
<version>2.0.16-SNAPSHOT</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Multi World plugin, http://www.spigotmc.org/resources/multiverse-core.390/ -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.onarandombox</groupId>
|
<groupId>com.onarandombox.multiversecore</groupId>
|
||||||
<artifactId>MultiverseCore</artifactId>
|
<artifactId>Multiverse-Core</artifactId>
|
||||||
<version>2.5-b654</version>
|
<version>2.5</version>
|
||||||
<scope>system</scope>
|
</dependency>
|
||||||
<systemPath>${project.basedir}/lib/Multiverse-Core-2.5.jar</systemPath>
|
|
||||||
</dependency>
|
<!-- EssentialsX, a fork of Spigot Essentials (1.8) with fixes and optimizations, https://github.com/drtshock/Essentials/ -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.earth2me.essentials</groupId>
|
<groupId>net.ess3</groupId>
|
||||||
<artifactId>Essentials</artifactId>
|
<artifactId>EssentialsX</artifactId>
|
||||||
<version>2.13.1</version>
|
<version>2.0.1-SNAPSHOT</version>
|
||||||
<scope>system</scope>
|
</dependency>
|
||||||
<systemPath>${project.basedir}/lib/Essentials.jar</systemPath>
|
|
||||||
</dependency>
|
<!-- Anti PvPLogging plugin, https://github.com/MinelinkNetwork/CombatTagPlus -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.minelink</groupId>
|
<groupId>net.minelink</groupId>
|
||||||
<artifactId>CombatTagPlus</artifactId>
|
<artifactId>CombatTagPlus</artifactId>
|
||||||
<version>1.1.2-SNAPSHOT</version>
|
<version>1.2.1-SNAPSHOT</version>
|
||||||
<scope>system</scope>
|
</dependency>
|
||||||
<systemPath>${project.basedir}/lib/CombatTagPlus.jar</systemPath>
|
|
||||||
</dependency>
|
<!-- Anti PvPLogging plugin, http://www.spigotmc.org/resources/combat-tag.3182/ -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.trc202</groupId>
|
||||||
|
<artifactId>combattag</artifactId>
|
||||||
|
<version>6.4.1-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- XAuth, another authentication plugin, required by the database converter -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>de.luricos.bukkit</groupId>
|
||||||
|
<artifactId>xAuth</artifactId>
|
||||||
|
<version>2.6</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Spout API, https://spoutcraft.org/downloads/ -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.spoutcraft</groupId>
|
||||||
|
<artifactId>spoutcraftplugin</artifactId>
|
||||||
|
<version>1.6.4-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Local Dependencies -->
|
||||||
|
|
||||||
|
<!-- It doesn't have a Maven Repo, http://dev.bukkit.org/bukkit-plugins/chestshop/ -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.Acrobot</groupId>
|
||||||
|
<artifactId>ChestShop</artifactId>
|
||||||
|
<version>3.8.10</version>
|
||||||
|
<scope>system</scope>
|
||||||
|
<systemPath>${project.basedir}/libs/ChestShop.jar</systemPath>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Citizens 1.X (No API) -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.citizensnpcs</groupId>
|
||||||
|
<artifactId>citizens</artifactId>
|
||||||
|
<version>1.2.4</version>
|
||||||
|
<scope>system</scope>
|
||||||
|
<systemPath>${project.basedir}/libs/Citizens.jar</systemPath>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Old version of xAuth by Cypherx -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.cypherx</groupId>
|
||||||
|
<artifactId>xauth</artifactId>
|
||||||
|
<version>2.0.26</version>
|
||||||
|
<scope>system</scope>
|
||||||
|
<systemPath>${project.basedir}/libs/xAuth.jar</systemPath>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- A SpoutApi Plugin, http://dev.bukkit.org/bukkit-plugins/notifications/ -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>me.muizers</groupId>
|
||||||
|
<artifactId>Notifications</artifactId>
|
||||||
|
<version>1.6</version>
|
||||||
|
<scope>system</scope>
|
||||||
|
<systemPath>${project.basedir}/libs/Notifications.jar</systemPath>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
BIN
snapshots/AuthMe-5.0-SNAPSHOT.jar
Normal file
BIN
snapshots/AuthMe-5.0-SNAPSHOT.jar
Normal file
Binary file not shown.
@ -1,61 +0,0 @@
|
|||||||
/**
|
|
||||||
* Country.java
|
|
||||||
*
|
|
||||||
* Copyright (C) 2003 MaxMind LLC. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.maxmind.geoip;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a country.
|
|
||||||
*
|
|
||||||
* @author Matt Tucker
|
|
||||||
*/
|
|
||||||
public class Country {
|
|
||||||
|
|
||||||
private String code;
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new Country.
|
|
||||||
*
|
|
||||||
* @param code the country code.
|
|
||||||
* @param name the country name.
|
|
||||||
*/
|
|
||||||
public Country(String code, String name) {
|
|
||||||
this.code = code;
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the ISO two-letter country code of this country.
|
|
||||||
*
|
|
||||||
* @return the country code.
|
|
||||||
*/
|
|
||||||
public String getCode() {
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the name of this country.
|
|
||||||
*
|
|
||||||
* @return the country name.
|
|
||||||
*/
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,117 +0,0 @@
|
|||||||
/**
|
|
||||||
* DatabaseInfo.java
|
|
||||||
*
|
|
||||||
* Copyright (C) 2003 MaxMind LLC. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.maxmind.geoip;
|
|
||||||
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encapsulates metadata about the GeoIP database. The database has a date, is a premium or
|
|
||||||
* standard version, and is one of the following types:
|
|
||||||
*
|
|
||||||
* <ul>
|
|
||||||
* <li>Country edition -- this is the most common version of the database. It includes
|
|
||||||
* the name of the country and it's ISO country code given an IP address.
|
|
||||||
* <li>Region edition -- includes the country information as well as
|
|
||||||
* what U.S. state or Canadian province the IP address is from if the IP address
|
|
||||||
* is from the U.S. or Canada.
|
|
||||||
* <li>City edition -- includes country, region, city, postal code, latitude, and
|
|
||||||
* longitude information.
|
|
||||||
* <li>Org edition -- includes netblock owner.
|
|
||||||
* <li>ISP edition -- ISP information.
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @see com.maxmind.geoip.LookupService#getDatabaseInfo()
|
|
||||||
* @author Matt Tucker
|
|
||||||
*/
|
|
||||||
public class DatabaseInfo {
|
|
||||||
|
|
||||||
public final static int COUNTRY_EDITION = 1;
|
|
||||||
public final static int REGION_EDITION_REV0 = 7;
|
|
||||||
public final static int REGION_EDITION_REV1 = 3;
|
|
||||||
public final static int CITY_EDITION_REV0 = 6;
|
|
||||||
public final static int CITY_EDITION_REV1 = 2;
|
|
||||||
public final static int ORG_EDITION = 5;
|
|
||||||
public final static int ISP_EDITION = 4;
|
|
||||||
public final static int PROXY_EDITION = 8;
|
|
||||||
public final static int ASNUM_EDITION = 9;
|
|
||||||
public final static int NETSPEED_EDITION = 10;
|
|
||||||
public final static int COUNTRY_EDITION_V6 = 12;
|
|
||||||
|
|
||||||
private static SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
|
|
||||||
|
|
||||||
private String info;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new DatabaseInfo object given the database info String.
|
|
||||||
* @param info
|
|
||||||
*/
|
|
||||||
public DatabaseInfo(String info) {
|
|
||||||
this.info = info;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getType() {
|
|
||||||
if (info == null || info.equals("")) {
|
|
||||||
return COUNTRY_EDITION;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Get the type code from the database info string and then
|
|
||||||
// subtract 105 from the value to preserve compatability with
|
|
||||||
// databases from April 2003 and earlier.
|
|
||||||
return Integer.parseInt(info.substring(4, 7)) - 105;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the database is the premium version.
|
|
||||||
*
|
|
||||||
* @return true if the premium version of the database.
|
|
||||||
*/
|
|
||||||
public boolean isPremium() {
|
|
||||||
return info.indexOf("FREE") < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the date of the database.
|
|
||||||
*
|
|
||||||
* @return the date of the database.
|
|
||||||
*/
|
|
||||||
public Date getDate() {
|
|
||||||
for (int i=0; i<info.length()-9; i++) {
|
|
||||||
if (Character.isWhitespace(info.charAt(i))) {
|
|
||||||
String dateString = info.substring(i+1, i+9);
|
|
||||||
try {
|
|
||||||
synchronized (formatter) {
|
|
||||||
return formatter.parse(dateString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (ParseException pe) { }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,504 +0,0 @@
|
|||||||
GNU LESSER GENERAL PUBLIC LICENSE
|
|
||||||
Version 2.1, February 1999
|
|
||||||
|
|
||||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
[This is the first released version of the Lesser GPL. It also counts
|
|
||||||
as the successor of the GNU Library Public License, version 2, hence
|
|
||||||
the version number 2.1.]
|
|
||||||
|
|
||||||
Preamble
|
|
||||||
|
|
||||||
The licenses for most software are designed to take away your
|
|
||||||
freedom to share and change it. By contrast, the GNU General Public
|
|
||||||
Licenses are intended to guarantee your freedom to share and change
|
|
||||||
free software--to make sure the software is free for all its users.
|
|
||||||
|
|
||||||
This license, the Lesser General Public License, applies to some
|
|
||||||
specially designated software packages--typically libraries--of the
|
|
||||||
Free Software Foundation and other authors who decide to use it. You
|
|
||||||
can use it too, but we suggest you first think carefully about whether
|
|
||||||
this license or the ordinary General Public License is the better
|
|
||||||
strategy to use in any particular case, based on the explanations below.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom of use,
|
|
||||||
not price. Our General Public Licenses are designed to make sure that
|
|
||||||
you have the freedom to distribute copies of free software (and charge
|
|
||||||
for this service if you wish); that you receive source code or can get
|
|
||||||
it if you want it; that you can change the software and use pieces of
|
|
||||||
it in new free programs; and that you are informed that you can do
|
|
||||||
these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to make restrictions that forbid
|
|
||||||
distributors to deny you these rights or to ask you to surrender these
|
|
||||||
rights. These restrictions translate to certain responsibilities for
|
|
||||||
you if you distribute copies of the library or if you modify it.
|
|
||||||
|
|
||||||
For example, if you distribute copies of the library, whether gratis
|
|
||||||
or for a fee, you must give the recipients all the rights that we gave
|
|
||||||
you. You must make sure that they, too, receive or can get the source
|
|
||||||
code. If you link other code with the library, you must provide
|
|
||||||
complete object files to the recipients, so that they can relink them
|
|
||||||
with the library after making changes to the library and recompiling
|
|
||||||
it. And you must show them these terms so they know their rights.
|
|
||||||
|
|
||||||
We protect your rights with a two-step method: (1) we copyright the
|
|
||||||
library, and (2) we offer you this license, which gives you legal
|
|
||||||
permission to copy, distribute and/or modify the library.
|
|
||||||
|
|
||||||
To protect each distributor, we want to make it very clear that
|
|
||||||
there is no warranty for the free library. Also, if the library is
|
|
||||||
modified by someone else and passed on, the recipients should know
|
|
||||||
that what they have is not the original version, so that the original
|
|
||||||
author's reputation will not be affected by problems that might be
|
|
||||||
introduced by others.
|
|
||||||
|
|
||||||
Finally, software patents pose a constant threat to the existence of
|
|
||||||
any free program. We wish to make sure that a company cannot
|
|
||||||
effectively restrict the users of a free program by obtaining a
|
|
||||||
restrictive license from a patent holder. Therefore, we insist that
|
|
||||||
any patent license obtained for a version of the library must be
|
|
||||||
consistent with the full freedom of use specified in this license.
|
|
||||||
|
|
||||||
Most GNU software, including some libraries, is covered by the
|
|
||||||
ordinary GNU General Public License. This license, the GNU Lesser
|
|
||||||
General Public License, applies to certain designated libraries, and
|
|
||||||
is quite different from the ordinary General Public License. We use
|
|
||||||
this license for certain libraries in order to permit linking those
|
|
||||||
libraries into non-free programs.
|
|
||||||
|
|
||||||
When a program is linked with a library, whether statically or using
|
|
||||||
a shared library, the combination of the two is legally speaking a
|
|
||||||
combined work, a derivative of the original library. The ordinary
|
|
||||||
General Public License therefore permits such linking only if the
|
|
||||||
entire combination fits its criteria of freedom. The Lesser General
|
|
||||||
Public License permits more lax criteria for linking other code with
|
|
||||||
the library.
|
|
||||||
|
|
||||||
We call this license the "Lesser" General Public License because it
|
|
||||||
does Less to protect the user's freedom than the ordinary General
|
|
||||||
Public License. It also provides other free software developers Less
|
|
||||||
of an advantage over competing non-free programs. These disadvantages
|
|
||||||
are the reason we use the ordinary General Public License for many
|
|
||||||
libraries. However, the Lesser license provides advantages in certain
|
|
||||||
special circumstances.
|
|
||||||
|
|
||||||
For example, on rare occasions, there may be a special need to
|
|
||||||
encourage the widest possible use of a certain library, so that it becomes
|
|
||||||
a de-facto standard. To achieve this, non-free programs must be
|
|
||||||
allowed to use the library. A more frequent case is that a free
|
|
||||||
library does the same job as widely used non-free libraries. In this
|
|
||||||
case, there is little to gain by limiting the free library to free
|
|
||||||
software only, so we use the Lesser General Public License.
|
|
||||||
|
|
||||||
In other cases, permission to use a particular library in non-free
|
|
||||||
programs enables a greater number of people to use a large body of
|
|
||||||
free software. For example, permission to use the GNU C Library in
|
|
||||||
non-free programs enables many more people to use the whole GNU
|
|
||||||
operating system, as well as its variant, the GNU/Linux operating
|
|
||||||
system.
|
|
||||||
|
|
||||||
Although the Lesser General Public License is Less protective of the
|
|
||||||
users' freedom, it does ensure that the user of a program that is
|
|
||||||
linked with the Library has the freedom and the wherewithal to run
|
|
||||||
that program using a modified version of the Library.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow. Pay close attention to the difference between a
|
|
||||||
"work based on the library" and a "work that uses the library". The
|
|
||||||
former contains code derived from the library, whereas the latter must
|
|
||||||
be combined with the library in order to run.
|
|
||||||
|
|
||||||
GNU LESSER GENERAL PUBLIC LICENSE
|
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
||||||
|
|
||||||
0. This License Agreement applies to any software library or other
|
|
||||||
program which contains a notice placed by the copyright holder or
|
|
||||||
other authorized party saying it may be distributed under the terms of
|
|
||||||
this Lesser General Public License (also called "this License").
|
|
||||||
Each licensee is addressed as "you".
|
|
||||||
|
|
||||||
A "library" means a collection of software functions and/or data
|
|
||||||
prepared so as to be conveniently linked with application programs
|
|
||||||
(which use some of those functions and data) to form executables.
|
|
||||||
|
|
||||||
The "Library", below, refers to any such software library or work
|
|
||||||
which has been distributed under these terms. A "work based on the
|
|
||||||
Library" means either the Library or any derivative work under
|
|
||||||
copyright law: that is to say, a work containing the Library or a
|
|
||||||
portion of it, either verbatim or with modifications and/or translated
|
|
||||||
straightforwardly into another language. (Hereinafter, translation is
|
|
||||||
included without limitation in the term "modification".)
|
|
||||||
|
|
||||||
"Source code" for a work means the preferred form of the work for
|
|
||||||
making modifications to it. For a library, complete source code means
|
|
||||||
all the source code for all modules it contains, plus any associated
|
|
||||||
interface definition files, plus the scripts used to control compilation
|
|
||||||
and installation of the library.
|
|
||||||
|
|
||||||
Activities other than copying, distribution and modification are not
|
|
||||||
covered by this License; they are outside its scope. The act of
|
|
||||||
running a program using the Library is not restricted, and output from
|
|
||||||
such a program is covered only if its contents constitute a work based
|
|
||||||
on the Library (independent of the use of the Library in a tool for
|
|
||||||
writing it). Whether that is true depends on what the Library does
|
|
||||||
and what the program that uses the Library does.
|
|
||||||
|
|
||||||
1. You may copy and distribute verbatim copies of the Library's
|
|
||||||
complete source code as you receive it, in any medium, provided that
|
|
||||||
you conspicuously and appropriately publish on each copy an
|
|
||||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
|
||||||
all the notices that refer to this License and to the absence of any
|
|
||||||
warranty; and distribute a copy of this License along with the
|
|
||||||
Library.
|
|
||||||
|
|
||||||
You may charge a fee for the physical act of transferring a copy,
|
|
||||||
and you may at your option offer warranty protection in exchange for a
|
|
||||||
fee.
|
|
||||||
|
|
||||||
2. You may modify your copy or copies of the Library or any portion
|
|
||||||
of it, thus forming a work based on the Library, and copy and
|
|
||||||
distribute such modifications or work under the terms of Section 1
|
|
||||||
above, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) The modified work must itself be a software library.
|
|
||||||
|
|
||||||
b) You must cause the files modified to carry prominent notices
|
|
||||||
stating that you changed the files and the date of any change.
|
|
||||||
|
|
||||||
c) You must cause the whole of the work to be licensed at no
|
|
||||||
charge to all third parties under the terms of this License.
|
|
||||||
|
|
||||||
d) If a facility in the modified Library refers to a function or a
|
|
||||||
table of data to be supplied by an application program that uses
|
|
||||||
the facility, other than as an argument passed when the facility
|
|
||||||
is invoked, then you must make a good faith effort to ensure that,
|
|
||||||
in the event an application does not supply such function or
|
|
||||||
table, the facility still operates, and performs whatever part of
|
|
||||||
its purpose remains meaningful.
|
|
||||||
|
|
||||||
(For example, a function in a library to compute square roots has
|
|
||||||
a purpose that is entirely well-defined independent of the
|
|
||||||
application. Therefore, Subsection 2d requires that any
|
|
||||||
application-supplied function or table used by this function must
|
|
||||||
be optional: if the application does not supply it, the square
|
|
||||||
root function must still compute square roots.)
|
|
||||||
|
|
||||||
These requirements apply to the modified work as a whole. If
|
|
||||||
identifiable sections of that work are not derived from the Library,
|
|
||||||
and can be reasonably considered independent and separate works in
|
|
||||||
themselves, then this License, and its terms, do not apply to those
|
|
||||||
sections when you distribute them as separate works. But when you
|
|
||||||
distribute the same sections as part of a whole which is a work based
|
|
||||||
on the Library, the distribution of the whole must be on the terms of
|
|
||||||
this License, whose permissions for other licensees extend to the
|
|
||||||
entire whole, and thus to each and every part regardless of who wrote
|
|
||||||
it.
|
|
||||||
|
|
||||||
Thus, it is not the intent of this section to claim rights or contest
|
|
||||||
your rights to work written entirely by you; rather, the intent is to
|
|
||||||
exercise the right to control the distribution of derivative or
|
|
||||||
collective works based on the Library.
|
|
||||||
|
|
||||||
In addition, mere aggregation of another work not based on the Library
|
|
||||||
with the Library (or with a work based on the Library) on a volume of
|
|
||||||
a storage or distribution medium does not bring the other work under
|
|
||||||
the scope of this License.
|
|
||||||
|
|
||||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
|
||||||
License instead of this License to a given copy of the Library. To do
|
|
||||||
this, you must alter all the notices that refer to this License, so
|
|
||||||
that they refer to the ordinary GNU General Public License, version 2,
|
|
||||||
instead of to this License. (If a newer version than version 2 of the
|
|
||||||
ordinary GNU General Public License has appeared, then you can specify
|
|
||||||
that version instead if you wish.) Do not make any other change in
|
|
||||||
these notices.
|
|
||||||
|
|
||||||
Once this change is made in a given copy, it is irreversible for
|
|
||||||
that copy, so the ordinary GNU General Public License applies to all
|
|
||||||
subsequent copies and derivative works made from that copy.
|
|
||||||
|
|
||||||
This option is useful when you wish to copy part of the code of
|
|
||||||
the Library into a program that is not a library.
|
|
||||||
|
|
||||||
4. You may copy and distribute the Library (or a portion or
|
|
||||||
derivative of it, under Section 2) in object code or executable form
|
|
||||||
under the terms of Sections 1 and 2 above provided that you accompany
|
|
||||||
it with the complete corresponding machine-readable source code, which
|
|
||||||
must be distributed under the terms of Sections 1 and 2 above on a
|
|
||||||
medium customarily used for software interchange.
|
|
||||||
|
|
||||||
If distribution of object code is made by offering access to copy
|
|
||||||
from a designated place, then offering equivalent access to copy the
|
|
||||||
source code from the same place satisfies the requirement to
|
|
||||||
distribute the source code, even though third parties are not
|
|
||||||
compelled to copy the source along with the object code.
|
|
||||||
|
|
||||||
5. A program that contains no derivative of any portion of the
|
|
||||||
Library, but is designed to work with the Library by being compiled or
|
|
||||||
linked with it, is called a "work that uses the Library". Such a
|
|
||||||
work, in isolation, is not a derivative work of the Library, and
|
|
||||||
therefore falls outside the scope of this License.
|
|
||||||
|
|
||||||
However, linking a "work that uses the Library" with the Library
|
|
||||||
creates an executable that is a derivative of the Library (because it
|
|
||||||
contains portions of the Library), rather than a "work that uses the
|
|
||||||
library". The executable is therefore covered by this License.
|
|
||||||
Section 6 states terms for distribution of such executables.
|
|
||||||
|
|
||||||
When a "work that uses the Library" uses material from a header file
|
|
||||||
that is part of the Library, the object code for the work may be a
|
|
||||||
derivative work of the Library even though the source code is not.
|
|
||||||
Whether this is true is especially significant if the work can be
|
|
||||||
linked without the Library, or if the work is itself a library. The
|
|
||||||
threshold for this to be true is not precisely defined by law.
|
|
||||||
|
|
||||||
If such an object file uses only numerical parameters, data
|
|
||||||
structure layouts and accessors, and small macros and small inline
|
|
||||||
functions (ten lines or less in length), then the use of the object
|
|
||||||
file is unrestricted, regardless of whether it is legally a derivative
|
|
||||||
work. (Executables containing this object code plus portions of the
|
|
||||||
Library will still fall under Section 6.)
|
|
||||||
|
|
||||||
Otherwise, if the work is a derivative of the Library, you may
|
|
||||||
distribute the object code for the work under the terms of Section 6.
|
|
||||||
Any executables containing that work also fall under Section 6,
|
|
||||||
whether or not they are linked directly with the Library itself.
|
|
||||||
|
|
||||||
6. As an exception to the Sections above, you may also combine or
|
|
||||||
link a "work that uses the Library" with the Library to produce a
|
|
||||||
work containing portions of the Library, and distribute that work
|
|
||||||
under terms of your choice, provided that the terms permit
|
|
||||||
modification of the work for the customer's own use and reverse
|
|
||||||
engineering for debugging such modifications.
|
|
||||||
|
|
||||||
You must give prominent notice with each copy of the work that the
|
|
||||||
Library is used in it and that the Library and its use are covered by
|
|
||||||
this License. You must supply a copy of this License. If the work
|
|
||||||
during execution displays copyright notices, you must include the
|
|
||||||
copyright notice for the Library among them, as well as a reference
|
|
||||||
directing the user to the copy of this License. Also, you must do one
|
|
||||||
of these things:
|
|
||||||
|
|
||||||
a) Accompany the work with the complete corresponding
|
|
||||||
machine-readable source code for the Library including whatever
|
|
||||||
changes were used in the work (which must be distributed under
|
|
||||||
Sections 1 and 2 above); and, if the work is an executable linked
|
|
||||||
with the Library, with the complete machine-readable "work that
|
|
||||||
uses the Library", as object code and/or source code, so that the
|
|
||||||
user can modify the Library and then relink to produce a modified
|
|
||||||
executable containing the modified Library. (It is understood
|
|
||||||
that the user who changes the contents of definitions files in the
|
|
||||||
Library will not necessarily be able to recompile the application
|
|
||||||
to use the modified definitions.)
|
|
||||||
|
|
||||||
b) Use a suitable shared library mechanism for linking with the
|
|
||||||
Library. A suitable mechanism is one that (1) uses at run time a
|
|
||||||
copy of the library already present on the user's computer system,
|
|
||||||
rather than copying library functions into the executable, and (2)
|
|
||||||
will operate properly with a modified version of the library, if
|
|
||||||
the user installs one, as long as the modified version is
|
|
||||||
interface-compatible with the version that the work was made with.
|
|
||||||
|
|
||||||
c) Accompany the work with a written offer, valid for at
|
|
||||||
least three years, to give the same user the materials
|
|
||||||
specified in Subsection 6a, above, for a charge no more
|
|
||||||
than the cost of performing this distribution.
|
|
||||||
|
|
||||||
d) If distribution of the work is made by offering access to copy
|
|
||||||
from a designated place, offer equivalent access to copy the above
|
|
||||||
specified materials from the same place.
|
|
||||||
|
|
||||||
e) Verify that the user has already received a copy of these
|
|
||||||
materials or that you have already sent this user a copy.
|
|
||||||
|
|
||||||
For an executable, the required form of the "work that uses the
|
|
||||||
Library" must include any data and utility programs needed for
|
|
||||||
reproducing the executable from it. However, as a special exception,
|
|
||||||
the materials to be distributed need not include anything that is
|
|
||||||
normally distributed (in either source or binary form) with the major
|
|
||||||
components (compiler, kernel, and so on) of the operating system on
|
|
||||||
which the executable runs, unless that component itself accompanies
|
|
||||||
the executable.
|
|
||||||
|
|
||||||
It may happen that this requirement contradicts the license
|
|
||||||
restrictions of other proprietary libraries that do not normally
|
|
||||||
accompany the operating system. Such a contradiction means you cannot
|
|
||||||
use both them and the Library together in an executable that you
|
|
||||||
distribute.
|
|
||||||
|
|
||||||
7. You may place library facilities that are a work based on the
|
|
||||||
Library side-by-side in a single library together with other library
|
|
||||||
facilities not covered by this License, and distribute such a combined
|
|
||||||
library, provided that the separate distribution of the work based on
|
|
||||||
the Library and of the other library facilities is otherwise
|
|
||||||
permitted, and provided that you do these two things:
|
|
||||||
|
|
||||||
a) Accompany the combined library with a copy of the same work
|
|
||||||
based on the Library, uncombined with any other library
|
|
||||||
facilities. This must be distributed under the terms of the
|
|
||||||
Sections above.
|
|
||||||
|
|
||||||
b) Give prominent notice with the combined library of the fact
|
|
||||||
that part of it is a work based on the Library, and explaining
|
|
||||||
where to find the accompanying uncombined form of the same work.
|
|
||||||
|
|
||||||
8. You may not copy, modify, sublicense, link with, or distribute
|
|
||||||
the Library except as expressly provided under this License. Any
|
|
||||||
attempt otherwise to copy, modify, sublicense, link with, or
|
|
||||||
distribute the Library is void, and will automatically terminate your
|
|
||||||
rights under this License. However, parties who have received copies,
|
|
||||||
or rights, from you under this License will not have their licenses
|
|
||||||
terminated so long as such parties remain in full compliance.
|
|
||||||
|
|
||||||
9. You are not required to accept this License, since you have not
|
|
||||||
signed it. However, nothing else grants you permission to modify or
|
|
||||||
distribute the Library or its derivative works. These actions are
|
|
||||||
prohibited by law if you do not accept this License. Therefore, by
|
|
||||||
modifying or distributing the Library (or any work based on the
|
|
||||||
Library), you indicate your acceptance of this License to do so, and
|
|
||||||
all its terms and conditions for copying, distributing or modifying
|
|
||||||
the Library or works based on it.
|
|
||||||
|
|
||||||
10. Each time you redistribute the Library (or any work based on the
|
|
||||||
Library), the recipient automatically receives a license from the
|
|
||||||
original licensor to copy, distribute, link with or modify the Library
|
|
||||||
subject to these terms and conditions. You may not impose any further
|
|
||||||
restrictions on the recipients' exercise of the rights granted herein.
|
|
||||||
You are not responsible for enforcing compliance by third parties with
|
|
||||||
this License.
|
|
||||||
|
|
||||||
11. If, as a consequence of a court judgment or allegation of patent
|
|
||||||
infringement or for any other reason (not limited to patent issues),
|
|
||||||
conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot
|
|
||||||
distribute so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you
|
|
||||||
may not distribute the Library at all. For example, if a patent
|
|
||||||
license would not permit royalty-free redistribution of the Library by
|
|
||||||
all those who receive copies directly or indirectly through you, then
|
|
||||||
the only way you could satisfy both it and this License would be to
|
|
||||||
refrain entirely from distribution of the Library.
|
|
||||||
|
|
||||||
If any portion of this section is held invalid or unenforceable under any
|
|
||||||
particular circumstance, the balance of the section is intended to apply,
|
|
||||||
and the section as a whole is intended to apply in other circumstances.
|
|
||||||
|
|
||||||
It is not the purpose of this section to induce you to infringe any
|
|
||||||
patents or other property right claims or to contest validity of any
|
|
||||||
such claims; this section has the sole purpose of protecting the
|
|
||||||
integrity of the free software distribution system which is
|
|
||||||
implemented by public license practices. Many people have made
|
|
||||||
generous contributions to the wide range of software distributed
|
|
||||||
through that system in reliance on consistent application of that
|
|
||||||
system; it is up to the author/donor to decide if he or she is willing
|
|
||||||
to distribute software through any other system and a licensee cannot
|
|
||||||
impose that choice.
|
|
||||||
|
|
||||||
This section is intended to make thoroughly clear what is believed to
|
|
||||||
be a consequence of the rest of this License.
|
|
||||||
|
|
||||||
12. If the distribution and/or use of the Library is restricted in
|
|
||||||
certain countries either by patents or by copyrighted interfaces, the
|
|
||||||
original copyright holder who places the Library under this License may add
|
|
||||||
an explicit geographical distribution limitation excluding those countries,
|
|
||||||
so that distribution is permitted only in or among countries not thus
|
|
||||||
excluded. In such case, this License incorporates the limitation as if
|
|
||||||
written in the body of this License.
|
|
||||||
|
|
||||||
13. The Free Software Foundation may publish revised and/or new
|
|
||||||
versions of the Lesser General Public License from time to time.
|
|
||||||
Such new versions will be similar in spirit to the present version,
|
|
||||||
but may differ in detail to address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the Library
|
|
||||||
specifies a version number of this License which applies to it and
|
|
||||||
"any later version", you have the option of following the terms and
|
|
||||||
conditions either of that version or of any later version published by
|
|
||||||
the Free Software Foundation. If the Library does not specify a
|
|
||||||
license version number, you may choose any version ever published by
|
|
||||||
the Free Software Foundation.
|
|
||||||
|
|
||||||
14. If you wish to incorporate parts of the Library into other free
|
|
||||||
programs whose distribution conditions are incompatible with these,
|
|
||||||
write to the author to ask for permission. For software which is
|
|
||||||
copyrighted by the Free Software Foundation, write to the Free
|
|
||||||
Software Foundation; we sometimes make exceptions for this. Our
|
|
||||||
decision will be guided by the two goals of preserving the free status
|
|
||||||
of all derivatives of our free software and of promoting the sharing
|
|
||||||
and reuse of software generally.
|
|
||||||
|
|
||||||
NO WARRANTY
|
|
||||||
|
|
||||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
|
||||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
|
||||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
|
||||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
|
||||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
|
||||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
|
||||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
|
||||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
|
||||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
|
||||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
|
||||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
|
||||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
|
||||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
|
||||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
|
||||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
|
||||||
DAMAGES.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Libraries
|
|
||||||
|
|
||||||
If you develop a new library, and you want it to be of the greatest
|
|
||||||
possible use to the public, we recommend making it free software that
|
|
||||||
everyone can redistribute and change. You can do so by permitting
|
|
||||||
redistribution under these terms (or, alternatively, under the terms of the
|
|
||||||
ordinary General Public License).
|
|
||||||
|
|
||||||
To apply these terms, attach the following notices to the library. It is
|
|
||||||
safest to attach them to the start of each source file to most effectively
|
|
||||||
convey the exclusion of warranty; and each file should have at least the
|
|
||||||
"copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
<one line to give the library's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) <year> <name of author>
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or your
|
|
||||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
|
||||||
necessary. Here is a sample; alter the names:
|
|
||||||
|
|
||||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
|
||||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
|
||||||
|
|
||||||
<signature of Ty Coon>, 1 April 1990
|
|
||||||
Ty Coon, President of Vice
|
|
||||||
|
|
||||||
That's all there is to it!
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
/**
|
|
||||||
* Location.java
|
|
||||||
*
|
|
||||||
* Copyright (C) 2004 MaxMind LLC. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Lesser Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.maxmind.geoip;
|
|
||||||
|
|
||||||
public class Location {
|
|
||||||
public String countryCode;
|
|
||||||
public String countryName;
|
|
||||||
public String region;
|
|
||||||
public String city;
|
|
||||||
public String postalCode;
|
|
||||||
public float latitude;
|
|
||||||
public float longitude;
|
|
||||||
public int dma_code;
|
|
||||||
public int area_code;
|
|
||||||
public int metro_code;
|
|
||||||
|
|
||||||
private final static double EARTH_DIAMETER = 2 * 6378.2;
|
|
||||||
private final static double PI = 3.14159265;
|
|
||||||
private final static double RAD_CONVERT = PI / 180;
|
|
||||||
|
|
||||||
public double distance (Location loc) {
|
|
||||||
double delta_lat, delta_lon;
|
|
||||||
double temp;
|
|
||||||
|
|
||||||
float lat1 = latitude;
|
|
||||||
float lon1 = longitude;
|
|
||||||
float lat2 = loc.latitude;
|
|
||||||
float lon2 = loc.longitude;
|
|
||||||
|
|
||||||
// convert degrees to radians
|
|
||||||
lat1 *= RAD_CONVERT;
|
|
||||||
lat2 *= RAD_CONVERT;
|
|
||||||
|
|
||||||
// find the deltas
|
|
||||||
delta_lat = lat2 - lat1;
|
|
||||||
delta_lon = (lon2 - lon1) * RAD_CONVERT;
|
|
||||||
|
|
||||||
// Find the great circle distance
|
|
||||||
temp = Math.pow(Math.sin(delta_lat/2),2) + Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(delta_lon/2),2);
|
|
||||||
return EARTH_DIAMETER * Math.atan2(Math.sqrt(temp),Math.sqrt(1-temp));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,8 +0,0 @@
|
|||||||
package com.maxmind.geoip;
|
|
||||||
|
|
||||||
public class Region{
|
|
||||||
public String countryCode;
|
|
||||||
public String countryName;
|
|
||||||
public String region;
|
|
||||||
}
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,295 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2005-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copied from OpenJDK with permission.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.auth;
|
|
||||||
|
|
||||||
import java.security.*;
|
|
||||||
|
|
||||||
//import static sun.security.provider.ByteArrayAccess.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The MD4 class is used to compute an MD4 message digest over a given
|
|
||||||
* buffer of bytes. It is an implementation of the RSA Data Security Inc
|
|
||||||
* MD4 algorithim as described in internet RFC 1320.
|
|
||||||
*
|
|
||||||
* @author Andreas Sterbenz
|
|
||||||
* @author Bill Shannon (adapted for JavaMail)
|
|
||||||
*/
|
|
||||||
public final class MD4 {
|
|
||||||
|
|
||||||
// state of this object
|
|
||||||
private final int[] state;
|
|
||||||
// temporary buffer, used by implCompress()
|
|
||||||
private final int[] x;
|
|
||||||
|
|
||||||
// size of the input to the compression function in bytes
|
|
||||||
private static final int blockSize = 64;
|
|
||||||
|
|
||||||
// buffer to store partial blocks, blockSize bytes large
|
|
||||||
private final byte[] buffer = new byte[blockSize];
|
|
||||||
// offset into buffer
|
|
||||||
private int bufOfs;
|
|
||||||
|
|
||||||
// number of bytes processed so far.
|
|
||||||
// also used as a flag to indicate reset status
|
|
||||||
// -1: need to call engineReset() before next call to update()
|
|
||||||
// 0: is already reset
|
|
||||||
private long bytesProcessed;
|
|
||||||
|
|
||||||
// rotation constants
|
|
||||||
private static final int S11 = 3;
|
|
||||||
private static final int S12 = 7;
|
|
||||||
private static final int S13 = 11;
|
|
||||||
private static final int S14 = 19;
|
|
||||||
private static final int S21 = 3;
|
|
||||||
private static final int S22 = 5;
|
|
||||||
private static final int S23 = 9;
|
|
||||||
private static final int S24 = 13;
|
|
||||||
private static final int S31 = 3;
|
|
||||||
private static final int S32 = 9;
|
|
||||||
private static final int S33 = 11;
|
|
||||||
private static final int S34 = 15;
|
|
||||||
|
|
||||||
private static final byte[] padding;
|
|
||||||
|
|
||||||
static {
|
|
||||||
padding = new byte[136];
|
|
||||||
padding[0] = (byte)0x80;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Standard constructor, creates a new MD4 instance.
|
|
||||||
public MD4() {
|
|
||||||
state = new int[4];
|
|
||||||
x = new int[16];
|
|
||||||
implReset();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compute and return the message digest of the input byte array.
|
|
||||||
*/
|
|
||||||
public byte[] digest(byte[] in) {
|
|
||||||
implReset();
|
|
||||||
engineUpdate(in, 0, in.length);
|
|
||||||
byte[] out = new byte[16];
|
|
||||||
implDigest(out, 0);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset the state of this object.
|
|
||||||
*/
|
|
||||||
private void implReset() {
|
|
||||||
// Load magic initialization constants.
|
|
||||||
state[0] = 0x67452301;
|
|
||||||
state[1] = 0xefcdab89;
|
|
||||||
state[2] = 0x98badcfe;
|
|
||||||
state[3] = 0x10325476;
|
|
||||||
bufOfs = 0;
|
|
||||||
bytesProcessed = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform the final computations, any buffered bytes are added
|
|
||||||
* to the digest, the count is added to the digest, and the resulting
|
|
||||||
* digest is stored.
|
|
||||||
*/
|
|
||||||
private void implDigest(byte[] out, int ofs) {
|
|
||||||
long bitsProcessed = bytesProcessed << 3;
|
|
||||||
|
|
||||||
int index = (int)bytesProcessed & 0x3f;
|
|
||||||
int padLen = (index < 56) ? (56 - index) : (120 - index);
|
|
||||||
engineUpdate(padding, 0, padLen);
|
|
||||||
|
|
||||||
//i2bLittle4((int)bitsProcessed, buffer, 56);
|
|
||||||
//i2bLittle4((int)(bitsProcessed >>> 32), buffer, 60);
|
|
||||||
buffer[56] = (byte)bitsProcessed;
|
|
||||||
buffer[57] = (byte)(bitsProcessed>>8);
|
|
||||||
buffer[58] = (byte)(bitsProcessed>>16);
|
|
||||||
buffer[59] = (byte)(bitsProcessed>>24);
|
|
||||||
buffer[60] = (byte)(bitsProcessed>>32);
|
|
||||||
buffer[61] = (byte)(bitsProcessed>>40);
|
|
||||||
buffer[62] = (byte)(bitsProcessed>>48);
|
|
||||||
buffer[63] = (byte)(bitsProcessed>>56);
|
|
||||||
implCompress(buffer, 0);
|
|
||||||
|
|
||||||
//i2bLittle(state, 0, out, ofs, 16);
|
|
||||||
for (int i = 0; i < state.length; i++) {
|
|
||||||
int x = state[i];
|
|
||||||
out[ofs++] = (byte)x;
|
|
||||||
out[ofs++] = (byte)(x>>8);
|
|
||||||
out[ofs++] = (byte)(x>>16);
|
|
||||||
out[ofs++] = (byte)(x>>24);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void engineUpdate(byte[] b, int ofs, int len) {
|
|
||||||
if (len == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((ofs < 0) || (len < 0) || (ofs > b.length - len)) {
|
|
||||||
throw new ArrayIndexOutOfBoundsException();
|
|
||||||
}
|
|
||||||
if (bytesProcessed < 0) {
|
|
||||||
implReset();
|
|
||||||
}
|
|
||||||
bytesProcessed += len;
|
|
||||||
// if buffer is not empty, we need to fill it before proceeding
|
|
||||||
if (bufOfs != 0) {
|
|
||||||
int n = Math.min(len, blockSize - bufOfs);
|
|
||||||
System.arraycopy(b, ofs, buffer, bufOfs, n);
|
|
||||||
bufOfs += n;
|
|
||||||
ofs += n;
|
|
||||||
len -= n;
|
|
||||||
if (bufOfs >= blockSize) {
|
|
||||||
// compress completed block now
|
|
||||||
implCompress(buffer, 0);
|
|
||||||
bufOfs = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// compress complete blocks
|
|
||||||
while (len >= blockSize) {
|
|
||||||
implCompress(b, ofs);
|
|
||||||
len -= blockSize;
|
|
||||||
ofs += blockSize;
|
|
||||||
}
|
|
||||||
// copy remainder to buffer
|
|
||||||
if (len > 0) {
|
|
||||||
System.arraycopy(b, ofs, buffer, 0, len);
|
|
||||||
bufOfs = len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int FF(int a, int b, int c, int d, int x, int s) {
|
|
||||||
a += ((b & c) | ((~b) & d)) + x;
|
|
||||||
return ((a << s) | (a >>> (32 - s)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int GG(int a, int b, int c, int d, int x, int s) {
|
|
||||||
a += ((b & c) | (b & d) | (c & d)) + x + 0x5a827999;
|
|
||||||
return ((a << s) | (a >>> (32 - s)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int HH(int a, int b, int c, int d, int x, int s) {
|
|
||||||
a += ((b ^ c) ^ d) + x + 0x6ed9eba1;
|
|
||||||
return ((a << s) | (a >>> (32 - s)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is where the functions come together as the generic MD4
|
|
||||||
* transformation operation. It consumes 64
|
|
||||||
* bytes from the buffer, beginning at the specified offset.
|
|
||||||
*/
|
|
||||||
private void implCompress(byte[] buf, int ofs) {
|
|
||||||
//b2iLittle64(buf, ofs, x);
|
|
||||||
for (int xfs = 0; xfs < x.length; xfs++) {
|
|
||||||
x[xfs] = (buf[ofs] & 0xff) | ((buf[ofs+1] & 0xff) << 8) |
|
|
||||||
((buf[ofs+2] & 0xff) << 16) | ((buf[ofs+3] & 0xff) << 24);
|
|
||||||
ofs += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
int a = state[0];
|
|
||||||
int b = state[1];
|
|
||||||
int c = state[2];
|
|
||||||
int d = state[3];
|
|
||||||
|
|
||||||
/* Round 1 */
|
|
||||||
a = FF (a, b, c, d, x[ 0], S11); /* 1 */
|
|
||||||
d = FF (d, a, b, c, x[ 1], S12); /* 2 */
|
|
||||||
c = FF (c, d, a, b, x[ 2], S13); /* 3 */
|
|
||||||
b = FF (b, c, d, a, x[ 3], S14); /* 4 */
|
|
||||||
a = FF (a, b, c, d, x[ 4], S11); /* 5 */
|
|
||||||
d = FF (d, a, b, c, x[ 5], S12); /* 6 */
|
|
||||||
c = FF (c, d, a, b, x[ 6], S13); /* 7 */
|
|
||||||
b = FF (b, c, d, a, x[ 7], S14); /* 8 */
|
|
||||||
a = FF (a, b, c, d, x[ 8], S11); /* 9 */
|
|
||||||
d = FF (d, a, b, c, x[ 9], S12); /* 10 */
|
|
||||||
c = FF (c, d, a, b, x[10], S13); /* 11 */
|
|
||||||
b = FF (b, c, d, a, x[11], S14); /* 12 */
|
|
||||||
a = FF (a, b, c, d, x[12], S11); /* 13 */
|
|
||||||
d = FF (d, a, b, c, x[13], S12); /* 14 */
|
|
||||||
c = FF (c, d, a, b, x[14], S13); /* 15 */
|
|
||||||
b = FF (b, c, d, a, x[15], S14); /* 16 */
|
|
||||||
|
|
||||||
/* Round 2 */
|
|
||||||
a = GG (a, b, c, d, x[ 0], S21); /* 17 */
|
|
||||||
d = GG (d, a, b, c, x[ 4], S22); /* 18 */
|
|
||||||
c = GG (c, d, a, b, x[ 8], S23); /* 19 */
|
|
||||||
b = GG (b, c, d, a, x[12], S24); /* 20 */
|
|
||||||
a = GG (a, b, c, d, x[ 1], S21); /* 21 */
|
|
||||||
d = GG (d, a, b, c, x[ 5], S22); /* 22 */
|
|
||||||
c = GG (c, d, a, b, x[ 9], S23); /* 23 */
|
|
||||||
b = GG (b, c, d, a, x[13], S24); /* 24 */
|
|
||||||
a = GG (a, b, c, d, x[ 2], S21); /* 25 */
|
|
||||||
d = GG (d, a, b, c, x[ 6], S22); /* 26 */
|
|
||||||
c = GG (c, d, a, b, x[10], S23); /* 27 */
|
|
||||||
b = GG (b, c, d, a, x[14], S24); /* 28 */
|
|
||||||
a = GG (a, b, c, d, x[ 3], S21); /* 29 */
|
|
||||||
d = GG (d, a, b, c, x[ 7], S22); /* 30 */
|
|
||||||
c = GG (c, d, a, b, x[11], S23); /* 31 */
|
|
||||||
b = GG (b, c, d, a, x[15], S24); /* 32 */
|
|
||||||
|
|
||||||
/* Round 3 */
|
|
||||||
a = HH (a, b, c, d, x[ 0], S31); /* 33 */
|
|
||||||
d = HH (d, a, b, c, x[ 8], S32); /* 34 */
|
|
||||||
c = HH (c, d, a, b, x[ 4], S33); /* 35 */
|
|
||||||
b = HH (b, c, d, a, x[12], S34); /* 36 */
|
|
||||||
a = HH (a, b, c, d, x[ 2], S31); /* 37 */
|
|
||||||
d = HH (d, a, b, c, x[10], S32); /* 38 */
|
|
||||||
c = HH (c, d, a, b, x[ 6], S33); /* 39 */
|
|
||||||
b = HH (b, c, d, a, x[14], S34); /* 40 */
|
|
||||||
a = HH (a, b, c, d, x[ 1], S31); /* 41 */
|
|
||||||
d = HH (d, a, b, c, x[ 9], S32); /* 42 */
|
|
||||||
c = HH (c, d, a, b, x[ 5], S33); /* 43 */
|
|
||||||
b = HH (b, c, d, a, x[13], S34); /* 44 */
|
|
||||||
a = HH (a, b, c, d, x[ 3], S31); /* 45 */
|
|
||||||
d = HH (d, a, b, c, x[11], S32); /* 46 */
|
|
||||||
c = HH (c, d, a, b, x[ 7], S33); /* 47 */
|
|
||||||
b = HH (b, c, d, a, x[15], S34); /* 48 */
|
|
||||||
|
|
||||||
state[0] += a;
|
|
||||||
state[1] += b;
|
|
||||||
state[2] += c;
|
|
||||||
state[3] += d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,361 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2005-2012 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copied from OpenJDK with permission.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.auth;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.io.PrintStream;
|
|
||||||
import java.security.GeneralSecurityException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import javax.crypto.Cipher;
|
|
||||||
import javax.crypto.NoSuchPaddingException;
|
|
||||||
import javax.crypto.SecretKey;
|
|
||||||
import javax.crypto.SecretKeyFactory;
|
|
||||||
import javax.crypto.spec.DESKeySpec;
|
|
||||||
|
|
||||||
import com.sun.mail.util.BASE64DecoderStream;
|
|
||||||
import com.sun.mail.util.BASE64EncoderStream;
|
|
||||||
import com.sun.mail.util.MailLogger;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* NTLMAuthentication:
|
|
||||||
*
|
|
||||||
* @author Michael McMahon
|
|
||||||
* @author Bill Shannon (adapted for JavaMail)
|
|
||||||
*/
|
|
||||||
public class Ntlm {
|
|
||||||
|
|
||||||
private byte[] type1;
|
|
||||||
private byte[] type3;
|
|
||||||
|
|
||||||
private SecretKeyFactory fac;
|
|
||||||
private Cipher cipher;
|
|
||||||
private MD4 md4;
|
|
||||||
private String hostname;
|
|
||||||
private String ntdomain;
|
|
||||||
private String username;
|
|
||||||
private String password;
|
|
||||||
|
|
||||||
private MailLogger logger;
|
|
||||||
|
|
||||||
private void init0() {
|
|
||||||
type1 = new byte[256];
|
|
||||||
type3 = new byte[256];
|
|
||||||
System.arraycopy(new byte[] {'N','T','L','M','S','S','P',0,1}, 0,
|
|
||||||
type1, 0, 9);
|
|
||||||
type1[12] = (byte) 3;
|
|
||||||
type1[13] = (byte) 0xb2;
|
|
||||||
type1[28] = (byte) 0x20;
|
|
||||||
System.arraycopy(new byte[] {'N','T','L','M','S','S','P',0,3}, 0,
|
|
||||||
type3, 0, 9);
|
|
||||||
type3[12] = (byte) 0x18;
|
|
||||||
type3[14] = (byte) 0x18;
|
|
||||||
type3[20] = (byte) 0x18;
|
|
||||||
type3[22] = (byte) 0x18;
|
|
||||||
type3[32] = (byte) 0x40;
|
|
||||||
type3[60] = (byte) 1;
|
|
||||||
type3[61] = (byte) 0x82;
|
|
||||||
|
|
||||||
try {
|
|
||||||
fac = SecretKeyFactory.getInstance("DES");
|
|
||||||
cipher = Cipher.getInstance("DES/ECB/NoPadding");
|
|
||||||
md4 = new MD4();
|
|
||||||
} catch (NoSuchPaddingException e) {
|
|
||||||
assert false;
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
assert false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an NTLM authenticator.
|
|
||||||
* Username may be specified as domain\\username in the Authenticator.
|
|
||||||
* If this notation is not used, then the domain will be taken
|
|
||||||
* from the ntdomain parameter.
|
|
||||||
*/
|
|
||||||
public Ntlm(String ntdomain, String hostname, String username,
|
|
||||||
String password, MailLogger logger) {
|
|
||||||
int i = hostname.indexOf('.');
|
|
||||||
if (i != -1) {
|
|
||||||
hostname = hostname.substring(0, i);
|
|
||||||
}
|
|
||||||
i = username.indexOf('\\');
|
|
||||||
if (i != -1) {
|
|
||||||
ntdomain = username.substring(0, i).toUpperCase();
|
|
||||||
username = username.substring(i+1);
|
|
||||||
} else if (ntdomain == null) {
|
|
||||||
ntdomain = "";
|
|
||||||
}
|
|
||||||
this.ntdomain = ntdomain;
|
|
||||||
this.hostname = hostname;
|
|
||||||
this.username = username;
|
|
||||||
this.password = password;
|
|
||||||
this.logger = logger.getLogger(this.getClass(), "DEBUG NTLM");
|
|
||||||
init0();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void copybytes(byte[] dest, int destpos, String src, String enc) {
|
|
||||||
try {
|
|
||||||
byte[] x = src.getBytes(enc);
|
|
||||||
System.arraycopy(x, 0, dest, destpos, x.length);
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
assert false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String generateType1Msg(int flags) {
|
|
||||||
// XXX - should set "flags" in generated message
|
|
||||||
int dlen = ntdomain.length();
|
|
||||||
type1[16]= (byte) (dlen % 256);
|
|
||||||
type1[17]= (byte) (dlen / 256);
|
|
||||||
type1[18] = type1[16];
|
|
||||||
type1[19] = type1[17];
|
|
||||||
if (dlen == 0)
|
|
||||||
type1[13] &= ~0x10;
|
|
||||||
|
|
||||||
int hlen = hostname.length();
|
|
||||||
type1[24]= (byte) (hlen % 256);
|
|
||||||
type1[25]= (byte) (hlen / 256);
|
|
||||||
type1[26] = type1[24];
|
|
||||||
type1[27] = type1[25];
|
|
||||||
|
|
||||||
copybytes(type1, 32, hostname, "iso-8859-1");
|
|
||||||
copybytes(type1, hlen+32, ntdomain, "iso-8859-1");
|
|
||||||
type1[20] = (byte) ((hlen+32) % 256);
|
|
||||||
type1[21] = (byte) ((hlen+32) / 256);
|
|
||||||
|
|
||||||
byte[] msg = new byte[32 + hlen + dlen];
|
|
||||||
System.arraycopy(type1, 0, msg, 0, 32 + hlen + dlen);
|
|
||||||
if (logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("type 1 message: " + toHex(msg));
|
|
||||||
|
|
||||||
String result = null;
|
|
||||||
try {
|
|
||||||
result = new String(BASE64EncoderStream.encode(msg), "iso-8859-1");
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
assert false;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a 7 byte array to an 8 byte array (for a des key with parity).
|
|
||||||
* Input starts at offset off.
|
|
||||||
*/
|
|
||||||
private byte[] makeDesKey(byte[] input, int off) {
|
|
||||||
int[] in = new int[input.length];
|
|
||||||
for (int i = 0; i < in.length; i++) {
|
|
||||||
in[i] = input[i] < 0 ? input[i] + 256: input[i];
|
|
||||||
}
|
|
||||||
byte[] out = new byte[8];
|
|
||||||
out[0] = (byte)in[off+0];
|
|
||||||
out[1] = (byte)(((in[off+0] << 7) & 0xFF) | (in[off+1] >> 1));
|
|
||||||
out[2] = (byte)(((in[off+1] << 6) & 0xFF) | (in[off+2] >> 2));
|
|
||||||
out[3] = (byte)(((in[off+2] << 5) & 0xFF) | (in[off+3] >> 3));
|
|
||||||
out[4] = (byte)(((in[off+3] << 4) & 0xFF) | (in[off+4] >> 4));
|
|
||||||
out[5] = (byte)(((in[off+4] << 3) & 0xFF) | (in[off+5] >> 5));
|
|
||||||
out[6] = (byte)(((in[off+5] << 2) & 0xFF) | (in[off+6] >> 6));
|
|
||||||
out[7] = (byte)((in[off+6] << 1) & 0xFF);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] calcLMHash() throws GeneralSecurityException {
|
|
||||||
byte[] magic = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
|
|
||||||
byte[] pwb = null;
|
|
||||||
try {
|
|
||||||
pwb = password.toUpperCase(Locale.ENGLISH).getBytes("iso-8859-1");
|
|
||||||
} catch (UnsupportedEncodingException ex) {
|
|
||||||
// should never happen
|
|
||||||
assert false;
|
|
||||||
}
|
|
||||||
byte[] pwb1 = new byte[14];
|
|
||||||
int len = password.length();
|
|
||||||
if (len > 14)
|
|
||||||
len = 14;
|
|
||||||
System.arraycopy(pwb, 0, pwb1, 0, len); /* Zero padded */
|
|
||||||
|
|
||||||
DESKeySpec dks1 = new DESKeySpec(makeDesKey(pwb1, 0));
|
|
||||||
DESKeySpec dks2 = new DESKeySpec(makeDesKey(pwb1, 7));
|
|
||||||
|
|
||||||
SecretKey key1 = fac.generateSecret(dks1);
|
|
||||||
SecretKey key2 = fac.generateSecret(dks2);
|
|
||||||
cipher.init(Cipher.ENCRYPT_MODE, key1);
|
|
||||||
byte[] out1 = cipher.doFinal(magic, 0, 8);
|
|
||||||
cipher.init(Cipher.ENCRYPT_MODE, key2);
|
|
||||||
byte[] out2 = cipher.doFinal(magic, 0, 8);
|
|
||||||
|
|
||||||
byte[] result = new byte [21];
|
|
||||||
System.arraycopy(out1, 0, result, 0, 8);
|
|
||||||
System.arraycopy(out2, 0, result, 8, 8);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] calcNTHash() throws GeneralSecurityException {
|
|
||||||
byte[] pw = null;
|
|
||||||
try {
|
|
||||||
pw = password.getBytes("UnicodeLittleUnmarked");
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
assert false;
|
|
||||||
}
|
|
||||||
byte[] out = md4.digest(pw);
|
|
||||||
byte[] result = new byte[21];
|
|
||||||
System.arraycopy(out, 0, result, 0, 16);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Key is a 21 byte array. Split it into 3 7 byte chunks,
|
|
||||||
* convert each to 8 byte DES keys, encrypt the text arg with
|
|
||||||
* each key and return the three results in a sequential [].
|
|
||||||
*/
|
|
||||||
private byte[] calcResponse(byte[] key, byte[] text)
|
|
||||||
throws GeneralSecurityException {
|
|
||||||
assert key.length == 21;
|
|
||||||
DESKeySpec dks1 = new DESKeySpec(makeDesKey(key, 0));
|
|
||||||
DESKeySpec dks2 = new DESKeySpec(makeDesKey(key, 7));
|
|
||||||
DESKeySpec dks3 = new DESKeySpec(makeDesKey(key, 14));
|
|
||||||
SecretKey key1 = fac.generateSecret(dks1);
|
|
||||||
SecretKey key2 = fac.generateSecret(dks2);
|
|
||||||
SecretKey key3 = fac.generateSecret(dks3);
|
|
||||||
cipher.init(Cipher.ENCRYPT_MODE, key1);
|
|
||||||
byte[] out1 = cipher.doFinal(text, 0, 8);
|
|
||||||
cipher.init(Cipher.ENCRYPT_MODE, key2);
|
|
||||||
byte[] out2 = cipher.doFinal(text, 0, 8);
|
|
||||||
cipher.init(Cipher.ENCRYPT_MODE, key3);
|
|
||||||
byte[] out3 = cipher.doFinal(text, 0, 8);
|
|
||||||
byte[] result = new byte[24];
|
|
||||||
System.arraycopy(out1, 0, result, 0, 8);
|
|
||||||
System.arraycopy(out2, 0, result, 8, 8);
|
|
||||||
System.arraycopy(out3, 0, result, 16, 8);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String generateType3Msg(String challenge) {
|
|
||||||
try {
|
|
||||||
/* First decode the type2 message to get the server nonce */
|
|
||||||
/* nonce is located at type2[24] for 8 bytes */
|
|
||||||
|
|
||||||
byte[] type2 = null;
|
|
||||||
try {
|
|
||||||
type2 = BASE64DecoderStream.decode(challenge.getBytes("us-ascii"));
|
|
||||||
} catch (UnsupportedEncodingException ex) {
|
|
||||||
// should never happen
|
|
||||||
assert false;
|
|
||||||
}
|
|
||||||
byte[] nonce = new byte[8];
|
|
||||||
System.arraycopy(type2, 24, nonce, 0, 8);
|
|
||||||
|
|
||||||
int ulen = username.length()*2;
|
|
||||||
type3[36] = type3[38] = (byte) (ulen % 256);
|
|
||||||
type3[37] = type3[39] = (byte) (ulen / 256);
|
|
||||||
int dlen = ntdomain.length()*2;
|
|
||||||
type3[28] = type3[30] = (byte) (dlen % 256);
|
|
||||||
type3[29] = type3[31] = (byte) (dlen / 256);
|
|
||||||
int hlen = hostname.length()*2;
|
|
||||||
type3[44] = type3[46] = (byte) (hlen % 256);
|
|
||||||
type3[45] = type3[47] = (byte) (hlen / 256);
|
|
||||||
|
|
||||||
int l = 64;
|
|
||||||
copybytes(type3, l, ntdomain, "UnicodeLittleUnmarked");
|
|
||||||
type3[32] = (byte) (l % 256);
|
|
||||||
type3[33] = (byte) (l / 256);
|
|
||||||
l += dlen;
|
|
||||||
copybytes(type3, l, username, "UnicodeLittleUnmarked");
|
|
||||||
type3[40] = (byte) (l % 256);
|
|
||||||
type3[41] = (byte) (l / 256);
|
|
||||||
l += ulen;
|
|
||||||
copybytes(type3, l, hostname, "UnicodeLittleUnmarked");
|
|
||||||
type3[48] = (byte) (l % 256);
|
|
||||||
type3[49] = (byte) (l / 256);
|
|
||||||
l += hlen;
|
|
||||||
|
|
||||||
byte[] lmhash = calcLMHash();
|
|
||||||
byte[] lmresponse = calcResponse(lmhash, nonce);
|
|
||||||
byte[] nthash = calcNTHash();
|
|
||||||
byte[] ntresponse = calcResponse(nthash, nonce);
|
|
||||||
System.arraycopy(lmresponse, 0, type3, l, 24);
|
|
||||||
type3[16] = (byte) (l % 256);
|
|
||||||
type3[17] = (byte) (l / 256);
|
|
||||||
l += 24;
|
|
||||||
System.arraycopy(ntresponse, 0, type3, l, 24);
|
|
||||||
type3[24] = (byte) (l % 256);
|
|
||||||
type3[25] = (byte) (l / 256);
|
|
||||||
l += 24;
|
|
||||||
type3[56] = (byte) (l % 256);
|
|
||||||
type3[57] = (byte) (l / 256);
|
|
||||||
|
|
||||||
byte[] msg = new byte[l];
|
|
||||||
System.arraycopy(type3, 0, msg, 0, l);
|
|
||||||
if (logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("type 3 message: " + toHex(msg));
|
|
||||||
|
|
||||||
String result = null;
|
|
||||||
try {
|
|
||||||
result = new String(BASE64EncoderStream.encode(msg), "iso-8859-1");
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
assert false;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
|
|
||||||
} catch (GeneralSecurityException ex) {
|
|
||||||
// should never happen
|
|
||||||
logger.log(Level.FINE, "GeneralSecurityException", ex);
|
|
||||||
return ""; // will fail later
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static char[] hex =
|
|
||||||
{ '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
|
|
||||||
|
|
||||||
private static String toHex(byte[] b) {
|
|
||||||
StringBuffer sb = new StringBuffer(b.length * 3);
|
|
||||||
for (int i = 0; i < b.length; i++)
|
|
||||||
sb.append(hex[(b[i]>>4)&0xF]).append(hex[b[i]&0xF]).append(' ');
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,123 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.handlers;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.datatransfer.DataFlavor;
|
|
||||||
import javax.activation.*;
|
|
||||||
import javax.mail.internet.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DataContentHandler for image/gif.
|
|
||||||
*/
|
|
||||||
public class image_gif implements DataContentHandler {
|
|
||||||
private static ActivationDataFlavor myDF = new ActivationDataFlavor(
|
|
||||||
java.awt.Image.class,
|
|
||||||
"image/gif",
|
|
||||||
"GIF Image");
|
|
||||||
|
|
||||||
protected ActivationDataFlavor getDF() {
|
|
||||||
return myDF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the DataFlavors for this <code>DataContentHandler</code>.
|
|
||||||
*
|
|
||||||
* @return The DataFlavors
|
|
||||||
*/
|
|
||||||
public DataFlavor[] getTransferDataFlavors() { // throws Exception;
|
|
||||||
return new DataFlavor[] { getDF() };
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the Transfer Data of type DataFlavor from InputStream.
|
|
||||||
*
|
|
||||||
* @param df The DataFlavor
|
|
||||||
* @param ds The DataSource corresponding to the data
|
|
||||||
* @return String object
|
|
||||||
*/
|
|
||||||
public Object getTransferData(DataFlavor df, DataSource ds)
|
|
||||||
throws IOException {
|
|
||||||
// use myDF.equals to be sure to get ActivationDataFlavor.equals,
|
|
||||||
// which properly ignores Content-Type parameters in comparison
|
|
||||||
if (getDF().equals(df))
|
|
||||||
return getContent(ds);
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getContent(DataSource ds) throws IOException {
|
|
||||||
InputStream is = ds.getInputStream();
|
|
||||||
int pos = 0;
|
|
||||||
int count;
|
|
||||||
byte buf[] = new byte[1024];
|
|
||||||
|
|
||||||
while ((count = is.read(buf, pos, buf.length - pos)) != -1) {
|
|
||||||
pos += count;
|
|
||||||
if (pos >= buf.length) {
|
|
||||||
int size = buf.length;
|
|
||||||
if (size < 256*1024)
|
|
||||||
size += size;
|
|
||||||
else
|
|
||||||
size += 256*1024;
|
|
||||||
byte tbuf[] = new byte[size];
|
|
||||||
System.arraycopy(buf, 0, tbuf, 0, pos);
|
|
||||||
buf = tbuf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Toolkit tk = Toolkit.getDefaultToolkit();
|
|
||||||
return tk.createImage(buf, 0, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write the object to the output stream, using the specified MIME type.
|
|
||||||
*/
|
|
||||||
public void writeTo(Object obj, String type, OutputStream os)
|
|
||||||
throws IOException {
|
|
||||||
if (!(obj instanceof Image))
|
|
||||||
throw new IOException("\"" + getDF().getMimeType() +
|
|
||||||
"\" DataContentHandler requires Image object, " +
|
|
||||||
"was given object of type " + obj.getClass().toString());
|
|
||||||
|
|
||||||
throw new IOException(getDF().getMimeType() + " encoding not supported");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.handlers;
|
|
||||||
|
|
||||||
import java.awt.datatransfer.DataFlavor;
|
|
||||||
import javax.activation.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DataContentHandler for image/jpeg.
|
|
||||||
*/
|
|
||||||
public class image_jpeg extends image_gif {
|
|
||||||
private static ActivationDataFlavor myDF = new ActivationDataFlavor(
|
|
||||||
java.awt.Image.class,
|
|
||||||
"image/jpeg",
|
|
||||||
"JPEG Image");
|
|
||||||
|
|
||||||
protected ActivationDataFlavor getDF() {
|
|
||||||
return myDF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,130 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.handlers;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.awt.datatransfer.DataFlavor;
|
|
||||||
import javax.activation.*;
|
|
||||||
import javax.mail.*;
|
|
||||||
import javax.mail.internet.*;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Christopher Cotton
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
public class message_rfc822 implements DataContentHandler {
|
|
||||||
|
|
||||||
ActivationDataFlavor ourDataFlavor = new ActivationDataFlavor(
|
|
||||||
javax.mail.Message.class,
|
|
||||||
"message/rfc822",
|
|
||||||
"Message");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return the DataFlavors for this <code>DataContentHandler</code>
|
|
||||||
* @return The DataFlavors.
|
|
||||||
*/
|
|
||||||
public DataFlavor[] getTransferDataFlavors() {
|
|
||||||
return new DataFlavor[] { ourDataFlavor };
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return the Transfer Data of type DataFlavor from InputStream
|
|
||||||
* @param df The DataFlavor.
|
|
||||||
* @param ds The DataSource corresponding to the data
|
|
||||||
* @return a Message object
|
|
||||||
*/
|
|
||||||
public Object getTransferData(DataFlavor df, DataSource ds)
|
|
||||||
throws IOException {
|
|
||||||
// make sure we can handle this DataFlavor
|
|
||||||
if (ourDataFlavor.equals(df))
|
|
||||||
return getContent(ds);
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the content.
|
|
||||||
*/
|
|
||||||
public Object getContent(DataSource ds) throws IOException {
|
|
||||||
// create a new MimeMessage
|
|
||||||
try {
|
|
||||||
Session session;
|
|
||||||
if (ds instanceof MessageAware) {
|
|
||||||
MessageContext mc = ((MessageAware)ds).getMessageContext();
|
|
||||||
session = mc.getSession();
|
|
||||||
} else {
|
|
||||||
// Hopefully a rare case. Also hopefully the application
|
|
||||||
// has created a default Session that can just be returned
|
|
||||||
// here. If not, the one we create here is better than
|
|
||||||
// nothing, but overall not a really good answer.
|
|
||||||
session = Session.getDefaultInstance(new Properties(), null);
|
|
||||||
}
|
|
||||||
return new MimeMessage(session, ds.getInputStream());
|
|
||||||
} catch (MessagingException me) {
|
|
||||||
throw new IOException("Exception creating MimeMessage in " +
|
|
||||||
"message/rfc822 DataContentHandler: " + me.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* construct an object from a byte stream
|
|
||||||
* (similar semantically to previous method, we are deciding
|
|
||||||
* which one to support)
|
|
||||||
*/
|
|
||||||
public void writeTo(Object obj, String mimeType, OutputStream os)
|
|
||||||
throws IOException {
|
|
||||||
// if the object is a message, we know how to write that out
|
|
||||||
if (obj instanceof Message) {
|
|
||||||
Message m = (Message)obj;
|
|
||||||
try {
|
|
||||||
m.writeTo(os);
|
|
||||||
} catch (MessagingException me) {
|
|
||||||
throw new IOException(me.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
throw new IOException("unsupported object");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,109 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.handlers;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.awt.datatransfer.DataFlavor;
|
|
||||||
import javax.activation.*;
|
|
||||||
import javax.mail.MessagingException;
|
|
||||||
import javax.mail.internet.*;
|
|
||||||
|
|
||||||
|
|
||||||
public class multipart_mixed implements DataContentHandler {
|
|
||||||
private ActivationDataFlavor myDF = new ActivationDataFlavor(
|
|
||||||
javax.mail.internet.MimeMultipart.class,
|
|
||||||
"multipart/mixed",
|
|
||||||
"Multipart");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the DataFlavors for this <code>DataContentHandler</code>.
|
|
||||||
*
|
|
||||||
* @return The DataFlavors
|
|
||||||
*/
|
|
||||||
public DataFlavor[] getTransferDataFlavors() { // throws Exception;
|
|
||||||
return new DataFlavor[] { myDF };
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the Transfer Data of type DataFlavor from InputStream.
|
|
||||||
*
|
|
||||||
* @param df The DataFlavor
|
|
||||||
* @param ds The DataSource corresponding to the data
|
|
||||||
* @return String object
|
|
||||||
*/
|
|
||||||
public Object getTransferData(DataFlavor df, DataSource ds)
|
|
||||||
throws IOException {
|
|
||||||
// use myDF.equals to be sure to get ActivationDataFlavor.equals,
|
|
||||||
// which properly ignores Content-Type parameters in comparison
|
|
||||||
if (myDF.equals(df))
|
|
||||||
return getContent(ds);
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the content.
|
|
||||||
*/
|
|
||||||
public Object getContent(DataSource ds) throws IOException {
|
|
||||||
try {
|
|
||||||
return new MimeMultipart(ds);
|
|
||||||
} catch (MessagingException e) {
|
|
||||||
IOException ioex =
|
|
||||||
new IOException("Exception while constructing MimeMultipart");
|
|
||||||
ioex.initCause(e);
|
|
||||||
throw ioex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write the object to the output stream, using the specific MIME type.
|
|
||||||
*/
|
|
||||||
public void writeTo(Object obj, String mimeType, OutputStream os)
|
|
||||||
throws IOException {
|
|
||||||
if (obj instanceof MimeMultipart) {
|
|
||||||
try {
|
|
||||||
((MimeMultipart)obj).writeTo(os);
|
|
||||||
} catch (MessagingException e) {
|
|
||||||
throw new IOException(e.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.handlers;
|
|
||||||
|
|
||||||
import javax.activation.ActivationDataFlavor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DataContentHandler for text/html.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class text_html extends text_plain {
|
|
||||||
private static ActivationDataFlavor myDF = new ActivationDataFlavor(
|
|
||||||
java.lang.String.class,
|
|
||||||
"text/html",
|
|
||||||
"HTML String");
|
|
||||||
|
|
||||||
protected ActivationDataFlavor getDF() {
|
|
||||||
return myDF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,198 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.handlers;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.awt.datatransfer.DataFlavor;
|
|
||||||
import javax.activation.*;
|
|
||||||
import javax.mail.internet.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DataContentHandler for text/plain.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class text_plain implements DataContentHandler {
|
|
||||||
private static ActivationDataFlavor myDF = new ActivationDataFlavor(
|
|
||||||
java.lang.String.class,
|
|
||||||
"text/plain",
|
|
||||||
"Text String");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An OuputStream wrapper that doesn't close the underlying stream.
|
|
||||||
*/
|
|
||||||
private static class NoCloseOutputStream extends FilterOutputStream {
|
|
||||||
public NoCloseOutputStream(OutputStream os) {
|
|
||||||
super(os);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ActivationDataFlavor getDF() {
|
|
||||||
return myDF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the DataFlavors for this <code>DataContentHandler</code>.
|
|
||||||
*
|
|
||||||
* @return The DataFlavors
|
|
||||||
*/
|
|
||||||
public DataFlavor[] getTransferDataFlavors() {
|
|
||||||
return new DataFlavor[] { getDF() };
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the Transfer Data of type DataFlavor from InputStream.
|
|
||||||
*
|
|
||||||
* @param df The DataFlavor
|
|
||||||
* @param ds The DataSource corresponding to the data
|
|
||||||
* @return String object
|
|
||||||
*/
|
|
||||||
public Object getTransferData(DataFlavor df, DataSource ds)
|
|
||||||
throws IOException {
|
|
||||||
// use myDF.equals to be sure to get ActivationDataFlavor.equals,
|
|
||||||
// which properly ignores Content-Type parameters in comparison
|
|
||||||
if (getDF().equals(df))
|
|
||||||
return getContent(ds);
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getContent(DataSource ds) throws IOException {
|
|
||||||
String enc = null;
|
|
||||||
InputStreamReader is = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
enc = getCharset(ds.getContentType());
|
|
||||||
is = new InputStreamReader(ds.getInputStream(), enc);
|
|
||||||
} catch (IllegalArgumentException iex) {
|
|
||||||
/*
|
|
||||||
* An unknown charset of the form ISO-XXX-XXX will cause
|
|
||||||
* the JDK to throw an IllegalArgumentException. The
|
|
||||||
* JDK will attempt to create a classname using this string,
|
|
||||||
* but valid classnames must not contain the character '-',
|
|
||||||
* and this results in an IllegalArgumentException, rather than
|
|
||||||
* the expected UnsupportedEncodingException. Yikes.
|
|
||||||
*/
|
|
||||||
throw new UnsupportedEncodingException(enc);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
int pos = 0;
|
|
||||||
int count;
|
|
||||||
char buf[] = new char[1024];
|
|
||||||
|
|
||||||
while ((count = is.read(buf, pos, buf.length - pos)) != -1) {
|
|
||||||
pos += count;
|
|
||||||
if (pos >= buf.length) {
|
|
||||||
int size = buf.length;
|
|
||||||
if (size < 256*1024)
|
|
||||||
size += size;
|
|
||||||
else
|
|
||||||
size += 256*1024;
|
|
||||||
char tbuf[] = new char[size];
|
|
||||||
System.arraycopy(buf, 0, tbuf, 0, pos);
|
|
||||||
buf = tbuf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new String(buf, 0, pos);
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
is.close();
|
|
||||||
} catch (IOException ex) { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write the object to the output stream, using the specified MIME type.
|
|
||||||
*/
|
|
||||||
public void writeTo(Object obj, String type, OutputStream os)
|
|
||||||
throws IOException {
|
|
||||||
if (!(obj instanceof String))
|
|
||||||
throw new IOException("\"" + getDF().getMimeType() +
|
|
||||||
"\" DataContentHandler requires String object, " +
|
|
||||||
"was given object of type " + obj.getClass().toString());
|
|
||||||
|
|
||||||
String enc = null;
|
|
||||||
OutputStreamWriter osw = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
enc = getCharset(type);
|
|
||||||
osw = new OutputStreamWriter(new NoCloseOutputStream(os), enc);
|
|
||||||
} catch (IllegalArgumentException iex) {
|
|
||||||
/*
|
|
||||||
* An unknown charset of the form ISO-XXX-XXX will cause
|
|
||||||
* the JDK to throw an IllegalArgumentException. The
|
|
||||||
* JDK will attempt to create a classname using this string,
|
|
||||||
* but valid classnames must not contain the character '-',
|
|
||||||
* and this results in an IllegalArgumentException, rather than
|
|
||||||
* the expected UnsupportedEncodingException. Yikes.
|
|
||||||
*/
|
|
||||||
throw new UnsupportedEncodingException(enc);
|
|
||||||
}
|
|
||||||
|
|
||||||
String s = (String)obj;
|
|
||||||
osw.write(s, 0, s.length());
|
|
||||||
/*
|
|
||||||
* Have to call osw.close() instead of osw.flush() because
|
|
||||||
* some charset converts, such as the iso-2022-jp converter,
|
|
||||||
* don't output the "shift out" sequence unless they're closed.
|
|
||||||
* The NoCloseOutputStream wrapper prevents the underlying
|
|
||||||
* stream from being closed.
|
|
||||||
*/
|
|
||||||
osw.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getCharset(String type) {
|
|
||||||
try {
|
|
||||||
ContentType ct = new ContentType(type);
|
|
||||||
String charset = ct.getParameter("charset");
|
|
||||||
if (charset == null)
|
|
||||||
// If the charset parameter is absent, use US-ASCII.
|
|
||||||
charset = "us-ascii";
|
|
||||||
return MimeUtility.javaCharset(charset);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,157 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.handlers;
|
|
||||||
|
|
||||||
import java.awt.datatransfer.DataFlavor;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
|
|
||||||
import javax.activation.ActivationDataFlavor;
|
|
||||||
import javax.activation.DataContentHandler;
|
|
||||||
import javax.activation.DataSource;
|
|
||||||
import javax.mail.internet.ContentType;
|
|
||||||
import javax.xml.transform.Source;
|
|
||||||
import javax.xml.transform.Transformer;
|
|
||||||
import javax.xml.transform.TransformerFactory;
|
|
||||||
import javax.xml.transform.stream.StreamResult;
|
|
||||||
import javax.xml.transform.stream.StreamSource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DataContentHandler for text/xml.
|
|
||||||
*
|
|
||||||
* @author Anil Vijendran
|
|
||||||
* @author Bill Shannon
|
|
||||||
*/
|
|
||||||
public class text_xml extends text_plain {
|
|
||||||
|
|
||||||
private final DataFlavor[] flavors;
|
|
||||||
|
|
||||||
public text_xml() {
|
|
||||||
flavors = new DataFlavor[] {
|
|
||||||
new ActivationDataFlavor(String.class, "text/xml", "XML String"),
|
|
||||||
new ActivationDataFlavor(String.class, "application/xml",
|
|
||||||
"XML String"),
|
|
||||||
new ActivationDataFlavor(StreamSource.class, "text/xml", "XML"),
|
|
||||||
new ActivationDataFlavor(StreamSource.class, "application/xml",
|
|
||||||
"XML")
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the DataFlavors for this <code>DataContentHandler</code>.
|
|
||||||
*
|
|
||||||
* @return the DataFlavors
|
|
||||||
*/
|
|
||||||
public DataFlavor[] getTransferDataFlavors() { // throws Exception;
|
|
||||||
return (DataFlavor[])flavors.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the Transfer Data of type DataFlavor from InputStream.
|
|
||||||
*
|
|
||||||
* @param df the DataFlavor
|
|
||||||
* @param ds the InputStream corresponding to the data
|
|
||||||
* @return the constructed Object
|
|
||||||
*/
|
|
||||||
public Object getTransferData(DataFlavor df, DataSource ds)
|
|
||||||
throws IOException {
|
|
||||||
|
|
||||||
for (int i = 0; i < flavors.length; i++) {
|
|
||||||
DataFlavor aFlavor = flavors[i];
|
|
||||||
if (aFlavor.equals(df)) {
|
|
||||||
if (aFlavor.getRepresentationClass() == String.class)
|
|
||||||
return super.getContent(ds);
|
|
||||||
else if (aFlavor.getRepresentationClass() == StreamSource.class)
|
|
||||||
return new StreamSource(ds.getInputStream());
|
|
||||||
else
|
|
||||||
return null; // XXX - should never happen
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
public void writeTo(Object obj, String mimeType, OutputStream os)
|
|
||||||
throws IOException {
|
|
||||||
if (!isXmlType(mimeType))
|
|
||||||
throw new IOException(
|
|
||||||
"Invalid content type \"" + mimeType + "\" for text/xml DCH");
|
|
||||||
if (obj instanceof String) {
|
|
||||||
super.writeTo(obj, mimeType, os);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!(obj instanceof DataSource || obj instanceof Source)) {
|
|
||||||
throw new IOException("Invalid Object type = "+obj.getClass()+
|
|
||||||
". XmlDCH can only convert DataSource or Source to XML.");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
Transformer transformer =
|
|
||||||
TransformerFactory.newInstance().newTransformer();
|
|
||||||
StreamResult result = new StreamResult(os);
|
|
||||||
if (obj instanceof DataSource) {
|
|
||||||
// Streaming transform applies only to
|
|
||||||
// javax.xml.transform.StreamSource
|
|
||||||
transformer.transform(
|
|
||||||
new StreamSource(((DataSource)obj).getInputStream()),
|
|
||||||
result);
|
|
||||||
} else {
|
|
||||||
transformer.transform((Source)obj, result);
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
|
||||||
throw new IOException(
|
|
||||||
"Unable to run the JAXP transformer on a stream "
|
|
||||||
+ ex.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isXmlType(String type) {
|
|
||||||
try {
|
|
||||||
ContentType ct = new ContentType(type);
|
|
||||||
return ct.getSubType().equals("xml") &&
|
|
||||||
(ct.getPrimaryType().equals("text") ||
|
|
||||||
ct.getPrimaryType().equals("application"));
|
|
||||||
} catch (Exception ex) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,308 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.iap;
|
|
||||||
|
|
||||||
import java.util.Vector;
|
|
||||||
import java.io.*;
|
|
||||||
import com.sun.mail.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class Argument {
|
|
||||||
protected Vector items;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
public Argument() {
|
|
||||||
items = new Vector(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* append the given Argument to this Argument. All items
|
|
||||||
* from the source argument are copied into this destination
|
|
||||||
* argument.
|
|
||||||
*/
|
|
||||||
public void append(Argument arg) {
|
|
||||||
items.ensureCapacity(items.size() + arg.items.size());
|
|
||||||
for (int i=0; i < arg.items.size(); i++)
|
|
||||||
items.addElement(arg.items.elementAt(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write out given string as an ASTRING, depending on the type
|
|
||||||
* of the characters inside the string. The string should
|
|
||||||
* contain only ASCII characters. <p>
|
|
||||||
*
|
|
||||||
* XXX: Hmm .. this should really be called writeASCII()
|
|
||||||
*
|
|
||||||
* @param s String to write out
|
|
||||||
*/
|
|
||||||
public void writeString(String s) {
|
|
||||||
items.addElement(new AString(ASCIIUtility.getBytes(s)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert the given string into bytes in the specified
|
|
||||||
* charset, and write the bytes out as an ASTRING
|
|
||||||
*/
|
|
||||||
public void writeString(String s, String charset)
|
|
||||||
throws UnsupportedEncodingException {
|
|
||||||
if (charset == null) // convenience
|
|
||||||
writeString(s);
|
|
||||||
else
|
|
||||||
items.addElement(new AString(s.getBytes(charset)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write out given byte[] as a Literal.
|
|
||||||
* @param b byte[] to write out
|
|
||||||
*/
|
|
||||||
public void writeBytes(byte[] b) {
|
|
||||||
items.addElement(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write out given ByteArrayOutputStream as a Literal.
|
|
||||||
* @param b ByteArrayOutputStream to be written out.
|
|
||||||
*/
|
|
||||||
public void writeBytes(ByteArrayOutputStream b) {
|
|
||||||
items.addElement(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write out given data as a literal.
|
|
||||||
* @param b Literal representing data to be written out.
|
|
||||||
*/
|
|
||||||
public void writeBytes(Literal b) {
|
|
||||||
items.addElement(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write out given string as an Atom. Note that an Atom can contain only
|
|
||||||
* certain US-ASCII characters. No validation is done on the characters
|
|
||||||
* in the string.
|
|
||||||
* @param s String
|
|
||||||
*/
|
|
||||||
public void writeAtom(String s) {
|
|
||||||
items.addElement(new Atom(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write out number.
|
|
||||||
* @param i number
|
|
||||||
*/
|
|
||||||
public void writeNumber(int i) {
|
|
||||||
items.addElement(new Integer(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write out number.
|
|
||||||
* @param i number
|
|
||||||
*/
|
|
||||||
public void writeNumber(long i) {
|
|
||||||
items.addElement(new Long(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write out as parenthesised list.
|
|
||||||
*/
|
|
||||||
public void writeArgument(Argument c) {
|
|
||||||
items.addElement(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Write out all the buffered items into the output stream.
|
|
||||||
*/
|
|
||||||
public void write(Protocol protocol)
|
|
||||||
throws IOException, ProtocolException {
|
|
||||||
int size = items != null ? items.size() : 0;
|
|
||||||
DataOutputStream os = (DataOutputStream)protocol.getOutputStream();
|
|
||||||
|
|
||||||
for (int i=0; i < size; i++) {
|
|
||||||
if (i > 0) // write delimiter if not the first item
|
|
||||||
os.write(' ');
|
|
||||||
|
|
||||||
Object o = items.elementAt(i);
|
|
||||||
if (o instanceof Atom) {
|
|
||||||
os.writeBytes(((Atom)o).string);
|
|
||||||
} else if (o instanceof Number) {
|
|
||||||
os.writeBytes(((Number)o).toString());
|
|
||||||
} else if (o instanceof AString) {
|
|
||||||
astring(((AString)o).bytes, protocol);
|
|
||||||
} else if (o instanceof byte[]) {
|
|
||||||
literal((byte[])o, protocol);
|
|
||||||
} else if (o instanceof ByteArrayOutputStream) {
|
|
||||||
literal((ByteArrayOutputStream)o, protocol);
|
|
||||||
} else if (o instanceof Literal) {
|
|
||||||
literal((Literal)o, protocol);
|
|
||||||
} else if (o instanceof Argument) {
|
|
||||||
os.write('('); // open parans
|
|
||||||
((Argument)o).write(protocol);
|
|
||||||
os.write(')'); // close parans
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write out given String as either an Atom, QuotedString or Literal
|
|
||||||
*/
|
|
||||||
private void astring(byte[] bytes, Protocol protocol)
|
|
||||||
throws IOException, ProtocolException {
|
|
||||||
DataOutputStream os = (DataOutputStream)protocol.getOutputStream();
|
|
||||||
int len = bytes.length;
|
|
||||||
|
|
||||||
// If length is greater than 1024 bytes, send as literal
|
|
||||||
if (len > 1024) {
|
|
||||||
literal(bytes, protocol);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if 0 length, send as quoted-string
|
|
||||||
boolean quote = len == 0 ? true: false;
|
|
||||||
boolean escape = false;
|
|
||||||
|
|
||||||
byte b;
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
b = bytes[i];
|
|
||||||
if (b == '\0' || b == '\r' || b == '\n' || ((b & 0xff) > 0177)) {
|
|
||||||
// NUL, CR or LF means the bytes need to be sent as literals
|
|
||||||
literal(bytes, protocol);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (b == '*' || b == '%' || b == '(' || b == ')' || b == '{' ||
|
|
||||||
b == '"' || b == '\\' || ((b & 0xff) <= ' ')) {
|
|
||||||
quote = true;
|
|
||||||
if (b == '"' || b == '\\') // need to escape these characters
|
|
||||||
escape = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (quote) // start quote
|
|
||||||
os.write('"');
|
|
||||||
|
|
||||||
if (escape) {
|
|
||||||
// already quoted
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
b = bytes[i];
|
|
||||||
if (b == '"' || b == '\\')
|
|
||||||
os.write('\\');
|
|
||||||
os.write(b);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
os.write(bytes);
|
|
||||||
|
|
||||||
|
|
||||||
if (quote) // end quote
|
|
||||||
os.write('"');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write out given byte[] as a literal
|
|
||||||
*/
|
|
||||||
private void literal(byte[] b, Protocol protocol)
|
|
||||||
throws IOException, ProtocolException {
|
|
||||||
startLiteral(protocol, b.length).write(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write out given ByteArrayOutputStream as a literal.
|
|
||||||
*/
|
|
||||||
private void literal(ByteArrayOutputStream b, Protocol protocol)
|
|
||||||
throws IOException, ProtocolException {
|
|
||||||
b.writeTo(startLiteral(protocol, b.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write out given Literal as a literal.
|
|
||||||
*/
|
|
||||||
private void literal(Literal b, Protocol protocol)
|
|
||||||
throws IOException, ProtocolException {
|
|
||||||
b.writeTo(startLiteral(protocol, b.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private OutputStream startLiteral(Protocol protocol, int size)
|
|
||||||
throws IOException, ProtocolException {
|
|
||||||
DataOutputStream os = (DataOutputStream)protocol.getOutputStream();
|
|
||||||
boolean nonSync = protocol.supportsNonSyncLiterals();
|
|
||||||
|
|
||||||
os.write('{');
|
|
||||||
os.writeBytes(Integer.toString(size));
|
|
||||||
if (nonSync) // server supports non-sync literals
|
|
||||||
os.writeBytes("+}\r\n");
|
|
||||||
else
|
|
||||||
os.writeBytes("}\r\n");
|
|
||||||
os.flush();
|
|
||||||
|
|
||||||
// If we are using synchronized literals, wait for the server's
|
|
||||||
// continuation signal
|
|
||||||
if (!nonSync) {
|
|
||||||
for (; ;) {
|
|
||||||
Response r = protocol.readResponse();
|
|
||||||
if (r.isContinuation())
|
|
||||||
break;
|
|
||||||
if (r.isTagged())
|
|
||||||
throw new LiteralException(r);
|
|
||||||
// XXX - throw away untagged responses;
|
|
||||||
// violates IMAP spec, hope no servers do this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Atom {
|
|
||||||
String string;
|
|
||||||
|
|
||||||
Atom(String s) {
|
|
||||||
string = s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class AString {
|
|
||||||
byte[] bytes;
|
|
||||||
|
|
||||||
AString(byte[] b) {
|
|
||||||
bytes = b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,73 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.iap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class BadCommandException extends ProtocolException {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 5769722539397237515L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs an BadCommandException with no detail message.
|
|
||||||
*/
|
|
||||||
public BadCommandException() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs an BadCommandException with the specified detail message.
|
|
||||||
* @param s the detail message
|
|
||||||
*/
|
|
||||||
public BadCommandException(String s) {
|
|
||||||
super(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs an BadCommandException with the specified Response.
|
|
||||||
* @param r the Response
|
|
||||||
*/
|
|
||||||
public BadCommandException(Response r) {
|
|
||||||
super(r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,132 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.iap;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple wrapper around a byte array, with a start position and
|
|
||||||
* count of bytes.
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class ByteArray {
|
|
||||||
private byte[] bytes; // the byte array
|
|
||||||
private int start; // start position
|
|
||||||
private int count; // count of bytes
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
public ByteArray(byte[] b, int start, int count) {
|
|
||||||
bytes = b;
|
|
||||||
this.start = start;
|
|
||||||
this.count = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor that creates a byte array of the specified size.
|
|
||||||
*
|
|
||||||
* @since JavaMail 1.4.1
|
|
||||||
*/
|
|
||||||
public ByteArray(int size) {
|
|
||||||
this(new byte[size], 0, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the internal byte array. Note that this is a live
|
|
||||||
* reference to the actual data, not a copy.
|
|
||||||
*/
|
|
||||||
public byte[] getBytes() {
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a new byte array that is a copy of the data.
|
|
||||||
*/
|
|
||||||
public byte[] getNewBytes() {
|
|
||||||
byte[] b = new byte[count];
|
|
||||||
System.arraycopy(bytes, start, b, 0, count);
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the start position
|
|
||||||
*/
|
|
||||||
public int getStart() {
|
|
||||||
return start;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the count of bytes
|
|
||||||
*/
|
|
||||||
public int getCount() {
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the count of bytes.
|
|
||||||
*
|
|
||||||
* @since JavaMail 1.4.1
|
|
||||||
*/
|
|
||||||
public void setCount(int count) {
|
|
||||||
this.count = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a ByteArrayInputStream.
|
|
||||||
*/
|
|
||||||
public ByteArrayInputStream toByteArrayInputStream() {
|
|
||||||
return new ByteArrayInputStream(bytes, start, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Grow the byte array by incr bytes.
|
|
||||||
*
|
|
||||||
* @since JavaMail 1.4.1
|
|
||||||
*/
|
|
||||||
public void grow(int incr) {
|
|
||||||
byte[] nbuf = new byte[bytes.length + incr];
|
|
||||||
System.arraycopy(bytes, 0, nbuf, 0, bytes.length);
|
|
||||||
bytes = nbuf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,73 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.iap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class CommandFailedException extends ProtocolException {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 793932807880443631L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs an CommandFailedException with no detail message.
|
|
||||||
*/
|
|
||||||
public CommandFailedException() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs an CommandFailedException with the specified detail message.
|
|
||||||
* @param s the detail message
|
|
||||||
*/
|
|
||||||
public CommandFailedException(String s) {
|
|
||||||
super(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs an CommandFailedException with the specified Response.
|
|
||||||
* @param r the Response.
|
|
||||||
*/
|
|
||||||
public CommandFailedException(Response r) {
|
|
||||||
super(r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.iap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class ConnectionException extends ProtocolException {
|
|
||||||
private transient Protocol p;
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 5749739604257464727L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs an ConnectionException with no detail message.
|
|
||||||
*/
|
|
||||||
public ConnectionException() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs an ConnectionException with the specified detail message.
|
|
||||||
* @param s the detail message
|
|
||||||
*/
|
|
||||||
public ConnectionException(String s) {
|
|
||||||
super(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs an ConnectionException with the specified Response.
|
|
||||||
* @param r the Response
|
|
||||||
*/
|
|
||||||
public ConnectionException(Protocol p, Response r) {
|
|
||||||
super(r);
|
|
||||||
this.p = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Protocol getProtocol() {
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.iap;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An interface for objects that provide data dynamically for use in
|
|
||||||
* a literal protocol element.
|
|
||||||
*
|
|
||||||
* @author Bill Shannon
|
|
||||||
*/
|
|
||||||
|
|
||||||
public interface Literal {
|
|
||||||
/**
|
|
||||||
* Return the size of the data.
|
|
||||||
*/
|
|
||||||
public int size();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write the data to the OutputStream.
|
|
||||||
*/
|
|
||||||
public void writeTo(OutputStream os) throws IOException;
|
|
||||||
}
|
|
||||||
@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.iap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Bill Shannon
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class LiteralException extends ProtocolException {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = -6919179828339609913L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a LiteralException with the specified Response object.
|
|
||||||
*/
|
|
||||||
public LiteralException(Response r) {
|
|
||||||
super(r.toString());
|
|
||||||
response = r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,73 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.iap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class ParsingException extends ProtocolException {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 7756119840142724839L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs an ParsingException with no detail message.
|
|
||||||
*/
|
|
||||||
public ParsingException() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs an ParsingException with the specified detail message.
|
|
||||||
* @param s the detail message
|
|
||||||
*/
|
|
||||||
public ParsingException(String s) {
|
|
||||||
super(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs an ParsingException with the specified Response.
|
|
||||||
* @param r the Response
|
|
||||||
*/
|
|
||||||
public ParsingException(Response r) {
|
|
||||||
super(r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,496 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.iap;
|
|
||||||
|
|
||||||
import java.util.Vector;
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.io.*;
|
|
||||||
import java.net.*;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import javax.net.ssl.SSLSocket;
|
|
||||||
import com.sun.mail.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* General protocol handling code for IMAP-like protocols. <p>
|
|
||||||
*
|
|
||||||
* The Protocol object is multithread safe.
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
* @author Max Spivak
|
|
||||||
* @author Bill Shannon
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class Protocol {
|
|
||||||
protected String host;
|
|
||||||
private Socket socket;
|
|
||||||
// in case we turn on TLS, we'll need these later
|
|
||||||
protected boolean quote;
|
|
||||||
protected MailLogger logger;
|
|
||||||
protected MailLogger traceLogger;
|
|
||||||
protected Properties props;
|
|
||||||
protected String prefix;
|
|
||||||
|
|
||||||
private boolean connected = false; // did constructor succeed?
|
|
||||||
private TraceInputStream traceInput; // the Tracer
|
|
||||||
private volatile ResponseInputStream input;
|
|
||||||
|
|
||||||
private TraceOutputStream traceOutput; // the Tracer
|
|
||||||
private volatile DataOutputStream output;
|
|
||||||
|
|
||||||
private int tagCounter = 0;
|
|
||||||
|
|
||||||
private String localHostName;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* handlers is a Vector, initialized here,
|
|
||||||
* because we depend on it always existing and depend
|
|
||||||
* on the synchronization that Vector provides.
|
|
||||||
*/
|
|
||||||
private final Vector handlers = new Vector(); // response handlers
|
|
||||||
|
|
||||||
private volatile long timestamp;
|
|
||||||
|
|
||||||
private static final byte[] CRLF = { (byte)'\r', (byte)'\n'};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor. <p>
|
|
||||||
*
|
|
||||||
* Opens a connection to the given host at given port.
|
|
||||||
*
|
|
||||||
* @param host host to connect to
|
|
||||||
* @param port portnumber to connect to
|
|
||||||
* @param props Properties object used by this protocol
|
|
||||||
* @param prefix Prefix to prepend to property keys
|
|
||||||
* @param isSSL use SSL?
|
|
||||||
* @param logger log messages here
|
|
||||||
*/
|
|
||||||
public Protocol(String host, int port,
|
|
||||||
Properties props, String prefix,
|
|
||||||
boolean isSSL, MailLogger logger)
|
|
||||||
throws IOException, ProtocolException {
|
|
||||||
try {
|
|
||||||
this.host = host;
|
|
||||||
this.props = props;
|
|
||||||
this.prefix = prefix;
|
|
||||||
this.logger = logger;
|
|
||||||
traceLogger = logger.getSubLogger("protocol", null);
|
|
||||||
|
|
||||||
socket = SocketFetcher.getSocket(host, port, props, prefix, isSSL);
|
|
||||||
quote = PropUtil.getBooleanProperty(props,
|
|
||||||
"mail.debug.quote", false);
|
|
||||||
|
|
||||||
initStreams();
|
|
||||||
|
|
||||||
// Read server greeting
|
|
||||||
processGreeting(readResponse());
|
|
||||||
|
|
||||||
timestamp = System.currentTimeMillis();
|
|
||||||
|
|
||||||
connected = true; // must be last statement in constructor
|
|
||||||
} finally {
|
|
||||||
/*
|
|
||||||
* If we get here because an exception was thrown, we need
|
|
||||||
* to disconnect to avoid leaving a connected socket that
|
|
||||||
* no one will be able to use because this object was never
|
|
||||||
* completely constructed.
|
|
||||||
*/
|
|
||||||
if (!connected)
|
|
||||||
disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initStreams() throws IOException {
|
|
||||||
traceInput = new TraceInputStream(socket.getInputStream(), traceLogger);
|
|
||||||
traceInput.setQuote(quote);
|
|
||||||
input = new ResponseInputStream(traceInput);
|
|
||||||
|
|
||||||
traceOutput =
|
|
||||||
new TraceOutputStream(socket.getOutputStream(), traceLogger);
|
|
||||||
traceOutput.setQuote(quote);
|
|
||||||
output = new DataOutputStream(new BufferedOutputStream(traceOutput));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for debugging.
|
|
||||||
*/
|
|
||||||
public Protocol(InputStream in, PrintStream out, boolean debug)
|
|
||||||
throws IOException {
|
|
||||||
this.host = "localhost";
|
|
||||||
this.quote = false;
|
|
||||||
logger = new MailLogger(this.getClass(), "DEBUG", debug, out);
|
|
||||||
traceLogger = logger.getSubLogger("protocol", null);
|
|
||||||
|
|
||||||
// XXX - inlined initStreams, won't allow later startTLS
|
|
||||||
traceInput = new TraceInputStream(in, traceLogger);
|
|
||||||
traceInput.setQuote(quote);
|
|
||||||
input = new ResponseInputStream(traceInput);
|
|
||||||
|
|
||||||
traceOutput = new TraceOutputStream(out, traceLogger);
|
|
||||||
traceOutput.setQuote(quote);
|
|
||||||
output = new DataOutputStream(new BufferedOutputStream(traceOutput));
|
|
||||||
|
|
||||||
timestamp = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the timestamp.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public long getTimestamp() {
|
|
||||||
return timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a response handler.
|
|
||||||
*/
|
|
||||||
public void addResponseHandler(ResponseHandler h) {
|
|
||||||
handlers.addElement(h);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removed the specified response handler.
|
|
||||||
*/
|
|
||||||
public void removeResponseHandler(ResponseHandler h) {
|
|
||||||
handlers.removeElement(h);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify response handlers
|
|
||||||
*/
|
|
||||||
public void notifyResponseHandlers(Response[] responses) {
|
|
||||||
if (handlers.size() == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (int i = 0; i < responses.length; i++) { // go thru responses
|
|
||||||
Response r = responses[i];
|
|
||||||
|
|
||||||
// skip responses that have already been handled
|
|
||||||
if (r == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Need to copy handlers list because handlers can be removed
|
|
||||||
// when handling a response.
|
|
||||||
Object[] h = handlers.toArray();
|
|
||||||
|
|
||||||
// dispatch 'em
|
|
||||||
for (int j = 0; j < h.length; j++) {
|
|
||||||
if (h[j] != null)
|
|
||||||
((ResponseHandler)h[j]).handleResponse(r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void processGreeting(Response r) throws ProtocolException {
|
|
||||||
if (r.isBYE())
|
|
||||||
throw new ConnectionException(this, r);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the Protocol's InputStream.
|
|
||||||
*/
|
|
||||||
protected ResponseInputStream getInputStream() {
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the Protocol's OutputStream
|
|
||||||
*/
|
|
||||||
protected OutputStream getOutputStream() {
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether this Protocol supports non-synchronizing literals
|
|
||||||
* Default is false. Subclasses should override this if required
|
|
||||||
*/
|
|
||||||
protected synchronized boolean supportsNonSyncLiterals() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Response readResponse()
|
|
||||||
throws IOException, ProtocolException {
|
|
||||||
return new Response(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a buffer to be used to read a response.
|
|
||||||
* The default implementation returns null, which causes
|
|
||||||
* a new buffer to be allocated for every response.
|
|
||||||
*
|
|
||||||
* @since JavaMail 1.4.1
|
|
||||||
*/
|
|
||||||
protected ByteArray getResponseBuffer() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String writeCommand(String command, Argument args)
|
|
||||||
throws IOException, ProtocolException {
|
|
||||||
// assert Thread.holdsLock(this);
|
|
||||||
// can't assert because it's called from constructor
|
|
||||||
String tag = "A" + Integer.toString(tagCounter++, 10); // unique tag
|
|
||||||
|
|
||||||
output.writeBytes(tag + " " + command);
|
|
||||||
|
|
||||||
if (args != null) {
|
|
||||||
output.write(' ');
|
|
||||||
args.write(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
output.write(CRLF);
|
|
||||||
output.flush();
|
|
||||||
return tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a command to the server. Collect all responses until either
|
|
||||||
* the corresponding command completion response or a BYE response
|
|
||||||
* (indicating server failure). Return all the collected responses.
|
|
||||||
*
|
|
||||||
* @param command the command
|
|
||||||
* @param args the arguments
|
|
||||||
* @return array of Response objects returned by the server
|
|
||||||
*/
|
|
||||||
public synchronized Response[] command(String command, Argument args) {
|
|
||||||
commandStart(command);
|
|
||||||
Vector v = new Vector();
|
|
||||||
boolean done = false;
|
|
||||||
String tag = null;
|
|
||||||
Response r = null;
|
|
||||||
|
|
||||||
// write the command
|
|
||||||
try {
|
|
||||||
tag = writeCommand(command, args);
|
|
||||||
} catch (LiteralException lex) {
|
|
||||||
v.addElement(lex.getResponse());
|
|
||||||
done = true;
|
|
||||||
} catch (Exception ex) {
|
|
||||||
// Convert this into a BYE response
|
|
||||||
v.addElement(Response.byeResponse(ex));
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Response byeResp = null;
|
|
||||||
while (!done) {
|
|
||||||
try {
|
|
||||||
r = readResponse();
|
|
||||||
} catch (IOException ioex) {
|
|
||||||
if (byeResp != null) // connection closed after BYE was sent
|
|
||||||
break;
|
|
||||||
// convert this into a BYE response
|
|
||||||
r = Response.byeResponse(ioex);
|
|
||||||
} catch (ProtocolException pex) {
|
|
||||||
continue; // skip this response
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r.isBYE()) {
|
|
||||||
byeResp = r;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
v.addElement(r);
|
|
||||||
|
|
||||||
// If this is a matching command completion response, we are done
|
|
||||||
if (r.isTagged() && r.getTag().equals(tag))
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (byeResp != null)
|
|
||||||
v.addElement(byeResp); // must be last
|
|
||||||
Response[] responses = new Response[v.size()];
|
|
||||||
v.copyInto(responses);
|
|
||||||
timestamp = System.currentTimeMillis();
|
|
||||||
commandEnd();
|
|
||||||
return responses;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience routine to handle OK, NO, BAD and BYE responses.
|
|
||||||
*/
|
|
||||||
public void handleResult(Response response) throws ProtocolException {
|
|
||||||
if (response.isOK())
|
|
||||||
return;
|
|
||||||
else if (response.isNO())
|
|
||||||
throw new CommandFailedException(response);
|
|
||||||
else if (response.isBAD())
|
|
||||||
throw new BadCommandException(response);
|
|
||||||
else if (response.isBYE()) {
|
|
||||||
disconnect();
|
|
||||||
throw new ConnectionException(this, response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience routine to handle simple IAP commands
|
|
||||||
* that do not have responses specific to that command.
|
|
||||||
*/
|
|
||||||
public void simpleCommand(String cmd, Argument args)
|
|
||||||
throws ProtocolException {
|
|
||||||
// Issue command
|
|
||||||
Response[] r = command(cmd, args);
|
|
||||||
|
|
||||||
// dispatch untagged responses
|
|
||||||
notifyResponseHandlers(r);
|
|
||||||
|
|
||||||
// Handle result of this command
|
|
||||||
handleResult(r[r.length-1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start TLS on the current connection.
|
|
||||||
* <code>cmd</code> is the command to issue to start TLS negotiation.
|
|
||||||
* If the command succeeds, we begin TLS negotiation.
|
|
||||||
* If the socket is already an SSLSocket this is a nop and the command
|
|
||||||
* is not issued.
|
|
||||||
*/
|
|
||||||
public synchronized void startTLS(String cmd)
|
|
||||||
throws IOException, ProtocolException {
|
|
||||||
if (socket instanceof SSLSocket)
|
|
||||||
return; // nothing to do
|
|
||||||
simpleCommand(cmd, null);
|
|
||||||
socket = SocketFetcher.startTLS(socket, host, props, prefix);
|
|
||||||
initStreams();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this connection using an SSL socket?
|
|
||||||
*
|
|
||||||
* @return true if using SSL
|
|
||||||
* @since JavaMail 1.4.6
|
|
||||||
*/
|
|
||||||
public boolean isSSL() {
|
|
||||||
return socket instanceof SSLSocket;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disconnect.
|
|
||||||
*/
|
|
||||||
protected synchronized void disconnect() {
|
|
||||||
if (socket != null) {
|
|
||||||
try {
|
|
||||||
socket.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
// ignore it
|
|
||||||
}
|
|
||||||
socket = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the name of the local host.
|
|
||||||
* The property <prefix>.localhost overrides <prefix>.localaddress,
|
|
||||||
* which overrides what InetAddress would tell us.
|
|
||||||
*/
|
|
||||||
protected synchronized String getLocalHost() {
|
|
||||||
// get our hostname and cache it for future use
|
|
||||||
if (localHostName == null || localHostName.length() <= 0)
|
|
||||||
localHostName =
|
|
||||||
props.getProperty(prefix + ".localhost");
|
|
||||||
if (localHostName == null || localHostName.length() <= 0)
|
|
||||||
localHostName =
|
|
||||||
props.getProperty(prefix + ".localaddress");
|
|
||||||
try {
|
|
||||||
if (localHostName == null || localHostName.length() <= 0) {
|
|
||||||
InetAddress localHost = InetAddress.getLocalHost();
|
|
||||||
localHostName = localHost.getCanonicalHostName();
|
|
||||||
// if we can't get our name, use local address literal
|
|
||||||
if (localHostName == null)
|
|
||||||
// XXX - not correct for IPv6
|
|
||||||
localHostName = "[" + localHost.getHostAddress() + "]";
|
|
||||||
}
|
|
||||||
} catch (UnknownHostException uhex) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// last chance, try to get our address from our socket
|
|
||||||
if (localHostName == null || localHostName.length() <= 0) {
|
|
||||||
if (socket != null && socket.isBound()) {
|
|
||||||
InetAddress localHost = socket.getLocalAddress();
|
|
||||||
localHostName = localHost.getCanonicalHostName();
|
|
||||||
// if we can't get our name, use local address literal
|
|
||||||
if (localHostName == null)
|
|
||||||
// XXX - not correct for IPv6
|
|
||||||
localHostName = "[" + localHost.getHostAddress() + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return localHostName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is protocol tracing enabled?
|
|
||||||
*/
|
|
||||||
protected boolean isTracing() {
|
|
||||||
return traceLogger.isLoggable(Level.FINEST);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Temporarily turn off protocol tracing, e.g., to prevent
|
|
||||||
* tracing the authentication sequence, including the password.
|
|
||||||
*/
|
|
||||||
protected void suspendTracing() {
|
|
||||||
if (traceLogger.isLoggable(Level.FINEST)) {
|
|
||||||
traceInput.setTrace(false);
|
|
||||||
traceOutput.setTrace(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resume protocol tracing, if it was enabled to begin with.
|
|
||||||
*/
|
|
||||||
protected void resumeTracing() {
|
|
||||||
if (traceLogger.isLoggable(Level.FINEST)) {
|
|
||||||
traceInput.setTrace(true);
|
|
||||||
traceOutput.setTrace(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finalizer.
|
|
||||||
*/
|
|
||||||
protected void finalize() throws Throwable {
|
|
||||||
super.finalize();
|
|
||||||
disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Probe points for GlassFish monitoring.
|
|
||||||
*/
|
|
||||||
private void commandStart(String command) { }
|
|
||||||
private void commandEnd() { }
|
|
||||||
}
|
|
||||||
@ -1,91 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.iap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class ProtocolException extends Exception {
|
|
||||||
protected transient Response response = null;
|
|
||||||
|
|
||||||
private static final long serialVersionUID = -4360500807971797439L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a ProtocolException with no detail message.
|
|
||||||
*/
|
|
||||||
public ProtocolException() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a ProtocolException with the specified detail message.
|
|
||||||
* @param message the detail message
|
|
||||||
*/
|
|
||||||
public ProtocolException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a ProtocolException with the specified detail message
|
|
||||||
* and cause.
|
|
||||||
* @param message the detail message
|
|
||||||
* @param cause the cause
|
|
||||||
*/
|
|
||||||
public ProtocolException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a ProtocolException with the specified Response object.
|
|
||||||
*/
|
|
||||||
public ProtocolException(Response r) {
|
|
||||||
super(r.toString());
|
|
||||||
response = r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the offending Response object.
|
|
||||||
*/
|
|
||||||
public Response getResponse() {
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,530 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2013 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.iap;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.*;
|
|
||||||
import com.sun.mail.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class represents a response obtained from the input stream
|
|
||||||
* of an IMAP server.
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class Response {
|
|
||||||
protected int index; // internal index (updated during the parse)
|
|
||||||
protected int pindex; // index after parse, for reset
|
|
||||||
protected int size; // number of valid bytes in our buffer
|
|
||||||
protected byte[] buffer = null;
|
|
||||||
protected int type = 0;
|
|
||||||
protected String tag = null;
|
|
||||||
|
|
||||||
private static final int increment = 100;
|
|
||||||
|
|
||||||
// The first and second bits indicate whether this response
|
|
||||||
// is a Continuation, Tagged or Untagged
|
|
||||||
public final static int TAG_MASK = 0x03;
|
|
||||||
public final static int CONTINUATION = 0x01;
|
|
||||||
public final static int TAGGED = 0x02;
|
|
||||||
public final static int UNTAGGED = 0x03;
|
|
||||||
|
|
||||||
// The third, fourth and fifth bits indicate whether this response
|
|
||||||
// is an OK, NO, BAD or BYE response
|
|
||||||
public final static int TYPE_MASK = 0x1C;
|
|
||||||
public final static int OK = 0x04;
|
|
||||||
public final static int NO = 0x08;
|
|
||||||
public final static int BAD = 0x0C;
|
|
||||||
public final static int BYE = 0x10;
|
|
||||||
|
|
||||||
// The sixth bit indicates whether a BYE response is synthetic or real
|
|
||||||
public final static int SYNTHETIC = 0x20;
|
|
||||||
|
|
||||||
public Response(String s) {
|
|
||||||
buffer = ASCIIUtility.getBytes(s);
|
|
||||||
size = buffer.length;
|
|
||||||
parse();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a new Response from the given Protocol
|
|
||||||
* @param p the Protocol object
|
|
||||||
*/
|
|
||||||
public Response(Protocol p) throws IOException, ProtocolException {
|
|
||||||
// read one response into 'buffer'
|
|
||||||
ByteArray ba = p.getResponseBuffer();
|
|
||||||
ByteArray response = p.getInputStream().readResponse(ba);
|
|
||||||
buffer = response.getBytes();
|
|
||||||
size = response.getCount() - 2; // Skip the terminating CRLF
|
|
||||||
|
|
||||||
parse();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy constructor.
|
|
||||||
*/
|
|
||||||
public Response(Response r) {
|
|
||||||
index = r.index;
|
|
||||||
size = r.size;
|
|
||||||
buffer = r.buffer;
|
|
||||||
type = r.type;
|
|
||||||
tag = r.tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a Response object that looks like a BYE protocol response.
|
|
||||||
* Include the details of the exception in the response string.
|
|
||||||
*/
|
|
||||||
public static Response byeResponse(Exception ex) {
|
|
||||||
String err = "* BYE JavaMail Exception: " + ex.toString();
|
|
||||||
err = err.replace('\r', ' ').replace('\n', ' ');
|
|
||||||
Response r = new Response(err);
|
|
||||||
r.type |= SYNTHETIC;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parse() {
|
|
||||||
index = 0; // position internal index at start
|
|
||||||
|
|
||||||
if (size == 0) // empty line
|
|
||||||
return;
|
|
||||||
if (buffer[index] == '+') { // Continuation statement
|
|
||||||
type |= CONTINUATION;
|
|
||||||
index += 1; // Position beyond the '+'
|
|
||||||
return; // return
|
|
||||||
} else if (buffer[index] == '*') { // Untagged statement
|
|
||||||
type |= UNTAGGED;
|
|
||||||
index += 1; // Position beyond the '*'
|
|
||||||
} else { // Tagged statement
|
|
||||||
type |= TAGGED;
|
|
||||||
tag = readAtom(); // read the TAG, index positioned beyond tag
|
|
||||||
if (tag == null)
|
|
||||||
tag = ""; // avoid possible NPE
|
|
||||||
}
|
|
||||||
|
|
||||||
int mark = index; // mark
|
|
||||||
String s = readAtom(); // updates index
|
|
||||||
if (s == null)
|
|
||||||
s = ""; // avoid possible NPE
|
|
||||||
if (s.equalsIgnoreCase("OK"))
|
|
||||||
type |= OK;
|
|
||||||
else if (s.equalsIgnoreCase("NO"))
|
|
||||||
type |= NO;
|
|
||||||
else if (s.equalsIgnoreCase("BAD"))
|
|
||||||
type |= BAD;
|
|
||||||
else if (s.equalsIgnoreCase("BYE"))
|
|
||||||
type |= BYE;
|
|
||||||
else
|
|
||||||
index = mark; // reset
|
|
||||||
|
|
||||||
pindex = index;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void skipSpaces() {
|
|
||||||
while (index < size && buffer[index] == ' ')
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Skip to the next space, for use in error recovery while parsing.
|
|
||||||
*/
|
|
||||||
public void skipToken() {
|
|
||||||
while (index < size && buffer[index] != ' ')
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void skip(int count) {
|
|
||||||
index += count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte peekByte() {
|
|
||||||
if (index < size)
|
|
||||||
return buffer[index];
|
|
||||||
else
|
|
||||||
return 0; // XXX - how else to signal error?
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the next byte from this Statement.
|
|
||||||
* @return the next byte.
|
|
||||||
*/
|
|
||||||
public byte readByte() {
|
|
||||||
if (index < size)
|
|
||||||
return buffer[index++];
|
|
||||||
else
|
|
||||||
return 0; // XXX - how else to signal error?
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract an ATOM, starting at the current position. Updates
|
|
||||||
* the internal index to beyond the Atom.
|
|
||||||
* @return an Atom
|
|
||||||
*/
|
|
||||||
public String readAtom() {
|
|
||||||
return readAtom('\0');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract an ATOM, but stop at the additional delimiter
|
|
||||||
* (if not NUL). Used to parse a response code inside [].
|
|
||||||
*/
|
|
||||||
public String readAtom(char delim) {
|
|
||||||
skipSpaces();
|
|
||||||
|
|
||||||
if (index >= size) // already at end of response
|
|
||||||
return null;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* An ATOM is any CHAR delimited by :
|
|
||||||
* SPACE | CTL | '(' | ')' | '{' | '%' | '*' | '"' | '\'
|
|
||||||
*/
|
|
||||||
byte b;
|
|
||||||
int start = index;
|
|
||||||
while (index < size && ((b = buffer[index]) > ' ') &&
|
|
||||||
b != '(' && b != ')' && b != '%' && b != '*' &&
|
|
||||||
b != '"' && b != '\\' && b != 0x7f &&
|
|
||||||
(delim == '\0' || b != delim))
|
|
||||||
index++;
|
|
||||||
|
|
||||||
return ASCIIUtility.toString(buffer, start, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a string as an arbitrary sequence of characters,
|
|
||||||
* stopping at the delimiter Used to read part of a
|
|
||||||
* response code inside [].
|
|
||||||
*/
|
|
||||||
public String readString(char delim) {
|
|
||||||
skipSpaces();
|
|
||||||
|
|
||||||
if (index >= size) // already at end of response
|
|
||||||
return null;
|
|
||||||
|
|
||||||
int start = index;
|
|
||||||
while (index < size && buffer[index] != delim)
|
|
||||||
index++;
|
|
||||||
|
|
||||||
return ASCIIUtility.toString(buffer, start, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String[] readStringList() {
|
|
||||||
return readStringList(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String[] readAtomStringList() {
|
|
||||||
return readStringList(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String[] readStringList(boolean atom) {
|
|
||||||
skipSpaces();
|
|
||||||
|
|
||||||
if (buffer[index] != '(') // not what we expected
|
|
||||||
return null;
|
|
||||||
index++; // skip '('
|
|
||||||
|
|
||||||
Vector v = new Vector();
|
|
||||||
do {
|
|
||||||
v.addElement(atom ? readAtomString() : readString());
|
|
||||||
} while (buffer[index++] != ')');
|
|
||||||
|
|
||||||
int size = v.size();
|
|
||||||
if (size > 0) {
|
|
||||||
String[] s = new String[size];
|
|
||||||
v.copyInto(s);
|
|
||||||
return s;
|
|
||||||
} else // empty list
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract an integer, starting at the current position. Updates the
|
|
||||||
* internal index to beyond the number. Returns -1 if a number was
|
|
||||||
* not found.
|
|
||||||
*
|
|
||||||
* @return a number
|
|
||||||
*/
|
|
||||||
public int readNumber() {
|
|
||||||
// Skip leading spaces
|
|
||||||
skipSpaces();
|
|
||||||
|
|
||||||
int start = index;
|
|
||||||
while (index < size && Character.isDigit((char)buffer[index]))
|
|
||||||
index++;
|
|
||||||
|
|
||||||
if (index > start) {
|
|
||||||
try {
|
|
||||||
return ASCIIUtility.parseInt(buffer, start, index);
|
|
||||||
} catch (NumberFormatException nex) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract a long number, starting at the current position. Updates the
|
|
||||||
* internal index to beyond the number. Returns -1 if a long number
|
|
||||||
* was not found.
|
|
||||||
*
|
|
||||||
* @return a long
|
|
||||||
*/
|
|
||||||
public long readLong() {
|
|
||||||
// Skip leading spaces
|
|
||||||
skipSpaces();
|
|
||||||
|
|
||||||
int start = index;
|
|
||||||
while (index < size && Character.isDigit((char)buffer[index]))
|
|
||||||
index++;
|
|
||||||
|
|
||||||
if (index > start) {
|
|
||||||
try {
|
|
||||||
return ASCIIUtility.parseLong(buffer, start, index);
|
|
||||||
} catch (NumberFormatException nex) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract a NSTRING, starting at the current position. Return it as
|
|
||||||
* a String. The sequence 'NIL' is returned as null
|
|
||||||
*
|
|
||||||
* NSTRING := QuotedString | Literal | "NIL"
|
|
||||||
*
|
|
||||||
* @return a String
|
|
||||||
*/
|
|
||||||
public String readString() {
|
|
||||||
return (String)parseString(false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract a NSTRING, starting at the current position. Return it as
|
|
||||||
* a ByteArrayInputStream. The sequence 'NIL' is returned as null
|
|
||||||
*
|
|
||||||
* NSTRING := QuotedString | Literal | "NIL"
|
|
||||||
*
|
|
||||||
* @return a ByteArrayInputStream
|
|
||||||
*/
|
|
||||||
public ByteArrayInputStream readBytes() {
|
|
||||||
ByteArray ba = readByteArray();
|
|
||||||
if (ba != null)
|
|
||||||
return ba.toByteArrayInputStream();
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract a NSTRING, starting at the current position. Return it as
|
|
||||||
* a ByteArray. The sequence 'NIL' is returned as null
|
|
||||||
*
|
|
||||||
* NSTRING := QuotedString | Literal | "NIL"
|
|
||||||
*
|
|
||||||
* @return a ByteArray
|
|
||||||
*/
|
|
||||||
public ByteArray readByteArray() {
|
|
||||||
/*
|
|
||||||
* Special case, return the data after the continuation uninterpreted.
|
|
||||||
* It's usually a challenge for an AUTHENTICATE command.
|
|
||||||
*/
|
|
||||||
if (isContinuation()) {
|
|
||||||
skipSpaces();
|
|
||||||
return new ByteArray(buffer, index, size - index);
|
|
||||||
}
|
|
||||||
return (ByteArray)parseString(false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract an ASTRING, starting at the current position
|
|
||||||
* and return as a String. An ASTRING can be a QuotedString, a
|
|
||||||
* Literal or an Atom
|
|
||||||
*
|
|
||||||
* Any errors in parsing returns null
|
|
||||||
*
|
|
||||||
* ASTRING := QuotedString | Literal | Atom
|
|
||||||
*
|
|
||||||
* @return a String
|
|
||||||
*/
|
|
||||||
public String readAtomString() {
|
|
||||||
return (String)parseString(true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generic parsing routine that can parse out a Quoted-String,
|
|
||||||
* Literal or Atom and return the parsed token as a String
|
|
||||||
* or a ByteArray. Errors or NIL data will return null.
|
|
||||||
*/
|
|
||||||
private Object parseString(boolean parseAtoms, boolean returnString) {
|
|
||||||
byte b;
|
|
||||||
|
|
||||||
// Skip leading spaces
|
|
||||||
skipSpaces();
|
|
||||||
|
|
||||||
b = buffer[index];
|
|
||||||
if (b == '"') { // QuotedString
|
|
||||||
index++; // skip the quote
|
|
||||||
int start = index;
|
|
||||||
int copyto = index;
|
|
||||||
|
|
||||||
while (index < size && (b = buffer[index]) != '"') {
|
|
||||||
if (b == '\\') // skip escaped byte
|
|
||||||
index++;
|
|
||||||
if (index != copyto) { // only copy if we need to
|
|
||||||
// Beware: this is a destructive copy. I'm
|
|
||||||
// pretty sure this is OK, but ... ;>
|
|
||||||
buffer[copyto] = buffer[index];
|
|
||||||
}
|
|
||||||
copyto++;
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
if (index >= size) {
|
|
||||||
// didn't find terminating quote, something is seriously wrong
|
|
||||||
//throw new ArrayIndexOutOfBoundsException(
|
|
||||||
// "index = " + index + ", size = " + size);
|
|
||||||
return null;
|
|
||||||
} else
|
|
||||||
index++; // skip past the terminating quote
|
|
||||||
|
|
||||||
if (returnString)
|
|
||||||
return ASCIIUtility.toString(buffer, start, copyto);
|
|
||||||
else
|
|
||||||
return new ByteArray(buffer, start, copyto-start);
|
|
||||||
} else if (b == '{') { // Literal
|
|
||||||
int start = ++index; // note the start position
|
|
||||||
|
|
||||||
while (buffer[index] != '}')
|
|
||||||
index++;
|
|
||||||
|
|
||||||
int count = 0;
|
|
||||||
try {
|
|
||||||
count = ASCIIUtility.parseInt(buffer, start, index);
|
|
||||||
} catch (NumberFormatException nex) {
|
|
||||||
// throw new ParsingException();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
start = index + 3; // skip "}\r\n"
|
|
||||||
index = start + count; // position index to beyond the literal
|
|
||||||
|
|
||||||
if (returnString) // return as String
|
|
||||||
return ASCIIUtility.toString(buffer, start, start + count);
|
|
||||||
else
|
|
||||||
return new ByteArray(buffer, start, count);
|
|
||||||
} else if (parseAtoms) { // parse as an ATOM
|
|
||||||
int start = index; // track this, so that we can use to
|
|
||||||
// creating ByteArrayInputStream below.
|
|
||||||
String s = readAtom();
|
|
||||||
if (returnString)
|
|
||||||
return s;
|
|
||||||
else // *very* unlikely
|
|
||||||
return new ByteArray(buffer, start, index);
|
|
||||||
} else if (b == 'N' || b == 'n') { // the only valid value is 'NIL'
|
|
||||||
index += 3; // skip past NIL
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return null; // Error
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isContinuation() {
|
|
||||||
return ((type & TAG_MASK) == CONTINUATION);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isTagged() {
|
|
||||||
return ((type & TAG_MASK) == TAGGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isUnTagged() {
|
|
||||||
return ((type & TAG_MASK) == UNTAGGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isOK() {
|
|
||||||
return ((type & TYPE_MASK) == OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isNO() {
|
|
||||||
return ((type & TYPE_MASK) == NO);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isBAD() {
|
|
||||||
return ((type & TYPE_MASK) == BAD);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isBYE() {
|
|
||||||
return ((type & TYPE_MASK) == BYE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSynthetic() {
|
|
||||||
return ((type & SYNTHETIC) == SYNTHETIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the tag, if this is a tagged statement.
|
|
||||||
* @return tag of this tagged statement
|
|
||||||
*/
|
|
||||||
public String getTag() {
|
|
||||||
return tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the rest of the response as a string, usually used to
|
|
||||||
* return the arbitrary message text after a NO response.
|
|
||||||
*/
|
|
||||||
public String getRest() {
|
|
||||||
skipSpaces();
|
|
||||||
return ASCIIUtility.toString(buffer, index, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset pointer to beginning of response.
|
|
||||||
*/
|
|
||||||
public void reset() {
|
|
||||||
index = pindex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return ASCIIUtility.toString(buffer, 0, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.iap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
|
|
||||||
public interface ResponseHandler {
|
|
||||||
public void handleResponse(Response r);
|
|
||||||
}
|
|
||||||
@ -1,164 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.iap;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import com.sun.mail.iap.ByteArray;
|
|
||||||
import com.sun.mail.util.ASCIIUtility;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Inputstream that is used to read a Response.
|
|
||||||
*
|
|
||||||
* @author Arun Krishnan
|
|
||||||
* @author Bill Shannon
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class ResponseInputStream {
|
|
||||||
|
|
||||||
private static final int minIncrement = 256;
|
|
||||||
private static final int maxIncrement = 256 * 1024;
|
|
||||||
private static final int incrementSlop = 16;
|
|
||||||
|
|
||||||
// where we read from
|
|
||||||
private BufferedInputStream bin;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
*/
|
|
||||||
public ResponseInputStream(InputStream in) {
|
|
||||||
bin = new BufferedInputStream(in, 2 * 1024);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a Response from the InputStream.
|
|
||||||
* @return ByteArray that contains the Response
|
|
||||||
*/
|
|
||||||
public ByteArray readResponse() throws IOException {
|
|
||||||
return readResponse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a Response from the InputStream.
|
|
||||||
* @return ByteArray that contains the Response
|
|
||||||
*/
|
|
||||||
public ByteArray readResponse(ByteArray ba) throws IOException {
|
|
||||||
if (ba == null)
|
|
||||||
ba = new ByteArray(new byte[128], 0, 128);
|
|
||||||
|
|
||||||
byte[] buffer = ba.getBytes();
|
|
||||||
int idx = 0;
|
|
||||||
for (;;) { // read until CRLF with no preceeding literal
|
|
||||||
// XXX - b needs to be an int, to handle bytes with value 0xff
|
|
||||||
int b = 0;
|
|
||||||
boolean gotCRLF=false;
|
|
||||||
|
|
||||||
// Read a CRLF terminated line from the InputStream
|
|
||||||
while (!gotCRLF &&
|
|
||||||
((b = bin.read()) != -1)) {
|
|
||||||
switch (b) {
|
|
||||||
case '\n':
|
|
||||||
if ((idx > 0) && buffer[idx-1] == '\r')
|
|
||||||
gotCRLF = true;
|
|
||||||
default:
|
|
||||||
if (idx >= buffer.length) {
|
|
||||||
int incr = buffer.length;
|
|
||||||
if (incr > maxIncrement)
|
|
||||||
incr = maxIncrement;
|
|
||||||
ba.grow(incr);
|
|
||||||
buffer = ba.getBytes();
|
|
||||||
}
|
|
||||||
buffer[idx++] = (byte)b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (b == -1)
|
|
||||||
throw new IOException("Connection dropped by server?");
|
|
||||||
|
|
||||||
// Now lets check for literals : {<digits>}CRLF
|
|
||||||
// Note: index needs to >= 5 for the above sequence to occur
|
|
||||||
if (idx < 5 || buffer[idx-3] != '}')
|
|
||||||
break;
|
|
||||||
|
|
||||||
int i;
|
|
||||||
// look for left curly
|
|
||||||
for (i = idx - 4; i >= 0; i--)
|
|
||||||
if (buffer[i] == '{')
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (i < 0) // Nope, not a literal ?
|
|
||||||
break;
|
|
||||||
|
|
||||||
int count = 0;
|
|
||||||
// OK, handle the literal ..
|
|
||||||
try {
|
|
||||||
count = ASCIIUtility.parseInt(buffer, i+1, idx-3);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now read 'count' bytes. (Note: count could be 0)
|
|
||||||
if (count > 0) {
|
|
||||||
int avail = buffer.length - idx; // available space in buffer
|
|
||||||
if (count + incrementSlop > avail) {
|
|
||||||
// need count-avail more bytes
|
|
||||||
ba.grow(minIncrement > count + incrementSlop - avail ?
|
|
||||||
minIncrement : count + incrementSlop - avail);
|
|
||||||
buffer = ba.getBytes();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* read() might not return all the bytes in one shot,
|
|
||||||
* so call repeatedly till we are done
|
|
||||||
*/
|
|
||||||
int actual;
|
|
||||||
while (count > 0) {
|
|
||||||
actual = bin.read(buffer, idx, count);
|
|
||||||
count -= actual;
|
|
||||||
idx += actual;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// back to top of loop to read until CRLF
|
|
||||||
}
|
|
||||||
ba.setCount(idx);
|
|
||||||
return ba;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,117 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An access control list entry for a particular authentication identifier
|
|
||||||
* (user or group). Associates a set of Rights with the identifier.
|
|
||||||
* See RFC 2086.
|
|
||||||
* <p>
|
|
||||||
*
|
|
||||||
* @author Bill Shannon
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class ACL implements Cloneable {
|
|
||||||
|
|
||||||
private String name;
|
|
||||||
private Rights rights;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct an ACL entry for the given identifier and with no rights.
|
|
||||||
*
|
|
||||||
* @param name the identifier name
|
|
||||||
*/
|
|
||||||
public ACL(String name) {
|
|
||||||
this.name = name;
|
|
||||||
this.rights = new Rights();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct an ACL entry for the given identifier with the given rights.
|
|
||||||
*
|
|
||||||
* @param name the identifier name
|
|
||||||
* @param rights the rights
|
|
||||||
*/
|
|
||||||
public ACL(String name, Rights rights) {
|
|
||||||
this.name = name;
|
|
||||||
this.rights = rights;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the identifier name for this ACL entry.
|
|
||||||
*
|
|
||||||
* @return the identifier name
|
|
||||||
*/
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the rights associated with this ACL entry.
|
|
||||||
*
|
|
||||||
* @param rights the rights
|
|
||||||
*/
|
|
||||||
public void setRights(Rights rights) {
|
|
||||||
this.rights = rights;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the rights associated with this ACL entry.
|
|
||||||
* Returns the actual Rights object referenced by this ACL;
|
|
||||||
* modifications to the Rights object will effect this ACL.
|
|
||||||
*
|
|
||||||
* @return the rights
|
|
||||||
*/
|
|
||||||
public Rights getRights() {
|
|
||||||
return rights;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clone this ACL entry.
|
|
||||||
*/
|
|
||||||
public Object clone() throws CloneNotSupportedException {
|
|
||||||
ACL acl = (ACL)super.clone();
|
|
||||||
acl.rights = (Rights)this.rights.clone();
|
|
||||||
return acl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap;
|
|
||||||
|
|
||||||
import com.sun.mail.iap.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Information from the APPENDUID response code
|
|
||||||
* defined by the UIDPLUS extension -
|
|
||||||
* <A HREF="http://www.ietf.org/rfc/rfc2359.txt">RFC 2359</A>.
|
|
||||||
*
|
|
||||||
* @author Bill Shannon
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class AppendUID {
|
|
||||||
public long uidvalidity = -1;
|
|
||||||
public long uid = -1;
|
|
||||||
|
|
||||||
public AppendUID(long uidvalidity, long uid) {
|
|
||||||
this.uidvalidity = uidvalidity;
|
|
||||||
this.uid = uid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,137 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap;
|
|
||||||
|
|
||||||
import javax.mail.*;
|
|
||||||
import javax.mail.internet.*;
|
|
||||||
import com.sun.mail.util.*;
|
|
||||||
import com.sun.mail.iap.*;
|
|
||||||
import com.sun.mail.imap.protocol.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The default IMAP folder (root of the naming hierarchy).
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class DefaultFolder extends IMAPFolder {
|
|
||||||
|
|
||||||
protected DefaultFolder(IMAPStore store) {
|
|
||||||
super("", UNKNOWN_SEPARATOR, store, null);
|
|
||||||
exists = true; // of course
|
|
||||||
type = HOLDS_FOLDERS; // obviously
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized String getName() {
|
|
||||||
return fullName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Folder getParent() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized Folder[] list(final String pattern)
|
|
||||||
throws MessagingException {
|
|
||||||
ListInfo[] li = null;
|
|
||||||
|
|
||||||
li = (ListInfo[])doCommand(new ProtocolCommand() {
|
|
||||||
public Object doCommand(IMAPProtocol p) throws ProtocolException {
|
|
||||||
return p.list("", pattern);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (li == null)
|
|
||||||
return new Folder[0];
|
|
||||||
|
|
||||||
IMAPFolder[] folders = new IMAPFolder[li.length];
|
|
||||||
for (int i = 0; i < folders.length; i++)
|
|
||||||
folders[i] = ((IMAPStore)store).newIMAPFolder(li[i]);
|
|
||||||
return folders;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized Folder[] listSubscribed(final String pattern)
|
|
||||||
throws MessagingException {
|
|
||||||
ListInfo[] li = null;
|
|
||||||
|
|
||||||
li = (ListInfo[])doCommand(new ProtocolCommand() {
|
|
||||||
public Object doCommand(IMAPProtocol p) throws ProtocolException {
|
|
||||||
return p.lsub("", pattern);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (li == null)
|
|
||||||
return new Folder[0];
|
|
||||||
|
|
||||||
IMAPFolder[] folders = new IMAPFolder[li.length];
|
|
||||||
for (int i = 0; i < folders.length; i++)
|
|
||||||
folders[i] = ((IMAPStore)store).newIMAPFolder(li[i]);
|
|
||||||
return folders;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasNewMessages() throws MessagingException {
|
|
||||||
// Not applicable on DefaultFolder
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Folder getFolder(String name) throws MessagingException {
|
|
||||||
return ((IMAPStore)store).newIMAPFolder(name, UNKNOWN_SEPARATOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean delete(boolean recurse) throws MessagingException {
|
|
||||||
// Not applicable on DefaultFolder
|
|
||||||
throw new MethodNotSupportedException("Cannot delete Default Folder");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean renameTo(Folder f) throws MessagingException {
|
|
||||||
// Not applicable on DefaultFolder
|
|
||||||
throw new MethodNotSupportedException("Cannot rename Default Folder");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void appendMessages(Message[] msgs) throws MessagingException {
|
|
||||||
// Not applicable on DefaultFolder
|
|
||||||
throw new MethodNotSupportedException("Cannot append to Default Folder");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Message[] expunge() throws MessagingException {
|
|
||||||
// Not applicable on DefaultFolder
|
|
||||||
throw new MethodNotSupportedException("Cannot expunge Default Folder");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,438 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
|
|
||||||
import java.util.Enumeration;
|
|
||||||
import javax.mail.*;
|
|
||||||
import javax.mail.internet.*;
|
|
||||||
import javax.activation.*;
|
|
||||||
|
|
||||||
import com.sun.mail.util.*;
|
|
||||||
import com.sun.mail.iap.*;
|
|
||||||
import com.sun.mail.imap.protocol.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An IMAP body part.
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
* @author Bill Shannon
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class IMAPBodyPart extends MimeBodyPart implements ReadableMime {
|
|
||||||
private IMAPMessage message;
|
|
||||||
private BODYSTRUCTURE bs;
|
|
||||||
private String sectionId;
|
|
||||||
|
|
||||||
// processed values ..
|
|
||||||
private String type;
|
|
||||||
private String description;
|
|
||||||
|
|
||||||
private boolean headersLoaded = false;
|
|
||||||
|
|
||||||
private static final boolean decodeFileName =
|
|
||||||
PropUtil.getBooleanSystemProperty("mail.mime.decodefilename", false);
|
|
||||||
|
|
||||||
protected IMAPBodyPart(BODYSTRUCTURE bs, String sid, IMAPMessage message) {
|
|
||||||
super();
|
|
||||||
this.bs = bs;
|
|
||||||
this.sectionId = sid;
|
|
||||||
this.message = message;
|
|
||||||
// generate content-type
|
|
||||||
ContentType ct = new ContentType(bs.type, bs.subtype, bs.cParams);
|
|
||||||
type = ct.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Override this method to make it a no-op, rather than throw
|
|
||||||
* an IllegalWriteException. This will permit IMAPBodyParts to
|
|
||||||
* be inserted in newly crafted MimeMessages, especially when
|
|
||||||
* forwarding or replying to messages.
|
|
||||||
*/
|
|
||||||
protected void updateHeaders() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSize() throws MessagingException {
|
|
||||||
return bs.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getLineCount() throws MessagingException {
|
|
||||||
return bs.lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getContentType() throws MessagingException {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDisposition() throws MessagingException {
|
|
||||||
return bs.disposition;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDisposition(String disposition) throws MessagingException {
|
|
||||||
throw new IllegalWriteException("IMAPBodyPart is read-only");
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getEncoding() throws MessagingException {
|
|
||||||
return bs.encoding;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getContentID() throws MessagingException {
|
|
||||||
return bs.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getContentMD5() throws MessagingException {
|
|
||||||
return bs.md5;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setContentMD5(String md5) throws MessagingException {
|
|
||||||
throw new IllegalWriteException("IMAPBodyPart is read-only");
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDescription() throws MessagingException {
|
|
||||||
if (description != null) // cached value ?
|
|
||||||
return description;
|
|
||||||
|
|
||||||
if (bs.description == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
description = MimeUtility.decodeText(bs.description);
|
|
||||||
} catch (UnsupportedEncodingException ex) {
|
|
||||||
description = bs.description;
|
|
||||||
}
|
|
||||||
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDescription(String description, String charset)
|
|
||||||
throws MessagingException {
|
|
||||||
throw new IllegalWriteException("IMAPBodyPart is read-only");
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFileName() throws MessagingException {
|
|
||||||
String filename = null;
|
|
||||||
if (bs.dParams != null)
|
|
||||||
filename = bs.dParams.get("filename");
|
|
||||||
if (filename == null && bs.cParams != null)
|
|
||||||
filename = bs.cParams.get("name");
|
|
||||||
if (decodeFileName && filename != null) {
|
|
||||||
try {
|
|
||||||
filename = MimeUtility.decodeText(filename);
|
|
||||||
} catch (UnsupportedEncodingException ex) {
|
|
||||||
throw new MessagingException("Can't decode filename", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFileName(String filename) throws MessagingException {
|
|
||||||
throw new IllegalWriteException("IMAPBodyPart is read-only");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected InputStream getContentStream() throws MessagingException {
|
|
||||||
InputStream is = null;
|
|
||||||
boolean pk = message.getPeek(); // acquire outside of message cache lock
|
|
||||||
|
|
||||||
// Acquire MessageCacheLock, to freeze seqnum.
|
|
||||||
synchronized(message.getMessageCacheLock()) {
|
|
||||||
try {
|
|
||||||
IMAPProtocol p = message.getProtocol();
|
|
||||||
|
|
||||||
// Check whether this message is expunged
|
|
||||||
message.checkExpunged();
|
|
||||||
|
|
||||||
if (p.isREV1() && (message.getFetchBlockSize() != -1))
|
|
||||||
return new IMAPInputStream(message, sectionId,
|
|
||||||
message.ignoreBodyStructureSize() ? -1 : bs.size, pk);
|
|
||||||
|
|
||||||
// Else, vanila IMAP4, no partial fetch
|
|
||||||
|
|
||||||
int seqnum = message.getSequenceNumber();
|
|
||||||
BODY b;
|
|
||||||
if (pk)
|
|
||||||
b = p.peekBody(seqnum, sectionId);
|
|
||||||
else
|
|
||||||
b = p.fetchBody(seqnum, sectionId);
|
|
||||||
if (b != null)
|
|
||||||
is = b.getByteArrayInputStream();
|
|
||||||
} catch (ConnectionException cex) {
|
|
||||||
throw new FolderClosedException(
|
|
||||||
message.getFolder(), cex.getMessage());
|
|
||||||
} catch (ProtocolException pex) {
|
|
||||||
throw new MessagingException(pex.getMessage(), pex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is == null)
|
|
||||||
throw new MessagingException("No content");
|
|
||||||
else
|
|
||||||
return is;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the MIME format stream of headers for this body part.
|
|
||||||
*/
|
|
||||||
private InputStream getHeaderStream() throws MessagingException {
|
|
||||||
if (!message.isREV1())
|
|
||||||
loadHeaders(); // will be needed below
|
|
||||||
|
|
||||||
// Acquire MessageCacheLock, to freeze seqnum.
|
|
||||||
synchronized(message.getMessageCacheLock()) {
|
|
||||||
try {
|
|
||||||
IMAPProtocol p = message.getProtocol();
|
|
||||||
|
|
||||||
// Check whether this message got expunged
|
|
||||||
message.checkExpunged();
|
|
||||||
|
|
||||||
if (p.isREV1()) {
|
|
||||||
int seqnum = message.getSequenceNumber();
|
|
||||||
BODY b = p.peekBody(seqnum, sectionId + ".MIME");
|
|
||||||
|
|
||||||
if (b == null)
|
|
||||||
throw new MessagingException("Failed to fetch headers");
|
|
||||||
|
|
||||||
ByteArrayInputStream bis = b.getByteArrayInputStream();
|
|
||||||
if (bis == null)
|
|
||||||
throw new MessagingException("Failed to fetch headers");
|
|
||||||
return bis;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Can't read it from server, have to fake it
|
|
||||||
SharedByteArrayOutputStream bos =
|
|
||||||
new SharedByteArrayOutputStream(0);
|
|
||||||
LineOutputStream los = new LineOutputStream(bos);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Write out the header
|
|
||||||
Enumeration hdrLines = super.getAllHeaderLines();
|
|
||||||
while (hdrLines.hasMoreElements())
|
|
||||||
los.writeln((String)hdrLines.nextElement());
|
|
||||||
|
|
||||||
// The CRLF separator between header and content
|
|
||||||
los.writeln();
|
|
||||||
} catch (IOException ioex) {
|
|
||||||
// should never happen
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
los.close();
|
|
||||||
} catch (IOException cex) { }
|
|
||||||
}
|
|
||||||
return bos.toStream();
|
|
||||||
}
|
|
||||||
} catch (ConnectionException cex) {
|
|
||||||
throw new FolderClosedException(
|
|
||||||
message.getFolder(), cex.getMessage());
|
|
||||||
} catch (ProtocolException pex) {
|
|
||||||
throw new MessagingException(pex.getMessage(), pex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the MIME format stream corresponding to this message part.
|
|
||||||
*
|
|
||||||
* @return the MIME format stream
|
|
||||||
* @since JavaMail 1.4.5
|
|
||||||
*/
|
|
||||||
public InputStream getMimeStream() throws MessagingException {
|
|
||||||
/*
|
|
||||||
* The IMAP protocol doesn't support returning the entire
|
|
||||||
* part content in one operation so we have to fake it by
|
|
||||||
* concatenating the header stream and the content stream.
|
|
||||||
*/
|
|
||||||
return new SequenceInputStream(getHeaderStream(), getContentStream());
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized DataHandler getDataHandler()
|
|
||||||
throws MessagingException {
|
|
||||||
if (dh == null) {
|
|
||||||
if (bs.isMulti())
|
|
||||||
dh = new DataHandler(
|
|
||||||
new IMAPMultipartDataSource(
|
|
||||||
this, bs.bodies, sectionId, message)
|
|
||||||
);
|
|
||||||
else if (bs.isNested() && message.isREV1() && bs.envelope != null)
|
|
||||||
dh = new DataHandler(
|
|
||||||
new IMAPNestedMessage(message,
|
|
||||||
bs.bodies[0],
|
|
||||||
bs.envelope,
|
|
||||||
sectionId),
|
|
||||||
type
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.getDataHandler();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDataHandler(DataHandler content) throws MessagingException {
|
|
||||||
throw new IllegalWriteException("IMAPBodyPart is read-only");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setContent(Object o, String type) throws MessagingException {
|
|
||||||
throw new IllegalWriteException("IMAPBodyPart is read-only");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setContent(Multipart mp) throws MessagingException {
|
|
||||||
throw new IllegalWriteException("IMAPBodyPart is read-only");
|
|
||||||
}
|
|
||||||
|
|
||||||
public String[] getHeader(String name) throws MessagingException {
|
|
||||||
loadHeaders();
|
|
||||||
return super.getHeader(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHeader(String name, String value)
|
|
||||||
throws MessagingException {
|
|
||||||
throw new IllegalWriteException("IMAPBodyPart is read-only");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addHeader(String name, String value)
|
|
||||||
throws MessagingException {
|
|
||||||
throw new IllegalWriteException("IMAPBodyPart is read-only");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeHeader(String name) throws MessagingException {
|
|
||||||
throw new IllegalWriteException("IMAPBodyPart is read-only");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Enumeration getAllHeaders() throws MessagingException {
|
|
||||||
loadHeaders();
|
|
||||||
return super.getAllHeaders();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Enumeration getMatchingHeaders(String[] names)
|
|
||||||
throws MessagingException {
|
|
||||||
loadHeaders();
|
|
||||||
return super.getMatchingHeaders(names);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Enumeration getNonMatchingHeaders(String[] names)
|
|
||||||
throws MessagingException {
|
|
||||||
loadHeaders();
|
|
||||||
return super.getNonMatchingHeaders(names);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addHeaderLine(String line) throws MessagingException {
|
|
||||||
throw new IllegalWriteException("IMAPBodyPart is read-only");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Enumeration getAllHeaderLines() throws MessagingException {
|
|
||||||
loadHeaders();
|
|
||||||
return super.getAllHeaderLines();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Enumeration getMatchingHeaderLines(String[] names)
|
|
||||||
throws MessagingException {
|
|
||||||
loadHeaders();
|
|
||||||
return super.getMatchingHeaderLines(names);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Enumeration getNonMatchingHeaderLines(String[] names)
|
|
||||||
throws MessagingException {
|
|
||||||
loadHeaders();
|
|
||||||
return super.getNonMatchingHeaderLines(names);
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void loadHeaders() throws MessagingException {
|
|
||||||
if (headersLoaded)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// "headers" should never be null since it's set in the constructor.
|
|
||||||
// If something did go wrong this will fix it, but is an unsynchronized
|
|
||||||
// assignment of "headers".
|
|
||||||
if (headers == null)
|
|
||||||
headers = new InternetHeaders();
|
|
||||||
|
|
||||||
// load headers
|
|
||||||
|
|
||||||
// Acquire MessageCacheLock, to freeze seqnum.
|
|
||||||
synchronized(message.getMessageCacheLock()) {
|
|
||||||
try {
|
|
||||||
IMAPProtocol p = message.getProtocol();
|
|
||||||
|
|
||||||
// Check whether this message got expunged
|
|
||||||
message.checkExpunged();
|
|
||||||
|
|
||||||
if (p.isREV1()) {
|
|
||||||
int seqnum = message.getSequenceNumber();
|
|
||||||
BODY b = p.peekBody(seqnum, sectionId + ".MIME");
|
|
||||||
|
|
||||||
if (b == null)
|
|
||||||
throw new MessagingException("Failed to fetch headers");
|
|
||||||
|
|
||||||
ByteArrayInputStream bis = b.getByteArrayInputStream();
|
|
||||||
if (bis == null)
|
|
||||||
throw new MessagingException("Failed to fetch headers");
|
|
||||||
|
|
||||||
headers.load(bis);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// RFC 1730 does not provide for fetching BodyPart headers
|
|
||||||
// So, just dump the RFC1730 BODYSTRUCTURE into the
|
|
||||||
// headerStore
|
|
||||||
|
|
||||||
// Content-Type
|
|
||||||
headers.addHeader("Content-Type", type);
|
|
||||||
// Content-Transfer-Encoding
|
|
||||||
headers.addHeader("Content-Transfer-Encoding", bs.encoding);
|
|
||||||
// Content-Description
|
|
||||||
if (bs.description != null)
|
|
||||||
headers.addHeader("Content-Description",
|
|
||||||
bs.description);
|
|
||||||
// Content-ID
|
|
||||||
if (bs.id != null)
|
|
||||||
headers.addHeader("Content-ID", bs.id);
|
|
||||||
// Content-MD5
|
|
||||||
if (bs.md5 != null)
|
|
||||||
headers.addHeader("Content-MD5", bs.md5);
|
|
||||||
}
|
|
||||||
} catch (ConnectionException cex) {
|
|
||||||
throw new FolderClosedException(
|
|
||||||
message.getFolder(), cex.getMessage());
|
|
||||||
} catch (ProtocolException pex) {
|
|
||||||
throw new MessagingException(pex.getMessage(), pex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
headersLoaded = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,269 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import javax.mail.*;
|
|
||||||
import com.sun.mail.imap.protocol.*;
|
|
||||||
import com.sun.mail.iap.*;
|
|
||||||
import com.sun.mail.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class implements an IMAP data stream.
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class IMAPInputStream extends InputStream {
|
|
||||||
private IMAPMessage msg; // this message
|
|
||||||
private String section; // section-id
|
|
||||||
private int pos; // track the position within the IMAP datastream
|
|
||||||
private int blksize; // number of bytes to read in each FETCH request
|
|
||||||
private int max; // the total number of bytes in this section.
|
|
||||||
// -1 indicates unknown
|
|
||||||
private byte[] buf; // the buffer obtained from fetchBODY()
|
|
||||||
private int bufcount; // The index one greater than the index of the
|
|
||||||
// last valid byte in 'buf'
|
|
||||||
private int bufpos; // The current position within 'buf'
|
|
||||||
private boolean lastBuffer; // is this the last buffer of data?
|
|
||||||
private boolean peek; // peek instead of fetch?
|
|
||||||
private ByteArray readbuf; // reuse for each read
|
|
||||||
|
|
||||||
// Allocate this much extra space in the read buffer to allow
|
|
||||||
// space for the FETCH response overhead
|
|
||||||
private static final int slop = 64;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an IMAPInputStream.
|
|
||||||
*/
|
|
||||||
public IMAPInputStream(IMAPMessage msg, String section, int max,
|
|
||||||
boolean peek) {
|
|
||||||
this.msg = msg;
|
|
||||||
this.section = section;
|
|
||||||
this.max = max;
|
|
||||||
this.peek = peek;
|
|
||||||
pos = 0;
|
|
||||||
blksize = msg.getFetchBlockSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Do a NOOP to force any untagged EXPUNGE responses
|
|
||||||
* and then check if this message is expunged.
|
|
||||||
*/
|
|
||||||
private void forceCheckExpunged()
|
|
||||||
throws MessageRemovedIOException, FolderClosedIOException {
|
|
||||||
synchronized (msg.getMessageCacheLock()) {
|
|
||||||
try {
|
|
||||||
msg.getProtocol().noop();
|
|
||||||
} catch (ConnectionException cex) {
|
|
||||||
throw new FolderClosedIOException(msg.getFolder(),
|
|
||||||
cex.getMessage());
|
|
||||||
} catch (FolderClosedException fex) {
|
|
||||||
throw new FolderClosedIOException(fex.getFolder(),
|
|
||||||
fex.getMessage());
|
|
||||||
} catch (ProtocolException pex) {
|
|
||||||
// ignore it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (msg.isExpunged())
|
|
||||||
throw new MessageRemovedIOException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch more data from the server. This method assumes that all
|
|
||||||
* data has already been read in, hence bufpos > bufcount.
|
|
||||||
*/
|
|
||||||
private void fill() throws IOException {
|
|
||||||
/*
|
|
||||||
* If we've read the last buffer, there's no more to read.
|
|
||||||
* If we know the total number of bytes available from this
|
|
||||||
* section, let's check if we have consumed that many bytes.
|
|
||||||
*/
|
|
||||||
if (lastBuffer || max != -1 && pos >= max) {
|
|
||||||
if (pos == 0)
|
|
||||||
checkSeen();
|
|
||||||
readbuf = null; // XXX - return to pool?
|
|
||||||
return; // the caller of fill() will return -1.
|
|
||||||
}
|
|
||||||
|
|
||||||
BODY b = null;
|
|
||||||
if (readbuf == null)
|
|
||||||
readbuf = new ByteArray(blksize + slop);
|
|
||||||
|
|
||||||
ByteArray ba;
|
|
||||||
int cnt;
|
|
||||||
// Acquire MessageCacheLock, to freeze seqnum.
|
|
||||||
synchronized (msg.getMessageCacheLock()) {
|
|
||||||
try {
|
|
||||||
IMAPProtocol p = msg.getProtocol();
|
|
||||||
|
|
||||||
// Check whether this message is expunged
|
|
||||||
if (msg.isExpunged())
|
|
||||||
throw new MessageRemovedIOException(
|
|
||||||
"No content for expunged message");
|
|
||||||
|
|
||||||
int seqnum = msg.getSequenceNumber();
|
|
||||||
cnt = blksize;
|
|
||||||
if (max != -1 && pos + blksize > max)
|
|
||||||
cnt = max - pos;
|
|
||||||
if (peek)
|
|
||||||
b = p.peekBody(seqnum, section, pos, cnt, readbuf);
|
|
||||||
else
|
|
||||||
b = p.fetchBody(seqnum, section, pos, cnt, readbuf);
|
|
||||||
} catch (ProtocolException pex) {
|
|
||||||
forceCheckExpunged();
|
|
||||||
throw new IOException(pex.getMessage());
|
|
||||||
} catch (FolderClosedException fex) {
|
|
||||||
throw new FolderClosedIOException(fex.getFolder(),
|
|
||||||
fex.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (b == null || ((ba = b.getByteArray()) == null)) {
|
|
||||||
forceCheckExpunged();
|
|
||||||
throw new IOException("No content");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure the SEEN flag is set after reading the first chunk
|
|
||||||
if (pos == 0)
|
|
||||||
checkSeen();
|
|
||||||
|
|
||||||
// setup new values ..
|
|
||||||
buf = ba.getBytes();
|
|
||||||
bufpos = ba.getStart();
|
|
||||||
int n = ba.getCount(); // will be zero, if all data has been
|
|
||||||
// consumed from the server.
|
|
||||||
// if we got less than we asked for, this is the last buffer of data
|
|
||||||
lastBuffer = n < cnt;
|
|
||||||
bufcount = bufpos + n;
|
|
||||||
pos += n;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads the next byte of data from this buffered input stream.
|
|
||||||
* If no byte is available, the value <code>-1</code> is returned.
|
|
||||||
*/
|
|
||||||
public synchronized int read() throws IOException {
|
|
||||||
if (bufpos >= bufcount) {
|
|
||||||
fill();
|
|
||||||
if (bufpos >= bufcount)
|
|
||||||
return -1; // EOF
|
|
||||||
}
|
|
||||||
return buf[bufpos++] & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads up to <code>len</code> bytes of data from this
|
|
||||||
* input stream into the given buffer. <p>
|
|
||||||
*
|
|
||||||
* Returns the total number of bytes read into the buffer,
|
|
||||||
* or <code>-1</code> if there is no more data. <p>
|
|
||||||
*
|
|
||||||
* Note that this method mimics the "weird !" semantics of
|
|
||||||
* BufferedInputStream in that the number of bytes actually
|
|
||||||
* returned may be less that the requested value. So callers
|
|
||||||
* of this routine should be aware of this and must check
|
|
||||||
* the return value to insure that they have obtained the
|
|
||||||
* requisite number of bytes.
|
|
||||||
*/
|
|
||||||
public synchronized int read(byte b[], int off, int len)
|
|
||||||
throws IOException {
|
|
||||||
|
|
||||||
int avail = bufcount - bufpos;
|
|
||||||
if (avail <= 0) {
|
|
||||||
fill();
|
|
||||||
avail = bufcount - bufpos;
|
|
||||||
if (avail <= 0)
|
|
||||||
return -1; // EOF
|
|
||||||
}
|
|
||||||
int cnt = (avail < len) ? avail : len;
|
|
||||||
System.arraycopy(buf, bufpos, b, off, cnt);
|
|
||||||
bufpos += cnt;
|
|
||||||
return cnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads up to <code>b.length</code> bytes of data from this input
|
|
||||||
* stream into an array of bytes. <p>
|
|
||||||
*
|
|
||||||
* Returns the total number of bytes read into the buffer, or
|
|
||||||
* <code>-1</code> is there is no more data. <p>
|
|
||||||
*
|
|
||||||
* Note that this method mimics the "weird !" semantics of
|
|
||||||
* BufferedInputStream in that the number of bytes actually
|
|
||||||
* returned may be less that the requested value. So callers
|
|
||||||
* of this routine should be aware of this and must check
|
|
||||||
* the return value to insure that they have obtained the
|
|
||||||
* requisite number of bytes.
|
|
||||||
*/
|
|
||||||
public int read(byte b[]) throws IOException {
|
|
||||||
return read(b, 0, b.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of bytes that can be read from this input
|
|
||||||
* stream without blocking.
|
|
||||||
*/
|
|
||||||
public synchronized int available() throws IOException {
|
|
||||||
return (bufcount - bufpos);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Normally the SEEN flag will have been set by now, but if not,
|
|
||||||
* force it to be set (as long as the folder isn't open read-only
|
|
||||||
* and we're not peeking).
|
|
||||||
* And of course, if there's no folder (e.g., a nested message)
|
|
||||||
* don't do anything.
|
|
||||||
*/
|
|
||||||
private void checkSeen() {
|
|
||||||
if (peek) // if we're peeking, don't set the SEEN flag
|
|
||||||
return;
|
|
||||||
try {
|
|
||||||
Folder f = msg.getFolder();
|
|
||||||
if (f != null && f.getMode() != Folder.READ_ONLY &&
|
|
||||||
!msg.isSet(Flags.Flag.SEEN))
|
|
||||||
msg.setFlag(Flags.Flag.SEEN, true);
|
|
||||||
} catch (MessagingException ex) {
|
|
||||||
// ignore it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,86 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
import javax.mail.*;
|
|
||||||
import javax.mail.internet.*;
|
|
||||||
|
|
||||||
import com.sun.mail.util.*;
|
|
||||||
import com.sun.mail.iap.*;
|
|
||||||
import com.sun.mail.imap.protocol.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class IMAPMultipartDataSource extends MimePartDataSource
|
|
||||||
implements MultipartDataSource {
|
|
||||||
private Vector parts;
|
|
||||||
|
|
||||||
protected IMAPMultipartDataSource(MimePart part, BODYSTRUCTURE[] bs,
|
|
||||||
String sectionId, IMAPMessage msg) {
|
|
||||||
super(part);
|
|
||||||
|
|
||||||
parts = new Vector(bs.length);
|
|
||||||
for (int i = 0; i < bs.length; i++)
|
|
||||||
parts.addElement(
|
|
||||||
new IMAPBodyPart(bs[i],
|
|
||||||
sectionId == null ?
|
|
||||||
Integer.toString(i+1) :
|
|
||||||
sectionId + "." + Integer.toString(i+1),
|
|
||||||
msg)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCount() {
|
|
||||||
return parts.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public BodyPart getBodyPart(int index) throws MessagingException {
|
|
||||||
return (BodyPart)parts.elementAt(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,151 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2013 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import javax.mail.*;
|
|
||||||
import com.sun.mail.imap.protocol.*;
|
|
||||||
import com.sun.mail.iap.ProtocolException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class implements a nested IMAP message
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class IMAPNestedMessage extends IMAPMessage {
|
|
||||||
private IMAPMessage msg; // the enclosure of this nested message
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Package private constructor. <p>
|
|
||||||
*
|
|
||||||
* Note that nested messages have no containing folder, nor
|
|
||||||
* a message number.
|
|
||||||
*/
|
|
||||||
IMAPNestedMessage(IMAPMessage m, BODYSTRUCTURE b, ENVELOPE e, String sid) {
|
|
||||||
super(m._getSession());
|
|
||||||
msg = m;
|
|
||||||
bs = b;
|
|
||||||
envelope = e;
|
|
||||||
sectionId = sid;
|
|
||||||
setPeek(m.getPeek());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the enclosing message's Protocol object. Overrides
|
|
||||||
* IMAPMessage.getProtocol().
|
|
||||||
*/
|
|
||||||
protected IMAPProtocol getProtocol()
|
|
||||||
throws ProtocolException, FolderClosedException {
|
|
||||||
return msg.getProtocol();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Is this an IMAP4 REV1 server?
|
|
||||||
*/
|
|
||||||
protected boolean isREV1() throws FolderClosedException {
|
|
||||||
return msg.isREV1();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the enclosing message's messageCacheLock. Overrides
|
|
||||||
* IMAPMessage.getMessageCacheLock().
|
|
||||||
*/
|
|
||||||
protected Object getMessageCacheLock() {
|
|
||||||
return msg.getMessageCacheLock();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the enclosing message's sequence number. Overrides
|
|
||||||
* IMAPMessage.getSequenceNumber().
|
|
||||||
*/
|
|
||||||
protected int getSequenceNumber() {
|
|
||||||
return msg.getSequenceNumber();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check whether the enclosing message is expunged. Overrides
|
|
||||||
* IMAPMessage.checkExpunged().
|
|
||||||
*/
|
|
||||||
protected void checkExpunged() throws MessageRemovedException {
|
|
||||||
msg.checkExpunged();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check whether the enclosing message is expunged. Overrides
|
|
||||||
* Message.isExpunged().
|
|
||||||
*/
|
|
||||||
public boolean isExpunged() {
|
|
||||||
return msg.isExpunged();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the enclosing message's fetchBlockSize.
|
|
||||||
*/
|
|
||||||
protected int getFetchBlockSize() {
|
|
||||||
return msg.getFetchBlockSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the enclosing message's ignoreBodyStructureSize.
|
|
||||||
*/
|
|
||||||
protected boolean ignoreBodyStructureSize() {
|
|
||||||
return msg.ignoreBodyStructureSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* IMAPMessage uses RFC822.SIZE. We use the "size" field from
|
|
||||||
* our BODYSTRUCTURE.
|
|
||||||
*/
|
|
||||||
public int getSize() throws MessagingException {
|
|
||||||
return bs.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Disallow setting flags on nested messages
|
|
||||||
*/
|
|
||||||
public synchronized void setFlags(Flags flag, boolean set)
|
|
||||||
throws MessagingException {
|
|
||||||
// Cannot set FLAGS on a nested IMAP message
|
|
||||||
throw new MethodNotSupportedException(
|
|
||||||
"Cannot set flags on this nested message");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap;
|
|
||||||
|
|
||||||
import javax.mail.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class provides access to an IMAP message store over SSL. <p>
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class IMAPSSLStore extends IMAPStore {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor that takes a Session object and a URLName that
|
|
||||||
* represents a specific IMAP server.
|
|
||||||
*/
|
|
||||||
public IMAPSSLStore(Session session, URLName url) {
|
|
||||||
super(session, url, "imaps", true); // call super constructor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,444 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap;
|
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
|
|
||||||
import javax.mail.*;
|
|
||||||
import com.sun.mail.util.PropUtil;
|
|
||||||
import com.sun.mail.util.MailLogger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A cache of IMAPMessage objects along with the
|
|
||||||
* mapping from message number to IMAP sequence number.
|
|
||||||
*
|
|
||||||
* All operations on this object are protected by the messageCacheLock
|
|
||||||
* in IMAPFolder.
|
|
||||||
*/
|
|
||||||
public class MessageCache {
|
|
||||||
/*
|
|
||||||
* The array of IMAPMessage objects. Elements of the array might
|
|
||||||
* be null if no one has asked for the message. The array expands
|
|
||||||
* as needed and might be larger than the number of messages in the
|
|
||||||
* folder. The "size" field indicates the number of entries that
|
|
||||||
* are valid.
|
|
||||||
*/
|
|
||||||
private IMAPMessage[] messages;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A parallel array of sequence numbers for each message. If the
|
|
||||||
* array pointer is null, the sequence number of a message is just
|
|
||||||
* its message number. This is the common case, until a message is
|
|
||||||
* expunged.
|
|
||||||
*/
|
|
||||||
private int[] seqnums;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The amount of the messages (and seqnum) array that is valid.
|
|
||||||
* Might be less than the actual size of the array.
|
|
||||||
*/
|
|
||||||
private int size;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The folder these messages belong to.
|
|
||||||
*/
|
|
||||||
private IMAPFolder folder;
|
|
||||||
|
|
||||||
// debugging logger
|
|
||||||
private MailLogger logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Grow the array by at least this much, to avoid constantly
|
|
||||||
* reallocating the array.
|
|
||||||
*/
|
|
||||||
private static final int SLOP = 64;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new message cache of the indicated size.
|
|
||||||
*/
|
|
||||||
MessageCache(IMAPFolder folder, IMAPStore store, int size) {
|
|
||||||
this.folder = folder;
|
|
||||||
logger = folder.logger.getSubLogger("messagecache", "DEBUG IMAP MC",
|
|
||||||
store.getMessageCacheDebug());
|
|
||||||
if (logger.isLoggable(Level.CONFIG))
|
|
||||||
logger.config("create cache of size " + size);
|
|
||||||
ensureCapacity(size, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for debugging and testing.
|
|
||||||
*/
|
|
||||||
MessageCache(int size, boolean debug) {
|
|
||||||
this.folder = null;
|
|
||||||
logger = new MailLogger(
|
|
||||||
this.getClass(), "messagecache",
|
|
||||||
"DEBUG IMAP MC", debug, System.out);
|
|
||||||
if (logger.isLoggable(Level.CONFIG))
|
|
||||||
logger.config("create DEBUG cache of size " + size);
|
|
||||||
ensureCapacity(size, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Size of cache.
|
|
||||||
*/
|
|
||||||
public int size() {
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the message object for the indicated message number.
|
|
||||||
* If the message object hasn't been created, create it.
|
|
||||||
*/
|
|
||||||
public IMAPMessage getMessage(int msgnum) {
|
|
||||||
// check range
|
|
||||||
if (msgnum < 1 || msgnum > size)
|
|
||||||
throw new ArrayIndexOutOfBoundsException(
|
|
||||||
"message number (" + msgnum + ") out of bounds (" + size + ")");
|
|
||||||
IMAPMessage msg = messages[msgnum-1];
|
|
||||||
if (msg == null) {
|
|
||||||
if (logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("create message number " + msgnum);
|
|
||||||
msg = folder.newIMAPMessage(msgnum);
|
|
||||||
messages[msgnum-1] = msg;
|
|
||||||
// mark message expunged if no seqnum
|
|
||||||
if (seqnumOf(msgnum) <= 0) {
|
|
||||||
logger.fine("it's expunged!");
|
|
||||||
msg.setExpunged(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the message object for the indicated sequence number.
|
|
||||||
* If the message object hasn't been created, create it.
|
|
||||||
* Return null if there's no message with that sequence number.
|
|
||||||
*/
|
|
||||||
public IMAPMessage getMessageBySeqnum(int seqnum) {
|
|
||||||
int msgnum = msgnumOf(seqnum);
|
|
||||||
if (msgnum < 0) { // XXX - < 1 ?
|
|
||||||
if (logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("no message seqnum " + seqnum);
|
|
||||||
return null;
|
|
||||||
} else
|
|
||||||
return getMessage(msgnum);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Expunge the message with the given sequence number.
|
|
||||||
*/
|
|
||||||
public void expungeMessage(int seqnum) {
|
|
||||||
int msgnum = msgnumOf(seqnum);
|
|
||||||
if (msgnum < 0) {
|
|
||||||
if (logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("expunge no seqnum " + seqnum);
|
|
||||||
return; // XXX - should never happen
|
|
||||||
}
|
|
||||||
IMAPMessage msg = messages[msgnum-1];
|
|
||||||
if (msg != null) {
|
|
||||||
if (logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("expunge existing " + msgnum);
|
|
||||||
msg.setExpunged(true);
|
|
||||||
}
|
|
||||||
if (seqnums == null) { // time to fill it in
|
|
||||||
logger.fine("create seqnums array");
|
|
||||||
seqnums = new int[messages.length];
|
|
||||||
for (int i = 1; i < msgnum; i++)
|
|
||||||
seqnums[i-1] = i;
|
|
||||||
seqnums[msgnum - 1] = 0;
|
|
||||||
for (int i = msgnum + 1; i <= seqnums.length; i++)
|
|
||||||
seqnums[i-1] = i - 1;
|
|
||||||
} else {
|
|
||||||
seqnums[msgnum - 1] = 0;
|
|
||||||
for (int i = msgnum + 1; i <= seqnums.length; i++) {
|
|
||||||
assert seqnums[i-1] != 1;
|
|
||||||
if (seqnums[i-1] > 0)
|
|
||||||
seqnums[i-1]--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove all the expunged messages from the array,
|
|
||||||
* returning a list of removed message objects.
|
|
||||||
*/
|
|
||||||
public IMAPMessage[] removeExpungedMessages() {
|
|
||||||
logger.fine("remove expunged messages");
|
|
||||||
List mlist = new ArrayList(); // list of expunged messages
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Walk through the array compressing it by copying
|
|
||||||
* higher numbered messages further down in the array,
|
|
||||||
* effectively removing expunged messages from the array.
|
|
||||||
* oldnum is the index we use to walk through the array.
|
|
||||||
* newnum is the index where we copy the next valid message.
|
|
||||||
* oldnum == newnum until we encounter an expunged message.
|
|
||||||
*/
|
|
||||||
int oldnum = 1;
|
|
||||||
int newnum = 1;
|
|
||||||
while (oldnum <= size) {
|
|
||||||
// is message expunged?
|
|
||||||
if (seqnumOf(oldnum) <= 0) {
|
|
||||||
IMAPMessage m = getMessage(oldnum);
|
|
||||||
mlist.add(m);
|
|
||||||
} else {
|
|
||||||
// keep this message
|
|
||||||
if (newnum != oldnum) {
|
|
||||||
// move message down in the array (compact array)
|
|
||||||
messages[newnum-1] = messages[oldnum-1];
|
|
||||||
if (messages[newnum-1] != null)
|
|
||||||
messages[newnum-1].setMessageNumber(newnum);
|
|
||||||
}
|
|
||||||
newnum++;
|
|
||||||
}
|
|
||||||
oldnum++;
|
|
||||||
}
|
|
||||||
seqnums = null;
|
|
||||||
shrink(newnum, oldnum);
|
|
||||||
|
|
||||||
IMAPMessage[] rmsgs = new IMAPMessage[mlist.size()];
|
|
||||||
if (logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("return " + rmsgs.length);
|
|
||||||
mlist.toArray(rmsgs);
|
|
||||||
return rmsgs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove expunged messages in msgs from the array,
|
|
||||||
* returning a list of removed message objects.
|
|
||||||
* All messages in msgs must be IMAPMessage objects
|
|
||||||
* from this folder.
|
|
||||||
*/
|
|
||||||
public IMAPMessage[] removeExpungedMessages(Message[] msgs) {
|
|
||||||
logger.fine("remove expunged messages");
|
|
||||||
List mlist = new ArrayList(); // list of expunged messages
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copy the message numbers of the expunged messages into
|
|
||||||
* a separate array and sort the array to make it easier to
|
|
||||||
* process later.
|
|
||||||
*/
|
|
||||||
int[] mnum = new int[msgs.length];
|
|
||||||
for (int i = 0; i < msgs.length; i++)
|
|
||||||
mnum[i] = msgs[i].getMessageNumber();
|
|
||||||
Arrays.sort(mnum);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Walk through the array compressing it by copying
|
|
||||||
* higher numbered messages further down in the array,
|
|
||||||
* effectively removing expunged messages from the array.
|
|
||||||
* oldnum is the index we use to walk through the array.
|
|
||||||
* newnum is the index where we copy the next valid message.
|
|
||||||
* oldnum == newnum until we encounter an expunged message.
|
|
||||||
*
|
|
||||||
* Even though we know the message number of the first possibly
|
|
||||||
* expunged message, we still start scanning at message number 1
|
|
||||||
* so that we can check whether there's any message whose
|
|
||||||
* sequence number is different than its message number. If there
|
|
||||||
* is, we can't throw away the seqnums array when we're done.
|
|
||||||
*/
|
|
||||||
int oldnum = 1;
|
|
||||||
int newnum = 1;
|
|
||||||
int mnumi = 0; // index into mnum
|
|
||||||
boolean keepSeqnums = false;
|
|
||||||
while (oldnum <= size) {
|
|
||||||
/*
|
|
||||||
* Are there still expunged messsages in msgs to consider,
|
|
||||||
* and is the message we're considering the next one in the
|
|
||||||
* list, and is it expunged?
|
|
||||||
*/
|
|
||||||
if (mnumi < mnum.length &&
|
|
||||||
oldnum == mnum[mnumi] &&
|
|
||||||
seqnumOf(oldnum) <= 0) {
|
|
||||||
IMAPMessage m = getMessage(oldnum);
|
|
||||||
mlist.add(m);
|
|
||||||
/*
|
|
||||||
* Just in case there are duplicate entries in the msgs array,
|
|
||||||
* we keep advancing mnumi past any duplicates, but of course
|
|
||||||
* stop when we get to the end of the array.
|
|
||||||
*/
|
|
||||||
while (mnumi < mnum.length && mnum[mnumi] <= oldnum)
|
|
||||||
mnumi++; // consider next message in array
|
|
||||||
} else {
|
|
||||||
// keep this message
|
|
||||||
if (newnum != oldnum) {
|
|
||||||
// move message down in the array (compact array)
|
|
||||||
messages[newnum-1] = messages[oldnum-1];
|
|
||||||
if (messages[newnum-1] != null)
|
|
||||||
messages[newnum-1].setMessageNumber(newnum);
|
|
||||||
if (seqnums != null)
|
|
||||||
seqnums[newnum-1] = seqnums[oldnum-1];
|
|
||||||
}
|
|
||||||
if (seqnums != null && seqnums[newnum-1] != newnum)
|
|
||||||
keepSeqnums = true;
|
|
||||||
newnum++;
|
|
||||||
}
|
|
||||||
oldnum++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!keepSeqnums)
|
|
||||||
seqnums = null;
|
|
||||||
shrink(newnum, oldnum);
|
|
||||||
|
|
||||||
IMAPMessage[] rmsgs = new IMAPMessage[mlist.size()];
|
|
||||||
if (logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("return " + rmsgs.length);
|
|
||||||
mlist.toArray(rmsgs);
|
|
||||||
return rmsgs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shrink the messages and seqnums arrays. newend is one past last
|
|
||||||
* valid element. oldend is one past the previous last valid element.
|
|
||||||
*/
|
|
||||||
private void shrink(int newend, int oldend) {
|
|
||||||
size = newend - 1;
|
|
||||||
if (logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("size now " + size);
|
|
||||||
if (size == 0) { // no messages left
|
|
||||||
messages = null;
|
|
||||||
seqnums = null;
|
|
||||||
} else if (size > SLOP && size < messages.length / 2) {
|
|
||||||
// if array shrinks by too much, reallocate it
|
|
||||||
logger.fine("reallocate array");
|
|
||||||
IMAPMessage[] newm = new IMAPMessage[size + SLOP];
|
|
||||||
System.arraycopy(messages, 0, newm, 0, size);
|
|
||||||
messages = newm;
|
|
||||||
if (seqnums != null) {
|
|
||||||
int[] news = new int[size + SLOP];
|
|
||||||
System.arraycopy(seqnums, 0, news, 0, size);
|
|
||||||
seqnums = news;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("clean " + newend + " to " + oldend);
|
|
||||||
// clear out unused entries in array
|
|
||||||
for (int msgnum = newend; msgnum < oldend; msgnum++) {
|
|
||||||
messages[msgnum-1] = null;
|
|
||||||
if (seqnums != null)
|
|
||||||
seqnums[msgnum-1] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add count messages to the cache.
|
|
||||||
* newSeqNum is the sequence number of the first message added.
|
|
||||||
*/
|
|
||||||
public void addMessages(int count, int newSeqNum) {
|
|
||||||
if (logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("add " + count + " messages");
|
|
||||||
// don't have to do anything other than making sure there's space
|
|
||||||
ensureCapacity(size + count, newSeqNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure the arrays are at least big enough to hold
|
|
||||||
* "newsize" messages.
|
|
||||||
*/
|
|
||||||
private void ensureCapacity(int newsize, int newSeqNum) {
|
|
||||||
if (messages == null)
|
|
||||||
messages = new IMAPMessage[newsize + SLOP];
|
|
||||||
else if (messages.length < newsize) {
|
|
||||||
if (logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("expand capacity to " + newsize);
|
|
||||||
IMAPMessage[] newm = new IMAPMessage[newsize + SLOP];
|
|
||||||
System.arraycopy(messages, 0, newm, 0, messages.length);
|
|
||||||
messages = newm;
|
|
||||||
if (seqnums != null) {
|
|
||||||
int[] news = new int[newsize + SLOP];
|
|
||||||
System.arraycopy(seqnums, 0, news, 0, seqnums.length);
|
|
||||||
for (int i = size; i < news.length; i++)
|
|
||||||
news[i] = newSeqNum++;
|
|
||||||
seqnums = news;
|
|
||||||
if (logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("message " + newsize +
|
|
||||||
" has sequence number " + seqnums[newsize-1]);
|
|
||||||
}
|
|
||||||
} else if (newsize < size) { // shrinking?
|
|
||||||
// this should never happen
|
|
||||||
if (logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("shrink capacity to " + newsize);
|
|
||||||
for (int msgnum = newsize + 1; msgnum <= size; msgnum++) {
|
|
||||||
messages[msgnum-1] = null;
|
|
||||||
if (seqnums != null)
|
|
||||||
seqnums[msgnum-1] = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
size = newsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the sequence number for the given message number.
|
|
||||||
*/
|
|
||||||
public int seqnumOf(int msgnum) {
|
|
||||||
if (seqnums == null)
|
|
||||||
return msgnum;
|
|
||||||
else {
|
|
||||||
if (logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("msgnum " + msgnum + " is seqnum " +
|
|
||||||
seqnums[msgnum-1]);
|
|
||||||
return seqnums[msgnum-1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the message number for the given sequence number.
|
|
||||||
*/
|
|
||||||
private int msgnumOf(int seqnum) {
|
|
||||||
if (seqnums == null)
|
|
||||||
return seqnum;
|
|
||||||
if (seqnum < 1) { // should never happen
|
|
||||||
if (logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("bad seqnum " + seqnum);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
for (int msgnum = seqnum; msgnum <= size; msgnum++) {
|
|
||||||
if (seqnums[msgnum-1] == seqnum)
|
|
||||||
return msgnum;
|
|
||||||
if (seqnums[msgnum-1] > seqnum)
|
|
||||||
break; // message doesn't exist
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,460 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Rights class represents the set of rights for an authentication
|
|
||||||
* identifier (for instance, a user or a group). <p>
|
|
||||||
*
|
|
||||||
* A right is represented by the <code>Rights.Right</code>
|
|
||||||
* inner class. <p>
|
|
||||||
*
|
|
||||||
* A set of standard rights are predefined (see RFC 2086). Most folder
|
|
||||||
* implementations are expected to support these rights. Some
|
|
||||||
* implementations may also support site-defined rights. <p>
|
|
||||||
*
|
|
||||||
* The following code sample illustrates how to examine your
|
|
||||||
* rights for a folder. <p>
|
|
||||||
* <pre>
|
|
||||||
*
|
|
||||||
* Rights rights = folder.myRights();
|
|
||||||
*
|
|
||||||
* // Check if I can write this folder
|
|
||||||
* if (rights.contains(Rights.Right.WRITE))
|
|
||||||
* System.out.println("Can write folder");
|
|
||||||
*
|
|
||||||
* // Now give Joe all my rights, except the ability to write the folder
|
|
||||||
* rights.remove(Rights.Right.WRITE);
|
|
||||||
* ACL acl = new ACL("joe", rights);
|
|
||||||
* folder.setACL(acl);
|
|
||||||
* </pre>
|
|
||||||
* <p>
|
|
||||||
*
|
|
||||||
* @author Bill Shannon
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class Rights implements Cloneable {
|
|
||||||
|
|
||||||
private boolean[] rights = new boolean[128]; // XXX
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This inner class represents an individual right. A set
|
|
||||||
* of standard rights objects are predefined here.
|
|
||||||
*/
|
|
||||||
public static final class Right {
|
|
||||||
private static Right[] cache = new Right[128];
|
|
||||||
|
|
||||||
// XXX - initialization order?
|
|
||||||
/**
|
|
||||||
* Lookup - mailbox is visible to LIST/LSUB commands.
|
|
||||||
*/
|
|
||||||
public static final Right LOOKUP = getInstance('l');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read - SELECT the mailbox, perform CHECK, FETCH, PARTIAL,
|
|
||||||
* SEARCH, COPY from mailbox
|
|
||||||
*/
|
|
||||||
public static final Right READ = getInstance('r');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Keep seen/unseen information across sessions - STORE \SEEN flag.
|
|
||||||
*/
|
|
||||||
public static final Right KEEP_SEEN = getInstance('s');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write - STORE flags other than \SEEN and \DELETED.
|
|
||||||
*/
|
|
||||||
public static final Right WRITE = getInstance('w');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert - perform APPEND, COPY into mailbox.
|
|
||||||
*/
|
|
||||||
public static final Right INSERT = getInstance('i');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Post - send mail to submission address for mailbox,
|
|
||||||
* not enforced by IMAP4 itself.
|
|
||||||
*/
|
|
||||||
public static final Right POST = getInstance('p');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create - CREATE new sub-mailboxes in any implementation-defined
|
|
||||||
* hierarchy, RENAME or DELETE mailbox.
|
|
||||||
*/
|
|
||||||
public static final Right CREATE = getInstance('c');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete - STORE \DELETED flag, perform EXPUNGE.
|
|
||||||
*/
|
|
||||||
public static final Right DELETE = getInstance('d');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Administer - perform SETACL.
|
|
||||||
*/
|
|
||||||
public static final Right ADMINISTER = getInstance('a');
|
|
||||||
|
|
||||||
char right; // the right represented by this Right object
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private constructor used only by getInstance.
|
|
||||||
*/
|
|
||||||
private Right(char right) {
|
|
||||||
if ((int)right >= 128)
|
|
||||||
throw new IllegalArgumentException("Right must be ASCII");
|
|
||||||
this.right = right;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a Right object representing the specified character.
|
|
||||||
* Characters are assigned per RFC 2086.
|
|
||||||
*/
|
|
||||||
public static synchronized Right getInstance(char right) {
|
|
||||||
if ((int)right >= 128)
|
|
||||||
throw new IllegalArgumentException("Right must be ASCII");
|
|
||||||
if (cache[(int)right] == null)
|
|
||||||
cache[(int)right] = new Right(right);
|
|
||||||
return cache[(int)right];
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return String.valueOf(right);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct an empty Rights object.
|
|
||||||
*/
|
|
||||||
public Rights() { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a Rights object initialized with the given rights.
|
|
||||||
*
|
|
||||||
* @param rights the rights for initialization
|
|
||||||
*/
|
|
||||||
public Rights(Rights rights) {
|
|
||||||
System.arraycopy(rights.rights, 0, this.rights, 0, this.rights.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a Rights object initialized with the given rights.
|
|
||||||
*
|
|
||||||
* @param rights the rights for initialization
|
|
||||||
*/
|
|
||||||
public Rights(String rights) {
|
|
||||||
for (int i = 0; i < rights.length(); i++)
|
|
||||||
add(Right.getInstance(rights.charAt(i)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a Rights object initialized with the given right.
|
|
||||||
*
|
|
||||||
* @param right the right for initialization
|
|
||||||
*/
|
|
||||||
public Rights(Right right) {
|
|
||||||
this.rights[(int)right.right] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add the specified right to this Rights object.
|
|
||||||
*
|
|
||||||
* @param right the right to add
|
|
||||||
*/
|
|
||||||
public void add(Right right) {
|
|
||||||
this.rights[(int)right.right] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add all the rights in the given Rights object to this
|
|
||||||
* Rights object.
|
|
||||||
*
|
|
||||||
* @param rights Rights object
|
|
||||||
*/
|
|
||||||
public void add(Rights rights) {
|
|
||||||
for (int i = 0; i < rights.rights.length; i++)
|
|
||||||
if (rights.rights[i])
|
|
||||||
this.rights[i] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the specified right from this Rights object.
|
|
||||||
*
|
|
||||||
* @param right the right to be removed
|
|
||||||
*/
|
|
||||||
public void remove(Right right) {
|
|
||||||
this.rights[(int)right.right] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove all rights in the given Rights object from this
|
|
||||||
* Rights object.
|
|
||||||
*
|
|
||||||
* @param rights the rights to be removed
|
|
||||||
*/
|
|
||||||
public void remove(Rights rights) {
|
|
||||||
for (int i = 0; i < rights.rights.length; i++)
|
|
||||||
if (rights.rights[i])
|
|
||||||
this.rights[i] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether the specified right is present in this Rights object.
|
|
||||||
*
|
|
||||||
* @return true of the given right is present, otherwise false.
|
|
||||||
*/
|
|
||||||
public boolean contains(Right right) {
|
|
||||||
return this.rights[(int)right.right];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether all the rights in the specified Rights object are
|
|
||||||
* present in this Rights object.
|
|
||||||
*
|
|
||||||
* @return true if all rights in the given Rights object are present,
|
|
||||||
* otherwise false.
|
|
||||||
*/
|
|
||||||
public boolean contains(Rights rights) {
|
|
||||||
for (int i = 0; i < rights.rights.length; i++)
|
|
||||||
if (rights.rights[i] && !this.rights[i])
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// If we've made it till here, return true
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether the two Rights objects are equal.
|
|
||||||
*
|
|
||||||
* @return true if they're equal
|
|
||||||
*/
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (!(obj instanceof Rights))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Rights rights = (Rights)obj;
|
|
||||||
|
|
||||||
for (int i = 0; i < rights.rights.length; i++)
|
|
||||||
if (rights.rights[i] != this.rights[i])
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compute a hash code for this Rights object.
|
|
||||||
*
|
|
||||||
* @return the hash code
|
|
||||||
*/
|
|
||||||
public int hashCode() {
|
|
||||||
int hash = 0;
|
|
||||||
for (int i = 0; i < this.rights.length; i++)
|
|
||||||
if (this.rights[i])
|
|
||||||
hash++;
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return all the rights in this Rights object. Returns
|
|
||||||
* an array of size zero if no rights are set.
|
|
||||||
*
|
|
||||||
* @return array of Rights.Right objects representing rights
|
|
||||||
*/
|
|
||||||
public Right[] getRights() {
|
|
||||||
Vector v = new Vector();
|
|
||||||
for (int i = 0; i < this.rights.length; i++)
|
|
||||||
if (this.rights[i])
|
|
||||||
v.addElement(Right.getInstance((char)i));
|
|
||||||
Right[] rights = new Right[v.size()];
|
|
||||||
v.copyInto(rights);
|
|
||||||
return rights;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a clone of this Rights object.
|
|
||||||
*/
|
|
||||||
public Object clone() {
|
|
||||||
Rights r = null;
|
|
||||||
try {
|
|
||||||
r = (Rights)super.clone();
|
|
||||||
r.rights = new boolean[128];
|
|
||||||
System.arraycopy(this.rights, 0, r.rights, 0, this.rights.length);
|
|
||||||
} catch (CloneNotSupportedException cex) {
|
|
||||||
// ignore, can't happen
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
StringBuffer sb = new StringBuffer();
|
|
||||||
for (int i = 0; i < this.rights.length; i++)
|
|
||||||
if (this.rights[i])
|
|
||||||
sb.append((char)i);
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****
|
|
||||||
public static void main(String argv[]) throws Exception {
|
|
||||||
// a new rights object
|
|
||||||
Rights f1 = new Rights();
|
|
||||||
f1.add(Rights.Right.READ);
|
|
||||||
f1.add(Rights.Right.WRITE);
|
|
||||||
f1.add(Rights.Right.CREATE);
|
|
||||||
f1.add(Rights.Right.DELETE);
|
|
||||||
|
|
||||||
// check copy constructor
|
|
||||||
Rights fc = new Rights(f1);
|
|
||||||
if (f1.equals(fc) && fc.equals(f1))
|
|
||||||
System.out.println("success");
|
|
||||||
else
|
|
||||||
System.out.println("fail");
|
|
||||||
|
|
||||||
// check clone
|
|
||||||
fc = (Rights)f1.clone();
|
|
||||||
if (f1.equals(fc) && fc.equals(f1))
|
|
||||||
System.out.println("success");
|
|
||||||
else
|
|
||||||
System.out.println("fail");
|
|
||||||
|
|
||||||
// add a right and make sure it still works right
|
|
||||||
f1.add(Rights.Right.ADMINISTER);
|
|
||||||
|
|
||||||
// shouldn't be equal here
|
|
||||||
if (!f1.equals(fc) && !fc.equals(f1))
|
|
||||||
System.out.println("success");
|
|
||||||
else
|
|
||||||
System.out.println("fail");
|
|
||||||
|
|
||||||
// check clone
|
|
||||||
fc = (Rights)f1.clone();
|
|
||||||
if (f1.equals(fc) && fc.equals(f1))
|
|
||||||
System.out.println("success");
|
|
||||||
else
|
|
||||||
System.out.println("fail");
|
|
||||||
|
|
||||||
fc.add(Rights.Right.INSERT);
|
|
||||||
if (!f1.equals(fc) && !fc.equals(f1))
|
|
||||||
System.out.println("success");
|
|
||||||
else
|
|
||||||
System.out.println("fail");
|
|
||||||
|
|
||||||
// check copy constructor
|
|
||||||
fc = new Rights(f1);
|
|
||||||
if (f1.equals(fc) && fc.equals(f1))
|
|
||||||
System.out.println("success");
|
|
||||||
else
|
|
||||||
System.out.println("fail");
|
|
||||||
|
|
||||||
// another new rights object
|
|
||||||
Rights f2 = new Rights(Rights.Right.READ);
|
|
||||||
f2.add(Rights.Right.WRITE);
|
|
||||||
|
|
||||||
if (f1.contains(Rights.Right.READ))
|
|
||||||
System.out.println("success");
|
|
||||||
else
|
|
||||||
System.out.println("fail");
|
|
||||||
|
|
||||||
if (f1.contains(Rights.Right.WRITE))
|
|
||||||
System.out.println("success");
|
|
||||||
else
|
|
||||||
System.out.println("fail");
|
|
||||||
|
|
||||||
if (f1.contains(Rights.Right.CREATE))
|
|
||||||
System.out.println("success");
|
|
||||||
else
|
|
||||||
System.out.println("fail");
|
|
||||||
|
|
||||||
if (f1.contains(Rights.Right.DELETE))
|
|
||||||
System.out.println("success");
|
|
||||||
else
|
|
||||||
System.out.println("fail");
|
|
||||||
|
|
||||||
if (f2.contains(Rights.Right.WRITE))
|
|
||||||
System.out.println("success");
|
|
||||||
else
|
|
||||||
System.out.println("fail");
|
|
||||||
|
|
||||||
|
|
||||||
System.out.println("----------------");
|
|
||||||
|
|
||||||
Right[] r = f1.getRights();
|
|
||||||
for (int i = 0; i < r.length; i++)
|
|
||||||
System.out.println(r[i]);
|
|
||||||
System.out.println("----------------");
|
|
||||||
|
|
||||||
if (f1.contains(f2)) // this should be true
|
|
||||||
System.out.println("success");
|
|
||||||
else
|
|
||||||
System.out.println("fail");
|
|
||||||
|
|
||||||
if (!f2.contains(f1)) // this should be false
|
|
||||||
System.out.println("success");
|
|
||||||
else
|
|
||||||
System.out.println("fail");
|
|
||||||
|
|
||||||
Rights f3 = new Rights();
|
|
||||||
f3.add(Rights.Right.READ);
|
|
||||||
f3.add(Rights.Right.WRITE);
|
|
||||||
f3.add(Rights.Right.CREATE);
|
|
||||||
f3.add(Rights.Right.DELETE);
|
|
||||||
f3.add(Rights.Right.ADMINISTER);
|
|
||||||
f3.add(Rights.Right.LOOKUP);
|
|
||||||
|
|
||||||
f1.add(Rights.Right.LOOKUP);
|
|
||||||
|
|
||||||
if (f1.equals(f3))
|
|
||||||
System.out.println("equals success");
|
|
||||||
else
|
|
||||||
System.out.println("fail");
|
|
||||||
if (f3.equals(f1))
|
|
||||||
System.out.println("equals success");
|
|
||||||
else
|
|
||||||
System.out.println("fail");
|
|
||||||
System.out.println("f1 hash code " + f1.hashCode());
|
|
||||||
System.out.println("f3 hash code " + f3.hashCode());
|
|
||||||
if (f1.hashCode() == f3.hashCode())
|
|
||||||
System.out.println("success");
|
|
||||||
else
|
|
||||||
System.out.println("fail");
|
|
||||||
}
|
|
||||||
****/
|
|
||||||
}
|
|
||||||
@ -1,104 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A particular sort criteria, as defined by
|
|
||||||
* <A HREF="http://www.ietf.org/rfc/rfc5256.txt">RFC 5256</A>.
|
|
||||||
* Sort criteria are used with the
|
|
||||||
* {@link IMAPFolder#getSortedMessages getSortedMessages} method.
|
|
||||||
* Multiple sort criteria are specified in an array with the order in
|
|
||||||
* the array specifying the order in which the sort criteria are applied.
|
|
||||||
*
|
|
||||||
* @since JavaMail 1.4.4
|
|
||||||
*/
|
|
||||||
public final class SortTerm {
|
|
||||||
/**
|
|
||||||
* Sort by message arrival date and time.
|
|
||||||
*/
|
|
||||||
public static final SortTerm ARRIVAL = new SortTerm("ARRIVAL");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sort by email address of first Cc recipient.
|
|
||||||
*/
|
|
||||||
public static final SortTerm CC = new SortTerm("CC");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sort by sent date and time.
|
|
||||||
*/
|
|
||||||
public static final SortTerm DATE = new SortTerm("DATE");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sort by first From email address.
|
|
||||||
*/
|
|
||||||
public static final SortTerm FROM = new SortTerm("FROM");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the sort order of the following item.
|
|
||||||
*/
|
|
||||||
public static final SortTerm REVERSE = new SortTerm("REVERSE");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sort by the message size.
|
|
||||||
*/
|
|
||||||
public static final SortTerm SIZE = new SortTerm("SIZE");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sort by the base subject text. Note that the "base subject"
|
|
||||||
* is defined by RFC 5256 and doesn't include items such as "Re:"
|
|
||||||
* in the subject header.
|
|
||||||
*/
|
|
||||||
public static final SortTerm SUBJECT = new SortTerm("SUBJECT");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sort by email address of first To recipient.
|
|
||||||
*/
|
|
||||||
public static final SortTerm TO = new SortTerm("TO");
|
|
||||||
|
|
||||||
private String term;
|
|
||||||
private SortTerm(String term) {
|
|
||||||
this.term = term;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return term;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,186 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap;
|
|
||||||
|
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
import javax.mail.*;
|
|
||||||
|
|
||||||
import com.sun.mail.util.*;
|
|
||||||
import com.sun.mail.imap.protocol.MessageSet;
|
|
||||||
import com.sun.mail.imap.protocol.UIDSet;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holder for some static utility methods.
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
* @author Bill Shannon
|
|
||||||
*/
|
|
||||||
|
|
||||||
public final class Utility {
|
|
||||||
|
|
||||||
// Cannot be initialized
|
|
||||||
private Utility() { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run thru the given array of messages, apply the given
|
|
||||||
* Condition on each message and generate sets of contiguous
|
|
||||||
* sequence-numbers for the successful messages. If a message
|
|
||||||
* in the given array is found to be expunged, it is ignored.
|
|
||||||
*
|
|
||||||
* ASSERT: Since this method uses and returns message sequence
|
|
||||||
* numbers, you should use this method only when holding the
|
|
||||||
* messageCacheLock.
|
|
||||||
*/
|
|
||||||
public static
|
|
||||||
MessageSet[] toMessageSet(Message[] msgs, Condition cond) {
|
|
||||||
Vector v = new Vector(1);
|
|
||||||
int current, next;
|
|
||||||
|
|
||||||
IMAPMessage msg;
|
|
||||||
for (int i = 0; i < msgs.length; i++) {
|
|
||||||
msg = (IMAPMessage)msgs[i];
|
|
||||||
if (msg.isExpunged()) // expunged message, skip it
|
|
||||||
continue;
|
|
||||||
|
|
||||||
current = msg.getSequenceNumber();
|
|
||||||
// Apply the condition. If it fails, skip it.
|
|
||||||
if ((cond != null) && !cond.test(msg))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
MessageSet set = new MessageSet();
|
|
||||||
set.start = current;
|
|
||||||
|
|
||||||
// Look for contiguous sequence numbers
|
|
||||||
for (++i; i < msgs.length; i++) {
|
|
||||||
// get next message
|
|
||||||
msg = (IMAPMessage)msgs[i];
|
|
||||||
|
|
||||||
if (msg.isExpunged()) // expunged message, skip it
|
|
||||||
continue;
|
|
||||||
next = msg.getSequenceNumber();
|
|
||||||
|
|
||||||
// Does this message match our condition ?
|
|
||||||
if ((cond != null) && !cond.test(msg))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (next == current+1)
|
|
||||||
current = next;
|
|
||||||
else { // break in sequence
|
|
||||||
// We need to reexamine this message at the top of
|
|
||||||
// the outer loop, so decrement 'i' to cancel the
|
|
||||||
// outer loop's autoincrement
|
|
||||||
i--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
set.end = current;
|
|
||||||
v.addElement(set);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v.isEmpty()) // No valid messages
|
|
||||||
return null;
|
|
||||||
else {
|
|
||||||
MessageSet[] sets = new MessageSet[v.size()];
|
|
||||||
v.copyInto(sets);
|
|
||||||
return sets;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return UIDSets for the messages. Note that the UIDs
|
|
||||||
* must have already been fetched for the messages.
|
|
||||||
*/
|
|
||||||
public static UIDSet[] toUIDSet(Message[] msgs) {
|
|
||||||
Vector v = new Vector(1);
|
|
||||||
long current, next;
|
|
||||||
|
|
||||||
IMAPMessage msg;
|
|
||||||
for (int i = 0; i < msgs.length; i++) {
|
|
||||||
msg = (IMAPMessage)msgs[i];
|
|
||||||
if (msg.isExpunged()) // expunged message, skip it
|
|
||||||
continue;
|
|
||||||
|
|
||||||
current = msg.getUID();
|
|
||||||
|
|
||||||
UIDSet set = new UIDSet();
|
|
||||||
set.start = current;
|
|
||||||
|
|
||||||
// Look for contiguous UIDs
|
|
||||||
for (++i; i < msgs.length; i++) {
|
|
||||||
// get next message
|
|
||||||
msg = (IMAPMessage)msgs[i];
|
|
||||||
|
|
||||||
if (msg.isExpunged()) // expunged message, skip it
|
|
||||||
continue;
|
|
||||||
next = msg.getUID();
|
|
||||||
|
|
||||||
if (next == current+1)
|
|
||||||
current = next;
|
|
||||||
else { // break in sequence
|
|
||||||
// We need to reexamine this message at the top of
|
|
||||||
// the outer loop, so decrement 'i' to cancel the
|
|
||||||
// outer loop's autoincrement
|
|
||||||
i--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
set.end = current;
|
|
||||||
v.addElement(set);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v.isEmpty()) // No valid messages
|
|
||||||
return null;
|
|
||||||
else {
|
|
||||||
UIDSet[] sets = new UIDSet[v.size()];
|
|
||||||
v.copyInto(sets);
|
|
||||||
return sets;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This interface defines the test to be executed in
|
|
||||||
* <code>toMessageSet()</code>.
|
|
||||||
*/
|
|
||||||
public static interface Condition {
|
|
||||||
public boolean test(IMAPMessage message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,623 +0,0 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
|
||||||
<HTML>
|
|
||||||
<HEAD>
|
|
||||||
<!--
|
|
||||||
|
|
||||||
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
|
|
||||||
Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
|
|
||||||
The contents of this file are subject to the terms of either the GNU
|
|
||||||
General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
may not use this file except in compliance with the License. You can
|
|
||||||
obtain a copy of the License at
|
|
||||||
https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
language governing permissions and limitations under the License.
|
|
||||||
|
|
||||||
When distributing the software, include this License Header Notice in each
|
|
||||||
file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
|
|
||||||
GPL Classpath Exception:
|
|
||||||
Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
file that accompanied this code.
|
|
||||||
|
|
||||||
Modifications:
|
|
||||||
If applicable, add the following below the License Header, with the fields
|
|
||||||
enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
"Portions Copyright [year] [name of copyright owner]"
|
|
||||||
|
|
||||||
Contributor(s):
|
|
||||||
If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
recipient has the option to distribute your version of this file under
|
|
||||||
either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
only if the new code is made subject to such option by the copyright
|
|
||||||
holder.
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
</HEAD>
|
|
||||||
<BODY BGCOLOR="white">
|
|
||||||
|
|
||||||
An IMAP protocol provider for the JavaMail API
|
|
||||||
that provides access to an IMAP message store.
|
|
||||||
Both the IMAP4 and IMAP4rev1 protocols are supported.
|
|
||||||
Refer to <A HREF="http://www.ietf.org/rfc/rfc2060.txt" TARGET="_top">
|
|
||||||
RFC 2060</A>
|
|
||||||
for more information.
|
|
||||||
<P>
|
|
||||||
The IMAP protocol provider can use SASL
|
|
||||||
(<A HREF="http://www.ietf.org/rfc/rfc2222.txt" TARGET="_top">RFC 2222</A>)
|
|
||||||
authentication mechanisms on systems that support the
|
|
||||||
<CODE>javax.security.sasl</CODE> APIs, such as J2SE 5.0.
|
|
||||||
In addition to the SASL mechanisms that are built into
|
|
||||||
the SASL implementation, users can also provide additional
|
|
||||||
SASL mechanisms of their own design to support custom authentication
|
|
||||||
schemes. See the
|
|
||||||
<A HREF="http://docs.oracle.com/javase/1.5.0/docs/guide/security/sasl/sasl-refguide.html" TARGET="_top">
|
|
||||||
Java SASL API Programming and Deployment Guide</A> for details.
|
|
||||||
Note that the current implementation doesn't support SASL mechanisms
|
|
||||||
that provide their own integrity or confidentiality layer.
|
|
||||||
<P>
|
|
||||||
A connected IMAPStore maintains a pool of IMAP protocol objects for
|
|
||||||
use in communicating with the IMAP server. The IMAPStore will create
|
|
||||||
the initial AUTHENTICATED connection and seed the pool with this
|
|
||||||
connection. As folders are opened and new IMAP protocol objects are
|
|
||||||
needed, the IMAPStore will provide them from the connection pool,
|
|
||||||
or create them if none are available. When a folder is closed,
|
|
||||||
its IMAP protocol object is returned to the connection pool if the
|
|
||||||
pool is not over capacity.
|
|
||||||
<P>
|
|
||||||
A mechanism is provided for timing out idle connection pool IMAP
|
|
||||||
protocol objects. Timed out connections are closed and removed (pruned)
|
|
||||||
from the connection pool.
|
|
||||||
<P>
|
|
||||||
The connected IMAPStore object may or may not maintain a separate IMAP
|
|
||||||
protocol object that provides the store a dedicated connection to the
|
|
||||||
IMAP server. This is provided mainly for compatibility with previous
|
|
||||||
implementations of the IMAP protocol provider.
|
|
||||||
<P>
|
|
||||||
The IMAP protocol provider supports the following properties,
|
|
||||||
which may be set in the JavaMail <code>Session</code> object.
|
|
||||||
The properties are always set as strings; the Type column describes
|
|
||||||
how the string is interpreted. For example, use
|
|
||||||
<PRE>
|
|
||||||
props.put("mail.imap.port", "888");
|
|
||||||
</PRE>
|
|
||||||
to set the <CODE>mail.imap.port</CODE> property, which is of type int.
|
|
||||||
<P>
|
|
||||||
Note that if you're using the "imaps" protocol to access IMAP over SSL,
|
|
||||||
all the properties would be named "mail.imaps.*".
|
|
||||||
<P>
|
|
||||||
<TABLE BORDER>
|
|
||||||
<TR>
|
|
||||||
<TH>Name</TH>
|
|
||||||
<TH>Type</TH>
|
|
||||||
<TH>Description</TH>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.user</TD>
|
|
||||||
<TD>String</TD>
|
|
||||||
<TD>Default user name for IMAP.</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.host</TD>
|
|
||||||
<TD>String</TD>
|
|
||||||
<TD>The IMAP server to connect to.</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.port</TD>
|
|
||||||
<TD>int</TD>
|
|
||||||
<TD>The IMAP server port to connect to, if the connect() method doesn't
|
|
||||||
explicitly specify one. Defaults to 143.</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.partialfetch</TD>
|
|
||||||
<TD>boolean</TD>
|
|
||||||
<TD>Controls whether the IMAP partial-fetch capability should be used.
|
|
||||||
Defaults to true.</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.fetchsize</TD>
|
|
||||||
<TD>int</TD>
|
|
||||||
<TD>Partial fetch size in bytes. Defaults to 16K.</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.ignorebodystructuresize</TD>
|
|
||||||
<TD>boolean</TD>
|
|
||||||
<TD>The IMAP BODYSTRUCTURE response includes the exact size of each body part.
|
|
||||||
Normally, this size is used to determine how much data to fetch for each
|
|
||||||
body part.
|
|
||||||
Some servers report this size incorrectly in some cases; this property can
|
|
||||||
be set to work around such server bugs.
|
|
||||||
If this property is set to true, this size is ignored and data is fetched
|
|
||||||
until the server reports the end of data.
|
|
||||||
This will result in an extra fetch if the data size is a multiple of the
|
|
||||||
block size.
|
|
||||||
Defaults to false.</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.connectiontimeout</TD>
|
|
||||||
<TD>int</TD>
|
|
||||||
<TD>Socket connection timeout value in milliseconds.
|
|
||||||
Default is infinite timeout.</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.timeout</TD>
|
|
||||||
<TD>int</TD>
|
|
||||||
<TD>Socket I/O timeout value in milliseconds. Default is infinite timeout.</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.statuscachetimeout</TD>
|
|
||||||
<TD>int</TD>
|
|
||||||
<TD>Timeout value in milliseconds for cache of STATUS command response.
|
|
||||||
Default is 1000 (1 second). Zero disables cache.</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.appendbuffersize</TD>
|
|
||||||
<TD>int</TD>
|
|
||||||
<TD>
|
|
||||||
Maximum size of a message to buffer in memory when appending to an IMAP
|
|
||||||
folder. If not set, or set to -1, there is no maximum and all messages
|
|
||||||
are buffered. If set to 0, no messages are buffered. If set to (e.g.)
|
|
||||||
8192, messages of 8K bytes or less are buffered, larger messages are
|
|
||||||
not buffered. Buffering saves cpu time at the expense of short term
|
|
||||||
memory usage. If you commonly append very large messages to IMAP
|
|
||||||
mailboxes you might want to set this to a moderate value (1M or less).
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.connectionpoolsize</TD>
|
|
||||||
<TD>int</TD>
|
|
||||||
<TD>Maximum number of available connections in the connection pool.
|
|
||||||
Default is 1.</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.connectionpooltimeout</TD>
|
|
||||||
<TD>int</TD>
|
|
||||||
<TD>Timeout value in milliseconds for connection pool connections. Default
|
|
||||||
is 45000 (45 seconds).</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.separatestoreconnection</TD>
|
|
||||||
<TD>boolean</TD>
|
|
||||||
<TD>Flag to indicate whether to use a dedicated store connection for store
|
|
||||||
commands. Default is false.</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.allowreadonlyselect</TD>
|
|
||||||
<TD>boolean</TD>
|
|
||||||
<TD>If false, attempts to open a folder read/write will fail
|
|
||||||
if the SELECT command succeeds but indicates that the folder is READ-ONLY.
|
|
||||||
This sometimes indicates that the folder contents can'tbe changed, but
|
|
||||||
the flags are per-user and can be changed, such as might be the case for
|
|
||||||
public shared folders. If true, such open attempts will succeed, allowing
|
|
||||||
the flags to be changed. The <code>getMode</code> method on the
|
|
||||||
<code>Folder</code> object will return <code>Folder.READ_ONLY</code>
|
|
||||||
in this case even though the <code>open</code> method specified
|
|
||||||
<code>Folder.READ_WRITE</code>. Default is false.</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.auth.login.disable</TD>
|
|
||||||
<TD>boolean</TD>
|
|
||||||
<TD>If true, prevents use of the non-standard <code>AUTHENTICATE LOGIN</code>
|
|
||||||
command, instead using the plain <code>LOGIN</code> command.
|
|
||||||
Default is false.</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.auth.plain.disable</TD>
|
|
||||||
<TD>boolean</TD>
|
|
||||||
<TD>If true, prevents use of the <code>AUTHENTICATE PLAIN</code> command.
|
|
||||||
Default is false.</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.auth.ntlm.disable</TD>
|
|
||||||
<TD>boolean</TD>
|
|
||||||
<TD>If true, prevents use of the <code>AUTHENTICATE NTLM</code> command.
|
|
||||||
Default is false.</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.proxyauth.user</TD>
|
|
||||||
<TD>String</TD>
|
|
||||||
<TD>If the server supports the PROXYAUTH extension, this property
|
|
||||||
specifies the name of the user to act as. Authenticate to the
|
|
||||||
server using the administrator's credentials. After authentication,
|
|
||||||
the IMAP provider will issue the <code>PROXYAUTH</code> command with
|
|
||||||
the user name specified in this property.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.localaddress</TD>
|
|
||||||
<TD>String</TD>
|
|
||||||
<TD>
|
|
||||||
Local address (host name) to bind to when creating the IMAP socket.
|
|
||||||
Defaults to the address picked by the Socket class.
|
|
||||||
Should not normally need to be set, but useful with multi-homed hosts
|
|
||||||
where it's important to pick a particular local address to bind to.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.localport</TD>
|
|
||||||
<TD>int</TD>
|
|
||||||
<TD>
|
|
||||||
Local port number to bind to when creating the IMAP socket.
|
|
||||||
Defaults to the port number picked by the Socket class.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.sasl.enable</TD>
|
|
||||||
<TD>boolean</TD>
|
|
||||||
<TD>
|
|
||||||
If set to true, attempt to use the javax.security.sasl package to
|
|
||||||
choose an authentication mechanism for login.
|
|
||||||
Defaults to false.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.sasl.mechanisms</TD>
|
|
||||||
<TD>String</TD>
|
|
||||||
<TD>
|
|
||||||
A space or comma separated list of SASL mechanism names to try
|
|
||||||
to use.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.sasl.authorizationid</TD>
|
|
||||||
<TD>String</TD>
|
|
||||||
<TD>
|
|
||||||
The authorization ID to use in the SASL authentication.
|
|
||||||
If not set, the authentication ID (user name) is used.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.sasl.realm</TD>
|
|
||||||
<TD>String</TD>
|
|
||||||
<TD>The realm to use with SASL authentication mechanisms that
|
|
||||||
require a realm, such as DIGEST-MD5.</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.sasl. xgwtrustedapphack.enable</TD>
|
|
||||||
<TD>boolean</TD>
|
|
||||||
<TD>
|
|
||||||
If set to true, enables a workaround for a bug in the Novell Groupwise
|
|
||||||
XGWTRUSTEDAPP SASL mechanism, when that mechanism is being used.
|
|
||||||
Defaults to true.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.auth.ntlm.domain</TD>
|
|
||||||
<TD>String</TD>
|
|
||||||
<TD>
|
|
||||||
The NTLM authentication domain.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.auth.ntlm.flags</TD>
|
|
||||||
<TD>int</TD>
|
|
||||||
<TD>
|
|
||||||
NTLM protocol-specific flags.
|
|
||||||
See <A HREF="http://curl.haxx.se/rfc/ntlm.html#theNtlmFlags" TARGET="_top">
|
|
||||||
http://curl.haxx.se/rfc/ntlm.html#theNtlmFlags</A> for details.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.socketFactory</TD>
|
|
||||||
<TD>SocketFactory</TD>
|
|
||||||
<TD>
|
|
||||||
If set to a class that implements the
|
|
||||||
<code>javax.net.SocketFactory</code> interface, this class
|
|
||||||
will be used to create IMAP sockets. Note that this is an
|
|
||||||
instance of a class, not a name, and must be set using the
|
|
||||||
<code>put</code> method, not the <code>setProperty</code> method.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.socketFactory.class</TD>
|
|
||||||
<TD>String</TD>
|
|
||||||
<TD>
|
|
||||||
If set, specifies the name of a class that implements the
|
|
||||||
<code>javax.net.SocketFactory</code> interface. This class
|
|
||||||
will be used to create IMAP sockets.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.socketFactory.fallback</TD>
|
|
||||||
<TD>boolean</TD>
|
|
||||||
<TD>
|
|
||||||
If set to true, failure to create a socket using the specified
|
|
||||||
socket factory class will cause the socket to be created using
|
|
||||||
the <code>java.net.Socket</code> class.
|
|
||||||
Defaults to true.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.socketFactory.port</TD>
|
|
||||||
<TD>int</TD>
|
|
||||||
<TD>
|
|
||||||
Specifies the port to connect to when using the specified socket
|
|
||||||
factory.
|
|
||||||
If not set, the default port will be used.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.ssl.enable</TD>
|
|
||||||
<TD>boolean</TD>
|
|
||||||
<TD>
|
|
||||||
If set to true, use SSL to connect and use the SSL port by default.
|
|
||||||
Defaults to false for the "imap" protocol and true for the "imaps" protocol.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.ssl.checkserveridentity</TD>
|
|
||||||
<TD>boolean</TD>
|
|
||||||
<TD>
|
|
||||||
If set to true, check the server identity as specified by
|
|
||||||
<A HREF="http://www.ietf.org/rfc/rfc2595.txt" TARGET="_top">RFC 2595</A>.
|
|
||||||
These additional checks based on the content of the server's certificate
|
|
||||||
are intended to prevent man-in-the-middle attacks.
|
|
||||||
Defaults to false.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.ssl.trust</TD>
|
|
||||||
<TD>String</TD>
|
|
||||||
<TD>
|
|
||||||
If set, and a socket factory hasn't been specified, enables use of a
|
|
||||||
{@link com.sun.mail.util.MailSSLSocketFactory MailSSLSocketFactory}.
|
|
||||||
If set to "*", all hosts are trusted.
|
|
||||||
If set to a whitespace separated list of hosts, those hosts are trusted.
|
|
||||||
Otherwise, trust depends on the certificate the server presents.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.ssl.socketFactory</TD>
|
|
||||||
<TD>SSLSocketFactory</TD>
|
|
||||||
<TD>
|
|
||||||
If set to a class that extends the
|
|
||||||
<code>javax.net.ssl.SSLSocketFactory</code> class, this class
|
|
||||||
will be used to create IMAP SSL sockets. Note that this is an
|
|
||||||
instance of a class, not a name, and must be set using the
|
|
||||||
<code>put</code> method, not the <code>setProperty</code> method.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.ssl.socketFactory.class</TD>
|
|
||||||
<TD>String</TD>
|
|
||||||
<TD>
|
|
||||||
If set, specifies the name of a class that extends the
|
|
||||||
<code>javax.net.ssl.SSLSocketFactory</code> class. This class
|
|
||||||
will be used to create IMAP SSL sockets.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.ssl.socketFactory.port</TD>
|
|
||||||
<TD>int</TD>
|
|
||||||
<TD>
|
|
||||||
Specifies the port to connect to when using the specified socket
|
|
||||||
factory.
|
|
||||||
If not set, the default port will be used.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.ssl.protocols</TD>
|
|
||||||
<TD>string</TD>
|
|
||||||
<TD>
|
|
||||||
Specifies the SSL protocols that will be enabled for SSL connections.
|
|
||||||
The property value is a whitespace separated list of tokens acceptable
|
|
||||||
to the <code>javax.net.ssl.SSLSocket.setEnabledProtocols</code> method.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.ssl.ciphersuites</TD>
|
|
||||||
<TD>string</TD>
|
|
||||||
<TD>
|
|
||||||
Specifies the SSL cipher suites that will be enabled for SSL connections.
|
|
||||||
The property value is a whitespace separated list of tokens acceptable
|
|
||||||
to the <code>javax.net.ssl.SSLSocket.setEnabledCipherSuites</code> method.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.starttls.enable</TD>
|
|
||||||
<TD>boolean</TD>
|
|
||||||
<TD>If true, enables the use of the <code>STARTTLS</code> command (if
|
|
||||||
supported by the server) to switch the connection to a TLS-protected
|
|
||||||
connection before issuing any login commands. Note that an appropriate
|
|
||||||
trust store must configured so that the client will trust the server's
|
|
||||||
certificate. This feature only works on J2SE 1.4 and newer systems.
|
|
||||||
Default is false.</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.starttls.required</TD>
|
|
||||||
<TD>boolean</TD>
|
|
||||||
<TD>
|
|
||||||
If true, requires the use of the <code>STARTTLS</code> command.
|
|
||||||
If the server doesn't support the STARTTLS command, or the command
|
|
||||||
fails, the connect method will fail.
|
|
||||||
Defaults to false.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.socks.host</TD>
|
|
||||||
<TD>string</TD>
|
|
||||||
<TD>
|
|
||||||
Specifies the host name of a SOCKS5 proxy server that will be used for
|
|
||||||
connections to the mail server.
|
|
||||||
(Note that this only works on JDK 1.5 or newer.)
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.socks.port</TD>
|
|
||||||
<TD>string</TD>
|
|
||||||
<TD>
|
|
||||||
Specifies the port number for the SOCKS5 proxy server.
|
|
||||||
This should only need to be used if the proxy server is not using
|
|
||||||
the standard port number of 1080.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.minidletime</TD>
|
|
||||||
<TD>int</TD>
|
|
||||||
<TD>
|
|
||||||
Applications typically call the idle method in a loop. If another
|
|
||||||
thread termiantes the IDLE command, it needs a chance to do its
|
|
||||||
work before another IDLE command is issued. The idle method enforces
|
|
||||||
a delay to prevent thrashing between the IDLE command and regular
|
|
||||||
commands. This property sets the delay in milliseconds. If not
|
|
||||||
set, the default is 10 milliseconds.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.enableimapevents</TD>
|
|
||||||
<TD>boolean</TD>
|
|
||||||
<TD>
|
|
||||||
Enable special IMAP-specific events to be delivered to the Store's
|
|
||||||
<code>ConnectionListener</code>. If true, unsolicited responses
|
|
||||||
received during the Store's <code>idle</code> method will be sent
|
|
||||||
as <code>ConnectionEvent</code>s with a type of
|
|
||||||
<code>IMAPStore.RESPONSE</code>. The event's message will be the
|
|
||||||
raw IMAP response string.
|
|
||||||
By default, these events are not sent.
|
|
||||||
NOTE: This capability is highly experimental and likely will change
|
|
||||||
in future releases.
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>mail.imap.folder.class</TD>
|
|
||||||
<TD>String</TD>
|
|
||||||
<TD>
|
|
||||||
Class name of a subclass of <code>com.sun.mail.imap.IMAPFolder</code>.
|
|
||||||
The subclass can be used to provide support for additional IMAP commands.
|
|
||||||
The subclass must have public constructors of the form
|
|
||||||
<code>public MyIMAPFolder(String fullName, char separator, IMAPStore store,
|
|
||||||
Boolean isNamespace)</code> and
|
|
||||||
<code>public MyIMAPFolder(ListInfo li, IMAPStore store)</code>
|
|
||||||
</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
</TABLE>
|
|
||||||
<P>
|
|
||||||
In general, applications should not need to use the classes in this
|
|
||||||
package directly. Instead, they should use the APIs defined by
|
|
||||||
<code>javax.mail</code> package (and subpackages). Applications should
|
|
||||||
never construct instances of <code>IMAPStore</code> or
|
|
||||||
<code>IMAPFolder</code> directly. Instead, they should use the
|
|
||||||
<code>Session</code> method <code>getStore</code> to acquire an
|
|
||||||
appropriate <code>Store</code> object, and from that acquire
|
|
||||||
<code>Folder</code> objects.
|
|
||||||
<P>
|
|
||||||
In addition to printing debugging output as controlled by the
|
|
||||||
{@link javax.mail.Session Session} configuration,
|
|
||||||
the com.sun.mail.imap provider logs the same information using
|
|
||||||
{@link java.util.logging.Logger} as described in the following table:
|
|
||||||
<P>
|
|
||||||
<TABLE BORDER>
|
|
||||||
<TR>
|
|
||||||
<TH>Logger Name</TH>
|
|
||||||
<TH>Logging Level</TH>
|
|
||||||
<TH>Purpose</TH>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>com.sun.mail.imap</TD>
|
|
||||||
<TD>CONFIG</TD>
|
|
||||||
<TD>Configuration of the IMAPStore</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>com.sun.mail.imap</TD>
|
|
||||||
<TD>FINE</TD>
|
|
||||||
<TD>General debugging output</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>com.sun.mail.imap.connectionpool</TD>
|
|
||||||
<TD>CONFIG</TD>
|
|
||||||
<TD>Configuration of the IMAP connection pool</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>com.sun.mail.imap.connectionpool</TD>
|
|
||||||
<TD>FINE</TD>
|
|
||||||
<TD>Debugging output related to the IMAP connection pool</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>com.sun.mail.imap.messagecache</TD>
|
|
||||||
<TD>CONFIG</TD>
|
|
||||||
<TD>Configuration of the IMAP message cache</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>com.sun.mail.imap.messagecache</TD>
|
|
||||||
<TD>FINE</TD>
|
|
||||||
<TD>Debugging output related to the IMAP message cache</TD>
|
|
||||||
</TR>
|
|
||||||
|
|
||||||
<TR>
|
|
||||||
<TD>com.sun.mail.imap.protocol</TD>
|
|
||||||
<TD>FINEST</TD>
|
|
||||||
<TD>Complete protocol trace</TD>
|
|
||||||
</TR>
|
|
||||||
</TABLE>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
<strong>WARNING:</strong> The APIs unique to this package should be
|
|
||||||
considered <strong>EXPERIMENTAL</strong>. They may be changed in the
|
|
||||||
future in ways that are incompatible with applications using the
|
|
||||||
current APIs.
|
|
||||||
|
|
||||||
</BODY>
|
|
||||||
</HTML>
|
|
||||||
@ -1,194 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap.protocol;
|
|
||||||
|
|
||||||
import java.text.StringCharacterIterator;
|
|
||||||
import java.text.CharacterIterator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See the BASE64MailboxEncoder for a description of the RFC2060 and how
|
|
||||||
* mailbox names should be encoded. This class will do the correct decoding
|
|
||||||
* for mailbox names.
|
|
||||||
*
|
|
||||||
* @author Christopher Cotton
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class BASE64MailboxDecoder {
|
|
||||||
|
|
||||||
public static String decode(String original) {
|
|
||||||
if (original == null || original.length() == 0)
|
|
||||||
return original;
|
|
||||||
|
|
||||||
boolean changedString = false;
|
|
||||||
int copyTo = 0;
|
|
||||||
// it will always be less than the original
|
|
||||||
char[] chars = new char[original.length()];
|
|
||||||
StringCharacterIterator iter = new StringCharacterIterator(original);
|
|
||||||
|
|
||||||
for(char c = iter.first(); c != CharacterIterator.DONE;
|
|
||||||
c = iter.next()) {
|
|
||||||
|
|
||||||
if (c == '&') {
|
|
||||||
changedString = true;
|
|
||||||
copyTo = base64decode(chars, copyTo, iter);
|
|
||||||
} else {
|
|
||||||
chars[copyTo++] = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now create our string from the char array
|
|
||||||
if (changedString) {
|
|
||||||
return new String(chars, 0, copyTo);
|
|
||||||
} else {
|
|
||||||
return original;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected static int base64decode(char[] buffer, int offset,
|
|
||||||
CharacterIterator iter) {
|
|
||||||
boolean firsttime = true;
|
|
||||||
int leftover = -1;
|
|
||||||
|
|
||||||
while(true) {
|
|
||||||
// get the first byte
|
|
||||||
byte orig_0 = (byte) iter.next();
|
|
||||||
if (orig_0 == -1) break; // no more chars
|
|
||||||
if (orig_0 == '-') {
|
|
||||||
if (firsttime) {
|
|
||||||
// means we got the string "&-" which is turned into a "&"
|
|
||||||
buffer[offset++] = '&';
|
|
||||||
}
|
|
||||||
// we are done now
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
firsttime = false;
|
|
||||||
|
|
||||||
// next byte
|
|
||||||
byte orig_1 = (byte) iter.next();
|
|
||||||
if (orig_1 == -1 || orig_1 == '-')
|
|
||||||
break; // no more chars, invalid base64
|
|
||||||
|
|
||||||
byte a, b, current;
|
|
||||||
a = pem_convert_array[orig_0 & 0xff];
|
|
||||||
b = pem_convert_array[orig_1 & 0xff];
|
|
||||||
// The first decoded byte
|
|
||||||
current = (byte)(((a << 2) & 0xfc) | ((b >>> 4) & 3));
|
|
||||||
|
|
||||||
// use the leftover to create a Unicode Character (2 bytes)
|
|
||||||
if (leftover != -1) {
|
|
||||||
buffer[offset++] = (char)(leftover << 8 | (current & 0xff));
|
|
||||||
leftover = -1;
|
|
||||||
} else {
|
|
||||||
leftover = current & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte orig_2 = (byte) iter.next();
|
|
||||||
if (orig_2 == '=') { // End of this BASE64 encoding
|
|
||||||
continue;
|
|
||||||
} else if (orig_2 == -1 || orig_2 == '-') {
|
|
||||||
break; // no more chars
|
|
||||||
}
|
|
||||||
|
|
||||||
// second decoded byte
|
|
||||||
a = b;
|
|
||||||
b = pem_convert_array[orig_2 & 0xff];
|
|
||||||
current = (byte)(((a << 4) & 0xf0) | ((b >>> 2) & 0xf));
|
|
||||||
|
|
||||||
// use the leftover to create a Unicode Character (2 bytes)
|
|
||||||
if (leftover != -1) {
|
|
||||||
buffer[offset++] = (char)(leftover << 8 | (current & 0xff));
|
|
||||||
leftover = -1;
|
|
||||||
} else {
|
|
||||||
leftover = current & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte orig_3 = (byte) iter.next();
|
|
||||||
if (orig_3 == '=') { // End of this BASE64 encoding
|
|
||||||
continue;
|
|
||||||
} else if (orig_3 == -1 || orig_3 == '-') {
|
|
||||||
break; // no more chars
|
|
||||||
}
|
|
||||||
|
|
||||||
// The third decoded byte
|
|
||||||
a = b;
|
|
||||||
b = pem_convert_array[orig_3 & 0xff];
|
|
||||||
current = (byte)(((a << 6) & 0xc0) | (b & 0x3f));
|
|
||||||
|
|
||||||
// use the leftover to create a Unicode Character (2 bytes)
|
|
||||||
if (leftover != -1) {
|
|
||||||
buffer[offset++] = (char)(leftover << 8 | (current & 0xff));
|
|
||||||
leftover = -1;
|
|
||||||
} else {
|
|
||||||
leftover = current & 0xff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This character array provides the character to value map
|
|
||||||
* based on RFC1521, but with the modification from RFC2060
|
|
||||||
* which changes the '/' to a ','.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// shared with BASE64MailboxEncoder
|
|
||||||
static final char pem_array[] = {
|
|
||||||
'A','B','C','D','E','F','G','H', // 0
|
|
||||||
'I','J','K','L','M','N','O','P', // 1
|
|
||||||
'Q','R','S','T','U','V','W','X', // 2
|
|
||||||
'Y','Z','a','b','c','d','e','f', // 3
|
|
||||||
'g','h','i','j','k','l','m','n', // 4
|
|
||||||
'o','p','q','r','s','t','u','v', // 5
|
|
||||||
'w','x','y','z','0','1','2','3', // 6
|
|
||||||
'4','5','6','7','8','9','+',',' // 7
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final byte pem_convert_array[] = new byte[256];
|
|
||||||
|
|
||||||
static {
|
|
||||||
for (int i = 0; i < 255; i++)
|
|
||||||
pem_convert_array[i] = -1;
|
|
||||||
for(int i = 0; i < pem_array.length; i++)
|
|
||||||
pem_convert_array[pem_array[i]] = (byte) i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,260 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap.protocol;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
from RFC2060
|
|
||||||
|
|
||||||
5.1.3. Mailbox International Naming Convention
|
|
||||||
|
|
||||||
By convention, international mailbox names are specified using a
|
|
||||||
modified version of the UTF-7 encoding described in [UTF-7]. The
|
|
||||||
purpose of these modifications is to correct the following problems
|
|
||||||
with UTF-7:
|
|
||||||
|
|
||||||
1) UTF-7 uses the "+" character for shifting; this conflicts with
|
|
||||||
the common use of "+" in mailbox names, in particular USENET
|
|
||||||
newsgroup names.
|
|
||||||
|
|
||||||
2) UTF-7's encoding is BASE64 which uses the "/" character; this
|
|
||||||
conflicts with the use of "/" as a popular hierarchy delimiter.
|
|
||||||
|
|
||||||
3) UTF-7 prohibits the unencoded usage of "\"; this conflicts with
|
|
||||||
the use of "\" as a popular hierarchy delimiter.
|
|
||||||
|
|
||||||
4) UTF-7 prohibits the unencoded usage of "~"; this conflicts with
|
|
||||||
the use of "~" in some servers as a home directory indicator.
|
|
||||||
|
|
||||||
5) UTF-7 permits multiple alternate forms to represent the same
|
|
||||||
string; in particular, printable US-ASCII chararacters can be
|
|
||||||
represented in encoded form.
|
|
||||||
|
|
||||||
In modified UTF-7, printable US-ASCII characters except for "&"
|
|
||||||
represent themselves; that is, characters with octet values 0x20-0x25
|
|
||||||
and 0x27-0x7e. The character "&" (0x26) is represented by the two-
|
|
||||||
octet sequence "&-".
|
|
||||||
|
|
||||||
All other characters (octet values 0x00-0x1f, 0x7f-0xff, and all
|
|
||||||
Unicode 16-bit octets) are represented in modified BASE64, with a
|
|
||||||
further modification from [UTF-7] that "," is used instead of "/".
|
|
||||||
Modified BASE64 MUST NOT be used to represent any printing US-ASCII
|
|
||||||
character which can represent itself.
|
|
||||||
|
|
||||||
"&" is used to shift to modified BASE64 and "-" to shift back to US-
|
|
||||||
ASCII. All names start in US-ASCII, and MUST end in US-ASCII (that
|
|
||||||
is, a name that ends with a Unicode 16-bit octet MUST end with a "-
|
|
||||||
").
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Crispin Standards Track [Page 15]
|
|
||||||
|
|
||||||
RFC 2060 IMAP4rev1 December 1996
|
|
||||||
|
|
||||||
|
|
||||||
For example, here is a mailbox name which mixes English, Japanese,
|
|
||||||
and Chinese text: ~peter/mail/&ZeVnLIqe-/&U,BTFw-
|
|
||||||
|
|
||||||
|
|
||||||
* This class will do the correct Encoding for the IMAP mailboxes
|
|
||||||
*
|
|
||||||
* @author Christopher Cotton
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class BASE64MailboxEncoder {
|
|
||||||
protected byte[] buffer = new byte[4];
|
|
||||||
protected int bufsize = 0;
|
|
||||||
protected boolean started = false;
|
|
||||||
protected Writer out = null;
|
|
||||||
|
|
||||||
|
|
||||||
public static String encode(String original) {
|
|
||||||
BASE64MailboxEncoder base64stream = null;
|
|
||||||
char origchars[] = original.toCharArray();
|
|
||||||
int length = origchars.length;
|
|
||||||
boolean changedString = false;
|
|
||||||
CharArrayWriter writer = new CharArrayWriter(length);
|
|
||||||
|
|
||||||
// loop over all the chars
|
|
||||||
for(int index = 0; index < length; index++) {
|
|
||||||
char current = origchars[index];
|
|
||||||
|
|
||||||
// octets in the range 0x20-0x25,0x27-0x7e are themselves
|
|
||||||
// 0x26 "&" is represented as "&-"
|
|
||||||
if (current >= 0x20 && current <= 0x7e) {
|
|
||||||
if (base64stream != null) {
|
|
||||||
base64stream.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current == '&') {
|
|
||||||
changedString = true;
|
|
||||||
writer.write('&');
|
|
||||||
writer.write('-');
|
|
||||||
} else {
|
|
||||||
writer.write(current);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// use a B64MailboxEncoder to write out the other bytes
|
|
||||||
// as a modified BASE64. The stream will write out
|
|
||||||
// the beginning '&' and the ending '-' which is part
|
|
||||||
// of every encoding.
|
|
||||||
|
|
||||||
if (base64stream == null) {
|
|
||||||
base64stream = new BASE64MailboxEncoder(writer);
|
|
||||||
changedString = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
base64stream.write(current);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (base64stream != null) {
|
|
||||||
base64stream.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changedString) {
|
|
||||||
return writer.toString();
|
|
||||||
} else {
|
|
||||||
return original;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a BASE64 encoder
|
|
||||||
*/
|
|
||||||
public BASE64MailboxEncoder(Writer what) {
|
|
||||||
out = what;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void write(int c) {
|
|
||||||
try {
|
|
||||||
// write out the initial character if this is the first time
|
|
||||||
if (!started) {
|
|
||||||
started = true;
|
|
||||||
out.write('&');
|
|
||||||
}
|
|
||||||
|
|
||||||
// we write each character as a 2 byte unicode character
|
|
||||||
buffer[bufsize++] = (byte) (c >> 8);
|
|
||||||
buffer[bufsize++] = (byte) (c & 0xff);
|
|
||||||
|
|
||||||
if (bufsize >= 3) {
|
|
||||||
encode();
|
|
||||||
bufsize -= 3;
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
//e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void flush() {
|
|
||||||
try {
|
|
||||||
// flush any bytes we have
|
|
||||||
if (bufsize > 0) {
|
|
||||||
encode();
|
|
||||||
bufsize = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// write the terminating character of the encoding
|
|
||||||
if (started) {
|
|
||||||
out.write('-');
|
|
||||||
started = false;
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
//e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected void encode() throws IOException {
|
|
||||||
byte a, b, c;
|
|
||||||
if (bufsize == 1) {
|
|
||||||
a = buffer[0];
|
|
||||||
b = 0;
|
|
||||||
c = 0;
|
|
||||||
out.write(pem_array[(a >>> 2) & 0x3F]);
|
|
||||||
out.write(pem_array[((a << 4) & 0x30) + ((b >>> 4) & 0xf)]);
|
|
||||||
// no padding characters are written
|
|
||||||
} else if (bufsize == 2) {
|
|
||||||
a = buffer[0];
|
|
||||||
b = buffer[1];
|
|
||||||
c = 0;
|
|
||||||
out.write(pem_array[(a >>> 2) & 0x3F]);
|
|
||||||
out.write(pem_array[((a << 4) & 0x30) + ((b >>> 4) & 0xf)]);
|
|
||||||
out.write(pem_array[((b << 2) & 0x3c) + ((c >>> 6) & 0x3)]);
|
|
||||||
// no padding characters are written
|
|
||||||
} else {
|
|
||||||
a = buffer[0];
|
|
||||||
b = buffer[1];
|
|
||||||
c = buffer[2];
|
|
||||||
out.write(pem_array[(a >>> 2) & 0x3F]);
|
|
||||||
out.write(pem_array[((a << 4) & 0x30) + ((b >>> 4) & 0xf)]);
|
|
||||||
out.write(pem_array[((b << 2) & 0x3c) + ((c >>> 6) & 0x3)]);
|
|
||||||
out.write(pem_array[c & 0x3F]);
|
|
||||||
|
|
||||||
// copy back the extra byte
|
|
||||||
if (bufsize == 4)
|
|
||||||
buffer[0] = buffer[3];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final static char pem_array[] = {
|
|
||||||
'A','B','C','D','E','F','G','H', // 0
|
|
||||||
'I','J','K','L','M','N','O','P', // 1
|
|
||||||
'Q','R','S','T','U','V','W','X', // 2
|
|
||||||
'Y','Z','a','b','c','d','e','f', // 3
|
|
||||||
'g','h','i','j','k','l','m','n', // 4
|
|
||||||
'o','p','q','r','s','t','u','v', // 5
|
|
||||||
'w','x','y','z','0','1','2','3', // 6
|
|
||||||
'4','5','6','7','8','9','+',',' // 7
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap.protocol;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import com.sun.mail.iap.*;
|
|
||||||
import com.sun.mail.util.ASCIIUtility;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The BODY fetch response item.
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class BODY implements Item {
|
|
||||||
|
|
||||||
static final char[] name = {'B','O','D','Y'};
|
|
||||||
|
|
||||||
public int msgno;
|
|
||||||
public ByteArray data;
|
|
||||||
public String section;
|
|
||||||
public int origin = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
public BODY(FetchResponse r) throws ParsingException {
|
|
||||||
msgno = r.getNumber();
|
|
||||||
|
|
||||||
r.skipSpaces();
|
|
||||||
|
|
||||||
int b;
|
|
||||||
while ((b = r.readByte()) != ']') { // skip section
|
|
||||||
if (b == 0)
|
|
||||||
throw new ParsingException(
|
|
||||||
"BODY parse error: missing ``]'' at section end");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (r.readByte() == '<') { // origin
|
|
||||||
origin = r.readNumber();
|
|
||||||
r.skip(1); // skip '>';
|
|
||||||
}
|
|
||||||
|
|
||||||
data = r.readByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ByteArray getByteArray() {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ByteArrayInputStream getByteArrayInputStream() {
|
|
||||||
if (data != null)
|
|
||||||
return data.toByteArrayInputStream();
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,429 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap.protocol;
|
|
||||||
|
|
||||||
import java.util.Vector;
|
|
||||||
import javax.mail.internet.ParameterList;
|
|
||||||
import com.sun.mail.iap.*;
|
|
||||||
import com.sun.mail.util.PropUtil;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A BODYSTRUCTURE response.
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
* @author Bill Shannon
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class BODYSTRUCTURE implements Item {
|
|
||||||
|
|
||||||
static final char[] name =
|
|
||||||
{'B','O','D','Y','S','T','R','U','C','T','U','R','E'};
|
|
||||||
public int msgno;
|
|
||||||
|
|
||||||
public String type; // Type
|
|
||||||
public String subtype; // Subtype
|
|
||||||
public String encoding; // Encoding
|
|
||||||
public int lines = -1; // Size in lines
|
|
||||||
public int size = -1; // Size in bytes
|
|
||||||
public String disposition; // Disposition
|
|
||||||
public String id; // Content-ID
|
|
||||||
public String description; // Content-Description
|
|
||||||
public String md5; // MD-5 checksum
|
|
||||||
public String attachment; // Attachment name
|
|
||||||
public ParameterList cParams; // Body parameters
|
|
||||||
public ParameterList dParams; // Disposition parameters
|
|
||||||
public String[] language; // Language
|
|
||||||
public BODYSTRUCTURE[] bodies; // array of BODYSTRUCTURE objects
|
|
||||||
// for multipart & message/rfc822
|
|
||||||
public ENVELOPE envelope; // for message/rfc822
|
|
||||||
|
|
||||||
private static int SINGLE = 1;
|
|
||||||
private static int MULTI = 2;
|
|
||||||
private static int NESTED = 3;
|
|
||||||
private int processedType; // MULTI | SINGLE | NESTED
|
|
||||||
|
|
||||||
// special debugging output to debug parsing errors
|
|
||||||
private static boolean parseDebug =
|
|
||||||
PropUtil.getBooleanSystemProperty("mail.imap.parse.debug", false);
|
|
||||||
|
|
||||||
|
|
||||||
public BODYSTRUCTURE(FetchResponse r) throws ParsingException {
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: parsing BODYSTRUCTURE");
|
|
||||||
msgno = r.getNumber();
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: msgno " + msgno);
|
|
||||||
|
|
||||||
r.skipSpaces();
|
|
||||||
|
|
||||||
if (r.readByte() != '(')
|
|
||||||
throw new ParsingException(
|
|
||||||
"BODYSTRUCTURE parse error: missing ``('' at start");
|
|
||||||
|
|
||||||
if (r.peekByte() == '(') { // multipart
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: parsing multipart");
|
|
||||||
type = "multipart";
|
|
||||||
processedType = MULTI;
|
|
||||||
Vector v = new Vector(1);
|
|
||||||
int i = 1;
|
|
||||||
do {
|
|
||||||
v.addElement(new BODYSTRUCTURE(r));
|
|
||||||
/*
|
|
||||||
* Even though the IMAP spec says there can't be any spaces
|
|
||||||
* between parts, some servers erroneously put a space in
|
|
||||||
* here. In the spirit of "be liberal in what you accept",
|
|
||||||
* we skip it.
|
|
||||||
*/
|
|
||||||
r.skipSpaces();
|
|
||||||
} while (r.peekByte() == '(');
|
|
||||||
|
|
||||||
// setup bodies.
|
|
||||||
bodies = new BODYSTRUCTURE[v.size()];
|
|
||||||
v.copyInto(bodies);
|
|
||||||
|
|
||||||
subtype = r.readString(); // subtype
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: subtype " + subtype);
|
|
||||||
|
|
||||||
if (r.readByte() == ')') { // done
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: parse DONE");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Else, we have extension data
|
|
||||||
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: parsing extension data");
|
|
||||||
// Body parameters
|
|
||||||
cParams = parseParameters(r);
|
|
||||||
if (r.readByte() == ')') { // done
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: body parameters DONE");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disposition
|
|
||||||
byte b = r.readByte();
|
|
||||||
if (b == '(') {
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: parse disposition");
|
|
||||||
disposition = r.readString();
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: disposition " +
|
|
||||||
disposition);
|
|
||||||
dParams = parseParameters(r);
|
|
||||||
if (r.readByte() != ')') // eat the end ')'
|
|
||||||
throw new ParsingException(
|
|
||||||
"BODYSTRUCTURE parse error: " +
|
|
||||||
"missing ``)'' at end of disposition in multipart");
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: disposition DONE");
|
|
||||||
} else if (b == 'N' || b == 'n') {
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: disposition NIL");
|
|
||||||
r.skip(2); // skip 'NIL'
|
|
||||||
} else {
|
|
||||||
throw new ParsingException(
|
|
||||||
"BODYSTRUCTURE parse error: " +
|
|
||||||
type + "/" + subtype + ": " +
|
|
||||||
"bad multipart disposition, b " + b);
|
|
||||||
}
|
|
||||||
|
|
||||||
// RFC3501 allows no body-fld-lang after body-fld-disp,
|
|
||||||
// even though RFC2060 required it
|
|
||||||
if ((b = r.readByte()) == ')') {
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: no body-fld-lang");
|
|
||||||
return; // done
|
|
||||||
}
|
|
||||||
|
|
||||||
if (b != ' ')
|
|
||||||
throw new ParsingException(
|
|
||||||
"BODYSTRUCTURE parse error: " +
|
|
||||||
"missing space after disposition");
|
|
||||||
|
|
||||||
// Language
|
|
||||||
if (r.peekByte() == '(') { // a list follows
|
|
||||||
language = r.readStringList();
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println(
|
|
||||||
"DEBUG IMAP: language len " + language.length);
|
|
||||||
} else {
|
|
||||||
String l = r.readString();
|
|
||||||
if (l != null) {
|
|
||||||
String[] la = { l };
|
|
||||||
language = la;
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: language " + l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RFC3501 defines an optional "body location" next,
|
|
||||||
// but for now we ignore it along with other extensions.
|
|
||||||
|
|
||||||
// Throw away any further extension data
|
|
||||||
while (r.readByte() == ' ')
|
|
||||||
parseBodyExtension(r);
|
|
||||||
}
|
|
||||||
else { // Single part
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: single part");
|
|
||||||
type = r.readString();
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: type " + type);
|
|
||||||
processedType = SINGLE;
|
|
||||||
subtype = r.readString();
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: subtype " + subtype);
|
|
||||||
|
|
||||||
// SIMS 4.0 returns NIL for a Content-Type of "binary", fix it here
|
|
||||||
if (type == null) {
|
|
||||||
type = "application";
|
|
||||||
subtype = "octet-stream";
|
|
||||||
}
|
|
||||||
cParams = parseParameters(r);
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: cParams " + cParams);
|
|
||||||
id = r.readString();
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: id " + id);
|
|
||||||
description = r.readString();
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: description " + description);
|
|
||||||
/*
|
|
||||||
* XXX - Work around bug in Exchange 2010 that
|
|
||||||
* returns unquoted string.
|
|
||||||
*/
|
|
||||||
encoding = r.readAtomString();
|
|
||||||
if (encoding != null && encoding.equalsIgnoreCase("NIL"))
|
|
||||||
encoding = null;
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: encoding " + encoding);
|
|
||||||
size = r.readNumber();
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: size " + size);
|
|
||||||
if (size < 0)
|
|
||||||
throw new ParsingException(
|
|
||||||
"BODYSTRUCTURE parse error: bad ``size'' element");
|
|
||||||
|
|
||||||
// "text/*" & "message/rfc822" types have additional data ..
|
|
||||||
if (type.equalsIgnoreCase("text")) {
|
|
||||||
lines = r.readNumber();
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: lines " + lines);
|
|
||||||
if (lines < 0)
|
|
||||||
throw new ParsingException(
|
|
||||||
"BODYSTRUCTURE parse error: bad ``lines'' element");
|
|
||||||
} else if (type.equalsIgnoreCase("message") &&
|
|
||||||
subtype.equalsIgnoreCase("rfc822")) {
|
|
||||||
// Nested message
|
|
||||||
processedType = NESTED;
|
|
||||||
// The envelope comes next, but sadly Gmail handles nested
|
|
||||||
// messages just like simple body parts and fails to return
|
|
||||||
// the envelope and body structure of the message (sort of
|
|
||||||
// like IMAP4 before rev1).
|
|
||||||
r.skipSpaces();
|
|
||||||
if (r.peekByte() == '(') { // the envelope follows
|
|
||||||
envelope = new ENVELOPE(r);
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println(
|
|
||||||
"DEBUG IMAP: got envelope of nested message");
|
|
||||||
BODYSTRUCTURE[] bs = { new BODYSTRUCTURE(r) };
|
|
||||||
bodies = bs;
|
|
||||||
lines = r.readNumber();
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: lines " + lines);
|
|
||||||
if (lines < 0)
|
|
||||||
throw new ParsingException(
|
|
||||||
"BODYSTRUCTURE parse error: bad ``lines'' element");
|
|
||||||
} else {
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: " +
|
|
||||||
"missing envelope and body of nested message");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Detect common error of including lines element on other types
|
|
||||||
r.skipSpaces();
|
|
||||||
byte bn = r.peekByte();
|
|
||||||
if (Character.isDigit((char)bn)) // number
|
|
||||||
throw new ParsingException(
|
|
||||||
"BODYSTRUCTURE parse error: server erroneously " +
|
|
||||||
"included ``lines'' element with type " +
|
|
||||||
type + "/" + subtype);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r.peekByte() == ')') {
|
|
||||||
r.readByte();
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: parse DONE");
|
|
||||||
return; // done
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optional extension data
|
|
||||||
|
|
||||||
// MD5
|
|
||||||
md5 = r.readString();
|
|
||||||
if (r.readByte() == ')') {
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: no MD5 DONE");
|
|
||||||
return; // done
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disposition
|
|
||||||
byte b = r.readByte();
|
|
||||||
if (b == '(') {
|
|
||||||
disposition = r.readString();
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: disposition " +
|
|
||||||
disposition);
|
|
||||||
dParams = parseParameters(r);
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: dParams " + dParams);
|
|
||||||
if (r.readByte() != ')') // eat the end ')'
|
|
||||||
throw new ParsingException(
|
|
||||||
"BODYSTRUCTURE parse error: " +
|
|
||||||
"missing ``)'' at end of disposition");
|
|
||||||
} else if (b == 'N' || b == 'n') {
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: disposition NIL");
|
|
||||||
r.skip(2); // skip 'NIL'
|
|
||||||
} else {
|
|
||||||
throw new ParsingException(
|
|
||||||
"BODYSTRUCTURE parse error: " +
|
|
||||||
type + "/" + subtype + ": " +
|
|
||||||
"bad single part disposition, b " + b);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r.readByte() == ')') {
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: disposition DONE");
|
|
||||||
return; // done
|
|
||||||
}
|
|
||||||
|
|
||||||
// Language
|
|
||||||
if (r.peekByte() == '(') { // a list follows
|
|
||||||
language = r.readStringList();
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: language len " +
|
|
||||||
language.length);
|
|
||||||
} else { // protocol is unnessarily complex here
|
|
||||||
String l = r.readString();
|
|
||||||
if (l != null) {
|
|
||||||
String[] la = { l };
|
|
||||||
language = la;
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: language " + l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RFC3501 defines an optional "body location" next,
|
|
||||||
// but for now we ignore it along with other extensions.
|
|
||||||
|
|
||||||
// Throw away any further extension data
|
|
||||||
while (r.readByte() == ' ')
|
|
||||||
parseBodyExtension(r);
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: all DONE");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMulti() {
|
|
||||||
return processedType == MULTI;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSingle() {
|
|
||||||
return processedType == SINGLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isNested() {
|
|
||||||
return processedType == NESTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ParameterList parseParameters(Response r)
|
|
||||||
throws ParsingException {
|
|
||||||
r.skipSpaces();
|
|
||||||
|
|
||||||
ParameterList list = null;
|
|
||||||
byte b = r.readByte();
|
|
||||||
if (b == '(') {
|
|
||||||
list = new ParameterList();
|
|
||||||
do {
|
|
||||||
String name = r.readString();
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: parameter name " + name);
|
|
||||||
if (name == null)
|
|
||||||
throw new ParsingException(
|
|
||||||
"BODYSTRUCTURE parse error: " +
|
|
||||||
type + "/" + subtype + ": " +
|
|
||||||
"null name in parameter list");
|
|
||||||
String value = r.readString();
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: parameter value " + value);
|
|
||||||
list.set(name, value);
|
|
||||||
} while (r.readByte() != ')');
|
|
||||||
list.combineSegments();
|
|
||||||
} else if (b == 'N' || b == 'n') {
|
|
||||||
if (parseDebug)
|
|
||||||
System.out.println("DEBUG IMAP: parameter list NIL");
|
|
||||||
r.skip(2);
|
|
||||||
} else
|
|
||||||
throw new ParsingException("Parameter list parse error");
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseBodyExtension(Response r) throws ParsingException {
|
|
||||||
r.skipSpaces();
|
|
||||||
|
|
||||||
byte b = r.peekByte();
|
|
||||||
if (b == '(') {
|
|
||||||
r.skip(1); // skip '('
|
|
||||||
do {
|
|
||||||
parseBodyExtension(r);
|
|
||||||
} while (r.readByte() != ')');
|
|
||||||
} else if (Character.isDigit((char)b)) // number
|
|
||||||
r.readNumber();
|
|
||||||
else // nstring
|
|
||||||
r.readString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,216 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap.protocol;
|
|
||||||
|
|
||||||
import java.util.Vector;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import javax.mail.internet.InternetAddress;
|
|
||||||
import javax.mail.internet.AddressException;
|
|
||||||
import javax.mail.internet.MailDateFormat;
|
|
||||||
import javax.mail.internet.MimeUtility;
|
|
||||||
import com.sun.mail.iap.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The ENEVELOPE item of an IMAP FETCH response.
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
* @author Bill Shannon
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class ENVELOPE implements Item {
|
|
||||||
|
|
||||||
// IMAP item name
|
|
||||||
static final char[] name = {'E','N','V','E','L','O','P','E'};
|
|
||||||
public int msgno;
|
|
||||||
|
|
||||||
public Date date = null;
|
|
||||||
public String subject;
|
|
||||||
public InternetAddress[] from;
|
|
||||||
public InternetAddress[] sender;
|
|
||||||
public InternetAddress[] replyTo;
|
|
||||||
public InternetAddress[] to;
|
|
||||||
public InternetAddress[] cc;
|
|
||||||
public InternetAddress[] bcc;
|
|
||||||
public String inReplyTo;
|
|
||||||
public String messageId;
|
|
||||||
|
|
||||||
// Used to parse dates
|
|
||||||
private static MailDateFormat mailDateFormat = new MailDateFormat();
|
|
||||||
|
|
||||||
public ENVELOPE(FetchResponse r) throws ParsingException {
|
|
||||||
msgno = r.getNumber();
|
|
||||||
|
|
||||||
r.skipSpaces();
|
|
||||||
|
|
||||||
if (r.readByte() != '(')
|
|
||||||
throw new ParsingException("ENVELOPE parse error");
|
|
||||||
|
|
||||||
String s = r.readString();
|
|
||||||
if (s != null) {
|
|
||||||
try {
|
|
||||||
date = mailDateFormat.parse(s);
|
|
||||||
} catch (Exception pex) {
|
|
||||||
// We need to be *very* tolerant about bogus dates (and
|
|
||||||
// there's lot of 'em around), so we ignore any
|
|
||||||
// exception (including RunTimeExceptions) and just let
|
|
||||||
// date be null.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
subject = r.readString();
|
|
||||||
from = parseAddressList(r);
|
|
||||||
sender = parseAddressList(r);
|
|
||||||
replyTo = parseAddressList(r);
|
|
||||||
to = parseAddressList(r);
|
|
||||||
cc = parseAddressList(r);
|
|
||||||
bcc = parseAddressList(r);
|
|
||||||
inReplyTo = r.readString();
|
|
||||||
messageId = r.readString();
|
|
||||||
|
|
||||||
if (r.readByte() != ')')
|
|
||||||
throw new ParsingException("ENVELOPE parse error");
|
|
||||||
}
|
|
||||||
|
|
||||||
private InternetAddress[] parseAddressList(Response r)
|
|
||||||
throws ParsingException {
|
|
||||||
r.skipSpaces(); // skip leading spaces
|
|
||||||
|
|
||||||
byte b = r.readByte();
|
|
||||||
if (b == '(') {
|
|
||||||
Vector v = new Vector();
|
|
||||||
|
|
||||||
do {
|
|
||||||
IMAPAddress a = new IMAPAddress(r);
|
|
||||||
// if we see an end-of-group address at the top, ignore it
|
|
||||||
if (!a.isEndOfGroup())
|
|
||||||
v.addElement(a);
|
|
||||||
} while (r.peekByte() != ')');
|
|
||||||
|
|
||||||
// skip the terminating ')' at the end of the addresslist
|
|
||||||
r.skip(1);
|
|
||||||
|
|
||||||
InternetAddress[] a = new InternetAddress[v.size()];
|
|
||||||
v.copyInto(a);
|
|
||||||
return a;
|
|
||||||
} else if (b == 'N' || b == 'n') { // NIL
|
|
||||||
r.skip(2); // skip 'NIL'
|
|
||||||
return null;
|
|
||||||
} else
|
|
||||||
throw new ParsingException("ADDRESS parse error");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class IMAPAddress extends InternetAddress {
|
|
||||||
private boolean group = false;
|
|
||||||
private InternetAddress[] grouplist;
|
|
||||||
private String groupname;
|
|
||||||
|
|
||||||
private static final long serialVersionUID = -3835822029483122232L;
|
|
||||||
|
|
||||||
IMAPAddress(Response r) throws ParsingException {
|
|
||||||
r.skipSpaces(); // skip leading spaces
|
|
||||||
|
|
||||||
if (r.readByte() != '(')
|
|
||||||
throw new ParsingException("ADDRESS parse error");
|
|
||||||
|
|
||||||
encodedPersonal = r.readString();
|
|
||||||
|
|
||||||
r.readString(); // throw away address_list
|
|
||||||
String mb = r.readString();
|
|
||||||
String host = r.readString();
|
|
||||||
// skip bogus spaces inserted by Yahoo IMAP server if
|
|
||||||
// "undisclosed-recipients" is a recipient
|
|
||||||
r.skipSpaces();
|
|
||||||
if (r.readByte() != ')') // skip past terminating ')'
|
|
||||||
throw new ParsingException("ADDRESS parse error");
|
|
||||||
|
|
||||||
if (host == null) {
|
|
||||||
// it's a group list, start or end
|
|
||||||
group = true;
|
|
||||||
groupname = mb;
|
|
||||||
if (groupname == null) // end of group list
|
|
||||||
return;
|
|
||||||
// Accumulate a group list. The members of the group
|
|
||||||
// are accumulated in a Vector and the corresponding string
|
|
||||||
// representation of the group is accumulated in a StringBuffer.
|
|
||||||
StringBuffer sb = new StringBuffer();
|
|
||||||
sb.append(groupname).append(':');
|
|
||||||
Vector v = new Vector();
|
|
||||||
while (r.peekByte() != ')') {
|
|
||||||
IMAPAddress a = new IMAPAddress(r);
|
|
||||||
if (a.isEndOfGroup()) // reached end of group
|
|
||||||
break;
|
|
||||||
if (v.size() != 0) // if not first element, need a comma
|
|
||||||
sb.append(',');
|
|
||||||
sb.append(a.toString());
|
|
||||||
v.addElement(a);
|
|
||||||
}
|
|
||||||
sb.append(';');
|
|
||||||
address = sb.toString();
|
|
||||||
grouplist = new IMAPAddress[v.size()];
|
|
||||||
v.copyInto(grouplist);
|
|
||||||
} else {
|
|
||||||
if (mb == null || mb.length() == 0)
|
|
||||||
address = host;
|
|
||||||
else if (host.length() == 0)
|
|
||||||
address = mb;
|
|
||||||
else
|
|
||||||
address = mb + "@" + host;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isEndOfGroup() {
|
|
||||||
return group && groupname == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isGroup() {
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InternetAddress[] getGroup(boolean strict) throws AddressException {
|
|
||||||
if (grouplist == null)
|
|
||||||
return null;
|
|
||||||
return (InternetAddress[])grouplist.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,107 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap.protocol;
|
|
||||||
|
|
||||||
import javax.mail.Flags;
|
|
||||||
import com.sun.mail.iap.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class FLAGS extends Flags implements Item {
|
|
||||||
|
|
||||||
// IMAP item name
|
|
||||||
static final char[] name = {'F','L','A','G','S'};
|
|
||||||
public int msgno;
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 439049847053756670L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
public FLAGS(IMAPResponse r) throws ParsingException {
|
|
||||||
msgno = r.getNumber();
|
|
||||||
|
|
||||||
r.skipSpaces();
|
|
||||||
String[] flags = r.readSimpleList();
|
|
||||||
if (flags != null) { // if not empty flaglist
|
|
||||||
for (int i = 0; i < flags.length; i++) {
|
|
||||||
String s = flags[i];
|
|
||||||
if (s.length() >= 2 && s.charAt(0) == '\\') {
|
|
||||||
switch (Character.toUpperCase(s.charAt(1))) {
|
|
||||||
case 'S': // \Seen
|
|
||||||
add(Flags.Flag.SEEN);
|
|
||||||
break;
|
|
||||||
case 'R': // \Recent
|
|
||||||
add(Flags.Flag.RECENT);
|
|
||||||
break;
|
|
||||||
case 'D':
|
|
||||||
if (s.length() >= 3) {
|
|
||||||
char c = s.charAt(2);
|
|
||||||
if (c == 'e' || c == 'E') // \Deleted
|
|
||||||
add(Flags.Flag.DELETED);
|
|
||||||
else if (c == 'r' || c == 'R') // \Draft
|
|
||||||
add(Flags.Flag.DRAFT);
|
|
||||||
} else
|
|
||||||
add(s); // unknown, treat it as a user flag
|
|
||||||
break;
|
|
||||||
case 'A': // \Answered
|
|
||||||
add(Flags.Flag.ANSWERED);
|
|
||||||
break;
|
|
||||||
case 'F': // \Flagged
|
|
||||||
add(Flags.Flag.FLAGGED);
|
|
||||||
break;
|
|
||||||
case '*': // \*
|
|
||||||
add(Flags.Flag.USER);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
add(s); // unknown, treat it as a user flag
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
add(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap.protocol;
|
|
||||||
|
|
||||||
import java.lang.reflect.*;
|
|
||||||
|
|
||||||
import javax.mail.FetchProfile;
|
|
||||||
import com.sun.mail.iap.ParsingException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Metadata describing a FETCH item.
|
|
||||||
* Note that the "name" field MUST be in uppercase. <p>
|
|
||||||
*
|
|
||||||
* @author Bill Shannon
|
|
||||||
* @since JavaMail 1.4.6
|
|
||||||
*/
|
|
||||||
|
|
||||||
public abstract class FetchItem {
|
|
||||||
private String name;
|
|
||||||
private FetchProfile.Item fetchProfileItem;
|
|
||||||
|
|
||||||
public FetchItem(String name, FetchProfile.Item fetchProfileItem) {
|
|
||||||
this.name = name;
|
|
||||||
this.fetchProfileItem = fetchProfileItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FetchProfile.Item getFetchProfileItem() {
|
|
||||||
return fetchProfileItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse the item into some kind of object appropriate for the item.
|
|
||||||
* Note that the item name will have been parsed and skipped already.
|
|
||||||
*/
|
|
||||||
public abstract Object parseItem(FetchResponse r) throws ParsingException;
|
|
||||||
}
|
|
||||||
@ -1,279 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap.protocol;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.*;
|
|
||||||
import com.sun.mail.util.*;
|
|
||||||
import com.sun.mail.iap.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class represents a FETCH response obtained from the input stream
|
|
||||||
* of an IMAP server.
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
* @author Bill Shannon
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class FetchResponse extends IMAPResponse {
|
|
||||||
/*
|
|
||||||
* Regular Items are saved in the items array.
|
|
||||||
* Extension items (items handled by subclasses
|
|
||||||
* that extend the IMAP provider) are saved in the
|
|
||||||
* extensionItems map, indexed by the FETCH item name.
|
|
||||||
* The map is only created when needed.
|
|
||||||
*
|
|
||||||
* XXX - Should consider unifying the handling of
|
|
||||||
* regular items and extension items.
|
|
||||||
*/
|
|
||||||
private Item[] items;
|
|
||||||
private Map extensionItems;
|
|
||||||
private final FetchItem[] fitems;
|
|
||||||
|
|
||||||
public FetchResponse(Protocol p)
|
|
||||||
throws IOException, ProtocolException {
|
|
||||||
super(p);
|
|
||||||
fitems = null;
|
|
||||||
parse();
|
|
||||||
}
|
|
||||||
|
|
||||||
public FetchResponse(IMAPResponse r)
|
|
||||||
throws IOException, ProtocolException {
|
|
||||||
this(r, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a FetchResponse that handles the additional FetchItems.
|
|
||||||
*
|
|
||||||
* @since JavaMail 1.4.6
|
|
||||||
*/
|
|
||||||
public FetchResponse(IMAPResponse r, FetchItem[] fitems)
|
|
||||||
throws IOException, ProtocolException {
|
|
||||||
super(r);
|
|
||||||
this.fitems = fitems;
|
|
||||||
parse();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getItemCount() {
|
|
||||||
return items.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Item getItem(int index) {
|
|
||||||
return items[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
public Item getItem(Class c) {
|
|
||||||
for (int i = 0; i < items.length; i++) {
|
|
||||||
if (c.isInstance(items[i]))
|
|
||||||
return items[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Item getItem(Response[] r, int msgno, Class c) {
|
|
||||||
if (r == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
for (int i = 0; i < r.length; i++) {
|
|
||||||
|
|
||||||
if (r[i] == null ||
|
|
||||||
!(r[i] instanceof FetchResponse) ||
|
|
||||||
((FetchResponse)r[i]).getNumber() != msgno)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
FetchResponse f = (FetchResponse)r[i];
|
|
||||||
for (int j = 0; j < f.items.length; j++) {
|
|
||||||
if (c.isInstance(f.items[j]))
|
|
||||||
return f.items[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a map of the extension items found in this fetch response.
|
|
||||||
* The map is indexed by extension item name. Callers should not
|
|
||||||
* modify the map.
|
|
||||||
*
|
|
||||||
* @since JavaMail 1.4.6
|
|
||||||
*/
|
|
||||||
public Map getExtensionItems() {
|
|
||||||
if (extensionItems == null)
|
|
||||||
extensionItems = new HashMap();
|
|
||||||
return extensionItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final static char[] HEADER = {'.','H','E','A','D','E','R'};
|
|
||||||
private final static char[] TEXT = {'.','T','E','X','T'};
|
|
||||||
|
|
||||||
private void parse() throws ParsingException {
|
|
||||||
skipSpaces();
|
|
||||||
if (buffer[index] != '(')
|
|
||||||
throw new ParsingException(
|
|
||||||
"error in FETCH parsing, missing '(' at index " + index);
|
|
||||||
|
|
||||||
Vector v = new Vector();
|
|
||||||
Item i = null;
|
|
||||||
do {
|
|
||||||
index++; // skip '(', or SPACE
|
|
||||||
|
|
||||||
if (index >= size)
|
|
||||||
throw new ParsingException(
|
|
||||||
"error in FETCH parsing, ran off end of buffer, size " + size);
|
|
||||||
|
|
||||||
i = parseItem();
|
|
||||||
if (i != null)
|
|
||||||
v.addElement(i);
|
|
||||||
else if (!parseExtensionItem())
|
|
||||||
throw new ParsingException(
|
|
||||||
"error in FETCH parsing, unrecognized item at index " + index);
|
|
||||||
} while (buffer[index] != ')');
|
|
||||||
|
|
||||||
index++; // skip ')'
|
|
||||||
items = new Item[v.size()];
|
|
||||||
v.copyInto(items);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse the item at the current position in the buffer,
|
|
||||||
* skipping over the item if successful. Otherwise, return null
|
|
||||||
* and leave the buffer position unmodified.
|
|
||||||
*/
|
|
||||||
private Item parseItem() throws ParsingException {
|
|
||||||
switch (buffer[index]) {
|
|
||||||
case 'E': case 'e':
|
|
||||||
if (match(ENVELOPE.name))
|
|
||||||
return new ENVELOPE(this);
|
|
||||||
break;
|
|
||||||
case 'F': case 'f':
|
|
||||||
if (match(FLAGS.name))
|
|
||||||
return new FLAGS((IMAPResponse)this);
|
|
||||||
break;
|
|
||||||
case 'I': case 'i':
|
|
||||||
if (match(INTERNALDATE.name))
|
|
||||||
return new INTERNALDATE(this);
|
|
||||||
break;
|
|
||||||
case 'B': case 'b':
|
|
||||||
if (match(BODYSTRUCTURE.name))
|
|
||||||
return new BODYSTRUCTURE(this);
|
|
||||||
else if (match(BODY.name)) {
|
|
||||||
if (buffer[index] == '[')
|
|
||||||
return new BODY(this);
|
|
||||||
else
|
|
||||||
return new BODYSTRUCTURE(this);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'R': case 'r':
|
|
||||||
if (match(RFC822SIZE.name))
|
|
||||||
return new RFC822SIZE(this);
|
|
||||||
else if (match(RFC822DATA.name)) {
|
|
||||||
if (match(HEADER))
|
|
||||||
; // skip ".HEADER"
|
|
||||||
else if (match(TEXT))
|
|
||||||
; // skip ".TEXT"
|
|
||||||
return new RFC822DATA(this);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'U': case 'u':
|
|
||||||
if (match(UID.name))
|
|
||||||
return new UID(this);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If this item is a known extension item, parse it.
|
|
||||||
*/
|
|
||||||
private boolean parseExtensionItem() throws ParsingException {
|
|
||||||
if (fitems == null)
|
|
||||||
return false;
|
|
||||||
for (int i = 0; i < fitems.length; i++) {
|
|
||||||
if (match(fitems[i].getName())) {
|
|
||||||
getExtensionItems().put(fitems[i].getName(),
|
|
||||||
fitems[i].parseItem(this));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does the current buffer match the given item name?
|
|
||||||
* itemName is the name of the IMAP item to compare against.
|
|
||||||
* NOTE that itemName *must* be all uppercase.
|
|
||||||
* If the match is successful, the buffer pointer (index)
|
|
||||||
* is incremented past the matched item.
|
|
||||||
*/
|
|
||||||
private boolean match(char[] itemName) {
|
|
||||||
int len = itemName.length;
|
|
||||||
for (int i = 0, j = index; i < len;)
|
|
||||||
// IMAP tokens are case-insensitive. We store itemNames in
|
|
||||||
// uppercase, so convert operand to uppercase before comparing.
|
|
||||||
if (Character.toUpperCase((char)buffer[j++]) != itemName[i++])
|
|
||||||
return false;
|
|
||||||
index += len;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does the current buffer match the given item name?
|
|
||||||
* itemName is the name of the IMAP item to compare against.
|
|
||||||
* NOTE that itemName *must* be all uppercase.
|
|
||||||
* If the match is successful, the buffer pointer (index)
|
|
||||||
* is incremented past the matched item.
|
|
||||||
*/
|
|
||||||
private boolean match(String itemName) {
|
|
||||||
int len = itemName.length();
|
|
||||||
for (int i = 0, j = index; i < len;)
|
|
||||||
// IMAP tokens are case-insensitive. We store itemNames in
|
|
||||||
// uppercase, so convert operand to uppercase before comparing.
|
|
||||||
if (Character.toUpperCase((char)buffer[j++]) !=
|
|
||||||
itemName.charAt(i++))
|
|
||||||
return false;
|
|
||||||
index += len;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,142 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap.protocol;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.*;
|
|
||||||
import com.sun.mail.util.*;
|
|
||||||
import com.sun.mail.iap.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class represents a response obtained from the input stream
|
|
||||||
* of an IMAP server.
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class IMAPResponse extends Response {
|
|
||||||
private String key;
|
|
||||||
private int number;
|
|
||||||
|
|
||||||
public IMAPResponse(Protocol c) throws IOException, ProtocolException {
|
|
||||||
super(c);
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init() throws IOException, ProtocolException {
|
|
||||||
// continue parsing if this is an untagged response
|
|
||||||
if (isUnTagged() && !isOK() && !isNO() && !isBAD() && !isBYE()) {
|
|
||||||
key = readAtom();
|
|
||||||
|
|
||||||
// Is this response of the form "* <number> <command>"
|
|
||||||
try {
|
|
||||||
number = Integer.parseInt(key);
|
|
||||||
key = readAtom();
|
|
||||||
} catch (NumberFormatException ne) { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy constructor.
|
|
||||||
*/
|
|
||||||
public IMAPResponse(IMAPResponse r) {
|
|
||||||
super((Response)r);
|
|
||||||
key = r.key;
|
|
||||||
number = r.number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For testing.
|
|
||||||
*/
|
|
||||||
public IMAPResponse(String r) throws IOException, ProtocolException {
|
|
||||||
super(r);
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a list of space-separated "flag_extension" sequences and
|
|
||||||
* return the list as a array of Strings. An empty list is returned
|
|
||||||
* as null. This is an IMAP-ism, and perhaps this method should
|
|
||||||
* moved into the IMAP layer.
|
|
||||||
*/
|
|
||||||
public String[] readSimpleList() {
|
|
||||||
skipSpaces();
|
|
||||||
|
|
||||||
if (buffer[index] != '(') // not what we expected
|
|
||||||
return null;
|
|
||||||
index++; // skip '('
|
|
||||||
|
|
||||||
Vector v = new Vector();
|
|
||||||
int start;
|
|
||||||
for (start = index; buffer[index] != ')'; index++) {
|
|
||||||
if (buffer[index] == ' ') { // got one item
|
|
||||||
v.addElement(ASCIIUtility.toString(buffer, start, index));
|
|
||||||
start = index+1; // index gets incremented at the top
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (index > start) // get the last item
|
|
||||||
v.addElement(ASCIIUtility.toString(buffer, start, index));
|
|
||||||
index++; // skip ')'
|
|
||||||
|
|
||||||
int size = v.size();
|
|
||||||
if (size > 0) {
|
|
||||||
String[] s = new String[size];
|
|
||||||
v.copyInto(s);
|
|
||||||
return s;
|
|
||||||
} else // empty list
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getKey() {
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean keyEquals(String k) {
|
|
||||||
if (key != null && key.equalsIgnoreCase(k))
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getNumber() {
|
|
||||||
return number;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,271 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap.protocol;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import javax.security.sasl.*;
|
|
||||||
import javax.security.auth.callback.*;
|
|
||||||
|
|
||||||
import com.sun.mail.iap.*;
|
|
||||||
import com.sun.mail.imap.*;
|
|
||||||
import com.sun.mail.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class contains a single method that does authentication using
|
|
||||||
* SASL. This is in a separate class so that it can be compiled with
|
|
||||||
* J2SE 1.5. Eventually it should be merged into IMAPProtocol.java.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class IMAPSaslAuthenticator implements SaslAuthenticator {
|
|
||||||
|
|
||||||
private IMAPProtocol pr;
|
|
||||||
private String name;
|
|
||||||
private Properties props;
|
|
||||||
private MailLogger logger;
|
|
||||||
private String host;
|
|
||||||
|
|
||||||
public IMAPSaslAuthenticator(IMAPProtocol pr, String name, Properties props,
|
|
||||||
MailLogger logger, String host) {
|
|
||||||
this.pr = pr;
|
|
||||||
this.name = name;
|
|
||||||
this.props = props;
|
|
||||||
this.logger = logger;
|
|
||||||
this.host = host;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean authenticate(String[] mechs, final String realm,
|
|
||||||
final String authzid, final String u,
|
|
||||||
final String p) throws ProtocolException {
|
|
||||||
|
|
||||||
synchronized (pr) { // authenticate method should be synchronized
|
|
||||||
Vector v = new Vector();
|
|
||||||
String tag = null;
|
|
||||||
Response r = null;
|
|
||||||
boolean done = false;
|
|
||||||
if (logger.isLoggable(Level.FINE)) {
|
|
||||||
logger.fine("SASL Mechanisms:");
|
|
||||||
for (int i = 0; i < mechs.length; i++)
|
|
||||||
logger.fine(" " + mechs[i]);
|
|
||||||
logger.fine("");
|
|
||||||
}
|
|
||||||
|
|
||||||
SaslClient sc;
|
|
||||||
CallbackHandler cbh = new CallbackHandler() {
|
|
||||||
public void handle(Callback[] callbacks) {
|
|
||||||
if (logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("SASL callback length: " + callbacks.length);
|
|
||||||
for (int i = 0; i < callbacks.length; i++) {
|
|
||||||
if (logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("SASL callback " + i + ": " + callbacks[i]);
|
|
||||||
if (callbacks[i] instanceof NameCallback) {
|
|
||||||
NameCallback ncb = (NameCallback)callbacks[i];
|
|
||||||
ncb.setName(u);
|
|
||||||
} else if (callbacks[i] instanceof PasswordCallback) {
|
|
||||||
PasswordCallback pcb = (PasswordCallback)callbacks[i];
|
|
||||||
pcb.setPassword(p.toCharArray());
|
|
||||||
} else if (callbacks[i] instanceof RealmCallback) {
|
|
||||||
RealmCallback rcb = (RealmCallback)callbacks[i];
|
|
||||||
rcb.setText(realm != null ?
|
|
||||||
realm : rcb.getDefaultText());
|
|
||||||
} else if (callbacks[i] instanceof RealmChoiceCallback) {
|
|
||||||
RealmChoiceCallback rcb =
|
|
||||||
(RealmChoiceCallback)callbacks[i];
|
|
||||||
if (realm == null)
|
|
||||||
rcb.setSelectedIndex(rcb.getDefaultChoice());
|
|
||||||
else {
|
|
||||||
// need to find specified realm in list
|
|
||||||
String[] choices = rcb.getChoices();
|
|
||||||
for (int k = 0; k < choices.length; k++) {
|
|
||||||
if (choices[k].equals(realm)) {
|
|
||||||
rcb.setSelectedIndex(k);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
sc = Sasl.createSaslClient(mechs, authzid, name, host,
|
|
||||||
(Map)props, cbh);
|
|
||||||
} catch (SaslException sex) {
|
|
||||||
logger.log(Level.FINE, "Failed to create SASL client", sex);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (sc == null) {
|
|
||||||
logger.fine("No SASL support");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("SASL client " + sc.getMechanismName());
|
|
||||||
|
|
||||||
try {
|
|
||||||
tag = pr.writeCommand("AUTHENTICATE " + sc.getMechanismName(),
|
|
||||||
null);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
logger.log(Level.FINE, "SASL AUTHENTICATE Exception", ex);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
OutputStream os = pr.getIMAPOutputStream(); // stream to IMAP server
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Wrap a BASE64Encoder around a ByteArrayOutputstream
|
|
||||||
* to craft b64 encoded username and password strings
|
|
||||||
*
|
|
||||||
* Note that the encoded bytes should be sent "as-is" to the
|
|
||||||
* server, *not* as literals or quoted-strings.
|
|
||||||
*
|
|
||||||
* Also note that unlike the B64 definition in MIME, CRLFs
|
|
||||||
* should *not* be inserted during the encoding process. So, I
|
|
||||||
* use Integer.MAX_VALUE (0x7fffffff (> 1G)) as the bytesPerLine,
|
|
||||||
* which should be sufficiently large !
|
|
||||||
*/
|
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
||||||
byte[] CRLF = { (byte)'\r', (byte)'\n'};
|
|
||||||
|
|
||||||
// Hack for Novell GroupWise XGWTRUSTEDAPP authentication mechanism
|
|
||||||
boolean isXGWTRUSTEDAPP =
|
|
||||||
sc.getMechanismName().equals("XGWTRUSTEDAPP") &&
|
|
||||||
PropUtil.getBooleanProperty(props,
|
|
||||||
"mail." + name + ".sasl.xgwtrustedapphack.enable", true);
|
|
||||||
while (!done) { // loop till we are done
|
|
||||||
try {
|
|
||||||
r = pr.readResponse();
|
|
||||||
if (r.isContinuation()) {
|
|
||||||
byte[] ba = null;
|
|
||||||
if (!sc.isComplete()) {
|
|
||||||
ba = r.readByteArray().getNewBytes();
|
|
||||||
if (ba.length > 0)
|
|
||||||
ba = BASE64DecoderStream.decode(ba);
|
|
||||||
if (logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("SASL challenge: " +
|
|
||||||
ASCIIUtility.toString(ba, 0, ba.length) + " :");
|
|
||||||
ba = sc.evaluateChallenge(ba);
|
|
||||||
}
|
|
||||||
if (ba == null) {
|
|
||||||
logger.fine("SASL no response");
|
|
||||||
os.write(CRLF); // write out empty line
|
|
||||||
os.flush(); // flush the stream
|
|
||||||
bos.reset(); // reset buffer
|
|
||||||
} else {
|
|
||||||
if (logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("SASL response: " +
|
|
||||||
ASCIIUtility.toString(ba, 0, ba.length) + " :");
|
|
||||||
ba = BASE64EncoderStream.encode(ba);
|
|
||||||
if (isXGWTRUSTEDAPP)
|
|
||||||
bos.write(ASCIIUtility.getBytes("XGWTRUSTEDAPP "));
|
|
||||||
bos.write(ba);
|
|
||||||
|
|
||||||
bos.write(CRLF); // CRLF termination
|
|
||||||
os.write(bos.toByteArray()); // write out line
|
|
||||||
os.flush(); // flush the stream
|
|
||||||
bos.reset(); // reset buffer
|
|
||||||
}
|
|
||||||
} else if (r.isTagged() && r.getTag().equals(tag))
|
|
||||||
// Ah, our tagged response
|
|
||||||
done = true;
|
|
||||||
else if (r.isBYE()) // outta here
|
|
||||||
done = true;
|
|
||||||
else // hmm .. unsolicited response here ?!
|
|
||||||
v.addElement(r);
|
|
||||||
} catch (Exception ioex) {
|
|
||||||
logger.log(Level.FINE, "SASL Exception", ioex);
|
|
||||||
// convert this into a BYE response
|
|
||||||
r = Response.byeResponse(ioex);
|
|
||||||
done = true;
|
|
||||||
// XXX - ultimately return true???
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sc.isComplete() /*&& res.status == SUCCESS*/) {
|
|
||||||
String qop = (String)sc.getNegotiatedProperty(Sasl.QOP);
|
|
||||||
if (qop != null && (qop.equalsIgnoreCase("auth-int") ||
|
|
||||||
qop.equalsIgnoreCase("auth-conf"))) {
|
|
||||||
// XXX - NOT SUPPORTED!!!
|
|
||||||
logger.fine(
|
|
||||||
"SASL Mechanism requires integrity or confidentiality");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dispatch untagged responses.
|
|
||||||
* NOTE: in our current upper level IMAP classes, we add the
|
|
||||||
* responseHandler to the Protocol object only *after* the
|
|
||||||
* connection has been authenticated. So, for now, the below
|
|
||||||
* code really ends up being just a no-op.
|
|
||||||
*/
|
|
||||||
Response[] responses = new Response[v.size()];
|
|
||||||
v.copyInto(responses);
|
|
||||||
pr.notifyResponseHandlers(responses);
|
|
||||||
|
|
||||||
// Handle the final OK, NO, BAD or BYE response
|
|
||||||
pr.handleResult(r);
|
|
||||||
pr.setCapabilities(r);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we're using the Novell Groupwise XGWTRUSTEDAPP mechanism
|
|
||||||
* we always have to issue a LOGIN command to select the user
|
|
||||||
* we want to operate as.
|
|
||||||
*/
|
|
||||||
if (isXGWTRUSTEDAPP) {
|
|
||||||
Argument args = new Argument();
|
|
||||||
args.writeString(authzid != null ? authzid : u);
|
|
||||||
|
|
||||||
responses = pr.command("LOGIN", args);
|
|
||||||
|
|
||||||
// dispatch untagged responses
|
|
||||||
pr.notifyResponseHandlers(responses);
|
|
||||||
|
|
||||||
// Handle result of this command
|
|
||||||
pr.handleResult(responses[responses.length-1]);
|
|
||||||
// If the response includes a CAPABILITY response code, process it
|
|
||||||
pr.setCapabilities(responses[responses.length-1]);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,144 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2013 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap.protocol;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.TimeZone;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.text.FieldPosition;
|
|
||||||
|
|
||||||
import javax.mail.internet.MailDateFormat;
|
|
||||||
|
|
||||||
import com.sun.mail.iap.*;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class INTERNALDATE implements Item {
|
|
||||||
|
|
||||||
static final char[] name =
|
|
||||||
{'I','N','T','E','R','N','A','L','D','A','T','E'};
|
|
||||||
public int msgno;
|
|
||||||
protected Date date;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Used to parse dates only. The parse method is thread safe
|
|
||||||
* so we only need to create a single object for use by all
|
|
||||||
* instances. We depend on the fact that the MailDateFormat
|
|
||||||
* class will parse dates in INTERNALDATE format as well as
|
|
||||||
* dates in RFC 822 format.
|
|
||||||
*/
|
|
||||||
private static MailDateFormat mailDateFormat = new MailDateFormat();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
public INTERNALDATE(FetchResponse r) throws ParsingException {
|
|
||||||
msgno = r.getNumber();
|
|
||||||
r.skipSpaces();
|
|
||||||
String s = r.readString();
|
|
||||||
if (s == null)
|
|
||||||
throw new ParsingException("INTERNALDATE is NIL");
|
|
||||||
try {
|
|
||||||
date = mailDateFormat.parse(s);
|
|
||||||
} catch (ParseException pex) {
|
|
||||||
throw new ParsingException("INTERNALDATE parse error");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getDate() {
|
|
||||||
return date;
|
|
||||||
}
|
|
||||||
|
|
||||||
// INTERNALDATE formatter
|
|
||||||
|
|
||||||
private static SimpleDateFormat df =
|
|
||||||
// Need Locale.US, the "MMM" field can produce unexpected values
|
|
||||||
// in non US locales !
|
|
||||||
new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss ", Locale.US);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Format given Date object into INTERNALDATE string
|
|
||||||
*/
|
|
||||||
public static String format(Date d) {
|
|
||||||
/*
|
|
||||||
* SimpleDateFormat objects aren't thread safe, so rather
|
|
||||||
* than create a separate such object for each request,
|
|
||||||
* we create one object and synchronize its use here
|
|
||||||
* so that only one thread is using it at a time. This
|
|
||||||
* trades off some potential concurrency for speed in the
|
|
||||||
* common case.
|
|
||||||
*
|
|
||||||
* This method is only used when formatting the date in a
|
|
||||||
* message that's being appended to a folder.
|
|
||||||
*/
|
|
||||||
StringBuffer sb = new StringBuffer();
|
|
||||||
synchronized (df) {
|
|
||||||
df.format(d, sb, new FieldPosition(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
// compute timezone offset string
|
|
||||||
TimeZone tz = TimeZone.getDefault();
|
|
||||||
int offset = tz.getOffset(d.getTime()); // get offset from GMT
|
|
||||||
int rawOffsetInMins = offset / 60 / 1000; // offset from GMT in mins
|
|
||||||
if (rawOffsetInMins < 0) {
|
|
||||||
sb.append('-');
|
|
||||||
rawOffsetInMins = (-rawOffsetInMins);
|
|
||||||
} else
|
|
||||||
sb.append('+');
|
|
||||||
|
|
||||||
int offsetInHrs = rawOffsetInMins / 60;
|
|
||||||
int offsetInMins = rawOffsetInMins % 60;
|
|
||||||
|
|
||||||
sb.append(Character.forDigit((offsetInHrs/10), 10));
|
|
||||||
sb.append(Character.forDigit((offsetInHrs%10), 10));
|
|
||||||
sb.append(Character.forDigit((offsetInMins/10), 10));
|
|
||||||
sb.append(Character.forDigit((offsetInMins%10), 10));
|
|
||||||
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap.protocol;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A tagging interface for all IMAP data items.
|
|
||||||
* Note that the "name" field of all IMAP items MUST be in uppercase. <p>
|
|
||||||
*
|
|
||||||
* See the BODY, BODYSTRUCTURE, ENVELOPE, FLAGS, INTERNALDATE, RFC822DATA,
|
|
||||||
* RFC822SIZE, and UID classes.
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
|
|
||||||
public interface Item {
|
|
||||||
}
|
|
||||||
@ -1,102 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap.protocol;
|
|
||||||
|
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
import com.sun.mail.iap.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A LIST response.
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
* @author Bill Shannon
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class ListInfo {
|
|
||||||
public String name = null;
|
|
||||||
public char separator = '/';
|
|
||||||
public boolean hasInferiors = true;
|
|
||||||
public boolean canOpen = true;
|
|
||||||
public int changeState = INDETERMINATE;
|
|
||||||
public String[] attrs;
|
|
||||||
|
|
||||||
public static final int CHANGED = 1;
|
|
||||||
public static final int UNCHANGED = 2;
|
|
||||||
public static final int INDETERMINATE = 3;
|
|
||||||
|
|
||||||
public ListInfo(IMAPResponse r) throws ParsingException {
|
|
||||||
String[] s = r.readSimpleList();
|
|
||||||
|
|
||||||
Vector v = new Vector(); // accumulate attributes
|
|
||||||
if (s != null) {
|
|
||||||
// non-empty attribute list
|
|
||||||
for (int i = 0; i < s.length; i++) {
|
|
||||||
if (s[i].equalsIgnoreCase("\\Marked"))
|
|
||||||
changeState = CHANGED;
|
|
||||||
else if (s[i].equalsIgnoreCase("\\Unmarked"))
|
|
||||||
changeState = UNCHANGED;
|
|
||||||
else if (s[i].equalsIgnoreCase("\\Noselect"))
|
|
||||||
canOpen = false;
|
|
||||||
else if (s[i].equalsIgnoreCase("\\Noinferiors"))
|
|
||||||
hasInferiors = false;
|
|
||||||
v.addElement(s[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
attrs = new String[v.size()];
|
|
||||||
v.copyInto(attrs);
|
|
||||||
|
|
||||||
r.skipSpaces();
|
|
||||||
if (r.readByte() == '"') {
|
|
||||||
if ((separator = (char)r.readByte()) == '\\')
|
|
||||||
// escaped separator character
|
|
||||||
separator = (char)r.readByte();
|
|
||||||
r.skip(1); // skip <">
|
|
||||||
} else // NIL
|
|
||||||
r.skip(2);
|
|
||||||
|
|
||||||
r.skipSpaces();
|
|
||||||
name = r.readAtomString();
|
|
||||||
|
|
||||||
// decode the name (using RFC2060's modified UTF7)
|
|
||||||
name = BASE64MailboxDecoder.decode(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,127 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap.protocol;
|
|
||||||
|
|
||||||
import javax.mail.Flags;
|
|
||||||
import com.sun.mail.iap.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class MailboxInfo {
|
|
||||||
public Flags availableFlags = null;
|
|
||||||
public Flags permanentFlags = null;
|
|
||||||
public int total = -1;
|
|
||||||
public int recent = -1;
|
|
||||||
public int first = -1;
|
|
||||||
public long uidvalidity = -1;
|
|
||||||
public long uidnext = -1;
|
|
||||||
public int mode;
|
|
||||||
|
|
||||||
public MailboxInfo(Response[] r) throws ParsingException {
|
|
||||||
for (int i = 0; i < r.length; i++) {
|
|
||||||
if (r[i] == null || !(r[i] instanceof IMAPResponse))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
IMAPResponse ir = (IMAPResponse)r[i];
|
|
||||||
|
|
||||||
if (ir.keyEquals("EXISTS")) {
|
|
||||||
total = ir.getNumber();
|
|
||||||
r[i] = null; // remove this response
|
|
||||||
}
|
|
||||||
else if (ir.keyEquals("RECENT")) {
|
|
||||||
recent = ir.getNumber();
|
|
||||||
r[i] = null; // remove this response
|
|
||||||
}
|
|
||||||
else if (ir.keyEquals("FLAGS")) {
|
|
||||||
availableFlags = new FLAGS(ir);
|
|
||||||
r[i] = null; // remove this response
|
|
||||||
}
|
|
||||||
else if (ir.isUnTagged() && ir.isOK()) {
|
|
||||||
/* should be one of:
|
|
||||||
* OK [UNSEEN 12]
|
|
||||||
* OK [UIDVALIDITY 3857529045]
|
|
||||||
* OK [PERMANENTFLAGS (\Deleted)]
|
|
||||||
* OK [UIDNEXT 44]
|
|
||||||
*/
|
|
||||||
ir.skipSpaces();
|
|
||||||
|
|
||||||
if (ir.readByte() != '[') { // huh ???
|
|
||||||
ir.reset();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean handled = true;
|
|
||||||
String s = ir.readAtom();
|
|
||||||
if (s.equalsIgnoreCase("UNSEEN"))
|
|
||||||
first = ir.readNumber();
|
|
||||||
else if (s.equalsIgnoreCase("UIDVALIDITY"))
|
|
||||||
uidvalidity = ir.readLong();
|
|
||||||
else if (s.equalsIgnoreCase("PERMANENTFLAGS"))
|
|
||||||
permanentFlags = new FLAGS(ir);
|
|
||||||
else if (s.equalsIgnoreCase("UIDNEXT"))
|
|
||||||
uidnext = ir.readLong();
|
|
||||||
else
|
|
||||||
handled = false; // possibly an ALERT
|
|
||||||
|
|
||||||
if (handled)
|
|
||||||
r[i] = null; // remove this response
|
|
||||||
else
|
|
||||||
ir.reset(); // so ALERT can be read
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The PERMANENTFLAGS response code is optional, and if
|
|
||||||
* not present implies that all flags in the required FLAGS
|
|
||||||
* response can be changed permanently.
|
|
||||||
*/
|
|
||||||
if (permanentFlags == null) {
|
|
||||||
if (availableFlags != null)
|
|
||||||
permanentFlags = new Flags(availableFlags);
|
|
||||||
else
|
|
||||||
permanentFlags = new Flags();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,137 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap.protocol;
|
|
||||||
|
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class holds the 'start' and 'end' for a range of messages
|
|
||||||
*/
|
|
||||||
public class MessageSet {
|
|
||||||
|
|
||||||
public int start;
|
|
||||||
public int end;
|
|
||||||
|
|
||||||
public MessageSet() { }
|
|
||||||
|
|
||||||
public MessageSet(int start, int end) {
|
|
||||||
this.start = start;
|
|
||||||
this.end = end;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Count the total number of elements in a MessageSet
|
|
||||||
**/
|
|
||||||
public int size() {
|
|
||||||
return end - start + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert an array of integers into an array of MessageSets
|
|
||||||
*/
|
|
||||||
public static MessageSet[] createMessageSets(int[] msgs) {
|
|
||||||
Vector v = new Vector();
|
|
||||||
int i,j;
|
|
||||||
|
|
||||||
for (i=0; i < msgs.length; i++) {
|
|
||||||
MessageSet ms = new MessageSet();
|
|
||||||
ms.start = msgs[i];
|
|
||||||
|
|
||||||
// Look for contiguous elements
|
|
||||||
for (j=i+1; j < msgs.length; j++) {
|
|
||||||
if (msgs[j] != msgs[j-1] +1)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ms.end = msgs[j-1];
|
|
||||||
v.addElement(ms);
|
|
||||||
i = j-1; // i gets incremented @ top of the loop
|
|
||||||
}
|
|
||||||
MessageSet[] msgsets = new MessageSet[v.size()];
|
|
||||||
v.copyInto(msgsets);
|
|
||||||
return msgsets;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert an array of MessageSets into an IMAP sequence range
|
|
||||||
*/
|
|
||||||
public static String toString(MessageSet[] msgsets) {
|
|
||||||
if (msgsets == null || msgsets.length == 0) // Empty msgset
|
|
||||||
return null;
|
|
||||||
|
|
||||||
int i = 0; // msgset index
|
|
||||||
StringBuffer s = new StringBuffer();
|
|
||||||
int size = msgsets.length;
|
|
||||||
int start, end;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
start = msgsets[i].start;
|
|
||||||
end = msgsets[i].end;
|
|
||||||
|
|
||||||
if (end > start)
|
|
||||||
s.append(start).append(':').append(end);
|
|
||||||
else // end == start means only one element
|
|
||||||
s.append(start);
|
|
||||||
|
|
||||||
i++; // Next MessageSet
|
|
||||||
if (i >= size) // No more MessageSets
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
s.append(',');
|
|
||||||
}
|
|
||||||
return s.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Count the total number of elements in an array of MessageSets
|
|
||||||
*/
|
|
||||||
public static int size(MessageSet[] msgsets) {
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
if (msgsets == null) // Null msgset
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (int i=0; i < msgsets.length; i++)
|
|
||||||
count += msgsets[i].size();
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,168 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap.protocol;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import com.sun.mail.iap.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class and its inner class represent the response to the
|
|
||||||
* NAMESPACE command. <p>
|
|
||||||
*
|
|
||||||
* See <A HREF="http://www.ietf.org/rfc/rfc2342.txt">RFC 2342</A>.
|
|
||||||
*
|
|
||||||
* @author Bill Shannon
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class Namespaces {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A single namespace entry.
|
|
||||||
*/
|
|
||||||
public static class Namespace {
|
|
||||||
/**
|
|
||||||
* Prefix string for the namespace.
|
|
||||||
*/
|
|
||||||
public String prefix;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delimiter between names in this namespace.
|
|
||||||
*/
|
|
||||||
public char delimiter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse a namespace element out of the response.
|
|
||||||
*/
|
|
||||||
public Namespace(Response r) throws ProtocolException {
|
|
||||||
// Namespace_Element = "(" string SP (<"> QUOTED_CHAR <"> / nil)
|
|
||||||
// *(Namespace_Response_Extension) ")"
|
|
||||||
if (r.readByte() != '(')
|
|
||||||
throw new ProtocolException(
|
|
||||||
"Missing '(' at start of Namespace");
|
|
||||||
// first, the prefix
|
|
||||||
prefix = BASE64MailboxDecoder.decode(r.readString());
|
|
||||||
r.skipSpaces();
|
|
||||||
// delimiter is a quoted character or NIL
|
|
||||||
if (r.peekByte() == '"') {
|
|
||||||
r.readByte();
|
|
||||||
delimiter = (char)r.readByte();
|
|
||||||
if (delimiter == '\\')
|
|
||||||
delimiter = (char)r.readByte();
|
|
||||||
if (r.readByte() != '"')
|
|
||||||
throw new ProtocolException(
|
|
||||||
"Missing '\"' at end of QUOTED_CHAR");
|
|
||||||
} else {
|
|
||||||
String s = r.readAtom();
|
|
||||||
if (s == null)
|
|
||||||
throw new ProtocolException("Expected NIL, got null");
|
|
||||||
if (!s.equalsIgnoreCase("NIL"))
|
|
||||||
throw new ProtocolException("Expected NIL, got " + s);
|
|
||||||
delimiter = 0;
|
|
||||||
}
|
|
||||||
// at end of Namespace data?
|
|
||||||
if (r.peekByte() != ')') {
|
|
||||||
// otherwise, must be a Namespace_Response_Extension
|
|
||||||
// Namespace_Response_Extension = SP string SP
|
|
||||||
// "(" string *(SP string) ")"
|
|
||||||
r.skipSpaces();
|
|
||||||
r.readString();
|
|
||||||
r.skipSpaces();
|
|
||||||
r.readStringList();
|
|
||||||
}
|
|
||||||
if (r.readByte() != ')')
|
|
||||||
throw new ProtocolException("Missing ')' at end of Namespace");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The personal namespaces.
|
|
||||||
* May be null.
|
|
||||||
*/
|
|
||||||
public Namespace[] personal;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The namespaces for other users.
|
|
||||||
* May be null.
|
|
||||||
*/
|
|
||||||
public Namespace[] otherUsers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The shared namespace.
|
|
||||||
* May be null.
|
|
||||||
*/
|
|
||||||
public Namespace[] shared;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse out all the namespaces.
|
|
||||||
*/
|
|
||||||
public Namespaces(Response r) throws ProtocolException {
|
|
||||||
personal = getNamespaces(r);
|
|
||||||
otherUsers = getNamespaces(r);
|
|
||||||
shared = getNamespaces(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse out one of the three sets of namespaces.
|
|
||||||
*/
|
|
||||||
private Namespace[] getNamespaces(Response r) throws ProtocolException {
|
|
||||||
r.skipSpaces();
|
|
||||||
// Namespace = nil / "(" 1*( Namespace_Element) ")"
|
|
||||||
if (r.peekByte() == '(') {
|
|
||||||
Vector v = new Vector();
|
|
||||||
r.readByte();
|
|
||||||
do {
|
|
||||||
Namespace ns = new Namespace(r);
|
|
||||||
v.addElement(ns);
|
|
||||||
} while (r.peekByte() != ')');
|
|
||||||
r.readByte();
|
|
||||||
Namespace[] nsa = new Namespace[v.size()];
|
|
||||||
v.copyInto(nsa);
|
|
||||||
return nsa;
|
|
||||||
} else {
|
|
||||||
String s = r.readAtom();
|
|
||||||
if (s == null)
|
|
||||||
throw new ProtocolException("Expected NIL, got null");
|
|
||||||
if (!s.equalsIgnoreCase("NIL"))
|
|
||||||
throw new ProtocolException("Expected NIL, got " + s);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap.protocol;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import com.sun.mail.iap.*;
|
|
||||||
import com.sun.mail.util.ASCIIUtility;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class RFC822DATA implements Item {
|
|
||||||
|
|
||||||
static final char[] name = {'R','F','C','8','2','2'};
|
|
||||||
public int msgno;
|
|
||||||
public ByteArray data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
public RFC822DATA(FetchResponse r) throws ParsingException {
|
|
||||||
msgno = r.getNumber();
|
|
||||||
r.skipSpaces();
|
|
||||||
data = r.readByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ByteArray getByteArray() {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ByteArrayInputStream getByteArrayInputStream() {
|
|
||||||
if (data != null)
|
|
||||||
return data.toByteArrayInputStream();
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap.protocol;
|
|
||||||
|
|
||||||
import com.sun.mail.iap.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class RFC822SIZE implements Item {
|
|
||||||
|
|
||||||
static final char[] name = {'R','F','C','8','2','2','.','S','I','Z','E'};
|
|
||||||
public int msgno;
|
|
||||||
|
|
||||||
public int size;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
public RFC822SIZE(FetchResponse r) throws ParsingException {
|
|
||||||
msgno = r.getNumber();
|
|
||||||
r.skipSpaces();
|
|
||||||
size = r.readNumber();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap.protocol;
|
|
||||||
|
|
||||||
import com.sun.mail.iap.ProtocolException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface to make it easier to call IMAPSaslAuthenticator.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public interface SaslAuthenticator {
|
|
||||||
public boolean authenticate(String[] mechs, String realm, String authzid,
|
|
||||||
String u, String p) throws ProtocolException;
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,446 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap.protocol;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import javax.mail.*;
|
|
||||||
import javax.mail.search.*;
|
|
||||||
import com.sun.mail.iap.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class traverses a search-tree and generates the
|
|
||||||
* corresponding IMAP search sequence.
|
|
||||||
*
|
|
||||||
* Each IMAPProtocol instance contains an instance of this class,
|
|
||||||
* which might be subclassed by subclasses of IMAPProtocol to add
|
|
||||||
* support for additional product-specific search terms.
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
public class SearchSequence {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate the IMAP search sequence for the given search expression.
|
|
||||||
*/
|
|
||||||
public Argument generateSequence(SearchTerm term, String charset)
|
|
||||||
throws SearchException, IOException {
|
|
||||||
/*
|
|
||||||
* Call the appropriate handler depending on the type of
|
|
||||||
* the search-term ...
|
|
||||||
*/
|
|
||||||
if (term instanceof AndTerm) // AND
|
|
||||||
return and((AndTerm)term, charset);
|
|
||||||
else if (term instanceof OrTerm) // OR
|
|
||||||
return or((OrTerm)term, charset);
|
|
||||||
else if (term instanceof NotTerm) // NOT
|
|
||||||
return not((NotTerm)term, charset);
|
|
||||||
else if (term instanceof HeaderTerm) // HEADER
|
|
||||||
return header((HeaderTerm)term, charset);
|
|
||||||
else if (term instanceof FlagTerm) // FLAG
|
|
||||||
return flag((FlagTerm)term);
|
|
||||||
else if (term instanceof FromTerm) { // FROM
|
|
||||||
FromTerm fterm = (FromTerm)term;
|
|
||||||
return from(fterm.getAddress().toString(), charset);
|
|
||||||
}
|
|
||||||
else if (term instanceof FromStringTerm) { // FROM
|
|
||||||
FromStringTerm fterm = (FromStringTerm)term;
|
|
||||||
return from(fterm.getPattern(), charset);
|
|
||||||
}
|
|
||||||
else if (term instanceof RecipientTerm) { // RECIPIENT
|
|
||||||
RecipientTerm rterm = (RecipientTerm)term;
|
|
||||||
return recipient(rterm.getRecipientType(),
|
|
||||||
rterm.getAddress().toString(),
|
|
||||||
charset);
|
|
||||||
}
|
|
||||||
else if (term instanceof RecipientStringTerm) { // RECIPIENT
|
|
||||||
RecipientStringTerm rterm = (RecipientStringTerm)term;
|
|
||||||
return recipient(rterm.getRecipientType(),
|
|
||||||
rterm.getPattern(),
|
|
||||||
charset);
|
|
||||||
}
|
|
||||||
else if (term instanceof SubjectTerm) // SUBJECT
|
|
||||||
return subject((SubjectTerm)term, charset);
|
|
||||||
else if (term instanceof BodyTerm) // BODY
|
|
||||||
return body((BodyTerm)term, charset);
|
|
||||||
else if (term instanceof SizeTerm) // SIZE
|
|
||||||
return size((SizeTerm)term);
|
|
||||||
else if (term instanceof SentDateTerm) // SENTDATE
|
|
||||||
return sentdate((SentDateTerm)term);
|
|
||||||
else if (term instanceof ReceivedDateTerm) // INTERNALDATE
|
|
||||||
return receiveddate((ReceivedDateTerm)term);
|
|
||||||
else if (term instanceof MessageIDTerm) // MessageID
|
|
||||||
return messageid((MessageIDTerm)term, charset);
|
|
||||||
else
|
|
||||||
throw new SearchException("Search too complex");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* *
|
|
||||||
* Check if the "text" terms in the given SearchTerm contain
|
|
||||||
* non US-ASCII characters.
|
|
||||||
*/
|
|
||||||
public static boolean isAscii(SearchTerm term) {
|
|
||||||
if (term instanceof AndTerm || term instanceof OrTerm) {
|
|
||||||
SearchTerm[] terms;
|
|
||||||
if (term instanceof AndTerm)
|
|
||||||
terms = ((AndTerm)term).getTerms();
|
|
||||||
else
|
|
||||||
terms = ((OrTerm)term).getTerms();
|
|
||||||
|
|
||||||
for (int i = 0; i < terms.length; i++)
|
|
||||||
if (!isAscii(terms[i])) // outta here !
|
|
||||||
return false;
|
|
||||||
} else if (term instanceof NotTerm)
|
|
||||||
return isAscii(((NotTerm)term).getTerm());
|
|
||||||
else if (term instanceof StringTerm)
|
|
||||||
return isAscii(((StringTerm)term).getPattern());
|
|
||||||
else if (term instanceof AddressTerm)
|
|
||||||
return isAscii(((AddressTerm)term).getAddress().toString());
|
|
||||||
|
|
||||||
// Any other term returns true.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does this string contain only ASCII characters?
|
|
||||||
*/
|
|
||||||
public static boolean isAscii(String s) {
|
|
||||||
int l = s.length();
|
|
||||||
|
|
||||||
for (int i=0; i < l; i++) {
|
|
||||||
if ((int)s.charAt(i) > 0177) // non-ascii
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Argument and(AndTerm term, String charset)
|
|
||||||
throws SearchException, IOException {
|
|
||||||
// Combine the sequences for both terms
|
|
||||||
SearchTerm[] terms = term.getTerms();
|
|
||||||
// Generate the search sequence for the first term
|
|
||||||
Argument result = generateSequence(terms[0], charset);
|
|
||||||
// Append other terms
|
|
||||||
for (int i = 1; i < terms.length; i++)
|
|
||||||
result.append(generateSequence(terms[i], charset));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Argument or(OrTerm term, String charset)
|
|
||||||
throws SearchException, IOException {
|
|
||||||
SearchTerm[] terms = term.getTerms();
|
|
||||||
|
|
||||||
/* The IMAP OR operator takes only two operands. So if
|
|
||||||
* we have more than 2 operands, group them into 2-operand
|
|
||||||
* OR Terms.
|
|
||||||
*/
|
|
||||||
if (terms.length > 2) {
|
|
||||||
SearchTerm t = terms[0];
|
|
||||||
|
|
||||||
// Include rest of the terms
|
|
||||||
for (int i = 1; i < terms.length; i++)
|
|
||||||
t = new OrTerm(t, terms[i]);
|
|
||||||
|
|
||||||
term = (OrTerm)t; // set 'term' to the new jumbo OrTerm we
|
|
||||||
// just created
|
|
||||||
terms = term.getTerms();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 'term' now has only two operands
|
|
||||||
Argument result = new Argument();
|
|
||||||
|
|
||||||
// Add the OR search-key, if more than one term
|
|
||||||
if (terms.length > 1)
|
|
||||||
result.writeAtom("OR");
|
|
||||||
|
|
||||||
/* If this term is an AND expression, we need to enclose it
|
|
||||||
* within paranthesis.
|
|
||||||
*
|
|
||||||
* AND expressions are either AndTerms or FlagTerms
|
|
||||||
*/
|
|
||||||
if (terms[0] instanceof AndTerm || terms[0] instanceof FlagTerm)
|
|
||||||
result.writeArgument(generateSequence(terms[0], charset));
|
|
||||||
else
|
|
||||||
result.append(generateSequence(terms[0], charset));
|
|
||||||
|
|
||||||
// Repeat the above for the second term, if there is one
|
|
||||||
if (terms.length > 1) {
|
|
||||||
if (terms[1] instanceof AndTerm || terms[1] instanceof FlagTerm)
|
|
||||||
result.writeArgument(generateSequence(terms[1], charset));
|
|
||||||
else
|
|
||||||
result.append(generateSequence(terms[1], charset));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Argument not(NotTerm term, String charset)
|
|
||||||
throws SearchException, IOException {
|
|
||||||
Argument result = new Argument();
|
|
||||||
|
|
||||||
// Add the NOT search-key
|
|
||||||
result.writeAtom("NOT");
|
|
||||||
|
|
||||||
/* If this term is an AND expression, we need to enclose it
|
|
||||||
* within paranthesis.
|
|
||||||
*
|
|
||||||
* AND expressions are either AndTerms or FlagTerms
|
|
||||||
*/
|
|
||||||
SearchTerm nterm = term.getTerm();
|
|
||||||
if (nterm instanceof AndTerm || nterm instanceof FlagTerm)
|
|
||||||
result.writeArgument(generateSequence(nterm, charset));
|
|
||||||
else
|
|
||||||
result.append(generateSequence(nterm, charset));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Argument header(HeaderTerm term, String charset)
|
|
||||||
throws SearchException, IOException {
|
|
||||||
Argument result = new Argument();
|
|
||||||
result.writeAtom("HEADER");
|
|
||||||
result.writeString(term.getHeaderName());
|
|
||||||
result.writeString(term.getPattern(), charset);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Argument messageid(MessageIDTerm term, String charset)
|
|
||||||
throws SearchException, IOException {
|
|
||||||
Argument result = new Argument();
|
|
||||||
result.writeAtom("HEADER");
|
|
||||||
result.writeString("Message-ID");
|
|
||||||
// XXX confirm that charset conversion ought to be done
|
|
||||||
result.writeString(term.getPattern(), charset);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Argument flag(FlagTerm term) throws SearchException {
|
|
||||||
boolean set = term.getTestSet();
|
|
||||||
|
|
||||||
Argument result = new Argument();
|
|
||||||
|
|
||||||
Flags flags = term.getFlags();
|
|
||||||
Flags.Flag[] sf = flags.getSystemFlags();
|
|
||||||
String[] uf = flags.getUserFlags();
|
|
||||||
if (sf.length == 0 && uf.length == 0)
|
|
||||||
throw new SearchException("Invalid FlagTerm");
|
|
||||||
|
|
||||||
for (int i = 0; i < sf.length; i++) {
|
|
||||||
if (sf[i] == Flags.Flag.DELETED)
|
|
||||||
result.writeAtom(set ? "DELETED": "UNDELETED");
|
|
||||||
else if (sf[i] == Flags.Flag.ANSWERED)
|
|
||||||
result.writeAtom(set ? "ANSWERED": "UNANSWERED");
|
|
||||||
else if (sf[i] == Flags.Flag.DRAFT)
|
|
||||||
result.writeAtom(set ? "DRAFT": "UNDRAFT");
|
|
||||||
else if (sf[i] == Flags.Flag.FLAGGED)
|
|
||||||
result.writeAtom(set ? "FLAGGED": "UNFLAGGED");
|
|
||||||
else if (sf[i] == Flags.Flag.RECENT)
|
|
||||||
result.writeAtom(set ? "RECENT": "OLD");
|
|
||||||
else if (sf[i] == Flags.Flag.SEEN)
|
|
||||||
result.writeAtom(set ? "SEEN": "UNSEEN");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < uf.length; i++) {
|
|
||||||
result.writeAtom(set ? "KEYWORD" : "UNKEYWORD");
|
|
||||||
result.writeAtom(uf[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Argument from(String address, String charset)
|
|
||||||
throws SearchException, IOException {
|
|
||||||
Argument result = new Argument();
|
|
||||||
result.writeAtom("FROM");
|
|
||||||
result.writeString(address, charset);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Argument recipient(Message.RecipientType type,
|
|
||||||
String address, String charset)
|
|
||||||
throws SearchException, IOException {
|
|
||||||
Argument result = new Argument();
|
|
||||||
|
|
||||||
if (type == Message.RecipientType.TO)
|
|
||||||
result.writeAtom("TO");
|
|
||||||
else if (type == Message.RecipientType.CC)
|
|
||||||
result.writeAtom("CC");
|
|
||||||
else if (type == Message.RecipientType.BCC)
|
|
||||||
result.writeAtom("BCC");
|
|
||||||
else
|
|
||||||
throw new SearchException("Illegal Recipient type");
|
|
||||||
|
|
||||||
result.writeString(address, charset);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Argument subject(SubjectTerm term, String charset)
|
|
||||||
throws SearchException, IOException {
|
|
||||||
Argument result = new Argument();
|
|
||||||
|
|
||||||
result.writeAtom("SUBJECT");
|
|
||||||
result.writeString(term.getPattern(), charset);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Argument body(BodyTerm term, String charset)
|
|
||||||
throws SearchException, IOException {
|
|
||||||
Argument result = new Argument();
|
|
||||||
|
|
||||||
result.writeAtom("BODY");
|
|
||||||
result.writeString(term.getPattern(), charset);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Argument size(SizeTerm term)
|
|
||||||
throws SearchException {
|
|
||||||
Argument result = new Argument();
|
|
||||||
|
|
||||||
switch (term.getComparison()) {
|
|
||||||
case ComparisonTerm.GT:
|
|
||||||
result.writeAtom("LARGER");
|
|
||||||
break;
|
|
||||||
case ComparisonTerm.LT:
|
|
||||||
result.writeAtom("SMALLER");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// GT and LT is all we get from IMAP for size
|
|
||||||
throw new SearchException("Cannot handle Comparison");
|
|
||||||
}
|
|
||||||
|
|
||||||
result.writeNumber(term.getNumber());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Date SEARCH stuff ...
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Print an IMAP Date string, that is suitable for the Date
|
|
||||||
* SEARCH commands.
|
|
||||||
*
|
|
||||||
* The IMAP Date string is :
|
|
||||||
* date ::= date_day "-" date_month "-" date_year
|
|
||||||
*
|
|
||||||
* Note that this format does not contain the TimeZone
|
|
||||||
*/
|
|
||||||
private static String monthTable[] = {
|
|
||||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
|
||||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
|
||||||
};
|
|
||||||
|
|
||||||
// A GregorianCalendar object in the current timezone
|
|
||||||
protected Calendar cal = new GregorianCalendar();
|
|
||||||
|
|
||||||
protected String toIMAPDate(Date date) {
|
|
||||||
StringBuffer s = new StringBuffer();
|
|
||||||
|
|
||||||
cal.setTime(date);
|
|
||||||
|
|
||||||
s.append(cal.get(Calendar.DATE)).append("-");
|
|
||||||
s.append(monthTable[cal.get(Calendar.MONTH)]).append('-');
|
|
||||||
s.append(cal.get(Calendar.YEAR));
|
|
||||||
|
|
||||||
return s.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Argument sentdate(DateTerm term)
|
|
||||||
throws SearchException {
|
|
||||||
Argument result = new Argument();
|
|
||||||
String date = toIMAPDate(term.getDate());
|
|
||||||
|
|
||||||
switch (term.getComparison()) {
|
|
||||||
case ComparisonTerm.GT:
|
|
||||||
result.writeAtom("SENTSINCE " + date);
|
|
||||||
break;
|
|
||||||
case ComparisonTerm.EQ:
|
|
||||||
result.writeAtom("SENTON " + date);
|
|
||||||
break;
|
|
||||||
case ComparisonTerm.LT:
|
|
||||||
result.writeAtom("SENTBEFORE " + date);
|
|
||||||
break;
|
|
||||||
case ComparisonTerm.GE:
|
|
||||||
result.writeAtom("OR SENTSINCE " + date + " SENTON " + date);
|
|
||||||
break;
|
|
||||||
case ComparisonTerm.LE:
|
|
||||||
result.writeAtom("OR SENTBEFORE " + date + " SENTON " + date);
|
|
||||||
break;
|
|
||||||
case ComparisonTerm.NE:
|
|
||||||
result.writeAtom("NOT SENTON " + date);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new SearchException("Cannot handle Date Comparison");
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Argument receiveddate(DateTerm term)
|
|
||||||
throws SearchException {
|
|
||||||
Argument result = new Argument();
|
|
||||||
String date = toIMAPDate(term.getDate());
|
|
||||||
|
|
||||||
switch (term.getComparison()) {
|
|
||||||
case ComparisonTerm.GT:
|
|
||||||
result.writeAtom("SINCE " + date);
|
|
||||||
break;
|
|
||||||
case ComparisonTerm.EQ:
|
|
||||||
result.writeAtom("ON " + date);
|
|
||||||
break;
|
|
||||||
case ComparisonTerm.LT:
|
|
||||||
result.writeAtom("BEFORE " + date);
|
|
||||||
break;
|
|
||||||
case ComparisonTerm.GE:
|
|
||||||
result.writeAtom("OR SINCE " + date + " ON " + date);
|
|
||||||
break;
|
|
||||||
case ComparisonTerm.LE:
|
|
||||||
result.writeAtom("OR BEFORE " + date + " ON " + date);
|
|
||||||
break;
|
|
||||||
case ComparisonTerm.NE:
|
|
||||||
result.writeAtom("NOT ON " + date);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new SearchException("Cannot handle Date Comparison");
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,114 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap.protocol;
|
|
||||||
|
|
||||||
import com.sun.mail.iap.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* STATUS response.
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class Status {
|
|
||||||
public String mbox = null;
|
|
||||||
public int total = -1;
|
|
||||||
public int recent = -1;
|
|
||||||
public long uidnext = -1;
|
|
||||||
public long uidvalidity = -1;
|
|
||||||
public int unseen = -1;
|
|
||||||
|
|
||||||
static final String[] standardItems =
|
|
||||||
{ "MESSAGES", "RECENT", "UNSEEN", "UIDNEXT", "UIDVALIDITY" };
|
|
||||||
|
|
||||||
public Status(Response r) throws ParsingException {
|
|
||||||
mbox = r.readAtomString(); // mailbox := astring
|
|
||||||
|
|
||||||
// Workaround buggy IMAP servers that don't quote folder names
|
|
||||||
// with spaces.
|
|
||||||
final StringBuffer buffer = new StringBuffer();
|
|
||||||
boolean onlySpaces = true;
|
|
||||||
|
|
||||||
while (r.peekByte() != '(' && r.peekByte() != 0) {
|
|
||||||
final char next = (char)r.readByte();
|
|
||||||
|
|
||||||
buffer.append(next);
|
|
||||||
|
|
||||||
if (next != ' ') {
|
|
||||||
onlySpaces = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!onlySpaces) {
|
|
||||||
mbox = (mbox + buffer).trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r.readByte() != '(')
|
|
||||||
throw new ParsingException("parse error in STATUS");
|
|
||||||
|
|
||||||
do {
|
|
||||||
String attr = r.readAtom();
|
|
||||||
if (attr.equalsIgnoreCase("MESSAGES"))
|
|
||||||
total = r.readNumber();
|
|
||||||
else if (attr.equalsIgnoreCase("RECENT"))
|
|
||||||
recent = r.readNumber();
|
|
||||||
else if (attr.equalsIgnoreCase("UIDNEXT"))
|
|
||||||
uidnext = r.readLong();
|
|
||||||
else if (attr.equalsIgnoreCase("UIDVALIDITY"))
|
|
||||||
uidvalidity = r.readLong();
|
|
||||||
else if (attr.equalsIgnoreCase("UNSEEN"))
|
|
||||||
unseen = r.readNumber();
|
|
||||||
} while (r.readByte() != ')');
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void add(Status s1, Status s2) {
|
|
||||||
if (s2.total != -1)
|
|
||||||
s1.total = s2.total;
|
|
||||||
if (s2.recent != -1)
|
|
||||||
s1.recent = s2.recent;
|
|
||||||
if (s2.uidnext != -1)
|
|
||||||
s1.uidnext = s2.uidnext;
|
|
||||||
if (s2.uidvalidity != -1)
|
|
||||||
s1.uidvalidity = s2.uidvalidity;
|
|
||||||
if (s2.unseen != -1)
|
|
||||||
s1.unseen = s2.unseen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap.protocol;
|
|
||||||
|
|
||||||
import com.sun.mail.iap.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class represents the UID data item
|
|
||||||
*
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class UID implements Item {
|
|
||||||
|
|
||||||
static final char[] name = {'U','I','D'};
|
|
||||||
public int seqnum;
|
|
||||||
|
|
||||||
public long uid;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
public UID(FetchResponse r) throws ParsingException {
|
|
||||||
seqnum = r.getNumber();
|
|
||||||
r.skipSpaces();
|
|
||||||
uid = r.readLong();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,138 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.imap.protocol;
|
|
||||||
|
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class holds the 'start' and 'end' for a range of UIDs.
|
|
||||||
* Just like MessageSet except using long instead of int.
|
|
||||||
*/
|
|
||||||
public class UIDSet {
|
|
||||||
|
|
||||||
public long start;
|
|
||||||
public long end;
|
|
||||||
|
|
||||||
public UIDSet() { }
|
|
||||||
|
|
||||||
public UIDSet(long start, long end) {
|
|
||||||
this.start = start;
|
|
||||||
this.end = end;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Count the total number of elements in a UIDSet
|
|
||||||
**/
|
|
||||||
public long size() {
|
|
||||||
return end - start + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert an array of longs into an array of UIDSets
|
|
||||||
*/
|
|
||||||
public static UIDSet[] createUIDSets(long[] msgs) {
|
|
||||||
Vector v = new Vector();
|
|
||||||
int i,j;
|
|
||||||
|
|
||||||
for (i=0; i < msgs.length; i++) {
|
|
||||||
UIDSet ms = new UIDSet();
|
|
||||||
ms.start = msgs[i];
|
|
||||||
|
|
||||||
// Look for contiguous elements
|
|
||||||
for (j=i+1; j < msgs.length; j++) {
|
|
||||||
if (msgs[j] != msgs[j-1] +1)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ms.end = msgs[j-1];
|
|
||||||
v.addElement(ms);
|
|
||||||
i = j-1; // i gets incremented @ top of the loop
|
|
||||||
}
|
|
||||||
UIDSet[] msgsets = new UIDSet[v.size()];
|
|
||||||
v.copyInto(msgsets);
|
|
||||||
return msgsets;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert an array of UIDSets into an IMAP sequence range
|
|
||||||
*/
|
|
||||||
public static String toString(UIDSet[] msgsets) {
|
|
||||||
if (msgsets == null || msgsets.length == 0) // Empty msgset
|
|
||||||
return null;
|
|
||||||
|
|
||||||
int i = 0; // msgset index
|
|
||||||
StringBuffer s = new StringBuffer();
|
|
||||||
int size = msgsets.length;
|
|
||||||
long start, end;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
start = msgsets[i].start;
|
|
||||||
end = msgsets[i].end;
|
|
||||||
|
|
||||||
if (end > start)
|
|
||||||
s.append(start).append(':').append(end);
|
|
||||||
else // end == start means only one element
|
|
||||||
s.append(start);
|
|
||||||
|
|
||||||
i++; // Next UIDSet
|
|
||||||
if (i >= size) // No more UIDSets
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
s.append(',');
|
|
||||||
}
|
|
||||||
return s.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Count the total number of elements in an array of UIDSets
|
|
||||||
*/
|
|
||||||
public static long size(UIDSet[] msgsets) {
|
|
||||||
long count = 0;
|
|
||||||
|
|
||||||
if (msgsets == null) // Null msgset
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (int i=0; i < msgsets.length; i++)
|
|
||||||
count += msgsets[i].size();
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,145 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.pop3;
|
|
||||||
|
|
||||||
import javax.mail.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The POP3 DefaultFolder. Only contains the "INBOX" folder.
|
|
||||||
*
|
|
||||||
* @author Christopher Cotton
|
|
||||||
*/
|
|
||||||
public class DefaultFolder extends Folder {
|
|
||||||
|
|
||||||
DefaultFolder(POP3Store store) {
|
|
||||||
super(store);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFullName() {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public Folder getParent() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean exists() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Folder[] list(String pattern) throws MessagingException {
|
|
||||||
Folder[] f = { getInbox() };
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
public char getSeparator() {
|
|
||||||
return '/';
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getType() {
|
|
||||||
return HOLDS_FOLDERS;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean create(int type) throws MessagingException {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasNewMessages() throws MessagingException {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Folder getFolder(String name) throws MessagingException {
|
|
||||||
if (!name.equalsIgnoreCase("INBOX")) {
|
|
||||||
throw new MessagingException("only INBOX supported");
|
|
||||||
} else {
|
|
||||||
return getInbox();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Folder getInbox() throws MessagingException {
|
|
||||||
return getStore().getFolder("INBOX");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public boolean delete(boolean recurse) throws MessagingException {
|
|
||||||
throw new MethodNotSupportedException("delete");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean renameTo(Folder f) throws MessagingException {
|
|
||||||
throw new MethodNotSupportedException("renameTo");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void open(int mode) throws MessagingException {
|
|
||||||
throw new MethodNotSupportedException("open");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close(boolean expunge) throws MessagingException {
|
|
||||||
throw new MethodNotSupportedException("close");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isOpen() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Flags getPermanentFlags() {
|
|
||||||
return new Flags(); // empty flags object
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMessageCount() throws MessagingException {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Message getMessage(int msgno) throws MessagingException {
|
|
||||||
throw new MethodNotSupportedException("getMessage");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void appendMessages(Message[] msgs) throws MessagingException {
|
|
||||||
throw new MethodNotSupportedException("Append not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Message[] expunge() throws MessagingException {
|
|
||||||
throw new MethodNotSupportedException("expunge");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,599 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.pop3;
|
|
||||||
|
|
||||||
import javax.mail.*;
|
|
||||||
import javax.mail.internet.*;
|
|
||||||
import javax.mail.event.*;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.EOFException;
|
|
||||||
import java.util.Vector;
|
|
||||||
import java.util.StringTokenizer;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
|
|
||||||
import com.sun.mail.util.LineInputStream;
|
|
||||||
import com.sun.mail.util.MailLogger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A POP3 Folder (can only be "INBOX").
|
|
||||||
*
|
|
||||||
* See the <a href="package-summary.html">com.sun.mail.pop3</a> package
|
|
||||||
* documentation for further information on the POP3 protocol provider. <p>
|
|
||||||
*
|
|
||||||
* @author Bill Shannon
|
|
||||||
* @author John Mani (ported to the javax.mail APIs)
|
|
||||||
*/
|
|
||||||
public class POP3Folder extends Folder {
|
|
||||||
|
|
||||||
private String name;
|
|
||||||
private POP3Store store;
|
|
||||||
private volatile Protocol port;
|
|
||||||
private int total;
|
|
||||||
private int size;
|
|
||||||
private boolean exists = false;
|
|
||||||
private volatile boolean opened = false;
|
|
||||||
private Vector message_cache;
|
|
||||||
private boolean doneUidl = false;
|
|
||||||
private volatile TempFile fileCache = null;
|
|
||||||
|
|
||||||
MailLogger logger; // package private, for POP3Message
|
|
||||||
|
|
||||||
POP3Folder(POP3Store store, String name) {
|
|
||||||
super(store);
|
|
||||||
this.name = name;
|
|
||||||
this.store = store;
|
|
||||||
if (name.equalsIgnoreCase("INBOX"))
|
|
||||||
exists = true;
|
|
||||||
logger = new MailLogger(this.getClass(),
|
|
||||||
"DEBUG POP3", store.getSession());
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFullName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Folder getParent() {
|
|
||||||
return new DefaultFolder(store);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Always true for the folder "INBOX", always false for
|
|
||||||
* any other name.
|
|
||||||
*
|
|
||||||
* @return true for INBOX, false otherwise
|
|
||||||
*/
|
|
||||||
public boolean exists() {
|
|
||||||
return exists;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Always throws <code>MessagingException</code> because no POP3 folders
|
|
||||||
* can contain subfolders.
|
|
||||||
*
|
|
||||||
* @exception MessagingException always
|
|
||||||
*/
|
|
||||||
public Folder[] list(String pattern) throws MessagingException {
|
|
||||||
throw new MessagingException("not a directory");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Always returns a NUL character because POP3 doesn't support a hierarchy.
|
|
||||||
*
|
|
||||||
* @return NUL
|
|
||||||
*/
|
|
||||||
public char getSeparator() {
|
|
||||||
return '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Always returns Folder.HOLDS_MESSAGES.
|
|
||||||
*
|
|
||||||
* @return Folder.HOLDS_MESSAGES
|
|
||||||
*/
|
|
||||||
public int getType() {
|
|
||||||
return HOLDS_MESSAGES;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Always returns <code>false</code>; the POP3 protocol doesn't
|
|
||||||
* support creating folders.
|
|
||||||
*
|
|
||||||
* @return false
|
|
||||||
*/
|
|
||||||
public boolean create(int type) throws MessagingException {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Always returns <code>false</code>; the POP3 protocol provides
|
|
||||||
* no way to determine when a new message arrives.
|
|
||||||
*
|
|
||||||
* @return false
|
|
||||||
*/
|
|
||||||
public boolean hasNewMessages() throws MessagingException {
|
|
||||||
return false; // no way to know
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Always throws <code>MessagingException</code> because no POP3 folders
|
|
||||||
* can contain subfolders.
|
|
||||||
*
|
|
||||||
* @exception MessagingException always
|
|
||||||
*/
|
|
||||||
public Folder getFolder(String name) throws MessagingException {
|
|
||||||
throw new MessagingException("not a directory");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Always throws <code>MethodNotSupportedException</code>
|
|
||||||
* because the POP3 protocol doesn't allow the INBOX to
|
|
||||||
* be deleted.
|
|
||||||
*
|
|
||||||
* @exception MethodNotSupportedException always
|
|
||||||
*/
|
|
||||||
public boolean delete(boolean recurse) throws MessagingException {
|
|
||||||
throw new MethodNotSupportedException("delete");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Always throws <code>MethodNotSupportedException</code>
|
|
||||||
* because the POP3 protocol doesn't support multiple folders.
|
|
||||||
*
|
|
||||||
* @exception MethodNotSupportedException always
|
|
||||||
*/
|
|
||||||
public boolean renameTo(Folder f) throws MessagingException {
|
|
||||||
throw new MethodNotSupportedException("renameTo");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Throws <code>FolderNotFoundException</code> unless this
|
|
||||||
* folder is named "INBOX".
|
|
||||||
*
|
|
||||||
* @exception FolderNotFoundException if not INBOX
|
|
||||||
* @exception AuthenticationException authentication failures
|
|
||||||
* @exception MessagingException other open failures
|
|
||||||
*/
|
|
||||||
public synchronized void open(int mode) throws MessagingException {
|
|
||||||
checkClosed();
|
|
||||||
if (!exists)
|
|
||||||
throw new FolderNotFoundException(this, "folder is not INBOX");
|
|
||||||
|
|
||||||
try {
|
|
||||||
port = store.getPort(this);
|
|
||||||
Status s = port.stat();
|
|
||||||
total = s.total;
|
|
||||||
size = s.size;
|
|
||||||
this.mode = mode;
|
|
||||||
if (store.useFileCache) {
|
|
||||||
try {
|
|
||||||
fileCache = new TempFile(store.fileCacheDir);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
logger.log(Level.FINE, "failed to create file cache", ex);
|
|
||||||
throw ex; // caught below
|
|
||||||
}
|
|
||||||
}
|
|
||||||
opened = true;
|
|
||||||
} catch (IOException ioex) {
|
|
||||||
try {
|
|
||||||
if (port != null)
|
|
||||||
port.quit();
|
|
||||||
} catch (IOException ioex2) {
|
|
||||||
// ignore
|
|
||||||
} finally {
|
|
||||||
port = null;
|
|
||||||
store.closePort(this);
|
|
||||||
}
|
|
||||||
throw new MessagingException("Open failed", ioex);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the message cache vector of appropriate size
|
|
||||||
message_cache = new Vector(total);
|
|
||||||
message_cache.setSize(total);
|
|
||||||
doneUidl = false;
|
|
||||||
|
|
||||||
notifyConnectionListeners(ConnectionEvent.OPENED);
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void close(boolean expunge) throws MessagingException {
|
|
||||||
checkOpen();
|
|
||||||
|
|
||||||
try {
|
|
||||||
/*
|
|
||||||
* Some POP3 servers will mark messages for deletion when
|
|
||||||
* they're read. To prevent such messages from being
|
|
||||||
* deleted before the client deletes them, you can set
|
|
||||||
* the mail.pop3.rsetbeforequit property to true. This
|
|
||||||
* causes us to issue a POP3 RSET command to clear all
|
|
||||||
* the "marked for deletion" flags. We can then explicitly
|
|
||||||
* delete messages as desired.
|
|
||||||
*/
|
|
||||||
if (store.rsetBeforeQuit)
|
|
||||||
port.rset();
|
|
||||||
POP3Message m;
|
|
||||||
if (expunge && mode == READ_WRITE) {
|
|
||||||
// find all messages marked deleted and issue DELE commands
|
|
||||||
for (int i = 0; i < message_cache.size(); i++) {
|
|
||||||
if ((m = (POP3Message)message_cache.elementAt(i)) != null) {
|
|
||||||
if (m.isSet(Flags.Flag.DELETED))
|
|
||||||
try {
|
|
||||||
port.dele(i + 1);
|
|
||||||
} catch (IOException ioex) {
|
|
||||||
throw new MessagingException(
|
|
||||||
"Exception deleting messages during close",
|
|
||||||
ioex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Flush and free all cached data for the messages.
|
|
||||||
*/
|
|
||||||
for (int i = 0; i < message_cache.size(); i++) {
|
|
||||||
if ((m = (POP3Message)message_cache.elementAt(i)) != null)
|
|
||||||
m.invalidate(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
port.quit();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
// do nothing
|
|
||||||
} finally {
|
|
||||||
port = null;
|
|
||||||
store.closePort(this);
|
|
||||||
message_cache = null;
|
|
||||||
opened = false;
|
|
||||||
notifyConnectionListeners(ConnectionEvent.CLOSED);
|
|
||||||
if (fileCache != null) {
|
|
||||||
fileCache.close();
|
|
||||||
fileCache = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized boolean isOpen() {
|
|
||||||
if (!opened)
|
|
||||||
return false;
|
|
||||||
try {
|
|
||||||
if (!port.noop())
|
|
||||||
throw new IOException("NOOP failed");
|
|
||||||
} catch (IOException ioex) {
|
|
||||||
try {
|
|
||||||
close(false);
|
|
||||||
} catch (MessagingException mex) {
|
|
||||||
// ignore it
|
|
||||||
} finally {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Always returns an empty <code>Flags</code> object because
|
|
||||||
* the POP3 protocol doesn't support any permanent flags.
|
|
||||||
*
|
|
||||||
* @return empty Flags object
|
|
||||||
*/
|
|
||||||
public Flags getPermanentFlags() {
|
|
||||||
return new Flags(); // empty flags object
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Will not change while the folder is open because the POP3
|
|
||||||
* protocol doesn't support notification of new messages
|
|
||||||
* arriving in open folders.
|
|
||||||
*/
|
|
||||||
public synchronized int getMessageCount() throws MessagingException {
|
|
||||||
if (!opened)
|
|
||||||
return -1;
|
|
||||||
checkReadable();
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized Message getMessage(int msgno)
|
|
||||||
throws MessagingException {
|
|
||||||
checkOpen();
|
|
||||||
|
|
||||||
POP3Message m;
|
|
||||||
|
|
||||||
// Assuming that msgno is <= total
|
|
||||||
if ((m = (POP3Message)message_cache.elementAt(msgno-1)) == null) {
|
|
||||||
m = createMessage(this, msgno);
|
|
||||||
message_cache.setElementAt(m, msgno-1);
|
|
||||||
}
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected POP3Message createMessage(Folder f, int msgno)
|
|
||||||
throws MessagingException {
|
|
||||||
POP3Message m = null;
|
|
||||||
Constructor cons = store.messageConstructor;
|
|
||||||
if (cons != null) {
|
|
||||||
try {
|
|
||||||
Object[] o = { this, new Integer(msgno) };
|
|
||||||
m = (POP3Message)cons.newInstance(o);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (m == null)
|
|
||||||
m = new POP3Message(this, msgno);
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Always throws <code>MethodNotSupportedException</code>
|
|
||||||
* because the POP3 protocol doesn't support appending messages.
|
|
||||||
*
|
|
||||||
* @exception MethodNotSupportedException always
|
|
||||||
*/
|
|
||||||
public void appendMessages(Message[] msgs) throws MessagingException {
|
|
||||||
throw new MethodNotSupportedException("Append not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Always throws <code>MethodNotSupportedException</code>
|
|
||||||
* because the POP3 protocol doesn't support expunging messages
|
|
||||||
* without closing the folder; call the {@link #close close} method
|
|
||||||
* with the <code>expunge</code> argument set to <code>true</code>
|
|
||||||
* instead.
|
|
||||||
*
|
|
||||||
* @exception MethodNotSupportedException always
|
|
||||||
*/
|
|
||||||
public Message[] expunge() throws MessagingException {
|
|
||||||
throw new MethodNotSupportedException("Expunge not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prefetch information about POP3 messages.
|
|
||||||
* If the FetchProfile contains <code>UIDFolder.FetchProfileItem.UID</code>,
|
|
||||||
* POP3 UIDs for all messages in the folder are fetched using the POP3
|
|
||||||
* UIDL command.
|
|
||||||
* If the FetchProfile contains <code>FetchProfile.Item.ENVELOPE</code>,
|
|
||||||
* the headers and size of all messages are fetched using the POP3 TOP
|
|
||||||
* and LIST commands.
|
|
||||||
*/
|
|
||||||
public synchronized void fetch(Message[] msgs, FetchProfile fp)
|
|
||||||
throws MessagingException {
|
|
||||||
checkReadable();
|
|
||||||
if (!doneUidl && store.supportsUidl &&
|
|
||||||
fp.contains(UIDFolder.FetchProfileItem.UID)) {
|
|
||||||
/*
|
|
||||||
* Since the POP3 protocol only lets us fetch the UID
|
|
||||||
* for a single message or for all messages, we go ahead
|
|
||||||
* and fetch UIDs for all messages here, ignoring the msgs
|
|
||||||
* parameter. We could be more intelligent and base this
|
|
||||||
* decision on the number of messages fetched, or the
|
|
||||||
* percentage of the total number of messages fetched.
|
|
||||||
*/
|
|
||||||
String[] uids = new String[message_cache.size()];
|
|
||||||
try {
|
|
||||||
if (!port.uidl(uids))
|
|
||||||
return;
|
|
||||||
} catch (EOFException eex) {
|
|
||||||
close(false);
|
|
||||||
throw new FolderClosedException(this, eex.toString());
|
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new MessagingException("error getting UIDL", ex);
|
|
||||||
}
|
|
||||||
for (int i = 0; i < uids.length; i++) {
|
|
||||||
if (uids[i] == null)
|
|
||||||
continue;
|
|
||||||
POP3Message m = (POP3Message)getMessage(i + 1);
|
|
||||||
m.uid = uids[i];
|
|
||||||
}
|
|
||||||
doneUidl = true; // only do this once
|
|
||||||
}
|
|
||||||
if (fp.contains(FetchProfile.Item.ENVELOPE)) {
|
|
||||||
for (int i = 0; i < msgs.length; i++) {
|
|
||||||
try {
|
|
||||||
POP3Message msg = (POP3Message)msgs[i];
|
|
||||||
// fetch headers
|
|
||||||
msg.getHeader("");
|
|
||||||
// fetch message size
|
|
||||||
msg.getSize();
|
|
||||||
} catch (MessageRemovedException mex) {
|
|
||||||
// should never happen, but ignore it if it does
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the unique ID string for this message, or null if
|
|
||||||
* not available. Uses the POP3 UIDL command.
|
|
||||||
*
|
|
||||||
* @return unique ID string
|
|
||||||
* @exception MessagingException
|
|
||||||
*/
|
|
||||||
public synchronized String getUID(Message msg) throws MessagingException {
|
|
||||||
checkOpen();
|
|
||||||
POP3Message m = (POP3Message)msg;
|
|
||||||
try {
|
|
||||||
if (!store.supportsUidl)
|
|
||||||
return null;
|
|
||||||
if (m.uid == POP3Message.UNKNOWN)
|
|
||||||
m.uid = port.uidl(m.getMessageNumber());
|
|
||||||
return m.uid;
|
|
||||||
} catch (EOFException eex) {
|
|
||||||
close(false);
|
|
||||||
throw new FolderClosedException(this, eex.toString());
|
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new MessagingException("error getting UIDL", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the size of this folder, as was returned by the POP3 STAT
|
|
||||||
* command when this folder was opened.
|
|
||||||
*
|
|
||||||
* @return folder size
|
|
||||||
* @exception IllegalStateException if the folder isn't open
|
|
||||||
*/
|
|
||||||
public synchronized int getSize() throws MessagingException {
|
|
||||||
checkOpen();
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the sizes of all messages in this folder, as returned
|
|
||||||
* by the POP3 LIST command. Each entry in the array corresponds
|
|
||||||
* to a message; entry <i>i</i> corresponds to message number <i>i+1</i>.
|
|
||||||
*
|
|
||||||
* @return array of message sizes
|
|
||||||
* @exception IllegalStateException if the folder isn't open
|
|
||||||
* @since JavaMail 1.3.3
|
|
||||||
*/
|
|
||||||
public synchronized int[] getSizes() throws MessagingException {
|
|
||||||
checkOpen();
|
|
||||||
int sizes[] = new int[total];
|
|
||||||
InputStream is = null;
|
|
||||||
LineInputStream lis = null;
|
|
||||||
try {
|
|
||||||
is = port.list();
|
|
||||||
lis = new LineInputStream(is);
|
|
||||||
String line;
|
|
||||||
while ((line = lis.readLine()) != null) {
|
|
||||||
try {
|
|
||||||
StringTokenizer st = new StringTokenizer(line);
|
|
||||||
int msgnum = Integer.parseInt(st.nextToken());
|
|
||||||
int size = Integer.parseInt(st.nextToken());
|
|
||||||
if (msgnum > 0 && msgnum <= total)
|
|
||||||
sizes[msgnum - 1] = size;
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException ex) {
|
|
||||||
// ignore it?
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
if (lis != null)
|
|
||||||
lis.close();
|
|
||||||
} catch (IOException cex) { }
|
|
||||||
try {
|
|
||||||
if (is != null)
|
|
||||||
is.close();
|
|
||||||
} catch (IOException cex) { }
|
|
||||||
}
|
|
||||||
return sizes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the raw results of the POP3 LIST command with no arguments.
|
|
||||||
*
|
|
||||||
* @return InputStream containing results
|
|
||||||
* @exception IllegalStateException if the folder isn't open
|
|
||||||
* @since JavaMail 1.3.3
|
|
||||||
*/
|
|
||||||
public synchronized InputStream listCommand()
|
|
||||||
throws MessagingException, IOException {
|
|
||||||
checkOpen();
|
|
||||||
return port.list();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close the folder when we're finalized.
|
|
||||||
*/
|
|
||||||
protected void finalize() throws Throwable {
|
|
||||||
super.finalize();
|
|
||||||
close(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ensure the folder is open */
|
|
||||||
private void checkOpen() throws IllegalStateException {
|
|
||||||
if (!opened)
|
|
||||||
throw new IllegalStateException("Folder is not Open");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ensure the folder is not open */
|
|
||||||
private void checkClosed() throws IllegalStateException {
|
|
||||||
if (opened)
|
|
||||||
throw new IllegalStateException("Folder is Open");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ensure the folder is open & readable */
|
|
||||||
private void checkReadable() throws IllegalStateException {
|
|
||||||
if (!opened || (mode != READ_ONLY && mode != READ_WRITE))
|
|
||||||
throw new IllegalStateException("Folder is not Readable");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ensure the folder is open & writable */
|
|
||||||
/*
|
|
||||||
private void checkWritable() throws IllegalStateException {
|
|
||||||
if (!opened || mode != READ_WRITE)
|
|
||||||
throw new IllegalStateException("Folder is not Writable");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Centralize access to the Protocol object by POP3Message
|
|
||||||
* objects so that they will fail appropriately when the folder
|
|
||||||
* is closed.
|
|
||||||
*/
|
|
||||||
Protocol getProtocol() throws MessagingException {
|
|
||||||
Protocol p = port; // read it before close() can set it to null
|
|
||||||
checkOpen();
|
|
||||||
// close() might happen here
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Only here to make accessible to POP3Message.
|
|
||||||
*/
|
|
||||||
protected void notifyMessageChangedListeners(int type, Message m) {
|
|
||||||
super.notifyMessageChangedListeners(type, m);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used by POP3Message.
|
|
||||||
*/
|
|
||||||
TempFile getFileCache() {
|
|
||||||
return fileCache;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,648 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.pop3;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.lang.ref.SoftReference;
|
|
||||||
import javax.mail.*;
|
|
||||||
import javax.mail.internet.*;
|
|
||||||
import javax.mail.event.*;
|
|
||||||
import com.sun.mail.util.ReadableMime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A POP3 Message. Just like a MimeMessage except that
|
|
||||||
* some things are not supported.
|
|
||||||
*
|
|
||||||
* @author Bill Shannon
|
|
||||||
*/
|
|
||||||
public class POP3Message extends MimeMessage implements ReadableMime {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Our locking strategy is to always lock the POP3Folder before the
|
|
||||||
* POP3Message so we have to be careful to drop our lock before calling
|
|
||||||
* back to the folder to close it and notify of connection lost events.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// flag to indicate we haven't tried to fetch the UID yet
|
|
||||||
static final String UNKNOWN = "UNKNOWN";
|
|
||||||
|
|
||||||
private POP3Folder folder; // overrides folder in MimeMessage
|
|
||||||
private int hdrSize = -1;
|
|
||||||
private int msgSize = -1;
|
|
||||||
String uid = UNKNOWN; // controlled by folder lock
|
|
||||||
|
|
||||||
// rawData itself is never null
|
|
||||||
private SoftReference rawData = new SoftReference(null);
|
|
||||||
|
|
||||||
public POP3Message(Folder folder, int msgno)
|
|
||||||
throws MessagingException {
|
|
||||||
super(folder, msgno);
|
|
||||||
this.folder = (POP3Folder)folder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the specified flags on this message to the specified value.
|
|
||||||
*
|
|
||||||
* @param newFlags the flags to be set
|
|
||||||
* @param set the value to be set
|
|
||||||
*/
|
|
||||||
public synchronized void setFlags(Flags newFlags, boolean set)
|
|
||||||
throws MessagingException {
|
|
||||||
Flags oldFlags = (Flags)flags.clone();
|
|
||||||
super.setFlags(newFlags, set);
|
|
||||||
if (!flags.equals(oldFlags))
|
|
||||||
folder.notifyMessageChangedListeners(
|
|
||||||
MessageChangedEvent.FLAGS_CHANGED, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the size of the content of this message in bytes.
|
|
||||||
* Returns -1 if the size cannot be determined. <p>
|
|
||||||
*
|
|
||||||
* Note that this number may not be an exact measure of the
|
|
||||||
* content size and may or may not account for any transfer
|
|
||||||
* encoding of the content. <p>
|
|
||||||
*
|
|
||||||
* @return size of content in bytes
|
|
||||||
* @exception MessagingException
|
|
||||||
*/
|
|
||||||
public int getSize() throws MessagingException {
|
|
||||||
try {
|
|
||||||
synchronized (this) {
|
|
||||||
// if we already have the size, return it
|
|
||||||
if (msgSize > 0)
|
|
||||||
return msgSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Use LIST to determine the entire message
|
|
||||||
* size and subtract out the header size
|
|
||||||
* (which may involve loading the headers,
|
|
||||||
* which may load the content as a side effect).
|
|
||||||
* If the content is loaded as a side effect of
|
|
||||||
* loading the headers, it will set the size.
|
|
||||||
*
|
|
||||||
* Make sure to call loadHeaders() outside of the
|
|
||||||
* synchronization block. There's a potential race
|
|
||||||
* condition here but synchronization will occur in
|
|
||||||
* loadHeaders() to make sure the headers are only
|
|
||||||
* loaded once, and again in the following block to
|
|
||||||
* only compute msgSize once.
|
|
||||||
*/
|
|
||||||
if (headers == null)
|
|
||||||
loadHeaders();
|
|
||||||
|
|
||||||
synchronized (this) {
|
|
||||||
if (msgSize < 0)
|
|
||||||
msgSize = folder.getProtocol().list(msgnum) - hdrSize;
|
|
||||||
return msgSize;
|
|
||||||
}
|
|
||||||
} catch (EOFException eex) {
|
|
||||||
folder.close(false);
|
|
||||||
throw new FolderClosedException(folder, eex.toString());
|
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new MessagingException("error getting size", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Produce the raw bytes of the message. The data is fetched using
|
|
||||||
* the POP3 RETR command. If skipHeader is true, just the content
|
|
||||||
* is returned.
|
|
||||||
*/
|
|
||||||
private InputStream getRawStream(boolean skipHeader)
|
|
||||||
throws MessagingException {
|
|
||||||
InputStream rawcontent = null;
|
|
||||||
try {
|
|
||||||
synchronized(this) {
|
|
||||||
rawcontent = (InputStream)rawData.get();
|
|
||||||
if (rawcontent == null) {
|
|
||||||
TempFile cache = folder.getFileCache();
|
|
||||||
if (cache != null) {
|
|
||||||
Session s = ((POP3Store)(folder.getStore())).getSession();
|
|
||||||
if (folder.logger.isLoggable(Level.FINE))
|
|
||||||
folder.logger.fine("caching message #" + msgnum +
|
|
||||||
" in temp file");
|
|
||||||
AppendStream os = cache.getAppendStream();
|
|
||||||
BufferedOutputStream bos = new BufferedOutputStream(os);
|
|
||||||
try {
|
|
||||||
folder.getProtocol().retr(msgnum, bos);
|
|
||||||
} finally {
|
|
||||||
bos.close();
|
|
||||||
}
|
|
||||||
rawcontent = os.getInputStream();
|
|
||||||
} else {
|
|
||||||
rawcontent = folder.getProtocol().retr(msgnum,
|
|
||||||
msgSize > 0 ? msgSize + hdrSize : 0);
|
|
||||||
}
|
|
||||||
if (rawcontent == null) {
|
|
||||||
expunged = true;
|
|
||||||
throw new MessageRemovedException(
|
|
||||||
"can't retrieve message #" + msgnum +
|
|
||||||
" in POP3Message.getContentStream"); // XXX - what else?
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headers == null ||
|
|
||||||
((POP3Store)(folder.getStore())).forgetTopHeaders) {
|
|
||||||
headers = new InternetHeaders(rawcontent);
|
|
||||||
hdrSize =
|
|
||||||
(int)((SharedInputStream)rawcontent).getPosition();
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* Already have the headers, have to skip the headers
|
|
||||||
* in the content array and return the body.
|
|
||||||
*
|
|
||||||
* XXX - It seems that some mail servers return slightly
|
|
||||||
* different headers in the RETR results than were returned
|
|
||||||
* in the TOP results, so we can't depend on remembering
|
|
||||||
* the size of the headers from the TOP command and just
|
|
||||||
* skipping that many bytes. Instead, we have to process
|
|
||||||
* the content, skipping over the header until we come to
|
|
||||||
* the empty line that separates the header from the body.
|
|
||||||
*/
|
|
||||||
int offset = 0;
|
|
||||||
for (;;) {
|
|
||||||
int len = 0; // number of bytes in this line
|
|
||||||
int c1;
|
|
||||||
while ((c1 = rawcontent.read()) >= 0) {
|
|
||||||
if (c1 == '\n') // end of line
|
|
||||||
break;
|
|
||||||
else if (c1 == '\r') {
|
|
||||||
// got CR, is the next char LF?
|
|
||||||
if (rawcontent.available() > 0) {
|
|
||||||
rawcontent.mark(1);
|
|
||||||
if (rawcontent.read() != '\n')
|
|
||||||
rawcontent.reset();
|
|
||||||
}
|
|
||||||
break; // in any case, end of line
|
|
||||||
}
|
|
||||||
|
|
||||||
// not CR, NL, or CRLF, count the byte
|
|
||||||
len++;
|
|
||||||
}
|
|
||||||
// here when end of line or out of data
|
|
||||||
|
|
||||||
// if out of data, we're done
|
|
||||||
if (rawcontent.available() == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// if it was an empty line, we're done
|
|
||||||
if (len == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
hdrSize =
|
|
||||||
(int)((SharedInputStream)rawcontent).getPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
// skipped the header, the message is what's left
|
|
||||||
msgSize = rawcontent.available();
|
|
||||||
|
|
||||||
rawData = new SoftReference(rawcontent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (EOFException eex) {
|
|
||||||
folder.close(false);
|
|
||||||
throw new FolderClosedException(folder, eex.toString());
|
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new MessagingException("error fetching POP3 content", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We have a cached stream, but we need to return
|
|
||||||
* a fresh stream to read from the beginning and
|
|
||||||
* that can be safely closed.
|
|
||||||
*/
|
|
||||||
rawcontent = ((SharedInputStream)rawcontent).newStream(
|
|
||||||
skipHeader ? hdrSize : 0, -1);
|
|
||||||
return rawcontent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Produce the raw bytes of the content. The data is fetched using
|
|
||||||
* the POP3 RETR command.
|
|
||||||
*
|
|
||||||
* @see #contentStream
|
|
||||||
*/
|
|
||||||
protected synchronized InputStream getContentStream()
|
|
||||||
throws MessagingException {
|
|
||||||
if (contentStream != null)
|
|
||||||
return ((SharedInputStream)contentStream).newStream(0, -1);
|
|
||||||
|
|
||||||
InputStream cstream = getRawStream(true);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Keep a hard reference to the data if we're using a file
|
|
||||||
* cache or if the "mail.pop3.keepmessagecontent" prop is set.
|
|
||||||
*/
|
|
||||||
TempFile cache = folder.getFileCache();
|
|
||||||
if (cache != null ||
|
|
||||||
((POP3Store)(folder.getStore())).keepMessageContent)
|
|
||||||
contentStream = ((SharedInputStream)cstream).newStream(0, -1);
|
|
||||||
return cstream;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the MIME format stream corresponding to this message part.
|
|
||||||
*
|
|
||||||
* @return the MIME format stream
|
|
||||||
* @since JavaMail 1.4.5
|
|
||||||
*/
|
|
||||||
public InputStream getMimeStream() throws MessagingException {
|
|
||||||
return getRawStream(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invalidate the cache of content for this message object, causing
|
|
||||||
* it to be fetched again from the server the next time it is needed.
|
|
||||||
* If <code>invalidateHeaders</code> is true, invalidate the headers
|
|
||||||
* as well.
|
|
||||||
*
|
|
||||||
* @param invalidateHeaders invalidate the headers as well?
|
|
||||||
*/
|
|
||||||
public synchronized void invalidate(boolean invalidateHeaders) {
|
|
||||||
content = null;
|
|
||||||
InputStream rstream = (InputStream)rawData.get();
|
|
||||||
if (rstream != null) {
|
|
||||||
// note that if the content is in the file cache, it will be lost
|
|
||||||
// and fetched from the server if it's needed again
|
|
||||||
try {
|
|
||||||
rstream.close();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
// ignore it
|
|
||||||
}
|
|
||||||
rawData = new SoftReference(null);
|
|
||||||
}
|
|
||||||
if (contentStream != null) {
|
|
||||||
try {
|
|
||||||
contentStream.close();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
// ignore it
|
|
||||||
}
|
|
||||||
contentStream = null;
|
|
||||||
}
|
|
||||||
msgSize = -1;
|
|
||||||
if (invalidateHeaders) {
|
|
||||||
headers = null;
|
|
||||||
hdrSize = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the header of the message and the first <code>n</code> lines
|
|
||||||
* of the raw content of the message. The headers and data are
|
|
||||||
* available in the returned InputStream.
|
|
||||||
*
|
|
||||||
* @param n number of lines of content to fetch
|
|
||||||
* @return InputStream containing the message headers and n content lines
|
|
||||||
*/
|
|
||||||
public InputStream top(int n) throws MessagingException {
|
|
||||||
try {
|
|
||||||
synchronized (this) {
|
|
||||||
return folder.getProtocol().top(msgnum, n);
|
|
||||||
}
|
|
||||||
} catch (EOFException eex) {
|
|
||||||
folder.close(false);
|
|
||||||
throw new FolderClosedException(folder, eex.toString());
|
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new MessagingException("error getting size", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all the headers for this header_name. Note that certain
|
|
||||||
* headers may be encoded as per RFC 2047 if they contain
|
|
||||||
* non US-ASCII characters and these should be decoded. <p>
|
|
||||||
*
|
|
||||||
* @param name name of header
|
|
||||||
* @return array of headers
|
|
||||||
* @exception MessagingException
|
|
||||||
* @see javax.mail.internet.MimeUtility
|
|
||||||
*/
|
|
||||||
public String[] getHeader(String name)
|
|
||||||
throws MessagingException {
|
|
||||||
if (headers == null)
|
|
||||||
loadHeaders();
|
|
||||||
return headers.getHeader(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all the headers for this header name, returned as a single
|
|
||||||
* String, with headers separated by the delimiter. If the
|
|
||||||
* delimiter is <code>null</code>, only the first header is
|
|
||||||
* returned.
|
|
||||||
*
|
|
||||||
* @param name the name of this header
|
|
||||||
* @param delimiter delimiter between returned headers
|
|
||||||
* @return the value fields for all headers with
|
|
||||||
* this name
|
|
||||||
* @exception MessagingException
|
|
||||||
*/
|
|
||||||
public String getHeader(String name, String delimiter)
|
|
||||||
throws MessagingException {
|
|
||||||
if (headers == null)
|
|
||||||
loadHeaders();
|
|
||||||
return headers.getHeader(name, delimiter);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the value for this header_name. Throws IllegalWriteException
|
|
||||||
* because POP3 messages are read-only.
|
|
||||||
*
|
|
||||||
* @param name header name
|
|
||||||
* @param value header value
|
|
||||||
* @see javax.mail.internet.MimeUtility
|
|
||||||
* @exception IllegalWriteException because the underlying
|
|
||||||
* implementation does not support modification
|
|
||||||
* @exception IllegalStateException if this message is
|
|
||||||
* obtained from a READ_ONLY folder.
|
|
||||||
*/
|
|
||||||
public void setHeader(String name, String value)
|
|
||||||
throws MessagingException {
|
|
||||||
// XXX - should check for read-only folder?
|
|
||||||
throw new IllegalWriteException("POP3 messages are read-only");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add this value to the existing values for this header_name.
|
|
||||||
* Throws IllegalWriteException because POP3 messages are read-only.
|
|
||||||
*
|
|
||||||
* @param name header name
|
|
||||||
* @param value header value
|
|
||||||
* @see javax.mail.internet.MimeUtility
|
|
||||||
* @exception IllegalWriteException because the underlying
|
|
||||||
* implementation does not support modification
|
|
||||||
* @exception IllegalStateException if this message is
|
|
||||||
* obtained from a READ_ONLY folder.
|
|
||||||
*/
|
|
||||||
public void addHeader(String name, String value)
|
|
||||||
throws MessagingException {
|
|
||||||
// XXX - should check for read-only folder?
|
|
||||||
throw new IllegalWriteException("POP3 messages are read-only");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove all headers with this name.
|
|
||||||
* Throws IllegalWriteException because POP3 messages are read-only.
|
|
||||||
*
|
|
||||||
* @exception IllegalWriteException because the underlying
|
|
||||||
* implementation does not support modification
|
|
||||||
* @exception IllegalStateException if this message is
|
|
||||||
* obtained from a READ_ONLY folder.
|
|
||||||
*/
|
|
||||||
public void removeHeader(String name)
|
|
||||||
throws MessagingException {
|
|
||||||
// XXX - should check for read-only folder?
|
|
||||||
throw new IllegalWriteException("POP3 messages are read-only");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return all the headers from this Message as an enumeration
|
|
||||||
* of Header objects. <p>
|
|
||||||
*
|
|
||||||
* Note that certain headers may be encoded as per RFC 2047
|
|
||||||
* if they contain non US-ASCII characters and these should
|
|
||||||
* be decoded. <p>
|
|
||||||
*
|
|
||||||
* @return array of header objects
|
|
||||||
* @exception MessagingException
|
|
||||||
* @see javax.mail.internet.MimeUtility
|
|
||||||
*/
|
|
||||||
public Enumeration getAllHeaders() throws MessagingException {
|
|
||||||
if (headers == null)
|
|
||||||
loadHeaders();
|
|
||||||
return headers.getAllHeaders();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return matching headers from this Message as an Enumeration of
|
|
||||||
* Header objects.
|
|
||||||
*
|
|
||||||
* @exception MessagingException
|
|
||||||
*/
|
|
||||||
public Enumeration getMatchingHeaders(String[] names)
|
|
||||||
throws MessagingException {
|
|
||||||
if (headers == null)
|
|
||||||
loadHeaders();
|
|
||||||
return headers.getMatchingHeaders(names);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return non-matching headers from this Message as an
|
|
||||||
* Enumeration of Header objects.
|
|
||||||
*
|
|
||||||
* @exception MessagingException
|
|
||||||
*/
|
|
||||||
public Enumeration getNonMatchingHeaders(String[] names)
|
|
||||||
throws MessagingException {
|
|
||||||
if (headers == null)
|
|
||||||
loadHeaders();
|
|
||||||
return headers.getNonMatchingHeaders(names);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a raw RFC822 header-line.
|
|
||||||
* Throws IllegalWriteException because POP3 messages are read-only.
|
|
||||||
*
|
|
||||||
* @exception IllegalWriteException because the underlying
|
|
||||||
* implementation does not support modification
|
|
||||||
* @exception IllegalStateException if this message is
|
|
||||||
* obtained from a READ_ONLY folder.
|
|
||||||
*/
|
|
||||||
public void addHeaderLine(String line) throws MessagingException {
|
|
||||||
// XXX - should check for read-only folder?
|
|
||||||
throw new IllegalWriteException("POP3 messages are read-only");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all header lines as an Enumeration of Strings. A Header
|
|
||||||
* line is a raw RFC822 header-line, containing both the "name"
|
|
||||||
* and "value" field.
|
|
||||||
*
|
|
||||||
* @exception MessagingException
|
|
||||||
*/
|
|
||||||
public Enumeration getAllHeaderLines() throws MessagingException {
|
|
||||||
if (headers == null)
|
|
||||||
loadHeaders();
|
|
||||||
return headers.getAllHeaderLines();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get matching header lines as an Enumeration of Strings.
|
|
||||||
* A Header line is a raw RFC822 header-line, containing both
|
|
||||||
* the "name" and "value" field.
|
|
||||||
*
|
|
||||||
* @exception MessagingException
|
|
||||||
*/
|
|
||||||
public Enumeration getMatchingHeaderLines(String[] names)
|
|
||||||
throws MessagingException {
|
|
||||||
if (headers == null)
|
|
||||||
loadHeaders();
|
|
||||||
return headers.getMatchingHeaderLines(names);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get non-matching header lines as an Enumeration of Strings.
|
|
||||||
* A Header line is a raw RFC822 header-line, containing both
|
|
||||||
* the "name" and "value" field.
|
|
||||||
*
|
|
||||||
* @exception MessagingException
|
|
||||||
*/
|
|
||||||
public Enumeration getNonMatchingHeaderLines(String[] names)
|
|
||||||
throws MessagingException {
|
|
||||||
if (headers == null)
|
|
||||||
loadHeaders();
|
|
||||||
return headers.getNonMatchingHeaderLines(names);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* POP3 message can't be changed. This method throws
|
|
||||||
* IllegalWriteException.
|
|
||||||
*
|
|
||||||
* @exception IllegalWriteException because the underlying
|
|
||||||
* implementation does not support modification
|
|
||||||
*/
|
|
||||||
public void saveChanges() throws MessagingException {
|
|
||||||
// POP3 Messages are read-only
|
|
||||||
throw new IllegalWriteException("POP3 messages are read-only");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Output the message as an RFC 822 format stream, without
|
|
||||||
* specified headers. If the property "mail.pop3.cachewriteto"
|
|
||||||
* is set to "true", and ignoreList is null, and the message hasn't
|
|
||||||
* already been cached as a side effect of other operations, the message
|
|
||||||
* content is cached before being written. Otherwise, the message is
|
|
||||||
* streamed directly to the output stream without being cached.
|
|
||||||
*
|
|
||||||
* @exception javax.mail.MessagingException
|
|
||||||
* @exception IOException if an error occurs writing to the stream
|
|
||||||
* or if an error is generated by the
|
|
||||||
* javax.activation layer.
|
|
||||||
* @see javax.activation.DataHandler#writeTo
|
|
||||||
*/
|
|
||||||
public synchronized void writeTo(OutputStream os, String[] ignoreList)
|
|
||||||
throws IOException, MessagingException {
|
|
||||||
InputStream rawcontent = (InputStream)rawData.get();
|
|
||||||
if (rawcontent == null && ignoreList == null &&
|
|
||||||
!((POP3Store)(folder.getStore())).cacheWriteTo) {
|
|
||||||
Session s = ((POP3Store)(folder.getStore())).getSession();
|
|
||||||
if (folder.logger.isLoggable(Level.FINE))
|
|
||||||
folder.logger.fine("streaming msg " + msgnum);
|
|
||||||
if (!folder.getProtocol().retr(msgnum, os)) {
|
|
||||||
expunged = true;
|
|
||||||
throw new MessageRemovedException("can't retrieve message #" +
|
|
||||||
msgnum + " in POP3Message.writeTo"); // XXX - what else?
|
|
||||||
}
|
|
||||||
} else if (rawcontent != null && ignoreList == null) {
|
|
||||||
// can just copy the cached data
|
|
||||||
InputStream in = ((SharedInputStream)rawcontent).newStream(0, -1);
|
|
||||||
try {
|
|
||||||
byte[] buf = new byte[16*1024];
|
|
||||||
int len;
|
|
||||||
while ((len = in.read(buf)) > 0)
|
|
||||||
os.write(buf, 0, len);
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
if (in != null)
|
|
||||||
in.close();
|
|
||||||
} catch (IOException ex) { }
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
super.writeTo(os, ignoreList);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load the headers for this message into the InternetHeaders object.
|
|
||||||
* The headers are fetched using the POP3 TOP command.
|
|
||||||
*/
|
|
||||||
private void loadHeaders() throws MessagingException {
|
|
||||||
assert !Thread.holdsLock(this);
|
|
||||||
try {
|
|
||||||
boolean fetchContent = false;
|
|
||||||
synchronized (this) {
|
|
||||||
if (headers != null) // check again under lock
|
|
||||||
return;
|
|
||||||
InputStream hdrs = null;
|
|
||||||
if (((POP3Store)(folder.getStore())).disableTop ||
|
|
||||||
(hdrs = folder.getProtocol().top(msgnum, 0)) == null) {
|
|
||||||
// possibly because the TOP command isn't supported,
|
|
||||||
// load headers as a side effect of loading the entire
|
|
||||||
// content.
|
|
||||||
fetchContent = true;
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
hdrSize = hdrs.available();
|
|
||||||
headers = new InternetHeaders(hdrs);
|
|
||||||
} finally {
|
|
||||||
hdrs.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Outside the synchronization block...
|
|
||||||
*
|
|
||||||
* Do we need to fetch the entire mesage content in order to
|
|
||||||
* load the headers as a side effect? Yes, there's a race
|
|
||||||
* condition here - multiple threads could decide that the
|
|
||||||
* content needs to be fetched. Fortunately, they'll all
|
|
||||||
* synchronize in the getContentStream method and the content
|
|
||||||
* will only be loaded once.
|
|
||||||
*/
|
|
||||||
if (fetchContent) {
|
|
||||||
InputStream cs = null;
|
|
||||||
try {
|
|
||||||
cs = getContentStream();
|
|
||||||
} finally {
|
|
||||||
if (cs != null)
|
|
||||||
cs.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (EOFException eex) {
|
|
||||||
folder.close(false);
|
|
||||||
throw new FolderClosedException(folder, eex.toString());
|
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new MessagingException("error loading POP3 headers", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.pop3;
|
|
||||||
|
|
||||||
import javax.mail.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A POP3 Message Store using SSL. Contains only one folder, "INBOX".
|
|
||||||
*
|
|
||||||
* @author Bill Shannon
|
|
||||||
*/
|
|
||||||
public class POP3SSLStore extends POP3Store {
|
|
||||||
|
|
||||||
public POP3SSLStore(Session session, URLName url) {
|
|
||||||
super(session, url, "pop3s", true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,420 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2013 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.pop3;
|
|
||||||
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.lang.reflect.*;
|
|
||||||
|
|
||||||
import javax.mail.*;
|
|
||||||
import javax.mail.internet.*;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.PrintStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.EOFException;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.sun.mail.util.PropUtil;
|
|
||||||
import com.sun.mail.util.MailLogger;
|
|
||||||
import com.sun.mail.util.SocketConnectException;
|
|
||||||
import com.sun.mail.util.MailConnectException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A POP3 Message Store. Contains only one folder, "INBOX".
|
|
||||||
*
|
|
||||||
* See the <a href="package-summary.html">com.sun.mail.pop3</a> package
|
|
||||||
* documentation for further information on the POP3 protocol provider. <p>
|
|
||||||
*
|
|
||||||
* @author Bill Shannon
|
|
||||||
* @author John Mani
|
|
||||||
*/
|
|
||||||
public class POP3Store extends Store {
|
|
||||||
|
|
||||||
private String name = "pop3"; // my protocol name
|
|
||||||
private int defaultPort = 110; // default POP3 port
|
|
||||||
private boolean isSSL = false; // use SSL?
|
|
||||||
|
|
||||||
private Protocol port = null; // POP3 port for self
|
|
||||||
private POP3Folder portOwner = null; // folder owning port
|
|
||||||
private String host = null; // host
|
|
||||||
private int portNum = -1;
|
|
||||||
private String user = null;
|
|
||||||
private String passwd = null;
|
|
||||||
private boolean useStartTLS = false;
|
|
||||||
private boolean requireStartTLS = false;
|
|
||||||
private boolean usingSSL = false;
|
|
||||||
private Map capabilities;
|
|
||||||
private MailLogger logger;
|
|
||||||
|
|
||||||
// following set here and accessed by other classes in this package
|
|
||||||
volatile Constructor messageConstructor = null;
|
|
||||||
volatile boolean rsetBeforeQuit = false;
|
|
||||||
volatile boolean disableTop = false;
|
|
||||||
volatile boolean forgetTopHeaders = false;
|
|
||||||
volatile boolean supportsUidl = true;
|
|
||||||
volatile boolean cacheWriteTo = false;
|
|
||||||
volatile boolean useFileCache = false;
|
|
||||||
volatile File fileCacheDir = null;
|
|
||||||
volatile boolean keepMessageContent = false;
|
|
||||||
|
|
||||||
public POP3Store(Session session, URLName url) {
|
|
||||||
this(session, url, "pop3", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public POP3Store(Session session, URLName url,
|
|
||||||
String name, boolean isSSL) {
|
|
||||||
super(session, url);
|
|
||||||
if (url != null)
|
|
||||||
name = url.getProtocol();
|
|
||||||
this.name = name;
|
|
||||||
logger = new MailLogger(this.getClass(),
|
|
||||||
"DEBUG POP3", session);
|
|
||||||
|
|
||||||
if (!isSSL)
|
|
||||||
isSSL = PropUtil.getBooleanSessionProperty(session,
|
|
||||||
"mail." + name + ".ssl.enable", false);
|
|
||||||
if (isSSL)
|
|
||||||
this.defaultPort = 995;
|
|
||||||
else
|
|
||||||
this.defaultPort = 110;
|
|
||||||
this.isSSL = isSSL;
|
|
||||||
|
|
||||||
rsetBeforeQuit = getBoolProp("rsetbeforequit");
|
|
||||||
disableTop = getBoolProp("disabletop");
|
|
||||||
forgetTopHeaders = getBoolProp("forgettopheaders");
|
|
||||||
cacheWriteTo = getBoolProp("cachewriteto");
|
|
||||||
useFileCache = getBoolProp("filecache.enable");
|
|
||||||
String dir = session.getProperty("mail." + name + ".filecache.dir");
|
|
||||||
if (dir != null && logger.isLoggable(Level.CONFIG))
|
|
||||||
logger.config("mail." + name + ".filecache.dir: " + dir);
|
|
||||||
if (dir != null)
|
|
||||||
fileCacheDir = new File(dir);
|
|
||||||
keepMessageContent = getBoolProp("keepmessagecontent");
|
|
||||||
|
|
||||||
// mail.pop3.starttls.enable enables use of STLS command
|
|
||||||
useStartTLS = getBoolProp("starttls.enable");
|
|
||||||
|
|
||||||
// mail.pop3.starttls.required requires use of STLS command
|
|
||||||
requireStartTLS = getBoolProp("starttls.required");
|
|
||||||
|
|
||||||
String s = session.getProperty("mail." + name + ".message.class");
|
|
||||||
if (s != null) {
|
|
||||||
logger.log(Level.CONFIG, "message class: {0}", s);
|
|
||||||
try {
|
|
||||||
ClassLoader cl = this.getClass().getClassLoader();
|
|
||||||
|
|
||||||
// now load the class
|
|
||||||
Class messageClass = null;
|
|
||||||
try {
|
|
||||||
// First try the "application's" class loader.
|
|
||||||
// This should eventually be replaced by
|
|
||||||
// Thread.currentThread().getContextClassLoader().
|
|
||||||
messageClass = Class.forName(s, false, cl);
|
|
||||||
} catch (ClassNotFoundException ex1) {
|
|
||||||
// That didn't work, now try the "system" class loader.
|
|
||||||
// (Need both of these because JDK 1.1 class loaders
|
|
||||||
// may not delegate to their parent class loader.)
|
|
||||||
messageClass = Class.forName(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
Class[] c = {javax.mail.Folder.class, int.class};
|
|
||||||
messageConstructor = messageClass.getConstructor(c);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
logger.log(Level.CONFIG, "failed to load message class", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the value of a boolean property.
|
|
||||||
* Print out the value if logging is enabled.
|
|
||||||
*/
|
|
||||||
private final synchronized boolean getBoolProp(String prop) {
|
|
||||||
prop = "mail." + name + "." + prop;
|
|
||||||
boolean val = PropUtil.getBooleanSessionProperty(session, prop, false);
|
|
||||||
if (logger.isLoggable(Level.CONFIG))
|
|
||||||
logger.config(prop + ": " + val);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a reference to the session.
|
|
||||||
*/
|
|
||||||
synchronized Session getSession() {
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected synchronized boolean protocolConnect(String host, int portNum,
|
|
||||||
String user, String passwd) throws MessagingException {
|
|
||||||
|
|
||||||
// check for non-null values of host, password, user
|
|
||||||
if (host == null || passwd == null || user == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// if port is not specified, set it to value of mail.pop3.port
|
|
||||||
// property if it exists, otherwise default to 110
|
|
||||||
if (portNum == -1)
|
|
||||||
portNum = PropUtil.getIntSessionProperty(session,
|
|
||||||
"mail." + name + ".port", -1);
|
|
||||||
|
|
||||||
if (portNum == -1)
|
|
||||||
portNum = defaultPort;
|
|
||||||
|
|
||||||
this.host = host;
|
|
||||||
this.portNum = portNum;
|
|
||||||
this.user = user;
|
|
||||||
this.passwd = passwd;
|
|
||||||
try {
|
|
||||||
port = getPort(null);
|
|
||||||
} catch (EOFException eex) {
|
|
||||||
throw new AuthenticationFailedException(eex.getMessage());
|
|
||||||
} catch (SocketConnectException scex) {
|
|
||||||
throw new MailConnectException(scex);
|
|
||||||
} catch (IOException ioex) {
|
|
||||||
throw new MessagingException("Connect failed", ioex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether this store is connected. Override superclass
|
|
||||||
* method, to actually ping our server connection. <p>
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* Note that we maintain somewhat of an illusion of being connected
|
|
||||||
* even if we're not really connected. This is because a Folder
|
|
||||||
* can use the connection and close it when it's done. If we then
|
|
||||||
* ask whether the Store's connected we want the answer to be true,
|
|
||||||
* as long as we can reconnect at that point. This means that we
|
|
||||||
* need to be able to reconnect the Store on demand.
|
|
||||||
*/
|
|
||||||
public synchronized boolean isConnected() {
|
|
||||||
if (!super.isConnected())
|
|
||||||
// if we haven't been connected at all, don't bother with
|
|
||||||
// the NOOP.
|
|
||||||
return false;
|
|
||||||
try {
|
|
||||||
if (port == null)
|
|
||||||
port = getPort(null);
|
|
||||||
else if (!port.noop())
|
|
||||||
throw new IOException("NOOP failed");
|
|
||||||
return true;
|
|
||||||
} catch (IOException ioex) {
|
|
||||||
// no longer connected, close it down
|
|
||||||
try {
|
|
||||||
super.close(); // notifies listeners
|
|
||||||
} catch (MessagingException mex) {
|
|
||||||
// ignore it
|
|
||||||
} finally {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized Protocol getPort(POP3Folder owner) throws IOException {
|
|
||||||
Protocol p;
|
|
||||||
|
|
||||||
// if we already have a port, remember who's using it
|
|
||||||
if (port != null && portOwner == null) {
|
|
||||||
portOwner = owner;
|
|
||||||
return port;
|
|
||||||
}
|
|
||||||
|
|
||||||
// need a new port, create it and try to login
|
|
||||||
p = new Protocol(host, portNum, logger,
|
|
||||||
session.getProperties(), "mail." + name, isSSL);
|
|
||||||
|
|
||||||
if (useStartTLS || requireStartTLS) {
|
|
||||||
if (p.hasCapability("STLS")) {
|
|
||||||
if (p.stls()) {
|
|
||||||
// success, refresh capabilities
|
|
||||||
p.setCapabilities(p.capa());
|
|
||||||
} else if (requireStartTLS) {
|
|
||||||
logger.fine("STLS required but failed");
|
|
||||||
try {
|
|
||||||
p.quit();
|
|
||||||
} catch (IOException ioex) {
|
|
||||||
} finally {
|
|
||||||
throw new EOFException("STLS required but failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (requireStartTLS) {
|
|
||||||
logger.fine("STLS required but not supported");
|
|
||||||
try {
|
|
||||||
p.quit();
|
|
||||||
} catch (IOException ioex) {
|
|
||||||
} finally {
|
|
||||||
throw new EOFException("STLS required but not supported");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
capabilities = p.getCapabilities(); // save for later, may be null
|
|
||||||
usingSSL = p.isSSL(); // in case anyone asks
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we haven't explicitly disabled use of the TOP command,
|
|
||||||
* and the server has provided its capabilities,
|
|
||||||
* and the server doesn't support the TOP command,
|
|
||||||
* disable the TOP command.
|
|
||||||
*/
|
|
||||||
if (!disableTop &&
|
|
||||||
capabilities != null && !capabilities.containsKey("TOP")) {
|
|
||||||
disableTop = true;
|
|
||||||
logger.fine("server doesn't support TOP, disabling it");
|
|
||||||
}
|
|
||||||
|
|
||||||
supportsUidl = capabilities == null || capabilities.containsKey("UIDL");
|
|
||||||
|
|
||||||
String msg = null;
|
|
||||||
if ((msg = p.login(user, passwd)) != null) {
|
|
||||||
try {
|
|
||||||
p.quit();
|
|
||||||
} catch (IOException ioex) {
|
|
||||||
} finally {
|
|
||||||
throw new EOFException(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If a Folder closes the port, and then a Folder
|
|
||||||
* is opened, the Store won't have a port. In that
|
|
||||||
* case, the getPort call will come from Folder.open,
|
|
||||||
* but we need to keep track of the port in the Store
|
|
||||||
* so that a later call to Folder.isOpen, which calls
|
|
||||||
* Store.isConnected, will use the same port.
|
|
||||||
*/
|
|
||||||
if (port == null && owner != null) {
|
|
||||||
port = p;
|
|
||||||
portOwner = owner;
|
|
||||||
}
|
|
||||||
if (portOwner == null)
|
|
||||||
portOwner = owner;
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized void closePort(POP3Folder owner) {
|
|
||||||
if (portOwner == owner) {
|
|
||||||
port = null;
|
|
||||||
portOwner = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void close() throws MessagingException {
|
|
||||||
try {
|
|
||||||
if (port != null)
|
|
||||||
port.quit();
|
|
||||||
} catch (IOException ioex) {
|
|
||||||
} finally {
|
|
||||||
port = null;
|
|
||||||
|
|
||||||
// to set the state and send the closed connection event
|
|
||||||
super.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Folder getDefaultFolder() throws MessagingException {
|
|
||||||
checkConnected();
|
|
||||||
return new DefaultFolder(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Only the name "INBOX" is supported.
|
|
||||||
*/
|
|
||||||
public Folder getFolder(String name) throws MessagingException {
|
|
||||||
checkConnected();
|
|
||||||
return new POP3Folder(this, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Folder getFolder(URLName url) throws MessagingException {
|
|
||||||
checkConnected();
|
|
||||||
return new POP3Folder(this, url.getFile());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a Map of the capabilities the server provided,
|
|
||||||
* as per RFC 2449. If the server doesn't support RFC 2449,
|
|
||||||
* an emtpy Map is returned. The returned Map can not be modified.
|
|
||||||
* The key to the Map is the upper case capability name as
|
|
||||||
* a String. The value of the entry is the entire String
|
|
||||||
* capability line returned by the server. <p>
|
|
||||||
*
|
|
||||||
* For example, to check if the server supports the STLS capability, use:
|
|
||||||
* <code>if (store.capabilities().containsKey("STLS")) ...</code>
|
|
||||||
*
|
|
||||||
* @return Map of capabilities
|
|
||||||
* @since JavaMail 1.4.3
|
|
||||||
*/
|
|
||||||
public Map capabilities() throws MessagingException {
|
|
||||||
Map c;
|
|
||||||
synchronized (this) {
|
|
||||||
c = capabilities;
|
|
||||||
}
|
|
||||||
if (c != null)
|
|
||||||
return Collections.unmodifiableMap(c);
|
|
||||||
else
|
|
||||||
return Collections.EMPTY_MAP;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this POP3Store using SSL to connect to the server?
|
|
||||||
*
|
|
||||||
* @return true if using SSL
|
|
||||||
* @since JavaMail 1.4.6
|
|
||||||
*/
|
|
||||||
public boolean isSSL() {
|
|
||||||
return usingSSL;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void finalize() throws Throwable {
|
|
||||||
super.finalize();
|
|
||||||
|
|
||||||
if (port != null) // don't force a connection attempt
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkConnected() throws MessagingException {
|
|
||||||
if (!super.isConnected())
|
|
||||||
throw new MessagingException("Not connected");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,847 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.pop3;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.net.*;
|
|
||||||
import java.io.*;
|
|
||||||
import java.security.*;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import javax.net.ssl.SSLSocket;
|
|
||||||
|
|
||||||
import com.sun.mail.util.*;
|
|
||||||
|
|
||||||
class Response {
|
|
||||||
boolean ok = false; // true if "+OK"
|
|
||||||
String data = null; // rest of line after "+OK" or "-ERR"
|
|
||||||
InputStream bytes = null; // all the bytes from a multi-line response
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class provides a POP3 connection and implements
|
|
||||||
* the POP3 protocol requests.
|
|
||||||
*
|
|
||||||
* APOP support courtesy of "chamness".
|
|
||||||
*
|
|
||||||
* @author Bill Shannon
|
|
||||||
*/
|
|
||||||
class Protocol {
|
|
||||||
private Socket socket; // POP3 socket
|
|
||||||
private String host; // host we're connected to
|
|
||||||
private Properties props; // session properties
|
|
||||||
private String prefix; // protocol name prefix, for props
|
|
||||||
private DataInputStream input; // input buf
|
|
||||||
private PrintWriter output; // output buf
|
|
||||||
private TraceInputStream traceInput;
|
|
||||||
private TraceOutputStream traceOutput;
|
|
||||||
private MailLogger logger;
|
|
||||||
private MailLogger traceLogger;
|
|
||||||
private String apopChallenge = null;
|
|
||||||
private Map capabilities = null;
|
|
||||||
private boolean pipelining;
|
|
||||||
private boolean noauthdebug = true; // hide auth info in debug output
|
|
||||||
private boolean traceSuspended; // temporarily suspend tracing
|
|
||||||
|
|
||||||
private static final int POP3_PORT = 110; // standard POP3 port
|
|
||||||
private static final String CRLF = "\r\n";
|
|
||||||
// sometimes the returned size isn't quite big enough
|
|
||||||
private static final int SLOP = 128;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open a connection to the POP3 server.
|
|
||||||
*/
|
|
||||||
Protocol(String host, int port, MailLogger logger,
|
|
||||||
Properties props, String prefix, boolean isSSL)
|
|
||||||
throws IOException {
|
|
||||||
this.host = host;
|
|
||||||
this.props = props;
|
|
||||||
this.prefix = prefix;
|
|
||||||
this.logger = logger;
|
|
||||||
traceLogger = logger.getSubLogger("protocol", null);
|
|
||||||
noauthdebug = !PropUtil.getBooleanProperty(props,
|
|
||||||
"mail.debug.auth", false);
|
|
||||||
|
|
||||||
Response r;
|
|
||||||
boolean enableAPOP = getBoolProp(props, prefix + ".apop.enable");
|
|
||||||
boolean disableCapa = getBoolProp(props, prefix + ".disablecapa");
|
|
||||||
try {
|
|
||||||
if (port == -1)
|
|
||||||
port = POP3_PORT;
|
|
||||||
if (logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("connecting to host \"" + host +
|
|
||||||
"\", port " + port + ", isSSL " + isSSL);
|
|
||||||
|
|
||||||
socket = SocketFetcher.getSocket(host, port, props, prefix, isSSL);
|
|
||||||
initStreams();
|
|
||||||
r = simpleCommand(null);
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
try {
|
|
||||||
socket.close();
|
|
||||||
} finally {
|
|
||||||
throw ioe;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!r.ok) {
|
|
||||||
try {
|
|
||||||
socket.close();
|
|
||||||
} finally {
|
|
||||||
throw new IOException("Connect failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (enableAPOP) {
|
|
||||||
int challStart = r.data.indexOf('<'); // start of challenge
|
|
||||||
int challEnd = r.data.indexOf('>', challStart); // end of challenge
|
|
||||||
if (challStart != -1 && challEnd != -1)
|
|
||||||
apopChallenge = r.data.substring(challStart, challEnd + 1);
|
|
||||||
logger.log(Level.FINE, "APOP challenge: {0}", apopChallenge);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if server supports RFC 2449, set capabilities
|
|
||||||
if (!disableCapa)
|
|
||||||
setCapabilities(capa());
|
|
||||||
|
|
||||||
pipelining = hasCapability("PIPELINING") ||
|
|
||||||
PropUtil.getBooleanProperty(props, prefix + ".pipelining", false);
|
|
||||||
if (pipelining)
|
|
||||||
logger.config("PIPELINING enabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the value of a boolean property.
|
|
||||||
* Print out the value if logging is enabled.
|
|
||||||
*/
|
|
||||||
private final synchronized boolean getBoolProp(Properties props,
|
|
||||||
String prop) {
|
|
||||||
boolean val = PropUtil.getBooleanProperty(props, prop, false);
|
|
||||||
if (logger.isLoggable(Level.CONFIG))
|
|
||||||
logger.config(prop + ": " + val);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initStreams() throws IOException {
|
|
||||||
boolean quote = PropUtil.getBooleanProperty(props,
|
|
||||||
"mail.debug.quote", false);
|
|
||||||
traceInput =
|
|
||||||
new TraceInputStream(socket.getInputStream(), traceLogger);
|
|
||||||
traceInput.setQuote(quote);
|
|
||||||
|
|
||||||
traceOutput =
|
|
||||||
new TraceOutputStream(socket.getOutputStream(), traceLogger);
|
|
||||||
traceOutput.setQuote(quote);
|
|
||||||
|
|
||||||
input = new DataInputStream(new BufferedInputStream(traceInput));
|
|
||||||
output = new PrintWriter(
|
|
||||||
new BufferedWriter(
|
|
||||||
new OutputStreamWriter(traceOutput, "iso-8859-1")));
|
|
||||||
// should be US-ASCII, but not all JDK's support
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void finalize() throws Throwable {
|
|
||||||
super.finalize();
|
|
||||||
if (socket != null) { // Forgot to logout ?!
|
|
||||||
quit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse the capabilities from a CAPA response.
|
|
||||||
*/
|
|
||||||
synchronized void setCapabilities(InputStream in) {
|
|
||||||
if (in == null) {
|
|
||||||
capabilities = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
capabilities = new HashMap(10);
|
|
||||||
BufferedReader r = null;
|
|
||||||
try {
|
|
||||||
r = new BufferedReader(new InputStreamReader(in, "us-ascii"));
|
|
||||||
} catch (UnsupportedEncodingException ex) {
|
|
||||||
// should never happen
|
|
||||||
assert false;
|
|
||||||
}
|
|
||||||
String s;
|
|
||||||
try {
|
|
||||||
while ((s = r.readLine()) != null) {
|
|
||||||
String cap = s;
|
|
||||||
int i = cap.indexOf(' ');
|
|
||||||
if (i > 0)
|
|
||||||
cap = cap.substring(0, i);
|
|
||||||
capabilities.put(cap.toUpperCase(Locale.ENGLISH), s);
|
|
||||||
}
|
|
||||||
} catch (IOException ex) {
|
|
||||||
// should never happen
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
in.close();
|
|
||||||
} catch (IOException ex) { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether the given capability is supported by
|
|
||||||
* this server. Returns <code>true</code> if so, otherwise
|
|
||||||
* returns false.
|
|
||||||
*/
|
|
||||||
synchronized boolean hasCapability(String c) {
|
|
||||||
return capabilities != null &&
|
|
||||||
capabilities.containsKey(c.toUpperCase(Locale.ENGLISH));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the map of capabilities returned by the server.
|
|
||||||
*/
|
|
||||||
synchronized Map getCapabilities() {
|
|
||||||
return capabilities;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Login to the server, using the USER and PASS commands.
|
|
||||||
*/
|
|
||||||
synchronized String login(String user, String password)
|
|
||||||
throws IOException {
|
|
||||||
Response r;
|
|
||||||
// only pipeline password if connection is secure
|
|
||||||
boolean batch = pipelining && socket instanceof SSLSocket;
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
if (noauthdebug && isTracing()) {
|
|
||||||
logger.fine("authentication command trace suppressed");
|
|
||||||
suspendTracing();
|
|
||||||
}
|
|
||||||
String dpw = null;
|
|
||||||
if (apopChallenge != null)
|
|
||||||
dpw = getDigest(password);
|
|
||||||
if (apopChallenge != null && dpw != null) {
|
|
||||||
r = simpleCommand("APOP " + user + " " + dpw);
|
|
||||||
} else if (batch) {
|
|
||||||
String cmd = "USER " + user;
|
|
||||||
batchCommandStart(cmd);
|
|
||||||
issueCommand(cmd);
|
|
||||||
cmd = "PASS " + password;
|
|
||||||
batchCommandContinue(cmd);
|
|
||||||
issueCommand(cmd);
|
|
||||||
r = readResponse();
|
|
||||||
if (!r.ok) {
|
|
||||||
String err = r.data != null ? r.data : "USER command failed";
|
|
||||||
r = readResponse();
|
|
||||||
batchCommandEnd();
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
r = readResponse();
|
|
||||||
batchCommandEnd();
|
|
||||||
} else {
|
|
||||||
r = simpleCommand("USER " + user);
|
|
||||||
if (!r.ok)
|
|
||||||
return r.data != null ? r.data : "USER command failed";
|
|
||||||
r = simpleCommand("PASS " + password);
|
|
||||||
}
|
|
||||||
if (noauthdebug && isTracing())
|
|
||||||
logger.log(Level.FINE, "authentication command {0}",
|
|
||||||
(r.ok ? "succeeded" : "failed"));
|
|
||||||
if (!r.ok)
|
|
||||||
return r.data != null ? r.data : "login failed";
|
|
||||||
return null;
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
resumeTracing();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the APOP message digest.
|
|
||||||
* From RFC 1939:
|
|
||||||
*
|
|
||||||
* The 'digest' parameter is calculated by applying the MD5
|
|
||||||
* algorithm [RFC1321] to a string consisting of the timestamp
|
|
||||||
* (including angle-brackets) followed by a shared secret.
|
|
||||||
* The 'digest' parameter itself is a 16-octet value which is
|
|
||||||
* sent in hexadecimal format, using lower-case ASCII characters.
|
|
||||||
*
|
|
||||||
* @param password The APOP password
|
|
||||||
* @return The APOP digest or an empty string if an error occurs.
|
|
||||||
*/
|
|
||||||
private String getDigest(String password) {
|
|
||||||
String key = apopChallenge + password;
|
|
||||||
byte[] digest;
|
|
||||||
try {
|
|
||||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
|
||||||
digest = md.digest(key.getBytes("iso-8859-1")); // XXX
|
|
||||||
} catch (NoSuchAlgorithmException nsae) {
|
|
||||||
return null;
|
|
||||||
} catch (UnsupportedEncodingException uee) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return toHex(digest);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static char[] digits = {
|
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
|
||||||
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a byte array to a string of hex digits representing the bytes.
|
|
||||||
*/
|
|
||||||
private static String toHex(byte[] bytes) {
|
|
||||||
char[] result = new char[bytes.length * 2];
|
|
||||||
|
|
||||||
for (int index = 0, i = 0; index < bytes.length; index++) {
|
|
||||||
int temp = bytes[index] & 0xFF;
|
|
||||||
result[i++] = digits[temp >> 4];
|
|
||||||
result[i++] = digits[temp & 0xF];
|
|
||||||
}
|
|
||||||
return new String(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close down the connection, sending the QUIT command.
|
|
||||||
*/
|
|
||||||
synchronized boolean quit() throws IOException {
|
|
||||||
boolean ok = false;
|
|
||||||
try {
|
|
||||||
Response r = simpleCommand("QUIT");
|
|
||||||
ok = r.ok;
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
socket.close();
|
|
||||||
} finally {
|
|
||||||
socket = null;
|
|
||||||
input = null;
|
|
||||||
output = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the total number of messages and mailbox size,
|
|
||||||
* using the STAT command.
|
|
||||||
*/
|
|
||||||
synchronized Status stat() throws IOException {
|
|
||||||
Response r = simpleCommand("STAT");
|
|
||||||
Status s = new Status();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Normally the STAT command shouldn't fail but apparently it
|
|
||||||
* does when accessing Hotmail too often, returning:
|
|
||||||
* -ERR login allowed only every 15 minutes
|
|
||||||
* (Why it doesn't just fail the login, I don't know.)
|
|
||||||
* This is a serious failure that we don't want to hide
|
|
||||||
* from the user.
|
|
||||||
*/
|
|
||||||
if (!r.ok)
|
|
||||||
throw new IOException("STAT command failed: " + r.data);
|
|
||||||
|
|
||||||
if (r.data != null) {
|
|
||||||
try {
|
|
||||||
StringTokenizer st = new StringTokenizer(r.data);
|
|
||||||
s.total = Integer.parseInt(st.nextToken());
|
|
||||||
s.size = Integer.parseInt(st.nextToken());
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the size of the message using the LIST command.
|
|
||||||
*/
|
|
||||||
synchronized int list(int msg) throws IOException {
|
|
||||||
Response r = simpleCommand("LIST " + msg);
|
|
||||||
int size = -1;
|
|
||||||
if (r.ok && r.data != null) {
|
|
||||||
try {
|
|
||||||
StringTokenizer st = new StringTokenizer(r.data);
|
|
||||||
st.nextToken(); // skip message number
|
|
||||||
size = Integer.parseInt(st.nextToken());
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the size of all messages using the LIST command.
|
|
||||||
*/
|
|
||||||
synchronized InputStream list() throws IOException {
|
|
||||||
Response r = multilineCommand("LIST", 128); // 128 == output size est
|
|
||||||
return r.bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the specified message.
|
|
||||||
* Given an estimate of the message's size we can be more efficient,
|
|
||||||
* preallocating the array and returning a SharedInputStream to allow
|
|
||||||
* us to share the array.
|
|
||||||
*/
|
|
||||||
synchronized InputStream retr(int msg, int size) throws IOException {
|
|
||||||
Response r;
|
|
||||||
String cmd;
|
|
||||||
boolean batch = size == 0 && pipelining;
|
|
||||||
if (batch) {
|
|
||||||
cmd = "LIST " + msg;
|
|
||||||
batchCommandStart(cmd);
|
|
||||||
issueCommand(cmd);
|
|
||||||
cmd = "RETR " + msg;
|
|
||||||
batchCommandContinue(cmd);
|
|
||||||
issueCommand(cmd);
|
|
||||||
r = readResponse();
|
|
||||||
if (r.ok && r.data != null) {
|
|
||||||
// parse the LIST response to get the message size
|
|
||||||
try {
|
|
||||||
StringTokenizer st = new StringTokenizer(r.data);
|
|
||||||
st.nextToken(); // skip message number
|
|
||||||
size = Integer.parseInt(st.nextToken());
|
|
||||||
// don't allow ridiculous sizes
|
|
||||||
if (size > 1024*1024*1024 || size < 0)
|
|
||||||
size = 0;
|
|
||||||
else {
|
|
||||||
if (logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("pipeline message size " + size);
|
|
||||||
size += SLOP;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
r = readResponse();
|
|
||||||
if (r.ok)
|
|
||||||
r.bytes = readMultilineResponse(size + SLOP);
|
|
||||||
batchCommandEnd();
|
|
||||||
} else {
|
|
||||||
cmd = "RETR " + msg;
|
|
||||||
multilineCommandStart(cmd);
|
|
||||||
issueCommand(cmd);
|
|
||||||
r = readResponse();
|
|
||||||
if (!r.ok) {
|
|
||||||
multilineCommandEnd();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Many servers return a response to the RETR command of the form:
|
|
||||||
* +OK 832 octets
|
|
||||||
* If we don't have a size guess already, try to parse the response
|
|
||||||
* for data in that format and use it if found. It's only a guess,
|
|
||||||
* but it might be a good guess.
|
|
||||||
*/
|
|
||||||
if (size <= 0 && r.data != null) {
|
|
||||||
try {
|
|
||||||
StringTokenizer st = new StringTokenizer(r.data);
|
|
||||||
String s = st.nextToken();
|
|
||||||
String octets = st.nextToken();
|
|
||||||
if (octets.equals("octets")) {
|
|
||||||
size = Integer.parseInt(s);
|
|
||||||
// don't allow ridiculous sizes
|
|
||||||
if (size > 1024*1024*1024 || size < 0)
|
|
||||||
size = 0;
|
|
||||||
else {
|
|
||||||
if (logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("guessing message size: " + size);
|
|
||||||
size += SLOP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
r.bytes = readMultilineResponse(size);
|
|
||||||
multilineCommandEnd();
|
|
||||||
}
|
|
||||||
if (r.ok) {
|
|
||||||
if (size > 0 && logger.isLoggable(Level.FINE))
|
|
||||||
logger.fine("got message size " + r.bytes.available());
|
|
||||||
}
|
|
||||||
return r.bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the specified message and stream the content to the
|
|
||||||
* specified OutputStream. Return true on success.
|
|
||||||
*/
|
|
||||||
synchronized boolean retr(int msg, OutputStream os) throws IOException {
|
|
||||||
String cmd = "RETR " + msg;
|
|
||||||
multilineCommandStart(cmd);
|
|
||||||
issueCommand(cmd);
|
|
||||||
Response r = readResponse();
|
|
||||||
if (!r.ok) {
|
|
||||||
multilineCommandEnd();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Throwable terr = null;
|
|
||||||
int b, lastb = '\n';
|
|
||||||
try {
|
|
||||||
while ((b = input.read()) >= 0) {
|
|
||||||
if (lastb == '\n' && b == '.') {
|
|
||||||
b = input.read();
|
|
||||||
if (b == '\r') {
|
|
||||||
// end of response, consume LF as well
|
|
||||||
b = input.read();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Keep writing unless we get an error while writing,
|
|
||||||
* which we defer until all of the data has been read.
|
|
||||||
*/
|
|
||||||
if (terr == null) {
|
|
||||||
try {
|
|
||||||
os.write(b);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
logger.log(Level.FINE, "exception while streaming", ex);
|
|
||||||
terr = ex;
|
|
||||||
} catch (RuntimeException ex) {
|
|
||||||
logger.log(Level.FINE, "exception while streaming", ex);
|
|
||||||
terr = ex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lastb = b;
|
|
||||||
}
|
|
||||||
} catch (InterruptedIOException iioex) {
|
|
||||||
/*
|
|
||||||
* As above in simpleCommand, close the socket to recover.
|
|
||||||
*/
|
|
||||||
try {
|
|
||||||
socket.close();
|
|
||||||
} catch (IOException cex) { }
|
|
||||||
throw iioex;
|
|
||||||
}
|
|
||||||
if (b < 0)
|
|
||||||
throw new EOFException("EOF on socket");
|
|
||||||
|
|
||||||
// was there a deferred error?
|
|
||||||
if (terr != null) {
|
|
||||||
if (terr instanceof IOException)
|
|
||||||
throw (IOException)terr;
|
|
||||||
if (terr instanceof RuntimeException)
|
|
||||||
throw (RuntimeException)terr;
|
|
||||||
assert false; // can't get here
|
|
||||||
}
|
|
||||||
multilineCommandEnd();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the message header and the first n lines of the message.
|
|
||||||
*/
|
|
||||||
synchronized InputStream top(int msg, int n) throws IOException {
|
|
||||||
Response r = multilineCommand("TOP " + msg + " " + n, 0);
|
|
||||||
return r.bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete (permanently) the specified message.
|
|
||||||
*/
|
|
||||||
synchronized boolean dele(int msg) throws IOException {
|
|
||||||
Response r = simpleCommand("DELE " + msg);
|
|
||||||
return r.ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the UIDL string for the message.
|
|
||||||
*/
|
|
||||||
synchronized String uidl(int msg) throws IOException {
|
|
||||||
Response r = simpleCommand("UIDL " + msg);
|
|
||||||
if (!r.ok)
|
|
||||||
return null;
|
|
||||||
int i = r.data.indexOf(' ');
|
|
||||||
if (i > 0)
|
|
||||||
return r.data.substring(i + 1);
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the UIDL strings for all messages.
|
|
||||||
* The UID for msg #N is returned in uids[N-1].
|
|
||||||
*/
|
|
||||||
synchronized boolean uidl(String[] uids) throws IOException {
|
|
||||||
Response r = multilineCommand("UIDL", 15 * uids.length);
|
|
||||||
if (!r.ok)
|
|
||||||
return false;
|
|
||||||
LineInputStream lis = new LineInputStream(r.bytes);
|
|
||||||
String line = null;
|
|
||||||
while ((line = lis.readLine()) != null) {
|
|
||||||
int i = line.indexOf(' ');
|
|
||||||
if (i < 1 || i >= line.length())
|
|
||||||
continue;
|
|
||||||
int n = Integer.parseInt(line.substring(0, i));
|
|
||||||
if (n > 0 && n <= uids.length)
|
|
||||||
uids[n - 1] = line.substring(i + 1);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
r.bytes.close();
|
|
||||||
} catch (IOException ex) { }
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Do a NOOP.
|
|
||||||
*/
|
|
||||||
synchronized boolean noop() throws IOException {
|
|
||||||
Response r = simpleCommand("NOOP");
|
|
||||||
return r.ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Do an RSET.
|
|
||||||
*/
|
|
||||||
synchronized boolean rset() throws IOException {
|
|
||||||
Response r = simpleCommand("RSET");
|
|
||||||
return r.ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start TLS using STLS command specified by RFC 2595.
|
|
||||||
* If already using SSL, this is a nop and the STLS command is not issued.
|
|
||||||
*/
|
|
||||||
synchronized boolean stls() throws IOException {
|
|
||||||
if (socket instanceof SSLSocket)
|
|
||||||
return true; // nothing to do
|
|
||||||
Response r = simpleCommand("STLS");
|
|
||||||
if (r.ok) {
|
|
||||||
// it worked, now switch the socket into TLS mode
|
|
||||||
try {
|
|
||||||
socket = SocketFetcher.startTLS(socket, host, props, prefix);
|
|
||||||
initStreams();
|
|
||||||
} catch (IOException ioex) {
|
|
||||||
try {
|
|
||||||
socket.close();
|
|
||||||
} finally {
|
|
||||||
socket = null;
|
|
||||||
input = null;
|
|
||||||
output = null;
|
|
||||||
}
|
|
||||||
IOException sioex =
|
|
||||||
new IOException("Could not convert socket to TLS");
|
|
||||||
sioex.initCause(ioex);
|
|
||||||
throw sioex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r.ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this connection using SSL?
|
|
||||||
*/
|
|
||||||
synchronized boolean isSSL() {
|
|
||||||
return socket instanceof SSLSocket;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get server capabilities using CAPA command specified by RFC 2449.
|
|
||||||
* Returns null if not supported.
|
|
||||||
*/
|
|
||||||
synchronized InputStream capa() throws IOException {
|
|
||||||
Response r = multilineCommand("CAPA", 128); // 128 == output size est
|
|
||||||
if (!r.ok)
|
|
||||||
return null;
|
|
||||||
return r.bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Issue a simple POP3 command and return the response.
|
|
||||||
*/
|
|
||||||
private Response simpleCommand(String cmd) throws IOException {
|
|
||||||
simpleCommandStart(cmd);
|
|
||||||
issueCommand(cmd);
|
|
||||||
Response r = readResponse();
|
|
||||||
simpleCommandEnd();
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send the specified command.
|
|
||||||
*/
|
|
||||||
private void issueCommand(String cmd) throws IOException {
|
|
||||||
if (socket == null)
|
|
||||||
throw new IOException("Folder is closed"); // XXX
|
|
||||||
|
|
||||||
if (cmd != null) {
|
|
||||||
cmd += CRLF;
|
|
||||||
output.print(cmd); // do it in one write
|
|
||||||
output.flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the response to a command.
|
|
||||||
*/
|
|
||||||
private Response readResponse() throws IOException {
|
|
||||||
String line = null;
|
|
||||||
try {
|
|
||||||
line = input.readLine(); // XXX - readLine is deprecated
|
|
||||||
} catch (InterruptedIOException iioex) {
|
|
||||||
/*
|
|
||||||
* If we get a timeout while using the socket, we have no idea
|
|
||||||
* what state the connection is in. The server could still be
|
|
||||||
* alive, but slow, and could still be sending data. The only
|
|
||||||
* safe way to recover is to drop the connection.
|
|
||||||
*/
|
|
||||||
try {
|
|
||||||
socket.close();
|
|
||||||
} catch (IOException cex) { }
|
|
||||||
throw new EOFException(iioex.getMessage());
|
|
||||||
} catch (SocketException ex) {
|
|
||||||
/*
|
|
||||||
* If we get an error while using the socket, we have no idea
|
|
||||||
* what state the connection is in. The server could still be
|
|
||||||
* alive, but slow, and could still be sending data. The only
|
|
||||||
* safe way to recover is to drop the connection.
|
|
||||||
*/
|
|
||||||
try {
|
|
||||||
socket.close();
|
|
||||||
} catch (IOException cex) { }
|
|
||||||
throw new EOFException(ex.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line == null) {
|
|
||||||
traceLogger.finest("<EOF>");
|
|
||||||
throw new EOFException("EOF on socket");
|
|
||||||
}
|
|
||||||
Response r = new Response();
|
|
||||||
if (line.startsWith("+OK"))
|
|
||||||
r.ok = true;
|
|
||||||
else if (line.startsWith("-ERR"))
|
|
||||||
r.ok = false;
|
|
||||||
else
|
|
||||||
throw new IOException("Unexpected response: " + line);
|
|
||||||
int i;
|
|
||||||
if ((i = line.indexOf(' ')) >= 0)
|
|
||||||
r.data = line.substring(i + 1);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Issue a POP3 command that expects a multi-line response.
|
|
||||||
* <code>size</code> is an estimate of the response size.
|
|
||||||
*/
|
|
||||||
private Response multilineCommand(String cmd, int size) throws IOException {
|
|
||||||
multilineCommandStart(cmd);
|
|
||||||
issueCommand(cmd);
|
|
||||||
Response r = readResponse();
|
|
||||||
if (!r.ok) {
|
|
||||||
multilineCommandEnd();
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
r.bytes = readMultilineResponse(size);
|
|
||||||
multilineCommandEnd();
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the response to a multiline command after the command response.
|
|
||||||
* The size parameter indicates the expected size of the response;
|
|
||||||
* the actual size can be different. Returns an InputStream to the
|
|
||||||
* response bytes.
|
|
||||||
*/
|
|
||||||
private InputStream readMultilineResponse(int size) throws IOException {
|
|
||||||
SharedByteArrayOutputStream buf = new SharedByteArrayOutputStream(size);
|
|
||||||
int b, lastb = '\n';
|
|
||||||
try {
|
|
||||||
while ((b = input.read()) >= 0) {
|
|
||||||
if (lastb == '\n' && b == '.') {
|
|
||||||
b = input.read();
|
|
||||||
if (b == '\r') {
|
|
||||||
// end of response, consume LF as well
|
|
||||||
b = input.read();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buf.write(b);
|
|
||||||
lastb = b;
|
|
||||||
}
|
|
||||||
} catch (InterruptedIOException iioex) {
|
|
||||||
/*
|
|
||||||
* As above in readResponse, close the socket to recover.
|
|
||||||
*/
|
|
||||||
try {
|
|
||||||
socket.close();
|
|
||||||
} catch (IOException cex) { }
|
|
||||||
throw iioex;
|
|
||||||
}
|
|
||||||
if (b < 0)
|
|
||||||
throw new EOFException("EOF on socket");
|
|
||||||
return buf.toStream();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is protocol tracing enabled?
|
|
||||||
*/
|
|
||||||
protected boolean isTracing() {
|
|
||||||
return traceLogger.isLoggable(Level.FINEST);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Temporarily turn off protocol tracing, e.g., to prevent
|
|
||||||
* tracing the authentication sequence, including the password.
|
|
||||||
*/
|
|
||||||
private void suspendTracing() {
|
|
||||||
if (traceLogger.isLoggable(Level.FINEST)) {
|
|
||||||
traceInput.setTrace(false);
|
|
||||||
traceOutput.setTrace(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resume protocol tracing, if it was enabled to begin with.
|
|
||||||
*/
|
|
||||||
private void resumeTracing() {
|
|
||||||
if (traceLogger.isLoggable(Level.FINEST)) {
|
|
||||||
traceInput.setTrace(true);
|
|
||||||
traceOutput.setTrace(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Probe points for GlassFish monitoring.
|
|
||||||
*/
|
|
||||||
private void simpleCommandStart(String command) { }
|
|
||||||
private void simpleCommandEnd() { }
|
|
||||||
private void multilineCommandStart(String command) { }
|
|
||||||
private void multilineCommandEnd() { }
|
|
||||||
private void batchCommandStart(String command) { }
|
|
||||||
private void batchCommandContinue(String command) { }
|
|
||||||
private void batchCommandEnd() { }
|
|
||||||
}
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.pop3;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Result of POP3 STAT command.
|
|
||||||
*/
|
|
||||||
class Status {
|
|
||||||
int total = 0; // number of messages in the mailbox
|
|
||||||
int size = 0; // size of the mailbox
|
|
||||||
};
|
|
||||||
@ -1,193 +0,0 @@
|
|||||||
/*
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2010-2011 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common Development
|
|
||||||
* and Distribution License("CDDL") (collectively, the "License"). You
|
|
||||||
* may not use this file except in compliance with the License. You can
|
|
||||||
* obtain a copy of the License at
|
|
||||||
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
|
|
||||||
* or packager/legal/LICENSE.txt. See the License for the specific
|
|
||||||
* language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing the software, include this License Header Notice in each
|
|
||||||
* file and include the License file at packager/legal/LICENSE.txt.
|
|
||||||
*
|
|
||||||
* GPL Classpath Exception:
|
|
||||||
* Oracle designates this particular file as subject to the "Classpath"
|
|
||||||
* exception as provided by Oracle in the GPL Version 2 section of the License
|
|
||||||
* file that accompanied this code.
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* If applicable, add the following below the License Header, with the fields
|
|
||||||
* enclosed by brackets [] replaced by your own identifying information:
|
|
||||||
* "Portions Copyright [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL or
|
|
||||||
* only the GPL Version 2, indicate your decision by adding "[Contributor]
|
|
||||||
* elects to include this software in this distribution under the [CDDL or GPL
|
|
||||||
* Version 2] license." If you don't indicate a single choice of license, a
|
|
||||||
* recipient has the option to distribute your version of this file under
|
|
||||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to
|
|
||||||
* its licensees as provided above. However, if you add GPL Version 2 code
|
|
||||||
* and therefore, elected the GPL Version 2 license, then the option applies
|
|
||||||
* only if the new code is made subject to such option by the copyright
|
|
||||||
* holder.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sun.mail.pop3;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.net.*;
|
|
||||||
import java.io.*;
|
|
||||||
import java.security.*;
|
|
||||||
|
|
||||||
import com.sun.mail.util.PropUtil;
|
|
||||||
import javax.mail.util.SharedFileInputStream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A temporary file used to cache POP3 messages.
|
|
||||||
*/
|
|
||||||
class TempFile {
|
|
||||||
|
|
||||||
private File file; // the temp file name
|
|
||||||
private WritableSharedFile sf;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a temp file in the specified directory (if not null).
|
|
||||||
* The file will be deleted when the JVM exits.
|
|
||||||
*/
|
|
||||||
public TempFile(File dir) throws IOException {
|
|
||||||
file = File.createTempFile("pop3.", ".mbox", dir);
|
|
||||||
// XXX - need JDK 6 to set permissions on the file to owner-only
|
|
||||||
file.deleteOnExit();
|
|
||||||
sf = new WritableSharedFile(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a stream for appending to the temp file.
|
|
||||||
*/
|
|
||||||
public AppendStream getAppendStream() throws IOException {
|
|
||||||
return sf.getAppendStream();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close and remove this temp file.
|
|
||||||
*/
|
|
||||||
public void close() {
|
|
||||||
try {
|
|
||||||
sf.close();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
// ignore it
|
|
||||||
}
|
|
||||||
file.delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void finalize() throws Throwable {
|
|
||||||
super.finalize();
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A subclass of SharedFileInputStream that also allows writing.
|
|
||||||
*/
|
|
||||||
class WritableSharedFile extends SharedFileInputStream {
|
|
||||||
private RandomAccessFile raf;
|
|
||||||
private AppendStream af;
|
|
||||||
|
|
||||||
public WritableSharedFile(File file) throws IOException {
|
|
||||||
super(file);
|
|
||||||
try {
|
|
||||||
raf = new RandomAccessFile(file, "rw");
|
|
||||||
} catch (IOException ex) {
|
|
||||||
// if anything goes wrong opening the writable file,
|
|
||||||
// close the readable file too
|
|
||||||
super.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the writable version of this file.
|
|
||||||
*/
|
|
||||||
public RandomAccessFile getWritableFile() {
|
|
||||||
return raf;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close the readable and writable files.
|
|
||||||
*/
|
|
||||||
public void close() throws IOException {
|
|
||||||
try {
|
|
||||||
super.close();
|
|
||||||
} finally {
|
|
||||||
raf.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the size of the readable file after writing
|
|
||||||
* to the file. Updates the length to be the current
|
|
||||||
* size of the file.
|
|
||||||
*/
|
|
||||||
synchronized long updateLength() throws IOException {
|
|
||||||
datalen = in.length();
|
|
||||||
af = null;
|
|
||||||
return datalen;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a new AppendStream, but only if one isn't in active use.
|
|
||||||
*/
|
|
||||||
public synchronized AppendStream getAppendStream() throws IOException {
|
|
||||||
if (af != null)
|
|
||||||
throw new IOException(
|
|
||||||
"POP3 file cache only supports single threaded access");
|
|
||||||
af = new AppendStream(this);
|
|
||||||
return af;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A stream for writing to the temp file, and when done
|
|
||||||
* can return a stream for reading the data just written.
|
|
||||||
* NOTE: We assume that only one thread is writing to the
|
|
||||||
* file at a time.
|
|
||||||
*/
|
|
||||||
class AppendStream extends OutputStream {
|
|
||||||
private final WritableSharedFile tf;
|
|
||||||
private RandomAccessFile raf;
|
|
||||||
private final long start;
|
|
||||||
private long end;
|
|
||||||
|
|
||||||
public AppendStream(WritableSharedFile tf) throws IOException {
|
|
||||||
this.tf = tf;
|
|
||||||
raf = tf.getWritableFile();
|
|
||||||
start = raf.length();
|
|
||||||
raf.seek(start);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void write(int b) throws IOException {
|
|
||||||
raf.write(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void write(byte[] b) throws IOException {
|
|
||||||
raf.write(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void write(byte[] b, int off, int len) throws IOException {
|
|
||||||
raf.write(b, off, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void close() throws IOException {
|
|
||||||
end = tf.updateLength();
|
|
||||||
raf = null; // no more writing allowed
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized InputStream getInputStream() throws IOException {
|
|
||||||
return tf.newStream(start, end);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user