diff --git a/src/WebDavClient/HttpRequestBuilder.cs b/src/WebDavClient/HttpRequestBuilder.cs
new file mode 100644
index 0000000..b455eca
--- /dev/null
+++ b/src/WebDavClient/HttpRequestBuilder.cs
@@ -0,0 +1,105 @@
+using System;
+using System.Net;
+using System.Net.Security;
+using System.Security.Cryptography.X509Certificates;
+
+
+namespace Cadenza.Net
+{
+    public class HttpRequestBuilder
+    {
+        public String User { get; set; }
+        public String Password { get; set; }
+
+        public bool ForceSSL { get; set; } = true;
+
+        /// <summary>
+        /// Cookies used for shiboleth or other "session based" auth
+        /// </summary>
+        public CookieContainer cookies { get; set; } = null;
+        /// <summary>
+        /// Bearer token is used for oauth and similar
+        /// </summary>
+        public String bearerToken { get; set; } = null;
+
+        /// <summary>
+        /// Set the proxy to use:
+        /// - System: user system proxy
+        /// - Direct: no proxy (direct connection)
+        /// - other: use the url as proxy (i.e. http://proxy:6138 )
+        /// only http proxy are supported
+        /// </summary>
+        public String proxy { get; set; } = "System";
+        public String proxyUser { get; set; }
+        public String proxyPassword { get; set; }
+
+        /// <summary>
+        /// This will create a web request object for a given uri with the builder parameter
+        /// </summary>
+        /// <param name="uri"></param>
+        /// <returns></returns>
+        public HttpWebRequest Build(String uri)
+        {
+            return Build(new Uri(uri));
+        }
+        /// <summary>
+        /// This will create a web request object for a given uri with the builder parameter
+        /// </summary>
+        /// <param name="uri"></param>
+        /// <returns></returns>
+        public HttpWebRequest Build(Uri uri)
+        {
+            HttpWebRequest httpWebRequest = (HttpWebRequest)System.Net.HttpWebRequest.Create(uri);
+
+            // If you want to disable SSL certificate validation
+
+            if (ForceSSL)
+            {
+                System.Net.ServicePointManager.ServerCertificateValidationCallback +=
+                delegate (object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors sslError)
+                {
+                    return true;
+                };
+            }
+
+            if (proxy == "Direct")
+            {
+                // no proxy
+            }
+            else if (proxy == "System" || String.IsNullOrEmpty(proxy))
+            {
+                // use system (IE) web proxy
+                httpWebRequest.Proxy = WebRequest.GetSystemWebProxy();
+            }
+            else
+            {
+                // custom proxy
+                WebProxy wproxy = new WebProxy(proxy, true);
+                if (!String.IsNullOrEmpty(proxyUser))
+                    wproxy.Credentials = new NetworkCredential(proxyUser, proxyPassword);
+                httpWebRequest.Proxy = wproxy;
+            }
+
+            // The server may use authentication
+            if(cookies != null)
+            {
+                httpWebRequest.CookieContainer = cookies;
+            } else if(!String.IsNullOrEmpty(bearerToken))
+            {
+                httpWebRequest.Headers.Add("Authorization", "Bearer " + bearerToken);
+            }
+            else if (!String.IsNullOrEmpty(User) && !String.IsNullOrEmpty(Password))
+            {
+                NetworkCredential networkCredential;
+                networkCredential = new NetworkCredential(User, Password);
+                httpWebRequest.Credentials = networkCredential;
+                // Send authentication along with first request.
+                httpWebRequest.PreAuthenticate = true;
+            }
+
+            // our user agent
+            httpWebRequest.UserAgent = "Mozilla/5.0 (epiK) mirall/2.4.0 (build 1234)";
+            return httpWebRequest;
+        }
+    }
+}
diff --git a/src/WebDavClient/WebDAVClient.cs b/src/WebDavClient/WebDAVClient.cs
index 9c3a924..9a77c6b 100644
--- a/src/WebDavClient/WebDAVClient.cs
+++ b/src/WebDavClient/WebDAVClient.cs
@@ -1,14 +1,14 @@
 /*
- * (C) 2010 Kees van den Broek: kvdb@kvdb.net
- *          D-centralize: d-centralize.nl
- *          
- * Latest van den Broek version and examples on: http://kvdb.net/projects/webdav
- * 
- * Feel free to use this code however you like.
- * http://creativecommons.org/license/zero/
- * 
- * Copyright (C) 2012 Xamarin Inc. (http://xamarin.com)
- */
+* (C) 2010 Kees van den Broek: kvdb@kvdb.net
+*          D-centralize: d-centralize.nl
+*          
+* Latest van den Broek version and examples on: http://kvdb.net/projects/webdav
+* 
+* Feel free to use this code however you like.
+* http://creativecommons.org/license/zero/
+* 
+* Copyright (C) 2012 Xamarin Inc. (http://xamarin.com)
+*/
 
 using System;
 using System.Collections.Generic;
@@ -17,44 +17,46 @@
 using System.Text;
 using System.Threading.Tasks;
 using System.Xml;
-/*
-// If you want to disable SSL certificate validation
-using System.Net.Security;
-using System.Security.Cryptography.X509Certificates;
-*/
 
 namespace Cadenza.Net
 {
-	public enum WebDavEntryType {
-		Default,
-		Directory,
-		File,
-	}
-
-	public class WebDavEntry {
-
-		public string Directory {get; internal set;}
-		public string Name {get; internal set;}
-		public string Path {get; internal set;}
-		public WebDavEntryType Type {get; internal set;}
-
-		internal WebDavEntry ()
-		{
-		}
-
-		public override string ToString ()
-		{
-			return Path;
-		}
-	}
-
-    public class WebDavClient
+    public enum WebDavEntryType {
+	    Default,
+	    Directory,
+	    File,
+    }
+
+    public class WebDavEntry {
+
+	    public string Directory {get; internal set;}
+	    public string Name {get; internal set;}
+	    public string Path {get; internal set;}
+        public string AbsoluteUri { get; internal set; }
+        public WebDavEntryType Type {get; internal set;}
+        public long? ContentLength { get; internal set; }
+
+	    internal WebDavEntry ()
+	    {
+	    }
+
+	    public override string ToString ()
+	    {
+		    return Path;
+	    }
+    }
+
+    public class WebDavClient : IDisposable
     {
 
         //XXX: submit along with state object.
         HttpWebRequest httpWebRequest;
 
         #region WebDAV connection parameters
+        /// <summary>
+        /// Request builder to handle authentication, proxy and so on
+        /// </summary>
+        public HttpRequestBuilder requestBuilder { get; set; }
+
         private String server;
         /// <summary>
         /// Specify the WebDAV hostname (required).
@@ -90,46 +92,22 @@ public int? Port
             get { return port; }
             set { port = value; }
         }
-        private String user;
-        /// <summary>
-        /// Specify a username (optional)
-        /// </summary>
-        public String User
-        {
-            get { return user; }
-            set { user = value; }
-        }
-        private String pass;
-        /// <summary>
-        /// Specify a password (optional)
-        /// </summary>
-        public String Pass
-        {
-            get { return pass; }
-            set { pass = value; }
-        }
-        private String domain = null;
-        public String Domain
-        {
-            get { return domain; }
-            set { domain = value; }
-        }
 
         Uri getServerUrl(String path, Boolean appendTrailingSlash)
         {
             String completePath = basePath;
             if (path != null)
             {
-            	completePath += path.Trim('/');
+                completePath += path.Trim('/');
             }
 
             if (appendTrailingSlash && completePath.EndsWith("/") == false) { completePath += '/'; }
 
             if(port.HasValue) {
-				return new Uri(server + ":" + port + completePath);
+			    return new Uri(server + ":" + port + completePath);
             }
             else {
-            	return new Uri(server + completePath);
+                return new Uri(server + completePath);
             }
             
         }
@@ -149,7 +127,7 @@ public Task<IEnumerable<WebDavEntry>> List()
         /// List files in the given directory
         /// </summary>
         /// <param name="path"></param>
-		public Task<IEnumerable<WebDavEntry>> List(String path)
+	    public Task<IEnumerable<WebDavEntry>> List(String path)
         {
             // Set default depth to 1. This would prevent recursion.
             return List(path, 1);
@@ -161,7 +139,7 @@ public Task<IEnumerable<WebDavEntry>> List(String path)
         /// <param name="remoteFilePath">List only files in this path</param>
         /// <param name="depth">Recursion depth</param>
         /// <returns>A list of files (entries without a trailing slash) and directories (entries with a trailing slash)</returns>
-		public Task<IEnumerable<WebDavEntry>> List(String remoteFilePath, int? depth)
+	    public Task<IEnumerable<WebDavEntry>> List(String remoteFilePath, int? depth)
         {
             // Uri should end with a trailing slash
             Uri listUri = getServerUrl(remoteFilePath, true);
@@ -180,13 +158,17 @@ public Task<IEnumerable<WebDavEntry>> List(String remoteFilePath, int? depth)
                 headers.Add("Depth", depth.ToString());
             }
 
-			return WebDavOperation(listUri, "PROPFIND", headers, Encoding.UTF8.GetBytes(propfind.ToString()), null, FinishList, remoteFilePath);
+		    return WebDavOperation(listUri, "PROPFIND", headers, Encoding.UTF8.GetBytes(propfind.ToString()), null, FinishList, remoteFilePath);
         }
 
+        private String NormalizePath(String path)
+        {
+            return path.Trim('/');
+        }
 
         IEnumerable<WebDavEntry> FinishList(IAsyncResult result)
         {
-            string remoteFilePath = (string)result.AsyncState;
+            string remoteFilePath = NormalizePath((string)result.AsyncState);
 
             using (HttpWebResponse response = (HttpWebResponse)httpWebRequest.EndGetResponse(result))
             {
@@ -201,21 +183,56 @@ IEnumerable<WebDavEntry> FinishList(IAsyncResult result)
                     {
                         XmlNode xmlNode = node.SelectSingleNode("d:href", xmlNsManager);
                         string filepath = Uri.UnescapeDataString(xmlNode.InnerXml);
-						if (filepath.StartsWith (basePath))
-							filepath = filepath.Substring (basePath.Length);
-						if (filepath.Length == 0 || filepath == remoteFilePath)
-							continue;
-						var type = filepath.EndsWith ("/") ? WebDavEntryType.Directory : WebDavEntryType.File;
-						int endDir = filepath.LastIndexOf ('/');
-						if (type == WebDavEntryType.Directory)
-							endDir = filepath.LastIndexOf ("/", endDir - 1);
-						endDir++;
-						yield return new WebDavEntry {
-							Directory   = filepath.Substring (0, endDir),
-							Name        = filepath.Substring (endDir),
-							Path        = filepath,
-							Type        = type,
-						};
+                        string uri = filepath;
+					    if (filepath.StartsWith (basePath))
+						    filepath = filepath.Substring (basePath.Length);
+
+                        // skip the "query" node
+					    if (filepath.Length == 0 || NormalizePath(filepath) == remoteFilePath)
+						    continue;
+					    var type = filepath.EndsWith ("/") ? WebDavEntryType.Directory : WebDavEntryType.File;
+					    int endDir = filepath.LastIndexOf ('/');
+					    if (type == WebDavEntryType.Directory)
+						    endDir = filepath.LastIndexOf ("/", endDir - 1);
+					    endDir++;
+
+                        long? contentLength = null;
+
+                        XmlNode propStatNode = node.SelectSingleNode("d:propstat", xmlNsManager);
+                        if(propStatNode != null)
+                        {
+                            XmlNode propNode = propStatNode.SelectSingleNode("d:prop", xmlNsManager);
+                            if (propNode != null)
+                            {
+                                // get content length
+                                XmlNode prop = propNode.SelectSingleNode("d:getcontentlength", xmlNsManager);
+                                if (prop != null)
+                                {
+                                    contentLength = long.Parse(prop.InnerText);
+                                }
+
+                                // get content type
+                                prop = propNode.SelectSingleNode("d:resourcetype", xmlNsManager);
+                                if (prop != null)
+                                {
+                                    if (prop.SelectSingleNode("d:collection", xmlNsManager) != null)
+                                        type = WebDavEntryType.Directory;
+                                    else
+                                        type = WebDavEntryType.File;
+                                }
+                            }
+                        }
+                        // get name and get rid of trailing /
+                        var name = filepath.Substring(endDir).Trim('/');
+
+                        yield return new WebDavEntry {
+                            Directory = filepath.Substring(0, endDir),
+                            Name = name,
+                            Path = filepath,
+                            Type = type,
+                            ContentLength = contentLength,
+                            AbsoluteUri = uri
+                        };
                     }
                 }
             }
@@ -226,7 +243,7 @@ IEnumerable<WebDavEntry> FinishList(IAsyncResult result)
         /// </summary>
         /// <param name="localFilePath">Local path and filename of the file to upload</param>
         /// <param name="remoteFilePath">Destination path and filename of the file on the server</param>
-		public Task<HttpStatusCode> Upload(String localFilePath, String remoteFilePath)
+	    public Task<HttpStatusCode> Upload(String localFilePath, String remoteFilePath)
         {
             return Upload(localFilePath, remoteFilePath, null);
         }
@@ -245,14 +262,12 @@ public Task<HttpStatusCode> Upload(String localFilePath, String remoteFilePath,
             Uri uploadUri = getServerUrl(remoteFilePath, false);
             string method = WebRequestMethods.Http.Put.ToString();
 
-			return WebDavOperation(uploadUri, method, null, null, localFilePath, FinishUpload, state);
+		    return WebDavOperation(uploadUri, method, null, null, localFilePath, FinishUpload, state);
         }
 
 
         HttpStatusCode FinishUpload(IAsyncResult result)
         {
-            int statusCode = 0;
-
             using (HttpWebResponse response = (HttpWebResponse)httpWebRequest.EndGetResponse(result))
             {
                 return response.StatusCode;
@@ -271,7 +286,7 @@ public Task<HttpStatusCode> Download(String remoteFilePath, String localFilePath
             Uri downloadUri = getServerUrl(remoteFilePath, false);
             string method = WebRequestMethods.Http.Get.ToString();
 
-			return WebDavOperation(downloadUri, method, null, null, null, FinishDownload, localFilePath);
+		    return WebDavOperation(downloadUri, method, null, null, null, FinishDownload, localFilePath);
         }
 
 
@@ -282,7 +297,7 @@ HttpStatusCode FinishDownload(IAsyncResult result)
             using (HttpWebResponse response = (HttpWebResponse)httpWebRequest.EndGetResponse(result))
             {
                 int contentLength = int.Parse(response.GetResponseHeader("Content-Length"));
-				int read = 0;
+			    int read = 0;
                 using (Stream s = response.GetResponseStream())
                 {
                     using (FileStream fs = new FileStream(localFilePath, FileMode.Create, FileAccess.Write))
@@ -293,13 +308,13 @@ HttpStatusCode FinishDownload(IAsyncResult result)
                         {
                             bytesRead = s.Read(content, 0, content.Length);
                             fs.Write(content, 0, bytesRead);
-							read += bytesRead;
+						    read += bytesRead;
                         } while (bytesRead > 0);
                     }
                 }
-				if (contentLength != read)
-					Console.WriteLine ("Length read doesn't match header! Content-Length={0}; Read={1}", contentLength, read);
-				return response.StatusCode;
+			    if (contentLength != read)
+				    Console.WriteLine ("Length read doesn't match header! Content-Length={0}; Read={1}", contentLength, read);
+			    return response.StatusCode;
             }
         }
 
@@ -318,14 +333,41 @@ public Task<HttpStatusCode> CreateDir(string remotePath)
             return WebDavOperation (dirUri, method, null, null, null, FinishCreateDir, null);
         }
 
+        public Task<Boolean> Exists(string remotePath)
+        {
+            string method = WebRequestMethods.Http.Head.ToString();
+            Uri dirUri = getServerUrl(remotePath, false);
+            return WebDavOperation(dirUri, method, null, null, null, (result) =>
+            {
+                try
+                {
+                    using (HttpWebResponse response = (HttpWebResponse)httpWebRequest.EndGetResponse(result))
+                    {
+                        return response.StatusCode == HttpStatusCode.OK;
+                    }
+                }
+                catch (WebException wex)
+                {
+                    var resp = (HttpWebResponse)wex.Response;
+                    if (resp != null && resp.StatusCode == HttpStatusCode.NotFound)
+                        return false;
+                    throw wex;
+                }
+            }, null);
+        }
 
         HttpStatusCode FinishCreateDir(IAsyncResult result)
         {
-            int statusCode = 0;
-
-            using (HttpWebResponse response = (HttpWebResponse)httpWebRequest.EndGetResponse(result))
+            try
             {
-                return response.StatusCode;
+                using (HttpWebResponse response = (HttpWebResponse)httpWebRequest.EndGetResponse(result))
+                {
+                    return response.StatusCode;
+                }
+            } catch (WebException wex)
+            {
+                var webresponse = ((WebException)wex).Response as HttpWebResponse;
+                return webresponse.StatusCode;
             }
         }
 
@@ -338,14 +380,12 @@ public Task<HttpStatusCode> Delete(string remoteFilePath)
         {
             Uri delUri = getServerUrl(remoteFilePath, remoteFilePath.EndsWith("/"));
 
-			return WebDavOperation(delUri, "DELETE", null, null, null, FinishDelete, null);
+		    return WebDavOperation(delUri, "DELETE", null, null, null, FinishDelete, null);
         }
 
 
         HttpStatusCode FinishDelete(IAsyncResult result)
         {
-            int statusCode = 0;
-
             using (HttpWebResponse response = (HttpWebResponse)httpWebRequest.EndGetResponse(result))
             {
                 return response.StatusCode;
@@ -367,6 +407,12 @@ class RequestState
             public string uploadFilePath;
         }
 
+        Task<TResult> WebDavOperation<TResult>(Uri uri, string requestMethod, IDictionary<string, string> headers, byte[] content, string uploadFilePath, Func<IAsyncResult, TResult> callback, object state)
+        {
+            return WebDavOperation(uri, requestMethod, headers, content, null, uploadFilePath, callback, state);
+        }
+
+
         /// <summary>
         /// Perform the WebDAV call and fire the callback when finished.
         /// </summary>
@@ -377,42 +423,16 @@ class RequestState
         /// <param name="uploadFilePath"></param>
         /// <param name="callback"></param>
         /// <param name="state"></param>
-		Task<TResult> WebDavOperation<TResult>(Uri uri, string requestMethod, IDictionary<string, string> headers, byte[] content, string uploadFilePath, Func<IAsyncResult, TResult> callback, object state)
+        Task<TResult> WebDavOperation<TResult>(Uri uri, string requestMethod, IDictionary<string, string> headers, byte[] content, String contentType, string uploadFilePath, Func<IAsyncResult, TResult> callback, object state)
         {
-            httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(uri);
+            httpWebRequest = requestBuilder.Build(uri);
 			
             /*
-             * The following line fixes an authentication problem explained here:
-             * http://www.devnewsgroups.net/dotnetframework/t9525-http-protocol-violation-long.aspx
-             */
-            System.Net.ServicePointManager.Expect100Continue = false;
-            
-            // If you want to disable SSL certificate validation
-            /*
-            System.Net.ServicePointManager.ServerCertificateValidationCallback +=
-            delegate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors sslError)
-            {
-                    bool validationResult = true;
-                    return validationResult;
-            };
+            * The following line fixes an authentication problem explained here:
+            * http://www.devnewsgroups.net/dotnetframework/t9525-http-protocol-violation-long.aspx
             */
-        
-            // The server may use authentication
-            if (user != null && pass != null)
-            {
-                NetworkCredential networkCredential;
-                if (domain != null)
-                {
-                    networkCredential = new NetworkCredential(user, pass, domain);
-                }
-                else
-                {
-                    networkCredential = new NetworkCredential(user, pass);
-                }
-                httpWebRequest.Credentials = networkCredential;
-                // Send authentication along with first request.
-                httpWebRequest.PreAuthenticate = true;
-            }
+            System.Net.ServicePointManager.Expect100Continue = false;
+
             httpWebRequest.Method = requestMethod;
 
             // Need to send along headers?
@@ -435,7 +455,8 @@ Task<TResult> WebDavOperation<TResult>(Uri uri, string requestMethod, IDictionar
                     // The request either contains actual content...
                     httpWebRequest.ContentLength = content.Length;
                     asyncState.content = content;
-                    httpWebRequest.ContentType = "text/xml";
+                    if(contentType != null)
+                        httpWebRequest.ContentType = "text/xml";
                 }
                 else
                 {
@@ -445,17 +466,17 @@ Task<TResult> WebDavOperation<TResult>(Uri uri, string requestMethod, IDictionar
                 }
 
                 // Perform asynchronous request.
-				return Task.Factory.FromAsync (asyncState.request.BeginGetRequestStream, ReadCallback, asyncState)
-					.ContinueWith (t => {
-						if (t.IsFaulted)
-							throw t.Exception;
-						return Task<TResult>.Factory.FromAsync (httpWebRequest.BeginGetResponse, callback, state).Result;
-					});
+			    return Task.Factory.FromAsync (asyncState.request.BeginGetRequestStream, ReadCallback, asyncState)
+				    .ContinueWith (t => {
+					    if (t.IsFaulted)
+						    throw t.Exception;
+					    return Task<TResult>.Factory.FromAsync (httpWebRequest.BeginGetResponse, callback, state).Result;
+				    });
             }
             else
             {
                 // Begin async communications
-				return Task<TResult>.Factory.FromAsync (httpWebRequest.BeginGetResponse, callback, state);
+			    return Task<TResult>.Factory.FromAsync (httpWebRequest.BeginGetResponse, callback, state);
             }
         }
 
@@ -493,6 +514,14 @@ private void ReadCallback(IAsyncResult result)
                 }
             }
         }
+
+        public void Dispose()
+        {
+            if (httpWebRequest != null)
+            {
+                httpWebRequest.Abort();
+            }
+        }
         #endregion
     }
 }