mirror of
https://github.com/moparisthebest/k-9
synced 2024-11-27 11:42:16 -05:00
Correctly encode/escape strings when used in IMAP commands.
Fixes issue 2832
This commit is contained in:
parent
5fef7f3b07
commit
f9f6160719
@ -222,7 +222,7 @@ public class ImapStore extends Store
|
|||||||
{
|
{
|
||||||
mCombinedPrefix = prefix;
|
mCombinedPrefix = prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final SimpleDateFormat RFC3501_DATE = new SimpleDateFormat("dd-MMM-yyyy", Locale.US);
|
private static final SimpleDateFormat RFC3501_DATE = new SimpleDateFormat("dd-MMM-yyyy", Locale.US);
|
||||||
@ -439,8 +439,8 @@ public class ImapStore extends Store
|
|||||||
LinkedList<Folder> folders = new LinkedList<Folder>();
|
LinkedList<Folder> folders = new LinkedList<Folder>();
|
||||||
|
|
||||||
List<ImapResponse> responses =
|
List<ImapResponse> responses =
|
||||||
connection.executeSimpleCommand(String.format(commandResponse + " \"\" \"%s*\"",
|
connection.executeSimpleCommand(String.format(commandResponse + " \"\" %s",
|
||||||
getCombinedPrefix()));
|
encodeString(getCombinedPrefix() + "*")));
|
||||||
|
|
||||||
for (ImapResponse response : responses)
|
for (ImapResponse response : responses)
|
||||||
{
|
{
|
||||||
@ -550,11 +550,29 @@ public class ImapStore extends Store
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a string to be able to use it in an IMAP command.
|
||||||
|
*
|
||||||
|
* "A quoted string is a sequence of zero or more 7-bit characters,
|
||||||
|
* excluding CR and LF, with double quote (<">) characters at each
|
||||||
|
* end." - § 4.3, RFC 3501
|
||||||
|
*
|
||||||
|
* Double quotes and backslash are escaped by prepending a backslash.
|
||||||
|
*
|
||||||
|
* @param str
|
||||||
|
* The input string (only 7-bit characters allowed).
|
||||||
|
* @return
|
||||||
|
* The string encoded as quoted (IMAP) string.
|
||||||
|
*/
|
||||||
|
private static String encodeString(String str)
|
||||||
|
{
|
||||||
|
return "\"" + str.replace("\\", "\\\\").replace("\"", "\\\"") + "\"";
|
||||||
|
}
|
||||||
|
|
||||||
private String encodeFolderName(String name)
|
private String encodeFolderName(String name)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
name = name.replace("\\","\\\\"); // backslashs in folder names must be escaped
|
|
||||||
ByteBuffer bb = mModifiedUtf7Charset.encode(name);
|
ByteBuffer bb = mModifiedUtf7Charset.encode(name);
|
||||||
byte[] b = new byte[bb.limit()];
|
byte[] b = new byte[bb.limit()];
|
||||||
bb.get(b);
|
bb.get(b);
|
||||||
@ -729,8 +747,8 @@ public class ImapStore extends Store
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
msgSeqUidMap.clear();
|
msgSeqUidMap.clear();
|
||||||
String command = String.format((mode == OpenMode.READ_WRITE ? "SELECT" : "EXAMINE") + " \"%s\"",
|
String command = String.format((mode == OpenMode.READ_WRITE ? "SELECT" : "EXAMINE") + " %s",
|
||||||
encodeFolderName(getPrefixedName()));
|
encodeString(encodeFolderName(getPrefixedName())));
|
||||||
|
|
||||||
List<ImapResponse> responses = executeSimpleCommand(command);
|
List<ImapResponse> responses = executeSimpleCommand(command);
|
||||||
|
|
||||||
@ -823,6 +841,16 @@ public class ImapStore extends Store
|
|||||||
return mName;
|
return mName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a given folder exists on the server.
|
||||||
|
*
|
||||||
|
* @param folderName
|
||||||
|
* The name of the folder encoded as quoted string.
|
||||||
|
* See {@link ImapStore#encodeString}
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* {@code True}, if the folder exists. {@code False}, otherwise.
|
||||||
|
*/
|
||||||
private boolean exists(String folderName) throws MessagingException
|
private boolean exists(String folderName) throws MessagingException
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -830,7 +858,7 @@ public class ImapStore extends Store
|
|||||||
// Since we don't care about RECENT, we'll use that for the check, because we're checking
|
// Since we don't care about RECENT, we'll use that for the check, because we're checking
|
||||||
// a folder other than ourself, and don't want any untagged responses to cause a change
|
// a folder other than ourself, and don't want any untagged responses to cause a change
|
||||||
// in our own fields
|
// in our own fields
|
||||||
mConnection.executeSimpleCommand(String.format("STATUS \"%s\" (RECENT)", folderName));
|
mConnection.executeSimpleCommand(String.format("STATUS %s (RECENT)", folderName));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (IOException ioe)
|
catch (IOException ioe)
|
||||||
@ -869,8 +897,8 @@ public class ImapStore extends Store
|
|||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
connection.executeSimpleCommand(String.format("STATUS \"%s\" (UIDVALIDITY)",
|
connection.executeSimpleCommand(String.format("STATUS %s (UIDVALIDITY)",
|
||||||
encodeFolderName(getPrefixedName())));
|
encodeString(encodeFolderName(getPrefixedName()))));
|
||||||
mExists = true;
|
mExists = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -913,8 +941,8 @@ public class ImapStore extends Store
|
|||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
connection.executeSimpleCommand(String.format("CREATE \"%s\"",
|
connection.executeSimpleCommand(String.format("CREATE %s",
|
||||||
encodeFolderName(getPrefixedName())));
|
encodeString(encodeFolderName(getPrefixedName()))));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (MessagingException me)
|
catch (MessagingException me)
|
||||||
@ -954,7 +982,7 @@ public class ImapStore extends Store
|
|||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
String remoteDestName = encodeFolderName(iFolder.getPrefixedName());
|
String remoteDestName = encodeString(encodeFolderName(iFolder.getPrefixedName()));
|
||||||
|
|
||||||
if (!exists(remoteDestName))
|
if (!exists(remoteDestName))
|
||||||
{
|
{
|
||||||
@ -968,9 +996,9 @@ public class ImapStore extends Store
|
|||||||
|
|
||||||
if (exists(remoteDestName))
|
if (exists(remoteDestName))
|
||||||
{
|
{
|
||||||
executeSimpleCommand(String.format("UID COPY %s \"%s\"",
|
executeSimpleCommand(String.format("UID COPY %s %s",
|
||||||
Utility.combine(uids, ','),
|
Utility.combine(uids, ','),
|
||||||
encodeFolderName(iFolder.getPrefixedName())));
|
remoteDestName));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1007,7 +1035,7 @@ public class ImapStore extends Store
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
ImapFolder remoteTrashFolder = (ImapFolder)getStore().getFolder(trashFolderName);
|
ImapFolder remoteTrashFolder = (ImapFolder)getStore().getFolder(trashFolderName);
|
||||||
String remoteTrashName = encodeFolderName(remoteTrashFolder.getPrefixedName());
|
String remoteTrashName = encodeString(encodeFolderName(remoteTrashFolder.getPrefixedName()));
|
||||||
|
|
||||||
if (!exists(remoteTrashName))
|
if (!exists(remoteTrashName))
|
||||||
{
|
{
|
||||||
@ -1924,8 +1952,8 @@ public class ImapStore extends Store
|
|||||||
eolOut.flush();
|
eolOut.flush();
|
||||||
|
|
||||||
mConnection.sendCommand(
|
mConnection.sendCommand(
|
||||||
String.format("APPEND \"%s\" (%s) {%d}",
|
String.format("APPEND %s (%s) {%d}",
|
||||||
encodeFolderName(getPrefixedName()),
|
encodeString(encodeFolderName(getPrefixedName())),
|
||||||
combineFlags(message.getFlags()),
|
combineFlags(message.getFlags()),
|
||||||
out.getCount()), false);
|
out.getCount()), false);
|
||||||
ImapResponse response;
|
ImapResponse response;
|
||||||
@ -2400,7 +2428,7 @@ public class ImapStore extends Store
|
|||||||
}
|
}
|
||||||
else if (mSettings.getAuthType() == AuthType.PLAIN)
|
else if (mSettings.getAuthType() == AuthType.PLAIN)
|
||||||
{
|
{
|
||||||
receiveCapabilities(executeSimpleCommand("LOGIN \"" + escapeString(mSettings.getUsername()) + "\" \"" + escapeString(mSettings.getPassword()) + "\"", true));
|
receiveCapabilities(executeSimpleCommand(String.format("LOGIN %s %s", ImapStore.encodeString(mSettings.getUsername()), ImapStore.encodeString(mSettings.getPassword())), true));
|
||||||
}
|
}
|
||||||
authSuccess = true;
|
authSuccess = true;
|
||||||
}
|
}
|
||||||
@ -2735,17 +2763,6 @@ public class ImapStore extends Store
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String escapeString(String in)
|
|
||||||
{
|
|
||||||
if (in == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
String out = in.replaceAll("\\\\", "\\\\\\\\");
|
|
||||||
out = out.replaceAll("\"", "\\\\\"");
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendContinuation(String continuation) throws IOException
|
public void sendContinuation(String continuation) throws IOException
|
||||||
{
|
{
|
||||||
mOut.write(continuation.getBytes());
|
mOut.write(continuation.getBytes());
|
||||||
|
Loading…
Reference in New Issue
Block a user