Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 651642fa authored by Daniel Applebaum's avatar Daniel Applebaum
Browse files

Automatically re-synchronize the IMAP protocol. Previously, losses of

synchronization could happen if an Exception was thrown while parsing
an untagged response without using executeSimpleCommand.  For
instance, while doing a fetch.  Once synchronization was lost, later
commands would fail in surprising ways.  One manifestation of such
failures was spontaneously emptying of folders when search results
were not returned properly.  The new code makes sure to only accept OK
responses with the tag of the command, and discards the untagged
responses from previous command.

parent 7daf4ef1
Loading
Loading
Loading
Loading
+3 −5
Original line number Diff line number Diff line
@@ -753,13 +753,10 @@ public class MessagingController implements Runnable {
                for (Message thisMess : remoteMessageArray)
                {
                	remoteMessages.add(thisMess);
			remoteUidMap.put(thisMess.getUid(), thisMess);
                }
             		if (Config.LOGV) {
            			Log.v(Email.LOG_TAG, "SYNC: Got messages for folder " + folder);
            		}

                for (Message message : remoteMessages) {
                    remoteUidMap.put(message.getUid(), message);
            			Log.v(Email.LOG_TAG, "SYNC: Got " + remoteUidMap.size() + " messages for folder " + folder);
            		}

                /*
@@ -923,6 +920,7 @@ s * critical data as fast as possible, and then we'll fill in the de
                    !localMessage.isSet(Flag.DELETED))
                {
                    localMessage.setFlag(Flag.X_DESTROYED, true);
		    //		    Log.d(Email.LOG_TAG, "Destroying message " + localMessage.getUid() + " which isn't in the most recent group on server");
                    for (MessagingListener l : getListeners()) {
                        l.synchronizeMailboxRemovedMessage(account, folder, localMessage);
                    }
+41 −4
Original line number Diff line number Diff line
@@ -384,10 +384,13 @@ public class ImapStore extends Store {
            			mPathDelimeter = nameResponses.get(0).getString(2);
            		    }
            		}
                
			//                executeSimpleCommand("CLOSE");
                
            		String command = String.format("SELECT \"%s\"",
                    encodeFolderName(getPrefixedName()));

            		mMessageCount = -1;
            		//mMessageCount = -1;

            		List<ImapResponse> responses = executeSimpleCommand(command);
            
@@ -429,6 +432,11 @@ public class ImapStore extends Store {
        }

        public void close(boolean expunge) throws MessagingException {
	    if (mMessageCount != -1)
	    {
	//	close();
		mMessageCount = -1;
	    }
            if (!isOpen()) {
                return;
            }
@@ -436,7 +444,6 @@ public class ImapStore extends Store {
            {
            	expunge();
            }
            mMessageCount = -1;
            synchronized (this) {
                releaseConnection(mConnection);
                mConnection = null;
@@ -584,6 +591,7 @@ public class ImapStore extends Store {
                    List<ImapResponse> responses =
                            executeSimpleCommand(String.format("UID SEARCH UID %S", uid));
                    for (ImapResponse response : responses) {
			//			Log.d(Email.LOG_TAG, "Got search response: " + response.get(0) + ", size " + response.size());
                        if (response.mTag == null && response.get(0).equals("SEARCH")) {
                            for (int i = 1, count = response.size(); i < count; i++) {
                                if (uid.equals(response.get(i))) {
@@ -614,15 +622,24 @@ public class ImapStore extends Store {
            checkOpen();
            ArrayList<Message> messages = new ArrayList<Message>();
            try {
		boolean gotSearchValues = false;
                ArrayList<Integer> uids = new ArrayList<Integer>();
                List<ImapResponse> responses = executeSimpleCommand(String.format("UID SEARCH %d:%d NOT DELETED", start, end));
                for (ImapResponse response : responses) {
		    //		    Log.d(Email.LOG_TAG, "Got search response: " + response.get(0) + ", size " + response.size());
                    if (response.get(0).equals("SEARCH")) {
			gotSearchValues = true;
                        for (int i = 1, count = response.size(); i < count; i++) {
			    //			    Log.d(Email.LOG_TAG, "Got search response UID: " + response.getString(i));

                            uids.add(Integer.parseInt(response.getString(i)));
                        }
                    }
                }
		if (gotSearchValues == false)
		{
		    throw new MessagingException("Did not get proper search response");
		}
                // Sort the uids in numerically ascending order
                Collections.sort(uids);
                for (int i = 0, count = uids.size(); i < count; i++) {
@@ -868,7 +885,7 @@ public class ImapStore extends Store {
        private void handleUntaggedResponse(ImapResponse response) {
            if (response.mTag == null && response.size() > 1 && response.get(1).equals("EXISTS")) {
                mMessageCount = response.getNumber(0);
                Log.i(Email.LOG_TAG, "Got untagged EXISTS with value " + mMessageCount);
		//Log.i(Email.LOG_TAG, "Got untagged EXISTS with value " + mMessageCount);
            }
        }

@@ -1137,6 +1154,15 @@ public class ImapStore extends Store {
            return null;
        }

        private void close() throws MessagingException {
            checkOpen();
            try {
                executeSimpleCommand("CLOSE");
            } catch (IOException ioe) {
                
            }
        }

        private String combineFlags(Flag[] flags)
        {
          ArrayList<String> flagNames = new ArrayList<String>();
@@ -1467,9 +1493,13 @@ public class ImapStore extends Store {
                throws IOException, ImapException, MessagingException {
        	if (Config.LOGV)
        	{
        		Log.v(Email.LOG_TAG, "Sending IMAP command " + command);
        		Log.v(Email.LOG_TAG, "Sending IMAP command " + command + " on connection " + this.hashCode());
        	}
            String tag = sendCommand(command, sensitive);
	    if (Config.LOGV)
            {
		Log.v(Email.LOG_TAG, "Sent IMAP command " + command + " with tag " + tag);
	    }
            ArrayList<ImapResponse> responses = new ArrayList<ImapResponse>();
            ImapResponse response;
            do {
@@ -1478,6 +1508,13 @@ public class ImapStore extends Store {
                {
                	Log.v(Email.LOG_TAG, "Got IMAP response " + response);
                }
		if (response.mTag != null && response.mTag.equals(tag) == false)
		{
		    Log.w(Email.LOG_TAG, "Got tag response from previous command " + response);
		    responses.clear();
		    response.mTag = null;
		    continue;
		}
                responses.add(response);
            } while (response.mTag == null);
            if (response.size() < 1 || !response.get(0).equals("OK")) {