You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by jl...@apache.org on 2020/10/07 15:58:41 UTC
svn commit: r1882306 [2/17] - in
/geronimo/javamail/trunk/geronimo-javamail_1.6: ./
geronimo-javamail_1.6_mail/ geronimo-javamail_1.6_mail/src/
geronimo-javamail_1.6_mail/src/site/ geronimo-javamail_1.6_provider/
geronimo-javamail_1.6_provider/src/ ger...
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/authentication/DigestMD5Authenticator.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/authentication/DigestMD5Authenticator.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/authentication/DigestMD5Authenticator.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/authentication/DigestMD5Authenticator.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,628 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.geronimo.javamail.authentication;
+
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+
+import javax.mail.AuthenticationFailedException;
+import javax.mail.MessagingException;
+
+import org.apache.geronimo.mail.util.Base64;
+import org.apache.geronimo.mail.util.Hex;
+
+/**
+ * Process a DIGEST-MD5 authentication, using the challenge/response mechanisms.
+ */
+public class DigestMD5Authenticator implements ClientAuthenticator {
+
+ protected static final int AUTHENTICATE_CLIENT = 0;
+
+ protected static final int AUTHENTICATE_SERVER = 1;
+
+ protected static final int AUTHENTICATION_COMPLETE = 2;
+
+ // the host server name
+ protected String host;
+
+ // the user we're authenticating
+ protected String username;
+
+ // the user's password (the "shared secret")
+ protected String password;
+
+ // the target login realm
+ protected String realm;
+
+ // our message digest for processing the challenges.
+ MessageDigest digest;
+
+ // the string we send to the server on the first challenge.
+ protected String clientResponse;
+
+ // the response back from an authentication challenge.
+ protected String authenticationResponse = null;
+
+ // our list of realms received from the server (normally just one).
+ protected ArrayList realms;
+
+ // the nonce value sent from the server
+ protected String nonce;
+
+ // indicates whether we've gone through the entire challenge process.
+ protected int stage = AUTHENTICATE_CLIENT;
+
+ /**
+ * Main constructor.
+ *
+ * @param host
+ * The server host name.
+ * @param username
+ * The login user name.
+ * @param password
+ * The login password.
+ * @param realm
+ * The target login realm (can be null).
+ */
+ public DigestMD5Authenticator(String host, String username, String password, String realm) {
+ this.host = host;
+ this.username = username;
+ this.password = password;
+ this.realm = realm;
+ }
+
+ /**
+ * Respond to the hasInitialResponse query. This mechanism does not have an
+ * initial response.
+ *
+ * @return Always returns false.
+ */
+ public boolean hasInitialResponse() {
+ return false;
+ }
+
+ /**
+ * Indicate whether the challenge/response process is complete.
+ *
+ * @return True if the last challenge has been processed, false otherwise.
+ */
+ public boolean isComplete() {
+ return stage == AUTHENTICATION_COMPLETE;
+ }
+
+ /**
+ * Retrieve the authenticator mechanism name.
+ *
+ * @return Always returns the string "DIGEST-MD5"
+ */
+ public String getMechanismName() {
+ return "DIGEST-MD5";
+ }
+
+ /**
+ * Evaluate a DIGEST-MD5 login challenge, returning the a result string that
+ * should satisfy the clallenge.
+ *
+ * @param challenge
+ * The decoded challenge data, as a string.
+ *
+ * @return A formatted challege response, as an array of bytes.
+ * @exception MessagingException
+ */
+ public byte[] evaluateChallenge(byte[] challenge) throws MessagingException {
+
+ // DIGEST-MD5 authentication goes in two stages. First state involves us
+ // validating with the
+ // server, the second stage is the server validating with us, using the
+ // shared secret.
+ switch (stage) {
+ // stage one of the process.
+ case AUTHENTICATE_CLIENT: {
+ // get the response and advance the processing stage.
+ byte[] response = authenticateClient(challenge);
+ stage = AUTHENTICATE_SERVER;
+ return response;
+ }
+
+ // stage two of the process.
+ case AUTHENTICATE_SERVER: {
+ // get the response and advance the processing stage to completed.
+ byte[] response = authenticateServer(challenge);
+ stage = AUTHENTICATION_COMPLETE;
+ return response;
+ }
+
+ // should never happen.
+ default:
+ throw new MessagingException("Invalid LOGIN challenge");
+ }
+ }
+
+ /**
+ * Evaluate a DIGEST-MD5 login server authentication challenge, returning
+ * the a result string that should satisfy the clallenge.
+ *
+ * @param challenge
+ * The decoded challenge data, as a string.
+ *
+ * @return A formatted challege response, as an array of bytes.
+ * @exception MessagingException
+ */
+ public byte[] authenticateServer(byte[] challenge) throws MessagingException {
+ // parse the challenge string and validate.
+ if (!parseChallenge(challenge)) {
+ return null;
+ }
+
+ try {
+ // like all of the client validation steps, the following is order
+ // critical.
+ // first add in the URI information.
+ digest.update((":smtp/" + host).getBytes("US-ASCII"));
+ // now mix in the response we sent originally
+ String responseString = clientResponse + new String(Hex.encode(digest.digest()), "US-ASCII");
+ digest.update(responseString.getBytes("US-ASCII"));
+
+ // now convert that into a hex encoded string.
+ String validationText = new String(Hex.encode(digest.digest()), "US-ASCII");
+
+ // if everything went well, this calculated value should match what
+ // we got back from the server.
+ // our response back is just a null string....
+ if (validationText.equals(authenticationResponse)) {
+ return new byte[0];
+ }
+ throw new AuthenticationFailedException("Invalid DIGEST-MD5 response from server");
+ } catch (UnsupportedEncodingException e) {
+ throw new MessagingException("Invalid character encodings");
+ }
+
+ }
+
+ /**
+ * Evaluate a DIGEST-MD5 login client authentication challenge, returning
+ * the a result string that should satisfy the clallenge.
+ *
+ * @param challenge
+ * The decoded challenge data, as a string.
+ *
+ * @return A formatted challege response, as an array of bytes.
+ * @exception MessagingException
+ */
+ public byte[] authenticateClient(byte[] challenge) throws MessagingException {
+ // parse the challenge string and validate.
+ if (!parseChallenge(challenge)) {
+ return null;
+ }
+
+ SecureRandom randomGenerator;
+ // before doing anything, make sure we can get the required crypto
+ // support.
+ try {
+ randomGenerator = new SecureRandom();
+ digest = MessageDigest.getInstance("MD5");
+ } catch (NoSuchAlgorithmException e) {
+ throw new MessagingException("Unable to access cryptography libraries");
+ }
+
+ // if not configured for a realm, take the first realm from the list, if
+ // any
+ if (realm == null) {
+ // if not handed any realms, just use the host name.
+ if (realms.isEmpty()) {
+ realm = host;
+ } else {
+ // pretty arbitrary at this point, so just use the first one.
+ realm = (String) realms.get(0);
+ }
+ }
+
+ // use secure random to generate a collection of bytes. that is our
+ // cnonce value.
+ byte[] cnonceBytes = new byte[32];
+
+ randomGenerator.nextBytes(cnonceBytes);
+
+ try {
+ // and get this as a base64 encoded string.
+ String cnonce = new String(Base64.encode(cnonceBytes), "US-ASCII");
+
+ // Now the digest computation part. This gets a bit tricky, and must be
+ // done in strict order.
+ // this identifies where we're logging into.
+ String idString = username + ":" + realm + ":" + password;
+ // we get a digest for this string, then use the digest for the
+ // first stage
+ // of the next digest operation.
+ digest.update(digest.digest(idString.getBytes("US-ASCII")));
+
+ // now we add the nonce strings to the digest.
+ String nonceString = ":" + nonce + ":" + cnonce;
+ digest.update(nonceString.getBytes("US-ASCII"));
+
+ // hex encode this digest, and add on the string values
+ // NB, we only support "auth" for the quality of protection value
+ // (qop). We save this in an
+ // instance variable because we'll need this to validate the
+ // response back from the server.
+ clientResponse = new String(Hex.encode(digest.digest()), "US-ASCII") + ":" + nonce + ":00000001:" + cnonce + ":auth:";
+
+ // now we add in identification values to the hash.
+ String authString = "AUTHENTICATE:smtp/" + host;
+ digest.update(authString.getBytes("US-ASCII"));
+
+ // this gets added on to the client response
+ String responseString = clientResponse + new String(Hex.encode(digest.digest()), "US-ASCII");
+ // and this gets fed back into the digest
+ digest.update(responseString.getBytes("US-ASCII"));
+
+ // and FINALLY, the challege digest is hex encoded for sending back
+ // to the server (whew).
+ String challengeResponse = new String(Hex.encode(digest.digest()), "US-ASCII");
+
+ // now finally build the keyword/value part of the challenge
+ // response. These can be
+ // in any order.
+ StringBuffer response = new StringBuffer();
+
+ response.append("username=\"");
+ response.append(username);
+ response.append("\"");
+
+ response.append(",realm=\"");
+ response.append(realm);
+ response.append("\"");
+
+ // we only support auth qop values, and the nonce-count (nc) is
+ // always 1.
+ response.append(",qop=auth");
+ response.append(",nc=00000001");
+
+ response.append(",nonce=\"");
+ response.append(nonce);
+ response.append("\"");
+
+ response.append(",cnonce=\"");
+ response.append(cnonce);
+ response.append("\"");
+
+ response.append(",digest-uri=\"smtp/");
+ response.append(host);
+ response.append("\"");
+
+ response.append(",response=");
+ response.append(challengeResponse);
+
+ return response.toString().getBytes("US-ASCII");
+
+ } catch (UnsupportedEncodingException e) {
+ throw new MessagingException("Invalid character encodings");
+ }
+ }
+
+ /**
+ * Parse the challege string, pulling out information required for our
+ * challenge response.
+ *
+ * @param challenge
+ * The challenge data.
+ *
+ * @return true if there were no errors parsing the string, false otherwise.
+ * @exception MessagingException
+ */
+ protected boolean parseChallenge(byte[] challenge) throws MessagingException {
+ realms = new ArrayList();
+
+ DigestParser parser = null;
+ try {
+ parser = new DigestParser(new String(challenge, "US-ASCII"));
+ } catch (UnsupportedEncodingException ex) {
+ }
+
+ // parse the entire string...but we ignore everything but the options we
+ // support.
+ while (parser.hasMore()) {
+ NameValuePair pair = parser.parseNameValuePair();
+
+ String name = pair.name;
+
+ // realm to add to our list?
+ if (name.equalsIgnoreCase("realm")) {
+ realms.add(pair.value);
+ }
+ // we need the nonce to evaluate the client challenge.
+ else if (name.equalsIgnoreCase("nonce")) {
+ nonce = pair.value;
+ }
+ // rspauth is the challenge replay back, which allows us to validate
+ // that server is also legit.
+ else if (name.equalsIgnoreCase("rspauth")) {
+ authenticationResponse = pair.value;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Inner class for parsing a DIGEST-MD5 challenge string, which is composed
+ * of "name=value" pairs, separated by "," characters.
+ */
+ class DigestParser {
+ // the challenge we're parsing
+ String challenge;
+
+ // length of the challenge
+ int length;
+
+ // current parsing position
+ int position;
+
+ /**
+ * Normal constructor.
+ *
+ * @param challenge
+ * The challenge string to be parsed.
+ */
+ public DigestParser(String challenge) {
+ this.challenge = challenge;
+ this.length = challenge.length();
+ position = 0;
+ }
+
+ /**
+ * Test if there are more values to parse.
+ *
+ * @return true if we've not reached the end of the challenge string,
+ * false if the challenge has been completely consumed.
+ */
+ private boolean hasMore() {
+ return position < length;
+ }
+
+ /**
+ * Return the character at the current parsing position.
+ *
+ * @return The string character for the current parse position.
+ */
+ private char currentChar() {
+ return challenge.charAt(position);
+ }
+
+ /**
+ * step forward to the next character position.
+ */
+ private void nextChar() {
+ position++;
+ }
+
+ /**
+ * Skip over any white space characters in the challenge string.
+ */
+ private void skipSpaces() {
+ while (position < length && Character.isWhitespace(currentChar())) {
+ position++;
+ }
+ }
+
+ /**
+ * Parse a quoted string used with a name/value pair, accounting for
+ * escape characters embedded within the string.
+ *
+ * @return The string value of the character string.
+ */
+ private String parseQuotedValue() {
+ // we're here because we found the starting double quote. Step over
+ // it and parse to the closing
+ // one.
+ nextChar();
+
+ StringBuffer value = new StringBuffer();
+
+ while (hasMore()) {
+ char ch = currentChar();
+
+ // is this an escape char?
+ if (ch == '\\') {
+ // step past this, and grab the following character
+ nextChar();
+ // we have an invalid quoted string....
+ if (!hasMore()) {
+ return null;
+ }
+ value.append(currentChar());
+ }
+ // end of the string?
+ else if (ch == '"') {
+ // step over this so the caller doesn't process it.
+ nextChar();
+ // return the constructed string.
+ return value.toString();
+ } else {
+ // step over the character and contine with the next
+ // characteer1
+ value.append(ch);
+ }
+ nextChar();
+ }
+ /* fell off the end without finding a closing quote! */
+ return null;
+ }
+
+ /**
+ * Parse a token value used with a name/value pair.
+ *
+ * @return The string value of the token. Returns null if nothing is
+ * found up to the separater.
+ */
+ private String parseTokenValue() {
+
+ StringBuffer value = new StringBuffer();
+
+ while (hasMore()) {
+ char ch = currentChar();
+ switch (ch) {
+ // process the token separators.
+ case ' ':
+ case '\t':
+ case '(':
+ case ')':
+ case '<':
+ case '>':
+ case '@':
+ case ',':
+ case ';':
+ case ':':
+ case '\\':
+ case '"':
+ case '/':
+ case '[':
+ case ']':
+ case '?':
+ case '=':
+ case '{':
+ case '}':
+ // no token characters found? this is bad.
+ if (value.length() == 0) {
+ return null;
+ }
+ // return the accumulated characters.
+ return value.toString();
+
+ default:
+ // is this a control character? That's a delimiter (likely
+ // invalid for the next step,
+ // but it is a token terminator.
+ if (ch < 32 || ch > 127) {
+ // no token characters found? this is bad.
+ if (value.length() == 0) {
+ return null;
+ }
+ // return the accumulated characters.
+ return value.toString();
+ }
+ value.append(ch);
+ break;
+ }
+ // step to the next character.
+ nextChar();
+ }
+ // no token characters found? this is bad.
+ if (value.length() == 0) {
+ return null;
+ }
+ // return the accumulated characters.
+ return value.toString();
+ }
+
+ /**
+ * Parse out a name token of a name/value pair.
+ *
+ * @return The string value of the name.
+ */
+ private String parseName() {
+ // skip to the value start
+ skipSpaces();
+
+ // the name is a token.
+ return parseTokenValue();
+ }
+
+ /**
+ * Parse out a a value of a name/value pair.
+ *
+ * @return The string value associated with the name.
+ */
+ private String parseValue() {
+ // skip to the value start
+ skipSpaces();
+
+ // start of a quoted string?
+ if (currentChar() == '"') {
+ // parse it out as a string.
+ return parseQuotedValue();
+ }
+ // the value must be a token.
+ return parseTokenValue();
+ }
+
+ /**
+ * Parse a name/value pair in an DIGEST-MD5 string.
+ *
+ * @return A NameValuePair object containing the two parts of the value.
+ * @exception MessagingException
+ */
+ public NameValuePair parseNameValuePair() throws MessagingException {
+ // get the name token
+ String name = parseName();
+ if (name == null) {
+ throw new MessagingException("Name syntax error");
+ }
+
+ // the name should be followed by an "=" sign
+ if (!hasMore() || currentChar() != '=') {
+ throw new MessagingException("Name/value pair syntax error");
+ }
+
+ // step over the equals
+ nextChar();
+
+ // now get the value part
+ String value = parseValue();
+ if (value == null) {
+ throw new MessagingException("Name/value pair syntax error");
+ }
+
+ // skip forward to the terminator, which should either be the end of
+ // the line or a ","
+ skipSpaces();
+ // all that work, only to have a syntax error at the end (sigh)
+ if (hasMore()) {
+ if (currentChar() != ',') {
+ throw new MessagingException("Name/value pair syntax error");
+ }
+ // step over, and make sure we position ourselves at either the
+ // end or the first
+ // real character for parsing the next name/value pair.
+ nextChar();
+ skipSpaces();
+ }
+ return new NameValuePair(name, value);
+ }
+ }
+
+ /**
+ * Simple inner class to represent a name/value pair.
+ */
+ public class NameValuePair {
+ public String name;
+
+ public String value;
+
+ NameValuePair(String name, String value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ }
+}
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/authentication/LoginAuthenticator.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/authentication/LoginAuthenticator.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/authentication/LoginAuthenticator.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/authentication/LoginAuthenticator.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.geronimo.javamail.authentication;
+
+import java.io.UnsupportedEncodingException;
+
+import javax.mail.MessagingException;
+
+public class LoginAuthenticator implements ClientAuthenticator {
+
+ // constants for the authentication stages
+ protected static final int USERNAME = 0;
+
+ protected static final int PASSWORD = 1;
+
+ protected static final int COMPLETE = 2;
+
+ // the user we're authenticating
+ protected String username;
+
+ // the user's password (the "shared secret")
+ protected String password;
+
+ // indicates whether we've gone through the entire challenge process.
+ protected int stage = USERNAME;
+
+ /**
+ * Main constructor.
+ *
+ * @param username
+ * The login user name.
+ * @param password
+ * The login password.
+ */
+ public LoginAuthenticator(String username, String password) {
+ this.username = username;
+ this.password = password;
+ }
+
+ /**
+ * Respond to the hasInitialResponse query. This mechanism does not have an
+ * initial response.
+ *
+ * @return Always returns false;
+ */
+ public boolean hasInitialResponse() {
+ return false;
+ }
+
+ /**
+ * Indicate whether the challenge/response process is complete.
+ *
+ * @return True if the last challenge has been processed, false otherwise.
+ */
+ public boolean isComplete() {
+ return stage == COMPLETE;
+ }
+
+ /**
+ * Retrieve the authenticator mechanism name.
+ *
+ * @return Always returns the string "LOGIN"
+ */
+ public String getMechanismName() {
+ return "LOGIN";
+ }
+
+ /**
+ * Evaluate a PLAIN login challenge, returning the a result string that
+ * should satisfy the clallenge.
+ *
+ * @param challenge
+ * The decoded challenge data, as a byte array
+ *
+ * @return A formatted challege response, as an array of bytes.
+ * @exception MessagingException
+ */
+ public byte[] evaluateChallenge(byte[] challenge) throws MessagingException {
+
+ // process the correct stage for the challenge
+ switch (stage) {
+ // should never happen
+ case COMPLETE:
+ throw new MessagingException("Invalid LOGIN challenge");
+
+ case USERNAME: {
+ byte[] userBytes;
+
+ try {
+ // get the username and password in an UTF-8 encoding to create
+ // the token
+ userBytes = username.getBytes("UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ // got an error, fail this (this should never happen).
+ throw new MessagingException("Invalid encoding");
+ }
+
+ // next time through we're looking for a password.
+ stage = PASSWORD;
+ // the user bytes are the entire challenge respose.
+ return userBytes;
+ }
+
+ case PASSWORD: {
+ byte[] passBytes;
+
+ try {
+ // get the username and password in an UTF-8 encoding to create
+ // the token
+ passBytes = password.getBytes("UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ // got an error, fail this (this should never happen).
+ throw new MessagingException("Invalid encoding");
+ }
+ // we're finished
+ stage = COMPLETE;
+ return passBytes;
+ }
+ }
+ // should never get here.
+ throw new MessagingException("Invalid LOGIN challenge");
+ }
+}
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/authentication/PlainAuthenticator.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/authentication/PlainAuthenticator.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/authentication/PlainAuthenticator.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/authentication/PlainAuthenticator.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.geronimo.javamail.authentication;
+
+import java.io.UnsupportedEncodingException;
+
+import javax.mail.MessagingException;
+
+//Implements RFC 4616 PLAIN SASL mechanism
+//See also RFC 3501, section 6.2.2"
+//an RFC 2595, section 6"
+public class PlainAuthenticator implements ClientAuthenticator {
+
+ // the sasl authzid we're authenticating
+ protected String authzid;
+
+ // the user we're authenticating
+ protected String username;
+
+ // the user's password (the "shared secret")
+ protected String password;
+
+ // indicates whether we've gone through the entire challenge process.
+ protected boolean complete = false;
+
+ /**
+ * Main constructor.
+ *
+ * @param authzid
+ * SASL authenticationid (optional)
+ * @param username
+ * The login user name.
+ * @param password
+ * The login password.
+ */
+ public PlainAuthenticator(String authzid, String username, String password) {
+ this.authzid = authzid;
+ this.username = username;
+ this.password = password;
+ }
+
+ /**
+ * Constructor without authzid
+ *
+ * @param username
+ * The login user name.
+ * @param password
+ * The login password.
+ */
+ public PlainAuthenticator(String username, String password) {
+ this(null, username, password);
+ }
+
+ /**
+ * Respond to the hasInitialResponse query. This mechanism does have an
+ * initial response, which is the entire challenge sequence.
+ *
+ * @return Always returns true.
+ */
+ public boolean hasInitialResponse() {
+ return true;
+ }
+
+ /**
+ * Indicate whether the challenge/response process is complete.
+ *
+ * @return True if the last challenge has been processed, false otherwise.
+ */
+ public boolean isComplete() {
+ return complete;
+ }
+
+ /**
+ * Retrieve the authenticator mechanism name.
+ *
+ * @return Always returns the string "PLAIN"
+ */
+ public String getMechanismName() {
+ return "PLAIN";
+ }
+
+ /**
+ * Evaluate a PLAIN login challenge, returning the a result string that
+ * should satisfy the challenge.
+ *
+ * @param challenge
+ * For PLAIN Authentication there is no challenge (so this is unused)
+ *
+ * @return A formatted challenge response, as an array of bytes.
+ * @exception MessagingException
+ */
+ public byte[] evaluateChallenge(byte[] challenge) throws MessagingException {
+ try {
+
+ String result = "\0"+username+"\0"+password;
+
+ if(authzid != null && authzid.length() > 0) {
+ result = authzid+result;
+ }
+
+ complete = true;
+ return result.getBytes("UTF-8");
+
+ } catch (UnsupportedEncodingException e) {
+ // got an error, fail this
+ throw new MessagingException("Invalid encoding");
+ }
+ }
+}
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/authentication/SASLAuthenticator.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/authentication/SASLAuthenticator.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/authentication/SASLAuthenticator.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/authentication/SASLAuthenticator.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.geronimo.javamail.authentication;
+
+import java.io.UnsupportedEncodingException ;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.mail.MessagingException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.RealmCallback;
+import javax.security.sasl.RealmChoiceCallback;
+
+public class SASLAuthenticator implements ClientAuthenticator, CallbackHandler {
+ // The realm we're authenticating within
+ protected String realm;
+ // the user we're authenticating
+ protected String username;
+ // the user's password (the "shared secret")
+ protected String password;
+ // the authenticator we're proxying
+ protected SaslClient authenticator;
+
+ protected boolean complete = false;
+
+ /**
+ * Main constructor.
+ *
+ * @param username
+ * The login user name.
+ * @param password
+ * The login password.
+ */
+ public SASLAuthenticator(String[] mechanisms, Properties properties, String protocol, String host, String realm,
+ String authorizationID, String username, String password) throws MessagingException {
+ this.realm = realm;
+ this.username = username;
+ this.password = password;
+ try {
+ authenticator = Sasl.createSaslClient(mechanisms, authorizationID, protocol, host, (Map)properties,
+ this);
+ } catch (SaslException e) {
+ }
+ }
+
+
+ /**
+ * Respond to the hasInitialResponse query. We defer this to the Sasl client.
+ *
+ * @return The SaslClient response to the same query.
+ */
+ public boolean hasInitialResponse() {
+ return authenticator.hasInitialResponse();
+ }
+
+ /**
+ * Indicate whether the challenge/response process is complete.
+ *
+ * @return True if the last challenge has been processed, false otherwise.
+ */
+ public boolean isComplete() {
+ return authenticator.hasInitialResponse();
+ }
+
+ /**
+ * Retrieve the authenticator mechanism name.
+ *
+ * @return Always returns the string "PLAIN"
+ */
+ public String getMechanismName() {
+ // the authenticator selects this for us.
+ return authenticator.getMechanismName();
+ }
+
+ /**
+ * Evaluate a login challenge, returning the a result string that
+ * should satisfy the clallenge. This is forwarded to the
+ * SaslClient, which will use the CallBackHandler to retrieve the
+ * information it needs for the given protocol.
+ *
+ * @param challenge
+ * The decoded challenge data, as byte array.
+ *
+ * @return A formatted challege response, as an array of bytes.
+ * @exception MessagingException
+ */
+ public byte[] evaluateChallenge(byte[] challenge) throws MessagingException {
+ // for an initial response challenge, there's no challenge date. The SASL
+ // client still expects a byte array argument.
+ if (challenge == null) {
+ challenge = new byte[0];
+ }
+
+ try {
+ return authenticator.evaluateChallenge(challenge);
+ } catch (SaslException e) {
+ // got an error, fail this
+ throw new MessagingException("Error performing SASL validation", e);
+ }
+ }
+
+ public void handle(Callback[] callBacks) {
+ for (int i = 0; i < callBacks.length; i++) {
+ Callback callBack = callBacks[i];
+ // requesting the user name
+ if (callBack instanceof NameCallback) {
+ ((NameCallback)callBack).setName(username);
+ }
+ // need the password
+ else if (callBack instanceof PasswordCallback) {
+ ((PasswordCallback)callBack).setPassword(password.toCharArray());
+ }
+ // direct request for the realm information
+ else if (callBack instanceof RealmCallback) {
+ RealmCallback realmCallback = (RealmCallback)callBack;
+ // we might not have a realm, so use the default from the
+ // callback item
+ if (realm == null) {
+ realmCallback.setText(realmCallback.getDefaultText());
+ }
+ else {
+ realmCallback.setText(realm);
+ }
+ }
+ // asked to select the realm information from a list
+ else if (callBack instanceof RealmChoiceCallback) {
+ RealmChoiceCallback realmCallback = (RealmChoiceCallback)callBack;
+ // if we don't have a realm, just tell it to use the default
+ if (realm == null) {
+ realmCallback.setSelectedIndex(realmCallback.getDefaultChoice());
+ }
+ else {
+ // locate our configured one in the list
+ String[] choices = realmCallback.getChoices();
+
+ for (int j = 0; j < choices.length; j++) {
+ // set the index to any match and get out of here.
+ if (choices[j].equals(realm)) {
+ realmCallback.setSelectedIndex(j);
+ break;
+ }
+ }
+ // NB: If there was no match, we don't set anything.
+ // this should cause an authentication failure.
+ }
+ }
+ }
+ }
+}
+
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/authentication/XOAUTH2Authenticator.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/authentication/XOAUTH2Authenticator.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/authentication/XOAUTH2Authenticator.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/authentication/XOAUTH2Authenticator.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,102 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.geronimo.javamail.authentication;
+
+import javax.mail.MessagingException;
+import java.io.UnsupportedEncodingException;
+import java.util.Properties;
+
+public class XOAUTH2Authenticator implements ClientAuthenticator {
+
+ //The user we're authenticating
+ protected String username;
+ //The user's password (the "shared secret")
+ protected String password;
+ protected boolean complete = false;
+
+ /**
+ * Main constructor.
+ *
+ * @param username The login user name.
+ * @param password The Oauth2 token.
+ */
+ public XOAUTH2Authenticator(String[] mechanisms, Properties properties, String protocol, String host, String realm,
+ String authorizationID, String username, String password) throws MessagingException {
+ this.username = username;
+ this.password = password;
+ }
+
+ /**
+ * Respond to the hasInitialResponse query.
+ *
+ * @return The SaslClient response to the same query.
+ */
+ public boolean hasInitialResponse() {
+ return true;
+ }
+
+ /**
+ * Indicate whether the challenge/response process is complete.
+ *
+ * @return True if the last challenge has been processed, false otherwise.
+ */
+ public boolean isComplete() {
+ return complete;
+ }
+
+ /**
+ * Retrieve the authenticator mechanism name.
+ *
+ * @return Will returns the string "XOAUTH2"
+ */
+ public String getMechanismName() {
+ return "XOAUTH2";
+ }
+
+ /**
+ * Evaluate a login challenge, returning the a result string that
+ * should satisfy the challenge. This use the CallBackHandler to retrieve the
+ * information it needs for the given protocol.
+ *
+ * @param challenge The decoded challenge data, as byte array.
+ * @return A formatted challenge response, as an array of bytes.
+ * @throws MessagingException
+ */
+ public byte[] evaluateChallenge(final byte[] challenge) throws MessagingException{
+ if (complete) {
+ return new byte[0];
+ }
+
+ final String response = new StringBuilder()
+ .append("user=")
+ .append(this.username)
+ .append("\001auth=Bearer ")
+ .append(this.password)
+ .append("\001\001")
+ .toString();
+
+
+ complete = true;
+
+ try {
+ return response.getBytes("UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new MessagingException("Invalid encoding");
+ }
+ }
+}
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/AbstractImageHandler.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/AbstractImageHandler.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/AbstractImageHandler.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/AbstractImageHandler.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,91 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geronimo.javamail.handlers;
+
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.awt.image.BufferedImage;
+import java.awt.image.RenderedImage;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Iterator;
+import javax.activation.ActivationDataFlavor;
+import javax.activation.DataContentHandler;
+import javax.activation.DataSource;
+import javax.activation.UnsupportedDataTypeException;
+import javax.imageio.IIOImage;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.ImageWriter;
+import javax.imageio.stream.ImageInputStream;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class AbstractImageHandler implements DataContentHandler {
+ private final ActivationDataFlavor flavour;
+
+ public AbstractImageHandler(ActivationDataFlavor flavour) {
+ this.flavour = flavour;
+ }
+
+ public DataFlavor[] getTransferDataFlavors() {
+ return new DataFlavor[]{flavour};
+ }
+
+ public Object getTransferData(DataFlavor dataFlavor, DataSource dataSource) throws UnsupportedFlavorException, IOException {
+ return flavour.equals(dataFlavor) ? getContent(dataSource) : null;
+ }
+
+ public Object getContent(DataSource ds) throws IOException {
+ Iterator i = ImageIO.getImageReadersByMIMEType(flavour.getMimeType());
+ if (!i.hasNext()) {
+ throw new UnsupportedDataTypeException("Unknown image type " + flavour.getMimeType());
+ }
+ ImageReader reader = (ImageReader) i.next();
+ ImageInputStream iis = ImageIO.createImageInputStream(ds.getInputStream());
+ reader.setInput(iis);
+ return reader.read(0);
+ }
+
+ public void writeTo(Object obj, String mimeType, OutputStream os) throws IOException {
+ Iterator i = ImageIO.getImageWritersByMIMEType(flavour.getMimeType());
+ if (!i.hasNext()) {
+ throw new UnsupportedDataTypeException("Unknown image type " + flavour.getMimeType());
+ }
+ ImageWriter writer = (ImageWriter) i.next();
+ writer.setOutput(ImageIO.createImageOutputStream(os));
+
+ if (obj instanceof RenderedImage) {
+ writer.write((RenderedImage) obj);
+ } else if (obj instanceof BufferedImage) {
+ BufferedImage buffered = (BufferedImage) obj;
+ writer.write(new IIOImage(buffered.getRaster(), null, null));
+ } else if (obj instanceof Image) {
+ Image image = (Image) obj;
+ BufferedImage buffered = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
+ Graphics2D graphics = buffered.createGraphics();
+ graphics.drawImage(image, 0, 0, null, null);
+ writer.write(new IIOImage(buffered.getRaster(), null, null));
+ } else {
+ throw new UnsupportedDataTypeException("Unknown image type " + obj.getClass().getName());
+ }
+ os.flush();
+ }
+}
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/AbstractTextHandler.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/AbstractTextHandler.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/AbstractTextHandler.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/AbstractTextHandler.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,134 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geronimo.javamail.handlers;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+
+import javax.activation.DataContentHandler;
+import javax.activation.DataSource;
+
+import javax.mail.internet.ContentType;
+import javax.mail.internet.MimeUtility;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class AbstractTextHandler implements DataContentHandler {
+ private final DataFlavor flavour;
+
+ public AbstractTextHandler(DataFlavor flavour) {
+ this.flavour = flavour;
+ }
+
+ public DataFlavor[] getTransferDataFlavors() {
+ return new DataFlavor[] {flavour};
+ }
+
+ public Object getTransferData(DataFlavor dataFlavor, DataSource dataSource) throws UnsupportedFlavorException, IOException {
+ return flavour.equals(dataFlavor) ? getContent(dataSource) : null;
+ }
+
+ /**
+ * Read the content from the DataSource and transform
+ * it into a text object (String).
+ *
+ * @param ds The source DataSource.
+ *
+ * @return The content object.
+ * @exception IOException
+ */
+ public Object getContent(DataSource ds) throws IOException {
+ InputStream is = ds.getInputStream();
+ InputStreamReader reader;
+ // process any encoding to make sure the chars get transformed into the
+ // correct byte types.
+ try {
+ String charset = getCharSet(ds.getContentType());
+ reader = new InputStreamReader(is, charset);
+ } catch (Exception ex) {
+ throw new UnsupportedEncodingException(ex.toString());
+ }
+ StringBuffer result = new StringBuffer(1024);
+ char[] buffer = new char[32768];
+ int count;
+ while ((count = reader.read(buffer)) > 0) {
+ result.append(buffer, 0, count);
+ }
+ return result.toString();
+ }
+
+
+ /**
+ * Write an object of "our" type out to the provided
+ * output stream. The content type might modify the
+ * result based on the content type parameters.
+ *
+ * @param object The object to write.
+ * @param contentType
+ * The content mime type, including parameters.
+ * @param outputstream
+ * The target output stream.
+ *
+ * @throws IOException
+ */
+ public void writeTo(Object o, String contentType, OutputStream outputstream) throws IOException {
+ String s;
+ if (o instanceof String) {
+ s = (String) o;
+ } else if (o != null) {
+ s = o.toString();
+ } else {
+ return;
+ }
+ // process any encoding to make sure the chars get transformed into the
+ // correct byte types.
+ OutputStreamWriter writer;
+ try {
+ String charset = getCharSet(contentType);
+ writer = new OutputStreamWriter(outputstream, charset);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ throw new UnsupportedEncodingException(ex.toString());
+ }
+ writer.write(s);
+ writer.flush();
+ }
+
+
+ /**
+ * get the character set from content type
+ * @param contentType
+ * @return
+ * @throws ParseException
+ */
+ protected String getCharSet(String contentType) throws Exception {
+ ContentType type = new ContentType(contentType);
+ String charset = type.getParameter("charset");
+ if (charset == null) {
+ charset = "us-ascii";
+ }
+ return MimeUtility.javaCharset(charset);
+ }
+}
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/ImageGifHandler.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/ImageGifHandler.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/ImageGifHandler.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/ImageGifHandler.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,29 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geronimo.javamail.handlers;
+
+import java.awt.Image;
+import javax.activation.ActivationDataFlavor;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ImageGifHandler extends AbstractImageHandler {
+ public ImageGifHandler() {
+ super(new ActivationDataFlavor(Image.class, "image/gif", "GIF Image"));
+ }
+}
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/ImageJpegHandler.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/ImageJpegHandler.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/ImageJpegHandler.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/ImageJpegHandler.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,29 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geronimo.javamail.handlers;
+
+import java.awt.Image;
+import javax.activation.ActivationDataFlavor;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ImageJpegHandler extends AbstractImageHandler {
+ public ImageJpegHandler() {
+ super(new ActivationDataFlavor(Image.class, "image/jpeg", "JPEG Image"));
+ }
+}
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/MultipartHandler.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/MultipartHandler.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/MultipartHandler.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/MultipartHandler.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,65 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geronimo.javamail.handlers;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
+import java.io.OutputStream;
+import javax.activation.ActivationDataFlavor;
+import javax.activation.DataContentHandler;
+import javax.activation.DataSource;
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMultipart;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class MultipartHandler implements DataContentHandler {
+ private final DataFlavor flavour;
+
+ public MultipartHandler() {
+ flavour = new ActivationDataFlavor(MimeMultipart.class, "multipart/mixed", "Multipart MIME");
+ }
+
+ public DataFlavor[] getTransferDataFlavors() {
+ return new DataFlavor[]{flavour};
+ }
+
+ public Object getTransferData(DataFlavor df, DataSource ds) throws UnsupportedFlavorException, IOException {
+ return flavour.equals(df) ? getContent(ds) : null;
+ }
+
+ public Object getContent(DataSource ds) throws IOException {
+ try {
+ return new MimeMultipart(ds);
+ } catch (MessagingException e) {
+ throw (IOException) new IOException(e.getMessage()).initCause(e);
+ }
+ }
+
+ public void writeTo(Object obj, String mimeType, OutputStream os) throws IOException {
+ if (obj instanceof MimeMultipart) {
+ MimeMultipart mp = (MimeMultipart) obj;
+ try {
+ mp.writeTo(os);
+ } catch (MessagingException e) {
+ throw (IOException) new IOException(e.getMessage()).initCause(e);
+ }
+ }
+ }
+}
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/RFC822MessageHandler.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/RFC822MessageHandler.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/RFC822MessageHandler.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/RFC822MessageHandler.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,120 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geronimo.javamail.handlers;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Properties;
+
+import javax.activation.ActivationDataFlavor;
+import javax.activation.DataContentHandler;
+import javax.activation.DataSource;
+import javax.mail.Message;
+import javax.mail.MessageAware;
+import javax.mail.MessageContext;
+import javax.mail.MessagingException;
+import javax.mail.Session;
+import javax.mail.internet.MimeMessage;
+
+/**
+ * Content handler for RFC-822 compliant messages.
+ * @version $Rev$ $Date$
+ */
+public class RFC822MessageHandler implements DataContentHandler {
+ // the data flavor defines what this looks like, and is fixed once the
+ // handler is instantiated
+ protected final DataFlavor flavour;
+
+ public RFC822MessageHandler() {
+ flavour = new ActivationDataFlavor(Message.class, "message/rfc822", "Message");
+ }
+
+ /**
+ * Return all of the flavors processed by this handler. This
+ * is just the singleton flavor.
+ *
+ * @return An array of the transfer flavors supported by this handler.
+ */
+ public DataFlavor[] getTransferDataFlavors() {
+ return new DataFlavor[] { flavour };
+ }
+
+ /**
+ * Retrieve the transfer data from the data source, but
+ * only if the requested flavor matches what we support.
+ *
+ * @param df The requested data flavor.
+ * @param ds The source DataSource.
+ *
+ * @return The extracted content object, or null if there is a
+ * mismatch of flavors.
+ * @exception UnsupportedFlavorException
+ * @exception IOException
+ */
+ public Object getTransferData(DataFlavor df, DataSource ds) throws UnsupportedFlavorException, IOException {
+ return flavour.equals(df) ? getContent(ds) : null;
+ }
+
+ /**
+ * Extract the RFC822 Message content from a DataSource.
+ *
+ * @param ds The source data source.
+ *
+ * @return An extracted MimeMessage object.
+ * @exception IOException
+ */
+ public Object getContent(DataSource ds) throws IOException {
+ try {
+ // creating a MimeMessage instance requires a session. If the DataSource
+ // is a MessageAware one, we can get the session information from the MessageContext.
+ // This is generally the case, but if it is not available, then just retrieve
+ // the default instance and use it.
+ if (ds instanceof MessageAware) {
+ MessageContext context = ((MessageAware)ds).getMessageContext();
+ return new MimeMessage(context.getSession(), ds.getInputStream());
+ }
+ else {
+ return new MimeMessage(Session.getDefaultInstance(new Properties(), null), ds.getInputStream());
+ }
+ } catch (MessagingException e) {
+ throw (IOException) new IOException(e.getMessage()).initCause(e);
+ }
+ }
+
+ /**
+ * Write an RFC 822 message object out to an output stream.
+ *
+ * @param obj The source message object.
+ * @param mimeType The target mimetype
+ * @param os The target output stream.
+ *
+ * @exception IOException
+ */
+ public void writeTo(Object obj, String mimeType, OutputStream os) throws IOException {
+ // we only handle message instances here
+ if (obj instanceof Message) {
+ Message message = (Message) obj;
+ try {
+ message.writeTo(os);
+ } catch (MessagingException e) {
+ throw (IOException) new IOException(e.getMessage()).initCause(e);
+ }
+ }
+ }
+}
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/TextHtmlHandler.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/TextHtmlHandler.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/TextHtmlHandler.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/TextHtmlHandler.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,29 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geronimo.javamail.handlers;
+
+import javax.activation.ActivationDataFlavor;
+
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class TextHtmlHandler extends AbstractTextHandler {
+ public TextHtmlHandler() {
+ super(new ActivationDataFlavor(String.class, "text/html", "HTML Text"));
+ }
+}
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/TextPlainHandler.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/TextPlainHandler.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/TextPlainHandler.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/TextPlainHandler.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,29 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geronimo.javamail.handlers;
+
+import javax.activation.ActivationDataFlavor;
+
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class TextPlainHandler extends AbstractTextHandler {
+ public TextPlainHandler() {
+ super(new ActivationDataFlavor(String.class, "text/plain", "Plain Text"));
+ }
+}
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/TextXmlHandler.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/TextXmlHandler.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/TextXmlHandler.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/handlers/TextXmlHandler.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,29 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geronimo.javamail.handlers;
+
+import javax.activation.ActivationDataFlavor;
+
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class TextXmlHandler extends AbstractTextHandler {
+ public TextXmlHandler() {
+ super(new ActivationDataFlavor(String.class, "text/xml", "XML Text"));
+ }
+}
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/store/imap/ACL.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/store/imap/ACL.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/store/imap/ACL.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/store/imap/ACL.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,93 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.geronimo.javamail.store.imap;
+
+/**
+ * A named access control list for IMAP resources.
+ */
+public class ACL implements Cloneable {
+ /**
+ * The name of the resource this ACL applies to.
+ */
+ private String name;
+ /**
+ * The rights associated with this resource.
+ */
+ private Rights rights;
+
+ /**
+ * Create an ACL for a resource. The ACL will have an empty Rights set.
+ *
+ * @param name The name of the resource.
+ */
+ public ACL(String name) {
+ this.name = name;
+ this.rights = new Rights();
+ }
+
+ /**
+ * Create a named ACL instance with an initial Rights set.
+ *
+ * @param name The name of the resouce this ACL applies to.
+ * @param rights The Rights associated with this resource.
+ */
+ public ACL(String name, Rights rights) {
+ this.name = name;
+ this.rights = rights;
+ }
+
+ /**
+ * Get the ACL name.
+ *
+ * @return The string name of the ACL.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Get the Rights associated with this ACL.
+ *
+ * @return The Rights set supported for this resource.
+ */
+ public Rights getRights() {
+ return rights;
+ }
+
+ /**
+ * Set a new set of Rights for this ACL instance.
+ *
+ * @param rights The new Rights set.
+ */
+ public void setRights(Rights rights) {
+ this.rights = rights;
+ }
+
+
+ /**
+ * Creates and returns a copy of this object.
+ *
+ * @return A cloned copy of this object. This is a deep
+ * copy, given that a new Rights set is also created.
+ * @exception CloneNotSupportedException
+ */
+ protected Object clone() throws CloneNotSupportedException {
+ return new ACL(name, new Rights(rights));
+ }
+}
Added: geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/store/imap/IMAPAttachedMessage.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/store/imap/IMAPAttachedMessage.java?rev=1882306&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/store/imap/IMAPAttachedMessage.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.6/geronimo-javamail_1.6_provider/src/main/java/org/apache/geronimo/javamail/store/imap/IMAPAttachedMessage.java Wed Oct 7 15:58:39 2020
@@ -0,0 +1,125 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.geronimo.javamail.store.imap;
+
+import javax.activation.DataHandler;
+
+import javax.mail.Flags;
+import javax.mail.MessagingException;
+import javax.mail.MethodNotSupportedException;
+
+import org.apache.geronimo.javamail.store.imap.connection.IMAPEnvelope;
+import org.apache.geronimo.javamail.store.imap.connection.IMAPBodyStructure;
+
+/**
+ * A nested message attachement inside of another
+ * IMAP message. This is a less-functional version
+ * of the top-level message.
+ */
+public class IMAPAttachedMessage extends IMAPMessage {
+ // the parent enclosing message.
+ protected IMAPMessage parent;
+
+ /**
+ * Constructor for an attached message part.
+ *
+ * @param parent The parent message (outer-most message).
+ * @param section The section identifier for this embedded part
+ * in IMAP section format. This will identify
+ * the part hierarchy used to locate this part within
+ * the message.
+ * @param envelope The Envelope that describes this part.
+ * @param bodyStructure
+ * The Body structure element that describes this part.
+ */
+ public IMAPAttachedMessage(IMAPMessage parent, String section, IMAPEnvelope envelope, IMAPBodyStructure bodyStructure) {
+ super((IMAPFolder)parent.getFolder(), parent.store, parent.getMessageNumber(), parent.sequenceNumber);
+ this.parent = parent;
+ // sets the subset we're looking for
+ this.section = section;
+ // the envelope and body structure are loaded from the server by the parent
+ this.envelope = envelope;
+ this.bodyStructure = bodyStructure;
+ }
+
+ /**
+ * Check if this message is still valid. This is
+ * delegated to the outer-most message.
+ *
+ * @exception MessagingException
+ */
+ protected void checkValidity() throws MessagingException {
+ parent.checkValidity();
+ }
+
+ /**
+ * Check if the outer-most message has been expunged.
+ *
+ * @return true if the message has been expunged.
+ */
+ public boolean isExpunged() {
+ return parent.isExpunged();
+ }
+
+ /**
+ * Get the size of this message part.
+ *
+ * @return The estimate size of this message part, in bytes.
+ */
+ public int getSize() {
+ return bodyStructure.bodySize;
+ }
+
+
+ /**
+ * Return a copy the flags associated with this message.
+ *
+ * @return a copy of the flags for this message
+ * @throws MessagingException if there was a problem accessing the Store
+ */
+ public Flags getFlags() throws MessagingException {
+ return parent.getFlags();
+ }
+
+
+ /**
+ * Check whether the supplied flag is set.
+ * The default implementation checks the flags returned by {@link #getFlags()}.
+ *
+ * @param flag the flags to check for
+ * @return true if the flags is set
+ * @throws MessagingException if there was a problem accessing the Store
+ */
+ public boolean isSet(Flags.Flag flag) throws MessagingException {
+ // load the flags, if needed
+ return parent.isSet(flag);
+ }
+
+ /**
+ * Set or clear a flag value.
+ *
+ * @param flags The set of flags to effect.
+ * @param set The value to set the flag to (true or false).
+ *
+ * @exception MessagingException
+ */
+ public void setFlags(Flags flag, boolean set) throws MessagingException {
+ throw new MethodNotSupportedException("Flags cannot be set on message attachements");
+ }
+}
+