mirror of https://github.com/M66B/FairEmail.git
				
				
				
			
			You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							406 lines
						
					
					
						
							14 KiB
						
					
					
				
			
		
		
	
	
							406 lines
						
					
					
						
							14 KiB
						
					
					
				diff -rupN /home/marcel/JavaMail/mail/src/main/java/com/sun/mail/handlers/handler_base.java ./app/src/main/java/com/sun/mail/handlers/handler_base.java
 | 
						|
--- /home/marcel/JavaMail/mail/src/main/java/com/sun/mail/handlers/handler_base.java	2020-08-14 11:44:05.401359065 +0200
 | 
						|
+++ ./app/src/main/java/com/sun/mail/handlers/handler_base.java	2020-08-26 15:38:37.903384284 +0200
 | 
						|
@@ -17,7 +17,6 @@
 | 
						|
 package com.sun.mail.handlers;
 | 
						|
 
 | 
						|
 import java.io.IOException;
 | 
						|
-import java.awt.datatransfer.DataFlavor;
 | 
						|
 import javax.activation.*;
 | 
						|
 
 | 
						|
 /**
 | 
						|
@@ -52,14 +51,8 @@ public abstract class handler_base imple
 | 
						|
      *
 | 
						|
      * @return The DataFlavors
 | 
						|
      */
 | 
						|
-    @Override
 | 
						|
-    public DataFlavor[] getTransferDataFlavors() {
 | 
						|
-	ActivationDataFlavor[] adf = getDataFlavors();
 | 
						|
-	if (adf.length == 1)	// the common case
 | 
						|
-	    return new DataFlavor[] { adf[0] };
 | 
						|
-	DataFlavor[] df = new DataFlavor[adf.length];
 | 
						|
-	System.arraycopy(adf, 0, df, 0, adf.length);
 | 
						|
-	return df;
 | 
						|
+    public ActivationDataFlavor[] getTransferDataFlavors() {
 | 
						|
+	return getDataFlavors().clone();
 | 
						|
     }
 | 
						|
 
 | 
						|
     /**
 | 
						|
@@ -70,8 +63,7 @@ public abstract class handler_base imple
 | 
						|
      * @return	the object
 | 
						|
      * @exception	IOException	for errors reading the data
 | 
						|
      */
 | 
						|
-    @Override
 | 
						|
-    public Object getTransferData(DataFlavor df, DataSource ds) 
 | 
						|
+    public Object getTransferData(ActivationDataFlavor df, DataSource ds) 
 | 
						|
 			throws IOException {
 | 
						|
 	ActivationDataFlavor[] adf = getDataFlavors();
 | 
						|
 	for (int i = 0; i < adf.length; i++) {
 | 
						|
diff -rupN /home/marcel/JavaMail/mail/src/main/java/com/sun/mail/iap/Protocol.java ./app/src/main/java/com/sun/mail/iap/Protocol.java
 | 
						|
--- /home/marcel/JavaMail/mail/src/main/java/com/sun/mail/iap/Protocol.java	2020-04-03 09:00:49.201313282 +0200
 | 
						|
+++ ./app/src/main/java/com/sun/mail/iap/Protocol.java	2020-08-28 08:09:12.005962733 +0200
 | 
						|
@@ -347,6 +347,15 @@ public class Protocol {
 | 
						|
      * @return		array of Response objects returned by the server
 | 
						|
      */
 | 
						|
     public synchronized Response[] command(String command, Argument args) {
 | 
						|
+	if (socket == null)
 | 
						|
+		return new Response[]{Response.byeResponse(new SocketException("disconnected"))};
 | 
						|
+	if ("LOGOUT".equals(command))
 | 
						|
+		try {
 | 
						|
+			socket.setSoTimeout(10 * 1000);
 | 
						|
+		} catch (SocketException ex) {
 | 
						|
+			eu.faircode.email.Log.e(ex);
 | 
						|
+		}
 | 
						|
+
 | 
						|
 	commandStart(command);
 | 
						|
 	List<Response> v = new ArrayList<>();
 | 
						|
 	boolean done = false;
 | 
						|
diff -rupN /home/marcel/JavaMail/mail/src/main/java/com/sun/mail/imap/IMAPFolder.java ./app/src/main/java/com/sun/mail/imap/IMAPFolder.java
 | 
						|
--- /home/marcel/JavaMail/mail/src/main/java/com/sun/mail/imap/IMAPFolder.java	2020-08-14 11:44:05.403359065 +0200
 | 
						|
+++ ./app/src/main/java/com/sun/mail/imap/IMAPFolder.java	2020-08-27 09:24:28.051446453 +0200
 | 
						|
@@ -1659,6 +1659,28 @@ public class IMAPFolder extends Folder i
 | 
						|
 	}
 | 
						|
     }
 | 
						|
 
 | 
						|
+	public synchronized int getCachedCount() {
 | 
						|
+		synchronized (messageCacheLock) {
 | 
						|
+			if (messageCache == null)
 | 
						|
+				return -1;
 | 
						|
+
 | 
						|
+			try {
 | 
						|
+				int count = 0;
 | 
						|
+				int size = messageCache.size();
 | 
						|
+				for (int i = 1; i <= size; i++) {
 | 
						|
+					Message message = messageCache.getMessage(i);
 | 
						|
+					if (message != null && !message.isExpunged())
 | 
						|
+						count++;
 | 
						|
+				}
 | 
						|
+
 | 
						|
+				return count;
 | 
						|
+			} catch (Throwable ex) {
 | 
						|
+				eu.faircode.email.Log.e(ex);
 | 
						|
+				return -1;
 | 
						|
+			}
 | 
						|
+		}
 | 
						|
+	}
 | 
						|
+
 | 
						|
     /**
 | 
						|
      * Get the new message count.
 | 
						|
      */
 | 
						|
@@ -2608,6 +2630,20 @@ public class IMAPFolder extends Folder i
 | 
						|
 	    throw new FolderClosedException(this, cex.getMessage());
 | 
						|
 	} catch (ProtocolException pex) {
 | 
						|
 	    throw new MessagingException(pex.getMessage(), pex);
 | 
						|
+	} catch (ArrayIndexOutOfBoundsException ex) {
 | 
						|
+		eu.faircode.email.Log.w(ex);
 | 
						|
+		/*
 | 
						|
+			java.lang.ArrayIndexOutOfBoundsException: message number (0) out of bounds (110)
 | 
						|
+					at com.sun.mail.imap.MessageCache.getMessage(SourceFile:116)
 | 
						|
+					at com.sun.mail.imap.MessageCache.getMessageBySeqnum(SourceFile:148)
 | 
						|
+					at com.sun.mail.imap.IMAPFolder.getMessageBySeqNumber(SourceFile:3999)
 | 
						|
+					at com.sun.mail.imap.IMAPFolder.processFetchResponse(SourceFile:3604)
 | 
						|
+					at com.sun.mail.imap.IMAPFolder.handleResponse(SourceFile:3586)
 | 
						|
+					at com.sun.mail.iap.Protocol.notifyResponseHandlers(SourceFile:245)
 | 
						|
+					at com.sun.mail.imap.protocol.IMAPProtocol.fetchSequenceNumber(SourceFile:2057)
 | 
						|
+					at com.sun.mail.imap.IMAPFolder.getMessageByUID(SourceFile:2598)
 | 
						|
+		 */
 | 
						|
+		return null;
 | 
						|
 	}
 | 
						|
 
 | 
						|
 	return m;
 | 
						|
@@ -3963,7 +3999,8 @@ public class IMAPFolder extends Folder i
 | 
						|
 		protocol.noop(); 
 | 
						|
 	}
 | 
						|
 
 | 
						|
-        if (keepStoreAlive && ((IMAPStore)store).hasSeparateStoreConnection()) {
 | 
						|
+        if (keepStoreAlive && ((IMAPStore)store).hasSeparateStoreConnection() &&
 | 
						|
+				!((IMAPStore)store).isStoreConnectionInUse()) {
 | 
						|
             IMAPProtocol p = null;
 | 
						|
 	    try {
 | 
						|
 		p = ((IMAPStore)store).getFolderStoreProtocol();
 | 
						|
diff -rupN /home/marcel/JavaMail/mail/src/main/java/com/sun/mail/imap/IMAPMessage.java ./app/src/main/java/com/sun/mail/imap/IMAPMessage.java
 | 
						|
--- /home/marcel/JavaMail/mail/src/main/java/com/sun/mail/imap/IMAPMessage.java	2020-08-14 11:44:05.403359065 +0200
 | 
						|
+++ ./app/src/main/java/com/sun/mail/imap/IMAPMessage.java	2020-08-26 15:38:37.906384284 +0200
 | 
						|
@@ -1697,4 +1697,28 @@ public class IMAPMessage extends MimeMes
 | 
						|
     Session _getSession() {
 | 
						|
 	return session;
 | 
						|
     }
 | 
						|
+
 | 
						|
+    @Override
 | 
						|
+    public boolean isExpunged() {
 | 
						|
+        if (super.isExpunged())
 | 
						|
+            return true;
 | 
						|
+
 | 
						|
+        // Workaround expunged messages without deleted flag
 | 
						|
+        if (envelope != null &&
 | 
						|
+                envelope.date == null &&
 | 
						|
+                envelope.subject == null &&
 | 
						|
+                envelope.from == null &&
 | 
						|
+                envelope.sender == null &&
 | 
						|
+                envelope.replyTo == null &&
 | 
						|
+                envelope.to == null &&
 | 
						|
+                envelope.cc == null &&
 | 
						|
+                envelope.inReplyTo == null &&
 | 
						|
+                envelope.messageId == null &&
 | 
						|
+                headersLoaded && loadedHeaders.size() == 0) {
 | 
						|
+			eu.faircode.email.Log.w("Expunged workaround host=" + ((IMAPStore) folder.getStore()).host);
 | 
						|
+			return true;
 | 
						|
+		}
 | 
						|
+
 | 
						|
+        return false;
 | 
						|
+    }
 | 
						|
 }
 | 
						|
diff -rupN /home/marcel/JavaMail/mail/src/main/java/com/sun/mail/imap/IMAPStore.java ./app/src/main/java/com/sun/mail/imap/IMAPStore.java
 | 
						|
--- /home/marcel/JavaMail/mail/src/main/java/com/sun/mail/imap/IMAPStore.java	2020-08-14 11:44:05.404359065 +0200
 | 
						|
+++ ./app/src/main/java/com/sun/mail/imap/IMAPStore.java	2020-08-26 15:38:37.907384284 +0200
 | 
						|
@@ -887,18 +887,26 @@ public class IMAPStore extends Store
 | 
						|
 		continue;
 | 
						|
 	    }
 | 
						|
 
 | 
						|
-	    if (m.equals("PLAIN"))
 | 
						|
-		p.authplain(authzid, user, password);
 | 
						|
-	    else if (m.equals("LOGIN"))
 | 
						|
-		p.authlogin(user, password);
 | 
						|
-	    else if (m.equals("NTLM"))
 | 
						|
-		p.authntlm(authzid, user, password);
 | 
						|
-	    else if (m.equals("XOAUTH2"))
 | 
						|
-		p.authoauth2(user, password);
 | 
						|
-	    else {
 | 
						|
-		logger.log(Level.FINE, "no authenticator for mechanism {0}", m);
 | 
						|
-		continue;
 | 
						|
-	    }
 | 
						|
+	    try {
 | 
						|
+			if (m.equals("PLAIN"))
 | 
						|
+				p.authplain(authzid, user, password);
 | 
						|
+			else if (m.equals("LOGIN"))
 | 
						|
+				p.authlogin(user, password);
 | 
						|
+			else if (m.equals("NTLM"))
 | 
						|
+				p.authntlm(authzid, user, password);
 | 
						|
+			else if (m.equals("XOAUTH2"))
 | 
						|
+				p.authoauth2(user, password);
 | 
						|
+			else {
 | 
						|
+				logger.log(Level.FINE, "no authenticator for mechanism {0}", m);
 | 
						|
+				continue;
 | 
						|
+			}
 | 
						|
+		} catch (ProtocolException ex) {
 | 
						|
+			if (m.equals("PLAIN") || m.equals("LOGIN")) {
 | 
						|
+				eu.faircode.email.Log.i("Falling back to classic LOGIN");
 | 
						|
+				p.authclassic(user, password);
 | 
						|
+			} else
 | 
						|
+				throw ex;
 | 
						|
+		}
 | 
						|
 	    return;
 | 
						|
 	}
 | 
						|
 
 | 
						|
@@ -1014,6 +1022,8 @@ public class IMAPStore extends Store
 | 
						|
                             p.disconnect();
 | 
						|
                         } catch (Exception ex2) { }
 | 
						|
                     p = null;
 | 
						|
+					eu.faircode.email.Log.e(new MessagingException("IMAP connection failure", ex1));
 | 
						|
+					throw new MessagingException("connection failure", ex1);
 | 
						|
                 }
 | 
						|
                  
 | 
						|
                 if (p == null)
 | 
						|
@@ -1175,7 +1185,11 @@ public class IMAPStore extends Store
 | 
						|
 		    // someone else is using the connection, give up
 | 
						|
 		    // and wait until they're done
 | 
						|
 		    p = null;
 | 
						|
-		    pool.wait();
 | 
						|
+		    pool.wait(pool.clientTimeoutInterval);
 | 
						|
+		    if (pool.storeConnectionInUse) {
 | 
						|
+				eu.faircode.email.Log.e("getStoreProtocol timeout");
 | 
						|
+				throw new InterruptedException("getStoreProtocol timeout");
 | 
						|
+			}
 | 
						|
 		} catch (InterruptedException ex) {
 | 
						|
 		    // restore the interrupted state, which callers might
 | 
						|
 		    // depend on
 | 
						|
@@ -1250,7 +1264,11 @@ public class IMAPStore extends Store
 | 
						|
         return pool.separateStoreConnection;
 | 
						|
     }
 | 
						|
 
 | 
						|
-    /** 
 | 
						|
+    boolean isStoreConnectionInUse() {
 | 
						|
+		return pool.storeConnectionInUse;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+    /**
 | 
						|
      * Return the connection pool logger.
 | 
						|
      */ 
 | 
						|
     MailLogger getConnectionPoolLogger() {
 | 
						|
@@ -1529,6 +1547,30 @@ public class IMAPStore extends Store
 | 
						|
         }
 | 
						|
     }
 | 
						|
 
 | 
						|
+    public synchronized String getCapability(String capability)
 | 
						|
+            throws MessagingException {
 | 
						|
+        IMAPProtocol p = null;
 | 
						|
+        try {
 | 
						|
+            p = getStoreProtocol();
 | 
						|
+            Map<String, String> caps = p.getCapabilities();
 | 
						|
+            if (caps != null)
 | 
						|
+                for (String cap : caps.values()) {
 | 
						|
+                    int eq = (cap == null ? -1 : cap.indexOf('='));
 | 
						|
+                    if (eq > 0) {
 | 
						|
+                        String key = cap.substring(0, eq);
 | 
						|
+                        String value = cap.substring(eq + 1);
 | 
						|
+                        if (capability.equals(key))
 | 
						|
+                            return value;
 | 
						|
+                    }
 | 
						|
+                }
 | 
						|
+            return null;
 | 
						|
+        } catch (ProtocolException pex) {
 | 
						|
+            throw new MessagingException(pex.getMessage(), pex);
 | 
						|
+        } finally {
 | 
						|
+            releaseStoreProtocol(p);
 | 
						|
+        }
 | 
						|
+    }
 | 
						|
+
 | 
						|
     /**
 | 
						|
      * Set the user name to be used with the PROXYAUTH command.
 | 
						|
      * The PROXYAUTH user name can also be set using the
 | 
						|
@@ -2035,7 +2077,11 @@ public class IMAPStore extends Store
 | 
						|
 		    // without aborting it ourselves
 | 
						|
 		    try {
 | 
						|
 			// give up lock and wait to be not idle
 | 
						|
-			pool.wait();
 | 
						|
+			pool.wait(pool.clientTimeoutInterval);
 | 
						|
+			if (pool.idleState != ConnectionPool.RUNNING) {
 | 
						|
+				eu.faircode.email.Log.e("idle timeout");
 | 
						|
+				throw new InterruptedException("idle timeout");
 | 
						|
+			}
 | 
						|
 		    } catch (InterruptedException ex) {
 | 
						|
 			// restore the interrupted state, which callers might
 | 
						|
 			// depend on
 | 
						|
@@ -2128,7 +2174,11 @@ public class IMAPStore extends Store
 | 
						|
 	    }
 | 
						|
 	    try {
 | 
						|
 		// give up lock and wait to be not idle
 | 
						|
-		pool.wait();
 | 
						|
+		pool.wait(pool.clientTimeoutInterval);
 | 
						|
+		if (pool.idleState != ConnectionPool.RUNNING) {
 | 
						|
+			eu.faircode.email.Log.e("waitIfIdle timeout");
 | 
						|
+			throw new InterruptedException("waitIfIdle timeout");
 | 
						|
+		}
 | 
						|
 	    } catch (InterruptedException ex) {
 | 
						|
 		// If someone is trying to interrupt us we can't keep going
 | 
						|
 		// around the loop waiting for IDLE to complete, but we can't
 | 
						|
diff -rupN /home/marcel/JavaMail/mail/src/main/java/com/sun/mail/imap/protocol/IMAPProtocol.java ./app/src/main/java/com/sun/mail/imap/protocol/IMAPProtocol.java
 | 
						|
--- /home/marcel/JavaMail/mail/src/main/java/com/sun/mail/imap/protocol/IMAPProtocol.java	2020-08-14 11:44:05.406359065 +0200
 | 
						|
+++ ./app/src/main/java/com/sun/mail/imap/protocol/IMAPProtocol.java	2020-08-28 17:41:28.427621762 +0200
 | 
						|
@@ -462,6 +462,9 @@ public class IMAPProtocol extends Protoc
 | 
						|
      */
 | 
						|
     public void logout() throws ProtocolException {
 | 
						|
 	try {
 | 
						|
+		if (!authenticated)
 | 
						|
+			return;
 | 
						|
+
 | 
						|
 	    Response[] r = command("LOGOUT", null);
 | 
						|
 
 | 
						|
 	    authenticated = false;
 | 
						|
@@ -627,6 +630,59 @@ public class IMAPProtocol extends Protoc
 | 
						|
 	authenticated = true;
 | 
						|
     }
 | 
						|
 
 | 
						|
+	public synchronized void authclassic(String u, String p)
 | 
						|
+			throws ProtocolException {
 | 
						|
+		List<Response> v = new ArrayList<>();
 | 
						|
+		String tag = null;
 | 
						|
+		Response r = null;
 | 
						|
+		boolean done = false;
 | 
						|
+
 | 
						|
+		try {
 | 
						|
+
 | 
						|
+			if (noauthdebug && isTracing()) {
 | 
						|
+				logger.fine("LOGIN command trace suppressed");
 | 
						|
+				suspendTracing();
 | 
						|
+			}
 | 
						|
+
 | 
						|
+			try {
 | 
						|
+				Argument arg = new Argument();
 | 
						|
+				arg.writeNString(u);
 | 
						|
+				arg.writeNString(p);
 | 
						|
+				tag = writeCommand("LOGIN", arg);
 | 
						|
+			} catch (Exception ex) {
 | 
						|
+				r = Response.byeResponse(ex);
 | 
						|
+				done = true;
 | 
						|
+			}
 | 
						|
+
 | 
						|
+			while (!done) {
 | 
						|
+				try {
 | 
						|
+					r = readResponse();
 | 
						|
+					if (r.isTagged() && r.getTag().equals(tag))
 | 
						|
+						done = true;
 | 
						|
+					else if (r.isBYE()) // outta here
 | 
						|
+						done = true;
 | 
						|
+				} catch (Exception ioex) {
 | 
						|
+					r = Response.byeResponse(ioex);
 | 
						|
+					done = true;
 | 
						|
+				}
 | 
						|
+				v.add(r);
 | 
						|
+			}
 | 
						|
+
 | 
						|
+		} finally {
 | 
						|
+			resumeTracing();
 | 
						|
+		}
 | 
						|
+
 | 
						|
+		Response[] responses = v.toArray(new Response[v.size()]);
 | 
						|
+
 | 
						|
+		handleCapabilityResponse(responses);
 | 
						|
+		notifyResponseHandlers(responses);
 | 
						|
+
 | 
						|
+		if (noauthdebug && isTracing())
 | 
						|
+			logger.fine("LOGIN command result: " + r);
 | 
						|
+		handleLoginResult(r);
 | 
						|
+		setCapabilities(r);
 | 
						|
+		authenticated = true;
 | 
						|
+	}
 | 
						|
 
 | 
						|
     /**
 | 
						|
      * The AUTHENTICATE command with AUTH=PLAIN authentication scheme.
 | 
						|
--- /home/marcel/JavaMail/mail/src/main/java/javax/mail/EventQueue.java	2020-08-14 11:44:05.413359065 +0200
 | 
						|
+++ app/src/main/java/javax/mail/EventQueue.java	2020-09-21 11:04:19.648547947 +0200
 | 
						|
@@ -154,6 +154,19 @@ class EventQueue implements Runnable {
 | 
						|
 	    }
 | 
						|
 	} catch (InterruptedException e) {
 | 
						|
 	    // just die
 | 
						|
+	} catch (Error ex) {
 | 
						|
+		/*
 | 
						|
+			java.lang.Error: java.lang.InterruptedException
 | 
						|
+			  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1173)
 | 
						|
+			  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
 | 
						|
+			  at java.lang.Thread.run(Thread.java:919)
 | 
						|
+			Caused by: java.lang.InterruptedException
 | 
						|
+			  at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1248)
 | 
						|
+			  at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:344)
 | 
						|
+			  at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:439)
 | 
						|
+			  at javax.mail.EventQueue.run(SourceFile:140)
 | 
						|
+			  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
 | 
						|
+		 */
 | 
						|
 	}
 | 
						|
     }
 | 
						|
 }
 | 
						|
diff --git a/app/src/main/java/com/sun/mail/imap/IMAPStore.java b/app/src/main/java/com/sun/mail/imap/IMAPStore.java
 | 
						|
index 087e5a6f5..5fa720f3d 100644
 | 
						|
--- a/app/src/main/java/com/sun/mail/imap/IMAPStore.java
 | 
						|
+++ b/app/src/main/java/com/sun/mail/imap/IMAPStore.java
 | 
						|
@@ -1571,6 +1571,19 @@ public class IMAPStore extends Store
 | 
						|
         }
 | 
						|
     }
 | 
						|
 
 | 
						|
+	public synchronized Map<String, String> getCapabilities()
 | 
						|
+			throws MessagingException {
 | 
						|
+		IMAPProtocol p = null;
 | 
						|
+		try {
 | 
						|
+			p = getStoreProtocol();
 | 
						|
+			return p.getCapabilities();
 | 
						|
+		} catch (ProtocolException pex) {
 | 
						|
+			throw new MessagingException(pex.getMessage(), pex);
 | 
						|
+		} finally {
 | 
						|
+			releaseStoreProtocol(p);
 | 
						|
+		}
 | 
						|
+	}
 | 
						|
+
 | 
						|
     /**
 | 
						|
      * Set the user name to be used with the PROXYAUTH command.
 | 
						|
      * The PROXYAUTH user name can also be set using the
 |