Major refactoring: replace deprecated jakarta slide with jackrabbit and upgrade httpclient

git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@488 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
mguessan 2009-04-01 15:51:12 +00:00
parent 44998b5631
commit 4fe7ea1026
13 changed files with 203 additions and 374 deletions

BIN
lib/commons-codec-1.3.jar Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
lib/slf4j-api-1.3.1.jar Normal file

Binary file not shown.

BIN
lib/slf4j-log4j12-1.3.1.jar Normal file

Binary file not shown.

Binary file not shown.

BIN
lib/xercesImpl-2.8.1.jar Normal file

Binary file not shown.

View File

@ -1,9 +1,8 @@
package davmail;
import davmail.exchange.ExchangeSession;
import davmail.exchange.ExchangeSessionFactory;
import davmail.tray.DavGatewayTray;
import org.apache.commons.httpclient.util.Base64;
import org.apache.commons.codec.binary.Base64;
import java.io.*;
import java.net.Socket;
@ -166,10 +165,10 @@ public class AbstractConnection extends Thread {
}
protected String base64Encode(String value) {
return new String(Base64.encode(value.getBytes()));
return new String(new Base64().encode(value.getBytes()));
}
protected String base64Decode(String value) {
return new String(Base64.decode(value.getBytes()));
return new String(new Base64().decode(value.getBytes()));
}
}

View File

@ -8,12 +8,16 @@ import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.util.URIUtil;
import org.apache.jackrabbit.webdav.MultiStatusResponse;
import org.apache.jackrabbit.webdav.client.methods.CopyMethod;
import org.apache.jackrabbit.webdav.client.methods.MoveMethod;
import org.apache.jackrabbit.webdav.client.methods.PropPatchMethod;
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.DefaultDavProperty;
import org.apache.jackrabbit.webdav.xml.Namespace;
import org.apache.log4j.Logger;
import org.apache.webdav.lib.Property;
import org.apache.webdav.lib.ResponseEntity;
import org.apache.webdav.lib.methods.CopyMethod;
import org.apache.webdav.lib.methods.MoveMethod;
import org.apache.webdav.lib.methods.PropPatchMethod;
import org.htmlcleaner.CommentToken;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
@ -40,42 +44,43 @@ public class ExchangeSession {
protected static final int FREE_BUSY_INTERVAL = 15;
protected static final Vector<String> EVENT_REQUEST_PROPERTIES = new Vector<String>();
protected static final DavPropertyNameSet EVENT_REQUEST_PROPERTIES = new DavPropertyNameSet();
static {
EVENT_REQUEST_PROPERTIES.add("DAV:getetag");
EVENT_REQUEST_PROPERTIES.add(DavPropertyName.GETETAG);
}
protected static final Vector<String> WELL_KNOWN_FOLDERS = new Vector<String>();
protected static final DavPropertyNameSet WELL_KNOWN_FOLDERS = new DavPropertyNameSet();
static {
WELL_KNOWN_FOLDERS.add("urn:schemas:httpmail:inbox");
WELL_KNOWN_FOLDERS.add("urn:schemas:httpmail:deleteditems");
WELL_KNOWN_FOLDERS.add("urn:schemas:httpmail:sentitems");
WELL_KNOWN_FOLDERS.add("urn:schemas:httpmail:sendmsg");
WELL_KNOWN_FOLDERS.add("urn:schemas:httpmail:drafts");
WELL_KNOWN_FOLDERS.add("urn:schemas:httpmail:calendar");
Namespace httpmailNameSpace = Namespace.getNamespace("urn:schemas:httpmail:");
WELL_KNOWN_FOLDERS.add(DavPropertyName.create("inbox", httpmailNameSpace));
WELL_KNOWN_FOLDERS.add(DavPropertyName.create("deleteditems", httpmailNameSpace));
WELL_KNOWN_FOLDERS.add(DavPropertyName.create("sentitems", httpmailNameSpace));
WELL_KNOWN_FOLDERS.add(DavPropertyName.create("sendmsg", httpmailNameSpace));
WELL_KNOWN_FOLDERS.add(DavPropertyName.create("drafts", httpmailNameSpace));
WELL_KNOWN_FOLDERS.add(DavPropertyName.create("calendar", httpmailNameSpace));
}
protected static final Vector<String> DISPLAY_NAME = new Vector<String>();
protected static final DavPropertyNameSet DISPLAY_NAME = new DavPropertyNameSet();
static {
DISPLAY_NAME.add("DAV:displayname");
DISPLAY_NAME.add(DavPropertyName.DISPLAYNAME);
}
protected static final Vector<String> FOLDER_PROPERTIES = new Vector<String>();
protected static final DavPropertyNameSet FOLDER_PROPERTIES = new DavPropertyNameSet();
static {
FOLDER_PROPERTIES.add("DAV:hassubs");
FOLDER_PROPERTIES.add("DAV:nosubs");
FOLDER_PROPERTIES.add("urn:schemas:httpmail:unreadcount");
FOLDER_PROPERTIES.add("http://schemas.microsoft.com/repl/contenttag");
FOLDER_PROPERTIES.add(DavPropertyName.create("hassubs"));
FOLDER_PROPERTIES.add(DavPropertyName.create("nosubs"));
FOLDER_PROPERTIES.add(DavPropertyName.create("unreadcount", Namespace.getNamespace("urn:schemas:httpmail:")));
FOLDER_PROPERTIES.add(DavPropertyName.create("contenttag", Namespace.getNamespace("http://schemas.microsoft.com/repl/")));
}
protected static final Vector<String> CONTENT_TAG = new Vector<String>();
protected static final DavPropertyNameSet CONTENT_TAG = new DavPropertyNameSet();
static {
CONTENT_TAG.add("http://schemas.microsoft.com/repl/contenttag");
CONTENT_TAG.add(DavPropertyName.create("contenttag", Namespace.getNamespace("http://schemas.microsoft.com/repl/")));
}
@ -402,36 +407,34 @@ public class ExchangeSession {
protected void getWellKnownFolders() throws IOException {
// Retrieve well known URLs
Enumeration foldersEnum = DavGatewayHttpClientFacade.executePropFindMethod(
MultiStatusResponse[] responses = DavGatewayHttpClientFacade.executePropFindMethod(
httpClient, URIUtil.encodePath(mailPath), 0, WELL_KNOWN_FOLDERS);
if (!foldersEnum.hasMoreElements()) {
if (responses.length == 0) {
throw new IOException("Unable to get mail folders");
}
ResponseEntity inboxResponse = (ResponseEntity) foldersEnum.
nextElement();
Enumeration inboxPropsEnum = inboxResponse.getProperties();
if (!inboxPropsEnum.hasMoreElements()) {
Iterator inboxPropsEnum = responses[0].getProperties(HttpStatus.SC_OK).iterator();
if (!inboxPropsEnum.hasNext()) {
throw new IOException("Unable to get mail folders");
}
while (inboxPropsEnum.hasMoreElements()) {
Property inboxProp = (Property) inboxPropsEnum.nextElement();
if ("inbox".equals(inboxProp.getLocalName())) {
inboxUrl = URIUtil.decode(inboxProp.getPropertyAsString());
while (inboxPropsEnum.hasNext()) {
DavProperty inboxProp = (DavProperty) inboxPropsEnum.next();
if ("inbox".equals(inboxProp.getName().getName())) {
inboxUrl = URIUtil.decode((String) inboxProp.getValue());
}
if ("deleteditems".equals(inboxProp.getLocalName())) {
deleteditemsUrl = URIUtil.decode(inboxProp.getPropertyAsString());
if ("deleteditems".equals(inboxProp.getName().getName())) {
deleteditemsUrl = URIUtil.decode((String) inboxProp.getValue());
}
if ("sentitems".equals(inboxProp.getLocalName())) {
sentitemsUrl = URIUtil.decode(inboxProp.getPropertyAsString());
if ("sentitems".equals(inboxProp.getName().getName())) {
sentitemsUrl = URIUtil.decode((String) inboxProp.getValue());
}
if ("sendmsg".equals(inboxProp.getLocalName())) {
sendmsgUrl = URIUtil.decode(inboxProp.getPropertyAsString());
if ("sendmsg".equals(inboxProp.getName().getName())) {
sendmsgUrl = URIUtil.decode((String) inboxProp.getValue());
}
if ("drafts".equals(inboxProp.getLocalName())) {
draftsUrl = URIUtil.decode(inboxProp.getPropertyAsString());
if ("drafts".equals(inboxProp.getName().getName())) {
draftsUrl = URIUtil.decode((String) inboxProp.getValue());
}
if ("calendar".equals(inboxProp.getLocalName())) {
calendarUrl = URIUtil.decode(inboxProp.getPropertyAsString());
if ("calendar".equals(inboxProp.getName().getName())) {
calendarUrl = URIUtil.decode((String) inboxProp.getValue());
}
}
LOGGER.debug("Inbox URL : " + inboxUrl +
@ -458,10 +461,9 @@ public class ExchangeSession {
PropPatchMethod patchMethod;
// create the message first as draft
if (properties.containsKey("draft")) {
patchMethod = new PropPatchMethod(messageUrl);
patchMethod = new PropPatchMethod(messageUrl, buildProperties(properties));
try {
// update message with blind carbon copy and other flags
addProperties(patchMethod, properties);
int statusCode = httpClient.executeMethod(patchMethod);
if (statusCode != HttpStatus.SC_MULTI_STATUS) {
throw new IOException("Unable to create message " + messageUrl + ": " + statusCode + " " + patchMethod.getStatusLine());
@ -498,10 +500,9 @@ public class ExchangeSession {
// add bcc and other properties
if (properties.size() > 0) {
patchMethod = new PropPatchMethod(messageUrl);
patchMethod = new PropPatchMethod(messageUrl, buildProperties(properties));
try {
// update message with blind carbon copy and other flags
addProperties(patchMethod, properties);
int statusCode = httpClient.executeMethod(patchMethod);
if (statusCode != HttpStatus.SC_MULTI_STATUS) {
throw new IOException("Unable to patch message " + messageUrl + ": " + statusCode + " " + patchMethod.getStatusLine());
@ -513,37 +514,37 @@ public class ExchangeSession {
}
}
protected Message buildMessage(ResponseEntity responseEntity) throws URIException {
protected Message buildMessage(MultiStatusResponse responseEntity) throws URIException {
Message message = new Message();
message.messageUrl = URIUtil.decode(responseEntity.getHref());
Enumeration propertiesEnum = responseEntity.getProperties();
while (propertiesEnum.hasMoreElements()) {
Property prop = (Property) propertiesEnum.nextElement();
String localName = prop.getLocalName();
Iterator propertiesEnum = responseEntity.getProperties(HttpStatus.SC_OK).iterator();
while (propertiesEnum.hasNext()) {
DavProperty prop = (DavProperty) propertiesEnum.next();
String localName = prop.getName().getName();
if ("x0e080003".equals(localName)) {
message.size = Integer.parseInt(prop.getPropertyAsString());
message.size = Integer.parseInt((String) prop.getValue());
} else if ("uid".equals(localName)) {
message.uid = prop.getPropertyAsString();
message.uid = (String) prop.getValue();
} else if ("x0e230003".equals(localName)) {
message.imapUid = Long.parseLong(prop.getPropertyAsString());
message.imapUid = Long.parseLong((String) prop.getValue());
} else if ("read".equals(localName)) {
message.read = "1".equals(prop.getPropertyAsString());
message.read = "1".equals(prop.getValue());
} else if ("x10830003".equals(localName)) {
message.junk = "1".equals(prop.getPropertyAsString());
message.junk = "1".equals(prop.getValue());
} else if ("x10900003".equals(localName)) {
message.flagged = "2".equals(prop.getPropertyAsString());
message.flagged = "2".equals(prop.getValue());
} else if ("x0E070003".equals(localName)) {
message.draft = "9".equals(prop.getPropertyAsString());
message.draft = "9".equals(prop.getValue());
} else if ("x10810003".equals(localName)) {
message.answered = "102".equals(prop.getPropertyAsString()) || "103".equals(prop.getPropertyAsString());
message.forwarded = "104".equals(prop.getPropertyAsString());
} else if ("date".equals(prop.getLocalName())) {
message.date = prop.getPropertyAsString();
message.answered = "102".equals(prop.getValue()) || "103".equals(prop.getValue());
message.forwarded = "104".equals(prop.getValue());
} else if ("date".equals(localName)) {
message.date = (String) prop.getValue();
} else if ("isdeleted".equals(localName)) {
message.deleted = "1".equals(prop.getPropertyAsString());
} else if ("message-id".equals(prop.getLocalName())) {
message.messageId = prop.getPropertyAsString();
message.deleted = "1".equals(prop.getValue());
} else if ("message-id".equals(localName)) {
message.messageId = (String) prop.getValue();
if (message.messageId.startsWith("<") && message.messageId.endsWith(">")) {
message.messageId = message.messageId.substring(1, message.messageId.length() - 1);
}
@ -553,40 +554,41 @@ public class ExchangeSession {
return message;
}
protected void addProperties(PropPatchMethod patchMethod, Map<String, String> properties) {
protected List<DavProperty> buildProperties(Map<String, String> properties) {
ArrayList<DavProperty> list = new ArrayList<DavProperty>();
for (Map.Entry<String, String> entry : properties.entrySet()) {
if ("read".equals(entry.getKey())) {
patchMethod.addPropertyToSet("read", entry.getValue(), "e", "urn:schemas:httpmail:");
list.add(new DefaultDavProperty(DavPropertyName.create("read", Namespace.getNamespace("urn:schemas:httpmail:")), entry.getValue()));
} else if ("junk".equals(entry.getKey())) {
patchMethod.addPropertyToSet("x10830003", entry.getValue(), "f", "http://schemas.microsoft.com/mapi/proptag/");
list.add(new DefaultDavProperty(DavPropertyName.create("x10830003", Namespace.getNamespace("http://schemas.microsoft.com/mapi/proptag/")), entry.getValue()));
} else if ("flagged".equals(entry.getKey())) {
patchMethod.addPropertyToSet("x10900003", entry.getValue(), "f", "http://schemas.microsoft.com/mapi/proptag/");
list.add(new DefaultDavProperty(DavPropertyName.create("x10900003", Namespace.getNamespace("http://schemas.microsoft.com/mapi/proptag/")), entry.getValue()));
} else if ("answered".equals(entry.getKey())) {
patchMethod.addPropertyToSet("x10810003", entry.getValue(), "f", "http://schemas.microsoft.com/mapi/proptag/");
list.add(new DefaultDavProperty(DavPropertyName.create("x10810003", Namespace.getNamespace("http://schemas.microsoft.com/mapi/proptag/")), entry.getValue()));
if ("102".equals(entry.getValue())) {
patchMethod.addPropertyToSet("x10800003", "261", "f", "http://schemas.microsoft.com/mapi/proptag/");
list.add(new DefaultDavProperty(DavPropertyName.create("x10800003", Namespace.getNamespace("http://schemas.microsoft.com/mapi/proptag/")), "261"));
}
} else if ("forwarded".equals(entry.getKey())) {
patchMethod.addPropertyToSet("x10810003", entry.getValue(), "f", "http://schemas.microsoft.com/mapi/proptag/");
list.add(new DefaultDavProperty(DavPropertyName.create("x10810003", Namespace.getNamespace("http://schemas.microsoft.com/mapi/proptag/")), entry.getValue()));
if ("104".equals(entry.getValue())) {
patchMethod.addPropertyToSet("x10800003", "262", "f", "http://schemas.microsoft.com/mapi/proptag/");
list.add(new DefaultDavProperty(DavPropertyName.create("x10800003", Namespace.getNamespace("http://schemas.microsoft.com/mapi/proptag/")), "262"));
}
} else if ("bcc".equals(entry.getKey())) {
patchMethod.addPropertyToSet("bcc", entry.getValue(), "b", "urn:schemas:mailheader:");
list.add(new DefaultDavProperty(DavPropertyName.create("bcc", Namespace.getNamespace("urn:schemas:mailheader:")), entry.getValue()));
} else if ("draft".equals(entry.getKey())) {
patchMethod.addPropertyToSet("x0E070003", entry.getValue(), "f", "http://schemas.microsoft.com/mapi/proptag/");
list.add(new DefaultDavProperty(DavPropertyName.create("x0E070003", Namespace.getNamespace("http://schemas.microsoft.com/mapi/proptag/")), entry.getValue()));
} else if ("deleted".equals(entry.getKey())) {
patchMethod.addPropertyToSet("isdeleted", entry.getValue(), "d", "DAV:");
list.add(new DefaultDavProperty(DavPropertyName.create("isdeleted"), entry.getValue()));
} else if ("datereceived".equals(entry.getKey())) {
patchMethod.addPropertyToSet("datereceived", entry.getValue(), "e", "urn:schemas:httpmail:");
list.add(new DefaultDavProperty(DavPropertyName.create("datereceived", Namespace.getNamespace("urn:schemas:httpmail:")), entry.getValue()));
}
}
return list;
}
public void updateMessage(Message message, Map<String, String> properties) throws IOException {
PropPatchMethod patchMethod = new PropPatchMethod(URIUtil.encodePathQuery(message.messageUrl));
PropPatchMethod patchMethod = new PropPatchMethod(URIUtil.encodePathQuery(message.messageUrl), buildProperties(properties));
try {
addProperties(patchMethod, properties);
int statusCode = httpClient.executeMethod(patchMethod);
if (statusCode != HttpStatus.SC_MULTI_STATUS) {
throw new IOException("Unable to update message properties");
@ -615,13 +617,11 @@ public class ExchangeSession {
searchRequest += conditions;
}
searchRequest += " ORDER BY \"urn:schemas:httpmail:date\" ASC";
Enumeration folderEnum = DavGatewayHttpClientFacade.executeSearchMethod(
MultiStatusResponse[] responses = DavGatewayHttpClientFacade.executeSearchMethod(
httpClient, URIUtil.encodePath(folderUrl), searchRequest);
while (folderEnum.hasMoreElements()) {
ResponseEntity entity = (ResponseEntity) folderEnum.nextElement();
Message message = buildMessage(entity);
for (MultiStatusResponse response : responses) {
Message message = buildMessage(response);
messages.add(message);
}
Collections.sort(messages);
@ -636,33 +636,32 @@ public class ExchangeSession {
" FROM Scope('" + mode + " TRAVERSAL OF \"" + getFolderPath(folderName) + "\"')\n" +
" WHERE \"DAV:ishidden\" = False AND \"DAV:isfolder\" = True \n" +
" AND (\"DAV:contentclass\"='urn:content-classes:mailfolder' OR \"DAV:contentclass\"='urn:content-classes:folder')";
Enumeration folderEnum = DavGatewayHttpClientFacade.executeSearchMethod(
MultiStatusResponse[] responses = DavGatewayHttpClientFacade.executeSearchMethod(
httpClient, URIUtil.encodePath(mailPath), searchRequest);
while (folderEnum.hasMoreElements()) {
ResponseEntity entity = (ResponseEntity) folderEnum.nextElement();
folders.add(buildFolder(entity));
for (MultiStatusResponse response : responses) {
folders.add(buildFolder(response));
}
return folders;
}
protected Folder buildFolder(ResponseEntity entity) throws URIException {
protected Folder buildFolder(MultiStatusResponse entity) throws URIException {
String href = URIUtil.decode(entity.getHref());
Folder folder = new Folder();
Enumeration enumeration = entity.getProperties();
while (enumeration.hasMoreElements()) {
Property property = (Property) enumeration.nextElement();
if ("hassubs".equals(property.getLocalName())) {
folder.hasChildren = "1".equals(property.getPropertyAsString());
Iterator enumeration = entity.getProperties(HttpStatus.SC_OK).iterator();
while (enumeration.hasNext()) {
DavProperty property = (DavProperty) enumeration.next();
if ("hassubs".equals(property.getName().getName())) {
folder.hasChildren = "1".equals((String) property.getValue());
}
if ("nosubs".equals(property.getLocalName())) {
folder.noInferiors = "1".equals(property.getPropertyAsString());
if ("nosubs".equals(property.getName().getName())) {
folder.noInferiors = "1".equals((String) property.getValue());
}
if ("unreadcount".equals(property.getLocalName())) {
folder.unreadCount = Integer.parseInt(property.getPropertyAsString());
if ("unreadcount".equals(property.getName().getName())) {
folder.unreadCount = Integer.parseInt((String) property.getValue());
}
if ("contenttag".equals(property.getLocalName())) {
folder.contenttag = property.getPropertyAsString();
if ("contenttag".equals(property.getName().getName())) {
folder.contenttag = (String) property.getValue();
}
}
if (href.endsWith("/")) {
@ -720,12 +719,11 @@ public class ExchangeSession {
" FROM Scope('SHALLOW TRAVERSAL OF \"" + folderUrl + "\"')\n" +
" WHERE \"DAV:isfolder\" = False\n" +
" AND \"DAV:getlastmodified\" < '" + formatDate(cal.getTime()) + "'\n";
Enumeration folderEnum = DavGatewayHttpClientFacade.executeSearchMethod(
MultiStatusResponse[] responses = DavGatewayHttpClientFacade.executeSearchMethod(
httpClient, URIUtil.encodePath(folderUrl), searchRequest);
while (folderEnum.hasMoreElements()) {
ResponseEntity entity = (ResponseEntity) folderEnum.nextElement();
String messageUrl = entity.getHref();
for (MultiStatusResponse response : responses) {
String messageUrl = response.getHref();
LOGGER.debug("Delete " + messageUrl);
DavGatewayHttpClientFacade.executeDeleteMethod(httpClient, messageUrl);
@ -799,7 +797,7 @@ public class ExchangeSession {
// warning : slide library expects *unencoded* urls
String tempUrl = draftsUrl + "/" + messageName + ".EML";
MoveMethod method = new MoveMethod(URIUtil.encodePath(tempUrl), URIUtil.encodePath(sendmsgUrl));
MoveMethod method = new MoveMethod(URIUtil.encodePath(tempUrl), URIUtil.encodePath(sendmsgUrl), true);
int status = DavGatewayHttpClientFacade.executeHttpMethod(httpClient, method);
if (status != HttpStatus.SC_OK) {
throw DavGatewayHttpClientFacade.buildHttpException(method);
@ -837,12 +835,11 @@ public class ExchangeSession {
* @throws IOException when unable to change folder
*/
public Folder getFolder(String folderName) throws IOException {
Enumeration folderEnum = DavGatewayHttpClientFacade.executePropFindMethod(
MultiStatusResponse[] responses = DavGatewayHttpClientFacade.executePropFindMethod(
httpClient, URIUtil.encodePath(getFolderPath(folderName)), 0, FOLDER_PROPERTIES);
Folder folder = null;
if (folderEnum.hasMoreElements()) {
ResponseEntity entity = (ResponseEntity) folderEnum.nextElement();
folder = buildFolder(entity);
if (responses.length > 0) {
folder = buildFolder(responses[0]);
folder.folderName = folderName;
}
return folder;
@ -871,12 +868,13 @@ public class ExchangeSession {
public void createFolder(String folderName) throws IOException {
String folderPath = getFolderPath(folderName);
PropPatchMethod method = new PropPatchMethod(URIUtil.encodePath(folderPath)) {
ArrayList<DavProperty> list = new ArrayList<DavProperty>();
list.add(new DefaultDavProperty(DavPropertyName.create("outlookfolderclass", Namespace.getNamespace("http://schemas.microsoft.com/exchange/")), "IPF.Note"));
PropPatchMethod method = new PropPatchMethod(URIUtil.encodePath(folderPath), list) {
public String getName() {
return "MKCOL";
}
};
method.addPropertyToSet("outlookfolderclass", "IPF.Note", "ex", "http://schemas.microsoft.com/exchange/");
int status = DavGatewayHttpClientFacade.executeHttpMethod(httpClient, method);
// ok or alredy exists
if (status != HttpStatus.SC_MULTI_STATUS && status != HttpStatus.SC_METHOD_NOT_ALLOWED) {
@ -887,8 +885,7 @@ public class ExchangeSession {
public void copyMessage(String messageUrl, String targetName) throws IOException {
String targetPath = getFolderPath(targetName) + messageUrl.substring(messageUrl.lastIndexOf('/'));
CopyMethod method = new CopyMethod(URIUtil.encodePath(messageUrl),
URIUtil.encodePath(targetPath));
method.setOverwrite(false);
URIUtil.encodePath(targetPath), false);
method.addRequestHeader("Allow-Rename", "t");
try {
int statusCode = httpClient.executeMethod(method);
@ -906,8 +903,7 @@ public class ExchangeSession {
String folderPath = getFolderPath(folderName);
String targetPath = getFolderPath(targetName);
MoveMethod method = new MoveMethod(URIUtil.encodePath(folderPath),
URIUtil.encodePath(targetPath));
method.setOverwrite(false);
URIUtil.encodePath(targetPath), false);
try {
int statusCode = httpClient.executeMethod(method);
if (statusCode == HttpStatus.SC_PRECONDITION_FAILED) {
@ -924,8 +920,7 @@ public class ExchangeSession {
String source = encodedPath + "/" + encodedMessageName;
String destination = URIUtil.encodePath(deleteditemsUrl) + "/" + encodedMessageName;
LOGGER.debug("Deleting : " + source + " to " + destination);
MoveMethod method = new MoveMethod(source, destination);
method.addRequestHeader("Overwrite", "f");
MoveMethod method = new MoveMethod(source, destination, false);
method.addRequestHeader("Allow-rename", "t");
int status = DavGatewayHttpClientFacade.executeHttpMethod(httpClient, method);
@ -1124,7 +1119,7 @@ public class ExchangeSession {
@Override
public int hashCode() {
return (int)(imapUid ^ (imapUid >>> 32));
return (int) (imapUid ^ (imapUid >>> 32));
}
}
@ -1249,9 +1244,9 @@ public class ExchangeSession {
public List<Event> getEvents(String path, String searchQuery) throws IOException {
List<Event> events = new ArrayList<Event>();
Enumeration calendarEnum = DavGatewayHttpClientFacade.executeSearchMethod(httpClient, URIUtil.encodePath(path), searchQuery);
while (calendarEnum.hasMoreElements()) {
events.add(buildEvent((ResponseEntity) calendarEnum.nextElement()));
MultiStatusResponse[] responses = DavGatewayHttpClientFacade.executeSearchMethod(httpClient, URIUtil.encodePath(path), searchQuery);
for (MultiStatusResponse response : responses) {
events.add(buildEvent(response));
}
return events;
}
@ -1259,23 +1254,22 @@ public class ExchangeSession {
public Event getEvent(String principal, String path, String eventName) throws IOException {
String eventPath = URIUtil.encodePath(replacePrincipal(getFolderPath(path), principal)) + "/" + URIUtil.encodeWithinQuery(eventName);
LOGGER.debug("getEvent(" + eventPath + "/" + eventName + ")");
Enumeration calendarEnum = DavGatewayHttpClientFacade.executePropFindMethod(httpClient, eventPath, 0, EVENT_REQUEST_PROPERTIES);
if (!calendarEnum.hasMoreElements()) {
MultiStatusResponse[] responses = DavGatewayHttpClientFacade.executePropFindMethod(httpClient, eventPath, 0, EVENT_REQUEST_PROPERTIES);
if (responses.length == 0) {
throw new IOException("Unable to get calendar event");
}
return buildEvent((ResponseEntity) calendarEnum.
nextElement());
return buildEvent(responses[0]);
}
protected Event buildEvent(ResponseEntity calendarResponse) throws URIException {
protected Event buildEvent(MultiStatusResponse calendarResponse) throws URIException {
Event event = new Event();
String href = calendarResponse.getHref();
event.href = URIUtil.decode(href);
Enumeration propertiesEnumeration = calendarResponse.getProperties();
while (propertiesEnumeration.hasMoreElements()) {
Property property = (Property) propertiesEnumeration.nextElement();
if ("getetag".equals(property.getLocalName())) {
event.etag = property.getPropertyAsString();
Iterator propertiesEnumeration = calendarResponse.getProperties(HttpStatus.SC_OK).iterator();
while (propertiesEnumeration.hasNext()) {
DavProperty property = (DavProperty) propertiesEnumeration.next();
if ("getetag".equals(property.getName().getName())) {
event.etag = (String) property.getValue();
}
}
return event;
@ -1413,17 +1407,6 @@ public class ExchangeSession {
}
String dateValue = line.substring(valueIndex + 1, valueEndIndex);
String key = line.substring(0, Math.max(keyIndex, valueIndex));
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date;
try {
date = dateFormat.parse(dateValue);
} catch (ParseException e) {
throw new IOException("Invalid ICS line: " + line);
}
if ("DTEND".equals(key)) {
date.setTime(date.getTime() - 1);
}
return key + ";VALUE=DATE:" + dateValue;
}
@ -1439,7 +1422,7 @@ public class ExchangeSession {
if (status != HttpStatus.SC_CREATED) {
return status;
} else {
MoveMethod method = new MoveMethod(URIUtil.encodePath(messageUrl), URIUtil.encodePath(sendmsgUrl));
MoveMethod method = new MoveMethod(URIUtil.encodePath(messageUrl), URIUtil.encodePath(sendmsgUrl), true);
status = DavGatewayHttpClientFacade.executeHttpMethod(httpClient, method);
if (status != HttpStatus.SC_OK) {
throw DavGatewayHttpClientFacade.buildHttpException(method);
@ -1619,9 +1602,10 @@ public class ExchangeSession {
int status;
if (path.startsWith("INBOX")) {
// do not delete calendar messages, mark read and processed
PropPatchMethod patchMethod = new PropPatchMethod(URIUtil.encodePath(replacePrincipal(getFolderPath(URIUtil.decode(path)), principal)) + "/" + eventName);
patchMethod.addPropertyToSet("schedule-state", "CALDAV:schedule-processed", "C", "CALDAV:");
patchMethod.addPropertyToSet("read", "1", "e", "urn:schemas:httpmail:");
ArrayList<DavProperty> list = new ArrayList<DavProperty>();
list.add(new DefaultDavProperty(DavPropertyName.create("schedule-state", Namespace.getNamespace("CALDAV:")), "CALDAV:schedule-processed"));
list.add(new DefaultDavProperty(DavPropertyName.create("read", Namespace.getNamespace("urn:schemas:httpmail:")), "1"));
PropPatchMethod patchMethod = new PropPatchMethod(URIUtil.encodePath(replacePrincipal(getFolderPath(URIUtil.decode(path)), principal)) + "/" + eventName, list);
DavGatewayHttpClientFacade.executeMethod(httpClient, patchMethod);
status = HttpStatus.SC_OK;
} else {
@ -1641,21 +1625,17 @@ public class ExchangeSession {
public String getFolderCtag(String folderUrl) throws IOException {
String ctag = null;
Enumeration calendarEnum = DavGatewayHttpClientFacade.executePropFindMethod(
MultiStatusResponse[] responses = DavGatewayHttpClientFacade.executePropFindMethod(
httpClient, URIUtil.encodePath(folderUrl), 0, CONTENT_TAG);
if (!calendarEnum.hasMoreElements()) {
if (responses.length == 0) {
throw new IOException("Unable to get folder object");
}
while (calendarEnum.hasMoreElements()) {
ResponseEntity calendarResponse = (ResponseEntity) calendarEnum.
nextElement();
Enumeration propertiesEnumeration = calendarResponse.getProperties();
while (propertiesEnumeration.hasMoreElements()) {
Property property = (Property) propertiesEnumeration.nextElement();
if ("http://schemas.microsoft.com/repl/".equals(property.getNamespaceURI())
&& "contenttag".equals(property.getLocalName())) {
ctag = property.getPropertyAsString();
}
MultiStatusResponse calendarResponse = responses[0];
Iterator propertiesEnumeration = calendarResponse.getProperties(HttpStatus.SC_OK).iterator();
while (propertiesEnumeration.hasNext()) {
DavProperty property = (DavProperty) propertiesEnumeration.next();
if ("contenttag".equals(property.getName().getName())) {
ctag = (String) property.getValue();
}
}
if (ctag == null) {
@ -1666,20 +1646,17 @@ public class ExchangeSession {
public String getCalendarEtag() throws IOException {
String etag = null;
Enumeration calendarEnum = DavGatewayHttpClientFacade.executePropFindMethod(
MultiStatusResponse[] responses = DavGatewayHttpClientFacade.executePropFindMethod(
httpClient, URIUtil.encodePath(calendarUrl), 0, EVENT_REQUEST_PROPERTIES);
if (!calendarEnum.hasMoreElements()) {
if (responses.length == 0) {
throw new IOException("Unable to get calendar object");
}
while (calendarEnum.hasMoreElements()) {
ResponseEntity calendarResponse = (ResponseEntity) calendarEnum.
nextElement();
Enumeration propertiesEnumeration = calendarResponse.getProperties();
while (propertiesEnumeration.hasMoreElements()) {
Property property = (Property) propertiesEnumeration.nextElement();
if ("getetag".equals(property.getLocalName())) {
etag = property.getPropertyAsString();
}
MultiStatusResponse calendarResponse = responses[0];
Iterator propertiesEnumeration = calendarResponse.getProperties(HttpStatus.SC_OK).iterator();
while (propertiesEnumeration.hasNext()) {
DavProperty property = (DavProperty) propertiesEnumeration.next();
if ("getetag".equals(property.getName().getName())) {
etag = (String) property.getValue();
}
}
if (etag == null) {
@ -1726,21 +1703,19 @@ public class ExchangeSession {
return null;
}
String alias = null;
Enumeration folderEnum = DavGatewayHttpClientFacade.executePropFindMethod(
MultiStatusResponse[] responses = DavGatewayHttpClientFacade.executePropFindMethod(
httpClient, URIUtil.encodePath(mailPath), 0, DISPLAY_NAME);
if (!folderEnum.hasMoreElements()) {
if (responses.length == 0) {
throw new IOException("Unable to get mail folder");
}
ResponseEntity mailboxResponse = (ResponseEntity) folderEnum.
nextElement();
Enumeration mailboxPropsEnum = mailboxResponse.getProperties();
if (!mailboxPropsEnum.hasMoreElements()) {
Iterator mailboxPropsEnum = responses[0].getProperties(HttpStatus.SC_OK).iterator();
if (!mailboxPropsEnum.hasNext()) {
throw new IOException("Unable to get mail folder");
}
while (mailboxPropsEnum.hasMoreElements()) {
Property inboxProp = (Property) mailboxPropsEnum.nextElement();
if ("displayname".equals(inboxProp.getLocalName())) {
alias = inboxProp.getPropertyAsString();
while (mailboxPropsEnum.hasNext()) {
DavProperty inboxProp = (DavProperty) mailboxPropsEnum.next();
if ("displayname".equals(inboxProp.getName().getName())) {
alias = (String) inboxProp.getValue();
}
}

View File

@ -3,20 +3,26 @@ package davmail.http;
import davmail.Settings;
import davmail.tray.DavGatewayTray;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.auth.AuthPolicy;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.webdav.lib.methods.PropFindMethod;
import org.apache.webdav.lib.methods.SearchMethod;
import org.apache.webdav.lib.methods.XMLResponseMethodBase;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.jackrabbit.webdav.DavException;
import org.apache.jackrabbit.webdav.MultiStatusResponse;
import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
import org.apache.jackrabbit.webdav.client.methods.DavMethodBase;
import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;
import java.util.ArrayList;
/**
* Create HttpClient instance according to DavGateway Settings
*/
public final class DavGatewayHttpClientFacade {
final static String IE_USER_AGENT = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)";
static MultiThreadedHttpConnectionManager multiThreadedHttpConnectionManager;
static {
@ -36,18 +42,20 @@ public final class DavGatewayHttpClientFacade {
public static HttpClient getInstance() {
// create an HttpClient instance
HttpClient httpClient = new HttpClient();
httpClient.getParams().setParameter(HttpMethodParams.USER_AGENT, IE_USER_AGENT);
configureClient(httpClient);
return httpClient;
}
public static HttpClient getInstance(HttpURL httpURL) throws URIException {
HttpClient httpClient = new HttpClient();
httpClient.getParams().setParameter(HttpMethodParams.USER_AGENT, IE_USER_AGENT);
HostConfiguration hostConfig = httpClient.getHostConfiguration();
hostConfig.setHost(httpURL);
UsernamePasswordCredentials hostCredentials =
new UsernamePasswordCredentials(httpURL.getUser(),
httpURL.getPassword());
httpClient.getState().setCredentials(null, httpURL.getHost(),
httpClient.getState().setCredentials(new AuthScope(httpURL.getHost(), httpURL.getPort(), AuthScope.ANY_REALM),
hostCredentials);
configureClient(httpClient);
return httpClient;
@ -79,20 +87,24 @@ public final class DavGatewayHttpClientFacade {
httpClient.getHostConfiguration().setProxy(proxyHost, proxyPort);
if (proxyUser != null && proxyUser.length() > 0) {
/* // Only available in newer HttpClient releases, not compatible with slide library
List authPrefs = new ArrayList();
// Only available in newer HttpClient releases, not compatible with slide library
ArrayList<String> authPrefs = new ArrayList<String>();
authPrefs.add(AuthPolicy.DIGEST);
authPrefs.add(AuthPolicy.BASIC);
httpClient.getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY,authPrefs);
*/
// exclude the NTLM authentication scheme
httpClient.getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);
AuthScope authScope = new AuthScope(proxyHost, proxyPort, AuthScope.ANY_REALM);
// instead detect ntlm authentication (windows domain name in user name)
int backslashindex = proxyUser.indexOf("\\");
if (backslashindex > 0) {
httpClient.getState().setProxyCredentials(null, proxyHost,
httpClient.getState().setProxyCredentials(authScope,
new NTCredentials(proxyUser.substring(backslashindex + 1),
proxyPassword, null,
proxyUser.substring(0, backslashindex)));
} else {
httpClient.getState().setProxyCredentials(null, proxyHost,
httpClient.getState().setProxyCredentials(authScope,
new UsernamePasswordCredentials(proxyUser, proxyPassword));
}
}
@ -180,12 +192,22 @@ public final class DavGatewayHttpClientFacade {
* @return Responses enumeration
* @throws IOException on error
*/
public static Enumeration executeSearchMethod(HttpClient httpClient, String path, String searchRequest) throws IOException {
public static MultiStatusResponse[] executeSearchMethod(HttpClient httpClient, String path, String searchRequest) throws IOException {
String searchBody = "<?xml version=\"1.0\"?>\n" +
"<d:searchrequest xmlns:d=\"DAV:\">\n" +
" <d:sql>" + searchRequest.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;") + "</d:sql>\n" +
"</d:searchrequest>";
SearchMethod searchMethod = new SearchMethod(path, searchBody);
DavMethodBase searchMethod = new DavMethodBase(path) {
public String getName() {
return "SEARCH";
}
protected boolean isSuccess(int statusCode) {
return statusCode == 207;
}
};
searchMethod.setRequestEntity(new StringRequestEntity(searchBody, "text/xml", "UTF-8"));
return executeMethod(httpClient, searchMethod);
}
@ -199,8 +221,8 @@ public final class DavGatewayHttpClientFacade {
* @return Responses enumeration
* @throws IOException on error
*/
public static Enumeration executePropFindMethod(HttpClient httpClient, String path, int depth, Vector properties) throws IOException {
PropFindMethod propFindMethod = new PropFindMethod(path, depth, properties.elements());
public static MultiStatusResponse[] executePropFindMethod(HttpClient httpClient, String path, int depth, DavPropertyNameSet properties) throws IOException {
PropFindMethod propFindMethod = new PropFindMethod(path, properties, depth);
return executeMethod(httpClient, propFindMethod);
}
@ -223,20 +245,22 @@ public final class DavGatewayHttpClientFacade {
* @return Responses enumeration
* @throws IOException on error
*/
public static Enumeration executeMethod(HttpClient httpClient, XMLResponseMethodBase method) throws IOException {
Enumeration responseEnumeration = null;
public static MultiStatusResponse[] executeMethod(HttpClient httpClient, DavMethodBase method) throws IOException {
MultiStatusResponse[] responses = null;
try {
int status = httpClient.executeMethod(method);
if (status != HttpStatus.SC_MULTI_STATUS) {
throw buildHttpException(method);
}
responseEnumeration = method.getResponses();
responses = method.getResponseBodyAsMultiStatus().getResponses();
} catch (DavException e) {
throw new IOException(e.getMessage());
} finally {
method.releaseConnection();
}
return responseEnumeration;
return responses;
}
public static int executeHttpMethod(HttpClient httpClient, HttpMethod method) throws IOException {

View File

@ -1,169 +0,0 @@
// Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://kpdus.tripod.com/jad.html
// Decompiler options: packimports(3)
// Source File Name: HttpAuthenticator.java
package org.apache.commons.httpclient.auth;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.httpclient.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
// Referenced classes of package org.apache.commons.httpclient.auth:
// NTLMScheme, DigestScheme, BasicScheme, AuthenticationException,
// MalformedChallengeException, AuthChallengeParser, AuthScheme
public final class HttpAuthenticator {
public HttpAuthenticator() {
}
public static AuthScheme selectAuthScheme(Header challenges[])
throws MalformedChallengeException {
LOG.trace("enter HttpAuthenticator.selectAuthScheme(Header[])");
if (challenges == null)
throw new IllegalArgumentException("Array of challenges may not be null");
if (challenges.length == 0)
throw new IllegalArgumentException("Array of challenges may not be empty");
String challenge = null;
Map challengemap = new HashMap(challenges.length);
for (int i = 0; i < challenges.length; i++) {
challenge = challenges[i].getValue();
String s = AuthChallengeParser.extractScheme(challenge);
challengemap.put(s, challenge);
}
challenge = (String) challengemap.get("digest");
if (challenge != null)
return new DigestScheme(challenge);
challenge = (String) challengemap.get("basic");
if (challenge != null)
return new BasicScheme(challenge);
// patch ntlm last priority
challenge = (String) challengemap.get("ntlm");
if (challenge != null)
return new NTLMScheme(challenge);
else
throw new UnsupportedOperationException("Authentication scheme(s) not supported: " + challengemap.toString());
}
private static boolean doAuthenticateDefault(HttpMethod method, HttpConnection conn, HttpState state, boolean proxy)
throws AuthenticationException {
if (method == null)
throw new IllegalArgumentException("HTTP method may not be null");
if (state == null)
throw new IllegalArgumentException("HTTP state may not be null");
String host = null;
if (conn != null)
host = proxy ? conn.getProxyHost() : conn.getHost();
org.apache.commons.httpclient.Credentials credentials = proxy ? state.getProxyCredentials(null, host) : state.getCredentials(null, host);
if (credentials == null) {
if (LOG.isWarnEnabled())
LOG.warn("Default credentials for " + host + " not available");
return false;
}
if (!(credentials instanceof UsernamePasswordCredentials))
throw new AuthenticationException("Credentials cannot be used for basic authentication: " + credentials.toString());
String auth = BasicScheme.authenticate((UsernamePasswordCredentials) credentials);
if (auth != null) {
String s = proxy ? "Proxy-Authorization" : "Authorization";
method.setRequestHeader(s, auth);
return true;
} else {
return false;
}
}
public static boolean authenticateDefault(HttpMethod method, HttpConnection conn, HttpState state)
throws AuthenticationException {
LOG.trace("enter HttpAuthenticator.authenticateDefault(HttpMethod, HttpConnection, HttpState)");
return doAuthenticateDefault(method, conn, state, false);
}
public static boolean authenticateProxyDefault(HttpMethod method, HttpConnection conn, HttpState state)
throws AuthenticationException {
LOG.trace("enter HttpAuthenticator.authenticateProxyDefault(HttpMethod, HttpState)");
return doAuthenticateDefault(method, conn, state, true);
}
private static boolean doAuthenticate(AuthScheme authscheme, HttpMethod method, HttpConnection conn, HttpState state, boolean proxy)
throws AuthenticationException {
if (authscheme == null)
throw new IllegalArgumentException("Authentication scheme may not be null");
if (method == null)
throw new IllegalArgumentException("HTTP method may not be null");
if (state == null)
throw new IllegalArgumentException("HTTP state may not be null");
String host = null;
if (conn != null)
if (proxy) {
host = conn.getProxyHost();
} else {
host = conn.getVirtualHost();
if (host == null)
host = conn.getHost();
}
String realm = authscheme.getRealm();
if (LOG.isDebugEnabled()) {
StringBuffer buffer = new StringBuffer();
buffer.append("Authenticating with the ");
if (realm == null) {
buffer.append("default");
} else {
buffer.append('\'');
buffer.append(realm);
buffer.append('\'');
}
buffer.append(" authentication realm at ");
buffer.append(host);
LOG.debug(buffer.toString());
}
if (realm == null)
realm = host;
org.apache.commons.httpclient.Credentials credentials = proxy ? state.getProxyCredentials(realm, host) : state.getCredentials(realm, host);
if (credentials == null)
throw new AuthenticationException("No credentials available for the '" + authscheme.getRealm() + "' authentication realm at " + host);
String auth = authscheme.authenticate(credentials, method.getName(), method.getPath());
if (auth != null) {
String s = proxy ? "Proxy-Authorization" : "Authorization";
method.setRequestHeader(s, auth);
return true;
} else {
return false;
}
}
public static boolean authenticate(AuthScheme authscheme, HttpMethod method, HttpConnection conn, HttpState state)
throws AuthenticationException {
LOG.trace("enter HttpAuthenticator.authenticate(AuthScheme, HttpMethod, HttpConnection, HttpState)");
return doAuthenticate(authscheme, method, conn, state, false);
}
public static boolean authenticateProxy(AuthScheme authscheme, HttpMethod method, HttpConnection conn, HttpState state)
throws AuthenticationException {
LOG.trace("enter HttpAuthenticator.authenticateProxy(AuthScheme, HttpMethod, HttpState)");
return doAuthenticate(authscheme, method, conn, state, true);
}
static Class _mthclass$(String x0) {
try {
return Class.forName(x0);
}
catch (ClassNotFoundException x1) {
throw new NoClassDefFoundError(x1.getMessage());
}
}
private static final Log LOG;
public static final String WWW_AUTH = "WWW-Authenticate";
public static final String WWW_AUTH_RESP = "Authorization";
public static final String PROXY_AUTH = "Proxy-Authenticate";
public static final String PROXY_AUTH_RESP = "Proxy-Authorization";
static {
LOG = LogFactory.getLog(org.apache.commons.httpclient.auth.HttpAuthenticator.class);
}
}