diff --git a/src/java/davmail/exchange/ExchangeSession.java b/src/java/davmail/exchange/ExchangeSession.java
index 5f70dc4d..4e2bdf65 100644
--- a/src/java/davmail/exchange/ExchangeSession.java
+++ b/src/java/davmail/exchange/ExchangeSession.java
@@ -556,6 +556,7 @@ public abstract class ExchangeSession {
static {
IMAP_MESSAGE_ATTRIBUTES.add("permanenturl");
+ IMAP_MESSAGE_ATTRIBUTES.add("urlcompname");
IMAP_MESSAGE_ATTRIBUTES.add("uid");
IMAP_MESSAGE_ATTRIBUTES.add("messageSize");
IMAP_MESSAGE_ATTRIBUTES.add("imapUid");
diff --git a/src/java/davmail/exchange/dav/DavExchangeSession.java b/src/java/davmail/exchange/dav/DavExchangeSession.java
index 4f5c7443..f88bd418 100644
--- a/src/java/davmail/exchange/dav/DavExchangeSession.java
+++ b/src/java/davmail/exchange/dav/DavExchangeSession.java
@@ -433,7 +433,11 @@ public class DavExchangeSession extends ExchangeSession {
if (Operator.Like == operator) {
buffer.append('%');
}
- buffer.append(value);
+ if ("urlcompname".equals(field.alias)) {
+ buffer.append(StringUtil.encodeUrlcompname(value));
+ } else {
+ buffer.append(value);
+ }
if (Operator.Like == operator || Operator.StartsWith == operator) {
buffer.append('%');
}
@@ -1202,22 +1206,7 @@ public class DavExchangeSession extends ExchangeSession {
@Override
public Item getItem(String folderPath, String itemName) throws IOException {
String itemPath = getFolderPath(folderPath) + '/' + convertItemNameToEML(itemName);
- Item item;
- try {
- item = getItem(itemPath);
- } catch (HttpNotFoundException hnfe) {
- // failover for Exchange 2007 plus encoding issue
- String decodedEventName = convertItemNameToEML(itemName).replaceAll("_xF8FF_", "/").replaceAll("_x003F_", "?").replaceAll("'", "''");
- LOGGER.debug("Item not found at " + itemPath + ", search by displayname: '" + decodedEventName + '\'');
- ExchangeSession.MessageList messages = searchMessages(folderPath, equals("displayname", decodedEventName));
- if (!messages.isEmpty()) {
- item = getItem(messages.get(0).getPermanentUrl());
- } else {
- throw hnfe;
- }
- }
-
- return item;
+ return getItem(itemPath);
}
@Override
diff --git a/src/java/davmail/exchange/ews/EwsExchangeSession.java b/src/java/davmail/exchange/ews/EwsExchangeSession.java
index 68f7c8ca..f1434005 100644
--- a/src/java/davmail/exchange/ews/EwsExchangeSession.java
+++ b/src/java/davmail/exchange/ews/EwsExchangeSession.java
@@ -174,7 +174,7 @@ public class EwsExchangeSession extends ExchangeSession {
fieldUpdates.add(Field.createFieldUpdate("messageFlags", "0"));
}
}
- fieldUpdates.add(Field.createFieldUpdate("urlcompname", messageName));
+ fieldUpdates.add(Field.createFieldUpdate("urlcompname", StringUtil.encodeUrlcompname(messageName)));
item.setFieldUpdates(fieldUpdates);
CreateItemMethod createItemMethod = new CreateItemMethod(MessageDisposition.SaveOnly, getFolderId(folderPath), item);
executeMethod(createItemMethod);
@@ -363,10 +363,16 @@ public class EwsExchangeSession extends ExchangeSession {
containmentComparison.appendTo(buffer);
}
buffer.append('>');
- getFieldURI(attributeName).appendTo(buffer);
+ FieldURI fieldURI = getFieldURI(attributeName);
+ fieldURI.appendTo(buffer);
buffer.append("");
buffer.append("');
@@ -577,7 +583,7 @@ public class EwsExchangeSession extends ExchangeSession {
* @inheritDoc
*/
@Override
- public int createFolder(String folderPath, String folderClass, Map properties) throws IOException {
+ public int createFolder(String folderPath, String folderClass, Map properties) throws IOException {
FolderPath path = new FolderPath(folderPath);
EWSMethod.Item folder = new EWSMethod.Item();
folder.type = "Folder";
@@ -1112,7 +1118,7 @@ public class EwsExchangeSession extends ExchangeSession {
parentFolderId,
FOLDER_PROPERTIES,
new TwoOperandExpression(TwoOperandExpression.Operator.IsEqualTo,
- Field.get("urlcompname"), StringUtil.urlEncodeAmpersand(folderName))
+ Field.get("urlcompname"), folderName)
);
executeMethod(findFolderMethod);
EWSMethod.Item item = findFolderMethod.getResponseItem();
diff --git a/src/java/davmail/exchange/ews/TwoOperandExpression.java b/src/java/davmail/exchange/ews/TwoOperandExpression.java
index a6863b3f..5b44555c 100644
--- a/src/java/davmail/exchange/ews/TwoOperandExpression.java
+++ b/src/java/davmail/exchange/ews/TwoOperandExpression.java
@@ -51,7 +51,12 @@ public class TwoOperandExpression implements SearchExpression {
fieldURI.appendTo(buffer);
buffer.append("");
buffer.append("');
diff --git a/src/java/davmail/util/StringUtil.java b/src/java/davmail/util/StringUtil.java
index b5bcac59..b5046ea3 100644
--- a/src/java/davmail/util/StringUtil.java
+++ b/src/java/davmail/util/StringUtil.java
@@ -135,6 +135,18 @@ public final class StringUtil {
private static final Pattern ENCODED_LT_PATTERN = Pattern.compile("<");
private static final Pattern ENCODED_GT_PATTERN = Pattern.compile(">");
+ private static final Pattern F8FF_PATTERN = Pattern.compile("_xF8FF_");
+ private static final Pattern PLUS_PATTERN = Pattern.compile("\\+");
+
+
+ public static String urlEncodeSlash(String name) {
+ String result = name;
+ if (name.indexOf("_xF8FF_") >= 0) {
+ result = F8FF_PATTERN.matcher(result).replaceAll(String.valueOf((char)0xF8FF));
+ }
+ return result;
+ }
+
/**
* Encode & to %26 for urlcompname.
*
@@ -232,4 +244,17 @@ public final class StringUtil {
return base64Value;
}
+ public static String encodeUrlcompname(String value) {
+ String result = value;
+ if (result.indexOf("_xF8FF_") >= 0) {
+ result = F8FF_PATTERN.matcher(result).replaceAll(String.valueOf((char)0xF8FF));
+ }
+ if (result.indexOf('&') >= 0) {
+ result = AMP_PATTERN.matcher(result).replaceAll("%26");
+ }
+ if (result.indexOf('+') >= 0) {
+ result = PLUS_PATTERN.matcher(result).replaceAll("%2B");
+ }
+ return result;
+ }
}
diff --git a/src/test/davmail/exchange/TestExchangeSessionMessage.java b/src/test/davmail/exchange/TestExchangeSessionMessage.java
index c8a16c9f..c4ab16b4 100644
--- a/src/test/davmail/exchange/TestExchangeSessionMessage.java
+++ b/src/test/davmail/exchange/TestExchangeSessionMessage.java
@@ -96,6 +96,46 @@ public class TestExchangeSessionMessage extends AbstractExchangeSessionTestCase
assertEquals(0, messageList.size());
}
+ public void testSpecialMessageCharacter() throws IOException, MessagingException {
+ session.deleteFolder("testfolder");
+ session.createMessageFolder("testfolder");
+ MimeMessage mimeMessage = createMimeMessage();
+ messageName = "Special & accenté.EML";
+ HashMap properties = new HashMap();
+ properties.put("draft", "0");
+ session.createMessage("testfolder", messageName, properties, getMimeBody(mimeMessage));
+ ExchangeSession.MessageList messageList = session.searchMessages("testfolder", session.equals("urlcompname", messageName));
+ assertNotNull(messageList);
+ assertEquals(1, messageList.size());
+ }
+
+ public void testSlashMessageName() throws IOException, MessagingException {
+ session.deleteFolder("testfolder");
+ session.createMessageFolder("testfolder");
+ MimeMessage mimeMessage = createMimeMessage();
+ messageName = "test _xF8FF_ slash.EML";
+ HashMap properties = new HashMap();
+ properties.put("draft", "0");
+ session.createMessage("testfolder", messageName, properties, getMimeBody(mimeMessage));
+ ExchangeSession.MessageList messageList = session.searchMessages("testfolder", session.equals("urlcompname", messageName));
+ assertNotNull(messageList);
+ assertEquals(1, messageList.size());
+ }
+
+ public void testPlusMessageName() throws IOException, MessagingException {
+ // fails on Exchange 2003
+ session.deleteFolder("testfolder");
+ session.createMessageFolder("testfolder");
+ MimeMessage mimeMessage = createMimeMessage();
+ messageName = "test + plus.EML";
+ HashMap properties = new HashMap();
+ properties.put("draft", "0");
+ session.createMessage("testfolder", messageName, properties, getMimeBody(mimeMessage));
+ ExchangeSession.MessageList messageList = session.searchMessages("testfolder", session.equals("urlcompname", messageName));
+ assertNotNull(messageList);
+ assertEquals(1, messageList.size());
+ }
+
/**
* Cleanup
*/