From 0529be03a19d7364c136e377c348794ff8e92f5c Mon Sep 17 00:00:00 2001 From: mguessan Date: Fri, 27 Aug 2010 07:13:51 +0000 Subject: [PATCH] Caldav: make timezone name retrieval more robust git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@1391 3d1905a2-6b24-0410-a738-b14d5a86fcbd --- src/java/davmail/exchange/XMLStreamUtil.java | 29 ++++++++++++++ .../exchange/dav/DavExchangeSession.java | 40 +++++++++++++------ 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/src/java/davmail/exchange/XMLStreamUtil.java b/src/java/davmail/exchange/XMLStreamUtil.java index 56081e32..a37b0bdf 100644 --- a/src/java/davmail/exchange/XMLStreamUtil.java +++ b/src/java/davmail/exchange/XMLStreamUtil.java @@ -93,4 +93,33 @@ public final class XMLStreamUtil { } return results; } + + /** + * Get attribute value for attribute name. + * reader must be at START_ELEMENT state + * + * @param reader xml stream reader + * @param attributeName attribute name + * @return attribute value + */ + public static String getAttributeValue(XMLStreamReader reader, String attributeName) { + for (int i = 0; i < reader.getAttributeCount(); i++) { + if (attributeName.equals(reader.getAttributeLocalName(i))) { + return reader.getAttributeValue(i); + } + } + return null; + } + + /** + * Test if reader is on a start tag named tagLocalName. + * + * @param reader xml stream reader + * @param tagLocalName tag local name + * @return true if reader is on a start tag named tagLocalName + */ + public static boolean isStartTag(XMLStreamReader reader, String tagLocalName) { + return (reader.getEventType() == XMLStreamConstants.START_ELEMENT) && (reader.getLocalName().equals(tagLocalName)); + } + } diff --git a/src/java/davmail/exchange/dav/DavExchangeSession.java b/src/java/davmail/exchange/dav/DavExchangeSession.java index 06e3c5fb..dbdc2d13 100644 --- a/src/java/davmail/exchange/dav/DavExchangeSession.java +++ b/src/java/davmail/exchange/dav/DavExchangeSession.java @@ -53,6 +53,9 @@ import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import javax.mail.internet.MimePart; import javax.mail.util.SharedByteArrayInputStream; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; import java.io.*; import java.net.URL; import java.text.ParseException; @@ -1963,19 +1966,7 @@ public class DavExchangeSession extends ExchangeSession { if (responses.length == 1) { byte[] roamingdictionary = getBinaryPropertyIfExists(responses[0].getProperties(HttpStatus.SC_OK), "roamingdictionary"); if (roamingdictionary != null) { - String roamingdictionaryString = new String(roamingdictionary, "UTF-8"); - int startIndex = roamingdictionaryString.lastIndexOf("18-"); - if (startIndex >= 0) { - int endIndex = roamingdictionaryString.indexOf('"', startIndex); - if (endIndex >= 0) { - String timezoneName = roamingdictionaryString.substring(startIndex + 3, endIndex); - try { - timezoneId = ResourceBundle.getBundle("timezoneids").getString(timezoneName); - } catch (MissingResourceException mre) { - LOGGER.warn("Invalid timezone name: " + timezoneName); - } - } - } + timezoneId = ResourceBundle.getBundle("timezoneids").getString(getTimezoneNameFromRoamingDictionary(roamingdictionary)); } } } catch (UnsupportedEncodingException e) { @@ -1986,6 +1977,29 @@ public class DavExchangeSession extends ExchangeSession { return timezoneId; } + protected String getTimezoneNameFromRoamingDictionary(byte[] roamingdictionary) { + String timezoneName = null; + XMLStreamReader reader; + try { + XMLInputFactory xmlInputFactory = XMLStreamUtil.getXmlInputFactory(); + reader = xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(roamingdictionary)); + while (reader.hasNext()) { + reader.next(); + if (XMLStreamUtil.isStartTag(reader, "e") + && "18-timezone".equals( XMLStreamUtil.getAttributeValue(reader, "k"))) { + String value = XMLStreamUtil.getAttributeValue(reader, "v"); + if (value != null && value.startsWith("18-")) { + timezoneName = value.substring(3); + } + } + } + + } catch (XMLStreamException e) { + LOGGER.error("Error while parsing RoamingDictionary: " + e, e); + } + return timezoneName; + } + @Override protected ItemResult internalCreateOrUpdateContact(String folderPath, String itemName, Map properties, String etag, String noneMatch) throws IOException { return new Contact(getFolderPath(folderPath), itemName, properties, etag, noneMatch).createOrUpdate();