using Microsoft.AspNetCore.Mvc; using Nop.Core; using Nop.Core.Domain.Customers; using Nop.Services.Catalog; using Nop.Services.Localization; using Nop.Services.Media; using Nop.Services.Orders; using Nop.Web.Framework.Mvc.Filters; namespace Nop.Web.Controllers; public partial class DownloadController : BasePublicController { protected readonly CustomerSettings _customerSettings; protected readonly IDownloadService _downloadService; protected readonly ILocalizationService _localizationService; protected readonly IOrderService _orderService; protected readonly IProductService _productService; protected readonly IWorkContext _workContext; public DownloadController(CustomerSettings customerSettings, IDownloadService downloadService, ILocalizationService localizationService, IOrderService orderService, IProductService productService, IWorkContext workContext) { _customerSettings = customerSettings; _downloadService = downloadService; _localizationService = localizationService; _orderService = orderService; _productService = productService; _workContext = workContext; } //ignore SEO friendly URLs checks [CheckLanguageSeoCode(ignore: true)] public virtual async Task Sample(int productId) { var product = await _productService.GetProductByIdAsync(productId); if (product == null) return InvokeHttp404(); if (!product.HasSampleDownload) return Content("Product doesn't have a sample download."); var download = await _downloadService.GetDownloadByIdAsync(product.SampleDownloadId); if (download == null) return Content("Sample download is not available any more."); //A warning (SCS0027 - Open Redirect) from the "Security Code Scan" analyzer may appear at this point. //In this case, it is not relevant. Url may not be local. if (download.UseDownloadUrl) return new RedirectResult(download.DownloadUrl); if (download.DownloadBinary == null) return Content("Download data is not available any more."); var fileName = !string.IsNullOrWhiteSpace(download.Filename) ? download.Filename : product.Id.ToString(); var contentType = !string.IsNullOrWhiteSpace(download.ContentType) ? download.ContentType : MimeTypes.ApplicationOctetStream; return new FileContentResult(download.DownloadBinary, contentType) { FileDownloadName = fileName + download.Extension }; } //ignore SEO friendly URLs checks [CheckLanguageSeoCode(ignore: true)] public virtual async Task GetDownload(Guid orderItemId, bool agree = false) { var orderItem = await _orderService.GetOrderItemByGuidAsync(orderItemId); if (orderItem == null) return InvokeHttp404(); var order = await _orderService.GetOrderByIdAsync(orderItem.OrderId); if (!await _orderService.IsDownloadAllowedAsync(orderItem)) return Content("Downloads are not allowed"); if (_customerSettings.DownloadableProductsValidateUser) { var customer = await _workContext.GetCurrentCustomerAsync(); if (customer == null) return Challenge(); if (order.CustomerId != customer.Id) return Content("This is not your order"); } var product = await _productService.GetProductByIdAsync(orderItem.ProductId); var download = await _downloadService.GetDownloadByIdAsync(product.DownloadId); if (download == null) return Content("Download is not available any more."); if (product.HasUserAgreement && !agree) return RedirectToRoute("DownloadUserAgreement", new { orderItemId = orderItemId }); if (!product.UnlimitedDownloads && orderItem.DownloadCount >= product.MaxNumberOfDownloads) return Content(string.Format(await _localizationService.GetResourceAsync("DownloadableProducts.ReachedMaximumNumber"), product.MaxNumberOfDownloads)); if (download.UseDownloadUrl) { //increase download orderItem.DownloadCount++; await _orderService.UpdateOrderItemAsync(orderItem); //return result //A warning (SCS0027 - Open Redirect) from the "Security Code Scan" analyzer may appear at this point. //In this case, it is not relevant. Url may not be local. return new RedirectResult(download.DownloadUrl); } //binary download if (download.DownloadBinary == null) return Content("Download data is not available any more."); //increase download orderItem.DownloadCount++; await _orderService.UpdateOrderItemAsync(orderItem); //return result var fileName = !string.IsNullOrWhiteSpace(download.Filename) ? download.Filename : product.Id.ToString(); var contentType = !string.IsNullOrWhiteSpace(download.ContentType) ? download.ContentType : MimeTypes.ApplicationOctetStream; return new FileContentResult(download.DownloadBinary, contentType) { FileDownloadName = fileName + download.Extension }; } //ignore SEO friendly URLs checks [CheckLanguageSeoCode(ignore: true)] public virtual async Task GetLicense(Guid orderItemId) { var orderItem = await _orderService.GetOrderItemByGuidAsync(orderItemId); if (orderItem == null) return InvokeHttp404(); var order = await _orderService.GetOrderByIdAsync(orderItem.OrderId); if (!await _orderService.IsLicenseDownloadAllowedAsync(orderItem)) return Content("Downloads are not allowed"); if (_customerSettings.DownloadableProductsValidateUser) { var customer = await _workContext.GetCurrentCustomerAsync(); if (customer == null || order.CustomerId != customer.Id) return Challenge(); } var download = await _downloadService.GetDownloadByIdAsync(orderItem.LicenseDownloadId ?? 0); if (download == null) return Content("Download is not available any more."); //A warning (SCS0027 - Open Redirect) from the "Security Code Scan" analyzer may appear at this point. //In this case, it is not relevant. Url may not be local. if (download.UseDownloadUrl) return new RedirectResult(download.DownloadUrl); //binary download if (download.DownloadBinary == null) return Content("Download data is not available any more."); //return result var fileName = !string.IsNullOrWhiteSpace(download.Filename) ? download.Filename : orderItem.ProductId.ToString(); var contentType = !string.IsNullOrWhiteSpace(download.ContentType) ? download.ContentType : MimeTypes.ApplicationOctetStream; return new FileContentResult(download.DownloadBinary, contentType) { FileDownloadName = fileName + download.Extension }; } public virtual async Task GetFileUpload(Guid downloadId) { var download = await _downloadService.GetDownloadByGuidAsync(downloadId); if (download == null) return Content("Download is not available any more."); //A warning (SCS0027 - Open Redirect) from the "Security Code Scan" analyzer may appear at this point. //In this case, it is not relevant. Url may not be local. if (download.UseDownloadUrl) return new RedirectResult(download.DownloadUrl); //binary download if (download.DownloadBinary == null) return Content("Download data is not available any more."); //return result var fileName = !string.IsNullOrWhiteSpace(download.Filename) ? download.Filename : downloadId.ToString(); var contentType = !string.IsNullOrWhiteSpace(download.ContentType) ? download.ContentType : MimeTypes.ApplicationOctetStream; return new FileContentResult(download.DownloadBinary, contentType) { FileDownloadName = fileName + download.Extension }; } //ignore SEO friendly URLs checks [CheckLanguageSeoCode(ignore: true)] public virtual async Task GetOrderNoteFile(int orderNoteId) { var orderNote = await _orderService.GetOrderNoteByIdAsync(orderNoteId); if (orderNote == null) return InvokeHttp404(); var order = await _orderService.GetOrderByIdAsync(orderNote.OrderId); var customer = await _workContext.GetCurrentCustomerAsync(); if (customer == null || order.CustomerId != customer.Id) return Challenge(); var download = await _downloadService.GetDownloadByIdAsync(orderNote.DownloadId); if (download == null) return Content("Download is not available any more."); //A warning (SCS0027 - Open Redirect) from the "Security Code Scan" analyzer may appear at this point. //In this case, it is not relevant. Url may not be local. if (download.UseDownloadUrl) return new RedirectResult(download.DownloadUrl); //binary download if (download.DownloadBinary == null) return Content("Download data is not available any more."); //return result var fileName = !string.IsNullOrWhiteSpace(download.Filename) ? download.Filename : orderNote.Id.ToString(); var contentType = !string.IsNullOrWhiteSpace(download.ContentType) ? download.ContentType : MimeTypes.ApplicationOctetStream; return new FileContentResult(download.DownloadBinary, contentType) { FileDownloadName = fileName + download.Extension }; } }