From 722be0aeb18284af0952aed2ae9e2c34c78bb86f Mon Sep 17 00:00:00 2001 From: mguessan Date: Sat, 24 Jul 2010 12:38:10 +0000 Subject: [PATCH] Dav: patch filter on invalid Exchange Webdav response git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@1262 3d1905a2-6b24-0410-a738-b14d5a86fcbd --- .../exchange/dav/DavExchangeSession.java | 10 ++-- .../exchange/dav/ExchangePropPatchMethod.java | 54 ++++++++++--------- src/java/davmail/exchange/dav/Field.java | 2 +- 3 files changed, 35 insertions(+), 31 deletions(-) diff --git a/src/java/davmail/exchange/dav/DavExchangeSession.java b/src/java/davmail/exchange/dav/DavExchangeSession.java index 13b04b92..d71b6d9d 100644 --- a/src/java/davmail/exchange/dav/DavExchangeSession.java +++ b/src/java/davmail/exchange/dav/DavExchangeSession.java @@ -44,6 +44,8 @@ import org.apache.jackrabbit.webdav.property.DavProperty; import org.apache.jackrabbit.webdav.property.DavPropertyName; import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; import org.w3c.dom.Node; import javax.mail.MessagingException; @@ -616,12 +618,7 @@ public class DavExchangeSession extends ExchangeSession { */ public ItemResult createOrUpdate() throws IOException { int status = 0; - ExchangePropPatchMethod propPatchMethod = new ExchangePropPatchMethod(URIUtil.encodePath(getHref()), buildProperties()) { - @Override - protected void processResponseBody(HttpState httpState, HttpConnection httpConnection) { - // ignore response body, sometimes invalid with exchange mapi properties - } - }; + ExchangePropPatchMethod propPatchMethod = new ExchangePropPatchMethod(URIUtil.encodePath(getHref()), buildProperties()); propPatchMethod.setRequestHeader("Translate", "f"); if (etag != null) { propPatchMethod.setRequestHeader("If-Match", etag); @@ -632,6 +629,7 @@ public class DavExchangeSession extends ExchangeSession { try { status = httpClient.executeMethod(propPatchMethod); if (status == HttpStatus.SC_MULTI_STATUS) { + List responses = propPatchMethod.getResponses(); //noinspection VariableNotUsedInsideIf if (etag == null) { status = HttpStatus.SC_CREATED; diff --git a/src/java/davmail/exchange/dav/ExchangePropPatchMethod.java b/src/java/davmail/exchange/dav/ExchangePropPatchMethod.java index fd1f6fbc..a9e272de 100644 --- a/src/java/davmail/exchange/dav/ExchangePropPatchMethod.java +++ b/src/java/davmail/exchange/dav/ExchangePropPatchMethod.java @@ -19,7 +19,7 @@ package davmail.exchange.dav; import org.apache.commons.httpclient.*; -import org.apache.commons.httpclient.methods.EntityEnclosingMethod; +import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.RequestEntity; import org.apache.jackrabbit.webdav.MultiStatusResponse; import org.apache.jackrabbit.webdav.property.DefaultDavProperty; @@ -37,7 +37,7 @@ import java.util.*; * Custom Exchange PROPPATCH method. * Supports extended property update with type. */ -public class ExchangePropPatchMethod extends EntityEnclosingMethod { +public class ExchangePropPatchMethod extends PostMethod { protected static final Logger logger = Logger.getLogger(ExchangePropPatchMethod.class); static final String TYPE_NAMESPACE = "urn:schemas-microsoft-com:datatypes"; @@ -196,9 +196,23 @@ public class ExchangePropPatchMethod extends EntityEnclosingMethod { try { XMLInputFactory xmlInputFactory = getXmlInputFactory(); reader = xmlInputFactory.createXMLStreamReader(new FilterInputStream(getResponseBodyAsStream()) { + final byte[] lastbytes = new byte[3]; + @Override - public int read() throws IOException { - return in.read(); + public int read(byte b[], int off, int len) throws IOException { + int count = in.read(b, off, len); + // patch invalid element name + for (int i = 0; i < count; i++) { + byte currentByte = b[off + i]; + if ((lastbytes[0] == '<') && (currentByte >= '0' && currentByte <= '9')) { + // move invalid first tag char to valid range + b[off + i] = (byte) (currentByte + 49); + } + lastbytes[0] = lastbytes[1]; + lastbytes[1] = lastbytes[2]; + lastbytes[2] = currentByte; + } + return count; } }); @@ -218,9 +232,8 @@ public class ExchangePropPatchMethod extends EntityEnclosingMethod { } protected void handleResponse(XMLStreamReader reader) throws XMLStreamException { - MultiStatusResponse multiStatusResponse = null; - int status = 0; String href = null; + String responseStatus = ""; while (reader.hasNext() && !isEndTag(reader, "response")) { int event = reader.next(); if (event == XMLStreamConstants.START_ELEMENT) { @@ -228,15 +241,11 @@ public class ExchangePropPatchMethod extends EntityEnclosingMethod { if ("href".equals(tagLocalName)) { href = reader.getElementText(); } else if ("status".equals(tagLocalName)) { - String responseStatus = reader.getElementText(); - if ("HTTP/1.1 200 OK".equals(responseStatus)) { - status = HttpStatus.SC_OK; - } else if ("HTTP/1.1 201 Created".equals(responseStatus)) { - status = HttpStatus.SC_CREATED; - } - multiStatusResponse = new MultiStatusResponse(href, status); + responseStatus = reader.getElementText(); } else if ("propstat".equals(tagLocalName)) { + MultiStatusResponse multiStatusResponse = new MultiStatusResponse(href, responseStatus); handlePropstat(reader, multiStatusResponse); + responses.add(multiStatusResponse); } } } @@ -252,6 +261,8 @@ public class ExchangePropPatchMethod extends EntityEnclosingMethod { if ("status".equals(tagLocalName)) { if ("HTTP/1.1 200 OK".equals(reader.getElementText())) { propstatStatus = HttpStatus.SC_OK; + } else { + propstatStatus = 0; } } else if ("prop".equals(tagLocalName) && propstatStatus == HttpStatus.SC_OK) { handleProperty(reader, multiStatusResponse); @@ -263,17 +274,12 @@ public class ExchangePropPatchMethod extends EntityEnclosingMethod { protected void handleProperty(XMLStreamReader reader, MultiStatusResponse multiStatusResponse) throws XMLStreamException { - while (reader.hasNext() && !isEndTag(reader, "prop")) { - try { - int event = reader.next(); - if (event == XMLStreamConstants.START_ELEMENT) { - String tagLocalName = reader.getLocalName(); - Namespace namespace = Namespace.getNamespace(reader.getNamespaceURI()); - multiStatusResponse.add(new DefaultDavProperty(tagLocalName, reader.getElementText(), namespace)); - } - } catch (XMLStreamException e) { - // ignore, exchange invalid response - logger.debug("Ignore invalid response tag name"); + while (reader.hasNext() && !isEndTag(reader, "prop")){ + int event = reader.nextTag(); + if (event == XMLStreamConstants.START_ELEMENT) { + String tagLocalName = reader.getLocalName(); + Namespace namespace = Namespace.getNamespace(reader.getNamespaceURI()); + multiStatusResponse.add(new DefaultDavProperty(tagLocalName, reader.getElementText(), namespace)); } } } diff --git a/src/java/davmail/exchange/dav/Field.java b/src/java/davmail/exchange/dav/Field.java index 0978e791..64e51f5e 100644 --- a/src/java/davmail/exchange/dav/Field.java +++ b/src/java/davmail/exchange/dav/Field.java @@ -490,7 +490,7 @@ public class Field { // multivalued field, split values separated by \n String[] values = value.split("\n"); for (final String singleValue : values) { - buffer.append(""); + buffer.append(""); buffer.append(StringUtil.xmlEncode(singleValue)); buffer.append(""); }