/// <summary> /// Processes GSuite request. /// </summary> public async Task Invoke(HttpContext context, ContextBaseAsync davContext) { if (!await engine.RunAsync(davContext)) { await next(context); } }
/// <summary> /// Handles GET and HEAD request. /// </summary> /// <param name="context">Instace of <see cref="ContextBaseAsync"/>.</param> /// <param name="item">Instance of <see cref="IHierarchyItemAsync"/> which was returned by /// <see cref="ContextBaseAsync.GetHierarchyItemAsync"/> for this request.</param> public async Task ProcessRequestAsync(ContextBaseAsync context, IHierarchyItemBaseAsync 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); } }
/// <summary> /// Handles GET and HEAD request. /// </summary> /// <param name="context">Instace of <see cref="ContextBaseAsync"/>.</param> /// <param name="item">Instance of <see cref="IHierarchyItemAsync"/> which was returned by /// <see cref="ContextBaseAsync.GetHierarchyItemAsync"/> for this request.</param> public async Task ProcessRequestAsync(ContextBaseAsync context, IHierarchyItemBaseAsync 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); } }
/// <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="ContextBaseAsync"/>.</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(ContextBaseAsync 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") { using (var writer = new StreamWriter(context.Response.OutputStream, encoding)) { await writer.WriteAsync(content); } } }
/// <summary> /// Writes iOS / OS X CalDAV/CardDAV profile. /// </summary> /// <param name="context">Instace of <see cref="ContextBaseAsync"/>.</param> /// <param name="item">ICalendarFolderAsync or IAddressbookFolderAsync item.</param> /// <returns></returns> private async Task WriteProfileAsync(ContextBaseAsync 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).Identity.Name // 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; using (BinaryWriter writer = new BinaryWriter(context.Response.OutputStream)) { writer.Write(profileBytes); } }
/// <summary> /// Signs iOS / OS X payload profile with SSL certificate. /// </summary> /// <param name="context">Instace of <see cref="ContextBaseAsync"/>.</param> /// <param name="profile">Profile to sign.</param> /// <returns>Signed profile.</returns> private byte[] SignProfile(ContextBaseAsync 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)); }
/// <summary> /// Handles GET and HEAD request. /// </summary> /// <param name="context">Instace of <see cref="ContextBaseAsync"/>.</param> /// <param name="item">Instance of <see cref="IHierarchyItemAsync"/> which was returned by /// <see cref="ContextBaseAsync.GetHierarchyItemAsync"/> for this request.</param> public async Task ProcessRequestAsync(ContextBaseAsync context, IHierarchyItemBaseAsync 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); } }
/// <summary> /// Processes WebDAV request. /// </summary> public async Task Invoke(HttpContext context, ContextBaseAsync davContext, IOptions <DavContextOptions> tmp, ILogger logger) { await engine.RunAsync(davContext); }