/// <summary>
        /// Handles GET and HEAD request.
        /// </summary>
        /// <param name="context">Instace of <see cref="ContextAsync{IHierarchyItemAsync}"/>.</param>
        /// <param name="item">Instance of <see cref="IHierarchyItemAsync"/> which was returned by
        /// <see cref="ContextAsync{IHierarchyItemAsync}.GetHierarchyItemAsync"/> for this request.</param>
        public async Task ProcessRequestAsync(ContextAsync <IHierarchyItemAsync> context, IHierarchyItemAsync item)
        {
            string urlPath = context.Request.RawUrl.Substring(context.Request.ApplicationPath.TrimEnd('/').Length);

            if (item is IItemCollectionAsync)
            {
                // In case of GET requests to WebDAV folders we serve a web page to display
                // any information about this server and how to use it.

                // Remember to call EnsureBeforeResponseWasCalledAsync here if your context implementation
                // makes some useful things in BeforeResponseAsync.
                await context.EnsureBeforeResponseWasCalledAsync();

                string htmlName = "MyCustomHandlerPage.html";
                using (TextReader reader = File.OpenText(Path.Combine(htmlPath, htmlName)))
                {
                    string html = await reader.ReadToEndAsync();

                    html = html.Replace("_webDavServerRoot_", context.Request.ApplicationPath.TrimEnd('/'));
                    html = html.Replace("_webDavServerVersion_",
                                        typeof(DavEngineAsync).GetTypeInfo().Assembly.GetName().Version.ToString());

                    await WriteFileContentAsync(context, html, htmlName);
                }
            }
            else
            {
                await OriginalHandler.ProcessRequestAsync(context, item);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Handles GET and HEAD request.
        /// </summary>
        /// <param name="context">Instace of <see cref="ContextAsync{IHierarchyItemAsync}"/>.</param>
        /// <param name="item">Instance of <see cref="IHierarchyItemAsync"/> which was returned by
        /// <see cref="ContextAsync{IHierarchyItemAsync}.GetHierarchyItemAsync"/> for this request.</param>
        public async Task ProcessRequestAsync(ContextAsync <IHierarchyItemAsync> context, IHierarchyItemAsync item)
        {
            string urlPath = context.Request.RawUrl.Substring(context.Request.ApplicationPath.TrimEnd('/').Length);

            if (item is IItemCollectionAsync)
            {
                // In case of GET requests to WebDAV folders we serve a web page to display
                // any information about this server and how to use it.

                // Remember to call EnsureBeforeResponseWasCalledAsync here if your context implementation
                // makes some useful things in BeforeResponseAsync.
                await context.EnsureBeforeResponseWasCalledAsync();

                IHttpAsyncHandler page = (IHttpAsyncHandler)System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(
                    "~/MyCustomHandlerPage.aspx", typeof(MyCustomHandlerPage));

                if (Type.GetType("Mono.Runtime") != null)
                {
                    page.ProcessRequest(HttpContext.Current);
                }
                else
                {
                    // Here we call BeginProcessRequest instead of ProcessRequest to start an async page execution and be able to call RegisterAsyncTask if required.
                    // To call APM method (Begin/End) from TAP method (Task/async/await) the Task.FromAsync must be used.
                    await Task.Factory.FromAsync(page.BeginProcessRequest, page.EndProcessRequest, HttpContext.Current, null);
                }
            }
            else
            {
                await OriginalHandler.ProcessRequestAsync(context, item);
            }
        }
Beispiel #3
0
        /// <summary>
        /// Gets all user address books URLs.
        /// </summary>
        private async Task <string> AllUserAddressbooksUrlAsync(ContextAsync <IHierarchyItemAsync> context)
        {
            Discovery discovery = new Discovery(context as DavContext);
            List <IHierarchyItemAsync> items = new List <IHierarchyItemAsync>();

            // get list of folders that contain user address books and enumerate address books in each folder
            foreach (IItemCollectionAsync folder in await discovery.GetAddressbookHomeSetAsync())
            {
                IEnumerable <IHierarchyItemAsync> children = (await folder.GetChildrenAsync(new PropertyName[0], null, null, null)).Page;
                items.AddRange(children.Where(x => x is IAddressbookFolderAsync));
            }
            IEnumerable <string> nameAndUrls = items.Select(x => string.Format("<tr><td><span class=\"glyphicon glyphicon - book\"></span></td><td>{0}</td><td>{1}</td><td><a href=\"{1}?connect\" class=\"btn btn-default\">Connect</a></td></tr>", x.Name, AddAppPath(context, x.Path)));

            return(String.Join(string.Empty, nameAndUrls.ToArray()));
        }
Beispiel #4
0
        /// <summary>
        /// Writes HTML to the output stream in case of GET request using encoding specified in Engine.
        /// Writes headers only in case of HEAD request.
        /// </summary>
        /// <param name="context">Instace of <see cref="ContextAsync{IHierarchyItemAsync}"/>.</param>
        /// <param name="content">String representation of the content to write.</param>
        /// <param name="filePath">Relative file path, which holds the content.</param>
        private async Task WriteFileContentAsync(ContextAsync <IHierarchyItemAsync> context, string content, string filePath)
        {
            Encoding encoding = context.Engine.ContentEncoding; // UTF-8 by default

            context.Response.ContentLength = encoding.GetByteCount(content);
            context.Response.ContentType   = string.Format("{0}; charset={1}", MimeType.GetMimeType(Path.GetExtension(filePath)) ?? "application/octet-stream", encoding.WebName);

            // Return file content in case of GET request, in case of HEAD just return headers.
            if (context.Request.HttpMethod == "GET")
            {
                await using (var writer = new StreamWriter(context.Response.OutputStream, encoding))
                {
                    await writer.WriteAsync(content);
                }
            }
        }
Beispiel #5
0
        /// <summary>
        /// Writes iOS / OS X CalDAV/CardDAV profile.
        /// </summary>
        /// <param name="context">Instace of <see cref="ContextAsync{IHierarchyItemAsync}"/>.</param>
        /// <param name="item">ICalendarFolderAsync or IAddressbookFolderAsync item.</param>
        /// <returns></returns>
        private async Task WriteProfileAsync(ContextAsync <IHierarchyItemAsync> context, IHierarchyItemBaseAsync item, string htmlPath)
        {
            string mobileconfigFileName = null;
            string decription           = null;

            if (item is IAddressbookFolderAsync)
            {
                mobileconfigFileName = "CardDAV.AppleProfileTemplete.mobileconfig";
                decription           = (item as IAddressbookFolderAsync).AddressbookDescription;
            }

            decription = !string.IsNullOrEmpty(decription) ? decription : item.Name;

            string templateContent = null;

            using (TextReader reader = new StreamReader(Path.Combine(htmlPath, mobileconfigFileName)))
            {
                templateContent = await reader.ReadToEndAsync();
            }

            Uri url = new Uri(context.Request.UrlPrefix);

            string payloadUUID = item.Path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries).Last(); // PayloadUUID

            string profile = string.Format(templateContent
                                           , url.Host                                     // host name
                                           , item.Path                                    // CalDAV / CardDAV Principal URL. Here we can return (await (item as ICurrentUserPrincipalAsync).GetCurrentUserPrincipalAsync()).Path if needed.
                                           , (context as DavContext).UserName             // user name
                                           , url.Port                                     // port
                                           , (url.Scheme == "https").ToString().ToLower() // SSL
                                           , decription                                   // CardDAV / CardDAV Account Description
                                           , Assembly.GetAssembly(this.GetType()).GetName().Version.ToString()
                                           , Assembly.GetAssembly(typeof(DavEngineAsync)).GetName().Version.ToString()
                                           , payloadUUID
                                           );

            byte[] profileBytes = SignProfile(context, profile);

            context.Response.ContentType = "application/x-apple-aspen-config";
            context.Response.AddHeader("Content-Disposition", "attachment; filename=profile.mobileconfig");
            context.Response.ContentLength = profileBytes.Length;
            await context.Response.OutputStream.WriteAsync(profileBytes, 0, profileBytes.Length);
        }
        /// <summary>
        /// Handles GET and HEAD request.
        /// </summary>
        /// <param name="context">Instace of <see cref="ContextAsync{IHierarchyItemAsync}"/>.</param>
        /// <param name="item">Instance of <see cref="IHierarchyItemAsync"/> which was returned by
        /// <see cref="ContextAsync{IHierarchyItemAsync}.GetHierarchyItemAsync"/> for this request.</param>
        public async Task ProcessRequestAsync(ContextAsync <IHierarchyItemAsync> context, IHierarchyItemAsync item)
        {
            string urlPath = context.Request.RawUrl.Substring(context.Request.ApplicationPath.TrimEnd('/').Length);

            if (item is IItemCollectionAsync)
            {
                // In case of GET requests to WebDAV folders we serve a web page to display
                // any information about this server and how to use it.

                // Remember to call EnsureBeforeResponseWasCalledAsync here if your context implementation
                // makes some useful things in BeforeResponseAsync.
                await context.EnsureBeforeResponseWasCalledAsync();

                string htmlName = "MyCustomHandlerPage.html";
                using (TextReader reader = File.OpenText(Path.Combine(htmlPath, htmlName)))
                {
                    string html = await reader.ReadToEndAsync();

                    html = html.Replace("_webDavServerRoot_", "");
                    html = html.Replace("_webDavServerVersion_",
                                        typeof(DavEngineAsync).GetTypeInfo().Assembly.GetName().Version.ToString());

                    // Set list of cookie names for ajax lib.
                    if (context.Request.Headers.ContainsKey("Cookie"))
                    {
                        html = html.Replace("_webDavAuthCookieNames_", string.Join(",", context.Request.Headers["Cookie"]
                                                                                   .TrimEnd(';').Split(';').Select(p => p.Split(new[] { '=' }, 2)[0].Trim())
                                                                                   .Where(p => p.StartsWith(".AspNetCore.Identity.Application") || p.StartsWith(".AspNetCore.Cookies") || p.StartsWith(".AspNetCore.AzureADCookie"))));
                    }

                    await WriteFileContentAsync(context, html, htmlName);
                }
            }
            else
            {
                await OriginalHandler.ProcessRequestAsync(context, item);
            }
        }
Beispiel #7
0
 /// <summary>
 /// Signs iOS / OS X payload profile with SSL certificate.
 /// </summary>
 /// <param name="context">Instace of <see cref="ContextAsync{IHierarchyItemAsync}"/>.</param>
 /// <param name="profile">Profile to sign.</param>
 /// <returns>Signed profile.</returns>
 private byte[] SignProfile(ContextAsync <IHierarchyItemAsync> context, string profile)
 {
     // Here you will sign your profile with SSL certificate to avoid "Unsigned" warning on iOS and OS X.
     // For demo purposes we just return the profile content unmodified.
     return(context.Engine.ContentEncoding.GetBytes(profile));
 }
Beispiel #8
0
        private static string AddAppPath(ContextAsync <IHierarchyItemAsync> context, string path)
        {
            string applicationPath = context.Request.UrlPrefix + context.Request.ApplicationPath;

            return(string.Format("{0}/{1}", applicationPath.TrimEnd(new[] { '/' }), path.TrimStart(new[] { '/' })));
        }
        /// <summary>
        /// Handles GET and HEAD request.
        /// </summary>
        /// <param name="context">Instace of <see cref="ContextAsync{IHierarchyItemAsync}"/>.</param>
        /// <param name="item">Instance of <see cref="IHierarchyItemAsync"/> which was returned by
        /// <see cref="ContextAsync{IHierarchyItemAsync}.GetHierarchyItemAsync"/> for this request.</param>
        public async Task ProcessRequestAsync(ContextAsync <IHierarchyItemAsync> context, IHierarchyItemAsync item)
        {
            string urlPath = context.Request.RawUrl.Substring(context.Request.ApplicationPath.TrimEnd('/').Length);

            if (item is IItemCollectionAsync)
            {
                // In case of GET requests to WebDAV folders we serve a web page to display
                // any information about this server and how to use it.

                // Remember to call EnsureBeforeResponseWasCalledAsync here if your context implementation
                // makes some useful things in BeforeResponseAsync.
                await context.EnsureBeforeResponseWasCalledAsync();

                string htmlName = "MyCustomHandlerPage.html";
                using (TextReader reader = File.OpenText(Path.Combine(htmlPath, htmlName)))
                {
                    string html = await reader.ReadToEndAsync();

                    html = html.Replace("_webDavServerRoot_", context.Request.ApplicationPath.TrimEnd('/'));
                    html = html.Replace("_webDavServerVersion_",
                                        typeof(DavEngineAsync).GetTypeInfo().Assembly.GetName().Version.ToString());

                    await WriteFileContentAsync(context, html, htmlName);
                }
            }
            else if (urlPath.StartsWith("/AjaxFileBrowser/") || urlPath.StartsWith("/wwwroot/"))
            {
                // The "/AjaxFileBrowser/" are not a WebDAV folders. They can be used to store client script files,
                // images, static HTML files or any other files that does not require access via WebDAV.
                // Any request to the files in this folder will just serve them to the client.

                await context.EnsureBeforeResponseWasCalledAsync();

                string filePath = Path.Combine(htmlPath, urlPath.TrimStart('/').Replace('/', Path.DirectorySeparatorChar));

                // Remove query string.
                int queryIndex = filePath.LastIndexOf('?');
                if (queryIndex > -1)
                {
                    filePath = filePath.Remove(queryIndex);
                }

                if (!File.Exists(filePath))
                {
                    throw new DavException("File not found: " + filePath, DavStatus.NOT_FOUND);
                }

                Encoding encoding = context.Engine.ContentEncoding; // UTF-8 by default
                context.Response.ContentType = string.Format("{0}; charset={1}", MimeType.GetMimeType(Path.GetExtension(filePath)) ?? "application/octet-stream", encoding.WebName);

                // Return file content in case of GET request, in case of HEAD just return headers.
                if (context.Request.HttpMethod == "GET")
                {
                    using (FileStream fileStream = File.OpenRead(filePath))
                    {
                        context.Response.ContentLength = fileStream.Length;
                        await fileStream.CopyToAsync(context.Response.OutputStream);
                    }
                }
            }
            else
            {
                await OriginalHandler.ProcessRequestAsync(context, item);
            }
        }