diff --git a/OurUmbraco.Site/macroScripts/repository-view-project.cshtml b/OurUmbraco.Site/macroScripts/repository-view-project.cshtml index 0a29ba3f..4867c181 100644 --- a/OurUmbraco.Site/macroScripts/repository-view-project.cshtml +++ b/OurUmbraco.Site/macroScripts/repository-view-project.cshtml @@ -1,4 +1,6 @@ @using OurUmbraco.Project +@using OurUmbraco.Repository.Services +@using Umbraco.Core @using Umbraco.Web @{ System.Web.Helpers.AntiForgeryConfig.SuppressXFrameOptionsHeader = true; @@ -7,6 +9,7 @@ int projectId; if (int.TryParse(Request.QueryString["project_id"], out projectId) == false) { + //TODO: Exception probably ! return; } @@ -14,6 +17,11 @@ var callback = Request.QueryString["callback"]; var Project = ProjectsProvider.GetListing(projectId, false); + if (Project == null) + { + throw new InvalidOperationException("No project found with id " + projectId); + } + var node = new umbraco.NodeFactory.Node(projectId); var parentId = node.Parent.Id; var categoryName = node.Parent.Name; @@ -30,10 +38,26 @@ descCssClass = "wrap"; } + var umbracoHelper = new UmbracoHelper(UmbracoContext.Current); + var packageRepoService = new PackageRepositoryService(umbracoHelper, umbracoHelper.MembershipHelper, ApplicationContext.Current.DatabaseContext); + //This doesn't matter what we set it to so long as it's below 7.5 since that is the version we introduce strict dependencies + var currUmbracoVersion = new Version(4, 0, 0); + var packageDetails = packageRepoService.GetDetails(Project.ProjectGuid, currUmbracoVersion); + + if (packageDetails == null) + { + throw new InvalidOperationException("No package found with id " + Project.ProjectGuid); + } + + if (packageDetails.ZipUrl.IsNullOrWhiteSpace()) + { + throw new InvalidOperationException("This package is not compatible with the Umbraco version " + currUmbracoVersion); + } + int currentReleaseFile = 0; if (int.TryParse(Project.CurrentReleaseFile, out currentReleaseFile)) { - var file = Project.PackageFile.Where(x => x.Id == currentReleaseFile).FirstOrDefault(); + var file = Project.PackageFile.FirstOrDefault(x => x.Id == currentReleaseFile); if (file != null) { var ct = "This project is compaitible with "; @@ -66,27 +90,33 @@ } }
- @if (currentReleaseFile != 0) + @if (string.IsNullOrWhiteSpace(packageDetails.ZipUrl) == false) {

@Project.Name Install package

} + else if (currentReleaseFile != 0) + { + Unfortunately, this package is not compatible with the version of Umbraco you are running.
+ Go to the package page to learn more + } else { Unfortunately, this package has no current release file to install at the moment.
- Go to the package page to learn more} + Go to the package page to learn more + }
@@ -94,10 +124,10 @@
Project owner:
@{ - var umbracoHelper = new UmbracoHelper(UmbracoContext.Current); + var ownerName = umbracoHelper.MembershipHelper.GetById(Project.VendorId).Name; } -
@ownerName
+
@ownerName
Package downloads
@Project.Downloads
@@ -119,9 +149,9 @@ @if (Project.Stable) {
Is Stable:
-
- Project is stable -
+
+ Project is stable +
}
Current version
@@ -130,9 +160,9 @@ @if (!string.IsNullOrEmpty(Project.LicenseName)) {
License
-
- @Project.LicenseName -
+
+ @Project.LicenseName +
}
@@ -158,7 +188,7 @@ image.Path.EndsWith("jpeg")) { - + } } diff --git a/OurUmbraco/Repository/Controllers/PackageRepositoryController.cs b/OurUmbraco/Repository/Controllers/PackageRepositoryController.cs index d05dff3c..28c7737f 100644 --- a/OurUmbraco/Repository/Controllers/PackageRepositoryController.cs +++ b/OurUmbraco/Repository/Controllers/PackageRepositoryController.cs @@ -9,6 +9,11 @@ using Umbraco.Core.Cache; using Umbraco.Web.WebApi; using System.Net.Http; using System.Net; +using System.Net.Http.Headers; +using OurUmbraco.Wiki.BusinessLogic; +using Semver; +using Umbraco.Core; +using Umbraco.Web; namespace OurUmbraco.Repository.Controllers { @@ -87,21 +92,90 @@ namespace OurUmbraco.Repository.Controllers TimeSpan.FromMinutes(1)); //cache for 1 min } - public Models.PackageDetails GetDetails(Guid id) + /// + /// Returns the package details for the package Id passed in and ensures that + /// the resulting ZipUrl is the compatible package for the version passed in. + /// + /// + /// The umbraco version requesting the details, if null than the ZipUrl will be the latest package zip + /// pass in true to get the package file otherwise leave blank or set to false to retreive the package details + /// + public HttpResponseMessage Get(Guid id, string version = null, bool? asFile = false) + { + SemVersion parsed = null; + if (version.IsNullOrWhiteSpace() == false) + { + SemVersion.TryParse(version, out parsed); + } + else + { + //if the version is null then the current umbraco version must be 7.5.x because this endpoint was only ever used by 7.5.x and 7.6.x and above will always + // suppy the version, therefore we can assume that this is 7.5.x, let's make it 7.5.13 which is the latest 7.5 we have right now + parsed = new SemVersion(7, 5, 13); + } + + //this should never be null, if it is return not found + if (parsed == null) + { + throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); + } + + var v = new System.Version(parsed.Major, parsed.Minor, parsed.Patch); + + return asFile.HasValue && asFile.Value + ? GetPackageFile(id, v) + : GetDetails(id, v); + } + + private HttpResponseMessage GetDetails(Guid id, System.Version currUmbracoVersion) { //return the results, but cache for 1 minute - var key = string.Format("PackageRepositoryController.GetDetails.{0}", id); + var key = string.Format("PackageRepositoryController.GetDetails.{0}.{1}", id, currUmbracoVersion.ToString(3)); var package = ApplicationContext.ApplicationCache.RuntimeCache.GetCacheItem - (key, - () => Service.GetDetails(id), - TimeSpan.FromMinutes(1)); //cache for 1 min - + (key, + () => + { + var details = Service.GetDetails(id, currUmbracoVersion); + + if (details.ZipUrl.IsNullOrWhiteSpace()) + throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, "This package is not compatible with the Umbraco version " + currUmbracoVersion)); + + return details; + }, + TimeSpan.FromMinutes(1)); //cache for 1 min + if (package == null) { throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); } - return package; + return Request.CreateResponse(HttpStatusCode.OK, package); + } + + private HttpResponseMessage GetPackageFile(Guid packageId, System.Version currUmbracoVersion) + { + var pckRepoService = new PackageRepositoryService(Umbraco, Members, DatabaseContext); + + var details = pckRepoService.GetDetails(packageId, currUmbracoVersion); + if (details == null) + throw new InvalidOperationException("No package found with id " + packageId); + + if (details.ZipUrl.IsNullOrWhiteSpace()) + throw new InvalidOperationException("This package is not compatible with the Umbraco version " + currUmbracoVersion); + + var wf = new WikiFile(details.ZipFileId); + if (wf == null) + throw new InvalidOperationException("Could not find wiki file by id " + details.ZipFileId); + wf.UpdateDownloadCounter(true, true); + + var result = new HttpResponseMessage(HttpStatusCode.OK) + { + Content = new ByteArrayContent(wf.ToByteArray()) + }; + + result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); + + return result; } } } \ No newline at end of file diff --git a/OurUmbraco/Repository/Models/Package.cs b/OurUmbraco/Repository/Models/Package.cs index f0668a09..a94cfc10 100644 --- a/OurUmbraco/Repository/Models/Package.cs +++ b/OurUmbraco/Repository/Models/Package.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace OurUmbraco.Repository.Models { @@ -27,18 +28,13 @@ namespace OurUmbraco.Repository.Models public string Category { get; set; } + /// + /// The latest version of this package + /// public string LatestVersion { get; set; } public PackageOwnerInfo OwnerInfo { get; set; } - - /// - /// This is the minimum Umbraco version that this package supports - /// - /// - /// This could be null if it is a legacy package - /// - public string MinimumVersion { get; set; } - + public long Score { get; set; } } } \ No newline at end of file diff --git a/OurUmbraco/Repository/Models/PackageDetails.cs b/OurUmbraco/Repository/Models/PackageDetails.cs index 8f85678e..2bce790c 100644 --- a/OurUmbraco/Repository/Models/PackageDetails.cs +++ b/OurUmbraco/Repository/Models/PackageDetails.cs @@ -24,7 +24,6 @@ namespace OurUmbraco.Repository.Models this.Name = package.Name; this.Icon = package.Icon; this.LatestVersion = package.LatestVersion; - this.MinimumVersion = package.MinimumVersion; this.OwnerInfo = package.OwnerInfo; } } @@ -35,6 +34,11 @@ namespace OurUmbraco.Repository.Models public List Compatibility { get; set; } + /// + /// A list of all supported/targeted Umbraco versions for all files for this package + /// + public string[] TargetedUmbracoVersions { get; set; } + public List ExternalSources { get; set; } public string LicenseName { get; set; } @@ -44,5 +48,7 @@ namespace OurUmbraco.Repository.Models public string NetVersion { get; set; } public string ZipUrl { get; set; } + + public int ZipFileId { get; set; } } } \ No newline at end of file diff --git a/OurUmbraco/Repository/Projects.cs b/OurUmbraco/Repository/Projects.cs index f6965d56..18c9df2d 100644 --- a/OurUmbraco/Repository/Projects.cs +++ b/OurUmbraco/Repository/Projects.cs @@ -352,9 +352,12 @@ namespace OurUmbraco.Repository if (xpn.MoveNext()) { - if (xpn.Current is IHasXmlNode) + var xmlNode = xpn.Current as IHasXmlNode; + if (xmlNode != null) { - Node node = new Node(((IHasXmlNode)xpn.Current).GetNode()); + //This will get the latest marked file id + + Node node = new Node(xmlNode.GetNode()); string fileId = safeProperty(node, "file"); int _id; diff --git a/OurUmbraco/Repository/Services/PackageRepositoryService.cs b/OurUmbraco/Repository/Services/PackageRepositoryService.cs index f738fd67..7ef1e240 100644 --- a/OurUmbraco/Repository/Services/PackageRepositoryService.cs +++ b/OurUmbraco/Repository/Services/PackageRepositoryService.cs @@ -29,7 +29,7 @@ using Umbraco.Web.Security; namespace OurUmbraco.Repository.Services { - internal class PackageRepositoryService + public class PackageRepositoryService { private readonly DatabaseContext DatabaseContext; private readonly MembershipHelper MembershipHelper; @@ -145,8 +145,19 @@ namespace OurUmbraco.Repository.Services }; } - public PackageDetails GetDetails(Guid id) + /// + /// Returns the package details for the package Id passed in and ensures that + /// the resulting ZipUrl is the compatible package for the version passed in. + /// + /// + /// The umbraco version requesting the details, if null than the ZipUrl will be the latest package zip + /// + /// If the current umbraco version is not compatible with any package files, the ZipUrl and ZipFileId will be empty + /// + public PackageDetails GetDetails(Guid id, System.Version version) { + if (version == null) throw new ArgumentNullException(nameof(version)); + // [LK:2016-06-13@CGRT16] We're using XPath as we experienced issues with query Examine for GUIDs, // (it might worth but we were up against the clock). // The XPath 'translate' is being used to force the 'packageGuid' to be lowercase for comparison. @@ -156,16 +167,14 @@ namespace OurUmbraco.Repository.Services if (item == null) return null; - return MapContentToPackageDetails(item); + return MapContentToPackageDetails(item, version); } private Models.Package MapContentToPackage(IPublishedContent content) { if (content == null) return null; - - var wikiFiles = WikiFile.CurrentFiles(content.Id); - + return new Models.Package { Category = content.Parent.Name, @@ -177,29 +186,116 @@ namespace OurUmbraco.Repository.Services Name = content.Name, Icon = GetThumbnailUrl(BASE_URL + content.GetPropertyValue("defaultScreenshotPath", "/css/img/package2.png"), 154, 281), LatestVersion = content.GetPropertyValue("version"), - MinimumVersion = GetMinimumVersion(content.GetPropertyValue("file"), wikiFiles.Where(x => x.FileType.InvariantEquals("package"))), OwnerInfo = GetPackageOwnerInfo(content.GetPropertyValue("owner"), content.GetPropertyValue("openForCollab", false), content.Id), Url = string.Concat(BASE_URL, content.Url) }; } - - private PackageDetails MapContentToPackageDetails(IPublishedContent content) - { - if (content == null) - return null; + + /// + /// Returns a PackageDetails instance + /// + /// + /// + /// + /// If the current umbraco version is not compatible with any package files, the ZipUrl and ZipFileId will be empty + /// + private PackageDetails MapContentToPackageDetails(IPublishedContent content, System.Version currentUmbracoVersion) + { + if (currentUmbracoVersion == null) throw new ArgumentNullException(nameof(currentUmbracoVersion)); + if (content == null) return null; var package = MapContentToPackage(content); - var packageDetails = new PackageDetails(package); + if (package == null) + return null; + var wikiFiles = WikiFile.CurrentFiles(content.Id); - packageDetails.Compatibility = GetPackageCompatibility(content); - packageDetails.NetVersion = content.GetPropertyValue("dotNetVersion"); - packageDetails.LicenseName = content.GetPropertyValue("licenseName"); - packageDetails.LicenseUrl = content.GetPropertyValue("licenseUrl"); - packageDetails.Description = content.GetPropertyValue("description").CleanHtmlAttributes(); - packageDetails.Images = GetPackageImages(wikiFiles.Where(x => x.FileType.InvariantEquals("screenshot")), 154, 281); - packageDetails.ExternalSources = GetExternalSources(content); - packageDetails.ZipUrl = string.Concat(BASE_URL, "/FileDownload?id=", content.GetPropertyValue("file")); + //TODO: SD: I dunno where these come from or if we care about it? + //var deliCompatVersions = Utils.GetProjectCompatibleVersions(content.Id) ?? new List(); + + var allPackageFiles = wikiFiles.Where(x => x.FileType.InvariantEquals("package")).ToArray(); + + //get the strict packages in the correct desc order + var strictPackageFileVersions = GetAllStrictSupportedPackageVersions(allPackageFiles).ToArray(); + + var packageDetails = new PackageDetails(package) + { + TargetedUmbracoVersions = GetAllFilePackageVersions(allPackageFiles).Select(x => x.ToString(3)).ToArray(), + Compatibility = GetPackageCompatibility(content), + NetVersion = content.GetPropertyValue("dotNetVersion"), + LicenseName = content.GetPropertyValue("licenseName"), + LicenseUrl = content.GetPropertyValue("licenseUrl"), + Description = content.GetPropertyValue("description").CleanHtmlAttributes(), + Images = GetPackageImages(wikiFiles.Where(x => x.FileType.InvariantEquals("screenshot")), 154, 281), + ExternalSources = GetExternalSources(content) + }; + + var version75 = new System.Version(7, 5, 0); + + //this is the file marked as the current/latest release + var currentReleaseFile = content.GetPropertyValue("file"); + + if (strictPackageFileVersions.Length == 0) + { + //if there are no strict package files then return the latest package file + + packageDetails.ZipUrl = string.Concat(BASE_URL, "/FileDownload?id=", currentReleaseFile); + packageDetails.ZipFileId = currentReleaseFile; + } + else if (currentUmbracoVersion < version75) + { + //if the umbraco version is < 7.5 it means that strict package formats are not supported + + //TODO: Now we have to do the opposite of below and filter out any package file versions that have strict + // umbraco dependencies applied. Anything that has 7.5 (which would be the very minimum strict dependency) we can check for + + //these are ordered by package version desc + var nonStrictPackageFiles = GetNonStrictSupportedPackageVersions(wikiFiles).ToArray(); + + if (nonStrictPackageFiles.Length != 0) + { + //there might be a case where the 'current release file' is not the latest version found, so let's check if + //the latest release file is included in the non-strict packages and if so we'll use that, otherwise we'll use the latest + var found = nonStrictPackageFiles.FirstOrDefault(x => x.PackageId == currentReleaseFile); + if (found != null) + { + //it's included in the non strict packages so use it + packageDetails.ZipUrl = string.Concat(BASE_URL, "/FileDownload?id=", currentReleaseFile); + packageDetails.ZipFileId = currentReleaseFile; + } + else + { + //use the latest available package version + packageDetails.ZipUrl = string.Concat(BASE_URL, "/FileDownload?id=", nonStrictPackageFiles[0].PackageId); + packageDetails.ZipFileId = nonStrictPackageFiles[0].PackageId; + } + } + } + else + { + //this package has some strict version dependency files, so we need to figure out which one is + // compatible with the current umbraco version passed in and also use the latest available + // package version that is compatible. + + int found = -1; + foreach (var pckVersion in strictPackageFileVersions) + { + //if this version will work with the umbraco version, then use it + if (currentUmbracoVersion >= pckVersion.MinUmbracoVersion) + { + found = pckVersion.PackageId; + break; + } + } + + if (found != -1) + { + //got one! so use it's id for the file download + packageDetails.ZipUrl = string.Concat(BASE_URL, "/FileDownload?id=", found); + packageDetails.ZipFileId = found; + } + } + packageDetails.Created = content.CreateDate; return packageDetails; @@ -222,29 +318,139 @@ namespace OurUmbraco.Repository.Services .ToList(); } - private string GetMinimumVersion(int filePropertyValue, IEnumerable packages) + /// + /// Based on all of the files that this package go retrieve all targeted Umbraco versions + /// + /// + /// + private IEnumerable GetAllFilePackageVersions(IEnumerable packages) { - var currentVersion = filePropertyValue; - var latest = packages.FirstOrDefault(x => x.Id == currentVersion); + var allVersions = packages + .Select(x => ConvertToVersion(x.Version.Version)) + .WhereNotNull() + .Distinct() + .OrderBy(x => x) + .ToArray(); - if (latest == null || string.IsNullOrWhiteSpace(latest.Version.Version) || latest.Version.Version.InvariantEquals("nan")) - return null; + return allVersions; + } - if (latest.Version.Version.InvariantStartsWith("v")) + /// + /// Based on all of the files that this package go retrieve all targeted Umbraco versions + /// + /// + /// + /// Order from latest package version and lastest min umb version and start from the top, we want to return the most recent + /// available package version for the current Umbraco version + /// + private IEnumerable GetAllStrictSupportedPackageVersions(IEnumerable packages) + { + var allVersions = packages + .Where(x => x.MinimumVersionStrict.IsNullOrWhiteSpace() == false) + .Select(x => new PackageVersionSupport(x.Id, ConvertToVersion(x.Version.Version), ConvertToVersion(x.MinimumVersionStrict))) + .Where(x => x.PackageVersion != null && x.MinUmbracoVersion != null) + .OrderByDescending(x => x.PackageVersion) + .ThenByDescending(x => x.MinUmbracoVersion) + .ToArray(); + return allVersions; + } + + /// + /// Based on all of the files that this package go retrieve all non targeted Umbraco versions + /// + /// + /// + /// Order from latest package version and start from the top, we want to return the most recent + /// available package version for the current Umbraco version + /// + private IEnumerable GetNonStrictSupportedPackageVersions(IEnumerable packages) + { + var allVersions = packages + .Where(x => x.MinimumVersionStrict.IsNullOrWhiteSpace()) + .Select(x => new PackageVersionSupport(x.Id, ConvertToVersion(x.Version.Version), null)) + .Where(x => x.PackageVersion != null) + .OrderByDescending(x => x.PackageVersion) + .ToArray(); + return allVersions; + } + + private class PackageVersionSupport : IEquatable + { + private readonly int _packageId; + + public PackageVersionSupport(int packageId, System.Version packageVersion, System.Version minUmbracoVersion) { - var legacyFormat = latest.Version.Version; + _packageId = packageId; + MinUmbracoVersion = minUmbracoVersion; + PackageVersion = packageVersion; + } - if (legacyFormat.InvariantStartsWith("v4")) + public int PackageId + { + get { return _packageId; } + } + + public System.Version MinUmbracoVersion { get; private set; } + public System.Version PackageVersion { get; private set; } + + public bool Equals(PackageVersionSupport other) + { + return _packageId == other._packageId; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is PackageVersionSupport && Equals((PackageVersionSupport) obj); + } + + public override int GetHashCode() + { + return _packageId; + } + + public static bool operator ==(PackageVersionSupport left, PackageVersionSupport right) + { + return left.Equals(right); + } + + public static bool operator !=(PackageVersionSupport left, PackageVersionSupport right) + { + return !left.Equals(right); + } + } + + /// + /// Try to convert the string to a real version based on legacy version formats + /// + /// + /// + private System.Version ConvertToVersion(string ver) + { + string normalized = ver; + if (ver.InvariantStartsWith("v")) + { + if (ver.InvariantStartsWith("v4")) { - return string.Concat(legacyFormat.Replace("v4", "4."), ".0"); + normalized = string.Concat(ver.Replace("v4", "4."), ".0"); } else { - return string.Join(".", legacyFormat.ToCharArray().Skip(1)); + normalized = string.Join(".", ver.ToCharArray().Skip(1)); } } - return latest.Version.Version; + if (normalized.EndsWith(".x")) + { + normalized = normalized.TrimEnd(".x").EnsureEndsWith(".0"); + } + + System.Version result; + if (System.Version.TryParse(normalized, out result)) + { + return result; + } + return null; } private PackageOwnerInfo GetPackageOwnerInfo(int ownerId, bool openForCollab, int contentId) diff --git a/OurUmbraco/Repository/webservices/repository.asmx.cs b/OurUmbraco/Repository/webservices/repository.asmx.cs index 44c22afe..ac40ff48 100644 --- a/OurUmbraco/Repository/webservices/repository.asmx.cs +++ b/OurUmbraco/Repository/webservices/repository.asmx.cs @@ -4,8 +4,11 @@ using System.ComponentModel; using System.IO; using System.Web.Services; using System.Xml.XPath; +using OurUmbraco.Repository.Services; using OurUmbraco.Wiki.BusinessLogic; using umbraco.cms.businesslogic.web; +using Umbraco.Core; +using Umbraco.Web; namespace OurUmbraco.Repository.webservices { @@ -76,12 +79,82 @@ namespace OurUmbraco.Repository.webservices } } + /// + /// This will return the byte array for the package file for the package id specified + /// + /// + /// The Version of the umbraco install requesting the package file, this is in the normaly version format such as 7.6.0 + /// + /// + /// This endpoint is new and is only referenced from 7.5.14 and above + /// + [WebMethod] + public byte[] GetPackageFile(string packageGuid, string umbracoVersion) + { + var umbHelper = new UmbracoHelper(UmbracoContext.Current); + var pckRepoService = new PackageRepositoryService(umbHelper, umbHelper.MembershipHelper, ApplicationContext.Current.DatabaseContext); + + System.Version currUmbracoVersion; + if (!System.Version.TryParse(umbracoVersion, out currUmbracoVersion)) + throw new InvalidOperationException("Could not parse the version specified " + umbracoVersion); + + var guid = new Guid(packageGuid); + var details = pckRepoService.GetDetails(guid, currUmbracoVersion); + if (details == null) + throw new InvalidOperationException("No package found with id " + packageGuid); + + if (details.ZipUrl.IsNullOrWhiteSpace()) + throw new InvalidOperationException("This package is not compatible with the Umbraco version " + umbracoVersion); + + var wf = new WikiFile(details.ZipFileId); + if (wf == null) + throw new InvalidOperationException("Could not find wiki file by id " + details.ZipFileId); + wf.UpdateDownloadCounter(true, true); + + return wf.ToByteArray(); + } + + /// + /// This will return the byte array for the package file for the package id specified - since this endpoint is ONLY used + /// for Umbraco installs that are less than 7.6.0 and only when legacy XML schema is enabled, we know that this is only used for old umbraco versions + /// + /// + /// [WebMethod] public byte[] fetchPackage(string packageGuid) { - return OurUmbraco.Repository.Packages.PackageFileByGuid(new Guid(packageGuid)).ToByteArray(); + var umbHelper = new UmbracoHelper(UmbracoContext.Current); + var pckRepoService = new PackageRepositoryService(umbHelper, umbHelper.MembershipHelper, ApplicationContext.Current.DatabaseContext); + + //This doesn't matter what we set it to so long as it's below 7.5 since that is the version we introduce strict dependencies + var currUmbracoVersion = new System.Version(4, 0, 0); + var guid = new Guid(packageGuid); + var details = pckRepoService.GetDetails(guid, currUmbracoVersion); + if (details == null) + throw new InvalidOperationException("No package found with id " + packageGuid); + + if (details.ZipUrl.IsNullOrWhiteSpace()) + throw new InvalidOperationException("This package is not compatible with your Umbraco version"); + + var wf = new WikiFile(details.ZipFileId); + if (wf == null) + throw new InvalidOperationException("Could not find wiki file by id " + details.ZipFileId); + wf.UpdateDownloadCounter(true, true); + + return wf.ToByteArray(); } + /// + /// This will return the byte array for the package file for the package id specified - since this endpoint is ONLY used + /// for Umbraco installs that are less than 7.6.0 and only when legacy XML schema is enabled, we know that this is only used for old umbraco versions + /// + /// + /// + /// This is a strange Umbraco version parameter - but it's not really an umbraco version, it's a special/odd version format like Version41 + /// + /// The repoVersion will never be null for for 7.5.x and this method will never be used by 7.6+ + /// + /// [WebMethod] public byte[] fetchPackageByVersion(string packageGuid, string repoVersion) { @@ -112,51 +185,59 @@ namespace OurUmbraco.Repository.webservices break; } - WikiFile wf = OurUmbraco.Repository.Packages.PackageFileByGuid(new Guid(packageGuid)); + var umbHelper = new UmbracoHelper(UmbracoContext.Current); + var pckRepoService = new PackageRepositoryService(umbHelper, umbHelper.MembershipHelper, ApplicationContext.Current.DatabaseContext); + //This doesn't matter what we set it to so long as it's below 7.5 since that is the version we introduce strict dependencies + //Side note: Umbraco 7.5.0 uses this endpoint but since 7.5.0 is already out there's nothing we can do about this, if we pass in 7.5.x then + // the logic will use strict file versions which we cannot do because this endpoint is also used for < 7.5! + // The worst that can happen in this case is that a strict package dependency has been made on 7.5 and then an umbraco 7.5 package + // requests the file, well it won't get it because this will only return non strict packages. + var currUmbracoVersion = new System.Version(4, 0, 0); + var guid = new Guid(packageGuid); + var details = pckRepoService.GetDetails(guid, currUmbracoVersion); + if (details == null) + return new byte[0]; - if (wf != null) + if (details.ZipUrl.IsNullOrWhiteSpace()) + throw new InvalidOperationException("This package is not compatible with the Umbraco version " + currUmbracoVersion); + + var wf = new WikiFile(details.ZipFileId); + + //WikiFile wf = OurUmbraco.Repository.Packages.PackageFileByGuid(new Guid(packageGuid)); + + //if the package doesn't care about the umbraco version needed... + if (wf.Version.Version == "nan") + return wf.ToByteArray(); + + //if v45 + if (version == "v45") { + int v = 0; + if (int.TryParse(wf.Version.Version.Replace("v", ""), out v)) + if (v >= 45) + return wf.ToByteArray(); - //if the package doesn't care about the umbraco version needed... - if (wf.Version.Version == "nan") + if (wf.Version.Version == "v47" || wf.Version.Version == "v45") return wf.ToByteArray(); - - //if v45 - if (version == "v45") + if (wf.Version.Version != version && wf.Version.Version != "nan") { - int v = 0; - if (int.TryParse(wf.Version.Version.Replace("v", ""), out v)) - if (v >= 45) - return wf.ToByteArray(); - - - if (wf.Version.Version == "v47" || wf.Version.Version == "v45") - return wf.ToByteArray(); - else if (wf.Version.Version != version && wf.Version.Version != "nan") - { - wf = WikiFile.FindPackageForUmbracoVersion(wf.NodeId, version); - return wf.ToByteArray(); - } + wf = WikiFile.FindPackageForUmbracoVersion(wf.NodeId, version); + return wf.ToByteArray(); } } - return new byte[0]; - - /* - if (wf.Version.Version != version && wf.Version.Version != "nan") - wf = uWiki.Businesslogic.WikiFile.FindPackageForUmbracoVersion(wf.NodeId, version); - - - if(wf != null) - return wf.ToByteArray(); - else - return new byte[0];*/ + return new byte[0]; } - + /// + /// SD: Pretty sure this is no longer used/needed it should probably be removed - maybe really old versions might try to use this? + /// + /// + /// + /// [WebMethod] public byte[] fetchProtectedPackage(string packageGuid, string memberKey) { @@ -225,24 +306,6 @@ namespace OurUmbraco.Repository.webservices return item; } - private static umbraco.cms.businesslogic.contentitem.ContentItem repositoryContentItem(string guid) - { - - umbraco.cms.businesslogic.contentitem.ContentItem item = new umbraco.cms.businesslogic.contentitem.ContentItem(1052); - - XPathNodeIterator xpn = umbraco.library.GetXmlNodeByXPath("descendant::node[data [@alias = 'repositoryGuid'] = '" + guid + "']"); - - if (xpn.MoveNext()) - { - - int id = int.Parse(xpn.Current.GetAttribute("id", "")); ; - - item = new umbraco.cms.businesslogic.contentitem.ContentItem(id); - } - - return item; - } - private static string md5(string input) { diff --git a/OurUmbraco/Wiki/BusinessLogic/WikiFile.cs b/OurUmbraco/Wiki/BusinessLogic/WikiFile.cs index 96c34be7..bab1628e 100644 --- a/OurUmbraco/Wiki/BusinessLogic/WikiFile.cs +++ b/OurUmbraco/Wiki/BusinessLogic/WikiFile.cs @@ -497,6 +497,9 @@ namespace OurUmbraco.Wiki.BusinessLogic byte[] packageByteArray; + if(File.Exists(path) == false) + throw new InvalidOperationException("The file " + path + " does not exist on the server"); + using (var fileStream = File.Open(path, FileMode.Open, FileAccess.Read)) { packageByteArray = new byte[fileStream.Length];