diff --git a/.gitignore b/.gitignore
index 5c3fb3fc..a0348ece 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,125 @@
-/target/
-/bin/
-/.settings/
-.classpath
+# Created by https://www.gitignore.io
+
+### Java ###
+*.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
-/target/
\ No newline at end of file
+
+# 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/
diff --git a/.travis.yml b/.travis.yml
index ec31f553..2ad8a664 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,4 +1,4 @@
language: java
jdk:
- - openjdk6
+ - oraclejdk7
script: "mvn clean install"
diff --git a/lib/ChestShop.jar b/lib/ChestShop.jar
deleted file mode 100644
index 8bb2747f..00000000
Binary files a/lib/ChestShop.jar and /dev/null differ
diff --git a/lib/CombatTag-5.4.jar b/lib/CombatTag-5.4.jar
deleted file mode 100644
index 8dd68c9f..00000000
Binary files a/lib/CombatTag-5.4.jar and /dev/null differ
diff --git a/lib/CombatTagPlus.jar b/lib/CombatTagPlus.jar
deleted file mode 100644
index ae2ee9bf..00000000
Binary files a/lib/CombatTagPlus.jar and /dev/null differ
diff --git a/lib/CraftBukkit.jar b/lib/CraftBukkit.jar
deleted file mode 100644
index 9bbf0811..00000000
Binary files a/lib/CraftBukkit.jar and /dev/null differ
diff --git a/lib/Essentials.jar b/lib/Essentials.jar
deleted file mode 100644
index 1deedd11..00000000
Binary files a/lib/Essentials.jar and /dev/null differ
diff --git a/lib/Multiverse-Core-2.5.jar b/lib/Multiverse-Core-2.5.jar
deleted file mode 100644
index 69e8faf2..00000000
Binary files a/lib/Multiverse-Core-2.5.jar and /dev/null differ
diff --git a/lib/Spigot.jar b/lib/Spigot.jar
deleted file mode 100644
index a9be4209..00000000
Binary files a/lib/Spigot.jar and /dev/null differ
diff --git a/lib/SpoutPlugin.jar b/lib/SpoutPlugin.jar
deleted file mode 100644
index d191e624..00000000
Binary files a/lib/SpoutPlugin.jar and /dev/null differ
diff --git a/lib/Vault.jar b/lib/Vault.jar
deleted file mode 100644
index f9aa3240..00000000
Binary files a/lib/Vault.jar and /dev/null differ
diff --git a/lib/citizensapi-2.0.13-SNAPSHOT.jar b/lib/citizensapi-2.0.13-SNAPSHOT.jar
deleted file mode 100644
index 43a895db..00000000
Binary files a/lib/citizensapi-2.0.13-SNAPSHOT.jar and /dev/null differ
diff --git a/lib/h2-1.3.164.jar b/lib/h2-1.3.164.jar
deleted file mode 100644
index f5519a6b..00000000
Binary files a/lib/h2-1.3.164.jar and /dev/null differ
diff --git a/lib/mysql-connector-java.jar b/lib/mysql-connector-java.jar
deleted file mode 100644
index 0539039f..00000000
Binary files a/lib/mysql-connector-java.jar and /dev/null differ
diff --git a/lib/sqlite-jdbc.jar b/lib/sqlite-jdbc.jar
deleted file mode 100644
index b0bec7b0..00000000
Binary files a/lib/sqlite-jdbc.jar and /dev/null differ
diff --git a/lib/xAuth-2.4.4.jar b/lib/xAuth-2.4.4.jar
deleted file mode 100644
index 39c79f9f..00000000
Binary files a/lib/xAuth-2.4.4.jar and /dev/null differ
diff --git a/libs/ChestShop.jar b/libs/ChestShop.jar
new file mode 100644
index 00000000..e2a7f458
Binary files /dev/null and b/libs/ChestShop.jar differ
diff --git a/lib/Citizens.jar b/libs/Citizens.jar
similarity index 56%
rename from lib/Citizens.jar
rename to libs/Citizens.jar
index ee6f92e6..9cf4d17c 100644
Binary files a/lib/Citizens.jar and b/libs/Citizens.jar differ
diff --git a/lib/Notifications.jar b/libs/Notifications.jar
similarity index 100%
rename from lib/Notifications.jar
rename to libs/Notifications.jar
diff --git a/lib/xAuth.jar b/libs/xAuth.jar
similarity index 100%
rename from lib/xAuth.jar
rename to libs/xAuth.jar
diff --git a/pom.xml b/pom.xml
index 89293563..0ed082f7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,138 +1,288 @@
-
+
+4.0.0
+
fr.xephi.authme.AuthMeAuthMe
- jar
- AuthMe
-
- UTF-8
-
-
-
-
- maven-jar-plugin
- 2.5
-
-
- ${manifest.file}
-
-
-
-
- 5.0-SNAPSHOT
+
+ AuthMeReloaded
+ Authentication plugin for CraftBukkit/Spigot!
+ http://dev.bukkit.org/bukkit-plugins/authme-reloaded/
+
+ jar
+
+
+ UTF-8
+
+
+ 1.7
+ 1.7
+
+
+ 1.8.7-R0.1-SNAPSHOT
+
+ ${project.groupId}.${project.artifactId}
+
+
+
+
+ jenkins
+ http://ci.xephi.fr
+
+
+
+ GitHub
+ https://github.com/Xephi/AuthMeReloaded/issues
+
+
+
+
+
+ maven-jar-plugin
+ 2.5
+
+
+ ${manifest.file}
+
+
+
+
+
+
+
+
+
+
+
+ spigot-repo
+ https://hub.spigotmc.org/nexus/content/groups/public/
+
+
+
+
+ vault-repo
+ http://nexus.theyeticave.net/content/repositories/pub_releases
+
+
+
+
+ everything
+ http://repo.citizensnpcs.co
+
+
+
+
+ onarandombox
+ http://repo.onarandombox.com/content/groups/public
+
+
+
+
+ ess-repo
+ https://ci.drtshock.net/plugin/repository/everything/
+
+
+
+
+ minelink-thirdparty
+ http://repo.minelink.net/content/repositories/public
+
+
+
+
+ techcable-repo
+ http://repo.techcable.net/content/repositories/snapshots/
+
+
+
+
+ bukkit-plugins-releases
+ repo.luricos.de releases
+ http://repo.luricos.de/content/repositories/releases/
+
+
+
+
+ sonatype-nexus-releases
+ https://oss.sonatype.org/content/repositories/releases
+
+
+ sonatype-nexus-snapshots
+ https://oss.sonatype.org/content/repositories/snapshots
+
+ true
+ always
+
+
+
+
+
+
+
+
-
- org.spigotmc
- spigot
- 1.8.3
- system
- ${project.basedir}/lib/Spigot.jar
-
-
- net.milkbowl.vault
- Vault
- 1.5.3
- system
- ${project.basedir}/lib/Vault.jar
-
-
- net.citizensnpcs
- citizensapi
- 2.0.13-SNAPSHOT
- system
- ${project.basedir}/lib/citizensapi-2.0.13-SNAPSHOT.jar
-
-
- net.citizensnpcs
- Citizens
- 1.2.1
- system
- ${project.basedir}/lib/Citizens.jar
-
-
- org.getspout
- spoutapi
- 1.6.4-SNAPSHOT
- system
- ${project.basedir}/lib/SpoutPlugin.jar
-
-
- com.trc202
- CombatTag
- 5.4
- system
- ${project.basedir}/lib/CombatTag-5.4.jar
-
-
- mysql
- mysql-connector-java
- 5.1.6
- system
- ${project.basedir}/lib/mysql-connector-java.jar
-
-
- org.xerial
- sqlite-jdbc
- 3.7.2
- system
- ${project.basedir}/lib/sqlite-jdbc.jar
-
+
+
+
+
+
+ mysql
+ mysql-connector-java
+ 5.1.35
+
+
+
+
+ org.xerial
+ sqlite-jdbc
+ 3.8.10.1
+
+
+
- me.muizers
- Notifications
- 1.6
- system
- ${project.basedir}/lib/Notifications.jar
-
+ com.h2database
+ h2
+ 1.4.187
+
+
+
- com.Acrobot
- ChestShop
- 3.7.9
- system
- ${project.basedir}/lib/ChestShop.jar
-
+ com.sun.mail
+ javax.mail
+ 1.5.3
+
- com.h2
- h2
- 1.3.164
- system
- ${project.basedir}/lib/h2-1.3.164.jar
-
+ javax.mail
+ mail
+ 1.5.0-b01
+
+
+
+
+
- de.luricos.bukkit
- xAuth
- 2.4.4
- system
- ${project.basedir}/lib/xAuth-2.4.4.jar
-
+ com.maxmind.geoip
+ geoip-api
+ 1.2.14
+
+
+
+
+ org.spigotmc
+ spigot-api
+ ${bukkitVersion}
+
+
+
+
+ net.milkbowl.vault
+ Vault
+ 1.5.4
+ provided
+
+
+
+
+ net.citizensnpcs
+ citizensapi
+ 2.0.16-SNAPSHOT
+ provided
+
+
+
- com.onarandombox
- MultiverseCore
- 2.5-b654
- system
- ${project.basedir}/lib/Multiverse-Core-2.5.jar
-
-
- com.earth2me.essentials
- Essentials
- 2.13.1
- system
- ${project.basedir}/lib/Essentials.jar
-
-
- net.minelink
- CombatTagPlus
- 1.1.2-SNAPSHOT
- system
- ${project.basedir}/lib/CombatTagPlus.jar
-
+ com.onarandombox.multiversecore
+ Multiverse-Core
+ 2.5
+
+
+
+
+ net.ess3
+ EssentialsX
+ 2.0.1-SNAPSHOT
+
+
+
+
+ net.minelink
+ CombatTagPlus
+ 1.2.1-SNAPSHOT
+
+
+
+
+ com.trc202
+ combattag
+ 6.4.1-SNAPSHOT
+
+
+
+
+ de.luricos.bukkit
+ xAuth
+ 2.6
+
+
+
+
+ org.spoutcraft
+ spoutcraftplugin
+ 1.6.4-SNAPSHOT
+
+
+
+
+
+
+ com.Acrobot
+ ChestShop
+ 3.8.10
+ system
+ ${project.basedir}/libs/ChestShop.jar
+
+
+
+
+ net.citizensnpcs
+ citizens
+ 1.2.4
+ system
+ ${project.basedir}/libs/Citizens.jar
+
+
+
+
+ com.cypherx
+ xauth
+ 2.0.26
+ system
+ ${project.basedir}/libs/xAuth.jar
+
+
+
+
+ me.muizers
+ Notifications
+ 1.6
+ system
+ ${project.basedir}/libs/Notifications.jar
+
+
-
\ No newline at end of file
+
diff --git a/snapshots/AuthMe-5.0-SNAPSHOT.jar b/snapshots/AuthMe-5.0-SNAPSHOT.jar
new file mode 100644
index 00000000..2aee53fc
Binary files /dev/null and b/snapshots/AuthMe-5.0-SNAPSHOT.jar differ
diff --git a/src/main/java/com/maxmind/geoip/Country.java b/src/main/java/com/maxmind/geoip/Country.java
deleted file mode 100644
index d250eb76..00000000
--- a/src/main/java/com/maxmind/geoip/Country.java
+++ /dev/null
@@ -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;
- }
-}
diff --git a/src/main/java/com/maxmind/geoip/DatabaseInfo.java b/src/main/java/com/maxmind/geoip/DatabaseInfo.java
deleted file mode 100644
index 939259eb..00000000
--- a/src/main/java/com/maxmind/geoip/DatabaseInfo.java
+++ /dev/null
@@ -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:
- *
- *
- *
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.
- *
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.
- *
City edition -- includes country, region, city, postal code, latitude, and
- * longitude information.
- *
Org edition -- includes netblock owner.
- *
ISP edition -- ISP information.
- *
- *
- * @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
- Copyright (C)
-
- 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.
-
- , 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
-
-
diff --git a/src/main/java/com/maxmind/geoip/Location.java b/src/main/java/com/maxmind/geoip/Location.java
deleted file mode 100644
index 040fcb6b..00000000
--- a/src/main/java/com/maxmind/geoip/Location.java
+++ /dev/null
@@ -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));
- }
-}
diff --git a/src/main/java/com/maxmind/geoip/LookupService.java b/src/main/java/com/maxmind/geoip/LookupService.java
deleted file mode 100644
index 72a33260..00000000
--- a/src/main/java/com/maxmind/geoip/LookupService.java
+++ /dev/null
@@ -1,1046 +0,0 @@
-/**
- * LookupService.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.io.File;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.StringTokenizer;
-import javax.naming.NamingException;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.InitialDirContext;
-
-/**
- * Provides a lookup service for information based on an IP address. The location of
- * a database file is supplied when creating a lookup service instance. The edition of
- * the database determines what information is available about an IP address. See the
- * DatabaseInfo class for further details.
- *
- * The following code snippet demonstrates looking up the country that an IP
- * address is from:
- *
- * // First, create a LookupService instance with the location of the database.
- * LookupService lookupService = new LookupService("c:\\geoip.dat");
- * // Assume we have a String ipAddress (in dot-decimal form).
- * Country country = lookupService.getCountry(ipAddress);
- * System.out.println("The country is: " + country.getName());
- * System.out.println("The country code is: " + country.getCode());
- *
- *
- * In general, a single LookupService instance should be created and then reused
- * repeatedly.
- *
- * Tip: Those deploying the GeoIP API as part of a web application may find it
- * difficult to pass in a File to create the lookup service, as the location of the
- * database may vary per deployment or may even be part of the web-application. In this
- * case, the database should be added to the classpath of the web-app. For example, by
- * putting it into the WEB-INF/classes directory of the web application. The following code
- * snippet demonstrates how to create a LookupService using a database that can be found
- * on the classpath:
- *
- *
- *
- * @author Matt Tucker (matt@jivesoftware.com)
- */
-public class LookupService {
-
- /**
- * Database file.
- */
- private RandomAccessFile file = null;
- private File databaseFile = null;
-
- /**
- * Information about the database.
- */
- private DatabaseInfo databaseInfo = null;
-
- /**
- * The database type. Default is the country edition.
- */
- byte databaseType = DatabaseInfo.COUNTRY_EDITION;
-
- int databaseSegments[];
- int recordLength;
-
- String licenseKey;
- int dnsService = 0;
- int dboptions;
- byte dbbuffer[];
- byte index_cache[];
- long mtime;
- int last_netmask;
- private final static int US_OFFSET = 1;
- private final static int CANADA_OFFSET = 677;
- private final static int WORLD_OFFSET = 1353;
- private final static int FIPS_RANGE = 360;
- private final static int COUNTRY_BEGIN = 16776960;
- private final static int STATE_BEGIN_REV0 = 16700000;
- private final static int STATE_BEGIN_REV1 = 16000000;
- private final static int STRUCTURE_INFO_MAX_SIZE = 20;
- private final static int DATABASE_INFO_MAX_SIZE = 100;
- public final static int GEOIP_STANDARD = 0;
- public final static int GEOIP_MEMORY_CACHE = 1;
- public final static int GEOIP_CHECK_CACHE = 2;
- public final static int GEOIP_INDEX_CACHE = 4;
- public final static int GEOIP_UNKNOWN_SPEED = 0;
- public final static int GEOIP_DIALUP_SPEED = 1;
- public final static int GEOIP_CABLEDSL_SPEED = 2;
- public final static int GEOIP_CORPORATE_SPEED = 3;
-
-
- private final static int SEGMENT_RECORD_LENGTH = 3;
- private final static int STANDARD_RECORD_LENGTH = 3;
- private final static int ORG_RECORD_LENGTH = 4;
- private final static int MAX_RECORD_LENGTH = 4;
-
- private final static int MAX_ORG_RECORD_LENGTH = 300;
- private final static int FULL_RECORD_LENGTH = 60;
-
- private final Country UNKNOWN_COUNTRY = new Country("--", "N/A");
-
- private static final HashMap hashmapcountryCodetoindex = new HashMap(512);
- private static final HashMap hashmapcountryNametoindex = new HashMap(512);
- private static final String[] countryCode = {
- "--","AP","EU","AD","AE","AF","AG","AI","AL","AM","AN","AO","AQ","AR",
- "AS","AT","AU","AW","AZ","BA","BB","BD","BE","BF","BG","BH","BI","BJ",
- "BM","BN","BO","BR","BS","BT","BV","BW","BY","BZ","CA","CC","CD","CF",
- "CG","CH","CI","CK","CL","CM","CN","CO","CR","CU","CV","CX","CY","CZ",
- "DE","DJ","DK","DM","DO","DZ","EC","EE","EG","EH","ER","ES","ET","FI",
- "FJ","FK","FM","FO","FR","FX","GA","GB","GD","GE","GF","GH","GI","GL",
- "GM","GN","GP","GQ","GR","GS","GT","GU","GW","GY","HK","HM","HN","HR",
- "HT","HU","ID","IE","IL","IN","IO","IQ","IR","IS","IT","JM","JO","JP",
- "KE","KG","KH","KI","KM","KN","KP","KR","KW","KY","KZ","LA","LB","LC",
- "LI","LK","LR","LS","LT","LU","LV","LY","MA","MC","MD","MG","MH","MK",
- "ML","MM","MN","MO","MP","MQ","MR","MS","MT","MU","MV","MW","MX","MY",
- "MZ","NA","NC","NE","NF","NG","NI","NL","NO","NP","NR","NU","NZ","OM",
- "PA","PE","PF","PG","PH","PK","PL","PM","PN","PR","PS","PT","PW","PY",
- "QA","RE","RO","RU","RW","SA","SB","SC","SD","SE","SG","SH","SI","SJ",
- "SK","SL","SM","SN","SO","SR","ST","SV","SY","SZ","TC","TD","TF","TG",
- "TH","TJ","TK","TM","TN","TO","TL","TR","TT","TV","TW","TZ","UA","UG",
- "UM","US","UY","UZ","VA","VC","VE","VG","VI","VN","VU","WF","WS","YE",
- "YT","RS","ZA","ZM","ME","ZW","A1","A2","O1","AX","GG","IM","JE","BL",
- "MF"};
-
- private static final String[] countryName = {
- "N/A","Asia/Pacific Region","Europe","Andorra","United Arab Emirates",
- "Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia",
- "Netherlands Antilles","Angola","Antarctica","Argentina","American Samoa",
- "Austria","Australia","Aruba","Azerbaijan","Bosnia and Herzegovina",
- "Barbados","Bangladesh","Belgium","Burkina Faso","Bulgaria","Bahrain",
- "Burundi","Benin","Bermuda","Brunei Darussalam","Bolivia","Brazil","Bahamas",
- "Bhutan","Bouvet Island","Botswana","Belarus","Belize","Canada",
- "Cocos (Keeling) Islands","Congo, The Democratic Republic of the",
- "Central African Republic","Congo","Switzerland","Cote D'Ivoire",
- "Cook Islands","Chile","Cameroon","China","Colombia","Costa Rica","Cuba",
- "Cape Verde","Christmas Island","Cyprus","Czech Republic","Germany",
- "Djibouti","Denmark","Dominica","Dominican Republic","Algeria","Ecuador",
- "Estonia","Egypt","Western Sahara","Eritrea","Spain","Ethiopia","Finland",
- "Fiji","Falkland Islands (Malvinas)","Micronesia, Federated States of",
- "Faroe Islands","France","France, Metropolitan","Gabon","United Kingdom",
- "Grenada","Georgia","French Guiana","Ghana","Gibraltar","Greenland","Gambia",
- "Guinea","Guadeloupe","Equatorial Guinea","Greece",
- "South Georgia and the South Sandwich Islands","Guatemala","Guam",
- "Guinea-Bissau","Guyana","Hong Kong","Heard Island and McDonald Islands",
- "Honduras","Croatia","Haiti","Hungary","Indonesia","Ireland","Israel","India",
- "British Indian Ocean Territory","Iraq","Iran, Islamic Republic of",
- "Iceland","Italy","Jamaica","Jordan","Japan","Kenya","Kyrgyzstan","Cambodia",
- "Kiribati","Comoros","Saint Kitts and Nevis",
- "Korea, Democratic People's Republic of","Korea, Republic of","Kuwait",
- "Cayman Islands","Kazakhstan","Lao People's Democratic Republic","Lebanon",
- "Saint Lucia","Liechtenstein","Sri Lanka","Liberia","Lesotho","Lithuania",
- "Luxembourg","Latvia","Libyan Arab Jamahiriya","Morocco","Monaco",
- "Moldova, Republic of","Madagascar","Marshall Islands",
- "Macedonia","Mali","Myanmar","Mongolia",
- "Macau","Northern Mariana Islands","Martinique","Mauritania","Montserrat",
- "Malta","Mauritius","Maldives","Malawi","Mexico","Malaysia","Mozambique",
- "Namibia","New Caledonia","Niger","Norfolk Island","Nigeria","Nicaragua",
- "Netherlands","Norway","Nepal","Nauru","Niue","New Zealand","Oman","Panama",
- "Peru","French Polynesia","Papua New Guinea","Philippines","Pakistan",
- "Poland","Saint Pierre and Miquelon","Pitcairn Islands","Puerto Rico","" +
- "Palestinian Territory","Portugal","Palau","Paraguay","Qatar",
- "Reunion","Romania","Russian Federation","Rwanda","Saudi Arabia",
- "Solomon Islands","Seychelles","Sudan","Sweden","Singapore","Saint Helena",
- "Slovenia","Svalbard and Jan Mayen","Slovakia","Sierra Leone","San Marino",
- "Senegal","Somalia","Suriname","Sao Tome and Principe","El Salvador",
- "Syrian Arab Republic","Swaziland","Turks and Caicos Islands","Chad",
- "French Southern Territories","Togo","Thailand","Tajikistan","Tokelau",
- "Turkmenistan","Tunisia","Tonga","Timor-Leste","Turkey","Trinidad and Tobago",
- "Tuvalu","Taiwan","Tanzania, United Republic of","Ukraine","Uganda",
- "United States Minor Outlying Islands","United States","Uruguay","Uzbekistan",
- "Holy See (Vatican City State)","Saint Vincent and the Grenadines",
- "Venezuela","Virgin Islands, British","Virgin Islands, U.S.","Vietnam",
- "Vanuatu","Wallis and Futuna","Samoa","Yemen","Mayotte","Serbia",
- "South Africa","Zambia","Montenegro","Zimbabwe","Anonymous Proxy",
- "Satellite Provider","Other","Aland Islands","Guernsey","Isle of Man","Jersey",
- "Saint Barthelemy","Saint Martin"};
-
-
- /* init the hashmap once at startup time */
- static {
- int i;
- if(countryCode.length!=countryName.length)
- throw new AssertionError("countryCode.length!=countryName.length");
-
- // distributed service only
- for (i = 0; i < countryCode.length ;i++){
- hashmapcountryCodetoindex.put(countryCode[i],Integer.valueOf(i));
- hashmapcountryNametoindex.put(countryName[i],Integer.valueOf(i));
- }
- };
-
-
- /**
- * Create a new distributed lookup service using the license key
- *
- * @param databaseFile String representation of the database file.
- * @param licenseKey license key provided by Maxmind to access distributed service
- */
- public LookupService(String databaseFile,String licenseKey) throws IOException {
- this(new File(databaseFile));
- this.licenseKey = licenseKey;
- dnsService = 1;
- }
- /**
- * Create a new distributed lookup service using the license key
- *
- * @param databaseFile the database file.
- * @param licenseKey license key provided by Maxmind to access distributed service
- */
- public LookupService(File databaseFile,String licenseKey) throws IOException {
- this(databaseFile);
- this.licenseKey = licenseKey;
- dnsService = 1;
- }
- /**
- * Create a new distributed lookup service using the license key
- *
- * @param options Resevered for future use
- * @param licenseKey license key provided by Maxmind to access distributed service
- */
- public LookupService(int options,String licenseKey) throws IOException {
- this.licenseKey = licenseKey;
- dnsService = 1;
- init();
- }
- /**
- * Create a new lookup service using the specified database file.
- *
- * @param databaseFile String representation of the database file.
- * @throws java.io.IOException if an error occured creating the lookup service
- * from the database file.
- */
- public LookupService(String databaseFile) throws IOException {
- this(new File(databaseFile));
- }
-
- /**
- * Create a new lookup service using the specified database file.
- *
- * @param databaseFile the database file.
- * @throws java.io.IOException if an error occured creating the lookup service
- * from the database file.
- */
- public LookupService(File databaseFile) throws IOException {
- this.databaseFile = databaseFile;
- this.file = new RandomAccessFile(databaseFile, "r");
- init();
- }
-
- /**
- * Create a new lookup service using the specified database file.
- *
- * @param databaseFile String representation of the database file.
- * @param options database flags to use when opening the database
- * GEOIP_STANDARD read database from disk
- * GEOIP_MEMORY_CACHE cache the database in RAM and read it from RAM
- * @throws java.io.IOException if an error occured creating the lookup service
- * from the database file.
- */
- public LookupService(String databaseFile, int options) throws IOException{
- this(new File(databaseFile),options);
- }
-
- /**
- * Create a new lookup service using the specified database file.
- *
- * @param databaseFile the database file.
- * @param options database flags to use when opening the database
- * GEOIP_STANDARD read database from disk
- * GEOIP_MEMORY_CACHE cache the database in RAM and read it from RAM
- * @throws java.io.IOException if an error occured creating the lookup service
- * from the database file.
- */
- public LookupService(File databaseFile, int options) throws IOException{
- this.databaseFile = databaseFile;
- this.file = new RandomAccessFile(databaseFile, "r");
- dboptions = options;
- init();
- }
- /**
- * Reads meta-data from the database file.
- *
- * @throws java.io.IOException if an error occurs reading from the database file.
- */
- private void init() throws IOException {
- int i, j;
- byte [] delim = new byte[3];
- byte [] buf = new byte[SEGMENT_RECORD_LENGTH];
-
- if (file == null) {
- return;
- }
- if ((dboptions & GEOIP_CHECK_CACHE) != 0) {
- mtime = databaseFile.lastModified();
- }
- file.seek(file.length() - 3);
- for (i = 0; i < STRUCTURE_INFO_MAX_SIZE; i++) {
- file.readFully(delim);
- if (delim[0] == -1 && delim[1] == -1 && delim[2] == -1) {
- databaseType = file.readByte();
- if (databaseType >= 106) {
- // Backward compatibility with databases from April 2003 and earlier
- databaseType -= 105;
- }
- // Determine the database type.
- if (databaseType == DatabaseInfo.REGION_EDITION_REV0) {
- databaseSegments = new int[1];
- databaseSegments[0] = STATE_BEGIN_REV0;
- recordLength = STANDARD_RECORD_LENGTH;
- }else if (databaseType == DatabaseInfo.REGION_EDITION_REV1){
- databaseSegments = new int[1];
- databaseSegments[0] = STATE_BEGIN_REV1;
- recordLength = STANDARD_RECORD_LENGTH;
- }
- else if (databaseType == DatabaseInfo.CITY_EDITION_REV0 ||
- databaseType == DatabaseInfo.CITY_EDITION_REV1 ||
- databaseType == DatabaseInfo.ORG_EDITION ||
- databaseType == DatabaseInfo.ISP_EDITION ||
- databaseType == DatabaseInfo.ASNUM_EDITION) {
- databaseSegments = new int[1];
- databaseSegments[0] = 0;
- if (databaseType == DatabaseInfo.CITY_EDITION_REV0 ||
- databaseType == DatabaseInfo.CITY_EDITION_REV1 ||
- databaseType == DatabaseInfo.ASNUM_EDITION) {
- recordLength = STANDARD_RECORD_LENGTH;
- }
- else {
- recordLength = ORG_RECORD_LENGTH;
- }
- file.readFully(buf);
- for (j = 0; j < SEGMENT_RECORD_LENGTH; j++) {
- databaseSegments[0] += (unsignedByteToInt(buf[j]) << (j * 8));
- }
- }
- break;
- }
- else {
- file.seek(file.getFilePointer() - 4);
- }
- }
- if ((databaseType == DatabaseInfo.COUNTRY_EDITION) ||
- (databaseType == DatabaseInfo.COUNTRY_EDITION_V6) ||
- (databaseType == DatabaseInfo.PROXY_EDITION) ||
- (databaseType == DatabaseInfo.NETSPEED_EDITION)) {
- databaseSegments = new int[1];
- databaseSegments[0] = COUNTRY_BEGIN;
- recordLength = STANDARD_RECORD_LENGTH;
- }
- if ((dboptions & GEOIP_MEMORY_CACHE) == 1) {
- int l = (int) file.length();
- dbbuffer = new byte[l];
- file.seek(0);
- file.readFully(dbbuffer,0,l);
- databaseInfo = this.getDatabaseInfo();
- file.close();
- }
- if ((dboptions & GEOIP_INDEX_CACHE) != 0) {
- int l = databaseSegments[0] * recordLength * 2;
- index_cache = new byte[l];
- if (index_cache != null){
- file.seek(0);
- file.readFully(index_cache,0,l);
- }
- } else {
- index_cache = null;
- }
- }
-
- /**
- * Closes the lookup service.
- */
- public void close() {
- try {
- if (file != null){
- file.close();
- }
- file = null;
- }
- catch (Exception e) { }
- }
-
- /**
- * Returns the country the IP address is in.
- *
- * @param ipAddress String version of an IPv6 address, i.e. "::127.0.0.1"
- * @return the country the IP address is from.
- */
- public Country getCountryV6(String ipAddress) {
- InetAddress addr;
- try {
- addr = Inet6Address.getByName(ipAddress);
- }
- catch (UnknownHostException e) {
- return UNKNOWN_COUNTRY;
- }
- return getCountryV6(addr);
- }
-
- /**
- * Returns the country the IP address is in.
- *
- * @param ipAddress String version of an IP address, i.e. "127.0.0.1"
- * @return the country the IP address is from.
- */
- public Country getCountry(String ipAddress) {
- InetAddress addr;
- try {
- addr = InetAddress.getByName(ipAddress);
- }
- catch (UnknownHostException e) {
- return UNKNOWN_COUNTRY;
- }
- return getCountry(bytesToLong(addr.getAddress()));
- }
-
- /**
- * Returns the country the IP address is in.
- *
- * @param ipAddress the IP address.
- * @return the country the IP address is from.
- */
- public synchronized Country getCountry(InetAddress ipAddress) {
- return getCountry(bytesToLong(ipAddress.getAddress()));
- }
-
- /**
- * Returns the country the IP address is in.
- *
- * @param addr the IP address as Inet6Address.
- * @return the country the IP address is from.
- */
- public Country getCountryV6(InetAddress addr) {
- if (file == null && (dboptions & GEOIP_MEMORY_CACHE) == 0) {
- throw new IllegalStateException("Database has been closed.");
- }
- int ret = seekCountryV6(addr) - COUNTRY_BEGIN;
- if (ret == 0) {
- return UNKNOWN_COUNTRY;
- }
- else {
- return new Country(countryCode[ret], countryName[ret]);
- }
- }
-
- /**
- * Returns the country the IP address is in.
- *
- * @param ipAddress the IP address in long format.
- * @return the country the IP address is from.
- */
- public Country getCountry(long ipAddress) {
- if (file == null && (dboptions & GEOIP_MEMORY_CACHE) == 0) {
- throw new IllegalStateException("Database has been closed.");
- }
- int ret = seekCountry(ipAddress) - COUNTRY_BEGIN;
- if (ret == 0) {
- return UNKNOWN_COUNTRY;
- }
- else {
- return new Country(countryCode[ret], countryName[ret]);
- }
- }
-
- public int getID(String ipAddress) {
- InetAddress addr;
- try {
- addr = InetAddress.getByName(ipAddress);
- }
- catch (UnknownHostException e) {
- return 0;
- }
- return getID(bytesToLong(addr.getAddress()));
- }
-
- public int getID(InetAddress ipAddress) {
- return getID(bytesToLong(ipAddress.getAddress()));
- }
-
- public synchronized int getID(long ipAddress) {
- if (file == null && (dboptions & GEOIP_MEMORY_CACHE) == 0) {
- throw new IllegalStateException("Database has been closed.");
- }
- int ret = seekCountry(ipAddress) - databaseSegments[0];
- return ret;
- }
-
- public int last_netmask() {
- return this.last_netmask;
- }
-
- public void netmask(int nm){
- this.last_netmask = nm;
- }
-
- /**
- * Returns information about the database.
- *
- * @return database info.
- */
- public synchronized DatabaseInfo getDatabaseInfo() {
- if (databaseInfo != null) {
- return databaseInfo;
- }
- try {
- _check_mtime();
- boolean hasStructureInfo = false;
- byte [] delim = new byte[3];
- // Advance to part of file where database info is stored.
- file.seek(file.length() - 3);
- for (int i=0; i env = new Hashtable();
- env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
- // TODO don't specify ws1, instead use ns servers for s.maxmind.com
- env.put("java.naming.provider.url","dns://ws1.maxmind.com/");
-
- DirContext ictx = new InitialDirContext(env);
- Attributes attrs = ictx.getAttributes(licenseKey + "." + ip + ".s.maxmind.com", new String[] {"txt"});
- //System.out.println(attrs.get("txt").get());
- String str = attrs.get("txt").get().toString();
- return str;
- }
- catch(NamingException e) {
- // TODO fix this to handle exceptions
- System.out.println("DNS error");
- return null;
- }
-
- }
-
- public Location getLocationwithdnsservice(String str) {
- Location record = new Location();
- String key;
- String value;
- StringTokenizer st = new StringTokenizer(str,";=\"");
- while (st.hasMoreTokens()) {
- key = st.nextToken();
- if (st.hasMoreTokens()) {
- value = st.nextToken();
- } else {
- value = "";}
- if (key.equals("co")) {
- Integer i = (Integer)hashmapcountryCodetoindex.get(value);
- record.countryCode = value;
- record.countryName = countryName[i.intValue()];
- }
- if (key.equals("ci")) {
- record.city = value;
- }
- if (key.equals("re")) {
- record.region = value;
- }
- if (key.equals("zi")) {
- record.postalCode = value;
- }
- // TODO, ISP and Organization
- //if (key.equals("or")) {
- //record.org = value;
- //}
- //if (key.equals("is")) {
- //record.isp = value;
- //}
- if (key.equals("la")) {
- try{
- record.latitude = Float.parseFloat(value);
- } catch(NumberFormatException e) {
- record.latitude = 0;
- }
- }
- if (key.equals("lo")) {
- try{
- record.longitude = Float.parseFloat(value);
- } catch(NumberFormatException e) {
- record.latitude = 0;
- }
- }
- // dm depreciated use me ( metro_code ) instead
- if (key.equals("dm") || key.equals("me")) {
- try{
- record.metro_code = record.dma_code = Integer.parseInt(value);
- } catch(NumberFormatException e) {
- record.metro_code = record.dma_code = 0;
- }
- }
- if (key.equals("ac")) {
- try{
- record.area_code = Integer.parseInt(value);
- } catch(NumberFormatException e) {
- record.area_code = 0;
- }
- }
- }
- return record;
- }
-
- public synchronized Region getRegion(String str) {
- InetAddress addr;
- try {
- addr = InetAddress.getByName(str);
- }
- catch (UnknownHostException e) {
- return null;
- }
-
- return getRegion(bytesToLong(addr.getAddress()));
- }
-
- public synchronized Region getRegion(long ipnum) {
- Region record = new Region();
- int seek_region = 0;
- if (databaseType == DatabaseInfo.REGION_EDITION_REV0) {
- seek_region = seekCountry(ipnum) - STATE_BEGIN_REV0;
- char ch[] = new char[2];
- if (seek_region >= 1000) {
- record.countryCode = "US";
- record.countryName = "United States";
- ch[0] = (char)(((seek_region - 1000)/26) + 65);
- ch[1] = (char)(((seek_region - 1000)%26) + 65);
- record.region = new String(ch);
- } else {
- record.countryCode = countryCode[seek_region];
- record.countryName = countryName[seek_region];
- record.region = "";
- }
- } else if (databaseType == DatabaseInfo.REGION_EDITION_REV1) {
- seek_region = seekCountry(ipnum) - STATE_BEGIN_REV1;
- char ch[] = new char[2];
- if (seek_region < US_OFFSET) {
- record.countryCode = "";
- record.countryName = "";
- record.region = "";
- } else if (seek_region < CANADA_OFFSET) {
- record.countryCode = "US";
- record.countryName = "United States";
- ch[0] = (char)(((seek_region - US_OFFSET)/26) + 65);
- ch[1] = (char)(((seek_region - US_OFFSET)%26) + 65);
- record.region = new String(ch);
- } else if (seek_region < WORLD_OFFSET) {
- record.countryCode = "CA";
- record.countryName = "Canada";
- ch[0] = (char)(((seek_region - CANADA_OFFSET)/26) + 65);
- ch[1] = (char)(((seek_region - CANADA_OFFSET)%26) + 65);
- record.region = new String(ch);
- } else {
- record.countryCode = countryCode[(seek_region - WORLD_OFFSET) / FIPS_RANGE];
- record.countryName = countryName[(seek_region - WORLD_OFFSET) / FIPS_RANGE];
- record.region = "";
- }
- }
- return record;
- }
-
- public synchronized Location getLocation(long ipnum) {
- int record_pointer;
- byte record_buf[] = new byte[FULL_RECORD_LENGTH];
- int record_buf_offset = 0;
- Location record = new Location();
- int str_length = 0;
- int j, seek_country;
- double latitude = 0, longitude = 0;
-
- try {
- seek_country = seekCountry(ipnum);
- if (seek_country == databaseSegments[0]) {
- return null;
- }
- record_pointer = seek_country + (2 * recordLength - 1) * databaseSegments[0];
-
- if ((dboptions & GEOIP_MEMORY_CACHE) == 1) {
- //read from memory
- System.arraycopy(dbbuffer, record_pointer, record_buf, 0, Math.min(dbbuffer.length - record_pointer, FULL_RECORD_LENGTH));
- } else {
- //read from disk
- file.seek(record_pointer);
- file.readFully(record_buf);
- }
-
- // get country
- record.countryCode = countryCode[unsignedByteToInt(record_buf[0])];
- record.countryName = countryName[unsignedByteToInt(record_buf[0])];
- record_buf_offset++;
-
- // get region
- while (record_buf[record_buf_offset + str_length] != '\0')
- str_length++;
- if (str_length > 0) {
- record.region = new String(record_buf, record_buf_offset, str_length);
- }
- record_buf_offset += str_length + 1;
- str_length = 0;
-
- // get city
- while (record_buf[record_buf_offset + str_length] != '\0')
- str_length++;
- if (str_length > 0) {
- record.city = new String(record_buf, record_buf_offset, str_length, "ISO-8859-1");
- }
- record_buf_offset += str_length + 1;
- str_length = 0;
-
- // get postal code
- while (record_buf[record_buf_offset + str_length] != '\0')
- str_length++;
- if (str_length > 0) {
- record.postalCode = new String(record_buf, record_buf_offset, str_length);
- }
- record_buf_offset += str_length + 1;
-
- // get latitude
- for (j = 0; j < 3; j++)
- latitude += (unsignedByteToInt(record_buf[record_buf_offset + j]) << (j * 8));
- record.latitude = (float) latitude/10000 - 180;
- record_buf_offset += 3;
-
- // get longitude
- for (j = 0; j < 3; j++)
- longitude += (unsignedByteToInt(record_buf[record_buf_offset + j]) << (j * 8));
- record.longitude = (float) longitude/10000 - 180;
-
- record.dma_code = record.metro_code = 0;
- record.area_code = 0;
- if (databaseType == DatabaseInfo.CITY_EDITION_REV1) {
- // get DMA code
- int metroarea_combo = 0;
- if (record.countryCode == "US") {
- record_buf_offset += 3;
- for (j = 0; j < 3; j++)
- metroarea_combo += (unsignedByteToInt(record_buf[record_buf_offset + j]) << (j * 8));
- record.metro_code = record.dma_code = metroarea_combo/1000;
- record.area_code = metroarea_combo % 1000;
- }
- }
- }
- catch (IOException e) {
- System.err.println("IO Exception while setting up segments");
- }
- return record;
- }
-
- public String getOrg(InetAddress addr) {
- return getOrg(bytesToLong(addr.getAddress()));
- }
-
- public String getOrg(String str) {
- InetAddress addr;
- try {
- addr = InetAddress.getByName(str);
- }
- catch (UnknownHostException e) {
- return null;
- }
- return getOrg(addr);
- }
-
- // GeoIP Organization and ISP Edition methods
- public synchronized String getOrg(long ipnum) {
- int seek_org;
- int record_pointer;
- int str_length = 0;
- byte [] buf = new byte[MAX_ORG_RECORD_LENGTH];
- String org_buf;
-
- try {
- seek_org = seekCountry(ipnum);
- if (seek_org == databaseSegments[0]) {
- return null;
- }
-
- record_pointer = seek_org + (2 * recordLength - 1) * databaseSegments[0];
- if ((dboptions & GEOIP_MEMORY_CACHE) == 1) {
- //read from memory
- System.arraycopy(dbbuffer, record_pointer, buf, 0, Math.min(dbbuffer.length - record_pointer, MAX_ORG_RECORD_LENGTH));
- } else {
- //read from disk
- file.seek(record_pointer);
- file.readFully(buf);
- }
- while (buf[str_length] != '\0') {
- str_length++;
- }
- org_buf = new String(buf, 0, str_length, "ISO-8859-1");
- return org_buf;
- }
- catch (IOException e) {
- System.out.println("IO Exception");
- return null;
- }
- }
-
- /**
- * Finds the country index value given an IPv6 address.
- *
- * @param addr the ip address to find in long format.
- * @return the country index.
- */
- private synchronized int seekCountryV6(InetAddress addr) {
- byte [] v6vec = addr.getAddress();
- byte [] buf = new byte[2 * MAX_RECORD_LENGTH];
- int [] x = new int[2];
- int offset = 0;
- _check_mtime();
- for (int depth = 127; depth >= 0; depth--) {
- if ((dboptions & GEOIP_MEMORY_CACHE) == 1) {
- //read from memory
- for (int i = 0;i < 2 * MAX_RECORD_LENGTH;i++) {
- buf[i] = dbbuffer[(2 * recordLength * offset)+i];
- }
- } else if ((dboptions & GEOIP_INDEX_CACHE) != 0) {
- //read from index cache
- for (int i = 0;i < 2 * MAX_RECORD_LENGTH;i++) {
- buf[i] = index_cache[(2 * recordLength * offset)+i];
- }
- } else {
- //read from disk
- try {
- file.seek(2 * recordLength * offset);
- file.readFully(buf);
- }
- catch (IOException e) {
- System.out.println("IO Exception");
- }
- }
- for (int i = 0; i<2; i++) {
- x[i] = 0;
- for (int j = 0; j> 3;
- int b_mask = 1 << ( bnum & 7 ^ 7 );
- if ((v6vec[idx] & b_mask) > 0) {
- if (x[1] >= databaseSegments[0]) {
- last_netmask = 128 - depth;
- return x[1];
- }
- offset = x[1];
- }
- else {
- if (x[0] >= databaseSegments[0]) {
- last_netmask = 128 - depth;
- return x[0];
- }
- offset = x[0];
- }
- }
-
- // shouldn't reach here
- System.err.println("Error seeking country while seeking " + addr.getHostAddress() );
- return 0;
- }
- /**
- * Finds the country index value given an IP address.
- *
- * @param ipAddress the ip address to find in long format.
- * @return the country index.
- */
- private synchronized int seekCountry(long ipAddress) {
- byte [] buf = new byte[2 * MAX_RECORD_LENGTH];
- int [] x = new int[2];
- int offset = 0;
- _check_mtime();
- for (int depth = 31; depth >= 0; depth--) {
- if ((dboptions & GEOIP_MEMORY_CACHE) == 1) {
- //read from memory
- for (int i = 0;i < 2 * MAX_RECORD_LENGTH;i++) {
- buf[i] = dbbuffer[(2 * recordLength * offset)+i];
- }
- } else if ((dboptions & GEOIP_INDEX_CACHE) != 0) {
- //read from index cache
- for (int i = 0;i < 2 * MAX_RECORD_LENGTH;i++) {
- buf[i] = index_cache[(2 * recordLength * offset)+i];
- }
- } else {
- //read from disk
- try {
- file.seek(2 * recordLength * offset);
- file.readFully(buf);
- }
- catch (IOException e) {
- System.out.println("IO Exception");
- }
- }
- for (int i = 0; i<2; i++) {
- x[i] = 0;
- for (int j = 0; j 0) {
- if (x[1] >= databaseSegments[0]) {
- last_netmask = 32 - depth;
- return x[1];
- }
- offset = x[1];
- }
- else {
- if (x[0] >= databaseSegments[0]) {
- last_netmask = 32 - depth;
- return x[0];
- }
- offset = x[0];
- }
- }
-
- // shouldn't reach here
- System.err.println("Error seeking country while seeking " + ipAddress);
- return 0;
- }
-
- /**
- * Returns the long version of an IP address given an InetAddress object.
- *
- * @param address the InetAddress.
- * @return the long form of the IP address.
- */
- private static long bytesToLong(byte [] address) {
- long ipnum = 0;
- for (int i = 0; i < 4; ++i) {
- long y = address[i];
- if (y < 0) {
- y+= 256;
- }
- ipnum += y << ((3-i)*8);
- }
- return ipnum;
- }
-
- private static int unsignedByteToInt(byte b) {
- return (int) b & 0xFF;
- }
-}
diff --git a/src/main/java/com/maxmind/geoip/Region.java b/src/main/java/com/maxmind/geoip/Region.java
deleted file mode 100644
index cba0594b..00000000
--- a/src/main/java/com/maxmind/geoip/Region.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.maxmind.geoip;
-
-public class Region{
- public String countryCode;
- public String countryName;
- public String region;
-}
-
diff --git a/src/main/java/com/maxmind/geoip/regionName.java b/src/main/java/com/maxmind/geoip/regionName.java
deleted file mode 100644
index da261ca1..00000000
--- a/src/main/java/com/maxmind/geoip/regionName.java
+++ /dev/null
@@ -1,13400 +0,0 @@
-package com.maxmind.geoip;
-// generated automatically from admin/generate_regionName.pl
-public class regionName {
-static public String regionNameByCode(String country_code,String region_code) {
- String name = null;
- int region_code2 = -1;
- if (region_code == null) { return null; }
- if (region_code.equals("")) { return null; }
-
- if ( ((region_code.charAt(0) >= 48 ) && ( region_code.charAt(0) < ( 48 + 10 )))
- && ((region_code.charAt(1) >= 48 ) && ( region_code.charAt(1) < ( 48 + 10 )))
- ){
- // only numbers, that shorten the large switch statements
- region_code2 = (region_code.charAt(0)- 48) * 10 + region_code.charAt(1) - 48;
- }
- else if ( ( ((region_code.charAt(0) >= 65) && (region_code.charAt(0) < (65 + 26)))
- || ((region_code.charAt(0) >= 48) && (region_code.charAt(0) < (48 + 10))))
- && ( ((region_code.charAt(1) >= 65) && (region_code.charAt(1) < (65 + 26)))
- || ((region_code.charAt(1) >= 48) && (region_code.charAt(1) < (48 + 10))))
- ) {
-
- region_code2 = (region_code.charAt(0) - 48) * (65 + 26 - 48) + region_code.charAt(1) - 48 + 100;
- }
-
- if (region_code2 == -1) {return null;}
- if (country_code.equals("CA") == true) {
- switch (region_code2) {
- case 849:
- name = "Alberta";
- break;
- case 893:
- name = "British Columbia";
- break;
- case 1365:
- name = "Manitoba";
- break;
- case 1408:
- name = "New Brunswick";
- break;
- case 1418:
- name = "Newfoundland";
- break;
- case 1425:
- name = "Nova Scotia";
- break;
- case 1427:
- name = "Nunavut";
- break;
- case 1463:
- name = "Ontario";
- break;
- case 1497:
- name = "Prince Edward Island";
- break;
- case 1538:
- name = "Quebec";
- break;
- case 1632:
- name = "Saskatchewan";
- break;
- case 1426:
- name = "Northwest Territories";
- break;
- case 1899:
- name = "Yukon Territory";
- break;
- }
- }
- if (country_code.equals("US") == true) {
- switch (region_code2) {
- case 848:
- name = "Armed Forces Americas";
- break;
- case 852:
- name = "Armed Forces Europe";
- break;
- case 858:
- name = "Alaska";
- break;
- case 859:
- name = "Alabama";
- break;
- case 863:
- name = "Armed Forces Pacific";
- break;
- case 865:
- name = "Arkansas";
- break;
- case 866:
- name = "American Samoa";
- break;
- case 873:
- name = "Arizona";
- break;
- case 934:
- name = "California";
- break;
- case 948:
- name = "Colorado";
- break;
- case 953:
- name = "Connecticut";
- break;
- case 979:
- name = "District of Columbia";
- break;
- case 981:
- name = "Delaware";
- break;
- case 1074:
- name = "Florida";
- break;
- case 1075:
- name = "Federated States of Micronesia";
- break;
- case 1106:
- name = "Georgia";
- break;
- case 1126:
- name = "Guam";
- break;
- case 1157:
- name = "Hawaii";
- break;
- case 1192:
- name = "Iowa";
- break;
- case 1195:
- name = "Idaho";
- break;
- case 1203:
- name = "Illinois";
- break;
- case 1205:
- name = "Indiana";
- break;
- case 1296:
- name = "Kansas";
- break;
- case 1302:
- name = "Kentucky";
- break;
- case 1321:
- name = "Louisiana";
- break;
- case 1364:
- name = "Massachusetts";
- break;
- case 1367:
- name = "Maryland";
- break;
- case 1368:
- name = "Maine";
- break;
- case 1371:
- name = "Marshall Islands";
- break;
- case 1372:
- name = "Michigan";
- break;
- case 1377:
- name = "Minnesota";
- break;
- case 1378:
- name = "Missouri";
- break;
- case 1379:
- name = "Northern Mariana Islands";
- break;
- case 1382:
- name = "Mississippi";
- break;
- case 1383:
- name = "Montana";
- break;
- case 1409:
- name = "North Carolina";
- break;
- case 1410:
- name = "North Dakota";
- break;
- case 1411:
- name = "Nebraska";
- break;
- case 1414:
- name = "New Hampshire";
- break;
- case 1416:
- name = "New Jersey";
- break;
- case 1419:
- name = "New Mexico";
- break;
- case 1428:
- name = "Nevada";
- break;
- case 1431:
- name = "New York";
- break;
- case 1457:
- name = "Ohio";
- break;
- case 1460:
- name = "Oklahoma";
- break;
- case 1467:
- name = "Oregon";
- break;
- case 1493:
- name = "Pennsylvania";
- break;
- case 1510:
- name = "Puerto Rico";
- break;
- case 1515:
- name = "Palau";
- break;
- case 1587:
- name = "Rhode Island";
- break;
- case 1624:
- name = "South Carolina";
- break;
- case 1625:
- name = "South Dakota";
- break;
- case 1678:
- name = "Tennessee";
- break;
- case 1688:
- name = "Texas";
- break;
- case 1727:
- name = "Utah";
- break;
- case 1751:
- name = "Virginia";
- break;
- case 1759:
- name = "Virgin Islands";
- break;
- case 1770:
- name = "Vermont";
- break;
- case 1794:
- name = "Washington";
- break;
- case 1815:
- name = "West Virginia";
- break;
- case 1802:
- name = "Wisconsin";
- break;
- case 1818:
- name = "Wyoming";
- break;
- }
- }
- if (country_code.equals("AD") == true) {
- switch (region_code2) {
- case 2:
- name = "Canillo";
- break;
- case 3:
- name = "Encamp";
- break;
- case 4:
- name = "La Massana";
- break;
- case 5:
- name = "Ordino";
- break;
- case 6:
- name = "Sant Julia de Loria";
- break;
- case 7:
- name = "Andorra la Vella";
- break;
- case 8:
- name = "Escaldes-Engordany";
- break;
- }
- }
- if (country_code.equals("AE") == true) {
- switch (region_code2) {
- case 1:
- name = "Abu Dhabi";
- break;
- case 2:
- name = "Ajman";
- break;
- case 3:
- name = "Dubai";
- break;
- case 4:
- name = "Fujairah";
- break;
- case 5:
- name = "Ras Al Khaimah";
- break;
- case 6:
- name = "Sharjah";
- break;
- case 7:
- name = "Umm Al Quwain";
- break;
- }
- }
- if (country_code.equals("AF") == true) {
- switch (region_code2) {
- case 1:
- name = "Badakhshan";
- break;
- case 2:
- name = "Badghis";
- break;
- case 3:
- name = "Baghlan";
- break;
- case 5:
- name = "Bamian";
- break;
- case 6:
- name = "Farah";
- break;
- case 7:
- name = "Faryab";
- break;
- case 8:
- name = "Ghazni";
- break;
- case 9:
- name = "Ghowr";
- break;
- case 10:
- name = "Helmand";
- break;
- case 11:
- name = "Herat";
- break;
- case 13:
- name = "Kabol";
- break;
- case 14:
- name = "Kapisa";
- break;
- case 15:
- name = "Konar";
- break;
- case 16:
- name = "Laghman";
- break;
- case 17:
- name = "Lowgar";
- break;
- case 18:
- name = "Nangarhar";
- break;
- case 19:
- name = "Nimruz";
- break;
- case 21:
- name = "Paktia";
- break;
- case 22:
- name = "Parvan";
- break;
- case 23:
- name = "Kandahar";
- break;
- case 24:
- name = "Kondoz";
- break;
- case 26:
- name = "Takhar";
- break;
- case 27:
- name = "Vardak";
- break;
- case 28:
- name = "Zabol";
- break;
- case 29:
- name = "Paktika";
- break;
- case 30:
- name = "Balkh";
- break;
- case 31:
- name = "Jowzjan";
- break;
- case 32:
- name = "Samangan";
- break;
- case 33:
- name = "Sar-e Pol";
- break;
- case 34:
- name = "Konar";
- break;
- case 35:
- name = "Laghman";
- break;
- case 36:
- name = "Paktia";
- break;
- case 37:
- name = "Khowst";
- break;
- case 38:
- name = "Nurestan";
- break;
- case 39:
- name = "Oruzgan";
- break;
- case 40:
- name = "Parvan";
- break;
- case 41:
- name = "Daykondi";
- break;
- case 42:
- name = "Panjshir";
- break;
- }
- }
- if (country_code.equals("AG") == true) {
- switch (region_code2) {
- case 1:
- name = "Barbuda";
- break;
- case 3:
- name = "Saint George";
- break;
- case 4:
- name = "Saint John";
- break;
- case 5:
- name = "Saint Mary";
- break;
- case 6:
- name = "Saint Paul";
- break;
- case 7:
- name = "Saint Peter";
- break;
- case 8:
- name = "Saint Philip";
- break;
- }
- }
- if (country_code.equals("AL") == true) {
- switch (region_code2) {
- case 40:
- name = "Berat";
- break;
- case 41:
- name = "Diber";
- break;
- case 42:
- name = "Durres";
- break;
- case 43:
- name = "Elbasan";
- break;
- case 44:
- name = "Fier";
- break;
- case 45:
- name = "Gjirokaster";
- break;
- case 46:
- name = "Korce";
- break;
- case 47:
- name = "Kukes";
- break;
- case 48:
- name = "Lezhe";
- break;
- case 49:
- name = "Shkoder";
- break;
- case 50:
- name = "Tirane";
- break;
- case 51:
- name = "Vlore";
- break;
- }
- }
- if (country_code.equals("AM") == true) {
- switch (region_code2) {
- case 1:
- name = "Aragatsotn";
- break;
- case 2:
- name = "Ararat";
- break;
- case 3:
- name = "Armavir";
- break;
- case 4:
- name = "Geghark'unik'";
- break;
- case 5:
- name = "Kotayk'";
- break;
- case 6:
- name = "Lorri";
- break;
- case 7:
- name = "Shirak";
- break;
- case 8:
- name = "Syunik'";
- break;
- case 9:
- name = "Tavush";
- break;
- case 10:
- name = "Vayots' Dzor";
- break;
- case 11:
- name = "Yerevan";
- break;
- }
- }
- if (country_code.equals("AO") == true) {
- switch (region_code2) {
- case 1:
- name = "Benguela";
- break;
- case 2:
- name = "Bie";
- break;
- case 3:
- name = "Cabinda";
- break;
- case 4:
- name = "Cuando Cubango";
- break;
- case 5:
- name = "Cuanza Norte";
- break;
- case 6:
- name = "Cuanza Sul";
- break;
- case 7:
- name = "Cunene";
- break;
- case 8:
- name = "Huambo";
- break;
- case 9:
- name = "Huila";
- break;
- case 10:
- name = "Luanda";
- break;
- case 12:
- name = "Malanje";
- break;
- case 13:
- name = "Namibe";
- break;
- case 14:
- name = "Moxico";
- break;
- case 15:
- name = "Uige";
- break;
- case 16:
- name = "Zaire";
- break;
- case 17:
- name = "Lunda Norte";
- break;
- case 18:
- name = "Lunda Sul";
- break;
- case 19:
- name = "Bengo";
- break;
- case 20:
- name = "Luanda";
- break;
- }
- }
- if (country_code.equals("AR") == true) {
- switch (region_code2) {
- case 1:
- name = "Buenos Aires";
- break;
- case 2:
- name = "Catamarca";
- break;
- case 3:
- name = "Chaco";
- break;
- case 4:
- name = "Chubut";
- break;
- case 5:
- name = "Cordoba";
- break;
- case 6:
- name = "Corrientes";
- break;
- case 7:
- name = "Distrito Federal";
- break;
- case 8:
- name = "Entre Rios";
- break;
- case 9:
- name = "Formosa";
- break;
- case 10:
- name = "Jujuy";
- break;
- case 11:
- name = "La Pampa";
- break;
- case 12:
- name = "La Rioja";
- break;
- case 13:
- name = "Mendoza";
- break;
- case 14:
- name = "Misiones";
- break;
- case 15:
- name = "Neuquen";
- break;
- case 16:
- name = "Rio Negro";
- break;
- case 17:
- name = "Salta";
- break;
- case 18:
- name = "San Juan";
- break;
- case 19:
- name = "San Luis";
- break;
- case 20:
- name = "Santa Cruz";
- break;
- case 21:
- name = "Santa Fe";
- break;
- case 22:
- name = "Santiago del Estero";
- break;
- case 23:
- name = "Tierra del Fuego";
- break;
- case 24:
- name = "Tucuman";
- break;
- }
- }
- if (country_code.equals("AT") == true) {
- switch (region_code2) {
- case 1:
- name = "Burgenland";
- break;
- case 2:
- name = "Karnten";
- break;
- case 3:
- name = "Niederosterreich";
- break;
- case 4:
- name = "Oberosterreich";
- break;
- case 5:
- name = "Salzburg";
- break;
- case 6:
- name = "Steiermark";
- break;
- case 7:
- name = "Tirol";
- break;
- case 8:
- name = "Vorarlberg";
- break;
- case 9:
- name = "Wien";
- break;
- }
- }
- if (country_code.equals("AU") == true) {
- switch (region_code2) {
- case 1:
- name = "Australian Capital Territory";
- break;
- case 2:
- name = "New South Wales";
- break;
- case 3:
- name = "Northern Territory";
- break;
- case 4:
- name = "Queensland";
- break;
- case 5:
- name = "South Australia";
- break;
- case 6:
- name = "Tasmania";
- break;
- case 7:
- name = "Victoria";
- break;
- case 8:
- name = "Western Australia";
- break;
- }
- }
- if (country_code.equals("AZ") == true) {
- switch (region_code2) {
- case 1:
- name = "Abseron";
- break;
- case 2:
- name = "Agcabadi";
- break;
- case 3:
- name = "Agdam";
- break;
- case 4:
- name = "Agdas";
- break;
- case 5:
- name = "Agstafa";
- break;
- case 6:
- name = "Agsu";
- break;
- case 7:
- name = "Ali Bayramli";
- break;
- case 8:
- name = "Astara";
- break;
- case 9:
- name = "Baki";
- break;
- case 10:
- name = "Balakan";
- break;
- case 11:
- name = "Barda";
- break;
- case 12:
- name = "Beylaqan";
- break;
- case 13:
- name = "Bilasuvar";
- break;
- case 14:
- name = "Cabrayil";
- break;
- case 15:
- name = "Calilabad";
- break;
- case 16:
- name = "Daskasan";
- break;
- case 17:
- name = "Davaci";
- break;
- case 18:
- name = "Fuzuli";
- break;
- case 19:
- name = "Gadabay";
- break;
- case 20:
- name = "Ganca";
- break;
- case 21:
- name = "Goranboy";
- break;
- case 22:
- name = "Goycay";
- break;
- case 23:
- name = "Haciqabul";
- break;
- case 24:
- name = "Imisli";
- break;
- case 25:
- name = "Ismayilli";
- break;
- case 26:
- name = "Kalbacar";
- break;
- case 27:
- name = "Kurdamir";
- break;
- case 28:
- name = "Lacin";
- break;
- case 29:
- name = "Lankaran";
- break;
- case 30:
- name = "Lankaran";
- break;
- case 31:
- name = "Lerik";
- break;
- case 32:
- name = "Masalli";
- break;
- case 33:
- name = "Mingacevir";
- break;
- case 34:
- name = "Naftalan";
- break;
- case 35:
- name = "Naxcivan";
- break;
- case 36:
- name = "Neftcala";
- break;
- case 37:
- name = "Oguz";
- break;
- case 38:
- name = "Qabala";
- break;
- case 39:
- name = "Qax";
- break;
- case 40:
- name = "Qazax";
- break;
- case 41:
- name = "Qobustan";
- break;
- case 42:
- name = "Quba";
- break;
- case 43:
- name = "Qubadli";
- break;
- case 44:
- name = "Qusar";
- break;
- case 45:
- name = "Saatli";
- break;
- case 46:
- name = "Sabirabad";
- break;
- case 47:
- name = "Saki";
- break;
- case 48:
- name = "Saki";
- break;
- case 49:
- name = "Salyan";
- break;
- case 50:
- name = "Samaxi";
- break;
- case 51:
- name = "Samkir";
- break;
- case 52:
- name = "Samux";
- break;
- case 53:
- name = "Siyazan";
- break;
- case 54:
- name = "Sumqayit";
- break;
- case 55:
- name = "Susa";
- break;
- case 56:
- name = "Susa";
- break;
- case 57:
- name = "Tartar";
- break;
- case 58:
- name = "Tovuz";
- break;
- case 59:
- name = "Ucar";
- break;
- case 60:
- name = "Xacmaz";
- break;
- case 61:
- name = "Xankandi";
- break;
- case 62:
- name = "Xanlar";
- break;
- case 63:
- name = "Xizi";
- break;
- case 64:
- name = "Xocali";
- break;
- case 65:
- name = "Xocavand";
- break;
- case 66:
- name = "Yardimli";
- break;
- case 67:
- name = "Yevlax";
- break;
- case 68:
- name = "Yevlax";
- break;
- case 69:
- name = "Zangilan";
- break;
- case 70:
- name = "Zaqatala";
- break;
- case 71:
- name = "Zardab";
- break;
- }
- }
- if (country_code.equals("BA") == true) {
- switch (region_code2) {
- case 1:
- name = "Federation of Bosnia and Herzegovina";
- break;
- case 2:
- name = "Republika Srpska";
- break;
- }
- }
- if (country_code.equals("BB") == true) {
- switch (region_code2) {
- case 1:
- name = "Christ Church";
- break;
- case 2:
- name = "Saint Andrew";
- break;
- case 3:
- name = "Saint George";
- break;
- case 4:
- name = "Saint James";
- break;
- case 5:
- name = "Saint John";
- break;
- case 6:
- name = "Saint Joseph";
- break;
- case 7:
- name = "Saint Lucy";
- break;
- case 8:
- name = "Saint Michael";
- break;
- case 9:
- name = "Saint Peter";
- break;
- case 10:
- name = "Saint Philip";
- break;
- case 11:
- name = "Saint Thomas";
- break;
- }
- }
- if (country_code.equals("BD") == true) {
- switch (region_code2) {
- case 1:
- name = "Barisal";
- break;
- case 4:
- name = "Bandarban";
- break;
- case 5:
- name = "Comilla";
- break;
- case 12:
- name = "Mymensingh";
- break;
- case 13:
- name = "Noakhali";
- break;
- case 15:
- name = "Patuakhali";
- break;
- case 22:
- name = "Bagerhat";
- break;
- case 23:
- name = "Bhola";
- break;
- case 24:
- name = "Bogra";
- break;
- case 25:
- name = "Barguna";
- break;
- case 26:
- name = "Brahmanbaria";
- break;
- case 27:
- name = "Chandpur";
- break;
- case 28:
- name = "Chapai Nawabganj";
- break;
- case 29:
- name = "Chattagram";
- break;
- case 30:
- name = "Chuadanga";
- break;
- case 31:
- name = "Cox's Bazar";
- break;
- case 32:
- name = "Dhaka";
- break;
- case 33:
- name = "Dinajpur";
- break;
- case 34:
- name = "Faridpur";
- break;
- case 35:
- name = "Feni";
- break;
- case 36:
- name = "Gaibandha";
- break;
- case 37:
- name = "Gazipur";
- break;
- case 38:
- name = "Gopalganj";
- break;
- case 39:
- name = "Habiganj";
- break;
- case 40:
- name = "Jaipurhat";
- break;
- case 41:
- name = "Jamalpur";
- break;
- case 42:
- name = "Jessore";
- break;
- case 43:
- name = "Jhalakati";
- break;
- case 44:
- name = "Jhenaidah";
- break;
- case 45:
- name = "Khagrachari";
- break;
- case 46:
- name = "Khulna";
- break;
- case 47:
- name = "Kishorganj";
- break;
- case 48:
- name = "Kurigram";
- break;
- case 49:
- name = "Kushtia";
- break;
- case 50:
- name = "Laksmipur";
- break;
- case 51:
- name = "Lalmonirhat";
- break;
- case 52:
- name = "Madaripur";
- break;
- case 53:
- name = "Magura";
- break;
- case 54:
- name = "Manikganj";
- break;
- case 55:
- name = "Meherpur";
- break;
- case 56:
- name = "Moulavibazar";
- break;
- case 57:
- name = "Munshiganj";
- break;
- case 58:
- name = "Naogaon";
- break;
- case 59:
- name = "Narail";
- break;
- case 60:
- name = "Narayanganj";
- break;
- case 61:
- name = "Narsingdi";
- break;
- case 62:
- name = "Nator";
- break;
- case 63:
- name = "Netrakona";
- break;
- case 64:
- name = "Nilphamari";
- break;
- case 65:
- name = "Pabna";
- break;
- case 66:
- name = "Panchagar";
- break;
- case 67:
- name = "Parbattya Chattagram";
- break;
- case 68:
- name = "Pirojpur";
- break;
- case 69:
- name = "Rajbari";
- break;
- case 70:
- name = "Rajshahi";
- break;
- case 71:
- name = "Rangpur";
- break;
- case 72:
- name = "Satkhira";
- break;
- case 73:
- name = "Shariyatpur";
- break;
- case 74:
- name = "Sherpur";
- break;
- case 75:
- name = "Sirajganj";
- break;
- case 76:
- name = "Sunamganj";
- break;
- case 77:
- name = "Sylhet";
- break;
- case 78:
- name = "Tangail";
- break;
- case 79:
- name = "Thakurgaon";
- break;
- case 81:
- name = "Dhaka";
- break;
- case 82:
- name = "Khulna";
- break;
- case 83:
- name = "Rajshahi";
- break;
- case 84:
- name = "Chittagong";
- break;
- case 85:
- name = "Barisal";
- break;
- case 86:
- name = "Sylhet";
- break;
- }
- }
- if (country_code.equals("BE") == true) {
- switch (region_code2) {
- case 1:
- name = "Antwerpen";
- break;
- case 2:
- name = "Brabant";
- break;
- case 3:
- name = "Hainaut";
- break;
- case 4:
- name = "Liege";
- break;
- case 5:
- name = "Limburg";
- break;
- case 6:
- name = "Luxembourg";
- break;
- case 7:
- name = "Namur";
- break;
- case 8:
- name = "Oost-Vlaanderen";
- break;
- case 9:
- name = "West-Vlaanderen";
- break;
- case 10:
- name = "Brabant Wallon";
- break;
- case 11:
- name = "Brussels Hoofdstedelijk Gewest";
- break;
- case 12:
- name = "Vlaams-Brabant";
- break;
- }
- }
- if (country_code.equals("BF") == true) {
- switch (region_code2) {
- case 15:
- name = "Bam";
- break;
- case 19:
- name = "Boulkiemde";
- break;
- case 20:
- name = "Ganzourgou";
- break;
- case 21:
- name = "Gnagna";
- break;
- case 28:
- name = "Kouritenga";
- break;
- case 33:
- name = "Oudalan";
- break;
- case 34:
- name = "Passore";
- break;
- case 36:
- name = "Sanguie";
- break;
- case 40:
- name = "Soum";
- break;
- case 42:
- name = "Tapoa";
- break;
- case 44:
- name = "Zoundweogo";
- break;
- case 45:
- name = "Bale";
- break;
- case 46:
- name = "Banwa";
- break;
- case 47:
- name = "Bazega";
- break;
- case 48:
- name = "Bougouriba";
- break;
- case 49:
- name = "Boulgou";
- break;
- case 50:
- name = "Gourma";
- break;
- case 51:
- name = "Houet";
- break;
- case 52:
- name = "Ioba";
- break;
- case 53:
- name = "Kadiogo";
- break;
- case 54:
- name = "Kenedougou";
- break;
- case 55:
- name = "Komoe";
- break;
- case 56:
- name = "Komondjari";
- break;
- case 57:
- name = "Kompienga";
- break;
- case 58:
- name = "Kossi";
- break;
- case 59:
- name = "Koulpelogo";
- break;
- case 60:
- name = "Kourweogo";
- break;
- case 61:
- name = "Leraba";
- break;
- case 62:
- name = "Loroum";
- break;
- case 63:
- name = "Mouhoun";
- break;
- case 64:
- name = "Namentenga";
- break;
- case 65:
- name = "Naouri";
- break;
- case 66:
- name = "Nayala";
- break;
- case 67:
- name = "Noumbiel";
- break;
- case 68:
- name = "Oubritenga";
- break;
- case 69:
- name = "Poni";
- break;
- case 70:
- name = "Sanmatenga";
- break;
- case 71:
- name = "Seno";
- break;
- case 72:
- name = "Sissili";
- break;
- case 73:
- name = "Sourou";
- break;
- case 74:
- name = "Tuy";
- break;
- case 75:
- name = "Yagha";
- break;
- case 76:
- name = "Yatenga";
- break;
- case 77:
- name = "Ziro";
- break;
- case 78:
- name = "Zondoma";
- break;
- }
- }
- if (country_code.equals("BG") == true) {
- switch (region_code2) {
- case 33:
- name = "Mikhaylovgrad";
- break;
- case 38:
- name = "Blagoevgrad";
- break;
- case 39:
- name = "Burgas";
- break;
- case 40:
- name = "Dobrich";
- break;
- case 41:
- name = "Gabrovo";
- break;
- case 42:
- name = "Grad Sofiya";
- break;
- case 43:
- name = "Khaskovo";
- break;
- case 44:
- name = "Kurdzhali";
- break;
- case 45:
- name = "Kyustendil";
- break;
- case 46:
- name = "Lovech";
- break;
- case 47:
- name = "Montana";
- break;
- case 48:
- name = "Pazardzhik";
- break;
- case 49:
- name = "Pernik";
- break;
- case 50:
- name = "Pleven";
- break;
- case 51:
- name = "Plovdiv";
- break;
- case 52:
- name = "Razgrad";
- break;
- case 53:
- name = "Ruse";
- break;
- case 54:
- name = "Shumen";
- break;
- case 55:
- name = "Silistra";
- break;
- case 56:
- name = "Sliven";
- break;
- case 57:
- name = "Smolyan";
- break;
- case 58:
- name = "Sofiya";
- break;
- case 59:
- name = "Stara Zagora";
- break;
- case 60:
- name = "Turgovishte";
- break;
- case 61:
- name = "Varna";
- break;
- case 62:
- name = "Veliko Turnovo";
- break;
- case 63:
- name = "Vidin";
- break;
- case 64:
- name = "Vratsa";
- break;
- case 65:
- name = "Yambol";
- break;
- }
- }
- if (country_code.equals("BH") == true) {
- switch (region_code2) {
- case 1:
- name = "Al Hadd";
- break;
- case 2:
- name = "Al Manamah";
- break;
- case 3:
- name = "Al Muharraq";
- break;
- case 5:
- name = "Jidd Hafs";
- break;
- case 6:
- name = "Sitrah";
- break;
- case 7:
- name = "Ar Rifa' wa al Mintaqah al Janubiyah";
- break;
- case 8:
- name = "Al Mintaqah al Gharbiyah";
- break;
- case 9:
- name = "Mintaqat Juzur Hawar";
- break;
- case 10:
- name = "Al Mintaqah ash Shamaliyah";
- break;
- case 11:
- name = "Al Mintaqah al Wusta";
- break;
- case 12:
- name = "Madinat";
- break;
- case 13:
- name = "Ar Rifa";
- break;
- case 14:
- name = "Madinat Hamad";
- break;
- case 15:
- name = "Al Muharraq";
- break;
- case 16:
- name = "Al Asimah";
- break;
- case 17:
- name = "Al Janubiyah";
- break;
- case 18:
- name = "Ash Shamaliyah";
- break;
- case 19:
- name = "Al Wusta";
- break;
- }
- }
- if (country_code.equals("BI") == true) {
- switch (region_code2) {
- case 2:
- name = "Bujumbura";
- break;
- case 9:
- name = "Bubanza";
- break;
- case 10:
- name = "Bururi";
- break;
- case 11:
- name = "Cankuzo";
- break;
- case 12:
- name = "Cibitoke";
- break;
- case 13:
- name = "Gitega";
- break;
- case 14:
- name = "Karuzi";
- break;
- case 15:
- name = "Kayanza";
- break;
- case 16:
- name = "Kirundo";
- break;
- case 17:
- name = "Makamba";
- break;
- case 18:
- name = "Muyinga";
- break;
- case 19:
- name = "Ngozi";
- break;
- case 20:
- name = "Rutana";
- break;
- case 21:
- name = "Ruyigi";
- break;
- case 22:
- name = "Muramvya";
- break;
- case 23:
- name = "Mwaro";
- break;
- }
- }
- if (country_code.equals("BJ") == true) {
- switch (region_code2) {
- case 1:
- name = "Atakora";
- break;
- case 2:
- name = "Atlantique";
- break;
- case 3:
- name = "Borgou";
- break;
- case 4:
- name = "Mono";
- break;
- case 5:
- name = "Oueme";
- break;
- case 6:
- name = "Zou";
- break;
- case 7:
- name = "Alibori";
- break;
- case 8:
- name = "Atakora";
- break;
- case 9:
- name = "Atlanyique";
- break;
- case 10:
- name = "Borgou";
- break;
- case 11:
- name = "Collines";
- break;
- case 12:
- name = "Kouffo";
- break;
- case 13:
- name = "Donga";
- break;
- case 14:
- name = "Littoral";
- break;
- case 15:
- name = "Mono";
- break;
- case 16:
- name = "Oueme";
- break;
- case 17:
- name = "Plateau";
- break;
- case 18:
- name = "Zou";
- break;
- }
- }
- if (country_code.equals("BM") == true) {
- switch (region_code2) {
- case 1:
- name = "Devonshire";
- break;
- case 2:
- name = "Hamilton";
- break;
- case 3:
- name = "Hamilton";
- break;
- case 4:
- name = "Paget";
- break;
- case 5:
- name = "Pembroke";
- break;
- case 6:
- name = "Saint George";
- break;
- case 7:
- name = "Saint George's";
- break;
- case 8:
- name = "Sandys";
- break;
- case 9:
- name = "Smiths";
- break;
- case 10:
- name = "Southampton";
- break;
- case 11:
- name = "Warwick";
- break;
- }
- }
- if (country_code.equals("BN") == true) {
- switch (region_code2) {
- case 7:
- name = "Alibori";
- break;
- case 8:
- name = "Belait";
- break;
- case 9:
- name = "Brunei and Muara";
- break;
- case 10:
- name = "Temburong";
- break;
- case 11:
- name = "Collines";
- break;
- case 12:
- name = "Kouffo";
- break;
- case 13:
- name = "Donga";
- break;
- case 14:
- name = "Littoral";
- break;
- case 15:
- name = "Tutong";
- break;
- case 16:
- name = "Oueme";
- break;
- case 17:
- name = "Plateau";
- break;
- case 18:
- name = "Zou";
- break;
- }
- }
- if (country_code.equals("BO") == true) {
- switch (region_code2) {
- case 1:
- name = "Chuquisaca";
- break;
- case 2:
- name = "Cochabamba";
- break;
- case 3:
- name = "El Beni";
- break;
- case 4:
- name = "La Paz";
- break;
- case 5:
- name = "Oruro";
- break;
- case 6:
- name = "Pando";
- break;
- case 7:
- name = "Potosi";
- break;
- case 8:
- name = "Santa Cruz";
- break;
- case 9:
- name = "Tarija";
- break;
- }
- }
- if (country_code.equals("BR") == true) {
- switch (region_code2) {
- case 1:
- name = "Acre";
- break;
- case 2:
- name = "Alagoas";
- break;
- case 3:
- name = "Amapa";
- break;
- case 4:
- name = "Amazonas";
- break;
- case 5:
- name = "Bahia";
- break;
- case 6:
- name = "Ceara";
- break;
- case 7:
- name = "Distrito Federal";
- break;
- case 8:
- name = "Espirito Santo";
- break;
- case 11:
- name = "Mato Grosso do Sul";
- break;
- case 13:
- name = "Maranhao";
- break;
- case 14:
- name = "Mato Grosso";
- break;
- case 15:
- name = "Minas Gerais";
- break;
- case 16:
- name = "Para";
- break;
- case 17:
- name = "Paraiba";
- break;
- case 18:
- name = "Parana";
- break;
- case 20:
- name = "Piaui";
- break;
- case 21:
- name = "Rio de Janeiro";
- break;
- case 22:
- name = "Rio Grande do Norte";
- break;
- case 23:
- name = "Rio Grande do Sul";
- break;
- case 24:
- name = "Rondonia";
- break;
- case 25:
- name = "Roraima";
- break;
- case 26:
- name = "Santa Catarina";
- break;
- case 27:
- name = "Sao Paulo";
- break;
- case 28:
- name = "Sergipe";
- break;
- case 29:
- name = "Goias";
- break;
- case 30:
- name = "Pernambuco";
- break;
- case 31:
- name = "Tocantins";
- break;
- }
- }
- if (country_code.equals("BS") == true) {
- switch (region_code2) {
- case 5:
- name = "Bimini";
- break;
- case 6:
- name = "Cat Island";
- break;
- case 10:
- name = "Exuma";
- break;
- case 13:
- name = "Inagua";
- break;
- case 15:
- name = "Long Island";
- break;
- case 16:
- name = "Mayaguana";
- break;
- case 18:
- name = "Ragged Island";
- break;
- case 22:
- name = "Harbour Island";
- break;
- case 23:
- name = "New Providence";
- break;
- case 24:
- name = "Acklins and Crooked Islands";
- break;
- case 25:
- name = "Freeport";
- break;
- case 26:
- name = "Fresh Creek";
- break;
- case 27:
- name = "Governor's Harbour";
- break;
- case 28:
- name = "Green Turtle Cay";
- break;
- case 29:
- name = "High Rock";
- break;
- case 30:
- name = "Kemps Bay";
- break;
- case 31:
- name = "Marsh Harbour";
- break;
- case 32:
- name = "Nichollstown and Berry Islands";
- break;
- case 33:
- name = "Rock Sound";
- break;
- case 34:
- name = "Sandy Point";
- break;
- case 35:
- name = "San Salvador and Rum Cay";
- break;
- }
- }
- if (country_code.equals("BT") == true) {
- switch (region_code2) {
- case 5:
- name = "Bumthang";
- break;
- case 6:
- name = "Chhukha";
- break;
- case 7:
- name = "Chirang";
- break;
- case 8:
- name = "Daga";
- break;
- case 9:
- name = "Geylegphug";
- break;
- case 10:
- name = "Ha";
- break;
- case 11:
- name = "Lhuntshi";
- break;
- case 12:
- name = "Mongar";
- break;
- case 13:
- name = "Paro";
- break;
- case 14:
- name = "Pemagatsel";
- break;
- case 15:
- name = "Punakha";
- break;
- case 16:
- name = "Samchi";
- break;
- case 17:
- name = "Samdrup";
- break;
- case 18:
- name = "Shemgang";
- break;
- case 19:
- name = "Tashigang";
- break;
- case 20:
- name = "Thimphu";
- break;
- case 21:
- name = "Tongsa";
- break;
- case 22:
- name = "Wangdi Phodrang";
- break;
- }
- }
- if (country_code.equals("BW") == true) {
- switch (region_code2) {
- case 1:
- name = "Central";
- break;
- case 3:
- name = "Ghanzi";
- break;
- case 4:
- name = "Kgalagadi";
- break;
- case 5:
- name = "Kgatleng";
- break;
- case 6:
- name = "Kweneng";
- break;
- case 8:
- name = "North-East";
- break;
- case 9:
- name = "South-East";
- break;
- case 10:
- name = "Southern";
- break;
- case 11:
- name = "North-West";
- break;
- }
- }
- if (country_code.equals("BY") == true) {
- switch (region_code2) {
- case 1:
- name = "Brestskaya Voblasts'";
- break;
- case 2:
- name = "Homyel'skaya Voblasts'";
- break;
- case 3:
- name = "Hrodzyenskaya Voblasts'";
- break;
- case 4:
- name = "Minsk";
- break;
- case 5:
- name = "Minskaya Voblasts'";
- break;
- case 6:
- name = "Mahilyowskaya Voblasts'";
- break;
- case 7:
- name = "Vitsyebskaya Voblasts'";
- break;
- }
- }
- if (country_code.equals("BZ") == true) {
- switch (region_code2) {
- case 1:
- name = "Belize";
- break;
- case 2:
- name = "Cayo";
- break;
- case 3:
- name = "Corozal";
- break;
- case 4:
- name = "Orange Walk";
- break;
- case 5:
- name = "Stann Creek";
- break;
- case 6:
- name = "Toledo";
- break;
- }
- }
- if (country_code.equals("CD") == true) {
- switch (region_code2) {
- case 1:
- name = "Bandundu";
- break;
- case 2:
- name = "Equateur";
- break;
- case 4:
- name = "Kasai-Oriental";
- break;
- case 5:
- name = "Katanga";
- break;
- case 6:
- name = "Kinshasa";
- break;
- case 7:
- name = "Kivu";
- break;
- case 8:
- name = "Bas-Congo";
- break;
- case 9:
- name = "Orientale";
- break;
- case 10:
- name = "Maniema";
- break;
- case 11:
- name = "Nord-Kivu";
- break;
- case 12:
- name = "Sud-Kivu";
- break;
- case 13:
- name = "Cuvette";
- break;
- }
- }
- if (country_code.equals("CF") == true) {
- switch (region_code2) {
- case 1:
- name = "Bamingui-Bangoran";
- break;
- case 2:
- name = "Basse-Kotto";
- break;
- case 3:
- name = "Haute-Kotto";
- break;
- case 4:
- name = "Mambere-Kadei";
- break;
- case 5:
- name = "Haut-Mbomou";
- break;
- case 6:
- name = "Kemo";
- break;
- case 7:
- name = "Lobaye";
- break;
- case 8:
- name = "Mbomou";
- break;
- case 9:
- name = "Nana-Mambere";
- break;
- case 11:
- name = "Ouaka";
- break;
- case 12:
- name = "Ouham";
- break;
- case 13:
- name = "Ouham-Pende";
- break;
- case 14:
- name = "Cuvette-Ouest";
- break;
- case 15:
- name = "Nana-Grebizi";
- break;
- case 16:
- name = "Sangha-Mbaere";
- break;
- case 17:
- name = "Ombella-Mpoko";
- break;
- case 18:
- name = "Bangui";
- break;
- }
- }
- if (country_code.equals("CG") == true) {
- switch (region_code2) {
- case 1:
- name = "Bouenza";
- break;
- case 3:
- name = "Cuvette";
- break;
- case 4:
- name = "Kouilou";
- break;
- case 5:
- name = "Lekoumou";
- break;
- case 6:
- name = "Likouala";
- break;
- case 7:
- name = "Niari";
- break;
- case 8:
- name = "Plateaux";
- break;
- case 10:
- name = "Sangha";
- break;
- case 11:
- name = "Pool";
- break;
- case 12:
- name = "Brazzaville";
- break;
- }
- }
- if (country_code.equals("CH") == true) {
- switch (region_code2) {
- case 1:
- name = "Aargau";
- break;
- case 2:
- name = "Ausser-Rhoden";
- break;
- case 3:
- name = "Basel-Landschaft";
- break;
- case 4:
- name = "Basel-Stadt";
- break;
- case 5:
- name = "Bern";
- break;
- case 6:
- name = "Fribourg";
- break;
- case 7:
- name = "Geneve";
- break;
- case 8:
- name = "Glarus";
- break;
- case 9:
- name = "Graubunden";
- break;
- case 10:
- name = "Inner-Rhoden";
- break;
- case 11:
- name = "Luzern";
- break;
- case 12:
- name = "Neuchatel";
- break;
- case 13:
- name = "Nidwalden";
- break;
- case 14:
- name = "Obwalden";
- break;
- case 15:
- name = "Sankt Gallen";
- break;
- case 16:
- name = "Schaffhausen";
- break;
- case 17:
- name = "Schwyz";
- break;
- case 18:
- name = "Solothurn";
- break;
- case 19:
- name = "Thurgau";
- break;
- case 20:
- name = "Ticino";
- break;
- case 21:
- name = "Uri";
- break;
- case 22:
- name = "Valais";
- break;
- case 23:
- name = "Vaud";
- break;
- case 24:
- name = "Zug";
- break;
- case 25:
- name = "Zurich";
- break;
- case 26:
- name = "Jura";
- break;
- }
- }
- if (country_code.equals("CI") == true) {
- switch (region_code2) {
- case 5:
- name = "Atacama";
- break;
- case 6:
- name = "Biobio";
- break;
- case 51:
- name = "Sassandra";
- break;
- case 61:
- name = "Abidjan";
- break;
- case 74:
- name = "Agneby";
- break;
- case 75:
- name = "Bafing";
- break;
- case 76:
- name = "Bas-Sassandra";
- break;
- case 77:
- name = "Denguele";
- break;
- case 78:
- name = "Dix-Huit Montagnes";
- break;
- case 79:
- name = "Fromager";
- break;
- case 80:
- name = "Haut-Sassandra";
- break;
- case 81:
- name = "Lacs";
- break;
- case 82:
- name = "Lagunes";
- break;
- case 83:
- name = "Marahoue";
- break;
- case 84:
- name = "Moyen-Cavally";
- break;
- case 85:
- name = "Moyen-Comoe";
- break;
- case 86:
- name = "N'zi-Comoe";
- break;
- case 87:
- name = "Savanes";
- break;
- case 88:
- name = "Sud-Bandama";
- break;
- case 89:
- name = "Sud-Comoe";
- break;
- case 90:
- name = "Vallee du Bandama";
- break;
- case 91:
- name = "Worodougou";
- break;
- case 92:
- name = "Zanzan";
- break;
- }
- }
- if (country_code.equals("CL") == true) {
- switch (region_code2) {
- case 1:
- name = "Valparaiso";
- break;
- case 2:
- name = "Aisen del General Carlos Ibanez del Campo";
- break;
- case 3:
- name = "Antofagasta";
- break;
- case 4:
- name = "Araucania";
- break;
- case 5:
- name = "Atacama";
- break;
- case 6:
- name = "Bio-Bio";
- break;
- case 7:
- name = "Coquimbo";
- break;
- case 8:
- name = "Libertador General Bernardo O'Higgins";
- break;
- case 9:
- name = "Los Lagos";
- break;
- case 10:
- name = "Magallanes y de la Antartica Chilena";
- break;
- case 11:
- name = "Maule";
- break;
- case 12:
- name = "Region Metropolitana";
- break;
- case 13:
- name = "Tarapaca";
- break;
- case 14:
- name = "Los Lagos";
- break;
- case 15:
- name = "Tarapaca";
- break;
- case 16:
- name = "Arica y Parinacota";
- break;
- case 17:
- name = "Los Rios";
- break;
- }
- }
- if (country_code.equals("CM") == true) {
- switch (region_code2) {
- case 4:
- name = "Est";
- break;
- case 5:
- name = "Littoral";
- break;
- case 7:
- name = "Nord-Ouest";
- break;
- case 8:
- name = "Ouest";
- break;
- case 9:
- name = "Sud-Ouest";
- break;
- case 10:
- name = "Adamaoua";
- break;
- case 11:
- name = "Centre";
- break;
- case 12:
- name = "Extreme-Nord";
- break;
- case 13:
- name = "Nord";
- break;
- case 14:
- name = "Sud";
- break;
- }
- }
- if (country_code.equals("CN") == true) {
- switch (region_code2) {
- case 1:
- name = "Anhui";
- break;
- case 2:
- name = "Zhejiang";
- break;
- case 3:
- name = "Jiangxi";
- break;
- case 4:
- name = "Jiangsu";
- break;
- case 5:
- name = "Jilin";
- break;
- case 6:
- name = "Qinghai";
- break;
- case 7:
- name = "Fujian";
- break;
- case 8:
- name = "Heilongjiang";
- break;
- case 9:
- name = "Henan";
- break;
- case 10:
- name = "Hebei";
- break;
- case 11:
- name = "Hunan";
- break;
- case 12:
- name = "Hubei";
- break;
- case 13:
- name = "Xinjiang";
- break;
- case 14:
- name = "Xizang";
- break;
- case 15:
- name = "Gansu";
- break;
- case 16:
- name = "Guangxi";
- break;
- case 18:
- name = "Guizhou";
- break;
- case 19:
- name = "Liaoning";
- break;
- case 20:
- name = "Nei Mongol";
- break;
- case 21:
- name = "Ningxia";
- break;
- case 22:
- name = "Beijing";
- break;
- case 23:
- name = "Shanghai";
- break;
- case 24:
- name = "Shanxi";
- break;
- case 25:
- name = "Shandong";
- break;
- case 26:
- name = "Shaanxi";
- break;
- case 28:
- name = "Tianjin";
- break;
- case 29:
- name = "Yunnan";
- break;
- case 30:
- name = "Guangdong";
- break;
- case 31:
- name = "Hainan";
- break;
- case 32:
- name = "Sichuan";
- break;
- case 33:
- name = "Chongqing";
- break;
- }
- }
- if (country_code.equals("CO") == true) {
- switch (region_code2) {
- case 1:
- name = "Amazonas";
- break;
- case 2:
- name = "Antioquia";
- break;
- case 3:
- name = "Arauca";
- break;
- case 4:
- name = "Atlantico";
- break;
- case 5:
- name = "Bolivar Department";
- break;
- case 6:
- name = "Boyaca Department";
- break;
- case 7:
- name = "Caldas Department";
- break;
- case 8:
- name = "Caqueta";
- break;
- case 9:
- name = "Cauca";
- break;
- case 10:
- name = "Cesar";
- break;
- case 11:
- name = "Choco";
- break;
- case 12:
- name = "Cordoba";
- break;
- case 14:
- name = "Guaviare";
- break;
- case 15:
- name = "Guainia";
- break;
- case 16:
- name = "Huila";
- break;
- case 17:
- name = "La Guajira";
- break;
- case 18:
- name = "Magdalena Department";
- break;
- case 19:
- name = "Meta";
- break;
- case 20:
- name = "Narino";
- break;
- case 21:
- name = "Norte de Santander";
- break;
- case 22:
- name = "Putumayo";
- break;
- case 23:
- name = "Quindio";
- break;
- case 24:
- name = "Risaralda";
- break;
- case 25:
- name = "San Andres y Providencia";
- break;
- case 26:
- name = "Santander";
- break;
- case 27:
- name = "Sucre";
- break;
- case 28:
- name = "Tolima";
- break;
- case 29:
- name = "Valle del Cauca";
- break;
- case 30:
- name = "Vaupes";
- break;
- case 31:
- name = "Vichada";
- break;
- case 32:
- name = "Casanare";
- break;
- case 33:
- name = "Cundinamarca";
- break;
- case 34:
- name = "Distrito Especial";
- break;
- case 35:
- name = "Bolivar";
- break;
- case 36:
- name = "Boyaca";
- break;
- case 37:
- name = "Caldas";
- break;
- case 38:
- name = "Magdalena";
- break;
- }
- }
- if (country_code.equals("CR") == true) {
- switch (region_code2) {
- case 1:
- name = "Alajuela";
- break;
- case 2:
- name = "Cartago";
- break;
- case 3:
- name = "Guanacaste";
- break;
- case 4:
- name = "Heredia";
- break;
- case 6:
- name = "Limon";
- break;
- case 7:
- name = "Puntarenas";
- break;
- case 8:
- name = "San Jose";
- break;
- }
- }
- if (country_code.equals("CU") == true) {
- switch (region_code2) {
- case 1:
- name = "Pinar del Rio";
- break;
- case 2:
- name = "Ciudad de la Habana";
- break;
- case 3:
- name = "Matanzas";
- break;
- case 4:
- name = "Isla de la Juventud";
- break;
- case 5:
- name = "Camaguey";
- break;
- case 7:
- name = "Ciego de Avila";
- break;
- case 8:
- name = "Cienfuegos";
- break;
- case 9:
- name = "Granma";
- break;
- case 10:
- name = "Guantanamo";
- break;
- case 11:
- name = "La Habana";
- break;
- case 12:
- name = "Holguin";
- break;
- case 13:
- name = "Las Tunas";
- break;
- case 14:
- name = "Sancti Spiritus";
- break;
- case 15:
- name = "Santiago de Cuba";
- break;
- case 16:
- name = "Villa Clara";
- break;
- }
- }
- if (country_code.equals("CV") == true) {
- switch (region_code2) {
- case 1:
- name = "Boa Vista";
- break;
- case 2:
- name = "Brava";
- break;
- case 4:
- name = "Maio";
- break;
- case 5:
- name = "Paul";
- break;
- case 7:
- name = "Ribeira Grande";
- break;
- case 8:
- name = "Sal";
- break;
- case 10:
- name = "Sao Nicolau";
- break;
- case 11:
- name = "Sao Vicente";
- break;
- case 13:
- name = "Mosteiros";
- break;
- case 14:
- name = "Praia";
- break;
- case 15:
- name = "Santa Catarina";
- break;
- case 16:
- name = "Santa Cruz";
- break;
- case 17:
- name = "Sao Domingos";
- break;
- case 18:
- name = "Sao Filipe";
- break;
- case 19:
- name = "Sao Miguel";
- break;
- case 20:
- name = "Tarrafal";
- break;
- }
- }
- if (country_code.equals("CY") == true) {
- switch (region_code2) {
- case 1:
- name = "Famagusta";
- break;
- case 2:
- name = "Kyrenia";
- break;
- case 3:
- name = "Larnaca";
- break;
- case 4:
- name = "Nicosia";
- break;
- case 5:
- name = "Limassol";
- break;
- case 6:
- name = "Paphos";
- break;
- }
- }
- if (country_code.equals("CZ") == true) {
- switch (region_code2) {
- case 3:
- name = "Blansko";
- break;
- case 4:
- name = "Breclav";
- break;
- case 20:
- name = "Hradec Kralove";
- break;
- case 21:
- name = "Jablonec nad Nisou";
- break;
- case 23:
- name = "Jicin";
- break;
- case 24:
- name = "Jihlava";
- break;
- case 30:
- name = "Kolin";
- break;
- case 33:
- name = "Liberec";
- break;
- case 36:
- name = "Melnik";
- break;
- case 37:
- name = "Mlada Boleslav";
- break;
- case 39:
- name = "Nachod";
- break;
- case 41:
- name = "Nymburk";
- break;
- case 45:
- name = "Pardubice";
- break;
- case 52:
- name = "Hlavni mesto Praha";
- break;
- case 61:
- name = "Semily";
- break;
- case 70:
- name = "Trutnov";
- break;
- case 78:
- name = "Jihomoravsky kraj";
- break;
- case 79:
- name = "Jihocesky kraj";
- break;
- case 80:
- name = "Vysocina";
- break;
- case 81:
- name = "Karlovarsky kraj";
- break;
- case 82:
- name = "Kralovehradecky kraj";
- break;
- case 83:
- name = "Liberecky kraj";
- break;
- case 84:
- name = "Olomoucky kraj";
- break;
- case 85:
- name = "Moravskoslezsky kraj";
- break;
- case 86:
- name = "Pardubicky kraj";
- break;
- case 87:
- name = "Plzensky kraj";
- break;
- case 88:
- name = "Stredocesky kraj";
- break;
- case 89:
- name = "Ustecky kraj";
- break;
- case 90:
- name = "Zlinsky kraj";
- break;
- }
- }
- if (country_code.equals("DE") == true) {
- switch (region_code2) {
- case 1:
- name = "Baden-Wurttemberg";
- break;
- case 2:
- name = "Bayern";
- break;
- case 3:
- name = "Bremen";
- break;
- case 4:
- name = "Hamburg";
- break;
- case 5:
- name = "Hessen";
- break;
- case 6:
- name = "Niedersachsen";
- break;
- case 7:
- name = "Nordrhein-Westfalen";
- break;
- case 8:
- name = "Rheinland-Pfalz";
- break;
- case 9:
- name = "Saarland";
- break;
- case 10:
- name = "Schleswig-Holstein";
- break;
- case 11:
- name = "Brandenburg";
- break;
- case 12:
- name = "Mecklenburg-Vorpommern";
- break;
- case 13:
- name = "Sachsen";
- break;
- case 14:
- name = "Sachsen-Anhalt";
- break;
- case 15:
- name = "Thuringen";
- break;
- case 16:
- name = "Berlin";
- break;
- }
- }
- if (country_code.equals("DJ") == true) {
- switch (region_code2) {
- case 1:
- name = "Ali Sabieh";
- break;
- case 4:
- name = "Obock";
- break;
- case 5:
- name = "Tadjoura";
- break;
- case 6:
- name = "Dikhil";
- break;
- case 7:
- name = "Djibouti";
- break;
- case 8:
- name = "Arta";
- break;
- }
- }
- if (country_code.equals("DK") == true) {
- switch (region_code2) {
- case 17:
- name = "Hovedstaden";
- break;
- case 18:
- name = "Midtjylland";
- break;
- case 19:
- name = "Nordjylland";
- break;
- case 20:
- name = "Sjelland";
- break;
- case 21:
- name = "Syddanmark";
- break;
- }
- }
- if (country_code.equals("DM") == true) {
- switch (region_code2) {
- case 2:
- name = "Saint Andrew";
- break;
- case 3:
- name = "Saint David";
- break;
- case 4:
- name = "Saint George";
- break;
- case 5:
- name = "Saint John";
- break;
- case 6:
- name = "Saint Joseph";
- break;
- case 7:
- name = "Saint Luke";
- break;
- case 8:
- name = "Saint Mark";
- break;
- case 9:
- name = "Saint Patrick";
- break;
- case 10:
- name = "Saint Paul";
- break;
- case 11:
- name = "Saint Peter";
- break;
- }
- }
- if (country_code.equals("DO") == true) {
- switch (region_code2) {
- case 1:
- name = "Azua";
- break;
- case 2:
- name = "Baoruco";
- break;
- case 3:
- name = "Barahona";
- break;
- case 4:
- name = "Dajabon";
- break;
- case 5:
- name = "Distrito Nacional";
- break;
- case 6:
- name = "Duarte";
- break;
- case 8:
- name = "Espaillat";
- break;
- case 9:
- name = "Independencia";
- break;
- case 10:
- name = "La Altagracia";
- break;
- case 11:
- name = "Elias Pina";
- break;
- case 12:
- name = "La Romana";
- break;
- case 14:
- name = "Maria Trinidad Sanchez";
- break;
- case 15:
- name = "Monte Cristi";
- break;
- case 16:
- name = "Pedernales";
- break;
- case 17:
- name = "Peravia";
- break;
- case 18:
- name = "Puerto Plata";
- break;
- case 19:
- name = "Salcedo";
- break;
- case 20:
- name = "Samana";
- break;
- case 21:
- name = "Sanchez Ramirez";
- break;
- case 23:
- name = "San Juan";
- break;
- case 24:
- name = "San Pedro De Macoris";
- break;
- case 25:
- name = "Santiago";
- break;
- case 26:
- name = "Santiago Rodriguez";
- break;
- case 27:
- name = "Valverde";
- break;
- case 28:
- name = "El Seibo";
- break;
- case 29:
- name = "Hato Mayor";
- break;
- case 30:
- name = "La Vega";
- break;
- case 31:
- name = "Monsenor Nouel";
- break;
- case 32:
- name = "Monte Plata";
- break;
- case 33:
- name = "San Cristobal";
- break;
- case 34:
- name = "Distrito Nacional";
- break;
- case 35:
- name = "Peravia";
- break;
- case 36:
- name = "San Jose de Ocoa";
- break;
- case 37:
- name = "Santo Domingo";
- break;
- }
- }
- if (country_code.equals("DZ") == true) {
- switch (region_code2) {
- case 1:
- name = "Alger";
- break;
- case 3:
- name = "Batna";
- break;
- case 4:
- name = "Constantine";
- break;
- case 6:
- name = "Medea";
- break;
- case 7:
- name = "Mostaganem";
- break;
- case 9:
- name = "Oran";
- break;
- case 10:
- name = "Saida";
- break;
- case 12:
- name = "Setif";
- break;
- case 13:
- name = "Tiaret";
- break;
- case 14:
- name = "Tizi Ouzou";
- break;
- case 15:
- name = "Tlemcen";
- break;
- case 18:
- name = "Bejaia";
- break;
- case 19:
- name = "Biskra";
- break;
- case 20:
- name = "Blida";
- break;
- case 21:
- name = "Bouira";
- break;
- case 22:
- name = "Djelfa";
- break;
- case 23:
- name = "Guelma";
- break;
- case 24:
- name = "Jijel";
- break;
- case 25:
- name = "Laghouat";
- break;
- case 26:
- name = "Mascara";
- break;
- case 27:
- name = "M'sila";
- break;
- case 29:
- name = "Oum el Bouaghi";
- break;
- case 30:
- name = "Sidi Bel Abbes";
- break;
- case 31:
- name = "Skikda";
- break;
- case 33:
- name = "Tebessa";
- break;
- case 34:
- name = "Adrar";
- break;
- case 35:
- name = "Ain Defla";
- break;
- case 36:
- name = "Ain Temouchent";
- break;
- case 37:
- name = "Annaba";
- break;
- case 38:
- name = "Bechar";
- break;
- case 39:
- name = "Bordj Bou Arreridj";
- break;
- case 40:
- name = "Boumerdes";
- break;
- case 41:
- name = "Chlef";
- break;
- case 42:
- name = "El Bayadh";
- break;
- case 43:
- name = "El Oued";
- break;
- case 44:
- name = "El Tarf";
- break;
- case 45:
- name = "Ghardaia";
- break;
- case 46:
- name = "Illizi";
- break;
- case 47:
- name = "Khenchela";
- break;
- case 48:
- name = "Mila";
- break;
- case 49:
- name = "Naama";
- break;
- case 50:
- name = "Ouargla";
- break;
- case 51:
- name = "Relizane";
- break;
- case 52:
- name = "Souk Ahras";
- break;
- case 53:
- name = "Tamanghasset";
- break;
- case 54:
- name = "Tindouf";
- break;
- case 55:
- name = "Tipaza";
- break;
- case 56:
- name = "Tissemsilt";
- break;
- }
- }
- if (country_code.equals("EC") == true) {
- switch (region_code2) {
- case 1:
- name = "Galapagos";
- break;
- case 2:
- name = "Azuay";
- break;
- case 3:
- name = "Bolivar";
- break;
- case 4:
- name = "Canar";
- break;
- case 5:
- name = "Carchi";
- break;
- case 6:
- name = "Chimborazo";
- break;
- case 7:
- name = "Cotopaxi";
- break;
- case 8:
- name = "El Oro";
- break;
- case 9:
- name = "Esmeraldas";
- break;
- case 10:
- name = "Guayas";
- break;
- case 11:
- name = "Imbabura";
- break;
- case 12:
- name = "Loja";
- break;
- case 13:
- name = "Los Rios";
- break;
- case 14:
- name = "Manabi";
- break;
- case 15:
- name = "Morona-Santiago";
- break;
- case 17:
- name = "Pastaza";
- break;
- case 18:
- name = "Pichincha";
- break;
- case 19:
- name = "Tungurahua";
- break;
- case 20:
- name = "Zamora-Chinchipe";
- break;
- case 22:
- name = "Sucumbios";
- break;
- case 23:
- name = "Napo";
- break;
- case 24:
- name = "Orellana";
- break;
- }
- }
- if (country_code.equals("EE") == true) {
- switch (region_code2) {
- case 1:
- name = "Harjumaa";
- break;
- case 2:
- name = "Hiiumaa";
- break;
- case 3:
- name = "Ida-Virumaa";
- break;
- case 4:
- name = "Jarvamaa";
- break;
- case 5:
- name = "Jogevamaa";
- break;
- case 6:
- name = "Kohtla-Jarve";
- break;
- case 7:
- name = "Laanemaa";
- break;
- case 8:
- name = "Laane-Virumaa";
- break;
- case 9:
- name = "Narva";
- break;
- case 10:
- name = "Parnu";
- break;
- case 11:
- name = "Parnumaa";
- break;
- case 12:
- name = "Polvamaa";
- break;
- case 13:
- name = "Raplamaa";
- break;
- case 14:
- name = "Saaremaa";
- break;
- case 15:
- name = "Sillamae";
- break;
- case 16:
- name = "Tallinn";
- break;
- case 17:
- name = "Tartu";
- break;
- case 18:
- name = "Tartumaa";
- break;
- case 19:
- name = "Valgamaa";
- break;
- case 20:
- name = "Viljandimaa";
- break;
- case 21:
- name = "Vorumaa";
- break;
- }
- }
- if (country_code.equals("EG") == true) {
- switch (region_code2) {
- case 1:
- name = "Ad Daqahliyah";
- break;
- case 2:
- name = "Al Bahr al Ahmar";
- break;
- case 3:
- name = "Al Buhayrah";
- break;
- case 4:
- name = "Al Fayyum";
- break;
- case 5:
- name = "Al Gharbiyah";
- break;
- case 6:
- name = "Al Iskandariyah";
- break;
- case 7:
- name = "Al Isma'iliyah";
- break;
- case 8:
- name = "Al Jizah";
- break;
- case 9:
- name = "Al Minufiyah";
- break;
- case 10:
- name = "Al Minya";
- break;
- case 11:
- name = "Al Qahirah";
- break;
- case 12:
- name = "Al Qalyubiyah";
- break;
- case 13:
- name = "Al Wadi al Jadid";
- break;
- case 14:
- name = "Ash Sharqiyah";
- break;
- case 15:
- name = "As Suways";
- break;
- case 16:
- name = "Aswan";
- break;
- case 17:
- name = "Asyut";
- break;
- case 18:
- name = "Bani Suwayf";
- break;
- case 19:
- name = "Bur Sa'id";
- break;
- case 20:
- name = "Dumyat";
- break;
- case 21:
- name = "Kafr ash Shaykh";
- break;
- case 22:
- name = "Matruh";
- break;
- case 23:
- name = "Qina";
- break;
- case 24:
- name = "Suhaj";
- break;
- case 26:
- name = "Janub Sina'";
- break;
- case 27:
- name = "Shamal Sina'";
- break;
- }
- }
- if (country_code.equals("ER") == true) {
- switch (region_code2) {
- case 1:
- name = "Anseba";
- break;
- case 2:
- name = "Debub";
- break;
- case 3:
- name = "Debubawi K'eyih Bahri";
- break;
- case 4:
- name = "Gash Barka";
- break;
- case 5:
- name = "Ma'akel";
- break;
- case 6:
- name = "Semenawi K'eyih Bahri";
- break;
- }
- }
- if (country_code.equals("ES") == true) {
- switch (region_code2) {
- case 7:
- name = "Islas Baleares";
- break;
- case 27:
- name = "La Rioja";
- break;
- case 29:
- name = "Madrid";
- break;
- case 31:
- name = "Murcia";
- break;
- case 32:
- name = "Navarra";
- break;
- case 34:
- name = "Asturias";
- break;
- case 39:
- name = "Cantabria";
- break;
- case 51:
- name = "Andalucia";
- break;
- case 52:
- name = "Aragon";
- break;
- case 53:
- name = "Canarias";
- break;
- case 54:
- name = "Castilla-La Mancha";
- break;
- case 55:
- name = "Castilla y Leon";
- break;
- case 56:
- name = "Catalonia";
- break;
- case 57:
- name = "Extremadura";
- break;
- case 58:
- name = "Galicia";
- break;
- case 59:
- name = "Pais Vasco";
- break;
- case 60:
- name = "Comunidad Valenciana";
- break;
- }
- }
- if (country_code.equals("ET") == true) {
- switch (region_code2) {
- case 2:
- name = "Amhara";
- break;
- case 7:
- name = "Somali";
- break;
- case 8:
- name = "Gambella";
- break;
- case 10:
- name = "Addis Abeba";
- break;
- case 11:
- name = "Southern";
- break;
- case 12:
- name = "Tigray";
- break;
- case 13:
- name = "Benishangul";
- break;
- case 14:
- name = "Afar";
- break;
- case 44:
- name = "Adis Abeba";
- break;
- case 45:
- name = "Afar";
- break;
- case 46:
- name = "Amara";
- break;
- case 47:
- name = "Binshangul Gumuz";
- break;
- case 48:
- name = "Dire Dawa";
- break;
- case 49:
- name = "Gambela Hizboch";
- break;
- case 50:
- name = "Hareri Hizb";
- break;
- case 51:
- name = "Oromiya";
- break;
- case 52:
- name = "Sumale";
- break;
- case 53:
- name = "Tigray";
- break;
- case 54:
- name = "YeDebub Biheroch Bihereseboch na Hizboch";
- break;
- }
- }
- if (country_code.equals("FI") == true) {
- switch (region_code2) {
- case 1:
- name = "Aland";
- break;
- case 6:
- name = "Lapland";
- break;
- case 8:
- name = "Oulu";
- break;
- case 13:
- name = "Southern Finland";
- break;
- case 14:
- name = "Eastern Finland";
- break;
- case 15:
- name = "Western Finland";
- break;
- }
- }
- if (country_code.equals("FJ") == true) {
- switch (region_code2) {
- case 1:
- name = "Central";
- break;
- case 2:
- name = "Eastern";
- break;
- case 3:
- name = "Northern";
- break;
- case 4:
- name = "Rotuma";
- break;
- case 5:
- name = "Western";
- break;
- }
- }
- if (country_code.equals("FM") == true) {
- switch (region_code2) {
- case 1:
- name = "Kosrae";
- break;
- case 2:
- name = "Pohnpei";
- break;
- case 3:
- name = "Chuuk";
- break;
- case 4:
- name = "Yap";
- break;
- }
- }
- if (country_code.equals("FR") == true) {
- switch (region_code2) {
- case 97:
- name = "Aquitaine";
- break;
- case 98:
- name = "Auvergne";
- break;
- case 99:
- name = "Basse-Normandie";
- break;
- case 832:
- name = "Bourgogne";
- break;
- case 833:
- name = "Bretagne";
- break;
- case 834:
- name = "Centre";
- break;
- case 835:
- name = "Champagne-Ardenne";
- break;
- case 836:
- name = "Corse";
- break;
- case 837:
- name = "Franche-Comte";
- break;
- case 838:
- name = "Haute-Normandie";
- break;
- case 839:
- name = "Ile-de-France";
- break;
- case 840:
- name = "Languedoc-Roussillon";
- break;
- case 875:
- name = "Limousin";
- break;
- case 876:
- name = "Lorraine";
- break;
- case 877:
- name = "Midi-Pyrenees";
- break;
- case 878:
- name = "Nord-Pas-de-Calais";
- break;
- case 879:
- name = "Pays de la Loire";
- break;
- case 880:
- name = "Picardie";
- break;
- case 881:
- name = "Poitou-Charentes";
- break;
- case 882:
- name = "Provence-Alpes-Cote d'Azur";
- break;
- case 883:
- name = "Rhone-Alpes";
- break;
- case 918:
- name = "Alsace";
- break;
- }
- }
- if (country_code.equals("GA") == true) {
- switch (region_code2) {
- case 1:
- name = "Estuaire";
- break;
- case 2:
- name = "Haut-Ogooue";
- break;
- case 3:
- name = "Moyen-Ogooue";
- break;
- case 4:
- name = "Ngounie";
- break;
- case 5:
- name = "Nyanga";
- break;
- case 6:
- name = "Ogooue-Ivindo";
- break;
- case 7:
- name = "Ogooue-Lolo";
- break;
- case 8:
- name = "Ogooue-Maritime";
- break;
- case 9:
- name = "Woleu-Ntem";
- break;
- }
- }
- if (country_code.equals("GB") == true) {
- switch (region_code2) {
- case 1:
- name = "Avon";
- break;
- case 3:
- name = "Berkshire";
- break;
- case 7:
- name = "Cleveland";
- break;
- case 17:
- name = "Greater London";
- break;
- case 18:
- name = "Greater Manchester";
- break;
- case 20:
- name = "Hereford and Worcester";
- break;
- case 22:
- name = "Humberside";
- break;
- case 28:
- name = "Merseyside";
- break;
- case 37:
- name = "South Yorkshire";
- break;
- case 41:
- name = "Tyne and Wear";
- break;
- case 43:
- name = "West Midlands";
- break;
- case 45:
- name = "West Yorkshire";
- break;
- case 79:
- name = "Central";
- break;
- case 82:
- name = "Grampian";
- break;
- case 84:
- name = "Lothian";
- break;
- case 87:
- name = "Strathclyde";
- break;
- case 88:
- name = "Tayside";
- break;
- case 90:
- name = "Clwyd";
- break;
- case 91:
- name = "Dyfed";
- break;
- case 92:
- name = "Gwent";
- break;
- case 94:
- name = "Mid Glamorgan";
- break;
- case 96:
- name = "South Glamorgan";
- break;
- case 97:
- name = "West Glamorgan";
- break;
- case 832:
- name = "Barking and Dagenham";
- break;
- case 833:
- name = "Barnet";
- break;
- case 834:
- name = "Barnsley";
- break;
- case 835:
- name = "Bath and North East Somerset";
- break;
- case 836:
- name = "Bedfordshire";
- break;
- case 837:
- name = "Bexley";
- break;
- case 838:
- name = "Birmingham";
- break;
- case 839:
- name = "Blackburn with Darwen";
- break;
- case 840:
- name = "Blackpool";
- break;
- case 875:
- name = "Bolton";
- break;
- case 876:
- name = "Bournemouth";
- break;
- case 877:
- name = "Bracknell Forest";
- break;
- case 878:
- name = "Bradford";
- break;
- case 879:
- name = "Brent";
- break;
- case 880:
- name = "Brighton and Hove";
- break;
- case 881:
- name = "Bristol";
- break;
- case 882:
- name = "Bromley";
- break;
- case 883:
- name = "Buckinghamshire";
- break;
- case 918:
- name = "Bury";
- break;
- case 919:
- name = "Calderdale";
- break;
- case 920:
- name = "Cambridgeshire";
- break;
- case 921:
- name = "Camden";
- break;
- case 922:
- name = "Cheshire";
- break;
- case 923:
- name = "Cornwall";
- break;
- case 924:
- name = "Coventry";
- break;
- case 925:
- name = "Croydon";
- break;
- case 926:
- name = "Cumbria";
- break;
- case 961:
- name = "Darlington";
- break;
- case 962:
- name = "Derby";
- break;
- case 963:
- name = "Derbyshire";
- break;
- case 964:
- name = "Devon";
- break;
- case 965:
- name = "Doncaster";
- break;
- case 966:
- name = "Dorset";
- break;
- case 967:
- name = "Dudley";
- break;
- case 968:
- name = "Durham";
- break;
- case 969:
- name = "Ealing";
- break;
- case 1004:
- name = "East Riding of Yorkshire";
- break;
- case 1005:
- name = "East Sussex";
- break;
- case 1006:
- name = "Enfield";
- break;
- case 1007:
- name = "Essex";
- break;
- case 1008:
- name = "Gateshead";
- break;
- case 1009:
- name = "Gloucestershire";
- break;
- case 1010:
- name = "Greenwich";
- break;
- case 1011:
- name = "Hackney";
- break;
- case 1012:
- name = "Halton";
- break;
- case 1047:
- name = "Hammersmith and Fulham";
- break;
- case 1048:
- name = "Hampshire";
- break;
- case 1049:
- name = "Haringey";
- break;
- case 1050:
- name = "Harrow";
- break;
- case 1051:
- name = "Hartlepool";
- break;
- case 1052:
- name = "Havering";
- break;
- case 1053:
- name = "Herefordshire";
- break;
- case 1054:
- name = "Hertford";
- break;
- case 1055:
- name = "Hillingdon";
- break;
- case 1090:
- name = "Hounslow";
- break;
- case 1091:
- name = "Isle of Wight";
- break;
- case 1092:
- name = "Islington";
- break;
- case 1093:
- name = "Kensington and Chelsea";
- break;
- case 1094:
- name = "Kent";
- break;
- case 1095:
- name = "Kingston upon Hull";
- break;
- case 1096:
- name = "Kingston upon Thames";
- break;
- case 1097:
- name = "Kirklees";
- break;
- case 1098:
- name = "Knowsley";
- break;
- case 1133:
- name = "Lambeth";
- break;
- case 1134:
- name = "Lancashire";
- break;
- case 1135:
- name = "Leeds";
- break;
- case 1136:
- name = "Leicester";
- break;
- case 1137:
- name = "Leicestershire";
- break;
- case 1138:
- name = "Lewisham";
- break;
- case 1139:
- name = "Lincolnshire";
- break;
- case 1140:
- name = "Liverpool";
- break;
- case 1141:
- name = "London";
- break;
- case 1176:
- name = "Luton";
- break;
- case 1177:
- name = "Manchester";
- break;
- case 1178:
- name = "Medway";
- break;
- case 1179:
- name = "Merton";
- break;
- case 1180:
- name = "Middlesbrough";
- break;
- case 1181:
- name = "Milton Keynes";
- break;
- case 1182:
- name = "Newcastle upon Tyne";
- break;
- case 1183:
- name = "Newham";
- break;
- case 1184:
- name = "Norfolk";
- break;
- case 1219:
- name = "Northamptonshire";
- break;
- case 1220:
- name = "North East Lincolnshire";
- break;
- case 1221:
- name = "North Lincolnshire";
- break;
- case 1222:
- name = "North Somerset";
- break;
- case 1223:
- name = "North Tyneside";
- break;
- case 1224:
- name = "Northumberland";
- break;
- case 1225:
- name = "North Yorkshire";
- break;
- case 1226:
- name = "Nottingham";
- break;
- case 1227:
- name = "Nottinghamshire";
- break;
- case 1262:
- name = "Oldham";
- break;
- case 1263:
- name = "Oxfordshire";
- break;
- case 1264:
- name = "Peterborough";
- break;
- case 1265:
- name = "Plymouth";
- break;
- case 1266:
- name = "Poole";
- break;
- case 1267:
- name = "Portsmouth";
- break;
- case 1268:
- name = "Reading";
- break;
- case 1269:
- name = "Redbridge";
- break;
- case 1270:
- name = "Redcar and Cleveland";
- break;
- case 1305:
- name = "Richmond upon Thames";
- break;
- case 1306:
- name = "Rochdale";
- break;
- case 1307:
- name = "Rotherham";
- break;
- case 1308:
- name = "Rutland";
- break;
- case 1309:
- name = "Salford";
- break;
- case 1310:
- name = "Shropshire";
- break;
- case 1311:
- name = "Sandwell";
- break;
- case 1312:
- name = "Sefton";
- break;
- case 1313:
- name = "Sheffield";
- break;
- case 1348:
- name = "Slough";
- break;
- case 1349:
- name = "Solihull";
- break;
- case 1350:
- name = "Somerset";
- break;
- case 1351:
- name = "Southampton";
- break;
- case 1352:
- name = "Southend-on-Sea";
- break;
- case 1353:
- name = "South Gloucestershire";
- break;
- case 1354:
- name = "South Tyneside";
- break;
- case 1355:
- name = "Southwark";
- break;
- case 1356:
- name = "Staffordshire";
- break;
- case 1391:
- name = "St. Helens";
- break;
- case 1392:
- name = "Stockport";
- break;
- case 1393:
- name = "Stockton-on-Tees";
- break;
- case 1394:
- name = "Stoke-on-Trent";
- break;
- case 1395:
- name = "Suffolk";
- break;
- case 1396:
- name = "Sunderland";
- break;
- case 1397:
- name = "Surrey";
- break;
- case 1398:
- name = "Sutton";
- break;
- case 1399:
- name = "Swindon";
- break;
- case 1434:
- name = "Tameside";
- break;
- case 1435:
- name = "Telford and Wrekin";
- break;
- case 1436:
- name = "Thurrock";
- break;
- case 1437:
- name = "Torbay";
- break;
- case 1438:
- name = "Tower Hamlets";
- break;
- case 1439:
- name = "Trafford";
- break;
- case 1440:
- name = "Wakefield";
- break;
- case 1441:
- name = "Walsall";
- break;
- case 1442:
- name = "Waltham Forest";
- break;
- case 1477:
- name = "Wandsworth";
- break;
- case 1478:
- name = "Warrington";
- break;
- case 1479:
- name = "Warwickshire";
- break;
- case 1480:
- name = "West Berkshire";
- break;
- case 1481:
- name = "Westminster";
- break;
- case 1482:
- name = "West Sussex";
- break;
- case 1483:
- name = "Wigan";
- break;
- case 1484:
- name = "Wiltshire";
- break;
- case 1485:
- name = "Windsor and Maidenhead";
- break;
- case 1520:
- name = "Wirral";
- break;
- case 1521:
- name = "Wokingham";
- break;
- case 1522:
- name = "Wolverhampton";
- break;
- case 1523:
- name = "Worcestershire";
- break;
- case 1524:
- name = "York";
- break;
- case 1525:
- name = "Antrim";
- break;
- case 1526:
- name = "Ards";
- break;
- case 1527:
- name = "Armagh";
- break;
- case 1528:
- name = "Ballymena";
- break;
- case 1563:
- name = "Ballymoney";
- break;
- case 1564:
- name = "Banbridge";
- break;
- case 1565:
- name = "Belfast";
- break;
- case 1566:
- name = "Carrickfergus";
- break;
- case 1567:
- name = "Castlereagh";
- break;
- case 1568:
- name = "Coleraine";
- break;
- case 1569:
- name = "Cookstown";
- break;
- case 1570:
- name = "Craigavon";
- break;
- case 1571:
- name = "Down";
- break;
- case 1606:
- name = "Dungannon";
- break;
- case 1607:
- name = "Fermanagh";
- break;
- case 1608:
- name = "Larne";
- break;
- case 1609:
- name = "Limavady";
- break;
- case 1610:
- name = "Lisburn";
- break;
- case 1611:
- name = "Derry";
- break;
- case 1612:
- name = "Magherafelt";
- break;
- case 1613:
- name = "Moyle";
- break;
- case 1614:
- name = "Newry and Mourne";
- break;
- case 1649:
- name = "Newtownabbey";
- break;
- case 1650:
- name = "North Down";
- break;
- case 1651:
- name = "Omagh";
- break;
- case 1652:
- name = "Strabane";
- break;
- case 1653:
- name = "Aberdeen City";
- break;
- case 1654:
- name = "Aberdeenshire";
- break;
- case 1655:
- name = "Angus";
- break;
- case 1656:
- name = "Argyll and Bute";
- break;
- case 1657:
- name = "Scottish Borders";
- break;
- case 1692:
- name = "Clackmannanshire";
- break;
- case 1693:
- name = "Dumfries and Galloway";
- break;
- case 1694:
- name = "Dundee City";
- break;
- case 1695:
- name = "East Ayrshire";
- break;
- case 1696:
- name = "East Dunbartonshire";
- break;
- case 1697:
- name = "East Lothian";
- break;
- case 1698:
- name = "East Renfrewshire";
- break;
- case 1699:
- name = "Edinburgh";
- break;
- case 1700:
- name = "Falkirk";
- break;
- case 1735:
- name = "Fife";
- break;
- case 1736:
- name = "Glasgow City";
- break;
- case 1737:
- name = "Highland";
- break;
- case 1738:
- name = "Inverclyde";
- break;
- case 1739:
- name = "Midlothian";
- break;
- case 1740:
- name = "Moray";
- break;
- case 1741:
- name = "North Ayrshire";
- break;
- case 1742:
- name = "North Lanarkshire";
- break;
- case 1743:
- name = "Orkney";
- break;
- case 1778:
- name = "Perth and Kinross";
- break;
- case 1779:
- name = "Renfrewshire";
- break;
- case 1780:
- name = "Shetland Islands";
- break;
- case 1781:
- name = "South Ayrshire";
- break;
- case 1782:
- name = "South Lanarkshire";
- break;
- case 1783:
- name = "Stirling";
- break;
- case 1784:
- name = "West Dunbartonshire";
- break;
- case 1785:
- name = "Eilean Siar";
- break;
- case 1786:
- name = "West Lothian";
- break;
- case 1821:
- name = "Isle of Anglesey";
- break;
- case 1822:
- name = "Blaenau Gwent";
- break;
- case 1823:
- name = "Bridgend";
- break;
- case 1824:
- name = "Caerphilly";
- break;
- case 1825:
- name = "Cardiff";
- break;
- case 1826:
- name = "Ceredigion";
- break;
- case 1827:
- name = "Carmarthenshire";
- break;
- case 1828:
- name = "Conwy";
- break;
- case 1829:
- name = "Denbighshire";
- break;
- case 1864:
- name = "Flintshire";
- break;
- case 1865:
- name = "Gwynedd";
- break;
- case 1866:
- name = "Merthyr Tydfil";
- break;
- case 1867:
- name = "Monmouthshire";
- break;
- case 1868:
- name = "Neath Port Talbot";
- break;
- case 1869:
- name = "Newport";
- break;
- case 1870:
- name = "Pembrokeshire";
- break;
- case 1871:
- name = "Powys";
- break;
- case 1872:
- name = "Rhondda Cynon Taff";
- break;
- case 1907:
- name = "Swansea";
- break;
- case 1908:
- name = "Torfaen";
- break;
- case 1909:
- name = "Vale of Glamorgan";
- break;
- case 1910:
- name = "Wrexham";
- break;
- }
- }
- if (country_code.equals("GD") == true) {
- switch (region_code2) {
- case 1:
- name = "Saint Andrew";
- break;
- case 2:
- name = "Saint David";
- break;
- case 3:
- name = "Saint George";
- break;
- case 4:
- name = "Saint John";
- break;
- case 5:
- name = "Saint Mark";
- break;
- case 6:
- name = "Saint Patrick";
- break;
- }
- }
- if (country_code.equals("GE") == true) {
- switch (region_code2) {
- case 1:
- name = "Abashis Raioni";
- break;
- case 2:
- name = "Abkhazia";
- break;
- case 3:
- name = "Adigenis Raioni";
- break;
- case 4:
- name = "Ajaria";
- break;
- case 5:
- name = "Akhalgoris Raioni";
- break;
- case 6:
- name = "Akhalk'alak'is Raioni";
- break;
- case 7:
- name = "Akhalts'ikhis Raioni";
- break;
- case 8:
- name = "Akhmetis Raioni";
- break;
- case 9:
- name = "Ambrolauris Raioni";
- break;
- case 10:
- name = "Aspindzis Raioni";
- break;
- case 11:
- name = "Baghdat'is Raioni";
- break;
- case 12:
- name = "Bolnisis Raioni";
- break;
- case 13:
- name = "Borjomis Raioni";
- break;
- case 14:
- name = "Chiat'ura";
- break;
- case 15:
- name = "Ch'khorotsqus Raioni";
- break;
- case 16:
- name = "Ch'okhatauris Raioni";
- break;
- case 17:
- name = "Dedop'listsqaros Raioni";
- break;
- case 18:
- name = "Dmanisis Raioni";
- break;
- case 19:
- name = "Dushet'is Raioni";
- break;
- case 20:
- name = "Gardabanis Raioni";
- break;
- case 21:
- name = "Gori";
- break;
- case 22:
- name = "Goris Raioni";
- break;
- case 23:
- name = "Gurjaanis Raioni";
- break;
- case 24:
- name = "Javis Raioni";
- break;
- case 25:
- name = "K'arelis Raioni";
- break;
- case 26:
- name = "Kaspis Raioni";
- break;
- case 27:
- name = "Kharagaulis Raioni";
- break;
- case 28:
- name = "Khashuris Raioni";
- break;
- case 29:
- name = "Khobis Raioni";
- break;
- case 30:
- name = "Khonis Raioni";
- break;
- case 31:
- name = "K'ut'aisi";
- break;
- case 32:
- name = "Lagodekhis Raioni";
- break;
- case 33:
- name = "Lanch'khut'is Raioni";
- break;
- case 34:
- name = "Lentekhis Raioni";
- break;
- case 35:
- name = "Marneulis Raioni";
- break;
- case 36:
- name = "Martvilis Raioni";
- break;
- case 37:
- name = "Mestiis Raioni";
- break;
- case 38:
- name = "Mts'khet'is Raioni";
- break;
- case 39:
- name = "Ninotsmindis Raioni";
- break;
- case 40:
- name = "Onis Raioni";
- break;
- case 41:
- name = "Ozurget'is Raioni";
- break;
- case 42:
- name = "P'ot'i";
- break;
- case 43:
- name = "Qazbegis Raioni";
- break;
- case 44:
- name = "Qvarlis Raioni";
- break;
- case 45:
- name = "Rust'avi";
- break;
- case 46:
- name = "Sach'kheris Raioni";
- break;
- case 47:
- name = "Sagarejos Raioni";
- break;
- case 48:
- name = "Samtrediis Raioni";
- break;
- case 49:
- name = "Senakis Raioni";
- break;
- case 50:
- name = "Sighnaghis Raioni";
- break;
- case 51:
- name = "T'bilisi";
- break;
- case 52:
- name = "T'elavis Raioni";
- break;
- case 53:
- name = "T'erjolis Raioni";
- break;
- case 54:
- name = "T'et'ritsqaros Raioni";
- break;
- case 55:
- name = "T'ianet'is Raioni";
- break;
- case 56:
- name = "Tqibuli";
- break;
- case 57:
- name = "Ts'ageris Raioni";
- break;
- case 58:
- name = "Tsalenjikhis Raioni";
- break;
- case 59:
- name = "Tsalkis Raioni";
- break;
- case 60:
- name = "Tsqaltubo";
- break;
- case 61:
- name = "Vanis Raioni";
- break;
- case 62:
- name = "Zestap'onis Raioni";
- break;
- case 63:
- name = "Zugdidi";
- break;
- case 64:
- name = "Zugdidis Raioni";
- break;
- }
- }
- if (country_code.equals("GH") == true) {
- switch (region_code2) {
- case 1:
- name = "Greater Accra";
- break;
- case 2:
- name = "Ashanti";
- break;
- case 3:
- name = "Brong-Ahafo";
- break;
- case 4:
- name = "Central";
- break;
- case 5:
- name = "Eastern";
- break;
- case 6:
- name = "Northern";
- break;
- case 8:
- name = "Volta";
- break;
- case 9:
- name = "Western";
- break;
- case 10:
- name = "Upper East";
- break;
- case 11:
- name = "Upper West";
- break;
- }
- }
- if (country_code.equals("GL") == true) {
- switch (region_code2) {
- case 1:
- name = "Nordgronland";
- break;
- case 2:
- name = "Ostgronland";
- break;
- case 3:
- name = "Vestgronland";
- break;
- }
- }
- if (country_code.equals("GM") == true) {
- switch (region_code2) {
- case 1:
- name = "Banjul";
- break;
- case 2:
- name = "Lower River";
- break;
- case 3:
- name = "Central River";
- break;
- case 4:
- name = "Upper River";
- break;
- case 5:
- name = "Western";
- break;
- case 7:
- name = "North Bank";
- break;
- }
- }
- if (country_code.equals("GN") == true) {
- switch (region_code2) {
- case 1:
- name = "Beyla";
- break;
- case 2:
- name = "Boffa";
- break;
- case 3:
- name = "Boke";
- break;
- case 4:
- name = "Conakry";
- break;
- case 5:
- name = "Dabola";
- break;
- case 6:
- name = "Dalaba";
- break;
- case 7:
- name = "Dinguiraye";
- break;
- case 9:
- name = "Faranah";
- break;
- case 10:
- name = "Forecariah";
- break;
- case 11:
- name = "Fria";
- break;
- case 12:
- name = "Gaoual";
- break;
- case 13:
- name = "Gueckedou";
- break;
- case 15:
- name = "Kerouane";
- break;
- case 16:
- name = "Kindia";
- break;
- case 17:
- name = "Kissidougou";
- break;
- case 18:
- name = "Koundara";
- break;
- case 19:
- name = "Kouroussa";
- break;
- case 21:
- name = "Macenta";
- break;
- case 22:
- name = "Mali";
- break;
- case 23:
- name = "Mamou";
- break;
- case 25:
- name = "Pita";
- break;
- case 27:
- name = "Telimele";
- break;
- case 28:
- name = "Tougue";
- break;
- case 29:
- name = "Yomou";
- break;
- case 30:
- name = "Coyah";
- break;
- case 31:
- name = "Dubreka";
- break;
- case 32:
- name = "Kankan";
- break;
- case 33:
- name = "Koubia";
- break;
- case 34:
- name = "Labe";
- break;
- case 35:
- name = "Lelouma";
- break;
- case 36:
- name = "Lola";
- break;
- case 37:
- name = "Mandiana";
- break;
- case 38:
- name = "Nzerekore";
- break;
- case 39:
- name = "Siguiri";
- break;
- }
- }
- if (country_code.equals("GQ") == true) {
- switch (region_code2) {
- case 3:
- name = "Annobon";
- break;
- case 4:
- name = "Bioko Norte";
- break;
- case 5:
- name = "Bioko Sur";
- break;
- case 6:
- name = "Centro Sur";
- break;
- case 7:
- name = "Kie-Ntem";
- break;
- case 8:
- name = "Litoral";
- break;
- case 9:
- name = "Wele-Nzas";
- break;
- }
- }
- if (country_code.equals("GR") == true) {
- switch (region_code2) {
- case 1:
- name = "Evros";
- break;
- case 2:
- name = "Rodhopi";
- break;
- case 3:
- name = "Xanthi";
- break;
- case 4:
- name = "Drama";
- break;
- case 5:
- name = "Serrai";
- break;
- case 6:
- name = "Kilkis";
- break;
- case 7:
- name = "Pella";
- break;
- case 8:
- name = "Florina";
- break;
- case 9:
- name = "Kastoria";
- break;
- case 10:
- name = "Grevena";
- break;
- case 11:
- name = "Kozani";
- break;
- case 12:
- name = "Imathia";
- break;
- case 13:
- name = "Thessaloniki";
- break;
- case 14:
- name = "Kavala";
- break;
- case 15:
- name = "Khalkidhiki";
- break;
- case 16:
- name = "Pieria";
- break;
- case 17:
- name = "Ioannina";
- break;
- case 18:
- name = "Thesprotia";
- break;
- case 19:
- name = "Preveza";
- break;
- case 20:
- name = "Arta";
- break;
- case 21:
- name = "Larisa";
- break;
- case 22:
- name = "Trikala";
- break;
- case 23:
- name = "Kardhitsa";
- break;
- case 24:
- name = "Magnisia";
- break;
- case 25:
- name = "Kerkira";
- break;
- case 26:
- name = "Levkas";
- break;
- case 27:
- name = "Kefallinia";
- break;
- case 28:
- name = "Zakinthos";
- break;
- case 29:
- name = "Fthiotis";
- break;
- case 30:
- name = "Evritania";
- break;
- case 31:
- name = "Aitolia kai Akarnania";
- break;
- case 32:
- name = "Fokis";
- break;
- case 33:
- name = "Voiotia";
- break;
- case 34:
- name = "Evvoia";
- break;
- case 35:
- name = "Attiki";
- break;
- case 36:
- name = "Argolis";
- break;
- case 37:
- name = "Korinthia";
- break;
- case 38:
- name = "Akhaia";
- break;
- case 39:
- name = "Ilia";
- break;
- case 40:
- name = "Messinia";
- break;
- case 41:
- name = "Arkadhia";
- break;
- case 42:
- name = "Lakonia";
- break;
- case 43:
- name = "Khania";
- break;
- case 44:
- name = "Rethimni";
- break;
- case 45:
- name = "Iraklion";
- break;
- case 46:
- name = "Lasithi";
- break;
- case 47:
- name = "Dhodhekanisos";
- break;
- case 48:
- name = "Samos";
- break;
- case 49:
- name = "Kikladhes";
- break;
- case 50:
- name = "Khios";
- break;
- case 51:
- name = "Lesvos";
- break;
- }
- }
- if (country_code.equals("GT") == true) {
- switch (region_code2) {
- case 1:
- name = "Alta Verapaz";
- break;
- case 2:
- name = "Baja Verapaz";
- break;
- case 3:
- name = "Chimaltenango";
- break;
- case 4:
- name = "Chiquimula";
- break;
- case 5:
- name = "El Progreso";
- break;
- case 6:
- name = "Escuintla";
- break;
- case 7:
- name = "Guatemala";
- break;
- case 8:
- name = "Huehuetenango";
- break;
- case 9:
- name = "Izabal";
- break;
- case 10:
- name = "Jalapa";
- break;
- case 11:
- name = "Jutiapa";
- break;
- case 12:
- name = "Peten";
- break;
- case 13:
- name = "Quetzaltenango";
- break;
- case 14:
- name = "Quiche";
- break;
- case 15:
- name = "Retalhuleu";
- break;
- case 16:
- name = "Sacatepequez";
- break;
- case 17:
- name = "San Marcos";
- break;
- case 18:
- name = "Santa Rosa";
- break;
- case 19:
- name = "Solola";
- break;
- case 20:
- name = "Suchitepequez";
- break;
- case 21:
- name = "Totonicapan";
- break;
- case 22:
- name = "Zacapa";
- break;
- }
- }
- if (country_code.equals("GW") == true) {
- switch (region_code2) {
- case 1:
- name = "Bafata";
- break;
- case 2:
- name = "Quinara";
- break;
- case 4:
- name = "Oio";
- break;
- case 5:
- name = "Bolama";
- break;
- case 6:
- name = "Cacheu";
- break;
- case 7:
- name = "Tombali";
- break;
- case 10:
- name = "Gabu";
- break;
- case 11:
- name = "Bissau";
- break;
- case 12:
- name = "Biombo";
- break;
- }
- }
- if (country_code.equals("GY") == true) {
- switch (region_code2) {
- case 10:
- name = "Barima-Waini";
- break;
- case 11:
- name = "Cuyuni-Mazaruni";
- break;
- case 12:
- name = "Demerara-Mahaica";
- break;
- case 13:
- name = "East Berbice-Corentyne";
- break;
- case 14:
- name = "Essequibo Islands-West Demerara";
- break;
- case 15:
- name = "Mahaica-Berbice";
- break;
- case 16:
- name = "Pomeroon-Supenaam";
- break;
- case 17:
- name = "Potaro-Siparuni";
- break;
- case 18:
- name = "Upper Demerara-Berbice";
- break;
- case 19:
- name = "Upper Takutu-Upper Essequibo";
- break;
- }
- }
- if (country_code.equals("HN") == true) {
- switch (region_code2) {
- case 1:
- name = "Atlantida";
- break;
- case 2:
- name = "Choluteca";
- break;
- case 3:
- name = "Colon";
- break;
- case 4:
- name = "Comayagua";
- break;
- case 5:
- name = "Copan";
- break;
- case 6:
- name = "Cortes";
- break;
- case 7:
- name = "El Paraiso";
- break;
- case 8:
- name = "Francisco Morazan";
- break;
- case 9:
- name = "Gracias a Dios";
- break;
- case 10:
- name = "Intibuca";
- break;
- case 11:
- name = "Islas de la Bahia";
- break;
- case 12:
- name = "La Paz";
- break;
- case 13:
- name = "Lempira";
- break;
- case 14:
- name = "Ocotepeque";
- break;
- case 15:
- name = "Olancho";
- break;
- case 16:
- name = "Santa Barbara";
- break;
- case 17:
- name = "Valle";
- break;
- case 18:
- name = "Yoro";
- break;
- }
- }
- if (country_code.equals("HR") == true) {
- switch (region_code2) {
- case 1:
- name = "Bjelovarsko-Bilogorska";
- break;
- case 2:
- name = "Brodsko-Posavska";
- break;
- case 3:
- name = "Dubrovacko-Neretvanska";
- break;
- case 4:
- name = "Istarska";
- break;
- case 5:
- name = "Karlovacka";
- break;
- case 6:
- name = "Koprivnicko-Krizevacka";
- break;
- case 7:
- name = "Krapinsko-Zagorska";
- break;
- case 8:
- name = "Licko-Senjska";
- break;
- case 9:
- name = "Medimurska";
- break;
- case 10:
- name = "Osjecko-Baranjska";
- break;
- case 11:
- name = "Pozesko-Slavonska";
- break;
- case 12:
- name = "Primorsko-Goranska";
- break;
- case 13:
- name = "Sibensko-Kninska";
- break;
- case 14:
- name = "Sisacko-Moslavacka";
- break;
- case 15:
- name = "Splitsko-Dalmatinska";
- break;
- case 16:
- name = "Varazdinska";
- break;
- case 17:
- name = "Viroviticko-Podravska";
- break;
- case 18:
- name = "Vukovarsko-Srijemska";
- break;
- case 19:
- name = "Zadarska";
- break;
- case 20:
- name = "Zagrebacka";
- break;
- case 21:
- name = "Grad Zagreb";
- break;
- }
- }
- if (country_code.equals("HT") == true) {
- switch (region_code2) {
- case 3:
- name = "Nord-Ouest";
- break;
- case 6:
- name = "Artibonite";
- break;
- case 7:
- name = "Centre";
- break;
- case 9:
- name = "Nord";
- break;
- case 10:
- name = "Nord-Est";
- break;
- case 11:
- name = "Ouest";
- break;
- case 12:
- name = "Sud";
- break;
- case 13:
- name = "Sud-Est";
- break;
- case 14:
- name = "Grand' Anse";
- break;
- case 15:
- name = "Nippes";
- break;
- }
- }
- if (country_code.equals("HU") == true) {
- switch (region_code2) {
- case 1:
- name = "Bacs-Kiskun";
- break;
- case 2:
- name = "Baranya";
- break;
- case 3:
- name = "Bekes";
- break;
- case 4:
- name = "Borsod-Abauj-Zemplen";
- break;
- case 5:
- name = "Budapest";
- break;
- case 6:
- name = "Csongrad";
- break;
- case 7:
- name = "Debrecen";
- break;
- case 8:
- name = "Fejer";
- break;
- case 9:
- name = "Gyor-Moson-Sopron";
- break;
- case 10:
- name = "Hajdu-Bihar";
- break;
- case 11:
- name = "Heves";
- break;
- case 12:
- name = "Komarom-Esztergom";
- break;
- case 13:
- name = "Miskolc";
- break;
- case 14:
- name = "Nograd";
- break;
- case 15:
- name = "Pecs";
- break;
- case 16:
- name = "Pest";
- break;
- case 17:
- name = "Somogy";
- break;
- case 18:
- name = "Szabolcs-Szatmar-Bereg";
- break;
- case 19:
- name = "Szeged";
- break;
- case 20:
- name = "Jasz-Nagykun-Szolnok";
- break;
- case 21:
- name = "Tolna";
- break;
- case 22:
- name = "Vas";
- break;
- case 23:
- name = "Veszprem";
- break;
- case 24:
- name = "Zala";
- break;
- case 25:
- name = "Gyor";
- break;
- case 26:
- name = "Bekescsaba";
- break;
- case 27:
- name = "Dunaujvaros";
- break;
- case 28:
- name = "Eger";
- break;
- case 29:
- name = "Hodmezovasarhely";
- break;
- case 30:
- name = "Kaposvar";
- break;
- case 31:
- name = "Kecskemet";
- break;
- case 32:
- name = "Nagykanizsa";
- break;
- case 33:
- name = "Nyiregyhaza";
- break;
- case 34:
- name = "Sopron";
- break;
- case 35:
- name = "Szekesfehervar";
- break;
- case 36:
- name = "Szolnok";
- break;
- case 37:
- name = "Szombathely";
- break;
- case 38:
- name = "Tatabanya";
- break;
- case 39:
- name = "Veszprem";
- break;
- case 40:
- name = "Zalaegerszeg";
- break;
- case 41:
- name = "Salgotarjan";
- break;
- case 42:
- name = "Szekszard";
- break;
- }
- }
- if (country_code.equals("ID") == true) {
- switch (region_code2) {
- case 1:
- name = "Aceh";
- break;
- case 2:
- name = "Bali";
- break;
- case 3:
- name = "Bengkulu";
- break;
- case 4:
- name = "Jakarta Raya";
- break;
- case 5:
- name = "Jambi";
- break;
- case 6:
- name = "Jawa Barat";
- break;
- case 7:
- name = "Jawa Tengah";
- break;
- case 8:
- name = "Jawa Timur";
- break;
- case 9:
- name = "Papua";
- break;
- case 10:
- name = "Yogyakarta";
- break;
- case 11:
- name = "Kalimantan Barat";
- break;
- case 12:
- name = "Kalimantan Selatan";
- break;
- case 13:
- name = "Kalimantan Tengah";
- break;
- case 14:
- name = "Kalimantan Timur";
- break;
- case 15:
- name = "Lampung";
- break;
- case 16:
- name = "Maluku";
- break;
- case 17:
- name = "Nusa Tenggara Barat";
- break;
- case 18:
- name = "Nusa Tenggara Timur";
- break;
- case 19:
- name = "Riau";
- break;
- case 20:
- name = "Sulawesi Selatan";
- break;
- case 21:
- name = "Sulawesi Tengah";
- break;
- case 22:
- name = "Sulawesi Tenggara";
- break;
- case 23:
- name = "Sulawesi Utara";
- break;
- case 24:
- name = "Sumatera Barat";
- break;
- case 25:
- name = "Sumatera Selatan";
- break;
- case 26:
- name = "Sumatera Utara";
- break;
- case 28:
- name = "Maluku";
- break;
- case 29:
- name = "Maluku Utara";
- break;
- case 30:
- name = "Jawa Barat";
- break;
- case 31:
- name = "Sulawesi Utara";
- break;
- case 32:
- name = "Sumatera Selatan";
- break;
- case 33:
- name = "Banten";
- break;
- case 34:
- name = "Gorontalo";
- break;
- case 35:
- name = "Kepulauan Bangka Belitung";
- break;
- case 36:
- name = "Papua";
- break;
- case 37:
- name = "Riau";
- break;
- case 38:
- name = "Sulawesi Selatan";
- break;
- case 39:
- name = "Irian Jaya Barat";
- break;
- case 40:
- name = "Kepulauan Riau";
- break;
- case 41:
- name = "Sulawesi Barat";
- break;
- }
- }
- if (country_code.equals("IE") == true) {
- switch (region_code2) {
- case 1:
- name = "Carlow";
- break;
- case 2:
- name = "Cavan";
- break;
- case 3:
- name = "Clare";
- break;
- case 4:
- name = "Cork";
- break;
- case 6:
- name = "Donegal";
- break;
- case 7:
- name = "Dublin";
- break;
- case 10:
- name = "Galway";
- break;
- case 11:
- name = "Kerry";
- break;
- case 12:
- name = "Kildare";
- break;
- case 13:
- name = "Kilkenny";
- break;
- case 14:
- name = "Leitrim";
- break;
- case 15:
- name = "Laois";
- break;
- case 16:
- name = "Limerick";
- break;
- case 18:
- name = "Longford";
- break;
- case 19:
- name = "Louth";
- break;
- case 20:
- name = "Mayo";
- break;
- case 21:
- name = "Meath";
- break;
- case 22:
- name = "Monaghan";
- break;
- case 23:
- name = "Offaly";
- break;
- case 24:
- name = "Roscommon";
- break;
- case 25:
- name = "Sligo";
- break;
- case 26:
- name = "Tipperary";
- break;
- case 27:
- name = "Waterford";
- break;
- case 29:
- name = "Westmeath";
- break;
- case 30:
- name = "Wexford";
- break;
- case 31:
- name = "Wicklow";
- break;
- }
- }
- if (country_code.equals("IL") == true) {
- switch (region_code2) {
- case 1:
- name = "HaDarom";
- break;
- case 2:
- name = "HaMerkaz";
- break;
- case 3:
- name = "HaZafon";
- break;
- case 4:
- name = "Hefa";
- break;
- case 5:
- name = "Tel Aviv";
- break;
- case 6:
- name = "Yerushalayim";
- break;
- }
- }
- if (country_code.equals("IN") == true) {
- switch (region_code2) {
- case 1:
- name = "Andaman and Nicobar Islands";
- break;
- case 2:
- name = "Andhra Pradesh";
- break;
- case 3:
- name = "Assam";
- break;
- case 5:
- name = "Chandigarh";
- break;
- case 6:
- name = "Dadra and Nagar Haveli";
- break;
- case 7:
- name = "Delhi";
- break;
- case 9:
- name = "Gujarat";
- break;
- case 10:
- name = "Haryana";
- break;
- case 11:
- name = "Himachal Pradesh";
- break;
- case 12:
- name = "Jammu and Kashmir";
- break;
- case 13:
- name = "Kerala";
- break;
- case 14:
- name = "Lakshadweep";
- break;
- case 16:
- name = "Maharashtra";
- break;
- case 17:
- name = "Manipur";
- break;
- case 18:
- name = "Meghalaya";
- break;
- case 19:
- name = "Karnataka";
- break;
- case 20:
- name = "Nagaland";
- break;
- case 21:
- name = "Orissa";
- break;
- case 22:
- name = "Puducherry";
- break;
- case 23:
- name = "Punjab";
- break;
- case 24:
- name = "Rajasthan";
- break;
- case 25:
- name = "Tamil Nadu";
- break;
- case 26:
- name = "Tripura";
- break;
- case 28:
- name = "West Bengal";
- break;
- case 29:
- name = "Sikkim";
- break;
- case 30:
- name = "Arunachal Pradesh";
- break;
- case 31:
- name = "Mizoram";
- break;
- case 32:
- name = "Daman and Diu";
- break;
- case 33:
- name = "Goa";
- break;
- case 34:
- name = "Bihar";
- break;
- case 35:
- name = "Madhya Pradesh";
- break;
- case 36:
- name = "Uttar Pradesh";
- break;
- case 37:
- name = "Chhattisgarh";
- break;
- case 38:
- name = "Jharkhand";
- break;
- case 39:
- name = "Uttarakhand";
- break;
- }
- }
- if (country_code.equals("IQ") == true) {
- switch (region_code2) {
- case 1:
- name = "Al Anbar";
- break;
- case 2:
- name = "Al Basrah";
- break;
- case 3:
- name = "Al Muthanna";
- break;
- case 4:
- name = "Al Qadisiyah";
- break;
- case 5:
- name = "As Sulaymaniyah";
- break;
- case 6:
- name = "Babil";
- break;
- case 7:
- name = "Baghdad";
- break;
- case 8:
- name = "Dahuk";
- break;
- case 9:
- name = "Dhi Qar";
- break;
- case 10:
- name = "Diyala";
- break;
- case 11:
- name = "Arbil";
- break;
- case 12:
- name = "Karbala'";
- break;
- case 13:
- name = "At Ta'mim";
- break;
- case 14:
- name = "Maysan";
- break;
- case 15:
- name = "Ninawa";
- break;
- case 16:
- name = "Wasit";
- break;
- case 17:
- name = "An Najaf";
- break;
- case 18:
- name = "Salah ad Din";
- break;
- }
- }
- if (country_code.equals("IR") == true) {
- switch (region_code2) {
- case 1:
- name = "Azarbayjan-e Bakhtari";
- break;
- case 2:
- name = "Azarbayjan-e Khavari";
- break;
- case 3:
- name = "Chahar Mahall va Bakhtiari";
- break;
- case 4:
- name = "Sistan va Baluchestan";
- break;
- case 5:
- name = "Kohkiluyeh va Buyer Ahmadi";
- break;
- case 7:
- name = "Fars";
- break;
- case 8:
- name = "Gilan";
- break;
- case 9:
- name = "Hamadan";
- break;
- case 10:
- name = "Ilam";
- break;
- case 11:
- name = "Hormozgan";
- break;
- case 12:
- name = "Kerman";
- break;
- case 13:
- name = "Bakhtaran";
- break;
- case 15:
- name = "Khuzestan";
- break;
- case 16:
- name = "Kordestan";
- break;
- case 17:
- name = "Mazandaran";
- break;
- case 18:
- name = "Semnan Province";
- break;
- case 19:
- name = "Markazi";
- break;
- case 21:
- name = "Zanjan";
- break;
- case 22:
- name = "Bushehr";
- break;
- case 23:
- name = "Lorestan";
- break;
- case 24:
- name = "Markazi";
- break;
- case 25:
- name = "Semnan";
- break;
- case 26:
- name = "Tehran";
- break;
- case 27:
- name = "Zanjan";
- break;
- case 28:
- name = "Esfahan";
- break;
- case 29:
- name = "Kerman";
- break;
- case 30:
- name = "Khorasan";
- break;
- case 31:
- name = "Yazd";
- break;
- case 32:
- name = "Ardabil";
- break;
- case 33:
- name = "East Azarbaijan";
- break;
- case 34:
- name = "Markazi";
- break;
- case 35:
- name = "Mazandaran";
- break;
- case 36:
- name = "Zanjan";
- break;
- case 37:
- name = "Golestan";
- break;
- case 38:
- name = "Qazvin";
- break;
- case 39:
- name = "Qom";
- break;
- case 40:
- name = "Yazd";
- break;
- case 41:
- name = "Khorasan-e Janubi";
- break;
- case 42:
- name = "Khorasan-e Razavi";
- break;
- case 43:
- name = "Khorasan-e Shemali";
- break;
- }
- }
- if (country_code.equals("IS") == true) {
- switch (region_code2) {
- case 3:
- name = "Arnessysla";
- break;
- case 5:
- name = "Austur-Hunavatnssysla";
- break;
- case 6:
- name = "Austur-Skaftafellssysla";
- break;
- case 7:
- name = "Borgarfjardarsysla";
- break;
- case 9:
- name = "Eyjafjardarsysla";
- break;
- case 10:
- name = "Gullbringusysla";
- break;
- case 15:
- name = "Kjosarsysla";
- break;
- case 17:
- name = "Myrasysla";
- break;
- case 20:
- name = "Nordur-Mulasysla";
- break;
- case 21:
- name = "Nordur-Tingeyjarsysla";
- break;
- case 23:
- name = "Rangarvallasysla";
- break;
- case 28:
- name = "Skagafjardarsysla";
- break;
- case 29:
- name = "Snafellsnes- og Hnappadalssysla";
- break;
- case 30:
- name = "Strandasysla";
- break;
- case 31:
- name = "Sudur-Mulasysla";
- break;
- case 32:
- name = "Sudur-Tingeyjarsysla";
- break;
- case 34:
- name = "Vestur-Bardastrandarsysla";
- break;
- case 35:
- name = "Vestur-Hunavatnssysla";
- break;
- case 36:
- name = "Vestur-Isafjardarsysla";
- break;
- case 37:
- name = "Vestur-Skaftafellssysla";
- break;
- case 40:
- name = "Norourland Eystra";
- break;
- case 41:
- name = "Norourland Vestra";
- break;
- case 42:
- name = "Suourland";
- break;
- case 43:
- name = "Suournes";
- break;
- case 44:
- name = "Vestfiroir";
- break;
- case 45:
- name = "Vesturland";
- break;
- }
- }
- if (country_code.equals("IT") == true) {
- switch (region_code2) {
- case 1:
- name = "Abruzzi";
- break;
- case 2:
- name = "Basilicata";
- break;
- case 3:
- name = "Calabria";
- break;
- case 4:
- name = "Campania";
- break;
- case 5:
- name = "Emilia-Romagna";
- break;
- case 6:
- name = "Friuli-Venezia Giulia";
- break;
- case 7:
- name = "Lazio";
- break;
- case 8:
- name = "Liguria";
- break;
- case 9:
- name = "Lombardia";
- break;
- case 10:
- name = "Marche";
- break;
- case 11:
- name = "Molise";
- break;
- case 12:
- name = "Piemonte";
- break;
- case 13:
- name = "Puglia";
- break;
- case 14:
- name = "Sardegna";
- break;
- case 15:
- name = "Sicilia";
- break;
- case 16:
- name = "Toscana";
- break;
- case 17:
- name = "Trentino-Alto Adige";
- break;
- case 18:
- name = "Umbria";
- break;
- case 19:
- name = "Valle d'Aosta";
- break;
- case 20:
- name = "Veneto";
- break;
- }
- }
- if (country_code.equals("JM") == true) {
- switch (region_code2) {
- case 1:
- name = "Clarendon";
- break;
- case 2:
- name = "Hanover";
- break;
- case 4:
- name = "Manchester";
- break;
- case 7:
- name = "Portland";
- break;
- case 8:
- name = "Saint Andrew";
- break;
- case 9:
- name = "Saint Ann";
- break;
- case 10:
- name = "Saint Catherine";
- break;
- case 11:
- name = "Saint Elizabeth";
- break;
- case 12:
- name = "Saint James";
- break;
- case 13:
- name = "Saint Mary";
- break;
- case 14:
- name = "Saint Thomas";
- break;
- case 15:
- name = "Trelawny";
- break;
- case 16:
- name = "Westmoreland";
- break;
- case 17:
- name = "Kingston";
- break;
- }
- }
- if (country_code.equals("JO") == true) {
- switch (region_code2) {
- case 2:
- name = "Al Balqa'";
- break;
- case 7:
- name = "Ma";
- break;
- case 9:
- name = "Al Karak";
- break;
- case 10:
- name = "Al Mafraq";
- break;
- case 11:
- name = "Amman Governorate";
- break;
- case 12:
- name = "At Tafilah";
- break;
- case 13:
- name = "Az Zarqa";
- break;
- case 14:
- name = "Irbid";
- break;
- case 16:
- name = "Amman";
- break;
- }
- }
- if (country_code.equals("JP") == true) {
- switch (region_code2) {
- case 1:
- name = "Aichi";
- break;
- case 2:
- name = "Akita";
- break;
- case 3:
- name = "Aomori";
- break;
- case 4:
- name = "Chiba";
- break;
- case 5:
- name = "Ehime";
- break;
- case 6:
- name = "Fukui";
- break;
- case 7:
- name = "Fukuoka";
- break;
- case 8:
- name = "Fukushima";
- break;
- case 9:
- name = "Gifu";
- break;
- case 10:
- name = "Gumma";
- break;
- case 11:
- name = "Hiroshima";
- break;
- case 12:
- name = "Hokkaido";
- break;
- case 13:
- name = "Hyogo";
- break;
- case 14:
- name = "Ibaraki";
- break;
- case 15:
- name = "Ishikawa";
- break;
- case 16:
- name = "Iwate";
- break;
- case 17:
- name = "Kagawa";
- break;
- case 18:
- name = "Kagoshima";
- break;
- case 19:
- name = "Kanagawa";
- break;
- case 20:
- name = "Kochi";
- break;
- case 21:
- name = "Kumamoto";
- break;
- case 22:
- name = "Kyoto";
- break;
- case 23:
- name = "Mie";
- break;
- case 24:
- name = "Miyagi";
- break;
- case 25:
- name = "Miyazaki";
- break;
- case 26:
- name = "Nagano";
- break;
- case 27:
- name = "Nagasaki";
- break;
- case 28:
- name = "Nara";
- break;
- case 29:
- name = "Niigata";
- break;
- case 30:
- name = "Oita";
- break;
- case 31:
- name = "Okayama";
- break;
- case 32:
- name = "Osaka";
- break;
- case 33:
- name = "Saga";
- break;
- case 34:
- name = "Saitama";
- break;
- case 35:
- name = "Shiga";
- break;
- case 36:
- name = "Shimane";
- break;
- case 37:
- name = "Shizuoka";
- break;
- case 38:
- name = "Tochigi";
- break;
- case 39:
- name = "Tokushima";
- break;
- case 40:
- name = "Tokyo";
- break;
- case 41:
- name = "Tottori";
- break;
- case 42:
- name = "Toyama";
- break;
- case 43:
- name = "Wakayama";
- break;
- case 44:
- name = "Yamagata";
- break;
- case 45:
- name = "Yamaguchi";
- break;
- case 46:
- name = "Yamanashi";
- break;
- case 47:
- name = "Okinawa";
- break;
- }
- }
- if (country_code.equals("KE") == true) {
- switch (region_code2) {
- case 1:
- name = "Central";
- break;
- case 2:
- name = "Coast";
- break;
- case 3:
- name = "Eastern";
- break;
- case 5:
- name = "Nairobi Area";
- break;
- case 6:
- name = "North-Eastern";
- break;
- case 7:
- name = "Nyanza";
- break;
- case 8:
- name = "Rift Valley";
- break;
- case 9:
- name = "Western";
- break;
- }
- }
- if (country_code.equals("KG") == true) {
- switch (region_code2) {
- case 1:
- name = "Bishkek";
- break;
- case 2:
- name = "Chuy";
- break;
- case 3:
- name = "Jalal-Abad";
- break;
- case 4:
- name = "Naryn";
- break;
- case 5:
- name = "Osh";
- break;
- case 6:
- name = "Talas";
- break;
- case 7:
- name = "Ysyk-Kol";
- break;
- case 8:
- name = "Osh";
- break;
- case 9:
- name = "Batken";
- break;
- }
- }
- if (country_code.equals("KH") == true) {
- switch (region_code2) {
- case 1:
- name = "Batdambang";
- break;
- case 2:
- name = "Kampong Cham";
- break;
- case 3:
- name = "Kampong Chhnang";
- break;
- case 4:
- name = "Kampong Speu";
- break;
- case 5:
- name = "Kampong Thum";
- break;
- case 6:
- name = "Kampot";
- break;
- case 7:
- name = "Kandal";
- break;
- case 8:
- name = "Koh Kong";
- break;
- case 9:
- name = "Kracheh";
- break;
- case 10:
- name = "Mondulkiri";
- break;
- case 11:
- name = "Phnum Penh";
- break;
- case 12:
- name = "Pursat";
- break;
- case 13:
- name = "Preah Vihear";
- break;
- case 14:
- name = "Prey Veng";
- break;
- case 15:
- name = "Ratanakiri Kiri";
- break;
- case 16:
- name = "Siem Reap";
- break;
- case 17:
- name = "Stung Treng";
- break;
- case 18:
- name = "Svay Rieng";
- break;
- case 19:
- name = "Takeo";
- break;
- case 25:
- name = "Banteay Meanchey";
- break;
- case 29:
- name = "Batdambang";
- break;
- case 30:
- name = "Pailin";
- break;
- }
- }
- if (country_code.equals("KI") == true) {
- switch (region_code2) {
- case 1:
- name = "Gilbert Islands";
- break;
- case 2:
- name = "Line Islands";
- break;
- case 3:
- name = "Phoenix Islands";
- break;
- }
- }
- if (country_code.equals("KM") == true) {
- switch (region_code2) {
- case 1:
- name = "Anjouan";
- break;
- case 2:
- name = "Grande Comore";
- break;
- case 3:
- name = "Moheli";
- break;
- }
- }
- if (country_code.equals("KN") == true) {
- switch (region_code2) {
- case 1:
- name = "Christ Church Nichola Town";
- break;
- case 2:
- name = "Saint Anne Sandy Point";
- break;
- case 3:
- name = "Saint George Basseterre";
- break;
- case 4:
- name = "Saint George Gingerland";
- break;
- case 5:
- name = "Saint James Windward";
- break;
- case 6:
- name = "Saint John Capisterre";
- break;
- case 7:
- name = "Saint John Figtree";
- break;
- case 8:
- name = "Saint Mary Cayon";
- break;
- case 9:
- name = "Saint Paul Capisterre";
- break;
- case 10:
- name = "Saint Paul Charlestown";
- break;
- case 11:
- name = "Saint Peter Basseterre";
- break;
- case 12:
- name = "Saint Thomas Lowland";
- break;
- case 13:
- name = "Saint Thomas Middle Island";
- break;
- case 15:
- name = "Trinity Palmetto Point";
- break;
- }
- }
- if (country_code.equals("KP") == true) {
- switch (region_code2) {
- case 1:
- name = "Chagang-do";
- break;
- case 3:
- name = "Hamgyong-namdo";
- break;
- case 6:
- name = "Hwanghae-namdo";
- break;
- case 7:
- name = "Hwanghae-bukto";
- break;
- case 8:
- name = "Kaesong-si";
- break;
- case 9:
- name = "Kangwon-do";
- break;
- case 11:
- name = "P'yongan-bukto";
- break;
- case 12:
- name = "P'yongyang-si";
- break;
- case 13:
- name = "Yanggang-do";
- break;
- case 14:
- name = "Namp'o-si";
- break;
- case 15:
- name = "P'yongan-namdo";
- break;
- case 17:
- name = "Hamgyong-bukto";
- break;
- case 18:
- name = "Najin Sonbong-si";
- break;
- }
- }
- if (country_code.equals("KR") == true) {
- switch (region_code2) {
- case 1:
- name = "Cheju-do";
- break;
- case 3:
- name = "Cholla-bukto";
- break;
- case 5:
- name = "Ch'ungch'ong-bukto";
- break;
- case 6:
- name = "Kangwon-do";
- break;
- case 10:
- name = "Pusan-jikhalsi";
- break;
- case 11:
- name = "Seoul-t'ukpyolsi";
- break;
- case 12:
- name = "Inch'on-jikhalsi";
- break;
- case 13:
- name = "Kyonggi-do";
- break;
- case 14:
- name = "Kyongsang-bukto";
- break;
- case 15:
- name = "Taegu-jikhalsi";
- break;
- case 16:
- name = "Cholla-namdo";
- break;
- case 17:
- name = "Ch'ungch'ong-namdo";
- break;
- case 18:
- name = "Kwangju-jikhalsi";
- break;
- case 19:
- name = "Taejon-jikhalsi";
- break;
- case 20:
- name = "Kyongsang-namdo";
- break;
- case 21:
- name = "Ulsan-gwangyoksi";
- break;
- }
- }
- if (country_code.equals("KW") == true) {
- switch (region_code2) {
- case 1:
- name = "Al Ahmadi";
- break;
- case 2:
- name = "Al Kuwayt";
- break;
- case 5:
- name = "Al Jahra";
- break;
- case 7:
- name = "Al Farwaniyah";
- break;
- case 8:
- name = "Hawalli";
- break;
- case 9:
- name = "Mubarak al Kabir";
- break;
- }
- }
- if (country_code.equals("KY") == true) {
- switch (region_code2) {
- case 1:
- name = "Creek";
- break;
- case 2:
- name = "Eastern";
- break;
- case 3:
- name = "Midland";
- break;
- case 4:
- name = "South Town";
- break;
- case 5:
- name = "Spot Bay";
- break;
- case 6:
- name = "Stake Bay";
- break;
- case 7:
- name = "West End";
- break;
- case 8:
- name = "Western";
- break;
- }
- }
- if (country_code.equals("KZ") == true) {
- switch (region_code2) {
- case 1:
- name = "Almaty";
- break;
- case 2:
- name = "Almaty City";
- break;
- case 3:
- name = "Aqmola";
- break;
- case 4:
- name = "Aqtobe";
- break;
- case 5:
- name = "Astana";
- break;
- case 6:
- name = "Atyrau";
- break;
- case 7:
- name = "West Kazakhstan";
- break;
- case 8:
- name = "Bayqonyr";
- break;
- case 9:
- name = "Mangghystau";
- break;
- case 10:
- name = "South Kazakhstan";
- break;
- case 11:
- name = "Pavlodar";
- break;
- case 12:
- name = "Qaraghandy";
- break;
- case 13:
- name = "Qostanay";
- break;
- case 14:
- name = "Qyzylorda";
- break;
- case 15:
- name = "East Kazakhstan";
- break;
- case 16:
- name = "North Kazakhstan";
- break;
- case 17:
- name = "Zhambyl";
- break;
- }
- }
- if (country_code.equals("LA") == true) {
- switch (region_code2) {
- case 1:
- name = "Attapu";
- break;
- case 2:
- name = "Champasak";
- break;
- case 3:
- name = "Houaphan";
- break;
- case 4:
- name = "Khammouan";
- break;
- case 5:
- name = "Louang Namtha";
- break;
- case 7:
- name = "Oudomxai";
- break;
- case 8:
- name = "Phongsali";
- break;
- case 9:
- name = "Saravan";
- break;
- case 10:
- name = "Savannakhet";
- break;
- case 11:
- name = "Vientiane";
- break;
- case 13:
- name = "Xaignabouri";
- break;
- case 14:
- name = "Xiangkhoang";
- break;
- case 17:
- name = "Louangphrabang";
- break;
- }
- }
- if (country_code.equals("LB") == true) {
- switch (region_code2) {
- case 1:
- name = "Beqaa";
- break;
- case 2:
- name = "Al Janub";
- break;
- case 3:
- name = "Liban-Nord";
- break;
- case 4:
- name = "Beyrouth";
- break;
- case 5:
- name = "Mont-Liban";
- break;
- case 6:
- name = "Liban-Sud";
- break;
- case 7:
- name = "Nabatiye";
- break;
- case 8:
- name = "Beqaa";
- break;
- case 9:
- name = "Liban-Nord";
- break;
- case 10:
- name = "Aakk";
- break;
- case 11:
- name = "Baalbek-Hermel";
- break;
- }
- }
- if (country_code.equals("LC") == true) {
- switch (region_code2) {
- case 1:
- name = "Anse-la-Raye";
- break;
- case 2:
- name = "Dauphin";
- break;
- case 3:
- name = "Castries";
- break;
- case 4:
- name = "Choiseul";
- break;
- case 5:
- name = "Dennery";
- break;
- case 6:
- name = "Gros-Islet";
- break;
- case 7:
- name = "Laborie";
- break;
- case 8:
- name = "Micoud";
- break;
- case 9:
- name = "Soufriere";
- break;
- case 10:
- name = "Vieux-Fort";
- break;
- case 11:
- name = "Praslin";
- break;
- }
- }
- if (country_code.equals("LI") == true) {
- switch (region_code2) {
- case 1:
- name = "Balzers";
- break;
- case 2:
- name = "Eschen";
- break;
- case 3:
- name = "Gamprin";
- break;
- case 4:
- name = "Mauren";
- break;
- case 5:
- name = "Planken";
- break;
- case 6:
- name = "Ruggell";
- break;
- case 7:
- name = "Schaan";
- break;
- case 8:
- name = "Schellenberg";
- break;
- case 9:
- name = "Triesen";
- break;
- case 10:
- name = "Triesenberg";
- break;
- case 11:
- name = "Vaduz";
- break;
- case 21:
- name = "Gbarpolu";
- break;
- case 22:
- name = "River Gee";
- break;
- }
- }
- if (country_code.equals("LK") == true) {
- switch (region_code2) {
- case 1:
- name = "Amparai";
- break;
- case 2:
- name = "Anuradhapura";
- break;
- case 3:
- name = "Badulla";
- break;
- case 4:
- name = "Batticaloa";
- break;
- case 6:
- name = "Galle";
- break;
- case 7:
- name = "Hambantota";
- break;
- case 9:
- name = "Kalutara";
- break;
- case 10:
- name = "Kandy";
- break;
- case 11:
- name = "Kegalla";
- break;
- case 12:
- name = "Kurunegala";
- break;
- case 14:
- name = "Matale";
- break;
- case 15:
- name = "Matara";
- break;
- case 16:
- name = "Moneragala";
- break;
- case 17:
- name = "Nuwara Eliya";
- break;
- case 18:
- name = "Polonnaruwa";
- break;
- case 19:
- name = "Puttalam";
- break;
- case 20:
- name = "Ratnapura";
- break;
- case 21:
- name = "Trincomalee";
- break;
- case 23:
- name = "Colombo";
- break;
- case 24:
- name = "Gampaha";
- break;
- case 25:
- name = "Jaffna";
- break;
- case 26:
- name = "Mannar";
- break;
- case 27:
- name = "Mullaittivu";
- break;
- case 28:
- name = "Vavuniya";
- break;
- case 29:
- name = "Central";
- break;
- case 30:
- name = "North Central";
- break;
- case 31:
- name = "Northern";
- break;
- case 32:
- name = "North Western";
- break;
- case 33:
- name = "Sabaragamuwa";
- break;
- case 34:
- name = "Southern";
- break;
- case 35:
- name = "Uva";
- break;
- case 36:
- name = "Western";
- break;
- }
- }
- if (country_code.equals("LR") == true) {
- switch (region_code2) {
- case 1:
- name = "Bong";
- break;
- case 4:
- name = "Grand Cape Mount";
- break;
- case 5:
- name = "Lofa";
- break;
- case 6:
- name = "Maryland";
- break;
- case 7:
- name = "Monrovia";
- break;
- case 9:
- name = "Nimba";
- break;
- case 10:
- name = "Sino";
- break;
- case 11:
- name = "Grand Bassa";
- break;
- case 12:
- name = "Grand Cape Mount";
- break;
- case 13:
- name = "Maryland";
- break;
- case 14:
- name = "Montserrado";
- break;
- case 17:
- name = "Margibi";
- break;
- case 18:
- name = "River Cess";
- break;
- case 19:
- name = "Grand Gedeh";
- break;
- case 20:
- name = "Lofa";
- break;
- case 21:
- name = "Gbarpolu";
- break;
- case 22:
- name = "River Gee";
- break;
- }
- }
- if (country_code.equals("LS") == true) {
- switch (region_code2) {
- case 10:
- name = "Berea";
- break;
- case 11:
- name = "Butha-Buthe";
- break;
- case 12:
- name = "Leribe";
- break;
- case 13:
- name = "Mafeteng";
- break;
- case 14:
- name = "Maseru";
- break;
- case 15:
- name = "Mohales Hoek";
- break;
- case 16:
- name = "Mokhotlong";
- break;
- case 17:
- name = "Qachas Nek";
- break;
- case 18:
- name = "Quthing";
- break;
- case 19:
- name = "Thaba-Tseka";
- break;
- }
- }
- if (country_code.equals("LT") == true) {
- switch (region_code2) {
- case 56:
- name = "Alytaus Apskritis";
- break;
- case 57:
- name = "Kauno Apskritis";
- break;
- case 58:
- name = "Klaipedos Apskritis";
- break;
- case 59:
- name = "Marijampoles Apskritis";
- break;
- case 60:
- name = "Panevezio Apskritis";
- break;
- case 61:
- name = "Siauliu Apskritis";
- break;
- case 62:
- name = "Taurages Apskritis";
- break;
- case 63:
- name = "Telsiu Apskritis";
- break;
- case 64:
- name = "Utenos Apskritis";
- break;
- case 65:
- name = "Vilniaus Apskritis";
- break;
- }
- }
- if (country_code.equals("LU") == true) {
- switch (region_code2) {
- case 1:
- name = "Diekirch";
- break;
- case 2:
- name = "Grevenmacher";
- break;
- case 3:
- name = "Luxembourg";
- break;
- }
- }
- if (country_code.equals("LV") == true) {
- switch (region_code2) {
- case 1:
- name = "Aizkraukles";
- break;
- case 2:
- name = "Aluksnes";
- break;
- case 3:
- name = "Balvu";
- break;
- case 4:
- name = "Bauskas";
- break;
- case 5:
- name = "Cesu";
- break;
- case 6:
- name = "Daugavpils";
- break;
- case 7:
- name = "Daugavpils";
- break;
- case 8:
- name = "Dobeles";
- break;
- case 9:
- name = "Gulbenes";
- break;
- case 10:
- name = "Jekabpils";
- break;
- case 11:
- name = "Jelgava";
- break;
- case 12:
- name = "Jelgavas";
- break;
- case 13:
- name = "Jurmala";
- break;
- case 14:
- name = "Kraslavas";
- break;
- case 15:
- name = "Kuldigas";
- break;
- case 16:
- name = "Liepaja";
- break;
- case 17:
- name = "Liepajas";
- break;
- case 18:
- name = "Limbazu";
- break;
- case 19:
- name = "Ludzas";
- break;
- case 20:
- name = "Madonas";
- break;
- case 21:
- name = "Ogres";
- break;
- case 22:
- name = "Preilu";
- break;
- case 23:
- name = "Rezekne";
- break;
- case 24:
- name = "Rezeknes";
- break;
- case 25:
- name = "Riga";
- break;
- case 26:
- name = "Rigas";
- break;
- case 27:
- name = "Saldus";
- break;
- case 28:
- name = "Talsu";
- break;
- case 29:
- name = "Tukuma";
- break;
- case 30:
- name = "Valkas";
- break;
- case 31:
- name = "Valmieras";
- break;
- case 32:
- name = "Ventspils";
- break;
- case 33:
- name = "Ventspils";
- break;
- }
- }
- if (country_code.equals("LY") == true) {
- switch (region_code2) {
- case 3:
- name = "Al Aziziyah";
- break;
- case 5:
- name = "Al Jufrah";
- break;
- case 8:
- name = "Al Kufrah";
- break;
- case 13:
- name = "Ash Shati'";
- break;
- case 30:
- name = "Murzuq";
- break;
- case 34:
- name = "Sabha";
- break;
- case 41:
- name = "Tarhunah";
- break;
- case 42:
- name = "Tubruq";
- break;
- case 45:
- name = "Zlitan";
- break;
- case 47:
- name = "Ajdabiya";
- break;
- case 48:
- name = "Al Fatih";
- break;
- case 49:
- name = "Al Jabal al Akhdar";
- break;
- case 50:
- name = "Al Khums";
- break;
- case 51:
- name = "An Nuqat al Khams";
- break;
- case 52:
- name = "Awbari";
- break;
- case 53:
- name = "Az Zawiyah";
- break;
- case 54:
- name = "Banghazi";
- break;
- case 55:
- name = "Darnah";
- break;
- case 56:
- name = "Ghadamis";
- break;
- case 57:
- name = "Gharyan";
- break;
- case 58:
- name = "Misratah";
- break;
- case 59:
- name = "Sawfajjin";
- break;
- case 60:
- name = "Surt";
- break;
- case 61:
- name = "Tarabulus";
- break;
- case 62:
- name = "Yafran";
- break;
- }
- }
- if (country_code.equals("MA") == true) {
- switch (region_code2) {
- case 1:
- name = "Agadir";
- break;
- case 2:
- name = "Al Hoceima";
- break;
- case 3:
- name = "Azilal";
- break;
- case 4:
- name = "Ben Slimane";
- break;
- case 5:
- name = "Beni Mellal";
- break;
- case 6:
- name = "Boulemane";
- break;
- case 7:
- name = "Casablanca";
- break;
- case 8:
- name = "Chaouen";
- break;
- case 9:
- name = "El Jadida";
- break;
- case 10:
- name = "El Kelaa des Srarhna";
- break;
- case 11:
- name = "Er Rachidia";
- break;
- case 12:
- name = "Essaouira";
- break;
- case 13:
- name = "Fes";
- break;
- case 14:
- name = "Figuig";
- break;
- case 15:
- name = "Kenitra";
- break;
- case 16:
- name = "Khemisset";
- break;
- case 17:
- name = "Khenifra";
- break;
- case 18:
- name = "Khouribga";
- break;
- case 19:
- name = "Marrakech";
- break;
- case 20:
- name = "Meknes";
- break;
- case 21:
- name = "Nador";
- break;
- case 22:
- name = "Ouarzazate";
- break;
- case 23:
- name = "Oujda";
- break;
- case 24:
- name = "Rabat-Sale";
- break;
- case 25:
- name = "Safi";
- break;
- case 26:
- name = "Settat";
- break;
- case 27:
- name = "Tanger";
- break;
- case 29:
- name = "Tata";
- break;
- case 30:
- name = "Taza";
- break;
- case 32:
- name = "Tiznit";
- break;
- case 33:
- name = "Guelmim";
- break;
- case 34:
- name = "Ifrane";
- break;
- case 35:
- name = "Laayoune";
- break;
- case 36:
- name = "Tan-Tan";
- break;
- case 37:
- name = "Taounate";
- break;
- case 38:
- name = "Sidi Kacem";
- break;
- case 39:
- name = "Taroudannt";
- break;
- case 40:
- name = "Tetouan";
- break;
- case 41:
- name = "Larache";
- break;
- case 45:
- name = "Grand Casablanca";
- break;
- case 46:
- name = "Fes-Boulemane";
- break;
- case 47:
- name = "Marrakech-Tensift-Al Haouz";
- break;
- case 48:
- name = "Meknes-Tafilalet";
- break;
- case 49:
- name = "Rabat-Sale-Zemmour-Zaer";
- break;
- case 50:
- name = "Chaouia-Ouardigha";
- break;
- case 51:
- name = "Doukkala-Abda";
- break;
- case 52:
- name = "Gharb-Chrarda-Beni Hssen";
- break;
- case 53:
- name = "Guelmim-Es Smara";
- break;
- case 54:
- name = "Oriental";
- break;
- case 55:
- name = "Souss-Massa-Dr";
- break;
- case 56:
- name = "Tadla-Azilal";
- break;
- case 57:
- name = "Tanger-Tetouan";
- break;
- case 58:
- name = "Taza-Al Hoceima-Taounate";
- break;
- case 59:
- name = "La";
- break;
- }
- }
- if (country_code.equals("MC") == true) {
- switch (region_code2) {
- case 1:
- name = "La Condamine";
- break;
- case 2:
- name = "Monaco";
- break;
- case 3:
- name = "Monte-Carlo";
- break;
- }
- }
- if (country_code.equals("MD") == true) {
- switch (region_code2) {
- case 46:
- name = "Balti";
- break;
- case 47:
- name = "Cahul";
- break;
- case 48:
- name = "Chisinau";
- break;
- case 49:
- name = "Stinga Nistrului";
- break;
- case 50:
- name = "Edinet";
- break;
- case 51:
- name = "Gagauzia";
- break;
- case 52:
- name = "Lapusna";
- break;
- case 53:
- name = "Orhei";
- break;
- case 54:
- name = "Soroca";
- break;
- case 55:
- name = "Tighina";
- break;
- case 56:
- name = "Ungheni";
- break;
- case 58:
- name = "Stinga Nistrului";
- break;
- case 59:
- name = "Anenii Noi";
- break;
- case 60:
- name = "Balti";
- break;
- case 61:
- name = "Basarabeasca";
- break;
- case 62:
- name = "Bender";
- break;
- case 63:
- name = "Briceni";
- break;
- case 64:
- name = "Cahul";
- break;
- case 65:
- name = "Cantemir";
- break;
- case 66:
- name = "Calarasi";
- break;
- case 67:
- name = "Causeni";
- break;
- case 68:
- name = "Cimislia";
- break;
- case 69:
- name = "Criuleni";
- break;
- case 70:
- name = "Donduseni";
- break;
- case 71:
- name = "Drochia";
- break;
- case 72:
- name = "Dubasari";
- break;
- case 73:
- name = "Edinet";
- break;
- case 74:
- name = "Falesti";
- break;
- case 75:
- name = "Floresti";
- break;
- case 76:
- name = "Glodeni";
- break;
- case 77:
- name = "Hincesti";
- break;
- case 78:
- name = "Ialoveni";
- break;
- case 79:
- name = "Leova";
- break;
- case 80:
- name = "Nisporeni";
- break;
- case 81:
- name = "Ocnita";
- break;
- case 83:
- name = "Rezina";
- break;
- case 84:
- name = "Riscani";
- break;
- case 85:
- name = "Singerei";
- break;
- case 86:
- name = "Soldanesti";
- break;
- case 87:
- name = "Soroca";
- break;
- case 88:
- name = "Stefan-Voda";
- break;
- case 89:
- name = "Straseni";
- break;
- case 90:
- name = "Taraclia";
- break;
- case 91:
- name = "Telenesti";
- break;
- case 92:
- name = "Ungheni";
- break;
- }
- }
- if (country_code.equals("MG") == true) {
- switch (region_code2) {
- case 1:
- name = "Antsiranana";
- break;
- case 2:
- name = "Fianarantsoa";
- break;
- case 3:
- name = "Mahajanga";
- break;
- case 4:
- name = "Toamasina";
- break;
- case 5:
- name = "Antananarivo";
- break;
- case 6:
- name = "Toliara";
- break;
- }
- }
- if (country_code.equals("MK") == true) {
- switch (region_code2) {
- case 1:
- name = "Aracinovo";
- break;
- case 2:
- name = "Bac";
- break;
- case 3:
- name = "Belcista";
- break;
- case 4:
- name = "Berovo";
- break;
- case 5:
- name = "Bistrica";
- break;
- case 6:
- name = "Bitola";
- break;
- case 7:
- name = "Blatec";
- break;
- case 8:
- name = "Bogdanci";
- break;
- case 9:
- name = "Bogomila";
- break;
- case 10:
- name = "Bogovinje";
- break;
- case 11:
- name = "Bosilovo";
- break;
- case 12:
- name = "Brvenica";
- break;
- case 13:
- name = "Cair";
- break;
- case 14:
- name = "Capari";
- break;
- case 15:
- name = "Caska";
- break;
- case 16:
- name = "Cegrane";
- break;
- case 17:
- name = "Centar";
- break;
- case 18:
- name = "Centar Zupa";
- break;
- case 19:
- name = "Cesinovo";
- break;
- case 20:
- name = "Cucer-Sandevo";
- break;
- case 21:
- name = "Debar";
- break;
- case 22:
- name = "Delcevo";
- break;
- case 23:
- name = "Delogozdi";
- break;
- case 24:
- name = "Demir Hisar";
- break;
- case 25:
- name = "Demir Kapija";
- break;
- case 26:
- name = "Dobrusevo";
- break;
- case 27:
- name = "Dolna Banjica";
- break;
- case 28:
- name = "Dolneni";
- break;
- case 29:
- name = "Dorce Petrov";
- break;
- case 30:
- name = "Drugovo";
- break;
- case 31:
- name = "Dzepciste";
- break;
- case 32:
- name = "Gazi Baba";
- break;
- case 33:
- name = "Gevgelija";
- break;
- case 34:
- name = "Gostivar";
- break;
- case 35:
- name = "Gradsko";
- break;
- case 36:
- name = "Ilinden";
- break;
- case 37:
- name = "Izvor";
- break;
- case 38:
- name = "Jegunovce";
- break;
- case 39:
- name = "Kamenjane";
- break;
- case 40:
- name = "Karbinci";
- break;
- case 41:
- name = "Karpos";
- break;
- case 42:
- name = "Kavadarci";
- break;
- case 43:
- name = "Kicevo";
- break;
- case 44:
- name = "Kisela Voda";
- break;
- case 45:
- name = "Klecevce";
- break;
- case 46:
- name = "Kocani";
- break;
- case 47:
- name = "Konce";
- break;
- case 48:
- name = "Kondovo";
- break;
- case 49:
- name = "Konopiste";
- break;
- case 50:
- name = "Kosel";
- break;
- case 51:
- name = "Kratovo";
- break;
- case 52:
- name = "Kriva Palanka";
- break;
- case 53:
- name = "Krivogastani";
- break;
- case 54:
- name = "Krusevo";
- break;
- case 55:
- name = "Kuklis";
- break;
- case 56:
- name = "Kukurecani";
- break;
- case 57:
- name = "Kumanovo";
- break;
- case 58:
- name = "Labunista";
- break;
- case 59:
- name = "Lipkovo";
- break;
- case 60:
- name = "Lozovo";
- break;
- case 61:
- name = "Lukovo";
- break;
- case 62:
- name = "Makedonska Kamenica";
- break;
- case 63:
- name = "Makedonski Brod";
- break;
- case 64:
- name = "Mavrovi Anovi";
- break;
- case 65:
- name = "Meseista";
- break;
- case 66:
- name = "Miravci";
- break;
- case 67:
- name = "Mogila";
- break;
- case 68:
- name = "Murtino";
- break;
- case 69:
- name = "Negotino";
- break;
- case 70:
- name = "Negotino-Polosko";
- break;
- case 71:
- name = "Novaci";
- break;
- case 72:
- name = "Novo Selo";
- break;
- case 73:
- name = "Oblesevo";
- break;
- case 74:
- name = "Ohrid";
- break;
- case 75:
- name = "Orasac";
- break;
- case 76:
- name = "Orizari";
- break;
- case 77:
- name = "Oslomej";
- break;
- case 78:
- name = "Pehcevo";
- break;
- case 79:
- name = "Petrovec";
- break;
- case 80:
- name = "Plasnica";
- break;
- case 81:
- name = "Podares";
- break;
- case 82:
- name = "Prilep";
- break;
- case 83:
- name = "Probistip";
- break;
- case 84:
- name = "Radovis";
- break;
- case 85:
- name = "Rankovce";
- break;
- case 86:
- name = "Resen";
- break;
- case 87:
- name = "Rosoman";
- break;
- case 88:
- name = "Rostusa";
- break;
- case 89:
- name = "Samokov";
- break;
- case 90:
- name = "Saraj";
- break;
- case 91:
- name = "Sipkovica";
- break;
- case 92:
- name = "Sopiste";
- break;
- case 93:
- name = "Sopotnica";
- break;
- case 94:
- name = "Srbinovo";
- break;
- case 95:
- name = "Staravina";
- break;
- case 96:
- name = "Star Dojran";
- break;
- case 97:
- name = "Staro Nagoricane";
- break;
- case 98:
- name = "Stip";
- break;
- case 99:
- name = "Struga";
- break;
- case 832:
- name = "Strumica";
- break;
- case 833:
- name = "Studenicani";
- break;
- case 834:
- name = "Suto Orizari";
- break;
- case 835:
- name = "Sveti Nikole";
- break;
- case 836:
- name = "Tearce";
- break;
- case 837:
- name = "Tetovo";
- break;
- case 838:
- name = "Topolcani";
- break;
- case 839:
- name = "Valandovo";
- break;
- case 840:
- name = "Vasilevo";
- break;
- case 875:
- name = "Veles";
- break;
- case 876:
- name = "Velesta";
- break;
- case 877:
- name = "Vevcani";
- break;
- case 878:
- name = "Vinica";
- break;
- case 879:
- name = "Vitoliste";
- break;
- case 880:
- name = "Vranestica";
- break;
- case 881:
- name = "Vrapciste";
- break;
- case 882:
- name = "Vratnica";
- break;
- case 883:
- name = "Vrutok";
- break;
- case 918:
- name = "Zajas";
- break;
- case 919:
- name = "Zelenikovo";
- break;
- case 920:
- name = "Zelino";
- break;
- case 921:
- name = "Zitose";
- break;
- case 922:
- name = "Zletovo";
- break;
- case 923:
- name = "Zrnovci";
- break;
- }
- }
- if (country_code.equals("ML") == true) {
- switch (region_code2) {
- case 1:
- name = "Bamako";
- break;
- case 3:
- name = "Kayes";
- break;
- case 4:
- name = "Mopti";
- break;
- case 5:
- name = "Segou";
- break;
- case 6:
- name = "Sikasso";
- break;
- case 7:
- name = "Koulikoro";
- break;
- case 8:
- name = "Tombouctou";
- break;
- case 9:
- name = "Gao";
- break;
- case 10:
- name = "Kidal";
- break;
- }
- }
- if (country_code.equals("MM") == true) {
- switch (region_code2) {
- case 1:
- name = "Rakhine State";
- break;
- case 2:
- name = "Chin State";
- break;
- case 3:
- name = "Irrawaddy";
- break;
- case 4:
- name = "Kachin State";
- break;
- case 5:
- name = "Karan State";
- break;
- case 6:
- name = "Kayah State";
- break;
- case 7:
- name = "Magwe";
- break;
- case 8:
- name = "Mandalay";
- break;
- case 9:
- name = "Pegu";
- break;
- case 10:
- name = "Sagaing";
- break;
- case 11:
- name = "Shan State";
- break;
- case 12:
- name = "Tenasserim";
- break;
- case 13:
- name = "Mon State";
- break;
- case 14:
- name = "Rangoon";
- break;
- case 17:
- name = "Yangon";
- break;
- }
- }
- if (country_code.equals("MN") == true) {
- switch (region_code2) {
- case 1:
- name = "Arhangay";
- break;
- case 2:
- name = "Bayanhongor";
- break;
- case 3:
- name = "Bayan-Olgiy";
- break;
- case 5:
- name = "Darhan";
- break;
- case 6:
- name = "Dornod";
- break;
- case 7:
- name = "Dornogovi";
- break;
- case 8:
- name = "Dundgovi";
- break;
- case 9:
- name = "Dzavhan";
- break;
- case 10:
- name = "Govi-Altay";
- break;
- case 11:
- name = "Hentiy";
- break;
- case 12:
- name = "Hovd";
- break;
- case 13:
- name = "Hovsgol";
- break;
- case 14:
- name = "Omnogovi";
- break;
- case 15:
- name = "Ovorhangay";
- break;
- case 16:
- name = "Selenge";
- break;
- case 17:
- name = "Suhbaatar";
- break;
- case 18:
- name = "Tov";
- break;
- case 19:
- name = "Uvs";
- break;
- case 20:
- name = "Ulaanbaatar";
- break;
- case 21:
- name = "Bulgan";
- break;
- case 22:
- name = "Erdenet";
- break;
- case 23:
- name = "Darhan-Uul";
- break;
- case 24:
- name = "Govisumber";
- break;
- case 25:
- name = "Orhon";
- break;
- }
- }
- if (country_code.equals("MO") == true) {
- switch (region_code2) {
- case 1:
- name = "Ilhas";
- break;
- case 2:
- name = "Macau";
- break;
- }
- }
- if (country_code.equals("MR") == true) {
- switch (region_code2) {
- case 1:
- name = "Hodh Ech Chargui";
- break;
- case 2:
- name = "Hodh El Gharbi";
- break;
- case 3:
- name = "Assaba";
- break;
- case 4:
- name = "Gorgol";
- break;
- case 5:
- name = "Brakna";
- break;
- case 6:
- name = "Trarza";
- break;
- case 7:
- name = "Adrar";
- break;
- case 8:
- name = "Dakhlet Nouadhibou";
- break;
- case 9:
- name = "Tagant";
- break;
- case 10:
- name = "Guidimaka";
- break;
- case 11:
- name = "Tiris Zemmour";
- break;
- case 12:
- name = "Inchiri";
- break;
- }
- }
- if (country_code.equals("MS") == true) {
- switch (region_code2) {
- case 1:
- name = "Saint Anthony";
- break;
- case 2:
- name = "Saint Georges";
- break;
- case 3:
- name = "Saint Peter";
- break;
- }
- }
- if (country_code.equals("MU") == true) {
- switch (region_code2) {
- case 12:
- name = "Black River";
- break;
- case 13:
- name = "Flacq";
- break;
- case 14:
- name = "Grand Port";
- break;
- case 15:
- name = "Moka";
- break;
- case 16:
- name = "Pamplemousses";
- break;
- case 17:
- name = "Plaines Wilhems";
- break;
- case 18:
- name = "Port Louis";
- break;
- case 19:
- name = "Riviere du Rempart";
- break;
- case 20:
- name = "Savanne";
- break;
- case 21:
- name = "Agalega Islands";
- break;
- case 22:
- name = "Cargados Carajos";
- break;
- case 23:
- name = "Rodrigues";
- break;
- }
- }
- if (country_code.equals("MV") == true) {
- switch (region_code2) {
- case 1:
- name = "Seenu";
- break;
- case 2:
- name = "Aliff";
- break;
- case 3:
- name = "Laviyani";
- break;
- case 4:
- name = "Waavu";
- break;
- case 5:
- name = "Laamu";
- break;
- case 7:
- name = "Haa Aliff";
- break;
- case 8:
- name = "Thaa";
- break;
- case 12:
- name = "Meemu";
- break;
- case 13:
- name = "Raa";
- break;
- case 14:
- name = "Faafu";
- break;
- case 17:
- name = "Daalu";
- break;
- case 20:
- name = "Baa";
- break;
- case 23:
- name = "Haa Daalu";
- break;
- case 24:
- name = "Shaviyani";
- break;
- case 25:
- name = "Noonu";
- break;
- case 26:
- name = "Kaafu";
- break;
- case 27:
- name = "Gaafu Aliff";
- break;
- case 28:
- name = "Gaafu Daalu";
- break;
- case 29:
- name = "Naviyani";
- break;
- case 40:
- name = "Male";
- break;
- }
- }
- if (country_code.equals("MW") == true) {
- switch (region_code2) {
- case 2:
- name = "Chikwawa";
- break;
- case 3:
- name = "Chiradzulu";
- break;
- case 4:
- name = "Chitipa";
- break;
- case 5:
- name = "Thyolo";
- break;
- case 6:
- name = "Dedza";
- break;
- case 7:
- name = "Dowa";
- break;
- case 8:
- name = "Karonga";
- break;
- case 9:
- name = "Kasungu";
- break;
- case 11:
- name = "Lilongwe";
- break;
- case 12:
- name = "Mangochi";
- break;
- case 13:
- name = "Mchinji";
- break;
- case 15:
- name = "Mzimba";
- break;
- case 16:
- name = "Ntcheu";
- break;
- case 17:
- name = "Nkhata Bay";
- break;
- case 18:
- name = "Nkhotakota";
- break;
- case 19:
- name = "Nsanje";
- break;
- case 20:
- name = "Ntchisi";
- break;
- case 21:
- name = "Rumphi";
- break;
- case 22:
- name = "Salima";
- break;
- case 23:
- name = "Zomba";
- break;
- case 24:
- name = "Blantyre";
- break;
- case 25:
- name = "Mwanza";
- break;
- case 26:
- name = "Balaka";
- break;
- case 27:
- name = "Likoma";
- break;
- case 28:
- name = "Machinga";
- break;
- case 29:
- name = "Mulanje";
- break;
- case 30:
- name = "Phalombe";
- break;
- }
- }
- if (country_code.equals("MX") == true) {
- switch (region_code2) {
- case 1:
- name = "Aguascalientes";
- break;
- case 2:
- name = "Baja California";
- break;
- case 3:
- name = "Baja California Sur";
- break;
- case 4:
- name = "Campeche";
- break;
- case 5:
- name = "Chiapas";
- break;
- case 6:
- name = "Chihuahua";
- break;
- case 7:
- name = "Coahuila de Zaragoza";
- break;
- case 8:
- name = "Colima";
- break;
- case 9:
- name = "Distrito Federal";
- break;
- case 10:
- name = "Durango";
- break;
- case 11:
- name = "Guanajuato";
- break;
- case 12:
- name = "Guerrero";
- break;
- case 13:
- name = "Hidalgo";
- break;
- case 14:
- name = "Jalisco";
- break;
- case 15:
- name = "Mexico";
- break;
- case 16:
- name = "Michoacan de Ocampo";
- break;
- case 17:
- name = "Morelos";
- break;
- case 18:
- name = "Nayarit";
- break;
- case 19:
- name = "Nuevo Leon";
- break;
- case 20:
- name = "Oaxaca";
- break;
- case 21:
- name = "Puebla";
- break;
- case 22:
- name = "Queretaro de Arteaga";
- break;
- case 23:
- name = "Quintana Roo";
- break;
- case 24:
- name = "San Luis Potosi";
- break;
- case 25:
- name = "Sinaloa";
- break;
- case 26:
- name = "Sonora";
- break;
- case 27:
- name = "Tabasco";
- break;
- case 28:
- name = "Tamaulipas";
- break;
- case 29:
- name = "Tlaxcala";
- break;
- case 30:
- name = "Veracruz-Llave";
- break;
- case 31:
- name = "Yucatan";
- break;
- case 32:
- name = "Zacatecas";
- break;
- }
- }
- if (country_code.equals("MY") == true) {
- switch (region_code2) {
- case 1:
- name = "Johor";
- break;
- case 2:
- name = "Kedah";
- break;
- case 3:
- name = "Kelantan";
- break;
- case 4:
- name = "Melaka";
- break;
- case 5:
- name = "Negeri Sembilan";
- break;
- case 6:
- name = "Pahang";
- break;
- case 7:
- name = "Perak";
- break;
- case 8:
- name = "Perlis";
- break;
- case 9:
- name = "Pulau Pinang";
- break;
- case 11:
- name = "Sarawak";
- break;
- case 12:
- name = "Selangor";
- break;
- case 13:
- name = "Terengganu";
- break;
- case 14:
- name = "Kuala Lumpur";
- break;
- case 15:
- name = "Labuan";
- break;
- case 16:
- name = "Sabah";
- break;
- case 17:
- name = "Putrajaya";
- break;
- }
- }
- if (country_code.equals("MZ") == true) {
- switch (region_code2) {
- case 1:
- name = "Cabo Delgado";
- break;
- case 2:
- name = "Gaza";
- break;
- case 3:
- name = "Inhambane";
- break;
- case 4:
- name = "Maputo";
- break;
- case 5:
- name = "Sofala";
- break;
- case 6:
- name = "Nampula";
- break;
- case 7:
- name = "Niassa";
- break;
- case 8:
- name = "Tete";
- break;
- case 9:
- name = "Zambezia";
- break;
- case 10:
- name = "Manica";
- break;
- case 11:
- name = "Maputo";
- break;
- }
- }
- if (country_code.equals("NA") == true) {
- switch (region_code2) {
- case 1:
- name = "Bethanien";
- break;
- case 2:
- name = "Caprivi Oos";
- break;
- case 3:
- name = "Boesmanland";
- break;
- case 4:
- name = "Gobabis";
- break;
- case 5:
- name = "Grootfontein";
- break;
- case 6:
- name = "Kaokoland";
- break;
- case 7:
- name = "Karibib";
- break;
- case 8:
- name = "Keetmanshoop";
- break;
- case 9:
- name = "Luderitz";
- break;
- case 10:
- name = "Maltahohe";
- break;
- case 11:
- name = "Okahandja";
- break;
- case 12:
- name = "Omaruru";
- break;
- case 13:
- name = "Otjiwarongo";
- break;
- case 14:
- name = "Outjo";
- break;
- case 15:
- name = "Owambo";
- break;
- case 16:
- name = "Rehoboth";
- break;
- case 17:
- name = "Swakopmund";
- break;
- case 18:
- name = "Tsumeb";
- break;
- case 20:
- name = "Karasburg";
- break;
- case 21:
- name = "Windhoek";
- break;
- case 22:
- name = "Damaraland";
- break;
- case 23:
- name = "Hereroland Oos";
- break;
- case 24:
- name = "Hereroland Wes";
- break;
- case 25:
- name = "Kavango";
- break;
- case 26:
- name = "Mariental";
- break;
- case 27:
- name = "Namaland";
- break;
- case 28:
- name = "Caprivi";
- break;
- case 29:
- name = "Erongo";
- break;
- case 30:
- name = "Hardap";
- break;
- case 31:
- name = "Karas";
- break;
- case 32:
- name = "Kunene";
- break;
- case 33:
- name = "Ohangwena";
- break;
- case 34:
- name = "Okavango";
- break;
- case 35:
- name = "Omaheke";
- break;
- case 36:
- name = "Omusati";
- break;
- case 37:
- name = "Oshana";
- break;
- case 38:
- name = "Oshikoto";
- break;
- case 39:
- name = "Otjozondjupa";
- break;
- }
- }
- if (country_code.equals("NE") == true) {
- switch (region_code2) {
- case 1:
- name = "Agadez";
- break;
- case 2:
- name = "Diffa";
- break;
- case 3:
- name = "Dosso";
- break;
- case 4:
- name = "Maradi";
- break;
- case 5:
- name = "Niamey";
- break;
- case 6:
- name = "Tahoua";
- break;
- case 7:
- name = "Zinder";
- break;
- case 8:
- name = "Niamey";
- break;
- }
- }
- if (country_code.equals("NG") == true) {
- switch (region_code2) {
- case 5:
- name = "Lagos";
- break;
- case 10:
- name = "Rivers";
- break;
- case 11:
- name = "Federal Capital Territory";
- break;
- case 12:
- name = "Gongola";
- break;
- case 16:
- name = "Ogun";
- break;
- case 17:
- name = "Ondo";
- break;
- case 18:
- name = "Oyo";
- break;
- case 21:
- name = "Akwa Ibom";
- break;
- case 22:
- name = "Cross River";
- break;
- case 23:
- name = "Kaduna";
- break;
- case 24:
- name = "Katsina";
- break;
- case 25:
- name = "Anambra";
- break;
- case 26:
- name = "Benue";
- break;
- case 27:
- name = "Borno";
- break;
- case 28:
- name = "Imo";
- break;
- case 29:
- name = "Kano";
- break;
- case 30:
- name = "Kwara";
- break;
- case 31:
- name = "Niger";
- break;
- case 32:
- name = "Oyo";
- break;
- case 35:
- name = "Adamawa";
- break;
- case 36:
- name = "Delta";
- break;
- case 37:
- name = "Edo";
- break;
- case 39:
- name = "Jigawa";
- break;
- case 40:
- name = "Kebbi";
- break;
- case 41:
- name = "Kogi";
- break;
- case 42:
- name = "Osun";
- break;
- case 43:
- name = "Taraba";
- break;
- case 44:
- name = "Yobe";
- break;
- case 45:
- name = "Abia";
- break;
- case 46:
- name = "Bauchi";
- break;
- case 47:
- name = "Enugu";
- break;
- case 48:
- name = "Ondo";
- break;
- case 49:
- name = "Plateau";
- break;
- case 50:
- name = "Rivers";
- break;
- case 51:
- name = "Sokoto";
- break;
- case 52:
- name = "Bayelsa";
- break;
- case 53:
- name = "Ebonyi";
- break;
- case 54:
- name = "Ekiti";
- break;
- case 55:
- name = "Gombe";
- break;
- case 56:
- name = "Nassarawa";
- break;
- case 57:
- name = "Zamfara";
- break;
- }
- }
- if (country_code.equals("NI") == true) {
- switch (region_code2) {
- case 1:
- name = "Boaco";
- break;
- case 2:
- name = "Carazo";
- break;
- case 3:
- name = "Chinandega";
- break;
- case 4:
- name = "Chontales";
- break;
- case 5:
- name = "Esteli";
- break;
- case 6:
- name = "Granada";
- break;
- case 7:
- name = "Jinotega";
- break;
- case 8:
- name = "Leon";
- break;
- case 9:
- name = "Madriz";
- break;
- case 10:
- name = "Managua";
- break;
- case 11:
- name = "Masaya";
- break;
- case 12:
- name = "Matagalpa";
- break;
- case 13:
- name = "Nueva Segovia";
- break;
- case 14:
- name = "Rio San Juan";
- break;
- case 15:
- name = "Rivas";
- break;
- case 16:
- name = "Zelaya";
- break;
- case 17:
- name = "Autonoma Atlantico Norte";
- break;
- case 18:
- name = "Region Autonoma Atlantico Sur";
- break;
- }
- }
- if (country_code.equals("NL") == true) {
- switch (region_code2) {
- case 1:
- name = "Drenthe";
- break;
- case 2:
- name = "Friesland";
- break;
- case 3:
- name = "Gelderland";
- break;
- case 4:
- name = "Groningen";
- break;
- case 5:
- name = "Limburg";
- break;
- case 6:
- name = "Noord-Brabant";
- break;
- case 7:
- name = "Noord-Holland";
- break;
- case 8:
- name = "Overijssel";
- break;
- case 9:
- name = "Utrecht";
- break;
- case 10:
- name = "Zeeland";
- break;
- case 11:
- name = "Zuid-Holland";
- break;
- case 12:
- name = "Dronten";
- break;
- case 13:
- name = "Zuidelijke IJsselmeerpolders";
- break;
- case 14:
- name = "Lelystad";
- break;
- case 15:
- name = "Overijssel";
- break;
- case 16:
- name = "Flevoland";
- break;
- }
- }
- if (country_code.equals("NO") == true) {
- switch (region_code2) {
- case 1:
- name = "Akershus";
- break;
- case 2:
- name = "Aust-Agder";
- break;
- case 4:
- name = "Buskerud";
- break;
- case 5:
- name = "Finnmark";
- break;
- case 6:
- name = "Hedmark";
- break;
- case 7:
- name = "Hordaland";
- break;
- case 8:
- name = "More og Romsdal";
- break;
- case 9:
- name = "Nordland";
- break;
- case 10:
- name = "Nord-Trondelag";
- break;
- case 11:
- name = "Oppland";
- break;
- case 12:
- name = "Oslo";
- break;
- case 13:
- name = "Ostfold";
- break;
- case 14:
- name = "Rogaland";
- break;
- case 15:
- name = "Sogn og Fjordane";
- break;
- case 16:
- name = "Sor-Trondelag";
- break;
- case 17:
- name = "Telemark";
- break;
- case 18:
- name = "Troms";
- break;
- case 19:
- name = "Vest-Agder";
- break;
- case 20:
- name = "Vestfold";
- break;
- }
- }
- if (country_code.equals("NP") == true) {
- switch (region_code2) {
- case 1:
- name = "Bagmati";
- break;
- case 2:
- name = "Bheri";
- break;
- case 3:
- name = "Dhawalagiri";
- break;
- case 4:
- name = "Gandaki";
- break;
- case 5:
- name = "Janakpur";
- break;
- case 6:
- name = "Karnali";
- break;
- case 7:
- name = "Kosi";
- break;
- case 8:
- name = "Lumbini";
- break;
- case 9:
- name = "Mahakali";
- break;
- case 10:
- name = "Mechi";
- break;
- case 11:
- name = "Narayani";
- break;
- case 12:
- name = "Rapti";
- break;
- case 13:
- name = "Sagarmatha";
- break;
- case 14:
- name = "Seti";
- break;
- }
- }
- if (country_code.equals("NR") == true) {
- switch (region_code2) {
- case 1:
- name = "Aiwo";
- break;
- case 2:
- name = "Anabar";
- break;
- case 3:
- name = "Anetan";
- break;
- case 4:
- name = "Anibare";
- break;
- case 5:
- name = "Baiti";
- break;
- case 6:
- name = "Boe";
- break;
- case 7:
- name = "Buada";
- break;
- case 8:
- name = "Denigomodu";
- break;
- case 9:
- name = "Ewa";
- break;
- case 10:
- name = "Ijuw";
- break;
- case 11:
- name = "Meneng";
- break;
- case 12:
- name = "Nibok";
- break;
- case 13:
- name = "Uaboe";
- break;
- case 14:
- name = "Yaren";
- break;
- }
- }
- if (country_code.equals("NZ") == true) {
- switch (region_code2) {
- case 10:
- name = "Chatham Islands";
- break;
- case 1010:
- name = "Auckland";
- break;
- case 1011:
- name = "Bay of Plenty";
- break;
- case 1012:
- name = "Canterbury";
- break;
- case 1047:
- name = "Gisborne";
- break;
- case 1048:
- name = "Hawke's Bay";
- break;
- case 1049:
- name = "Manawatu-Wanganui";
- break;
- case 1050:
- name = "Marlborough";
- break;
- case 1051:
- name = "Nelson";
- break;
- case 1052:
- name = "Northland";
- break;
- case 1053:
- name = "Otago";
- break;
- case 1054:
- name = "Southland";
- break;
- case 1055:
- name = "Taranaki";
- break;
- case 1090:
- name = "Waikato";
- break;
- case 1091:
- name = "Wellington";
- break;
- case 1092:
- name = "West Coast";
- break;
- case 85:
- name = "Waikato";
- break;
- }
- }
- if (country_code.equals("OM") == true) {
- switch (region_code2) {
- case 1:
- name = "Ad Dakhiliyah";
- break;
- case 2:
- name = "Al Batinah";
- break;
- case 3:
- name = "Al Wusta";
- break;
- case 4:
- name = "Ash Sharqiyah";
- break;
- case 5:
- name = "Az Zahirah";
- break;
- case 6:
- name = "Masqat";
- break;
- case 7:
- name = "Musandam";
- break;
- case 8:
- name = "Zufar";
- break;
- }
- }
- if (country_code.equals("PA") == true) {
- switch (region_code2) {
- case 1:
- name = "Bocas del Toro";
- break;
- case 2:
- name = "Chiriqui";
- break;
- case 3:
- name = "Cocle";
- break;
- case 4:
- name = "Colon";
- break;
- case 5:
- name = "Darien";
- break;
- case 6:
- name = "Herrera";
- break;
- case 7:
- name = "Los Santos";
- break;
- case 8:
- name = "Panama";
- break;
- case 9:
- name = "San Blas";
- break;
- case 10:
- name = "Veraguas";
- break;
- }
- }
- if (country_code.equals("PE") == true) {
- switch (region_code2) {
- case 1:
- name = "Amazonas";
- break;
- case 2:
- name = "Ancash";
- break;
- case 3:
- name = "Apurimac";
- break;
- case 4:
- name = "Arequipa";
- break;
- case 5:
- name = "Ayacucho";
- break;
- case 6:
- name = "Cajamarca";
- break;
- case 7:
- name = "Callao";
- break;
- case 8:
- name = "Cusco";
- break;
- case 9:
- name = "Huancavelica";
- break;
- case 10:
- name = "Huanuco";
- break;
- case 11:
- name = "Ica";
- break;
- case 12:
- name = "Junin";
- break;
- case 13:
- name = "La Libertad";
- break;
- case 14:
- name = "Lambayeque";
- break;
- case 15:
- name = "Lima";
- break;
- case 16:
- name = "Loreto";
- break;
- case 17:
- name = "Madre de Dios";
- break;
- case 18:
- name = "Moquegua";
- break;
- case 19:
- name = "Pasco";
- break;
- case 20:
- name = "Piura";
- break;
- case 21:
- name = "Puno";
- break;
- case 22:
- name = "San Martin";
- break;
- case 23:
- name = "Tacna";
- break;
- case 24:
- name = "Tumbes";
- break;
- case 25:
- name = "Ucayali";
- break;
- }
- }
- if (country_code.equals("PG") == true) {
- switch (region_code2) {
- case 1:
- name = "Central";
- break;
- case 2:
- name = "Gulf";
- break;
- case 3:
- name = "Milne Bay";
- break;
- case 4:
- name = "Northern";
- break;
- case 5:
- name = "Southern Highlands";
- break;
- case 6:
- name = "Western";
- break;
- case 7:
- name = "North Solomons";
- break;
- case 8:
- name = "Chimbu";
- break;
- case 9:
- name = "Eastern Highlands";
- break;
- case 10:
- name = "East New Britain";
- break;
- case 11:
- name = "East Sepik";
- break;
- case 12:
- name = "Madang";
- break;
- case 13:
- name = "Manus";
- break;
- case 14:
- name = "Morobe";
- break;
- case 15:
- name = "New Ireland";
- break;
- case 16:
- name = "Western Highlands";
- break;
- case 17:
- name = "West New Britain";
- break;
- case 18:
- name = "Sandaun";
- break;
- case 19:
- name = "Enga";
- break;
- case 20:
- name = "National Capital";
- break;
- }
- }
- if (country_code.equals("PH") == true) {
- switch (region_code2) {
- case 1:
- name = "Abra";
- break;
- case 2:
- name = "Agusan del Norte";
- break;
- case 3:
- name = "Agusan del Sur";
- break;
- case 4:
- name = "Aklan";
- break;
- case 5:
- name = "Albay";
- break;
- case 6:
- name = "Antique";
- break;
- case 7:
- name = "Bataan";
- break;
- case 8:
- name = "Batanes";
- break;
- case 9:
- name = "Batangas";
- break;
- case 10:
- name = "Benguet";
- break;
- case 11:
- name = "Bohol";
- break;
- case 12:
- name = "Bukidnon";
- break;
- case 13:
- name = "Bulacan";
- break;
- case 14:
- name = "Cagayan";
- break;
- case 15:
- name = "Camarines Norte";
- break;
- case 16:
- name = "Camarines Sur";
- break;
- case 17:
- name = "Camiguin";
- break;
- case 18:
- name = "Capiz";
- break;
- case 19:
- name = "Catanduanes";
- break;
- case 20:
- name = "Cavite";
- break;
- case 21:
- name = "Cebu";
- break;
- case 22:
- name = "Basilan";
- break;
- case 23:
- name = "Eastern Samar";
- break;
- case 24:
- name = "Davao";
- break;
- case 25:
- name = "Davao del Sur";
- break;
- case 26:
- name = "Davao Oriental";
- break;
- case 27:
- name = "Ifugao";
- break;
- case 28:
- name = "Ilocos Norte";
- break;
- case 29:
- name = "Ilocos Sur";
- break;
- case 30:
- name = "Iloilo";
- break;
- case 31:
- name = "Isabela";
- break;
- case 32:
- name = "Kalinga-Apayao";
- break;
- case 33:
- name = "Laguna";
- break;
- case 34:
- name = "Lanao del Norte";
- break;
- case 35:
- name = "Lanao del Sur";
- break;
- case 36:
- name = "La Union";
- break;
- case 37:
- name = "Leyte";
- break;
- case 38:
- name = "Marinduque";
- break;
- case 39:
- name = "Masbate";
- break;
- case 40:
- name = "Mindoro Occidental";
- break;
- case 41:
- name = "Mindoro Oriental";
- break;
- case 42:
- name = "Misamis Occidental";
- break;
- case 43:
- name = "Misamis Oriental";
- break;
- case 44:
- name = "Mountain";
- break;
- case 45:
- name = "Negros Occidental";
- break;
- case 46:
- name = "Negros Oriental";
- break;
- case 47:
- name = "Nueva Ecija";
- break;
- case 48:
- name = "Nueva Vizcaya";
- break;
- case 49:
- name = "Palawan";
- break;
- case 50:
- name = "Pampanga";
- break;
- case 51:
- name = "Pangasinan";
- break;
- case 53:
- name = "Rizal";
- break;
- case 54:
- name = "Romblon";
- break;
- case 55:
- name = "Samar";
- break;
- case 56:
- name = "Maguindanao";
- break;
- case 57:
- name = "North Cotabato";
- break;
- case 58:
- name = "Sorsogon";
- break;
- case 59:
- name = "Southern Leyte";
- break;
- case 60:
- name = "Sulu";
- break;
- case 61:
- name = "Surigao del Norte";
- break;
- case 62:
- name = "Surigao del Sur";
- break;
- case 63:
- name = "Tarlac";
- break;
- case 64:
- name = "Zambales";
- break;
- case 65:
- name = "Zamboanga del Norte";
- break;
- case 66:
- name = "Zamboanga del Sur";
- break;
- case 67:
- name = "Northern Samar";
- break;
- case 68:
- name = "Quirino";
- break;
- case 69:
- name = "Siquijor";
- break;
- case 70:
- name = "South Cotabato";
- break;
- case 71:
- name = "Sultan Kudarat";
- break;
- case 72:
- name = "Tawitawi";
- break;
- case 832:
- name = "Angeles";
- break;
- case 833:
- name = "Bacolod";
- break;
- case 834:
- name = "Bago";
- break;
- case 835:
- name = "Baguio";
- break;
- case 836:
- name = "Bais";
- break;
- case 837:
- name = "Basilan City";
- break;
- case 838:
- name = "Batangas City";
- break;
- case 839:
- name = "Butuan";
- break;
- case 840:
- name = "Cabanatuan";
- break;
- case 875:
- name = "Cadiz";
- break;
- case 876:
- name = "Cagayan de Oro";
- break;
- case 877:
- name = "Calbayog";
- break;
- case 878:
- name = "Caloocan";
- break;
- case 879:
- name = "Canlaon";
- break;
- case 880:
- name = "Cavite City";
- break;
- case 881:
- name = "Cebu City";
- break;
- case 882:
- name = "Cotabato";
- break;
- case 883:
- name = "Dagupan";
- break;
- case 918:
- name = "Danao";
- break;
- case 919:
- name = "Dapitan";
- break;
- case 920:
- name = "Davao City";
- break;
- case 921:
- name = "Dipolog";
- break;
- case 922:
- name = "Dumaguete";
- break;
- case 923:
- name = "General Santos";
- break;
- case 924:
- name = "Gingoog";
- break;
- case 925:
- name = "Iligan";
- break;
- case 926:
- name = "Iloilo City";
- break;
- case 961:
- name = "Iriga";
- break;
- case 962:
- name = "La Carlota";
- break;
- case 963:
- name = "Laoag";
- break;
- case 964:
- name = "Lapu-Lapu";
- break;
- case 965:
- name = "Legaspi";
- break;
- case 966:
- name = "Lipa";
- break;
- case 967:
- name = "Lucena";
- break;
- case 968:
- name = "Mandaue";
- break;
- case 969:
- name = "Manila";
- break;
- case 1004:
- name = "Marawi";
- break;
- case 1005:
- name = "Naga";
- break;
- case 1006:
- name = "Olongapo";
- break;
- case 1007:
- name = "Ormoc";
- break;
- case 1008:
- name = "Oroquieta";
- break;
- case 1009:
- name = "Ozamis";
- break;
- case 1010:
- name = "Pagadian";
- break;
- case 1011:
- name = "Palayan";
- break;
- case 1012:
- name = "Pasay";
- break;
- case 1047:
- name = "Puerto Princesa";
- break;
- case 1048:
- name = "Quezon City";
- break;
- case 1049:
- name = "Roxas";
- break;
- case 1050:
- name = "San Carlos";
- break;
- case 1051:
- name = "San Carlos";
- break;
- case 1052:
- name = "San Jose";
- break;
- case 1053:
- name = "San Pablo";
- break;
- case 1054:
- name = "Silay";
- break;
- case 1055:
- name = "Surigao";
- break;
- case 1090:
- name = "Tacloban";
- break;
- case 1091:
- name = "Tagaytay";
- break;
- case 1092:
- name = "Tagbilaran";
- break;
- case 1093:
- name = "Tangub";
- break;
- case 1094:
- name = "Toledo";
- break;
- case 1095:
- name = "Trece Martires";
- break;
- case 1096:
- name = "Zamboanga";
- break;
- case 1097:
- name = "Aurora";
- break;
- case 1134:
- name = "Quezon";
- break;
- case 1135:
- name = "Negros Occidental";
- break;
- }
- }
- if (country_code.equals("PK") == true) {
- switch (region_code2) {
- case 1:
- name = "Federally Administered Tribal Areas";
- break;
- case 2:
- name = "Balochistan";
- break;
- case 3:
- name = "North-West Frontier";
- break;
- case 4:
- name = "Punjab";
- break;
- case 5:
- name = "Sindh";
- break;
- case 6:
- name = "Azad Kashmir";
- break;
- case 7:
- name = "Northern Areas";
- break;
- case 8:
- name = "Islamabad";
- break;
- }
- }
- if (country_code.equals("PL") == true) {
- switch (region_code2) {
- case 72:
- name = "Dolnoslaskie";
- break;
- case 73:
- name = "Kujawsko-Pomorskie";
- break;
- case 74:
- name = "Lodzkie";
- break;
- case 75:
- name = "Lubelskie";
- break;
- case 76:
- name = "Lubuskie";
- break;
- case 77:
- name = "Malopolskie";
- break;
- case 78:
- name = "Mazowieckie";
- break;
- case 79:
- name = "Opolskie";
- break;
- case 80:
- name = "Podkarpackie";
- break;
- case 81:
- name = "Podlaskie";
- break;
- case 82:
- name = "Pomorskie";
- break;
- case 83:
- name = "Slaskie";
- break;
- case 84:
- name = "Swietokrzyskie";
- break;
- case 85:
- name = "Warminsko-Mazurskie";
- break;
- case 86:
- name = "Wielkopolskie";
- break;
- case 87:
- name = "Zachodniopomorskie";
- break;
- }
- }
- if (country_code.equals("PS") == true) {
- switch (region_code2) {
- case 1131:
- name = "Gaza";
- break;
- case 1798:
- name = "West Bank";
- break;
- }
- }
- if (country_code.equals("PT") == true) {
- switch (region_code2) {
- case 2:
- name = "Aveiro";
- break;
- case 3:
- name = "Beja";
- break;
- case 4:
- name = "Braga";
- break;
- case 5:
- name = "Braganca";
- break;
- case 6:
- name = "Castelo Branco";
- break;
- case 7:
- name = "Coimbra";
- break;
- case 8:
- name = "Evora";
- break;
- case 9:
- name = "Faro";
- break;
- case 10:
- name = "Madeira";
- break;
- case 11:
- name = "Guarda";
- break;
- case 13:
- name = "Leiria";
- break;
- case 14:
- name = "Lisboa";
- break;
- case 16:
- name = "Portalegre";
- break;
- case 17:
- name = "Porto";
- break;
- case 18:
- name = "Santarem";
- break;
- case 19:
- name = "Setubal";
- break;
- case 20:
- name = "Viana do Castelo";
- break;
- case 21:
- name = "Vila Real";
- break;
- case 22:
- name = "Viseu";
- break;
- case 23:
- name = "Azores";
- break;
- }
- }
- if (country_code.equals("PY") == true) {
- switch (region_code2) {
- case 1:
- name = "Alto Parana";
- break;
- case 2:
- name = "Amambay";
- break;
- case 3:
- name = "Boqueron";
- break;
- case 4:
- name = "Caaguazu";
- break;
- case 5:
- name = "Caazapa";
- break;
- case 6:
- name = "Central";
- break;
- case 7:
- name = "Concepcion";
- break;
- case 8:
- name = "Cordillera";
- break;
- case 10:
- name = "Guaira";
- break;
- case 11:
- name = "Itapua";
- break;
- case 12:
- name = "Misiones";
- break;
- case 13:
- name = "Neembucu";
- break;
- case 15:
- name = "Paraguari";
- break;
- case 16:
- name = "Presidente Hayes";
- break;
- case 17:
- name = "San Pedro";
- break;
- case 19:
- name = "Canindeyu";
- break;
- case 20:
- name = "Chaco";
- break;
- case 21:
- name = "Nueva Asuncion";
- break;
- case 23:
- name = "Alto Paraguay";
- break;
- }
- }
- if (country_code.equals("QA") == true) {
- switch (region_code2) {
- case 1:
- name = "Ad Dawhah";
- break;
- case 2:
- name = "Al Ghuwariyah";
- break;
- case 3:
- name = "Al Jumaliyah";
- break;
- case 4:
- name = "Al Khawr";
- break;
- case 5:
- name = "Al Wakrah Municipality";
- break;
- case 6:
- name = "Ar Rayyan";
- break;
- case 8:
- name = "Madinat ach Shamal";
- break;
- case 9:
- name = "Umm Salal";
- break;
- case 10:
- name = "Al Wakrah";
- break;
- case 11:
- name = "Jariyan al Batnah";
- break;
- case 12:
- name = "Umm Sa'id";
- break;
- }
- }
- if (country_code.equals("RO") == true) {
- switch (region_code2) {
- case 1:
- name = "Alba";
- break;
- case 2:
- name = "Arad";
- break;
- case 3:
- name = "Arges";
- break;
- case 4:
- name = "Bacau";
- break;
- case 5:
- name = "Bihor";
- break;
- case 6:
- name = "Bistrita-Nasaud";
- break;
- case 7:
- name = "Botosani";
- break;
- case 8:
- name = "Braila";
- break;
- case 9:
- name = "Brasov";
- break;
- case 10:
- name = "Bucuresti";
- break;
- case 11:
- name = "Buzau";
- break;
- case 12:
- name = "Caras-Severin";
- break;
- case 13:
- name = "Cluj";
- break;
- case 14:
- name = "Constanta";
- break;
- case 15:
- name = "Covasna";
- break;
- case 16:
- name = "Dambovita";
- break;
- case 17:
- name = "Dolj";
- break;
- case 18:
- name = "Galati";
- break;
- case 19:
- name = "Gorj";
- break;
- case 20:
- name = "Harghita";
- break;
- case 21:
- name = "Hunedoara";
- break;
- case 22:
- name = "Ialomita";
- break;
- case 23:
- name = "Iasi";
- break;
- case 25:
- name = "Maramures";
- break;
- case 26:
- name = "Mehedinti";
- break;
- case 27:
- name = "Mures";
- break;
- case 28:
- name = "Neamt";
- break;
- case 29:
- name = "Olt";
- break;
- case 30:
- name = "Prahova";
- break;
- case 31:
- name = "Salaj";
- break;
- case 32:
- name = "Satu Mare";
- break;
- case 33:
- name = "Sibiu";
- break;
- case 34:
- name = "Suceava";
- break;
- case 35:
- name = "Teleorman";
- break;
- case 36:
- name = "Timis";
- break;
- case 37:
- name = "Tulcea";
- break;
- case 38:
- name = "Vaslui";
- break;
- case 39:
- name = "Valcea";
- break;
- case 40:
- name = "Vrancea";
- break;
- case 41:
- name = "Calarasi";
- break;
- case 42:
- name = "Giurgiu";
- break;
- case 43:
- name = "Ilfov";
- break;
- }
- }
- if (country_code.equals("RS") == true) {
- switch (region_code2) {
- case 1:
- name = "Kosovo";
- break;
- case 2:
- name = "Vojvodina";
- break;
- }
- }
- if (country_code.equals("RU") == true) {
- switch (region_code2) {
- case 1:
- name = "Adygeya";
- break;
- case 2:
- name = "Aginsky Buryatsky AO";
- break;
- case 3:
- name = "Gorno-Altay";
- break;
- case 4:
- name = "Altaisky krai";
- break;
- case 5:
- name = "Amur";
- break;
- case 6:
- name = "Arkhangel'sk";
- break;
- case 7:
- name = "Astrakhan'";
- break;
- case 8:
- name = "Bashkortostan";
- break;
- case 9:
- name = "Belgorod";
- break;
- case 10:
- name = "Bryansk";
- break;
- case 11:
- name = "Buryat";
- break;
- case 12:
- name = "Chechnya";
- break;
- case 13:
- name = "Chelyabinsk";
- break;
- case 14:
- name = "Chita";
- break;
- case 15:
- name = "Chukot";
- break;
- case 16:
- name = "Chuvashia";
- break;
- case 17:
- name = "Dagestan";
- break;
- case 18:
- name = "Evenk";
- break;
- case 19:
- name = "Ingush";
- break;
- case 20:
- name = "Irkutsk";
- break;
- case 21:
- name = "Ivanovo";
- break;
- case 22:
- name = "Kabardin-Balkar";
- break;
- case 23:
- name = "Kaliningrad";
- break;
- case 24:
- name = "Kalmyk";
- break;
- case 25:
- name = "Kaluga";
- break;
- case 26:
- name = "Kamchatka";
- break;
- case 27:
- name = "Karachay-Cherkess";
- break;
- case 28:
- name = "Karelia";
- break;
- case 29:
- name = "Kemerovo";
- break;
- case 30:
- name = "Khabarovsk";
- break;
- case 31:
- name = "Khakass";
- break;
- case 32:
- name = "Khanty-Mansiy";
- break;
- case 33:
- name = "Kirov";
- break;
- case 34:
- name = "Komi";
- break;
- case 35:
- name = "Komi-Permyak";
- break;
- case 36:
- name = "Koryak";
- break;
- case 37:
- name = "Kostroma";
- break;
- case 38:
- name = "Krasnodar";
- break;
- case 39:
- name = "Krasnoyarsk";
- break;
- case 40:
- name = "Kurgan";
- break;
- case 41:
- name = "Kursk";
- break;
- case 42:
- name = "Leningrad";
- break;
- case 43:
- name = "Lipetsk";
- break;
- case 44:
- name = "Magadan";
- break;
- case 45:
- name = "Mariy-El";
- break;
- case 46:
- name = "Mordovia";
- break;
- case 47:
- name = "Moskva";
- break;
- case 48:
- name = "Moscow City";
- break;
- case 49:
- name = "Murmansk";
- break;
- case 50:
- name = "Nenets";
- break;
- case 51:
- name = "Nizhegorod";
- break;
- case 52:
- name = "Novgorod";
- break;
- case 53:
- name = "Novosibirsk";
- break;
- case 54:
- name = "Omsk";
- break;
- case 55:
- name = "Orenburg";
- break;
- case 56:
- name = "Orel";
- break;
- case 57:
- name = "Penza";
- break;
- case 58:
- name = "Perm'";
- break;
- case 59:
- name = "Primor'ye";
- break;
- case 60:
- name = "Pskov";
- break;
- case 61:
- name = "Rostov";
- break;
- case 62:
- name = "Ryazan'";
- break;
- case 63:
- name = "Sakha";
- break;
- case 64:
- name = "Sakhalin";
- break;
- case 65:
- name = "Samara";
- break;
- case 66:
- name = "Saint Petersburg City";
- break;
- case 67:
- name = "Saratov";
- break;
- case 68:
- name = "North Ossetia";
- break;
- case 69:
- name = "Smolensk";
- break;
- case 70:
- name = "Stavropol'";
- break;
- case 71:
- name = "Sverdlovsk";
- break;
- case 72:
- name = "Tambovskaya oblast";
- break;
- case 73:
- name = "Tatarstan";
- break;
- case 74:
- name = "Taymyr";
- break;
- case 75:
- name = "Tomsk";
- break;
- case 76:
- name = "Tula";
- break;
- case 77:
- name = "Tver'";
- break;
- case 78:
- name = "Tyumen'";
- break;
- case 79:
- name = "Tuva";
- break;
- case 80:
- name = "Udmurt";
- break;
- case 81:
- name = "Ul'yanovsk";
- break;
- case 82:
- name = "Ust-Orda Buryat";
- break;
- case 83:
- name = "Vladimir";
- break;
- case 84:
- name = "Volgograd";
- break;
- case 85:
- name = "Vologda";
- break;
- case 86:
- name = "Voronezh";
- break;
- case 87:
- name = "Yamal-Nenets";
- break;
- case 88:
- name = "Yaroslavl'";
- break;
- case 89:
- name = "Yevrey";
- break;
- case 90:
- name = "Permskiy Kray";
- break;
- case 91:
- name = "Krasnoyarskiy Kray";
- break;
- case 942:
- name = "Chechnya Republic";
- break;
- }
- }
- if (country_code.equals("RW") == true) {
- switch (region_code2) {
- case 1:
- name = "Butare";
- break;
- case 6:
- name = "Gitarama";
- break;
- case 7:
- name = "Kibungo";
- break;
- case 9:
- name = "Kigali";
- break;
- case 11:
- name = "Est";
- break;
- case 12:
- name = "Kigali";
- break;
- case 13:
- name = "Nord";
- break;
- case 14:
- name = "Ouest";
- break;
- case 15:
- name = "Sud";
- break;
- }
- }
- if (country_code.equals("SA") == true) {
- switch (region_code2) {
- case 2:
- name = "Al Bahah";
- break;
- case 3:
- name = "Al Jawf";
- break;
- case 5:
- name = "Al Madinah";
- break;
- case 6:
- name = "Ash Sharqiyah";
- break;
- case 8:
- name = "Al Qasim";
- break;
- case 9:
- name = "Al Qurayyat";
- break;
- case 10:
- name = "Ar Riyad";
- break;
- case 13:
- name = "Ha'il";
- break;
- case 14:
- name = "Makkah";
- break;
- case 15:
- name = "Al Hudud ash Shamaliyah";
- break;
- case 16:
- name = "Najran";
- break;
- case 17:
- name = "Jizan";
- break;
- case 19:
- name = "Tabuk";
- break;
- case 20:
- name = "Al Jawf";
- break;
- }
- }
- if (country_code.equals("SB") == true) {
- switch (region_code2) {
- case 3:
- name = "Malaita";
- break;
- case 6:
- name = "Guadalcanal";
- break;
- case 7:
- name = "Isabel";
- break;
- case 8:
- name = "Makira";
- break;
- case 9:
- name = "Temotu";
- break;
- case 10:
- name = "Central";
- break;
- case 11:
- name = "Western";
- break;
- case 12:
- name = "Choiseul";
- break;
- case 13:
- name = "Rennell and Bellona";
- break;
- }
- }
- if (country_code.equals("SC") == true) {
- switch (region_code2) {
- case 1:
- name = "Anse aux Pins";
- break;
- case 2:
- name = "Anse Boileau";
- break;
- case 3:
- name = "Anse Etoile";
- break;
- case 4:
- name = "Anse Louis";
- break;
- case 5:
- name = "Anse Royale";
- break;
- case 6:
- name = "Baie Lazare";
- break;
- case 7:
- name = "Baie Sainte Anne";
- break;
- case 8:
- name = "Beau Vallon";
- break;
- case 9:
- name = "Bel Air";
- break;
- case 10:
- name = "Bel Ombre";
- break;
- case 11:
- name = "Cascade";
- break;
- case 12:
- name = "Glacis";
- break;
- case 13:
- name = "Grand' Anse";
- break;
- case 14:
- name = "Grand' Anse";
- break;
- case 15:
- name = "La Digue";
- break;
- case 16:
- name = "La Riviere Anglaise";
- break;
- case 17:
- name = "Mont Buxton";
- break;
- case 18:
- name = "Mont Fleuri";
- break;
- case 19:
- name = "Plaisance";
- break;
- case 20:
- name = "Pointe La Rue";
- break;
- case 21:
- name = "Port Glaud";
- break;
- case 22:
- name = "Saint Louis";
- break;
- case 23:
- name = "Takamaka";
- break;
- }
- }
- if (country_code.equals("SD") == true) {
- switch (region_code2) {
- case 27:
- name = "Al Wusta";
- break;
- case 28:
- name = "Al Istiwa'iyah";
- break;
- case 29:
- name = "Al Khartum";
- break;
- case 30:
- name = "Ash Shamaliyah";
- break;
- case 31:
- name = "Ash Sharqiyah";
- break;
- case 32:
- name = "Bahr al Ghazal";
- break;
- case 33:
- name = "Darfur";
- break;
- case 34:
- name = "Kurdufan";
- break;
- case 35:
- name = "Upper Nile";
- break;
- case 40:
- name = "Al Wahadah State";
- break;
- case 44:
- name = "Central Equatoria State";
- break;
- }
- }
- if (country_code.equals("SE") == true) {
- switch (region_code2) {
- case 1:
- name = "Alvsborgs Lan";
- break;
- case 2:
- name = "Blekinge Lan";
- break;
- case 3:
- name = "Gavleborgs Lan";
- break;
- case 4:
- name = "Goteborgs och Bohus Lan";
- break;
- case 5:
- name = "Gotlands Lan";
- break;
- case 6:
- name = "Hallands Lan";
- break;
- case 7:
- name = "Jamtlands Lan";
- break;
- case 8:
- name = "Jonkopings Lan";
- break;
- case 9:
- name = "Kalmar Lan";
- break;
- case 10:
- name = "Dalarnas Lan";
- break;
- case 11:
- name = "Kristianstads Lan";
- break;
- case 12:
- name = "Kronobergs Lan";
- break;
- case 13:
- name = "Malmohus Lan";
- break;
- case 14:
- name = "Norrbottens Lan";
- break;
- case 15:
- name = "Orebro Lan";
- break;
- case 16:
- name = "Ostergotlands Lan";
- break;
- case 17:
- name = "Skaraborgs Lan";
- break;
- case 18:
- name = "Sodermanlands Lan";
- break;
- case 21:
- name = "Uppsala Lan";
- break;
- case 22:
- name = "Varmlands Lan";
- break;
- case 23:
- name = "Vasterbottens Lan";
- break;
- case 24:
- name = "Vasternorrlands Lan";
- break;
- case 25:
- name = "Vastmanlands Lan";
- break;
- case 26:
- name = "Stockholms Lan";
- break;
- case 27:
- name = "Skane Lan";
- break;
- case 28:
- name = "Vastra Gotaland";
- break;
- }
- }
- if (country_code.equals("SH") == true) {
- switch (region_code2) {
- case 1:
- name = "Ascension";
- break;
- case 2:
- name = "Saint Helena";
- break;
- case 3:
- name = "Tristan da Cunha";
- break;
- }
- }
- if (country_code.equals("SI") == true) {
- switch (region_code2) {
- case 1:
- name = "Ajdovscina";
- break;
- case 2:
- name = "Beltinci";
- break;
- case 3:
- name = "Bled";
- break;
- case 4:
- name = "Bohinj";
- break;
- case 5:
- name = "Borovnica";
- break;
- case 6:
- name = "Bovec";
- break;
- case 7:
- name = "Brda";
- break;
- case 8:
- name = "Brezice";
- break;
- case 9:
- name = "Brezovica";
- break;
- case 11:
- name = "Celje";
- break;
- case 12:
- name = "Cerklje na Gorenjskem";
- break;
- case 13:
- name = "Cerknica";
- break;
- case 14:
- name = "Cerkno";
- break;
- case 15:
- name = "Crensovci";
- break;
- case 16:
- name = "Crna na Koroskem";
- break;
- case 17:
- name = "Crnomelj";
- break;
- case 19:
- name = "Divaca";
- break;
- case 20:
- name = "Dobrepolje";
- break;
- case 22:
- name = "Dol pri Ljubljani";
- break;
- case 24:
- name = "Dornava";
- break;
- case 25:
- name = "Dravograd";
- break;
- case 26:
- name = "Duplek";
- break;
- case 27:
- name = "Gorenja Vas-Poljane";
- break;
- case 28:
- name = "Gorisnica";
- break;
- case 29:
- name = "Gornja Radgona";
- break;
- case 30:
- name = "Gornji Grad";
- break;
- case 31:
- name = "Gornji Petrovci";
- break;
- case 32:
- name = "Grosuplje";
- break;
- case 34:
- name = "Hrastnik";
- break;
- case 35:
- name = "Hrpelje-Kozina";
- break;
- case 36:
- name = "Idrija";
- break;
- case 37:
- name = "Ig";
- break;
- case 38:
- name = "Ilirska Bistrica";
- break;
- case 39:
- name = "Ivancna Gorica";
- break;
- case 40:
- name = "Izola-Isola";
- break;
- case 42:
- name = "Jursinci";
- break;
- case 44:
- name = "Kanal";
- break;
- case 45:
- name = "Kidricevo";
- break;
- case 46:
- name = "Kobarid";
- break;
- case 47:
- name = "Kobilje";
- break;
- case 49:
- name = "Komen";
- break;
- case 50:
- name = "Koper-Capodistria";
- break;
- case 51:
- name = "Kozje";
- break;
- case 52:
- name = "Kranj";
- break;
- case 53:
- name = "Kranjska Gora";
- break;
- case 54:
- name = "Krsko";
- break;
- case 55:
- name = "Kungota";
- break;
- case 57:
- name = "Lasko";
- break;
- case 61:
- name = "Ljubljana";
- break;
- case 62:
- name = "Ljubno";
- break;
- case 64:
- name = "Logatec";
- break;
- case 66:
- name = "Loski Potok";
- break;
- case 68:
- name = "Lukovica";
- break;
- case 71:
- name = "Medvode";
- break;
- case 72:
- name = "Menges";
- break;
- case 73:
- name = "Metlika";
- break;
- case 74:
- name = "Mezica";
- break;
- case 76:
- name = "Mislinja";
- break;
- case 77:
- name = "Moravce";
- break;
- case 78:
- name = "Moravske Toplice";
- break;
- case 79:
- name = "Mozirje";
- break;
- case 80:
- name = "Murska Sobota";
- break;
- case 81:
- name = "Muta";
- break;
- case 82:
- name = "Naklo";
- break;
- case 83:
- name = "Nazarje";
- break;
- case 84:
- name = "Nova Gorica";
- break;
- case 86:
- name = "Odranci";
- break;
- case 87:
- name = "Ormoz";
- break;
- case 88:
- name = "Osilnica";
- break;
- case 89:
- name = "Pesnica";
- break;
- case 91:
- name = "Pivka";
- break;
- case 92:
- name = "Podcetrtek";
- break;
- case 94:
- name = "Postojna";
- break;
- case 97:
- name = "Puconci";
- break;
- case 98:
- name = "Racam";
- break;
- case 99:
- name = "Radece";
- break;
- case 832:
- name = "Radenci";
- break;
- case 833:
- name = "Radlje ob Dravi";
- break;
- case 834:
- name = "Radovljica";
- break;
- case 837:
- name = "Rogasovci";
- break;
- case 838:
- name = "Rogaska Slatina";
- break;
- case 839:
- name = "Rogatec";
- break;
- case 875:
- name = "Semic";
- break;
- case 876:
- name = "Sencur";
- break;
- case 877:
- name = "Sentilj";
- break;
- case 878:
- name = "Sentjernej";
- break;
- case 880:
- name = "Sevnica";
- break;
- case 881:
- name = "Sezana";
- break;
- case 882:
- name = "Skocjan";
- break;
- case 883:
- name = "Skofja Loka";
- break;
- case 918:
- name = "Skofljica";
- break;
- case 919:
- name = "Slovenj Gradec";
- break;
- case 921:
- name = "Slovenske Konjice";
- break;
- case 922:
- name = "Smarje pri Jelsah";
- break;
- case 923:
- name = "Smartno ob Paki";
- break;
- case 924:
- name = "Sostanj";
- break;
- case 925:
- name = "Starse";
- break;
- case 926:
- name = "Store";
- break;
- case 961:
- name = "Sveti Jurij";
- break;
- case 962:
- name = "Tolmin";
- break;
- case 963:
- name = "Trbovlje";
- break;
- case 964:
- name = "Trebnje";
- break;
- case 965:
- name = "Trzic";
- break;
- case 966:
- name = "Turnisce";
- break;
- case 967:
- name = "Velenje";
- break;
- case 968:
- name = "Velike Lasce";
- break;
- case 1004:
- name = "Vipava";
- break;
- case 1005:
- name = "Vitanje";
- break;
- case 1006:
- name = "Vodice";
- break;
- case 1008:
- name = "Vrhnika";
- break;
- case 1009:
- name = "Vuzenica";
- break;
- case 1010:
- name = "Zagorje ob Savi";
- break;
- case 1012:
- name = "Zavrc";
- break;
- case 1047:
- name = "Zelezniki";
- break;
- case 1048:
- name = "Ziri";
- break;
- case 1049:
- name = "Zrece";
- break;
- case 1093:
- name = "Dobrova-Horjul-Polhov Gradec";
- break;
- case 1096:
- name = "Domzale";
- break;
- case 1136:
- name = "Jesenice";
- break;
- case 1138:
- name = "Kamnik";
- break;
- case 1139:
- name = "Kocevje";
- break;
- case 1177:
- name = "Kuzma";
- break;
- case 1178:
- name = "Lenart";
- break;
- case 1180:
- name = "Litija";
- break;
- case 1181:
- name = "Ljutomer";
- break;
- case 1182:
- name = "Loska Dolina";
- break;
- case 1184:
- name = "Luce";
- break;
- case 1219:
- name = "Majsperk";
- break;
- case 1220:
- name = "Maribor";
- break;
- case 1223:
- name = "Miren-Kostanjevica";
- break;
- case 1225:
- name = "Novo Mesto";
- break;
- case 1227:
- name = "Piran";
- break;
- case 1266:
- name = "Preddvor";
- break;
- case 1268:
- name = "Ptuj";
- break;
- case 1305:
- name = "Ribnica";
- break;
- case 1307:
- name = "Ruse";
- break;
- case 1311:
- name = "Sentjur pri Celju";
- break;
- case 1312:
- name = "Slovenska Bistrica";
- break;
- case 1392:
- name = "Videm";
- break;
- case 1393:
- name = "Vojnik";
- break;
- case 1395:
- name = "Zalec";
- break;
- }
- }
- if (country_code.equals("SK") == true) {
- switch (region_code2) {
- case 1:
- name = "Banska Bystrica";
- break;
- case 2:
- name = "Bratislava";
- break;
- case 3:
- name = "Kosice";
- break;
- case 4:
- name = "Nitra";
- break;
- case 5:
- name = "Presov";
- break;
- case 6:
- name = "Trencin";
- break;
- case 7:
- name = "Trnava";
- break;
- case 8:
- name = "Zilina";
- break;
- }
- }
- if (country_code.equals("SL") == true) {
- switch (region_code2) {
- case 1:
- name = "Eastern";
- break;
- case 2:
- name = "Northern";
- break;
- case 3:
- name = "Southern";
- break;
- case 4:
- name = "Western Area";
- break;
- }
- }
- if (country_code.equals("SM") == true) {
- switch (region_code2) {
- case 1:
- name = "Acquaviva";
- break;
- case 2:
- name = "Chiesanuova";
- break;
- case 3:
- name = "Domagnano";
- break;
- case 4:
- name = "Faetano";
- break;
- case 5:
- name = "Fiorentino";
- break;
- case 6:
- name = "Borgo Maggiore";
- break;
- case 7:
- name = "San Marino";
- break;
- case 8:
- name = "Monte Giardino";
- break;
- case 9:
- name = "Serravalle";
- break;
- }
- }
- if (country_code.equals("SN") == true) {
- switch (region_code2) {
- case 1:
- name = "Dakar";
- break;
- case 3:
- name = "Diourbel";
- break;
- case 4:
- name = "Saint-Louis";
- break;
- case 5:
- name = "Tambacounda";
- break;
- case 7:
- name = "Thies";
- break;
- case 8:
- name = "Louga";
- break;
- case 9:
- name = "Fatick";
- break;
- case 10:
- name = "Kaolack";
- break;
- case 11:
- name = "Kolda";
- break;
- case 12:
- name = "Ziguinchor";
- break;
- case 13:
- name = "Louga";
- break;
- case 14:
- name = "Saint-Louis";
- break;
- case 15:
- name = "Matam";
- break;
- }
- }
- if (country_code.equals("SO") == true) {
- switch (region_code2) {
- case 1:
- name = "Bakool";
- break;
- case 2:
- name = "Banaadir";
- break;
- case 3:
- name = "Bari";
- break;
- case 4:
- name = "Bay";
- break;
- case 5:
- name = "Galguduud";
- break;
- case 6:
- name = "Gedo";
- break;
- case 7:
- name = "Hiiraan";
- break;
- case 8:
- name = "Jubbada Dhexe";
- break;
- case 9:
- name = "Jubbada Hoose";
- break;
- case 10:
- name = "Mudug";
- break;
- case 11:
- name = "Nugaal";
- break;
- case 12:
- name = "Sanaag";
- break;
- case 13:
- name = "Shabeellaha Dhexe";
- break;
- case 14:
- name = "Shabeellaha Hoose";
- break;
- case 16:
- name = "Woqooyi Galbeed";
- break;
- case 18:
- name = "Nugaal";
- break;
- case 19:
- name = "Togdheer";
- break;
- case 20:
- name = "Woqooyi Galbeed";
- break;
- case 21:
- name = "Awdal";
- break;
- case 22:
- name = "Sool";
- break;
- }
- }
- if (country_code.equals("SR") == true) {
- switch (region_code2) {
- case 10:
- name = "Brokopondo";
- break;
- case 11:
- name = "Commewijne";
- break;
- case 12:
- name = "Coronie";
- break;
- case 13:
- name = "Marowijne";
- break;
- case 14:
- name = "Nickerie";
- break;
- case 15:
- name = "Para";
- break;
- case 16:
- name = "Paramaribo";
- break;
- case 17:
- name = "Saramacca";
- break;
- case 18:
- name = "Sipaliwini";
- break;
- case 19:
- name = "Wanica";
- break;
- }
- }
- if (country_code.equals("ST") == true) {
- switch (region_code2) {
- case 1:
- name = "Principe";
- break;
- case 2:
- name = "Sao Tome";
- break;
- }
- }
- if (country_code.equals("SV") == true) {
- switch (region_code2) {
- case 1:
- name = "Ahuachapan";
- break;
- case 2:
- name = "Cabanas";
- break;
- case 3:
- name = "Chalatenango";
- break;
- case 4:
- name = "Cuscatlan";
- break;
- case 5:
- name = "La Libertad";
- break;
- case 6:
- name = "La Paz";
- break;
- case 7:
- name = "La Union";
- break;
- case 8:
- name = "Morazan";
- break;
- case 9:
- name = "San Miguel";
- break;
- case 10:
- name = "San Salvador";
- break;
- case 11:
- name = "Santa Ana";
- break;
- case 12:
- name = "San Vicente";
- break;
- case 13:
- name = "Sonsonate";
- break;
- case 14:
- name = "Usulutan";
- break;
- }
- }
- if (country_code.equals("SY") == true) {
- switch (region_code2) {
- case 1:
- name = "Al Hasakah";
- break;
- case 2:
- name = "Al Ladhiqiyah";
- break;
- case 3:
- name = "Al Qunaytirah";
- break;
- case 4:
- name = "Ar Raqqah";
- break;
- case 5:
- name = "As Suwayda'";
- break;
- case 6:
- name = "Dar";
- break;
- case 7:
- name = "Dayr az Zawr";
- break;
- case 8:
- name = "Rif Dimashq";
- break;
- case 9:
- name = "Halab";
- break;
- case 10:
- name = "Hamah";
- break;
- case 11:
- name = "Hims";
- break;
- case 12:
- name = "Idlib";
- break;
- case 13:
- name = "Dimashq";
- break;
- case 14:
- name = "Tartus";
- break;
- }
- }
- if (country_code.equals("SZ") == true) {
- switch (region_code2) {
- case 1:
- name = "Hhohho";
- break;
- case 2:
- name = "Lubombo";
- break;
- case 3:
- name = "Manzini";
- break;
- case 4:
- name = "Shiselweni";
- break;
- case 5:
- name = "Praslin";
- break;
- }
- }
- if (country_code.equals("TD") == true) {
- switch (region_code2) {
- case 1:
- name = "Batha";
- break;
- case 2:
- name = "Biltine";
- break;
- case 3:
- name = "Borkou-Ennedi-Tibesti";
- break;
- case 4:
- name = "Chari-Baguirmi";
- break;
- case 5:
- name = "Guera";
- break;
- case 6:
- name = "Kanem";
- break;
- case 7:
- name = "Lac";
- break;
- case 8:
- name = "Logone Occidental";
- break;
- case 9:
- name = "Logone Oriental";
- break;
- case 10:
- name = "Mayo-Kebbi";
- break;
- case 11:
- name = "Moyen-Chari";
- break;
- case 12:
- name = "Ouaddai";
- break;
- case 13:
- name = "Salamat";
- break;
- case 14:
- name = "Tandjile";
- break;
- }
- }
- if (country_code.equals("TG") == true) {
- switch (region_code2) {
- case 9:
- name = "Lama-Kara";
- break;
- case 18:
- name = "Tsevie";
- break;
- case 22:
- name = "Centrale";
- break;
- case 23:
- name = "Kara";
- break;
- case 24:
- name = "Maritime";
- break;
- case 25:
- name = "Plateaux";
- break;
- case 26:
- name = "Savanes";
- break;
- }
- }
- if (country_code.equals("TH") == true) {
- switch (region_code2) {
- case 1:
- name = "Mae Hong Son";
- break;
- case 2:
- name = "Chiang Mai";
- break;
- case 3:
- name = "Chiang Rai";
- break;
- case 4:
- name = "Nan";
- break;
- case 5:
- name = "Lamphun";
- break;
- case 6:
- name = "Lampang";
- break;
- case 7:
- name = "Phrae";
- break;
- case 8:
- name = "Tak";
- break;
- case 9:
- name = "Sukhothai";
- break;
- case 10:
- name = "Uttaradit";
- break;
- case 11:
- name = "Kamphaeng Phet";
- break;
- case 12:
- name = "Phitsanulok";
- break;
- case 13:
- name = "Phichit";
- break;
- case 14:
- name = "Phetchabun";
- break;
- case 15:
- name = "Uthai Thani";
- break;
- case 16:
- name = "Nakhon Sawan";
- break;
- case 17:
- name = "Nong Khai";
- break;
- case 18:
- name = "Loei";
- break;
- case 20:
- name = "Sakon Nakhon";
- break;
- case 21:
- name = "Nakhon Phanom";
- break;
- case 22:
- name = "Khon Kaen";
- break;
- case 23:
- name = "Kalasin";
- break;
- case 24:
- name = "Maha Sarakham";
- break;
- case 25:
- name = "Roi Et";
- break;
- case 26:
- name = "Chaiyaphum";
- break;
- case 27:
- name = "Nakhon Ratchasima";
- break;
- case 28:
- name = "Buriram";
- break;
- case 29:
- name = "Surin";
- break;
- case 30:
- name = "Sisaket";
- break;
- case 31:
- name = "Narathiwat";
- break;
- case 32:
- name = "Chai Nat";
- break;
- case 33:
- name = "Sing Buri";
- break;
- case 34:
- name = "Lop Buri";
- break;
- case 35:
- name = "Ang Thong";
- break;
- case 36:
- name = "Phra Nakhon Si Ayutthaya";
- break;
- case 37:
- name = "Saraburi";
- break;
- case 38:
- name = "Nonthaburi";
- break;
- case 39:
- name = "Pathum Thani";
- break;
- case 40:
- name = "Krung Thep";
- break;
- case 41:
- name = "Phayao";
- break;
- case 42:
- name = "Samut Prakan";
- break;
- case 43:
- name = "Nakhon Nayok";
- break;
- case 44:
- name = "Chachoengsao";
- break;
- case 45:
- name = "Prachin Buri";
- break;
- case 46:
- name = "Chon Buri";
- break;
- case 47:
- name = "Rayong";
- break;
- case 48:
- name = "Chanthaburi";
- break;
- case 49:
- name = "Trat";
- break;
- case 50:
- name = "Kanchanaburi";
- break;
- case 51:
- name = "Suphan Buri";
- break;
- case 52:
- name = "Ratchaburi";
- break;
- case 53:
- name = "Nakhon Pathom";
- break;
- case 54:
- name = "Samut Songkhram";
- break;
- case 55:
- name = "Samut Sakhon";
- break;
- case 56:
- name = "Phetchaburi";
- break;
- case 57:
- name = "Prachuap Khiri Khan";
- break;
- case 58:
- name = "Chumphon";
- break;
- case 59:
- name = "Ranong";
- break;
- case 60:
- name = "Surat Thani";
- break;
- case 61:
- name = "Phangnga";
- break;
- case 62:
- name = "Phuket";
- break;
- case 63:
- name = "Krabi";
- break;
- case 64:
- name = "Nakhon Si Thammarat";
- break;
- case 65:
- name = "Trang";
- break;
- case 66:
- name = "Phatthalung";
- break;
- case 67:
- name = "Satun";
- break;
- case 68:
- name = "Songkhla";
- break;
- case 69:
- name = "Pattani";
- break;
- case 70:
- name = "Yala";
- break;
- case 71:
- name = "Ubon Ratchathani";
- break;
- case 72:
- name = "Yasothon";
- break;
- case 73:
- name = "Nakhon Phanom";
- break;
- case 75:
- name = "Ubon Ratchathani";
- break;
- case 76:
- name = "Udon Thani";
- break;
- case 77:
- name = "Amnat Charoen";
- break;
- case 78:
- name = "Mukdahan";
- break;
- case 79:
- name = "Nong Bua Lamphu";
- break;
- case 80:
- name = "Sa Kaeo";
- break;
- }
- }
- if (country_code.equals("TJ") == true) {
- switch (region_code2) {
- case 1:
- name = "Kuhistoni Badakhshon";
- break;
- case 2:
- name = "Khatlon";
- break;
- case 3:
- name = "Sughd";
- break;
- }
- }
- if (country_code.equals("TM") == true) {
- switch (region_code2) {
- case 1:
- name = "Ahal";
- break;
- case 2:
- name = "Balkan";
- break;
- case 3:
- name = "Dashoguz";
- break;
- case 4:
- name = "Lebap";
- break;
- case 5:
- name = "Mary";
- break;
- }
- }
- if (country_code.equals("TN") == true) {
- switch (region_code2) {
- case 2:
- name = "Kasserine";
- break;
- case 3:
- name = "Kairouan";
- break;
- case 6:
- name = "Jendouba";
- break;
- case 14:
- name = "El Kef";
- break;
- case 15:
- name = "Al Mahdia";
- break;
- case 16:
- name = "Al Munastir";
- break;
- case 17:
- name = "Bajah";
- break;
- case 18:
- name = "Bizerte";
- break;
- case 19:
- name = "Nabeul";
- break;
- case 22:
- name = "Siliana";
- break;
- case 23:
- name = "Sousse";
- break;
- case 26:
- name = "Ariana";
- break;
- case 27:
- name = "Ben Arous";
- break;
- case 28:
- name = "Madanin";
- break;
- case 29:
- name = "Gabes";
- break;
- case 30:
- name = "Gafsa";
- break;
- case 31:
- name = "Kebili";
- break;
- case 32:
- name = "Sfax";
- break;
- case 33:
- name = "Sidi Bou Zid";
- break;
- case 34:
- name = "Tataouine";
- break;
- case 35:
- name = "Tozeur";
- break;
- case 36:
- name = "Tunis";
- break;
- case 37:
- name = "Zaghouan";
- break;
- case 38:
- name = "Aiana";
- break;
- case 39:
- name = "Manouba";
- break;
- }
- }
- if (country_code.equals("TO") == true) {
- switch (region_code2) {
- case 1:
- name = "Ha";
- break;
- case 2:
- name = "Tongatapu";
- break;
- case 3:
- name = "Vava";
- break;
- }
- }
- if (country_code.equals("TR") == true) {
- switch (region_code2) {
- case 2:
- name = "Adiyaman";
- break;
- case 3:
- name = "Afyonkarahisar";
- break;
- case 4:
- name = "Agri";
- break;
- case 5:
- name = "Amasya";
- break;
- case 7:
- name = "Antalya";
- break;
- case 8:
- name = "Artvin";
- break;
- case 9:
- name = "Aydin";
- break;
- case 10:
- name = "Balikesir";
- break;
- case 11:
- name = "Bilecik";
- break;
- case 12:
- name = "Bingol";
- break;
- case 13:
- name = "Bitlis";
- break;
- case 14:
- name = "Bolu";
- break;
- case 15:
- name = "Burdur";
- break;
- case 16:
- name = "Bursa";
- break;
- case 17:
- name = "Canakkale";
- break;
- case 19:
- name = "Corum";
- break;
- case 20:
- name = "Denizli";
- break;
- case 21:
- name = "Diyarbakir";
- break;
- case 22:
- name = "Edirne";
- break;
- case 23:
- name = "Elazig";
- break;
- case 24:
- name = "Erzincan";
- break;
- case 25:
- name = "Erzurum";
- break;
- case 26:
- name = "Eskisehir";
- break;
- case 28:
- name = "Giresun";
- break;
- case 31:
- name = "Hatay";
- break;
- case 32:
- name = "Mersin";
- break;
- case 33:
- name = "Isparta";
- break;
- case 34:
- name = "Istanbul";
- break;
- case 35:
- name = "Izmir";
- break;
- case 37:
- name = "Kastamonu";
- break;
- case 38:
- name = "Kayseri";
- break;
- case 39:
- name = "Kirklareli";
- break;
- case 40:
- name = "Kirsehir";
- break;
- case 41:
- name = "Kocaeli";
- break;
- case 43:
- name = "Kutahya";
- break;
- case 44:
- name = "Malatya";
- break;
- case 45:
- name = "Manisa";
- break;
- case 46:
- name = "Kahramanmaras";
- break;
- case 48:
- name = "Mugla";
- break;
- case 49:
- name = "Mus";
- break;
- case 50:
- name = "Nevsehir";
- break;
- case 52:
- name = "Ordu";
- break;
- case 53:
- name = "Rize";
- break;
- case 54:
- name = "Sakarya";
- break;
- case 55:
- name = "Samsun";
- break;
- case 57:
- name = "Sinop";
- break;
- case 58:
- name = "Sivas";
- break;
- case 59:
- name = "Tekirdag";
- break;
- case 60:
- name = "Tokat";
- break;
- case 61:
- name = "Trabzon";
- break;
- case 62:
- name = "Tunceli";
- break;
- case 63:
- name = "Sanliurfa";
- break;
- case 64:
- name = "Usak";
- break;
- case 65:
- name = "Van";
- break;
- case 66:
- name = "Yozgat";
- break;
- case 68:
- name = "Ankara";
- break;
- case 69:
- name = "Gumushane";
- break;
- case 70:
- name = "Hakkari";
- break;
- case 71:
- name = "Konya";
- break;
- case 72:
- name = "Mardin";
- break;
- case 73:
- name = "Nigde";
- break;
- case 74:
- name = "Siirt";
- break;
- case 75:
- name = "Aksaray";
- break;
- case 76:
- name = "Batman";
- break;
- case 77:
- name = "Bayburt";
- break;
- case 78:
- name = "Karaman";
- break;
- case 79:
- name = "Kirikkale";
- break;
- case 80:
- name = "Sirnak";
- break;
- case 81:
- name = "Adana";
- break;
- case 82:
- name = "Cankiri";
- break;
- case 83:
- name = "Gaziantep";
- break;
- case 84:
- name = "Kars";
- break;
- case 85:
- name = "Zonguldak";
- break;
- case 86:
- name = "Ardahan";
- break;
- case 87:
- name = "Bartin";
- break;
- case 88:
- name = "Igdir";
- break;
- case 89:
- name = "Karabuk";
- break;
- case 90:
- name = "Kilis";
- break;
- case 91:
- name = "Osmaniye";
- break;
- case 92:
- name = "Yalova";
- break;
- case 93:
- name = "Duzce";
- break;
- }
- }
- if (country_code.equals("TT") == true) {
- switch (region_code2) {
- case 1:
- name = "Arima";
- break;
- case 2:
- name = "Caroni";
- break;
- case 3:
- name = "Mayaro";
- break;
- case 4:
- name = "Nariva";
- break;
- case 5:
- name = "Port-of-Spain";
- break;
- case 6:
- name = "Saint Andrew";
- break;
- case 7:
- name = "Saint David";
- break;
- case 8:
- name = "Saint George";
- break;
- case 9:
- name = "Saint Patrick";
- break;
- case 10:
- name = "San Fernando";
- break;
- case 11:
- name = "Tobago";
- break;
- case 12:
- name = "Victoria";
- break;
- }
- }
- if (country_code.equals("TW") == true) {
- switch (region_code2) {
- case 1:
- name = "Fu-chien";
- break;
- case 2:
- name = "Kao-hsiung";
- break;
- case 3:
- name = "T'ai-pei";
- break;
- case 4:
- name = "T'ai-wan";
- break;
- }
- }
- if (country_code.equals("TZ") == true) {
- switch (region_code2) {
- case 2:
- name = "Pwani";
- break;
- case 3:
- name = "Dodoma";
- break;
- case 4:
- name = "Iringa";
- break;
- case 5:
- name = "Kigoma";
- break;
- case 6:
- name = "Kilimanjaro";
- break;
- case 7:
- name = "Lindi";
- break;
- case 8:
- name = "Mara";
- break;
- case 9:
- name = "Mbeya";
- break;
- case 10:
- name = "Morogoro";
- break;
- case 11:
- name = "Mtwara";
- break;
- case 12:
- name = "Mwanza";
- break;
- case 13:
- name = "Pemba North";
- break;
- case 14:
- name = "Ruvuma";
- break;
- case 15:
- name = "Shinyanga";
- break;
- case 16:
- name = "Singida";
- break;
- case 17:
- name = "Tabora";
- break;
- case 18:
- name = "Tanga";
- break;
- case 19:
- name = "Kagera";
- break;
- case 20:
- name = "Pemba South";
- break;
- case 21:
- name = "Zanzibar Central";
- break;
- case 22:
- name = "Zanzibar North";
- break;
- case 23:
- name = "Dar es Salaam";
- break;
- case 24:
- name = "Rukwa";
- break;
- case 25:
- name = "Zanzibar Urban";
- break;
- case 26:
- name = "Arusha";
- break;
- case 27:
- name = "Manyara";
- break;
- }
- }
- if (country_code.equals("UA") == true) {
- switch (region_code2) {
- case 1:
- name = "Cherkas'ka Oblast'";
- break;
- case 2:
- name = "Chernihivs'ka Oblast'";
- break;
- case 3:
- name = "Chernivets'ka Oblast'";
- break;
- case 4:
- name = "Dnipropetrovs'ka Oblast'";
- break;
- case 5:
- name = "Donets'ka Oblast'";
- break;
- case 6:
- name = "Ivano-Frankivs'ka Oblast'";
- break;
- case 7:
- name = "Kharkivs'ka Oblast'";
- break;
- case 8:
- name = "Khersons'ka Oblast'";
- break;
- case 9:
- name = "Khmel'nyts'ka Oblast'";
- break;
- case 10:
- name = "Kirovohrads'ka Oblast'";
- break;
- case 11:
- name = "Krym";
- break;
- case 12:
- name = "Kyyiv";
- break;
- case 13:
- name = "Kyyivs'ka Oblast'";
- break;
- case 14:
- name = "Luhans'ka Oblast'";
- break;
- case 15:
- name = "L'vivs'ka Oblast'";
- break;
- case 16:
- name = "Mykolayivs'ka Oblast'";
- break;
- case 17:
- name = "Odes'ka Oblast'";
- break;
- case 18:
- name = "Poltavs'ka Oblast'";
- break;
- case 19:
- name = "Rivnens'ka Oblast'";
- break;
- case 20:
- name = "Sevastopol'";
- break;
- case 21:
- name = "Sums'ka Oblast'";
- break;
- case 22:
- name = "Ternopil's'ka Oblast'";
- break;
- case 23:
- name = "Vinnyts'ka Oblast'";
- break;
- case 24:
- name = "Volyns'ka Oblast'";
- break;
- case 25:
- name = "Zakarpats'ka Oblast'";
- break;
- case 26:
- name = "Zaporiz'ka Oblast'";
- break;
- case 27:
- name = "Zhytomyrs'ka Oblast'";
- break;
- }
- }
- if (country_code.equals("UG") == true) {
- switch (region_code2) {
- case 5:
- name = "Busoga";
- break;
- case 8:
- name = "Karamoja";
- break;
- case 12:
- name = "South Buganda";
- break;
- case 18:
- name = "Central";
- break;
- case 20:
- name = "Eastern";
- break;
- case 21:
- name = "Nile";
- break;
- case 22:
- name = "North Buganda";
- break;
- case 23:
- name = "Northern";
- break;
- case 24:
- name = "Southern";
- break;
- case 25:
- name = "Western";
- break;
- case 33:
- name = "Jinja";
- break;
- case 36:
- name = "Kalangala";
- break;
- case 37:
- name = "Kampala";
- break;
- case 42:
- name = "Kiboga";
- break;
- case 52:
- name = "Mbarara";
- break;
- case 56:
- name = "Mubende";
- break;
- case 65:
- name = "Adjumani";
- break;
- case 66:
- name = "Bugiri";
- break;
- case 67:
- name = "Busia";
- break;
- case 69:
- name = "Katakwi";
- break;
- case 71:
- name = "Masaka";
- break;
- case 73:
- name = "Nakasongola";
- break;
- case 74:
- name = "Sembabule";
- break;
- case 77:
- name = "Arua";
- break;
- case 78:
- name = "Iganga";
- break;
- case 79:
- name = "Kabarole";
- break;
- case 80:
- name = "Kaberamaido";
- break;
- case 81:
- name = "Kamwenge";
- break;
- case 82:
- name = "Kanungu";
- break;
- case 83:
- name = "Kayunga";
- break;
- case 84:
- name = "Kitgum";
- break;
- case 85:
- name = "Kyenjojo";
- break;
- case 86:
- name = "Mayuge";
- break;
- case 87:
- name = "Mbale";
- break;
- case 88:
- name = "Moroto";
- break;
- case 89:
- name = "Mpigi";
- break;
- case 90:
- name = "Mukono";
- break;
- case 91:
- name = "Nakapiripirit";
- break;
- case 92:
- name = "Pader";
- break;
- case 93:
- name = "Rukungiri";
- break;
- case 94:
- name = "Sironko";
- break;
- case 95:
- name = "Soroti";
- break;
- case 96:
- name = "Wakiso";
- break;
- case 97:
- name = "Yumbe";
- break;
- }
- }
- if (country_code.equals("UY") == true) {
- switch (region_code2) {
- case 1:
- name = "Artigas";
- break;
- case 2:
- name = "Canelones";
- break;
- case 3:
- name = "Cerro Largo";
- break;
- case 4:
- name = "Colonia";
- break;
- case 5:
- name = "Durazno";
- break;
- case 6:
- name = "Flores";
- break;
- case 7:
- name = "Florida";
- break;
- case 8:
- name = "Lavalleja";
- break;
- case 9:
- name = "Maldonado";
- break;
- case 10:
- name = "Montevideo";
- break;
- case 11:
- name = "Paysandu";
- break;
- case 12:
- name = "Rio Negro";
- break;
- case 13:
- name = "Rivera";
- break;
- case 14:
- name = "Rocha";
- break;
- case 15:
- name = "Salto";
- break;
- case 16:
- name = "San Jose";
- break;
- case 17:
- name = "Soriano";
- break;
- case 18:
- name = "Tacuarembo";
- break;
- case 19:
- name = "Treinta y Tres";
- break;
- }
- }
- if (country_code.equals("UZ") == true) {
- switch (region_code2) {
- case 1:
- name = "Andijon";
- break;
- case 2:
- name = "Bukhoro";
- break;
- case 3:
- name = "Farghona";
- break;
- case 4:
- name = "Jizzakh";
- break;
- case 5:
- name = "Khorazm";
- break;
- case 6:
- name = "Namangan";
- break;
- case 7:
- name = "Nawoiy";
- break;
- case 8:
- name = "Qashqadaryo";
- break;
- case 9:
- name = "Qoraqalpoghiston";
- break;
- case 10:
- name = "Samarqand";
- break;
- case 11:
- name = "Sirdaryo";
- break;
- case 12:
- name = "Surkhondaryo";
- break;
- case 13:
- name = "Toshkent";
- break;
- case 14:
- name = "Toshkent";
- break;
- }
- }
- if (country_code.equals("VC") == true) {
- switch (region_code2) {
- case 1:
- name = "Charlotte";
- break;
- case 2:
- name = "Saint Andrew";
- break;
- case 3:
- name = "Saint David";
- break;
- case 4:
- name = "Saint George";
- break;
- case 5:
- name = "Saint Patrick";
- break;
- case 6:
- name = "Grenadines";
- break;
- }
- }
- if (country_code.equals("VE") == true) {
- switch (region_code2) {
- case 1:
- name = "Amazonas";
- break;
- case 2:
- name = "Anzoategui";
- break;
- case 3:
- name = "Apure";
- break;
- case 4:
- name = "Aragua";
- break;
- case 5:
- name = "Barinas";
- break;
- case 6:
- name = "Bolivar";
- break;
- case 7:
- name = "Carabobo";
- break;
- case 8:
- name = "Cojedes";
- break;
- case 9:
- name = "Delta Amacuro";
- break;
- case 11:
- name = "Falcon";
- break;
- case 12:
- name = "Guarico";
- break;
- case 13:
- name = "Lara";
- break;
- case 14:
- name = "Merida";
- break;
- case 15:
- name = "Miranda";
- break;
- case 16:
- name = "Monagas";
- break;
- case 17:
- name = "Nueva Esparta";
- break;
- case 18:
- name = "Portuguesa";
- break;
- case 19:
- name = "Sucre";
- break;
- case 20:
- name = "Tachira";
- break;
- case 21:
- name = "Trujillo";
- break;
- case 22:
- name = "Yaracuy";
- break;
- case 23:
- name = "Zulia";
- break;
- case 24:
- name = "Dependencias Federales";
- break;
- case 25:
- name = "Distrito Federal";
- break;
- case 26:
- name = "Vargas";
- break;
- }
- }
- if (country_code.equals("VN") == true) {
- switch (region_code2) {
- case 1:
- name = "An Giang";
- break;
- case 2:
- name = "Bac Thai";
- break;
- case 3:
- name = "Ben Tre";
- break;
- case 4:
- name = "Binh Tri Thien";
- break;
- case 5:
- name = "Cao Bang";
- break;
- case 6:
- name = "Cuu Long";
- break;
- case 7:
- name = "Dac Lac";
- break;
- case 9:
- name = "Dong Thap";
- break;
- case 11:
- name = "Ha Bac";
- break;
- case 12:
- name = "Hai Hung";
- break;
- case 13:
- name = "Hai Phong";
- break;
- case 14:
- name = "Ha Nam Ninh";
- break;
- case 15:
- name = "Ha Noi";
- break;
- case 16:
- name = "Ha Son Binh";
- break;
- case 17:
- name = "Ha Tuyen";
- break;
- case 19:
- name = "Hoang Lien Son";
- break;
- case 20:
- name = "Ho Chi Minh";
- break;
- case 21:
- name = "Kien Giang";
- break;
- case 22:
- name = "Lai Chau";
- break;
- case 23:
- name = "Lam Dong";
- break;
- case 24:
- name = "Long An";
- break;
- case 25:
- name = "Minh Hai";
- break;
- case 26:
- name = "Nghe Tinh";
- break;
- case 27:
- name = "Nghia Binh";
- break;
- case 28:
- name = "Phu Khanh";
- break;
- case 29:
- name = "Quang Nam-Da Nang";
- break;
- case 30:
- name = "Quang Ninh";
- break;
- case 31:
- name = "Song Be";
- break;
- case 32:
- name = "Son La";
- break;
- case 33:
- name = "Tay Ninh";
- break;
- case 34:
- name = "Thanh Hoa";
- break;
- case 35:
- name = "Thai Binh";
- break;
- case 36:
- name = "Thuan Hai";
- break;
- case 37:
- name = "Tien Giang";
- break;
- case 38:
- name = "Vinh Phu";
- break;
- case 39:
- name = "Lang Son";
- break;
- case 40:
- name = "Dong Nai";
- break;
- case 43:
- name = "An Giang";
- break;
- case 44:
- name = "Dac Lac";
- break;
- case 45:
- name = "Dong Nai";
- break;
- case 46:
- name = "Dong Thap";
- break;
- case 47:
- name = "Kien Giang";
- break;
- case 48:
- name = "Minh Hai";
- break;
- case 49:
- name = "Song Be";
- break;
- case 50:
- name = "Vinh Phu";
- break;
- case 51:
- name = "Ha Noi";
- break;
- case 52:
- name = "Ho Chi Minh";
- break;
- case 53:
- name = "Ba Ria-Vung Tau";
- break;
- case 54:
- name = "Binh Dinh";
- break;
- case 55:
- name = "Binh Thuan";
- break;
- case 56:
- name = "Can Tho";
- break;
- case 57:
- name = "Gia Lai";
- break;
- case 58:
- name = "Ha Giang";
- break;
- case 59:
- name = "Ha Tay";
- break;
- case 60:
- name = "Ha Tinh";
- break;
- case 61:
- name = "Hoa Binh";
- break;
- case 62:
- name = "Khanh Hoa";
- break;
- case 63:
- name = "Kon Tum";
- break;
- case 64:
- name = "Quang Tri";
- break;
- case 65:
- name = "Nam Ha";
- break;
- case 66:
- name = "Nghe An";
- break;
- case 67:
- name = "Ninh Binh";
- break;
- case 68:
- name = "Ninh Thuan";
- break;
- case 69:
- name = "Phu Yen";
- break;
- case 70:
- name = "Quang Binh";
- break;
- case 71:
- name = "Quang Ngai";
- break;
- case 72:
- name = "Quang Tri";
- break;
- case 73:
- name = "Soc Trang";
- break;
- case 74:
- name = "Thua Thien";
- break;
- case 75:
- name = "Tra Vinh";
- break;
- case 76:
- name = "Tuyen Quang";
- break;
- case 77:
- name = "Vinh Long";
- break;
- case 78:
- name = "Da Nang";
- break;
- case 79:
- name = "Hai Duong";
- break;
- case 80:
- name = "Ha Nam";
- break;
- case 81:
- name = "Hung Yen";
- break;
- case 82:
- name = "Nam Dinh";
- break;
- case 83:
- name = "Phu Tho";
- break;
- case 84:
- name = "Quang Nam";
- break;
- case 85:
- name = "Thai Nguyen";
- break;
- case 86:
- name = "Vinh Puc Province";
- break;
- case 87:
- name = "Can Tho";
- break;
- case 88:
- name = "Dak Lak";
- break;
- case 89:
- name = "Lai Chau";
- break;
- case 90:
- name = "Lao Cai";
- break;
- case 91:
- name = "Dak Nong";
- break;
- case 92:
- name = "Dien Bien";
- break;
- case 93:
- name = "Hau Giang";
- break;
- }
- }
- if (country_code.equals("VU") == true) {
- switch (region_code2) {
- case 5:
- name = "Ambrym";
- break;
- case 6:
- name = "Aoba";
- break;
- case 7:
- name = "Torba";
- break;
- case 8:
- name = "Efate";
- break;
- case 9:
- name = "Epi";
- break;
- case 10:
- name = "Malakula";
- break;
- case 11:
- name = "Paama";
- break;
- case 12:
- name = "Pentecote";
- break;
- case 13:
- name = "Sanma";
- break;
- case 14:
- name = "Shepherd";
- break;
- case 15:
- name = "Tafea";
- break;
- case 16:
- name = "Malampa";
- break;
- case 17:
- name = "Penama";
- break;
- case 18:
- name = "Shefa";
- break;
- }
- }
- if (country_code.equals("WS") == true) {
- switch (region_code2) {
- case 2:
- name = "Aiga-i-le-Tai";
- break;
- case 3:
- name = "Atua";
- break;
- case 4:
- name = "Fa";
- break;
- case 5:
- name = "Gaga";
- break;
- case 6:
- name = "Va";
- break;
- case 7:
- name = "Gagaifomauga";
- break;
- case 8:
- name = "Palauli";
- break;
- case 9:
- name = "Satupa";
- break;
- case 10:
- name = "Tuamasaga";
- break;
- case 11:
- name = "Vaisigano";
- break;
- }
- }
- if (country_code.equals("YE") == true) {
- switch (region_code2) {
- case 1:
- name = "Abyan";
- break;
- case 2:
- name = "Adan";
- break;
- case 3:
- name = "Al Mahrah";
- break;
- case 4:
- name = "Hadramawt";
- break;
- case 5:
- name = "Shabwah";
- break;
- case 6:
- name = "Al Ghaydah";
- break;
- case 8:
- name = "Al Hudaydah";
- break;
- case 10:
- name = "Al Mahwit";
- break;
- case 11:
- name = "Dhamar";
- break;
- case 14:
- name = "Ma'rib";
- break;
- case 15:
- name = "Sa";
- break;
- case 16:
- name = "San";
- break;
- case 20:
- name = "Al Bayda'";
- break;
- case 21:
- name = "Al Jawf";
- break;
- case 22:
- name = "Hajjah";
- break;
- case 23:
- name = "Ibb";
- break;
- case 24:
- name = "Lahij";
- break;
- case 25:
- name = "Ta";
- break;
- }
- }
- if (country_code.equals("ZA") == true) {
- switch (region_code2) {
- case 1:
- name = "North-Western Province";
- break;
- case 2:
- name = "KwaZulu-Natal";
- break;
- case 3:
- name = "Free State";
- break;
- case 5:
- name = "Eastern Cape";
- break;
- case 6:
- name = "Gauteng";
- break;
- case 7:
- name = "Mpumalanga";
- break;
- case 8:
- name = "Northern Cape";
- break;
- case 9:
- name = "Limpopo";
- break;
- case 10:
- name = "North-West";
- break;
- case 11:
- name = "Western Cape";
- break;
- }
- }
- if (country_code.equals("ZM") == true) {
- switch (region_code2) {
- case 1:
- name = "Western";
- break;
- case 2:
- name = "Central";
- break;
- case 3:
- name = "Eastern";
- break;
- case 4:
- name = "Luapula";
- break;
- case 5:
- name = "Northern";
- break;
- case 6:
- name = "North-Western";
- break;
- case 7:
- name = "Southern";
- break;
- case 8:
- name = "Copperbelt";
- break;
- case 9:
- name = "Lusaka";
- break;
- }
- }
- if (country_code.equals("ZW") == true) {
- switch (region_code2) {
- case 1:
- name = "Manicaland";
- break;
- case 2:
- name = "Midlands";
- break;
- case 3:
- name = "Mashonaland Central";
- break;
- case 4:
- name = "Mashonaland East";
- break;
- case 5:
- name = "Mashonaland West";
- break;
- case 6:
- name = "Matabeleland North";
- break;
- case 7:
- name = "Matabeleland South";
- break;
- case 8:
- name = "Masvingo";
- break;
- case 9:
- name = "Bulawayo";
- break;
- case 10:
- name = "Harare";
- break;
- }
- }
- return name;
- }
-}
diff --git a/src/main/java/com/maxmind/geoip/timeZone.java b/src/main/java/com/maxmind/geoip/timeZone.java
deleted file mode 100644
index c47802a8..00000000
--- a/src/main/java/com/maxmind/geoip/timeZone.java
+++ /dev/null
@@ -1,1403 +0,0 @@
-package com.maxmind.geoip;
-// generated automatically from admin/generate_timeZone.pl
-public class timeZone {
- static public String timeZoneByCountryAndRegion(String country,String region) {
- String timezone = null;
- if (country == null) {
- return null;
- }
- if (region == null) {
- region = "";
- }
- if (country.equals("US") == true) {
- if (region.equals("AL") == true) {
- timezone = "America/Chicago";
- } else if (region.equals("AK") == true) {
- timezone = "America/Anchorage";
- } else if (region.equals("AZ") == true) {
- timezone = "America/Phoenix";
- } else if (region.equals("AR") == true) {
- timezone = "America/Chicago";
- } else if (region.equals("CA") == true) {
- timezone = "America/Los_Angeles";
- } else if (region.equals("CO") == true) {
- timezone = "America/Denver";
- } else if (region.equals("CT") == true) {
- timezone = "America/New_York";
- } else if (region.equals("DE") == true) {
- timezone = "America/New_York";
- } else if (region.equals("DC") == true) {
- timezone = "America/New_York";
- } else if (region.equals("FL") == true) {
- timezone = "America/New_York";
- } else if (region.equals("GA") == true) {
- timezone = "America/New_York";
- } else if (region.equals("HI") == true) {
- timezone = "Pacific/Honolulu";
- } else if (region.equals("ID") == true) {
- timezone = "America/Denver";
- } else if (region.equals("IL") == true) {
- timezone = "America/Chicago";
- } else if (region.equals("IN") == true) {
- timezone = "America/Indianapolis";
- } else if (region.equals("IA") == true) {
- timezone = "America/Chicago";
- } else if (region.equals("KS") == true) {
- timezone = "America/Chicago";
- } else if (region.equals("KY") == true) {
- timezone = "America/New_York";
- } else if (region.equals("LA") == true) {
- timezone = "America/Chicago";
- } else if (region.equals("ME") == true) {
- timezone = "America/New_York";
- } else if (region.equals("MD") == true) {
- timezone = "America/New_York";
- } else if (region.equals("MA") == true) {
- timezone = "America/New_York";
- } else if (region.equals("MI") == true) {
- timezone = "America/New_York";
- } else if (region.equals("MN") == true) {
- timezone = "America/Chicago";
- } else if (region.equals("MS") == true) {
- timezone = "America/Chicago";
- } else if (region.equals("MO") == true) {
- timezone = "America/Chicago";
- } else if (region.equals("MT") == true) {
- timezone = "America/Denver";
- } else if (region.equals("NE") == true) {
- timezone = "America/Chicago";
- } else if (region.equals("NV") == true) {
- timezone = "America/Los_Angeles";
- } else if (region.equals("NH") == true) {
- timezone = "America/New_York";
- } else if (region.equals("NJ") == true) {
- timezone = "America/New_York";
- } else if (region.equals("NM") == true) {
- timezone = "America/Denver";
- } else if (region.equals("NY") == true) {
- timezone = "America/New_York";
- } else if (region.equals("NC") == true) {
- timezone = "America/New_York";
- } else if (region.equals("ND") == true) {
- timezone = "America/Chicago";
- } else if (region.equals("OH") == true) {
- timezone = "America/New_York";
- } else if (region.equals("OK") == true) {
- timezone = "America/Chicago";
- } else if (region.equals("OR") == true) {
- timezone = "America/Los_Angeles";
- } else if (region.equals("PA") == true) {
- timezone = "America/New_York";
- } else if (region.equals("RI") == true) {
- timezone = "America/New_York";
- } else if (region.equals("SC") == true) {
- timezone = "America/New_York";
- } else if (region.equals("SD") == true) {
- timezone = "America/Chicago";
- } else if (region.equals("TN") == true) {
- timezone = "America/Chicago";
- } else if (region.equals("TX") == true) {
- timezone = "America/Chicago";
- } else if (region.equals("UT") == true) {
- timezone = "America/Denver";
- } else if (region.equals("VT") == true) {
- timezone = "America/New_York";
- } else if (region.equals("VA") == true) {
- timezone = "America/New_York";
- } else if (region.equals("WA") == true) {
- timezone = "America/Los_Angeles";
- } else if (region.equals("WV") == true) {
- timezone = "America/New_York";
- } else if (region.equals("WI") == true) {
- timezone = "America/Chicago";
- } else if (region.equals("WY") == true) {
- timezone = "America/Denver";
- }
- } else if (country.equals("CA") == true) {
- if (region.equals("AB") == true) {
- timezone = "America/Edmonton";
- } else if (region.equals("BC") == true) {
- timezone = "America/Vancouver";
- } else if (region.equals("MB") == true) {
- timezone = "America/Winnipeg";
- } else if (region.equals("NB") == true) {
- timezone = "America/Halifax";
- } else if (region.equals("NL") == true) {
- timezone = "America/St_Johns";
- } else if (region.equals("NT") == true) {
- timezone = "America/Yellowknife";
- } else if (region.equals("NS") == true) {
- timezone = "America/Halifax";
- } else if (region.equals("NU") == true) {
- timezone = "America/Rankin_Inlet";
- } else if (region.equals("ON") == true) {
- timezone = "America/Rainy_River";
- } else if (region.equals("PE") == true) {
- timezone = "America/Halifax";
- } else if (region.equals("QC") == true) {
- timezone = "America/Montreal";
- } else if (region.equals("SK") == true) {
- timezone = "America/Regina";
- } else if (region.equals("YT") == true) {
- timezone = "America/Whitehorse";
- }
- } else if (country.equals("AU") == true) {
- if (region.equals("01") == true) {
- timezone = "Australia/Canberra";
- } else if (region.equals("02") == true) {
- timezone = "Australia/NSW";
- } else if (region.equals("03") == true) {
- timezone = "Australia/North";
- } else if (region.equals("04") == true) {
- timezone = "Australia/Queensland";
- } else if (region.equals("05") == true) {
- timezone = "Australia/South";
- } else if (region.equals("06") == true) {
- timezone = "Australia/Tasmania";
- } else if (region.equals("07") == true) {
- timezone = "Australia/Victoria";
- } else if (region.equals("08") == true) {
- timezone = "Australia/West";
- }
- } else if (country.equals("AS") == true) {
- timezone = "US/Samoa";
- } else if (country.equals("CI") == true) {
- timezone = "Africa/Abidjan";
- } else if (country.equals("GH") == true) {
- timezone = "Africa/Accra";
- } else if (country.equals("DZ") == true) {
- timezone = "Africa/Algiers";
- } else if (country.equals("ER") == true) {
- timezone = "Africa/Asmera";
- } else if (country.equals("ML") == true) {
- timezone = "Africa/Bamako";
- } else if (country.equals("CF") == true) {
- timezone = "Africa/Bangui";
- } else if (country.equals("GM") == true) {
- timezone = "Africa/Banjul";
- } else if (country.equals("GW") == true) {
- timezone = "Africa/Bissau";
- } else if (country.equals("CG") == true) {
- timezone = "Africa/Brazzaville";
- } else if (country.equals("BI") == true) {
- timezone = "Africa/Bujumbura";
- } else if (country.equals("EG") == true) {
- timezone = "Africa/Cairo";
- } else if (country.equals("MA") == true) {
- timezone = "Africa/Casablanca";
- } else if (country.equals("GN") == true) {
- timezone = "Africa/Conakry";
- } else if (country.equals("SN") == true) {
- timezone = "Africa/Dakar";
- } else if (country.equals("DJ") == true) {
- timezone = "Africa/Djibouti";
- } else if (country.equals("SL") == true) {
- timezone = "Africa/Freetown";
- } else if (country.equals("BW") == true) {
- timezone = "Africa/Gaborone";
- } else if (country.equals("ZW") == true) {
- timezone = "Africa/Harare";
- } else if (country.equals("ZA") == true) {
- timezone = "Africa/Johannesburg";
- } else if (country.equals("UG") == true) {
- timezone = "Africa/Kampala";
- } else if (country.equals("SD") == true) {
- timezone = "Africa/Khartoum";
- } else if (country.equals("RW") == true) {
- timezone = "Africa/Kigali";
- } else if (country.equals("NG") == true) {
- timezone = "Africa/Lagos";
- } else if (country.equals("GA") == true) {
- timezone = "Africa/Libreville";
- } else if (country.equals("TG") == true) {
- timezone = "Africa/Lome";
- } else if (country.equals("AO") == true) {
- timezone = "Africa/Luanda";
- } else if (country.equals("ZM") == true) {
- timezone = "Africa/Lusaka";
- } else if (country.equals("GQ") == true) {
- timezone = "Africa/Malabo";
- } else if (country.equals("MZ") == true) {
- timezone = "Africa/Maputo";
- } else if (country.equals("LS") == true) {
- timezone = "Africa/Maseru";
- } else if (country.equals("SZ") == true) {
- timezone = "Africa/Mbabane";
- } else if (country.equals("SO") == true) {
- timezone = "Africa/Mogadishu";
- } else if (country.equals("LR") == true) {
- timezone = "Africa/Monrovia";
- } else if (country.equals("KE") == true) {
- timezone = "Africa/Nairobi";
- } else if (country.equals("TD") == true) {
- timezone = "Africa/Ndjamena";
- } else if (country.equals("NE") == true) {
- timezone = "Africa/Niamey";
- } else if (country.equals("MR") == true) {
- timezone = "Africa/Nouakchott";
- } else if (country.equals("BF") == true) {
- timezone = "Africa/Ouagadougou";
- } else if (country.equals("ST") == true) {
- timezone = "Africa/Sao_Tome";
- } else if (country.equals("LY") == true) {
- timezone = "Africa/Tripoli";
- } else if (country.equals("TN") == true) {
- timezone = "Africa/Tunis";
- } else if (country.equals("AI") == true) {
- timezone = "America/Anguilla";
- } else if (country.equals("AG") == true) {
- timezone = "America/Antigua";
- } else if (country.equals("AW") == true) {
- timezone = "America/Aruba";
- } else if (country.equals("BB") == true) {
- timezone = "America/Barbados";
- } else if (country.equals("BZ") == true) {
- timezone = "America/Belize";
- } else if (country.equals("CO") == true) {
- timezone = "America/Bogota";
- } else if (country.equals("VE") == true) {
- timezone = "America/Caracas";
- } else if (country.equals("KY") == true) {
- timezone = "America/Cayman";
- } else if (country.equals("CR") == true) {
- timezone = "America/Costa_Rica";
- } else if (country.equals("DM") == true) {
- timezone = "America/Dominica";
- } else if (country.equals("SV") == true) {
- timezone = "America/El_Salvador";
- } else if (country.equals("GD") == true) {
- timezone = "America/Grenada";
- } else if (country.equals("FR") == true) {
- timezone = "Europe/Paris";
- } else if (country.equals("GP") == true) {
- timezone = "America/Guadeloupe";
- } else if (country.equals("GT") == true) {
- timezone = "America/Guatemala";
- } else if (country.equals("GY") == true) {
- timezone = "America/Guyana";
- } else if (country.equals("CU") == true) {
- timezone = "America/Havana";
- } else if (country.equals("JM") == true) {
- timezone = "America/Jamaica";
- } else if (country.equals("BO") == true) {
- timezone = "America/La_Paz";
- } else if (country.equals("PE") == true) {
- timezone = "America/Lima";
- } else if (country.equals("NI") == true) {
- timezone = "America/Managua";
- } else if (country.equals("MQ") == true) {
- timezone = "America/Martinique";
- } else if (country.equals("UY") == true) {
- timezone = "America/Montevideo";
- } else if (country.equals("MS") == true) {
- timezone = "America/Montserrat";
- } else if (country.equals("BS") == true) {
- timezone = "America/Nassau";
- } else if (country.equals("PA") == true) {
- timezone = "America/Panama";
- } else if (country.equals("SR") == true) {
- timezone = "America/Paramaribo";
- } else if (country.equals("PR") == true) {
- timezone = "America/Puerto_Rico";
- } else if (country.equals("KN") == true) {
- timezone = "America/St_Kitts";
- } else if (country.equals("LC") == true) {
- timezone = "America/St_Lucia";
- } else if (country.equals("VC") == true) {
- timezone = "America/St_Vincent";
- } else if (country.equals("HN") == true) {
- timezone = "America/Tegucigalpa";
- } else if (country.equals("YE") == true) {
- timezone = "Asia/Aden";
- } else if (country.equals("JO") == true) {
- timezone = "Asia/Amman";
- } else if (country.equals("TM") == true) {
- timezone = "Asia/Ashgabat";
- } else if (country.equals("IQ") == true) {
- timezone = "Asia/Baghdad";
- } else if (country.equals("BH") == true) {
- timezone = "Asia/Bahrain";
- } else if (country.equals("AZ") == true) {
- timezone = "Asia/Baku";
- } else if (country.equals("TH") == true) {
- timezone = "Asia/Bangkok";
- } else if (country.equals("LB") == true) {
- timezone = "Asia/Beirut";
- } else if (country.equals("KG") == true) {
- timezone = "Asia/Bishkek";
- } else if (country.equals("BN") == true) {
- timezone = "Asia/Brunei";
- } else if (country.equals("IN") == true) {
- timezone = "Asia/Calcutta";
- } else if (country.equals("MN") == true) {
- timezone = "Asia/Choibalsan";
- } else if (country.equals("LK") == true) {
- timezone = "Asia/Colombo";
- } else if (country.equals("BD") == true) {
- timezone = "Asia/Dhaka";
- } else if (country.equals("AE") == true) {
- timezone = "Asia/Dubai";
- } else if (country.equals("TJ") == true) {
- timezone = "Asia/Dushanbe";
- } else if (country.equals("HK") == true) {
- timezone = "Asia/Hong_Kong";
- } else if (country.equals("TR") == true) {
- timezone = "Asia/Istanbul";
- } else if (country.equals("IL") == true) {
- timezone = "Asia/Jerusalem";
- } else if (country.equals("AF") == true) {
- timezone = "Asia/Kabul";
- } else if (country.equals("PK") == true) {
- timezone = "Asia/Karachi";
- } else if (country.equals("NP") == true) {
- timezone = "Asia/Katmandu";
- } else if (country.equals("KW") == true) {
- timezone = "Asia/Kuwait";
- } else if (country.equals("MO") == true) {
- timezone = "Asia/Macao";
- } else if (country.equals("PH") == true) {
- timezone = "Asia/Manila";
- } else if (country.equals("OM") == true) {
- timezone = "Asia/Muscat";
- } else if (country.equals("CY") == true) {
- timezone = "Asia/Nicosia";
- } else if (country.equals("KP") == true) {
- timezone = "Asia/Pyongyang";
- } else if (country.equals("QA") == true) {
- timezone = "Asia/Qatar";
- } else if (country.equals("MM") == true) {
- timezone = "Asia/Rangoon";
- } else if (country.equals("SA") == true) {
- timezone = "Asia/Riyadh";
- } else if (country.equals("KR") == true) {
- timezone = "Asia/Seoul";
- } else if (country.equals("SG") == true) {
- timezone = "Asia/Singapore";
- } else if (country.equals("TW") == true) {
- timezone = "Asia/Taipei";
- } else if (country.equals("GE") == true) {
- timezone = "Asia/Tbilisi";
- } else if (country.equals("BT") == true) {
- timezone = "Asia/Thimphu";
- } else if (country.equals("JP") == true) {
- timezone = "Asia/Tokyo";
- } else if (country.equals("LA") == true) {
- timezone = "Asia/Vientiane";
- } else if (country.equals("AM") == true) {
- timezone = "Asia/Yerevan";
- } else if (country.equals("BM") == true) {
- timezone = "Atlantic/Bermuda";
- } else if (country.equals("CV") == true) {
- timezone = "Atlantic/Cape_Verde";
- } else if (country.equals("FO") == true) {
- timezone = "Atlantic/Faeroe";
- } else if (country.equals("IS") == true) {
- timezone = "Atlantic/Reykjavik";
- } else if (country.equals("GS") == true) {
- timezone = "Atlantic/South_Georgia";
- } else if (country.equals("SH") == true) {
- timezone = "Atlantic/St_Helena";
- } else if (country.equals("CL") == true) {
- timezone = "Chile/Continental";
- } else if (country.equals("NL") == true) {
- timezone = "Europe/Amsterdam";
- } else if (country.equals("AD") == true) {
- timezone = "Europe/Andorra";
- } else if (country.equals("GR") == true) {
- timezone = "Europe/Athens";
- } else if (country.equals("YU") == true) {
- timezone = "Europe/Belgrade";
- } else if (country.equals("DE") == true) {
- timezone = "Europe/Berlin";
- } else if (country.equals("SK") == true) {
- timezone = "Europe/Bratislava";
- } else if (country.equals("BE") == true) {
- timezone = "Europe/Brussels";
- } else if (country.equals("RO") == true) {
- timezone = "Europe/Bucharest";
- } else if (country.equals("HU") == true) {
- timezone = "Europe/Budapest";
- } else if (country.equals("DK") == true) {
- timezone = "Europe/Copenhagen";
- } else if (country.equals("IE") == true) {
- timezone = "Europe/Dublin";
- } else if (country.equals("GI") == true) {
- timezone = "Europe/Gibraltar";
- } else if (country.equals("FI") == true) {
- timezone = "Europe/Helsinki";
- } else if (country.equals("SI") == true) {
- timezone = "Europe/Ljubljana";
- } else if (country.equals("GB") == true) {
- timezone = "Europe/London";
- } else if (country.equals("LU") == true) {
- timezone = "Europe/Luxembourg";
- } else if (country.equals("MT") == true) {
- timezone = "Europe/Malta";
- } else if (country.equals("BY") == true) {
- timezone = "Europe/Minsk";
- } else if (country.equals("MC") == true) {
- timezone = "Europe/Monaco";
- } else if (country.equals("NO") == true) {
- timezone = "Europe/Oslo";
- } else if (country.equals("CZ") == true) {
- timezone = "Europe/Prague";
- } else if (country.equals("LV") == true) {
- timezone = "Europe/Riga";
- } else if (country.equals("IT") == true) {
- timezone = "Europe/Rome";
- } else if (country.equals("SM") == true) {
- timezone = "Europe/San_Marino";
- } else if (country.equals("BA") == true) {
- timezone = "Europe/Sarajevo";
- } else if (country.equals("MK") == true) {
- timezone = "Europe/Skopje";
- } else if (country.equals("BG") == true) {
- timezone = "Europe/Sofia";
- } else if (country.equals("SE") == true) {
- timezone = "Europe/Stockholm";
- } else if (country.equals("EE") == true) {
- timezone = "Europe/Tallinn";
- } else if (country.equals("AL") == true) {
- timezone = "Europe/Tirane";
- } else if (country.equals("LI") == true) {
- timezone = "Europe/Vaduz";
- } else if (country.equals("VA") == true) {
- timezone = "Europe/Vatican";
- } else if (country.equals("AT") == true) {
- timezone = "Europe/Vienna";
- } else if (country.equals("LT") == true) {
- timezone = "Europe/Vilnius";
- } else if (country.equals("PL") == true) {
- timezone = "Europe/Warsaw";
- } else if (country.equals("HR") == true) {
- timezone = "Europe/Zagreb";
- } else if (country.equals("IR") == true) {
- timezone = "Asia/Tehran";
- } else if (country.equals("MG") == true) {
- timezone = "Indian/Antananarivo";
- } else if (country.equals("CX") == true) {
- timezone = "Indian/Christmas";
- } else if (country.equals("CC") == true) {
- timezone = "Indian/Cocos";
- } else if (country.equals("KM") == true) {
- timezone = "Indian/Comoro";
- } else if (country.equals("MV") == true) {
- timezone = "Indian/Maldives";
- } else if (country.equals("MU") == true) {
- timezone = "Indian/Mauritius";
- } else if (country.equals("YT") == true) {
- timezone = "Indian/Mayotte";
- } else if (country.equals("RE") == true) {
- timezone = "Indian/Reunion";
- } else if (country.equals("FJ") == true) {
- timezone = "Pacific/Fiji";
- } else if (country.equals("TV") == true) {
- timezone = "Pacific/Funafuti";
- } else if (country.equals("GU") == true) {
- timezone = "Pacific/Guam";
- } else if (country.equals("NR") == true) {
- timezone = "Pacific/Nauru";
- } else if (country.equals("NU") == true) {
- timezone = "Pacific/Niue";
- } else if (country.equals("NF") == true) {
- timezone = "Pacific/Norfolk";
- } else if (country.equals("PW") == true) {
- timezone = "Pacific/Palau";
- } else if (country.equals("PN") == true) {
- timezone = "Pacific/Pitcairn";
- } else if (country.equals("CK") == true) {
- timezone = "Pacific/Rarotonga";
- } else if (country.equals("WS") == true) {
- timezone = "Pacific/Samoa";
- } else if (country.equals("KI") == true) {
- timezone = "Pacific/Tarawa";
- } else if (country.equals("TO") == true) {
- timezone = "Pacific/Tongatapu";
- } else if (country.equals("WF") == true) {
- timezone = "Pacific/Wallis";
- } else if (country.equals("TZ") == true) {
- timezone = "Africa/Dar_es_Salaam";
- } else if (country.equals("VN") == true) {
- timezone = "Asia/Phnom_Penh";
- } else if (country.equals("KH") == true) {
- timezone = "Asia/Phnom_Penh";
- } else if (country.equals("CM") == true) {
- timezone = "Africa/Lagos";
- } else if (country.equals("DO") == true) {
- timezone = "America/Santo_Domingo";
- } else if (country.equals("ET") == true) {
- timezone = "Africa/Addis_Ababa";
- } else if (country.equals("FX") == true) {
- timezone = "Europe/Paris";
- } else if (country.equals("HT") == true) {
- timezone = "America/Port-au-Prince";
- } else if (country.equals("CH") == true) {
- timezone = "Europe/Zurich";
- } else if (country.equals("AN") == true) {
- timezone = "America/Curacao";
- } else if (country.equals("BJ") == true) {
- timezone = "Africa/Porto-Novo";
- } else if (country.equals("EH") == true) {
- timezone = "Africa/El_Aaiun";
- } else if (country.equals("FK") == true) {
- timezone = "Atlantic/Stanley";
- } else if (country.equals("GF") == true) {
- timezone = "America/Cayenne";
- } else if (country.equals("IO") == true) {
- timezone = "Indian/Chagos";
- } else if (country.equals("MD") == true) {
- timezone = "Europe/Chisinau";
- } else if (country.equals("MP") == true) {
- timezone = "Pacific/Saipan";
- } else if (country.equals("MW") == true) {
- timezone = "Africa/Blantyre";
- } else if (country.equals("NA") == true) {
- timezone = "Africa/Windhoek";
- } else if (country.equals("NC") == true) {
- timezone = "Pacific/Noumea";
- } else if (country.equals("PG") == true) {
- timezone = "Pacific/Port_Moresby";
- } else if (country.equals("PM") == true) {
- timezone = "America/Miquelon";
- } else if (country.equals("PS") == true) {
- timezone = "Asia/Gaza";
- } else if (country.equals("PY") == true) {
- timezone = "America/Asuncion";
- } else if (country.equals("SB") == true) {
- timezone = "Pacific/Guadalcanal";
- } else if (country.equals("SC") == true) {
- timezone = "Indian/Mahe";
- } else if (country.equals("SJ") == true) {
- timezone = "Arctic/Longyearbyen";
- } else if (country.equals("SY") == true) {
- timezone = "Asia/Damascus";
- } else if (country.equals("TC") == true) {
- timezone = "America/Grand_Turk";
- } else if (country.equals("TF") == true) {
- timezone = "Indian/Kerguelen";
- } else if (country.equals("TK") == true) {
- timezone = "Pacific/Fakaofo";
- } else if (country.equals("TT") == true) {
- timezone = "America/Port_of_Spain";
- } else if (country.equals("VG") == true) {
- timezone = "America/Tortola";
- } else if (country.equals("VI") == true) {
- timezone = "America/St_Thomas";
- } else if (country.equals("VU") == true) {
- timezone = "Pacific/Efate";
- } else if (country.equals("RS") == true) {
- timezone = "Europe/Belgrade";
- } else if (country.equals("ME") == true) {
- timezone = "Europe/Podgorica";
- } else if (country.equals("AX") == true) {
- timezone = "Europe/Mariehamn";
- } else if (country.equals("GG") == true) {
- timezone = "Europe/Guernsey";
- } else if (country.equals("IM") == true) {
- timezone = "Europe/Isle_of_Man";
- } else if (country.equals("JE") == true) {
- timezone = "Europe/Jersey";
- } else if (country.equals("BL") == true) {
- timezone = "America/St_Barthelemy";
- } else if (country.equals("MF") == true) {
- timezone = "America/Marigot";
- } else if (country.equals("AR") == true) {
- if (region.equals("01") == true) {
- timezone = "America/Argentina/Buenos_Aires";
- } else if (region.equals("02") == true) {
- timezone = "America/Argentina/Catamarca";
- } else if (region.equals("03") == true) {
- timezone = "America/Argentina/Tucuman";
- } else if (region.equals("04") == true) {
- timezone = "America/Argentina/Rio_Gallegos";
- } else if (region.equals("05") == true) {
- timezone = "America/Argentina/Cordoba";
- } else if (region.equals("06") == true) {
- timezone = "America/Argentina/Tucuman";
- } else if (region.equals("07") == true) {
- timezone = "America/Argentina/Buenos_Aires";
- } else if (region.equals("08") == true) {
- timezone = "America/Argentina/Buenos_Aires";
- } else if (region.equals("09") == true) {
- timezone = "America/Argentina/Tucuman";
- } else if (region.equals("10") == true) {
- timezone = "America/Argentina/Jujuy";
- } else if (region.equals("11") == true) {
- timezone = "America/Argentina/San_Luis";
- } else if (region.equals("12") == true) {
- timezone = "America/Argentina/La_Rioja";
- } else if (region.equals("13") == true) {
- timezone = "America/Argentina/Mendoza";
- } else if (region.equals("14") == true) {
- timezone = "America/Argentina/Buenos_Aires";
- } else if (region.equals("15") == true) {
- timezone = "America/Argentina/San_Luis";
- } else if (region.equals("16") == true) {
- timezone = "America/Argentina/Buenos_Aires";
- } else if (region.equals("17") == true) {
- timezone = "America/Argentina/Salta";
- } else if (region.equals("18") == true) {
- timezone = "America/Argentina/San_Juan";
- } else if (region.equals("19") == true) {
- timezone = "America/Argentina/San_Luis";
- } else if (region.equals("20") == true) {
- timezone = "America/Argentina/Rio_Gallegos";
- } else if (region.equals("21") == true) {
- timezone = "America/Argentina/Buenos_Aires";
- } else if (region.equals("22") == true) {
- timezone = "America/Argentina/Catamarca";
- } else if (region.equals("23") == true) {
- timezone = "America/Argentina/Ushuaia";
- } else if (region.equals("24") == true) {
- timezone = "America/Argentina/Tucuman";
- }
- } else if (country.equals("BR") == true) {
- if (region.equals("01") == true) {
- timezone = "America/Rio_Branco";
- } else if (region.equals("02") == true) {
- timezone = "America/Maceio";
- } else if (region.equals("03") == true) {
- timezone = "America/Sao_Paulo";
- } else if (region.equals("04") == true) {
- timezone = "America/Manaus";
- } else if (region.equals("05") == true) {
- timezone = "America/Bahia";
- } else if (region.equals("06") == true) {
- timezone = "America/Fortaleza";
- } else if (region.equals("07") == true) {
- timezone = "America/Sao_Paulo";
- } else if (region.equals("08") == true) {
- timezone = "America/Sao_Paulo";
- } else if (region.equals("11") == true) {
- timezone = "America/Campo_Grande";
- } else if (region.equals("13") == true) {
- timezone = "America/Belem";
- } else if (region.equals("14") == true) {
- timezone = "America/Cuiaba";
- } else if (region.equals("15") == true) {
- timezone = "America/Sao_Paulo";
- } else if (region.equals("16") == true) {
- timezone = "America/Belem";
- } else if (region.equals("17") == true) {
- timezone = "America/Recife";
- } else if (region.equals("18") == true) {
- timezone = "America/Sao_Paulo";
- } else if (region.equals("20") == true) {
- timezone = "America/Fortaleza";
- } else if (region.equals("21") == true) {
- timezone = "America/Sao_Paulo";
- } else if (region.equals("22") == true) {
- timezone = "America/Recife";
- } else if (region.equals("23") == true) {
- timezone = "America/Sao_Paulo";
- } else if (region.equals("24") == true) {
- timezone = "America/Porto_Velho";
- } else if (region.equals("25") == true) {
- timezone = "America/Boa_Vista";
- } else if (region.equals("26") == true) {
- timezone = "America/Sao_Paulo";
- } else if (region.equals("27") == true) {
- timezone = "America/Sao_Paulo";
- } else if (region.equals("28") == true) {
- timezone = "America/Maceio";
- } else if (region.equals("29") == true) {
- timezone = "America/Sao_Paulo";
- } else if (region.equals("30") == true) {
- timezone = "America/Recife";
- } else if (region.equals("31") == true) {
- timezone = "America/Araguaina";
- }
- } else if (country.equals("CD") == true) {
- if (region.equals("02") == true) {
- timezone = "Africa/Kinshasa";
- } else if (region.equals("05") == true) {
- timezone = "Africa/Lubumbashi";
- } else if (region.equals("06") == true) {
- timezone = "Africa/Kinshasa";
- } else if (region.equals("08") == true) {
- timezone = "Africa/Kinshasa";
- } else if (region.equals("10") == true) {
- timezone = "Africa/Lubumbashi";
- } else if (region.equals("11") == true) {
- timezone = "Africa/Lubumbashi";
- } else if (region.equals("12") == true) {
- timezone = "Africa/Lubumbashi";
- }
- } else if (country.equals("CN") == true) {
- if (region.equals("01") == true) {
- timezone = "Asia/Shanghai";
- } else if (region.equals("02") == true) {
- timezone = "Asia/Shanghai";
- } else if (region.equals("03") == true) {
- timezone = "Asia/Shanghai";
- } else if (region.equals("04") == true) {
- timezone = "Asia/Shanghai";
- } else if (region.equals("05") == true) {
- timezone = "Asia/Harbin";
- } else if (region.equals("06") == true) {
- timezone = "Asia/Chongqing";
- } else if (region.equals("07") == true) {
- timezone = "Asia/Shanghai";
- } else if (region.equals("08") == true) {
- timezone = "Asia/Harbin";
- } else if (region.equals("09") == true) {
- timezone = "Asia/Shanghai";
- } else if (region.equals("10") == true) {
- timezone = "Asia/Shanghai";
- } else if (region.equals("11") == true) {
- timezone = "Asia/Chongqing";
- } else if (region.equals("12") == true) {
- timezone = "Asia/Shanghai";
- } else if (region.equals("13") == true) {
- timezone = "Asia/Urumqi";
- } else if (region.equals("14") == true) {
- timezone = "Asia/Chongqing";
- } else if (region.equals("15") == true) {
- timezone = "Asia/Chongqing";
- } else if (region.equals("16") == true) {
- timezone = "Asia/Chongqing";
- } else if (region.equals("18") == true) {
- timezone = "Asia/Chongqing";
- } else if (region.equals("19") == true) {
- timezone = "Asia/Harbin";
- } else if (region.equals("20") == true) {
- timezone = "Asia/Harbin";
- } else if (region.equals("21") == true) {
- timezone = "Asia/Chongqing";
- } else if (region.equals("22") == true) {
- timezone = "Asia/Harbin";
- } else if (region.equals("23") == true) {
- timezone = "Asia/Shanghai";
- } else if (region.equals("24") == true) {
- timezone = "Asia/Chongqing";
- } else if (region.equals("25") == true) {
- timezone = "Asia/Shanghai";
- } else if (region.equals("26") == true) {
- timezone = "Asia/Chongqing";
- } else if (region.equals("28") == true) {
- timezone = "Asia/Shanghai";
- } else if (region.equals("29") == true) {
- timezone = "Asia/Chongqing";
- } else if (region.equals("30") == true) {
- timezone = "Asia/Chongqing";
- } else if (region.equals("31") == true) {
- timezone = "Asia/Chongqing";
- } else if (region.equals("32") == true) {
- timezone = "Asia/Chongqing";
- } else if (region.equals("33") == true) {
- timezone = "Asia/Chongqing";
- }
- } else if (country.equals("EC") == true) {
- if (region.equals("01") == true) {
- timezone = "Pacific/Galapagos";
- } else if (region.equals("02") == true) {
- timezone = "America/Guayaquil";
- } else if (region.equals("03") == true) {
- timezone = "America/Guayaquil";
- } else if (region.equals("04") == true) {
- timezone = "America/Guayaquil";
- } else if (region.equals("05") == true) {
- timezone = "America/Guayaquil";
- } else if (region.equals("06") == true) {
- timezone = "America/Guayaquil";
- } else if (region.equals("07") == true) {
- timezone = "America/Guayaquil";
- } else if (region.equals("08") == true) {
- timezone = "America/Guayaquil";
- } else if (region.equals("09") == true) {
- timezone = "America/Guayaquil";
- } else if (region.equals("10") == true) {
- timezone = "America/Guayaquil";
- } else if (region.equals("11") == true) {
- timezone = "America/Guayaquil";
- } else if (region.equals("12") == true) {
- timezone = "America/Guayaquil";
- } else if (region.equals("13") == true) {
- timezone = "America/Guayaquil";
- } else if (region.equals("14") == true) {
- timezone = "America/Guayaquil";
- } else if (region.equals("15") == true) {
- timezone = "America/Guayaquil";
- } else if (region.equals("17") == true) {
- timezone = "America/Guayaquil";
- } else if (region.equals("18") == true) {
- timezone = "America/Guayaquil";
- } else if (region.equals("19") == true) {
- timezone = "America/Guayaquil";
- } else if (region.equals("20") == true) {
- timezone = "America/Guayaquil";
- } else if (region.equals("22") == true) {
- timezone = "America/Guayaquil";
- }
- } else if (country.equals("ES") == true) {
- if (region.equals("07") == true) {
- timezone = "Europe/Madrid";
- } else if (region.equals("27") == true) {
- timezone = "Europe/Madrid";
- } else if (region.equals("29") == true) {
- timezone = "Europe/Madrid";
- } else if (region.equals("31") == true) {
- timezone = "Europe/Madrid";
- } else if (region.equals("32") == true) {
- timezone = "Europe/Madrid";
- } else if (region.equals("34") == true) {
- timezone = "Europe/Madrid";
- } else if (region.equals("39") == true) {
- timezone = "Europe/Madrid";
- } else if (region.equals("51") == true) {
- timezone = "Africa/Ceuta";
- } else if (region.equals("52") == true) {
- timezone = "Europe/Madrid";
- } else if (region.equals("53") == true) {
- timezone = "Atlantic/Canary";
- } else if (region.equals("54") == true) {
- timezone = "Europe/Madrid";
- } else if (region.equals("55") == true) {
- timezone = "Europe/Madrid";
- } else if (region.equals("56") == true) {
- timezone = "Europe/Madrid";
- } else if (region.equals("57") == true) {
- timezone = "Europe/Madrid";
- } else if (region.equals("58") == true) {
- timezone = "Europe/Madrid";
- } else if (region.equals("59") == true) {
- timezone = "Europe/Madrid";
- } else if (region.equals("60") == true) {
- timezone = "Europe/Madrid";
- }
- } else if (country.equals("GL") == true) {
- if (region.equals("01") == true) {
- timezone = "America/Thule";
- } else if (region.equals("02") == true) {
- timezone = "America/Godthab";
- } else if (region.equals("03") == true) {
- timezone = "America/Godthab";
- }
- } else if (country.equals("ID") == true) {
- if (region.equals("01") == true) {
- timezone = "Asia/Pontianak";
- } else if (region.equals("02") == true) {
- timezone = "Asia/Makassar";
- } else if (region.equals("03") == true) {
- timezone = "Asia/Jakarta";
- } else if (region.equals("04") == true) {
- timezone = "Asia/Jakarta";
- } else if (region.equals("05") == true) {
- timezone = "Asia/Jakarta";
- } else if (region.equals("06") == true) {
- timezone = "Asia/Jakarta";
- } else if (region.equals("07") == true) {
- timezone = "Asia/Jakarta";
- } else if (region.equals("08") == true) {
- timezone = "Asia/Jakarta";
- } else if (region.equals("09") == true) {
- timezone = "Asia/Jayapura";
- } else if (region.equals("10") == true) {
- timezone = "Asia/Jakarta";
- } else if (region.equals("11") == true) {
- timezone = "Asia/Pontianak";
- } else if (region.equals("12") == true) {
- timezone = "Asia/Makassar";
- } else if (region.equals("13") == true) {
- timezone = "Asia/Makassar";
- } else if (region.equals("14") == true) {
- timezone = "Asia/Makassar";
- } else if (region.equals("15") == true) {
- timezone = "Asia/Jakarta";
- } else if (region.equals("16") == true) {
- timezone = "Asia/Makassar";
- } else if (region.equals("17") == true) {
- timezone = "Asia/Makassar";
- } else if (region.equals("18") == true) {
- timezone = "Asia/Makassar";
- } else if (region.equals("19") == true) {
- timezone = "Asia/Pontianak";
- } else if (region.equals("20") == true) {
- timezone = "Asia/Makassar";
- } else if (region.equals("21") == true) {
- timezone = "Asia/Makassar";
- } else if (region.equals("22") == true) {
- timezone = "Asia/Makassar";
- } else if (region.equals("23") == true) {
- timezone = "Asia/Makassar";
- } else if (region.equals("24") == true) {
- timezone = "Asia/Jakarta";
- } else if (region.equals("25") == true) {
- timezone = "Asia/Pontianak";
- } else if (region.equals("26") == true) {
- timezone = "Asia/Pontianak";
- } else if (region.equals("30") == true) {
- timezone = "Asia/Jakarta";
- } else if (region.equals("31") == true) {
- timezone = "Asia/Makassar";
- } else if (region.equals("33") == true) {
- timezone = "Asia/Jakarta";
- }
- } else if (country.equals("KZ") == true) {
- if (region.equals("01") == true) {
- timezone = "Asia/Almaty";
- } else if (region.equals("02") == true) {
- timezone = "Asia/Almaty";
- } else if (region.equals("03") == true) {
- timezone = "Asia/Qyzylorda";
- } else if (region.equals("04") == true) {
- timezone = "Asia/Aqtobe";
- } else if (region.equals("05") == true) {
- timezone = "Asia/Qyzylorda";
- } else if (region.equals("06") == true) {
- timezone = "Asia/Aqtau";
- } else if (region.equals("07") == true) {
- timezone = "Asia/Oral";
- } else if (region.equals("08") == true) {
- timezone = "Asia/Qyzylorda";
- } else if (region.equals("09") == true) {
- timezone = "Asia/Aqtau";
- } else if (region.equals("10") == true) {
- timezone = "Asia/Qyzylorda";
- } else if (region.equals("11") == true) {
- timezone = "Asia/Almaty";
- } else if (region.equals("12") == true) {
- timezone = "Asia/Qyzylorda";
- } else if (region.equals("13") == true) {
- timezone = "Asia/Aqtobe";
- } else if (region.equals("14") == true) {
- timezone = "Asia/Qyzylorda";
- } else if (region.equals("15") == true) {
- timezone = "Asia/Almaty";
- } else if (region.equals("16") == true) {
- timezone = "Asia/Aqtobe";
- } else if (region.equals("17") == true) {
- timezone = "Asia/Almaty";
- }
- } else if (country.equals("MX") == true) {
- if (region.equals("01") == true) {
- timezone = "America/Mexico_City";
- } else if (region.equals("02") == true) {
- timezone = "America/Tijuana";
- } else if (region.equals("03") == true) {
- timezone = "America/Hermosillo";
- } else if (region.equals("04") == true) {
- timezone = "America/Merida";
- } else if (region.equals("05") == true) {
- timezone = "America/Mexico_City";
- } else if (region.equals("06") == true) {
- timezone = "America/Chihuahua";
- } else if (region.equals("07") == true) {
- timezone = "America/Monterrey";
- } else if (region.equals("08") == true) {
- timezone = "America/Mexico_City";
- } else if (region.equals("09") == true) {
- timezone = "America/Mexico_City";
- } else if (region.equals("10") == true) {
- timezone = "America/Mazatlan";
- } else if (region.equals("11") == true) {
- timezone = "America/Mexico_City";
- } else if (region.equals("12") == true) {
- timezone = "America/Mexico_City";
- } else if (region.equals("13") == true) {
- timezone = "America/Mexico_City";
- } else if (region.equals("14") == true) {
- timezone = "America/Mazatlan";
- } else if (region.equals("15") == true) {
- timezone = "America/Chihuahua";
- } else if (region.equals("16") == true) {
- timezone = "America/Mexico_City";
- } else if (region.equals("17") == true) {
- timezone = "America/Mexico_City";
- } else if (region.equals("18") == true) {
- timezone = "America/Mazatlan";
- } else if (region.equals("19") == true) {
- timezone = "America/Monterrey";
- } else if (region.equals("20") == true) {
- timezone = "America/Mexico_City";
- } else if (region.equals("21") == true) {
- timezone = "America/Mexico_City";
- } else if (region.equals("22") == true) {
- timezone = "America/Mexico_City";
- } else if (region.equals("23") == true) {
- timezone = "America/Cancun";
- } else if (region.equals("24") == true) {
- timezone = "America/Mexico_City";
- } else if (region.equals("25") == true) {
- timezone = "America/Mazatlan";
- } else if (region.equals("26") == true) {
- timezone = "America/Hermosillo";
- } else if (region.equals("27") == true) {
- timezone = "America/Merida";
- } else if (region.equals("28") == true) {
- timezone = "America/Monterrey";
- } else if (region.equals("29") == true) {
- timezone = "America/Mexico_City";
- } else if (region.equals("30") == true) {
- timezone = "America/Mexico_City";
- } else if (region.equals("31") == true) {
- timezone = "America/Merida";
- } else if (region.equals("32") == true) {
- timezone = "America/Monterrey";
- }
- } else if (country.equals("MY") == true) {
- if (region.equals("01") == true) {
- timezone = "Asia/Kuala_Lumpur";
- } else if (region.equals("02") == true) {
- timezone = "Asia/Kuala_Lumpur";
- } else if (region.equals("03") == true) {
- timezone = "Asia/Kuala_Lumpur";
- } else if (region.equals("04") == true) {
- timezone = "Asia/Kuala_Lumpur";
- } else if (region.equals("05") == true) {
- timezone = "Asia/Kuala_Lumpur";
- } else if (region.equals("06") == true) {
- timezone = "Asia/Kuala_Lumpur";
- } else if (region.equals("07") == true) {
- timezone = "Asia/Kuala_Lumpur";
- } else if (region.equals("08") == true) {
- timezone = "Asia/Kuala_Lumpur";
- } else if (region.equals("09") == true) {
- timezone = "Asia/Kuala_Lumpur";
- } else if (region.equals("11") == true) {
- timezone = "Asia/Kuching";
- } else if (region.equals("12") == true) {
- timezone = "Asia/Kuala_Lumpur";
- } else if (region.equals("13") == true) {
- timezone = "Asia/Kuala_Lumpur";
- } else if (region.equals("14") == true) {
- timezone = "Asia/Kuala_Lumpur";
- } else if (region.equals("15") == true) {
- timezone = "Asia/Kuching";
- } else if (region.equals("16") == true) {
- timezone = "Asia/Kuching";
- }
- } else if (country.equals("NZ") == true) {
- if (region.equals("85") == true) {
- timezone = "Pacific/Auckland";
- } else if (region.equals("E7") == true) {
- timezone = "Pacific/Auckland";
- } else if (region.equals("E8") == true) {
- timezone = "Pacific/Auckland";
- } else if (region.equals("E9") == true) {
- timezone = "Pacific/Auckland";
- } else if (region.equals("F1") == true) {
- timezone = "Pacific/Auckland";
- } else if (region.equals("F2") == true) {
- timezone = "Pacific/Auckland";
- } else if (region.equals("F3") == true) {
- timezone = "Pacific/Auckland";
- } else if (region.equals("F4") == true) {
- timezone = "Pacific/Auckland";
- } else if (region.equals("F5") == true) {
- timezone = "Pacific/Auckland";
- } else if (region.equals("F7") == true) {
- timezone = "Pacific/Chatham";
- } else if (region.equals("F8") == true) {
- timezone = "Pacific/Auckland";
- } else if (region.equals("F9") == true) {
- timezone = "Pacific/Auckland";
- } else if (region.equals("G1") == true) {
- timezone = "Pacific/Auckland";
- } else if (region.equals("G2") == true) {
- timezone = "Pacific/Auckland";
- } else if (region.equals("G3") == true) {
- timezone = "Pacific/Auckland";
- }
- } else if (country.equals("PT") == true) {
- if (region.equals("02") == true) {
- timezone = "Europe/Lisbon";
- } else if (region.equals("03") == true) {
- timezone = "Europe/Lisbon";
- } else if (region.equals("04") == true) {
- timezone = "Europe/Lisbon";
- } else if (region.equals("05") == true) {
- timezone = "Europe/Lisbon";
- } else if (region.equals("06") == true) {
- timezone = "Europe/Lisbon";
- } else if (region.equals("07") == true) {
- timezone = "Europe/Lisbon";
- } else if (region.equals("08") == true) {
- timezone = "Europe/Lisbon";
- } else if (region.equals("09") == true) {
- timezone = "Europe/Lisbon";
- } else if (region.equals("10") == true) {
- timezone = "Atlantic/Madeira";
- } else if (region.equals("11") == true) {
- timezone = "Europe/Lisbon";
- } else if (region.equals("13") == true) {
- timezone = "Europe/Lisbon";
- } else if (region.equals("14") == true) {
- timezone = "Europe/Lisbon";
- } else if (region.equals("16") == true) {
- timezone = "Europe/Lisbon";
- } else if (region.equals("17") == true) {
- timezone = "Europe/Lisbon";
- } else if (region.equals("18") == true) {
- timezone = "Europe/Lisbon";
- } else if (region.equals("19") == true) {
- timezone = "Europe/Lisbon";
- } else if (region.equals("20") == true) {
- timezone = "Europe/Lisbon";
- } else if (region.equals("21") == true) {
- timezone = "Europe/Lisbon";
- } else if (region.equals("22") == true) {
- timezone = "Europe/Lisbon";
- }
- } else if (country.equals("RU") == true) {
- if (region.equals("01") == true) {
- timezone = "Europe/Volgograd";
- } else if (region.equals("02") == true) {
- timezone = "Asia/Irkutsk";
- } else if (region.equals("03") == true) {
- timezone = "Asia/Novokuznetsk";
- } else if (region.equals("04") == true) {
- timezone = "Asia/Novosibirsk";
- } else if (region.equals("05") == true) {
- timezone = "Asia/Vladivostok";
- } else if (region.equals("06") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("07") == true) {
- timezone = "Europe/Volgograd";
- } else if (region.equals("08") == true) {
- timezone = "Europe/Samara";
- } else if (region.equals("09") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("10") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("11") == true) {
- timezone = "Asia/Irkutsk";
- } else if (region.equals("13") == true) {
- timezone = "Asia/Yekaterinburg";
- } else if (region.equals("14") == true) {
- timezone = "Asia/Irkutsk";
- } else if (region.equals("15") == true) {
- timezone = "Asia/Anadyr";
- } else if (region.equals("16") == true) {
- timezone = "Europe/Samara";
- } else if (region.equals("17") == true) {
- timezone = "Europe/Volgograd";
- } else if (region.equals("18") == true) {
- timezone = "Asia/Krasnoyarsk";
- } else if (region.equals("20") == true) {
- timezone = "Asia/Irkutsk";
- } else if (region.equals("21") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("22") == true) {
- timezone = "Europe/Volgograd";
- } else if (region.equals("23") == true) {
- timezone = "Europe/Kaliningrad";
- } else if (region.equals("24") == true) {
- timezone = "Europe/Volgograd";
- } else if (region.equals("25") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("26") == true) {
- timezone = "Asia/Kamchatka";
- } else if (region.equals("27") == true) {
- timezone = "Europe/Volgograd";
- } else if (region.equals("28") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("29") == true) {
- timezone = "Asia/Novokuznetsk";
- } else if (region.equals("30") == true) {
- timezone = "Asia/Vladivostok";
- } else if (region.equals("31") == true) {
- timezone = "Asia/Krasnoyarsk";
- } else if (region.equals("32") == true) {
- timezone = "Asia/Omsk";
- } else if (region.equals("33") == true) {
- timezone = "Asia/Yekaterinburg";
- } else if (region.equals("34") == true) {
- timezone = "Asia/Yekaterinburg";
- } else if (region.equals("35") == true) {
- timezone = "Asia/Yekaterinburg";
- } else if (region.equals("36") == true) {
- timezone = "Asia/Anadyr";
- } else if (region.equals("37") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("38") == true) {
- timezone = "Europe/Volgograd";
- } else if (region.equals("39") == true) {
- timezone = "Asia/Krasnoyarsk";
- } else if (region.equals("40") == true) {
- timezone = "Asia/Yekaterinburg";
- } else if (region.equals("41") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("42") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("43") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("44") == true) {
- timezone = "Asia/Magadan";
- } else if (region.equals("45") == true) {
- timezone = "Europe/Samara";
- } else if (region.equals("46") == true) {
- timezone = "Europe/Samara";
- } else if (region.equals("47") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("48") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("49") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("50") == true) {
- timezone = "Asia/Yekaterinburg";
- } else if (region.equals("51") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("52") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("53") == true) {
- timezone = "Asia/Novosibirsk";
- } else if (region.equals("54") == true) {
- timezone = "Asia/Omsk";
- } else if (region.equals("55") == true) {
- timezone = "Europe/Samara";
- } else if (region.equals("56") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("57") == true) {
- timezone = "Europe/Samara";
- } else if (region.equals("58") == true) {
- timezone = "Asia/Yekaterinburg";
- } else if (region.equals("59") == true) {
- timezone = "Asia/Vladivostok";
- } else if (region.equals("60") == true) {
- timezone = "Europe/Kaliningrad";
- } else if (region.equals("61") == true) {
- timezone = "Europe/Volgograd";
- } else if (region.equals("62") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("63") == true) {
- timezone = "Asia/Yakutsk";
- } else if (region.equals("64") == true) {
- timezone = "Asia/Sakhalin";
- } else if (region.equals("65") == true) {
- timezone = "Europe/Samara";
- } else if (region.equals("66") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("67") == true) {
- timezone = "Europe/Samara";
- } else if (region.equals("68") == true) {
- timezone = "Europe/Volgograd";
- } else if (region.equals("69") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("70") == true) {
- timezone = "Europe/Volgograd";
- } else if (region.equals("71") == true) {
- timezone = "Asia/Yekaterinburg";
- } else if (region.equals("72") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("73") == true) {
- timezone = "Europe/Samara";
- } else if (region.equals("74") == true) {
- timezone = "Asia/Krasnoyarsk";
- } else if (region.equals("75") == true) {
- timezone = "Asia/Novosibirsk";
- } else if (region.equals("76") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("77") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("78") == true) {
- timezone = "Asia/Yekaterinburg";
- } else if (region.equals("79") == true) {
- timezone = "Asia/Irkutsk";
- } else if (region.equals("80") == true) {
- timezone = "Asia/Yekaterinburg";
- } else if (region.equals("81") == true) {
- timezone = "Europe/Samara";
- } else if (region.equals("82") == true) {
- timezone = "Asia/Irkutsk";
- } else if (region.equals("83") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("84") == true) {
- timezone = "Europe/Volgograd";
- } else if (region.equals("85") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("86") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("87") == true) {
- timezone = "Asia/Novosibirsk";
- } else if (region.equals("88") == true) {
- timezone = "Europe/Moscow";
- } else if (region.equals("89") == true) {
- timezone = "Asia/Vladivostok";
- }
- } else if (country.equals("UA") == true) {
- if (region.equals("01") == true) {
- timezone = "Europe/Kiev";
- } else if (region.equals("02") == true) {
- timezone = "Europe/Kiev";
- } else if (region.equals("03") == true) {
- timezone = "Europe/Uzhgorod";
- } else if (region.equals("04") == true) {
- timezone = "Europe/Zaporozhye";
- } else if (region.equals("05") == true) {
- timezone = "Europe/Zaporozhye";
- } else if (region.equals("06") == true) {
- timezone = "Europe/Uzhgorod";
- } else if (region.equals("07") == true) {
- timezone = "Europe/Zaporozhye";
- } else if (region.equals("08") == true) {
- timezone = "Europe/Simferopol";
- } else if (region.equals("09") == true) {
- timezone = "Europe/Kiev";
- } else if (region.equals("10") == true) {
- timezone = "Europe/Zaporozhye";
- } else if (region.equals("11") == true) {
- timezone = "Europe/Simferopol";
- } else if (region.equals("13") == true) {
- timezone = "Europe/Kiev";
- } else if (region.equals("14") == true) {
- timezone = "Europe/Zaporozhye";
- } else if (region.equals("15") == true) {
- timezone = "Europe/Uzhgorod";
- } else if (region.equals("16") == true) {
- timezone = "Europe/Zaporozhye";
- } else if (region.equals("17") == true) {
- timezone = "Europe/Simferopol";
- } else if (region.equals("18") == true) {
- timezone = "Europe/Zaporozhye";
- } else if (region.equals("19") == true) {
- timezone = "Europe/Kiev";
- } else if (region.equals("20") == true) {
- timezone = "Europe/Simferopol";
- } else if (region.equals("21") == true) {
- timezone = "Europe/Kiev";
- } else if (region.equals("22") == true) {
- timezone = "Europe/Uzhgorod";
- } else if (region.equals("23") == true) {
- timezone = "Europe/Kiev";
- } else if (region.equals("24") == true) {
- timezone = "Europe/Uzhgorod";
- } else if (region.equals("25") == true) {
- timezone = "Europe/Uzhgorod";
- } else if (region.equals("26") == true) {
- timezone = "Europe/Zaporozhye";
- } else if (region.equals("27") == true) {
- timezone = "Europe/Kiev";
- }
- } else if (country.equals("UZ") == true) {
- if (region.equals("01") == true) {
- timezone = "Asia/Tashkent";
- } else if (region.equals("02") == true) {
- timezone = "Asia/Samarkand";
- } else if (region.equals("03") == true) {
- timezone = "Asia/Tashkent";
- } else if (region.equals("06") == true) {
- timezone = "Asia/Tashkent";
- } else if (region.equals("07") == true) {
- timezone = "Asia/Samarkand";
- } else if (region.equals("08") == true) {
- timezone = "Asia/Samarkand";
- } else if (region.equals("09") == true) {
- timezone = "Asia/Samarkand";
- } else if (region.equals("10") == true) {
- timezone = "Asia/Samarkand";
- } else if (region.equals("12") == true) {
- timezone = "Asia/Samarkand";
- } else if (region.equals("13") == true) {
- timezone = "Asia/Tashkent";
- } else if (region.equals("14") == true) {
- timezone = "Asia/Tashkent";
- }
- } else if (country.equals("TL") == true) {
- timezone = "Asia/Dili";
- } else if (country.equals("PF") == true) {
- timezone = "Pacific/Marquesas";
- }
- return timezone;
- }
-}
diff --git a/src/main/java/com/sun/mail/auth/MD4.java b/src/main/java/com/sun/mail/auth/MD4.java
deleted file mode 100644
index a3cfcecb..00000000
--- a/src/main/java/com/sun/mail/auth/MD4.java
+++ /dev/null
@@ -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;
- }
-}
diff --git a/src/main/java/com/sun/mail/auth/Ntlm.java b/src/main/java/com/sun/mail/auth/Ntlm.java
deleted file mode 100644
index 0d3d70b5..00000000
--- a/src/main/java/com/sun/mail/auth/Ntlm.java
+++ /dev/null
@@ -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();
- }
-}
diff --git a/src/main/java/com/sun/mail/handlers/image_gif.java b/src/main/java/com/sun/mail/handlers/image_gif.java
deleted file mode 100644
index 1686130b..00000000
--- a/src/main/java/com/sun/mail/handlers/image_gif.java
+++ /dev/null
@@ -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 DataContentHandler.
- *
- * @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");
- }
-}
diff --git a/src/main/java/com/sun/mail/handlers/image_jpeg.java b/src/main/java/com/sun/mail/handlers/image_jpeg.java
deleted file mode 100644
index 6aa1f94c..00000000
--- a/src/main/java/com/sun/mail/handlers/image_jpeg.java
+++ /dev/null
@@ -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;
- }
-}
diff --git a/src/main/java/com/sun/mail/handlers/message_rfc822.java b/src/main/java/com/sun/mail/handlers/message_rfc822.java
deleted file mode 100644
index 25ced6ae..00000000
--- a/src/main/java/com/sun/mail/handlers/message_rfc822.java
+++ /dev/null
@@ -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 DataContentHandler
- * @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");
- }
- }
-}
diff --git a/src/main/java/com/sun/mail/handlers/multipart_mixed.java b/src/main/java/com/sun/mail/handlers/multipart_mixed.java
deleted file mode 100644
index ea4bd79a..00000000
--- a/src/main/java/com/sun/mail/handlers/multipart_mixed.java
+++ /dev/null
@@ -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 DataContentHandler.
- *
- * @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());
- }
- }
- }
-}
diff --git a/src/main/java/com/sun/mail/handlers/text_html.java b/src/main/java/com/sun/mail/handlers/text_html.java
deleted file mode 100644
index efac8f5e..00000000
--- a/src/main/java/com/sun/mail/handlers/text_html.java
+++ /dev/null
@@ -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;
- }
-}
diff --git a/src/main/java/com/sun/mail/handlers/text_plain.java b/src/main/java/com/sun/mail/handlers/text_plain.java
deleted file mode 100644
index a665c374..00000000
--- a/src/main/java/com/sun/mail/handlers/text_plain.java
+++ /dev/null
@@ -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 DataContentHandler.
- *
- * @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;
- }
- }
-}
diff --git a/src/main/java/com/sun/mail/handlers/text_xml.java b/src/main/java/com/sun/mail/handlers/text_xml.java
deleted file mode 100644
index 05e7dd15..00000000
--- a/src/main/java/com/sun/mail/handlers/text_xml.java
+++ /dev/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 DataContentHandler.
- *
- * @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;
- }
- }
-}
diff --git a/src/main/java/com/sun/mail/iap/Argument.java b/src/main/java/com/sun/mail/iap/Argument.java
deleted file mode 100644
index 2d8a244b..00000000
--- a/src/main/java/com/sun/mail/iap/Argument.java
+++ /dev/null
@@ -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.
- *
- * 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;
- }
-}
diff --git a/src/main/java/com/sun/mail/iap/BadCommandException.java b/src/main/java/com/sun/mail/iap/BadCommandException.java
deleted file mode 100644
index 132b5919..00000000
--- a/src/main/java/com/sun/mail/iap/BadCommandException.java
+++ /dev/null
@@ -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);
- }
-}
diff --git a/src/main/java/com/sun/mail/iap/ByteArray.java b/src/main/java/com/sun/mail/iap/ByteArray.java
deleted file mode 100644
index 2712c6d0..00000000
--- a/src/main/java/com/sun/mail/iap/ByteArray.java
+++ /dev/null
@@ -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;
- }
-}
diff --git a/src/main/java/com/sun/mail/iap/CommandFailedException.java b/src/main/java/com/sun/mail/iap/CommandFailedException.java
deleted file mode 100644
index 45b55c30..00000000
--- a/src/main/java/com/sun/mail/iap/CommandFailedException.java
+++ /dev/null
@@ -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);
- }
-}
diff --git a/src/main/java/com/sun/mail/iap/ConnectionException.java b/src/main/java/com/sun/mail/iap/ConnectionException.java
deleted file mode 100644
index dca420c9..00000000
--- a/src/main/java/com/sun/mail/iap/ConnectionException.java
+++ /dev/null
@@ -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;
- }
-}
diff --git a/src/main/java/com/sun/mail/iap/Literal.java b/src/main/java/com/sun/mail/iap/Literal.java
deleted file mode 100644
index d964061e..00000000
--- a/src/main/java/com/sun/mail/iap/Literal.java
+++ /dev/null
@@ -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;
-}
diff --git a/src/main/java/com/sun/mail/iap/LiteralException.java b/src/main/java/com/sun/mail/iap/LiteralException.java
deleted file mode 100644
index 110d45ac..00000000
--- a/src/main/java/com/sun/mail/iap/LiteralException.java
+++ /dev/null
@@ -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;
- }
-}
diff --git a/src/main/java/com/sun/mail/iap/ParsingException.java b/src/main/java/com/sun/mail/iap/ParsingException.java
deleted file mode 100644
index 6e73f211..00000000
--- a/src/main/java/com/sun/mail/iap/ParsingException.java
+++ /dev/null
@@ -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);
- }
-}
diff --git a/src/main/java/com/sun/mail/iap/Protocol.java b/src/main/java/com/sun/mail/iap/Protocol.java
deleted file mode 100644
index f04eef87..00000000
--- a/src/main/java/com/sun/mail/iap/Protocol.java
+++ /dev/null
@@ -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.
- *
- * 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.
- *
- * 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.
- * cmd 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 .localhost overrides .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() { }
-}
diff --git a/src/main/java/com/sun/mail/iap/ProtocolException.java b/src/main/java/com/sun/mail/iap/ProtocolException.java
deleted file mode 100644
index 19ec0920..00000000
--- a/src/main/java/com/sun/mail/iap/ProtocolException.java
+++ /dev/null
@@ -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;
- }
-}
diff --git a/src/main/java/com/sun/mail/iap/Response.java b/src/main/java/com/sun/mail/iap/Response.java
deleted file mode 100644
index 5ef9e6f7..00000000
--- a/src/main/java/com/sun/mail/iap/Response.java
+++ /dev/null
@@ -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);
- }
-
-}
diff --git a/src/main/java/com/sun/mail/iap/ResponseHandler.java b/src/main/java/com/sun/mail/iap/ResponseHandler.java
deleted file mode 100644
index 0b3685af..00000000
--- a/src/main/java/com/sun/mail/iap/ResponseHandler.java
+++ /dev/null
@@ -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);
-}
diff --git a/src/main/java/com/sun/mail/iap/ResponseInputStream.java b/src/main/java/com/sun/mail/iap/ResponseInputStream.java
deleted file mode 100644
index ad1ad7bf..00000000
--- a/src/main/java/com/sun/mail/iap/ResponseInputStream.java
+++ /dev/null
@@ -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 : {}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;
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/ACL.java b/src/main/java/com/sun/mail/imap/ACL.java
deleted file mode 100644
index 25e94afc..00000000
--- a/src/main/java/com/sun/mail/imap/ACL.java
+++ /dev/null
@@ -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.
- *
- *
- * @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;
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/AppendUID.java b/src/main/java/com/sun/mail/imap/AppendUID.java
deleted file mode 100644
index 27de5e77..00000000
--- a/src/main/java/com/sun/mail/imap/AppendUID.java
+++ /dev/null
@@ -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 -
- * RFC 2359.
- *
- * @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;
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/DefaultFolder.java b/src/main/java/com/sun/mail/imap/DefaultFolder.java
deleted file mode 100644
index 4d394f29..00000000
--- a/src/main/java/com/sun/mail/imap/DefaultFolder.java
+++ /dev/null
@@ -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");
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/IMAPBodyPart.java b/src/main/java/com/sun/mail/imap/IMAPBodyPart.java
deleted file mode 100644
index 7f0e0cf6..00000000
--- a/src/main/java/com/sun/mail/imap/IMAPBodyPart.java
+++ /dev/null
@@ -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;
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/IMAPFolder.java b/src/main/java/com/sun/mail/imap/IMAPFolder.java
deleted file mode 100644
index 5711243b..00000000
--- a/src/main/java/com/sun/mail/imap/IMAPFolder.java
+++ /dev/null
@@ -1,3127 +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.util.Date;
-import java.util.Vector;
-import java.util.Hashtable;
-import java.util.NoSuchElementException;
-import java.util.logging.Level;
-import java.io.*;
-
-import javax.mail.*;
-import javax.mail.event.*;
-import javax.mail.internet.*;
-import javax.mail.search.*;
-
-import com.sun.mail.util.*;
-import com.sun.mail.iap.*;
-import com.sun.mail.imap.protocol.*;
-
-/**
- * This class implements an IMAP folder.
- *
- * A closed IMAPFolder object shares a protocol connection with its IMAPStore
- * object. When the folder is opened, it gets its own protocol connection.
- *
- * Applications that need to make use of IMAP-specific features may cast
- * a Folder object to an IMAPFolder object and
- * use the methods on this class. The {@link #getQuota getQuota} and
- * {@link #setQuota setQuota} methods support the IMAP QUOTA extension.
- * Refer to RFC 2087
- * for more information.
- *
- * The {@link #getACL getACL}, {@link #addACL addACL},
- * {@link #removeACL removeACL}, {@link #addRights addRights},
- * {@link #removeRights removeRights}, {@link #listRights listRights}, and
- * {@link #myRights myRights} methods support the IMAP ACL extension.
- * Refer to RFC 2086
- * for more information.
- *
- * The {@link #getSortedMessages getSortedMessages}
- * methods support the IMAP SORT extension.
- * Refer to RFC 5256
- * for more information.
- *
- * The {@link #doCommand doCommand} method and
- * {@link IMAPFolder.ProtocolCommand IMAPFolder.ProtocolCommand}
- * interface support use of arbitrary IMAP protocol commands.
- *
- * See the com.sun.mail.imap package
- * documentation for further information on the IMAP protocol provider.
- *
- * WARNING: The APIs unique to this class should be
- * considered EXPERIMENTAL. They may be changed in the
- * future in ways that are incompatible with applications using the
- * current APIs.
- *
- * @author John Mani
- * @author Bill Shannon
- * @author Jim Glennon
- */
-
-/*
- * The folder object itself serves as a lock for the folder's state
- * EXCEPT for the message cache (see below), typically by using
- * synchronized methods. When checking that a folder is open or
- * closed, the folder's lock must be held. It's important that the
- * folder's lock is acquired before the messageCacheLock (see below).
- * Thus, the locking hierarchy is that the folder lock, while optional,
- * must be acquired before the messageCacheLock, if it's acquired at
- * all. Be especially careful of callbacks that occur while holding
- * the messageCacheLock into (e.g.) superclass Folder methods that are
- * synchronized. Note that methods in IMAPMessage will acquire the
- * messageCacheLock without acquiring the folder lock.
- *
- * When a folder is opened, it creates a messageCache (a Vector) of
- * empty IMAPMessage objects. Each Message has a messageNumber - which
- * is its index into the messageCache, and a sequenceNumber - which is
- * its IMAP sequence-number. All operations on a Message which involve
- * communication with the server, use the message's sequenceNumber.
- *
- * The most important thing to note here is that the server can send
- * unsolicited EXPUNGE notifications as part of the responses for "most"
- * commands. Refer RFC2060, sections 5.3 & 5.5 for gory details. Also,
- * the server sends these notifications AFTER the message has been
- * expunged. And once a message is expunged, the sequence-numbers of
- * those messages after the expunged one are renumbered. This essentially
- * means that the mapping between *any* Message and its sequence-number
- * can change in the period when a IMAP command is issued and its responses
- * are processed. Hence we impose a strict locking model as follows:
- *
- * We define one mutex per folder - this is just a Java Object (named
- * messageCacheLock). Any time a command is to be issued to the IMAP
- * server (i.e., anytime the corresponding IMAPProtocol method is
- * invoked), follow the below style:
- *
- * synchronized (messageCacheLock) { // ACQUIRE LOCK
- * issue command ()
- *
- * // The response processing is typically done within
- * // the handleResponse() callback. A few commands (Fetch,
- * // Expunge) return *all* responses and hence their
- * // processing is done here itself. Now, as part of the
- * // processing unsolicited EXPUNGE responses, we renumber
- * // the necessary sequence-numbers. Thus the renumbering
- * // happens within this critical-region, surrounded by
- * // locks.
- * process responses ()
- * } // RELEASE LOCK
- *
- * This technique is used both by methods in IMAPFolder and by methods
- * in IMAPMessage and other classes that operate on data in the folder.
- * Note that holding the messageCacheLock has the side effect of
- * preventing the folder from being closed, and thus ensuring that the
- * folder's protocol object is still valid. The protocol object should
- * only be accessed while holding the messageCacheLock (except for calls
- * to IMAPProtocol.isREV1(), which don't need to be protected because it
- * doesn't access the server).
- *
- * Note that interactions with the Store's protocol connection do
- * not have to be protected as above, since the Store's protocol is
- * never in a "meaningful" SELECT-ed state.
- */
-
-public class IMAPFolder extends Folder implements UIDFolder, ResponseHandler {
-
- protected String fullName; // full name
- protected String name; // name
- protected int type; // folder type.
- protected char separator; // separator
- protected Flags availableFlags; // available flags
- protected Flags permanentFlags; // permanent flags
- protected volatile boolean exists; // whether this folder really exists ?
- protected boolean isNamespace = false; // folder is a namespace name
- protected volatile String[] attributes;// name attributes from LIST response
-
- protected volatile IMAPProtocol protocol; // this folder's protocol object
- protected MessageCache messageCache;// message cache
- // accessor lock for message cache
- protected final Object messageCacheLock = new Object();
-
- protected Hashtable uidTable; // UID->Message hashtable
-
- /* An IMAP delimiter is a 7bit US-ASCII character. (except NUL).
- * We use '\uffff' (a non 7bit character) to indicate that we havent
- * yet determined what the separator character is.
- * We use '\u0000' (NUL) to indicate that no separator character
- * exists, i.e., a flat hierarchy
- */
- static final protected char UNKNOWN_SEPARATOR = '\uffff';
-
- private volatile boolean opened = false; // is this folder opened ?
-
- /* This field tracks the state of this folder. If the folder is closed
- * due to external causes (i.e, not thru the close() method), then
- * this field will remain false. If the folder is closed thru the
- * close() method, then this field is set to true.
- *
- * If reallyClosed is false, then a FolderClosedException is
- * generated when a method is invoked on any Messaging object
- * owned by this folder. If reallyClosed is true, then the
- * IllegalStateException runtime exception is thrown.
- */
- private boolean reallyClosed = true;
-
- /*
- * The idleState field supports the IDLE command.
- * Normally when executing an IMAP command we hold the
- * messageCacheLock and often the folder lock (see above).
- * While executing the IDLE command we can't hold either
- * of these locks or it would prevent other threads from
- * entering Folder methods even far enough to check whether
- * an IDLE command is in progress. We need to check before
- * issuing another command so that we can abort the IDLE
- * command.
- *
- * The idleState field is protected by the messageCacheLock.
- * The RUNNING state is the normal state and means no IDLE
- * command is in progress. The IDLE state means we've issued
- * an IDLE command and are reading responses. The ABORTING
- * state means we've sent the DONE continuation command and
- * are waiting for the thread running the IDLE command to
- * break out of its read loop.
- *
- * When an IDLE command is in progress, the thread calling
- * the idle method will be reading from the IMAP connection
- * while holding neither the folder lock nor the messageCacheLock.
- * It's obviously critical that no other thread try to send a
- * command or read from the connection while in this state.
- * However, other threads can send the DONE continuation
- * command that will cause the server to break out of the IDLE
- * loop and send the ending tag response to the IDLE command.
- * The thread in the idle method that's reading the responses
- * from the IDLE command will see this ending response and
- * complete the idle method, setting the idleState field back
- * to RUNNING, and notifying any threads waiting to use the
- * connection.
- *
- * All uses of the IMAP connection (IMAPProtocol object) must
- * be done while holding the messageCacheLock and must be
- * preceeded by a check to make sure an IDLE command is not
- * running, and abort the IDLE command if necessary. While
- * waiting for the IDLE command to complete, these other threads
- * will give up the messageCacheLock, but might still be holding
- * the folder lock. This check is done by the getProtocol()
- * method, resulting in a typical usage pattern of:
- *
- * synchronized (messageCacheLock) {
- * IMAPProtocol p = getProtocol(); // may block waiting for IDLE
- * // ... use protocol
- * }
- */
- private static final int RUNNING = 0; // not doing IDLE command
- private static final int IDLE = 1; // IDLE command in effect
- private static final int ABORTING = 2; // IDLE command aborting
- private int idleState = RUNNING;
-
- private volatile int total = -1; // total number of messages in the
- // message cache
- private volatile int recent = -1; // number of recent messages
- private int realTotal = -1; // total number of messages on
- // the server
- private long uidvalidity = -1; // UIDValidity
- private long uidnext = -1; // UIDNext
- private boolean doExpungeNotification = true; // used in expunge handler
-
- private Status cachedStatus = null;
- private long cachedStatusTime = 0;
-
- private boolean hasMessageCountListener = false; // optimize notification
-
- protected MailLogger logger;
- private MailLogger connectionPoolLogger;
-
- /**
- * A fetch profile item for fetching headers.
- * This inner class extends the FetchProfile.Item
- * class to add new FetchProfile item types, specific to IMAPFolders.
- *
- * @see FetchProfile
- */
- public static class FetchProfileItem extends FetchProfile.Item {
- protected FetchProfileItem(String name) {
- super(name);
- }
-
- /**
- * HEADERS is a fetch profile item that can be included in a
- * FetchProfile during a fetch request to a Folder.
- * This item indicates that the headers for messages in the specified
- * range are desired to be prefetched.
- *
- * An example of how a client uses this is below:
- */
- public static final FetchProfileItem HEADERS =
- new FetchProfileItem("HEADERS");
-
- /**
- * SIZE is a fetch profile item that can be included in a
- * FetchProfile during a fetch request to a Folder.
- * This item indicates that the sizes of the messages in the specified
- * range are desired to be prefetched.
- *
- * SIZE was moved to FetchProfile.Item in JavaMail 1.5.
- *
- * @deprecated
- */
- public static final FetchProfileItem SIZE =
- new FetchProfileItem("SIZE");
- }
-
- /**
- * Constructor used to create a possibly non-existent folder.
- *
- * @param fullName fullname of this folder
- * @param separator the default separator character for this
- * folder's namespace
- * @param store the Store
- */
- protected IMAPFolder(String fullName, char separator, IMAPStore store,
- Boolean isNamespace) {
- super(store);
- if (fullName == null)
- throw new NullPointerException("Folder name is null");
- this.fullName = fullName;
- this.separator = separator;
- logger = new MailLogger(this.getClass(),
- "DEBUG IMAP", store.getSession());
- connectionPoolLogger = ((IMAPStore)store).getConnectionPoolLogger();
-
- /*
- * Work around apparent bug in Exchange. Exchange
- * will return a name of "Public Folders/" from
- * LIST "%".
- *
- * If name has one separator, and it's at the end,
- * assume this is a namespace name and treat it
- * accordingly. Usually this will happen as a result
- * of the list method, but this also allows getFolder
- * to work with namespace names.
- */
- this.isNamespace = false;
- if (separator != UNKNOWN_SEPARATOR && separator != '\0') {
- int i = this.fullName.indexOf(separator);
- if (i > 0 && i == this.fullName.length() - 1) {
- this.fullName = this.fullName.substring(0, i);
- this.isNamespace = true;
- }
- }
-
- // if we were given a value, override default chosen above
- if (isNamespace != null)
- this.isNamespace = isNamespace.booleanValue();
- }
-
- /**
- * Constructor used to create an existing folder.
- */
- protected IMAPFolder(ListInfo li, IMAPStore store) {
- this(li.name, li.separator, store, null);
-
- if (li.hasInferiors)
- type |= HOLDS_FOLDERS;
- if (li.canOpen)
- type |= HOLDS_MESSAGES;
- exists = true;
- attributes = li.attrs;
- }
-
- /*
- * Ensure that this folder exists. If 'exists' has been set to true,
- * we don't attempt to validate it with the server again. Note that
- * this can result in a possible loss of sync with the server.
- * ASSERT: Must be called with this folder's synchronization lock held.
- */
- protected void checkExists() throws MessagingException {
- // If the boolean field 'exists' is false, check with the
- // server by invoking exists() ..
- if (!exists && !exists())
- throw new FolderNotFoundException(
- this, fullName + " not found");
- }
-
- /*
- * Ensure the folder is closed.
- * ASSERT: Must be called with this folder's synchronization lock held.
- */
- protected void checkClosed() {
- if (opened)
- throw new IllegalStateException(
- "This operation is not allowed on an open folder"
- );
- }
-
- /*
- * Ensure the folder is open.
- * ASSERT: Must be called with this folder's synchronization lock held.
- */
- protected void checkOpened() throws FolderClosedException {
- assert Thread.holdsLock(this);
- if (!opened) {
- if (reallyClosed)
- throw new IllegalStateException(
- "This operation is not allowed on a closed folder"
- );
- else // Folder was closed "implicitly"
- throw new FolderClosedException(this,
- "Lost folder connection to server"
- );
- }
- }
-
- /*
- * Check that the given message number is within the range
- * of messages present in this folder. If the message
- * number is out of range, we ping the server to obtain any
- * pending new message notifications from the server.
- */
- protected void checkRange(int msgno) throws MessagingException {
- if (msgno < 1) // message-numbers start at 1
- throw new IndexOutOfBoundsException("message number < 1");
-
- if (msgno <= total)
- return;
-
- // Out of range, let's ping the server and see if
- // the server has more messages for us.
-
- synchronized(messageCacheLock) { // Acquire lock
- try {
- keepConnectionAlive(false);
- } catch (ConnectionException cex) {
- // Oops, lost connection
- throw new FolderClosedException(this, cex.getMessage());
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- }
- } // Release lock
-
- if (msgno > total) // Still out of range ? Throw up ...
- throw new IndexOutOfBoundsException(msgno + " > " + total);
- }
-
- /*
- * Check whether the given flags are supported by this server,
- * and also verify that the folder allows setting flags.
- */
- private void checkFlags(Flags flags) throws MessagingException {
- assert Thread.holdsLock(this);
- if (mode != READ_WRITE)
- throw new IllegalStateException(
- "Cannot change flags on READ_ONLY folder: " + fullName
- );
- /*
- if (!availableFlags.contains(flags))
- throw new MessagingException(
- "These flags are not supported by this implementation"
- );
- */
- }
-
- /**
- * Get the name of this folder.
- */
- public synchronized String getName() {
- /* Return the last component of this Folder's full name.
- * Folder components are delimited by the separator character.
- */
- if (name == null) {
- try {
- name = fullName.substring(
- fullName.lastIndexOf(getSeparator()) + 1
- );
- } catch (MessagingException mex) { }
- }
- return name;
- }
-
- /**
- * Get the fullname of this folder.
- */
- public synchronized String getFullName() {
- return fullName;
- }
-
- /**
- * Get this folder's parent.
- */
- public synchronized Folder getParent() throws MessagingException {
- char c = getSeparator();
- int index;
- if ((index = fullName.lastIndexOf(c)) != -1)
- return ((IMAPStore)store).newIMAPFolder(
- fullName.substring(0, index), c);
- else
- return new DefaultFolder((IMAPStore)store);
- }
-
- /**
- * Check whether this folder really exists on the server.
- */
- public synchronized boolean exists() throws MessagingException {
- // Check whether this folder exists ..
- ListInfo[] li = null;
- final String lname;
- if (isNamespace && separator != '\0')
- lname = fullName + separator;
- else
- lname = fullName;
-
- li = (ListInfo[])doCommand(new ProtocolCommand() {
- public Object doCommand(IMAPProtocol p) throws ProtocolException {
- return p.list("", lname);
- }
- });
-
- if (li != null) {
- int i = findName(li, lname);
- fullName = li[i].name;
- separator = li[i].separator;
- int len = fullName.length();
- if (separator != '\0' && len > 0 &&
- fullName.charAt(len - 1) == separator) {
- fullName = fullName.substring(0, len - 1);
- }
- type = 0;
- if (li[i].hasInferiors)
- type |= HOLDS_FOLDERS;
- if (li[i].canOpen)
- type |= HOLDS_MESSAGES;
- exists = true;
- attributes = li[i].attrs;
- } else {
- exists = opened;
- attributes = null;
- }
-
- return exists;
- }
-
- /**
- * Which entry in li matches lname?
- * If the name contains wildcards, more than one entry may be
- * returned.
- */
- private int findName(ListInfo[] li, String lname) {
- int i;
- // if the name contains a wildcard, there might be more than one
- for (i = 0; i < li.length; i++) {
- if (li[i].name.equals(lname))
- break;
- }
- if (i >= li.length) { // nothing matched exactly
- // XXX - possibly should fail? But what if server
- // is case insensitive and returns the preferred
- // case of the name here?
- i = 0; // use first one
- }
- return i;
- }
-
- /**
- * List all subfolders matching the specified pattern.
- */
- public Folder[] list(String pattern) throws MessagingException {
- return doList(pattern, false);
- }
-
- /**
- * List all subscribed subfolders matching the specified pattern.
- */
- public Folder[] listSubscribed(String pattern) throws MessagingException {
- return doList(pattern, true);
- }
-
- private synchronized Folder[] doList(final String pattern,
- final boolean subscribed) throws MessagingException {
- checkExists(); // insure that this folder does exist.
-
- // Why waste a roundtrip to the server?
- if (attributes != null && !isDirectory())
- return new Folder[0];
-
- final char c = getSeparator();
-
- ListInfo[] li = (ListInfo[])doCommandIgnoreFailure(
- new ProtocolCommand() {
- public Object doCommand(IMAPProtocol p)
- throws ProtocolException {
- if (subscribed)
- return p.lsub("", fullName + c + pattern);
- else
- return p.list("", fullName + c + pattern);
- }
- });
-
- if (li == null)
- return new Folder[0];
-
- /*
- * The UW based IMAP4 servers (e.g. SIMS2.0) include
- * current folder (terminated with the separator), when
- * the LIST pattern is '%' or '*'. i.e,
- * returns "mail/" as the first LIST response.
- *
- * Doesn't make sense to include the current folder in this
- * case, so we filter it out. Note that I'm assuming that
- * the offending response is the *first* one, my experiments
- * with the UW & SIMS2.0 servers indicate that ..
- */
- int start = 0;
- // Check the first LIST response.
- if (li.length > 0 && li[0].name.equals(fullName + c))
- start = 1; // start from index = 1
-
- IMAPFolder[] folders = new IMAPFolder[li.length - start];
- IMAPStore st = (IMAPStore)store;
- for (int i = start; i < li.length; i++)
- folders[i-start] = st.newIMAPFolder(li[i]);
- return folders;
- }
-
- /**
- * Get the separator character.
- */
- public synchronized char getSeparator() throws MessagingException {
- if (separator == UNKNOWN_SEPARATOR) {
- ListInfo[] li = null;
-
- li = (ListInfo[])doCommand(new ProtocolCommand() {
- public Object doCommand(IMAPProtocol p)
- throws ProtocolException {
- // REV1 allows the following LIST format to obtain
- // the hierarchy delimiter of non-existent folders
- if (p.isREV1()) // IMAP4rev1
- return p.list(fullName, "");
- else // IMAP4, note that this folder must exist for this
- // to work :(
- return p.list("", fullName);
- }
- });
-
- if (li != null)
- separator = li[0].separator;
- else
- separator = '/'; // punt !
- }
- return separator;
- }
-
- /**
- * Get the type of this folder.
- */
- public synchronized int getType() throws MessagingException {
- if (opened) {
- // never throw FolderNotFoundException if folder is open
- if (attributes == null)
- exists(); // try to fetch attributes
- } else {
- checkExists();
- }
- return type;
- }
-
- /**
- * Check whether this folder is subscribed.
- */
- public synchronized boolean isSubscribed() {
- ListInfo[] li = null;
- final String lname;
- if (isNamespace && separator != '\0')
- lname = fullName + separator;
- else
- lname = fullName;
-
- try {
- li = (ListInfo[])doProtocolCommand(new ProtocolCommand() {
- public Object doCommand(IMAPProtocol p)
- throws ProtocolException {
- return p.lsub("", lname);
- }
- });
- } catch (ProtocolException pex) {
- }
-
- if (li != null) {
- int i = findName(li, lname);
- return li[i].canOpen;
- } else
- return false;
- }
-
- /**
- * Subscribe/Unsubscribe this folder.
- */
- public synchronized void setSubscribed(final boolean subscribe)
- throws MessagingException {
- doCommandIgnoreFailure(new ProtocolCommand() {
- public Object doCommand(IMAPProtocol p) throws ProtocolException {
- if (subscribe)
- p.subscribe(fullName);
- else
- p.unsubscribe(fullName);
- return null;
- }
- });
- }
-
- /**
- * Create this folder, with the specified type.
- */
- public synchronized boolean create(final int type)
- throws MessagingException {
-
- char c = 0;
- if ((type & HOLDS_MESSAGES) == 0) // only holds folders
- c = getSeparator();
- final char sep = c;
- Object ret = doCommandIgnoreFailure(new ProtocolCommand() {
- public Object doCommand(IMAPProtocol p)
- throws ProtocolException {
- if ((type & HOLDS_MESSAGES) == 0) // only holds folders
- p.create(fullName + sep);
- else {
- p.create(fullName);
-
- // Certain IMAP servers do not allow creation of folders
- // that can contain messages *and* subfolders. So, if we
- // were asked to create such a folder, we should verify
- // that we could indeed do so.
- if ((type & HOLDS_FOLDERS) != 0) {
- // we want to hold subfolders and messages. Check
- // whether we could create such a folder.
- ListInfo[] li = p.list("", fullName);
- if (li != null && !li[0].hasInferiors) {
- // Hmm ..the new folder
- // doesn't support Inferiors ? Fail
- p.delete(fullName);
- throw new ProtocolException("Unsupported type");
- }
- }
- }
- return Boolean.TRUE;
- }
- });
-
- if (ret == null)
- return false; // CREATE failure, maybe this
- // folder already exists ?
-
- // exists = true;
- // this.type = type;
- boolean retb = exists(); // set exists, type, and attributes
- if (retb) // Notify listeners on self and our Store
- notifyFolderListeners(FolderEvent.CREATED);
- return retb;
- }
-
- /**
- * Check whether this folder has new messages.
- */
- public synchronized boolean hasNewMessages() throws MessagingException {
- if (opened) { // If we are open, we already have this information
- // Folder is open, make sure information is up to date
- synchronized(messageCacheLock) {
- // tickle the folder and store connections.
- try {
- keepConnectionAlive(true);
- } catch (ConnectionException cex) {
- throw new FolderClosedException(this, cex.getMessage());
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- }
- return recent > 0 ? true : false;
- }
- }
-
- // First, the cheap way - use LIST and look for the \Marked
- // or \Unmarked tag
-
- ListInfo[] li = null;
- final String lname;
- if (isNamespace && separator != '\0')
- lname = fullName + separator;
- else
- lname = fullName;
- li = (ListInfo[])doCommandIgnoreFailure(new ProtocolCommand() {
- public Object doCommand(IMAPProtocol p) throws ProtocolException {
- return p.list("", lname);
- }
- });
-
- // if folder doesn't exist, throw exception
- if (li == null)
- throw new FolderNotFoundException(this, fullName + " not found");
-
- int i = findName(li, lname);
- if (li[i].changeState == ListInfo.CHANGED)
- return true;
- else if (li[i].changeState == ListInfo.UNCHANGED)
- return false;
-
- // LIST didn't work. Try the hard way, using STATUS
- try {
- Status status = getStatus();
- if (status.recent > 0)
- return true;
- else
- return false;
- } catch (BadCommandException bex) {
- // Probably doesn't support STATUS, tough luck.
- return false;
- } catch (ConnectionException cex) {
- throw new StoreClosedException(store, cex.getMessage());
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- }
- }
-
- /**
- * Get the named subfolder.
- */
- public synchronized Folder getFolder(String name)
- throws MessagingException {
- // If we know that this folder is *not* a directory, don't
- // send the request to the server at all ...
- if (attributes != null && !isDirectory())
- throw new MessagingException("Cannot contain subfolders");
-
- char c = getSeparator();
- return ((IMAPStore)store).newIMAPFolder(fullName + c + name, c);
- }
-
- /**
- * Delete this folder.
- */
- public synchronized boolean delete(boolean recurse)
- throws MessagingException {
- checkClosed(); // insure that this folder is closed.
-
- if (recurse) {
- // Delete all subfolders.
- Folder[] f = list();
- for (int i = 0; i < f.length; i++)
- f[i].delete(recurse); // ignore intermediate failures
- }
-
- // Attempt to delete this folder
-
- Object ret = doCommandIgnoreFailure(new ProtocolCommand() {
- public Object doCommand(IMAPProtocol p) throws ProtocolException {
- p.delete(fullName);
- return Boolean.TRUE;
- }
- });
-
- if (ret == null)
- // Non-existent folder/No permission ??
- return false;
-
- // DELETE succeeded.
- exists = false;
- attributes = null;
-
- // Notify listeners on self and our Store
- notifyFolderListeners(FolderEvent.DELETED);
- return true;
- }
-
- /**
- * Rename this folder.
- */
- public synchronized boolean renameTo(final Folder f)
- throws MessagingException {
- checkClosed(); // insure that we are closed.
- checkExists();
- if (f.getStore() != store)
- throw new MessagingException("Can't rename across Stores");
-
-
- Object ret = doCommandIgnoreFailure(new ProtocolCommand() {
- public Object doCommand(IMAPProtocol p) throws ProtocolException {
- p.rename(fullName, f.getFullName());
- return Boolean.TRUE;
- }
- });
-
- if (ret == null)
- return false;
-
- exists = false;
- attributes = null;
- notifyFolderRenamedListeners(f);
- return true;
- }
-
- /**
- * Open this folder in the given mode.
- */
- public synchronized void open(int mode) throws MessagingException {
- checkClosed(); // insure that we are not already open
-
- MailboxInfo mi = null;
- // Request store for our own protocol connection.
- protocol = ((IMAPStore)store).getProtocol(this);
-
- synchronized(messageCacheLock) { // Acquire messageCacheLock
-
- /*
- * Add response handler right away so we get any alerts or
- * notifications that occur during the SELECT or EXAMINE.
- * Have to be sure to remove it if we fail to open the
- * folder.
- */
- protocol.addResponseHandler(this);
-
- try {
- if (mode == READ_ONLY)
- mi = protocol.examine(fullName);
- else
- mi = protocol.select(fullName);
- } catch (CommandFailedException cex) {
- /*
- * Handle SELECT or EXAMINE failure.
- * Try to figure out why the operation failed so we can
- * report a more reasonable exception.
- *
- * Will use our existing protocol object.
- */
- try {
- checkExists(); // throw exception if folder doesn't exist
-
- if ((type & HOLDS_MESSAGES) == 0)
- throw new MessagingException(
- "folder cannot contain messages");
- throw new MessagingException(cex.getMessage(), cex);
-
- } finally {
- // folder not open, don't keep this information
- exists = false;
- attributes = null;
- type = 0;
- // connection still good, return it
- releaseProtocol(true);
- }
- // NOTREACHED
- } catch (ProtocolException pex) {
- // got a BAD or a BYE; connection may be bad, close it
- try {
- protocol.logout();
- } catch (ProtocolException pex2) {
- // ignore
- } finally {
- releaseProtocol(false);
- throw new MessagingException(pex.getMessage(), pex);
- }
- }
-
- if (mi.mode != mode) {
- if (mode == READ_WRITE && mi.mode == READ_ONLY &&
- ((IMAPStore)store).allowReadOnlySelect()) {
- ; // all ok, allow it
- } else { // otherwise, it's an error
- try {
- // close mailbox and return connection
- protocol.close();
- releaseProtocol(true);
- } catch (ProtocolException pex) {
- // something went wrong, close connection
- try {
- protocol.logout();
- } catch (ProtocolException pex2) {
- // ignore
- } finally {
- releaseProtocol(false);
- }
- } finally {
- throw new ReadOnlyFolderException(this,
- "Cannot open in desired mode");
- }
-
- }
- }
-
- // Initialize stuff.
- opened = true;
- reallyClosed = false;
- this.mode = mi.mode;
- availableFlags = mi.availableFlags;
- permanentFlags = mi.permanentFlags;
- total = realTotal = mi.total;
- recent = mi.recent;
- uidvalidity = mi.uidvalidity;
- uidnext = mi.uidnext;
-
- // Create the message cache of appropriate size
- messageCache = new MessageCache(this, (IMAPStore)store, total);
-
- } // Release lock
-
- exists = true; // if we opened it, it must exist
- attributes = null; // but we don't yet know its attributes
- type = HOLDS_MESSAGES; // lacking more info, we know at least this much
-
- // notify listeners
- notifyConnectionListeners(ConnectionEvent.OPENED);
- }
-
- /**
- * Prefetch attributes, based on the given FetchProfile.
- */
- public synchronized void fetch(Message[] msgs, FetchProfile fp)
- throws MessagingException {
- checkOpened();
-
- StringBuffer command = new StringBuffer();
- boolean first = true;
- boolean allHeaders = false;
-
- if (fp.contains(FetchProfile.Item.ENVELOPE)) {
- command.append(getEnvelopeCommand());
- first = false;
- }
- if (fp.contains(FetchProfile.Item.FLAGS)) {
- command.append(first ? "FLAGS" : " FLAGS");
- first = false;
- }
- if (fp.contains(FetchProfile.Item.CONTENT_INFO)) {
- command.append(first ? "BODYSTRUCTURE" : " BODYSTRUCTURE");
- first = false;
- }
- if (fp.contains(UIDFolder.FetchProfileItem.UID)) {
- command.append(first ? "UID" : " UID");
- first = false;
- }
- if (fp.contains(IMAPFolder.FetchProfileItem.HEADERS)) {
- allHeaders = true;
- if (protocol.isREV1())
- command.append(first ?
- "BODY.PEEK[HEADER]" : " BODY.PEEK[HEADER]");
- else
- command.append(first ? "RFC822.HEADER" : " RFC822.HEADER");
- first = false;
- }
- if (fp.contains(FetchProfile.Item.SIZE) ||
- fp.contains(IMAPFolder.FetchProfileItem.SIZE)) {
- command.append(first ? "RFC822.SIZE" : " RFC822.SIZE");
- first = false;
- }
-
- // if we're not fetching all headers, fetch individual headers
- String[] hdrs = null;
- if (!allHeaders) {
- hdrs = fp.getHeaderNames();
- if (hdrs.length > 0) {
- if (!first)
- command.append(" ");
- command.append(createHeaderCommand(hdrs));
- }
- }
-
- /*
- * Add any additional extension fetch items.
- */
- FetchItem[] fitems = protocol.getFetchItems();
- for (int i = 0; i < fitems.length; i++) {
- if (fp.contains(fitems[i].getFetchProfileItem())) {
- if (command.length() != 0)
- command.append(" ");
- command.append(fitems[i].getName());
- }
- }
-
- Utility.Condition condition =
- new IMAPMessage.FetchProfileCondition(fp, fitems);
-
- // Acquire the Folder's MessageCacheLock.
- synchronized(messageCacheLock) {
-
- // Apply the test, and get the sequence-number set for
- // the messages that need to be prefetched.
- MessageSet[] msgsets = Utility.toMessageSet(msgs, condition);
-
- if (msgsets == null)
- // We already have what we need.
- return;
-
- Response[] r = null;
- Vector v = new Vector(); // to collect non-FETCH responses &
- // unsolicited FETCH FLAG responses
- try {
- r = getProtocol().fetch(msgsets, command.toString());
- } catch (ConnectionException cex) {
- throw new FolderClosedException(this, cex.getMessage());
- } catch (CommandFailedException cfx) {
- // Ignore these, as per RFC 2180
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- }
-
- if (r == null)
- return;
-
- for (int i = 0; i < r.length; i++) {
- if (r[i] == null)
- continue;
- if (!(r[i] instanceof FetchResponse)) {
- v.addElement(r[i]); // Unsolicited Non-FETCH response
- continue;
- }
-
- // Got a FetchResponse.
- FetchResponse f = (FetchResponse)r[i];
- // Get the corresponding message.
- IMAPMessage msg = getMessageBySeqNumber(f.getNumber());
-
- int count = f.getItemCount();
- boolean unsolicitedFlags = false;
-
- for (int j = 0; j < count; j++) {
- Item item = f.getItem(j);
- // Check for the FLAGS item
- if (item instanceof Flags &&
- (!fp.contains(FetchProfile.Item.FLAGS) ||
- msg == null)) {
- // Ok, Unsolicited FLAGS update.
- unsolicitedFlags = true;
- } else if (msg != null)
- msg.handleFetchItem(item, hdrs, allHeaders);
- }
- if (msg != null)
- msg.handleExtensionFetchItems(f.getExtensionItems());
-
- // If this response contains any unsolicited FLAGS
- // add it to the unsolicited response vector
- if (unsolicitedFlags)
- v.addElement(f);
- }
-
- // Dispatch any unsolicited responses
- int size = v.size();
- if (size != 0) {
- Response[] responses = new Response[size];
- v.copyInto(responses);
- handleResponses(responses);
- }
-
- } // Release messageCacheLock
- }
-
- /**
- * Return the IMAP FETCH items to request in order to load
- * all the "envelope" data. Subclasses can override this
- * method to fetch more data when FetchProfile.Item.ENVELOPE
- * is requested.
- *
- * @since JavaMail 1.4.6
- */
- protected String getEnvelopeCommand() {
- return IMAPMessage.EnvelopeCmd;
- }
-
- /**
- * Create a new IMAPMessage object to represent the given message number.
- * Subclasses of IMAPFolder may override this method to create a
- * subclass of IMAPMessage.
- *
- * @since JavaMail 1.4.6
- */
- protected IMAPMessage newIMAPMessage(int msgnum) {
- return new IMAPMessage(this, msgnum);
- }
-
- /**
- * Create the appropriate IMAP FETCH command items to fetch the
- * requested headers.
- */
- private String createHeaderCommand(String[] hdrs) {
- StringBuffer sb;
-
- if (protocol.isREV1())
- sb = new StringBuffer("BODY.PEEK[HEADER.FIELDS (");
- else
- sb = new StringBuffer("RFC822.HEADER.LINES (");
-
- for (int i = 0; i < hdrs.length; i++) {
- if (i > 0)
- sb.append(" ");
- sb.append(hdrs[i]);
- }
-
- if (protocol.isREV1())
- sb.append(")]");
- else
- sb.append(")");
-
- return sb.toString();
- }
-
- /**
- * Set the specified flags for the given array of messages.
- */
- public synchronized void setFlags(Message[] msgs, Flags flag, boolean value)
- throws MessagingException {
- checkOpened();
- checkFlags(flag); // validate flags
-
- if (msgs.length == 0) // boundary condition
- return;
-
- synchronized(messageCacheLock) {
- try {
- IMAPProtocol p = getProtocol();
- MessageSet[] ms = Utility.toMessageSet(msgs, null);
- if (ms == null)
- throw new MessageRemovedException(
- "Messages have been removed");
- p.storeFlags(ms, flag, value);
- } catch (ConnectionException cex) {
- throw new FolderClosedException(this, cex.getMessage());
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- }
- }
- }
-
- /**
- * Set the specified flags for the given range of message numbers.
- */
- public synchronized void setFlags(int start, int end,
- Flags flag, boolean value) throws MessagingException {
- checkOpened();
- Message[] msgs = new Message[end - start + 1];
- int i = 0;
- for (int n = start; n <= end; n++)
- msgs[i++] = getMessage(n);
- setFlags(msgs, flag, value);
- }
-
- /**
- * Set the specified flags for the given array of message numbers.
- */
- public synchronized void setFlags(int[] msgnums, Flags flag, boolean value)
- throws MessagingException {
- checkOpened();
- Message[] msgs = new Message[msgnums.length];
- for (int i = 0; i < msgnums.length; i++)
- msgs[i] = getMessage(msgnums[i]);
- setFlags(msgs, flag, value);
- }
-
- /**
- * Close this folder.
- */
- public synchronized void close(boolean expunge) throws MessagingException {
- close(expunge, false);
- }
-
- /**
- * Close this folder without waiting for the server.
- */
- public synchronized void forceClose() throws MessagingException {
- close(false, true);
- }
-
- /*
- * Common close method.
- */
- private void close(boolean expunge, boolean force)
- throws MessagingException {
- assert Thread.holdsLock(this);
- synchronized(messageCacheLock) {
- /*
- * If we already know we're closed, this is illegal.
- * Can't use checkOpened() because if we were forcibly
- * closed asynchronously we just want to complete the
- * closing here.
- */
- if (!opened && reallyClosed)
- throw new IllegalStateException(
- "This operation is not allowed on a closed folder"
- );
-
- reallyClosed = true; // Ok, lets reset
-
- // Maybe this folder is already closed, or maybe another
- // thread which had the messageCacheLock earlier, found
- // that our server connection is dead and cleaned up
- // everything ..
- if (!opened)
- return;
-
- try {
- waitIfIdle();
- if (force) {
- logger.log(Level.FINE, "forcing folder {0} to close",
- fullName);
- if (protocol != null)
- protocol.disconnect();
- } else if (((IMAPStore)store).isConnectionPoolFull()) {
- // If the connection pool is full, logout the connection
- logger.fine(
- "pool is full, not adding an Authenticated connection");
-
- // If the expunge flag is set, close the folder first.
- if (expunge && protocol != null)
- protocol.close();
-
- if (protocol != null)
- protocol.logout();
- } else {
- // If the expunge flag is set or we're open read-only we
- // can just close the folder, otherwise open it read-only
- // before closing, or unselect it if supported.
- if (!expunge && mode == READ_WRITE) {
- try {
- if (protocol != null &&
- protocol.hasCapability("UNSELECT"))
- protocol.unselect();
- else {
- if (protocol != null) {
- MailboxInfo mi = protocol.examine(fullName);
- if (protocol != null) // XXX - unnecessary?
- protocol.close();
- }
- }
- } catch (ProtocolException pex2) {
- if (protocol != null)
- protocol.disconnect();
- }
- } else {
- if (protocol != null)
- protocol.close();
- }
- }
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- } finally {
- // cleanup if we haven't already
- if (opened)
- cleanup(true);
- }
- }
- }
-
- // NOTE: this method can currently be invoked from close() or
- // from handleResponses(). Both invocations are conditional,
- // based on the "opened" flag, so we are sure that multiple
- // Connection.CLOSED events are not generated. Also both
- // invocations are from within messageCacheLock-ed areas.
- private void cleanup(boolean returnToPool) {
- assert Thread.holdsLock(messageCacheLock);
- releaseProtocol(returnToPool);
- messageCache = null;
- uidTable = null;
- exists = false; // to force a recheck in exists().
- attributes = null;
- opened = false;
- idleState = RUNNING; // just in case
- notifyConnectionListeners(ConnectionEvent.CLOSED);
- }
-
- /**
- * Check whether this connection is really open.
- */
- public synchronized boolean isOpen() {
- synchronized(messageCacheLock) {
- // Probe the connection to make sure its really open.
- if (opened) {
- try {
- keepConnectionAlive(false);
- } catch (ProtocolException pex) { }
- }
- }
-
- return opened;
- }
-
- /**
- * Return the permanent flags supported by the server.
- */
- public synchronized Flags getPermanentFlags() {
- if (permanentFlags == null)
- return null;
- return (Flags)(permanentFlags.clone());
- }
-
- /**
- * Get the total message count.
- */
- public synchronized int getMessageCount() throws MessagingException {
- if (!opened) {
- checkExists();
- // If this folder is not yet open, we use STATUS to
- // get the total message count
- try {
- Status status = getStatus();
- return status.total;
- } catch (BadCommandException bex) {
- // doesn't support STATUS, probably vanilla IMAP4 ..
- // lets try EXAMINE
- IMAPProtocol p = null;
-
- try {
- p = getStoreProtocol(); // XXX
- MailboxInfo minfo = p.examine(fullName);
- p.close();
- return minfo.total;
- } catch (ProtocolException pex) {
- // Give up.
- throw new MessagingException(pex.getMessage(), pex);
- } finally {
- releaseStoreProtocol(p);
- }
- } catch (ConnectionException cex) {
- throw new StoreClosedException(store, cex.getMessage());
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- }
- }
-
- // Folder is open, we know what the total message count is ..
- synchronized(messageCacheLock) {
- // tickle the folder and store connections.
- try {
- keepConnectionAlive(true);
- return total;
- } catch (ConnectionException cex) {
- throw new FolderClosedException(this, cex.getMessage());
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- }
- }
- }
-
- /**
- * Get the new message count.
- */
- public synchronized int getNewMessageCount()
- throws MessagingException {
- if (!opened) {
- checkExists();
- // If this folder is not yet open, we use STATUS to
- // get the new message count
- try {
- Status status = getStatus();
- return status.recent;
- } catch (BadCommandException bex) {
- // doesn't support STATUS, probably vanilla IMAP4 ..
- // lets try EXAMINE
- IMAPProtocol p = null;
-
- try {
- p = getStoreProtocol(); // XXX
- MailboxInfo minfo = p.examine(fullName);
- p.close();
- return minfo.recent;
- } catch (ProtocolException pex) {
- // Give up.
- throw new MessagingException(pex.getMessage(), pex);
- } finally {
- releaseStoreProtocol(p);
- }
- } catch (ConnectionException cex) {
- throw new StoreClosedException(store, cex.getMessage());
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- }
- }
-
- // Folder is open, we know what the new message count is ..
- synchronized(messageCacheLock) {
- // tickle the folder and store connections.
- try {
- keepConnectionAlive(true);
- return recent;
- } catch (ConnectionException cex) {
- throw new FolderClosedException(this, cex.getMessage());
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- }
- }
- }
-
- /**
- * Get the unread message count.
- */
- public synchronized int getUnreadMessageCount()
- throws MessagingException {
- if (!opened) {
- checkExists();
- // If this folder is not yet open, we use STATUS to
- // get the unseen message count
- try {
- Status status = getStatus();
- return status.unseen;
- } catch (BadCommandException bex) {
- // doesn't support STATUS, probably vanilla IMAP4 ..
- // Could EXAMINE, SEARCH for UNREAD messages and
- // return the count .. bah, not worth it.
- return -1;
- } catch (ConnectionException cex) {
- throw new StoreClosedException(store, cex.getMessage());
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- }
- }
-
- // if opened, issue server-side search for messages that do
- // *not* have the SEEN flag.
- Flags f = new Flags();
- f.add(Flags.Flag.SEEN);
- try {
- synchronized(messageCacheLock) {
- int[] matches = getProtocol().search(new FlagTerm(f, false));
- return matches.length; // NOTE: 'matches' is never null
- }
- } catch (ConnectionException cex) {
- throw new FolderClosedException(this, cex.getMessage());
- } catch (ProtocolException pex) {
- // Shouldn't happen
- throw new MessagingException(pex.getMessage(), pex);
- }
- }
-
- /**
- * Get the deleted message count.
- */
- public synchronized int getDeletedMessageCount()
- throws MessagingException {
- if (!opened) {
- checkExists();
- // no way to do this on closed folders
- return -1;
- }
-
- // if opened, issue server-side search for messages that do
- // have the DELETED flag.
- Flags f = new Flags();
- f.add(Flags.Flag.DELETED);
- try {
- synchronized(messageCacheLock) {
- int[] matches = getProtocol().search(new FlagTerm(f, true));
- return matches.length; // NOTE: 'matches' is never null
- }
- } catch (ConnectionException cex) {
- throw new FolderClosedException(this, cex.getMessage());
- } catch (ProtocolException pex) {
- // Shouldn't happen
- throw new MessagingException(pex.getMessage(), pex);
- }
- }
-
- /*
- * Get results of STATUS command for this folder, checking cache first.
- * ASSERT: Must be called with this folder's synchronization lock held.
- * ASSERT: The folder must be closed.
- */
- private Status getStatus() throws ProtocolException {
- int statusCacheTimeout = ((IMAPStore)store).getStatusCacheTimeout();
-
- // if allowed to cache and our cache is still valid, return it
- if (statusCacheTimeout > 0 && cachedStatus != null &&
- System.currentTimeMillis() - cachedStatusTime < statusCacheTimeout)
- return cachedStatus;
-
- IMAPProtocol p = null;
-
- try {
- p = getStoreProtocol(); // XXX
- Status s = p.status(fullName, null);
- // if allowed to cache, do so
- if (statusCacheTimeout > 0) {
- cachedStatus = s;
- cachedStatusTime = System.currentTimeMillis();
- }
- return s;
- } finally {
- releaseStoreProtocol(p);
- }
- }
-
- /**
- * Get the specified message.
- */
- public synchronized Message getMessage(int msgnum)
- throws MessagingException {
- checkOpened();
- checkRange(msgnum);
-
- return messageCache.getMessage(msgnum);
- }
-
- /**
- * Append the given messages into this folder.
- */
- public synchronized void appendMessages(Message[] msgs)
- throws MessagingException {
- checkExists(); // verify that self exists
-
- // XXX - have to verify that messages are in a different
- // store (if any) than target folder, otherwise could
- // deadlock trying to fetch messages on the same connection
- // we're using for the append.
-
- int maxsize = ((IMAPStore)store).getAppendBufferSize();
-
- for (int i = 0; i < msgs.length; i++) {
- final Message m = msgs[i];
- Date d = m.getReceivedDate(); // retain dates
- if (d == null)
- d = m.getSentDate();
- final Date dd = d;
- final Flags f = m.getFlags();
-
- final MessageLiteral mos;
- try {
- // if we know the message is too big, don't buffer any of it
- mos = new MessageLiteral(m,
- m.getSize() > maxsize ? 0 : maxsize);
- } catch (IOException ex) {
- throw new MessagingException(
- "IOException while appending messages", ex);
- } catch (MessageRemovedException mrex) {
- continue; // just skip this expunged message
- }
-
- doCommand(new ProtocolCommand() {
- public Object doCommand(IMAPProtocol p)
- throws ProtocolException {
- p.append(fullName, f, dd, mos);
- return null;
- }
- });
- }
- }
-
- /**
- * Append the given messages into this folder.
- * Return array of AppendUID objects containing
- * UIDs of these messages in the destination folder.
- * Each element of the returned array corresponds to
- * an element of the msgs array. A null
- * element means the server didn't return UID information
- * for the appended message.
- *
- * Depends on the APPENDUID response code defined by the
- * UIDPLUS extension -
- * RFC 2359.
- *
- * @since JavaMail 1.4
- */
- public synchronized AppendUID[] appendUIDMessages(Message[] msgs)
- throws MessagingException {
- checkExists(); // verify that self exists
-
- // XXX - have to verify that messages are in a different
- // store (if any) than target folder, otherwise could
- // deadlock trying to fetch messages on the same connection
- // we're using for the append.
-
- int maxsize = ((IMAPStore)store).getAppendBufferSize();
-
- AppendUID[] uids = new AppendUID[msgs.length];
- for (int i = 0; i < msgs.length; i++) {
- final Message m = msgs[i];
- final MessageLiteral mos;
-
- try {
- // if we know the message is too big, don't buffer any of it
- mos = new MessageLiteral(m,
- m.getSize() > maxsize ? 0 : maxsize);
- } catch (IOException ex) {
- throw new MessagingException(
- "IOException while appending messages", ex);
- } catch (MessageRemovedException mrex) {
- continue; // just skip this expunged message
- }
-
- Date d = m.getReceivedDate(); // retain dates
- if (d == null)
- d = m.getSentDate();
- final Date dd = d;
- final Flags f = m.getFlags();
- AppendUID auid = (AppendUID)doCommand(new ProtocolCommand() {
- public Object doCommand(IMAPProtocol p)
- throws ProtocolException {
- return p.appenduid(fullName, f, dd, mos);
- }
- });
- uids[i] = auid;
- }
- return uids;
- }
-
- /**
- * Append the given messages into this folder.
- * Return array of Message objects representing
- * the messages in the destination folder. Note
- * that the folder must be open.
- * Each element of the returned array corresponds to
- * an element of the msgs array. A null
- * element means the server didn't return UID information
- * for the appended message.
- *
- * Depends on the APPENDUID response code defined by the
- * UIDPLUS extension -
- * RFC 2359.
- *
- * @since JavaMail 1.4
- */
- public synchronized Message[] addMessages(Message[] msgs)
- throws MessagingException {
- checkOpened();
- Message[] rmsgs = new MimeMessage[msgs.length];
- AppendUID[] uids = appendUIDMessages(msgs);
- for (int i = 0; i < uids.length; i++) {
- AppendUID auid = uids[i];
- if (auid != null) {
- if (auid.uidvalidity == uidvalidity) {
- try {
- rmsgs[i] = getMessageByUID(auid.uid);
- } catch (MessagingException mex) {
- // ignore errors at this stage
- }
- }
- }
- }
- return rmsgs;
- }
-
- /**
- * Copy the specified messages from this folder, to the
- * specified destination.
- */
- public synchronized void copyMessages(Message[] msgs, Folder folder)
- throws MessagingException {
- checkOpened();
-
- if (msgs.length == 0) // boundary condition
- return;
-
- // If the destination belongs to our same store, optimize
- if (folder.getStore() == store) {
- synchronized(messageCacheLock) {
- try {
- IMAPProtocol p = getProtocol();
- MessageSet[] ms = Utility.toMessageSet(msgs, null);
- if (ms == null)
- throw new MessageRemovedException(
- "Messages have been removed");
- p.copy(ms, folder.getFullName());
- } catch (CommandFailedException cfx) {
- if (cfx.getMessage().indexOf("TRYCREATE") != -1)
- throw new FolderNotFoundException(
- folder,
- folder.getFullName() + " does not exist"
- );
- else
- throw new MessagingException(cfx.getMessage(), cfx);
- } catch (ConnectionException cex) {
- throw new FolderClosedException(this, cex.getMessage());
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- }
- }
- } else // destination is a different store.
- super.copyMessages(msgs, folder);
- }
-
- /**
- * Expunge all messages marked as DELETED.
- */
- public synchronized Message[] expunge() throws MessagingException {
- return expunge(null);
- }
-
- /**
- * Expunge the indicated messages, which must have been marked as DELETED.
- *
- * Depends on the UIDPLUS extension -
- * RFC 2359.
- */
- public synchronized Message[] expunge(Message[] msgs)
- throws MessagingException {
- checkOpened();
-
- if (msgs != null) {
- // call fetch to make sure we have all the UIDs
- FetchProfile fp = new FetchProfile();
- fp.add(UIDFolder.FetchProfileItem.UID);
- fetch(msgs, fp);
- }
-
- IMAPMessage[] rmsgs;
- synchronized(messageCacheLock) {
- doExpungeNotification = false; // We do this ourselves later
- try {
- IMAPProtocol p = getProtocol();
- if (msgs != null)
- p.uidexpunge(Utility.toUIDSet(msgs));
- else
- p.expunge();
- } catch (CommandFailedException cfx) {
- // expunge not allowed, perhaps due to a permission problem?
- if (mode != READ_WRITE)
- throw new IllegalStateException(
- "Cannot expunge READ_ONLY folder: " + fullName);
- else
- throw new MessagingException(cfx.getMessage(), cfx);
- } catch (ConnectionException cex) {
- throw new FolderClosedException(this, cex.getMessage());
- } catch (ProtocolException pex) {
- // Bad bad server ..
- throw new MessagingException(pex.getMessage(), pex);
- } finally {
- doExpungeNotification = true;
- }
-
- // Cleanup expunged messages and sync messageCache with reality.
- if (msgs != null)
- rmsgs = messageCache.removeExpungedMessages(msgs);
- else
- rmsgs = messageCache.removeExpungedMessages();
- if (uidTable != null) {
- for (int i = 0; i < rmsgs.length; i++) {
- IMAPMessage m = rmsgs[i];
- /* remove this message from the UIDTable */
- long uid = m.getUID();
- if (uid != -1)
- uidTable.remove(new Long(uid));
- }
- }
-
- // Update 'total'
- total = messageCache.size();
- }
-
- // Notify listeners. This time its for real, guys.
- if (rmsgs.length > 0)
- notifyMessageRemovedListeners(true, rmsgs);
- return rmsgs;
- }
-
- /**
- * Search whole folder for messages matching the given term.
- */
- public synchronized Message[] search(SearchTerm term)
- throws MessagingException {
- checkOpened();
-
- try {
- Message[] matchMsgs = null;
-
- synchronized(messageCacheLock) {
- int[] matches = getProtocol().search(term);
- if (matches != null) {
- matchMsgs = new IMAPMessage[matches.length];
- // Map seq-numbers into actual Messages.
- for (int i = 0; i < matches.length; i++)
- matchMsgs[i] = getMessageBySeqNumber(matches[i]);
- }
- }
- return matchMsgs;
-
- } catch (CommandFailedException cfx) {
- // unsupported charset or search criterion
- return super.search(term);
- } catch (SearchException sex) {
- // too complex for IMAP
- return super.search(term);
- } catch (ConnectionException cex) {
- throw new FolderClosedException(this, cex.getMessage());
- } catch (ProtocolException pex) {
- // bug in our IMAP layer ?
- throw new MessagingException(pex.getMessage(), pex);
- }
- }
-
- /**
- * Search the folder for messages matching the given term. Returns
- * array of matching messages. Returns an empty array if no matching
- * messages are found.
- */
- public synchronized Message[] search(SearchTerm term, Message[] msgs)
- throws MessagingException {
- checkOpened();
-
- if (msgs.length == 0)
- // need to return an empty array (not null!)
- return msgs;
-
- try {
- Message[] matchMsgs = null;
-
- synchronized(messageCacheLock) {
- IMAPProtocol p = getProtocol();
- MessageSet[] ms = Utility.toMessageSet(msgs, null);
- if (ms == null)
- throw new MessageRemovedException(
- "Messages have been removed");
- int[] matches = p.search(ms, term);
- if (matches != null) {
- matchMsgs = new IMAPMessage[matches.length];
- for (int i = 0; i < matches.length; i++)
- matchMsgs[i] = getMessageBySeqNumber(matches[i]);
- }
- }
- return matchMsgs;
-
- } catch (CommandFailedException cfx) {
- // unsupported charset or search criterion
- return super.search(term, msgs);
- } catch (SearchException sex) {
- // too complex for IMAP
- return super.search(term, msgs);
- } catch (ConnectionException cex) {
- throw new FolderClosedException(this, cex.getMessage());
- } catch (ProtocolException pex) {
- // bug in our IMAP layer ?
- throw new MessagingException(pex.getMessage(), pex);
- }
- }
-
- /**
- * Sort the messages in the folder according to the sort criteria.
- * The messages are returned in the sorted order, but the order of
- * the messages in the folder is not changed.
- *
- * Depends on the SORT extension -
- * RFC 5256.
- *
- * @since JavaMail 1.4.4
- */
- public synchronized Message[] getSortedMessages(SortTerm[] term)
- throws MessagingException {
- return getSortedMessages(term, null);
- }
-
- /**
- * Sort the messages in the folder according to the sort criteria.
- * The messages are returned in the sorted order, but the order of
- * the messages in the folder is not changed. Only messages matching
- * the search criteria are considered.
- *
- * Depends on the SORT extension -
- * RFC 5256.
- *
- * @since JavaMail 1.4.4
- */
- public synchronized Message[] getSortedMessages(SortTerm[] term,
- SearchTerm sterm) throws MessagingException {
- checkOpened();
-
- try {
- Message[] matchMsgs = null;
-
- synchronized(messageCacheLock) {
- int[] matches = getProtocol().sort(term, sterm);
- if (matches != null) {
- matchMsgs = new IMAPMessage[matches.length];
- // Map seq-numbers into actual Messages.
- for (int i = 0; i < matches.length; i++)
- matchMsgs[i] = getMessageBySeqNumber(matches[i]);
- }
- }
- return matchMsgs;
-
- } catch (CommandFailedException cfx) {
- // unsupported charset or search criterion
- throw new MessagingException(cfx.getMessage(), cfx);
- } catch (SearchException sex) {
- // too complex for IMAP
- throw new MessagingException(sex.getMessage(), sex);
- } catch (ConnectionException cex) {
- throw new FolderClosedException(this, cex.getMessage());
- } catch (ProtocolException pex) {
- // bug in our IMAP layer ?
- throw new MessagingException(pex.getMessage(), pex);
- }
- }
-
- /*
- * Override Folder method to keep track of whether we have any
- * message count listeners. Normally we won't have any, so we
- * can avoid creating message objects to pass to the notify
- * method. It's too hard to keep track of when all listeners
- * are removed, and that's a rare case, so we don't try.
- */
- public synchronized void addMessageCountListener(MessageCountListener l) {
- super.addMessageCountListener(l);
- hasMessageCountListener = true;
- }
-
- /***********************************************************
- * UIDFolder interface methods
- **********************************************************/
-
- /**
- * Returns the UIDValidity for this folder.
- */
- public synchronized long getUIDValidity() throws MessagingException {
- if (opened) // we already have this information
- return uidvalidity;
-
- IMAPProtocol p = null;
- Status status = null;
-
- try {
- p = getStoreProtocol(); // XXX
- String[] item = { "UIDVALIDITY" };
- status = p.status(fullName, item);
- } catch (BadCommandException bex) {
- // Probably a RFC1730 server
- throw new MessagingException("Cannot obtain UIDValidity", bex);
- } catch (ConnectionException cex) {
- // Oops, the store or folder died on us.
- throwClosedException(cex);
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- } finally {
- releaseStoreProtocol(p);
- }
-
- return status.uidvalidity;
- }
-
- /**
- * Returns the predicted UID that will be assigned to the
- * next message that is appended to this folder.
- * If the folder is closed, the STATUS command is used to
- * retrieve this value. If the folder is open, the value
- * returned from the SELECT or EXAMINE command is returned.
- * Note that messages may have been appended to the folder
- * while it was open and thus this value may be out of
- * date.
- *
- * Servers implementing RFC2060 likely won't return this value
- * when a folder is opened. Servers implementing RFC3501
- * should return this value when a folder is opened.
- *
- * @return the UIDNEXT value, or -1 if unknown
- * @since JavaMail 1.3.3
- */
- // Not a UIDFolder method, but still useful
- public synchronized long getUIDNext() throws MessagingException {
- if (opened) // we already have this information
- return uidnext;
-
- IMAPProtocol p = null;
- Status status = null;
-
- try {
- p = getStoreProtocol(); // XXX
- String[] item = { "UIDNEXT" };
- status = p.status(fullName, item);
- } catch (BadCommandException bex) {
- // Probably a RFC1730 server
- throw new MessagingException("Cannot obtain UIDNext", bex);
- } catch (ConnectionException cex) {
- // Oops, the store or folder died on us.
- throwClosedException(cex);
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- } finally {
- releaseStoreProtocol(p);
- }
-
- return status.uidnext;
- }
-
- /**
- * Get the Message corresponding to the given UID.
- * If no such message exists, null is returned.
- */
- public synchronized Message getMessageByUID(long uid)
- throws MessagingException {
- checkOpened(); // insure folder is open
-
- IMAPMessage m = null;
-
- try {
- synchronized(messageCacheLock) {
- Long l = new Long(uid);
-
- if (uidTable != null) {
- // Check in uidTable
- m = (IMAPMessage)uidTable.get(l);
- if (m != null) // found it
- return m;
- } else
- uidTable = new Hashtable();
-
- // Check with the server
- // Issue UID FETCH command
- UID u = getProtocol().fetchSequenceNumber(uid);
-
- if (u != null && u.seqnum <= total) { // Valid UID
- m = getMessageBySeqNumber(u.seqnum);
- m.setUID(u.uid); // set this message's UID ..
- // .. and put this into the hashtable
- uidTable.put(l, m);
- }
- }
- } catch(ConnectionException cex) {
- throw new FolderClosedException(this, cex.getMessage());
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- }
-
- return m;
- }
-
- /**
- * Get the Messages specified by the given range.
- * Returns Message objects for all valid messages in this range.
- * Returns an empty array if no messages are found.
- */
- public synchronized Message[] getMessagesByUID(long start, long end)
- throws MessagingException {
- checkOpened(); // insure that folder is open
-
- Message[] msgs; // array of messages to be returned
-
- try {
- synchronized(messageCacheLock) {
- if (uidTable == null)
- uidTable = new Hashtable();
-
- // Issue UID FETCH for given range
- UID[] ua = getProtocol().fetchSequenceNumbers(start, end);
-
- msgs = new Message[ua.length];
- IMAPMessage m;
- // NOTE: Below must be within messageCacheLock region
- for (int i = 0; i < ua.length; i++) {
- m = getMessageBySeqNumber(ua[i].seqnum);
- m.setUID(ua[i].uid);
- msgs[i] = m;
- uidTable.put(new Long(ua[i].uid), m);
- }
- }
- } catch(ConnectionException cex) {
- throw new FolderClosedException(this, cex.getMessage());
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- }
-
- return msgs;
- }
-
- /**
- * Get the Messages specified by the given array.
- *
- * uids.length() elements are returned.
- * If any UID in the array is invalid, a null entry
- * is returned for that element.
- */
- public synchronized Message[] getMessagesByUID(long[] uids)
- throws MessagingException {
- checkOpened(); // insure that folder is open
-
- try {
- synchronized(messageCacheLock) {
- long[] unavailUids = uids;
- if (uidTable != null) {
- Vector v = new Vector(); // to collect unavailable UIDs
- Long l;
- for (int i = 0; i < uids.length; i++) {
- if (!uidTable.containsKey(l = new Long(uids[i])))
- // This UID has not been loaded yet.
- v.addElement(l);
- }
-
- int vsize = v.size();
- unavailUids = new long[vsize];
- for (int i = 0; i < vsize; i++)
- unavailUids[i] = ((Long)v.elementAt(i)).longValue();
- } else
- uidTable = new Hashtable();
-
- if (unavailUids.length > 0) {
- // Issue UID FETCH request for given uids
- UID[] ua = getProtocol().fetchSequenceNumbers(unavailUids);
- IMAPMessage m;
- for (int i = 0; i < ua.length; i++) {
- m = getMessageBySeqNumber(ua[i].seqnum);
- m.setUID(ua[i].uid);
- uidTable.put(new Long(ua[i].uid), m);
- }
- }
-
- // Return array of size = uids.length
- Message[] msgs = new Message[uids.length];
- for (int i = 0; i < uids.length; i++)
- msgs[i] = (Message)uidTable.get(new Long(uids[i]));
- return msgs;
- }
- } catch(ConnectionException cex) {
- throw new FolderClosedException(this, cex.getMessage());
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- }
- }
-
- /**
- * Get the UID for the specified message.
- */
- public synchronized long getUID(Message message)
- throws MessagingException {
- if (message.getFolder() != this)
- throw new NoSuchElementException(
- "Message does not belong to this folder");
-
- checkOpened(); // insure that folder is open
-
- IMAPMessage m = (IMAPMessage)message;
- // If the message already knows its UID, great ..
- long uid;
- if ((uid = m.getUID()) != -1)
- return uid;
-
- synchronized(messageCacheLock) { // Acquire Lock
- try {
- IMAPProtocol p = getProtocol();
- m.checkExpunged(); // insure that message is not expunged
- UID u = p.fetchUID(m.getSequenceNumber());
-
- if (u != null) {
- uid = u.uid;
- m.setUID(uid); // set message's UID
-
- // insert this message into uidTable
- if (uidTable == null)
- uidTable = new Hashtable();
- uidTable.put(new Long(uid), m);
- }
- } catch (ConnectionException cex) {
- throw new FolderClosedException(this, cex.getMessage());
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- }
- }
-
- return uid;
- }
-
- /**
- * Get the quotas for the quotaroot associated with this
- * folder. Note that many folders may have the same quotaroot.
- * Quotas are controlled on the basis of a quotaroot, not
- * (necessarily) a folder. The relationship between folders
- * and quotaroots depends on the IMAP server. Some servers
- * might implement a single quotaroot for all folders owned by
- * a user. Other servers might implement a separate quotaroot
- * for each folder. A single folder can even have multiple
- * quotaroots, perhaps controlling quotas for different
- * resources.
- *
- * @return array of Quota objects for the quotaroots associated with
- * this folder
- * @exception MessagingException if the server doesn't support the
- * QUOTA extension
- */
- public Quota[] getQuota() throws MessagingException {
- return (Quota[])doOptionalCommand("QUOTA not supported",
- new ProtocolCommand() {
- public Object doCommand(IMAPProtocol p)
- throws ProtocolException {
- return p.getQuotaRoot(fullName);
- }
- });
- }
-
- /**
- * Set the quotas for the quotaroot specified in the quota argument.
- * Typically this will be one of the quotaroots associated with this
- * folder, as obtained from the getQuota method, but it
- * need not be.
- *
- * @param quota the quota to set
- * @exception MessagingException if the server doesn't support the
- * QUOTA extension
- */
- public void setQuota(final Quota quota) throws MessagingException {
- doOptionalCommand("QUOTA not supported",
- new ProtocolCommand() {
- public Object doCommand(IMAPProtocol p)
- throws ProtocolException {
- p.setQuota(quota);
- return null;
- }
- });
- }
-
- /**
- * Get the access control list entries for this folder.
- *
- * @return array of access control list entries
- * @exception MessagingException if the server doesn't support the
- * ACL extension
- */
- public ACL[] getACL() throws MessagingException {
- return (ACL[])doOptionalCommand("ACL not supported",
- new ProtocolCommand() {
- public Object doCommand(IMAPProtocol p)
- throws ProtocolException {
- return p.getACL(fullName);
- }
- });
- }
-
- /**
- * Add an access control list entry to the access control list
- * for this folder.
- *
- * @param acl the access control list entry to add
- * @exception MessagingException if the server doesn't support the
- * ACL extension
- */
- public void addACL(ACL acl) throws MessagingException {
- setACL(acl, '\0');
- }
-
- /**
- * Remove any access control list entry for the given identifier
- * from the access control list for this folder.
- *
- * @param name the identifier for which to remove all ACL entries
- * @exception MessagingException if the server doesn't support the
- * ACL extension
- */
- public void removeACL(final String name) throws MessagingException {
- doOptionalCommand("ACL not supported",
- new ProtocolCommand() {
- public Object doCommand(IMAPProtocol p)
- throws ProtocolException {
- p.deleteACL(fullName, name);
- return null;
- }
- });
- }
-
- /**
- * Add the rights specified in the ACL to the entry for the
- * identifier specified in the ACL. If an entry for the identifier
- * doesn't already exist, add one.
- *
- * @param acl the identifer and rights to add
- * @exception MessagingException if the server doesn't support the
- * ACL extension
- */
- public void addRights(ACL acl) throws MessagingException {
- setACL(acl, '+');
- }
-
- /**
- * Remove the rights specified in the ACL from the entry for the
- * identifier specified in the ACL.
- *
- * @param acl the identifer and rights to remove
- * @exception MessagingException if the server doesn't support the
- * ACL extension
- */
- public void removeRights(ACL acl) throws MessagingException {
- setACL(acl, '-');
- }
-
- /**
- * Get all the rights that may be allowed to the given identifier.
- * Rights are grouped per RFC 2086 and each group is returned as an
- * element of the array. The first element of the array is the set
- * of rights that are always granted to the identifier. Later
- * elements are rights that may be optionally granted to the
- * identifier.
- *
- * Note that this method lists the rights that it is possible to
- * assign to the given identifier, not the rights that are
- * actually granted to the given identifier. For the latter, see
- * the getACL method.
- *
- * @param name the identifier to list rights for
- * @return array of Rights objects representing possible
- * rights for the identifier
- * @exception MessagingException if the server doesn't support the
- * ACL extension
- */
- public Rights[] listRights(final String name) throws MessagingException {
- return (Rights[])doOptionalCommand("ACL not supported",
- new ProtocolCommand() {
- public Object doCommand(IMAPProtocol p)
- throws ProtocolException {
- return p.listRights(fullName, name);
- }
- });
- }
-
- /**
- * Get the rights allowed to the currently authenticated user.
- *
- * @return the rights granted to the current user
- * @exception MessagingException if the server doesn't support the
- * ACL extension
- */
- public Rights myRights() throws MessagingException {
- return (Rights)doOptionalCommand("ACL not supported",
- new ProtocolCommand() {
- public Object doCommand(IMAPProtocol p)
- throws ProtocolException {
- return p.myRights(fullName);
- }
- });
- }
-
- private void setACL(final ACL acl, final char mod)
- throws MessagingException {
- doOptionalCommand("ACL not supported",
- new ProtocolCommand() {
- public Object doCommand(IMAPProtocol p)
- throws ProtocolException {
- p.setACL(fullName, mod, acl);
- return null;
- }
- });
- }
-
- /**
- * Get the attributes that the IMAP server returns with the
- * LIST response.
- *
- * @since JavaMail 1.3.3
- */
- public synchronized String[] getAttributes() throws MessagingException {
- checkExists();
- if (attributes == null)
- exists(); // do a LIST to set the attributes
- return attributes == null ? new String[0] :
- (String[])(attributes.clone());
- }
-
- /**
- * Use the IMAP IDLE command (see
- * RFC 2177),
- * if supported by the server, to enter idle mode so that the server
- * can send unsolicited notifications of new messages arriving, etc.
- * without the need for the client to constantly poll the server.
- * Use an appropriate listener to be notified of new messages or
- * other events. When another thread (e.g., the listener thread)
- * needs to issue an IMAP comand for this folder, the idle mode will
- * be terminated and this method will return. Typically the caller
- * will invoke this method in a loop.
- *
- * The mail.imap.minidletime property enforces a minimum delay
- * before returning from this method, to ensure that other threads
- * have a chance to issue commands before the caller invokes this
- * method again. The default delay is 10 milliseconds.
- *
- * @exception MessagingException if the server doesn't support the
- * IDLE extension
- * @exception IllegalStateException if the folder isn't open
- *
- * @since JavaMail 1.4.1
- */
- public void idle() throws MessagingException {
- idle(false);
- }
-
- /**
- * Like {@link #idle}, but if once is true, abort the
- * IDLE command after the first notification, to allow the caller
- * to process any notification synchronously.
- *
- * @exception MessagingException if the server doesn't support the
- * IDLE extension
- * @exception IllegalStateException if the folder isn't open
- *
- * @since JavaMail 1.4.3
- */
- public void idle(boolean once) throws MessagingException {
- // ASSERT: Must NOT be called with this folder's
- // synchronization lock held.
- assert !Thread.holdsLock(this);
- synchronized(this) {
- checkOpened();
- Boolean started = (Boolean)doOptionalCommand("IDLE not supported",
- new ProtocolCommand() {
- public Object doCommand(IMAPProtocol p)
- throws ProtocolException {
- if (idleState == RUNNING) {
- p.idleStart();
- idleState = IDLE;
- return Boolean.TRUE;
- } else {
- // some other thread must be running the IDLE
- // command, we'll just wait for it to finish
- // without aborting it ourselves
- try {
- // give up lock and wait to be not idle
- messageCacheLock.wait();
- } catch (InterruptedException ex) { }
- return Boolean.FALSE;
- }
- }
- });
- if (!started.booleanValue())
- return;
- }
-
- /*
- * We gave up the folder lock so that other threads
- * can get into the folder far enough to see that we're
- * in IDLE and abort the IDLE.
- *
- * Now we read responses from the IDLE command, especially
- * including unsolicited notifications from the server.
- * We don't hold the messageCacheLock while reading because
- * it protects the idleState and other threads need to be
- * able to examine the state.
- *
- * We hold the messageCacheLock while processing the
- * responses so that we can update the number of messages
- * in the folder (for example).
- */
- for (;;) {
- Response r = protocol.readIdleResponse();
- try {
- synchronized (messageCacheLock) {
- try {
- if (r == null || protocol == null ||
- !protocol.processIdleResponse(r)) {
- idleState = RUNNING;
- messageCacheLock.notifyAll();
- break;
- }
- } catch (ProtocolException pex) {
- idleState = RUNNING;
- messageCacheLock.notifyAll();
- throw pex;
- }
- if (once) {
- if (idleState == IDLE) {
- protocol.idleAbort();
- idleState = ABORTING;
- }
- }
- }
- } catch (ConnectionException cex) {
- // Oops, the store or folder died on us.
- throwClosedException(cex);
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- }
- }
-
- /*
- * Enforce a minimum delay to give time to threads
- * processing the responses that came in while we
- * were idle.
- */
- int minidle = ((IMAPStore)store).getMinIdleTime();
- if (minidle > 0) {
- try {
- Thread.sleep(minidle);
- } catch (InterruptedException ex) { }
- }
- }
-
- /*
- * If an IDLE command is in progress, abort it if necessary,
- * and wait until it completes.
- * ASSERT: Must be called with the message cache lock held.
- */
- void waitIfIdle() throws ProtocolException {
- assert Thread.holdsLock(messageCacheLock);
- while (idleState != RUNNING) {
- if (idleState == IDLE) {
- protocol.idleAbort();
- idleState = ABORTING;
- }
- try {
- // give up lock and wait to be not idle
- messageCacheLock.wait();
- } catch (InterruptedException ex) { }
- }
- }
-
- /**
- * The response handler. This is the callback routine that is
- * invoked by the protocol layer.
- */
- /*
- * ASSERT: This method must be called only when holding the
- * messageCacheLock.
- * ASSERT: This method must *not* invoke any other method that
- * might grab the 'folder' lock or 'message' lock (i.e., any
- * synchronized methods on IMAPFolder or IMAPMessage)
- * since that will result in violating the locking hierarchy.
- */
- public void handleResponse(Response r) {
- assert Thread.holdsLock(messageCacheLock);
-
- /*
- * First, delegate possible ALERT or notification to the Store.
- */
- if (r.isOK() || r.isNO() || r.isBAD() || r.isBYE())
- ((IMAPStore)store).handleResponseCode(r);
-
- /*
- * Now check whether this is a BYE or OK response and
- * handle appropriately.
- */
- if (r.isBYE()) {
- if (opened) // XXX - accessed without holding folder lock
- cleanup(false);
- return;
- } else if (r.isOK()) {
- return;
- } else if (!r.isUnTagged()) {
- return; // might be a continuation for IDLE
- }
-
- /* Now check whether this is an IMAP specific response */
- if (!(r instanceof IMAPResponse)) {
- // Probably a bug in our code !
- // XXX - should be an assert
- logger.fine("UNEXPECTED RESPONSE : " + r.toString());
- return;
- }
-
- IMAPResponse ir = (IMAPResponse)r;
-
- if (ir.keyEquals("EXISTS")) { // EXISTS
- int exists = ir.getNumber();
- if (exists <= realTotal)
- // Could be the EXISTS following EXPUNGE, ignore 'em
- return;
-
- int count = exists - realTotal; // number of new messages
- Message[] msgs = new Message[count];
-
- // Add 'count' new IMAPMessage objects into the messageCache
- messageCache.addMessages(count, realTotal + 1);
- int oldtotal = total; // used in loop below
- realTotal += count;
- total += count;
-
- // avoid instantiating Message objects if no listeners.
- if (hasMessageCountListener) {
- for (int i = 0; i < count; i++)
- msgs[i] = messageCache.getMessage(++oldtotal);
-
- // Notify listeners.
- notifyMessageAddedListeners(msgs);
- }
-
- } else if (ir.keyEquals("EXPUNGE")) {
- // EXPUNGE response.
-
- int seqnum = ir.getNumber();
- Message[] msgs = null;
- if (doExpungeNotification && hasMessageCountListener) {
- // save the Message object first; can't look it
- // up after it's expunged
- msgs = new Message[] { getMessageBySeqNumber(seqnum) };
- }
-
- messageCache.expungeMessage(seqnum);
-
- // decrement 'realTotal'; but leave 'total' unchanged
- realTotal--;
-
- if (msgs != null) // Do the notification here.
- notifyMessageRemovedListeners(false, msgs);
-
- } else if (ir.keyEquals("FETCH")) {
- // The only unsolicited FETCH response that makes sense
- // to me (for now) is FLAGS updates. Ignore any other junk.
- assert ir instanceof FetchResponse : "!ir instanceof FetchResponse";
- FetchResponse f = (FetchResponse)ir;
- // Get FLAGS response, if present
- Flags flags = (Flags)f.getItem(Flags.class);
-
- if (flags != null) {
- IMAPMessage msg = getMessageBySeqNumber(f.getNumber());
- if (msg != null) { // should always be true
- msg._setFlags(flags);
- notifyMessageChangedListeners(
- MessageChangedEvent.FLAGS_CHANGED, msg);
- }
- }
-
- } else if (ir.keyEquals("RECENT")) {
- // update 'recent'
- recent = ir.getNumber();
- }
- }
-
- /**
- * Handle the given array of Responses.
- *
- * ASSERT: This method must be called only when holding the
- * messageCacheLock
- */
- void handleResponses(Response[] r) {
- for (int i = 0; i < r.length; i++) {
- if (r[i] != null)
- handleResponse(r[i]);
- }
- }
-
- /**
- * Get this folder's Store's protocol connection.
- *
- * When acquiring a store protocol object, it is important to
- * use the following steps:
- *
- * IMAPProtocol p = null;
- * try {
- * p = getStoreProtocol();
- * // perform the command
- * } catch (WhateverException ex) {
- * // handle it
- * } finally {
- * releaseStoreProtocol(p);
- * }
- */
- protected synchronized IMAPProtocol getStoreProtocol()
- throws ProtocolException {
- connectionPoolLogger.fine("getStoreProtocol() borrowing a connection");
- return ((IMAPStore)store).getFolderStoreProtocol();
- }
-
- /**
- * Throw the appropriate 'closed' exception.
- */
- protected synchronized void throwClosedException(ConnectionException cex)
- throws FolderClosedException, StoreClosedException {
- // If it's the folder's protocol object, throw a FolderClosedException;
- // otherwise, throw a StoreClosedException.
- // If a command has failed because the connection is closed,
- // the folder will have already been forced closed by the
- // time we get here and our protocol object will have been
- // released, so if we no longer have a protocol object we base
- // this decision on whether we *think* the folder is open.
- if ((protocol != null && cex.getProtocol() == protocol) ||
- (protocol == null && !reallyClosed))
- throw new FolderClosedException(this, cex.getMessage());
- else
- throw new StoreClosedException(store, cex.getMessage());
- }
-
- /**
- * Return the IMAPProtocol object for this folder.
- *
- * This method will block if necessary to wait for an IDLE
- * command to finish.
- *
- * @return the IMAPProtocol object used when the folder is open
- */
- protected IMAPProtocol getProtocol() throws ProtocolException {
- assert Thread.holdsLock(messageCacheLock);
- waitIfIdle();
- return protocol;
- }
-
- /**
- * A simple interface for user-defined IMAP protocol commands.
- */
- public static interface ProtocolCommand {
- /**
- * Execute the user-defined command using the supplied IMAPProtocol
- * object.
- */
- public Object doCommand(IMAPProtocol protocol) throws ProtocolException;
- }
-
- /**
- * Execute a user-supplied IMAP command. The command is executed
- * in the appropriate context with the necessary locks held and
- * using the appropriate IMAPProtocol object.
- *
- * This method returns whatever the ProtocolCommand
- * object's doCommand method returns. If the
- * doCommand method throws a ConnectionException
- * it is translated into a StoreClosedException or
- * FolderClosedException as appropriate. If the
- * doCommand method throws a ProtocolException
- * it is translated into a MessagingException.
- *
- * The following example shows how to execute the IMAP NOOP command.
- * Executing more complex IMAP commands requires intimate knowledge
- * of the com.sun.mail.iap and
- * com.sun.mail.imap.protocol packages, best acquired by
- * reading the source code.
- */
- public Object doCommand(ProtocolCommand cmd) throws MessagingException {
- try {
- return doProtocolCommand(cmd);
- } catch (ConnectionException cex) {
- // Oops, the store or folder died on us.
- throwClosedException(cex);
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- }
- return null;
- }
-
- public Object doOptionalCommand(String err, ProtocolCommand cmd)
- throws MessagingException {
- try {
- return doProtocolCommand(cmd);
- } catch (BadCommandException bex) {
- throw new MessagingException(err, bex);
- } catch (ConnectionException cex) {
- // Oops, the store or folder died on us.
- throwClosedException(cex);
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- }
- return null;
- }
-
- public Object doCommandIgnoreFailure(ProtocolCommand cmd)
- throws MessagingException {
- try {
- return doProtocolCommand(cmd);
- } catch (CommandFailedException cfx) {
- return null;
- } catch (ConnectionException cex) {
- // Oops, the store or folder died on us.
- throwClosedException(cex);
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- }
- return null;
- }
-
- protected Object doProtocolCommand(ProtocolCommand cmd)
- throws ProtocolException {
- synchronized (this) {
- /*
- * Check whether we have a protocol object, not whether we're
- * opened, to allow use of the exsting protocol object in the
- * open method before the state is changed to "opened".
- */
- if (protocol != null) {
- synchronized (messageCacheLock) {
- return cmd.doCommand(getProtocol());
- }
- }
- }
-
- // only get here if using store's connection
- IMAPProtocol p = null;
-
- try {
- p = getStoreProtocol();
- return cmd.doCommand(p);
- } finally {
- releaseStoreProtocol(p);
- }
- }
-
- /**
- * Release the store protocol object. If we borrowed a protocol
- * object from the connection pool, give it back. If we used our
- * own protocol object, nothing to do.
- */
- protected synchronized void releaseStoreProtocol(IMAPProtocol p) {
- if (p != protocol)
- ((IMAPStore)store).releaseFolderStoreProtocol(p);
- else {
- // XXX - should never happen
- logger.fine("releasing our protocol as store protocol?");
- }
- }
-
- /**
- * Release the protocol object.
- *
- * ASSERT: This method must be called only when holding the
- * messageCacheLock
- */
- protected void releaseProtocol(boolean returnToPool) {
- if (protocol != null) {
- protocol.removeResponseHandler(this);
-
- if (returnToPool)
- ((IMAPStore)store).releaseProtocol(this, protocol);
- else {
- protocol.disconnect(); // make sure it's disconnected
- ((IMAPStore)store).releaseProtocol(this, null);
- }
- protocol = null;
- }
- }
-
- /**
- * Issue a noop command for the connection if the connection has not been
- * used in more than a second. If keepStoreAlive is true,
- * also issue a noop over the store's connection.
- *
- * ASSERT: This method must be called only when holding the
- * messageCacheLock
- */
- protected void keepConnectionAlive(boolean keepStoreAlive)
- throws ProtocolException {
-
- if (System.currentTimeMillis() - protocol.getTimestamp() > 1000) {
- waitIfIdle();
- if (protocol != null)
- protocol.noop();
- }
-
- if (keepStoreAlive && ((IMAPStore)store).hasSeparateStoreConnection()) {
- IMAPProtocol p = null;
- try {
- p = ((IMAPStore)store).getFolderStoreProtocol();
- if (System.currentTimeMillis() - p.getTimestamp() > 1000)
- p.noop();
- } finally {
- ((IMAPStore)store).releaseFolderStoreProtocol(p);
- }
- }
- }
-
- /**
- * Get the message object for the given sequence number. If
- * none found, null is returned.
- *
- * ASSERT: This method must be called only when holding the
- * messageCacheLock
- */
- protected IMAPMessage getMessageBySeqNumber(int seqnum) {
- return messageCache.getMessageBySeqnum(seqnum);
- }
-
- private boolean isDirectory() {
- return ((type & HOLDS_FOLDERS) != 0);
- }
-}
-
-/**
- * An object that holds a Message object
- * and reports its size and writes it to another OutputStream
- * on demand. Used by appendMessages to avoid the need to
- * buffer the entire message in memory in a single byte array
- * before sending it to the server.
- */
-class MessageLiteral implements Literal {
- private Message msg;
- private int msgSize = -1;
- private byte[] buf; // the buffered message, if not null
-
- public MessageLiteral(Message msg, int maxsize)
- throws MessagingException, IOException {
- this.msg = msg;
- // compute the size here so exceptions can be returned immediately
- LengthCounter lc = new LengthCounter(maxsize);
- OutputStream os = new CRLFOutputStream(lc);
- msg.writeTo(os);
- os.flush();
- msgSize = lc.getSize();
- buf = lc.getBytes();
- }
-
- public int size() {
- return msgSize;
- }
-
- public void writeTo(OutputStream os) throws IOException {
- // the message should not change between the constructor and this call
- try {
- if (buf != null)
- os.write(buf, 0, msgSize);
- else {
- os = new CRLFOutputStream(os);
- msg.writeTo(os);
- }
- } catch (MessagingException mex) {
- // exceptions here are bad, "should" never happen
- throw new IOException("MessagingException while appending message: "
- + mex);
- }
- }
-}
-
-/**
- * Count the number of bytes written to the stream.
- * Also, save a copy of small messages to avoid having to process
- * the data again.
- */
-class LengthCounter extends OutputStream {
- private int size = 0;
- private byte[] buf;
- private int maxsize;
-
- public LengthCounter(int maxsize) {
- buf = new byte[8192];
- this.maxsize = maxsize;
- }
-
- public void write(int b) {
- int newsize = size + 1;
- if (buf != null) {
- if (newsize > maxsize && maxsize >= 0) {
- buf = null;
- } else if (newsize > buf.length) {
- byte newbuf[] = new byte[Math.max(buf.length << 1, newsize)];
- System.arraycopy(buf, 0, newbuf, 0, size);
- buf = newbuf;
- buf[size] = (byte)b;
- } else {
- buf[size] = (byte)b;
- }
- }
- size = newsize;
- }
-
- public void write(byte b[], int off, int len) {
- if ((off < 0) || (off > b.length) || (len < 0) ||
- ((off + len) > b.length) || ((off + len) < 0)) {
- throw new IndexOutOfBoundsException();
- } else if (len == 0) {
- return;
- }
- int newsize = size + len;
- if (buf != null) {
- if (newsize > maxsize && maxsize >= 0) {
- buf = null;
- } else if (newsize > buf.length) {
- byte newbuf[] = new byte[Math.max(buf.length << 1, newsize)];
- System.arraycopy(buf, 0, newbuf, 0, size);
- buf = newbuf;
- System.arraycopy(b, off, buf, size, len);
- } else {
- System.arraycopy(b, off, buf, size, len);
- }
- }
- size = newsize;
- }
-
- public void write(byte[] b) throws IOException {
- write(b, 0, b.length);
- }
-
- public int getSize() {
- return size;
- }
-
- public byte[] getBytes() {
- return buf;
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/IMAPInputStream.java b/src/main/java/com/sun/mail/imap/IMAPInputStream.java
deleted file mode 100644
index e44ef11f..00000000
--- a/src/main/java/com/sun/mail/imap/IMAPInputStream.java
+++ /dev/null
@@ -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 -1 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 len bytes of data from this
- * input stream into the given buffer.
- *
- * Returns the total number of bytes read into the buffer,
- * or -1 if there is no more data.
- *
- * 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 b.length bytes of data from this input
- * stream into an array of bytes.
- *
- * Returns the total number of bytes read into the buffer, or
- * -1 is there is no more data.
- *
- * 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
- }
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/IMAPMessage.java b/src/main/java/com/sun/mail/imap/IMAPMessage.java
deleted file mode 100644
index f3233b49..00000000
--- a/src/main/java/com/sun/mail/imap/IMAPMessage.java
+++ /dev/null
@@ -1,1468 +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.util.Date;
-import java.io.*;
-import java.util.*;
-
-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.*;
-
-/**
- * This class implements an IMAPMessage object.
- *
- * An IMAPMessage object starts out as a light-weight object. It gets
- * filled-in incrementally when a request is made for some item. Or
- * when a prefetch is done using the FetchProfile.
- *
- * An IMAPMessage has a messageNumber and a sequenceNumber. The
- * messageNumber is its index into its containing folder's messageCache.
- * The sequenceNumber is its IMAP sequence-number.
- *
- * @author John Mani
- * @author Bill Shannon
- */
-/*
- * The lock hierarchy is that the lock on the IMAPMessage object, if
- * it's acquired at all, must be acquired before the message cache lock.
- * The IMAPMessage lock protects the message flags, sort of.
- *
- * XXX - I'm not convinced that all fields of IMAPMessage are properly
- * protected by locks.
- */
-
-public class IMAPMessage extends MimeMessage implements ReadableMime {
- protected BODYSTRUCTURE bs; // BODYSTRUCTURE
- protected ENVELOPE envelope; // ENVELOPE
-
- /**
- * A map of the extension FETCH items. In addition to saving the
- * data in this map, an entry in this map indicates that we *have*
- * the data, and so it doesn't need to be fetched again. The map
- * is created only when needed, to avoid significantly increasing
- * the effective size of an IMAPMessage object.
- *
- * @since JavaMail 1.4.6
- */
- protected Map items; // Map
-
- private Date receivedDate; // INTERNALDATE
- private int size = -1; // RFC822.SIZE
-
- private boolean peek; // use BODY.PEEK when fetching content?
-
- // this message's IMAP UID
- private long uid = -1;
-
- // this message's IMAP sectionId (null for toplevel message,
- // non-null for a nested message)
- protected String sectionId;
-
- // processed values
- private String type; // Content-Type (with params)
- private String subject; // decoded (Unicode) subject
- private String description; // decoded (Unicode) desc
-
- // Indicates that we've loaded *all* headers for this message
- private volatile boolean headersLoaded = false;
-
- /* Hashtable of names of headers we've loaded from the server.
- * Used in isHeaderLoaded() and getHeaderLoaded() to keep track
- * of those headers we've attempted to load from the server. We
- * need this table of names to avoid multiple attempts at loading
- * headers that don't exist for a particular message.
- *
- * Could this somehow be included in the InternetHeaders object ??
- */
- private Hashtable loadedHeaders = new Hashtable(1);
-
- // This is our Envelope
- static final String EnvelopeCmd = "ENVELOPE INTERNALDATE RFC822.SIZE";
-
- /**
- * Constructor.
- */
- protected IMAPMessage(IMAPFolder folder, int msgnum) {
- super(folder, msgnum);
- flags = null;
- }
-
- /**
- * Constructor, for use by IMAPNestedMessage.
- */
- protected IMAPMessage(Session session) {
- super(session);
- }
-
- /**
- * Get this message's folder's protocol connection.
- * Throws FolderClosedException, if the protocol connection
- * is not available.
- *
- * ASSERT: Must hold the messageCacheLock.
- */
- protected IMAPProtocol getProtocol()
- throws ProtocolException, FolderClosedException {
- ((IMAPFolder)folder).waitIfIdle();
- IMAPProtocol p = ((IMAPFolder)folder).protocol;
- if (p == null)
- throw new FolderClosedException(folder);
- else
- return p;
- }
-
- /*
- * Is this an IMAP4 REV1 server?
- */
- protected boolean isREV1() throws FolderClosedException {
- // access the folder's protocol object without waiting
- // for IDLE to complete
- IMAPProtocol p = ((IMAPFolder)folder).protocol;
- if (p == null)
- throw new FolderClosedException(folder);
- else
- return p.isREV1();
- }
-
- /**
- * Get the messageCacheLock, associated with this Message's
- * Folder.
- */
- protected Object getMessageCacheLock() {
- return ((IMAPFolder)folder).messageCacheLock;
- }
-
- /**
- * Get this message's IMAP sequence number.
- *
- * ASSERT: This method must be called only when holding the
- * messageCacheLock.
- */
- protected int getSequenceNumber() {
- return ((IMAPFolder)folder).messageCache.seqnumOf(getMessageNumber());
- }
-
- /**
- * Wrapper around the protected method Message.setMessageNumber() to
- * make that method accessible to IMAPFolder.
- */
- protected void setMessageNumber(int msgnum) {
- super.setMessageNumber(msgnum);
- }
-
- protected long getUID() {
- return uid;
- }
-
- protected void setUID(long uid) {
- this.uid = uid;
- }
-
- // expose to MessageCache
- protected void setExpunged(boolean set) {
- super.setExpunged(set);
- }
-
- // Convenience routine
- protected void checkExpunged() throws MessageRemovedException {
- if (expunged)
- throw new MessageRemovedException();
- }
-
- /**
- * Do a NOOP to force any untagged EXPUNGE responses
- * and then check if this message is expunged.
- */
- protected void forceCheckExpunged()
- throws MessageRemovedException, FolderClosedException {
- synchronized (getMessageCacheLock()) {
- try {
- getProtocol().noop();
- } catch (ConnectionException cex) {
- throw new FolderClosedException(folder, cex.getMessage());
- } catch (ProtocolException pex) {
- // ignore it
- }
- }
- if (expunged)
- throw new MessageRemovedException();
- }
-
- // Return the block size for FETCH requests
- // MUST be overridden by IMAPNestedMessage
- protected int getFetchBlockSize() {
- return ((IMAPStore)folder.getStore()).getFetchBlockSize();
- }
-
- // Return the block size for FETCH requests
- // MUST be overridden by IMAPNestedMessage
- protected boolean ignoreBodyStructureSize() {
- return ((IMAPStore)folder.getStore()).ignoreBodyStructureSize();
- }
-
- /**
- * Get the "From" attribute.
- */
- public Address[] getFrom() throws MessagingException {
- checkExpunged();
- loadEnvelope();
- InternetAddress[] a = envelope.from;
- /*
- * Per RFC 2822, the From header is required, and thus the IMAP
- * spec also requires that it be present, but we know that in
- * practice it is often missing. Some servers fill in the
- * From field with the Sender field in this case, but at least
- * Exchange 2007 does not. Use the same fallback strategy used
- * by MimeMessage.
- */
- if (a == null || a.length == 0)
- a = envelope.sender;
- return aaclone(a);
- }
-
- public void setFrom(Address address) throws MessagingException {
- throw new IllegalWriteException("IMAPMessage is read-only");
- }
-
- public void addFrom(Address[] addresses) throws MessagingException {
- throw new IllegalWriteException("IMAPMessage is read-only");
- }
-
- /**
- * Get the "Sender" attribute.
- */
- public Address getSender() throws MessagingException {
- checkExpunged();
- loadEnvelope();
- if (envelope.sender != null)
- return (envelope.sender)[0]; // there can be only one sender
- else
- return null;
- }
-
-
- public void setSender(Address address) throws MessagingException {
- throw new IllegalWriteException("IMAPMessage is read-only");
- }
-
- /**
- * Get the desired Recipient type.
- */
- public Address[] getRecipients(Message.RecipientType type)
- throws MessagingException {
- checkExpunged();
- loadEnvelope();
-
- if (type == Message.RecipientType.TO)
- return aaclone(envelope.to);
- else if (type == Message.RecipientType.CC)
- return aaclone(envelope.cc);
- else if (type == Message.RecipientType.BCC)
- return aaclone(envelope.bcc);
- else
- return super.getRecipients(type);
- }
-
- public void setRecipients(Message.RecipientType type, Address[] addresses)
- throws MessagingException {
- throw new IllegalWriteException("IMAPMessage is read-only");
- }
-
- public void addRecipients(Message.RecipientType type, Address[] addresses)
- throws MessagingException {
- throw new IllegalWriteException("IMAPMessage is read-only");
- }
-
- /**
- * Get the ReplyTo addresses.
- */
- public Address[] getReplyTo() throws MessagingException {
- checkExpunged();
- loadEnvelope();
- /*
- * The IMAP spec requires that the Reply-To field never be
- * null, but at least Exchange 2007 fails to fill it in in
- * some cases. Use the same fallback strategy used by
- * MimeMessage.
- */
- if (envelope.replyTo == null || envelope.replyTo.length == 0)
- return getFrom();
- return aaclone(envelope.replyTo);
- }
-
- public void setReplyTo(Address[] addresses) throws MessagingException {
- throw new IllegalWriteException("IMAPMessage is read-only");
- }
-
- /**
- * Get the decoded subject.
- */
- public String getSubject() throws MessagingException {
- checkExpunged();
-
- if (subject != null) // already cached ?
- return subject;
-
- loadEnvelope();
- if (envelope.subject == null) // no subject
- return null;
-
- // Cache and return the decoded value.
- try {
- // The server *should* unfold the value, but just in case it
- // doesn't we unfold it here.
- subject =
- MimeUtility.decodeText(MimeUtility.unfold(envelope.subject));
- } catch (UnsupportedEncodingException ex) {
- subject = envelope.subject;
- }
-
- return subject;
- }
-
- public void setSubject(String subject, String charset)
- throws MessagingException {
- throw new IllegalWriteException("IMAPMessage is read-only");
- }
-
- /**
- * Get the SentDate.
- */
- public Date getSentDate() throws MessagingException {
- checkExpunged();
- loadEnvelope();
- if (envelope.date == null)
- return null;
- else
- return new Date(envelope.date.getTime());
- }
-
- public void setSentDate(Date d) throws MessagingException {
- throw new IllegalWriteException("IMAPMessage is read-only");
- }
-
- /**
- * Get the recieved date (INTERNALDATE)
- */
- public Date getReceivedDate() throws MessagingException {
- checkExpunged();
- loadEnvelope();
- if (receivedDate == null)
- return null;
- else
- return new Date(receivedDate.getTime());
- }
-
- /**
- * Get the message size.
- *
- * Note that this returns RFC822.SIZE. That is, it's the
- * size of the whole message, header and body included.
- */
- public int getSize() throws MessagingException {
- checkExpunged();
- if (size == -1)
- loadEnvelope(); // XXX - could just fetch the size
- return size;
- }
-
- /**
- * Get the total number of lines.
- *
- * Returns the "body_fld_lines" field from the
- * BODYSTRUCTURE. Note that this field is available
- * only for text/plain and message/rfc822 types
- */
- public int getLineCount() throws MessagingException {
- checkExpunged();
- loadBODYSTRUCTURE();
- return bs.lines;
- }
-
- /**
- * Get the content language.
- */
- public String[] getContentLanguage() throws MessagingException {
- checkExpunged();
- loadBODYSTRUCTURE();
- if (bs.language != null)
- return (String[])(bs.language).clone();
- else
- return null;
- }
-
- public void setContentLanguage(String[] languages)
- throws MessagingException {
- throw new IllegalWriteException("IMAPMessage is read-only");
- }
-
- /**
- * Get the In-Reply-To header.
- *
- * @since JavaMail 1.3.3
- */
- public String getInReplyTo() throws MessagingException {
- checkExpunged();
- loadEnvelope();
- return envelope.inReplyTo;
- }
-
- /**
- * Get the Content-Type.
- *
- * Generate this header from the BODYSTRUCTURE. Append parameters
- * as well.
- */
- public synchronized String getContentType() throws MessagingException {
- checkExpunged();
-
- // If we haven't cached the type yet ..
- if (type == null) {
- loadBODYSTRUCTURE();
- // generate content-type from BODYSTRUCTURE
- ContentType ct = new ContentType(bs.type, bs.subtype, bs.cParams);
- type = ct.toString();
- }
- return type;
- }
-
- /**
- * Get the Content-Disposition.
- */
- public String getDisposition() throws MessagingException {
- checkExpunged();
- loadBODYSTRUCTURE();
- return bs.disposition;
- }
-
- public void setDisposition(String disposition) throws MessagingException {
- throw new IllegalWriteException("IMAPMessage is read-only");
- }
-
- /**
- * Get the Content-Transfer-Encoding.
- */
- public String getEncoding() throws MessagingException {
- checkExpunged();
- loadBODYSTRUCTURE();
- return bs.encoding;
- }
-
- /**
- * Get the Content-ID.
- */
- public String getContentID() throws MessagingException {
- checkExpunged();
- loadBODYSTRUCTURE();
- return bs.id;
- }
-
- public void setContentID(String cid) throws MessagingException {
- throw new IllegalWriteException("IMAPMessage is read-only");
- }
-
- /**
- * Get the Content-MD5.
- */
- public String getContentMD5() throws MessagingException {
- checkExpunged();
- loadBODYSTRUCTURE();
- return bs.md5;
- }
-
- public void setContentMD5(String md5) throws MessagingException {
- throw new IllegalWriteException("IMAPMessage is read-only");
- }
-
- /**
- * Get the decoded Content-Description.
- */
- public String getDescription() throws MessagingException {
- checkExpunged();
-
- if (description != null) // cached value ?
- return description;
-
- loadBODYSTRUCTURE();
- 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("IMAPMessage is read-only");
- }
-
- /**
- * Get the Message-ID.
- */
- public String getMessageID() throws MessagingException {
- checkExpunged();
- loadEnvelope();
- return envelope.messageId;
- }
-
- /**
- * Get the "filename" Disposition parameter. (Only available in
- * IMAP4rev1). If thats not available, get the "name" ContentType
- * parameter.
- */
- public String getFileName() throws MessagingException {
- checkExpunged();
-
- String filename = null;
- loadBODYSTRUCTURE();
-
- if (bs.dParams != null)
- filename = bs.dParams.get("filename");
- if (filename == null && bs.cParams != null)
- filename = bs.cParams.get("name");
- return filename;
- }
-
- public void setFileName(String filename) throws MessagingException {
- throw new IllegalWriteException("IMAPMessage is read-only");
- }
-
- /**
- * Get all the bytes for this message. Overrides getContentStream()
- * in MimeMessage. This method is ultimately used by the DataHandler
- * to obtain the input stream for this message.
- *
- * @see javax.mail.internet.MimeMessage#getContentStream
- */
- protected InputStream getContentStream() throws MessagingException {
- InputStream is = null;
- boolean pk = getPeek(); // get before acquiring message cache lock
-
- // Acquire MessageCacheLock, to freeze seqnum.
- synchronized(getMessageCacheLock()) {
- try {
- IMAPProtocol p = getProtocol();
-
- // This message could be expunged when we were waiting
- // to acquire the lock ...
- checkExpunged();
-
- if (p.isREV1() && (getFetchBlockSize() != -1)) // IMAP4rev1
- return new IMAPInputStream(this, toSection("TEXT"),
- bs != null && !ignoreBodyStructureSize() ?
- bs.size : -1, pk);
-
- if (p.isREV1()) {
- BODY b;
- if (pk)
- b = p.peekBody(getSequenceNumber(), toSection("TEXT"));
- else
- b = p.fetchBody(getSequenceNumber(), toSection("TEXT"));
- if (b != null)
- is = b.getByteArrayInputStream();
- } else {
- RFC822DATA rd = p.fetchRFC822(getSequenceNumber(), "TEXT");
- if (rd != null)
- is = rd.getByteArrayInputStream();
- }
- } catch (ConnectionException cex) {
- throw new FolderClosedException(folder, cex.getMessage());
- } catch (ProtocolException pex) {
- forceCheckExpunged();
- throw new MessagingException(pex.getMessage(), pex);
- }
- }
-
- if (is == null)
- throw new MessagingException("No content");
- else
- return is;
- }
-
- /**
- * Get the DataHandler object for this message.
- */
- public synchronized DataHandler getDataHandler()
- throws MessagingException {
- checkExpunged();
-
- if (dh == null) {
- loadBODYSTRUCTURE();
- if (type == null) { // type not yet computed
- // generate content-type from BODYSTRUCTURE
- ContentType ct = new ContentType(bs.type, bs.subtype,
- bs.cParams);
- type = ct.toString();
- }
-
- /* Special-case Multipart and Nested content. All other
- * cases are handled by the superclass.
- */
- if (bs.isMulti())
- dh = new DataHandler(
- new IMAPMultipartDataSource(this, bs.bodies,
- sectionId, this)
- );
- else if (bs.isNested() && isREV1() && bs.envelope != null)
- /* Nested messages are handled specially only for
- * IMAP4rev1. IMAP4 doesn't provide enough support to
- * FETCH the components of nested messages
- */
- dh = new DataHandler(
- new IMAPNestedMessage(this,
- bs.bodies[0],
- bs.envelope,
- sectionId == null ? "1" : sectionId + ".1"),
- type
- );
- }
-
- return super.getDataHandler();
- }
-
- public void setDataHandler(DataHandler content)
- throws MessagingException {
- throw new IllegalWriteException("IMAPMessage is read-only");
- }
-
- /**
- * Return the MIME format stream corresponding to this message.
- *
- * @return the MIME format stream
- * @since JavaMail 1.4.5
- */
- public InputStream getMimeStream() throws MessagingException {
- InputStream is = null;
- boolean pk = getPeek(); // get before acquiring message cache lock
-
- // Acquire MessageCacheLock, to freeze seqnum.
- synchronized(getMessageCacheLock()) {
- try {
- IMAPProtocol p = getProtocol();
-
- checkExpunged(); // insure this message is not expunged
-
- if (p.isREV1() && (getFetchBlockSize() != -1)) // IMAP4rev1
- return new IMAPInputStream(this, sectionId, -1, pk);
-
- if (p.isREV1()) {
- BODY b;
- if (pk)
- b = p.peekBody(getSequenceNumber(), sectionId);
- else
- b = p.fetchBody(getSequenceNumber(), sectionId);
- if (b != null)
- is = b.getByteArrayInputStream();
- } else {
- RFC822DATA rd = p.fetchRFC822(getSequenceNumber(), null);
- if (rd != null)
- is = rd.getByteArrayInputStream();
- }
- } catch (ConnectionException cex) {
- throw new FolderClosedException(folder, cex.getMessage());
- } catch (ProtocolException pex) {
- forceCheckExpunged();
- throw new MessagingException(pex.getMessage(), pex);
- }
- }
-
- if (is == null) {
- forceCheckExpunged(); // may throw MessageRemovedException
- // nope, the server doesn't think it's expunged,
- // something else is wrong
- throw new MessagingException("No content");
- }
- return is;
- }
-
- /**
- * Write out the bytes into the given OutputStream.
- */
- public void writeTo(OutputStream os)
- throws IOException, MessagingException {
- InputStream is = getMimeStream();
- try {
- // write out the bytes
- byte[] bytes = new byte[16*1024];
- int count;
- while ((count = is.read(bytes)) != -1)
- os.write(bytes, 0, count);
- } finally {
- is.close();
- }
- }
-
- /**
- * Get the named header.
- */
- public String[] getHeader(String name) throws MessagingException {
- checkExpunged();
-
- if (isHeaderLoaded(name)) // already loaded ?
- return headers.getHeader(name);
-
- // Load this particular header
- InputStream is = null;
-
- // Acquire MessageCacheLock, to freeze seqnum.
- synchronized(getMessageCacheLock()) {
- try {
- IMAPProtocol p = getProtocol();
-
- // This message could be expunged when we were waiting
- // to acquire the lock ...
- checkExpunged();
-
- if (p.isREV1()) {
- BODY b = p.peekBody(getSequenceNumber(),
- toSection("HEADER.FIELDS (" + name + ")")
- );
- if (b != null)
- is = b.getByteArrayInputStream();
- } else {
- RFC822DATA rd = p.fetchRFC822(getSequenceNumber(),
- "HEADER.LINES (" + name + ")");
- if (rd != null)
- is = rd.getByteArrayInputStream();
- }
- } catch (ConnectionException cex) {
- throw new FolderClosedException(folder, cex.getMessage());
- } catch (ProtocolException pex) {
- forceCheckExpunged();
- throw new MessagingException(pex.getMessage(), pex);
- }
- }
-
- // if we get this far without "is" being set, something has gone
- // wrong; prevent a later NullPointerException and return null here
- if (is == null)
- return null;
-
- if (headers == null)
- headers = new InternetHeaders();
- headers.load(is); // load this header into the Headers object.
- setHeaderLoaded(name); // Mark this header as loaded
-
- return headers.getHeader(name);
- }
-
- /**
- * Get the named header.
- */
- public String getHeader(String name, String delimiter)
- throws MessagingException {
- checkExpunged();
-
- // force the header to be loaded by invoking getHeader(name)
- if (getHeader(name) == null)
- return null;
- return headers.getHeader(name, delimiter);
- }
-
- public void setHeader(String name, String value)
- throws MessagingException {
- throw new IllegalWriteException("IMAPMessage is read-only");
- }
-
- public void addHeader(String name, String value)
- throws MessagingException {
- throw new IllegalWriteException("IMAPMessage is read-only");
- }
-
- public void removeHeader(String name)
- throws MessagingException {
- throw new IllegalWriteException("IMAPMessage is read-only");
- }
-
- /**
- * Get all headers.
- */
- public Enumeration getAllHeaders() throws MessagingException {
- checkExpunged();
- loadHeaders();
- return super.getAllHeaders();
- }
-
- /**
- * Get matching headers.
- */
- public Enumeration getMatchingHeaders(String[] names)
- throws MessagingException {
- checkExpunged();
- loadHeaders();
- return super.getMatchingHeaders(names);
- }
-
- /**
- * Get non-matching headers.
- */
- public Enumeration getNonMatchingHeaders(String[] names)
- throws MessagingException {
- checkExpunged();
- loadHeaders();
- return super.getNonMatchingHeaders(names);
- }
-
- public void addHeaderLine(String line) throws MessagingException {
- throw new IllegalWriteException("IMAPMessage is read-only");
- }
-
- /**
- * Get all header-lines.
- */
- public Enumeration getAllHeaderLines() throws MessagingException {
- checkExpunged();
- loadHeaders();
- return super.getAllHeaderLines();
- }
-
- /**
- * Get all matching header-lines.
- */
- public Enumeration getMatchingHeaderLines(String[] names)
- throws MessagingException {
- checkExpunged();
- loadHeaders();
- return super.getMatchingHeaderLines(names);
- }
-
- /**
- * Get all non-matching headerlines.
- */
- public Enumeration getNonMatchingHeaderLines(String[] names)
- throws MessagingException {
- checkExpunged();
- loadHeaders();
- return super.getNonMatchingHeaderLines(names);
- }
-
- /**
- * Get the Flags for this message.
- */
- public synchronized Flags getFlags() throws MessagingException {
- checkExpunged();
- loadFlags();
- return super.getFlags();
- }
-
- /**
- * Test if the given Flags are set in this message.
- */
- public synchronized boolean isSet(Flags.Flag flag)
- throws MessagingException {
- checkExpunged();
- loadFlags();
- return super.isSet(flag);
- }
-
- /**
- * Set/Unset the given flags in this message.
- */
- public synchronized void setFlags(Flags flag, boolean set)
- throws MessagingException {
- // Acquire MessageCacheLock, to freeze seqnum.
- synchronized(getMessageCacheLock()) {
- try {
- IMAPProtocol p = getProtocol();
- checkExpunged(); // Insure that this message is not expunged
- p.storeFlags(getSequenceNumber(), flag, set);
- } catch (ConnectionException cex) {
- throw new FolderClosedException(folder, cex.getMessage());
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- }
- }
- }
-
- /**
- * Set whether or not to use the PEEK variant of FETCH when
- * fetching message content.
- *
- * @since JavaMail 1.3.3
- */
- public synchronized void setPeek(boolean peek) {
- this.peek = peek;
- }
-
- /**
- * Get whether or not to use the PEEK variant of FETCH when
- * fetching message content.
- *
- * @since JavaMail 1.3.3
- */
- public synchronized boolean getPeek() {
- return peek;
- }
-
- /**
- * Invalidate cached header and envelope information for this
- * message. Subsequent accesses of this information will
- * cause it to be fetched from the server.
- *
- * @since JavaMail 1.3.3
- */
- public synchronized void invalidateHeaders() {
- headersLoaded = false;
- loadedHeaders.clear();
- headers = null;
- envelope = null;
- bs = null;
- receivedDate = null;
- size = -1;
- type = null;
- subject = null;
- description = null;
- flags = null;
- }
-
- /**
- * This class implements the test to be done on each
- * message in the folder. The test is to check whether the
- * message has already cached all the items requested in the
- * FetchProfile. If any item is missing, the test succeeds and
- * breaks out.
- */
- public static class FetchProfileCondition implements Utility.Condition {
- private boolean needEnvelope = false;
- private boolean needFlags = false;
- private boolean needBodyStructure = false;
- private boolean needUID = false;
- private boolean needHeaders = false;
- private boolean needSize = false;
- private String[] hdrs = null;
- private Set need = new HashSet(); // Set
-
- /**
- * Create a FetchProfileCondition to determine if we need to fetch
- * any of the information specified in the FetchProfile.
- */
- public FetchProfileCondition(FetchProfile fp, FetchItem[] fitems) {
- if (fp.contains(FetchProfile.Item.ENVELOPE))
- needEnvelope = true;
- if (fp.contains(FetchProfile.Item.FLAGS))
- needFlags = true;
- if (fp.contains(FetchProfile.Item.CONTENT_INFO))
- needBodyStructure = true;
- if (fp.contains(FetchProfile.Item.SIZE))
- needSize = true;
- if (fp.contains(UIDFolder.FetchProfileItem.UID))
- needUID = true;
- if (fp.contains(IMAPFolder.FetchProfileItem.HEADERS))
- needHeaders = true;
- if (fp.contains(IMAPFolder.FetchProfileItem.SIZE))
- needSize = true;
- hdrs = fp.getHeaderNames();
- for (int i = 0; i < fitems.length; i++) {
- if (fp.contains(fitems[i].getFetchProfileItem()))
- need.add(fitems[i]);
- }
- }
-
- /**
- * Return true if we NEED to fetch the requested information
- * for the specified message.
- */
- public boolean test(IMAPMessage m) {
- if (needEnvelope && m._getEnvelope() == null)
- return true; // no envelope
- if (needFlags && m._getFlags() == null)
- return true; // no flags
- if (needBodyStructure && m._getBodyStructure() == null)
- return true; // no BODYSTRUCTURE
- if (needUID && m.getUID() == -1) // no UID
- return true;
- if (needHeaders && !m.areHeadersLoaded()) // no headers
- return true;
- if (needSize && m.size == -1) // no size
- return true;
-
- // Is the desired header present ?
- for (int i = 0; i < hdrs.length; i++) {
- if (!m.isHeaderLoaded(hdrs[i]))
- return true; // Nope, return
- }
- Iterator it = need.iterator();
- while (it.hasNext()) {
- FetchItem fitem = (FetchItem)it.next();
- if (m.items == null || m.items.get(fitem.getName()) == null)
- return true;
- }
-
- return false;
- }
- }
-
- /**
- * Apply the data in the FETCH item to this message.
- *
- * ASSERT: Must hold the messageCacheLock.
- *
- * @since JavaMail 1.4.6
- */
- protected boolean handleFetchItem(Item item,
- String[] hdrs, boolean allHeaders)
- throws MessagingException {
- // Check for the FLAGS item
- if (item instanceof Flags)
- flags = (Flags)item;
- // Check for ENVELOPE items
- else if (item instanceof ENVELOPE)
- envelope = (ENVELOPE)item;
- else if (item instanceof INTERNALDATE)
- receivedDate = ((INTERNALDATE)item).getDate();
- else if (item instanceof RFC822SIZE)
- size = ((RFC822SIZE)item).size;
-
- // Check for the BODYSTRUCTURE item
- else if (item instanceof BODYSTRUCTURE)
- bs = (BODYSTRUCTURE)item;
- // Check for the UID item
- else if (item instanceof UID) {
- UID u = (UID)item;
- uid = u.uid; // set uid
- // add entry into uid table
- if (((IMAPFolder)folder).uidTable == null)
- ((IMAPFolder)folder).uidTable = new Hashtable();
- ((IMAPFolder)folder).uidTable.put(new Long(u.uid), this);
- }
-
- // Check for header items
- else if (item instanceof RFC822DATA ||
- item instanceof BODY) {
- InputStream headerStream;
- if (item instanceof RFC822DATA) // IMAP4
- headerStream =
- ((RFC822DATA)item).getByteArrayInputStream();
- else // IMAP4rev1
- headerStream =
- ((BODY)item).getByteArrayInputStream();
-
- // Load the obtained headers.
- InternetHeaders h = new InternetHeaders();
- // Some IMAP servers (e.g., gmx.net) return NIL
- // instead of a string just containing a CR/LF
- // when the header list is empty.
- if (headerStream != null)
- h.load(headerStream);
- if (headers == null || allHeaders)
- headers = h;
- else {
- /*
- * This is really painful. A second fetch
- * of the same headers (which might occur because
- * a new header was added to the set requested)
- * will return headers we already know about.
- * In this case, only load the headers we haven't
- * seen before to avoid adding duplicates of
- * headers we already have.
- *
- * XXX - There's a race condition here if another
- * thread is reading headers in the same message
- * object, because InternetHeaders is not thread
- * safe.
- */
- Enumeration e = h.getAllHeaders();
- while (e.hasMoreElements()) {
- Header he = (Header)e.nextElement();
- if (!isHeaderLoaded(he.getName()))
- headers.addHeader(
- he.getName(), he.getValue());
- }
- }
-
- // if we asked for all headers, assume we got them
- if (allHeaders)
- setHeadersLoaded(true);
- else {
- // Mark all headers we asked for as 'loaded'
- for (int k = 0; k < hdrs.length; k++)
- setHeaderLoaded(hdrs[k]);
- }
- } else
- return false; // not handled
- return true; // something above handled it
- }
-
- /**
- * Apply the data in the extension FETCH items to this message.
- * This method adds all the items to the items map.
- * Subclasses may override this method to call super and then
- * also copy the data to a more convenient form.
- *
- * ASSERT: Must hold the messageCacheLock.
- *
- * @since JavaMail 1.4.6
- */
- protected void handleExtensionFetchItems(Map extensionItems)
- throws MessagingException {
- if (items == null)
- items = extensionItems;
- else
- items.putAll(extensionItems);
- }
-
- /**
- * Fetch an individual item for the current message.
- * Note that handleExtensionFetchItems will have been called
- * to store this item in the message before this method
- * returns.
- *
- * @since JavaMail 1.4.6
- */
- protected Object fetchItem(FetchItem fitem)
- throws MessagingException {
-
- // Acquire MessageCacheLock, to freeze seqnum.
- synchronized(getMessageCacheLock()) {
- Object robj = null;
-
- try {
- IMAPProtocol p = getProtocol();
-
- checkExpunged(); // Insure that this message is not expunged
-
- int seqnum = getSequenceNumber();
- Response[] r = p.fetch(seqnum, fitem.getName());
-
- for (int i = 0; i < r.length; i++) {
- // If this response is NOT a FetchResponse or if it does
- // not match our seqnum, skip.
- if (r[i] == null ||
- !(r[i] instanceof FetchResponse) ||
- ((FetchResponse)r[i]).getNumber() != seqnum)
- continue;
-
- FetchResponse f = (FetchResponse)r[i];
- Object o = f.getExtensionItems().get(fitem.getName());
- if (o != null)
- robj = o;
- }
-
- // ((IMAPFolder)folder).handleResponses(r);
- p.notifyResponseHandlers(r);
- p.handleResult(r[r.length - 1]);
- } catch (ConnectionException cex) {
- throw new FolderClosedException(folder, cex.getMessage());
- } catch (ProtocolException pex) {
- forceCheckExpunged();
- throw new MessagingException(pex.getMessage(), pex);
- }
- return robj;
-
- } // Release MessageCacheLock
- }
-
- /**
- * Return the data associated with the FetchItem.
- * If the data hasn't been fetched, call the fetchItem
- * method to fetch it. Returns null if there is no
- * data for the FetchItem.
- *
- * @since JavaMail 1.4.6
- */
- public synchronized Object getItem(FetchItem fitem)
- throws MessagingException {
- Object item = items == null ? null : items.get(fitem.getName());
- if (item == null)
- item = fetchItem(fitem);
- return item;
- }
-
- /*
- * Load the Envelope for this message.
- */
- private synchronized void loadEnvelope() throws MessagingException {
- if (envelope != null) // already loaded
- return;
-
- Response[] r = null;
-
- // Acquire MessageCacheLock, to freeze seqnum.
- synchronized(getMessageCacheLock()) {
- try {
- IMAPProtocol p = getProtocol();
-
- checkExpunged(); // Insure that this message is not expunged
-
- int seqnum = getSequenceNumber();
- r = p.fetch(seqnum, EnvelopeCmd);
-
- for (int i = 0; i < r.length; i++) {
- // If this response is NOT a FetchResponse or if it does
- // not match our seqnum, skip.
- if (r[i] == null ||
- !(r[i] instanceof FetchResponse) ||
- ((FetchResponse)r[i]).getNumber() != seqnum)
- continue;
-
- FetchResponse f = (FetchResponse)r[i];
-
- // Look for the Envelope items.
- int count = f.getItemCount();
- for (int j = 0; j < count; j++) {
- Item item = f.getItem(j);
-
- if (item instanceof ENVELOPE)
- envelope = (ENVELOPE)item;
- else if (item instanceof INTERNALDATE)
- receivedDate = ((INTERNALDATE)item).getDate();
- else if (item instanceof RFC822SIZE)
- size = ((RFC822SIZE)item).size;
- }
- }
-
- // ((IMAPFolder)folder).handleResponses(r);
- p.notifyResponseHandlers(r);
- p.handleResult(r[r.length - 1]);
- } catch (ConnectionException cex) {
- throw new FolderClosedException(folder, cex.getMessage());
- } catch (ProtocolException pex) {
- forceCheckExpunged();
- throw new MessagingException(pex.getMessage(), pex);
- }
-
- } // Release MessageCacheLock
-
- if (envelope == null)
- throw new MessagingException("Failed to load IMAP envelope");
- }
-
- /*
- * Load the BODYSTRUCTURE
- */
- private synchronized void loadBODYSTRUCTURE()
- throws MessagingException {
- if (bs != null) // already loaded
- return;
-
- // Acquire MessageCacheLock, to freeze seqnum.
- synchronized(getMessageCacheLock()) {
- try {
- IMAPProtocol p = getProtocol();
-
- // This message could be expunged when we were waiting
- // to acquire the lock ...
- checkExpunged();
-
- bs = p.fetchBodyStructure(getSequenceNumber());
- } catch (ConnectionException cex) {
- throw new FolderClosedException(folder, cex.getMessage());
- } catch (ProtocolException pex) {
- forceCheckExpunged();
- throw new MessagingException(pex.getMessage(), pex);
- }
- if (bs == null) {
- // if the FETCH is successful, we should always get a
- // BODYSTRUCTURE, but some servers fail to return it
- // if the message has been expunged
- forceCheckExpunged();
- throw new MessagingException("Unable to load BODYSTRUCTURE");
- }
- }
- }
-
- /*
- * Load all headers.
- */
- private synchronized void loadHeaders() throws MessagingException {
- if (headersLoaded)
- return;
-
- InputStream is = null;
-
- // Acquire MessageCacheLock, to freeze seqnum.
- synchronized (getMessageCacheLock()) {
- try {
- IMAPProtocol p = getProtocol();
-
- // This message could be expunged when we were waiting
- // to acquire the lock ...
- checkExpunged();
-
- if (p.isREV1()) {
- BODY b = p.peekBody(getSequenceNumber(),
- toSection("HEADER"));
- if (b != null)
- is = b.getByteArrayInputStream();
- } else {
- RFC822DATA rd = p.fetchRFC822(getSequenceNumber(),
- "HEADER");
- if (rd != null)
- is = rd.getByteArrayInputStream();
- }
- } catch (ConnectionException cex) {
- throw new FolderClosedException(folder, cex.getMessage());
- } catch (ProtocolException pex) {
- forceCheckExpunged();
- throw new MessagingException(pex.getMessage(), pex);
- }
- } // Release MessageCacheLock
-
- if (is == null)
- throw new MessagingException("Cannot load header");
- headers = new InternetHeaders(is);
- headersLoaded = true;
- }
-
- /*
- * Load this message's Flags
- */
- private synchronized void loadFlags() throws MessagingException {
- if (flags != null)
- return;
-
- // Acquire MessageCacheLock, to freeze seqnum.
- synchronized(getMessageCacheLock()) {
- try {
- IMAPProtocol p = getProtocol();
-
- // This message could be expunged when we were waiting
- // to acquire the lock ...
- checkExpunged();
-
- flags = p.fetchFlags(getSequenceNumber());
- // make sure flags is always set, even if server is broken
- if (flags == null)
- flags = new Flags();
- } catch (ConnectionException cex) {
- throw new FolderClosedException(folder, cex.getMessage());
- } catch (ProtocolException pex) {
- forceCheckExpunged();
- throw new MessagingException(pex.getMessage(), pex);
- }
- } // Release MessageCacheLock
- }
-
- /*
- * Are all headers loaded?
- */
- private boolean areHeadersLoaded() {
- return headersLoaded;
- }
-
- /*
- * Set whether all headers are loaded.
- */
- private void setHeadersLoaded(boolean loaded) {
- headersLoaded = loaded;
- }
-
- /*
- * Check if the given header was ever loaded from the server
- */
- private boolean isHeaderLoaded(String name) {
- if (headersLoaded) // All headers for this message have been loaded
- return true;
-
- return loadedHeaders.containsKey(name.toUpperCase(Locale.ENGLISH));
- }
-
- /*
- * Mark that the given headers have been loaded from the server.
- */
- private void setHeaderLoaded(String name) {
- loadedHeaders.put(name.toUpperCase(Locale.ENGLISH), name);
- }
-
- /*
- * Convert the given FETCH item identifier to the approriate
- * section-string for this message.
- */
- private String toSection(String what) {
- if (sectionId == null)
- return what;
- else
- return sectionId + "." + what;
- }
-
- /*
- * Clone an array of InternetAddresses.
- */
- private InternetAddress[] aaclone(InternetAddress[] aa) {
- if (aa == null)
- return null;
- else
- return (InternetAddress[])aa.clone();
- }
-
- private Flags _getFlags() {
- return flags;
- }
-
- private ENVELOPE _getEnvelope() {
- return envelope;
- }
-
- private BODYSTRUCTURE _getBodyStructure() {
- return bs;
- }
-
- /***********************************************************
- * accessor routines to make available certain private/protected
- * fields to other classes in this package.
- ***********************************************************/
-
- /*
- * Called by IMAPFolder.
- * Must not be synchronized.
- */
- void _setFlags(Flags flags) {
- this.flags = flags;
- }
-
- /*
- * Called by IMAPNestedMessage.
- */
- Session _getSession() {
- return session;
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/IMAPMultipartDataSource.java b/src/main/java/com/sun/mail/imap/IMAPMultipartDataSource.java
deleted file mode 100644
index fdd80687..00000000
--- a/src/main/java/com/sun/mail/imap/IMAPMultipartDataSource.java
+++ /dev/null
@@ -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);
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/IMAPNestedMessage.java b/src/main/java/com/sun/mail/imap/IMAPNestedMessage.java
deleted file mode 100644
index 5d058a21..00000000
--- a/src/main/java/com/sun/mail/imap/IMAPNestedMessage.java
+++ /dev/null
@@ -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.
- *
- * 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");
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/IMAPSSLStore.java b/src/main/java/com/sun/mail/imap/IMAPSSLStore.java
deleted file mode 100644
index fdb2c25f..00000000
--- a/src/main/java/com/sun/mail/imap/IMAPSSLStore.java
+++ /dev/null
@@ -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.
- */
-
-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
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/IMAPStore.java b/src/main/java/com/sun/mail/imap/IMAPStore.java
deleted file mode 100644
index 77c2edd3..00000000
--- a/src/main/java/com/sun/mail/imap/IMAPStore.java
+++ /dev/null
@@ -1,1934 +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.lang.reflect.*;
-import java.util.Vector;
-import java.util.StringTokenizer;
-import java.io.PrintStream;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.logging.Level;
-
-import javax.mail.*;
-import javax.mail.event.*;
-
-import com.sun.mail.iap.*;
-import com.sun.mail.imap.protocol.*;
-import com.sun.mail.util.PropUtil;
-import com.sun.mail.util.MailLogger;
-import com.sun.mail.util.SocketConnectException;
-import com.sun.mail.util.MailConnectException;
-
-/**
- * This class provides access to an IMAP message store.
- *
- * Applications that need to make use of IMAP-specific features may cast
- * a Store object to an IMAPStore object and
- * use the methods on this class. The {@link #getQuota getQuota} and
- * {@link #setQuota setQuota} methods support the IMAP QUOTA extension.
- * Refer to RFC 2087
- * for more information.
- *
- * See the com.sun.mail.imap package
- * documentation for further information on the IMAP protocol provider.
- *
- * WARNING: The APIs unique to this class should be
- * considered EXPERIMENTAL. They may be changed in the
- * future in ways that are incompatible with applications using the
- * current APIs.
- *
- * @author John Mani
- * @author Bill Shannon
- * @author Jim Glennon
- */
-/*
- * This package is implemented over the "imap.protocol" package, which
- * implements the protocol-level commands.
- *
- * 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. The pool size can be configured by setting
- * the mail.imap.connectionpoolsize property.
- *
- * Note that all connections in the connection pool have their response
- * handler set to be the Store. When the connection is removed from the
- * pool for use by a folder, the response handler is removed and then set
- * to either the Folder or to the special nonStoreResponseHandler, depending
- * on how the connection is being used. This is probably excessive.
- * Better would be for the Protocol object to support only a single
- * response handler, which would be set before the connection is used
- * and cleared when the connection is in the pool and can't be used.
- *
- * 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. The time out interval can be configured via
- * the mail.imap.connectionpooltimeout property.
- *
- * 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 JavaMail and is determined by the value of the
- * mail.imap.separatestoreconnection property.
- *
- * An IMAPStore object provides closed IMAPFolder objects thru its list()
- * and listSubscribed() methods. A closed IMAPFolder object acquires an
- * IMAP protocol object from the store to communicate with the server. When
- * the folder is opened, it gets its own protocol object and thus its own,
- * separate connection to the server. The store maintains references to
- * all 'open' folders. When a folder is/gets closed, the store removes
- * it from its list. When the store is/gets closed, it closes all open
- * folders in its list, thus cleaning up all open connections to the
- * server.
- *
- * A mutex is used to control access to the connection pool resources.
- * Any time any of these resources need to be accessed, the following
- * convention should be followed:
- *
- * synchronized (pool) { // ACQUIRE LOCK
- * // access connection pool resources
- * } // RELEASE LOCK
- *
- * The locking relationship between the store and folders is that the
- * store lock must be acquired before a folder lock. This is currently only
- * applicable in the store's cleanup method. It's important that the
- * connection pool lock is not held when calling into folder objects.
- * The locking hierarchy is that a folder lock must be acquired before
- * any connection pool operations are performed. You never need to hold
- * all three locks, but if you hold more than one this is the order you
- * have to acquire them in.
- *
- * That is: Store > Folder, Folder > pool, Store > pool
- *
- * The IMAPStore implements the ResponseHandler interface and listens to
- * BYE or untagged OK-notification events from the server as a result of
- * Store operations. IMAPFolder forwards notifications that result from
- * Folder operations using the store connection; the IMAPStore ResponseHandler
- * is not used directly in this case.
- */
-
-public class IMAPStore extends Store
- implements QuotaAwareStore, ResponseHandler {
-
- /**
- * A special event type for a StoreEvent to indicate an IMAP
- * response, if the mail.imap.enableimapevents property is set.
- */
- public static final int RESPONSE = 1000;
-
- protected final String name; // name of this protocol
- protected final int defaultPort; // default IMAP port
- protected final boolean isSSL; // use SSL?
-
- private final int blksize; // Block size for data requested
- // in FETCH requests. Defaults to
- // 16K
-
- private boolean ignoreSize; // ignore the size in BODYSTRUCTURE?
-
- private final int statusCacheTimeout; // cache Status for 1 second
-
- private final int appendBufferSize; // max size of msg buffered for append
-
- private final int minIdleTime; // minimum idle time
-
- private volatile int port = -1; // port to use
-
- // Auth info
- protected String host;
- protected String user;
- protected String password;
- protected String proxyAuthUser;
- protected String authorizationID;
- protected String saslRealm;
-
- private Namespaces namespaces;
-
- private boolean disableAuthLogin = false; // disable AUTH=LOGIN
- private boolean disableAuthPlain = false; // disable AUTH=PLAIN
- private boolean disableAuthNtlm = false; // disable AUTH=NTLM
- private boolean enableStartTLS = false; // enable STARTTLS
- private boolean requireStartTLS = false; // require STARTTLS
- private boolean usingSSL = false; // using SSL?
- private boolean enableSASL = false; // enable SASL authentication
- private String[] saslMechanisms;
- private boolean forcePasswordRefresh = false;
- // enable notification of IMAP responses
- private boolean enableImapEvents = false;
- private String guid; // for Yahoo! Mail IMAP
-
- /*
- * This field is set in the Store's response handler if we see
- * a BYE response. The releaseStore method checks this field
- * and if set it cleans up the Store. Field is volatile because
- * there's no lock we consistently hold while manipulating it.
- *
- * Because volatile doesn't really work before JDK 1.5,
- * use a lock to protect these two fields.
- */
- private volatile boolean connectionFailed = false;
- private volatile boolean forceClose = false;
- private final Object connectionFailedLock = new Object();
-
- private boolean debugusername; // include username in debug output?
- private boolean debugpassword; // include password in debug output?
- protected MailLogger logger; // for debug output
-
- private boolean messageCacheDebug;
-
- // constructors for IMAPFolder class provided by user
- private volatile Constructor folderConstructor = null;
- private volatile Constructor folderConstructorLI = null;
-
- // Connection pool info
-
- static class ConnectionPool {
-
- // container for the pool's IMAP protocol objects
- private Vector authenticatedConnections = new Vector();
-
- // vectore of open folders
- private Vector folders;
-
- // is the store connection being used?
- private boolean storeConnectionInUse = false;
-
- // the last time (in millis) the pool was checked for timed out
- // connections
- private long lastTimePruned;
-
- // flag to indicate whether there is a dedicated connection for
- // store commands
- private final boolean separateStoreConnection;
-
- // client timeout interval
- private final long clientTimeoutInterval;
-
- // server timeout interval
- private final long serverTimeoutInterval;
-
- // size of the connection pool
- private final int poolSize;
-
- // interval for checking for timed out connections
- private final long pruningInterval;
-
- // connection pool logger
- private final MailLogger logger;
-
- /*
- * The idleState field supports the IDLE command.
- * Normally when executing an IMAP command we hold the
- * store's lock.
- * While executing the IDLE command we can't hold the
- * lock or it would prevent other threads from
- * entering Store methods even far enough to check whether
- * an IDLE command is in progress. We need to check before
- * issuing another command so that we can abort the IDLE
- * command.
- *
- * The idleState field is protected by the store's lock.
- * The RUNNING state is the normal state and means no IDLE
- * command is in progress. The IDLE state means we've issued
- * an IDLE command and are reading responses. The ABORTING
- * state means we've sent the DONE continuation command and
- * are waiting for the thread running the IDLE command to
- * break out of its read loop.
- *
- * When an IDLE command is in progress, the thread calling
- * the idle method will be reading from the IMAP connection
- * while not holding the store's lock.
- * It's obviously critical that no other thread try to send a
- * command or read from the connection while in this state.
- * However, other threads can send the DONE continuation
- * command that will cause the server to break out of the IDLE
- * loop and send the ending tag response to the IDLE command.
- * The thread in the idle method that's reading the responses
- * from the IDLE command will see this ending response and
- * complete the idle method, setting the idleState field back
- * to RUNNING, and notifying any threads waiting to use the
- * connection.
- *
- * All uses of the IMAP connection (IMAPProtocol object) must
- * be preceeded by a check to make sure an IDLE command is not
- * running, and abort the IDLE command if necessary. This check
- * is made while holding the connection pool lock. While
- * waiting for the IDLE command to complete, these other threads
- * will give up the connection pool lock. This check is done by
- * the getStoreProtocol() method.
- */
- private static final int RUNNING = 0; // not doing IDLE command
- private static final int IDLE = 1; // IDLE command in effect
- private static final int ABORTING = 2; // IDLE command aborting
- private int idleState = RUNNING;
- private IMAPProtocol idleProtocol; // protocol object when IDLE
-
- ConnectionPool(String name, MailLogger plogger, Session session) {
- lastTimePruned = System.currentTimeMillis();
-
- boolean debug = PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".connectionpool.debug", false);
- logger = plogger.getSubLogger("connectionpool",
- "DEBUG IMAP CP", debug);
-
- // check if the default connection pool size is overridden
- int size = PropUtil.getIntSessionProperty(session,
- "mail." + name + ".connectionpoolsize", -1);
- if (size > 0) {
- poolSize = size;
- if (logger.isLoggable(Level.CONFIG))
- logger.config("mail.imap.connectionpoolsize: " + poolSize);
- } else
- poolSize = 1;
-
- // check if the default client-side timeout value is overridden
- int connectionPoolTimeout = PropUtil.getIntSessionProperty(session,
- "mail." + name + ".connectionpooltimeout", -1);
- if (connectionPoolTimeout > 0) {
- clientTimeoutInterval = connectionPoolTimeout;
- if (logger.isLoggable(Level.CONFIG))
- logger.config("mail.imap.connectionpooltimeout: " +
- clientTimeoutInterval);
- } else
- clientTimeoutInterval = 45 * 1000; // 45 seconds
-
- // check if the default server-side timeout value is overridden
- int serverTimeout = PropUtil.getIntSessionProperty(session,
- "mail." + name + ".servertimeout", -1);
- if (serverTimeout > 0) {
- serverTimeoutInterval = serverTimeout;
- if (logger.isLoggable(Level.CONFIG))
- logger.config("mail.imap.servertimeout: " +
- serverTimeoutInterval);
- } else
- serverTimeoutInterval = 30 * 60 * 1000; // 30 minutes
-
- // check if the default server-side timeout value is overridden
- int pruning = PropUtil.getIntSessionProperty(session,
- "mail." + name + ".pruninginterval", -1);
- if (pruning > 0) {
- pruningInterval = pruning;
- if (logger.isLoggable(Level.CONFIG))
- logger.config("mail.imap.pruninginterval: " +
- pruningInterval);
- } else
- pruningInterval = 60 * 1000; // 1 minute
-
- // check to see if we should use a separate (i.e. dedicated)
- // store connection
- separateStoreConnection =
- PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".separatestoreconnection", false);
- if (separateStoreConnection)
- logger.config("dedicate a store connection");
-
- }
- }
-
- private final ConnectionPool pool;
-
- /**
- * A special response handler for connections that are being used
- * to perform operations on behalf of an object other than the Store.
- * It DOESN'T cause the Store to be cleaned up if a BYE is seen.
- * The BYE may be real or synthetic and in either case just indicates
- * that the connection is dead.
- */
- private ResponseHandler nonStoreResponseHandler = new ResponseHandler() {
- public void handleResponse(Response r) {
- // Any of these responses may have a response code.
- if (r.isOK() || r.isNO() || r.isBAD() || r.isBYE())
- handleResponseCode(r);
- if (r.isBYE())
- logger.fine("IMAPStore non-store connection dead");
- }
- };
-
- /**
- * Constructor that takes a Session object and a URLName that
- * represents a specific IMAP server.
- */
- public IMAPStore(Session session, URLName url) {
- this(session, url, "imap", false);
- }
-
- /**
- * Constructor used by this class and by IMAPSSLStore subclass.
- */
- protected IMAPStore(Session session, URLName url,
- String name, boolean isSSL) {
- super(session, url); // call super constructor
- if (url != null)
- name = url.getProtocol();
- this.name = name;
- if (!isSSL)
- isSSL = PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".ssl.enable", false);
- if (isSSL)
- this.defaultPort = 993;
- else
- this.defaultPort = 143;
- this.isSSL = isSSL;
-
- debug = session.getDebug();
- debugusername = PropUtil.getBooleanSessionProperty(session,
- "mail.debug.auth.username", true);
- debugpassword = PropUtil.getBooleanSessionProperty(session,
- "mail.debug.auth.password", false);
- logger = new MailLogger(this.getClass(),
- "DEBUG " + name.toUpperCase(), session);
-
- boolean partialFetch = PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".partialfetch", true);
- if (!partialFetch) {
- blksize = -1;
- logger.config("mail.imap.partialfetch: false");
- } else {
- blksize = PropUtil.getIntSessionProperty(session,
- "mail." + name +".fetchsize", 1024 * 16);
- if (logger.isLoggable(Level.CONFIG))
- logger.config("mail.imap.fetchsize: " + blksize);
- }
-
- ignoreSize = PropUtil.getBooleanSessionProperty(session,
- "mail." + name +".ignorebodystructuresize", false);
- if (logger.isLoggable(Level.CONFIG))
- logger.config("mail.imap.ignorebodystructuresize: " + ignoreSize);
-
- statusCacheTimeout = PropUtil.getIntSessionProperty(session,
- "mail." + name + ".statuscachetimeout", 1000);
- if (logger.isLoggable(Level.CONFIG))
- logger.config("mail.imap.statuscachetimeout: " +
- statusCacheTimeout);
-
- appendBufferSize = PropUtil.getIntSessionProperty(session,
- "mail." + name + ".appendbuffersize", -1);
- if (logger.isLoggable(Level.CONFIG))
- logger.config("mail.imap.appendbuffersize: " + appendBufferSize);
-
- minIdleTime = PropUtil.getIntSessionProperty(session,
- "mail." + name + ".minidletime", 10);
- if (logger.isLoggable(Level.CONFIG))
- logger.config("mail.imap.minidletime: " + minIdleTime);
-
- // check if we should do a PROXYAUTH login
- String s = session.getProperty("mail." + name + ".proxyauth.user");
- if (s != null) {
- proxyAuthUser = s;
- if (logger.isLoggable(Level.CONFIG))
- logger.config("mail.imap.proxyauth.user: " + proxyAuthUser);
- }
-
- // check if AUTH=LOGIN is disabled
- disableAuthLogin = PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".auth.login.disable", false);
- if (disableAuthLogin)
- logger.config("disable AUTH=LOGIN");
-
- // check if AUTH=PLAIN is disabled
- disableAuthPlain = PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".auth.plain.disable", false);
- if (disableAuthPlain)
- logger.config("disable AUTH=PLAIN");
-
- // check if AUTH=NTLM is disabled
- disableAuthNtlm = PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".auth.ntlm.disable", false);
- if (disableAuthNtlm)
- logger.config("disable AUTH=NTLM");
-
- // check if STARTTLS is enabled
- enableStartTLS = PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".starttls.enable", false);
- if (enableStartTLS)
- logger.config("enable STARTTLS");
-
- // check if STARTTLS is required
- requireStartTLS = PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".starttls.required", false);
- if (requireStartTLS)
- logger.config("require STARTTLS");
-
- // check if SASL is enabled
- enableSASL = PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".sasl.enable", false);
- if (enableSASL)
- logger.config("enable SASL");
-
- // check if SASL mechanisms are specified
- if (enableSASL) {
- s = session.getProperty("mail." + name + ".sasl.mechanisms");
- if (s != null && s.length() > 0) {
- if (logger.isLoggable(Level.CONFIG))
- logger.config("SASL mechanisms allowed: " + s);
- Vector v = new Vector(5);
- StringTokenizer st = new StringTokenizer(s, " ,");
- while (st.hasMoreTokens()) {
- String m = st.nextToken();
- if (m.length() > 0)
- v.addElement(m);
- }
- saslMechanisms = new String[v.size()];
- v.copyInto(saslMechanisms);
- }
- }
-
- // check if an authorization ID has been specified
- s = session.getProperty("mail." + name + ".sasl.authorizationid");
- if (s != null) {
- authorizationID = s;
- logger.log(Level.CONFIG, "mail.imap.sasl.authorizationid: {0}",
- authorizationID);
- }
-
- // check if a SASL realm has been specified
- s = session.getProperty("mail." + name + ".sasl.realm");
- if (s != null) {
- saslRealm = s;
- logger.log(Level.CONFIG, "mail.imap.sasl.realm: {0}", saslRealm);
- }
-
- // check if forcePasswordRefresh is enabled
- forcePasswordRefresh = PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".forcepasswordrefresh", false);
- if (forcePasswordRefresh)
- logger.config("enable forcePasswordRefresh");
-
- // check if enableimapevents is enabled
- enableImapEvents = PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".enableimapevents", false);
- if (enableImapEvents)
- logger.config("enable IMAP events");
-
- // check if message cache debugging set
- messageCacheDebug = PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".messagecache.debug", false);
-
- guid = session.getProperty("mail." + name + ".yahoo.guid");
- if (guid != null)
- logger.log(Level.CONFIG, "mail.imap.yahoo.guid: {0}", guid);
-
- s = session.getProperty("mail." + name + ".folder.class");
- if (s != null) {
- logger.log(Level.CONFIG, "IMAP: folder class: {0}", s);
- try {
- ClassLoader cl = this.getClass().getClassLoader();
-
- // now load the class
- Class folderClass = null;
- try {
- // First try the "application's" class loader.
- // This should eventually be replaced by
- // Thread.currentThread().getContextClassLoader().
- folderClass = 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.)
- folderClass = Class.forName(s);
- }
-
- Class[] c = { String.class, char.class, IMAPStore.class,
- Boolean.class };
- folderConstructor = folderClass.getConstructor(c);
- Class[] c2 = { ListInfo.class, IMAPStore.class };
- folderConstructorLI = folderClass.getConstructor(c2);
- } catch (Exception ex) {
- logger.log(Level.CONFIG,
- "IMAP: failed to load folder class", ex);
- }
- }
-
- pool = new ConnectionPool(name, logger, session);
- }
-
- /**
- * Implementation of protocolConnect(). Will create a connection
- * to the server and authenticate the user using the mechanisms
- * specified by various properties.
- *
- * The host, user, and password
- * parameters must all be non-null. If the authentication mechanism
- * being used does not require a password, an empty string or other
- * suitable dummy password should be used.
- */
- protected synchronized boolean
- protocolConnect(String host, int pport, String user, String password)
- throws MessagingException {
-
- IMAPProtocol protocol = null;
-
- // check for non-null values of host, password, user
- if (host == null || password == null || user == null) {
- if (logger.isLoggable(Level.FINE))
- logger.fine("protocolConnect returning false" +
- ", host=" + host +
- ", user=" + traceUser(user) +
- ", password=" + tracePassword(password));
- return false;
- }
-
- // set the port correctly
- if (pport != -1) {
- port = pport;
- } else {
- port = PropUtil.getIntSessionProperty(session,
- "mail." + name + ".port", port);
- }
-
- // use the default if needed
- if (port == -1) {
- port = defaultPort;
- }
-
- try {
- boolean poolEmpty;
- synchronized (pool) {
- poolEmpty = pool.authenticatedConnections.isEmpty();
- }
-
- if (poolEmpty) {
- if (logger.isLoggable(Level.FINE))
- logger.fine("trying to connect to host \"" + host +
- "\", port " + port + ", isSSL " + isSSL);
- protocol = newIMAPProtocol(host, port);
- if (logger.isLoggable(Level.FINE))
- logger.fine("protocolConnect login" +
- ", host=" + host +
- ", user=" + traceUser(user) +
- ", password=" + tracePassword(password));
- login(protocol, user, password);
-
- protocol.addResponseHandler(this);
-
- usingSSL = protocol.isSSL(); // in case anyone asks
-
- this.host = host;
- this.user = user;
- this.password = password;
-
- synchronized (pool) {
- pool.authenticatedConnections.addElement(protocol);
- }
- }
- } catch (CommandFailedException cex) {
- // login failure, close connection to server
- if (protocol != null)
- protocol.disconnect();
- protocol = null;
- throw new AuthenticationFailedException(
- cex.getResponse().getRest());
- } catch (ProtocolException pex) { // any other exception
- // failure in login command, close connection to server
- if (protocol != null)
- protocol.disconnect();
- protocol = null;
- throw new MessagingException(pex.getMessage(), pex);
- } catch (SocketConnectException scex) {
- throw new MailConnectException(scex);
- } catch (IOException ioex) {
- throw new MessagingException(ioex.getMessage(), ioex);
- }
-
- return true;
- }
-
- /**
- * Create an IMAPProtocol object connected to the host and port.
- * Subclasses of IMAPStore may override this method to return a
- * subclass of IMAPProtocol that supports product-specific extensions.
- *
- * @since JavaMail 1.4.6
- */
- protected IMAPProtocol newIMAPProtocol(String host, int port)
- throws IOException, ProtocolException {
- return new IMAPProtocol(name, host, port,
- session.getProperties(),
- isSSL,
- logger
- );
- }
-
- private void login(IMAPProtocol p, String u, String pw)
- throws ProtocolException {
- // turn on TLS if it's been enabled or required and is supported
- if (enableStartTLS || requireStartTLS) {
- if (p.hasCapability("STARTTLS")) {
- p.startTLS();
- // if startTLS succeeds, refresh capabilities
- p.capability();
- } else if (requireStartTLS) {
- logger.fine("STARTTLS required but not supported by server");
- throw new ProtocolException(
- "STARTTLS required but not supported by server");
- }
- }
- if (p.isAuthenticated())
- return; // no need to login
-
- // allow subclasses to issue commands before login
- preLogin(p);
-
- // issue special ID command to Yahoo! Mail IMAP server
- if (guid != null)
- p.id(guid);
-
- /*
- * Put a special "marker" in the capabilities list so we can
- * detect if the server refreshed the capabilities in the OK
- * response.
- */
- p.getCapabilities().put("__PRELOGIN__", "");
- String authzid;
- if (authorizationID != null)
- authzid = authorizationID;
- else if (proxyAuthUser != null)
- authzid = proxyAuthUser;
- else
- authzid = null;
-
- if (enableSASL)
- p.sasllogin(saslMechanisms, saslRealm, authzid, u, pw);
-
- if (p.isAuthenticated())
- ; // SASL login succeeded, go to bottom
- else if (p.hasCapability("AUTH=PLAIN") && !disableAuthPlain)
- p.authplain(authzid, u, pw);
- else if ((p.hasCapability("AUTH-LOGIN") ||
- p.hasCapability("AUTH=LOGIN")) && !disableAuthLogin)
- p.authlogin(u, pw);
- else if (p.hasCapability("AUTH=NTLM") && !disableAuthNtlm)
- p.authntlm(authzid, u, pw);
- else if (!p.hasCapability("LOGINDISABLED"))
- p.login(u, pw);
- else
- throw new ProtocolException("No login methods supported!");
-
- if (proxyAuthUser != null)
- p.proxyauth(proxyAuthUser);
-
- /*
- * If marker is still there, capabilities haven't been refreshed,
- * refresh them now.
- */
- if (p.hasCapability("__PRELOGIN__")) {
- try {
- p.capability();
- } catch (ConnectionException cex) {
- throw cex; // rethrow connection failures
- // XXX - assume connection has been closed
- } catch (ProtocolException pex) {
- // ignore other exceptions that "should never happen"
- }
- }
- }
-
- /**
- * This method is called after the connection is made and
- * TLS is started (if needed), but before any authentication
- * is attempted. Subclasses can override this method to
- * issue commands that are needed in the "not authenticated"
- * state. Note that if the connection is pre-authenticated,
- * this method won't be called.
- *
- * The implementation of this method in this class does nothing.
- *
- * @since JavaMail 1.4.4
- */
- protected void preLogin(IMAPProtocol p) throws ProtocolException {
- }
-
- /**
- * Does this IMAPStore use SSL when connecting to the server?
- *
- * @return true if using SSL
- * @since JavaMail 1.4.6
- */
- public boolean isSSL() {
- return usingSSL;
- }
-
- /**
- * Set the user name that will be used for subsequent connections
- * after this Store is first connected (for example, when creating
- * a connection to open a Folder). This value is overridden
- * by any call to the Store's connect method.
- *
- * Some IMAP servers may provide an authentication ID that can
- * be used for more efficient authentication for future connections.
- * This authentication ID is provided in a server-specific manner
- * not described here.
- *
- * Most applications will never need to use this method.
- *
- * @since JavaMail 1.3.3
- */
- public synchronized void setUsername(String user) {
- this.user = user;
- }
-
- /**
- * Set the password that will be used for subsequent connections
- * after this Store is first connected (for example, when creating
- * a connection to open a Folder). This value is overridden
- * by any call to the Store's connect method.
- *
- * Most applications will never need to use this method.
- *
- * @since JavaMail 1.3.3
- */
- public synchronized void setPassword(String password) {
- this.password = password;
- }
-
- /*
- * Get a new authenticated protocol object for this Folder.
- * Also store a reference to this folder in our list of
- * open folders.
- */
- IMAPProtocol getProtocol(IMAPFolder folder)
- throws MessagingException {
- IMAPProtocol p = null;
-
- // keep looking for a connection until we get a good one
- while (p == null) {
-
- // New authenticated protocol objects are either acquired
- // from the connection pool, or created when the pool is
- // empty or no connections are available. None are available
- // if the current pool size is one and the separate store
- // property is set or the connection is in use.
-
- synchronized (pool) {
-
- // If there's none available in the pool,
- // create a new one.
- if (pool.authenticatedConnections.isEmpty() ||
- (pool.authenticatedConnections.size() == 1 &&
- (pool.separateStoreConnection || pool.storeConnectionInUse))) {
-
- logger.fine("no connections in the pool, creating a new one");
- try {
- if (forcePasswordRefresh)
- refreshPassword();
- // Use cached host, port and timeout values.
- p = newIMAPProtocol(host, port);
- // Use cached auth info
- login(p, user, password);
- } catch(Exception ex1) {
- if (p != null)
- try {
- p.disconnect();
- } catch (Exception ex2) { }
- p = null;
- }
-
- if (p == null)
- throw new MessagingException("connection failure");
- } else {
- if (logger.isLoggable(Level.FINE))
- logger.fine("connection available -- size: " +
- pool.authenticatedConnections.size());
-
- // remove the available connection from the Authenticated queue
- p = (IMAPProtocol)pool.authenticatedConnections.lastElement();
- pool.authenticatedConnections.removeElement(p);
-
- // check if the connection is still live
- long lastUsed = System.currentTimeMillis() - p.getTimestamp();
- if (lastUsed > pool.serverTimeoutInterval) {
- try {
- /*
- * Swap in a special response handler that will handle
- * alerts, but won't cause the store to be closed and
- * cleaned up if the connection is dead.
- */
- p.removeResponseHandler(this);
- p.addResponseHandler(nonStoreResponseHandler);
- p.noop();
- p.removeResponseHandler(nonStoreResponseHandler);
- p.addResponseHandler(this);
- } catch (ProtocolException pex) {
- try {
- p.removeResponseHandler(nonStoreResponseHandler);
- p.disconnect();
- } finally {
- // don't let any exception stop us
- p = null;
- continue; // try again, from the top
- }
- }
- }
-
- // remove the store as a response handler.
- p.removeResponseHandler(this);
- }
-
- // check if we need to look for client-side timeouts
- timeoutConnections();
-
- // Add folder to folder-list
- if (folder != null) {
- if (pool.folders == null)
- pool.folders = new Vector();
- pool.folders.addElement(folder);
- }
- }
-
- }
-
- return p;
- }
-
- /**
- * Get this Store's protocol connection.
- *
- * When acquiring a store protocol object, it is important to
- * use the following steps:
- *
- * IMAPProtocol p = null;
- * try {
- * p = getStoreProtocol();
- * // perform the command
- * } catch (ConnectionException cex) {
- * throw new StoreClosedException(this, cex.getMessage());
- * } catch (WhateverException ex) {
- * // handle it
- * } finally {
- * releaseStoreProtocol(p);
- * }
- */
- private IMAPProtocol getStoreProtocol() throws ProtocolException {
- IMAPProtocol p = null;
-
- while (p == null) {
- synchronized (pool) {
- waitIfIdle();
-
- // If there's no authenticated connections available create a
- // new one and place it in the authenticated queue.
- if (pool.authenticatedConnections.isEmpty()) {
- pool.logger.fine("getStoreProtocol() - no connections " +
- "in the pool, creating a new one");
- try {
- if (forcePasswordRefresh)
- refreshPassword();
- // Use cached host, port and timeout values.
- p = newIMAPProtocol(host, port);
- // Use cached auth info
- login(p, user, password);
- } catch(Exception ex1) {
- if (p != null)
- try {
- p.logout();
- } catch (Exception ex2) { }
- p = null;
- }
-
- if (p == null)
- throw new ConnectionException(
- "failed to create new store connection");
-
- p.addResponseHandler(this);
- pool.authenticatedConnections.addElement(p);
-
- } else {
- // Always use the first element in the Authenticated queue.
- if (pool.logger.isLoggable(Level.FINE))
- pool.logger.fine("getStoreProtocol() - " +
- "connection available -- size: " +
- pool.authenticatedConnections.size());
- p = (IMAPProtocol)pool.authenticatedConnections.firstElement();
- }
-
- if (pool.storeConnectionInUse) {
- try {
- // someone else is using the connection, give up
- // and wait until they're done
- p = null;
- pool.wait();
- } catch (InterruptedException ex) { }
- } else {
- pool.storeConnectionInUse = true;
-
- pool.logger.fine("getStoreProtocol() -- storeConnectionInUse");
- }
-
- timeoutConnections();
- }
- }
- return p;
- }
-
- /**
- * Get a store protocol object for use by a folder.
- */
- IMAPProtocol getFolderStoreProtocol() throws ProtocolException {
- IMAPProtocol p = getStoreProtocol();
- p.removeResponseHandler(this);
- p.addResponseHandler(nonStoreResponseHandler);
- return p;
- }
-
- /*
- * Some authentication systems use one time passwords
- * or tokens, so each authentication request requires
- * a new password. This "kludge" allows a callback
- * to application code to get a new password.
- *
- * XXX - remove this when SASL support is added
- */
- private void refreshPassword() {
- if (logger.isLoggable(Level.FINE))
- logger.fine("refresh password, user: " + traceUser(user));
- InetAddress addr;
- try {
- addr = InetAddress.getByName(host);
- } catch (UnknownHostException e) {
- addr = null;
- }
- PasswordAuthentication pa =
- session.requestPasswordAuthentication(addr, port,
- name, null, user);
- if (pa != null) {
- user = pa.getUserName();
- password = pa.getPassword();
- }
- }
-
- /**
- * If a SELECT succeeds, but indicates that the folder is
- * READ-ONLY, and the user asked to open the folder READ_WRITE,
- * do we allow the open to succeed?
- */
- boolean allowReadOnlySelect() {
- return PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".allowreadonlyselect", false);
- }
-
- /**
- * Report whether the separateStoreConnection is set.
- */
- boolean hasSeparateStoreConnection() {
- return pool.separateStoreConnection;
- }
-
- /**
- * Return the connection pool logger.
- */
- MailLogger getConnectionPoolLogger() {
- return pool.logger;
- }
-
- /**
- * Report whether message cache debugging is enabled.
- */
- boolean getMessageCacheDebug() {
- return messageCacheDebug;
- }
-
- /**
- * Report whether the connection pool is full.
- */
- boolean isConnectionPoolFull() {
-
- synchronized (pool) {
- if (pool.logger.isLoggable(Level.FINE))
- pool.logger.fine("connection pool current size: " +
- pool.authenticatedConnections.size() +
- " pool size: " + pool.poolSize);
-
- return (pool.authenticatedConnections.size() >= pool.poolSize);
-
- }
- }
-
- /**
- * Release the protocol object back to the connection pool.
- */
- void releaseProtocol(IMAPFolder folder, IMAPProtocol protocol) {
-
- synchronized (pool) {
- if (protocol != null) {
- // If the pool is not full, add the store as a response handler
- // and return the protocol object to the connection pool.
- if (!isConnectionPoolFull()) {
- protocol.addResponseHandler(this);
- pool.authenticatedConnections.addElement(protocol);
-
- if (logger.isLoggable(Level.FINE))
- logger.fine(
- "added an Authenticated connection -- size: " +
- pool.authenticatedConnections.size());
- } else {
- logger.fine(
- "pool is full, not adding an Authenticated connection");
- try {
- protocol.logout();
- } catch (ProtocolException pex) {};
- }
- }
-
- if (pool.folders != null)
- pool.folders.removeElement(folder);
-
- timeoutConnections();
- }
- }
-
- /**
- * Release the store connection.
- */
- private void releaseStoreProtocol(IMAPProtocol protocol) {
-
- // will be called from idle() without the Store lock held,
- // but cleanup is synchronized and will acquire the Store lock
-
- if (protocol == null) {
- cleanup(); // failed to ever get the connection
- return; // nothing to release
- }
-
- /*
- * Read out the flag that says whether this connection failed
- * before releasing the protocol object for others to use.
- */
- boolean failed;
- synchronized (connectionFailedLock) {
- failed = connectionFailed;
- connectionFailed = false; // reset for next use
- }
-
- // now free the store connection
- synchronized (pool) {
- pool.storeConnectionInUse = false;
- pool.notifyAll(); // in case anyone waiting
-
- pool.logger.fine("releaseStoreProtocol()");
-
- timeoutConnections();
- }
-
- /*
- * If the connection died while we were using it, clean up.
- * It's critical that the store connection be freed and the
- * connection pool not be locked while we do this.
- */
- assert !Thread.holdsLock(pool);
- if (failed)
- cleanup();
- }
-
- /**
- * Release a store protocol object that was being used by a folder.
- */
- void releaseFolderStoreProtocol(IMAPProtocol protocol) {
- if (protocol == null)
- return; // should never happen
- protocol.removeResponseHandler(nonStoreResponseHandler);
- protocol.addResponseHandler(this);
- synchronized (pool) {
- pool.storeConnectionInUse = false;
- pool.notifyAll(); // in case anyone waiting
-
- pool.logger.fine("releaseFolderStoreProtocol()");
-
- timeoutConnections();
- }
- }
-
- /**
- * Empty the connection pool.
- */
- private void emptyConnectionPool(boolean force) {
-
- synchronized (pool) {
- for (int index = pool.authenticatedConnections.size() - 1;
- index >= 0; --index) {
- try {
- IMAPProtocol p = (IMAPProtocol)
- pool.authenticatedConnections.elementAt(index);
- p.removeResponseHandler(this);
- if (force)
- p.disconnect();
- else
- p.logout();
- } catch (ProtocolException pex) {};
- }
-
- pool.authenticatedConnections.removeAllElements();
- }
-
- pool.logger.fine("removed all authenticated connections from pool");
- }
-
- /**
- * Check to see if it's time to shrink the connection pool.
- */
- private void timeoutConnections() {
-
- synchronized (pool) {
-
- // If we've exceeded the pruning interval, look for stale
- // connections to logout.
- if (System.currentTimeMillis() - pool.lastTimePruned >
- pool.pruningInterval &&
- pool.authenticatedConnections.size() > 1) {
-
- if (pool.logger.isLoggable(Level.FINE)) {
- pool.logger.fine("checking for connections to prune: " +
- (System.currentTimeMillis() - pool.lastTimePruned));
- pool.logger.fine("clientTimeoutInterval: " +
- pool.clientTimeoutInterval);
- }
-
- IMAPProtocol p;
-
- // Check the timestamp of the protocol objects in the pool and
- // logout if the interval exceeds the client timeout value
- // (leave the first connection).
- for (int index = pool.authenticatedConnections.size() - 1;
- index > 0; index--) {
- p = (IMAPProtocol)pool.authenticatedConnections.
- elementAt(index);
- if (pool.logger.isLoggable(Level.FINE))
- pool.logger.fine("protocol last used: " +
- (System.currentTimeMillis() - p.getTimestamp()));
- if (System.currentTimeMillis() - p.getTimestamp() >
- pool.clientTimeoutInterval) {
-
- pool.logger.fine(
- "authenticated connection timed out, " +
- "logging out the connection");
-
- p.removeResponseHandler(this);
- pool.authenticatedConnections.removeElementAt(index);
-
- try {
- p.logout();
- } catch (ProtocolException pex) {}
- }
- }
- pool.lastTimePruned = System.currentTimeMillis();
- }
- }
- }
-
- /**
- * Get the block size to use for fetch requests on this Store.
- */
- int getFetchBlockSize() {
- return blksize;
- }
-
- /**
- * Ignore the size reported in the BODYSTRUCTURE when fetching data?
- */
- boolean ignoreBodyStructureSize() {
- return ignoreSize;
- }
-
- /**
- * Get a reference to the session.
- */
- Session getSession() {
- return session;
- }
-
- /**
- * Get the number of milliseconds to cache STATUS response.
- */
- int getStatusCacheTimeout() {
- return statusCacheTimeout;
- }
-
- /**
- * Get the maximum size of a message to buffer for append.
- */
- int getAppendBufferSize() {
- return appendBufferSize;
- }
-
- /**
- * Get the minimum amount of time to delay when returning from idle.
- */
- int getMinIdleTime() {
- return minIdleTime;
- }
-
- /**
- * Return true if the specified capability string is in the list
- * of capabilities the server announced.
- *
- * @since JavaMail 1.3.3
- */
- public synchronized boolean hasCapability(String capability)
- throws MessagingException {
- IMAPProtocol p = null;
- try {
- p = getStoreProtocol();
- return p.hasCapability(capability);
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- } finally {
- releaseStoreProtocol(p);
- }
- }
-
- /**
- * Check whether this store is connected. Override superclass
- * method, to actually ping our server connection.
- */
- public synchronized boolean isConnected() {
- if (!super.isConnected()) {
- // if we haven't been connected at all, don't bother with
- // the NOOP.
- return false;
- }
-
- /*
- * The below noop() request can:
- * (1) succeed - in which case all is fine.
- *
- * (2) fail because the server returns NO or BAD, in which
- * case we ignore it since we can't really do anything.
- * (2) fail because a BYE response is obtained from the
- * server
- * (3) fail because the socket.write() to the server fails,
- * in which case the iap.protocol() code converts the
- * IOException into a BYE response.
- *
- * Thus, our BYE handler will take care of closing the Store
- * in case our connection is really gone.
- */
-
- IMAPProtocol p = null;
- try {
- p = getStoreProtocol();
- p.noop();
- } catch (ProtocolException pex) {
- // will return false below
- } finally {
- releaseStoreProtocol(p);
- }
-
-
- return super.isConnected();
- }
-
- /**
- * Close this Store.
- */
- public synchronized void close() throws MessagingException {
- if (!super.isConnected()) // Already closed.
- return;
-
- IMAPProtocol protocol = null;
- try {
- boolean isEmpty;
- synchronized (pool) {
- // If there's no authenticated connections available
- // don't create a new one
- isEmpty = pool.authenticatedConnections.isEmpty();
- }
- /*
- * Have to drop the lock before calling cleanup.
- * Yes, there's a potential race here. The pool could
- * become empty after we check, in which case we'll just
- * waste time getting a new connection and closing it.
- * Or, the pool could be empty now and not empty by the
- * time we get into cleanup, but that's ok because cleanup
- * will just close the connection.
- */
- if (isEmpty) {
- pool.logger.fine("close() - no connections ");
- cleanup();
- return;
- }
-
- protocol = getStoreProtocol();
- /*
- * We have to remove the protocol from the pool so that,
- * when our response handler processes the BYE response
- * and calls cleanup, which calls emptyConnection, that
- * we don't try to log out this connection twice.
- */
- synchronized (pool) {
- pool.authenticatedConnections.removeElement(protocol);
- }
-
- /*
- * LOGOUT.
- *
- * Note that protocol.logout() closes the server socket
- * connection, regardless of what happens ..
- *
- * Also note that protocol.logout() results in a BYE
- * response (As per rfc 2060, BYE is a *required* response
- * to LOGOUT). In fact, even if protocol.logout() fails
- * with an IOException (if the server connection is dead),
- * iap.Protocol.command() converts that exception into a
- * BYE response. So, I depend on my BYE handler to set the
- * flag that causes releaseStoreProtocol to do the
- * Store cleanup.
- */
- protocol.logout();
- } catch (ProtocolException pex) {
- // Hmm .. will this ever happen ?
- throw new MessagingException(pex.getMessage(), pex);
- } finally {
- releaseStoreProtocol(protocol);
- }
- }
-
- protected void finalize() throws Throwable {
- super.finalize();
- close();
- }
-
- /**
- * Cleanup before dying.
- */
- private synchronized void cleanup() {
- // if we're not connected, someone beat us to it
- if (!super.isConnected()) {
- logger.fine("IMAPStore cleanup, not connected");
- return;
- }
-
- /*
- * If forceClose is true, some thread ran into an error that suggests
- * the server might be dead, so we force the folders to close
- * abruptly without waiting for the server. Used when
- * the store connection times out, for example.
- */
- boolean force;
- synchronized (connectionFailedLock) {
- force = forceClose;
- forceClose = false;
- connectionFailed = false;
- }
- if (logger.isLoggable(Level.FINE))
- logger.fine("IMAPStore cleanup, force " + force);
-
- Vector foldersCopy = null;
- boolean done = true;
-
- // To avoid violating the locking hierarchy, there's no lock we
- // can hold that prevents another thread from trying to open a
- // folder at the same time we're trying to close all the folders.
- // Thus, there's an inherent race condition here. We close all
- // the folders we know about and then check whether any new folders
- // have been opened in the mean time. We keep trying until we're
- // successful in closing all the folders.
- for (;;) {
- // Make a copy of the folders list so we do not violate the
- // folder-connection pool locking hierarchy.
- synchronized (pool) {
- if (pool.folders != null) {
- done = false;
- foldersCopy = pool.folders;
- pool.folders = null;
- } else {
- done = true;
- }
- }
- if (done)
- break;
-
- // Close and remove any open folders under this Store.
- for (int i = 0, fsize = foldersCopy.size(); i < fsize; i++) {
- IMAPFolder f = (IMAPFolder)foldersCopy.elementAt(i);
-
- try {
- if (force) {
- logger.fine("force folder to close");
- // Don't want to wait for folder connection to timeout
- // (if, for example, the server is down) so we close
- // folders abruptly.
- f.forceClose();
- } else {
- logger.fine("close folder");
- f.close(false);
- }
- } catch (MessagingException mex) {
- // Who cares ?! Ignore 'em.
- } catch (IllegalStateException ex) {
- // Ditto
- }
- }
-
- }
-
- synchronized (pool) {
- emptyConnectionPool(force);
- }
-
- // to set the state and send the closed connection event
- try {
- super.close();
- } catch (MessagingException mex) { }
- logger.fine("IMAPStore cleanup done");
- }
-
- /**
- * Get the default folder, representing the root of this user's
- * namespace. Returns a closed DefaultFolder object.
- */
- public synchronized Folder getDefaultFolder() throws MessagingException {
- checkConnected();
- return new DefaultFolder(this);
- }
-
- /**
- * Get named folder. Returns a new, closed IMAPFolder.
- */
- public synchronized Folder getFolder(String name)
- throws MessagingException {
- checkConnected();
- return newIMAPFolder(name, IMAPFolder.UNKNOWN_SEPARATOR);
- }
-
- /**
- * Get named folder. Returns a new, closed IMAPFolder.
- */
- public synchronized Folder getFolder(URLName url)
- throws MessagingException {
- checkConnected();
- return newIMAPFolder(url.getFile(), IMAPFolder.UNKNOWN_SEPARATOR);
- }
-
- /**
- * Create an IMAPFolder object. If user supplied their own class,
- * use it. Otherwise, call the constructor.
- */
- protected IMAPFolder newIMAPFolder(String fullName, char separator,
- Boolean isNamespace) {
- IMAPFolder f = null;
- if (folderConstructor != null) {
- try {
- Object[] o =
- { fullName, new Character(separator), this, isNamespace };
- f = (IMAPFolder)folderConstructor.newInstance(o);
- } catch (Exception ex) {
- logger.log(Level.FINE,
- "exception creating IMAPFolder class", ex);
- }
- }
- if (f == null)
- f = new IMAPFolder(fullName, separator, this, isNamespace);
- return f;
- }
-
- /**
- * Create an IMAPFolder object. Call the newIMAPFolder method
- * above with a null isNamespace.
- */
- protected IMAPFolder newIMAPFolder(String fullName, char separator) {
- return newIMAPFolder(fullName, separator, null);
- }
-
- /**
- * Create an IMAPFolder object. If user supplied their own class,
- * use it. Otherwise, call the constructor.
- */
- protected IMAPFolder newIMAPFolder(ListInfo li) {
- IMAPFolder f = null;
- if (folderConstructorLI != null) {
- try {
- Object[] o = { li, this };
- f = (IMAPFolder)folderConstructorLI.newInstance(o);
- } catch (Exception ex) {
- logger.log(Level.FINE,
- "exception creating IMAPFolder class LI", ex);
- }
- }
- if (f == null)
- f = new IMAPFolder(li, this);
- return f;
- }
-
- /**
- * Using the IMAP NAMESPACE command (RFC 2342), return a set
- * of folders representing the Personal namespaces.
- */
- public Folder[] getPersonalNamespaces() throws MessagingException {
- Namespaces ns = getNamespaces();
- if (ns == null || ns.personal == null)
- return super.getPersonalNamespaces();
- return namespaceToFolders(ns.personal, null);
- }
-
- /**
- * Using the IMAP NAMESPACE command (RFC 2342), return a set
- * of folders representing the User's namespaces.
- */
- public Folder[] getUserNamespaces(String user)
- throws MessagingException {
- Namespaces ns = getNamespaces();
- if (ns == null || ns.otherUsers == null)
- return super.getUserNamespaces(user);
- return namespaceToFolders(ns.otherUsers, user);
- }
-
- /**
- * Using the IMAP NAMESPACE command (RFC 2342), return a set
- * of folders representing the Shared namespaces.
- */
- public Folder[] getSharedNamespaces() throws MessagingException {
- Namespaces ns = getNamespaces();
- if (ns == null || ns.shared == null)
- return super.getSharedNamespaces();
- return namespaceToFolders(ns.shared, null);
- }
-
- private synchronized Namespaces getNamespaces() throws MessagingException {
- checkConnected();
-
- IMAPProtocol p = null;
-
- if (namespaces == null) {
- try {
- p = getStoreProtocol();
- namespaces = p.namespace();
- } catch (BadCommandException bex) {
- // NAMESPACE not supported, ignore it
- } catch (ConnectionException cex) {
- throw new StoreClosedException(this, cex.getMessage());
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- } finally {
- releaseStoreProtocol(p);
- }
- }
- return namespaces;
- }
-
- private Folder[] namespaceToFolders(Namespaces.Namespace[] ns,
- String user) {
- Folder[] fa = new Folder[ns.length];
- for (int i = 0; i < fa.length; i++) {
- String name = ns[i].prefix;
- if (user == null) {
- // strip trailing delimiter
- int len = name.length();
- if ( len > 0 && name.charAt(len - 1) == ns[i].delimiter)
- name = name.substring(0, len - 1);
- } else {
- // add user
- name += user;
- }
- fa[i] = newIMAPFolder(name, ns[i].delimiter,
- Boolean.valueOf(user == null));
- }
- return fa;
- }
-
- /**
- * Get the quotas for the named quota root.
- * Quotas are controlled on the basis of a quota root, not
- * (necessarily) a folder. The relationship between folders
- * and quota roots depends on the IMAP server. Some servers
- * might implement a single quota root for all folders owned by
- * a user. Other servers might implement a separate quota root
- * for each folder. A single folder can even have multiple
- * quota roots, perhaps controlling quotas for different
- * resources.
- *
- * @param root the name of the quota root
- * @return array of Quota objects
- * @exception MessagingException if the server doesn't support the
- * QUOTA extension
- */
- public synchronized Quota[] getQuota(String root)
- throws MessagingException {
- checkConnected();
- Quota[] qa = null;
-
- IMAPProtocol p = null;
- try {
- p = getStoreProtocol();
- qa = p.getQuotaRoot(root);
- } catch (BadCommandException bex) {
- throw new MessagingException("QUOTA not supported", bex);
- } catch (ConnectionException cex) {
- throw new StoreClosedException(this, cex.getMessage());
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- } finally {
- releaseStoreProtocol(p);
- }
- return qa;
- }
-
- /**
- * Set the quotas for the quota root specified in the quota argument.
- * Typically this will be one of the quota roots obtained from the
- * getQuota method, but it need not be.
- *
- * @param quota the quota to set
- * @exception MessagingException if the server doesn't support the
- * QUOTA extension
- */
- public synchronized void setQuota(Quota quota) throws MessagingException {
- checkConnected();
- IMAPProtocol p = null;
- try {
- p = getStoreProtocol();
- p.setQuota(quota);
- } catch (BadCommandException bex) {
- throw new MessagingException("QUOTA not supported", bex);
- } catch (ConnectionException cex) {
- throw new StoreClosedException(this, cex.getMessage());
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- } finally {
- releaseStoreProtocol(p);
- }
- }
-
- private void checkConnected() {
- assert Thread.holdsLock(this);
- if (!super.isConnected())
- throw new IllegalStateException("Not connected");
- }
-
- /**
- * Response handler method.
- */
- public void handleResponse(Response r) {
- // Any of these responses may have a response code.
- if (r.isOK() || r.isNO() || r.isBAD() || r.isBYE())
- handleResponseCode(r);
- if (r.isBYE()) {
- logger.fine("IMAPStore connection dead");
- // Store's IMAP connection is dead, save the response so that
- // releaseStoreProtocol will cleanup later.
- synchronized (connectionFailedLock) {
- connectionFailed = true;
- if (r.isSynthetic())
- forceClose = true;
- }
- return;
- }
- }
-
- /**
- * Use the IMAP IDLE command (see
- * RFC 2177),
- * if supported by the server, to enter idle mode so that the server
- * can send unsolicited notifications
- * without the need for the client to constantly poll the server.
- * Use a ConnectionListener to be notified of
- * events. When another thread (e.g., the listener thread)
- * needs to issue an IMAP comand for this Store, the idle mode will
- * be terminated and this method will return. Typically the caller
- * will invoke this method in a loop.
- *
- * If the mail.imap.enableimapevents property is set, notifications
- * received while the IDLE command is active will be delivered to
- * ConnectionListeners as events with a type of
- * IMAPStore.RESPONSE. The event's message will be
- * the raw IMAP response string.
- * Note that most IMAP servers will not deliver any events when
- * using the IDLE command on a connection with no mailbox selected
- * (i.e., this method). In most cases you'll want to use the
- * idle method on IMAPFolder.
- *
- * NOTE: This capability is highly experimental and likely will change
- * in future releases.
- *
- * The mail.imap.minidletime property enforces a minimum delay
- * before returning from this method, to ensure that other threads
- * have a chance to issue commands before the caller invokes this
- * method again. The default delay is 10 milliseconds.
- *
- * @exception MessagingException if the server doesn't support the
- * IDLE extension
- * @exception IllegalStateException if the store isn't connected
- *
- * @since JavaMail 1.4.1
- */
- public void idle() throws MessagingException {
- IMAPProtocol p = null;
- // ASSERT: Must NOT be called with the connection pool
- // synchronization lock held.
- assert !Thread.holdsLock(pool);
- synchronized (this) {
- checkConnected();
- }
- boolean needNotification = false;
- try {
- synchronized (pool) {
- p = getStoreProtocol();
- if (pool.idleState != ConnectionPool.RUNNING) {
- // some other thread must be running the IDLE
- // command, we'll just wait for it to finish
- // without aborting it ourselves
- try {
- // give up lock and wait to be not idle
- pool.wait();
- } catch (InterruptedException ex) { }
- return;
- }
- p.idleStart();
- needNotification = true;
- pool.idleState = ConnectionPool.IDLE;
- pool.idleProtocol = p;
- }
-
- /*
- * We gave up the pool lock so that other threads
- * can get into the pool far enough to see that we're
- * in IDLE and abort the IDLE.
- *
- * Now we read responses from the IDLE command, especially
- * including unsolicited notifications from the server.
- * We don't hold the pool lock while reading because
- * it protects the idleState and other threads need to be
- * able to examine the state.
- *
- * We hold the pool lock while processing the responses.
- */
- for (;;) {
- Response r = p.readIdleResponse();
- synchronized (pool) {
- if (r == null || !p.processIdleResponse(r)) {
- pool.idleState = ConnectionPool.RUNNING;
- pool.idleProtocol = null;
- pool.notifyAll();
- needNotification = false;
- break;
- }
- }
- if (enableImapEvents && r.isUnTagged()) {
- notifyStoreListeners(IMAPStore.RESPONSE, r.toString());
- }
- }
-
- /*
- * Enforce a minimum delay to give time to threads
- * processing the responses that came in while we
- * were idle.
- */
- int minidle = getMinIdleTime();
- if (minidle > 0) {
- try {
- Thread.sleep(minidle);
- } catch (InterruptedException ex) { }
- }
-
- } catch (BadCommandException bex) {
- throw new MessagingException("IDLE not supported", bex);
- } catch (ConnectionException cex) {
- throw new StoreClosedException(this, cex.getMessage());
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
- } finally {
- if (needNotification) {
- synchronized (pool) {
- pool.idleState = ConnectionPool.RUNNING;
- pool.idleProtocol = null;
- pool.notifyAll();
- }
- }
- releaseStoreProtocol(p);
- }
- }
-
- /*
- * If an IDLE command is in progress, abort it if necessary,
- * and wait until it completes.
- * ASSERT: Must be called with the pool's lock held.
- */
- private void waitIfIdle() throws ProtocolException {
- assert Thread.holdsLock(pool);
- while (pool.idleState != ConnectionPool.RUNNING) {
- if (pool.idleState == ConnectionPool.IDLE) {
- pool.idleProtocol.idleAbort();
- pool.idleState = ConnectionPool.ABORTING;
- }
- try {
- // give up lock and wait to be not idle
- pool.wait();
- } catch (InterruptedException ex) { }
- }
- }
-
- /**
- * Handle notifications and alerts.
- * Response must be an OK, NO, BAD, or BYE response.
- */
- void handleResponseCode(Response r) {
- String s = r.getRest(); // get the text after the response
- boolean isAlert = false;
- if (s.startsWith("[")) { // a response code
- int i = s.indexOf(']');
- // remember if it's an alert
- if (i > 0 && s.substring(0, i + 1).equalsIgnoreCase("[ALERT]"))
- isAlert = true;
- // strip off the response code in any event
- s = s.substring(i + 1).trim();
- }
- if (isAlert)
- notifyStoreListeners(StoreEvent.ALERT, s);
- else if (r.isUnTagged() && s.length() > 0)
- // Only send notifications that come with untagged
- // responses, and only if there is actually some
- // text there.
- notifyStoreListeners(StoreEvent.NOTICE, s);
- }
-
- private String traceUser(String user) {
- return debugusername ? user : "";
- }
-
- private String tracePassword(String password) {
- return debugpassword ? password :
- (password == null ? "" : "");
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/MessageCache.java b/src/main/java/com/sun/mail/imap/MessageCache.java
deleted file mode 100644
index b4088921..00000000
--- a/src/main/java/com/sun/mail/imap/MessageCache.java
+++ /dev/null
@@ -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;
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/Rights.java b/src/main/java/com/sun/mail/imap/Rights.java
deleted file mode 100644
index 3705c362..00000000
--- a/src/main/java/com/sun/mail/imap/Rights.java
+++ /dev/null
@@ -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).
- *
- * A right is represented by the Rights.Right
- * inner class.
- *
- * 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.
- *
- * The following code sample illustrates how to examine your
- * rights for a folder.
- *
- *
- * 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);
- *
- *
- *
- * @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");
- }
- ****/
-}
diff --git a/src/main/java/com/sun/mail/imap/SortTerm.java b/src/main/java/com/sun/mail/imap/SortTerm.java
deleted file mode 100644
index 8d939549..00000000
--- a/src/main/java/com/sun/mail/imap/SortTerm.java
+++ /dev/null
@@ -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
- * RFC 5256.
- * 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;
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/Utility.java b/src/main/java/com/sun/mail/imap/Utility.java
deleted file mode 100644
index e0d2b224..00000000
--- a/src/main/java/com/sun/mail/imap/Utility.java
+++ /dev/null
@@ -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
- * toMessageSet().
- */
- public static interface Condition {
- public boolean test(IMAPMessage message);
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/package.html b/src/main/java/com/sun/mail/imap/package.html
deleted file mode 100644
index 336677ab..00000000
--- a/src/main/java/com/sun/mail/imap/package.html
+++ /dev/null
@@ -1,623 +0,0 @@
-
-
-
-
-
-
-
-
-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
-RFC 2060
-for more information.
-
-The IMAP protocol provider can use SASL
-(RFC 2222)
-authentication mechanisms on systems that support the
-javax.security.sasl 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
-
-Java SASL API Programming and Deployment Guide for details.
-Note that the current implementation doesn't support SASL mechanisms
-that provide their own integrity or confidentiality layer.
-
-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.
-
-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.
-
-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.
-
-The IMAP protocol provider supports the following properties,
-which may be set in the JavaMail Session object.
-The properties are always set as strings; the Type column describes
-how the string is interpreted. For example, use
-
- props.put("mail.imap.port", "888");
-
-to set the mail.imap.port property, which is of type int.
-
-Note that if you're using the "imaps" protocol to access IMAP over SSL,
-all the properties would be named "mail.imaps.*".
-
-
-
-
Name
-
Type
-
Description
-
-
-
-
mail.imap.user
-
String
-
Default user name for IMAP.
-
-
-
-
mail.imap.host
-
String
-
The IMAP server to connect to.
-
-
-
-
mail.imap.port
-
int
-
The IMAP server port to connect to, if the connect() method doesn't
-explicitly specify one. Defaults to 143.
-
-
-
-
mail.imap.partialfetch
-
boolean
-
Controls whether the IMAP partial-fetch capability should be used.
-Defaults to true.
-
-
-
-
mail.imap.fetchsize
-
int
-
Partial fetch size in bytes. Defaults to 16K.
-
-
-
-
mail.imap.ignorebodystructuresize
-
boolean
-
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.
-
-
-
-
mail.imap.connectiontimeout
-
int
-
Socket connection timeout value in milliseconds.
-Default is infinite timeout.
-
-
-
-
mail.imap.timeout
-
int
-
Socket I/O timeout value in milliseconds. Default is infinite timeout.
-
-
-
-
mail.imap.statuscachetimeout
-
int
-
Timeout value in milliseconds for cache of STATUS command response.
-Default is 1000 (1 second). Zero disables cache.
-
-
-
-
mail.imap.appendbuffersize
-
int
-
-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).
-
-
-
-
-
mail.imap.connectionpoolsize
-
int
-
Maximum number of available connections in the connection pool.
-Default is 1.
-
-
-
-
mail.imap.connectionpooltimeout
-
int
-
Timeout value in milliseconds for connection pool connections. Default
-is 45000 (45 seconds).
-
-
-
-
mail.imap.separatestoreconnection
-
boolean
-
Flag to indicate whether to use a dedicated store connection for store
-commands. Default is false.
-
-
-
-
mail.imap.allowreadonlyselect
-
boolean
-
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 getMode method on the
-Folder object will return Folder.READ_ONLY
-in this case even though the open method specified
-Folder.READ_WRITE. Default is false.
-
-
-
-
mail.imap.auth.login.disable
-
boolean
-
If true, prevents use of the non-standard AUTHENTICATE LOGIN
-command, instead using the plain LOGIN command.
-Default is false.
-
-
-
-
mail.imap.auth.plain.disable
-
boolean
-
If true, prevents use of the AUTHENTICATE PLAIN command.
-Default is false.
-
-
-
-
mail.imap.auth.ntlm.disable
-
boolean
-
If true, prevents use of the AUTHENTICATE NTLM command.
-Default is false.
-
-
-
-
mail.imap.proxyauth.user
-
String
-
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 PROXYAUTH command with
-the user name specified in this property.
-
-
-
-
-
mail.imap.localaddress
-
String
-
-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.
-
-
-
-
-
mail.imap.localport
-
int
-
-Local port number to bind to when creating the IMAP socket.
-Defaults to the port number picked by the Socket class.
-
-
-
-
-
mail.imap.sasl.enable
-
boolean
-
-If set to true, attempt to use the javax.security.sasl package to
-choose an authentication mechanism for login.
-Defaults to false.
-
-
-
-
-
mail.imap.sasl.mechanisms
-
String
-
-A space or comma separated list of SASL mechanism names to try
-to use.
-
-
-
-
-
mail.imap.sasl.authorizationid
-
String
-
-The authorization ID to use in the SASL authentication.
-If not set, the authentication ID (user name) is used.
-
-
-
-
-
mail.imap.sasl.realm
-
String
-
The realm to use with SASL authentication mechanisms that
-require a realm, such as DIGEST-MD5.
-
-
-
-
mail.imap.sasl. xgwtrustedapphack.enable
-
boolean
-
-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.
-
-If set to a class that implements the
-javax.net.SocketFactory 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
-put method, not the setProperty method.
-
-
-
-
-
mail.imap.socketFactory.class
-
String
-
-If set, specifies the name of a class that implements the
-javax.net.SocketFactory interface. This class
-will be used to create IMAP sockets.
-
-
-
-
-
mail.imap.socketFactory.fallback
-
boolean
-
-If set to true, failure to create a socket using the specified
-socket factory class will cause the socket to be created using
-the java.net.Socket class.
-Defaults to true.
-
-
-
-
-
mail.imap.socketFactory.port
-
int
-
-Specifies the port to connect to when using the specified socket
-factory.
-If not set, the default port will be used.
-
-
-
-
-
mail.imap.ssl.enable
-
boolean
-
-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.
-
-
-
-
-
mail.imap.ssl.checkserveridentity
-
boolean
-
-If set to true, check the server identity as specified by
-RFC 2595.
-These additional checks based on the content of the server's certificate
-are intended to prevent man-in-the-middle attacks.
-Defaults to false.
-
-
-
-
-
mail.imap.ssl.trust
-
String
-
-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.
-
-
-
-
-
mail.imap.ssl.socketFactory
-
SSLSocketFactory
-
-If set to a class that extends the
-javax.net.ssl.SSLSocketFactory 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
-put method, not the setProperty method.
-
-
-
-
-
mail.imap.ssl.socketFactory.class
-
String
-
-If set, specifies the name of a class that extends the
-javax.net.ssl.SSLSocketFactory class. This class
-will be used to create IMAP SSL sockets.
-
-
-
-
-
mail.imap.ssl.socketFactory.port
-
int
-
-Specifies the port to connect to when using the specified socket
-factory.
-If not set, the default port will be used.
-
-
-
-
-
mail.imap.ssl.protocols
-
string
-
-Specifies the SSL protocols that will be enabled for SSL connections.
-The property value is a whitespace separated list of tokens acceptable
-to the javax.net.ssl.SSLSocket.setEnabledProtocols method.
-
-
-
-
-
mail.imap.ssl.ciphersuites
-
string
-
-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 javax.net.ssl.SSLSocket.setEnabledCipherSuites method.
-
-
-
-
-
mail.imap.starttls.enable
-
boolean
-
If true, enables the use of the STARTTLS 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.
-
-
-
-
mail.imap.starttls.required
-
boolean
-
-If true, requires the use of the STARTTLS command.
-If the server doesn't support the STARTTLS command, or the command
-fails, the connect method will fail.
-Defaults to false.
-
-
-
-
-
mail.imap.socks.host
-
string
-
-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.)
-
-
-
-
-
mail.imap.socks.port
-
string
-
-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.
-
-
-
-
-
mail.imap.minidletime
-
int
-
-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.
-
-
-
-
-
mail.imap.enableimapevents
-
boolean
-
-Enable special IMAP-specific events to be delivered to the Store's
-ConnectionListener. If true, unsolicited responses
-received during the Store's idle method will be sent
-as ConnectionEvents with a type of
-IMAPStore.RESPONSE. 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.
-
-
-
-
-
mail.imap.folder.class
-
String
-
-Class name of a subclass of com.sun.mail.imap.IMAPFolder.
-The subclass can be used to provide support for additional IMAP commands.
-The subclass must have public constructors of the form
-public MyIMAPFolder(String fullName, char separator, IMAPStore store,
-Boolean isNamespace) and
-public MyIMAPFolder(ListInfo li, IMAPStore store)
-
-
-
-
-
-In general, applications should not need to use the classes in this
-package directly. Instead, they should use the APIs defined by
-javax.mail package (and subpackages). Applications should
-never construct instances of IMAPStore or
-IMAPFolder directly. Instead, they should use the
-Session method getStore to acquire an
-appropriate Store object, and from that acquire
-Folder objects.
-
-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:
-
-
-
-
Logger Name
-
Logging Level
-
Purpose
-
-
-
-
com.sun.mail.imap
-
CONFIG
-
Configuration of the IMAPStore
-
-
-
-
com.sun.mail.imap
-
FINE
-
General debugging output
-
-
-
-
com.sun.mail.imap.connectionpool
-
CONFIG
-
Configuration of the IMAP connection pool
-
-
-
-
com.sun.mail.imap.connectionpool
-
FINE
-
Debugging output related to the IMAP connection pool
-
-
-
-
com.sun.mail.imap.messagecache
-
CONFIG
-
Configuration of the IMAP message cache
-
-
-
-
com.sun.mail.imap.messagecache
-
FINE
-
Debugging output related to the IMAP message cache
-
-
-
-
com.sun.mail.imap.protocol
-
FINEST
-
Complete protocol trace
-
-
-
-
-WARNING: The APIs unique to this package should be
-considered EXPERIMENTAL. They may be changed in the
-future in ways that are incompatible with applications using the
-current APIs.
-
-
-
diff --git a/src/main/java/com/sun/mail/imap/protocol/BASE64MailboxDecoder.java b/src/main/java/com/sun/mail/imap/protocol/BASE64MailboxDecoder.java
deleted file mode 100644
index 9f0a8df5..00000000
--- a/src/main/java/com/sun/mail/imap/protocol/BASE64MailboxDecoder.java
+++ /dev/null
@@ -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;
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/protocol/BASE64MailboxEncoder.java b/src/main/java/com/sun/mail/imap/protocol/BASE64MailboxEncoder.java
deleted file mode 100644
index 55998fa0..00000000
--- a/src/main/java/com/sun/mail/imap/protocol/BASE64MailboxEncoder.java
+++ /dev/null
@@ -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
- };
-}
diff --git a/src/main/java/com/sun/mail/imap/protocol/BODY.java b/src/main/java/com/sun/mail/imap/protocol/BODY.java
deleted file mode 100644
index 040a9aa5..00000000
--- a/src/main/java/com/sun/mail/imap/protocol/BODY.java
+++ /dev/null
@@ -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;
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/protocol/BODYSTRUCTURE.java b/src/main/java/com/sun/mail/imap/protocol/BODYSTRUCTURE.java
deleted file mode 100644
index 580d4bb4..00000000
--- a/src/main/java/com/sun/mail/imap/protocol/BODYSTRUCTURE.java
+++ /dev/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();
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/protocol/ENVELOPE.java b/src/main/java/com/sun/mail/imap/protocol/ENVELOPE.java
deleted file mode 100644
index 5ea81c62..00000000
--- a/src/main/java/com/sun/mail/imap/protocol/ENVELOPE.java
+++ /dev/null
@@ -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();
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/protocol/FLAGS.java b/src/main/java/com/sun/mail/imap/protocol/FLAGS.java
deleted file mode 100644
index b8be7810..00000000
--- a/src/main/java/com/sun/mail/imap/protocol/FLAGS.java
+++ /dev/null
@@ -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);
- }
- }
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/protocol/FetchItem.java b/src/main/java/com/sun/mail/imap/protocol/FetchItem.java
deleted file mode 100644
index a1dd0da0..00000000
--- a/src/main/java/com/sun/mail/imap/protocol/FetchItem.java
+++ /dev/null
@@ -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.
- *
- * @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;
-}
diff --git a/src/main/java/com/sun/mail/imap/protocol/FetchResponse.java b/src/main/java/com/sun/mail/imap/protocol/FetchResponse.java
deleted file mode 100644
index a87d822d..00000000
--- a/src/main/java/com/sun/mail/imap/protocol/FetchResponse.java
+++ /dev/null
@@ -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;
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/protocol/IMAPProtocol.java b/src/main/java/com/sun/mail/imap/protocol/IMAPProtocol.java
deleted file mode 100644
index 544596b8..00000000
--- a/src/main/java/com/sun/mail/imap/protocol/IMAPProtocol.java
+++ /dev/null
@@ -1,2467 +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.io.*;
-import java.util.*;
-import java.text.*;
-import java.lang.reflect.*;
-import java.util.logging.Level;
-
-import javax.mail.*;
-import javax.mail.internet.*;
-import javax.mail.search.*;
-
-import com.sun.mail.util.*;
-import com.sun.mail.iap.*;
-import com.sun.mail.auth.Ntlm;
-
-import com.sun.mail.imap.ACL;
-import com.sun.mail.imap.Rights;
-import com.sun.mail.imap.AppendUID;
-import com.sun.mail.imap.SortTerm;
-
-/**
- * This class extends the iap.Protocol object and implements IMAP
- * semantics. In general, there is a method corresponding to each
- * IMAP protocol command. The typical implementation issues the
- * appropriate protocol command, collects all responses, processes
- * those responses that are specific to this command and then
- * dispatches the rest (the unsolicited ones) to the dispatcher
- * using the notifyResponseHandlers(r).
- *
- * @author John Mani
- * @author Bill Shannon
- */
-
-public class IMAPProtocol extends Protocol {
-
- private boolean connected = false; // did constructor succeed?
- private boolean rev1 = false; // REV1 server ?
- private boolean noauthdebug = true; // hide auth info in debug output
- private boolean authenticated; // authenticated?
- // WARNING: authenticated may be set to true in superclass
- // constructor, don't initialize it here.
-
- private Map capabilities;
- // WARNING: capabilities may be initialized as a result of superclass
- // constructor, don't initialize it here.
- private List authmechs;
- // WARNING: authmechs may be initialized as a result of superclass
- // constructor, don't initialize it here.
-
- protected SearchSequence searchSequence;
- protected String[] searchCharsets; // array of search charsets
-
- private String name;
- private SaslAuthenticator saslAuthenticator; // if SASL is being used
-
- private ByteArray ba; // a buffer for fetchBody
-
- private static final byte[] CRLF = { (byte)'\r', (byte)'\n'};
-
- private static final FetchItem[] fetchItems = { };
-
- /**
- * Constructor.
- * Opens a connection to the given host at given port.
- *
- * @param host host to connect to
- * @param port portnumber to connect to
- * @param debug debug mode
- * @param props Properties object used by this protocol
- */
- public IMAPProtocol(String name, String host, int port,
- Properties props, boolean isSSL, MailLogger logger)
- throws IOException, ProtocolException {
- super(host, port, props, "mail." + name, isSSL, logger);
-
- try {
- this.name = name;
- noauthdebug =
- !PropUtil.getBooleanProperty(props, "mail.debug.auth", false);
-
- if (capabilities == null)
- capability();
-
- if (hasCapability("IMAP4rev1"))
- rev1 = true;
-
- searchCharsets = new String[2]; // 2, for now.
- searchCharsets[0] = "UTF-8";
- searchCharsets[1] = MimeUtility.mimeCharset(
- MimeUtility.getDefaultJavaCharset()
- );
-
- 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();
- }
- }
-
- /**
- * Return an array of FetchItem objects describing the
- * FETCH items supported by this protocol. Subclasses may
- * override this method to combine their FetchItems with
- * the FetchItems returned by the superclass.
- *
- * @since JavaMail 1.4.6
- */
- public FetchItem[] getFetchItems() {
- return fetchItems;
- }
-
- /**
- * CAPABILITY command.
- *
- * @see "RFC2060, section 6.1.1"
- */
- public void capability() throws ProtocolException {
- // Check CAPABILITY
- Response[] r = command("CAPABILITY", null);
-
- if (!r[r.length-1].isOK())
- throw new ProtocolException(r[r.length-1].toString());
-
- capabilities = new HashMap(10);
- authmechs = new ArrayList(5);
- for (int i = 0, len = r.length; i < len; i++) {
- if (!(r[i] instanceof IMAPResponse))
- continue;
-
- IMAPResponse ir = (IMAPResponse)r[i];
-
- // Handle *all* untagged CAPABILITY responses.
- // Though the spec seemingly states that only
- // one CAPABILITY response string is allowed (6.1.1),
- // some server vendors claim otherwise.
- if (ir.keyEquals("CAPABILITY"))
- parseCapabilities(ir);
- }
- }
-
- /**
- * If the response contains a CAPABILITY response code, extract
- * it and save the capabilities.
- */
- protected void setCapabilities(Response r) {
- byte b;
- while ((b = r.readByte()) > 0 && b != (byte)'[')
- ;
- if (b == 0)
- return;
- String s;
- s = r.readAtom();
- if (!s.equalsIgnoreCase("CAPABILITY"))
- return;
- capabilities = new HashMap(10);
- authmechs = new ArrayList(5);
- parseCapabilities(r);
- }
-
- /**
- * Parse the capabilities from a CAPABILITY response or from
- * a CAPABILITY response code attached to (e.g.) an OK response.
- */
- protected void parseCapabilities(Response r) {
- String s;
- while ((s = r.readAtom(']')) != null) {
- if (s.length() == 0) {
- if (r.peekByte() == (byte)']')
- break;
- /*
- * Probably found something here that's not an atom.
- * Rather than loop forever or fail completely, we'll
- * try to skip this bogus capability. This is known
- * to happen with:
- * Netscape Messaging Server 4.03 (built Apr 27 1999)
- * that returns:
- * * CAPABILITY * CAPABILITY IMAP4 IMAP4rev1 ...
- * The "*" in the middle of the capability list causes
- * us to loop forever here.
- */
- r.skipToken();
- } else {
- capabilities.put(s.toUpperCase(Locale.ENGLISH), s);
- if (s.regionMatches(true, 0, "AUTH=", 0, 5)) {
- authmechs.add(s.substring(5));
- if (logger.isLoggable(Level.FINE))
- logger.fine("AUTH: " + s.substring(5));
- }
- }
- }
- }
-
- /**
- * Check the greeting when first connecting; look for PREAUTH response.
- */
- protected void processGreeting(Response r) throws ProtocolException {
- super.processGreeting(r); // check if it's BAD
- if (r.isOK()) { // check if it's OK
- setCapabilities(r);
- return;
- }
- // only other choice is PREAUTH
- IMAPResponse ir = (IMAPResponse)r;
- if (ir.keyEquals("PREAUTH")) {
- authenticated = true;
- setCapabilities(r);
- } else
- throw new ConnectionException(this, r);
- }
-
- /**
- * Returns true if the connection has been authenticated,
- * either due to a successful login, or due to a PREAUTH greeting response.
- */
- public boolean isAuthenticated() {
- return authenticated;
- }
-
- /**
- * Returns true if this is a IMAP4rev1 server
- */
- public boolean isREV1() {
- return rev1;
- }
-
- /**
- * Returns whether this Protocol supports non-synchronizing literals.
- */
- protected boolean supportsNonSyncLiterals() {
- return hasCapability("LITERAL+");
- }
-
- /**
- * Read a response from the server.
- */
- public Response readResponse() throws IOException, ProtocolException {
- // assert Thread.holdsLock(this);
- // can't assert because it's called from constructor
- IMAPResponse r = new IMAPResponse(this);
- if (r.keyEquals("FETCH"))
- r = new FetchResponse(r, getFetchItems());
- return r;
- }
-
- /**
- * Check whether the given capability is supported by
- * this server. Returns true if so, otherwise
- * returns false.
- */
- public boolean hasCapability(String c) {
- if (c.endsWith("*")) {
- c = c.substring(0, c.length() - 1).toUpperCase(Locale.ENGLISH);
- Iterator it = capabilities.keySet().iterator();
- while (it.hasNext()) {
- if (((String)it.next()).startsWith(c))
- return true;
- }
- return false;
- }
- return capabilities.containsKey(c.toUpperCase(Locale.ENGLISH));
- }
-
- /**
- * Return the map of capabilities returned by the server.
- *
- * @since JavaMail 1.4.1
- */
- public Map getCapabilities() {
- return capabilities;
- }
-
- /**
- * Close socket connection.
- *
- * This method just makes the Protocol.disconnect() method
- * public.
- */
- public void disconnect() {
- super.disconnect();
- authenticated = false; // just in case
- }
-
- /**
- * The NOOP command.
- *
- * @see "RFC2060, section 6.1.2"
- */
- public void noop() throws ProtocolException {
- logger.fine("IMAPProtocol noop");
- simpleCommand("NOOP", null);
- }
-
- /**
- * LOGOUT Command.
- *
- * @see "RFC2060, section 6.1.3"
- */
- public void logout() throws ProtocolException {
- try {
- Response[] r = command("LOGOUT", null);
-
- authenticated = false;
- // dispatch any unsolicited responses.
- // NOTE that the BYE response is dispatched here as well
- notifyResponseHandlers(r);
- } finally {
- disconnect();
- }
- }
-
- /**
- * LOGIN Command.
- *
- * @see "RFC2060, section 6.2.2"
- */
- public void login(String u, String p) throws ProtocolException {
- Argument args = new Argument();
- args.writeString(u);
- args.writeString(p);
-
- Response[] r = null;
- try {
- if (noauthdebug && isTracing()) {
- logger.fine("LOGIN command trace suppressed");
- suspendTracing();
- }
- r = command("LOGIN", args);
- } finally {
- resumeTracing();
- }
-
- // dispatch untagged responses
- notifyResponseHandlers(r);
-
- // Handle result of this command
- if (noauthdebug && isTracing())
- logger.fine("LOGIN command result: " + r[r.length-1]);
- handleResult(r[r.length-1]);
- // If the response includes a CAPABILITY response code, process it
- setCapabilities(r[r.length-1]);
- // if we get this far without an exception, we're authenticated
- authenticated = true;
- }
-
- /**
- * The AUTHENTICATE command with AUTH=LOGIN authenticate scheme
- *
- * @see "RFC2060, section 6.2.1"
- */
- public synchronized void authlogin(String u, String p)
- throws ProtocolException {
- Vector v = new Vector();
- String tag = null;
- Response r = null;
- boolean done = false;
-
- try {
-
- if (noauthdebug && isTracing()) {
- logger.fine("AUTHENTICATE LOGIN command trace suppressed");
- suspendTracing();
- }
-
- try {
- tag = writeCommand("AUTHENTICATE LOGIN", null);
- } catch (Exception ex) {
- // Convert this into a BYE response
- r = Response.byeResponse(ex);
- done = true;
- }
-
- OutputStream os = getOutputStream(); // 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 !
- *
- * Finally, format the line in a buffer so it can be sent as
- * a single packet, to avoid triggering a bug in SUN's SIMS 2.0
- * server caused by patch 105346.
- */
-
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- OutputStream b64os = new BASE64EncoderStream(bos, Integer.MAX_VALUE);
- boolean first = true;
-
- while (!done) { // loop till we are done
- try {
- r = readResponse();
- if (r.isContinuation()) {
- // Server challenge ..
- String s;
- if (first) { // Send encoded username
- s = u;
- first = false;
- } else // Send encoded password
- s = p;
-
- // obtain b64 encoded bytes
- b64os.write(ASCIIUtility.getBytes(s));
- b64os.flush(); // complete the encoding
-
- 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) {
- // convert this into a BYE response
- r = Response.byeResponse(ioex);
- done = true;
- }
- }
-
- } finally {
- resumeTracing();
- }
-
- /* 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);
- notifyResponseHandlers(responses);
-
- // Handle the final OK, NO, BAD or BYE response
- if (noauthdebug && isTracing())
- logger.fine("AUTHENTICATE LOGIN command result: " + r);
- handleResult(r);
- // If the response includes a CAPABILITY response code, process it
- setCapabilities(r);
- // if we get this far without an exception, we're authenticated
- authenticated = true;
- }
-
-
- /**
- * The AUTHENTICATE command with AUTH=PLAIN authentication scheme.
- * This is based heavly on the {@link #authlogin} method.
- *
- * @param authzid the authorization id
- * @param u the username
- * @param p the password
- * @throws ProtocolException as thrown by {@link Protocol#handleResult}.
- * @see "RFC3501, section 6.2.2"
- * @see "RFC2595, section 6"
- * @since JavaMail 1.3.2
- */
- public synchronized void authplain(String authzid, String u, String p)
- throws ProtocolException {
- Vector v = new Vector();
- String tag = null;
- Response r = null;
- boolean done = false;
-
- try {
-
- if (noauthdebug && isTracing()) {
- logger.fine("AUTHENTICATE PLAIN command trace suppressed");
- suspendTracing();
- }
-
- try {
- tag = writeCommand("AUTHENTICATE PLAIN", null);
- } catch (Exception ex) {
- // Convert this into a BYE response
- r = Response.byeResponse(ex);
- done = true;
- }
-
- OutputStream os = getOutputStream(); // 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 !
- *
- * Finally, format the line in a buffer so it can be sent as
- * a single packet, to avoid triggering a bug in SUN's SIMS 2.0
- * server caused by patch 105346.
- */
-
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- OutputStream b64os = new BASE64EncoderStream(bos, Integer.MAX_VALUE);
-
- while (!done) { // loop till we are done
- try {
- r = readResponse();
- if (r.isContinuation()) {
- // Server challenge ..
- final String nullByte = "\0";
- String s = (authzid == null ? "" : authzid) +
- nullByte + u + nullByte + p;
-
- // obtain b64 encoded bytes
- b64os.write(ASCIIUtility.getBytes(s));
- b64os.flush(); // complete the encoding
-
- 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) {
- // convert this into a BYE response
- r = Response.byeResponse(ioex);
- done = true;
- }
- }
-
- } finally {
- resumeTracing();
- }
-
- /* 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);
- notifyResponseHandlers(responses);
-
- // Handle the final OK, NO, BAD or BYE response
- if (noauthdebug && isTracing())
- logger.fine("AUTHENTICATE PLAIN command result: " + r);
- handleResult(r);
- // If the response includes a CAPABILITY response code, process it
- setCapabilities(r);
- // if we get this far without an exception, we're authenticated
- authenticated = true;
- }
-
- /**
- * The AUTHENTICATE command with AUTH=NTLM authentication scheme.
- * This is based heavly on the {@link #authlogin} method.
- *
- * @param authzid the authorization id
- * @param u the username
- * @param p the password
- * @throws ProtocolException as thrown by {@link Protocol#handleResult}.
- * @see "RFC3501, section 6.2.2"
- * @see "RFC2595, section 6"
- * @since JavaMail 1.4.3
- */
- public synchronized void authntlm(String authzid, String u, String p)
- throws ProtocolException {
- Vector v = new Vector();
- String tag = null;
- Response r = null;
- boolean done = false;
-
- String type1Msg = null;
- int flags = PropUtil.getIntProperty(props,
- "mail." + name + ".auth.ntlm.flags", 0);
- String domain = props.getProperty(
- "mail." + name + ".auth.ntlm.domain", "");
- Ntlm ntlm = new Ntlm(domain, getLocalHost(), u, p, logger);
-
- try {
-
- if (noauthdebug && isTracing()) {
- logger.fine("AUTHENTICATE NTLM command trace suppressed");
- suspendTracing();
- }
-
- try {
- tag = writeCommand("AUTHENTICATE NTLM", null);
- } catch (Exception ex) {
- // Convert this into a BYE response
- r = Response.byeResponse(ex);
- done = true;
- }
-
- OutputStream os = getOutputStream(); // stream to IMAP server
- boolean first = true;
-
- while (!done) { // loop till we are done
- try {
- r = readResponse();
- if (r.isContinuation()) {
- // Server challenge ..
- String s;
- if (first) {
- s = ntlm.generateType1Msg(flags);
- first = false;
- } else {
- s = ntlm.generateType3Msg(r.getRest());
- }
-
- os.write(ASCIIUtility.getBytes(s));
- os.write(CRLF); // CRLF termination
- os.flush(); // flush the stream
- } 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) {
- // convert this into a BYE response
- r = Response.byeResponse(ioex);
- done = true;
- }
- }
-
- } finally {
- resumeTracing();
- }
-
- /*
- * 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);
- notifyResponseHandlers(responses);
-
- // Handle the final OK, NO, BAD or BYE response
- if (noauthdebug && isTracing())
- logger.fine("AUTHENTICATE NTLM command result: " + r);
- handleResult(r);
- // If the response includes a CAPABILITY response code, process it
- setCapabilities(r);
- // if we get this far without an exception, we're authenticated
- authenticated = true;
- }
-
- /**
- * SASL-based login.
- */
- public void sasllogin(String[] allowed, String realm, String authzid,
- String u, String p) throws ProtocolException {
- if (saslAuthenticator == null) {
- try {
- Class sac = Class.forName(
- "com.sun.mail.imap.protocol.IMAPSaslAuthenticator");
- Constructor c = sac.getConstructor(new Class[] {
- IMAPProtocol.class,
- String.class,
- Properties.class,
- MailLogger.class,
- String.class
- });
- saslAuthenticator = (SaslAuthenticator)c.newInstance(
- new Object[] {
- this,
- name,
- props,
- logger,
- host
- });
- } catch (Exception ex) {
- logger.log(Level.FINE, "Can't load SASL authenticator", ex);
- // probably because we're running on a system without SASL
- return; // not authenticated, try without SASL
- }
- }
-
- // were any allowed mechanisms specified?
- List v;
- if (allowed != null && allowed.length > 0) {
- // remove anything not supported by the server
- v = new ArrayList(allowed.length);
- for (int i = 0; i < allowed.length; i++)
- if (authmechs.contains(allowed[i])) // XXX - case must match
- v.add(allowed[i]);
- } else {
- // everything is allowed
- v = authmechs;
- }
- String[] mechs = (String[])v.toArray(new String[v.size()]);
-
- try {
-
- if (noauthdebug && isTracing()) {
- logger.fine("SASL authentication command trace suppressed");
- suspendTracing();
- }
-
- if (saslAuthenticator.authenticate(mechs, realm, authzid, u, p)) {
- if (noauthdebug && isTracing())
- logger.fine("SASL authentication succeeded");
- authenticated = true;
- } else {
- if (noauthdebug && isTracing())
- logger.fine("SASL authentication failed");
- }
- } finally {
- resumeTracing();
- }
- }
-
- // XXX - for IMAPSaslAuthenticator access to protected method
- OutputStream getIMAPOutputStream() {
- return getOutputStream();
- }
-
- /**
- * PROXYAUTH Command.
- *
- * @see "Netscape/iPlanet/SunONE Messaging Server extension"
- */
- public void proxyauth(String u) throws ProtocolException {
- Argument args = new Argument();
- args.writeString(u);
-
- simpleCommand("PROXYAUTH", args);
- }
-
- /**
- * ID Command, for Yahoo! Mail IMAP server.
- *
- * See
- * http://en.wikipedia.org/wiki/Yahoo%21_Mail#Free_IMAP_and_SMTPs_access
- *
- * @since JavaMail 1.4.4
- */
- public void id(String guid) throws ProtocolException {
- /*
- * XXX - need to be able to write a string instead
- * of an astring for the following to work.
- Argument garg = new Argument();
- garg.writeString("GUID");
- garg.writeString(guid);
- Argument args = new Argument();
- args.writeArgument(garg);
- simpleCommand("ID", args);
- */
- simpleCommand("ID (\"GUID\" \"" + guid + "\")", null);
- }
-
- /**
- * STARTTLS Command.
- *
- * @see "RFC3501, section 6.2.1"
- */
- public void startTLS() throws ProtocolException {
- try {
- super.startTLS("STARTTLS");
- } catch (ProtocolException pex) {
- logger.log(Level.FINE, "STARTTLS ProtocolException", pex);
- // ProtocolException just means the command wasn't recognized,
- // or failed. This should never happen if we check the
- // CAPABILITY first.
- throw pex;
- } catch (Exception ex) {
- logger.log(Level.FINE, "STARTTLS Exception", ex);
- // any other exception means we have to shut down the connection
- // generate an artificial BYE response and disconnect
- Response[] r = { Response.byeResponse(ex) };
- notifyResponseHandlers(r);
- disconnect();
- throw new ProtocolException("STARTTLS failure", ex);
- }
- }
-
- /**
- * SELECT Command.
- *
- * @see "RFC2060, section 6.3.1"
- */
- public MailboxInfo select(String mbox) throws ProtocolException {
- // encode the mbox as per RFC2060
- mbox = BASE64MailboxEncoder.encode(mbox);
-
- Argument args = new Argument();
- args.writeString(mbox);
-
- Response[] r = command("SELECT", args);
-
- // Note that MailboxInfo also removes those responses
- // it knows about
- MailboxInfo minfo = new MailboxInfo(r);
-
- // dispatch any remaining untagged responses
- notifyResponseHandlers(r);
-
- Response response = r[r.length-1];
-
- if (response.isOK()) { // command succesful
- if (response.toString().indexOf("READ-ONLY") != -1)
- minfo.mode = Folder.READ_ONLY;
- else
- minfo.mode = Folder.READ_WRITE;
- }
-
- handleResult(response);
- return minfo;
- }
-
- /**
- * EXAMINE Command.
- *
- * @see "RFC2060, section 6.3.2"
- */
- public MailboxInfo examine(String mbox) throws ProtocolException {
- // encode the mbox as per RFC2060
- mbox = BASE64MailboxEncoder.encode(mbox);
-
- Argument args = new Argument();
- args.writeString(mbox);
-
- Response[] r = command("EXAMINE", args);
-
- // Note that MailboxInfo also removes those responses
- // it knows about
- MailboxInfo minfo = new MailboxInfo(r);
- minfo.mode = Folder.READ_ONLY; // Obviously
-
- // dispatch any remaining untagged responses
- notifyResponseHandlers(r);
-
- handleResult(r[r.length-1]);
- return minfo;
- }
-
- /**
- * UNSELECT Command.
- *
- * @see "RFC 3691"
- * @since JavaMail 1.4.4
- */
- public void unselect() throws ProtocolException {
- if (!hasCapability("UNSELECT"))
- throw new BadCommandException("UNSELECT not supported");
- simpleCommand("UNSELECT", null);
- }
-
- /**
- * STATUS Command.
- *
- * @see "RFC2060, section 6.3.10"
- */
- public Status status(String mbox, String[] items)
- throws ProtocolException {
- if (!isREV1() && !hasCapability("IMAP4SUNVERSION"))
- // STATUS is rev1 only, however the non-rev1 SIMS2.0
- // does support this.
- throw new BadCommandException("STATUS not supported");
-
- // encode the mbox as per RFC2060
- mbox = BASE64MailboxEncoder.encode(mbox);
-
- Argument args = new Argument();
- args.writeString(mbox);
-
- Argument itemArgs = new Argument();
- if (items == null)
- items = Status.standardItems;
-
- for (int i = 0, len = items.length; i < len; i++)
- itemArgs.writeAtom(items[i]);
- args.writeArgument(itemArgs);
-
- Response[] r = command("STATUS", args);
-
- Status status = null;
- Response response = r[r.length-1];
-
- // Grab all STATUS responses
- if (response.isOK()) { // command succesful
- for (int i = 0, len = r.length; i < len; i++) {
- if (!(r[i] instanceof IMAPResponse))
- continue;
-
- IMAPResponse ir = (IMAPResponse)r[i];
- if (ir.keyEquals("STATUS")) {
- if (status == null)
- status = new Status(ir);
- else // collect 'em all
- Status.add(status, new Status(ir));
- r[i] = null;
- }
- }
- }
-
- // dispatch remaining untagged responses
- notifyResponseHandlers(r);
- handleResult(response);
- return status;
- }
-
- /**
- * CREATE Command.
- *
- * @see "RFC2060, section 6.3.3"
- */
- public void create(String mbox) throws ProtocolException {
- // encode the mbox as per RFC2060
- mbox = BASE64MailboxEncoder.encode(mbox);
-
- Argument args = new Argument();
- args.writeString(mbox);
-
- simpleCommand("CREATE", args);
- }
-
- /**
- * DELETE Command.
- *
- * @see "RFC2060, section 6.3.4"
- */
- public void delete(String mbox) throws ProtocolException {
- // encode the mbox as per RFC2060
- mbox = BASE64MailboxEncoder.encode(mbox);
-
- Argument args = new Argument();
- args.writeString(mbox);
-
- simpleCommand("DELETE", args);
- }
-
- /**
- * RENAME Command.
- *
- * @see "RFC2060, section 6.3.5"
- */
- public void rename(String o, String n) throws ProtocolException {
- // encode the mbox as per RFC2060
- o = BASE64MailboxEncoder.encode(o);
- n = BASE64MailboxEncoder.encode(n);
-
- Argument args = new Argument();
- args.writeString(o);
- args.writeString(n);
-
- simpleCommand("RENAME", args);
- }
-
- /**
- * SUBSCRIBE Command.
- *
- * @see "RFC2060, section 6.3.6"
- */
- public void subscribe(String mbox) throws ProtocolException {
- Argument args = new Argument();
- // encode the mbox as per RFC2060
- mbox = BASE64MailboxEncoder.encode(mbox);
- args.writeString(mbox);
-
- simpleCommand("SUBSCRIBE", args);
- }
-
- /**
- * UNSUBSCRIBE Command.
- *
- * @see "RFC2060, section 6.3.7"
- */
- public void unsubscribe(String mbox) throws ProtocolException {
- Argument args = new Argument();
- // encode the mbox as per RFC2060
- mbox = BASE64MailboxEncoder.encode(mbox);
- args.writeString(mbox);
-
- simpleCommand("UNSUBSCRIBE", args);
- }
-
- /**
- * LIST Command.
- *
- * @see "RFC2060, section 6.3.8"
- */
- public ListInfo[] list(String ref, String pattern)
- throws ProtocolException {
- return doList("LIST", ref, pattern);
- }
-
- /**
- * LSUB Command.
- *
- * @see "RFC2060, section 6.3.9"
- */
- public ListInfo[] lsub(String ref, String pattern)
- throws ProtocolException {
- return doList("LSUB", ref, pattern);
- }
-
- /**
- * Execute the specified LIST-like command (e.g., "LIST" or "LSUB"),
- * using the reference and pattern.
- *
- * @since JavaMail 1.4.6
- */
- protected ListInfo[] doList(String cmd, String ref, String pat)
- throws ProtocolException {
- // encode the mbox as per RFC2060
- ref = BASE64MailboxEncoder.encode(ref);
- pat = BASE64MailboxEncoder.encode(pat);
-
- Argument args = new Argument();
- args.writeString(ref);
- args.writeString(pat);
-
- Response[] r = command(cmd, args);
-
- ListInfo[] linfo = null;
- Response response = r[r.length-1];
-
- if (response.isOK()) { // command succesful
- Vector v = new Vector(1);
- for (int i = 0, len = r.length; i < len; i++) {
- if (!(r[i] instanceof IMAPResponse))
- continue;
-
- IMAPResponse ir = (IMAPResponse)r[i];
- if (ir.keyEquals(cmd)) {
- v.addElement(new ListInfo(ir));
- r[i] = null;
- }
- }
- if (v.size() > 0) {
- linfo = new ListInfo[v.size()];
- v.copyInto(linfo);
- }
- }
-
- // Dispatch remaining untagged responses
- notifyResponseHandlers(r);
- handleResult(response);
- return linfo;
- }
-
- /**
- * APPEND Command.
- *
- * @see "RFC2060, section 6.3.11"
- */
- public void append(String mbox, Flags f, Date d,
- Literal data) throws ProtocolException {
- appenduid(mbox, f, d, data, false); // ignore return value
- }
-
- /**
- * APPEND Command, return uid from APPENDUID response code.
- *
- * @see "RFC2060, section 6.3.11"
- */
- public AppendUID appenduid(String mbox, Flags f, Date d,
- Literal data) throws ProtocolException {
- return appenduid(mbox, f, d, data, true);
- }
-
- public AppendUID appenduid(String mbox, Flags f, Date d,
- Literal data, boolean uid) throws ProtocolException {
- // encode the mbox as per RFC2060
- mbox = BASE64MailboxEncoder.encode(mbox);
-
- Argument args = new Argument();
- args.writeString(mbox);
-
- if (f != null) { // set Flags in appended message
- // can't set the \Recent flag in APPEND
- if (f.contains(Flags.Flag.RECENT)) {
- f = new Flags(f); // copy, don't modify orig
- f.remove(Flags.Flag.RECENT); // remove RECENT from copy
- }
-
- /*
- * HACK ALERT: We want the flag_list to be written out
- * without any checking/processing of the bytes in it. If
- * I use writeString(), the flag_list will end up being
- * quoted since it contains "illegal" characters. So I
- * am depending on implementation knowledge that writeAtom()
- * does not do any checking/processing - it just writes out
- * the bytes. What we really need is a writeFoo() that just
- * dumps out its argument.
- */
- args.writeAtom(createFlagList(f));
- }
- if (d != null) // set INTERNALDATE in appended message
- args.writeString(INTERNALDATE.format(d));
-
- args.writeBytes(data);
-
- Response[] r = command("APPEND", args);
-
- // dispatch untagged responses
- notifyResponseHandlers(r);
-
- // Handle result of this command
- handleResult(r[r.length-1]);
-
- if (uid)
- return getAppendUID(r[r.length-1]);
- else
- return null;
- }
-
- /**
- * If the response contains an APPENDUID response code, extract
- * it and return an AppendUID object with the information.
- */
- private AppendUID getAppendUID(Response r) {
- if (!r.isOK())
- return null;
- byte b;
- while ((b = r.readByte()) > 0 && b != (byte)'[')
- ;
- if (b == 0)
- return null;
- String s;
- s = r.readAtom();
- if (!s.equalsIgnoreCase("APPENDUID"))
- return null;
-
- long uidvalidity = r.readLong();
- long uid = r.readLong();
- return new AppendUID(uidvalidity, uid);
- }
-
- /**
- * CHECK Command.
- *
- * @see "RFC2060, section 6.4.1"
- */
- public void check() throws ProtocolException {
- simpleCommand("CHECK", null);
- }
-
- /**
- * CLOSE Command.
- *
- * @see "RFC2060, section 6.4.2"
- */
- public void close() throws ProtocolException {
- simpleCommand("CLOSE", null);
- }
-
- /**
- * EXPUNGE Command.
- *
- * @see "RFC2060, section 6.4.3"
- */
- public void expunge() throws ProtocolException {
- simpleCommand("EXPUNGE", null);
- }
-
- /**
- * UID EXPUNGE Command.
- *
- * @see "RFC2359, section 4.1"
- */
- public void uidexpunge(UIDSet[] set) throws ProtocolException {
- if (!hasCapability("UIDPLUS"))
- throw new BadCommandException("UID EXPUNGE not supported");
- simpleCommand("UID EXPUNGE " + UIDSet.toString(set), null);
- }
-
- /**
- * Fetch the BODYSTRUCTURE of the specified message.
- */
- public BODYSTRUCTURE fetchBodyStructure(int msgno)
- throws ProtocolException {
- Response[] r = fetch(msgno, "BODYSTRUCTURE");
- notifyResponseHandlers(r);
-
- Response response = r[r.length-1];
- if (response.isOK())
- return (BODYSTRUCTURE)FetchResponse.getItem(r, msgno,
- BODYSTRUCTURE.class);
- else if (response.isNO())
- return null;
- else {
- handleResult(response);
- return null;
- }
- }
-
- /**
- * Fetch given BODY section, without marking the message
- * as SEEN.
- */
- public BODY peekBody(int msgno, String section)
- throws ProtocolException {
- return fetchBody(msgno, section, true);
- }
-
- /**
- * Fetch given BODY section.
- */
- public BODY fetchBody(int msgno, String section)
- throws ProtocolException {
- return fetchBody(msgno, section, false);
- }
-
- protected BODY fetchBody(int msgno, String section, boolean peek)
- throws ProtocolException {
- Response[] r;
-
- if (peek)
- r = fetch(msgno,
- "BODY.PEEK[" + (section == null ? "]" : section + "]"));
- else
- r = fetch(msgno,
- "BODY[" + (section == null ? "]" : section + "]"));
-
- notifyResponseHandlers(r);
-
- Response response = r[r.length-1];
- if (response.isOK())
- return (BODY)FetchResponse.getItem(r, msgno, BODY.class);
- else if (response.isNO())
- return null;
- else {
- handleResult(response);
- return null;
- }
- }
-
- /**
- * Partial FETCH of given BODY section, without setting SEEN flag.
- */
- public BODY peekBody(int msgno, String section, int start, int size)
- throws ProtocolException {
- return fetchBody(msgno, section, start, size, true, null);
- }
-
- /**
- * Partial FETCH of given BODY section.
- */
- public BODY fetchBody(int msgno, String section, int start, int size)
- throws ProtocolException {
- return fetchBody(msgno, section, start, size, false, null);
- }
-
- /**
- * Partial FETCH of given BODY section, without setting SEEN flag.
- */
- public BODY peekBody(int msgno, String section, int start, int size,
- ByteArray ba) throws ProtocolException {
- return fetchBody(msgno, section, start, size, true, ba);
- }
-
- /**
- * Partial FETCH of given BODY section.
- */
- public BODY fetchBody(int msgno, String section, int start, int size,
- ByteArray ba) throws ProtocolException {
- return fetchBody(msgno, section, start, size, false, ba);
- }
-
- protected BODY fetchBody(int msgno, String section, int start, int size,
- boolean peek, ByteArray ba) throws ProtocolException {
- this.ba = ba; // save for later use by getResponseBuffer
- Response[] r = fetch(
- msgno, (peek ? "BODY.PEEK[" : "BODY[" ) +
- (section == null ? "]<" : (section +"]<")) +
- String.valueOf(start) + "." +
- String.valueOf(size) + ">"
- );
-
- notifyResponseHandlers(r);
-
- Response response = r[r.length-1];
- if (response.isOK())
- return (BODY)FetchResponse.getItem(r, msgno, BODY.class);
- else if (response.isNO())
- return null;
- else {
- handleResult(response);
- return null;
- }
- }
-
- /**
- * Return a buffer to read a response into.
- * The buffer is provided by fetchBody and is
- * used only once.
- */
- protected ByteArray getResponseBuffer() {
- ByteArray ret = ba;
- ba = null;
- return ret;
- }
-
- /**
- * Fetch the specified RFC822 Data item. 'what' names
- * the item to be fetched. 'what' can be null
- * to fetch the whole message.
- */
- public RFC822DATA fetchRFC822(int msgno, String what)
- throws ProtocolException {
- Response[] r = fetch(msgno,
- what == null ? "RFC822" : "RFC822." + what
- );
-
- // dispatch untagged responses
- notifyResponseHandlers(r);
-
- Response response = r[r.length-1];
- if (response.isOK())
- return (RFC822DATA)FetchResponse.getItem(r, msgno,
- RFC822DATA.class);
- else if (response.isNO())
- return null;
- else {
- handleResult(response);
- return null;
- }
- }
-
- /**
- * Fetch the FLAGS for the given message.
- */
- public Flags fetchFlags(int msgno) throws ProtocolException {
- Flags flags = null;
- Response[] r = fetch(msgno, "FLAGS");
-
- // Search for our FLAGS response
- for (int i = 0, len = r.length; i < len; i++) {
- if (r[i] == null ||
- !(r[i] instanceof FetchResponse) ||
- ((FetchResponse)r[i]).getNumber() != msgno)
- continue;
-
- FetchResponse fr = (FetchResponse)r[i];
- if ((flags = (Flags)fr.getItem(Flags.class)) != null) {
- r[i] = null; // remove this response
- break;
- }
- }
-
- // dispatch untagged responses
- notifyResponseHandlers(r);
- handleResult(r[r.length-1]);
- return flags;
- }
-
- /**
- * Fetch the IMAP UID for the given message.
- */
- public UID fetchUID(int msgno) throws ProtocolException {
- Response[] r = fetch(msgno, "UID");
-
- // dispatch untagged responses
- notifyResponseHandlers(r);
-
- Response response = r[r.length-1];
- if (response.isOK())
- return (UID)FetchResponse.getItem(r, msgno, UID.class);
- else if (response.isNO()) // XXX: Issue NOOP ?
- return null;
- else {
- handleResult(response);
- return null; // NOTREACHED
- }
- }
-
- /**
- * Get the sequence number for the given UID. A UID object
- * containing the sequence number is returned. If the given UID
- * is invalid, null is returned.
- */
- public UID fetchSequenceNumber(long uid) throws ProtocolException {
- UID u = null;
- Response[] r = fetch(String.valueOf(uid), "UID", true);
-
- for (int i = 0, len = r.length; i < len; i++) {
- if (r[i] == null || !(r[i] instanceof FetchResponse))
- continue;
-
- FetchResponse fr = (FetchResponse)r[i];
- if ((u = (UID)fr.getItem(UID.class)) != null) {
- if (u.uid == uid) // this is the one we want
- break;
- else
- u = null;
- }
- }
-
- notifyResponseHandlers(r);
- handleResult(r[r.length-1]);
- return u;
- }
-
- /**
- * Get the sequence numbers for UIDs ranging from start till end.
- * UID objects that contain the sequence numbers are returned.
- * If no UIDs in the given range are found, an empty array is returned.
- */
- public UID[] fetchSequenceNumbers(long start, long end)
- throws ProtocolException {
- Response[] r = fetch(String.valueOf(start) + ":" +
- (end == UIDFolder.LASTUID ? "*" :
- String.valueOf(end)),
- "UID", true);
-
- UID u;
- Vector v = new Vector();
- for (int i = 0, len = r.length; i < len; i++) {
- if (r[i] == null || !(r[i] instanceof FetchResponse))
- continue;
-
- FetchResponse fr = (FetchResponse)r[i];
- if ((u = (UID)fr.getItem(UID.class)) != null)
- v.addElement(u);
- }
-
- notifyResponseHandlers(r);
- handleResult(r[r.length-1]);
-
- UID[] ua = new UID[v.size()];
- v.copyInto(ua);
- return ua;
- }
-
- /**
- * Get the sequence numbers for UIDs ranging from start till end.
- * UID objects that contain the sequence numbers are returned.
- * If no UIDs in the given range are found, an empty array is returned.
- */
- public UID[] fetchSequenceNumbers(long[] uids) throws ProtocolException {
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < uids.length; i++) {
- if (i > 0)
- sb.append(",");
- sb.append(String.valueOf(uids[i]));
- }
-
- Response[] r = fetch(sb.toString(), "UID", true);
-
- UID u;
- Vector v = new Vector();
- for (int i = 0, len = r.length; i < len; i++) {
- if (r[i] == null || !(r[i] instanceof FetchResponse))
- continue;
-
- FetchResponse fr = (FetchResponse)r[i];
- if ((u = (UID)fr.getItem(UID.class)) != null)
- v.addElement(u);
- }
-
- notifyResponseHandlers(r);
- handleResult(r[r.length-1]);
-
- UID[] ua = new UID[v.size()];
- v.copyInto(ua);
- return ua;
- }
-
- public Response[] fetch(MessageSet[] msgsets, String what)
- throws ProtocolException {
- return fetch(MessageSet.toString(msgsets), what, false);
- }
-
- public Response[] fetch(int start, int end, String what)
- throws ProtocolException {
- return fetch(String.valueOf(start) + ":" + String.valueOf(end),
- what, false);
- }
-
- public Response[] fetch(int msg, String what)
- throws ProtocolException {
- return fetch(String.valueOf(msg), what, false);
- }
-
- private Response[] fetch(String msgSequence, String what, boolean uid)
- throws ProtocolException {
- if (uid)
- return command("UID FETCH " + msgSequence +" (" + what + ")",null);
- else
- return command("FETCH " + msgSequence + " (" + what + ")", null);
- }
-
- /**
- * COPY command.
- */
- public void copy(MessageSet[] msgsets, String mbox)
- throws ProtocolException {
- copy(MessageSet.toString(msgsets), mbox);
- }
-
- public void copy(int start, int end, String mbox)
- throws ProtocolException {
- copy(String.valueOf(start) + ":" + String.valueOf(end),
- mbox);
- }
-
- private void copy(String msgSequence, String mbox)
- throws ProtocolException {
- // encode the mbox as per RFC2060
- mbox = BASE64MailboxEncoder.encode(mbox);
-
- Argument args = new Argument();
- args.writeAtom(msgSequence);
- args.writeString(mbox);
-
- simpleCommand("COPY", args);
- }
-
- public void storeFlags(MessageSet[] msgsets, Flags flags, boolean set)
- throws ProtocolException {
- storeFlags(MessageSet.toString(msgsets), flags, set);
- }
-
- public void storeFlags(int start, int end, Flags flags, boolean set)
- throws ProtocolException {
- storeFlags(String.valueOf(start) + ":" + String.valueOf(end),
- flags, set);
- }
-
- /**
- * Set the specified flags on this message.
- */
- public void storeFlags(int msg, Flags flags, boolean set)
- throws ProtocolException {
- storeFlags(String.valueOf(msg), flags, set);
- }
-
- private void storeFlags(String msgset, Flags flags, boolean set)
- throws ProtocolException {
- Response[] r;
- if (set)
- r = command("STORE " + msgset + " +FLAGS " +
- createFlagList(flags), null);
- else
- r = command("STORE " + msgset + " -FLAGS " +
- createFlagList(flags), null);
-
- // Dispatch untagged responses
- notifyResponseHandlers(r);
- handleResult(r[r.length-1]);
- }
-
- /**
- * Creates an IMAP flag_list from the given Flags object.
- */
- private String createFlagList(Flags flags) {
- StringBuffer sb = new StringBuffer();
- sb.append("("); // start of flag_list
-
- Flags.Flag[] sf = flags.getSystemFlags(); // get the system flags
- boolean first = true;
- for (int i = 0; i < sf.length; i++) {
- String s;
- Flags.Flag f = sf[i];
- if (f == Flags.Flag.ANSWERED)
- s = "\\Answered";
- else if (f == Flags.Flag.DELETED)
- s = "\\Deleted";
- else if (f == Flags.Flag.DRAFT)
- s = "\\Draft";
- else if (f == Flags.Flag.FLAGGED)
- s = "\\Flagged";
- else if (f == Flags.Flag.RECENT)
- s = "\\Recent";
- else if (f == Flags.Flag.SEEN)
- s = "\\Seen";
- else
- continue; // skip it
- if (first)
- first = false;
- else
- sb.append(' ');
- sb.append(s);
- }
-
- String[] uf = flags.getUserFlags(); // get the user flag strings
- for (int i = 0; i < uf.length; i++) {
- if (first)
- first = false;
- else
- sb.append(' ');
- sb.append(uf[i]);
- }
-
- sb.append(")"); // terminate flag_list
- return sb.toString();
- }
-
- /**
- * Issue the given search criterion on the specified message sets.
- * Returns array of matching sequence numbers. An empty array
- * is returned if no matches are found.
- *
- * @param msgsets array of MessageSets
- * @param term SearchTerm
- * @return array of matching sequence numbers.
- */
- public int[] search(MessageSet[] msgsets, SearchTerm term)
- throws ProtocolException, SearchException {
- return search(MessageSet.toString(msgsets), term);
- }
-
- /**
- * Issue the given search criterion on all messages in this folder.
- * Returns array of matching sequence numbers. An empty array
- * is returned if no matches are found.
- *
- * @param term SearchTerm
- * @return array of matching sequence numbers.
- */
- public int[] search(SearchTerm term)
- throws ProtocolException, SearchException {
- return search("ALL", term);
- }
-
- /*
- * Apply the given SearchTerm on the specified sequence.
- * Returns array of matching sequence numbers. Note that an empty
- * array is returned for no matches.
- */
- private int[] search(String msgSequence, SearchTerm term)
- throws ProtocolException, SearchException {
- // Check if the search "text" terms contain only ASCII chars
- if (getSearchSequence().isAscii(term)) {
- try {
- return issueSearch(msgSequence, term, null);
- } catch (IOException ioex) { /* will not happen */ }
- }
-
- /*
- * The search "text" terms do contain non-ASCII chars. We need to
- * use SEARCH CHARSET ...
- * The charsets we try to use are UTF-8 and the locale's
- * default charset. If the server supports UTF-8, great,
- * always use it. Else we try to use the default charset.
- */
-
- // Cycle thru the list of charsets
- for (int i = 0; i < searchCharsets.length; i++) {
- if (searchCharsets[i] == null)
- continue;
-
- try {
- return issueSearch(msgSequence, term, searchCharsets[i]);
- } catch (CommandFailedException cfx) {
- /*
- * Server returned NO. For now, I'll just assume that
- * this indicates that this charset is unsupported.
- * We can check the BADCHARSET response code once
- * that's spec'd into the IMAP RFC ..
- */
- searchCharsets[i] = null;
- continue;
- } catch (IOException ioex) {
- /* Charset conversion failed. Try the next one */
- continue;
- } catch (ProtocolException pex) {
- throw pex;
- } catch (SearchException sex) {
- throw sex;
- }
- }
-
- // No luck.
- throw new SearchException("Search failed");
- }
-
- /* Apply the given SearchTerm on the specified sequence, using the
- * given charset.
- * Returns array of matching sequence numbers. Note that an empty
- * array is returned for no matches.
- */
- private int[] issueSearch(String msgSequence, SearchTerm term,
- String charset)
- throws ProtocolException, SearchException, IOException {
-
- // Generate a search-sequence with the given charset
- Argument args = getSearchSequence().generateSequence(term,
- charset == null ? null :
- MimeUtility.javaCharset(charset)
- );
- args.writeAtom(msgSequence);
-
- Response[] r;
-
- if (charset == null) // text is all US-ASCII
- r = command("SEARCH", args);
- else
- r = command("SEARCH CHARSET " + charset, args);
-
- Response response = r[r.length-1];
- int[] matches = null;
-
- // Grab all SEARCH responses
- if (response.isOK()) { // command succesful
- Vector v = new Vector();
- int num;
- for (int i = 0, len = r.length; i < len; i++) {
- if (!(r[i] instanceof IMAPResponse))
- continue;
-
- IMAPResponse ir = (IMAPResponse)r[i];
- // There *will* be one SEARCH response.
- if (ir.keyEquals("SEARCH")) {
- while ((num = ir.readNumber()) != -1)
- v.addElement(new Integer(num));
- r[i] = null;
- }
- }
-
- // Copy the vector into 'matches'
- int vsize = v.size();
- matches = new int[vsize];
- for (int i = 0; i < vsize; i++)
- matches[i] = ((Integer)v.elementAt(i)).intValue();
- }
-
- // dispatch remaining untagged responses
- notifyResponseHandlers(r);
- handleResult(response);
- return matches;
- }
-
- /**
- * Get the SearchSequence object.
- * The SearchSequence object instance is saved in the searchSequence
- * field. Subclasses of IMAPProtocol may override this method to
- * return a subclass of SearchSequence, in order to add support for
- * product-specific search terms.
- *
- * @since JavaMail 1.4.6
- */
- protected SearchSequence getSearchSequence() {
- if (searchSequence == null)
- searchSequence = new SearchSequence();
- return searchSequence;
- }
-
- /**
- * Sort messages in the folder according to the specified sort criteria.
- * If the search term is not null, limit the sort to only the messages
- * that match the search term.
- * Returns an array of sorted sequence numbers. An empty array
- * is returned if no matches are found.
- *
- * @param term sort criteria
- * @param sterm SearchTerm
- * @return array of matching sequence numbers.
- *
- * @see "RFC 5256"
- * @since JavaMail 1.4.4
- */
- public int[] sort(SortTerm[] term, SearchTerm sterm)
- throws ProtocolException, SearchException {
- if (!hasCapability("SORT*"))
- throw new BadCommandException("SORT not supported");
-
- if (term == null || term.length == 0)
- throw new BadCommandException("Must have at least one sort term");
-
- Argument args = new Argument();
- Argument sargs = new Argument();
- for (int i = 0; i < term.length; i++)
- sargs.writeAtom(term[i].toString());
- args.writeArgument(sargs); // sort criteria
-
- args.writeAtom("UTF-8"); // charset specification
- if (sterm != null) {
- try {
- args.append(
- getSearchSequence().generateSequence(sterm, "UTF-8"));
- } catch (IOException ioex) {
- // should never happen
- throw new SearchException(ioex.toString());
- }
- } else
- args.writeAtom("ALL");
-
- Response[] r = command("SORT", args);
- Response response = r[r.length-1];
- int[] matches = null;
-
- // Grab all SORT responses
- if (response.isOK()) { // command succesful
- Vector v = new Vector();
- int num;
- for (int i = 0, len = r.length; i < len; i++) {
- if (!(r[i] instanceof IMAPResponse))
- continue;
-
- IMAPResponse ir = (IMAPResponse)r[i];
- if (ir.keyEquals("SORT")) {
- while ((num = ir.readNumber()) != -1)
- v.addElement(new Integer(num));
- r[i] = null;
- }
- }
-
- // Copy the vector into 'matches'
- int vsize = v.size();
- matches = new int[vsize];
- for (int i = 0; i < vsize; i++)
- matches[i] = ((Integer)v.elementAt(i)).intValue();
- }
-
- // dispatch remaining untagged responses
- notifyResponseHandlers(r);
- handleResult(response);
- return matches;
- }
-
- /**
- * NAMESPACE Command.
- *
- * @see "RFC2342"
- */
- public Namespaces namespace() throws ProtocolException {
- if (!hasCapability("NAMESPACE"))
- throw new BadCommandException("NAMESPACE not supported");
-
- Response[] r = command("NAMESPACE", null);
-
- Namespaces namespace = null;
- Response response = r[r.length-1];
-
- // Grab NAMESPACE response
- if (response.isOK()) { // command succesful
- for (int i = 0, len = r.length; i < len; i++) {
- if (!(r[i] instanceof IMAPResponse))
- continue;
-
- IMAPResponse ir = (IMAPResponse)r[i];
- if (ir.keyEquals("NAMESPACE")) {
- if (namespace == null)
- namespace = new Namespaces(ir);
- r[i] = null;
- }
- }
- }
-
- // dispatch remaining untagged responses
- notifyResponseHandlers(r);
- handleResult(response);
- return namespace;
- }
-
- /**
- * GETQUOTAROOT Command.
- *
- * Returns an array of Quota objects, representing the quotas
- * for this mailbox and, indirectly, the quotaroots for this
- * mailbox.
- *
- * @see "RFC2087"
- */
- public Quota[] getQuotaRoot(String mbox) throws ProtocolException {
- if (!hasCapability("QUOTA"))
- throw new BadCommandException("GETQUOTAROOT not supported");
-
- // encode the mbox as per RFC2060
- mbox = BASE64MailboxEncoder.encode(mbox);
-
- Argument args = new Argument();
- args.writeString(mbox);
-
- Response[] r = command("GETQUOTAROOT", args);
-
- Response response = r[r.length-1];
-
- Hashtable tab = new Hashtable();
-
- // Grab all QUOTAROOT and QUOTA responses
- if (response.isOK()) { // command succesful
- for (int i = 0, len = r.length; i < len; i++) {
- if (!(r[i] instanceof IMAPResponse))
- continue;
-
- IMAPResponse ir = (IMAPResponse)r[i];
- if (ir.keyEquals("QUOTAROOT")) {
- // quotaroot_response
- // ::= "QUOTAROOT" SP astring *(SP astring)
-
- // read name of mailbox and throw away
- ir.readAtomString();
- // for each quotaroot add a placeholder quota
- String root = null;
- while ((root = ir.readAtomString()) != null &&
- root.length() > 0)
- tab.put(root, new Quota(root));
- r[i] = null;
- } else if (ir.keyEquals("QUOTA")) {
- Quota quota = parseQuota(ir);
- Quota q = (Quota)tab.get(quota.quotaRoot);
- if (q != null && q.resources != null) {
- // XXX - should merge resources
- }
- tab.put(quota.quotaRoot, quota);
- r[i] = null;
- }
- }
- }
-
- // dispatch remaining untagged responses
- notifyResponseHandlers(r);
- handleResult(response);
-
- Quota[] qa = new Quota[tab.size()];
- Enumeration e = tab.elements();
- for (int i = 0; e.hasMoreElements(); i++)
- qa[i] = (Quota)e.nextElement();
- return qa;
- }
-
- /**
- * GETQUOTA Command.
- *
- * Returns an array of Quota objects, representing the quotas
- * for this quotaroot.
- *
- * @see "RFC2087"
- */
- public Quota[] getQuota(String root) throws ProtocolException {
- if (!hasCapability("QUOTA"))
- throw new BadCommandException("QUOTA not supported");
-
- Argument args = new Argument();
- args.writeString(root);
-
- Response[] r = command("GETQUOTA", args);
-
- Quota quota = null;
- Vector v = new Vector();
- Response response = r[r.length-1];
-
- // Grab all QUOTA responses
- if (response.isOK()) { // command succesful
- for (int i = 0, len = r.length; i < len; i++) {
- if (!(r[i] instanceof IMAPResponse))
- continue;
-
- IMAPResponse ir = (IMAPResponse)r[i];
- if (ir.keyEquals("QUOTA")) {
- quota = parseQuota(ir);
- v.addElement(quota);
- r[i] = null;
- }
- }
- }
-
- // dispatch remaining untagged responses
- notifyResponseHandlers(r);
- handleResult(response);
- Quota[] qa = new Quota[v.size()];
- v.copyInto(qa);
- return qa;
- }
-
- /**
- * SETQUOTA Command.
- *
- * Set the indicated quota on the corresponding quotaroot.
- *
- * @see "RFC2087"
- */
- public void setQuota(Quota quota) throws ProtocolException {
- if (!hasCapability("QUOTA"))
- throw new BadCommandException("QUOTA not supported");
-
- Argument args = new Argument();
- args.writeString(quota.quotaRoot);
- Argument qargs = new Argument();
- if (quota.resources != null) {
- for (int i = 0; i < quota.resources.length; i++) {
- qargs.writeAtom(quota.resources[i].name);
- qargs.writeNumber(quota.resources[i].limit);
- }
- }
- args.writeArgument(qargs);
-
- Response[] r = command("SETQUOTA", args);
- Response response = r[r.length-1];
-
- // XXX - It's not clear from the RFC whether the SETQUOTA command
- // will provoke untagged QUOTA responses. If it does, perhaps
- // we should grab them here and return them?
-
- /*
- Quota quota = null;
- Vector v = new Vector();
-
- // Grab all QUOTA responses
- if (response.isOK()) { // command succesful
- for (int i = 0, len = r.length; i < len; i++) {
- if (!(r[i] instanceof IMAPResponse))
- continue;
-
- IMAPResponse ir = (IMAPResponse)r[i];
- if (ir.keyEquals("QUOTA")) {
- quota = parseQuota(ir);
- v.addElement(quota);
- r[i] = null;
- }
- }
- }
- */
-
- // dispatch remaining untagged responses
- notifyResponseHandlers(r);
- handleResult(response);
- /*
- Quota[] qa = new Quota[v.size()];
- v.copyInto(qa);
- return qa;
- */
- }
-
- /**
- * Parse a QUOTA response.
- */
- private Quota parseQuota(Response r) throws ParsingException {
- // quota_response ::= "QUOTA" SP astring SP quota_list
- String quotaRoot = r.readAtomString(); // quotaroot ::= astring
- Quota q = new Quota(quotaRoot);
- r.skipSpaces();
- // quota_list ::= "(" #quota_resource ")"
- if (r.readByte() != '(')
- throw new ParsingException("parse error in QUOTA");
-
- Vector v = new Vector();
- while (r.peekByte() != ')') {
- // quota_resource ::= atom SP number SP number
- String name = r.readAtom();
- if (name != null) {
- long usage = r.readLong();
- long limit = r.readLong();
- Quota.Resource res = new Quota.Resource(name, usage, limit);
- v.addElement(res);
- }
- }
- r.readByte();
- q.resources = new Quota.Resource[v.size()];
- v.copyInto(q.resources);
- return q;
- }
-
-
- /**
- * SETACL Command.
- *
- * @see "RFC2086"
- */
- public void setACL(String mbox, char modifier, ACL acl)
- throws ProtocolException {
- if (!hasCapability("ACL"))
- throw new BadCommandException("ACL not supported");
-
- // encode the mbox as per RFC2060
- mbox = BASE64MailboxEncoder.encode(mbox);
-
- Argument args = new Argument();
- args.writeString(mbox);
- args.writeString(acl.getName());
- String rights = acl.getRights().toString();
- if (modifier == '+' || modifier == '-')
- rights = modifier + rights;
- args.writeString(rights);
-
- Response[] r = command("SETACL", args);
- Response response = r[r.length-1];
-
- // dispatch untagged responses
- notifyResponseHandlers(r);
- handleResult(response);
- }
-
- /**
- * DELETEACL Command.
- *
- * @see "RFC2086"
- */
- public void deleteACL(String mbox, String user) throws ProtocolException {
- if (!hasCapability("ACL"))
- throw new BadCommandException("ACL not supported");
-
- // encode the mbox as per RFC2060
- mbox = BASE64MailboxEncoder.encode(mbox);
-
- Argument args = new Argument();
- args.writeString(mbox);
- args.writeString(user);
-
- Response[] r = command("DELETEACL", args);
- Response response = r[r.length-1];
-
- // dispatch untagged responses
- notifyResponseHandlers(r);
- handleResult(response);
- }
-
- /**
- * GETACL Command.
- *
- * @see "RFC2086"
- */
- public ACL[] getACL(String mbox) throws ProtocolException {
- if (!hasCapability("ACL"))
- throw new BadCommandException("ACL not supported");
-
- // encode the mbox as per RFC2060
- mbox = BASE64MailboxEncoder.encode(mbox);
-
- Argument args = new Argument();
- args.writeString(mbox);
-
- Response[] r = command("GETACL", args);
- Response response = r[r.length-1];
-
- // Grab all ACL responses
- Vector v = new Vector();
- if (response.isOK()) { // command succesful
- for (int i = 0, len = r.length; i < len; i++) {
- if (!(r[i] instanceof IMAPResponse))
- continue;
-
- IMAPResponse ir = (IMAPResponse)r[i];
- if (ir.keyEquals("ACL")) {
- // acl_data ::= "ACL" SPACE mailbox
- // *(SPACE identifier SPACE rights)
- // read name of mailbox and throw away
- ir.readAtomString();
- String name = null;
- while ((name = ir.readAtomString()) != null) {
- String rights = ir.readAtomString();
- if (rights == null)
- break;
- ACL acl = new ACL(name, new Rights(rights));
- v.addElement(acl);
- }
- r[i] = null;
- }
- }
- }
-
- // dispatch remaining untagged responses
- notifyResponseHandlers(r);
- handleResult(response);
- ACL[] aa = new ACL[v.size()];
- v.copyInto(aa);
- return aa;
- }
-
- /**
- * LISTRIGHTS Command.
- *
- * @see "RFC2086"
- */
- public Rights[] listRights(String mbox, String user)
- throws ProtocolException {
- if (!hasCapability("ACL"))
- throw new BadCommandException("ACL not supported");
-
- // encode the mbox as per RFC2060
- mbox = BASE64MailboxEncoder.encode(mbox);
-
- Argument args = new Argument();
- args.writeString(mbox);
- args.writeString(user);
-
- Response[] r = command("LISTRIGHTS", args);
- Response response = r[r.length-1];
-
- // Grab LISTRIGHTS response
- Vector v = new Vector();
- if (response.isOK()) { // command succesful
- for (int i = 0, len = r.length; i < len; i++) {
- if (!(r[i] instanceof IMAPResponse))
- continue;
-
- IMAPResponse ir = (IMAPResponse)r[i];
- if (ir.keyEquals("LISTRIGHTS")) {
- // listrights_data ::= "LISTRIGHTS" SPACE mailbox
- // SPACE identifier SPACE rights *(SPACE rights)
- // read name of mailbox and throw away
- ir.readAtomString();
- // read identifier and throw away
- ir.readAtomString();
- String rights;
- while ((rights = ir.readAtomString()) != null)
- v.addElement(new Rights(rights));
- r[i] = null;
- }
- }
- }
-
- // dispatch remaining untagged responses
- notifyResponseHandlers(r);
- handleResult(response);
- Rights[] ra = new Rights[v.size()];
- v.copyInto(ra);
- return ra;
- }
-
- /**
- * MYRIGHTS Command.
- *
- * @see "RFC2086"
- */
- public Rights myRights(String mbox) throws ProtocolException {
- if (!hasCapability("ACL"))
- throw new BadCommandException("ACL not supported");
-
- // encode the mbox as per RFC2060
- mbox = BASE64MailboxEncoder.encode(mbox);
-
- Argument args = new Argument();
- args.writeString(mbox);
-
- Response[] r = command("MYRIGHTS", args);
- Response response = r[r.length-1];
-
- // Grab MYRIGHTS response
- Rights rights = null;
- if (response.isOK()) { // command succesful
- for (int i = 0, len = r.length; i < len; i++) {
- if (!(r[i] instanceof IMAPResponse))
- continue;
-
- IMAPResponse ir = (IMAPResponse)r[i];
- if (ir.keyEquals("MYRIGHTS")) {
- // myrights_data ::= "MYRIGHTS" SPACE mailbox SPACE rights
- // read name of mailbox and throw away
- ir.readAtomString();
- String rs = ir.readAtomString();
- if (rights == null)
- rights = new Rights(rs);
- r[i] = null;
- }
- }
- }
-
- // dispatch remaining untagged responses
- notifyResponseHandlers(r);
- handleResult(response);
- return rights;
- }
-
- /*
- * The tag used on the IDLE command. Set by idleStart() and
- * used in processIdleResponse() to determine if the response
- * is the matching end tag.
- */
- private volatile String idleTag;
-
- /**
- * IDLE Command.
- *
- * If the server supports the IDLE command extension, the IDLE
- * command is issued and this method blocks until a response has
- * been received. Once the first response has been received, the
- * IDLE command is terminated and all responses are collected and
- * handled and this method returns.
- *
- * Note that while this method is blocked waiting for a response,
- * no other threads may issue any commands to the server that would
- * use this same connection.
- *
- * @see "RFC2177"
- * @since JavaMail 1.4.1
- */
- public synchronized void idleStart() throws ProtocolException {
- if (!hasCapability("IDLE"))
- throw new BadCommandException("IDLE not supported");
-
- Vector v = new Vector();
- boolean done = false;
- Response r = null;
-
- // write the command
- try {
- idleTag = writeCommand("IDLE", null);
- } 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;
- }
-
- while (!done) {
- try {
- r = readResponse();
- } catch (IOException ioex) {
- // convert this into a BYE response
- r = Response.byeResponse(ioex);
- } catch (ProtocolException pex) {
- continue; // skip this response
- }
-
- v.addElement(r);
-
- if (r.isContinuation() || r.isBYE())
- done = true;
- }
-
- Response[] responses = new Response[v.size()];
- v.copyInto(responses);
- r = responses[responses.length-1];
-
- // dispatch remaining untagged responses
- notifyResponseHandlers(responses);
- if (!r.isContinuation())
- handleResult(r);
- }
-
- /**
- * While an IDLE command is in progress, read a response
- * sent from the server. The response is read with no locks
- * held so that when the read blocks waiting for the response
- * from the server it's not holding locks that would prevent
- * other threads from interrupting the IDLE command.
- *
- * @since JavaMail 1.4.1
- */
- public synchronized Response readIdleResponse() {
- if (idleTag == null)
- return null; // IDLE not in progress
- Response r = null;
- while (r == null) {
- try {
- r = readResponse();
- } catch (InterruptedIOException iioex) {
- /*
- * If a socket timeout was set, the read will timeout
- * before the IDLE times out. In that case, just go
- * back and read some more. After all, the point of
- * IDLE is to sit here and wait until something happens.
- */
- if (iioex.bytesTransferred == 0)
- r = null; // keep trying
- else
- // convert this into a BYE response
- r = Response.byeResponse(iioex);
- } catch (IOException ioex) {
- // convert this into a BYE response
- r = Response.byeResponse(ioex);
- } catch (ProtocolException pex) {
- // convert this into a BYE response
- r = Response.byeResponse(pex);
- }
- }
- return r;
- }
-
- /**
- * Process a response returned by readIdleResponse().
- * This method will be called with appropriate locks
- * held so that the processing of the response is safe.
- *
- * @since JavaMail 1.4.1
- */
- public boolean processIdleResponse(Response r) throws ProtocolException {
- Response[] responses = new Response[1];
- responses[0] = r;
- boolean done = false; // done reading responses?
- notifyResponseHandlers(responses);
-
- if (r.isBYE()) // shouldn't wait for command completion response
- done = true;
-
- // If this is a matching command completion response, we are done
- if (r.isTagged() && r.getTag().equals(idleTag))
- done = true;
-
- if (done)
- idleTag = null; // no longer in IDLE
-
- handleResult(r);
- return !done;
- }
-
- // the DONE command to break out of IDLE
- private static final byte[] DONE = { 'D', 'O', 'N', 'E', '\r', '\n' };
-
- /**
- * Abort an IDLE command. While one thread is blocked in
- * readIdleResponse(), another thread will use this method
- * to abort the IDLE command, which will cause the server
- * to send the closing tag for the IDLE command, which
- * readIdleResponse() and processIdleResponse() will see
- * and terminate the IDLE state.
- *
- * @since JavaMail 1.4.1
- */
- public void idleAbort() throws ProtocolException {
- OutputStream os = getOutputStream();
- try {
- os.write(DONE);
- os.flush();
- } catch (IOException ex) {
- // nothing to do, hope to detect it again later
- }
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/protocol/IMAPResponse.java b/src/main/java/com/sun/mail/imap/protocol/IMAPResponse.java
deleted file mode 100644
index 6d8fc7b7..00000000
--- a/src/main/java/com/sun/mail/imap/protocol/IMAPResponse.java
+++ /dev/null
@@ -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 "* "
- 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;
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/protocol/IMAPSaslAuthenticator.java b/src/main/java/com/sun/mail/imap/protocol/IMAPSaslAuthenticator.java
deleted file mode 100644
index c3d49b9d..00000000
--- a/src/main/java/com/sun/mail/imap/protocol/IMAPSaslAuthenticator.java
+++ /dev/null
@@ -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;
- }
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/protocol/INTERNALDATE.java b/src/main/java/com/sun/mail/imap/protocol/INTERNALDATE.java
deleted file mode 100644
index 244cc1d4..00000000
--- a/src/main/java/com/sun/mail/imap/protocol/INTERNALDATE.java
+++ /dev/null
@@ -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();
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/protocol/Item.java b/src/main/java/com/sun/mail/imap/protocol/Item.java
deleted file mode 100644
index a119fe81..00000000
--- a/src/main/java/com/sun/mail/imap/protocol/Item.java
+++ /dev/null
@@ -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.
- *
- * See the BODY, BODYSTRUCTURE, ENVELOPE, FLAGS, INTERNALDATE, RFC822DATA,
- * RFC822SIZE, and UID classes.
- *
- * @author John Mani
- */
-
-public interface Item {
-}
diff --git a/src/main/java/com/sun/mail/imap/protocol/ListInfo.java b/src/main/java/com/sun/mail/imap/protocol/ListInfo.java
deleted file mode 100644
index 9cde3d63..00000000
--- a/src/main/java/com/sun/mail/imap/protocol/ListInfo.java
+++ /dev/null
@@ -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);
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/protocol/MailboxInfo.java b/src/main/java/com/sun/mail/imap/protocol/MailboxInfo.java
deleted file mode 100644
index bc02a47e..00000000
--- a/src/main/java/com/sun/mail/imap/protocol/MailboxInfo.java
+++ /dev/null
@@ -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();
- }
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/protocol/MessageSet.java b/src/main/java/com/sun/mail/imap/protocol/MessageSet.java
deleted file mode 100644
index 971428d0..00000000
--- a/src/main/java/com/sun/mail/imap/protocol/MessageSet.java
+++ /dev/null
@@ -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;
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/protocol/Namespaces.java b/src/main/java/com/sun/mail/imap/protocol/Namespaces.java
deleted file mode 100644
index d1ae451c..00000000
--- a/src/main/java/com/sun/mail/imap/protocol/Namespaces.java
+++ /dev/null
@@ -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.
- *
- * See RFC 2342.
- *
- * @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;
- }
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/protocol/RFC822DATA.java b/src/main/java/com/sun/mail/imap/protocol/RFC822DATA.java
deleted file mode 100644
index 5278be65..00000000
--- a/src/main/java/com/sun/mail/imap/protocol/RFC822DATA.java
+++ /dev/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;
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/protocol/RFC822SIZE.java b/src/main/java/com/sun/mail/imap/protocol/RFC822SIZE.java
deleted file mode 100644
index 2bc7b147..00000000
--- a/src/main/java/com/sun/mail/imap/protocol/RFC822SIZE.java
+++ /dev/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();
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/protocol/SaslAuthenticator.java b/src/main/java/com/sun/mail/imap/protocol/SaslAuthenticator.java
deleted file mode 100644
index 21c0bbeb..00000000
--- a/src/main/java/com/sun/mail/imap/protocol/SaslAuthenticator.java
+++ /dev/null
@@ -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;
-
-}
diff --git a/src/main/java/com/sun/mail/imap/protocol/SearchSequence.java b/src/main/java/com/sun/mail/imap/protocol/SearchSequence.java
deleted file mode 100644
index bf4628b2..00000000
--- a/src/main/java/com/sun/mail/imap/protocol/SearchSequence.java
+++ /dev/null
@@ -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;
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/protocol/Status.java b/src/main/java/com/sun/mail/imap/protocol/Status.java
deleted file mode 100644
index 58b21bc7..00000000
--- a/src/main/java/com/sun/mail/imap/protocol/Status.java
+++ /dev/null
@@ -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;
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/protocol/UID.java b/src/main/java/com/sun/mail/imap/protocol/UID.java
deleted file mode 100644
index 83113e39..00000000
--- a/src/main/java/com/sun/mail/imap/protocol/UID.java
+++ /dev/null
@@ -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();
- }
-}
diff --git a/src/main/java/com/sun/mail/imap/protocol/UIDSet.java b/src/main/java/com/sun/mail/imap/protocol/UIDSet.java
deleted file mode 100644
index 961d4644..00000000
--- a/src/main/java/com/sun/mail/imap/protocol/UIDSet.java
+++ /dev/null
@@ -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;
- }
-}
diff --git a/src/main/java/com/sun/mail/pop3/DefaultFolder.java b/src/main/java/com/sun/mail/pop3/DefaultFolder.java
deleted file mode 100644
index 71a62991..00000000
--- a/src/main/java/com/sun/mail/pop3/DefaultFolder.java
+++ /dev/null
@@ -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");
- }
-}
diff --git a/src/main/java/com/sun/mail/pop3/POP3Folder.java b/src/main/java/com/sun/mail/pop3/POP3Folder.java
deleted file mode 100644
index 6e20e1a4..00000000
--- a/src/main/java/com/sun/mail/pop3/POP3Folder.java
+++ /dev/null
@@ -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 com.sun.mail.pop3 package
- * documentation for further information on the POP3 protocol provider.
- *
- * @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 MessagingException 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 false; the POP3 protocol doesn't
- * support creating folders.
- *
- * @return false
- */
- public boolean create(int type) throws MessagingException {
- return false;
- }
-
- /**
- * Always returns false; 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 MessagingException 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 MethodNotSupportedException
- * 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 MethodNotSupportedException
- * because the POP3 protocol doesn't support multiple folders.
- *
- * @exception MethodNotSupportedException always
- */
- public boolean renameTo(Folder f) throws MessagingException {
- throw new MethodNotSupportedException("renameTo");
- }
-
- /**
- * Throws FolderNotFoundException 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 Flags 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 MethodNotSupportedException
- * 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 MethodNotSupportedException
- * because the POP3 protocol doesn't support expunging messages
- * without closing the folder; call the {@link #close close} method
- * with the expunge argument set to true
- * instead.
- *
- * @exception MethodNotSupportedException always
- */
- public Message[] expunge() throws MessagingException {
- throw new MethodNotSupportedException("Expunge not supported");
- }
-
- /**
- * Prefetch information about POP3 messages.
- * If the FetchProfile contains UIDFolder.FetchProfileItem.UID,
- * POP3 UIDs for all messages in the folder are fetched using the POP3
- * UIDL command.
- * If the FetchProfile contains FetchProfile.Item.ENVELOPE,
- * 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 corresponds to message number i+1.
- *
- * @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;
- }
-}
diff --git a/src/main/java/com/sun/mail/pop3/POP3Message.java b/src/main/java/com/sun/mail/pop3/POP3Message.java
deleted file mode 100644
index f69d1650..00000000
--- a/src/main/java/com/sun/mail/pop3/POP3Message.java
+++ /dev/null
@@ -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.
- *
- * 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.
- *
- * @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 invalidateHeaders 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 n 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.
- *
- * @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 null, 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.
- *
- * Note that certain headers may be encoded as per RFC 2047
- * if they contain non US-ASCII characters and these should
- * be decoded.
- *
- * @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);
- }
- }
-}
diff --git a/src/main/java/com/sun/mail/pop3/POP3SSLStore.java b/src/main/java/com/sun/mail/pop3/POP3SSLStore.java
deleted file mode 100644
index 57bd23ed..00000000
--- a/src/main/java/com/sun/mail/pop3/POP3SSLStore.java
+++ /dev/null
@@ -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);
- }
-}
diff --git a/src/main/java/com/sun/mail/pop3/POP3Store.java b/src/main/java/com/sun/mail/pop3/POP3Store.java
deleted file mode 100644
index e0e267c0..00000000
--- a/src/main/java/com/sun/mail/pop3/POP3Store.java
+++ /dev/null
@@ -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 com.sun.mail.pop3 package
- * documentation for further information on the POP3 protocol provider.
- *
- * @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.
- */
- /*
- * 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.
- *
- * For example, to check if the server supports the STLS capability, use:
- * if (store.capabilities().containsKey("STLS")) ...
- *
- * @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");
- }
-}
diff --git a/src/main/java/com/sun/mail/pop3/Protocol.java b/src/main/java/com/sun/mail/pop3/Protocol.java
deleted file mode 100644
index bb6cd697..00000000
--- a/src/main/java/com/sun/mail/pop3/Protocol.java
+++ /dev/null
@@ -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 true 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("");
- 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.
- * size 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() { }
-}
diff --git a/src/main/java/com/sun/mail/pop3/Status.java b/src/main/java/com/sun/mail/pop3/Status.java
deleted file mode 100644
index 309aa752..00000000
--- a/src/main/java/com/sun/mail/pop3/Status.java
+++ /dev/null
@@ -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
-};
diff --git a/src/main/java/com/sun/mail/pop3/TempFile.java b/src/main/java/com/sun/mail/pop3/TempFile.java
deleted file mode 100644
index 73863d89..00000000
--- a/src/main/java/com/sun/mail/pop3/TempFile.java
+++ /dev/null
@@ -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);
- }
-}
diff --git a/src/main/java/com/sun/mail/pop3/package.html b/src/main/java/com/sun/mail/pop3/package.html
deleted file mode 100644
index a1eb497a..00000000
--- a/src/main/java/com/sun/mail/pop3/package.html
+++ /dev/null
@@ -1,607 +0,0 @@
-
-
-
-
-
-
-
-
-A POP3 protocol provider for the JavaMail API
-that provides access to a POP3 message store.
-Refer to
-RFC 1939
-for more information.
-
-The POP3 provider provides a Store object that contains a single Folder
-named "INBOX". Due to the limitations of the POP3 protocol, many of
-the JavaMail API capabilities like event notification, folder management,
-flag management, etc. are not allowed. The corresponding methods throw
-the MethodNotSupportedException exception; see below for details.
-
-Note that JavaMail does not include a local store into
-which messages can be downloaded and stored. See our
-
-Third Party Products
-web page for availability of "mbox" and "MH" local store providers.
-
-The POP3 provider is accessed through the JavaMail APIs by using the protocol
-name "pop3" or a URL of the form "pop3://user:password@host:port/INBOX".
-
-POP3 supports only a single folder named "INBOX".
-
-POP3 supports no permanent flags (see
-{@link javax.mail.Folder#getPermanentFlags Folder.getPermanentFlags()}).
-In particular, the Flags.Flag.RECENT flag will never be set
-for POP3
-messages. It's up to the application to determine which messages in a
-POP3 mailbox are "new". There are several strategies to accomplish
-this, depending on the needs of the application and the environment:
-
-
-
-A simple approach would be to keep track of the newest
-message seen by the application.
-
-
-An alternative would be to keep track of the UIDs (see below)
-of all messages that have been seen.
-
-
-Another approach is to download all messages into a local
-mailbox, so that all messages in the POP3 mailbox are, by
-definition, new.
-
-
-
-All approaches will require some permanent storage associated with the client.
-
-POP3 does not support the Folder.expunge() method. To delete and
-expunge messages, set the Flags.Flag.DELETED flag on the messages
-and close the folder using the Folder.close(true) method. You
-cannot expunge without closing the folder.
-
-POP3 does not provide a "received date", so the getReceivedDate
-method will return null.
-It may be possible to examine other message headers (e.g., the
-"Received" headers) to estimate the received date, but these techniques
-are error-prone at best.
-
-The POP3 provider supports the POP3 UIDL command, see
-{@link com.sun.mail.pop3.POP3Folder#getUID POP3Folder.getUID()}.
-You can use it as follows:
-
-
-if (folder instanceof com.sun.mail.pop3.POP3Folder) {
- com.sun.mail.pop3.POP3Folder pf =
- (com.sun.mail.pop3.POP3Folder)folder;
- String uid = pf.getUID(msg);
- if (uid != null)
- ... // use it
-}
-
-
-You can also pre-fetch all the UIDs for all messages like this:
-
-
-FetchProfile fp = new FetchProfile();
-fp.add(UIDFolder.FetchProfileItem.UID);
-folder.fetch(folder.getMessages(), fp);
-
-
-Then use the technique above to get the UID for each message. This is
-similar to the technique used with the UIDFolder interface supported by
-IMAP, but note that POP3 UIDs are strings, not integers like IMAP
-UIDs. See the POP3 spec for details.
-
-When the headers of a POP3 message are accessed, the POP3 provider uses
-the TOP command to fetch all headers, which are then cached. Use of the
-TOP command can be disabled with the mail.pop3.disabletop
-property, in which case the entire message content is fetched with the
-RETR command.
-
-When the content of a POP3 message is accessed, the POP3 provider uses
-the RETR command to fetch the entire message. Normally the message
-content is cached in memory. By setting the
-mail.pop3.filecache.enable property, the message content
-will instead be cached in a temporary file. The file will be removed
-when the folder is closed. Caching message content in a file is generally
-slower, but uses substantially less memory and may be helpful when dealing
-with very large messages.
-
-The {@link com.sun.mail.pop3.POP3Message#invalidate POP3Message.invalidate}
-method can be used to invalidate cached data without closing the folder.
-Note that if the file cache is being used the data in the file will be
-forgotten and fetched from the server if it's needed again, and stored again
-in the file cache.
-
-The POP3 CAPA command (defined by
-RFC 2449)
-will be used to determine the capabilities supported by the server.
-Some servers don't implement the CAPA command, and some servers don't
-return correct information, so various properties are available to
-disable use of certain POP3 commands, including CAPA.
-
-If the server advertises the PIPELINING capability (defined by
-RFC 2449),
-or the mail.pop3.pipelining property is set, the POP3
-provider will send some commands in batches, which can significantly
-improve performance and memory use.
-Some servers that don't support the CAPA command or don't advertise
-PIPELINING may still support pipelining; experimentation may be required.
-
-If pipelining is supported and the connection is using
-SSL, the USER and PASS commands will be sent as a batch.
-(If SSL is not being used, the PASS command isn't sent
-until the user is verified to avoid exposing the password
-if the user name is bad.)
-
-If pipelining is supported, when fetching a message with the RETR command,
-the LIST command will be sent as well, and the result will be used to size
-the I/O buffer, greatly reducing memory usage when fetching messages.
-
-The POP3 protocol provider supports the following properties,
-which may be set in the JavaMail Session object.
-The properties are always set as strings; the Type column describes
-how the string is interpreted. For example, use
-
- props.put("mail.pop3.port", "888");
-
-to set the mail.pop3.port property, which is of type int.
-
-Note that if you're using the "pop3s" protocol to access POP3 over SSL,
-all the properties would be named "mail.pop3s.*".
-
-
-
-
Name
-
Type
-
Description
-
-
-
-
mail.pop3.user
-
String
-
Default user name for POP3.
-
-
-
-
mail.pop3.host
-
String
-
The POP3 server to connect to.
-
-
-
-
mail.pop3.port
-
int
-
The POP3 server port to connect to, if the connect() method doesn't
-explicitly specify one. Defaults to 110.
-
-
-
-
mail.pop3.connectiontimeout
-
int
-
Socket connection timeout value in milliseconds.
-Default is infinite timeout.
-
-
-
-
mail.pop3.timeout
-
int
-
Socket I/O timeout value in milliseconds. Default is infinite timeout.
-
-
-
-
mail.pop3.rsetbeforequit
-
boolean
-
-Send a POP3 RSET command when closing the folder, before sending the
-QUIT command. Useful with POP3 servers that implicitly mark all
-messages that are read as "deleted"; this will prevent such messages
-from being deleted and expunged unless the client requests so. Default
-is false.
-
-
-
-
-
mail.pop3.message.class
-
String
-
-Class name of a subclass of com.sun.mail.pop3.POP3Message.
-The subclass can be used to handle (for example) non-standard
-Content-Type headers. The subclass must have a public constructor
-of the form MyPOP3Message(Folder f, int msgno)
-throws MessagingException.
-
-
-
-
-
mail.pop3.localaddress
-
String
-
-Local address (host name) to bind to when creating the POP3 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.
-
-
-
-
-
mail.pop3.localport
-
int
-
-Local port number to bind to when creating the POP3 socket.
-Defaults to the port number picked by the Socket class.
-
-
-
-
-
mail.pop3.apop.enable
-
boolean
-
-If set to true, use APOP instead of USER/PASS to login to the
-POP3 server, if the POP3 server supports APOP. APOP sends a
-digest of the password rather than the clear text password.
-Defaults to false.
-
-
-
-
-
mail.pop3.socketFactory
-
SocketFactory
-
-If set to a class that implements the
-javax.net.SocketFactory interface, this class
-will be used to create POP3 sockets. Note that this is an
-instance of a class, not a name, and must be set using the
-put method, not the setProperty method.
-
-
-
-
-
mail.pop3.socketFactory.class
-
String
-
-If set, specifies the name of a class that implements the
-javax.net.SocketFactory interface. This class
-will be used to create POP3 sockets.
-
-
-
-
-
mail.pop3.socketFactory.fallback
-
boolean
-
-If set to true, failure to create a socket using the specified
-socket factory class will cause the socket to be created using
-the java.net.Socket class.
-Defaults to true.
-
-
-
-
-
mail.pop3.socketFactory.port
-
int
-
-Specifies the port to connect to when using the specified socket
-factory.
-If not set, the default port will be used.
-
-
-
-
-
mail.pop3.ssl.enable
-
boolean
-
-If set to true, use SSL to connect and use the SSL port by default.
-Defaults to false for the "pop3" protocol and true for the "pop3s" protocol.
-
-
-
-
-
mail.pop3.ssl.checkserveridentity
-
boolean
-
-If set to true, check the server identity as specified by
-RFC 2595.
-These additional checks based on the content of the server's certificate
-are intended to prevent man-in-the-middle attacks.
-Defaults to false.
-
-
-
-
-
mail.pop3.ssl.trust
-
String
-
-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.
-
-
-
-
-
mail.pop3.ssl.socketFactory
-
SSLSocketFactory
-
-If set to a class that extends the
-javax.net.ssl.SSLSocketFactory class, this class
-will be used to create POP3 SSL sockets. Note that this is an
-instance of a class, not a name, and must be set using the
-put method, not the setProperty method.
-
-
-
-
-
mail.pop3.ssl.socketFactory.class
-
String
-
-If set, specifies the name of a class that extends the
-javax.net.ssl.SSLSocketFactory class. This class
-will be used to create POP3 SSL sockets.
-
-
-
-
-
mail.pop3.ssl.socketFactory.port
-
int
-
-Specifies the port to connect to when using the specified socket
-factory.
-If not set, the default port will be used.
-
-
-
-
-
mail.pop3.ssl.protocols
-
string
-
-Specifies the SSL protocols that will be enabled for SSL connections.
-The property value is a whitespace separated list of tokens acceptable
-to the javax.net.ssl.SSLSocket.setEnabledProtocols method.
-
-
-
-
-
mail.pop3.ssl.ciphersuites
-
string
-
-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 javax.net.ssl.SSLSocket.setEnabledCipherSuites method.
-
-
-
-
-
mail.pop3.starttls.enable
-
boolean
-
-If true, enables the use of the STLS 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.
-Defaults to false.
-
-
-
-
-
mail.pop3.starttls.required
-
boolean
-
-If true, requires the use of the STLS command.
-If the server doesn't support the STLS command, or the command
-fails, the connect method will fail.
-Defaults to false.
-
-
-
-
-
mail.pop3.socks.host
-
string
-
-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.)
-
-
-
-
-
mail.pop3.socks.port
-
string
-
-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.
-
-
-
-
-
mail.pop3.disabletop
-
boolean
-
-If set to true, the POP3 TOP command will not be used to fetch
-message headers. This is useful for POP3 servers that don't
-properly implement the TOP command, or that provide incorrect
-information in the TOP command results.
-Defaults to false.
-
-
-
-
-
mail.pop3.disablecapa
-
boolean
-
-If set to true, the POP3 CAPA command will not be used to fetch
-server capabilities. This is useful for POP3 servers that don't
-properly implement the CAPA command, or that provide incorrect
-information in the CAPA command results.
-Defaults to false.
-
-
-
-
-
mail.pop3.forgettopheaders
-
boolean
-
-If set to true, the headers that might have been retrieved using
-the POP3 TOP command will be forgotten and replaced by headers
-retrieved as part of the POP3 RETR command. Some servers, such
-as some versions of Microsft Exchange and IBM Lotus Notes,
-will return slightly different
-headers each time the TOP or RETR command is used. To allow the
-POP3 provider to properly parse the message content returned from
-the RETR command, the headers also returned by the RETR command
-must be used. Setting this property to true will cause these
-headers to be used, even if they differ from the headers returned
-previously as a result of using the TOP command.
-Defaults to false.
-
-
-
-
-
mail.pop3.filecache.enable
-
boolean
-
-If set to true, the POP3 provider will cache message data in a temporary
-file rather than in memory. Messages are only added to the cache when
-accessing the message content. Message headers are always cached in
-memory (on demand). The file cache is removed when the folder is closed
-or the JVM terminates.
-Defaults to false.
-
-
-
-
-
mail.pop3.filecache.dir
-
String
-
-If the file cache is enabled, this property can be used to override the
-default directory used by the JDK for temporary files.
-
-
-
-
-
mail.pop3.cachewriteto
-
boolean
-
-Controls the behavior of the
-{@link com.sun.mail.pop3.POP3Message#writeTo writeTo} method
-on a POP3 message object.
-If set to true, and the message content hasn't yet been cached,
-and ignoreList is null, the message is cached before being written.
-Otherwise, the message is streamed directly
-to the output stream without being cached.
-Defaults to false.
-
-
-
-
-
mail.pop3.keepmessagecontent
-
boolean
-
-The content of a message is cached when it is first fetched.
-Normally this cache uses a {@link java.lang.ref.SoftReference SoftReference}
-to refer to the cached content. This allows the cached content to be purged
-if memory is low, in which case the content will be fetched again if it's
-needed.
-If this property is set to true, a hard reference to the cached content
-will be kept, preventing the memory from being reused until the folder
-is closed or the cached content is explicitly invalidated (using the
-{@link com.sun.mail.pop3.POP3Message#invalidate invalidate} method).
-(This was the behavior in previous versions of JavaMail.)
-Defaults to false.
-
-
-
-
-
-In general, applications should not need to use the classes in this
-package directly. Instead, they should use the APIs defined by
-javax.mail package (and subpackages). Applications should
-never construct instances of POP3Store or
-POP3Folder directly. Instead, they should use the
-Session method getStore to acquire an
-appropriate Store object, and from that acquire
-Folder objects.
-
-In addition to printing debugging output as controlled by the
-{@link javax.mail.Session Session} configuration,
-the com.sun.mail.pop3 provider logs the same information using
-{@link java.util.logging.Logger} as described in the following table:
-
-
-
-
Logger Name
-
Logging Level
-
Purpose
-
-
-
-
com.sun.mail.pop3
-
CONFIG
-
Configuration of the POP3Store
-
-
-
-
com.sun.mail.pop3
-
FINE
-
General debugging output
-
-
-
-
com.sun.mail.pop3.protocol
-
FINEST
-
Complete protocol trace
-
-
-
-
-WARNING: The APIs unique to this package should be
-considered EXPERIMENTAL. They may be changed in the
-future in ways that are incompatible with applications using the
-current APIs.
-
-
-
diff --git a/src/main/java/com/sun/mail/smtp/DigestMD5.java b/src/main/java/com/sun/mail/smtp/DigestMD5.java
deleted file mode 100644
index 85cdd54d..00000000
--- a/src/main/java/com/sun/mail/smtp/DigestMD5.java
+++ /dev/null
@@ -1,229 +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.smtp;
-
-import java.io.*;
-import java.util.*;
-import java.util.logging.Level;
-import java.security.*;
-
-import com.sun.mail.util.*;
-
-/**
- * DIGEST-MD5 authentication support.
- *
- * @author Dean Gibson
- * @author Bill Shannon
- */
-
-public class DigestMD5 {
-
- private MailLogger logger;
- private MessageDigest md5;
- private String uri;
- private String clientResponse;
-
- public DigestMD5(MailLogger logger) {
- this.logger = logger.getLogger(this.getClass(), "DEBUG DIGEST-MD5");
- logger.config("DIGEST-MD5 Loaded");
- }
-
- /**
- * Return client's authentication response to server's challenge.
- *
- * @return byte array with client's response
- */
- public byte[] authClient(String host, String user, String passwd,
- String realm, String serverChallenge)
- throws IOException {
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- OutputStream b64os = new BASE64EncoderStream(bos, Integer.MAX_VALUE);
- SecureRandom random;
- try {
- //random = SecureRandom.getInstance("SHA1PRNG");
- random = new SecureRandom();
- md5 = MessageDigest.getInstance("MD5");
- } catch (NoSuchAlgorithmException ex) {
- logger.log(Level.FINE, "NoSuchAlgorithmException", ex);
- throw new IOException(ex.toString());
- }
- StringBuffer result = new StringBuffer();
-
- uri = "smtp/" + host;
- String nc = "00000001";
- String qop = "auth";
- byte[] bytes = new byte[32]; // arbitrary size ...
- int resp;
-
- logger.fine("Begin authentication ...");
-
- // Code based on http://www.ietf.org/rfc/rfc2831.txt
- Hashtable map = tokenize(serverChallenge);
-
- if (realm == null) {
- String text = (String)map.get("realm");
- realm = text != null ? new StringTokenizer(text, ",").nextToken()
- : host;
- }
-
- // server challenge random value
- String nonce = (String)map.get("nonce");
-
- random.nextBytes(bytes);
- b64os.write(bytes);
- b64os.flush();
-
- // client challenge random value
- String cnonce = bos.toString("iso-8859-1"); // really ASCII?
- bos.reset();
-
- // DIGEST-MD5 computation, common portion (order critical)
- md5.update(md5.digest(
- ASCIIUtility.getBytes(user + ":" + realm + ":" + passwd)));
- md5.update(ASCIIUtility.getBytes(":" + nonce + ":" + cnonce));
- clientResponse = toHex(md5.digest())
- + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":";
-
- // DIGEST-MD5 computation, client response (order critical)
- md5.update(ASCIIUtility.getBytes("AUTHENTICATE:" + uri));
- md5.update(ASCIIUtility.getBytes(clientResponse + toHex(md5.digest())));
-
- // build response text (order not critical)
- result.append("username=\"" + user + "\"");
- result.append(",realm=\"" + realm + "\"");
- result.append(",qop=" + qop);
- result.append(",nc=" + nc);
- result.append(",nonce=\"" + nonce + "\"");
- result.append(",cnonce=\"" + cnonce + "\"");
- result.append(",digest-uri=\"" + uri + "\"");
- result.append(",response=" + toHex(md5.digest()));
-
- if (logger.isLoggable(Level.FINE))
- logger.fine("Response => " + result.toString());
- b64os.write(ASCIIUtility.getBytes(result.toString()));
- b64os.flush();
- return bos.toByteArray();
- }
-
- /**
- * Allow the client to authenticate the server based on its
- * response.
- *
- * @return true if server is authenticated
- */
- public boolean authServer(String serverResponse) throws IOException {
- Hashtable map = tokenize(serverResponse);
- // DIGEST-MD5 computation, server response (order critical)
- md5.update(ASCIIUtility.getBytes(":" + uri));
- md5.update(ASCIIUtility.getBytes(clientResponse + toHex(md5.digest())));
- String text = toHex(md5.digest());
- if (!text.equals((String)map.get("rspauth"))) {
- if (logger.isLoggable(Level.FINE))
- logger.fine("Expected => rspauth=" + text);
- return false; // server NOT authenticated by client !!!
- }
- return true;
- }
-
- /**
- * Tokenize a response from the server.
- *
- * @return Hashtable containing key/value pairs from server
- */
- private Hashtable tokenize(String serverResponse) throws IOException {
- Hashtable map = new Hashtable();
- byte[] bytes = serverResponse.getBytes("iso-8859-1"); // really ASCII?
- String key = null;
- int ttype;
- StreamTokenizer tokens
- = new StreamTokenizer(
- new InputStreamReader(
- new BASE64DecoderStream(
- new ByteArrayInputStream(bytes, 4, bytes.length - 4)
- ), "iso-8859-1" // really ASCII?
- )
- );
-
- tokens.ordinaryChars('0', '9'); // reset digits
- tokens.wordChars('0', '9'); // digits may start words
- while ((ttype = tokens.nextToken()) != StreamTokenizer.TT_EOF) {
- switch (ttype) {
- case StreamTokenizer.TT_WORD:
- if (key == null) {
- key = tokens.sval;
- break;
- }
- // fall-thru
- case '"':
- if (logger.isLoggable(Level.FINE))
- logger.fine("Received => " +
- key + "='" + tokens.sval + "'");
- if (map.containsKey(key)) { // concatenate multiple values
- map.put(key, map.get(key) + "," + tokens.sval);
- } else {
- map.put(key, tokens.sval);
- }
- key = null;
- break;
- }
- }
- return map;
- }
-
- 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);
- }
-}
diff --git a/src/main/java/com/sun/mail/smtp/SMTPAddressFailedException.java b/src/main/java/com/sun/mail/smtp/SMTPAddressFailedException.java
deleted file mode 100644
index 632604eb..00000000
--- a/src/main/java/com/sun/mail/smtp/SMTPAddressFailedException.java
+++ /dev/null
@@ -1,105 +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.smtp;
-
-import javax.mail.SendFailedException;
-import javax.mail.internet.InternetAddress;
-
-/**
- * This exception is thrown when the message cannot be sent.
- *
- * The exception includes the address to which the message could not be
- * sent. This will usually appear in a chained list of exceptions,
- * one per address, attached to a top level SendFailedException that
- * aggregates all the addresses.
- *
- * @since JavaMail 1.3.2
- */
-
-public class SMTPAddressFailedException extends SendFailedException {
- protected InternetAddress addr; // address that failed
- protected String cmd; // command issued to server
- protected int rc; // return code from SMTP server
-
- private static final long serialVersionUID = 804831199768630097L;
-
- /**
- * Constructs an SMTPAddressFailedException with the specified
- * address, return code, and error string.
- *
- * @param addr the address that failed
- * @param cmd the command that was sent to the SMTP server
- * @param rc the SMTP return code indicating the failure
- * @param err the error string from the SMTP server
- */
- public SMTPAddressFailedException(InternetAddress addr, String cmd, int rc,
- String err) {
- super(err);
- this.addr = addr;
- this.cmd = cmd;
- this.rc = rc;
- }
-
- /**
- * Return the address that failed.
- */
- public InternetAddress getAddress() {
- return addr;
- }
-
- /**
- * Return the command that failed.
- */
- public String getCommand() {
- return cmd;
- }
-
-
- /**
- * Return the return code from the SMTP server that indicates the
- * reason for the failure. See
- * RFC 821
- * for interpretation of the return code.
- */
- public int getReturnCode() {
- return rc;
- }
-}
diff --git a/src/main/java/com/sun/mail/smtp/SMTPAddressSucceededException.java b/src/main/java/com/sun/mail/smtp/SMTPAddressSucceededException.java
deleted file mode 100644
index b569ed53..00000000
--- a/src/main/java/com/sun/mail/smtp/SMTPAddressSucceededException.java
+++ /dev/null
@@ -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.smtp;
-
-import javax.mail.MessagingException;
-import javax.mail.internet.InternetAddress;
-
-/**
- * This exception is chained off a SendFailedException when the
- * mail.smtp.reportsuccess property is true. It
- * indicates an address to which the message was sent. The command
- * will be an SMTP RCPT command and the return code will be the
- * return code from that command.
- *
- * @since JavaMail 1.3.2
- */
-
-public class SMTPAddressSucceededException extends MessagingException {
- protected InternetAddress addr; // address that succeeded
- protected String cmd; // command issued to server
- protected int rc; // return code from SMTP server
-
- private static final long serialVersionUID = -1168335848623096749L;
-
- /**
- * Constructs an SMTPAddressSucceededException with the specified
- * address, return code, and error string.
- *
- * @param addr the address that succeeded
- * @param cmd the command that was sent to the SMTP server
- * @param rc the SMTP return code indicating the success
- * @param err the error string from the SMTP server
- */
- public SMTPAddressSucceededException(InternetAddress addr,
- String cmd, int rc, String err) {
- super(err);
- this.addr = addr;
- this.cmd = cmd;
- this.rc = rc;
- }
-
- /**
- * Return the address that succeeded.
- */
- public InternetAddress getAddress() {
- return addr;
- }
-
- /**
- * Return the command that succeeded.
- */
- public String getCommand() {
- return cmd;
- }
-
-
- /**
- * Return the return code from the SMTP server that indicates the
- * reason for the success. See
- * RFC 821
- * for interpretation of the return code.
- */
- public int getReturnCode() {
- return rc;
- }
-}
diff --git a/src/main/java/com/sun/mail/smtp/SMTPMessage.java b/src/main/java/com/sun/mail/smtp/SMTPMessage.java
deleted file mode 100644
index 859130da..00000000
--- a/src/main/java/com/sun/mail/smtp/SMTPMessage.java
+++ /dev/null
@@ -1,342 +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.smtp;
-
-import java.io.*;
-import javax.mail.*;
-import javax.mail.internet.*;
-
-/**
- * This class is a specialization of the MimeMessage class that allows
- * you to specify various SMTP options and parameters that will be
- * used when this message is sent over SMTP. Simply use this class
- * instead of MimeMessage and set SMTP options using the methods on
- * this class.
- *
- * See the com.sun.mail.smtp package
- * documentation for further information on the SMTP protocol provider.
- *
- * @author Bill Shannon
- * @see javax.mail.internet.MimeMessage
- */
-
-public class SMTPMessage extends MimeMessage {
-
- /** Never notify of delivery status */
- public static final int NOTIFY_NEVER = -1;
- /** Notify of delivery success */
- public static final int NOTIFY_SUCCESS = 1;
- /** Notify of delivery failure */
- public static final int NOTIFY_FAILURE = 2;
- /** Notify of delivery delay */
- public static final int NOTIFY_DELAY = 4;
-
- /** Return full message with delivery status notification */
- public static final int RETURN_FULL = 1;
- /** Return only message headers with delivery status notification */
- public static final int RETURN_HDRS = 2;
-
- private static final String[] returnOptionString = { null, "FULL", "HDRS" };
-
- private String envelopeFrom; // the string to use in the MAIL FROM: command
- private int notifyOptions = 0;
- private int returnOption = 0;
- private boolean sendPartial = false;
- private boolean allow8bitMIME = false;
- private String submitter = null; // RFC 2554 AUTH=submitter
- private String extension = null; // extensions to use with MAIL command
-
- /**
- * Default constructor. An empty message object is created.
- * The headers field is set to an empty InternetHeaders
- * object. The flags field is set to an empty Flags
- * object. The modified flag is set to true.
- */
- public SMTPMessage(Session session) {
- super(session);
- }
-
- /**
- * Constructs an SMTPMessage by reading and parsing the data from the
- * specified MIME InputStream. The InputStream will be left positioned
- * at the end of the data for the message. Note that the input stream
- * parse is done within this constructor itself.
- *
- * @param session Session object for this message
- * @param is the message input stream
- * @exception MessagingException
- */
- public SMTPMessage(Session session, InputStream is)
- throws MessagingException {
- super(session, is);
- }
-
- /**
- * Constructs a new SMTPMessage with content initialized from the
- * source MimeMessage. The new message is independent
- * of the original.
- *
- * Note: The current implementation is rather inefficient, copying
- * the data more times than strictly necessary.
- *
- * @param source the message to copy content from
- * @exception MessagingException
- */
- public SMTPMessage(MimeMessage source) throws MessagingException {
- super(source);
- }
-
- /**
- * Set the From address to appear in the SMTP envelope. Note that this
- * is different than the From address that appears in the message itself.
- * The envelope From address is typically used when reporting errors.
- * See RFC 821 for
- * details.
- *
- * If set, overrides the mail.smtp.from property.
- *
- * @param from the envelope From address
- */
- public void setEnvelopeFrom(String from) {
- envelopeFrom = from;
- }
-
- /**
- * Return the envelope From address.
- *
- * @return the envelope From address, or null if not set
- */
- public String getEnvelopeFrom() {
- return envelopeFrom;
- }
-
- /**
- * Set notification options to be used if the server supports
- * Delivery Status Notification
- * (RFC 1891).
- * Either NOTIFY_NEVER or some combination of
- * NOTIFY_SUCCESS, NOTIFY_FAILURE, and
- * NOTIFY_DELAY.
- *
- * If set, overrides the mail.smtp.dsn.notify property.
- *
- * @param options notification options
- */
- public void setNotifyOptions(int options) {
- if (options < -1 || options >= 8)
- throw new IllegalArgumentException("Bad return option");
- notifyOptions = options;
- }
-
- /**
- * Get notification options. Returns zero if no options set.
- *
- * @return notification options
- */
- public int getNotifyOptions() {
- return notifyOptions;
- }
-
- /**
- * Return notification options as an RFC 1891 string.
- * Returns null if no options set.
- */
- String getDSNNotify() {
- if (notifyOptions == 0)
- return null;
- if (notifyOptions == NOTIFY_NEVER)
- return "NEVER";
- StringBuffer sb = new StringBuffer();
- if ((notifyOptions & NOTIFY_SUCCESS) != 0)
- sb.append("SUCCESS");
- if ((notifyOptions & NOTIFY_FAILURE) != 0) {
- if (sb.length() != 0)
- sb.append(',');
- sb.append("FAILURE");
- }
- if ((notifyOptions & NOTIFY_DELAY) != 0) {
- if (sb.length() != 0)
- sb.append(',');
- sb.append("DELAY");
- }
- return sb.toString();
- }
-
- /**
- * Set return option to be used if server supports
- * Delivery Status Notification
- * (RFC 1891).
- * Either RETURN_FULL or RETURN_HDRS.
- *
- * If set, overrides the mail.smtp.dsn.ret property.
- *
- * @param option return option
- */
- public void setReturnOption(int option) {
- if (option < 0 || option > RETURN_HDRS)
- throw new IllegalArgumentException("Bad return option");
- returnOption = option;
- }
-
- /**
- * Return return option. Returns zero if no option set.
- *
- * @return return option
- */
- public int getReturnOption() {
- return returnOption;
- }
-
- /**
- * Return return option as an RFC 1891 string.
- * Returns null if no option set.
- */
- String getDSNRet() {
- return returnOptionString[returnOption];
- }
-
- /**
- * If set to true, and the server supports the 8BITMIME extension, text
- * parts of this message that use the "quoted-printable" or "base64"
- * encodings are converted to use "8bit" encoding if they follow the
- * RFC 2045 rules for 8bit text.
- *
- * If true, overrides the mail.smtp.allow8bitmime property.
- *
- * @param allow allow 8-bit flag
- */
- public void setAllow8bitMIME(boolean allow) {
- allow8bitMIME = allow;
- }
-
- /**
- * Is use of the 8BITMIME extension is allowed?
- *
- * @return allow 8-bit flag
- */
- public boolean getAllow8bitMIME() {
- return allow8bitMIME;
- }
-
- /**
- * If set to true, and this message has some valid and some invalid
- * addresses, send the message anyway, reporting the partial failure with
- * a SendFailedException. If set to false (the default), the message is
- * not sent to any of the recipients if there is an invalid recipient
- * address.
- *
- * If true, overrides the mail.smtp.sendpartial property.
- *
- * @param partial send partial flag
- */
- public void setSendPartial(boolean partial) {
- sendPartial = partial;
- }
-
- /**
- * Send message if some addresses are invalid?
- *
- * @return send partial flag
- */
- public boolean getSendPartial() {
- return sendPartial;
- }
-
- /**
- * Gets the submitter to be used for the RFC 2554 AUTH= value
- * in the MAIL FROM command.
- *
- * @return the name of the submitter.
- */
- public String getSubmitter() {
- return submitter;
- }
-
- /**
- * Sets the submitter to be used for the RFC 2554 AUTH= value
- * in the MAIL FROM command. Normally only used by a server
- * that's relaying a message. Clients will typically not
- * set a submitter. See
- * RFC 2554
- * for details.
- *
- * @param submitter the name of the submitter
- */
- public void setSubmitter(String submitter) {
- this.submitter = submitter;
- }
-
- /**
- * Gets the extension string to use with the MAIL command.
- *
- * @return the extension string
- *
- * @since JavaMail 1.3.2
- */
- public String getMailExtension() {
- return extension;
- }
-
- /**
- * Set the extension string to use with the MAIL command.
- * The extension string can be used to specify standard SMTP
- * service extensions as well as vendor-specific extensions.
- * Typically the application should use the
- * {@link com.sun.mail.smtp.SMTPTransport SMTPTransport}
- * method {@link com.sun.mail.smtp.SMTPTransport#supportsExtension
- * supportsExtension}
- * to verify that the server supports the desired service extension.
- * See RFC 1869
- * and other RFCs that define specific extensions.
- *
- * For example:
- *
- *
- * if (smtpTransport.supportsExtension("DELIVERBY"))
- * smtpMsg.setMailExtension("BY=60;R");
- *
- *
- * @since JavaMail 1.3.2
- */
- public void setMailExtension(String extension) {
- this.extension = extension;
- }
-}
diff --git a/src/main/java/com/sun/mail/smtp/SMTPOutputStream.java b/src/main/java/com/sun/mail/smtp/SMTPOutputStream.java
deleted file mode 100644
index 0a4f04f9..00000000
--- a/src/main/java/com/sun/mail/smtp/SMTPOutputStream.java
+++ /dev/null
@@ -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.smtp;
-
-import java.io.*;
-import com.sun.mail.util.CRLFOutputStream;
-
-/**
- * In addition to converting lines into the canonical format,
- * i.e., terminating lines with the CRLF sequence, escapes the "."
- * by adding another "." to any "." that appears in the beginning
- * of a line. See RFC821 section 4.5.2.
- *
- * @author Max Spivak
- * @see CRLFOutputStream
- */
-public class SMTPOutputStream extends CRLFOutputStream {
- public SMTPOutputStream(OutputStream os) {
- super(os);
- }
-
- public void write(int b) throws IOException {
- // if that last character was a newline, and the current
- // character is ".", we always write out an extra ".".
- if ((lastb == '\n' || lastb == '\r' || lastb == -1) && b == '.') {
- out.write('.');
- }
-
- super.write(b);
- }
-
- /*
- * This method has been added to improve performance.
- */
- public void write(byte b[], int off, int len) throws IOException {
- int lastc = (lastb == -1) ? '\n' : lastb;
- int start = off;
-
- len += off;
- for (int i = off; i < len; i++) {
- if ((lastc == '\n' || lastc == '\r') && b[i] == '.') {
- super.write(b, start, i - start);
- out.write('.');
- start = i;
- }
- lastc = b[i];
- }
- if ((len - start) > 0)
- super.write(b, start, len - start);
- }
-
- /**
- * Override flush method in FilterOutputStream.
- *
- * The MimeMessage writeTo method flushes its buffer at the end,
- * but we don't want to flush data out to the socket until we've
- * also written the terminating "\r\n.\r\n".
- *
- * We buffer nothing so there's nothing to flush. We depend
- * on the fact that CRLFOutputStream also buffers nothing.
- * SMTPTransport will manually flush the socket before reading
- * the response.
- */
- public void flush() {
- // do nothing
- }
-
- /**
- * Ensure we're at the beginning of a line.
- * Write CRLF if not.
- */
- public void ensureAtBOL() throws IOException {
- if (!atBOL)
- super.writeln();
- }
-}
diff --git a/src/main/java/com/sun/mail/smtp/SMTPSSLTransport.java b/src/main/java/com/sun/mail/smtp/SMTPSSLTransport.java
deleted file mode 100644
index a86304fc..00000000
--- a/src/main/java/com/sun/mail/smtp/SMTPSSLTransport.java
+++ /dev/null
@@ -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.smtp;
-
-import javax.mail.*;
-
-/**
- * This class implements the Transport abstract class using SMTP
- * over SSL for message submission and transport.
- *
- * @author Bill Shannon
- */
-
-public class SMTPSSLTransport extends SMTPTransport {
-
- /** Constructor */
- public SMTPSSLTransport(Session session, URLName urlname) {
- super(session, urlname, "smtps", true);
- }
-}
diff --git a/src/main/java/com/sun/mail/smtp/SMTPSaslAuthenticator.java b/src/main/java/com/sun/mail/smtp/SMTPSaslAuthenticator.java
deleted file mode 100644
index db0283ae..00000000
--- a/src/main/java/com/sun/mail/smtp/SMTPSaslAuthenticator.java
+++ /dev/null
@@ -1,228 +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.smtp;
-
-import java.io.*;
-import java.util.*;
-import java.util.logging.Level;
-import javax.security.sasl.*;
-import javax.security.auth.callback.*;
-import javax.mail.MessagingException;
-
-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 SMTPTransport.java.
- */
-
-public class SMTPSaslAuthenticator implements SaslAuthenticator {
-
- private SMTPTransport pr;
- private String name;
- private Properties props;
- private MailLogger logger;
- private String host;
-
- public SMTPSaslAuthenticator(SMTPTransport 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 MessagingException {
-
- 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());
-
- int resp;
- try {
- String mech = sc.getMechanismName();
- String ir = null;
- if (sc.hasInitialResponse()) {
- byte[] ba = sc.evaluateChallenge(new byte[0]);
- ba = BASE64EncoderStream.encode(ba);
- ir = ASCIIUtility.toString(ba, 0, ba.length);
- }
- if (ir != null)
- resp = pr.simpleCommand("AUTH " + mech + " " + ir);
- else
- resp = pr.simpleCommand("AUTH " + mech);
-
- /*
- * A 530 response indicates that the server wants us to
- * issue a STARTTLS command first. Do that and try again.
- */
- if (resp == 530) {
- pr.startTLS();
- if (ir != null)
- resp = pr.simpleCommand("AUTH " + mech + " " + ir);
- else
- resp = pr.simpleCommand("AUTH " + mech);
- }
-
- if (resp == 235)
- return true; // success already!
-
- if (resp != 334)
- return false;
- } catch (Exception ex) {
- logger.log(Level.FINE, "SASL AUTHENTICATE Exception", ex);
- return false;
- }
-
- while (!done) { // loop till we are done
- try {
- if (resp == 334) {
- byte[] ba = null;
- if (!sc.isComplete()) {
- ba = ASCIIUtility.getBytes(responseText(pr));
- 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");
- resp = pr.simpleCommand("*");
- } else {
- if (logger.isLoggable(Level.FINE))
- logger.fine("SASL response: " +
- ASCIIUtility.toString(ba, 0, ba.length) + " :");
- ba = BASE64EncoderStream.encode(ba);
- resp = pr.simpleCommand(ba);
- }
- } else
- done = true;
- } catch (Exception ioex) {
- logger.log(Level.FINE, "SASL Exception", 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;
- }
- }
-
- return true;
- }
-
- private static final String responseText(SMTPTransport pr) {
- String resp = pr.getLastServerResponse().trim();
- if (resp.length() > 4)
- return resp.substring(4);
- else
- return "";
- }
-}
diff --git a/src/main/java/com/sun/mail/smtp/SMTPSendFailedException.java b/src/main/java/com/sun/mail/smtp/SMTPSendFailedException.java
deleted file mode 100644
index 1df8f6a1..00000000
--- a/src/main/java/com/sun/mail/smtp/SMTPSendFailedException.java
+++ /dev/null
@@ -1,98 +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.smtp;
-
-import javax.mail.Address;
-import javax.mail.SendFailedException;
-import javax.mail.internet.InternetAddress;
-
-/**
- * This exception is thrown when the message cannot be sent.
- *
- * This exception will usually appear first in a chained list of exceptions,
- * followed by SMTPAddressFailedExceptions and/or
- * SMTPAddressSucceededExceptions, * one per address.
- * This exception corresponds to one of the SMTP commands used to
- * send a message, such as the MAIL, DATA, and "end of data" commands,
- * but not including the RCPT command.
- *
- * @since JavaMail 1.3.2
- */
-
-public class SMTPSendFailedException extends SendFailedException {
- protected InternetAddress addr; // address that failed
- protected String cmd; // command issued to server
- protected int rc; // return code from SMTP server
-
- private static final long serialVersionUID = 8049122628728932894L;
-
- /**
- * Constructs an SMTPSendFailedException with the specified
- * address, return code, and error string.
- *
- * @param cmd the command that was sent to the SMTP server
- * @param rc the SMTP return code indicating the failure
- * @param err the error string from the SMTP server
- */
- public SMTPSendFailedException(String cmd, int rc, String err, Exception ex,
- Address[] vs, Address[] vus, Address[] inv) {
- super(err, ex, vs, vus, inv);
- this.cmd = cmd;
- this.rc = rc;
- }
-
- /**
- * Return the command that failed.
- */
- public String getCommand() {
- return cmd;
- }
-
- /**
- * Return the return code from the SMTP server that indicates the
- * reason for the failure. See
- * RFC 821
- * for interpretation of the return code.
- */
- public int getReturnCode() {
- return rc;
- }
-}
diff --git a/src/main/java/com/sun/mail/smtp/SMTPSenderFailedException.java b/src/main/java/com/sun/mail/smtp/SMTPSenderFailedException.java
deleted file mode 100644
index 7d3c1121..00000000
--- a/src/main/java/com/sun/mail/smtp/SMTPSenderFailedException.java
+++ /dev/null
@@ -1,103 +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.smtp;
-
-import javax.mail.SendFailedException;
-import javax.mail.internet.InternetAddress;
-
-/**
- * This exception is thrown when the message cannot be sent.
- *
- * The exception includes the sender's address, which the mail server
- * rejected.
- *
- * @since JavaMail 1.4.4
- */
-
-public class SMTPSenderFailedException extends SendFailedException {
- protected InternetAddress addr; // address that failed
- protected String cmd; // command issued to server
- protected int rc; // return code from SMTP server
-
- private static final long serialVersionUID = 514540454964476947L;
-
- /**
- * Constructs an SMTPSenderFailedException with the specified
- * address, return code, and error string.
- *
- * @param addr the address that failed
- * @param cmd the command that was sent to the SMTP server
- * @param rc the SMTP return code indicating the failure
- * @param err the error string from the SMTP server
- */
- public SMTPSenderFailedException(InternetAddress addr, String cmd, int rc,
- String err) {
- super(err);
- this.addr = addr;
- this.cmd = cmd;
- this.rc = rc;
- }
-
- /**
- * Return the address that failed.
- */
- public InternetAddress getAddress() {
- return addr;
- }
-
- /**
- * Return the command that failed.
- */
- public String getCommand() {
- return cmd;
- }
-
-
- /**
- * Return the return code from the SMTP server that indicates the
- * reason for the failure. See
- * RFC 821
- * for interpretation of the return code.
- */
- public int getReturnCode() {
- return rc;
- }
-}
diff --git a/src/main/java/com/sun/mail/smtp/SMTPTransport.java b/src/main/java/com/sun/mail/smtp/SMTPTransport.java
deleted file mode 100644
index 0cc75786..00000000
--- a/src/main/java/com/sun/mail/smtp/SMTPTransport.java
+++ /dev/null
@@ -1,2383 +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.smtp;
-
-import java.io.*;
-import java.net.*;
-import java.util.*;
-import java.util.logging.Level;
-import java.lang.reflect.*;
-import javax.net.ssl.SSLSocket;
-
-import javax.mail.*;
-import javax.mail.event.*;
-import javax.mail.internet.*;
-
-import com.sun.mail.util.*;
-import com.sun.mail.auth.*;
-
-/**
- * This class implements the Transport abstract class using SMTP for
- * message submission and transport.
- *
- * See the com.sun.mail.smtp package
- * documentation for further information on the SMTP protocol provider.
- *
- * This class includes many protected methods that allow a subclass to
- * extend this class and add support for non-standard SMTP commands.
- * The {@link #issueCommand} and {@link #sendCommand} methods can be
- * used to send simple SMTP commands. Other methods such as the
- * {@link #mailFrom} and {@link #data} methods can be overridden to
- * insert new commands before or after the corresponding SMTP commands.
- * For example, a subclass could do this to send the XACT command
- * before sending the DATA command:
- *
- *
- * @author Max Spivak
- * @author Bill Shannon
- * @author Dean Gibson (DIGEST-MD5 authentication)
- * @author Lu\u00EDs Serralheiro (NTLM authentication)
- *
- * @see javax.mail.event.ConnectionEvent
- * @see javax.mail.event.TransportEvent
- */
-
-public class SMTPTransport extends Transport {
-
- private String name = "smtp"; // Name of this protocol
- private int defaultPort = 25; // default SMTP port
- private boolean isSSL = false; // use SSL?
- private String host; // host we're connected to
-
- // Following fields valid only during the sendMessage method.
- private MimeMessage message; // Message to be sent
- private Address[] addresses; // Addresses to which to send the msg
- // Valid sent, valid unsent and invalid addresses
- private Address[] validSentAddr, validUnsentAddr, invalidAddr;
- // Did we send the message even though some addresses were invalid?
- private boolean sendPartiallyFailed = false;
- // If so, here's an exception we need to throw
- private MessagingException exception;
- // stream where message data is written
- private SMTPOutputStream dataStream;
-
- // Map of SMTP service extensions supported by server, if EHLO used.
- private Hashtable extMap;
-
- private Map authenticators = new HashMap();
- private String defaultAuthenticationMechanisms; // set in constructor
-
- private boolean quitWait = false; // true if we should wait
-
- private String saslRealm = UNKNOWN;
- private String authorizationID = UNKNOWN;
- private boolean enableSASL = false; // enable SASL authentication
- private String[] saslMechanisms = UNKNOWN_SA;
-
- private String ntlmDomain = UNKNOWN; // for ntlm authentication
-
- private boolean reportSuccess; // throw an exception even on success
- private boolean useStartTLS; // use STARTTLS command
- private boolean requireStartTLS; // require STARTTLS command
- private boolean useRset; // use RSET instead of NOOP
- private boolean noopStrict = true; // NOOP must return 250 for success
-
- private MailLogger logger; // debug logger
- private MailLogger traceLogger; // protocol trace logger
- private String localHostName; // our own host name
- private String lastServerResponse; // last SMTP response
- private int lastReturnCode; // last SMTP return code
- private boolean notificationDone; // only notify once per send
-
- private SaslAuthenticator saslAuthenticator; // if SASL is being used
-
- private boolean noauthdebug = true; // hide auth info in debug output
-
- /** Headers that should not be included when sending */
- private static final String[] ignoreList = { "Bcc", "Content-Length" };
- private static final byte[] CRLF = { (byte)'\r', (byte)'\n' };
- private static final String UNKNOWN = "UNKNOWN"; // place holder
- private static final String[] UNKNOWN_SA = new String[0]; // place holder
-
- /**
- * Constructor that takes a Session object and a URLName
- * that represents a specific SMTP server.
- */
- public SMTPTransport(Session session, URLName urlname) {
- this(session, urlname, "smtp", false);
- }
-
- /**
- * Constructor used by this class and by SMTPSSLTransport subclass.
- */
- protected SMTPTransport(Session session, URLName urlname,
- String name, boolean isSSL) {
- super(session, urlname);
- logger = new MailLogger(this.getClass(), "DEBUG SMTP", session);
- traceLogger = logger.getSubLogger("protocol", null);
- noauthdebug = !PropUtil.getBooleanSessionProperty(session,
- "mail.debug.auth", false);
- if (urlname != null)
- name = urlname.getProtocol();
- this.name = name;
- if (!isSSL)
- isSSL = PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".ssl.enable", false);
- if (isSSL)
- this.defaultPort = 465;
- else
- this.defaultPort = 25;
- this.isSSL = isSSL;
-
- // setting mail.smtp.quitwait to false causes us to not wait for the
- // response from the QUIT command
- quitWait = PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".quitwait", true);
-
- // mail.smtp.reportsuccess causes us to throw an exception on success
- reportSuccess = PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".reportsuccess", false);
-
- // mail.smtp.starttls.enable enables use of STARTTLS command
- useStartTLS = PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".starttls.enable", false);
-
- // mail.smtp.starttls.required requires use of STARTTLS command
- requireStartTLS = PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".starttls.required", false);
-
- // mail.smtp.userset causes us to use RSET instead of NOOP
- // for isConnected
- useRset = PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".userset", false);
-
- // mail.smtp.noop.strict requires 250 response to indicate success
- noopStrict = PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".noop.strict", true);
-
- // check if SASL is enabled
- enableSASL = PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".sasl.enable", false);
- if (enableSASL)
- logger.config("enable SASL");
-
- // created here, because they're inner classes that reference "this"
- Authenticator[] a = new Authenticator[] {
- new LoginAuthenticator(),
- new PlainAuthenticator(),
- new DigestMD5Authenticator(),
- new NtlmAuthenticator()
- };
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < a.length; i++) {
- authenticators.put(a[i].getMechanism(), a[i]);
- sb.append(a[i].getMechanism()).append(' ');
- }
- defaultAuthenticationMechanisms = sb.toString();
- }
-
- /**
- * Get the name of the local host, for use in the EHLO and HELO commands.
- * The property mail.smtp.localhost overrides mail.smtp.localaddress,
- * which overrides what InetAddress would tell us.
- */
- public synchronized String getLocalHost() {
- // get our hostname and cache it for future use
- if (localHostName == null || localHostName.length() <= 0)
- localHostName =
- session.getProperty("mail." + name + ".localhost");
- if (localHostName == null || localHostName.length() <= 0)
- localHostName =
- session.getProperty("mail." + name + ".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 (serverSocket != null && serverSocket.isBound()) {
- InetAddress localHost = serverSocket.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;
- }
-
- /**
- * Set the name of the local host, for use in the EHLO and HELO commands.
- *
- * @since JavaMail 1.3.1
- */
- public synchronized void setLocalHost(String localhost) {
- localHostName = localhost;
- }
-
- /**
- * Start the SMTP protocol on the given socket, which was already
- * connected by the caller. Useful for implementing the SMTP ATRN
- * command (RFC 2645) where an existing connection is used when
- * the server reverses roles and becomes the client.
- *
- * @since JavaMail 1.3.3
- */
- public synchronized void connect(Socket socket) throws MessagingException {
- serverSocket = socket;
- super.connect();
- }
-
- /**
- * Gets the authorization ID to be used for authentication.
- *
- * @return the authorization ID to use for authentication.
- *
- * @since JavaMail 1.4.4
- */
- public synchronized String getAuthorizationId() {
- if (authorizationID == UNKNOWN) {
- authorizationID =
- session.getProperty("mail." + name + ".sasl.authorizationid");
- }
- return authorizationID;
- }
-
- /**
- * Sets the authorization ID to be used for authentication.
- *
- * @param authzid the authorization ID to use for
- * authentication.
- *
- * @since JavaMail 1.4.4
- */
- public synchronized void setAuthorizationID(String authzid) {
- this.authorizationID = authzid;
- }
-
- /**
- * Is SASL authentication enabled?
- *
- * @return true if SASL authentication is enabled
- *
- * @since JavaMail 1.4.4
- */
- public synchronized boolean getSASLEnabled() {
- return enableSASL;
- }
-
- /**
- * Set whether SASL authentication is enabled.
- *
- * @param enableSASL should we enable SASL authentication?
- *
- * @since JavaMail 1.4.4
- */
- public synchronized void setSASLEnabled(boolean enableSASL) {
- this.enableSASL = enableSASL;
- }
-
- /**
- * Gets the SASL realm to be used for DIGEST-MD5 authentication.
- *
- * @return the name of the realm to use for SASL authentication.
- *
- * @since JavaMail 1.3.1
- */
- public synchronized String getSASLRealm() {
- if (saslRealm == UNKNOWN) {
- saslRealm = session.getProperty("mail." + name + ".sasl.realm");
- if (saslRealm == null) // try old name
- saslRealm = session.getProperty("mail." + name + ".saslrealm");
- }
- return saslRealm;
- }
-
- /**
- * Sets the SASL realm to be used for DIGEST-MD5 authentication.
- *
- * @param saslRealm the name of the realm to use for
- * SASL authentication.
- *
- * @since JavaMail 1.3.1
- */
- public synchronized void setSASLRealm(String saslRealm) {
- this.saslRealm = saslRealm;
- }
-
- /**
- * Get the list of SASL mechanisms to consider if SASL authentication
- * is enabled. If the list is empty or null, all available SASL mechanisms
- * are considered.
- *
- * @return the array of SASL mechanisms to consider
- *
- * @since JavaMail 1.4.4
- */
- public synchronized String[] getSASLMechanisms() {
- if (saslMechanisms == UNKNOWN_SA) {
- List v = new ArrayList(5);
- String s = session.getProperty("mail." + name + ".sasl.mechanisms");
- if (s != null && s.length() > 0) {
- if (logger.isLoggable(Level.FINE))
- logger.fine("SASL mechanisms allowed: " + s);
- StringTokenizer st = new StringTokenizer(s, " ,");
- while (st.hasMoreTokens()) {
- String m = st.nextToken();
- if (m.length() > 0)
- v.add(m);
- }
- }
- saslMechanisms = new String[v.size()];
- v.toArray(saslMechanisms);
- }
- if (saslMechanisms == null)
- return null;
- return (String[])saslMechanisms.clone();
- }
-
- /**
- * Set the list of SASL mechanisms to consider if SASL authentication
- * is enabled. If the list is empty or null, all available SASL mechanisms
- * are considered.
- *
- * @param mechanisms the array of SASL mechanisms to consider
- *
- * @since JavaMail 1.4.4
- */
- public synchronized void setSASLMechanisms(String[] mechanisms) {
- if (mechanisms != null)
- mechanisms = (String[])mechanisms.clone();
- this.saslMechanisms = mechanisms;
- }
-
- /**
- * Gets the NTLM domain to be used for NTLM authentication.
- *
- * @return the name of the domain to use for NTLM authentication.
- *
- * @since JavaMail 1.4.3
- */
- public synchronized String getNTLMDomain() {
- if (ntlmDomain == UNKNOWN) {
- ntlmDomain =
- session.getProperty("mail." + name + ".auth.ntlm.domain");
- }
- return ntlmDomain;
- }
-
- /**
- * Sets the NTLM domain to be used for NTLM authentication.
- *
- * @param ntlmDomain the name of the domain to use for
- * NTLM authentication.
- *
- * @since JavaMail 1.4.3
- */
- public synchronized void setNTLMDomain(String ntlmDomain) {
- this.ntlmDomain = ntlmDomain;
- }
-
- /**
- * Should we report even successful sends by throwing an exception?
- * If so, a SendFailedException will always be thrown and
- * an {@link com.sun.mail.smtp.SMTPAddressSucceededException
- * SMTPAddressSucceededException} will be included in the exception
- * chain for each successful address, along with the usual
- * {@link com.sun.mail.smtp.SMTPAddressFailedException
- * SMTPAddressFailedException} for each unsuccessful address.
- *
- * @return true if an exception will be thrown on successful sends.
- *
- * @since JavaMail 1.3.2
- */
- public synchronized boolean getReportSuccess() {
- return reportSuccess;
- }
-
- /**
- * Set whether successful sends should be reported by throwing
- * an exception.
- *
- * @param reportSuccess should we throw an exception on success?
- *
- * @since JavaMail 1.3.2
- */
- public synchronized void setReportSuccess(boolean reportSuccess) {
- this.reportSuccess = reportSuccess;
- }
-
- /**
- * Should we use the STARTTLS command to secure the connection
- * if the server supports it?
- *
- * @return true if the STARTTLS command will be used
- *
- * @since JavaMail 1.3.2
- */
- public synchronized boolean getStartTLS() {
- return useStartTLS;
- }
-
- /**
- * Set whether the STARTTLS command should be used.
- *
- * @param useStartTLS should we use the STARTTLS command?
- *
- * @since JavaMail 1.3.2
- */
- public synchronized void setStartTLS(boolean useStartTLS) {
- this.useStartTLS = useStartTLS;
- }
-
- /**
- * Should we require the STARTTLS command to secure the connection?
- *
- * @return true if the STARTTLS command will be required
- *
- * @since JavaMail 1.4.2
- */
- public synchronized boolean getRequireStartTLS() {
- return requireStartTLS;
- }
-
- /**
- * Set whether the STARTTLS command should be required.
- *
- * @param requireStartTLS should we require the STARTTLS command?
- *
- * @since JavaMail 1.4.2
- */
- public synchronized void setRequireStartTLS(boolean requireStartTLS) {
- this.requireStartTLS = requireStartTLS;
- }
-
- /**
- * Is this Transport using SSL to connect to the server?
- *
- * @return true if using SSL
- * @since JavaMail 1.4.6
- */
- public boolean isSSL() {
- return serverSocket instanceof SSLSocket;
- }
-
- /**
- * Should we use the RSET command instead of the NOOP command
- * in the @{link #isConnected isConnected} method?
- *
- * @return true if RSET will be used
- *
- * @since JavaMail 1.4
- */
- public synchronized boolean getUseRset() {
- return useRset;
- }
-
- /**
- * Set whether the RSET command should be used instead of the
- * NOOP command in the @{link #isConnected isConnected} method.
- *
- * @param useRset should we use the RSET command?
- *
- * @since JavaMail 1.4
- */
- public synchronized void setUseRset(boolean useRset) {
- this.useRset = useRset;
- }
-
- /**
- * Is the NOOP command required to return a response code
- * of 250 to indicate success?
- *
- * @return true if NOOP must return 250
- *
- * @since JavaMail 1.4.3
- */
- public synchronized boolean getNoopStrict() {
- return noopStrict;
- }
-
- /**
- * Set whether the NOOP command is required to return a response code
- * of 250 to indicate success.
- *
- * @param noopStrict is NOOP required to return 250?
- *
- * @since JavaMail 1.4.3
- */
- public synchronized void setNoopStrict(boolean noopStrict) {
- this.noopStrict = noopStrict;
- }
-
- /**
- * Return the last response we got from the server.
- * A failed send is often followed by an RSET command,
- * but the response from the RSET command is not saved.
- * Instead, this returns the response from the command
- * before the RSET command.
- *
- * @return last response from server
- *
- * @since JavaMail 1.3.2
- */
- public synchronized String getLastServerResponse() {
- return lastServerResponse;
- }
-
- /**
- * Return the return code from the last response we got from the server.
- *
- * @return return code from last response from server
- *
- * @since JavaMail 1.4.1
- */
- public synchronized int getLastReturnCode() {
- return lastReturnCode;
- }
-
- /**
- * Performs the actual protocol-specific connection attempt.
- * Will attempt to connect to "localhost" if the host was null.
- *
- * Unless mail.smtp.ehlo is set to false, we'll try to identify
- * ourselves using the ESMTP command EHLO.
- *
- * If mail.smtp.auth is set to true, we insist on having a username
- * and password, and will try to authenticate ourselves if the server
- * supports the AUTH extension (RFC 2554).
- *
- * @param host the name of the host to connect to
- * @param port the port to use (-1 means use default port)
- * @param user the name of the user to login as
- * @param passwd the user's password
- * @return true if connection successful, false if authentication failed
- * @exception MessagingException for non-authentication failures
- */
- protected synchronized boolean protocolConnect(String host, int port,
- String user, String passwd) throws MessagingException {
- // setting mail.smtp.ehlo to false disables attempts to use EHLO
- boolean useEhlo = PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".ehlo", true);
- // setting mail.smtp.auth to true enables attempts to use AUTH
- boolean useAuth = PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".auth", false);
-
- if (logger.isLoggable(Level.FINE))
- logger.fine("useEhlo " + useEhlo + ", useAuth " + useAuth);
-
- /*
- * If mail.smtp.auth is set, make sure we have a valid username
- * and password, even if we might not end up using it (e.g.,
- * because the server doesn't support ESMTP or doesn't support
- * the AUTH extension).
- */
- if (useAuth && (user == null || passwd == null))
- return false;
-
- /*
- * If port is not specified, set it to value of mail.smtp.port
- * property if it exists, otherwise default to 25.
- */
- if (port == -1)
- port = PropUtil.getIntSessionProperty(session,
- "mail." + name + ".port", -1);
- if (port == -1)
- port = defaultPort;
-
- if (host == null || host.length() == 0)
- host = "localhost";
-
- /*
- * If anything goes wrong, we need to be sure
- * to close the connection.
- */
- boolean connected = false;
- try {
-
- if (serverSocket != null)
- openServer(); // only happens from connect(socket)
- else
- openServer(host, port);
-
- boolean succeed = false;
- if (useEhlo)
- succeed = ehlo(getLocalHost());
- if (!succeed)
- helo(getLocalHost());
-
- if (useStartTLS || requireStartTLS) {
- if (serverSocket instanceof SSLSocket) {
- logger.fine("STARTTLS requested but already using SSL");
- } else if (supportsExtension("STARTTLS")) {
- startTLS();
- /*
- * Have to issue another EHLO to update list of extensions
- * supported, especially authentication mechanisms.
- * Don't know if this could ever fail, but we ignore
- * failure.
- */
- ehlo(getLocalHost());
- } else if (requireStartTLS) {
- logger.fine("STARTTLS required but not supported");
- throw new MessagingException(
- "STARTTLS is required but " +
- "host does not support STARTTLS");
- }
- }
-
- if ((useAuth || (user != null && passwd != null)) &&
- (supportsExtension("AUTH") ||
- supportsExtension("AUTH=LOGIN"))) {
- connected = authenticate(user, passwd);
- return connected;
- }
-
- // we connected correctly
- connected = true;
- return true;
-
- } finally {
- // if we didn't connect successfully,
- // make sure the connection is closed
- if (!connected) {
- try {
- closeConnection();
- } catch (MessagingException mex) { } // ignore it
- }
- }
- }
-
- /**
- * Authenticate to the server.
- */
- private boolean authenticate(String user, String passwd)
- throws MessagingException {
- // setting mail.smtp.auth.mechanisms controls which mechanisms will
- // be used, and in what order they'll be considered. only the first
- // match is used.
- String mechs = session.getProperty("mail." + name + ".auth.mechanisms");
- if (mechs == null)
- mechs = defaultAuthenticationMechanisms;
-
- String authzid = getAuthorizationId();
- if (authzid == null)
- authzid = user;
- if (enableSASL) {
- logger.fine("Authenticate with SASL");
- if (sasllogin(getSASLMechanisms(), getSASLRealm(), authzid,
- user, passwd))
- return true; // success
- logger.fine("SASL authentication failed");
- }
-
- if (logger.isLoggable(Level.FINE))
- logger.fine("Attempt to authenticate using mechanisms: " + mechs);
-
- /*
- * Loop through the list of mechanisms supplied by the user
- * (or defaulted) and try each in turn. If the server supports
- * the mechanism and we have an authenticator for the mechanism,
- * and it hasn't been disabled, use it.
- */
- StringTokenizer st = new StringTokenizer(mechs);
- while (st.hasMoreTokens()) {
- String m = st.nextToken();
- String dprop = "mail." + name + ".auth." +
- m.toLowerCase(Locale.ENGLISH) + ".disable";
- boolean disabled =
- PropUtil.getBooleanSessionProperty(session, dprop, false);
- if (disabled) {
- if (logger.isLoggable(Level.FINE))
- logger.fine(
- "mechanism " + m + " disabled by property: " + dprop);
- continue;
- }
- m = m.toUpperCase(Locale.ENGLISH);
- if (!supportsAuthentication(m)) {
- logger.log(Level.FINE, "mechanism {0} not supported by server",
- m);
- continue;
- }
- Authenticator a = (Authenticator)authenticators.get(m);
- if (a == null) {
- logger.log(Level.FINE, "no authenticator for mechanism {0}", m);
- continue;
- }
- // only first supported mechanism is used
- return a.authenticate(host, authzid, user, passwd);
- }
-
- // if no authentication mechanism found, fail
- throw new AuthenticationFailedException(
- "No authentication mechansims supported by both server and client");
- }
-
- /**
- * Abstract base class for SMTP authentication mechanism implementations.
- */
- private abstract class Authenticator {
- protected int resp; // the response code, used by subclasses
- private String mech; // the mechanism name, set in the constructor
-
- Authenticator(String mech) {
- this.mech = mech.toUpperCase(Locale.ENGLISH);
- }
-
- String getMechanism() {
- return mech;
- }
-
- /**
- * Start the authentication handshake by issuing the AUTH command.
- * Delegate to the doAuth method to do the mechanism-specific
- * part of the handshake.
- */
- boolean authenticate(String host, String authzid,
- String user, String passwd) throws MessagingException {
- try {
- // use "initial response" capability, if supported
- String ir = getInitialResponse(host, authzid, user, passwd);
- if (noauthdebug && isTracing()) {
- logger.fine("AUTH " + mech + " command trace suppressed");
- suspendTracing();
- }
- if (ir != null)
- resp = simpleCommand("AUTH " + mech + " " +
- (ir.length() == 0 ? "=" : ir));
- else
- resp = simpleCommand("AUTH " + mech);
-
- /*
- * A 530 response indicates that the server wants us to
- * issue a STARTTLS command first. Do that and try again.
- */
- if (resp == 530) {
- startTLS();
- if (ir != null)
- resp = simpleCommand("AUTH " + mech + " " + ir);
- else
- resp = simpleCommand("AUTH " + mech);
- }
- if (resp == 334)
- doAuth(host, authzid, user, passwd);
- } catch (IOException ex) { // should never happen, ignore
- logger.log(Level.FINE, "AUTH " + mech + " failed", ex);
- } finally {
- if (noauthdebug && isTracing())
- logger.fine("AUTH " + mech + " " +
- (resp == 235 ? "succeeded" : "failed"));
- resumeTracing();
- if (resp != 235) {
- closeConnection();
- throw new AuthenticationFailedException(
- getLastServerResponse());
- }
- }
- return true;
- }
-
- /**
- * Provide the initial response to use in the AUTH command,
- * or null if not supported. Subclasses that support the
- * initial response capability will override this method.
- */
- String getInitialResponse(String host, String authzid, String user,
- String passwd) throws MessagingException, IOException {
- return null;
- }
-
- abstract void doAuth(String host, String authzid, String user,
- String passwd) throws MessagingException, IOException;
- }
-
- /**
- * Perform the authentication handshake for LOGIN authentication.
- */
- private class LoginAuthenticator extends Authenticator {
- LoginAuthenticator() {
- super("LOGIN");
- }
-
- void doAuth(String host, String authzid, String user, String passwd)
- throws MessagingException, IOException {
- // send username
- resp = simpleCommand(
- BASE64EncoderStream.encode(ASCIIUtility.getBytes(user)));
- if (resp == 334) {
- // send passwd
- resp = simpleCommand(
- BASE64EncoderStream.encode(ASCIIUtility.getBytes(passwd)));
- }
- }
- }
-
- /**
- * Perform the authentication handshake for PLAIN authentication.
- */
- private class PlainAuthenticator extends Authenticator {
- PlainAuthenticator() {
- super("PLAIN");
- }
-
- String getInitialResponse(String host, String authzid, String user,
- String passwd) throws MessagingException, IOException {
- // return "authziduserpasswd"
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- OutputStream b64os =
- new BASE64EncoderStream(bos, Integer.MAX_VALUE);
- if (authzid != null)
- b64os.write(ASCIIUtility.getBytes(authzid));
- b64os.write(0);
- b64os.write(ASCIIUtility.getBytes(user));
- b64os.write(0);
- b64os.write(ASCIIUtility.getBytes(passwd));
- b64os.flush(); // complete the encoding
-
- return ASCIIUtility.toString(bos.toByteArray());
- }
-
- void doAuth(String host, String authzid, String user, String passwd)
- throws MessagingException, IOException {
- // should never get here
- throw new AuthenticationFailedException("PLAIN asked for more");
- }
- }
-
- /**
- * Perform the authentication handshake for DIGEST-MD5 authentication.
- */
- private class DigestMD5Authenticator extends Authenticator {
- private DigestMD5 md5support; // only create if needed
-
- DigestMD5Authenticator() {
- super("DIGEST-MD5");
- }
-
- private synchronized DigestMD5 getMD5() {
- if (md5support == null)
- md5support = new DigestMD5(logger);
- return md5support;
- }
-
- void doAuth(String host, String authzid, String user, String passwd)
- throws MessagingException, IOException {
- DigestMD5 md5 = getMD5();
- if (md5 == null) {
- resp = -1;
- return; // XXX - should never happen
- }
-
- byte[] b = md5.authClient(host, user, passwd, getSASLRealm(),
- getLastServerResponse());
- resp = simpleCommand(b);
- if (resp == 334) { // client authenticated by server
- if (!md5.authServer(getLastServerResponse())) {
- // server NOT authenticated by client !!!
- resp = -1;
- } else {
- // send null response
- resp = simpleCommand(new byte[0]);
- }
- }
- }
- }
-
- /**
- * Perform the authentication handshake for NTLM authentication.
- */
- private class NtlmAuthenticator extends Authenticator {
- private Ntlm ntlm;
- private int flags;
-
- NtlmAuthenticator() {
- super("NTLM");
- }
-
- String getInitialResponse(String host, String authzid, String user,
- String passwd) throws MessagingException, IOException {
- ntlm = new Ntlm(getNTLMDomain(), getLocalHost(),
- user, passwd, logger);
-
- flags = PropUtil.getIntProperty(
- session.getProperties(),
- "mail." + name + ".auth.ntlm.flags", 0);
-
- String type1 = ntlm.generateType1Msg(flags);
- return type1;
- }
-
- void doAuth(String host, String authzid, String user, String passwd)
- throws MessagingException, IOException {
- String type3 = ntlm.generateType3Msg(
- getLastServerResponse().substring(4).trim());
-
- resp = simpleCommand(type3);
- }
- }
-
- /**
- * SASL-based login.
- */
- public boolean sasllogin(String[] allowed, String realm, String authzid,
- String u, String p) throws MessagingException {
- if (saslAuthenticator == null) {
- try {
- Class sac = Class.forName(
- "com.sun.mail.smtp.SMTPSaslAuthenticator");
- Constructor c = sac.getConstructor(new Class[] {
- SMTPTransport.class,
- String.class,
- Properties.class,
- MailLogger.class,
- String.class
- });
- saslAuthenticator = (SaslAuthenticator)c.newInstance(
- new Object[] {
- this,
- name,
- session.getProperties(),
- logger,
- host
- });
- } catch (Exception ex) {
- logger.log(Level.FINE, "Can't load SASL authenticator", ex);
- // probably because we're running on a system without SASL
- return false; // not authenticated, try without SASL
- }
- }
-
- // were any allowed mechanisms specified?
- List v;
- if (allowed != null && allowed.length > 0) {
- // remove anything not supported by the server
- v = new ArrayList(allowed.length);
- for (int i = 0; i < allowed.length; i++)
- if (supportsAuthentication(allowed[i])) // XXX - case must match
- v.add(allowed[i]);
- } else {
- // everything is allowed
- v = new ArrayList();
- if (extMap != null) {
- String a = (String)extMap.get("AUTH");
- if (a != null) {
- StringTokenizer st = new StringTokenizer(a);
- while (st.hasMoreTokens())
- v.add(st.nextToken());
- }
- }
- }
- String[] mechs = (String[])v.toArray(new String[v.size()]);
- try {
- if (noauthdebug && isTracing()) {
- logger.fine("SASL AUTH command trace suppressed");
- suspendTracing();
- }
- return saslAuthenticator.authenticate(mechs, realm, authzid, u, p);
- } finally {
- resumeTracing();
- }
- }
-
- /**
- * Send the Message to the specified list of addresses.
- *
- * If all the addresses succeed the SMTP check
- * using the RCPT TO: command, we attempt to send the message.
- * A TransportEvent of type MESSAGE_DELIVERED is fired indicating the
- * successful submission of a message to the SMTP host.
- *
- * If some of the addresses fail the SMTP check,
- * and the mail.stmp.sendpartial property is not set,
- * sending is aborted. The TransportEvent of type MESSAGE_NOT_DELIVERED
- * is fired containing the valid and invalid addresses. The
- * SendFailedException is also thrown.
- *
- * If some of the addresses fail the SMTP check,
- * and the mail.stmp.sendpartial property is set to true,
- * the message is sent. The TransportEvent of type
- * MESSAGE_PARTIALLY_DELIVERED
- * is fired containing the valid and invalid addresses. The
- * SMTPSendFailedException is also thrown.
- *
- * MessagingException is thrown if the message can't write out
- * an RFC822-compliant stream using its writeTo method.
- *
- * @param message The MimeMessage to be sent
- * @param addresses List of addresses to send this message to
- * @see javax.mail.event.TransportEvent
- * @exception SMTPSendFailedException if the send failed because of
- * an SMTP command error
- * @exception SendFailedException if the send failed because of
- * invalid addresses.
- * @exception MessagingException if the connection is dead
- * or not in the connected state or if the message is
- * not a MimeMessage.
- */
- public synchronized void sendMessage(Message message, Address[] addresses)
- throws MessagingException, SendFailedException {
-
- sendMessageStart(message != null ? message.getSubject() : "");
- checkConnected();
-
- // check if the message is a valid MIME/RFC822 message and that
- // it has all valid InternetAddresses; fail if not
- if (!(message instanceof MimeMessage)) {
- logger.fine("Can only send RFC822 msgs");
- throw new MessagingException("SMTP can only send RFC822 messages");
- }
- for (int i = 0; i < addresses.length; i++) {
- if (!(addresses[i] instanceof InternetAddress)) {
- throw new MessagingException(addresses[i] +
- " is not an InternetAddress");
- }
- }
- if (addresses.length == 0)
- throw new SendFailedException("No recipient addresses");
-
- this.message = (MimeMessage)message;
- this.addresses = addresses;
- validUnsentAddr = addresses; // until we know better
- expandGroups();
-
- boolean use8bit = false;
- if (message instanceof SMTPMessage)
- use8bit = ((SMTPMessage)message).getAllow8bitMIME();
- if (!use8bit)
- use8bit = PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".allow8bitmime", false);
- if (logger.isLoggable(Level.FINE))
- logger.fine("use8bit " + use8bit);
- if (use8bit && supportsExtension("8BITMIME")) {
- if (convertTo8Bit(this.message)) {
- // in case we made any changes, save those changes
- // XXX - this will change the Message-ID
- try {
- this.message.saveChanges();
- } catch (MessagingException mex) {
- // ignore it
- }
- }
- }
-
- try {
- mailFrom();
- rcptTo();
- this.message.writeTo(data(), ignoreList);
- finishData();
- if (sendPartiallyFailed) {
- // throw the exception,
- // fire TransportEvent.MESSAGE_PARTIALLY_DELIVERED event
- logger.fine("Sending partially failed " +
- "because of invalid destination addresses");
- notifyTransportListeners(
- TransportEvent.MESSAGE_PARTIALLY_DELIVERED,
- validSentAddr, validUnsentAddr, invalidAddr,
- this.message);
-
- throw new SMTPSendFailedException(".", lastReturnCode,
- lastServerResponse, exception,
- validSentAddr, validUnsentAddr, invalidAddr);
- }
- notifyTransportListeners(TransportEvent.MESSAGE_DELIVERED,
- validSentAddr, validUnsentAddr,
- invalidAddr, this.message);
- } catch (MessagingException mex) {
- logger.log(Level.FINE, "MessagingException while sending", mex);
- // the MessagingException might be wrapping an IOException
- if (mex.getNextException() instanceof IOException) {
- // if we catch an IOException, it means that we want
- // to drop the connection so that the message isn't sent
- logger.fine("nested IOException, closing");
- try {
- closeConnection();
- } catch (MessagingException cex) { /* ignore it */ }
- }
- addressesFailed();
- notifyTransportListeners(TransportEvent.MESSAGE_NOT_DELIVERED,
- validSentAddr, validUnsentAddr,
- invalidAddr, this.message);
-
- throw mex;
- } catch (IOException ex) {
- logger.log(Level.FINE, "IOException while sending, closing", ex);
- // if we catch an IOException, it means that we want
- // to drop the connection so that the message isn't sent
- try {
- closeConnection();
- } catch (MessagingException mex) { /* ignore it */ }
- addressesFailed();
- notifyTransportListeners(TransportEvent.MESSAGE_NOT_DELIVERED,
- validSentAddr, validUnsentAddr,
- invalidAddr, this.message);
-
- throw new MessagingException("IOException while sending message",
- ex);
- } finally {
- // no reason to keep this data around
- validSentAddr = validUnsentAddr = invalidAddr = null;
- this.addresses = null;
- this.message = null;
- this.exception = null;
- sendPartiallyFailed = false;
- notificationDone = false; // reset for next send
- }
- sendMessageEnd();
- }
-
- /**
- * The send failed, fix the address arrays to report the failure correctly.
- */
- private void addressesFailed() {
- if (validSentAddr != null) {
- if (validUnsentAddr != null) {
- Address newa[] =
- new Address[validSentAddr.length + validUnsentAddr.length];
- System.arraycopy(validSentAddr, 0,
- newa, 0, validSentAddr.length);
- System.arraycopy(validUnsentAddr, 0,
- newa, validSentAddr.length, validUnsentAddr.length);
- validSentAddr = null;
- validUnsentAddr = newa;
- } else {
- validUnsentAddr = validSentAddr;
- validSentAddr = null;
- }
- }
- }
-
- /**
- * Close the Transport and terminate the connection to the server.
- */
- public synchronized void close() throws MessagingException {
- if (!super.isConnected()) // Already closed.
- return;
- try {
- if (serverSocket != null) {
- sendCommand("QUIT");
- if (quitWait) {
- int resp = readServerResponse();
- if (resp != 221 && resp != -1 &&
- logger.isLoggable(Level.FINE))
- logger.fine("QUIT failed with " + resp);
- }
- }
- } finally {
- closeConnection();
- }
- }
-
- private void closeConnection() throws MessagingException {
- try {
- if (serverSocket != null)
- serverSocket.close();
- } catch (IOException ioex) { // shouldn't happen
- throw new MessagingException("Server Close Failed", ioex);
- } finally {
- serverSocket = null;
- serverOutput = null;
- serverInput = null;
- lineInputStream = null;
- if (super.isConnected()) // only notify if already connected
- super.close();
- }
- }
-
- /**
- * Check whether the transport is connected. Override superclass
- * method, to actually ping our server connection.
- */
- public synchronized boolean isConnected() {
- if (!super.isConnected())
- // if we haven't been connected at all, don't bother with NOOP
- return false;
-
- try {
- // sendmail may respond slowly to NOOP after many requests
- // so if mail.smtp.userset is set we use RSET instead of NOOP.
- if (useRset)
- sendCommand("RSET");
- else
- sendCommand("NOOP");
- int resp = readServerResponse();
-
- /*
- * NOOP should return 250 on success, however, SIMS 3.2 returns
- * 200, so we work around it.
- *
- * Hotmail didn't used to implement the NOOP command at all so
- * assume any kind of response means we're still connected.
- * That is, any response except 421, which means the server
- * is shutting down the connection.
- *
- * Some versions of Exchange return 451 instead of 421 when
- * timing out a connection.
- *
- * Argh!
- *
- * If mail.smtp.noop.strict is set to false, be tolerant of
- * servers that return the wrong response code for success.
- */
- if (resp >= 0 && (noopStrict ? resp == 250 : resp != 421)) {
- return true;
- } else {
- try {
- closeConnection();
- } catch (MessagingException mex) { } // ignore it
- return false;
- }
- } catch (Exception ex) {
- try {
- closeConnection();
- } catch (MessagingException mex) { } // ignore it
- return false;
- }
- }
-
- /**
- * Notify all TransportListeners. Keep track of whether notification
- * has been done so as to only notify once per send.
- *
- * @since JavaMail 1.4.2
- */
- protected void notifyTransportListeners(int type, Address[] validSent,
- Address[] validUnsent,
- Address[] invalid, Message msg) {
-
- if (!notificationDone) {
- super.notifyTransportListeners(type, validSent, validUnsent,
- invalid, msg);
- notificationDone = true;
- }
- }
-
- /**
- * Expand any group addresses.
- */
- private void expandGroups() {
- Vector groups = null;
- for (int i = 0; i < addresses.length; i++) {
- InternetAddress a = (InternetAddress)addresses[i];
- if (a.isGroup()) {
- if (groups == null) {
- // first group, catch up with where we are
- groups = new Vector();
- for (int k = 0; k < i; k++)
- groups.addElement(addresses[k]);
- }
- // parse it and add each individual address
- try {
- InternetAddress[] ia = a.getGroup(true);
- if (ia != null) {
- for (int j = 0; j < ia.length; j++)
- groups.addElement(ia[j]);
- } else
- groups.addElement(a);
- } catch (ParseException pex) {
- // parse failed, add the whole thing
- groups.addElement(a);
- }
- } else {
- // if we've started accumulating a list, add this to it
- if (groups != null)
- groups.addElement(a);
- }
- }
-
- // if we have a new list, convert it back to an array
- if (groups != null) {
- InternetAddress[] newa = new InternetAddress[groups.size()];
- groups.copyInto(newa);
- addresses = newa;
- }
- }
-
- /**
- * If the Part is a text part and has a Content-Transfer-Encoding
- * of "quoted-printable" or "base64", and it obeys the rules for
- * "8bit" encoding, change the encoding to "8bit". If the part is
- * a multipart, recursively process all its parts.
- *
- * @return true if any changes were made
- *
- * XXX - This is really quite a hack.
- */
- private boolean convertTo8Bit(MimePart part) {
- boolean changed = false;
- try {
- if (part.isMimeType("text/*")) {
- String enc = part.getEncoding();
- if (enc != null && (enc.equalsIgnoreCase("quoted-printable") ||
- enc.equalsIgnoreCase("base64"))) {
- InputStream is = null;
- try {
- is = part.getInputStream();
- if (is8Bit(is)) {
- /*
- * If the message was created using an InputStream
- * then we have to extract the content as an object
- * and set it back as an object so that the content
- * will be re-encoded.
- *
- * If the message was not created using an
- * InputStream, the following should have no effect.
- */
- part.setContent(part.getContent(),
- part.getContentType());
- part.setHeader("Content-Transfer-Encoding", "8bit");
- changed = true;
- }
- } finally {
- if (is != null) {
- try {
- is.close();
- } catch (IOException ex2) {
- // ignore it
- }
- }
- }
- }
- } else if (part.isMimeType("multipart/*")) {
- MimeMultipart mp = (MimeMultipart)part.getContent();
- int count = mp.getCount();
- for (int i = 0; i < count; i++) {
- if (convertTo8Bit((MimePart)mp.getBodyPart(i)))
- changed = true;
- }
- }
- } catch (IOException ioex) {
- // any exception causes us to give up
- } catch (MessagingException mex) {
- // any exception causes us to give up
- }
- return changed;
- }
-
- /**
- * Check whether the data in the given InputStream follows the
- * rules for 8bit text. Lines have to be 998 characters or less
- * and no NULs are allowed. CR and LF must occur in pairs but we
- * don't check that because we assume this is text and we convert
- * all CR/LF combinations into canonical CRLF later.
- */
- private boolean is8Bit(InputStream is) {
- int b;
- int linelen = 0;
- boolean need8bit = false;
- try {
- while ((b = is.read()) >= 0) {
- b &= 0xff;
- if (b == '\r' || b == '\n')
- linelen = 0;
- else if (b == 0)
- return false;
- else {
- linelen++;
- if (linelen > 998) // 1000 - CRLF
- return false;
- }
- if (b > 0x7f)
- need8bit = true;
- }
- } catch (IOException ex) {
- return false;
- }
- if (need8bit)
- logger.fine("found an 8bit part");
- return need8bit;
- }
-
- protected void finalize() throws Throwable {
- super.finalize();
- try {
- closeConnection();
- } catch (MessagingException mex) { } // ignore it
- }
-
- ///////////////////// smtp stuff ///////////////////////
- private BufferedInputStream serverInput;
- private LineInputStream lineInputStream;
- private OutputStream serverOutput;
- private Socket serverSocket;
- private TraceInputStream traceInput;
- private TraceOutputStream traceOutput;
-
- /////// smtp protocol //////
-
- /**
- * Issue the HELO command.
- *
- * @param domain our domain
- *
- * @since JavaMail 1.4.1
- */
- protected void helo(String domain) throws MessagingException {
- if (domain != null)
- issueCommand("HELO " + domain, 250);
- else
- issueCommand("HELO", 250);
- }
-
- /**
- * Issue the EHLO command.
- * Collect the returned list of service extensions.
- *
- * @param domain our domain
- * @return true if command succeeds
- *
- * @since JavaMail 1.4.1
- */
- protected boolean ehlo(String domain) throws MessagingException {
- String cmd;
- if (domain != null)
- cmd = "EHLO " + domain;
- else
- cmd = "EHLO";
- sendCommand(cmd);
- int resp = readServerResponse();
- if (resp == 250) {
- // extract the supported service extensions
- BufferedReader rd =
- new BufferedReader(new StringReader(lastServerResponse));
- String line;
- extMap = new Hashtable();
- try {
- boolean first = true;
- while ((line = rd.readLine()) != null) {
- if (first) { // skip first line which is the greeting
- first = false;
- continue;
- }
- if (line.length() < 5)
- continue; // shouldn't happen
- line = line.substring(4); // skip response code
- int i = line.indexOf(' ');
- String arg = "";
- if (i > 0) {
- arg = line.substring(i + 1);
- line = line.substring(0, i);
- }
- if (logger.isLoggable(Level.FINE))
- logger.fine("Found extension \"" +
- line + "\", arg \"" + arg + "\"");
- extMap.put(line.toUpperCase(Locale.ENGLISH), arg);
- }
- } catch (IOException ex) { } // can't happen
- }
- return resp == 250;
- }
-
- /**
- * Issue the MAIL FROM: command to start sending a message.
- *
- * Gets the sender's address in the following order:
- *
- *
SMTPMessage.getEnvelopeFrom()
- *
mail.smtp.from property
- *
From: header in the message
- *
System username using the
- * InternetAddress.getLocalAddress() method
- *
- *
- * @since JavaMail 1.4.1
- */
- protected void mailFrom() throws MessagingException {
- String from = null;
- if (message instanceof SMTPMessage)
- from = ((SMTPMessage)message).getEnvelopeFrom();
- if (from == null || from.length() <= 0)
- from = session.getProperty("mail." + name + ".from");
- if (from == null || from.length() <= 0) {
- Address[] fa;
- Address me;
- if (message != null && (fa = message.getFrom()) != null &&
- fa.length > 0)
- me = fa[0];
- else
- me = InternetAddress.getLocalAddress(session);
-
- if (me != null)
- from = ((InternetAddress)me).getAddress();
- else
- throw new MessagingException(
- "can't determine local email address");
- }
-
- String cmd = "MAIL FROM:" + normalizeAddress(from);
-
- // request delivery status notification?
- if (supportsExtension("DSN")) {
- String ret = null;
- if (message instanceof SMTPMessage)
- ret = ((SMTPMessage)message).getDSNRet();
- if (ret == null)
- ret = session.getProperty("mail." + name + ".dsn.ret");
- // XXX - check for legal syntax?
- if (ret != null)
- cmd += " RET=" + ret;
- }
-
- /*
- * If an RFC 2554 submitter has been specified, and the server
- * supports the AUTH extension, include the AUTH= element on
- * the MAIL FROM command.
- */
- if (supportsExtension("AUTH")) {
- String submitter = null;
- if (message instanceof SMTPMessage)
- submitter = ((SMTPMessage)message).getSubmitter();
- if (submitter == null)
- submitter = session.getProperty("mail." + name + ".submitter");
- // XXX - check for legal syntax?
- if (submitter != null) {
- try {
- String s = xtext(submitter);
- cmd += " AUTH=" + s;
- } catch (IllegalArgumentException ex) {
- if (logger.isLoggable(Level.FINE))
- logger.log(Level.FINE, "ignoring invalid submitter: " +
- submitter, ex);
- }
- }
- }
-
- /*
- * Have any extensions to the MAIL command been specified?
- */
- String ext = null;
- if (message instanceof SMTPMessage)
- ext = ((SMTPMessage)message).getMailExtension();
- if (ext == null)
- ext = session.getProperty("mail." + name + ".mailextension");
- if (ext != null && ext.length() > 0)
- cmd += " " + ext;
-
- try {
- issueSendCommand(cmd, 250);
- } catch (SMTPSendFailedException ex) {
- int retCode = ex.getReturnCode();
- switch (retCode) {
- case 550: case 553: case 503: case 551: case 501:
- // given address is invalid
- try {
- ex.setNextException(new SMTPSenderFailedException(
- new InternetAddress(from), cmd,
- retCode, ex.getMessage()));
- } catch (AddressException aex) {
- // oh well...
- }
- break;
- }
- throw ex;
- }
- }
-
- /**
- * Sends each address to the SMTP host using the RCPT TO:
- * command and copies the address either into
- * the validSentAddr or invalidAddr arrays.
- * Sets the sendFailed
- * flag to true if any addresses failed.
- *
- * @since JavaMail 1.4.1
- */
- /*
- * success/failure/error possibilities from the RCPT command
- * from rfc821, section 4.3
- * S: 250, 251
- * F: 550, 551, 552, 553, 450, 451, 452
- * E: 500, 501, 503, 421
- *
- * and how we map the above error/failure conditions to valid/invalid
- * address vectors that are reported in the thrown exception:
- * invalid addr: 550, 501, 503, 551, 553
- * valid addr: 552 (quota), 450, 451, 452 (quota), 421 (srvr abort)
- */
- protected void rcptTo() throws MessagingException {
- Vector valid = new Vector();
- Vector validUnsent = new Vector();
- Vector invalid = new Vector();
- int retCode = -1;
- MessagingException mex = null;
- boolean sendFailed = false;
- MessagingException sfex = null;
- validSentAddr = validUnsentAddr = invalidAddr = null;
- boolean sendPartial = false;
- if (message instanceof SMTPMessage)
- sendPartial = ((SMTPMessage)message).getSendPartial();
- if (!sendPartial)
- sendPartial = PropUtil.getBooleanSessionProperty(session,
- "mail." + name + ".sendpartial", false);
- if (sendPartial)
- logger.fine("sendPartial set");
-
- boolean dsn = false;
- String notify = null;
- if (supportsExtension("DSN")) {
- if (message instanceof SMTPMessage)
- notify = ((SMTPMessage)message).getDSNNotify();
- if (notify == null)
- notify = session.getProperty("mail." + name + ".dsn.notify");
- // XXX - check for legal syntax?
- if (notify != null)
- dsn = true;
- }
-
- // try the addresses one at a time
- for (int i = 0; i < addresses.length; i++) {
-
- sfex = null;
- InternetAddress ia = (InternetAddress)addresses[i];
- String cmd = "RCPT TO:" + normalizeAddress(ia.getAddress());
- if (dsn)
- cmd += " NOTIFY=" + notify;
- // send the addresses to the SMTP server
- sendCommand(cmd);
- // check the server's response for address validity
- retCode = readServerResponse();
- switch (retCode) {
- case 250: case 251:
- valid.addElement(ia);
- if (!reportSuccess)
- break;
-
- // user wants exception even when successful, including
- // details of the return code
-
- // create and chain the exception
- sfex = new SMTPAddressSucceededException(ia, cmd, retCode,
- lastServerResponse);
- if (mex == null)
- mex = sfex;
- else
- mex.setNextException(sfex);
- break;
-
- case 550: case 553: case 503: case 551: case 501:
- // given address is invalid
- if (!sendPartial)
- sendFailed = true;
- invalid.addElement(ia);
- // create and chain the exception
- sfex = new SMTPAddressFailedException(ia, cmd, retCode,
- lastServerResponse);
- if (mex == null)
- mex = sfex;
- else
- mex.setNextException(sfex);
- break;
-
- case 552: case 450: case 451: case 452:
- // given address is valid
- if (!sendPartial)
- sendFailed = true;
- validUnsent.addElement(ia);
- // create and chain the exception
- sfex = new SMTPAddressFailedException(ia, cmd, retCode,
- lastServerResponse);
- if (mex == null)
- mex = sfex;
- else
- mex.setNextException(sfex);
- break;
-
- default:
- // handle remaining 4xy & 5xy codes
- if (retCode >= 400 && retCode <= 499) {
- // assume address is valid, although we don't really know
- validUnsent.addElement(ia);
- } else if (retCode >= 500 && retCode <= 599) {
- // assume address is invalid, although we don't really know
- invalid.addElement(ia);
- } else {
- // completely unexpected response, just give up
- if (logger.isLoggable(Level.FINE))
- logger.fine("got response code " + retCode +
- ", with response: " + lastServerResponse);
- String _lsr = lastServerResponse; // else rset will nuke it
- int _lrc = lastReturnCode;
- if (serverSocket != null) // hasn't already been closed
- issueCommand("RSET", -1);
- lastServerResponse = _lsr; // restore, for get
- lastReturnCode = _lrc;
- throw new SMTPAddressFailedException(ia, cmd, retCode,
- _lsr);
- }
- if (!sendPartial)
- sendFailed = true;
- // create and chain the exception
- sfex = new SMTPAddressFailedException(ia, cmd, retCode,
- lastServerResponse);
- if (mex == null)
- mex = sfex;
- else
- mex.setNextException(sfex);
- break;
- }
- }
-
- // if we're willing to send to a partial list, and we found no
- // valid addresses, that's complete failure
- if (sendPartial && valid.size() == 0)
- sendFailed = true;
-
- // copy the vectors into appropriate arrays
- if (sendFailed) {
- // copy invalid addrs
- invalidAddr = new Address[invalid.size()];
- invalid.copyInto(invalidAddr);
-
- // copy all valid addresses to validUnsent, since something failed
- validUnsentAddr = new Address[valid.size() + validUnsent.size()];
- int i = 0;
- for (int j = 0; j < valid.size(); j++)
- validUnsentAddr[i++] = (Address)valid.elementAt(j);
- for (int j = 0; j < validUnsent.size(); j++)
- validUnsentAddr[i++] = (Address)validUnsent.elementAt(j);
- } else if (reportSuccess || (sendPartial &&
- (invalid.size() > 0 || validUnsent.size() > 0))) {
- // we'll go on to send the message, but after sending we'll
- // throw an exception with this exception nested
- sendPartiallyFailed = true;
- exception = mex;
-
- // copy invalid addrs
- invalidAddr = new Address[invalid.size()];
- invalid.copyInto(invalidAddr);
-
- // copy valid unsent addresses to validUnsent
- validUnsentAddr = new Address[validUnsent.size()];
- validUnsent.copyInto(validUnsentAddr);
-
- // copy valid addresses to validSent
- validSentAddr = new Address[valid.size()];
- valid.copyInto(validSentAddr);
- } else { // all addresses pass
- validSentAddr = addresses;
- }
-
-
- // print out the debug info
- if (logger.isLoggable(Level.FINE)) {
- if (validSentAddr != null && validSentAddr.length > 0) {
- logger.fine("Verified Addresses");
- for (int l = 0; l < validSentAddr.length; l++) {
- logger.fine(" " + validSentAddr[l]);
- }
- }
- if (validUnsentAddr != null && validUnsentAddr.length > 0) {
- logger.fine("Valid Unsent Addresses");
- for (int j = 0; j < validUnsentAddr.length; j++) {
- logger.fine(" " + validUnsentAddr[j]);
- }
- }
- if (invalidAddr != null && invalidAddr.length > 0) {
- logger.fine("Invalid Addresses");
- for (int k = 0; k < invalidAddr.length; k++) {
- logger.fine(" " + invalidAddr[k]);
- }
- }
- }
-
- // throw the exception, fire TransportEvent.MESSAGE_NOT_DELIVERED event
- if (sendFailed) {
- logger.fine(
- "Sending failed because of invalid destination addresses");
- notifyTransportListeners(TransportEvent.MESSAGE_NOT_DELIVERED,
- validSentAddr, validUnsentAddr,
- invalidAddr, this.message);
-
- // reset the connection so more sends are allowed
- String lsr = lastServerResponse; // save, for get
- int lrc = lastReturnCode;
- try {
- if (serverSocket != null)
- issueCommand("RSET", -1);
- } catch (MessagingException ex) {
- // if can't reset, best to close the connection
- try {
- close();
- } catch (MessagingException ex2) {
- // thrown by close()--ignore, will close() later anyway
- logger.log(Level.FINE, "close failed", ex2);
- }
- } finally {
- lastServerResponse = lsr; // restore
- lastReturnCode = lrc;
- }
-
- throw new SendFailedException("Invalid Addresses", mex,
- validSentAddr,
- validUnsentAddr, invalidAddr);
- }
- }
-
- /**
- * Send the DATA command to the SMTP host and return
- * an OutputStream to which the data is to be written.
- *
- * @since JavaMail 1.4.1
- */
- protected OutputStream data() throws MessagingException {
- assert Thread.holdsLock(this);
- issueSendCommand("DATA", 354);
- dataStream = new SMTPOutputStream(serverOutput);
- return dataStream;
- }
-
- /**
- * Terminate the sent data.
- *
- * @since JavaMail 1.4.1
- */
- protected void finishData() throws IOException, MessagingException {
- assert Thread.holdsLock(this);
- dataStream.ensureAtBOL();
- issueSendCommand(".", 250);
- }
-
- /**
- * Issue the STARTTLS command and switch the socket to
- * TLS mode if it succeeds.
- *
- * @since JavaMail 1.4.1
- */
- protected void startTLS() throws MessagingException {
- issueCommand("STARTTLS", 220);
- // it worked, now switch the socket into TLS mode
- try {
- serverSocket = SocketFetcher.startTLS(serverSocket, host,
- session.getProperties(), "mail." + name);
- initStreams();
- } catch (IOException ioex) {
- closeConnection();
- throw new MessagingException("Could not convert socket to TLS",
- ioex);
- }
- }
-
- /////// primitives ///////
-
- /**
- * Connect to host on port and start the SMTP protocol.
- */
- private void openServer(String host, int port)
- throws MessagingException {
-
- if (logger.isLoggable(Level.FINE))
- logger.fine("trying to connect to host \"" + host +
- "\", port " + port + ", isSSL " + isSSL);
-
- try {
- Properties props = session.getProperties();
-
- serverSocket = SocketFetcher.getSocket(host, port,
- props, "mail." + name, isSSL);
-
- // socket factory may've chosen a different port,
- // update it for the debug messages that follow
- port = serverSocket.getPort();
- // save host name for startTLS
- this.host = host;
-
- initStreams();
-
- int r = -1;
- if ((r = readServerResponse()) != 220) {
- serverSocket.close();
- serverSocket = null;
- serverOutput = null;
- serverInput = null;
- lineInputStream = null;
- if (logger.isLoggable(Level.FINE))
- logger.fine("could not connect to host \"" +
- host + "\", port: " + port +
- ", response: " + r + "\n");
- throw new MessagingException(
- "Could not connect to SMTP host: " + host +
- ", port: " + port +
- ", response: " + r);
- } else {
- if (logger.isLoggable(Level.FINE))
- logger.fine("connected to host \"" +
- host + "\", port: " + port + "\n");
- }
- } catch (UnknownHostException uhex) {
- throw new MessagingException("Unknown SMTP host: " + host, uhex);
- } catch (SocketConnectException scex) {
- throw new MailConnectException(scex);
- } catch (IOException ioe) {
- throw new MessagingException("Could not connect to SMTP host: " +
- host + ", port: " + port, ioe);
- }
- }
-
- /**
- * Start the protocol to the server on serverSocket,
- * assumed to be provided and connected by the caller.
- */
- private void openServer() throws MessagingException {
- int port = -1;
- host = "UNKNOWN";
- try {
- port = serverSocket.getPort();
- host = serverSocket.getInetAddress().getHostName();
- if (logger.isLoggable(Level.FINE))
- logger.fine("starting protocol to host \"" +
- host + "\", port " + port);
-
- initStreams();
-
- int r = -1;
- if ((r = readServerResponse()) != 220) {
- serverSocket.close();
- serverSocket = null;
- serverOutput = null;
- serverInput = null;
- lineInputStream = null;
- if (logger.isLoggable(Level.FINE))
- logger.fine("got bad greeting from host \"" +
- host + "\", port: " + port +
- ", response: " + r + "\n");
- throw new MessagingException(
- "Got bad greeting from SMTP host: " + host +
- ", port: " + port +
- ", response: " + r);
- } else {
- if (logger.isLoggable(Level.FINE))
- logger.fine("protocol started to host \"" +
- host + "\", port: " + port + "\n");
- }
- } catch (IOException ioe) {
- throw new MessagingException(
- "Could not start protocol to SMTP host: " +
- host + ", port: " + port, ioe);
- }
- }
-
-
- private void initStreams() throws IOException {
- boolean quote = PropUtil.getBooleanSessionProperty(session,
- "mail.debug.quote", false);
-
- traceInput =
- new TraceInputStream(serverSocket.getInputStream(), traceLogger);
- traceInput.setQuote(quote);
-
- traceOutput =
- new TraceOutputStream(serverSocket.getOutputStream(), traceLogger);
- traceOutput.setQuote(quote);
-
- serverOutput =
- new BufferedOutputStream(traceOutput);
- serverInput =
- new BufferedInputStream(traceInput);
- lineInputStream = new LineInputStream(serverInput);
- }
-
- /**
- * Is protocol tracing enabled?
- */
- private 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);
- }
- }
-
- /**
- * Send the command to the server. If the expected response code
- * is not received, throw a MessagingException.
- *
- * @param cmd the command to send
- * @param expect the expected response code (-1 means don't care)
- *
- * @since JavaMail 1.4.1
- */
- public synchronized void issueCommand(String cmd, int expect)
- throws MessagingException {
- sendCommand(cmd);
-
- // if server responded with an unexpected return code,
- // throw the exception, notifying the client of the response
- int resp = readServerResponse();
- if (expect != -1 && resp != expect)
- throw new MessagingException(lastServerResponse);
- }
-
- /**
- * Issue a command that's part of sending a message.
- */
- private void issueSendCommand(String cmd, int expect)
- throws MessagingException {
- sendCommand(cmd);
-
- // if server responded with an unexpected return code,
- // throw the exception, notifying the client of the response
- int ret;
- if ((ret = readServerResponse()) != expect) {
- // assume message was not sent to anyone,
- // combine valid sent & unsent addresses
- int vsl = validSentAddr == null ? 0 : validSentAddr.length;
- int vul = validUnsentAddr == null ? 0 : validUnsentAddr.length;
- Address[] valid = new Address[vsl + vul];
- if (vsl > 0)
- System.arraycopy(validSentAddr, 0, valid, 0, vsl);
- if (vul > 0)
- System.arraycopy(validUnsentAddr, 0, valid, vsl, vul);
- validSentAddr = null;
- validUnsentAddr = valid;
- if (logger.isLoggable(Level.FINE))
- logger.fine("got response code " + ret +
- ", with response: " + lastServerResponse);
- String _lsr = lastServerResponse; // else rset will nuke it
- int _lrc = lastReturnCode;
- if (serverSocket != null) // hasn't already been closed
- issueCommand("RSET", -1);
- lastServerResponse = _lsr; // restore, for get
- lastReturnCode = _lrc;
- throw new SMTPSendFailedException(cmd, ret, lastServerResponse,
- exception, validSentAddr, validUnsentAddr, invalidAddr);
- }
- }
-
- /**
- * Send the command to the server and return the response code
- * from the server.
- *
- * @since JavaMail 1.4.1
- */
- public synchronized int simpleCommand(String cmd)
- throws MessagingException {
- sendCommand(cmd);
- return readServerResponse();
- }
-
- /**
- * Send the command to the server and return the response code
- * from the server.
- *
- * @since JavaMail 1.4.1
- */
- protected int simpleCommand(byte[] cmd) throws MessagingException {
- assert Thread.holdsLock(this);
- sendCommand(cmd);
- return readServerResponse();
- }
-
- /**
- * Sends command cmd to the server terminating
- * it with CRLF.
- *
- * @since JavaMail 1.4.1
- */
- protected void sendCommand(String cmd) throws MessagingException {
- sendCommand(ASCIIUtility.getBytes(cmd));
- }
-
- private void sendCommand(byte[] cmdBytes) throws MessagingException {
- assert Thread.holdsLock(this);
- //if (logger.isLoggable(Level.FINE))
- //logger.fine("SENT: " + new String(cmdBytes, 0));
-
- try {
- serverOutput.write(cmdBytes);
- serverOutput.write(CRLF);
- serverOutput.flush();
- } catch (IOException ex) {
- throw new MessagingException("Can't send command to SMTP host", ex);
- }
- }
-
- /**
- * Reads server reponse returning the returnCode
- * as the number. Returns -1 on failure. Sets
- * lastServerResponse and lastReturnCode.
- *
- * @return server response code
- *
- * @since JavaMail 1.4.1
- */
- protected int readServerResponse() throws MessagingException {
- assert Thread.holdsLock(this);
- String serverResponse = "";
- int returnCode = 0;
- StringBuffer buf = new StringBuffer(100);
-
- // read the server response line(s) and add them to the buffer
- // that stores the response
- try {
- String line = null;
-
- do {
- line = lineInputStream.readLine();
- if (line == null) {
- serverResponse = buf.toString();
- if (serverResponse.length() == 0)
- serverResponse = "[EOF]";
- lastServerResponse = serverResponse;
- lastReturnCode = -1;
- logger.log(Level.FINE, "EOF: {0}", serverResponse);
- return -1;
- }
- buf.append(line);
- buf.append("\n");
- } while (isNotLastLine(line));
-
- serverResponse = buf.toString();
- } catch (IOException ioex) {
- logger.log(Level.FINE, "exception reading response", ioex);
- //ioex.printStackTrace(out);
- lastServerResponse = "";
- lastReturnCode = 0;
- throw new MessagingException("Exception reading response", ioex);
- //returnCode = -1;
- }
-
- // print debug info
- //if (logger.isLoggable(Level.FINE))
- //logger.fine("RCVD: " + serverResponse);
-
- // parse out the return code
- if (serverResponse.length() >= 3) {
- try {
- returnCode = Integer.parseInt(serverResponse.substring(0, 3));
- } catch (NumberFormatException nfe) {
- try {
- close();
- } catch (MessagingException mex) {
- // thrown by close()--ignore, will close() later anyway
- logger.log(Level.FINE, "close failed", mex);
- }
- returnCode = -1;
- } catch (StringIndexOutOfBoundsException ex) {
- try {
- close();
- } catch (MessagingException mex) {
- // thrown by close()--ignore, will close() later anyway
- logger.log(Level.FINE, "close failed", mex);
- }
- returnCode = -1;
- }
- } else {
- returnCode = -1;
- }
- if (returnCode == -1)
- logger.log(Level.FINE, "bad server response: {0}", serverResponse);
-
- lastServerResponse = serverResponse;
- lastReturnCode = returnCode;
- return returnCode;
- }
-
- /**
- * Check if we're in the connected state. Don't bother checking
- * whether the server is still alive, that will be detected later.
- *
- * @exception IllegalStateException if not connected
- *
- * @since JavaMail 1.4.1
- */
- protected void checkConnected() {
- if (!super.isConnected())
- throw new IllegalStateException("Not connected");
- }
-
- // tests if the line is an intermediate line according to SMTP
- private boolean isNotLastLine(String line) {
- return line != null && line.length() >= 4 && line.charAt(3) == '-';
- }
-
- // wraps an address in "<>"'s if necessary
- private String normalizeAddress(String addr) {
- if ((!addr.startsWith("<")) && (!addr.endsWith(">")))
- return "<" + addr + ">";
- else
- return addr;
- }
-
- /**
- * Return true if the SMTP server supports the specified service
- * extension. Extensions are reported as results of the EHLO
- * command when connecting to the server. See
- * RFC 1869
- * and other RFCs that define specific extensions.
- *
- * @param ext the service extension name
- * @return true if the extension is supported
- *
- * @since JavaMail 1.3.2
- */
- public boolean supportsExtension(String ext) {
- return extMap != null &&
- extMap.get(ext.toUpperCase(Locale.ENGLISH)) != null;
- }
-
- /**
- * Return the parameter the server provided for the specified
- * service extension, or null if the extension isn't supported.
- *
- * @param ext the service extension name
- * @return the extension parameter
- *
- * @since JavaMail 1.3.2
- */
- public String getExtensionParameter(String ext) {
- return extMap == null ? null :
- (String)extMap.get(ext.toUpperCase(Locale.ENGLISH));
- }
-
- /**
- * Does the server we're connected to support the specified
- * authentication mechanism? Uses the extension information
- * returned by the server from the EHLO command.
- *
- * @param auth the authentication mechanism
- * @return true if the authentication mechanism is supported
- *
- * @since JavaMail 1.4.1
- */
- protected boolean supportsAuthentication(String auth) {
- assert Thread.holdsLock(this);
- if (extMap == null)
- return false;
- String a = (String)extMap.get("AUTH");
- if (a == null)
- return false;
- StringTokenizer st = new StringTokenizer(a);
- while (st.hasMoreTokens()) {
- String tok = st.nextToken();
- if (tok.equalsIgnoreCase(auth))
- return true;
- }
- // hack for buggy servers that advertise capability incorrectly
- if (auth.equalsIgnoreCase("LOGIN") && supportsExtension("AUTH=LOGIN")) {
- logger.fine("use AUTH=LOGIN hack");
- return true;
- }
- return false;
- }
-
- private static char[] hexchar = {
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
- };
-
- /**
- * Convert a string to RFC 1891 xtext format.
- *
- *
- * xtext = *( xchar / hexchar )
- *
- * xchar = any ASCII CHAR between "!" (33) and "~" (126) inclusive,
- * except for "+" and "=".
- *
- * ; "hexchar"s are intended to encode octets that cannot appear
- * ; as ASCII characters within an esmtp-value.
- *
- * hexchar = ASCII "+" immediately followed by two upper case
- * hexadecimal digits
- *
- *
- * @since JavaMail 1.4.1
- */
- protected static String xtext(String s) {
- StringBuffer sb = null;
- for (int i = 0; i < s.length(); i++) {
- char c = s.charAt(i);
- if (c >= 128) // not ASCII
- throw new IllegalArgumentException(
- "Non-ASCII character in SMTP submitter: " + s);
- if (c < '!' || c > '~' || c == '+' || c == '=') {
- if (sb == null) {
- sb = new StringBuffer(s.length() + 4);
- sb.append(s.substring(0, i));
- }
- sb.append('+');
- sb.append(hexchar[(((int)c)& 0xf0) >> 4]);
- sb.append(hexchar[((int)c)& 0x0f]);
- } else {
- if (sb != null)
- sb.append(c);
- }
- }
- return sb != null ? sb.toString() : s;
- }
-
- /*
- * Probe points for GlassFish monitoring.
- */
- private void sendMessageStart(String subject) { }
- private void sendMessageEnd() { }
-}
diff --git a/src/main/java/com/sun/mail/smtp/SaslAuthenticator.java b/src/main/java/com/sun/mail/smtp/SaslAuthenticator.java
deleted file mode 100644
index 33008315..00000000
--- a/src/main/java/com/sun/mail/smtp/SaslAuthenticator.java
+++ /dev/null
@@ -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.smtp;
-
-import javax.mail.MessagingException;
-
-/**
- * Interface to make it easier to call SMTPSaslAuthenticator.
- */
-
-public interface SaslAuthenticator {
- public boolean authenticate(String[] mechs, String realm, String authzid,
- String u, String p) throws MessagingException;
-
-}
diff --git a/src/main/java/com/sun/mail/smtp/package.html b/src/main/java/com/sun/mail/smtp/package.html
deleted file mode 100644
index bae38d57..00000000
--- a/src/main/java/com/sun/mail/smtp/package.html
+++ /dev/null
@@ -1,732 +0,0 @@
-
-
-
-
-
-
-
-
-An SMTP protocol provider for the JavaMail API
-that provides access to an SMTP server.
-Refer to RFC 821
-for more information.
-
-When sending a message, detailed information on each address that
-fails is available in an
-{@link com.sun.mail.smtp.SMTPAddressFailedException SMTPAddressFailedException}
-chained off the top level
-{@link javax.mail.SendFailedException SendFailedException}
-that is thrown.
-In addition, if the mail.smtp.reportsuccess property
-is set, an
-{@link com.sun.mail.smtp.SMTPAddressSucceededException
-SMTPAddressSucceededException}
-will be included in the list for each address that is successful.
-Note that this will cause a top level
-{@link javax.mail.SendFailedException SendFailedException}
-to be thrown even though the send was successful.
-
-The SMTP provider also supports ESMTP
-(RFC 1651).
-It can optionally use SMTP Authentication
-(RFC 2554)
-using the LOGIN, PLAIN, DIGEST-MD5, and NTLM mechanisms
-(RFC 2595
-and RFC 2831).
-
-To use SMTP authentication you'll need to set the mail.smtp.auth
-property (see below) or provide the SMTP Transport
-with a username and password when connecting to the SMTP server. You
-can do this using one of the following approaches:
-
-
-
-Provide an Authenticator object when creating your mail Session
-and provide the username and password information during the
-Authenticator callback.
-
-Note that the mail.smtp.user property can be set to provide a
-default username for the callback, but the password will still need to be
-supplied explicitly.
-
-This approach allows you to use the static Transport send method
-to send messages.
-
-
-
-Call the Transport connect method explicitly with username and
-password arguments.
-
-This approach requires you to explicitly manage a Transport object
-and use the Transport sendMessage method to send the message.
-The transport.java demo program demonstrates how to manage a Transport
-object. The following is roughly equivalent to the static
-Transport send method, but supplies the needed username and
-password:
-
-When using DIGEST-MD5 authentication,
-you'll also need to supply an appropriate realm;
-your mail server administrator can supply this information.
-You can set this using the mail.smtp.sasl.realm property,
-or the setSASLRealm method on SMTPTransport.
-
-The SMTP protocol provider can use SASL
-(RFC 2222)
-authentication mechanisms on systems that support the
-javax.security.sasl 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
-
-Java SASL API Programming and Deployment Guide for details.
-Note that the current implementation doesn't support SASL mechanisms
-that provide their own integrity or confidentiality layer.
-
-SMTP can also optionally request Delivery Status Notifications
-(RFC 1891).
-The delivery status will typically be reported using
-a "multipart/report"
-(RFC 1892)
-message type with a "message/delivery-status"
-(RFC 1894)
-part.
-You can use the classes in the {@link com.sun.mail.dsn} package to
-handle these MIME types.
-Note that you'll need to include dsn.jar in your CLASSPATH
-as this support is not included in mail.jar.
-
-See below for the properties to enable these features.
-
-Note also that THERE IS NOT SUFFICIENT DOCUMENTATION HERE TO USE THESE
-FEATURES!!! You will need to read the appropriate RFCs mentioned above
-to understand what these features do and how to use them. Don't just
-start setting properties and then complain to us when it doesn't work
-like you expect it to work. READ THE RFCs FIRST!!!
-
-The SMTP protocol provider supports the following properties,
-which may be set in the JavaMail Session object.
-The properties are always set as strings; the Type column describes
-how the string is interpreted. For example, use
-
- props.put("mail.smtp.port", "888");
-
-to set the mail.smtp.port property, which is of type int.
-
-Note that if you're using the "smtps" protocol to access SMTP over SSL,
-all the properties would be named "mail.smtps.*".
-
-
-
-
Name
-
Type
-
Description
-
-
-
-
mail.smtp.user
-
String
-
Default user name for SMTP.
-
-
-
-
mail.smtp.host
-
String
-
The SMTP server to connect to.
-
-
-
-
mail.smtp.port
-
int
-
The SMTP server port to connect to, if the connect() method doesn't
-explicitly specify one. Defaults to 25.
-
-
-
-
mail.smtp.connectiontimeout
-
int
-
Socket connection timeout value in milliseconds.
-Default is infinite timeout.
-
-
-
-
mail.smtp.timeout
-
int
-
Socket I/O timeout value in milliseconds. Default is infinite timeout.
-
-
-
-
mail.smtp.from
-
String
-
-Email address to use for SMTP MAIL command. This sets the envelope
-return address. Defaults to msg.getFrom() or
-InternetAddress.getLocalAddress(). NOTE: mail.smtp.user was previously
-used for this.
-
-
-
-
-
mail.smtp.localhost
-
String
-
-Local host name used in the SMTP HELO or EHLO command.
-Defaults to InetAddress.getLocalHost().getHostName().
-Should not normally need to
-be set if your JDK and your name service are configured properly.
-
-
-
-
-
mail.smtp.localaddress
-
String
-
-Local address (host name) to bind to when creating the SMTP 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.
-
-
-
-
-
mail.smtp.localport
-
int
-
-Local port number to bind to when creating the SMTP socket.
-Defaults to the port number picked by the Socket class.
-
-
-
-
-
mail.smtp.ehlo
-
boolean
-
-If false, do not attempt to sign on with the EHLO command. Defaults to
-true. Normally failure of the EHLO command will fallback to the HELO
-command; this property exists only for servers that don't fail EHLO
-properly or don't implement EHLO properly.
-
-
-
-
-
mail.smtp.auth
-
boolean
-
If true, attempt to authenticate the user using the AUTH command.
-Defaults to false.
-
-
-
-
mail.smtp.auth.mechanisms
-
String
-
-If set, lists the authentication mechanisms to consider, and the order
-in which to consider them. Only mechanisms supported by the server and
-supported by the current implementation will be used.
-The default is "LOGIN PLAIN DIGEST-MD5 NTLM", which includes all
-the authentication mechanisms supported by the current implementation.
-
-
-
-
-
mail.smtp.auth.login.disable
-
boolean
-
If true, prevents use of the AUTH LOGIN command.
-Default is false.
-
-
-
-
mail.smtp.auth.plain.disable
-
boolean
-
If true, prevents use of the AUTH PLAIN command.
-Default is false.
-
-
-
-
mail.smtp.auth.digest-md5.disable
-
boolean
-
If true, prevents use of the AUTH DIGEST-MD5 command.
-Default is false.
-
-
-
-
mail.smtp.auth.ntlm.disable
-
boolean
-
If true, prevents use of the AUTH NTLM command.
-Default is false.
The submitter to use in the AUTH tag in the MAIL FROM command.
-Typically used by a mail relay to pass along information about the
-original submitter of the message.
-See also the {@link com.sun.mail.smtp.SMTPMessage#setSubmitter setSubmitter}
-method of {@link com.sun.mail.smtp.SMTPMessage SMTPMessage}.
-Mail clients typically do not use this.
-
-
-
-
-
mail.smtp.dsn.notify
-
String
-
The NOTIFY option to the RCPT command. Either NEVER, or some
-combination of SUCCESS, FAILURE, and DELAY (separated by commas).
-
-
-
-
mail.smtp.dsn.ret
-
String
-
The RET option to the MAIL command. Either FULL or HDRS.
-
-
-
-
mail.smtp.allow8bitmime
-
boolean
-
-If set to true, and the server supports the 8BITMIME extension, text
-parts of messages that use the "quoted-printable" or "base64" encodings
-are converted to use "8bit" encoding if they follow the RFC2045 rules
-for 8bit text.
-
-
-
-
-
mail.smtp.sendpartial
-
boolean
-
-If set to true, and a message has some valid and some invalid
-addresses, send the message anyway, reporting the partial failure with
-a SendFailedException. If set to false (the default), the message is
-not sent to any of the recipients if there is an invalid recipient
-address.
-
-
-
-
-
mail.smtp.sasl.enable
-
boolean
-
-If set to true, attempt to use the javax.security.sasl package to
-choose an authentication mechanism for login.
-Defaults to false.
-
-
-
-
-
mail.smtp.sasl.mechanisms
-
String
-
-A space or comma separated list of SASL mechanism names to try
-to use.
-
-
-
-
-
mail.smtp.sasl.authorizationid
-
String
-
-The authorization ID to use in the SASL authentication.
-If not set, the authentication ID (user name) is used.
-
-
-
-
-
mail.smtp.sasl.realm
-
String
-
The realm to use with DIGEST-MD5 authentication.
-
-
-
-
mail.smtp.quitwait
-
boolean
-
-If set to false, the QUIT command is sent
-and the connection is immediately closed.
-If set to true (the default), causes the transport to wait
-for the response to the QUIT command.
-
-
-
-
-
mail.smtp.reportsuccess
-
boolean
-
-If set to true, causes the transport to include an
-{@link com.sun.mail.smtp.SMTPAddressSucceededException
-SMTPAddressSucceededException}
-for each address that is successful.
-Note also that this will cause a
-{@link javax.mail.SendFailedException SendFailedException}
-to be thrown from the
-{@link com.sun.mail.smtp.SMTPTransport#sendMessage sendMessage}
-method of
-{@link com.sun.mail.smtp.SMTPTransport SMTPTransport}
-even if all addresses were correct and the message was sent
-successfully.
-
-
-
-
-
mail.smtp.socketFactory
-
SocketFactory
-
-If set to a class that implements the
-javax.net.SocketFactory interface, this class
-will be used to create SMTP sockets. Note that this is an
-instance of a class, not a name, and must be set using the
-put method, not the setProperty method.
-
-
-
-
-
mail.smtp.socketFactory.class
-
String
-
-If set, specifies the name of a class that implements the
-javax.net.SocketFactory interface. This class
-will be used to create SMTP sockets.
-
-
-
-
-
mail.smtp.socketFactory.fallback
-
boolean
-
-If set to true, failure to create a socket using the specified
-socket factory class will cause the socket to be created using
-the java.net.Socket class.
-Defaults to true.
-
-
-
-
-
mail.smtp.socketFactory.port
-
int
-
-Specifies the port to connect to when using the specified socket
-factory.
-If not set, the default port will be used.
-
-
-
-
-
mail.smtp.ssl.enable
-
boolean
-
-If set to true, use SSL to connect and use the SSL port by default.
-Defaults to false for the "smtp" protocol and true for the "smtps" protocol.
-
-
-
-
-
mail.smtp.ssl.checkserveridentity
-
boolean
-
-If set to true, check the server identity as specified by
-RFC 2595.
-These additional checks based on the content of the server's certificate
-are intended to prevent man-in-the-middle attacks.
-Defaults to false.
-
-
-
-
-
mail.smtp.ssl.trust
-
String
-
-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.
-
-
-
-
-
mail.smtp.ssl.socketFactory
-
SSLSocketFactory
-
-If set to a class that extends the
-javax.net.ssl.SSLSocketFactory class, this class
-will be used to create SMTP SSL sockets. Note that this is an
-instance of a class, not a name, and must be set using the
-put method, not the setProperty method.
-
-
-
-
-
mail.smtp.ssl.socketFactory.class
-
String
-
-If set, specifies the name of a class that extends the
-javax.net.ssl.SSLSocketFactory class. This class
-will be used to create SMTP SSL sockets.
-
-
-
-
-
mail.smtp.ssl.socketFactory.port
-
int
-
-Specifies the port to connect to when using the specified socket
-factory.
-If not set, the default port will be used.
-
-
-
-
-
mail.smtp.ssl.protocols
-
string
-
-Specifies the SSL protocols that will be enabled for SSL connections.
-The property value is a whitespace separated list of tokens acceptable
-to the javax.net.ssl.SSLSocket.setEnabledProtocols method.
-
-
-
-
-
mail.smtp.ssl.ciphersuites
-
string
-
-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 javax.net.ssl.SSLSocket.setEnabledCipherSuites method.
-
-
-
-
-
mail.smtp.starttls.enable
-
boolean
-
-If true, enables the use of the STARTTLS 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.
-Defaults to false.
-
-
-
-
-
mail.smtp.starttls.required
-
boolean
-
-If true, requires the use of the STARTTLS command.
-If the server doesn't support the STARTTLS command, or the command
-fails, the connect method will fail.
-Defaults to false.
-
-
-
-
-
mail.smtp.socks.host
-
string
-
-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.)
-
-
-
-
-
mail.smtp.socks.port
-
string
-
-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.
-
-
-
-
-
mail.smtp.mailextension
-
String
-
-Extension string to append to the MAIL command.
-The extension string can be used to specify standard SMTP
-service extensions as well as vendor-specific extensions.
-Typically the application should use the
-{@link com.sun.mail.smtp.SMTPTransport SMTPTransport}
-method {@link com.sun.mail.smtp.SMTPTransport#supportsExtension
-supportsExtension}
-to verify that the server supports the desired service extension.
-See RFC 1869
-and other RFCs that define specific extensions.
-
-
-
-
-
mail.smtp.userset
-
boolean
-
-If set to true, use the RSET command instead of the NOOP command
-in the {@link javax.mail.Transport#isConnected isConnected} method.
-In some cases sendmail will respond slowly after many NOOP commands;
-use of RSET avoids this sendmail issue.
-Defaults to false.
-
-
-
-
-
mail.smtp.noop.strict
-
boolean
-
-If set to true (the default), insist on a 250 response code from the NOOP
-command to indicate success. The NOOP command is used by the
-{@link javax.mail.Transport#isConnected isConnected} method to determine
-if the connection is still alive.
-Some older servers return the wrong response code on success, some
-servers don't implement the NOOP command at all and so always return
-a failure code. Set this property to false to handle servers
-that are broken in this way.
-Normally, when a server times out a connection, it will send a 421
-response code, which the client will see as the response to the next
-command it issues.
-Some servers send the wrong failure response code when timing out a
-connection.
-Do not set this property to false when dealing with servers that are
-broken in this way.
-
-
-
-
-
-In general, applications should not need to use the classes in this
-package directly. Instead, they should use the APIs defined by
-javax.mail package (and subpackages). Applications should
-never construct instances of SMTPTransport directly.
-Instead, they should use the
-Session method getTransport to acquire an
-appropriate Transport object.
-
-In addition to printing debugging output as controlled by the
-{@link javax.mail.Session Session} configuration,
-the com.sun.mail.smtp provider logs the same information using
-{@link java.util.logging.Logger} as described in the following table:
-
-
-
-
Logger Name
-
Logging Level
-
Purpose
-
-
-
-
com.sun.mail.smtp
-
CONFIG
-
Configuration of the SMTPTransport
-
-
-
-
com.sun.mail.smtp
-
FINE
-
General debugging output
-
-
-
-
com.sun.mail.smtp.protocol
-
FINEST
-
Complete protocol trace
-
-
-
-
-WARNING: The APIs unique to this package should be
-considered EXPERIMENTAL. They may be changed in the
-future in ways that are incompatible with applications using the
-current APIs.
-
-
-
diff --git a/src/main/java/com/sun/mail/util/ASCIIUtility.java b/src/main/java/com/sun/mail/util/ASCIIUtility.java
deleted file mode 100644
index 2b3446a5..00000000
--- a/src/main/java/com/sun/mail/util/ASCIIUtility.java
+++ /dev/null
@@ -1,275 +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.util;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.io.IOException;
-
-public class ASCIIUtility {
-
- // Private constructor so that this class is not instantiated
- private ASCIIUtility() { }
-
- /**
- * Convert the bytes within the specified range of the given byte
- * array into a signed integer in the given radix . The range extends
- * from start till, but not including end.
- *
- * Based on java.lang.Integer.parseInt()
- */
- public static int parseInt(byte[] b, int start, int end, int radix)
- throws NumberFormatException {
- if (b == null)
- throw new NumberFormatException("null");
-
- int result = 0;
- boolean negative = false;
- int i = start;
- int limit;
- int multmin;
- int digit;
-
- if (end > start) {
- if (b[i] == '-') {
- negative = true;
- limit = Integer.MIN_VALUE;
- i++;
- } else {
- limit = -Integer.MAX_VALUE;
- }
- multmin = limit / radix;
- if (i < end) {
- digit = Character.digit((char)b[i++], radix);
- if (digit < 0) {
- throw new NumberFormatException(
- "illegal number: " + toString(b, start, end)
- );
- } else {
- result = -digit;
- }
- }
- while (i < end) {
- // Accumulating negatively avoids surprises near MAX_VALUE
- digit = Character.digit((char)b[i++], radix);
- if (digit < 0) {
- throw new NumberFormatException("illegal number");
- }
- if (result < multmin) {
- throw new NumberFormatException("illegal number");
- }
- result *= radix;
- if (result < limit + digit) {
- throw new NumberFormatException("illegal number");
- }
- result -= digit;
- }
- } else {
- throw new NumberFormatException("illegal number");
- }
- if (negative) {
- if (i > start + 1) {
- return result;
- } else { /* Only got "-" */
- throw new NumberFormatException("illegal number");
- }
- } else {
- return -result;
- }
- }
-
- /**
- * Convert the bytes within the specified range of the given byte
- * array into a signed integer . The range extends from
- * start till, but not including end.
- */
- public static int parseInt(byte[] b, int start, int end)
- throws NumberFormatException {
- return parseInt(b, start, end, 10);
- }
-
- /**
- * Convert the bytes within the specified range of the given byte
- * array into a signed long in the given radix . The range extends
- * from start till, but not including end.
- *
- * Based on java.lang.Long.parseLong()
- */
- public static long parseLong(byte[] b, int start, int end, int radix)
- throws NumberFormatException {
- if (b == null)
- throw new NumberFormatException("null");
-
- long result = 0;
- boolean negative = false;
- int i = start;
- long limit;
- long multmin;
- int digit;
-
- if (end > start) {
- if (b[i] == '-') {
- negative = true;
- limit = Long.MIN_VALUE;
- i++;
- } else {
- limit = -Long.MAX_VALUE;
- }
- multmin = limit / radix;
- if (i < end) {
- digit = Character.digit((char)b[i++], radix);
- if (digit < 0) {
- throw new NumberFormatException(
- "illegal number: " + toString(b, start, end)
- );
- } else {
- result = -digit;
- }
- }
- while (i < end) {
- // Accumulating negatively avoids surprises near MAX_VALUE
- digit = Character.digit((char)b[i++], radix);
- if (digit < 0) {
- throw new NumberFormatException("illegal number");
- }
- if (result < multmin) {
- throw new NumberFormatException("illegal number");
- }
- result *= radix;
- if (result < limit + digit) {
- throw new NumberFormatException("illegal number");
- }
- result -= digit;
- }
- } else {
- throw new NumberFormatException("illegal number");
- }
- if (negative) {
- if (i > start + 1) {
- return result;
- } else { /* Only got "-" */
- throw new NumberFormatException("illegal number");
- }
- } else {
- return -result;
- }
- }
-
- /**
- * Convert the bytes within the specified range of the given byte
- * array into a signed long . The range extends from
- * start till, but not including end.
- */
- public static long parseLong(byte[] b, int start, int end)
- throws NumberFormatException {
- return parseLong(b, start, end, 10);
- }
-
- /**
- * Convert the bytes within the specified range of the given byte
- * array into a String. The range extends from start
- * till, but not including end.
- */
- public static String toString(byte[] b, int start, int end) {
- int size = end - start;
- char[] theChars = new char[size];
-
- for (int i = 0, j = start; i < size; )
- theChars[i++] = (char)(b[j++]&0xff);
-
- return new String(theChars);
- }
-
- /**
- * Convert the bytes into a String.
- *
- * @since JavaMail 1.4.4
- */
- public static String toString(byte[] b) {
- return toString(b, 0, b.length);
- }
-
- public static String toString(ByteArrayInputStream is) {
- int size = is.available();
- char[] theChars = new char[size];
- byte[] bytes = new byte[size];
-
- is.read(bytes, 0, size);
- for (int i = 0; i < size;)
- theChars[i] = (char)(bytes[i++]&0xff);
-
- return new String(theChars);
- }
-
-
- public static byte[] getBytes(String s) {
- char [] chars= s.toCharArray();
- int size = chars.length;
- byte[] bytes = new byte[size];
-
- for (int i = 0; i < size;)
- bytes[i] = (byte) chars[i++];
- return bytes;
- }
-
- public static byte[] getBytes(InputStream is) throws IOException {
-
- int len;
- int size = 1024;
- byte [] buf;
-
-
- if (is instanceof ByteArrayInputStream) {
- size = is.available();
- buf = new byte[size];
- len = is.read(buf, 0, size);
- }
- else {
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- buf = new byte[size];
- while ((len = is.read(buf, 0, size)) != -1)
- bos.write(buf, 0, len);
- buf = bos.toByteArray();
- }
- return buf;
- }
-}
diff --git a/src/main/java/com/sun/mail/util/BASE64DecoderStream.java b/src/main/java/com/sun/mail/util/BASE64DecoderStream.java
deleted file mode 100644
index 526e04b5..00000000
--- a/src/main/java/com/sun/mail/util/BASE64DecoderStream.java
+++ /dev/null
@@ -1,470 +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.util;
-
-import java.io.*;
-
-/**
- * This class implements a BASE64 Decoder. It is implemented as
- * a FilterInputStream, so one can just wrap this class around
- * any input stream and read bytes from this filter. The decoding
- * is done as the bytes are read out.
- *
- * @author John Mani
- * @author Bill Shannon
- */
-
-public class BASE64DecoderStream extends FilterInputStream {
- // buffer of decoded bytes for single byte reads
- private byte[] buffer = new byte[3];
- private int bufsize = 0; // size of the cache
- private int index = 0; // index into the cache
-
- // buffer for almost 8K of typical 76 chars + CRLF lines,
- // used by getByte method. this buffer contains encoded bytes.
- private byte[] input_buffer = new byte[78*105];
- private int input_pos = 0;
- private int input_len = 0;;
-
- private boolean ignoreErrors = false;
-
- /**
- * Create a BASE64 decoder that decodes the specified input stream.
- * The System property mail.mime.base64.ignoreerrors
- * controls whether errors in the encoded data cause an exception
- * or are ignored. The default is false (errors cause exception).
- *
- * @param in the input stream
- */
- public BASE64DecoderStream(InputStream in) {
- super(in);
- // default to false
- ignoreErrors = PropUtil.getBooleanSystemProperty(
- "mail.mime.base64.ignoreerrors", false);
- }
-
- /**
- * Create a BASE64 decoder that decodes the specified input stream.
- *
- * @param in the input stream
- * @param ignoreErrors ignore errors in encoded data?
- */
- public BASE64DecoderStream(InputStream in, boolean ignoreErrors) {
- super(in);
- this.ignoreErrors = ignoreErrors;
- }
-
- /**
- * Read the next decoded byte from this input stream. The byte
- * is returned as an int in the range 0
- * to 255. If no byte is available because the end of
- * the stream has been reached, the value -1 is returned.
- * This method blocks until input data is available, the end of the
- * stream is detected, or an exception is thrown.
- *
- * @return next byte of data, or -1 if the end of the
- * stream is reached.
- * @exception IOException if an I/O error occurs.
- * @see java.io.FilterInputStream#in
- */
- public int read() throws IOException {
- if (index >= bufsize) {
- bufsize = decode(buffer, 0, buffer.length);
- if (bufsize <= 0) // buffer is empty
- return -1;
- index = 0; // reset index into buffer
- }
- return buffer[index++] & 0xff; // Zero off the MSB
- }
-
- /**
- * Reads up to len decoded bytes of data from this input stream
- * into an array of bytes. This method blocks until some input is
- * available.
- *
- *
- * @param buf the buffer into which the data is read.
- * @param off the start offset of the data.
- * @param len the maximum number of bytes read.
- * @return the total number of bytes read into the buffer, or
- * -1 if there is no more data because the end of
- * the stream has been reached.
- * @exception IOException if an I/O error occurs.
- */
- public int read(byte[] buf, int off, int len) throws IOException {
- // empty out single byte read buffer
- int off0 = off;
- while (index < bufsize && len > 0) {
- buf[off++] = buffer[index++];
- len--;
- }
- if (index >= bufsize)
- bufsize = index = 0;
-
- int bsize = (len / 3) * 3; // round down to multiple of 3 bytes
- if (bsize > 0) {
- int size = decode(buf, off, bsize);
- off += size;
- len -= size;
-
- if (size != bsize) { // hit EOF?
- if (off == off0) // haven't returned any data
- return -1;
- else // returned some data before hitting EOF
- return off - off0;
- }
- }
-
- // finish up with a partial read if necessary
- for (; len > 0; len--) {
- int c = read();
- if (c == -1) // EOF
- break;
- buf[off++] = (byte)c;
- }
-
- if (off == off0) // haven't returned any data
- return -1;
- else // returned some data before hitting EOF
- return off - off0;
- }
-
- /**
- * Skips over and discards n bytes of data from this stream.
- */
- public long skip(long n) throws IOException {
- long skipped = 0;
- while (n-- > 0 && read() >= 0)
- skipped++;
- return skipped;
- }
-
- /**
- * Tests if this input stream supports marks. Currently this class
- * does not support marks
- */
- public boolean markSupported() {
- return false; // Maybe later ..
- }
-
- /**
- * Returns the number of bytes that can be read from this input
- * stream without blocking. However, this figure is only
- * a close approximation in case the original encoded stream
- * contains embedded CRLFs; since the CRLFs are discarded, not decoded
- */
- public int available() throws IOException {
- // This is only an estimate, since in.available()
- // might include CRLFs too ..
- return ((in.available() * 3)/4 + (bufsize-index));
- }
-
- /**
- * This character array provides the character to value map
- * based on RFC1521.
- */
- 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
- };
-
- private final static 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;
- }
-
- /**
- * The decoder algorithm. Most of the complexity here is dealing
- * with error cases. Returns the number of bytes decoded, which
- * may be zero. Decoding is done by filling an int with 4 6-bit
- * values by shifting them in from the bottom and then extracting
- * 3 8-bit bytes from the int by shifting them out from the bottom.
- *
- * @param outbuf the buffer into which to put the decoded bytes
- * @param pos position in the buffer to start filling
- * @param len the number of bytes to fill
- * @return the number of bytes filled, always a multiple
- * of three, and may be zero
- * @exception IOException if the data is incorrectly formatted
- */
- private int decode(byte[] outbuf, int pos, int len) throws IOException {
- int pos0 = pos;
- while (len >= 3) {
- /*
- * We need 4 valid base64 characters before we start decoding.
- * We skip anything that's not a valid base64 character (usually
- * just CRLF).
- */
- int got = 0;
- int val = 0;
- while (got < 4) {
- int i = getByte();
- if (i == -1 || i == -2) {
- boolean atEOF;
- if (i == -1) {
- if (got == 0)
- return pos - pos0;
- if (!ignoreErrors)
- throw new DecodingException(
- "BASE64Decoder: Error in encoded stream: " +
- "needed 4 valid base64 characters " +
- "but only got " + got + " before EOF" +
- recentChars());
- atEOF = true; // don't read any more
- } else { // i == -2
- // found a padding character, we're at EOF
- // XXX - should do something to make EOF "sticky"
- if (got < 2 && !ignoreErrors)
- throw new DecodingException(
- "BASE64Decoder: Error in encoded stream: " +
- "needed at least 2 valid base64 characters," +
- " but only got " + got +
- " before padding character (=)" +
- recentChars());
-
- // didn't get any characters before padding character?
- if (got == 0)
- return pos - pos0;
- atEOF = false; // need to keep reading
- }
-
- // pad partial result with zeroes
-
- // how many bytes will we produce on output?
- // (got always < 4, so size always < 3)
- int size = got - 1;
- if (size == 0)
- size = 1;
-
- // handle the one padding character we've seen
- got++;
- val <<= 6;
-
- while (got < 4) {
- if (!atEOF) {
- // consume the rest of the padding characters,
- // filling with zeroes
- i = getByte();
- if (i == -1) {
- if (!ignoreErrors)
- throw new DecodingException(
- "BASE64Decoder: Error in encoded " +
- "stream: hit EOF while looking for " +
- "padding characters (=)" +
- recentChars());
- } else if (i != -2) {
- if (!ignoreErrors)
- throw new DecodingException(
- "BASE64Decoder: Error in encoded " +
- "stream: found valid base64 " +
- "character after a padding character " +
- "(=)" + recentChars());
- }
- }
- val <<= 6;
- got++;
- }
-
- // now pull out however many valid bytes we got
- val >>= 8; // always skip first one
- if (size == 2)
- outbuf[pos + 1] = (byte)(val & 0xff);
- val >>= 8;
- outbuf[pos] = (byte)(val & 0xff);
- // len -= size; // not needed, return below
- pos += size;
- return pos - pos0;
- } else {
- // got a valid byte
- val <<= 6;
- got++;
- val |= i;
- }
- }
-
- // read 4 valid characters, now extract 3 bytes
- outbuf[pos + 2] = (byte)(val & 0xff);
- val >>= 8;
- outbuf[pos + 1] = (byte)(val & 0xff);
- val >>= 8;
- outbuf[pos] = (byte)(val & 0xff);
- len -= 3;
- pos += 3;
- }
- return pos - pos0;
- }
-
- /**
- * Read the next valid byte from the input stream.
- * Buffer lots of data from underlying stream in input_buffer,
- * for efficiency.
- *
- * @return the next byte, -1 on EOF, or -2 if next byte is '='
- * (padding at end of encoded data)
- */
- private int getByte() throws IOException {
- int c;
- do {
- if (input_pos >= input_len) {
- try {
- input_len = in.read(input_buffer);
- } catch (EOFException ex) {
- return -1;
- }
- if (input_len <= 0)
- return -1;
- input_pos = 0;
- }
- // get the next byte in the buffer
- c = input_buffer[input_pos++] & 0xff;
- // is it a padding byte?
- if (c == '=')
- return -2;
- // no, convert it
- c = pem_convert_array[c];
- // loop until we get a legitimate byte
- } while (c == -1);
- return c;
- }
-
- /**
- * Return the most recent characters, for use in an error message.
- */
- private String recentChars() {
- // reach into the input buffer and extract up to 10
- // recent characters, to help in debugging.
- String errstr = "";
- int nc = input_pos > 10 ? 10 : input_pos;
- if (nc > 0) {
- errstr += ", the " + nc +
- " most recent characters were: \"";
- for (int k = input_pos - nc; k < input_pos; k++) {
- char c = (char)(input_buffer[k] & 0xff);
- switch (c) {
- case '\r': errstr += "\\r"; break;
- case '\n': errstr += "\\n"; break;
- case '\t': errstr += "\\t"; break;
- default:
- if (c >= ' ' && c < 0177)
- errstr += c;
- else
- errstr += ("\\" + (int)c);
- }
- }
- errstr += "\"";
- }
- return errstr;
- }
-
- /**
- * Base64 decode a byte array. No line breaks are allowed.
- * This method is suitable for short strings, such as those
- * in the IMAP AUTHENTICATE protocol, but not to decode the
- * entire content of a MIME part.
- *
- * NOTE: inbuf may only contain valid base64 characters.
- * Whitespace is not ignored.
- */
- public static byte[] decode(byte[] inbuf) {
- int size = (inbuf.length / 4) * 3;
- if (size == 0)
- return inbuf;
-
- if (inbuf[inbuf.length - 1] == '=') {
- size--;
- if (inbuf[inbuf.length - 2] == '=')
- size--;
- }
- byte[] outbuf = new byte[size];
-
- int inpos = 0, outpos = 0;
- size = inbuf.length;
- while (size > 0) {
- int val;
- int osize = 3;
- val = pem_convert_array[inbuf[inpos++] & 0xff];
- val <<= 6;
- val |= pem_convert_array[inbuf[inpos++] & 0xff];
- val <<= 6;
- if (inbuf[inpos] != '=') // End of this BASE64 encoding
- val |= pem_convert_array[inbuf[inpos++] & 0xff];
- else
- osize--;
- val <<= 6;
- if (inbuf[inpos] != '=') // End of this BASE64 encoding
- val |= pem_convert_array[inbuf[inpos++] & 0xff];
- else
- osize--;
- if (osize > 2)
- outbuf[outpos + 2] = (byte)(val & 0xff);
- val >>= 8;
- if (osize > 1)
- outbuf[outpos + 1] = (byte)(val & 0xff);
- val >>= 8;
- outbuf[outpos] = (byte)(val & 0xff);
- outpos += osize;
- size -= 4;
- }
- return outbuf;
- }
-
- /*** begin TEST program ***
- public static void main(String argv[]) throws Exception {
- FileInputStream infile = new FileInputStream(argv[0]);
- BASE64DecoderStream decoder = new BASE64DecoderStream(infile);
- int c;
-
- while ((c = decoder.read()) != -1)
- System.out.print((char)c);
- System.out.flush();
- }
- *** end TEST program ***/
-}
diff --git a/src/main/java/com/sun/mail/util/BASE64EncoderStream.java b/src/main/java/com/sun/mail/util/BASE64EncoderStream.java
deleted file mode 100644
index aafb4437..00000000
--- a/src/main/java/com/sun/mail/util/BASE64EncoderStream.java
+++ /dev/null
@@ -1,322 +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.util;
-
-import java.io.*;
-
-/**
- * This class implements a BASE64 encoder. It is implemented as
- * a FilterOutputStream, so one can just wrap this class around
- * any output stream and write bytes into this filter. The encoding
- * is done as the bytes are written out.
- *
- * @author John Mani
- * @author Bill Shannon
- */
-
-public class BASE64EncoderStream extends FilterOutputStream {
- private byte[] buffer; // cache of bytes that are yet to be encoded
- private int bufsize = 0; // size of the cache
- private byte[] outbuf; // line size output buffer
- private int count = 0; // number of bytes that have been output
- private int bytesPerLine; // number of bytes per line
- private int lineLimit; // number of input bytes to output bytesPerLine
- private boolean noCRLF = false;
-
- private static byte[] newline = new byte[] { '\r', '\n' };
-
- /**
- * Create a BASE64 encoder that encodes the specified output stream.
- *
- * @param out the output stream
- * @param bytesPerLine number of bytes per line. The encoder inserts
- * a CRLF sequence after the specified number of bytes,
- * unless bytesPerLine is Integer.MAX_VALUE, in which
- * case no CRLF is inserted. bytesPerLine is rounded
- * down to a multiple of 4.
- */
- public BASE64EncoderStream(OutputStream out, int bytesPerLine) {
- super(out);
- buffer = new byte[3];
- if (bytesPerLine == Integer.MAX_VALUE || bytesPerLine < 4) {
- noCRLF = true;
- bytesPerLine = 76;
- }
- bytesPerLine = (bytesPerLine / 4) * 4; // Rounded down to 4n
- this.bytesPerLine = bytesPerLine; // save it
- lineLimit = bytesPerLine / 4 * 3;
-
- if (noCRLF) {
- outbuf = new byte[bytesPerLine];
- } else {
- outbuf = new byte[bytesPerLine + 2];
- outbuf[bytesPerLine] = (byte)'\r';
- outbuf[bytesPerLine + 1] = (byte)'\n';
- }
- }
-
- /**
- * Create a BASE64 encoder that encodes the specified input stream.
- * Inserts the CRLF sequence after outputting 76 bytes.
- *
- * @param out the output stream
- */
- public BASE64EncoderStream(OutputStream out) {
- this(out, 76);
- }
-
- /**
- * Encodes len bytes from the specified
- * byte array starting at offset off to
- * this output stream.
- *
- * @param b the data.
- * @param off the start offset in the data.
- * @param len the number of bytes to write.
- * @exception IOException if an I/O error occurs.
- */
- public synchronized void write(byte[] b, int off, int len)
- throws IOException {
- int end = off + len;
-
- // finish off incomplete coding unit
- while (bufsize != 0 && off < end)
- write(b[off++]);
-
- // finish off line
- int blen = ((bytesPerLine - count) / 4) * 3;
- if (off + blen <= end) {
- // number of bytes that will be produced in outbuf
- int outlen = encodedSize(blen);
- if (!noCRLF) {
- outbuf[outlen++] = (byte)'\r';
- outbuf[outlen++] = (byte)'\n';
- }
- out.write(encode(b, off, blen, outbuf), 0, outlen);
- off += blen;
- count = 0;
- }
-
- // do bulk encoding a line at a time.
- for (; off + lineLimit <= end; off += lineLimit)
- out.write(encode(b, off, lineLimit, outbuf));
-
- // handle remaining partial line
- if (off + 3 <= end) {
- blen = end - off;
- blen = (blen / 3) * 3; // round down
- // number of bytes that will be produced in outbuf
- int outlen = encodedSize(blen);
- out.write(encode(b, off, blen, outbuf), 0, outlen);
- off += blen;
- count += outlen;
- }
-
- // start next coding unit
- for (; off < end; off++)
- write(b[off]);
- }
-
- /**
- * Encodes b.length bytes to this output stream.
- *
- * @param b the data to be written.
- * @exception IOException if an I/O error occurs.
- */
- public void write(byte[] b) throws IOException {
- write(b, 0, b.length);
- }
-
- /**
- * Encodes the specified byte to this output stream.
- *
- * @param c the byte.
- * @exception IOException if an I/O error occurs.
- */
- public synchronized void write(int c) throws IOException {
- buffer[bufsize++] = (byte)c;
- if (bufsize == 3) { // Encoding unit = 3 bytes
- encode();
- bufsize = 0;
- }
- }
-
- /**
- * Flushes this output stream and forces any buffered output bytes
- * to be encoded out to the stream.
- *
- * @exception IOException if an I/O error occurs.
- */
- public synchronized void flush() throws IOException {
- if (bufsize > 0) { // If there's unencoded characters in the buffer ..
- encode(); // .. encode them
- bufsize = 0;
- }
- out.flush();
- }
-
- /**
- * Forces any buffered output bytes to be encoded out to the stream
- * and closes this output stream
- */
- public synchronized void close() throws IOException {
- flush();
- if (count > 0 && !noCRLF) {
- out.write(newline);
- out.flush();
- }
- out.close();
- }
-
- /** This array maps the characters to their 6 bit values */
- 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
- };
-
- /**
- * Encode the data stored in buffer.
- * Uses outbuf to store the encoded
- * data before writing.
- *
- * @exception IOException if an I/O error occurs.
- */
- private void encode() throws IOException {
- int osize = encodedSize(bufsize);
- out.write(encode(buffer, 0, bufsize, outbuf), 0, osize);
- // increment count
- count += osize;
- // If writing out this encoded unit caused overflow,
- // start a new line.
- if (count >= bytesPerLine) {
- if (!noCRLF)
- out.write(newline);
- count = 0;
- }
- }
-
- /**
- * Base64 encode a byte array. No line breaks are inserted.
- * This method is suitable for short strings, such as those
- * in the IMAP AUTHENTICATE protocol, but not to encode the
- * entire content of a MIME part.
- */
- public static byte[] encode(byte[] inbuf) {
- if (inbuf.length == 0)
- return inbuf;
- return encode(inbuf, 0, inbuf.length, null);
- }
-
- /**
- * Internal use only version of encode. Allow specifying which
- * part of the input buffer to encode. If outbuf is non-null,
- * it's used as is. Otherwise, a new output buffer is allocated.
- */
- private static byte[] encode(byte[] inbuf, int off, int size,
- byte[] outbuf) {
- if (outbuf == null)
- outbuf = new byte[encodedSize(size)];
- int inpos, outpos;
- int val;
- for (inpos = off, outpos = 0; size >= 3; size -= 3, outpos += 4) {
- val = inbuf[inpos++] & 0xff;
- val <<= 8;
- val |= inbuf[inpos++] & 0xff;
- val <<= 8;
- val |= inbuf[inpos++] & 0xff;
- outbuf[outpos+3] = (byte)pem_array[val & 0x3f];
- val >>= 6;
- outbuf[outpos+2] = (byte)pem_array[val & 0x3f];
- val >>= 6;
- outbuf[outpos+1] = (byte)pem_array[val & 0x3f];
- val >>= 6;
- outbuf[outpos+0] = (byte)pem_array[val & 0x3f];
- }
- // done with groups of three, finish up any odd bytes left
- if (size == 1) {
- val = inbuf[inpos++] & 0xff;
- val <<= 4;
- outbuf[outpos+3] = (byte)'='; // pad character;
- outbuf[outpos+2] = (byte)'='; // pad character;
- outbuf[outpos+1] = (byte)pem_array[val & 0x3f];
- val >>= 6;
- outbuf[outpos+0] = (byte)pem_array[val & 0x3f];
- } else if (size == 2) {
- val = inbuf[inpos++] & 0xff;
- val <<= 8;
- val |= inbuf[inpos++] & 0xff;
- val <<= 2;
- outbuf[outpos+3] = (byte)'='; // pad character;
- outbuf[outpos+2] = (byte)pem_array[val & 0x3f];
- val >>= 6;
- outbuf[outpos+1] = (byte)pem_array[val & 0x3f];
- val >>= 6;
- outbuf[outpos+0] = (byte)pem_array[val & 0x3f];
- }
- return outbuf;
- }
-
- /**
- * Return the corresponding encoded size for the given number
- * of bytes, not including any CRLF.
- */
- private static int encodedSize(int size) {
- return ((size + 2) / 3) * 4;
- }
-
- /*** begin TEST program
- public static void main(String argv[]) throws Exception {
- FileInputStream infile = new FileInputStream(argv[0]);
- BASE64EncoderStream encoder = new BASE64EncoderStream(System.out);
- int c;
-
- while ((c = infile.read()) != -1)
- encoder.write(c);
- encoder.close();
- }
- *** end TEST program **/
-}
diff --git a/src/main/java/com/sun/mail/util/BEncoderStream.java b/src/main/java/com/sun/mail/util/BEncoderStream.java
deleted file mode 100644
index a659afee..00000000
--- a/src/main/java/com/sun/mail/util/BEncoderStream.java
+++ /dev/null
@@ -1,71 +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.util;
-
-import java.io.*;
-
-/**
- * This class implements a 'B' Encoder as defined by RFC2047 for
- * encoding MIME headers. It subclasses the BASE64EncoderStream
- * class.
- *
- * @author John Mani
- */
-
-public class BEncoderStream extends BASE64EncoderStream {
-
- /**
- * Create a 'B' encoder that encodes the specified input stream.
- * @param out the output stream
- */
- public BEncoderStream(OutputStream out) {
- super(out, Integer.MAX_VALUE); // MAX_VALUE is 2^31, should
- // suffice (!) to indicate that
- // CRLFs should not be inserted
- }
-
- /**
- * Returns the length of the encoded version of this byte array.
- */
- public static int encodedLength(byte[] b) {
- return ((b.length + 2)/3) * 4;
- }
-}
diff --git a/src/main/java/com/sun/mail/util/CRLFOutputStream.java b/src/main/java/com/sun/mail/util/CRLFOutputStream.java
deleted file mode 100644
index f685b18b..00000000
--- a/src/main/java/com/sun/mail/util/CRLFOutputStream.java
+++ /dev/null
@@ -1,109 +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.util;
-
-import java.io.*;
-
-
-/**
- * Convert lines into the canonical format, that is, terminate lines with the
- * CRLF sequence.
- *
- * @author John Mani
- */
-public class CRLFOutputStream extends FilterOutputStream {
- protected int lastb = -1;
- protected boolean atBOL = true; // at beginning of line?
- private static final byte[] newline = { (byte)'\r', (byte)'\n' };
-
- public CRLFOutputStream(OutputStream os) {
- super(os);
- }
-
- public void write(int b) throws IOException {
- if (b == '\r') {
- writeln();
- } else if (b == '\n') {
- if (lastb != '\r')
- writeln();
- } else {
- out.write(b);
- atBOL = false;
- }
- lastb = b;
- }
-
- public void write(byte b[]) throws IOException {
- write(b, 0, b.length);
- }
-
- public void write(byte b[], int off, int len) throws IOException {
- int start = off;
-
- len += off;
- for (int i = start; i < len ; i++) {
- if (b[i] == '\r') {
- out.write(b, start, i - start);
- writeln();
- start = i + 1;
- } else if (b[i] == '\n') {
- if (lastb != '\r') {
- out.write(b, start, i - start);
- writeln();
- }
- start = i + 1;
- }
- lastb = b[i];
- }
- if ((len - start) > 0) {
- out.write(b, start, len - start);
- atBOL = false;
- }
- }
-
- /*
- * Just write out a new line, something similar to out.println()
- */
- public void writeln() throws IOException {
- out.write(newline);
- atBOL = true;
- }
-}
diff --git a/src/main/java/com/sun/mail/util/DecodingException.java b/src/main/java/com/sun/mail/util/DecodingException.java
deleted file mode 100644
index 3593292d..00000000
--- a/src/main/java/com/sun/mail/util/DecodingException.java
+++ /dev/null
@@ -1,63 +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.util;
-
-import java.io.IOException;
-
-/**
- * A special IOException that indicates a failure to decode data due
- * to an error in the formatting of the data. This allows applications
- * to distinguish decoding errors from other I/O errors.
- *
- * @author Bill Shannon
- */
-
-public class DecodingException extends IOException {
-
- private static final long serialVersionUID = -6913647794421459390L;
-
- /**
- * Constructor
- */
- public DecodingException(String s) {
- super(s);
- }
-}
diff --git a/src/main/java/com/sun/mail/util/FolderClosedIOException.java b/src/main/java/com/sun/mail/util/FolderClosedIOException.java
deleted file mode 100644
index 313a648a..00000000
--- a/src/main/java/com/sun/mail/util/FolderClosedIOException.java
+++ /dev/null
@@ -1,83 +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.util;
-
-import java.io.IOException;
-import javax.mail.Folder;
-
-/**
- * A variant of FolderClosedException that can be thrown from methods
- * that only throw IOException. The getContent method will catch this
- * exception and translate it back to FolderClosedException.
- *
- * @author Bill Shannon
- */
-
-public class FolderClosedIOException extends IOException {
- transient private Folder folder;
-
- private static final long serialVersionUID = 4281122580365555735L;
-
- /**
- * Constructor
- * @param folder the Folder
- */
- public FolderClosedIOException(Folder folder) {
- this(folder, null);
- }
-
- /**
- * Constructor
- * @param folder the Folder
- * @param message the detailed error message
- */
- public FolderClosedIOException(Folder folder, String message) {
- super(message);
- this.folder = folder;
- }
-
- /**
- * Returns the dead Folder object
- */
- public Folder getFolder() {
- return folder;
- }
-}
diff --git a/src/main/java/com/sun/mail/util/LineInputStream.java b/src/main/java/com/sun/mail/util/LineInputStream.java
deleted file mode 100644
index 6787fac3..00000000
--- a/src/main/java/com/sun/mail/util/LineInputStream.java
+++ /dev/null
@@ -1,147 +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.util;
-
-import java.io.*;
-
-/**
- * This class is to support reading CRLF terminated lines that
- * contain only US-ASCII characters from an input stream. Provides
- * functionality that is similar to the deprecated
- * DataInputStream.readLine(). Expected use is to read
- * lines as String objects from a RFC822 stream.
- *
- * It is implemented as a FilterInputStream, so one can just wrap
- * this class around any input stream and read bytes from this filter.
- *
- * @author John Mani
- */
-
-public class LineInputStream extends FilterInputStream {
-
- private char[] lineBuffer = null; // reusable byte buffer
- private static int MAX_INCR = 1024*1024; // 1MB
-
- public LineInputStream(InputStream in) {
- super(in);
- }
-
- /**
- * Read a line containing only ASCII characters from the input
- * stream. A line is terminated by a CR or NL or CR-NL sequence.
- * A common error is a CR-CR-NL sequence, which will also terminate
- * a line.
- * The line terminator is not returned as part of the returned
- * String. Returns null if no data is available.
- *
- * This class is similar to the deprecated
- * DataInputStream.readLine()
- */
- public String readLine() throws IOException {
- //InputStream in = this.in;
- char[] buf = lineBuffer;
-
- if (buf == null)
- buf = lineBuffer = new char[128];
-
- int c1;
- int room = buf.length;
- int offset = 0;
-
- while ((c1 = in.read()) != -1) {
- if (c1 == '\n') // Got NL, outa here.
- break;
- else if (c1 == '\r') {
- // Got CR, is the next char NL ?
- boolean twoCRs = false;
- if (in.markSupported())
- in.mark(2);
- int c2 = in.read();
- if (c2 == '\r') { // discard extraneous CR
- twoCRs = true;
- c2 = in.read();
- }
- if (c2 != '\n') {
- /*
- * If the stream supports it (which we hope will always
- * be the case), reset to after the first CR. Otherwise,
- * we wrap a PushbackInputStream around the stream so we
- * can unread the characters we don't need. The only
- * problem with that is that the caller might stop
- * reading from this LineInputStream, throw it away,
- * and then start reading from the underlying stream.
- * If that happens, the pushed back characters will be
- * lost forever.
- */
- if (in.markSupported())
- in.reset();
- else {
- if (!(in instanceof PushbackInputStream))
- in /*= this.in*/ = new PushbackInputStream(in, 2);
- if (c2 != -1)
- ((PushbackInputStream)in).unread(c2);
- if (twoCRs)
- ((PushbackInputStream)in).unread('\r');
- }
- }
- break; // outa here.
- }
-
- // Not CR, NL or CR-NL ...
- // .. Insert the byte into our byte buffer
- if (--room < 0) { // No room, need to grow.
- if (buf.length < MAX_INCR)
- buf = new char[buf.length * 2];
- else
- buf = new char[buf.length + MAX_INCR];
- room = buf.length - offset - 1;
- System.arraycopy(lineBuffer, 0, buf, 0, offset);
- lineBuffer = buf;
- }
- buf[offset++] = (char)c1;
- }
-
- if ((c1 == -1) && (offset == 0))
- return null;
-
- return String.copyValueOf(buf, 0, offset);
- }
-}
diff --git a/src/main/java/com/sun/mail/util/LineOutputStream.java b/src/main/java/com/sun/mail/util/LineOutputStream.java
deleted file mode 100644
index 6586f682..00000000
--- a/src/main/java/com/sun/mail/util/LineOutputStream.java
+++ /dev/null
@@ -1,78 +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.util;
-
-import java.io.*;
-
-/**
- * This class is to support writing out Strings as a sequence of bytes
- * terminated by a CRLF sequence. The String must contain only US-ASCII
- * characters.
- *
- * The expected use is to write out RFC822 style headers to an output
- * stream.
- *
- * @author John Mani
- */
-
-public class LineOutputStream extends FilterOutputStream {
- private static byte[] newline;
-
- static {
- newline = new byte[2];
- newline[0] = (byte)'\r';
- newline[1] = (byte)'\n';
- }
-
- public LineOutputStream(OutputStream out) {
- super(out);
- }
-
- public void writeln(String s) throws IOException {
- byte[] bytes = ASCIIUtility.getBytes(s);
- out.write(bytes);
- out.write(newline);
- }
-
- public void writeln() throws IOException {
- out.write(newline);
- }
-}
diff --git a/src/main/java/com/sun/mail/util/LogOutputStream.java b/src/main/java/com/sun/mail/util/LogOutputStream.java
deleted file mode 100644
index dc372e2c..00000000
--- a/src/main/java/com/sun/mail/util/LogOutputStream.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2008-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.util;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.logging.Level;
-
-/**
- * Capture output lines and send them to the mail logger.
- */
-public class LogOutputStream extends OutputStream {
- protected MailLogger logger;
- protected Level level;
-
- private int lastb = -1;
- private byte[] buf = new byte[80];
- private int pos = 0;
-
- /**
- * Log to the specified logger.
- */
- public LogOutputStream(MailLogger logger) {
- this.logger = logger;
- this.level = Level.FINEST;
- }
-
- public void write(int b) throws IOException {
- if (!logger.isLoggable(level))
- return;
-
- if (b == '\r') {
- logBuf();
- } else if (b == '\n') {
- if (lastb != '\r')
- logBuf();
- } else {
- expandCapacity(1);
- buf[pos++] = (byte)b;
- }
- lastb = b;
- }
-
- public void write(byte b[]) throws IOException {
- write(b, 0, b.length);
- }
-
- public void write(byte b[], int off, int len) throws IOException {
- int start = off;
-
- if (!logger.isLoggable(level))
- return;
- len += off;
- for (int i = start; i < len ; i++) {
- if (b[i] == '\r') {
- expandCapacity(i - start);
- System.arraycopy(b, start, buf, pos, i - start);
- pos += i - start;
- logBuf();
- start = i + 1;
- } else if (b[i] == '\n') {
- if (lastb != '\r') {
- expandCapacity(i - start);
- System.arraycopy(b, start, buf, pos, i - start);
- pos += i - start;
- logBuf();
- }
- start = i + 1;
- }
- lastb = b[i];
- }
- if ((len - start) > 0) {
- expandCapacity(len - start);
- System.arraycopy(b, start, buf, pos, len - start);
- pos += len - start;
- }
- }
-
- /**
- * Log the specified message.
- * Can be overridden by subclass to do different logging.
- */
- protected void log(String msg) {
- logger.log(level, msg);
- }
-
- /**
- * Convert the buffer to a string and log it.
- */
- private void logBuf() {
- String msg = new String(buf, 0, pos);
- pos = 0;
- log(msg);
- }
-
- /**
- * Ensure that the buffer can hold at least len bytes
- * beyond the current position.
- */
- private void expandCapacity(int len) {
- while (pos + len > buf.length) {
- byte[] nb = new byte[buf.length * 2];
- System.arraycopy(buf, 0, nb, 0, pos);
- buf = nb;
- }
- }
-}
diff --git a/src/main/java/com/sun/mail/util/MailConnectException.java b/src/main/java/com/sun/mail/util/MailConnectException.java
deleted file mode 100644
index 4b83293f..00000000
--- a/src/main/java/com/sun/mail/util/MailConnectException.java
+++ /dev/null
@@ -1,107 +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.util;
-
-import javax.mail.MessagingException;
-
-/**
- * A MessagingException that indicates a socket connection attempt failed.
- * Unlike java.net.ConnectException, it includes details of what we
- * were trying to connect to. The underlying exception is available
- * as the "cause" of this exception.
- *
- * @see java.net.ConnectException
- * @author Bill Shannon
- * @since JavaMail 1.5.0
- */
-
-public class MailConnectException extends MessagingException {
- private String host;
- private int port;
- private int cto;
-
- private static final long serialVersionUID = -3818807731125317729L;
-
- /**
- * Constructs a MailConnectException.
- *
- * @param cex the SocketConnectException with the details
- */
- public MailConnectException(SocketConnectException cex) {
- super(
- "Couldn't connect to host, port: " +
- cex.getHost() + ", " + cex.getPort() +
- "; timeout " + cex.getConnectionTimeout() +
- (cex.getMessage() != null ? ("; " + cex.getMessage()) : ""));
- // extract the details and save them here
- this.host = cex.getHost();
- this.port = cex.getPort();
- this.cto = cex.getConnectionTimeout();
- setNextException(cex.getException());
- }
-
- /**
- * The host we were trying to connect to.
- *
- * @return the host
- */
- public String getHost() {
- return host;
- }
-
- /**
- * The port we were trying to connect to.
- *
- * @return the port
- */
- public int getPort() {
- return port;
- }
-
- /**
- * The timeout used for the connection attempt.
- *
- * @return the connection timeout
- */
- public int getConnectionTimeout() {
- return cto;
- }
-}
diff --git a/src/main/java/com/sun/mail/util/MailLogger.java b/src/main/java/com/sun/mail/util/MailLogger.java
deleted file mode 100644
index 2354d280..00000000
--- a/src/main/java/com/sun/mail/util/MailLogger.java
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 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.util;
-
-import java.io.PrintStream;
-import java.text.MessageFormat;
-import java.util.logging.Logger;
-import java.util.logging.Level;
-
-import javax.mail.Session;
-
-/**
- * A simplified logger used by JavaMail to handle logging to a
- * PrintStream and logging through a java.util.logging.Logger.
- * If debug is set, messages are written to the PrintStream and
- * prefixed by the specified prefix (which is not included in
- * Logger messages).
- * Messages are logged by the Logger based on the configuration
- * of the logging system.
- */
-
-/*
- * It would be so much simpler to just subclass Logger and override
- * the log(LogRecord) method, as the javadocs suggest, but that doesn't
- * work because Logger makes the decision about whether to log the message
- * or not before calling the log(LogRecord) method. Instead, we just
- * provide the few log methods we need here.
- */
-
-public final class MailLogger {
- private final Logger logger; // for log messages
- private final String prefix; // for debug output
- private final boolean debug; // produce debug output?
- private final PrintStream out; // stream for debug output
-
- /**
- * Construct a new MailLogger using the specified Logger name,
- * debug prefix (e.g., "DEBUG"), debug flag, and PrintStream.
- *
- * @param name the Logger name
- * @param prefix the prefix for debug output, or null for none
- * @param debug if true, write to PrintStream
- * @param out the PrintStream to write to
- */
- public MailLogger(String name, String prefix, boolean debug,
- PrintStream out) {
- logger = Logger.getLogger(name);
- this.prefix = prefix;
- this.debug = debug;
- this.out = out != null ? out : System.out;
- }
-
- /**
- * Construct a new MailLogger using the specified class' package
- * name as the Logger name,
- * debug prefix (e.g., "DEBUG"), debug flag, and PrintStream.
- *
- * @param clazz the Logger name is the package name of this class
- * @param prefix the prefix for debug output, or null for none
- * @param debug if true, write to PrintStream
- * @param out the PrintStream to write to
- */
- public MailLogger(Class clazz, String prefix, boolean debug,
- PrintStream out) {
- String name = packageOf(clazz);
- logger = Logger.getLogger(name);
- this.prefix = prefix;
- this.debug = debug;
- this.out = out != null ? out : System.out;
- }
-
- /**
- * Construct a new MailLogger using the specified class' package
- * name combined with the specified subname as the Logger name,
- * debug prefix (e.g., "DEBUG"), debug flag, and PrintStream.
- *
- * @param clazz the Logger name is the package name of this class
- * @param subname the Logger name relative to this Logger name
- * @param prefix the prefix for debug output, or null for none
- * @param debug if true, write to PrintStream
- * @param out the PrintStream to write to
- */
- public MailLogger(Class clazz, String subname, String prefix, boolean debug,
- PrintStream out) {
- String name = packageOf(clazz) + "." + subname;
- logger = Logger.getLogger(name);
- this.prefix = prefix;
- this.debug = debug;
- this.out = out != null ? out : System.out;
- }
-
- /**
- * Construct a new MailLogger using the specified Logger name and
- * debug prefix (e.g., "DEBUG"). Get the debug flag and PrintStream
- * from the Session.
- *
- * @param name the Logger name
- * @param prefix the prefix for debug output, or null for none
- * @param session where to get the debug flag and PrintStream
- */
- public MailLogger(String name, String prefix, Session session) {
- this(name, prefix, session.getDebug(), session.getDebugOut());
- }
-
- /**
- * Construct a new MailLogger using the specified class' package
- * name as the Logger name and the specified
- * debug prefix (e.g., "DEBUG"). Get the debug flag and PrintStream
- * from the Session.
- *
- * @param clazz the Logger name is the package name of this class
- * @param prefix the prefix for debug output, or null for none
- * @param session where to get the debug flag and PrintStream
- */
- public MailLogger(Class clazz, String prefix, Session session) {
- this(clazz, prefix, session.getDebug(), session.getDebugOut());
- }
-
- /**
- * Create a MailLogger that uses a Logger with the specified name
- * and prefix. The new MailLogger uses the same debug flag and
- * PrintStream as this MailLogger.
- *
- * @param name the Logger name
- * @param prefix the prefix for debug output, or null for none
- */
- public MailLogger getLogger(String name, String prefix) {
- return new MailLogger(name, prefix, debug, out);
- }
-
- /**
- * Create a MailLogger using the specified class' package
- * name as the Logger name and the specified prefix.
- * The new MailLogger uses the same debug flag and
- * PrintStream as this MailLogger.
- *
- * @param clazz the Logger name is the package name of this class
- * @param prefix the prefix for debug output, or null for none
- */
- public MailLogger getLogger(Class clazz, String prefix) {
- return new MailLogger(clazz, prefix, debug, out);
- }
-
- /**
- * Create a MailLogger that uses a Logger whose name is composed
- * of this MailLogger's name plus the specified sub-name, separated
- * by a dot. The new MailLogger uses the new prefix for debug output.
- * This is used primarily by the protocol trace code that wants a
- * different prefix (none).
- *
- * @param subname the Logger name relative to this Logger name
- * @param prefix the prefix for debug output, or null for none
- */
- public MailLogger getSubLogger(String subname, String prefix) {
- return new MailLogger(logger.getName() + "." + subname, prefix,
- debug, out);
- }
-
- /**
- * Create a MailLogger that uses a Logger whose name is composed
- * of this MailLogger's name plus the specified sub-name, separated
- * by a dot. The new MailLogger uses the new prefix for debug output.
- * This is used primarily by the protocol trace code that wants a
- * different prefix (none).
- *
- * @param subname the Logger name relative to this Logger name
- * @param prefix the prefix for debug output, or null for none
- * @param debug the debug flag for the sub-logger
- */
- public MailLogger getSubLogger(String subname, String prefix,
- boolean debug) {
- return new MailLogger(logger.getName() + "." + subname, prefix,
- debug, out);
- }
-
- /**
- * Log the message at the specified level.
- */
- public void log(Level level, String msg) {
- ifDebugOut(msg);
- if (logger.isLoggable(level)) {
- final String[] frame = inferCaller();
- logger.logp(level, frame[0], frame[1], msg);
- }
- }
-
- /**
- * Log the message at the specified level.
- */
- public void log(Level level, String msg, Object param1) {
- if (debug) {
- msg = MessageFormat.format(msg, new Object[] { param1 });
- debugOut(msg);
- }
-
- if (logger.isLoggable(level)) {
- final String[] frame = inferCaller();
- logger.logp(level, frame[0], frame[1], msg, param1);
- }
- }
-
- /**
- * Log the message at the specified level.
- */
- public void log(Level level, String msg, Object params[]) {
- if (debug) {
- msg = MessageFormat.format(msg, params);
- debugOut(msg);
- }
-
- if (logger.isLoggable(level)) {
- final String[] frame = inferCaller();
- logger.logp(level, frame[0], frame[1], msg, params);
- }
- }
-
- /*
- * Maybe for JavaMail 1.5...
- *
- public void logf(Level level, String msg, Object... params) {
- msg = String.format(msg, params);
- ifDebugOut(msg);
- logger.log(level, msg);
- }
- */
-
- /**
- * Log the message at the specified level.
- */
- public void log(Level level, String msg, Throwable thrown) {
- if (debug) {
- if (thrown != null) {
- debugOut(msg + ", THROW: ");
- thrown.printStackTrace(out);
- } else {
- debugOut(msg);
- }
- }
-
- if (logger.isLoggable(level)) {
- final String[] frame = inferCaller();
- logger.logp(level, frame[0], frame[1], msg, thrown);
- }
- }
-
- /**
- * Log a message at the CONFIG level.
- */
- public void config(String msg) {
- log(Level.CONFIG, msg);
- }
-
- /**
- * Log a message at the FINE level.
- */
- public void fine(String msg) {
- log(Level.FINE, msg);
- }
-
- /**
- * Log a message at the FINER level.
- */
- public void finer(String msg) {
- log(Level.FINER, msg);
- }
-
- /**
- * Log a message at the FINEST level.
- */
- public void finest(String msg) {
- log(Level.FINEST, msg);
- }
-
- /**
- * If "debug" is set, or our embedded Logger is loggable at the
- * given level, return true.
- */
- public boolean isLoggable(Level level) {
- return debug || logger.isLoggable(level);
- }
-
- private final void ifDebugOut(String msg) {
- if (debug)
- debugOut(msg);
- }
-
- private final void debugOut(String msg) {
- if (prefix != null)
- out.println(prefix + ": " + msg);
- else
- out.println(msg);
- }
-
- /**
- * Return the package name of the class.
- * Sometimes there will be no Package object for the class,
- * e.g., if the class loader hasn't created one (see Class.getPackage()).
- */
- private String packageOf(Class clazz) {
- Package p = clazz.getPackage();
- if (p != null)
- return p.getName(); // hopefully the common case
- String cname = clazz.getName();
- int i = cname.lastIndexOf('.');
- if (i > 0)
- return cname.substring(0, i);
- // no package name, now what?
- return "";
- }
-
- /*
- * A disadvantage of not being able to use Logger directly in JavaMail
- * code is that the "source class" information that Logger guesses will
- * always refer to this class instead of our caller. This method
- * duplicates what Logger does to try to find *our* caller, so that
- * Logger doesn't have to do it (and get the wrong answer), and because
- * our caller is what's wanted.
- */
- private String[] inferCaller() {
- // Get the stack trace.
- StackTraceElement stack[] = (new Throwable()).getStackTrace();
- // First, search back to a method in the Logger class.
- int ix = 0;
- while (ix < stack.length) {
- StackTraceElement frame = stack[ix];
- String cname = frame.getClassName();
- if (isLoggerImplFrame(cname)) {
- break;
- }
- ix++;
- }
- // Now search for the first frame before the "Logger" class.
- while (ix < stack.length) {
- StackTraceElement frame = stack[ix];
- String cname = frame.getClassName();
- if (!isLoggerImplFrame(cname)) {
- // We've found the relevant frame.
- return new String[]{cname, frame.getMethodName()};
- }
- ix++;
- }
- // We haven't found a suitable frame, so just punt. This is
- // OK as we are only committed to making a "best effort" here.
- return new String[]{null, null};
- }
-
- private boolean isLoggerImplFrame(String cname) {
- return MailLogger.class.getName().equals(cname);
- }
-}
diff --git a/src/main/java/com/sun/mail/util/MailSSLSocketFactory.java b/src/main/java/com/sun/mail/util/MailSSLSocketFactory.java
deleted file mode 100644
index 0ec24a46..00000000
--- a/src/main/java/com/sun/mail/util/MailSSLSocketFactory.java
+++ /dev/null
@@ -1,365 +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.util;
-
-import java.io.*;
-import java.net.*;
-import java.security.*;
-import java.security.cert.*;
-import java.util.*;
-
-import javax.net.ssl.*;
-
-/**
- * An SSL socket factory that makes it easier to specify trust.
- * This socket factory can be configured to trust all hosts or
- * trust a specific set of hosts, in which case the server's
- * certificate isn't verified. Alternatively, a custom TrustManager
- * can be supplied.
- *
- * An instance of this factory can be set as the value of the
- * mail.<protocol>.ssl.socketFactory property.
- *
- * @since JavaMail 1.4.2
- * @author Stephan Sann
- * @author Bill Shannon
- */
-public class MailSSLSocketFactory extends SSLSocketFactory {
-
- /** Should all hosts be trusted? */
- private boolean trustAllHosts;
-
- /** String-array of trusted hosts */
- private String[] trustedHosts = null;
-
- /** Holds a SSLContext to get SSLSocketFactories from */
- private SSLContext sslcontext;
-
- /** Holds the KeyManager array to use */
- private KeyManager[] keyManagers;
-
- /** Holds the TrustManager array to use */
- private TrustManager[] trustManagers;
-
- /** Holds the SecureRandom to use */
- private SecureRandom secureRandom;
-
- /** Holds a SSLSocketFactory to pass all API-method-calls to */
- private SSLSocketFactory adapteeFactory = null;
-
- /**
- * Initializes a new MailSSLSocketFactory.
- *
- * @throws GeneralSecurityException
- */
- public MailSSLSocketFactory() throws GeneralSecurityException {
- this("TLS");
- }
-
- /**
- * Initializes a new MailSSLSocketFactory with a given protocol.
- * Normally the protocol will be specified as "TLS".
- *
- * @param protocol The protocol to use
- * @throws NoSuchAlgorithmException if given protocol is not supported
- */
- public MailSSLSocketFactory(String protocol)
- throws GeneralSecurityException {
-
- // By default we do NOT trust all hosts.
- trustAllHosts = false;
-
- // Get an instance of an SSLContext.
- sslcontext = SSLContext.getInstance(protocol);
-
- // Default properties to init the SSLContext
- keyManagers = null;
- trustManagers = new TrustManager[] { new MailTrustManager() };
- secureRandom = null;
-
- // Assemble a default SSLSocketFactory to delegate all API-calls to.
- newAdapteeFactory();
- }
-
-
- /**
- * Gets an SSLSocketFactory based on the given (or default)
- * KeyManager array, TrustManager array and SecureRandom and
- * sets it to the instance var adapteeFactory.
- */
- private synchronized void newAdapteeFactory()
- throws KeyManagementException {
- sslcontext.init(keyManagers, trustManagers, secureRandom);
-
- // Get SocketFactory and save it in our instance var
- adapteeFactory = (SSLSocketFactory)sslcontext.getSocketFactory();
- }
-
- /**
- * @return the keyManagers
- */
- public synchronized KeyManager[] getKeyManagers() {
- return (KeyManager[])keyManagers.clone();
- }
-
- /**
- * @param keyManagers the keyManagers to set
- */
- public synchronized void setKeyManagers(KeyManager[] keyManagers)
- throws GeneralSecurityException {
- this.keyManagers = (KeyManager[])keyManagers.clone();
- newAdapteeFactory();
- }
-
- /**
- * @return the secureRandom
- */
- public synchronized SecureRandom getSecureRandom() {
- return secureRandom;
- }
-
- /**
- * @param secureRandom the secureRandom to set
- */
- public synchronized void setSecureRandom(SecureRandom secureRandom)
- throws GeneralSecurityException {
- this.secureRandom = secureRandom;
- newAdapteeFactory();
- }
-
- /**
- * @return the trustManagers
- */
- public synchronized TrustManager[] getTrustManagers() {
- return trustManagers;
- }
-
- /**
- * @param trustManagers the trustManagers to set
- */
- public synchronized void setTrustManagers(TrustManager[] trustManagers)
- throws GeneralSecurityException {
- this.trustManagers = trustManagers;
- newAdapteeFactory();
- }
-
- /**
- * @return true if all hosts should be trusted
- */
- public synchronized boolean isTrustAllHosts() {
- return trustAllHosts;
- }
-
- /**
- * @param trustAllHosts should all hosts be trusted?
- */
- public synchronized void setTrustAllHosts(boolean trustAllHosts) {
- this.trustAllHosts = trustAllHosts;
- }
-
- /**
- * @return the trusted hosts
- */
- public synchronized String[] getTrustedHosts() {
- return (String[])trustedHosts.clone();
- }
-
- /**
- * @param trustedHosts the hosts to trust
- */
- public synchronized void setTrustedHosts(String[] trustedHosts) {
- this.trustedHosts = (String[])trustedHosts.clone();
- }
-
- /**
- * After a successful conection to the server, this method is
- * called to ensure that the server should be trusted.
- *
- * @param server name of the server we connected to
- * @param sslSocket SSLSocket connected to the server
- * @return true if "trustAllHosts" is set to true OR the server
- * is contained in the "trustedHosts" array;
- */
- public synchronized boolean isServerTrusted(String server,
- SSLSocket sslSocket) {
-
- //System.out.println("DEBUG: isServerTrusted host " + server);
-
- // If "trustAllHosts" is set to true, we return true
- if (trustAllHosts)
- return true;
-
- // If the socket host is contained in the "trustedHosts" array,
- // we return true
- if (trustedHosts != null)
- return Arrays.asList(trustedHosts).contains(server); // ignore case?
-
- // If we get here, trust of the server was verified by the trust manager
- return true;
- }
-
-
- // SocketFactory methods
-
- /* (non-Javadoc)
- * @see javax.net.ssl.SSLSocketFactory#createSocket(java.net.Socket,
- * java.lang.String, int, boolean)
- */
- //@Override
- public synchronized Socket createSocket(Socket socket, String s, int i,
- boolean flag) throws IOException {
- return adapteeFactory.createSocket(socket, s, i, flag);
- }
-
- /* (non-Javadoc)
- * @see javax.net.ssl.SSLSocketFactory#getDefaultCipherSuites()
- */
- //@Override
- public synchronized String[] getDefaultCipherSuites() {
- return adapteeFactory.getDefaultCipherSuites();
- }
-
- /* (non-Javadoc)
- * @see javax.net.ssl.SSLSocketFactory#getSupportedCipherSuites()
- */
- //@Override
- public synchronized String[] getSupportedCipherSuites() {
- return adapteeFactory.getSupportedCipherSuites();
- }
-
- /* (non-Javadoc)
- * @see javax.net.SocketFactory#createSocket()
- */
- //@Override
- public synchronized Socket createSocket() throws IOException {
- return adapteeFactory.createSocket();
- }
-
- /* (non-Javadoc)
- * @see javax.net.SocketFactory#createSocket(java.net.InetAddress, int,
- * java.net.InetAddress, int)
- */
- //@Override
- public synchronized Socket createSocket(InetAddress inetaddress, int i,
- InetAddress inetaddress1, int j) throws IOException {
- return adapteeFactory.createSocket(inetaddress, i, inetaddress1, j);
- }
-
- /* (non-Javadoc)
- * @see javax.net.SocketFactory#createSocket(java.net.InetAddress, int)
- */
- //@Override
- public synchronized Socket createSocket(InetAddress inetaddress, int i)
- throws IOException {
- return adapteeFactory.createSocket(inetaddress, i);
- }
-
- /* (non-Javadoc)
- * @see javax.net.SocketFactory#createSocket(java.lang.String, int,
- * java.net.InetAddress, int)
- */
- //@Override
- public synchronized Socket createSocket(String s, int i,
- InetAddress inetaddress, int j)
- throws IOException, UnknownHostException {
- return adapteeFactory.createSocket(s, i, inetaddress, j);
- }
-
- /* (non-Javadoc)
- * @see javax.net.SocketFactory#createSocket(java.lang.String, int)
- */
- //@Override
- public synchronized Socket createSocket(String s, int i)
- throws IOException, UnknownHostException {
- return adapteeFactory.createSocket(s, i);
- }
-
-
- // inner classes
-
- /**
- * A default Trustmanager.
- *
- * @author Stephan Sann
- */
- private class MailTrustManager implements X509TrustManager {
-
- /** A TrustManager to pass method calls to */
- private X509TrustManager adapteeTrustManager = null;
-
- /**
- * Initializes a new TrustManager instance.
- */
- private MailTrustManager() throws GeneralSecurityException {
- TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
- tmf.init((KeyStore)null);
- adapteeTrustManager = (X509TrustManager)tmf.getTrustManagers()[0];
- }
-
- /* (non-Javadoc)
- * @see javax.net.ssl.X509TrustManager#checkClientTrusted(
- * java.security.cert.X509Certificate[], java.lang.String)
- */
- public void checkClientTrusted(X509Certificate[] certs, String authType)
- throws CertificateException {
- if (!(isTrustAllHosts() || getTrustedHosts() != null))
- adapteeTrustManager.checkClientTrusted(certs, authType);
- }
-
- /* (non-Javadoc)
- * @see javax.net.ssl.X509TrustManager#checkServerTrusted(
- * java.security.cert.X509Certificate[], java.lang.String)
- */
- public void checkServerTrusted(X509Certificate[] certs, String authType)
- throws CertificateException {
-
- if (!(isTrustAllHosts() || getTrustedHosts() != null))
- adapteeTrustManager.checkServerTrusted(certs, authType);
- }
-
- /* (non-Javadoc)
- * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
- */
- public X509Certificate[] getAcceptedIssuers() {
- return adapteeTrustManager.getAcceptedIssuers();
- }
- }
-}
diff --git a/src/main/java/com/sun/mail/util/MessageRemovedIOException.java b/src/main/java/com/sun/mail/util/MessageRemovedIOException.java
deleted file mode 100644
index c4e65199..00000000
--- a/src/main/java/com/sun/mail/util/MessageRemovedIOException.java
+++ /dev/null
@@ -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.util;
-
-import java.io.IOException;
-
-/**
- * A variant of MessageRemovedException that can be thrown from methods
- * that only throw IOException. The getContent method will catch this
- * exception and translate it back to MessageRemovedException.
- *
- * @see javax.mail.Message#isExpunged()
- * @see javax.mail.Message#getMessageNumber()
- * @author Bill Shannon
- */
-
-public class MessageRemovedIOException extends IOException {
-
- private static final long serialVersionUID = 4280468026581616424L;
-
- /**
- * Constructs a MessageRemovedIOException with no detail message.
- */
- public MessageRemovedIOException() {
- super();
- }
-
- /**
- * Constructs a MessageRemovedIOException with the specified detail message.
- * @param s the detail message
- */
- public MessageRemovedIOException(String s) {
- super(s);
- }
-}
diff --git a/src/main/java/com/sun/mail/util/MimeUtil.java b/src/main/java/com/sun/mail/util/MimeUtil.java
deleted file mode 100644
index f3252210..00000000
--- a/src/main/java/com/sun/mail/util/MimeUtil.java
+++ /dev/null
@@ -1,123 +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.util;
-
-import java.lang.reflect.*;
-import java.security.*;
-
-import javax.mail.internet.MimePart;
-
-/**
- * General MIME-related utility methods.
- *
- * @author Bill Shannon
- * @since JavaMail 1.4.4
- */
-public class MimeUtil {
-
- private static final Method cleanContentType;
-
- static {
- Method meth = null;
- try {
- String cth = System.getProperty("mail.mime.contenttypehandler");
- if (cth != null) {
- ClassLoader cl = getContextClassLoader();
- Class clsHandler = null;
- if (cl != null) {
- try {
- clsHandler = Class.forName(cth, false, cl);
- } catch (ClassNotFoundException cex) { }
- }
- if (clsHandler == null)
- clsHandler = Class.forName(cth);
- meth = clsHandler.getMethod("cleanContentType",
- new Class[] { MimePart.class, String.class });
- }
- } catch (ClassNotFoundException ex) {
- // ignore it
- } catch (NoSuchMethodException ex) {
- // ignore it
- } catch (RuntimeException ex) {
- // ignore it
- } finally {
- cleanContentType = meth;
- }
- }
-
- // No one should instantiate this class.
- private MimeUtil() {
- }
-
- /**
- * If a Content-Type handler has been specified,
- * call it to clean up the Content-Type value.
- */
- public static String cleanContentType(MimePart mp, String contentType) {
- if (cleanContentType != null) {
- try {
- return (String)cleanContentType.invoke(null,
- new Object[] { mp, contentType });
- } catch (Exception ex) {
- return contentType;
- }
- } else
- return contentType;
- }
-
- /**
- * Convenience method to get our context class loader.
- * Assert any privileges we might have and then call the
- * Thread.getContextClassLoader method.
- */
- private static ClassLoader getContextClassLoader() {
- return (ClassLoader)
- AccessController.doPrivileged(new PrivilegedAction() {
- public Object run() {
- ClassLoader cl = null;
- try {
- cl = Thread.currentThread().getContextClassLoader();
- } catch (SecurityException ex) { }
- return cl;
- }
- });
- }
-}
diff --git a/src/main/java/com/sun/mail/util/PropUtil.java b/src/main/java/com/sun/mail/util/PropUtil.java
deleted file mode 100644
index ec1e1c4d..00000000
--- a/src/main/java/com/sun/mail/util/PropUtil.java
+++ /dev/null
@@ -1,167 +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.util;
-
-import java.util.*;
-import javax.mail.Session;
-
-/**
- * Utilities to make it easier to get property values.
- * Properties can be strings or type-specific value objects.
- *
- * @author Bill Shannon
- */
-public class PropUtil {
-
- // No one should instantiate this class.
- private PropUtil() {
- }
-
- /**
- * Get an integer valued property.
- */
- public static int getIntProperty(Properties props, String name, int def) {
- return getInt(getProp(props, name), def);
- }
-
- /**
- * Get a boolean valued property.
- */
- public static boolean getBooleanProperty(Properties props,
- String name, boolean def) {
- return getBoolean(getProp(props, name), def);
- }
-
- /**
- * Get an integer valued property.
- */
- public static int getIntSessionProperty(Session session,
- String name, int def) {
- return getInt(getProp(session.getProperties(), name), def);
- }
-
- /**
- * Get a boolean valued property.
- */
- public static boolean getBooleanSessionProperty(Session session,
- String name, boolean def) {
- return getBoolean(getProp(session.getProperties(), name), def);
- }
-
- /**
- * Get a boolean valued System property.
- */
- public static boolean getBooleanSystemProperty(String name, boolean def) {
- try {
- return getBoolean(getProp(System.getProperties(), name), def);
- } catch (SecurityException sex) {
- // fall through...
- }
-
- /*
- * If we can't get the entire System Properties object because
- * of a SecurityException, just ask for the specific property.
- */
- try {
- String value = System.getProperty(name);
- if (value == null)
- return def;
- if (def)
- return !value.equalsIgnoreCase("false");
- else
- return value.equalsIgnoreCase("true");
- } catch (SecurityException sex) {
- return def;
- }
- }
-
- /**
- * Get the value of the specified property.
- * If the "get" method returns null, use the getProperty method,
- * which might cascade to a default Properties object.
- */
- private static Object getProp(Properties props, String name) {
- Object val = props.get(name);
- if (val != null)
- return val;
- else
- return props.getProperty(name);
- }
-
- /**
- * Interpret the value object as an integer,
- * returning def if unable.
- */
- private static int getInt(Object value, int def) {
- if (value == null)
- return def;
- if (value instanceof String) {
- try {
- return Integer.parseInt((String)value);
- } catch (NumberFormatException nfex) { }
- }
- if (value instanceof Integer)
- return ((Integer)value).intValue();
- return def;
- }
-
- /**
- * Interpret the value object as a boolean,
- * returning def if unable.
- */
- private static boolean getBoolean(Object value, boolean def) {
- if (value == null)
- return def;
- if (value instanceof String) {
- /*
- * If the default is true, only "false" turns it off.
- * If the default is false, only "true" turns it on.
- */
- if (def)
- return !((String)value).equalsIgnoreCase("false");
- else
- return ((String)value).equalsIgnoreCase("true");
- }
- if (value instanceof Boolean)
- return ((Boolean)value).booleanValue();
- return def;
- }
-}
diff --git a/src/main/java/com/sun/mail/util/QDecoderStream.java b/src/main/java/com/sun/mail/util/QDecoderStream.java
deleted file mode 100644
index a0654d95..00000000
--- a/src/main/java/com/sun/mail/util/QDecoderStream.java
+++ /dev/null
@@ -1,93 +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.util;
-
-import java.io.*;
-
-/**
- * This class implements a Q Decoder as defined in RFC 2047
- * for decoding MIME headers. It subclasses the QPDecoderStream class.
- *
- * @author John Mani
- */
-
-public class QDecoderStream extends QPDecoderStream {
-
- /**
- * Create a Q-decoder that decodes the specified input stream.
- * @param in the input stream
- */
- public QDecoderStream(InputStream in) {
- super(in);
- }
-
- /**
- * Read the next decoded byte from this input stream. The byte
- * is returned as an int in the range 0
- * to 255. If no byte is available because the end of
- * the stream has been reached, the value -1 is returned.
- * This method blocks until input data is available, the end of the
- * stream is detected, or an exception is thrown.
- *
- * @return the next byte of data, or -1 if the end of the
- * stream is reached.
- * @exception IOException if an I/O error occurs.
- */
- public int read() throws IOException {
- int c = in.read();
-
- if (c == '_') // Return '_' as ' '
- return ' ';
- else if (c == '=') {
- // QP Encoded atom. Get the next two bytes ..
- ba[0] = (byte)in.read();
- ba[1] = (byte)in.read();
- // .. and decode them
- try {
- return ASCIIUtility.parseInt(ba, 0, 2, 16);
- } catch (NumberFormatException nex) {
- throw new DecodingException(
- "QDecoder: Error in QP stream " + nex.getMessage());
- }
- } else
- return c;
- }
-}
diff --git a/src/main/java/com/sun/mail/util/QEncoderStream.java b/src/main/java/com/sun/mail/util/QEncoderStream.java
deleted file mode 100644
index ec5744f4..00000000
--- a/src/main/java/com/sun/mail/util/QEncoderStream.java
+++ /dev/null
@@ -1,119 +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.util;
-
-import java.io.*;
-
-/**
- * This class implements a Q Encoder as defined by RFC 2047 for
- * encoding MIME headers. It subclasses the QPEncoderStream class.
- *
- * @author John Mani
- */
-
-public class QEncoderStream extends QPEncoderStream {
-
- private String specials;
- private static String WORD_SPECIALS = "=_?\"#$%&'(),.:;<>@[\\]^`{|}~";
- private static String TEXT_SPECIALS = "=_?";
-
- /**
- * Create a Q encoder that encodes the specified input stream
- * @param out the output stream
- * @param encodingWord true if we are Q-encoding a word within a
- * phrase.
- */
- public QEncoderStream(OutputStream out, boolean encodingWord) {
- super(out, Integer.MAX_VALUE); // MAX_VALUE is 2^31, should
- // suffice (!) to indicate that
- // CRLFs should not be inserted
- // when encoding rfc822 headers
-
- // a RFC822 "word" token has more restrictions than a
- // RFC822 "text" token.
- specials = encodingWord ? WORD_SPECIALS : TEXT_SPECIALS;
- }
-
- /**
- * Encodes the specified byte to this output stream.
- * @param c the byte.
- * @exception IOException if an I/O error occurs.
- */
- public void write(int c) throws IOException {
- c = c & 0xff; // Turn off the MSB.
- if (c == ' ')
- output('_', false);
- else if (c < 040 || c >= 0177 || specials.indexOf(c) >= 0)
- // Encoding required.
- output(c, true);
- else // No encoding required
- output(c, false);
- }
-
- /**
- * Returns the length of the encoded version of this byte array.
- */
- public static int encodedLength(byte[] b, boolean encodingWord) {
- int len = 0;
- String specials = encodingWord ? WORD_SPECIALS: TEXT_SPECIALS;
- for (int i = 0; i < b.length; i++) {
- int c = b[i] & 0xff; // Mask off MSB
- if (c < 040 || c >= 0177 || specials.indexOf(c) >= 0)
- // needs encoding
- len += 3; // Q-encoding is 1 -> 3 conversion
- else
- len++;
- }
- return len;
- }
-
- /**** begin TEST program ***
- public static void main(String argv[]) throws Exception {
- FileInputStream infile = new FileInputStream(argv[0]);
- QEncoderStream encoder = new QEncoderStream(System.out);
- int c;
-
- while ((c = infile.read()) != -1)
- encoder.write(c);
- encoder.close();
- }
- *** end TEST program ***/
-}
diff --git a/src/main/java/com/sun/mail/util/QPDecoderStream.java b/src/main/java/com/sun/mail/util/QPDecoderStream.java
deleted file mode 100644
index 8760cd67..00000000
--- a/src/main/java/com/sun/mail/util/QPDecoderStream.java
+++ /dev/null
@@ -1,217 +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.util;
-
-import java.io.*;
-
-/**
- * This class implements a QP Decoder. It is implemented as
- * a FilterInputStream, so one can just wrap this class around
- * any input stream and read bytes from this filter. The decoding
- * is done as the bytes are read out.
- *
- * @author John Mani
- */
-
-public class QPDecoderStream extends FilterInputStream {
- protected byte[] ba = new byte[2];
- protected int spaces = 0;
-
- /**
- * Create a Quoted Printable decoder that decodes the specified
- * input stream.
- * @param in the input stream
- */
- public QPDecoderStream(InputStream in) {
- super(new PushbackInputStream(in, 2)); // pushback of size=2
- }
-
- /**
- * Read the next decoded byte from this input stream. The byte
- * is returned as an int in the range 0
- * to 255. If no byte is available because the end of
- * the stream has been reached, the value -1 is returned.
- * This method blocks until input data is available, the end of the
- * stream is detected, or an exception is thrown.
- *
- * @return the next byte of data, or -1 if the end of the
- * stream is reached.
- * @exception IOException if an I/O error occurs.
- */
- public int read() throws IOException {
- if (spaces > 0) {
- // We have cached space characters, return one
- spaces--;
- return ' ';
- }
-
- int c = in.read();
-
- if (c == ' ') {
- // Got space, keep reading till we get a non-space char
- while ((c = in.read()) == ' ')
- spaces++;
-
- if (c == '\r' || c == '\n' || c == -1)
- // If the non-space char is CR/LF/EOF, the spaces we got
- // so far is junk introduced during transport. Junk 'em.
- spaces = 0;
- else {
- // The non-space char is NOT CR/LF, the spaces are valid.
- ((PushbackInputStream)in).unread(c);
- c = ' ';
- }
- return c; // return either or
- }
- else if (c == '=') {
- // QP Encoded atom. Decode the next two bytes
- int a = in.read();
-
- if (a == '\n') {
- /* Hmm ... not really confirming QP encoding, but lets
- * allow this as a LF terminated encoded line .. and
- * consider this a soft linebreak and recurse to fetch
- * the next char.
- */
- return read();
- } else if (a == '\r') {
- // Expecting LF. This forms a soft linebreak to be ignored.
- int b = in.read();
- if (b != '\n')
- /* Not really confirming QP encoding, but
- * lets allow this as well.
- */
- ((PushbackInputStream)in).unread(b);
- return read();
- } else if (a == -1) {
- // Not valid QP encoding, but we be nice and tolerant here !
- return -1;
- } else {
- ba[0] = (byte)a;
- ba[1] = (byte)in.read();
- try {
- return ASCIIUtility.parseInt(ba, 0, 2, 16);
- } catch (NumberFormatException nex) {
- /*
- System.err.println(
- "Illegal characters in QP encoded stream: " +
- ASCIIUtility.toString(ba, 0, 2)
- );
- */
-
- ((PushbackInputStream)in).unread(ba);
- return c;
- }
- }
- }
- return c;
- }
-
- /**
- * Reads up to len decoded bytes of data from this input stream
- * into an array of bytes. This method blocks until some input is
- * available.
- *
- *
- * @param buf the buffer into which the data is read.
- * @param off the start offset of the data.
- * @param len the maximum number of bytes read.
- * @return the total number of bytes read into the buffer, or
- * -1 if there is no more data because the end of
- * the stream has been reached.
- * @exception IOException if an I/O error occurs.
- */
- public int read(byte[] buf, int off, int len) throws IOException {
- int i, c;
- for (i = 0; i < len; i++) {
- if ((c = read()) == -1) {
- if (i == 0) // At end of stream, so we should
- i = -1; // return -1 , NOT 0.
- break;
- }
- buf[off+i] = (byte)c;
- }
- return i;
- }
-
- /**
- * Skips over and discards n bytes of data from this stream.
- */
- public long skip(long n) throws IOException {
- long skipped = 0;
- while (n-- > 0 && read() >= 0)
- skipped++;
- return skipped;
- }
-
- /**
- * Tests if this input stream supports marks. Currently this class
- * does not support marks
- */
- public boolean markSupported() {
- return false;
- }
-
- /**
- * Returns the number of bytes that can be read from this input
- * stream without blocking. The QP algorithm does not permit
- * a priori knowledge of the number of bytes after decoding, so
- * this method just invokes the available method
- * of the original input stream.
- */
- public int available() throws IOException {
- // This is bogus ! We don't really know how much
- // bytes are available *after* decoding
- return in.available();
- }
-
- /**** begin TEST program
- public static void main(String argv[]) throws Exception {
- FileInputStream infile = new FileInputStream(argv[0]);
- QPDecoderStream decoder = new QPDecoderStream(infile);
- int c;
-
- while ((c = decoder.read()) != -1)
- System.out.print((char)c);
- System.out.println();
- }
- *** end TEST program ****/
-}
diff --git a/src/main/java/com/sun/mail/util/QPEncoderStream.java b/src/main/java/com/sun/mail/util/QPEncoderStream.java
deleted file mode 100644
index 03776f46..00000000
--- a/src/main/java/com/sun/mail/util/QPEncoderStream.java
+++ /dev/null
@@ -1,212 +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.util;
-
-import java.io.*;
-
-/**
- * This class implements a Quoted Printable Encoder. It is implemented as
- * a FilterOutputStream, so one can just wrap this class around
- * any output stream and write bytes into this filter. The Encoding
- * is done as the bytes are written out.
- *
- * @author John Mani
- */
-
-public class QPEncoderStream extends FilterOutputStream {
- private int count = 0; // number of bytes that have been output
- private int bytesPerLine; // number of bytes per line
- private boolean gotSpace = false;
- private boolean gotCR = false;
-
- /**
- * Create a QP encoder that encodes the specified input stream
- * @param out the output stream
- * @param bytesPerLine the number of bytes per line. The encoder
- * inserts a CRLF sequence after this many number
- * of bytes.
- */
- public QPEncoderStream(OutputStream out, int bytesPerLine) {
- super(out);
- // Subtract 1 to account for the '=' in the soft-return
- // at the end of a line
- this.bytesPerLine = bytesPerLine - 1;
- }
-
- /**
- * Create a QP encoder that encodes the specified input stream.
- * Inserts the CRLF sequence after outputting 76 bytes.
- * @param out the output stream
- */
- public QPEncoderStream(OutputStream out) {
- this(out, 76);
- }
-
- /**
- * Encodes len bytes from the specified
- * byte array starting at offset off to
- * this output stream.
- *
- * @param b the data.
- * @param off the start offset in the data.
- * @param len the number of bytes to write.
- * @exception IOException if an I/O error occurs.
- */
- public void write(byte[] b, int off, int len) throws IOException {
- for (int i = 0; i < len; i++)
- write(b[off + i]);
- }
-
- /**
- * Encodes b.length bytes to this output stream.
- * @param b the data to be written.
- * @exception IOException if an I/O error occurs.
- */
- public void write(byte[] b) throws IOException {
- write(b, 0, b.length);
- }
-
- /**
- * Encodes the specified byte to this output stream.
- * @param c the byte.
- * @exception IOException if an I/O error occurs.
- */
- public void write(int c) throws IOException {
- c = c & 0xff; // Turn off the MSB.
- if (gotSpace) { // previous character was
- if (c == '\r' || c == '\n')
- // if CR/LF, we need to encode the char
- output(' ', true);
- else // no encoding required, just output the char
- output(' ', false);
- gotSpace = false;
- }
-
- if (c == '\r') {
- gotCR = true;
- outputCRLF();
- } else {
- if (c == '\n') {
- if (gotCR)
- // This is a CRLF sequence, we already output the
- // corresponding CRLF when we got the CR, so ignore this
- ;
- else
- outputCRLF();
- } else if (c == ' ') {
- gotSpace = true;
- } else if (c < 040 || c >= 0177 || c == '=')
- // Encoding required.
- output(c, true);
- else // No encoding required
- output(c, false);
- // whatever it was, it wasn't a CR
- gotCR = false;
- }
- }
-
- /**
- * Flushes this output stream and forces any buffered output bytes
- * to be encoded out to the stream.
- * @exception IOException if an I/O error occurs.
- */
- public void flush() throws IOException {
- out.flush();
- }
-
- /**
- * Forces any buffered output bytes to be encoded out to the stream
- * and closes this output stream
- */
- public void close() throws IOException {
- if (gotSpace) {
- output(' ', true);
- gotSpace = false;
- }
- out.close();
- }
-
- private void outputCRLF() throws IOException {
- out.write('\r');
- out.write('\n');
- count = 0;
- }
-
- // The encoding table
- private final static char hex[] = {
- '0','1', '2', '3', '4', '5', '6', '7',
- '8','9', 'A', 'B', 'C', 'D', 'E', 'F'
- };
-
- protected void output(int c, boolean encode) throws IOException {
- if (encode) {
- if ((count += 3) > bytesPerLine) {
- out.write('=');
- out.write('\r');
- out.write('\n');
- count = 3; // set the next line's length
- }
- out.write('=');
- out.write(hex[c >> 4]);
- out.write(hex[c & 0xf]);
- } else {
- if (++count > bytesPerLine) {
- out.write('=');
- out.write('\r');
- out.write('\n');
- count = 1; // set the next line's length
- }
- out.write(c);
- }
- }
-
- /**** begin TEST program ***
- public static void main(String argv[]) throws Exception {
- FileInputStream infile = new FileInputStream(argv[0]);
- QPEncoderStream encoder = new QPEncoderStream(System.out);
- int c;
-
- while ((c = infile.read()) != -1)
- encoder.write(c);
- encoder.close();
- }
- *** end TEST program ***/
-}
diff --git a/src/main/java/com/sun/mail/util/ReadableMime.java b/src/main/java/com/sun/mail/util/ReadableMime.java
deleted file mode 100644
index aab3497f..00000000
--- a/src/main/java/com/sun/mail/util/ReadableMime.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 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.util;
-
-import java.io.InputStream;
-
-import javax.mail.MessagingException;
-
-/**
- * A Message or message Part whose data can be read as a MIME format
- * stream. Note that the MIME stream will include both the headers
- * and the body of the message or part. This should be the same data
- * that is produced by the writeTo method, but in a readable form.
- *
- * @author Bill Shannon
- * @since JavaMail 1.4.5
- */
-public interface ReadableMime {
- /**
- * Return the MIME format stream corresponding to this message part.
- *
- * @return the MIME format stream
- */
- public InputStream getMimeStream() throws MessagingException;
-}
diff --git a/src/main/java/com/sun/mail/util/SharedByteArrayOutputStream.java b/src/main/java/com/sun/mail/util/SharedByteArrayOutputStream.java
deleted file mode 100644
index 521b126e..00000000
--- a/src/main/java/com/sun/mail/util/SharedByteArrayOutputStream.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 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.util;
-
-import java.io.InputStream;
-import java.io.ByteArrayOutputStream;
-
-import javax.mail.util.SharedByteArrayInputStream;
-
-/**
- * A ByteArrayOutputStream that allows us to share the byte array
- * rather than copy it. Eventually could replace this with something
- * that doesn't require a single contiguous byte array.
- *
- * @author Bill Shannon
- * @since JavaMail 1.4.5
- */
-public class SharedByteArrayOutputStream extends ByteArrayOutputStream {
- public SharedByteArrayOutputStream(int size) {
- super(size);
- }
-
- public InputStream toStream() {
- return new SharedByteArrayInputStream(buf, 0, count);
- }
-}
diff --git a/src/main/java/com/sun/mail/util/SocketConnectException.java b/src/main/java/com/sun/mail/util/SocketConnectException.java
deleted file mode 100644
index 6546badd..00000000
--- a/src/main/java/com/sun/mail/util/SocketConnectException.java
+++ /dev/null
@@ -1,117 +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.util;
-
-import java.io.IOException;
-
-/**
- * An IOException that indicates a socket connection attempt failed.
- * Unlike java.net.ConnectException, it includes details of what we
- * were trying to connect to.
- *
- * @see java.net.ConnectException
- * @author Bill Shannon
- * @since JavaMail 1.5.0
- */
-
-public class SocketConnectException extends IOException {
- private String host;
- private int port;
- private int cto;
-
- private static final long serialVersionUID = 3997871560538755463L;
-
- /**
- * Constructs a SocketConnectException.
- *
- * @param msg error message detail
- * @param cause the underlying exception that indicates the failure
- * @param host the host we were trying to connect to
- * @param port the port we were trying to connect to
- * @param cto the timeout for the connection attempt
- */
- public SocketConnectException(String msg, Exception cause,
- String host, int port, int cto) {
- super(msg);
- initCause(cause);
- this.host = host;
- this.port = port;
- this.cto = cto;
- }
-
- /**
- * The exception that caused the failure.
- *
- * @return the exception
- */
- public Exception getException() {
- // the "cause" is always an Exception; see constructor above
- assert getCause() instanceof Exception;
- return (Exception)getCause();
- }
-
- /**
- * The host we were trying to connect to.
- *
- * @return the host
- */
- public String getHost() {
- return host;
- }
-
- /**
- * The port we were trying to connect to.
- *
- * @return the port
- */
- public int getPort() {
- return port;
- }
-
- /**
- * The timeout used for the connection attempt.
- *
- * @return the connection timeout
- */
- public int getConnectionTimeout() {
- return cto;
- }
-}
diff --git a/src/main/java/com/sun/mail/util/SocketFetcher.java b/src/main/java/com/sun/mail/util/SocketFetcher.java
deleted file mode 100644
index 6cbfd00a..00000000
--- a/src/main/java/com/sun/mail/util/SocketFetcher.java
+++ /dev/null
@@ -1,722 +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.util;
-
-import java.security.*;
-import java.net.*;
-import java.io.*;
-import java.lang.reflect.*;
-import java.util.*;
-import java.util.regex.*;
-import java.util.logging.Level;
-import java.security.cert.*;
-import javax.net.*;
-import javax.net.ssl.*;
-import javax.security.auth.x500.X500Principal;
-
-/**
- * This class is used to get Sockets. Depending on the arguments passed
- * it will either return a plain java.net.Socket or dynamically load
- * the SocketFactory class specified in the classname param and return
- * a socket created by that SocketFactory.
- *
- * @author Max Spivak
- * @author Bill Shannon
- */
-public class SocketFetcher {
-
- private static MailLogger logger = new MailLogger(
- SocketFetcher.class,
- "socket",
- "DEBUG SocketFetcher",
- PropUtil.getBooleanSystemProperty("mail.socket.debug", false),
- System.out);
-
- // No one should instantiate this class.
- private SocketFetcher() {
- }
-
- /**
- * This method returns a Socket. Properties control the use of
- * socket factories and other socket characteristics. The properties
- * used are:
- *
- *
prefix.socketFactory
- *
prefix.socketFactory.class
- *
prefix.socketFactory.fallback
- *
prefix.socketFactory.port
- *
prefix.ssl.socketFactory
- *
prefix.ssl.socketFactory.class
- *
prefix.ssl.socketFactory.port
- *
prefix.timeout
- *
prefix.connectiontimeout
- *
prefix.localaddress
- *
prefix.localport
- *
- * If we're making an SSL connection, the ssl.socketFactory
- * properties are used first, if set.
- *
- * If the socketFactory property is set, the value is an
- * instance of a SocketFactory class, not a string. The
- * instance is used directly. If the socketFactory property
- * is not set, the socketFactory.class property is considered.
- * (Note that the SocketFactory property must be set using the
- * put method, not the setProperty
- * method.)
- *
- * If the socketFactory.class property isn't set, the socket
- * returned is an instance of java.net.Socket connected to the
- * given host and port. If the socketFactory.class property is set,
- * it is expected to contain a fully qualified classname of a
- * javax.net.SocketFactory subclass. In this case, the class is
- * dynamically instantiated and a socket created by that
- * SocketFactory is returned.
- *
- * If the socketFactory.fallback property is set to false, don't
- * fall back to using regular sockets if the socket factory fails.
- *
- * The socketFactory.port specifies a port to use when connecting
- * through the socket factory. If unset, the port argument will be
- * used.
- *
- * If the connectiontimeout property is set, the timeout is passed
- * to the socket connect method.
- *
- * If the timeout property is set, it is used to set the socket timeout.
- *
- *
- * If the localaddress property is set, it's used as the local address
- * to bind to. If the localport property is also set, it's used as the
- * local port number to bind to.
- *
- * @param host The host to connect to
- * @param port The port to connect to at the host
- * @param props Properties object containing socket properties
- * @param prefix Property name prefix, e.g., "mail.imap"
- * @param useSSL use the SSL socket factory as the default
- */
- public static Socket getSocket(String host, int port, Properties props,
- String prefix, boolean useSSL)
- throws IOException {
-
- if (logger.isLoggable(Level.FINER))
- logger.finer("getSocket" + ", host " + host + ", port " + port +
- ", prefix " + prefix + ", useSSL " + useSSL);
- if (prefix == null)
- prefix = "socket";
- if (props == null)
- props = new Properties(); // empty
- int cto = PropUtil.getIntProperty(props,
- prefix + ".connectiontimeout", -1);
- Socket socket = null;
- String localaddrstr = props.getProperty(prefix + ".localaddress", null);
- InetAddress localaddr = null;
- if (localaddrstr != null)
- localaddr = InetAddress.getByName(localaddrstr);
- int localport = PropUtil.getIntProperty(props,
- prefix + ".localport", 0);
-
- boolean fb = PropUtil.getBooleanProperty(props,
- prefix + ".socketFactory.fallback", true);
-
- int sfPort = -1;
- String sfErr = "unknown socket factory";
- int to = PropUtil.getIntProperty(props, prefix + ".timeout", -1);
- try {
- /*
- * If using SSL, first look for SSL-specific class name or
- * factory instance.
- */
- SocketFactory sf = null;
- String sfPortName = null;
- if (useSSL) {
- Object sfo = props.get(prefix + ".ssl.socketFactory");
- if (sfo instanceof SocketFactory) {
- sf = (SocketFactory)sfo;
- sfErr = "SSL socket factory instance " + sf;
- }
- if (sf == null) {
- String sfClass =
- props.getProperty(prefix + ".ssl.socketFactory.class");
- sf = getSocketFactory(sfClass);
- sfErr = "SSL socket factory class " + sfClass;
- }
- sfPortName = ".ssl.socketFactory.port";
- }
-
- if (sf == null) {
- Object sfo = props.get(prefix + ".socketFactory");
- if (sfo instanceof SocketFactory) {
- sf = (SocketFactory)sfo;
- sfErr = "socket factory instance " + sf;
- }
- if (sf == null) {
- String sfClass =
- props.getProperty(prefix + ".socketFactory.class");
- sf = getSocketFactory(sfClass);
- sfErr = "socket factory class " + sfClass;
- }
- sfPortName = ".socketFactory.port";
- }
-
- // if we now have a socket factory, use it
- if (sf != null) {
- sfPort = PropUtil.getIntProperty(props,
- prefix + sfPortName, -1);
-
- // if port passed in via property isn't valid, use param
- if (sfPort == -1)
- sfPort = port;
- socket = createSocket(localaddr, localport,
- host, sfPort, cto, to, props, prefix, sf, useSSL);
- }
- } catch (SocketTimeoutException sex) {
- throw sex;
- } catch (Exception ex) {
- if (!fb) {
- if (ex instanceof InvocationTargetException) {
- Throwable t =
- ((InvocationTargetException)ex).getTargetException();
- if (t instanceof Exception)
- ex = (Exception)t;
- }
- if (ex instanceof IOException)
- throw (IOException)ex;
- throw new SocketConnectException("Using " + sfErr, ex,
- host, sfPort, cto);
- }
- }
-
- if (socket == null) {
- socket = createSocket(localaddr, localport,
- host, port, cto, to, props, prefix, null, useSSL);
-
- } else {
- if (to >= 0)
- socket.setSoTimeout(to);
- }
-
- return socket;
- }
-
- public static Socket getSocket(String host, int port, Properties props,
- String prefix) throws IOException {
- return getSocket(host, port, props, prefix, false);
- }
-
- /**
- * Create a socket with the given local address and connected to
- * the given host and port. Use the specified connection timeout
- * and read timeout.
- * If a socket factory is specified, use it. Otherwise, use the
- * SSLSocketFactory if useSSL is true.
- */
- private static Socket createSocket(InetAddress localaddr, int localport,
- String host, int port, int cto, int to,
- Properties props, String prefix,
- SocketFactory sf, boolean useSSL)
- throws IOException {
- Socket socket = null;
-
- String socksHost = props.getProperty(prefix + ".socks.host", null);
- int socksPort = 1080;
- String err = null;
- if (socksHost != null) {
- int i = socksHost.indexOf(':');
- if (i >= 0) {
- socksHost = socksHost.substring(0, i);
- try {
- socksPort = Integer.parseInt(socksHost.substring(i + 1));
- } catch (NumberFormatException ex) {
- // ignore it
- }
- }
- socksPort = PropUtil.getIntProperty(props,
- prefix + ".socks.port", socksPort);
- err = "Using SOCKS host, port: " + socksHost + ", " + socksPort;
- if (logger.isLoggable(Level.FINER))
- logger.finer("socks host " + socksHost + ", port " + socksPort);
- }
-
- if (sf != null)
- socket = sf.createSocket();
- if (socket == null) {
- if (socksHost != null)
- socket = new Socket(
- new java.net.Proxy(java.net.Proxy.Type.SOCKS,
- new InetSocketAddress(socksHost, socksPort)));
- else
- socket = new Socket();
- }
- if (to >= 0)
- socket.setSoTimeout(to);
- if (localaddr != null)
- socket.bind(new InetSocketAddress(localaddr, localport));
- try {
- if (cto >= 0)
- socket.connect(new InetSocketAddress(host, port), cto);
- else
- socket.connect(new InetSocketAddress(host, port));
- } catch (IOException ex) {
- throw new SocketConnectException(err, ex, host, port, cto);
- }
-
- /*
- * If we want an SSL connection and we didn't get an SSLSocket,
- * wrap our plain Socket with an SSLSocket.
- */
- if (useSSL && !(socket instanceof SSLSocket)) {
- String trusted;
- SSLSocketFactory ssf;
- if ((trusted = props.getProperty(prefix + ".ssl.trust")) != null) {
- try {
- MailSSLSocketFactory msf = new MailSSLSocketFactory();
- if (trusted.equals("*"))
- msf.setTrustAllHosts(true);
- else
- msf.setTrustedHosts(trusted.split("\\s+"));
- ssf = msf;
- } catch (GeneralSecurityException gex) {
- IOException ioex = new IOException(
- "Can't create MailSSLSocketFactory");
- ioex.initCause(gex);
- throw ioex;
- }
- } else
- ssf = (SSLSocketFactory)SSLSocketFactory.getDefault();
- socket = ssf.createSocket(socket, host, port, true);
- sf = ssf;
- }
-
- /*
- * No matter how we created the socket, if it turns out to be an
- * SSLSocket, configure it.
- */
- configureSSLSocket(socket, host, props, prefix, sf);
-
- return socket;
- }
-
- /**
- * Return a socket factory of the specified class.
- */
- private static SocketFactory getSocketFactory(String sfClass)
- throws ClassNotFoundException,
- NoSuchMethodException,
- IllegalAccessException,
- InvocationTargetException {
- if (sfClass == null || sfClass.length() == 0)
- return null;
-
- // dynamically load the class
-
- ClassLoader cl = getContextClassLoader();
- Class clsSockFact = null;
- if (cl != null) {
- try {
- clsSockFact = Class.forName(sfClass, false, cl);
- } catch (ClassNotFoundException cex) { }
- }
- if (clsSockFact == null)
- clsSockFact = Class.forName(sfClass);
- // get & invoke the getDefault() method
- Method mthGetDefault = clsSockFact.getMethod("getDefault",
- new Class[]{});
- SocketFactory sf = (SocketFactory)
- mthGetDefault.invoke(new Object(), new Object[]{});
- return sf;
- }
-
- /**
- * Start TLS on an existing socket.
- * Supports the "STARTTLS" command in many protocols.
- * This version for compatibility with possible third party code
- * that might've used this API even though it shouldn't.
- */
- public static Socket startTLS(Socket socket) throws IOException {
- return startTLS(socket, new Properties(), "socket");
- }
-
- /**
- * Start TLS on an existing socket.
- * Supports the "STARTTLS" command in many protocols.
- * This version for compatibility with possible third party code
- * that might've used this API even though it shouldn't.
- */
- public static Socket startTLS(Socket socket, Properties props,
- String prefix) throws IOException {
- InetAddress a = socket.getInetAddress();
- String host = a.getHostName();
- return startTLS(socket, host, props, prefix);
- }
-
- /**
- * Start TLS on an existing socket.
- * Supports the "STARTTLS" command in many protocols.
- */
- public static Socket startTLS(Socket socket, String host, Properties props,
- String prefix) throws IOException {
- int port = socket.getPort();
- if (logger.isLoggable(Level.FINER))
- logger.finer("startTLS host " + host + ", port " + port);
-
- String sfErr = "unknown socket factory";
- try {
- SSLSocketFactory ssf = null;
- SocketFactory sf = null;
-
- // first, look for an SSL socket factory
- Object sfo = props.get(prefix + ".ssl.socketFactory");
- if (sfo instanceof SocketFactory) {
- sf = (SocketFactory)sfo;
- sfErr = "SSL socket factory instance " + sf;
- }
- if (sf == null) {
- String sfClass =
- props.getProperty(prefix + ".ssl.socketFactory.class");
- sf = getSocketFactory(sfClass);
- sfErr = "SSL socket factory class " + sfClass;
- }
- if (sf != null && sf instanceof SSLSocketFactory)
- ssf = (SSLSocketFactory)sf;
-
- // next, look for a regular socket factory that happens to be
- // an SSL socket factory
- if (ssf == null) {
- sfo = props.get(prefix + ".socketFactory");
- if (sfo instanceof SocketFactory) {
- sf = (SocketFactory)sfo;
- sfErr = "socket factory instance " + sf;
- }
- if (sf == null) {
- String sfClass =
- props.getProperty(prefix + ".socketFactory.class");
- sf = getSocketFactory(sfClass);
- sfErr = "socket factory class " + sfClass;
- }
- if (sf != null && sf instanceof SSLSocketFactory)
- ssf = (SSLSocketFactory)sf;
- }
-
- // finally, use the default SSL socket factory
- if (ssf == null) {
- String trusted;
- if ((trusted = props.getProperty(prefix + ".ssl.trust")) !=
- null) {
- try {
- MailSSLSocketFactory msf = new MailSSLSocketFactory();
- if (trusted.equals("*"))
- msf.setTrustAllHosts(true);
- else
- msf.setTrustedHosts(trusted.split("\\s+"));
- ssf = msf;
- sfErr = "mail SSL socket factory";
- } catch (GeneralSecurityException gex) {
- IOException ioex = new IOException(
- "Can't create MailSSLSocketFactory");
- ioex.initCause(gex);
- throw ioex;
- }
- } else {
- ssf = (SSLSocketFactory)SSLSocketFactory.getDefault();
- sfErr = "default SSL socket factory";
- }
- }
-
- socket = ssf.createSocket(socket, host, port, true);
- configureSSLSocket(socket, host, props, prefix, ssf);
- } catch (Exception ex) {
- if (ex instanceof InvocationTargetException) {
- Throwable t =
- ((InvocationTargetException)ex).getTargetException();
- if (t instanceof Exception)
- ex = (Exception)t;
- }
- if (ex instanceof IOException)
- throw (IOException)ex;
- // wrap anything else before sending it on
- IOException ioex = new IOException(
- "Exception in startTLS using " + sfErr +
- ": host, port: " +
- host + ", " + port +
- "; Exception: " + ex);
- ioex.initCause(ex);
- throw ioex;
- }
- return socket;
- }
-
- /**
- * Configure the SSL options for the socket (if it's an SSL socket),
- * based on the mail..ssl.protocols and
- * mail..ssl.ciphersuites properties.
- * Check the identity of the server as specified by the
- * mail..ssl.checkserveridentity property.
- */
- private static void configureSSLSocket(Socket socket, String host,
- Properties props, String prefix, SocketFactory sf)
- throws IOException {
- if (!(socket instanceof SSLSocket))
- return;
- SSLSocket sslsocket = (SSLSocket)socket;
-
- String protocols = props.getProperty(prefix + ".ssl.protocols", null);
- if (protocols != null)
- sslsocket.setEnabledProtocols(stringArray(protocols));
- else {
- /*
- * At least the UW IMAP server insists on only the TLSv1
- * protocol for STARTTLS, and won't accept the old SSLv2
- * or SSLv3 protocols. Here we enable only the TLSv1
- * protocol. XXX - this should probably be parameterized.
- */
- sslsocket.setEnabledProtocols(new String[] {"TLSv1"});
- }
- String ciphers = props.getProperty(prefix + ".ssl.ciphersuites", null);
- if (ciphers != null)
- sslsocket.setEnabledCipherSuites(stringArray(ciphers));
- if (logger.isLoggable(Level.FINER)) {
- logger.finer("SSL protocols after " +
- Arrays.asList(sslsocket.getEnabledProtocols()));
- logger.finer("SSL ciphers after " +
- Arrays.asList(sslsocket.getEnabledCipherSuites()));
- }
-
- /*
- * Force the handshake to be done now so that we can report any
- * errors (e.g., certificate errors) to the caller of the startTLS
- * method.
- */
- sslsocket.startHandshake();
-
- /*
- * Check server identity and trust.
- */
- boolean idCheck = PropUtil.getBooleanProperty(props,
- prefix + ".ssl.checkserveridentity", false);
- if (idCheck)
- checkServerIdentity(host, sslsocket);
- if (sf instanceof MailSSLSocketFactory) {
- MailSSLSocketFactory msf = (MailSSLSocketFactory)sf;
- if (!msf.isServerTrusted(host, sslsocket)) {
- try {
- sslsocket.close();
- } finally {
- throw new IOException("Server is not trusted: " + host);
- }
- }
- }
- }
-
- /**
- * Check the server from the Socket connection against the server name(s)
- * as expressed in the server certificate (RFC 2595 check).
- *
- * @param server name of the server expected
- * @param sslSocket SSLSocket connected to the server
- * @return true if the RFC 2595 check passes
- */
- private static void checkServerIdentity(String server, SSLSocket sslSocket)
- throws IOException {
-
- // Check against the server name(s) as expressed in server certificate
- try {
- java.security.cert.Certificate[] certChain =
- sslSocket.getSession().getPeerCertificates();
- if (certChain != null && certChain.length > 0 &&
- certChain[0] instanceof X509Certificate &&
- matchCert(server, (X509Certificate)certChain[0]))
- return;
- } catch (SSLPeerUnverifiedException e) {
- sslSocket.close();
- IOException ioex = new IOException(
- "Can't verify identity of server: " + server);
- ioex.initCause(e);
- throw ioex;
- }
-
- // If we get here, there is nothing to consider the server as trusted.
- sslSocket.close();
- throw new IOException("Can't verify identity of server: " + server);
- }
-
- /**
- * Do any of the names in the cert match the server name?
- *
- * @param server name of the server expected
- * @param cert X509Certificate to get the subject's name from
- * @return true if it matches
- */
- private static boolean matchCert(String server, X509Certificate cert) {
- if (logger.isLoggable(Level.FINER))
- logger.finer("matchCert server " +
- server + ", cert " + cert);
-
- /*
- * First, try to use sun.security.util.HostnameChecker,
- * which exists in Sun's JDK starting with 1.4.1.
- * We use reflection to access it in case it's not available
- * in the JDK we're running on.
- */
- try {
- Class hnc = Class.forName("sun.security.util.HostnameChecker");
- // invoke HostnameChecker.getInstance(HostnameChecker.TYPE_LDAP)
- // HostnameChecker.TYPE_LDAP == 2
- // LDAP requires the same regex handling as we need
- Method getInstance = hnc.getMethod("getInstance",
- new Class[] { byte.class });
- Object hostnameChecker = getInstance.invoke(new Object(),
- new Object[] { new Byte((byte)2) });
-
- // invoke hostnameChecker.match( server, cert)
- if (logger.isLoggable(Level.FINER))
- logger.finer("using sun.security.util.HostnameChecker");
- Method match = hnc.getMethod("match",
- new Class[] { String.class, X509Certificate.class });
- try {
- match.invoke(hostnameChecker, new Object[] { server, cert });
- return true;
- } catch (InvocationTargetException cex) {
- logger.log(Level.FINER, "FAIL", cex);
- return false;
- }
- } catch (Exception ex) {
- logger.log(Level.FINER, "NO sun.security.util.HostnameChecker", ex);
- // ignore failure and continue below
- }
-
- /*
- * Lacking HostnameChecker, we implement a crude version of
- * the same checks ourselves.
- */
- try {
- /*
- * Check each of the subjectAltNames.
- * XXX - only checks DNS names, should also handle
- * case where server name is a literal IP address
- */
- Collection names = cert.getSubjectAlternativeNames();
- if (names != null) {
- boolean foundName = false;
- for (Iterator it = names.iterator(); it.hasNext(); ) {
- List nameEnt = (List)it.next();
- Integer type = (Integer)nameEnt.get(0);
- if (type.intValue() == 2) { // 2 == dNSName
- foundName = true;
- String name = (String)nameEnt.get(1);
- if (logger.isLoggable(Level.FINER))
- logger.finer("found name: " + name);
- if (matchServer(server, name))
- return true;
- }
- }
- if (foundName) // found a name, but no match
- return false;
- }
- } catch (CertificateParsingException ex) {
- // ignore it
- }
-
- // XXX - following is a *very* crude parse of the name and ignores
- // all sorts of important issues such as quoting
- Pattern p = Pattern.compile("CN=([^,]*)");
- Matcher m = p.matcher(cert.getSubjectX500Principal().getName());
- if (m.find() && matchServer(server, m.group(1).trim()))
- return true;
-
- return false;
- }
-
- /**
- * Does the server we're expecting to connect to match the
- * given name from the server's certificate?
- *
- * @param server name of the server expected
- * @param name name from the server's certificate
- */
- private static boolean matchServer(String server, String name) {
- if (logger.isLoggable(Level.FINER))
- logger.finer("match server " + server + " with " + name);
- if (name.startsWith("*.")) {
- // match "foo.example.com" with "*.example.com"
- String tail = name.substring(2);
- if (tail.length() == 0)
- return false;
- int off = server.length() - tail.length();
- if (off < 1)
- return false;
- // if tail matches and is preceeded by "."
- return server.charAt(off - 1) == '.' &&
- server.regionMatches(true, off, tail, 0, tail.length());
- } else
- return server.equalsIgnoreCase(name);
- }
-
- /**
- * Parse a string into whitespace separated tokens
- * and return the tokens in an array.
- */
- private static String[] stringArray(String s) {
- StringTokenizer st = new StringTokenizer(s);
- List tokens = new ArrayList();
- while (st.hasMoreTokens())
- tokens.add(st.nextToken());
- return (String[])tokens.toArray(new String[tokens.size()]);
- }
-
- /**
- * Convenience method to get our context class loader.
- * Assert any privileges we might have and then call the
- * Thread.getContextClassLoader method.
- */
- private static ClassLoader getContextClassLoader() {
- return (ClassLoader)
- AccessController.doPrivileged(new PrivilegedAction() {
- public Object run() {
- ClassLoader cl = null;
- try {
- cl = Thread.currentThread().getContextClassLoader();
- } catch (SecurityException ex) { }
- return cl;
- }
- });
- }
-}
diff --git a/src/main/java/com/sun/mail/util/TraceInputStream.java b/src/main/java/com/sun/mail/util/TraceInputStream.java
deleted file mode 100644
index 27c6754e..00000000
--- a/src/main/java/com/sun/mail/util/TraceInputStream.java
+++ /dev/null
@@ -1,162 +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.util;
-
-import java.io.*;
-import java.util.logging.Level;
-
-/**
- * This class is a FilterInputStream that writes the bytes
- * being read from the given input stream into the given output
- * stream. This class is typically used to provide a trace of
- * the data that is being retrieved from an input stream.
- *
- * @author John Mani
- */
-
-public class TraceInputStream extends FilterInputStream {
- private boolean trace = false;
- private boolean quote = false;
- private OutputStream traceOut;
-
- /**
- * Creates an input stream filter built on top of the specified
- * input stream.
- *
- * @param in the underlying input stream.
- * @param logger log trace here
- */
- public TraceInputStream(InputStream in, MailLogger logger) {
- super(in);
- this.trace = logger.isLoggable(Level.FINEST);
- this.traceOut = new LogOutputStream(logger);
- }
-
- /**
- * Creates an input stream filter built on top of the specified
- * input stream.
- *
- * @param in the underlying input stream.
- * @param traceOut the trace stream.
- */
- public TraceInputStream(InputStream in, OutputStream traceOut) {
- super(in);
- this.traceOut = traceOut;
- }
-
- /**
- * Set trace mode.
- * @param trace the trace mode
- */
- public void setTrace(boolean trace) {
- this.trace = trace;
- }
-
- /**
- * Set quote mode.
- * @param quote the quote mode
- */
- public void setQuote(boolean quote) {
- this.quote = quote;
- }
-
- /**
- * Reads the next byte of data from this input stream. Returns
- * -1 if no data is available. Writes out the read
- * byte into the trace stream, if trace mode is true
- */
- public int read() throws IOException {
- int b = in.read();
- if (trace && b != -1) {
- if (quote)
- writeByte(b);
- else
- traceOut.write(b);
- }
- return b;
- }
-
- /**
- * Reads up to len bytes of data from this input stream
- * into an array of bytes. Returns -1 if no more data
- * is available. Writes out the read bytes into the trace stream, if
- * trace mode is true
- */
- public int read(byte b[], int off, int len) throws IOException {
- int count = in.read(b, off, len);
- if (trace && count != -1) {
- if (quote) {
- for (int i = 0; i < count; i++)
- writeByte(b[off + i]);
- } else
- traceOut.write(b, off, count);
- }
- return count;
- }
-
- /**
- * Write a byte in a way that every byte value is printable ASCII.
- */
- private final void writeByte(int b) throws IOException {
- b &= 0xff;
- if (b > 0x7f) {
- traceOut.write('M');
- traceOut.write('-');
- b &= 0x7f;
- }
- if (b == '\r') {
- traceOut.write('\\');
- traceOut.write('r');
- } else if (b == '\n') {
- traceOut.write('\\');
- traceOut.write('n');
- traceOut.write('\n');
- } else if (b == '\t') {
- traceOut.write('\\');
- traceOut.write('t');
- } else if (b < ' ') {
- traceOut.write('^');
- traceOut.write('@' + b);
- } else {
- traceOut.write(b);
- }
- }
-}
diff --git a/src/main/java/com/sun/mail/util/TraceOutputStream.java b/src/main/java/com/sun/mail/util/TraceOutputStream.java
deleted file mode 100644
index b325a93a..00000000
--- a/src/main/java/com/sun/mail/util/TraceOutputStream.java
+++ /dev/null
@@ -1,158 +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.util;
-
-import java.io.*;
-import java.util.logging.Level;
-
-/**
- * This class is a subclass of DataOutputStream that copies the
- * data being written into the DataOutputStream into another output
- * stream. This class is used here to provide a debug trace of the
- * stuff thats being written out into the DataOutputStream.
- *
- * @author John Mani
- */
-
-public class TraceOutputStream extends FilterOutputStream {
- private boolean trace = false;
- private boolean quote = false;
- private OutputStream traceOut;
-
- /**
- * Creates an output stream filter built on top of the specified
- * underlying output stream.
- *
- * @param out the underlying output stream.
- * @param logger log trace here
- */
- public TraceOutputStream(OutputStream out, MailLogger logger) {
- super(out);
- this.trace = logger.isLoggable(Level.FINEST);
- this.traceOut = new LogOutputStream(logger);;
- }
-
- /**
- * Creates an output stream filter built on top of the specified
- * underlying output stream.
- *
- * @param out the underlying output stream.
- * @param traceOut the trace stream.
- */
- public TraceOutputStream(OutputStream out, OutputStream traceOut) {
- super(out);
- this.traceOut = traceOut;
- }
-
- /**
- * Set the trace mode.
- */
- public void setTrace(boolean trace) {
- this.trace = trace;
- }
-
- /**
- * Set quote mode.
- * @param quote the quote mode
- */
- public void setQuote(boolean quote) {
- this.quote = quote;
- }
-
- /**
- * Writes the specified byte to this output stream.
- * Writes out the byte into the trace stream if the trace mode
- * is true
- */
- public void write(int b) throws IOException {
- if (trace) {
- if (quote)
- writeByte(b);
- else
- traceOut.write(b);
- }
- out.write(b);
- }
-
- /**
- * Writes b.length bytes to this output stream.
- * Writes out the bytes into the trace stream if the trace
- * mode is true
- */
- public void write(byte b[], int off, int len) throws IOException {
- if (trace) {
- if (quote) {
- for (int i = 0; i < len; i++)
- writeByte(b[off + i]);
- } else
- traceOut.write(b, off, len);
- }
- out.write(b, off, len);
- }
-
- /**
- * Write a byte in a way that every byte value is printable ASCII.
- */
- private final void writeByte(int b) throws IOException {
- b &= 0xff;
- if (b > 0x7f) {
- traceOut.write('M');
- traceOut.write('-');
- b &= 0x7f;
- }
- if (b == '\r') {
- traceOut.write('\\');
- traceOut.write('r');
- } else if (b == '\n') {
- traceOut.write('\\');
- traceOut.write('n');
- traceOut.write('\n');
- } else if (b == '\t') {
- traceOut.write('\\');
- traceOut.write('t');
- } else if (b < ' ') {
- traceOut.write('^');
- traceOut.write('@' + b);
- } else {
- traceOut.write(b);
- }
- }
-}
diff --git a/src/main/java/com/sun/mail/util/UUDecoderStream.java b/src/main/java/com/sun/mail/util/UUDecoderStream.java
deleted file mode 100644
index 0f25ab68..00000000
--- a/src/main/java/com/sun/mail/util/UUDecoderStream.java
+++ /dev/null
@@ -1,354 +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.util;
-
-import java.io.*;
-
-/**
- * This class implements a UUDecoder. It is implemented as
- * a FilterInputStream, so one can just wrap this class around
- * any input stream and read bytes from this filter. The decoding
- * is done as the bytes are read out.
- *
- * @author John Mani
- * @author Bill Shannon
- */
-
-public class UUDecoderStream extends FilterInputStream {
- private String name;
- private int mode;
-
- private byte[] buffer = new byte[45]; // max decoded chars in a line = 45
- private int bufsize = 0; // size of the cache
- private int index = 0; // index into the cache
- private boolean gotPrefix = false;
- private boolean gotEnd = false;
- private LineInputStream lin;
- private boolean ignoreErrors;
- private boolean ignoreMissingBeginEnd;
- private String readAhead;
-
- /**
- * Create a UUdecoder that decodes the specified input stream.
- * The System property mail.mime.uudecode.ignoreerrors
- * controls whether errors in the encoded data cause an exception
- * or are ignored. The default is false (errors cause exception).
- * The System property mail.mime.uudecode.ignoremissingbeginend
- * controls whether a missing begin or end line cause an exception
- * or are ignored. The default is false (errors cause exception).
- * @param in the input stream
- */
- public UUDecoderStream(InputStream in) {
- super(in);
- lin = new LineInputStream(in);
- // default to false
- ignoreErrors = PropUtil.getBooleanSystemProperty(
- "mail.mime.uudecode.ignoreerrors", false);
- // default to false
- ignoreMissingBeginEnd = PropUtil.getBooleanSystemProperty(
- "mail.mime.uudecode.ignoremissingbeginend", false);
- }
-
- /**
- * Create a UUdecoder that decodes the specified input stream.
- * @param in the input stream
- * @param ignoreErrors ignore errors?
- * @param ignoreMissingBeginEnd ignore missing begin or end?
- */
- public UUDecoderStream(InputStream in, boolean ignoreErrors,
- boolean ignoreMissingBeginEnd) {
- super(in);
- lin = new LineInputStream(in);
- this.ignoreErrors = ignoreErrors;
- this.ignoreMissingBeginEnd = ignoreMissingBeginEnd;
- }
-
- /**
- * Read the next decoded byte from this input stream. The byte
- * is returned as an int in the range 0
- * to 255. If no byte is available because the end of
- * the stream has been reached, the value -1 is returned.
- * This method blocks until input data is available, the end of the
- * stream is detected, or an exception is thrown.
- *
- * @return next byte of data, or -1 if the end of
- * stream is reached.
- * @exception IOException if an I/O error occurs.
- * @see java.io.FilterInputStream#in
- */
- public int read() throws IOException {
- if (index >= bufsize) {
- readPrefix();
- if (!decode())
- return -1;
- index = 0; // reset index into buffer
- }
- return buffer[index++] & 0xff; // return lower byte
- }
-
- public int read(byte[] buf, int off, int len) throws IOException {
- int i, c;
- for (i = 0; i < len; i++) {
- if ((c = read()) == -1) {
- if (i == 0) // At end of stream, so we should
- i = -1; // return -1, NOT 0.
- break;
- }
- buf[off+i] = (byte)c;
- }
- return i;
- }
-
- public boolean markSupported() {
- return false;
- }
-
- public int available() throws IOException {
- // This is only an estimate, since in.available()
- // might include CRLFs too ..
- return ((in.available() * 3)/4 + (bufsize-index));
- }
-
- /**
- * Get the "name" field from the prefix. This is meant to
- * be the pathname of the decoded file
- *
- * @return name of decoded file
- * @exception IOException if an I/O error occurs.
- */
- public String getName() throws IOException {
- readPrefix();
- return name;
- }
-
- /**
- * Get the "mode" field from the prefix. This is the permission
- * mode of the source file.
- *
- * @return permission mode of source file
- * @exception IOException if an I/O error occurs.
- */
- public int getMode() throws IOException {
- readPrefix();
- return mode;
- }
-
- /**
- * UUencoded streams start off with the line:
- * "begin "
- * Search for this prefix and gobble it up.
- */
- private void readPrefix() throws IOException {
- if (gotPrefix) // got the prefix
- return;
-
- mode = 0666; // defaults, overridden below
- name = "encoder.buf"; // same default used by encoder
- String line;
- for (;;) {
- // read till we get the prefix: "begin MODE FILENAME"
- line = lin.readLine(); // NOTE: readLine consumes CRLF pairs too
- if (line == null) {
- if (!ignoreMissingBeginEnd)
- throw new DecodingException("UUDecoder: Missing begin");
- // at EOF, fake it
- gotPrefix = true;
- gotEnd = true;
- break;
- }
- if (line.regionMatches(false, 0, "begin", 0, 5)) {
- try {
- mode = Integer.parseInt(line.substring(6,9));
- } catch (NumberFormatException ex) {
- if (!ignoreErrors)
- throw new DecodingException(
- "UUDecoder: Error in mode: " + ex.toString());
- }
- if (line.length() > 10) {
- name = line.substring(10);
- } else {
- if (!ignoreErrors)
- throw new DecodingException(
- "UUDecoder: Missing name: " + line);
- }
- gotPrefix = true;
- break;
- } else if (ignoreMissingBeginEnd && line.length() != 0) {
- int count = line.charAt(0);
- count = (count - ' ') & 0x3f;
- int need = ((count * 8)+5)/6;
- if (need == 0 || line.length() >= need + 1) {
- /*
- * Looks like a legitimate encoded line.
- * Pretend we saw the "begin" line and
- * save this line for later processing in
- * decode().
- */
- readAhead = line;
- gotPrefix = true; // fake it
- break;
- }
- }
- }
- }
-
- private boolean decode() throws IOException {
-
- if (gotEnd)
- return false;
- bufsize = 0;
- int count = 0;
- String line;
- for (;;) {
- /*
- * If we ignored a missing "begin", the first line
- * will be saved in readAhead.
- */
- if (readAhead != null) {
- line = readAhead;
- readAhead = null;
- } else
- line = lin.readLine();
-
- /*
- * Improperly encoded data sometimes omits the zero length
- * line that starts with a space character, we detect the
- * following "end" line here.
- */
- if (line == null) {
- if (!ignoreMissingBeginEnd)
- throw new DecodingException(
- "UUDecoder: Missing end at EOF");
- gotEnd = true;
- return false;
- }
- if (line.equals("end")) {
- gotEnd = true;
- return false;
- }
- if (line.length() == 0)
- continue;
- count = line.charAt(0);
- if (count < ' ') {
- if (!ignoreErrors)
- throw new DecodingException(
- "UUDecoder: Buffer format error");
- continue;
- }
-
- /*
- * The first character in a line is the number of original (not
- * the encoded atoms) characters in the line. Note that all the
- * code below has to handle the character that indicates
- * end of encoded stream.
- */
- count = (count - ' ') & 0x3f;
-
- if (count == 0) {
- line = lin.readLine();
- if (line == null || !line.equals("end")) {
- if (!ignoreMissingBeginEnd)
- throw new DecodingException(
- "UUDecoder: Missing End after count 0 line");
- }
- gotEnd = true;
- return false;
- }
-
- int need = ((count * 8)+5)/6;
-//System.out.println("count " + count + ", need " + need + ", len " + line.length());
- if (line.length() < need + 1) {
- if (!ignoreErrors)
- throw new DecodingException(
- "UUDecoder: Short buffer error");
- continue;
- }
-
- // got a line we're committed to, break out and decode it
- break;
- }
-
- int i = 1;
- byte a, b;
- /*
- * A correct uuencoder always encodes 3 characters at a time, even
- * if there aren't 3 characters left. But since some people out
- * there have broken uuencoders we handle the case where they
- * don't include these "unnecessary" characters.
- */
- while (bufsize < count) {
- // continue decoding until we get 'count' decoded chars
- a = (byte)((line.charAt(i++) - ' ') & 0x3f);
- b = (byte)((line.charAt(i++) - ' ') & 0x3f);
- buffer[bufsize++] = (byte)(((a << 2) & 0xfc) | ((b >>> 4) & 3));
-
- if (bufsize < count) {
- a = b;
- b = (byte)((line.charAt(i++) - ' ') & 0x3f);
- buffer[bufsize++] =
- (byte)(((a << 4) & 0xf0) | ((b >>> 2) & 0xf));
- }
-
- if (bufsize < count) {
- a = b;
- b = (byte)((line.charAt(i++) - ' ') & 0x3f);
- buffer[bufsize++] = (byte)(((a << 6) & 0xc0) | (b & 0x3f));
- }
- }
- return true;
- }
-
- /*** begin TEST program *****
- public static void main(String argv[]) throws Exception {
- FileInputStream infile = new FileInputStream(argv[0]);
- UUDecoderStream decoder = new UUDecoderStream(infile);
- int c;
-
- try {
- while ((c = decoder.read()) != -1)
- System.out.write(c);
- System.out.flush();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- **** end TEST program ****/
-}
diff --git a/src/main/java/com/sun/mail/util/UUEncoderStream.java b/src/main/java/com/sun/mail/util/UUEncoderStream.java
deleted file mode 100644
index 79dc0ebb..00000000
--- a/src/main/java/com/sun/mail/util/UUEncoderStream.java
+++ /dev/null
@@ -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.util;
-
-import java.io.*;
-
-/**
- * This class implements a UUEncoder. It is implemented as
- * a FilterOutputStream, so one can just wrap this class around
- * any output stream and write bytes into this filter. The Encoding
- * is done as the bytes are written out.
- *
- * @author John Mani
- */
-
-public class UUEncoderStream extends FilterOutputStream {
- private byte[] buffer; // cache of bytes that are yet to be encoded
- private int bufsize = 0; // size of the cache
- private boolean wrotePrefix = false;
-
- protected String name; // name of file
- protected int mode; // permissions mode
-
- /**
- * Create a UUencoder that encodes the specified input stream
- * @param out the output stream
- */
- public UUEncoderStream(OutputStream out) {
- this(out, "encoder.buf", 644);
- }
-
- /**
- * Create a UUencoder that encodes the specified input stream
- * @param out the output stream
- * @param name Specifies a name for the encoded buffer
- */
- public UUEncoderStream(OutputStream out, String name) {
- this(out, name, 644);
- }
-
- /**
- * Create a UUencoder that encodes the specified input stream
- * @param out the output stream
- * @param name Specifies a name for the encoded buffer
- * @param mode Specifies permission mode for the encoded buffer
- */
- public UUEncoderStream(OutputStream out, String name, int mode) {
- super(out);
- this.name = name;
- this.mode = mode;
- buffer = new byte[45];
- }
-
- /**
- * Set up the buffer name and permission mode.
- * This method has any effect only if it is invoked before
- * you start writing into the output stream
- */
- public void setNameMode(String name, int mode) {
- this.name = name;
- this.mode = mode;
- }
-
- public void write(byte[] b, int off, int len) throws IOException {
- for (int i = 0; i < len; i++)
- write(b[off + i]);
- }
-
- public void write(byte[] data) throws IOException {
- write(data, 0, data.length);
- }
-
- public void write(int c) throws IOException {
- /* buffer up characters till we get a line's worth, then encode
- * and write them out. Max number of characters allowed per
- * line is 45.
- */
- buffer[bufsize++] = (byte)c;
- if (bufsize == 45) {
- writePrefix();
- encode();
- bufsize = 0;
- }
- }
-
- public void flush() throws IOException {
- if (bufsize > 0) { // If there's unencoded characters in the buffer
- writePrefix();
- encode(); // .. encode them
- }
- writeSuffix();
- out.flush();
- }
-
- public void close() throws IOException {
- flush();
- out.close();
- }
-
- /**
- * Write out the prefix: "begin "
- */
- private void writePrefix() throws IOException {
- if (!wrotePrefix) {
- // name should be ASCII, but who knows...
- PrintStream ps = new PrintStream(out, false, "utf-8");
- ps.println("begin " + mode + " " + name);
- ps.flush();
- wrotePrefix = true;
- }
- }
-
- /**
- * Write a single line containing space and the suffix line
- * containing the single word "end" (terminated by a newline)
- */
- private void writeSuffix() throws IOException {
- PrintStream ps = new PrintStream(out, false, "us-ascii");
- ps.println(" \nend");
- ps.flush();
- }
-
- /**
- * Encode a line.
- * Start off with the character count, followed by the encoded atoms
- * and terminate with LF. (or is it CRLF or the local line-terminator ?)
- * Take three bytes and encodes them into 4 characters
- * If bufsize if not a multiple of 3, the remaining bytes are filled
- * with '1'. This insures that the last line won't end in spaces
- * and potentiallly be truncated.
- */
- private void encode() throws IOException {
- byte a, b, c;
- int c1, c2, c3, c4;
- int i = 0;
-
- // Start off with the count of characters in the line
- out.write((bufsize & 0x3f) + ' ');
-
- while (i < bufsize) {
- a = buffer[i++];
- if (i < bufsize) {
- b = buffer[i++];
- if (i < bufsize)
- c = buffer[i++];
- else // default c to 1
- c = 1;
- }
- else { // default b & c to 1
- b = 1;
- c = 1;
- }
-
- c1 = (a >>> 2) & 0x3f;
- c2 = ((a << 4) & 0x30) | ((b >>> 4) & 0xf);
- c3 = ((b << 2) & 0x3c) | ((c >>> 6) & 0x3);
- c4 = c & 0x3f;
- out.write(c1 + ' ');
- out.write(c2 + ' ');
- out.write(c3 + ' ');
- out.write(c4 + ' ');
- }
- // Terminate with LF. (should it be CRLF or local line-terminator ?)
- out.write('\n');
- }
-
- /**** begin TEST program *****
- public static void main(String argv[]) throws Exception {
- FileInputStream infile = new FileInputStream(argv[0]);
- UUEncoderStream encoder = new UUEncoderStream(System.out);
- int c;
-
- while ((c = infile.read()) != -1)
- encoder.write(c);
- encoder.close();
- }
- **** end TEST program *****/
-}
diff --git a/src/main/java/com/sun/mail/util/logging/LogManagerProperties.java b/src/main/java/com/sun/mail/util/logging/LogManagerProperties.java
deleted file mode 100644
index 0aadf4ea..00000000
--- a/src/main/java/com/sun/mail/util/logging/LogManagerProperties.java
+++ /dev/null
@@ -1,648 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2009-2013 Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2009-2013 Jason Mehrens. 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.util.logging;
-
-import java.io.ObjectStreamException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.*;
-import java.util.logging.Formatter;
-import java.util.logging.*;
-import javax.mail.Authenticator;
-
-/**
- * An adapter class to allow the Mail API to access the LogManager properties.
- * The LogManager properties are treated as the root of all properties.
- * First, the parent properties are searched. If no value is found, then,
- * the LogManager is searched with prefix value. If not found, then, just the
- * key itself is searched in the LogManager. If a value is found in the
- * LogManager it is then copied to this properties object with no key prefix.
- * If no value is found in the LogManager or the parent properties, then this
- * properties object is searched only by passing the key value.
- *
- *
- * This class also emulates the LogManager functions for creating new objects
- * from string class names. This is to support initial setup of objects such as
- * log filters, formatters, error managers, etc.
- *
- *
- * This class should never be exposed outside of this package. Keep this
- * class package private (default access).
- *
- * @author Jason Mehrens
- * @since JavaMail 1.4.3
- */
-final class LogManagerProperties extends Properties {
-
- private static final long serialVersionUID = -2239983349056806252L;
- /**
- * Caches the LogManager so we only read the config once.
- */
- private final static LogManager LOG_MANAGER = LogManager.getLogManager();
-
- /**
- * Gets the LogManger for the running JVM.
- * @return the LogManager.
- * @since JavaMail 1.4.5
- */
- static LogManager getLogManager() {
- return LOG_MANAGER;
- }
-
- /**
- * Converts a locale to a language tag.
- * @param locale the locale to convert.
- * @return the language tag.
- * @throws NullPointerException if the given locale is null.
- * @since JavaMail 1.4.5
- */
- static String toLanguageTag(final Locale locale) {
- final String l = locale.getLanguage();
- final String c = locale.getCountry();
- final String v = locale.getVariant();
- final char[] b = new char[l.length() + c.length() + v.length() + 2];
- int count = l.length();
- l.getChars(0, count, b, 0);
- if (c.length() != 0 || (l.length() != 0 && v.length() != 0)) {
- b[count] = '-';
- ++count; //be nice to the client compiler.
- c.getChars(0, c.length(), b, count);
- count += c.length();
- }
-
- if (v.length() != 0 && (l.length() != 0 || c.length() != 0)) {
- b[count] = '-';
- ++count; //be nice to the client compiler.
- v.getChars(0, v.length(), b, count);
- count += v.length();
- }
- return String.valueOf(b, 0, count);
- }
-
- /**
- * Creates a new filter from the given class name.
- * @param name the fully qualified class name.
- * @return a new filter.
- * @throws ClassCastException if class name does not match the type.
- * @throws ClassNotFoundException if the class name was not found.
- * @throws IllegalAccessException if the constructor is inaccessible.
- * @throws InstantiationException if the given class name is abstract.
- * @throws InvocationTargetException if the constructor throws an exception.
- * @throws LinkageError if the linkage fails.
- * @throws ExceptionInInitializerError if the static initializer fails.
- * @throws Exception to match the error method of the ErrorManager.
- * @throws NoSuchMethodException if the class name does not have a no
- * argument constructor.
- * @since JavaMail 1.4.5
- */
- static Filter newFilter(String name) throws Exception {
- return newObjectFrom(name, Filter.class);
- }
-
- /**
- * Creates a new formatter from the given class name.
- * @param name the fully qualified class name.
- * @return a new formatter.
- * @throws ClassCastException if class name does not match the type.
- * @throws ClassNotFoundException if the class name was not found.
- * @throws IllegalAccessException if the constructor is inaccessible.
- * @throws InstantiationException if the given class name is abstract.
- * @throws InvocationTargetException if the constructor throws an exception.
- * @throws LinkageError if the linkage fails.
- * @throws ExceptionInInitializerError if the static initializer fails.
- * @throws Exception to match the error method of the ErrorManager.
- * @throws NoSuchMethodException if the class name does not have a no
- * argument constructor.
- * @since JavaMail 1.4.5
- */
- static Formatter newFormatter(String name) throws Exception {
- return newObjectFrom(name, Formatter.class);
- }
-
- /**
- * Creates a new log record comparator from the given class name.
- * @param name the fully qualified class name.
- * @return a new comparator.
- * @throws ClassCastException if class name does not match the type.
- * @throws ClassNotFoundException if the class name was not found.
- * @throws IllegalAccessException if the constructor is inaccessible.
- * @throws InstantiationException if the given class name is abstract.
- * @throws InvocationTargetException if the constructor throws an exception.
- * @throws LinkageError if the linkage fails.
- * @throws ExceptionInInitializerError if the static initializer fails.
- * @throws Exception to match the error method of the ErrorManager.
- * @throws NoSuchMethodException if the class name does not have a no
- * argument constructor.
- * @since JavaMail 1.4.5
- * @see java.util.logging.LogRecord
- */
- @SuppressWarnings("unchecked")
- static Comparator super LogRecord> newComparator(String name) throws Exception {
- return newObjectFrom(name, Comparator.class);
- }
-
- /**
- * Returns a comparator that imposes the reverse ordering of the specified
- * {@link Comparator}. If the given comparator declares a public
- * reverseOrder method that method is called first and the return value is
- * used. If that method is not declared or the caller does not have access
- * then a comparator wrapping the given comparator is returned.
- *
- * @param the element type to be compared
- * @param c a comparator whose ordering is to be reversed by the returned
- * comparator
- * @return A comparator that imposes the reverse ordering of the specified
- * comparator.
- * @throws NullPointerException if the given comparator is null.
- * @since JavaMail 1.5.0
- */
- @SuppressWarnings("unchecked")
- static Comparator reverseOrder(final Comparator c) {
- Comparator reverse = null;
- //Comparator in Java 1.8 has 'reverseOrder' as a default method.
- //This code calls that method first to allow custom code to define what
- //reverse order means.
- try {
- //assert Modifier.isPublic(c.getClass().getModifiers()) :
- // Modifier.toString(c.getClass().getModifiers());
- final Method m = c.getClass().getMethod("reverseOrder");
- if (Comparator.class.isAssignableFrom(m.getReturnType())) {
- try {
- reverse = (Comparator) m.invoke(c);
- } catch (final ExceptionInInitializerError eiie) {
- throw wrapOrThrow(eiie);
- }
- }
- } catch (final NoSuchMethodException ignore) {
- } catch (final IllegalAccessException ignore) {
- } catch (final InvocationTargetException ite) {
- paramOrError(ite); //Ignore invocation bugs.
- }
-
- if (reverse == null) {
- reverse = Collections.reverseOrder(c);
- }
- return reverse;
- }
-
- /**
- * Creates a new error manager from the given class name.
- * @param name the fully qualified class name.
- * @return a new error manager.
- * @throws ClassCastException if class name does not match the type.
- * @throws ClassNotFoundException if the class name was not found.
- * @throws IllegalAccessException if the constructor is inaccessible.
- * @throws InstantiationException if the given class name is abstract.
- * @throws InvocationTargetException if the constructor throws an exception.
- * @throws LinkageError if the linkage fails.
- * @throws ExceptionInInitializerError if the static initializer fails.
- * @throws Exception to match the error method of the ErrorManager.
- * @throws NoSuchMethodException if the class name does not have a no
- * argument constructor.
- * @since JavaMail 1.4.5
- */
- static ErrorManager newErrorManager(String name) throws Exception {
- return newObjectFrom(name, ErrorManager.class);
- }
-
- /**
- * Creates a new authenticator from the given class name.
- * @param name the fully qualified class name.
- * @return a new authenticator.
- * @throws ClassCastException if class name does not match the type.
- * @throws ClassNotFoundException if the class name was not found.
- * @throws IllegalAccessException if the constructor is inaccessible.
- * @throws InstantiationException if the given class name is abstract.
- * @throws InvocationTargetException if the constructor throws an exception.
- * @throws LinkageError if the linkage fails.
- * @throws ExceptionInInitializerError if the static initializer fails.
- * @throws Exception to match the error method of the ErrorManager.
- * @throws NoSuchMethodException if the class name does not have a no
- * argument constructor.
- * @since JavaMail 1.4.5
- */
- static Authenticator newAuthenticator(String name) throws Exception {
- return newObjectFrom(name, Authenticator.class);
- }
-
- /**
- * Creates a new object from the given class name.
- * @param name the fully qualified class name.
- * @param type the assignable type for the given name.
- * @return a new object assignable to the given type.
- * @throws ClassCastException if class name does not match the type.
- * @throws ClassNotFoundException if the class name was not found.
- * @throws IllegalAccessException if the constructor is inaccessible.
- * @throws InstantiationException if the given class name is abstract.
- * @throws InvocationTargetException if the constructor throws an exception.
- * @throws LinkageError if the linkage fails.
- * @throws ExceptionInInitializerError if the static initializer fails.
- * @throws Exception to match the error method of the ErrorManager.
- * @throws NoSuchMethodException if the class name does not have a no
- * argument constructor.
- * @since JavaMail 1.4.5
- */
- private static T newObjectFrom(String name, Class type) throws Exception {
- try {
- final Class> clazz = LogManagerProperties.findClass(name);
- //This check avoids additional side effects when the name parameter
- //is a literal name and not a class name.
- if (type.isAssignableFrom(clazz)) {
- try {
- return type.cast(clazz.getConstructor().newInstance());
- } catch (final InvocationTargetException ITE) {
- throw paramOrError(ITE);
- }
- } else {
- throw new ClassCastException(clazz.getName()
- + " cannot be cast to " + type.getName());
- }
- } catch (final NoClassDefFoundError NCDFE) {
- //No class def found can occur on filesystems that are
- //case insensitive (BUG ID 6196068). In some cases, we allow class
- //names or literal names, this code guards against the case where a
- //literal name happens to match a class name in a different case.
- //This is also a nice way to adap this error for the error manager.
- throw new ClassNotFoundException(NCDFE.toString(), NCDFE);
- } catch (final ExceptionInInitializerError EIIE) {
- throw wrapOrThrow(EIIE);
- }
- }
-
- /**
- * Returns the given exception or throws the escaping cause.
- * @param ite any invocation target.
- * @return the exception.
- * @throws VirtualMachineError if present as cause.
- * @throws ThreadDeath if present as cause.
- * @since JavaMail 1.4.5
- */
- private static Exception paramOrError(InvocationTargetException ite) {
- final Throwable cause = ite.getCause();
- if (cause != null) {
- if (cause instanceof VirtualMachineError
- || cause instanceof ThreadDeath) {
- throw (Error) cause;
- }
- }
- return ite;
- }
-
- /**
- * Throws the given error if the cause is an error otherwise
- * the given error is wrapped.
- * @param eiie the error.
- * @return an InvocationTargetException.
- * @since JavaMail 1.5.0
- */
- private static InvocationTargetException wrapOrThrow(
- ExceptionInInitializerError eiie) {
- //This linkage error will escape the constructor new instance call.
- //If the cause is an error, rethrow to skip any error manager.
- if (eiie.getCause() instanceof Error) {
- throw eiie;
- } else {
- //Considered a bug in the code, wrap the error so it can be
- //reported to the error manager.
- return new InvocationTargetException(eiie);
- }
- }
-
- /**
- * This code is modified from the LogManager, which explictly states
- * searching the system class loader first, then the context class loader.
- * There is resistance (compatibility) to change this behavior to simply
- * searching the context class loader.
- * @param name full class name
- * @return the class.
- * @throws LinkageError if the linkage fails.
- * @throws ClassNotFoundException if the class name was not found.
- * @throws ExceptionInInitializerError if static initializer fails.
- */
- private static Class> findClass(String name) throws ClassNotFoundException {
- ClassLoader[] loaders = getClassLoaders();
- assert loaders.length == 2 : loaders.length;
- Class clazz;
- if (loaders[0] != null) {
- try {
- clazz = Class.forName(name, false, loaders[0]);
- } catch (ClassNotFoundException tryContext) {
- clazz = tryLoad(name, loaders[1]);
- }
- } else {
- clazz = tryLoad(name, loaders[1]);
- }
- return clazz;
- }
-
- private static Class> tryLoad(String name, ClassLoader l) throws ClassNotFoundException {
- if (l != null) {
- return Class.forName(name, false, l);
- } else {
- return Class.forName(name);
- }
- }
-
- private static ClassLoader[] getClassLoaders() {
- return AccessController.doPrivileged(new PrivilegedAction() {
-
- public ClassLoader[] run() {
- final ClassLoader[] loaders = new ClassLoader[2];
- try {
- loaders[0] = ClassLoader.getSystemClassLoader();
- } catch (SecurityException ignore) {
- loaders[0] = null;
- }
-
- try {
- loaders[1] = Thread.currentThread().getContextClassLoader();
- } catch (SecurityException ignore) {
- loaders[1] = null;
- }
- return loaders;
- }
- });
- }
- /**
- * The namespace prefix to search LogManager and defaults.
- */
- private final String prefix;
-
- /**
- * Creates a log manager properties object.
- * @param parent the parent properties.
- * @param prefix the namespace prefix.
- * @throws NullPointerException if prefix or parent is
- * null.
- */
- LogManagerProperties(final Properties parent, final String prefix) {
- super(parent);
- parent.isEmpty(); //null check, happens-before
- if (prefix == null) {
- throw new NullPointerException();
- }
- this.prefix = prefix;
-
- //'defaults' is not decalared final.
- super.isEmpty(); //happens-before.
- }
-
- /**
- * Returns a properties object that contains a snapshot of the current
- * state. This method violates the clone contract so that no instances
- * of LogManagerProperties is exported for public use.
- * @return the snapshot.
- * @since JavaMail 1.4.4
- */
- @Override
- public synchronized Object clone() {
- return exportCopy(defaults);
- }
-
- /**
- * Searches defaults, then searches the log manager
- * by the prefix property, and then by the key itself.
- * @param key a non null key.
- * @return the value for that key.
- */
- @Override
- public synchronized String getProperty(final String key) {
- String value = defaults.getProperty(key);
- if (value == null) {
- final LogManager manager = getLogManager();
- if (key.length() > 0) {
- value = manager.getProperty(prefix + '.' + key);
- }
-
- if (value == null) {
- value = manager.getProperty(key);
- }
-
- /**
- * Copy the log manager properties as we read them. If a value is
- * no longer present in the LogManager read it from here.
- * The reason this works is because LogManager.reset() closes
- * all attached handlers therefore, stale values only exist in
- * closed handlers.
- */
- if (value != null) {
- super.put(key, value);
- } else {
- Object v = super.get(key); //defaults are not used.
- value = v instanceof String ? (String) v : null;
- }
- }
- return value;
- }
-
- /**
- * Calls getProperty directly. If getProperty returns null the default
- * value is returned.
- * @param key a key to search for.
- * @param def the default value to use if not found.
- * @return the value for the key.
- * @since JavaMail 1.4.4
- */
- @Override
- public String getProperty(final String key, final String def) {
- final String value = this.getProperty(key);
- return value == null ? def : value;
- }
-
- /**
- * Required to work with PropUtil. Calls getProperty directly if the
- * given key is a string. Otherwise, performs a normal get operation.
- * @param key any key.
- * @return the value for the key or null.
- * @since JavaMail 1.4.5
- */
- @Override
- public Object get(final Object key) {
- if (key instanceof String) {
- return this.getProperty((String) key);
- } else {
- return super.get(key);
- }
- }
-
- /**
- * Required to work with PropUtil. An updated copy of the key is fetched
- * from the log manager if the key doesn't exist in this properties.
- * @param key any key.
- * @return the value for the key or the default value for the key.
- * @since JavaMail 1.4.5
- */
- @Override
- public synchronized Object put(final Object key, final Object value) {
- final Object def = preWrite(key);
- final Object man = super.put(key, value);
- return man == null ? def : man;
- }
-
- /**
- * Calls the put method directly.
- * @param key any key.
- * @return the value for the key or the default value for the key.
- * @since JavaMail 1.4.5
- */
- @Override
- public Object setProperty(String key, String value) {
- return this.put(key, value);
- }
-
- /**
- * Required to work with PropUtil. An updated copy of the key is fetched
- * from the log manager prior to returning.
- * @param key any key.
- * @return the value for the key or null.
- * @since JavaMail 1.4.5
- */
- @Override
- public boolean containsKey(final Object key) {
- if (key instanceof String) {
- return this.getProperty((String) key) != null;
- } else {
- return super.containsKey(key);
- }
- }
-
- /**
- * Required to work with PropUtil. An updated copy of the key is fetched
- * from the log manager if the key doesn't exist in this properties.
- * @param key any key.
- * @return the value for the key or the default value for the key.
- * @since JavaMail 1.4.5
- */
- @Override
- public synchronized Object remove(final Object key) {
- final Object def = preWrite(key);
- final Object man = super.remove(key);
- return man == null ? def : man;
- }
-
- /**
- * It is assumed that this method will never be called.
- * No way to get the property names from LogManager.
- * @return the property names
- */
- @Override
- public Enumeration propertyNames() {
- assert false;
- return super.propertyNames();
- }
-
- /**
- * It is assumed that this method will never be called.
- * The prefix value is not used for the equals method.
- * @param o any object or null.
- * @return true if equal, otherwise false.
- */
- @Override
- public boolean equals(final Object o) {
- if (o == null) {
- return false;
- }
- if (o == this) {
- return true;
- }
- if (o instanceof Properties == false) {
- return false;
- }
- assert false : prefix;
- return super.equals(o);
- }
-
- /**
- * It is assumed that this method will never be called. See equals.
- * @return the hash code.
- */
- @Override
- public int hashCode() {
- assert false : prefix.hashCode();
- return super.hashCode();
- }
-
- /**
- * Called before a write operation of a key.
- * Caches a key read from the log manager in this properties object.
- * The key is only cached if it is an instance of a String and
- * this properties doesn't contain a copy of the key.
- * @param key the key to search.
- * @return the default value for the key.
- */
- private Object preWrite(final Object key) {
- assert Thread.holdsLock(this);
- Object value;
- if (key instanceof String && !super.containsKey(key)) {
- value = this.getProperty((String) key); //fetch and cache.
- } else {
- value = null;
- }
- return value;
- }
-
- /**
- * Creates a public snapshot of this properties object using
- * the given parent properties.
- * @param parent the defaults to use with the snapshot.
- * @return the safe snapshot.
- */
- private Properties exportCopy(final Properties parent) {
- Thread.holdsLock(this);
- final Properties child = new Properties(parent);
- child.putAll(this);
- return child;
- }
-
- /**
- * It is assumed that this method will never be called.
- * We return a safe copy for export to avoid locking this properties
- * object or the defaults during write.
- * @return the parent properties.
- * @throws ObjectStreamException if there is a problem.
- */
- private synchronized Object writeReplace() throws ObjectStreamException {
- assert false;
- return exportCopy((Properties) defaults.clone());
- }
-}
diff --git a/src/main/java/com/sun/mail/util/logging/MailHandler.java b/src/main/java/com/sun/mail/util/logging/MailHandler.java
deleted file mode 100644
index 88127d54..00000000
--- a/src/main/java/com/sun/mail/util/logging/MailHandler.java
+++ /dev/null
@@ -1,3477 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2009-2013 Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2009-2013 Jason Mehrens. 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.util.logging;
-
-import com.sun.mail.smtp.SMTPTransport;
-import java.io.*;
-import java.lang.reflect.Array;
-import java.net.InetAddress;
-import java.net.URLConnection;
-import java.net.UnknownHostException;
-import java.nio.charset.Charset;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.*;
-import java.util.logging.*;
-import java.util.logging.Formatter;
-import javax.activation.DataHandler;
-import javax.activation.DataSource;
-import javax.activation.FileTypeMap;
-import javax.activation.MimetypesFileTypeMap;
-import javax.mail.*;
-import javax.mail.internet.*;
-import javax.mail.util.ByteArrayDataSource;
-
-/**
- * Handler that formats log records as an email message.
- *
- *
- * This Handler will store a fixed number of log records used to
- * generate a single email message. When the internal buffer reaches capacity,
- * all log records are formatted and placed in an email which is sent to an
- * email server. The code to manually setup this handler can be as simple as
- * the following:
- *
- *
- * Configuration:
- * The LogManager should define at least one or more recipient addresses and a
- * mail host for outgoing email. The code to setup this handler via the
- * logging properties can be as simple as the following:
- *
- *
- *
- * All mail properties documented in the Java Mail API cascade to the
- * LogManager by prefixing a key using the fully qualified class name of this
- * MailHandler or the fully qualified derived class name dot mail
- * property. If the prefixed property is not found, then the mail property
- * itself is searched in the LogManager. By default each MailHandler is
- * initialized using the following LogManager configuration properties where
- * refers to the fully-qualified class name of the
- * handler. If properties are not defined, or contain invalid values, then the
- * specified default values are used.
- *
- *
- *
<handler-name>.attachment.filters a comma
- * separated list of Filter class names used to create each attachment.
- * The literal null is reserved for attachments that do not require
- * filtering. (defaults to the
- * {@linkplain java.util.logging.Handler#getFilter() body} filter)
- *
- *
<handler-name>.attachment.formatters a comma
- * separated list of Formatter class names used to create each
- * attachment. (default is no attachments)
- *
- *
<handler-name>.attachment.names a comma separated
- * list of names or Formatter class names of each attachment. The
- * attachment file names must not contain any line breaks.
- * (default is {@linkplain java.util.logging.Formatter#toString() toString}
- * of the attachment formatter)
- *
- *
<handler-name>.authenticator name of an
- * {@linkplain javax.mail.Authenticator} class used to provide login credentials
- * to the email server or string literal that is the password used with the
- * {@linkplain Authenticator#getDefaultUserName() default} user name.
- * (default is null)
- *
- *
<handler-name>.capacity the max number of
- * LogRecord objects include in each email message.
- * (defaults to 1000)
- *
- *
<handler-name>.comparator name of a
- * {@linkplain java.util.Comparator} class used to sort the published
- * LogRecord objects prior to all formatting.
- * (defaults to null meaning records are unsorted).
- *
- *
<handler-name>.comparator.reverse a boolean
- * true to reverse the order of the specified comparator or
- * false to retain the original order. (defaults to false)
- *
- *
<handler-name>.encoding the name of the Java
- * {@linkplain java.nio.charset.Charset#name() character set} to use for the
- * email message. (defaults to null, the
- * {@linkplain javax.mail.internet.MimeUtility#getDefaultJavaCharset() default}
- * platform encoding).
- *
- *
<handler-name>.errorManager name of an
- * ErrorManager class used to handle any configuration or mail
- * transport problems. (defaults to java.util.logging.ErrorManager)
- *
- *
<handler-name>.filter name of a Filter
- * class used for the body of the message. (defaults to null,
- * allow all records)
- *
- *
<handler-name>.formatter name of a
- * Formatter class used to format the body of this message.
- * (defaults to java.util.logging.SimpleFormatter)
- *
- *
<handler-name>.level specifies the default level
- * for this Handler (defaults to Level.WARNING).
- *
- *
<handler-name>.mail.bcc a comma separated list of
- * addresses which will be blind carbon copied. Typically, this is set to the
- * recipients that may need to be privately notified of a log message or
- * notified that a log message was sent to a third party such as a support team.
- * The empty string can be used to specify no blind carbon copied address.
- * (defaults to null, none)
- *
- *
<handler-name>.mail.cc a comma separated list of
- * addresses which will be carbon copied. Typically, this is set to the
- * recipients that may need to be notified of a log message but, are not
- * required to provide direct support. The empty string can be used to specify
- * no carbon copied address. (defaults to null, none)
- *
- *
<handler-name>.mail.from a comma separated list of
- * addresses which will be from addresses. Typically, this is set to the email
- * address identifying the user running the application. The empty string can
- * be used to override the default behavior and specify no from address.
- * (defaults to the {@linkplain javax.mail.Message#setFrom() local address})
- *
- *
<handler-name>.mail.host the host name or IP
- * address of the email server. (defaults to null, use
- * {@linkplain Transport#protocolConnect default}
- * Java Mail behavior)
- *
- *
<handler-name>.mail.reply.to a comma separated
- * list of addresses which will be reply-to addresses. Typically, this is set
- * to the recipients that provide support for the application itself. The empty
- * string can be used to specify no reply-to address.
- * (defaults to null, none)
- *
- *
<handler-name>.mail.to a comma separated list of
- * addresses which will be send-to addresses. Typically, this is set to the
- * recipients that provide support for the application, system, and/or
- * supporting infrastructure. The empty string can be used to specify no
- * send-to address which overrides the default behavior. (defaults to
- * {@linkplain javax.mail.internet.InternetAddress.getLocalAddress
- * local address}.)
- *
- *
<handler-name>.mail.sender a single address
- * identifying sender of the email; never equal to the from address. Typically,
- * this is set to the email address identifying the application itself. The
- * empty string can be used to specify no sender address.
- * (defaults to null, none)
- *
- *
<handler-name>.subject the name of a
- * Formatter class or string literal used to create the subject line.
- * The empty string can be used to specify no subject. The subject line must
- * not contain any line breaks. (defaults to the empty string)
- *
- *
<handler-name>.pushFilter the name of a
- * Filter class used to trigger an early push.
- * (defaults to null, no early push)
- *
- *
<handler-name>.pushLevel the level which will
- * trigger an early push. (defaults to Level.OFF, only push when full)
- *
- *
<handler-name>.verify used to
- * verify the Handler configuration prior to a push.
- *
- *
If the value is not set, equal to an empty string, or equal to the
- * literal null then no settings are verified prior to a push.
- *
If set to a value of limited then the Handler will
- * verify minimal local machine settings.
- *
If set to a value of local the Handler will verify
- * all of settings of the local machine.
- *
If set to a value of resolve, the Handler will
- * verify all local settings and try to resolve the remote host name with
- * the domain name server.
- *
If set to a value of remote, the Handler will
- * verify all local settings and try to establish a connection with the
- * email server.
- *
- * If this Handler is only implicitly closed by the
- * LogManager, then verification should be turned on.
- * (defaults to null, no verify).
- *
- *
- * Normalization:
- * The error manager, filters, and formatters when loaded from the LogManager
- * are converted into canonical form inside the MailHandler. The pool of
- * interned values is limited to each MailHandler object such that no two
- * MailHandler objects created by the LogManager will be created sharing
- * identical error managers, filters, or formatters. If a filter or formatter
- * should not be interned then it is recommended to retain the identity
- * equals and identity hashCode methods as the implementation. For a filter or
- * formatter to be interned the class must implement the
- * {@linkplain java.lang.Object#equals(java.lang.Object) equals}
- * and {@linkplain java.lang.Object#hashCode() hashCode} methods.
- * The recommended code to use for stateless filters and formatters is:
- *
- * Sorting:
- * All LogRecord objects are ordered prior to formatting if this
- * Handler has a non null comparator. Developers might be interested
- * in sorting the formatted email by thread id, time, and sequence properties
- * of a LogRecord. Where as system administrators might be interested
- * in sorting the formatted email by thrown, level, time, and sequence
- * properties of a LogRecord. If comparator for this handler is
- * null then the order is unspecified.
- *
- *
- * Formatting:
- * The main message body is formatted using the Formatter returned by
- * getFormatter(). Only records that pass the filter returned by
- * getFilter() will be included in the message body. The subject
- * Formatter will see all LogRecord objects that were
- * published regardless of the current Filter. The MIME type of the
- * message body can be {@linkplain FileTypeMap#setDefaultFileTypeMap overridden}
- * by adding a MIME {@linkplain MimetypesFileTypeMap entry} using the simple
- * class name of the body formatter as the file extension. The MIME type of the
- * attachments can be overridden by changing the attachment file name extension
- * or by editing the default MIME entry for a specific file name extension.
- *
- *
- * Attachments:
- * This Handler allows multiple attachments per each email.
- * The attachment order maps directly to the array index order in this
- * Handler with zero index being the first attachment. The number of
- * attachment formatters controls the number of attachments per email and
- * the content type of each attachment. The attachment filters determine if a
- * LogRecord will be included in an attachment. If an attachment
- * filter is null then all records are included for that attachment.
- * Attachments without content will be omitted from email message. The
- * attachment name formatters create the file name for an attachment.
- * Custom attachment name formatters can be used to generate an attachment name
- * based on the contents of the attachment.
- *
- *
- * Push Level and Push Filter:
- * The push method, push level, and optional push filter can be used to
- * conditionally trigger a push at or prior to full capacity. When a push
- * occurs, the current buffer is formatted into an email and is sent to the
- * email server. If the push method, push level, or push filter trigger a push
- * then the outgoing email is flagged as high importance with urgent priority.
- *
- *
- * Buffering:
- * Log records that are published are stored in an internal buffer. When this
- * buffer reaches capacity the existing records are formatted and sent in an
- * email. Any published records can be sent before reaching capacity by
- * explictly calling the flush, push, or close
- * methods. If a circular buffer is required then this handler can be wrapped
- * with a {@linkplain java.util.logging.MemoryHandler} typically with an
- * equivalent capacity, level, and push level.
- *
- *
- * Error Handling:
- * If the transport of an email message fails, the email is converted to
- * a {@linkplain javax.mail.internet.MimeMessage#writeTo raw}
- * {@linkplain java.io.ByteArrayOutputStream#toString(java.lang.String) string}
- * and is then passed as the msg parameter to
- * {@linkplain Handler#reportError reportError} along with the exception
- * describing the cause of the failure. This allows custom error managers to
- * store, {@linkplain javax.mail.internet.MimeMessage#MimeMessage(
- * javax.mail.Session, java.io.InputStream) reconstruct}, and resend the
- * original MimeMessage. The message parameter string is not a raw email
- * if it starts with value returned from Level.SEVERE.getName().
- * Custom error managers can use the following test to determine if the
- * msg parameter from this handler is a raw email:
- *
- *
- * public void error(String msg, Exception ex, int code) {
- * if (msg == null || msg.length() == 0 || msg.startsWith(Level.SEVERE.getName())) {
- * super.error(msg, ex, code);
- * } else {
- * //The 'msg' parameter is a raw email.
- * }
- * }
- *
- *
- * @author Jason Mehrens
- * @since JavaMail 1.4.3
- */
-public class MailHandler extends Handler {
- /**
- * Use the emptyFilterArray method.
- */
- private static final Filter[] EMPTY_FILTERS = new Filter[0];
- /**
- * Use the emptyFormatterArray method.
- */
- private static final Formatter[] EMPTY_FORMATTERS = new Formatter[0];
- /**
- * Min byte size for header data. Used for initial arrays sizing.
- */
- private static final int MIN_HEADER_SIZE = 1024;
- /**
- * Cache the off value.
- */
- private static final int offValue = Level.OFF.intValue();
- /**
- * The action to get and set the context class loader.
- * Load this before it is loaded in the close method.
- */
- private static final GetAndSetContext GET_AND_SET_CCL =
- new GetAndSetContext(MailHandler.class);
- /**
- * A thread local mutex used to prevent logging loops.
- * The MUTEX has 3 states:
- * 1. MUTEX_RESET which is the null state.
- * 2. MUTEX_PUBLISH on first entry of a push or publish.
- * 3. MUTEX_REPORT when cycle of records is detected.
- */
- private static final ThreadLocal MUTEX = new ThreadLocal();
- /**
- * The marker object used to report a publishing state.
- */
- private static final Level MUTEX_PUBLISH = Level.ALL;
- /**
- * The marker object used to report a error reporting state.
- */
- private static final Level MUTEX_REPORT = Level.OFF;
- /**
- * Used to turn off security checks.
- */
- private volatile boolean sealed;
- /**
- * Determines if we are inside of a push.
- * Makes the handler properties read-only during a push.
- */
- private boolean isWriting;
- /**
- * Holds all of the email server properties.
- */
- private Properties mailProps;
- /**
- * Holds the authenticator required to login to the email server.
- */
- private Authenticator auth;
- /**
- * Holds the session object used to generate emails.
- * Sessions can be shared by multiple threads.
- * See BUGID 6228391
- */
- private Session session;
- /**
- * Holds all of the log records that will be used to create the email.
- */
- private LogRecord[] data;
- /**
- * The number of log records in the buffer.
- */
- private int size;
- /**
- * The maximum number of log records to format per email.
- * Used to roughly bound the size of an email.
- * Every time the capacity is reached, the handler will push.
- * The capacity will be negative if this handler is closed.
- * Negative values are used to ensure all records are pushed.
- */
- private int capacity;
- /**
- * Used to order all log records prior to formatting. The main email body
- * and all attachments use the order determined by this comparator. If no
- * comparator is present the log records will be in no specified order.
- */
- private Comparator super LogRecord> comparator;
- /**
- * Holds the formatter used to create the subject line of the email.
- * A subject formatter is not required for the email message.
- * All published records pass through the subject formatter.
- */
- private Formatter subjectFormatter;
- /**
- * Holds the push level for this handler.
- * This is only required if an email must be sent prior to shutdown
- * or before the buffer is full.
- */
- private Level pushLevel;
- /**
- * Holds the push filter for trigger conditions requiring an early push.
- * Only gets called if the given log record is greater than or equal
- * to the push level and the push level is not Level.OFF.
- */
- private Filter pushFilter;
- /**
- * Holds the filters for each attachment. Filters are optional for
- * each attachment.
- */
- private Filter[] attachmentFilters;
- /**
- * Holds the formatters that create the content for each attachment.
- * Each formatter maps directly to an attachment. The formatters
- * getHead, format, and getTail methods are only called if one or more
- * log records pass through the attachment filters.
- */
- private Formatter[] attachmentFormatters;
- /**
- * Holds the formatters that create the file name for each attachment.
- * Each formatter must produce a non null and non empty name.
- * The final file name will be the concatenation of one getHead call, plus
- * all of the format calls, plus one getTail call.
- */
- private Formatter[] attachmentNames;
- /**
- * Used to override the content type for the body and set the content type
- * for each attachment.
- */
- private FileTypeMap contentTypes;
-
- /**
- * Creates a MailHandler that is configured by the
- * LogManager configuration properties.
- * @throws SecurityException if a security manager exists and the
- * caller does not have LoggingPermission("control").
- */
- public MailHandler() {
- init((Properties) null);
- sealed = true;
- }
-
- /**
- * Creates a MailHandler that is configured by the
- * LogManager configuration properties but overrides the
- * LogManager capacity with the given capacity.
- * @param capacity of the internal buffer.
- * @throws IllegalArgumentException if capacity less than one.
- * @throws SecurityException if a security manager exists and the
- * caller does not have LoggingPermission("control").
- */
- public MailHandler(final int capacity) {
- init((Properties) null);
- sealed = true;
- setCapacity0(capacity);
- }
-
- /**
- * Creates a mail handler with the given mail properties.
- * The key/value pairs are defined in the Java Mail API
- * documentation. This Handler will also search the
- * LogManager for defaults if needed.
- * @param props a non null properties object.
- * @throws NullPointerException if props is null.
- * @throws SecurityException if a security manager exists and the
- * caller does not have LoggingPermission("control").
- */
- public MailHandler(final Properties props) {
- if (props == null) {
- throw new NullPointerException();
- }
- init(props);
- sealed = true;
- setMailProperties0(props);
- }
-
- /**
- * Check if this Handler would actually log a given
- * LogRecord into its internal buffer.
- *
- * This method checks if the LogRecord has an appropriate level and
- * whether it satisfies any Filter including any attachment filters.
- * However it does not check whether the LogRecord would
- * result in a "push" of the buffer contents.
- *
- * @param record a LogRecord
- * @return true if the LogRecord would be logged.
- */
- @Override
- public boolean isLoggable(final LogRecord record) {
- int levelValue = getLevel().intValue();
- if (record.getLevel().intValue() < levelValue || levelValue == offValue) {
- return false;
- }
-
- Filter body = getFilter();
- if (body == null || body.isLoggable(record)) {
- return true;
- }
-
- return isAttachmentLoggable(record);
- }
-
- /**
- * Stores a LogRecord in the internal buffer.
- *
- * The isLoggable method is called to check if the given log record
- * is loggable. If the given record is loggable, it is copied into
- * an internal buffer. Then the record's level property is compared with
- * the push level. If the given level of the LogRecord
- * is greater than or equal to the push level then the push filter is
- * called. If no push filter exists, the push filter returns true,
- * or the capacity of the internal buffer has been reached then all buffered
- * records are formatted into one email and sent to the server.
- *
- * @param record description of the log event.
- */
- public void publish(final LogRecord record) {
- /**
- * It is possible for the handler to be closed after the
- * call to isLoggable. In that case, the current thread
- * will push to ensure that all published records are sent.
- * See close().
- */
- if (tryMutex()) {
- try {
- if (isLoggable(record)) {
- record.getSourceMethodName(); //Infer caller.
- publish0(record);
- }
- } finally {
- releaseMutex();
- }
- } else {
- reportUnPublishedError(record);
- }
- }
-
- /**
- * Performs the publish after the record has been filtered.
- * @param record the record.
- * @since JavaMail 1.4.5
- */
- private void publish0(final LogRecord record) {
- Message msg;
- boolean priority;
- synchronized (this) {
- if (size == data.length && size < capacity) {
- grow();
- }
-
- if (size < data.length) {
- data[size] = record;
- ++size; //Be nice to client compiler.
- priority = isPushable(record);
- if (priority || size >= capacity) {
- msg = writeLogRecords(ErrorManager.WRITE_FAILURE);
- } else {
- msg = null;
- }
- } else {
- priority = false;
- msg = null;
- }
- }
-
- if (msg != null) {
- send(msg, priority, ErrorManager.WRITE_FAILURE);
- }
- }
-
- /**
- * Report to the error manager that a logging loop was detected and
- * we are going to break the cycle of messages. It is possible that
- * a custom error manager could continue the cycle in which case
- * we will stop trying to report errors.
- * @param record the record or null.
- * @since JavaMail 1.4.6
- */
- private void reportUnPublishedError(LogRecord record) {
- if (MUTEX_PUBLISH.equals(MUTEX.get())) {
- MUTEX.set(MUTEX_REPORT);
- try {
- final String msg;
- if (record != null) {
- final SimpleFormatter f = new SimpleFormatter();
- msg = "Log record " + record.getSequenceNumber()
- + " was not published. "
- + head(f) + format(f, record) + tail(f, "");
- } else {
- msg = null;
- }
- Exception e = new IllegalStateException(
- "Recursive publish detected by thread "
- + Thread.currentThread());
- reportError(msg, e, ErrorManager.WRITE_FAILURE);
- } finally {
- MUTEX.set(MUTEX_PUBLISH);
- }
- }
- }
-
- /**
- * Used to detect reentrance by the current thread to the publish method.
- * This mutex is thread local scope and will not block other threads.
- * The state is advanced on if the current thread is in a reset state.
- * @return true if the mutex was acquired.
- * @since JavaMail 1.4.6
- */
- private boolean tryMutex() {
- if (MUTEX.get() == null) {
- MUTEX.set(MUTEX_PUBLISH);
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Releases the mutex held by the current thread.
- * This mutex is thread local scope and will not block other threads.
- * @since JavaMail 1.4.6
- */
- private void releaseMutex() {
- MUTEX.remove();
- }
-
- /**
- * Pushes any buffered records to the email server as high importance with
- * urgent priority. The internal buffer is then cleared. Does nothing if
- * called from inside a push.
- * @see #flush()
- */
- public void push() {
- push(true, ErrorManager.FLUSH_FAILURE);
- }
-
- /**
- * Pushes any buffered records to the email server as normal priority.
- * The internal buffer is then cleared. Does nothing if called from inside
- * a push.
- * @see #push()
- */
- public void flush() {
- push(false, ErrorManager.FLUSH_FAILURE);
- }
-
- /**
- * Prevents any other records from being published.
- * Pushes any buffered records to the email server as normal priority.
- * The internal buffer is then cleared. Once this handler is closed it
- * will remain closed.
- *
- * If this Handler is only implicitly closed by the
- * LogManager, then verification should be
- * turned on.
- * @throws SecurityException if a security manager exists and the
- * caller does not have LoggingPermission("control").
- * @see #flush()
- */
- public void close() {
- checkAccess(); //Security check first.
- //The LogManager$Cleaner has a context class loader set to null.
- //Set the CCL to this class loader for loading content handlers.
- final Object ccl = getAndSetContextClassLoader();
- try {
- Message msg = null;
- synchronized (this) {
- try {
- msg = writeLogRecords(ErrorManager.CLOSE_FAILURE);
- } finally {
- super.setLevel(Level.OFF); //Change level after formatting.
- /**
- * The sign bit of the capacity is set to ensure that records
- * that have passed isLoggable, but have yet to be added to
- * the internal buffer, are immediately pushed as an email.
- */
- if (this.capacity > 0) {
- this.capacity = -this.capacity;
- }
-
- //Ensure not inside a push.
- if (size == 0 && data.length != 1) {
- this.data = new LogRecord[1];
- }
- }
- }
-
- if (msg != null) {
- send(msg, false, ErrorManager.CLOSE_FAILURE);
- }
- } finally {
- setContextClassLoader(ccl);
- }
- }
-
- /**
- * Set the log level specifying which message levels will be
- * logged by this Handler. Message levels lower than this
- * value will be discarded.
- * @param newLevel the new value for the log level
- * @throws NullPointerException if newLevel is null.
- * @throws SecurityException if a security manager exists and
- * the caller does not have LoggingPermission("control").
- */
- @Override
- public synchronized void setLevel(final Level newLevel) {
- if (this.capacity > 0) {
- super.setLevel(newLevel);
- } else { //Don't allow a closed handler to be opened (half way).
- if (newLevel == null) {
- throw new NullPointerException();
- }
- checkAccess();
- }
- }
-
- /**
- * Gets the push level. The default is Level.OFF meaning that
- * this Handler will only push when the internal buffer is full.
- * @return the push level.
- */
- public final synchronized Level getPushLevel() {
- return this.pushLevel;
- }
-
- /**
- * Sets the push level. This level is used to trigger a push so that
- * all pending records are formatted and sent to the email server. When
- * the push level triggers a send, the resulting email is flagged as
- * high importance with urgent priority.
- * @param level Level object.
- * @throws NullPointerException if level is null.
- * @throws SecurityException if a security manager exists and the
- * caller does not have LoggingPermission("control").
- * @throws IllegalStateException if called from inside a push.
- */
- public final synchronized void setPushLevel(final Level level) {
- checkAccess();
- if (level == null) {
- throw new NullPointerException();
- }
-
- if (isWriting) {
- throw new IllegalStateException();
- }
- this.pushLevel = level;
- }
-
- /**
- * Gets the push filter. The default is null.
- * @return the push filter or null.
- */
- public final synchronized Filter getPushFilter() {
- return this.pushFilter;
- }
-
- /**
- * Sets the push filter. This filter is only called if the given
- * LogRecord level was greater than the push level. If this
- * filter returns true, all pending records are formatted and sent
- * to the email server. When the push filter triggers a send, the resulting
- * email is flagged as high importance with urgent priority.
- * @param filter push filter or null
- * @throws SecurityException if a security manager exists and the
- * caller does not have LoggingPermission("control").
- * @throws IllegalStateException if called from inside a push.
- */
- public final synchronized void setPushFilter(final Filter filter) {
- checkAccess();
- if (isWriting) {
- throw new IllegalStateException();
- }
- this.pushFilter = filter;
- }
-
- /**
- * Gets the comparator used to order all LogRecord objects prior
- * to formatting. If null then the order is unspecified.
- * @return the LogRecord comparator.
- */
- public final synchronized Comparator super LogRecord> getComparator() {
- return this.comparator;
- }
-
- /**
- * Sets the comparator used to order all LogRecord objects prior
- * to formatting. If null then the order is unspecified.
- * @param c the LogRecord comparator.
- * @throws SecurityException if a security manager exists and the
- * caller does not have LoggingPermission("control").
- * @throws IllegalStateException if called from inside a push.
- */
- public final synchronized void setComparator(Comparator super LogRecord> c) {
- checkAccess();
- if (isWriting) {
- throw new IllegalStateException();
- }
- this.comparator = c;
- }
-
- /**
- * Gets the number of log records the internal buffer can hold. When
- * capacity is reached, Handler will format all LogRecord
- * objects into one email message.
- * @return the capacity.
- */
- public final synchronized int getCapacity() {
- assert capacity != Integer.MIN_VALUE && capacity != 0 : capacity;
- return Math.abs(capacity);
- }
-
- /**
- * Gets the Authenticator used to login to the email server.
- * @return an Authenticator or null if none is required.
- * @throws SecurityException if a security manager exists and the
- * caller does not have LoggingPermission("control").
- */
- public final synchronized Authenticator getAuthenticator() {
- checkAccess();
- return this.auth;
- }
-
- /**
- * Sets the Authenticator used to login to the email server.
- * @param auth an Authenticator object or null if none is required.
- * @throws SecurityException if a security manager exists and the
- * caller does not have LoggingPermission("control").
- * @throws IllegalStateException if called from inside a push.
- */
- public final void setAuthenticator(final Authenticator auth) {
- this.setAuthenticator0(auth);
- }
-
- /**
- * Sets the Authenticator used to login to the email server.
- * @param password a password or null if none is required.
- * @throws SecurityException if a security manager exists and the
- * caller does not have LoggingPermission("control").
- * @throws IllegalStateException if called from inside a push.
- * @see String#toCharArray()
- * @since JavaMail 1.4.6
- */
- public final void setAuthenticator(final char... password) {
- if (password == null) {
- setAuthenticator0((Authenticator) null);
- } else {
- setAuthenticator0(new DefaultAuthenticator(new String(password)));
- }
- }
-
- private void setAuthenticator0(final Authenticator auth) {
- checkAccess();
-
- Session settings;
- synchronized (this) {
- if (isWriting) {
- throw new IllegalStateException();
- }
- this.auth = auth;
- settings = fixUpSession();
- }
- verifySettings(settings);
- }
-
- /**
- * Sets the mail properties used for the session. The key/value pairs
- * are defined in the Java Mail API documentation. This
- * Handler will also search the LogManager for defaults
- * if needed.
- * @param props a non null properties object.
- * @throws SecurityException if a security manager exists and the
- * caller does not have LoggingPermission("control").
- * @throws NullPointerException if props is null.
- * @throws IllegalStateException if called from inside a push.
- */
- public final void setMailProperties(Properties props) {
- this.setMailProperties0(props);
- }
-
- private void setMailProperties0(Properties props) {
- checkAccess();
- props = (Properties) props.clone(); //Allow subclass.
- Session settings;
- synchronized (this) {
- if (isWriting) {
- throw new IllegalStateException();
- }
- this.mailProps = props;
- settings = fixUpSession();
- }
- verifySettings(settings);
- }
-
- /**
- * Gets a copy of the mail properties used for the session.
- * @return a non null properties object.
- * @throws SecurityException if a security manager exists and the
- * caller does not have LoggingPermission("control").
- */
- public final Properties getMailProperties() {
- checkAccess();
- final Properties props;
- synchronized (this) {
- props = this.mailProps;
- }
- return (Properties) props.clone();
- }
-
- /**
- * Gets the attachment filters. If the attachment filter does not
- * allow any LogRecord to be formatted, the attachment may
- * be omitted from the email.
- * @return a non null array of attachment filters.
- */
- public final Filter[] getAttachmentFilters() {
- return readOnlyAttachmentFilters().clone();
- }
-
- /**
- * Sets the attachment filters.
- * @param filters a non null array of filters. A null
- * index value is allowed. A null value means that all
- * records are allowed for the attachment at that index.
- * @throws SecurityException if a security manager exists and the
- * caller does not have LoggingPermission("control").
- * @throws NullPointerException if filters is null
- * @throws IndexOutOfBoundsException if the number of attachment
- * name formatters do not match the number of attachment formatters.
- * @throws IllegalStateException if called from inside a push.
- */
- public final void setAttachmentFilters(Filter... filters) {
- checkAccess();
- filters = copyOf(filters, filters.length, Filter[].class);
- synchronized (this) {
- if (this.attachmentFormatters.length != filters.length) {
- throw attachmentMismatch(this.attachmentFormatters.length, filters.length);
- }
-
- if (isWriting) {
- throw new IllegalStateException();
- }
- this.attachmentFilters = filters;
- }
- }
-
- /**
- * Gets the attachment formatters. This Handler is using
- * attachments only if the returned array length is non zero.
- * @return a non null array of formatters.
- */
- public final Formatter[] getAttachmentFormatters() {
- Formatter[] formatters;
- synchronized (this) {
- formatters = this.attachmentFormatters;
- }
- return formatters.clone();
- }
-
- /**
- * Sets the attachment Formatter object for this handler.
- * The number of formatters determines the number of attachments per
- * email. This method should be the first attachment method called.
- * To remove all attachments, call this method with empty array.
- * @param formatters a non null array of formatters.
- * @throws SecurityException if a security manager exists and the
- * caller does not have LoggingPermission("control").
- * @throws NullPointerException if the given array or any array index is
- * null.
- * @throws IllegalStateException if called from inside a push.
- */
- public final void setAttachmentFormatters(Formatter... formatters) {
- checkAccess();
- if (formatters.length == 0) { //Null check and length check.
- formatters = emptyFormatterArray();
- } else {
- formatters = copyOf(formatters,
- formatters.length, Formatter[].class);
- for (int i = 0; i < formatters.length; ++i) {
- if (formatters[i] == null) {
- throw new NullPointerException(atIndexMsg(i));
- }
- }
- }
-
- synchronized (this) {
- if (isWriting) {
- throw new IllegalStateException();
- }
-
- this.attachmentFormatters = formatters;
- this.fixUpAttachmentFilters();
- this.fixUpAttachmentNames();
- }
- }
-
- /**
- * Gets the attachment name formatters.
- * If the attachment names were set using explicit names then
- * the names can be returned by calling toString on each
- * attachment name formatter.
- * @return non null array of attachment name formatters.
- */
- public final Formatter[] getAttachmentNames() {
- final Formatter[] formatters;
- synchronized (this) {
- formatters = this.attachmentNames;
- }
- return formatters.clone();
- }
-
- /**
- * Sets the attachment file name for each attachment. The caller must
- * ensure that the attachment file names do not contain any line breaks.
- * This method will create a set of custom formatters.
- * @param names an array of names.
- * @throws SecurityException if a security manager exists and the
- * caller does not have LoggingPermission("control").
- * @throws IndexOutOfBoundsException if the number of attachment
- * names do not match the number of attachment formatters.
- * @throws IllegalArgumentException if any name is empty.
- * @throws NullPointerException if any given array or name is null.
- * @throws IllegalStateException if called from inside a push.
- * @see Character#isISOControl(char)
- * @see Character#isISOControl(int)
- */
- public final void setAttachmentNames(final String... names) {
- checkAccess();
-
- final Formatter[] formatters;
- if (names.length == 0) {
- formatters = emptyFormatterArray();
- } else {
- formatters = new Formatter[names.length];
- }
-
- for (int i = 0; i < names.length; ++i) {
- final String name = names[i];
- if (name != null) {
- if (name.length() > 0) {
- formatters[i] = new TailNameFormatter(name);
- } else {
- throw new IllegalArgumentException(atIndexMsg(i));
- }
- } else {
- throw new NullPointerException(atIndexMsg(i));
- }
- }
-
- synchronized (this) {
- if (this.attachmentFormatters.length != names.length) {
- throw attachmentMismatch(this.attachmentFormatters.length, names.length);
- }
-
- if (isWriting) {
- throw new IllegalStateException();
- }
- this.attachmentNames = formatters;
- }
- }
-
- /**
- * Sets the attachment file name formatters. The format method of each
- * attachment formatter will see only the LogRecord objects that
- * passed its attachment filter during formatting. The format method will
- * typically return an empty string. Instead of being used to format
- * records, it is used to gather information about the contents of an
- * attachment. The getTail method should be used to construct the
- * attachment file name and reset any formatter collected state. The
- * formatter must ensure that the attachment file name does not contain any
- * line breaks. The toString method of the given formatter should
- * be overridden to provide a useful attachment file name, if possible.
- * @param formatters and array of attachment name formatters.
- * @throws SecurityException if a security manager exists and the
- * caller does not have LoggingPermission("control").
- * @throws IndexOutOfBoundsException if the number of attachment
- * name formatters do not match the number of attachment formatters.
- * @throws NullPointerException if any given array or name is null.
- * @throws IllegalStateException if called from inside a push.
- * @see Character#isISOControl(char)
- * @see Character#isISOControl(int)
- */
- public final void setAttachmentNames(Formatter... formatters) {
- checkAccess();
-
- formatters = copyOf(formatters, formatters.length, Formatter[].class);
- for (int i = 0; i < formatters.length; ++i) {
- if (formatters[i] == null) {
- throw new NullPointerException(atIndexMsg(i));
- }
- }
-
- synchronized (this) {
- if (this.attachmentFormatters.length != formatters.length) {
- throw attachmentMismatch(this.attachmentFormatters.length, formatters.length);
- }
-
- if (isWriting) {
- throw new IllegalStateException();
- }
-
- this.attachmentNames = formatters;
- }
- }
-
- /**
- * Gets the formatter used to create the subject line.
- * If the subject was created using a literal string then
- * the toString method can be used to get the subject line.
- * @return the formatter.
- */
- public final synchronized Formatter getSubject() {
- return this.subjectFormatter;
- }
-
- /**
- * Sets a literal string for the email subject. The caller must ensure that
- * the subject line does not contain any line breaks.
- * @param subject a non null string.
- * @throws SecurityException if a security manager exists and the
- * caller does not have LoggingPermission("control").
- * @throws NullPointerException if subject is null.
- * @throws IllegalStateException if called from inside a push.
- * @see Character#isISOControl(char)
- * @see Character#isISOControl(int)
- */
- public final void setSubject(final String subject) {
- if (subject != null) {
- this.setSubject(new TailNameFormatter(subject));
- } else {
- checkAccess();
- throw new NullPointerException();
- }
- }
-
- /**
- * Sets the subject formatter for email. The format method of the subject
- * formatter will see all LogRecord objects that were published to
- * this Handler during formatting and will typically return an
- * empty string. This formatter is used to gather information to create a
- * summary about what information is contained in the email. The
- * getTail method should be used to construct the subject and reset
- * any formatter collected state. The formatter must ensure that the
- * subject line does not contain any line breaks. The toString
- * method of the given formatter should be overridden to provide a useful
- * subject, if possible.
- * @param format the subject formatter.
- * @throws SecurityException if a security manager exists and the
- * caller does not have LoggingPermission("control").
- * @throws NullPointerException if format is null.
- * @throws IllegalStateException if called from inside a push.
- * @see Character#isISOControl(char)
- * @see Character#isISOControl(int)
- */
- public final void setSubject(final Formatter format) {
- checkAccess();
- if (format == null) {
- throw new NullPointerException();
- }
-
- synchronized (this) {
- if (isWriting) {
- throw new IllegalStateException();
- }
- this.subjectFormatter = format;
- }
- }
-
- /**
- * Protected convenience method to report an error to this Handler's
- * ErrorManager. This method will prefix all non null error messages with
- * Level.SEVERE.getName(). This allows the receiving error
- * manager to determine if the msg parameter is a simple error
- * message or a raw email message.
- * @param msg a descriptive string (may be null)
- * @param ex an exception (may be null)
- * @param code an error code defined in ErrorManager
- */
- @Override
- protected void reportError(String msg, Exception ex, int code) {
- if (msg != null) {
- super.reportError(Level.SEVERE.getName() + ": " + msg, ex, code);
- } else {
- super.reportError(null, ex, code);
- }
- }
-
- /**
- * Calls log manager checkAccess if this is sealed.
- */
- final void checkAccess() {
- if (sealed) {
- LogManagerProperties.getLogManager().checkAccess();
- }
- }
-
- /**
- * Determines the mimeType of a formatter from the getHead call.
- * This could be made protected, or a new class could be created to do
- * this type of conversion. Currently, this is only used for the body
- * since the attachments are computed by filename.
- * Package-private for unit testing.
- * @param head any head string.
- * @return return the mime type or null for text/plain.
- */
- final String contentTypeOf(String head) {
- if (!isEmpty(head)) {
- final int MAX_CHARS = 25;
- if (head.length() > MAX_CHARS) {
- head = head.substring(0, MAX_CHARS);
- }
- try {
- final String encoding = getEncodingName();
- final ByteArrayInputStream in
- = new ByteArrayInputStream(head.getBytes(encoding));
-
- assert in.markSupported() : in.getClass().getName();
- return URLConnection.guessContentTypeFromStream(in);
- } catch (final IOException IOE) {
- reportError(IOE.getMessage(), IOE, ErrorManager.FORMAT_FAILURE);
- }
- }
- return null; //text/plain
- }
-
- /**
- * Determines if the given throwable is a no content exception.
- * Package-private for unit testing.
- * @param msg the message without content.
- * @param t the throwable to test.
- * @return true if the throwable is a missing content exception.
- * @throws NullPointerException if any of the arguments are null.
- * @since JavaMail 1.4.5
- */
- final boolean isMissingContent(Message msg, Throwable t) {
- for (Throwable cause = t.getCause(); cause != null;) {
- t = cause;
- cause = cause.getCause();
- }
-
- try {
- msg.writeTo(new ByteArrayOutputStream(MIN_HEADER_SIZE));
- } catch (final RuntimeException RE) {
- throw RE; //Avoid catch all.
- } catch (final Exception noContent) {
- final String txt = noContent.getMessage();
- if (!isEmpty(txt) && noContent.getClass() == t.getClass()) {
- return txt.equals(t.getMessage());
- }
- }
- return false;
- }
-
- /**
- * Converts a mime message to a raw string or formats the reason
- * why message can't be changed to raw string and reports it.
- * @param msg the mime message.
- * @param ex the original exception.
- * @param code the ErrorManager code.
- * @since JavaMail 1.4.5
- */
- private void reportError(Message msg, Exception ex, int code) {
- try { //Use super call so we do not prefix raw email.
- super.reportError(toRawString(msg), ex, code);
- } catch (final MessagingException rawMe) {
- reportError(toMsgString(rawMe), ex, code);
- } catch (final IOException rawIo) {
- reportError(toMsgString(rawIo), ex, code);
- }
- }
-
- /**
- * Determines the mimeType from the given file name.
- * Used to override the body content type and used for all attachments.
- * @param name the file name or class name.
- * @return the mime type or null for text/plain.
- */
- private String getContentType(final String name) {
- assert Thread.holdsLock(this);
- final String type = contentTypes.getContentType(name);
- if ("application/octet-stream".equalsIgnoreCase(type)) {
- return null; //Formatters return strings, default to text/plain.
- }
- return type;
- }
-
- /**
- * Gets the encoding set for this handler, mime encoding, or file encoding.
- * @return the java charset name, never null.
- * @since JavaMail 1.4.5
- */
- private String getEncodingName() {
- String encoding = getEncoding();
- if (encoding == null) {
- encoding = MimeUtility.getDefaultJavaCharset();
- }
- return encoding;
- }
-
- /**
- * Set the content for a part using the encoding assigned to the handler.
- * @param part the part to assign.
- * @param buf the formatted data.
- * @param type the mime type.
- * @throws MessagingException if there is a problem.
- */
- private void setContent(MimeBodyPart part, CharSequence buf, String type) throws MessagingException {
- final String encoding = getEncodingName();
- if (type != null && !"text/plain".equalsIgnoreCase(type)) {
- type = contentWithEncoding(type, encoding);
- try {
- DataSource source = new ByteArrayDataSource(buf.toString(), type);
- part.setDataHandler(new DataHandler(source));
- } catch (final IOException IOE) {
- reportError(IOE.getMessage(), IOE, ErrorManager.FORMAT_FAILURE);
- part.setText(buf.toString(), encoding);
- }
- } else {
- part.setText(buf.toString(), MimeUtility.mimeCharset(encoding));
- }
- }
-
- /**
- * Replaces the charset parameter with the current encoding.
- * @param type the content type.
- * @param encoding the java charset name.
- * @return the type with a specified encoding.
- */
- private String contentWithEncoding(String type, String encoding) {
- assert encoding != null;
- try {
- final ContentType ct = new ContentType(type);
- ct.setParameter("charset", MimeUtility.mimeCharset(encoding));
- encoding = ct.toString(); //See javax.mail.internet.ContentType.
- if (!isEmpty(encoding)) {
- type = encoding;
- }
- } catch (final MessagingException ME) {
- reportError(type, ME, ErrorManager.FORMAT_FAILURE);
- }
- return type;
- }
-
- /**
- * Sets the capacity for this handler. This method is kept private
- * because we would have to define a public policy for when the size is
- * greater than the capacity.
- * I.E. do nothing, flush now, truncate now, push now and resize.
- * @param newCapacity the max number of records.
- * @throws IllegalStateException if called from inside a push.
- */
- private synchronized void setCapacity0(final int newCapacity) {
- if (newCapacity <= 0) {
- throw new IllegalArgumentException("Capacity must be greater than zero.");
- }
-
- if (isWriting) {
- throw new IllegalStateException();
- }
-
- if (this.capacity < 0) { //If closed, remain closed.
- this.capacity = -newCapacity;
- } else {
- this.capacity = newCapacity;
- }
- }
-
- /**
- * Gets the attachment filters under a lock. The attachment filters
- * are treated as copy-on-write, so the returned array must never be
- * modified or published outside this class.
- * @return a read only array of filters.
- */
- private synchronized Filter[] readOnlyAttachmentFilters() {
- return this.attachmentFilters;
- }
-
- /**
- * Factory for empty formatter arrays.
- * @return an empty array.
- */
- private static Formatter[] emptyFormatterArray() {
- return EMPTY_FORMATTERS;
- }
-
- /**
- * Factory for empty filter arrays.
- * @return an empty array.
- */
- private static Filter[] emptyFilterArray() {
- return EMPTY_FILTERS;
- }
-
- /**
- * Expand or shrink the attachment name formatters.
- * @return true if fixed.
- */
- private boolean fixUpAttachmentNames() {
- assert Thread.holdsLock(this);
- boolean fixed = false;
- final int expect = this.attachmentFormatters.length;
- final int current = this.attachmentNames.length;
- if (current != expect) {
- this.attachmentNames = copyOf(attachmentNames, expect);
- fixed = current != 0;
- }
-
- //Copy of zero length array is cheap, warm up copyOf.
- if (expect == 0) {
- this.attachmentNames = emptyFormatterArray();
- assert this.attachmentNames.length == 0;
- } else {
- for (int i = 0; i < expect; ++i) {
- if (this.attachmentNames[i] == null) {
- this.attachmentNames[i] = new TailNameFormatter(
- toString(this.attachmentFormatters[i]));
- }
- }
- }
- return fixed;
- }
-
- /**
- * Expand or shrink the attachment filters.
- * @return true if fixed.
- */
- private boolean fixUpAttachmentFilters() {
- assert Thread.holdsLock(this);
-
- boolean fixed = false;
- final int expect = this.attachmentFormatters.length;
- final int current = this.attachmentFilters.length;
- if (current != expect) {
- this.attachmentFilters = copyOf(attachmentFilters, expect);
- fixed = current != 0;
-
- //Array elements default to null so skip filling if body filter
- //is null. If not null then only assign to expanded elements.
- final Filter body = super.getFilter();
- if (body != null) {
- for (int i = current; i < expect; ++i) {
- this.attachmentFilters[i] = body;
- }
- }
- }
-
- //Copy of zero length array is cheap, warm up copyOf.
- if (expect == 0) {
- this.attachmentFilters = emptyFilterArray();
- assert this.attachmentFilters.length == 0;
- }
- return fixed;
- }
-
- /**
- * Copies the given array. Can be removed when Java Mail requires Java 1.6.
- * @param a the original array.
- * @param len the new size.
- * @return new copy
- */
- private static T[] copyOf(final T[] a, final int len) {
- return (T[]) copyOf(a, len, a.getClass());
- }
-
- /**
- * Copies the given array to a new array type.
- * Can be removed when Java Mail requires Java 1.6.
- * @param a the original array.
- * @param len the new size.
- * @param type the array type.
- * @return new copy
- */
- private static T[] copyOf(U[] a, int len, Class extends T[]> type) {
- final T[] copy = (T[]) Array.newInstance(type.getComponentType(), len);
- System.arraycopy(a, 0, copy, 0, Math.min(len, a.length));
- return copy;
- }
-
- /**
- * Sets the size to zero and clears the current buffer.
- */
- private void reset() {
- assert Thread.holdsLock(this);
- if (size < data.length) {
- Arrays.fill(data, 0, size, null);
- } else {
- Arrays.fill(data, null);
- }
- this.size = 0;
- }
-
- /**
- * Expands the internal buffer up to the capacity.
- */
- private void grow() {
- assert Thread.holdsLock(this);
- final int len = data.length;
- int newCapacity = len + (len >> 1) + 1;
- if (newCapacity > capacity || newCapacity < len) {
- newCapacity = capacity;
- }
- assert len != capacity : len;
- this.data = copyOf(data, newCapacity);
- }
-
- /**
- * Configures the handler properties from the log manager.
- * @param props the given mail properties. Maybe null and are never
- * captured by this handler.
- * @throws SecurityException if a security manager exists and the
- * caller does not have LoggingPermission("control").
- */
- private synchronized void init(final Properties props) {
- final LogManager manager = LogManagerProperties.getLogManager();
- final String p = getClass().getName();
- this.mailProps = new Properties(); //See method comments.
- this.contentTypes = FileTypeMap.getDefaultFileTypeMap();
-
- //Assign any custom error manager first so it can detect all failures.
- initErrorManager(manager, p);
-
- initLevel(manager, p);
- initFilter(manager, p);
- initCapacity(manager, p);
- initAuthenticator(manager, p);
-
- initEncoding(manager, p);
- initFormatter(manager, p);
- initComparator(manager, p);
- initPushLevel(manager, p);
- initPushFilter(manager, p);
-
- initSubject(manager, p);
-
- initAttachmentFormaters(manager, p);
- initAttachmentFilters(manager, p);
- initAttachmentNames(manager, p);
-
- if (props == null && manager.getProperty(p.concat(".verify")) != null) {
- verifySettings(initSession());
- }
- intern(); //Show verify warnings first.
- }
-
- /**
- * Interns the error manager, formatters, and filters contained in this
- * handler. The comparator is not interned. This method can only be
- * called from init after all of formatters and filters are in a constructed
- * and in a consistent state.
- * @since JavaMail 1.5.0
- */
- private void intern() {
- assert Thread.holdsLock(this);
- try {
- Object canidate;
- Object result;
- final Map