diff --git a/src/com/fsck/k9/mail/store/WebDavStore.java b/src/com/fsck/k9/mail/store/WebDavStore.java index efedebf7b..297811357 100644 --- a/src/com/fsck/k9/mail/store/WebDavStore.java +++ b/src/com/fsck/k9/mail/store/WebDavStore.java @@ -1,58 +1,38 @@ package com.fsck.k9.mail.store; -import android.util.Log; +import java.io.*; +import java.net.*; +import java.security.*; +import java.text.*; +import java.util.*; +import java.util.zip.*; -import com.fsck.k9.Account; -import com.fsck.k9.K9; -import com.fsck.k9.R; -import com.fsck.k9.controller.MessageRetrievalListener; -import com.fsck.k9.helper.Utility; +import javax.net.ssl.*; +import javax.xml.parsers.*; + +import org.apache.http.*; +import org.apache.http.client.*; +import org.apache.http.client.entity.*; +import org.apache.http.client.methods.*; +import org.apache.http.client.protocol.*; +import org.apache.http.conn.scheme.*; +import org.apache.http.entity.*; +import org.apache.http.impl.client.*; +import org.apache.http.message.*; +import org.apache.http.protocol.*; +import org.xml.sax.*; +import org.xml.sax.helpers.*; + +import android.util.*; + +import com.fsck.k9.*; +import com.fsck.k9.controller.*; +import com.fsck.k9.helper.*; import com.fsck.k9.mail.*; import com.fsck.k9.mail.Folder.OpenMode; -import com.fsck.k9.mail.filter.EOLConvertingOutputStream; -import com.fsck.k9.mail.internet.MimeMessage; -import com.fsck.k9.mail.transport.TrustedSocketFactory; -import org.apache.http.*; -import org.apache.http.client.CookieStore; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.client.protocol.ClientContext; -import org.apache.http.conn.scheme.Scheme; -import org.apache.http.conn.scheme.SchemeRegistry; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.BasicCookieStore; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.message.BasicNameValuePair; -import org.apache.http.protocol.BasicHttpContext; -import org.apache.http.protocol.HttpContext; -import org.xml.sax.Attributes; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.XMLReader; -import org.xml.sax.helpers.DefaultHandler; - -import javax.net.ssl.SSLException; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; -import java.io.*; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URLDecoder; -import java.net.URLEncoder; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Stack; -import java.util.zip.GZIPInputStream; +import com.fsck.k9.mail.filter.*; +import com.fsck.k9.mail.internet.*; +import com.fsck.k9.mail.transport.*; /** *
@@ -79,8 +59,13 @@ public class WebDavStore extends Store {
 
     private static final Message[] EMPTY_MESSAGE_ARRAY = new Message[0];
 
+    private static final Object DAV_MAIL_INBOX_FOLDER = "inbox";
+    private static final Object DAV_MAIL_DRAFTS_FOLDER = "drafts";
+    private static final String DAV_MAIL_SPAM_FOLDER = "spam";
     private static final String DAV_MAIL_SEND_FOLDER = "##DavMailSubmissionURI##";
-    private static final String DAV_MAIL_TMP_FOLDER = "drafts";
+	private static final Object DAV_MAIL_TRASH_FOLDER = "deleteditems";
+	private static final Object DAV_MAIL_OUTBOX_FOLDER = "outbox";
+	private static final Object DAV_MAIL_SENT_FOLDER = "sentitems";
 
     private short mConnectionSecurity;
     private String mUsername; /* Stores the username for authentications */
@@ -101,6 +86,7 @@ public class WebDavStore extends Store {
     private short mAuthentication = AUTH_TYPE_NONE;
     private String mCachedLoginUrl;
 
+    private Folder mSendFolder = null;
     private HashMap mFolderList = new HashMap();
 
     /**
@@ -231,63 +217,120 @@ public class WebDavStore extends Store {
     @Override
     public List  getPersonalNamespaces(boolean forceListAll) throws MessagingException {
         LinkedList folderList = new LinkedList();
-        HashMap headers = new HashMap();
-        DataSet dataset = new DataSet();
-        String messageBody;
-        String[] folderUrls;
-        int urlLength;
-
-        String translatedInbox = K9.app.getString(R.string.special_mailbox_name_inbox);
-
         /**
          * We have to check authentication here so we have the proper URL stored
          */
         getHttpClient();
-        messageBody = getFolderListXml();
+
+        /**
+         *  Firstly we get the "special" folders list (inbox, outbox, etc)
+         *  and setup the account accordingly
+         */
+        HashMap headers = new HashMap();
+        DataSet dataset = new DataSet();
+        headers.put("Depth", "0");
         headers.put("Brief", "t");
-        dataset = processRequest(this.mUrl, "SEARCH", messageBody, headers);
+        dataset = processRequest(this.mUrl, "PROPFIND", getSpecialFoldersList(), headers);
 
-        folderUrls = dataset.getHrefs();
-        urlLength = folderUrls.length;
+        HashMap specialFoldersMap = dataset.getSpecialFolderToUrl();
+        String folderName = getFolderName(specialFoldersMap.get(DAV_MAIL_INBOX_FOLDER));
+        if(folderName != null) {
+		mAccount.setAutoExpandFolderName(folderName);
+		mAccount.setInboxFolderName(folderName);
+        }
 
-        for (int i = 0; i < urlLength; i++) {
-            String[] urlParts = folderUrls[i].split("/");
-            String folderName = urlParts[urlParts.length - 1];
-            String fullPathName = "";
-            WebDavFolder wdFolder;
+        folderName = getFolderName(specialFoldersMap.get(DAV_MAIL_DRAFTS_FOLDER));
+        if(folderName != null)
+		mAccount.setDraftsFolderName(folderName);
 
-            // Check each Exchange folder name to see if it is the user's inbox.
-            // We will check for the default English inbox ("Inbox"), and the user's
-            // translation for "Inbox", in case the user is using a non-English
-            // version of Exchange.
-            if (folderName.equalsIgnoreCase("Inbox") ||
-                    folderName.equalsIgnoreCase(translatedInbox)) {
-                folderName = K9.INBOX;
-            } else {
-                for (int j = 5, count = urlParts.length; j < count; j++) {
-                    if (j != 5) {
-                        fullPathName = fullPathName + "/" + urlParts[j];
-                    } else {
-                        fullPathName = urlParts[j];
-                    }
-                }
-                try {
-                    folderName = java.net.URLDecoder.decode(fullPathName, "UTF-8");
-                } catch (UnsupportedEncodingException uee) {
-                    /** If we don't support UTF-8 there's a problem, don't decode it then */
-                    folderName = fullPathName;
-                }
-            }
+        folderName = getFolderName(specialFoldersMap.get(DAV_MAIL_TRASH_FOLDER));
+        if(folderName != null)
+		mAccount.setTrashFolderName(folderName);
 
-            wdFolder = new WebDavFolder(this, folderName);
-            wdFolder.setUrl(folderUrls[i]);
-            folderList.add(wdFolder);
-            this.mFolderList.put(folderName, wdFolder);
+        folderName = getFolderName(specialFoldersMap.get(DAV_MAIL_SPAM_FOLDER));
+        if(folderName != null)
+		mAccount.setSpamFolderName(folderName);
+
+        folderName = getFolderName(specialFoldersMap.get(DAV_MAIL_OUTBOX_FOLDER));
+        if(folderName != null)
+		mAccount.setOutboxFolderName(folderName);
+
+        folderName = getFolderName(specialFoldersMap.get(DAV_MAIL_SENT_FOLDER));
+        if(folderName != null)
+		mAccount.setSentFolderName(folderName);
+
+        /**
+         * Next we get all the folders (including "special" ones)
+         */
+        headers = new HashMap();
+        dataset = new DataSet();
+        headers.put("Brief", "t");
+        dataset = processRequest(this.mUrl, "SEARCH", getFolderListXml(), headers);
+        String[] folderUrls = dataset.getHrefs();
+
+        for (int i = 0; i < folderUrls.length; i++) {
+            String tempUrl = folderUrls[i];
+            createFolder(tempUrl, folderList);
         }
 
         return folderList;
     }
 
+    private WebDavFolder createFolder(String folderUrl, LinkedList folderList) {
+	if(folderUrl == null || folderList == null)
+		return null;
+
+	WebDavFolder wdFolder=null;
+	String folderName = getFolderName(folderUrl);
+	if(folderName != null) {
+			if(!this.mFolderList.containsKey(folderName)) {
+                wdFolder = new WebDavFolder(this, folderName);
+                wdFolder.setUrl(folderUrl);
+		folderList.add(wdFolder);
+		mFolderList.put(folderName, wdFolder);
+			}
+        }
+	// else: Unknown URL format => NO Folder created
+
+	return wdFolder;
+	}
+
+    private String getFolderName(String folderUrl) {
+	if(folderUrl == null)
+		return null;
+
+        int folderSlash=-1;
+        for(int j=0; j < 5; j++) {
+		folderSlash=folderUrl.indexOf('/', folderSlash+1);
+		if(folderSlash < 0)
+			break;
+        }
+
+        if(folderSlash > 0) {
+		String folderName;
+		String fullPathName;
+
+		if(folderUrl.charAt(folderUrl.length()-1) == '/')
+			fullPathName = folderUrl.substring(folderSlash+1, folderUrl.length()-1);
+		else
+			fullPathName = folderUrl.substring(folderSlash+1);
+
+			try {
+				folderName = java.net.URLDecoder.decode(fullPathName, "UTF-8");
+			} catch (UnsupportedEncodingException uee) {
+				/**
+				 * If we don't support UTF-8 there's a problem, don't decode
+				 * it then
+				 */
+				folderName = fullPathName;
+			}
+
+			return folderName;
+		}
+
+        return null;
+    }
+
     @Override
     public Folder getFolder(String name) {
         WebDavFolder folder;
@@ -300,7 +343,10 @@ public class WebDavStore extends Store {
     }
 
     public Folder getSendSpoolFolder() throws MessagingException {
-        return getFolder(DAV_MAIL_SEND_FOLDER);
+		if (mSendFolder == null)
+			mSendFolder = getFolder(DAV_MAIL_SEND_FOLDER);
+
+		return mSendFolder;
     }
 
     @Override
@@ -313,6 +359,27 @@ public class WebDavStore extends Store {
         return true;
     }
 
+	private String getSpecialFoldersList() {
+		StringBuffer buffer = new StringBuffer(200);
+		buffer.append("");
+		buffer.append("");
+		buffer.append("");
+		buffer.append("<").append(DAV_MAIL_INBOX_FOLDER).append(" xmlns=\"urn:schemas:httpmail:\"/>");
+		buffer.append("<").append(DAV_MAIL_DRAFTS_FOLDER).append(" xmlns=\"urn:schemas:httpmail:\"/>");
+		buffer.append("<").append(DAV_MAIL_OUTBOX_FOLDER).append(" xmlns=\"urn:schemas:httpmail:\"/>");
+		buffer.append("<").append(DAV_MAIL_SENT_FOLDER).append(" xmlns=\"urn:schemas:httpmail:\"/>");
+		buffer.append("<").append(DAV_MAIL_TRASH_FOLDER).append(" xmlns=\"urn:schemas:httpmail:\"/>");
+		// This should always be ##DavMailSubmissionURI## for which we already have a constant
+		// buffer.append("");
+
+		//TODO: What is the id of the spam folder???
+		//buffer.append("<").append(DAV_MAIL_SPAM_FOLDER).append(" xmlns=\"urn:schemas:httpmail:\"/>");
+
+		buffer.append("");
+		buffer.append("");
+		return buffer.toString();
+	}
+
     /***************************************************************
      * WebDAV XML Request body retrieval functions
      */
@@ -980,7 +1047,7 @@ public class WebDavStore extends Store {
 
     @Override
     public void sendMessages(Message[] messages) throws MessagingException {
-        WebDavFolder tmpFolder = (WebDavStore.WebDavFolder) getFolder(DAV_MAIL_TMP_FOLDER);
+		WebDavFolder tmpFolder = (WebDavStore.WebDavFolder) getFolder(mAccount.getDraftsFolderName());
         try {
             tmpFolder.open(OpenMode.READ_WRITE);
             Message[] retMessages = tmpFolder.appendWebDavMessages(messages);
@@ -1017,37 +1084,30 @@ public class WebDavStore extends Store {
             store = nStore;
             this.mName = name;
 
-            if (DAV_MAIL_SEND_FOLDER.equals(name)) {
-                this.mFolderUrl = getUrl() + "/" + name + "/";
-            } else {
-                String encodedName = "";
-                try {
-                    String[] urlParts = name.split("/");
-                    String url = "";
-                    for (int i = 0, count = urlParts.length; i < count; i++) {
-                        if (i != 0) {
-                            url = url + "/" + java.net.URLEncoder.encode(urlParts[i], "UTF-8");
-                        } else {
-                            url = java.net.URLEncoder.encode(urlParts[i], "UTF-8");
-                        }
+            String encodedName = "";
+            try {
+                String[] urlParts = name.split("/");
+                String url = "";
+                for (int i = 0, count = urlParts.length; i < count; i++) {
+                    if (i != 0) {
+                        url = url + "/" + java.net.URLEncoder.encode(urlParts[i], "UTF-8");
+                    } else {
+                        url = java.net.URLEncoder.encode(urlParts[i], "UTF-8");
                     }
-                    encodedName = url;
-                } catch (UnsupportedEncodingException uee) {
-                    Log.e(K9.LOG_TAG, "UnsupportedEncodingException URLEncoding folder name, skipping encoded");
-                    encodedName = name;
                 }
-
-                encodedName = encodedName.replaceAll("\\+", "%20");
-
-                if (encodedName.equals(K9.INBOX)) {
-                    encodedName = "Inbox";
-                }
-                this.mFolderUrl = WebDavStore.this.mUrl;
-                if (!WebDavStore.this.mUrl.endsWith("/")) {
-                    this.mFolderUrl += "/";
-                }
-                this.mFolderUrl += encodedName;
+                encodedName = url;
+            } catch (UnsupportedEncodingException uee) {
+                Log.e(K9.LOG_TAG, "UnsupportedEncodingException URLEncoding folder name, skipping encoded");
+                encodedName = name;
             }
+
+            encodedName = encodedName.replaceAll("\\+", "%20");
+
+            this.mFolderUrl = WebDavStore.this.mUrl;
+            if (!WebDavStore.this.mUrl.endsWith("/")) {
+                this.mFolderUrl += "/";
+            }
+            this.mFolderUrl += encodedName;
         }
 
         public void setUrl(String url) {
@@ -1978,6 +2038,17 @@ public class WebDavStore extends Store {
         }
 
         /**
+		 * Returns a hashmap of special folder name => special folder url
+		 */
+		public HashMap getSpecialFolderToUrl() {
+			// We return the first (and only) map
+			for (HashMap folderMap : mData.values()) {
+				return folderMap;
+			}
+			return new HashMap();
+		}
+
+		/**
          * Returns a hashmap of Message UID => Message Url
          */
         public HashMap getUidToUrl() {