diff --git a/src/java/davmail/exchange/ews/EWSMethod.java b/src/java/davmail/exchange/ews/EWSMethod.java index 902e7677..94e2bf95 100644 --- a/src/java/davmail/exchange/ews/EWSMethod.java +++ b/src/java/davmail/exchange/ews/EWSMethod.java @@ -432,12 +432,21 @@ public abstract class EWSMethod extends PostMethod { protected byte[] mimeContent; protected Set fieldUpdates; protected List attachments; + protected List fieldNames = new ArrayList(); @Override public String toString() { return "type: " + type + ' ' + super.toString(); } + @Override + public String put(String key, String value) { + if (get(key) == null) { + fieldNames.add(key); + } + return super.put(key, value); + } + /** * Write XML content to writer. * @@ -448,18 +457,23 @@ public abstract class EWSMethod extends PostMethod { writer.write(""); - for (Map.Entry mapEntry : this.entrySet()) { - if ("MeetingTimeZone".equals(mapEntry.getKey())) { + // write ordered fields + for (String key:fieldNames) { + if ("MeetingTimeZone".equals(key)) { writer.write(""); + } else if ("StartTimeZone".equals(key)) { + writer.write(""); } else { writer.write(""); - writer.write(StringUtil.xmlEncode(mapEntry.getValue())); + writer.write(StringUtil.xmlEncode(get(key))); writer.write(""); } } @@ -643,6 +657,7 @@ public abstract class EWSMethod extends PostMethod { && !"NoError".equals(result) && !"ErrorNameResolutionMultipleResults".equals(result) && !"ErrorNameResolutionNoResults".equals(result) + && !"ErrorFolderExists".equals(result) ) { errorDetail = result; } diff --git a/src/java/davmail/exchange/ews/EwsExchangeSession.java b/src/java/davmail/exchange/ews/EwsExchangeSession.java index 2dbfa5a7..53395af8 100644 --- a/src/java/davmail/exchange/ews/EwsExchangeSession.java +++ b/src/java/davmail/exchange/ews/EwsExchangeSession.java @@ -612,7 +612,7 @@ public class EwsExchangeSession extends ExchangeSession { folder = buildFolder(folderId.mailbox, item); folder.folderPath = folderPath; } else { - throw new HttpNotFoundException("Folder "+folderPath+" not found"); + throw new HttpNotFoundException("Folder " + folderPath + " not found"); } return folder; } @@ -625,8 +625,8 @@ public class EwsExchangeSession extends ExchangeSession { FolderPath path = new FolderPath(folderPath); EWSMethod.Item folder = new EWSMethod.Item(); folder.type = "Folder"; - folder.put("DisplayName", path.folderName); folder.put("FolderClass", folderClass); + folder.put("DisplayName", path.folderName); // TODO: handle properties CreateFolderMethod createFolderMethod = new CreateFolderMethod(getFolderId(path.parentPath), folder); executeMethod(createFolderMethod); @@ -875,7 +875,7 @@ public class EwsExchangeSession extends ExchangeSession { @Override public ItemResult createOrUpdate() throws IOException { - byte[] itemContent = Base64.encodeBase64(vCalendar.toString().getBytes("UTF-8")); + byte[] itemContent = Base64.encodeBase64(createMimeContent()); ItemResult itemResult = new ItemResult(); EWSMethod createOrUpdateItemMethod; @@ -887,7 +887,7 @@ public class EwsExchangeSession extends ExchangeSession { if (currentItem != null) { currentItemId = new ItemId(currentItem); currentEtag = currentItem.get(Field.get("etag").getResponseName()); - LOGGER.debug("Existing item found with etag: "+currentEtag+" id: "+currentItemId.id); + LOGGER.debug("Existing item found with etag: " + currentEtag + " id: " + currentItemId.id); } if ("*".equals(noneMatch)) { // create requested @@ -915,16 +915,16 @@ public class EwsExchangeSession extends ExchangeSession { DeleteItemMethod deleteItemMethod = new DeleteItemMethod(currentItemId, DeleteType.HardDelete, SendMeetingCancellations.SendToNone); executeMethod(deleteItemMethod); } //else { - // create - EWSMethod.Item newItem = new EWSMethod.Item(); - newItem.type = "CalendarItem"; - newItem.mimeContent = itemContent; - HashSet updates = new HashSet(); - // force urlcompname - updates.add(Field.createFieldUpdate("urlcompname", convertItemNameToEML(itemName))); - //updates.add(Field.createFieldUpdate("outlookmessageclass", "IPM.Appointment")); - newItem.setFieldUpdates(updates); - createOrUpdateItemMethod = new CreateItemMethod(MessageDisposition.SaveOnly, SendMeetingInvitations.SendToNone, getFolderId(folderPath), newItem); + // create + EWSMethod.Item newItem = new EWSMethod.Item(); + newItem.type = "CalendarItem"; + newItem.mimeContent = itemContent; + HashSet updates = new HashSet(); + // force urlcompname + updates.add(Field.createFieldUpdate("urlcompname", convertItemNameToEML(itemName))); + //updates.add(Field.createFieldUpdate("outlookmessageclass", "IPM.Appointment")); + newItem.setFieldUpdates(updates); + createOrUpdateItemMethod = new CreateItemMethod(MessageDisposition.SaveOnly, SendMeetingInvitations.SendToNone, getFolderId(folderPath), newItem); //} executeMethod(createOrUpdateItemMethod); @@ -1142,19 +1142,36 @@ public class EwsExchangeSession extends ExchangeSession { @Override protected void loadVtimezone() { - String timezoneId = getTimezoneidFromOptions(); + try { - createCalendarFolder("davmailtemp", null); - EWSMethod.Item item = new EWSMethod.Item(); - item.type = "CalendarItem"; - item.put("MeetingTimeZone", timezoneId); - CreateItemMethod createItemMethod = new CreateItemMethod(MessageDisposition.SaveOnly, SendMeetingInvitations.SendToNone, getFolderId("davmailtemp"), item); - executeMethod(createItemMethod); - item = createItemMethod.getResponseItem(); - VCalendar vCalendar = new VCalendar(getContent(new ItemId(item)), email, null); - this.vTimezone = vCalendar.getVTimezone(); - // delete temporary folder - deleteFolder("davmailtemp"); + String timezoneId = null; + if ("Exchange2010".equals(serverVersion)) { + GetUserConfigurationMethod getUserConfigurationMethod = new GetUserConfigurationMethod(); + executeMethod(getUserConfigurationMethod); + EWSMethod.Item item = getUserConfigurationMethod.getResponseItem(); + if (item != null) { + timezoneId = item.get("timezone"); + } + } else { + getTimezoneidFromOptions(); + } + if (timezoneId != null) { + createCalendarFolder("davmailtemp", null); + EWSMethod.Item item = new EWSMethod.Item(); + item.type = "CalendarItem"; + if ("Exchange2010".equals(serverVersion)) { + item.put("StartTimeZone", timezoneId); + } else { + item.put("MeetingTimeZone", timezoneId); + } + CreateItemMethod createItemMethod = new CreateItemMethod(MessageDisposition.SaveOnly, SendMeetingInvitations.SendToNone, getFolderId("davmailtemp"), item); + executeMethod(createItemMethod); + item = createItemMethod.getResponseItem(); + VCalendar vCalendar = new VCalendar(getContent(new ItemId(item)), email, null); + this.vTimezone = vCalendar.getVTimezone(); + // delete temporary folder + deleteFolder("davmailtemp"); + } } catch (IOException e) { LOGGER.warn("Unable to get VTIMEZONE info: " + e, e); } diff --git a/src/java/davmail/exchange/ews/GetUserAvailabilityMethod.java b/src/java/davmail/exchange/ews/GetUserAvailabilityMethod.java index 5e8a8941..e6b9293e 100644 --- a/src/java/davmail/exchange/ews/GetUserAvailabilityMethod.java +++ b/src/java/davmail/exchange/ews/GetUserAvailabilityMethod.java @@ -95,11 +95,11 @@ public class GetUserAvailabilityMethod extends EWSMethod { ""); } - @Override - protected void handleCustom(XMLStreamReader reader) throws XMLStreamException { - if (isStartTag(reader, "MergedFreeBusy")) { - this.mergedFreeBusy = reader.getElementText(); - } + @Override + protected void handleCustom(XMLStreamReader reader) throws XMLStreamException { + if (isStartTag(reader, "MergedFreeBusy")) { + this.mergedFreeBusy = reader.getElementText(); + } } public String getMergedFreeBusy() { diff --git a/src/java/davmail/exchange/ews/GetUserConfigurationMethod.java b/src/java/davmail/exchange/ews/GetUserConfigurationMethod.java new file mode 100644 index 00000000..7f354fd2 --- /dev/null +++ b/src/java/davmail/exchange/ews/GetUserConfigurationMethod.java @@ -0,0 +1,87 @@ +/* + * DavMail POP/IMAP/SMTP/CalDav/LDAP Exchange Gateway + * Copyright (C) 2010 Mickael Guessant + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package davmail.exchange.ews; + +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import java.io.IOException; +import java.io.Writer; + +/** + * Get User Configuration method. + */ +public class GetUserConfigurationMethod extends EWSMethod { + + /** + * Get User Configuration method. + * + */ + public GetUserConfigurationMethod() { + super("UserConfiguration", "GetUserConfiguration"); + folderId = DistinguishedFolderId.getInstance(null, DistinguishedFolderId.Name.root); + } + + @Override + protected void writeSoapBody(Writer writer) throws IOException { + writer.write(""); + folderId.write(writer); + writer.write(""); + writer.write("All"); + } + + @Override + protected void handleCustom(XMLStreamReader reader) throws XMLStreamException { + if (isStartTag(reader, "UserConfiguration")) { + responseItems.add(handleUserConfiguration(reader)); + } + } + + private Item handleUserConfiguration(XMLStreamReader reader) throws XMLStreamException { + Item responseItem = new Item(); + while (reader.hasNext() && !(isEndTag(reader, "UserConfiguration"))) { + int event = reader.next(); + if (event == XMLStreamConstants.START_ELEMENT) { + String tagLocalName = reader.getLocalName(); + if ("DictionaryEntry".equals(tagLocalName)) { + handleDictionaryEntry(reader, responseItem); + } + } + } + return responseItem; + } + + private void handleDictionaryEntry(XMLStreamReader reader, Item responseItem) throws XMLStreamException { + String key = null; + while (reader.hasNext() && !(isEndTag(reader, "DictionaryEntry"))) { + int event = reader.next(); + if (event == XMLStreamConstants.START_ELEMENT) { + String tagLocalName = reader.getLocalName(); + if ("Value".equals(tagLocalName)) { + if (key == null) { + key = reader.getElementText(); + } else { + responseItem.put(key, reader.getElementText()); + } + } + } + } + } + +} diff --git a/src/java/davmail/util/StringUtil.java b/src/java/davmail/util/StringUtil.java index d5d82761..17214957 100644 --- a/src/java/davmail/util/StringUtil.java +++ b/src/java/davmail/util/StringUtil.java @@ -178,14 +178,16 @@ public final class StringUtil { */ public static String xmlEncode(String name) { String result = name; - if (name.indexOf('&') >= 0) { - result = AMP_PATTERN.matcher(result).replaceAll("&"); - } - if (name.indexOf('<') >= 0) { - result = LT_PATTERN.matcher(result).replaceAll("<"); - } - if (name.indexOf('>') >= 0) { - result = GT_PATTERN.matcher(result).replaceAll(">"); + if (name != null) { + if (name.indexOf('&') >= 0) { + result = AMP_PATTERN.matcher(result).replaceAll("&"); + } + if (name.indexOf('<') >= 0) { + result = LT_PATTERN.matcher(result).replaceAll("<"); + } + if (name.indexOf('>') >= 0) { + result = GT_PATTERN.matcher(result).replaceAll(">"); + } } return result; } diff --git a/src/test/davmail/exchange/ews/TestEwsExchangeSession.java b/src/test/davmail/exchange/ews/TestEwsExchangeSession.java index 45e35822..894998bf 100644 --- a/src/test/davmail/exchange/ews/TestEwsExchangeSession.java +++ b/src/test/davmail/exchange/ews/TestEwsExchangeSession.java @@ -66,4 +66,15 @@ public class TestEwsExchangeSession extends AbstractExchangeSessionTestCase { } } + public void testGetUserConfiguration() throws IOException { + GetUserConfigurationMethod getUserConfigurationMethod = new GetUserConfigurationMethod(); + ewsSession.executeMethod(getUserConfigurationMethod); + EWSMethod.Item item = getUserConfigurationMethod.getResponseItem(); + assertNotNull(item); + } + + public void testTimezone() { + ewsSession.loadVtimezone(); + } + }