Compare commits
87 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
25f1047922 | ||
![]() |
34155919a6 | ||
![]() |
ca94b09e91 | ||
![]() |
ceed3c27d8 | ||
![]() |
65e23d5859 | ||
![]() |
e245dd5ce1 | ||
![]() |
14b13c026a | ||
![]() |
0169fa68ee | ||
![]() |
cf9c6040d3 | ||
![]() |
88e39407ef | ||
![]() |
3ef5499d94 | ||
![]() |
81503f4363 | ||
![]() |
f194614296 | ||
![]() |
76af70e21d | ||
![]() |
a70b51eee0 | ||
![]() |
d3249afaca | ||
![]() |
ee2e8c7a6d | ||
![]() |
f9cf0b7fef | ||
![]() |
21cf463c3b | ||
![]() |
838fb79411 | ||
![]() |
997a9cda0c | ||
![]() |
94d87ff0eb | ||
![]() |
be01a7dac4 | ||
![]() |
0c758b5492 | ||
![]() |
c5dcf58022 | ||
![]() |
5facde1aee | ||
![]() |
7e07f2771f | ||
![]() |
8bab0d66ef | ||
![]() |
5d28589afe | ||
![]() |
5e4518119f | ||
![]() |
3c13172dea | ||
![]() |
efb70627fb | ||
![]() |
b88fc651f8 | ||
![]() |
7b7b640e8d | ||
![]() |
9f5db40605 | ||
![]() |
8baf0ca550 | ||
![]() |
016cdc4489 | ||
![]() |
e4e0f657f6 | ||
![]() |
b301e04fe5 | ||
![]() |
a3294affd2 | ||
![]() |
0832e344d7 | ||
![]() |
50db6acf45 | ||
![]() |
3df91b51de | ||
![]() |
d5ac015c12 | ||
![]() |
07b11ecaab | ||
![]() |
9154ecdf67 | ||
![]() |
d621232812 | ||
![]() |
e7209d308b | ||
![]() |
e510b179f5 | ||
![]() |
134b5e83a0 | ||
![]() |
7f6672861b | ||
![]() |
f0aa1aebc8 | ||
![]() |
849a41df6c | ||
![]() |
4462746c43 | ||
![]() |
1ebc5a6f78 | ||
![]() |
5221c01ae3 | ||
![]() |
88e7378165 | ||
![]() |
80744b1633 | ||
![]() |
56315b92d1 | ||
![]() |
bf9651e332 | ||
![]() |
d721a0189b | ||
![]() |
75e5a5ee1c | ||
![]() |
bc27d3d673 | ||
![]() |
94c1e6b7b9 | ||
![]() |
0d23e58f03 | ||
![]() |
a5196b4940 | ||
![]() |
e209571315 | ||
![]() |
8a180b8b8f | ||
![]() |
3cc5c3b4c3 | ||
![]() |
acbf738327 | ||
![]() |
50e4e5635f | ||
![]() |
c648e5b2ae | ||
![]() |
35f941cf4e | ||
![]() |
d63703903c | ||
![]() |
ea68f07d81 | ||
![]() |
042d87c309 | ||
![]() |
55790a606f | ||
![]() |
e942437481 | ||
![]() |
7d95f1184d | ||
![]() |
32cd707bd0 | ||
![]() |
abdb83a9c3 | ||
![]() |
82daedee80 | ||
![]() |
add2e1c3b9 | ||
![]() |
6ee3b0d2eb | ||
![]() |
b1fb3900d9 | ||
![]() |
cef0022df3 | ||
![]() |
d1fa8d4daf |
18
.gitignore
vendored
@@ -96,7 +96,6 @@ publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.Publish.xml
|
||||
*.pubxml
|
||||
|
||||
# NuGet Packages Directory
|
||||
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
|
||||
@@ -165,7 +164,7 @@ build/
|
||||
/buildtasks
|
||||
/artifacts
|
||||
*.sln.cache
|
||||
src/Orchard.Web/Media/*
|
||||
#src/Orchard.Web/Media/*
|
||||
log.xml
|
||||
profiling/
|
||||
*.orig
|
||||
@@ -183,9 +182,14 @@ src/Orchard.Web/Orchard.Web.Publish.xml
|
||||
src/TestResults/*
|
||||
src/Orchard.Web/Properties/PublishProfiles
|
||||
src/Orchard.Azure/Orchard.Azure.CloudService/Staging/
|
||||
src/Orchard.Web/Modules/Orchard.Azure.MediaServices/node_modules
|
||||
src/Orchard.Web/Modules/Orchard.Layouts/node_modules
|
||||
src/Orchard.Web/Modules/Orchard.DynamicForms/node_modules
|
||||
node_modules/
|
||||
|
||||
#enable all /lib artifacts
|
||||
!lib/*/*.*
|
||||
# Enable all /lib artifacts
|
||||
!lib/*/*.*
|
||||
|
||||
# Enable version control of some IDeliverable specifics.
|
||||
src/Orchard.Web/Media/Default/RecipeJournal/*
|
||||
src/Orchard.Web/Media/Default/_Profiles/*
|
||||
|
||||
# Enable "IDeliverable/Packaging/" folder.
|
||||
!src/IDeliverable/Packaging/*/*.*
|
20
README.md
@@ -5,19 +5,15 @@ Orchard is a free, open source, community-focused Content Management System buil
|
||||
|
||||
#### Please visit our website at http://orchardproject.net for the most current information about this project.
|
||||
|
||||
Orchard is a free, open source, community-focused project aimed at delivering applications and reusable components
|
||||
on the ASP.NET platform. It will create shared components for building ASP.NET applications and extensions, and
|
||||
specific applications that leverage these components to meet the needs of end-users, scripters, and developers.
|
||||
Additionally, we seek to create partnerships with existing application authors to help them achieve their goals.
|
||||
Orchard is delivered under the [.NET Foundation](http://www.dotnetfoundation.org/). It is licensed under a
|
||||
[New BSD license](http://www.opensource.org/licenses/bsd-license.php), which is approved by the OSI. The intended
|
||||
output of the Orchard project is three-fold:
|
||||
Orchard is a free, open source, community-focused **Content Management System** built on the ASP.NET MVC platform.
|
||||
|
||||
* Individual .NET-based applications that appeal to end-users, scripters, and developers
|
||||
* A set of re-usable components that makes it easy to build such applications
|
||||
* A vibrant community to help define these applications and extensions
|
||||
In the near term, the Orchard project is focused on delivering a .NET-based CMS application that will allow users
|
||||
to rapidly create content-driven Websites, and an extensibility framework that will allow developers and customizers to provide additional functionality through modules and themes. You can learn more about the project on the [Orchard Project Website](http://www.orchardproject.net).
|
||||
Orchard is built on a modern architecture that puts extensibility up-front, as its number one concern. All components in Orchard can be replaced or extended. Content is built from easily composable building blocks. Modules extend the system in a very decoupled fashion, where a commenting module for example can as easily apply to pages, blog posts, photos or products. A rich UI composition system completes the picture and ensures that you can get the exact presentation that you need for your content.
|
||||
|
||||
Orchard is delivered under the [.NET Foundation](http://www.dotnetfoundation.org/orchard). It is licensed under a [New BSD license](http://www.opensource.org/licenses/bsd-license.php), which is approved by the OSI.
|
||||
|
||||
Our mission is to empower our users and foster a dedicated and diverse community that builds the CMS that we all want to use.
|
||||
|
||||
There are many ways you can [contribute to Orchard](http://orchardproject.net/contribution): you can [fix bugs](https://github.com/OrchardCMS/Orchard/issues), contribute modules and themes to [our gallery](http://gallery.orchardproject.net/), [write documentation](https://github.com/OrchardCMS/OrchardDoc), [translate Orchard](http://orchardproject.net/localize), or answer questions [on our forums](http://orchard.codeplex.com/discussions) and [on Stack Overflow](http://stackoverflow.com/questions/tagged/orchardcms).
|
||||
|
||||
## Project Status
|
||||
Orchard is currently in version 1.8.1. We invite participation by the developer community in shaping the project’s direction, so that we can publicly validate our designs and development approach.
|
||||
|
@@ -0,0 +1,90 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{F1467A6B-2397-447B-BE90-766D192EC3D9}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>IDeliverable.Licensing.Orchard</RootNamespace>
|
||||
<AssemblyName>IDeliverable.Licensing.Orchard</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Autofac, Version=3.5.0.0, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\lib\autofac\Autofac.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\..\..\lib\newtonsoft.json\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Web.Abstractions" />
|
||||
<Reference Include="System.Web.Http, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\lib\aspnetwebapi\System.Web.Http.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Mvc, Version=5.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\lib\aspnetmvc\System.Web.Mvc.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ILicensedProductManifest.cs" />
|
||||
<Compile Include="LicenseValidationControllerBase.cs" />
|
||||
<Compile Include="LicenseValidationErrorBannerBase.cs" />
|
||||
<Compile Include="LicenseValidationHelper.cs" />
|
||||
<Compile Include="LicenseVerificationTokenStore.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="LicenseSettingsPartHandlerBase.cs" />
|
||||
<Compile Include="LicenseSettingsPartBase.cs" />
|
||||
<Compile Include="LicenseSettingsPartDriverBase.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\IDeliverable.Licensing\IDeliverable.Licensing.csproj">
|
||||
<Project>{7e439cb7-1ace-435f-a8f3-5bb929423e34}</Project>
|
||||
<Name>IDeliverable.Licensing</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Orchard\Orchard.Framework.csproj">
|
||||
<Project>{2d1d92bb-4555-4cbe-8d0e-63563d6ce4c6}</Project>
|
||||
<Name>Orchard.Framework</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
@@ -0,0 +1,14 @@
|
||||
using Orchard;
|
||||
using Orchard.Logging;
|
||||
|
||||
namespace IDeliverable.Licensing.Orchard
|
||||
{
|
||||
public interface ILicensedProductManifest : IDependency
|
||||
{
|
||||
string ProductId { get; }
|
||||
string ProductName { get; }
|
||||
bool SkipValidationForLocalRequests { get; }
|
||||
string LicenseKey { get; }
|
||||
ILogger Logger { get; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
using Orchard.ContentManagement;
|
||||
|
||||
namespace IDeliverable.Licensing.Orchard
|
||||
{
|
||||
public abstract class LicenseSettingsPartBase : ContentPart
|
||||
{
|
||||
public string LicenseKey
|
||||
{
|
||||
get { return this.Retrieve(x => x.LicenseKey); }
|
||||
set { this.Store(x => x.LicenseKey, value); }
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
|
||||
namespace IDeliverable.Licensing.Orchard
|
||||
{
|
||||
public abstract class LicenseSettingsPartDriverBase<TPart> : ContentPartDriver<TPart> where TPart : LicenseSettingsPartBase, new()
|
||||
{
|
||||
protected abstract string EditorShapeName { get; }
|
||||
protected abstract string EditorShapeTemplateName { get; }
|
||||
|
||||
protected override DriverResult Editor(TPart part, dynamic shapeHelper)
|
||||
{
|
||||
return Editor(part, null, shapeHelper);
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(TPart part, IUpdateModel updater, dynamic shapeHelper)
|
||||
{
|
||||
return ContentShape(EditorShapeName, () =>
|
||||
{
|
||||
updater?.TryUpdateModel(part, Prefix, null, null);
|
||||
return shapeHelper.EditorTemplate(TemplateName: EditorShapeTemplateName, Prefix: Prefix, Model: part);
|
||||
}).OnGroup("Licenses");
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Localization;
|
||||
|
||||
namespace IDeliverable.Licensing.Orchard
|
||||
{
|
||||
public abstract class LicenseSettingsPartHandlerBase<TPart> : ContentHandler where TPart : LicenseSettingsPartBase, new()
|
||||
{
|
||||
protected LicenseSettingsPartHandlerBase()
|
||||
{
|
||||
Filters.Add(new ActivatingFilter<TPart>("Site"));
|
||||
OnGetContentItemMetadata<TPart>((context, part) => context.Metadata.EditorGroupInfo.Add(new GroupInfo(T("Licenses"))));
|
||||
}
|
||||
|
||||
public Localizer T { get; set; } = NullLocalizer.Instance;
|
||||
}
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
using System.Web.Mvc;
|
||||
using Orchard.Localization;
|
||||
using Orchard.UI.Notify;
|
||||
using Orchard.Utility.Extensions;
|
||||
|
||||
namespace IDeliverable.Licensing.Orchard
|
||||
{
|
||||
public abstract class LicenseValidationControllerBase : Controller
|
||||
{
|
||||
protected LicenseValidationControllerBase(INotifier notifier)
|
||||
{
|
||||
Notifier = notifier;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public Localizer T { get; set; }
|
||||
protected INotifier Notifier { get; }
|
||||
protected abstract string ProductId { get; }
|
||||
|
||||
public ActionResult VerifyLicenseKey()
|
||||
{
|
||||
LicenseValidationHelper.Instance.ClearLicenseValidationResult(ProductId);
|
||||
|
||||
if (LicenseValidationHelper.GetLicenseIsValid(ProductId))
|
||||
Notifier.Information(T("License key succesfully validated."));
|
||||
|
||||
var urlReferrer = Request.UrlReferrer?.ToString();
|
||||
return Redirect(Request.IsLocalUrl(urlReferrer) ? urlReferrer : "~/");
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,68 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using IDeliverable.Licensing.Validation;
|
||||
using Orchard;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Logging;
|
||||
using Orchard.UI.Admin.Notification;
|
||||
using Orchard.UI.Notify;
|
||||
|
||||
namespace IDeliverable.Licensing.Orchard
|
||||
{
|
||||
public abstract class LicenseValidationErrorBannerBase : Component, INotificationProvider
|
||||
{
|
||||
protected LicenseValidationErrorBannerBase(IEnumerable<ILicensedProductManifest> products, UrlHelper urlHelper, string productId)
|
||||
{
|
||||
mProducts = products;
|
||||
mUrlHelper = urlHelper;
|
||||
mProductId = productId;
|
||||
}
|
||||
|
||||
private readonly IEnumerable<ILicensedProductManifest> mProducts;
|
||||
private readonly UrlHelper mUrlHelper;
|
||||
private readonly string mProductId;
|
||||
|
||||
public IEnumerable<NotifyEntry> GetNotifications()
|
||||
{
|
||||
var productManifest = mProducts.Single(x => x.ProductId == mProductId);
|
||||
var licenseSettingsUrl = mUrlHelper.Action("Index", "Admin", new { area = "Settings", groupInfoId = "Licenses" });
|
||||
var refreshResultUrl = mUrlHelper.Action("VerifyLicenseKey", "LicenseValidation", new { area = productManifest.ProductName });
|
||||
var refreshResultLink = T("<a href=\"{0}\">Refresh</a>", refreshResultUrl);
|
||||
LocalizedString message = null;
|
||||
|
||||
try
|
||||
{
|
||||
LicenseValidationHelper.EnsureLicenseIsValid(productManifest.ProductId);
|
||||
}
|
||||
catch (LicenseValidationException ex)
|
||||
{
|
||||
switch (ex.Error)
|
||||
{
|
||||
case LicenseValidationError.UnknownLicenseKey:
|
||||
message = T("The <a href=\"{0}\">configured license key</a> for the {1} module is invalid. {2}", licenseSettingsUrl, productManifest.ProductName, refreshResultLink);
|
||||
break;
|
||||
case LicenseValidationError.HostnameMismatch:
|
||||
message = T("The <a href=\"{0}\">configured license key</a> for the {1} module is invalid for the current host name. {2}", licenseSettingsUrl, productManifest.ProductName, refreshResultLink);
|
||||
break;
|
||||
case LicenseValidationError.NoActiveSubscription:
|
||||
message = T("The <a href=\"{0}\">configured license key</a> for the {1} module has no active subscription. {2}", licenseSettingsUrl, productManifest.ProductName, refreshResultLink);
|
||||
break;
|
||||
case LicenseValidationError.TokenAgeValidationFailed:
|
||||
case LicenseValidationError.TokenSignatureValidationFailed:
|
||||
case LicenseValidationError.LicensingServiceError:
|
||||
case LicenseValidationError.LicensingServiceUnreachable:
|
||||
case LicenseValidationError.UnexpectedError:
|
||||
default:
|
||||
message = T("There was an error validating the <a href=\"{0}\">configured license key</a> for the {1} module. {2}", licenseSettingsUrl, productManifest.ProductName, refreshResultLink);
|
||||
break;
|
||||
}
|
||||
|
||||
Logger.Warning(ex, "An error occurred while validating the configured license key for the {0} module. {1}", productManifest.ProductName, refreshResultLink);
|
||||
}
|
||||
|
||||
if (message != null)
|
||||
yield return new NotifyEntry { Message = message, Type = NotifyType.Warning };
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using IDeliverable.Licensing.Validation;
|
||||
using IDeliverable.Licensing.VerificationTokens;
|
||||
using Orchard;
|
||||
using Orchard.Logging;
|
||||
using Orchard.FileSystems.AppData;
|
||||
|
||||
namespace IDeliverable.Licensing.Orchard
|
||||
{
|
||||
public class LicenseValidationHelper
|
||||
{
|
||||
public static bool GetLicenseIsValid(string productId)
|
||||
{
|
||||
try
|
||||
{
|
||||
EnsureLicenseIsValid(productId);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void EnsureLicenseIsValid(string productId)
|
||||
{
|
||||
Instance.ValidateLicense(productId);
|
||||
}
|
||||
|
||||
public static LicenseValidationHelper Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
var workContext = HttpContext.Current.Request.RequestContext.GetWorkContext();
|
||||
var products = workContext.Resolve<IEnumerable<ILicensedProductManifest>>();
|
||||
var appDataFolder = workContext.Resolve<IAppDataFolder>();
|
||||
var instance = new LicenseValidationHelper(products, appDataFolder);
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly TimeSpan _validationResultCachedFor = TimeSpan.FromMinutes(5);
|
||||
|
||||
public LicenseValidationHelper(IEnumerable<ILicensedProductManifest> products, IAppDataFolder appDataFolder)
|
||||
{
|
||||
var tokenStore = new LicenseVerificationTokenStore(appDataFolder);
|
||||
var tokenAccessor = new LicenseVerificationTokenAccessor(tokenStore);
|
||||
|
||||
mProducts = products;
|
||||
mLicenseValidator = new LicenseValidator(tokenAccessor);
|
||||
mCacheService = new CacheService();
|
||||
}
|
||||
|
||||
private readonly IEnumerable<ILicensedProductManifest> mProducts;
|
||||
private readonly LicenseValidator mLicenseValidator;
|
||||
private readonly CacheService mCacheService;
|
||||
|
||||
public void ValidateLicense(string productId)
|
||||
{
|
||||
var productManifest = GetLicensedProductManifest(productId);
|
||||
productManifest.Logger.Debug("Validating license for product '{0}'...", productId);
|
||||
|
||||
try
|
||||
{
|
||||
var cacheKey = ComputeCacheKey(productManifest);
|
||||
mCacheService.GetValue(cacheKey, context =>
|
||||
{
|
||||
context.ValidFor = _validationResultCachedFor;
|
||||
|
||||
var options = LicenseValidationOptions.Default;
|
||||
if (productManifest.SkipValidationForLocalRequests)
|
||||
options = options | LicenseValidationOptions.SkipForLocalRequests;
|
||||
|
||||
productManifest.Logger.Debug("Validation result not in cache. Invoking the license validator for product '{0}'...", productId);
|
||||
mLicenseValidator.ValidateLicense(productManifest.ProductId, productManifest.LicenseKey, options);
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
productManifest.Logger.Debug("License successfully validated for product '{0}'.", productId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
productManifest.Logger.Error(ex, "An error occurred while validating the license for product '{0}'.", productId);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearLicenseValidationResult(string productId)
|
||||
{
|
||||
var productManifest = GetLicensedProductManifest(productId);
|
||||
productManifest.Logger.Debug("Clearing license validation result for product '{0}'...", productId);
|
||||
|
||||
var cacheKey = ComputeCacheKey(productManifest);
|
||||
mCacheService.RemoveValue(cacheKey);
|
||||
}
|
||||
|
||||
private ILicensedProductManifest GetLicensedProductManifest(string productId)
|
||||
{
|
||||
return mProducts.Single(x => x.ProductId == productId);
|
||||
}
|
||||
|
||||
private string ComputeCacheKey(ILicensedProductManifest productManifest)
|
||||
{
|
||||
return $"ValidateLicenseResult-{productManifest.ProductId}-{productManifest.LicenseKey}-{productManifest.SkipValidationForLocalRequests}";
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
using IDeliverable.Licensing.VerificationTokens;
|
||||
using Orchard.FileSystems.AppData;
|
||||
|
||||
namespace IDeliverable.Licensing.Orchard
|
||||
{
|
||||
internal class LicenseVerificationTokenStore : ILicenseVerificationTokenStore
|
||||
{
|
||||
public LicenseVerificationTokenStore(IAppDataFolder appDataFolder)
|
||||
{
|
||||
mAppDataFolder = appDataFolder;
|
||||
}
|
||||
|
||||
private readonly IAppDataFolder mAppDataFolder;
|
||||
|
||||
public LicenseVerificationToken Load(string productId)
|
||||
{
|
||||
var path = GetRelativeTokenFilePath(productId);
|
||||
if (!mAppDataFolder.FileExists(path))
|
||||
return null;
|
||||
|
||||
var tokenBase64 = mAppDataFolder.ReadFile(path);
|
||||
var token = LicenseVerificationToken.FromBase64(tokenBase64);
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
public void Save(string productId, LicenseVerificationToken token)
|
||||
{
|
||||
Clear(productId);
|
||||
|
||||
var path = GetRelativeTokenFilePath(productId);
|
||||
|
||||
var tokenBase64 = token.ToBase64();
|
||||
mAppDataFolder.CreateFile(path, tokenBase64);
|
||||
}
|
||||
|
||||
public void Clear(string productId)
|
||||
{
|
||||
var path = GetRelativeTokenFilePath(productId);
|
||||
if (mAppDataFolder.FileExists(path))
|
||||
mAppDataFolder.DeleteFile(path);
|
||||
}
|
||||
|
||||
private string GetRelativeTokenFilePath(string productId)
|
||||
{
|
||||
return $"IDeliverable.Licensing/{productId}.lic";
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("IDeliverable.Licensing.Orchard.Orchard")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("IDeliverable.Licensing.Orchard.Orchard")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("f1467a6b-2397-447b-be90-766d192ec3d9")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http.Controllers;
|
||||
using System.Web.Http.Filters;
|
||||
|
||||
namespace IDeliverable.Licensing.Service
|
||||
{
|
||||
internal class ApiKeyAuthorizationAttribute : AuthorizationFilterAttribute
|
||||
{
|
||||
public override void OnAuthorization(HttpActionContext actionContext)
|
||||
{
|
||||
var values = new List<string>();
|
||||
|
||||
var paramsQuery =
|
||||
from param in actionContext.Request.GetQueryNameValuePairs()
|
||||
where String.Equals(param.Key, "ApiKey", StringComparison.OrdinalIgnoreCase)
|
||||
select param.Value;
|
||||
values.AddRange(paramsQuery.ToArray());
|
||||
|
||||
IEnumerable<string> headers;
|
||||
actionContext.Request.Headers.TryGetValues("ApiKey", out headers);
|
||||
if (headers != null)
|
||||
values.AddRange(headers);
|
||||
|
||||
string apiKey = values != null ? values.FirstOrDefault() : null;
|
||||
|
||||
if (String.IsNullOrWhiteSpace(apiKey))
|
||||
actionContext.Response = actionContext.ControllerContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
|
||||
|
||||
var expectedApiKey = ConfigurationManager.AppSettings["ApiKey"];
|
||||
|
||||
if (apiKey != expectedApiKey)
|
||||
actionContext.Response = actionContext.ControllerContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
using System.Web.Http;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace IDeliverable.Licensing.Service
|
||||
{
|
||||
internal static class WebApiConfig
|
||||
{
|
||||
public static void Register(HttpConfiguration config)
|
||||
{
|
||||
ConfigSerializationSettings(config);
|
||||
|
||||
config.MapHttpAttributeRoutes();
|
||||
config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
|
||||
}
|
||||
|
||||
private static void ConfigSerializationSettings(HttpConfiguration config)
|
||||
{
|
||||
var jsonSetting = new JsonSerializerSettings();
|
||||
jsonSetting.Converters.Add(new StringEnumConverter());
|
||||
config.Formatters.JsonFormatter.SerializerSettings = jsonSetting;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ApplicationInsights xmlns="http://schemas.microsoft.com/ApplicationInsights/2013/Settings">
|
||||
<!--
|
||||
Learn more about Application Insights configuration with ApplicationInsights.config here:
|
||||
http://go.microsoft.com/fwlink/?LinkID=513840
|
||||
|
||||
Note: If not present, please add <InstrumentationKey>Your Key</InstrumentationKey> to the top of this file.
|
||||
-->
|
||||
<TelemetryModules>
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Implementation.Tracing.DiagnosticsTelemetryModule, Microsoft.ApplicationInsights" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.PerfCollector.PerformanceCollectorModule, Microsoft.ApplicationInsights.Extensibility.PerfCollector">
|
||||
<!--
|
||||
Use the following syntax here to collect additional performance counters:
|
||||
|
||||
<Counters>
|
||||
<Add PerformanceCounter="\Process(??APP_WIN32_PROC??)\Handle Count" ReportAs="Process handle count" />
|
||||
...
|
||||
</Counters>
|
||||
|
||||
PerformanceCounter must be either \CategoryName(InstanceName)\CounterName or \CategoryName\CounterName
|
||||
|
||||
Counter names may only contain letters, round brackets, forward slashes, hyphens, underscores, spaces and dots.
|
||||
You may provide an optional ReportAs attribute which will be used as the metric name when reporting counter data.
|
||||
For the purposes of reporting, metric names will be sanitized by removing all invalid characters from the resulting metric name.
|
||||
|
||||
The following placeholders are supported as InstanceName:
|
||||
??APP_WIN32_PROC?? - instance name of the application process for Win32 counters.
|
||||
??APP_W3SVC_PROC?? - instance name of the application IIS worker process for IIS/ASP.NET counters.
|
||||
??APP_CLR_PROC?? - instance name of the application CLR process for .NET counters.
|
||||
-->
|
||||
</Add>
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.RuntimeTelemetry.RemoteDependencyModule, Microsoft.ApplicationInsights.Extensibility.RuntimeTelemetry" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryModules.WebApplicationLifecycleModule, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryModules.WebRequestTrackingTelemetryModule, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryModules.WebExceptionTrackingTelemetryModule, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryModules.WebSessionTrackingTelemetryModule, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryModules.WebUserTrackingTelemetryModule, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
</TelemetryModules>
|
||||
<TelemetryChannel Type="Microsoft.ApplicationInsights.Channel.PersistenceChannel, Microsoft.ApplicationInsights.PersistenceChannel" />
|
||||
<ContextInitializers>
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.BuildInfoConfigComponentVersionContextInitializer, Microsoft.ApplicationInsights" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.DeviceContextInitializer, Microsoft.ApplicationInsights" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.ContextInitializers.AzureRoleEnvironmentContextInitializer, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.ContextInitializers.DomainNameRoleInstanceContextInitializer, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
</ContextInitializers>
|
||||
<TelemetryInitializers>
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryInitializers.WebSyntheticTelemetryInitializer, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryInitializers.WebClientIpHeaderTelemetryInitializer, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryInitializers.WebUserAgentTelemetryInitializer, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryInitializers.WebOperationNameTelemetryInitializer, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryInitializers.WebOperationIdTelemetryInitializer, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryInitializers.WebUserTelemetryInitializer, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Web.TelemetryInitializers.WebSessionTelemetryInitializer, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
</TelemetryInitializers>
|
||||
<!-- This key is for Application Insights resource 'ideliverable-licensing' in resource group 'Internal' -->
|
||||
<InstrumentationKey>4af2a280-2e97-489d-be03-52ed20a87ae4</InstrumentationKey>
|
||||
</ApplicationInsights>
|
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http;
|
||||
using IDeliverable.Licensing.Service.Exceptions;
|
||||
using IDeliverable.Licensing.Service.Services;
|
||||
using IDeliverable.Licensing.VerificationTokens;
|
||||
|
||||
namespace IDeliverable.Licensing.Service.Controllers
|
||||
{
|
||||
[RoutePrefix("api/v1")]
|
||||
public class LicenseController : ApiController
|
||||
{
|
||||
[HttpGet]
|
||||
[Route("license/{licenseKey}/verify")]
|
||||
[ApiKeyAuthorization]
|
||||
public LicenseVerificationToken Verify(string licenseKey, int productId, string hostname)
|
||||
{
|
||||
var sendOwlApiEndpoint = ConfigurationManager.AppSettings["SendOwlApiEndpoint"];
|
||||
var sendOwlApiKey = ConfigurationManager.AppSettings["SendOwlApiKey"];
|
||||
var sendOwlApiSecret = ConfigurationManager.AppSettings["SendOwlApiSecret"];
|
||||
var tokenSigningCertificateThumbprint = ConfigurationManager.AppSettings["TokenSigningCertificateThumbprint"];
|
||||
|
||||
var service = new LicenseService(sendOwlApiEndpoint, sendOwlApiKey, sendOwlApiSecret, tokenSigningCertificateThumbprint);
|
||||
|
||||
try
|
||||
{
|
||||
return service.VerifyLicense(licenseKey, productId, hostname);
|
||||
}
|
||||
catch (LicenseVerificationException ex)
|
||||
{
|
||||
switch (ex.Error)
|
||||
{
|
||||
case LicenseVerificationError.UnknownLicenseKey:
|
||||
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound) { ReasonPhrase = ex.Message });
|
||||
|
||||
case LicenseVerificationError.HostnameMismatch:
|
||||
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.Forbidden) { ReasonPhrase = ex.Message });
|
||||
|
||||
case LicenseVerificationError.NoActiveSubscription:
|
||||
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.Gone) { ReasonPhrase = ex.Message });
|
||||
|
||||
default:
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("test")]
|
||||
[ApiKeyAuthorization]
|
||||
public HttpResponseMessage Test()
|
||||
{
|
||||
var testProductId = ConfigurationManager.AppSettings["TestProductId"];
|
||||
var testHostname = ConfigurationManager.AppSettings["TestHostname"];
|
||||
var testKey = ConfigurationManager.AppSettings["TestKey"];
|
||||
|
||||
try
|
||||
{
|
||||
var token = Verify(testKey, Int32.Parse(testProductId), testHostname);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new HttpResponseMessage(HttpStatusCode.InternalServerError) { ReasonPhrase = $"Verification for a supposedly valid license failed: {ex.Message}." };
|
||||
}
|
||||
|
||||
return new HttpResponseMessage(HttpStatusCode.OK);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
namespace IDeliverable.Licensing.Service.Exceptions
|
||||
{
|
||||
internal enum LicenseVerificationError
|
||||
{
|
||||
UnknownLicenseKey,
|
||||
NoActiveSubscription,
|
||||
HostnameMismatch,
|
||||
UnhandledException
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
|
||||
namespace IDeliverable.Licensing.Service.Exceptions
|
||||
{
|
||||
internal class LicenseVerificationException : Exception
|
||||
{
|
||||
public LicenseVerificationException(LicenseVerificationError error)
|
||||
:this("An error occurred while verifying the license.", error)
|
||||
{
|
||||
}
|
||||
|
||||
public LicenseVerificationException(string message, LicenseVerificationError error) : base(message)
|
||||
{
|
||||
Error = error;
|
||||
}
|
||||
|
||||
public LicenseVerificationException(LicenseVerificationError error, Exception innerException)
|
||||
: this("An error occurred while verifying the license.", error, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
public LicenseVerificationException(string message, LicenseVerificationError error, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
Error = error;
|
||||
}
|
||||
|
||||
public LicenseVerificationError Error { get; private set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1 @@
|
||||
<%@ Application Codebehind="Global.asax.cs" Inherits="IDeliverable.Licensing.Service.WebApiApplication" Language="C#" %>
|
@@ -0,0 +1,14 @@
|
||||
using System.Web.Http;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
|
||||
namespace IDeliverable.Licensing.Service
|
||||
{
|
||||
public class WebApiApplication : System.Web.HttpApplication
|
||||
{
|
||||
protected void Application_Start()
|
||||
{
|
||||
GlobalConfiguration.Configure(WebApiConfig.Register);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,235 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>
|
||||
</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{6014E7AC-C979-4D50-B8D9-5FD9DC8CA641}</ProjectGuid>
|
||||
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>IDeliverable.Licensing.Service</RootNamespace>
|
||||
<AssemblyName>IDeliverable.Licensing.Service</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<MvcBuildViews>false</MvcBuildViews>
|
||||
<UseIISExpress>true</UseIISExpress>
|
||||
<IISExpressSSLPort />
|
||||
<IISExpressAnonymousAuthentication />
|
||||
<IISExpressWindowsAuthentication />
|
||||
<IISExpressUseClassicPipelineMode />
|
||||
<UseGlobalApplicationHostFile>true</UseGlobalApplicationHostFile>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
<ApplicationInsightsResourceId>/subscriptions/1788357e-d506-4118-9f88-092c1dcddc16/resourcegroups/Internal/providers/microsoft.insights/components/ideliverable-licensing</ApplicationInsightsResourceId>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.ApplicationInsights, Version=0.14.3.177, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.ApplicationInsights.0.14.3-build00177\lib\net40\Microsoft.ApplicationInsights.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.ApplicationInsights.Extensibility.PerfCollector, Version=0.14.3.185, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.ApplicationInsights.PerformanceCollector.0.14.3-build00177\lib\net40\Microsoft.ApplicationInsights.Extensibility.PerfCollector.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.ApplicationInsights.Extensibility.RuntimeTelemetry, Version=0.14.3.177, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.ApplicationInsights.RuntimeTelemetry.0.14.3-build00177\lib\net45\Microsoft.ApplicationInsights.Extensibility.RuntimeTelemetry.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.ApplicationInsights.Extensibility.Web, Version=0.14.3.177, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.ApplicationInsights.Web.0.14.3-build00177\lib\net45\Microsoft.ApplicationInsights.Extensibility.Web.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.ApplicationInsights.PersistenceChannel, Version=0.14.3.186, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.ApplicationInsights.PersistenceChannel.0.14.3-build00177\lib\net40\Microsoft.ApplicationInsights.PersistenceChannel.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="Microsoft.Diagnostics.Instrumentation.Extensions.Intercept, Version=0.14.0.8007, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.ApplicationInsights.Agent.Intercept.0.14.0-build08008\lib\net40\Microsoft.Diagnostics.Instrumentation.Extensions.Intercept.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Diagnostics.Tracing.EventSource, Version=1.1.16.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Diagnostics.Tracing.EventSource.Redist.1.1.16-beta\lib\net45\Microsoft.Diagnostics.Tracing.EventSource.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Threading.Tasks, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Threading.Tasks.Extensions, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop, Version=1.0.168.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Web.Infrastructure">
|
||||
<HintPath>..\..\..\lib\aspnetmvc\Microsoft.Web.Infrastructure.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\..\..\lib\newtonsoft.json\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Net" />
|
||||
<Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Entity" />
|
||||
<Reference Include="System.Web.ApplicationServices" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Web.Helpers">
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Http.WebHost, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.3\lib\net45\System.Web.Http.WebHost.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Mvc, Version=4.0.0.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Razor">
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.WebPages">
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.WebPages.Deployment">
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.WebPages.Razor">
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Web.Abstractions" />
|
||||
<Reference Include="System.Web.Routing" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.Net.Http">
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http.WebRequest">
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<Compile Include="App_Start\WebApiConfig.cs" />
|
||||
<Compile Include="ApiKeyAuthorizationAttribute.cs" />
|
||||
<Compile Include="Controllers\LicenseController.cs" />
|
||||
<Compile Include="Exceptions\LicenseVerificationError.cs" />
|
||||
<Compile Include="Global.asax.cs">
|
||||
<DependentUpon>Global.asax</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Services\LicenseInfo.cs" />
|
||||
<Compile Include="Services\LicenseService.cs" />
|
||||
<Compile Include="Exceptions\LicenseVerificationException.cs" />
|
||||
<Compile Include="Services\OrderInfo.cs" />
|
||||
<Compile Include="Services\OrderStatus.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Global.asax" />
|
||||
<Content Include="packages.config" />
|
||||
<Content Include="ApplicationInsights.config" />
|
||||
<None Include="Properties\PublishProfiles\ideliverable-licensing.pubxml" />
|
||||
<Content Include="Web.config">
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
<Content Include="Web.Debug.config">
|
||||
<DependentUpon>Web.config</DependentUpon>
|
||||
</Content>
|
||||
<Content Include="Web.Release.config">
|
||||
<DependentUpon>Web.config</DependentUpon>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\IDeliverable.Licensing\IDeliverable.Licensing.csproj">
|
||||
<Project>{7e439cb7-1ace-435f-a8f3-5bb929423e34}</Project>
|
||||
<Name>IDeliverable.Licensing</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
|
||||
<Target Name="MvcBuildViews" AfterTargets="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
|
||||
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" />
|
||||
</Target>
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
|
||||
<WebProjectProperties>
|
||||
<UseIIS>True</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>56979</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:56979/</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
</CustomServerUrl>
|
||||
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
|
||||
</WebProjectProperties>
|
||||
</FlavorProperties>
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<Import Project="..\..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" />
|
||||
<Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
|
||||
<Error Condition="Exists('..\..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
|
||||
</Target>
|
||||
<Import Project="..\..\packages\Microsoft.Diagnostics.Tracing.EventSource.Redist.1.1.16-beta\build\portable-net45+win8+wpa81\Microsoft.Diagnostics.Tracing.EventSource.Redist.targets" Condition="Exists('..\..\packages\Microsoft.Diagnostics.Tracing.EventSource.Redist.1.1.16-beta\build\portable-net45+win8+wpa81\Microsoft.Diagnostics.Tracing.EventSource.Redist.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.Diagnostics.Tracing.EventSource.Redist.1.1.16-beta\build\portable-net45+win8+wpa81\Microsoft.Diagnostics.Tracing.EventSource.Redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Diagnostics.Tracing.EventSource.Redist.1.1.16-beta\build\portable-net45+win8+wpa81\Microsoft.Diagnostics.Tracing.EventSource.Redist.targets'))" />
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.ApplicationInsights.Agent.Intercept.0.14.0-build08008\build\Microsoft.ApplicationInsights.Agent.Intercept.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.ApplicationInsights.Agent.Intercept.0.14.0-build08008\build\Microsoft.ApplicationInsights.Agent.Intercept.targets'))" />
|
||||
</Target>
|
||||
<Import Project="..\..\packages\Microsoft.ApplicationInsights.0.14.3-build00177\tools\net40\Microsoft.ApplicationInsights.targets" Condition="Exists('..\..\packages\Microsoft.ApplicationInsights.0.14.3-build00177\tools\net40\Microsoft.ApplicationInsights.targets')" />
|
||||
<Target Name="EnsureApplicationInsightsImported" BeforeTargets="BeforeBuild" Condition="'$(ApplicationInsightsImported)' == ''">
|
||||
<Error Condition="!Exists('..\..\packages\Microsoft.ApplicationInsights.0.14.3-build00177\tools\net40\Microsoft.ApplicationInsights.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." />
|
||||
<Error Condition="Exists('..\..\packages\Microsoft.ApplicationInsights.0.14.3-build00177\tools\net40\Microsoft.ApplicationInsights.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." />
|
||||
</Target>
|
||||
<Import Project="..\..\packages\Microsoft.ApplicationInsights.Agent.Intercept.0.14.0-build08008\build\Microsoft.ApplicationInsights.Agent.Intercept.targets" Condition="Exists('..\..\packages\Microsoft.ApplicationInsights.Agent.Intercept.0.14.0-build08008\build\Microsoft.ApplicationInsights.Agent.Intercept.targets')" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target> -->
|
||||
</Project>
|
@@ -0,0 +1,35 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("IDeliverable.Licensing.Service")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("IDeliverable.Licensing.Service")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("c2a67b6c-4615-4ecf-bfc6-39bf0f975c1f")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
@@ -0,0 +1,14 @@
|
||||
namespace IDeliverable.Licensing.Service.Services
|
||||
{
|
||||
internal class LicenseInfo
|
||||
{
|
||||
public LicenseInfo(string key, int orderId)
|
||||
{
|
||||
Key = key;
|
||||
OrderId = orderId;
|
||||
}
|
||||
|
||||
public string Key { get; }
|
||||
public int OrderId { get; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,152 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using IDeliverable.Licensing.Service.Exceptions;
|
||||
using IDeliverable.Licensing.VerificationTokens;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace IDeliverable.Licensing.Service.Services
|
||||
{
|
||||
internal class LicenseService
|
||||
{
|
||||
public LicenseService(string sendOwlApiEndpoint, string sendOwlApiKey, string sendOwlApiSecret, string tokenSigningCertificateThumbprint)
|
||||
{
|
||||
mSendOwlApiEndpoint = sendOwlApiEndpoint;
|
||||
mSendOwlApiKey = sendOwlApiKey;
|
||||
mSendOwlApiSecret = sendOwlApiSecret;
|
||||
mTokenSigningCertificateThumbprint = tokenSigningCertificateThumbprint;
|
||||
}
|
||||
|
||||
private readonly string mSendOwlApiEndpoint;
|
||||
private readonly string mSendOwlApiKey;
|
||||
private readonly string mSendOwlApiSecret;
|
||||
private readonly string mTokenSigningCertificateThumbprint;
|
||||
|
||||
public LicenseVerificationToken VerifyLicense(string licenseKey, int productId, string hostname)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
client.BaseAddress = new Uri(mSendOwlApiEndpoint);
|
||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", CreateBasicAuthenticationToken(mSendOwlApiKey, mSendOwlApiSecret));
|
||||
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
|
||||
var licenses = ParseLicenseInfo(client.GetAsync($"products/{productId}/licenses/check_valid?key={licenseKey}").Result.Content.ReadAsStringAsync().Result).ToList();
|
||||
|
||||
if (!licenses.Any())
|
||||
throw new LicenseVerificationException($"No license with key '{licenseKey}' was found.", LicenseVerificationError.UnknownLicenseKey);
|
||||
|
||||
var orderId = licenses.First(x => x.Key == licenseKey).OrderId;
|
||||
var order = ParseOrderInfo(client.GetAsync($"orders/{orderId}").Result.Content.ReadAsStringAsync().Result);
|
||||
|
||||
if (!order.IsProductAccessAllowed)
|
||||
throw new LicenseVerificationException($"The license with key '{licenseKey}' is not associated with an active subscription.", LicenseVerificationError.NoActiveSubscription);
|
||||
|
||||
if (!order.Hostnames.Contains(hostname, StringComparer.OrdinalIgnoreCase))
|
||||
throw new LicenseVerificationException($"The license with key '{licenseKey}' is not valid for the provided '{hostname}'. Valid hostnames are '{String.Join(",", order.Hostnames)}", LicenseVerificationError.HostnameMismatch);
|
||||
|
||||
var token = CreateVerificationToken(productId, hostname, licenseKey);
|
||||
|
||||
return token;
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (!(ex is LicenseVerificationException))
|
||||
{
|
||||
throw new LicenseVerificationException(LicenseVerificationError.UnhandledException, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private LicenseVerificationToken CreateVerificationToken(int productId, string hostname, string key)
|
||||
{
|
||||
X509Certificate2 signingCert = null;
|
||||
|
||||
// Try to find the certificate in either the CurrentUser or LocalMachine stores
|
||||
// to maximize code portability.
|
||||
signingCert = GetSigningCertificateFrom(StoreLocation.CurrentUser) ?? GetSigningCertificateFrom(StoreLocation.LocalMachine);
|
||||
if (signingCert == null)
|
||||
throw new Exception($"No certificate with thumbprint '{mTokenSigningCertificateThumbprint}' was found in the certificate store.");
|
||||
|
||||
var info = new LicenseVerificationInfo(productId, hostname, key, DateTime.UtcNow.Ticks);
|
||||
var token = LicenseVerificationToken.Create(info, signingCert);
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
private X509Certificate2 GetSigningCertificateFrom(StoreLocation location)
|
||||
{
|
||||
var store = new X509Store(StoreName.My, location);
|
||||
store.Open(OpenFlags.ReadOnly);
|
||||
|
||||
try
|
||||
{
|
||||
var certificates = store.Certificates.Find(X509FindType.FindByThumbprint, mTokenSigningCertificateThumbprint, validOnly: false);
|
||||
return certificates.Count > 0 ? certificates[0] : null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
store.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private static string CreateBasicAuthenticationToken(string userName, string password)
|
||||
{
|
||||
return Convert.ToBase64String(Encoding.UTF8.GetBytes($"{userName}:{password}"), Base64FormattingOptions.None);
|
||||
}
|
||||
|
||||
private static IEnumerable<LicenseInfo> ParseLicenseInfo(string json)
|
||||
{
|
||||
var licensesQuery =
|
||||
from node in JArray.Parse(json)
|
||||
select new LicenseInfo((string)node["license"]["key"], (int)node["license"]["order_id"]);
|
||||
|
||||
return licensesQuery.ToArray();
|
||||
}
|
||||
|
||||
private OrderInfo ParseOrderInfo(string json)
|
||||
{
|
||||
var order = JObject.Parse(json)["order"];
|
||||
var status = ReadOrderStatus(order);
|
||||
var isAccessAllowed = (bool) order["access_allowed"];
|
||||
var customFields = (JArray)order["order_custom_checkout_fields"];
|
||||
var hostnames = new List<string>();
|
||||
|
||||
if (customFields.Count > 0)
|
||||
hostnames.Add((string)customFields[0]["order_custom_checkout_field"]["value"]);
|
||||
|
||||
if (customFields.Count > 1)
|
||||
hostnames.Add((string)customFields[1]["order_custom_checkout_field"]["value"]);
|
||||
|
||||
return new OrderInfo((int)order["id"], status, isAccessAllowed, hostnames);
|
||||
}
|
||||
|
||||
private static OrderStatus ReadOrderStatus(JToken order)
|
||||
{
|
||||
var dictionary = new Dictionary<string, OrderStatus>
|
||||
{
|
||||
{"initial", OrderStatus.Initial },
|
||||
{"payment_started", OrderStatus.PaymentStarted },
|
||||
{"payment_pending", OrderStatus.PaymentPending },
|
||||
{"failed", OrderStatus.Failed },
|
||||
{"complete", OrderStatus.Complete },
|
||||
{"chargeback", OrderStatus.Chargeback },
|
||||
{"refunded", OrderStatus.Refunded },
|
||||
{"in_dispute", OrderStatus.InDispute },
|
||||
{"free", OrderStatus.Free },
|
||||
{"imported", OrderStatus.Imported },
|
||||
{"fraud_review", OrderStatus.FraudReview },
|
||||
{"subscription_setup", OrderStatus.SubscriptionSetup },
|
||||
{"subscription_active", OrderStatus.SubscriptionActive },
|
||||
{"subscription_complete", OrderStatus.SubscriptionComplete },
|
||||
{"subscription_cancelled", OrderStatus.SubscriptionCancelled }
|
||||
};
|
||||
var status = (string) order["state"];
|
||||
|
||||
return dictionary.ContainsKey(status) ? dictionary[status] : OrderStatus.Unknown;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace IDeliverable.Licensing.Service.Services
|
||||
{
|
||||
internal class OrderInfo
|
||||
{
|
||||
public OrderInfo(int orderId, OrderStatus status, bool isProductAccessAllowed, IEnumerable<string> hostnames)
|
||||
{
|
||||
OrderId = orderId;
|
||||
Hostnames = hostnames;
|
||||
Status = status;
|
||||
IsProductAccessAllowed = isProductAccessAllowed;
|
||||
}
|
||||
|
||||
public int OrderId { get; }
|
||||
public IEnumerable<string> Hostnames { get; }
|
||||
public OrderStatus Status { get; }
|
||||
public bool IsProductAccessAllowed { get; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
namespace IDeliverable.Licensing.Service.Services {
|
||||
internal enum OrderStatus
|
||||
{
|
||||
Unknown,
|
||||
Initial,
|
||||
PaymentStarted,
|
||||
PaymentPending,
|
||||
Failed,
|
||||
Complete,
|
||||
Chargeback,
|
||||
Refunded,
|
||||
InDispute,
|
||||
Free,
|
||||
Imported,
|
||||
FraudReview,
|
||||
SubscriptionSetup,
|
||||
SubscriptionActive,
|
||||
SubscriptionComplete,
|
||||
SubscriptionCancelled,
|
||||
}
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!-- For more information on using Web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=301874 -->
|
||||
|
||||
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
|
||||
<!--
|
||||
In the example below, the "SetAttributes" transform will change the value of
|
||||
"connectionString" to use "ReleaseSQLServer" only when the "Match" locator
|
||||
finds an attribute "name" that has a value of "MyDB".
|
||||
|
||||
<connectionStrings>
|
||||
<add name="MyDB"
|
||||
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
|
||||
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
|
||||
</connectionStrings>
|
||||
-->
|
||||
<system.web>
|
||||
<!--
|
||||
In the example below, the "Replace" transform will replace the entire
|
||||
<customErrors> section of your Web.config file.
|
||||
Note that because there is only one customErrors section under the
|
||||
<system.web> node, there is no need to use the "xdt:Locator" attribute.
|
||||
|
||||
<customErrors defaultRedirect="GenericError.htm"
|
||||
mode="RemoteOnly" xdt:Transform="Replace">
|
||||
<error statusCode="500" redirect="InternalError.htm"/>
|
||||
</customErrors>
|
||||
-->
|
||||
</system.web>
|
||||
</configuration>
|
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!-- For more information on using Web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=301874 -->
|
||||
|
||||
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
|
||||
<!--
|
||||
In the example below, the "SetAttributes" transform will change the value of
|
||||
"connectionString" to use "ReleaseSQLServer" only when the "Match" locator
|
||||
finds an attribute "name" that has a value of "MyDB".
|
||||
|
||||
<connectionStrings>
|
||||
<add name="MyDB"
|
||||
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
|
||||
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
|
||||
</connectionStrings>
|
||||
-->
|
||||
<system.web>
|
||||
<compilation xdt:Transform="RemoveAttributes(debug)" />
|
||||
<!--
|
||||
In the example below, the "Replace" transform will replace the entire
|
||||
<customErrors> section of your Web.config file.
|
||||
Note that because there is only one customErrors section under the
|
||||
<system.web> node, there is no need to use the "xdt:Locator" attribute.
|
||||
|
||||
<customErrors defaultRedirect="GenericError.htm"
|
||||
mode="RemoteOnly" xdt:Transform="Replace">
|
||||
<error statusCode="500" redirect="InternalError.htm"/>
|
||||
</customErrors>
|
||||
-->
|
||||
</system.web>
|
||||
</configuration>
|
51
src/IDeliverable/IDeliverable.Licensing.Service/Web.config
Normal file
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
|
||||
<appSettings>
|
||||
<!-- Below three settings can be overridden through the Azure portal. -->
|
||||
<add key="ApiKey" value="MJb17j7YAzSjyEYkhsoI" />
|
||||
<add key="TestProductId" value="233554" />
|
||||
<add key="TestHostname" value="ideliverable.com" />
|
||||
<add key="TestKey" value="ADB5-2D53-0A62-4C2F" />
|
||||
<add key="SendOwlApiEndpoint" value="https://www.sendowl.com/api/v1/" />
|
||||
<add key="SendOwlApiKey" value="14be9ee5e05222e" />
|
||||
<add key="SendOwlApiSecret" value="1a10fe7987724e0a56a1" />
|
||||
<add key="TokenSigningCertificateThumbprint" value="fa4746a778716109e7e80e1b8dc2ed2a2ba3b852" />
|
||||
</appSettings>
|
||||
|
||||
<system.web>
|
||||
<compilation debug="true" targetFramework="4.5.2" />
|
||||
<httpRuntime targetFramework="4.5.2" />
|
||||
<httpModules>
|
||||
<add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Extensibility.Web.RequestTracking.WebRequestTrackingModule, Microsoft.ApplicationInsights.Extensibility.Web" />
|
||||
</httpModules>
|
||||
</system.web>
|
||||
|
||||
<system.webServer>
|
||||
<handlers>
|
||||
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
|
||||
<remove name="OPTIONSVerbHandler" />
|
||||
<remove name="TRACEVerbHandler" />
|
||||
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
|
||||
</handlers>
|
||||
<validation validateIntegratedModeConfiguration="false" />
|
||||
<modules>
|
||||
<remove name="ApplicationInsightsWebTracking" />
|
||||
<add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Extensibility.Web.RequestTracking.WebRequestTrackingModule, Microsoft.ApplicationInsights.Extensibility.Web" preCondition="managedHandler" />
|
||||
</modules>
|
||||
</system.webServer>
|
||||
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
|
||||
<bindingRedirect oldVersion="1.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
||||
</configuration>
|
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.ApplicationInsights" version="0.14.3-build00177" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.ApplicationInsights.Agent.Intercept" version="0.14.0-build08008" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.ApplicationInsights.JavaScript" version="0.11.0-build09387" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.ApplicationInsights.PerformanceCollector" version="0.14.3-build00177" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.ApplicationInsights.PersistenceChannel" version="0.14.3-build00177" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.ApplicationInsights.RuntimeTelemetry" version="0.14.3-build00177" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.ApplicationInsights.Web" version="0.14.3-build00177" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.Razor" version="3.2.3" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.WebApi" version="5.2.3" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.WebApi.HelpPage" version="5.2.3" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.WebPages" version="3.2.3" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.Bcl" version="1.1.8" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.Diagnostics.Tracing.EventSource.Redist" version="1.1.16-beta" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Newtonsoft.Json" version="6.0.4" targetFramework="net452" userInstalled="true" />
|
||||
</packages>
|
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Web.Caching;
|
||||
|
||||
namespace IDeliverable.Licensing
|
||||
{
|
||||
public class CacheInvalidationContext
|
||||
{
|
||||
public CacheDependency CacheDependency { get; set; }
|
||||
public TimeSpan? ValidFor { get; set; }
|
||||
}
|
||||
}
|
52
src/IDeliverable/IDeliverable.Licensing/CacheService.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.Web.Caching;
|
||||
|
||||
namespace IDeliverable.Licensing
|
||||
{
|
||||
public class CacheService
|
||||
{
|
||||
private readonly HttpContextAccessor mHttpContextAccessor = new HttpContextAccessor();
|
||||
|
||||
private Cache Cache => mHttpContextAccessor.Current().Cache;
|
||||
|
||||
public void SetValue<T>(string key, T value, CacheDependency dependency = null, TimeSpan? validFor = null)
|
||||
{
|
||||
var absoluteExpiration = validFor != null ? DateTime.UtcNow.Add(validFor.Value) : Cache.NoAbsoluteExpiration;
|
||||
Cache.Insert(key, value, dependency, absoluteExpiration, Cache.NoSlidingExpiration);
|
||||
}
|
||||
|
||||
public T GetValue<T>(string key, Func<CacheInvalidationContext, T> valueFactory = null)
|
||||
{
|
||||
var value = Cache.Get(key);
|
||||
var exception = value as Exception;
|
||||
|
||||
if (exception != null)
|
||||
throw (Exception)value;
|
||||
|
||||
if (value != null)
|
||||
return (T)value;
|
||||
|
||||
if (valueFactory == null)
|
||||
return default(T);
|
||||
|
||||
var context = new CacheInvalidationContext();
|
||||
|
||||
try
|
||||
{
|
||||
value = valueFactory(context);
|
||||
SetValue(key, value, context.CacheDependency, context.ValidFor);
|
||||
return (T) value;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SetValue(key, ex, context.CacheDependency, context.ValidFor);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public object RemoveValue(string key)
|
||||
{
|
||||
return Cache.Remove(key);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
using System.Web;
|
||||
|
||||
namespace IDeliverable.Licensing
|
||||
{
|
||||
public class HttpContextAccessor
|
||||
{
|
||||
public HttpContextBase Current()
|
||||
{
|
||||
return new HttpContextWrapper(HttpContext.Current);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
using System.Web;
|
||||
|
||||
namespace IDeliverable.Licensing
|
||||
{
|
||||
internal static class HttpRequestExtensions
|
||||
{
|
||||
public static string GetHttpHost(this HttpRequestBase request)
|
||||
{
|
||||
var host = request.ServerVariables["HTTP_HOST"];
|
||||
|
||||
if (host?.Contains(":") == true)
|
||||
host = host.Substring(0, host.IndexOf(':'));
|
||||
|
||||
return host;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,72 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{7E439CB7-1ACE-435F-A8F3-5BB929423E34}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>IDeliverable.Licensing</RootNamespace>
|
||||
<AssemblyName>IDeliverable.Licensing</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\..\..\lib\newtonsoft.json\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CacheInvalidationContext.cs" />
|
||||
<Compile Include="CacheService.cs" />
|
||||
<Compile Include="HttpContextAccessor.cs" />
|
||||
<Compile Include="HttpRequestExtensions.cs" />
|
||||
<Compile Include="Validation\LicenseValidationError.cs" />
|
||||
<Compile Include="Validation\LicenseValidationException.cs" />
|
||||
<Compile Include="Validation\LicenseValidator.cs" />
|
||||
<Compile Include="VerificationTokens\LicenseVerificationTokenError.cs" />
|
||||
<Compile Include="VerificationTokens\LicenseVerificationTokenException.cs" />
|
||||
<Compile Include="VerificationTokens\LicenseVerificationInfo.cs" />
|
||||
<Compile Include="VerificationTokens\LicenseVerificationToken.cs" />
|
||||
<Compile Include="VerificationTokens\LicenseVerificationTokenAccessor.cs" />
|
||||
<Compile Include="VerificationTokens\LicensingServiceClient.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Validation\LicenseValidationOptions.cs" />
|
||||
<Compile Include="VerificationTokens\ILicenseVerificationTokenStore.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("IDeliverable.LicensingFramework")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("IDeliverable.LicensingFramework")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("7e439cb7-1ace-435f-a8f3-5bb929423e34")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
@@ -0,0 +1,14 @@
|
||||
namespace IDeliverable.Licensing.Validation
|
||||
{
|
||||
public enum LicenseValidationError
|
||||
{
|
||||
UnknownLicenseKey,
|
||||
HostnameMismatch,
|
||||
NoActiveSubscription,
|
||||
LicensingServiceError,
|
||||
LicensingServiceUnreachable,
|
||||
TokenAgeValidationFailed,
|
||||
TokenSignatureValidationFailed,
|
||||
UnexpectedError,
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
|
||||
namespace IDeliverable.Licensing.Validation
|
||||
{
|
||||
public class LicenseValidationException : Exception
|
||||
{
|
||||
public LicenseValidationException(LicenseValidationError error)
|
||||
:this("An error occurred while validating the license.", error)
|
||||
{
|
||||
}
|
||||
|
||||
public LicenseValidationException(string message, LicenseValidationError error) : base(message)
|
||||
{
|
||||
Error = error;
|
||||
}
|
||||
|
||||
public LicenseValidationException(LicenseValidationError error, Exception innerException)
|
||||
: this("An error occurred while validating the license.", error, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
public LicenseValidationException(string message, LicenseValidationError error, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
Error = error;
|
||||
}
|
||||
|
||||
public LicenseValidationError Error { get; private set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace IDeliverable.Licensing.Validation
|
||||
{
|
||||
[Flags]
|
||||
public enum LicenseValidationOptions
|
||||
{
|
||||
Default = 0,
|
||||
SkipForLocalRequests = 1,
|
||||
ForceRenewToken = 2,
|
||||
}
|
||||
}
|
@@ -0,0 +1,137 @@
|
||||
using System;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using IDeliverable.Licensing.VerificationTokens;
|
||||
|
||||
namespace IDeliverable.Licensing.Validation
|
||||
{
|
||||
public class LicenseValidator
|
||||
{
|
||||
private static readonly TimeSpan sVerificationTokenValidFor = TimeSpan.FromDays(21);
|
||||
private static readonly TimeSpan sAllowableClockSkew = TimeSpan.FromMinutes(10);
|
||||
|
||||
public LicenseValidator(LicenseVerificationTokenAccessor verificationTokenAccessor)
|
||||
{
|
||||
mHttpContextAccessor = new HttpContextAccessor();
|
||||
mVerificationTokenAccessor = verificationTokenAccessor;
|
||||
}
|
||||
|
||||
private readonly HttpContextAccessor mHttpContextAccessor;
|
||||
private readonly LicenseVerificationTokenAccessor mVerificationTokenAccessor;
|
||||
|
||||
public void ValidateLicense(string productId, string licenseKey, LicenseValidationOptions options = LicenseValidationOptions.Default)
|
||||
{
|
||||
var request = mHttpContextAccessor.Current().Request;
|
||||
|
||||
var skipForLocalRequests = (options & LicenseValidationOptions.SkipForLocalRequests) == LicenseValidationOptions.SkipForLocalRequests;
|
||||
if (request.IsLocal && skipForLocalRequests)
|
||||
return;
|
||||
|
||||
LicenseVerificationToken token;
|
||||
|
||||
try
|
||||
{
|
||||
var forceRenewToken = (options & LicenseValidationOptions.ForceRenewToken) == LicenseValidationOptions.ForceRenewToken;
|
||||
token = mVerificationTokenAccessor.GetLicenseVerificationToken(productId, licenseKey, request.GetHttpHost(), forceRenewToken);
|
||||
|
||||
// If the token we got back is too old to be considered valid anymore, try to get the token
|
||||
// again, this time forcing token renewal.
|
||||
if (token.Age > sVerificationTokenValidFor)
|
||||
token = mVerificationTokenAccessor.GetLicenseVerificationToken(productId, licenseKey, request.GetHttpHost(), forceRenew: true);
|
||||
}
|
||||
catch (LicenseVerificationTokenException ex)
|
||||
{
|
||||
var error = LicenseValidationError.UnexpectedError;
|
||||
|
||||
switch (ex.Error)
|
||||
{
|
||||
case LicenseVerificationTokenError.UnknownLicenseKey:
|
||||
error = LicenseValidationError.UnknownLicenseKey;
|
||||
break;
|
||||
|
||||
case LicenseVerificationTokenError.HostnameMismatch:
|
||||
error = LicenseValidationError.HostnameMismatch;
|
||||
break;
|
||||
|
||||
case LicenseVerificationTokenError.NoActiveSubscription:
|
||||
error = LicenseValidationError.NoActiveSubscription;
|
||||
break;
|
||||
|
||||
case LicenseVerificationTokenError.LicenseServiceError:
|
||||
error = LicenseValidationError.LicensingServiceError;
|
||||
break;
|
||||
|
||||
case LicenseVerificationTokenError.LicenseServiceUnreachable:
|
||||
error = LicenseValidationError.LicensingServiceUnreachable;
|
||||
break;
|
||||
}
|
||||
|
||||
throw new LicenseValidationException(ex.Message, error);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new LicenseValidationException("An unexpected error occurred while validating the license.", LicenseValidationError.UnexpectedError, ex);
|
||||
}
|
||||
|
||||
// It should never happen that at this point we don't have a token or it's too old.
|
||||
if (token == null || token.Age > sVerificationTokenValidFor)
|
||||
throw new LicenseValidationException(LicenseValidationError.UnexpectedError);
|
||||
|
||||
// If the token age is negative by more than 10 minutes (allowable clock skew between licensing
|
||||
// service and local machine) then this is a strong indication of an attempt to bypass license
|
||||
// validation by changing the system clock.
|
||||
if (token.Age < -sAllowableClockSkew)
|
||||
throw new LicenseValidationException("The license verification token age is negative by more than the allowable clock skew. This might indicate that system clock of either the client or the licensing service is offset.", LicenseValidationError.TokenAgeValidationFailed);
|
||||
|
||||
var signingCertificate = GetSigningCertificate();
|
||||
if (!token.GetSignatureIsValid(signingCertificate))
|
||||
throw new LicenseValidationException("License verification token signature validation failed.", LicenseValidationError.TokenSignatureValidationFailed);
|
||||
}
|
||||
|
||||
private static X509Certificate2 GetSigningCertificate()
|
||||
{
|
||||
const string certBase64 =
|
||||
@"MIIG0TCCBLmgAwIBAgIQ7qnUeLGos7hDPcw3o9G74jANBgkqhkiG9w0BAQ0FADCB
|
||||
ozELMAkGA1UEBhMCQ1kxETAPBgNVBAgTCExpbWFzc29sMREwDwYDVQQHEwhMaW1h
|
||||
c3NvbDEZMBcGA1UEChMQSURlbGl2ZXJhYmxlIEx0ZDETMBEGA1UECxMKT3BlcmF0
|
||||
aW9uczEYMBYGA1UEAxMPSURlbGl2ZXJhYmxlIENBMSQwIgYJKoZIhvcNAQkBFhVp
|
||||
bmZvQGlkZWxpdmVyYWJsZS5jb20wHhcNMTQxMjMxMjEwMDAwWhcNMjQxMjMxMjEw
|
||||
MDAwWjCBrjELMAkGA1UEBhMCQ1kxETAPBgNVBAgTCExpbWFzc29sMREwDwYDVQQH
|
||||
EwhMaW1hc3NvbDEZMBcGA1UEChMQSURlbGl2ZXJhYmxlIEx0ZDETMBEGA1UECxMK
|
||||
T3BlcmF0aW9uczEjMCEGA1UEAxMabGljZW5zaW5nLmlkZWxpdmVyYWJsZS5jb20x
|
||||
JDAiBgkqhkiG9w0BCQEWFWluZm9AaWRlbGl2ZXJhYmxlLmNvbTCCAiIwDQYJKoZI
|
||||
hvcNAQEBBQADggIPADCCAgoCggIBAJ0LddkeiE9f0p60exUCR1PxrKBHoVwF5von
|
||||
Lq+4GxA4I7Frtt8MV/dEYnYT44d/S6lEkAPLfF70CnyyWfpPO7MkIJYlFNZ2eJSz
|
||||
9wu0VZ12CZO9RilxrEzK1xLS+f6g7P+rPP3m1CqSt84wpd3YloLdBuB3HwPWNh5H
|
||||
a0Ew7W6IKyhzIX4MNzXXNc2evDIoaur3jQiPewtSastXzSQEEUx+S4St4qFbJ8lK
|
||||
v6pwC1BmqX37uoNURqqS1CWg3iKiAfzqtTIwt9vBu8C1ev4ZnlKmAF4C1fTuH3Wo
|
||||
X1lT+wpkycqWIUxoV7zoXYpxkleeNCw/GavDYmqhfU0qSjI4bdD/uy0s66dubtWB
|
||||
rCZ3VRC7mjHhmEWj1Y9GYvvg6Fjt/BchVMNEhIBd873MdXDqIx0cV6SILiQgudtr
|
||||
uvAUm5rT6KEYNSsHq9gQWN+LAgy8mDSOGLjYXdBtAOJMxS/w8XNA+bXWzvNYOl9q
|
||||
QO8w7Py3U/8mnLkxgHaVGktWazwQ1QkwaLyQz7lbTBedXkxOzP3LvLAe+POd4Zre
|
||||
wYcNUs/W51WfLup9o/IMEvDk/z0FCJ1fGFiHny3QFWrhJB3dAia1dwYtUpy42ZuY
|
||||
w4UQEuZVr3BzDCXudx6638WOURpvaMe/Enfdr2bcqvCYvzbT06RPD/VTtuKtZ8O7
|
||||
Q/hr0NvTAgMBAAGjgfMwgfAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwgdgGA1UdAQSB
|
||||
0DCBzYAQFBF2JL0Y1AduVxGNb4H7DqGBpjCBozELMAkGA1UEBhMCQ1kxETAPBgNV
|
||||
BAgTCExpbWFzc29sMREwDwYDVQQHEwhMaW1hc3NvbDEZMBcGA1UEChMQSURlbGl2
|
||||
ZXJhYmxlIEx0ZDETMBEGA1UECxMKT3BlcmF0aW9uczEYMBYGA1UEAxMPSURlbGl2
|
||||
ZXJhYmxlIENBMSQwIgYJKoZIhvcNAQkBFhVpbmZvQGlkZWxpdmVyYWJsZS5jb22C
|
||||
EMgq1WuLQwSJTj+ogMza3/YwDQYJKoZIhvcNAQENBQADggIBAEU9gdrydWT3ZwtA
|
||||
LP/HEct2DJRQdK9WuL02x2xbdmszyb8xoayTIcJdvs2WHPBqxM417XAhNTZuG3Aw
|
||||
Yx6OPSzbfmS1X7aVctSeBwZCfzxOk2MhTsKoZ+wjmFn6LVYz3P6K2deJVz6t+HRc
|
||||
mMwFrsctzgGZsxIvMXa0eqyDE6hhxj0XKYLFmYNGBdUd5sW68Ko26Njv1FPLkoqo
|
||||
Me2y+Gi6SltgjD/bmza36IRvaQVQtOjOxq+TncOBqLJ2+ikQOr93pkCgx3nso3CM
|
||||
YH1ryRpXbSAb5aA9sF0jb6LLLUgHv5q2ExpEFcoRja5gww5R2VKwEJ2PXjK+2O/A
|
||||
DgHOLKuiODxBF61+Ou/d29XiSX2HxCoH+onppi2h6ceJPcFwPrgzKVszsGkavtKL
|
||||
7myxufgdBUgTFxYMaTEtrU0yaRiJItxreH1wj/vl1zKyl25MXZLM1LyFvszAX49h
|
||||
9hgWApwE9hL1i6ygIfrpq2B+djPS8ZwX5S/t/QO5SmBjNLmw1GD1gHN5xqY0vMzS
|
||||
VxDXrH6Kllhwipu8GLeMWn/VmWWLy1vr//GoBjujhplIZHJPYBrYjqwfxH1ZLa4B
|
||||
O+N7bHDp63M0UVX5FdX1sN0laL29L1jXX/oe7x8PHNt3W4aOwVaIilh+/adXNDxr
|
||||
1yumH4G7QEeMQisiMhlPxnZJHajX";
|
||||
|
||||
var certBytes = Convert.FromBase64String(certBase64);
|
||||
var cert = new X509Certificate2(certBytes);
|
||||
|
||||
return cert;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
namespace IDeliverable.Licensing.VerificationTokens
|
||||
{
|
||||
public interface ILicenseVerificationTokenStore
|
||||
{
|
||||
LicenseVerificationToken Load(string productId);
|
||||
void Save(string productId, LicenseVerificationToken token);
|
||||
void Clear(string productId);
|
||||
}
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace IDeliverable.Licensing.VerificationTokens
|
||||
{
|
||||
public class LicenseVerificationInfo
|
||||
{
|
||||
public LicenseVerificationInfo(int productId, string hostname, string licenseKey, long verifiedUtcTicks)
|
||||
{
|
||||
ProductId = productId;
|
||||
Hostname = hostname;
|
||||
LicenseKey = licenseKey;
|
||||
VerifiedUtcTicks = verifiedUtcTicks;
|
||||
}
|
||||
|
||||
public int ProductId { get; }
|
||||
public string Hostname { get; }
|
||||
public string LicenseKey { get; }
|
||||
public long VerifiedUtcTicks { get; }
|
||||
|
||||
public DateTime VerifiedUtc => new DateTime(VerifiedUtcTicks, DateTimeKind.Utc);
|
||||
public TimeSpan Age => DateTime.UtcNow - VerifiedUtc;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return JsonConvert.SerializeObject(
|
||||
new
|
||||
{
|
||||
ProductId,
|
||||
Hostname,
|
||||
LicenseKey,
|
||||
VerifiedUtcTicks
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace IDeliverable.Licensing.VerificationTokens
|
||||
{
|
||||
public class LicenseVerificationToken
|
||||
{
|
||||
public static LicenseVerificationToken Create(LicenseVerificationInfo info, X509Certificate2 signingCert)
|
||||
{
|
||||
var infoString = info.ToString();
|
||||
var infoBytes = Encoding.UTF8.GetBytes(infoString);
|
||||
var privateKey = (RSACryptoServiceProvider)signingCert.PrivateKey;
|
||||
var signatureBytes = privateKey.SignData(infoBytes, "md5");
|
||||
var signature = Convert.ToBase64String(signatureBytes);
|
||||
|
||||
return new LicenseVerificationToken(info, signature);
|
||||
}
|
||||
|
||||
public static LicenseVerificationToken FromBase64(string value)
|
||||
{
|
||||
var tokenBytes = Convert.FromBase64String(value);
|
||||
var tokenJson = Encoding.UTF8.GetString(tokenBytes);
|
||||
return Parse(tokenJson);
|
||||
}
|
||||
|
||||
public static LicenseVerificationToken Parse(string value)
|
||||
{
|
||||
return JsonConvert.DeserializeObject<LicenseVerificationToken>(value, new StringEnumConverter());
|
||||
}
|
||||
|
||||
public LicenseVerificationToken(LicenseVerificationInfo info, string signature)
|
||||
{
|
||||
if (info == null)
|
||||
throw new ArgumentNullException(nameof(info), $"The parameter {nameof(info)} cannot be null.");
|
||||
|
||||
Info = info;
|
||||
Signature = signature;
|
||||
}
|
||||
|
||||
public LicenseVerificationInfo Info { get; }
|
||||
public string Signature { get; }
|
||||
|
||||
public DateTime VerifiedUtc => Info.VerifiedUtc; // Delegated to Info because it needs to be included in signature.
|
||||
public TimeSpan Age => Info.Age; // Delegated to Info because it needs to be included in signature.
|
||||
|
||||
public string ToBase64()
|
||||
{
|
||||
var tokenJson = ToString();
|
||||
var tokenBytes = Encoding.UTF8.GetBytes(tokenJson);
|
||||
return Convert.ToBase64String(tokenBytes);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return JsonConvert.SerializeObject(this);
|
||||
}
|
||||
|
||||
public bool GetSignatureIsValid(X509Certificate2 signingCert)
|
||||
{
|
||||
var publicKey = (RSACryptoServiceProvider)signingCert.PublicKey.Key;
|
||||
var infoBytes = Encoding.UTF8.GetBytes(Info.ToString());
|
||||
var signatureBytes = Convert.FromBase64String(Signature);
|
||||
var isValid = publicKey.VerifyData(infoBytes, "md5", signatureBytes);
|
||||
|
||||
return isValid;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
|
||||
namespace IDeliverable.Licensing.VerificationTokens
|
||||
{
|
||||
public class LicenseVerificationTokenAccessor
|
||||
{
|
||||
private static readonly TimeSpan sTokenRenewalInterval = TimeSpan.FromHours(48);
|
||||
|
||||
public LicenseVerificationTokenAccessor(ILicenseVerificationTokenStore store)
|
||||
{
|
||||
mStore = store;
|
||||
mLicensingServiceClient = new LicensingServiceClient();
|
||||
}
|
||||
|
||||
private readonly ILicenseVerificationTokenStore mStore;
|
||||
private readonly LicensingServiceClient mLicensingServiceClient;
|
||||
|
||||
public LicenseVerificationToken GetLicenseVerificationToken(string productId, string licenseKey, string hostname, bool forceRenew = false)
|
||||
{
|
||||
var token = mStore.Load(productId);
|
||||
|
||||
// Delete the existing verification token from store if:
|
||||
// * It was issued for a different license key OR
|
||||
// * We are instructed by caller to force renewal
|
||||
if (token != null && (token.Info.LicenseKey != licenseKey || forceRenew))
|
||||
{
|
||||
mStore.Clear(productId);
|
||||
token = null;
|
||||
}
|
||||
|
||||
// Try to renew verification token from licensing service if:
|
||||
// * We don't have a token in store OR
|
||||
// * The one we have has passed the token renewal interval
|
||||
if (token == null || token.Age > sTokenRenewalInterval)
|
||||
{
|
||||
try
|
||||
{
|
||||
token = mLicensingServiceClient.VerifyLicense(productId, licenseKey, hostname);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// If the license key is reported by licensing service to be either invalid or for
|
||||
// a different hostname, we delete any existing token from store and throw unconditionally.
|
||||
if (ex is LicenseVerificationTokenException)
|
||||
{
|
||||
var lvtex = (LicenseVerificationTokenException)ex;
|
||||
if (lvtex.Error == LicenseVerificationTokenError.UnknownLicenseKey ||
|
||||
lvtex.Error == LicenseVerificationTokenError.HostnameMismatch ||
|
||||
lvtex.Error == LicenseVerificationTokenError.NoActiveSubscription)
|
||||
{
|
||||
mStore.Clear(productId);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// If we have an existing token from before, return it rather than throwing.
|
||||
if (token != null)
|
||||
return token;
|
||||
|
||||
if (ex is LicenseVerificationTokenException)
|
||||
throw;
|
||||
|
||||
throw new LicenseVerificationTokenException(LicenseVerificationTokenError.UnexpectedError, ex);
|
||||
}
|
||||
|
||||
mStore.Save(productId, token);
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
namespace IDeliverable.Licensing.VerificationTokens
|
||||
{
|
||||
public enum LicenseVerificationTokenError
|
||||
{
|
||||
UnknownLicenseKey,
|
||||
HostnameMismatch,
|
||||
NoActiveSubscription,
|
||||
LicenseServiceError,
|
||||
LicenseServiceUnreachable,
|
||||
UnexpectedError
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
|
||||
namespace IDeliverable.Licensing.VerificationTokens
|
||||
{
|
||||
public class LicenseVerificationTokenException : Exception
|
||||
{
|
||||
public LicenseVerificationTokenException(LicenseVerificationTokenError error)
|
||||
:this("An error occurred while getting a license verification token.", error)
|
||||
{
|
||||
}
|
||||
|
||||
public LicenseVerificationTokenException(string message, LicenseVerificationTokenError error) : base(message)
|
||||
{
|
||||
Error = error;
|
||||
}
|
||||
|
||||
public LicenseVerificationTokenException(LicenseVerificationTokenError error, Exception innerException)
|
||||
: this("An error occurred while getting a license verification token.", error, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
public LicenseVerificationTokenException(string message, LicenseVerificationTokenError error, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
Error = error;
|
||||
}
|
||||
|
||||
public LicenseVerificationTokenError Error { get; private set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Net.Security;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace IDeliverable.Licensing.VerificationTokens
|
||||
{
|
||||
public class LicensingServiceClient
|
||||
{
|
||||
// These are consciously hard coded (need to be obfuscated).
|
||||
private static readonly string sLicensingServiceUrl = "https://licensing.ideliverable.com/api/v1/";
|
||||
private static readonly string sLicensingServiceApiKey = "MJb17j7YAzSjyEYkhsoI";
|
||||
private static readonly string sExpectedServerCertificateThumbprint = "fa4746a778716109e7e80e1b8dc2ed2a2ba3b852";
|
||||
|
||||
public LicenseVerificationToken VerifyLicense(string productId, string licenseKey, string hostname)
|
||||
{
|
||||
RemoteCertificateValidationCallback certValidationHandler = (sender, certificate, chain, errors) =>
|
||||
{
|
||||
// Accept the server certificate as long as it matches the expected thumbprint. This makes sure
|
||||
// that the API call works even if the client host doesn't trust IDeliverable CA certificate, but
|
||||
// fails if somebody is trying to spoof the service.
|
||||
var serverCertThumbprint = ((X509Certificate2)certificate).Thumbprint;
|
||||
return String.Equals(serverCertThumbprint, sExpectedServerCertificateThumbprint, StringComparison.OrdinalIgnoreCase);
|
||||
};
|
||||
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
client.BaseAddress = new Uri(sLicensingServiceUrl);
|
||||
client.DefaultRequestHeaders.Add("ApiKey", sLicensingServiceApiKey);
|
||||
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
|
||||
ServicePointManager.ServerCertificateValidationCallback += certValidationHandler;
|
||||
|
||||
try
|
||||
{
|
||||
HttpResponseMessage response = null;
|
||||
|
||||
try
|
||||
{
|
||||
response = client.GetAsync($"license/{licenseKey}/verify?productId={productId}&hostname={hostname}").Result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new LicenseVerificationTokenException("An error occurred while calling the licensing service.", LicenseVerificationTokenError.LicenseServiceUnreachable, ex);
|
||||
}
|
||||
|
||||
if (response.StatusCode == HttpStatusCode.NotFound)
|
||||
throw new LicenseVerificationTokenException(response.ReasonPhrase, LicenseVerificationTokenError.UnknownLicenseKey);
|
||||
|
||||
if (response.StatusCode == HttpStatusCode.Forbidden)
|
||||
throw new LicenseVerificationTokenException(response.ReasonPhrase, LicenseVerificationTokenError.HostnameMismatch);
|
||||
|
||||
if (response.StatusCode == HttpStatusCode.Gone)
|
||||
throw new LicenseVerificationTokenException(response.ReasonPhrase, LicenseVerificationTokenError.NoActiveSubscription);
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
throw new LicenseVerificationTokenException(response.ReasonPhrase, LicenseVerificationTokenError.LicenseServiceError);
|
||||
|
||||
var responseText = response.Content.ReadAsStringAsync().Result;
|
||||
var token = LicenseVerificationToken.Parse(responseText);
|
||||
|
||||
return token;
|
||||
}
|
||||
finally
|
||||
{
|
||||
ServicePointManager.ServerCertificateValidationCallback -= certValidationHandler;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
BIN
src/IDeliverable/Packaging/Confuser/Confuser.CLI.exe
Normal file
BIN
src/IDeliverable/Packaging/Confuser/Confuser.Core.dll
Normal file
3234
src/IDeliverable/Packaging/Confuser/Confuser.Core.xml
Normal file
BIN
src/IDeliverable/Packaging/Confuser/Confuser.DynCipher.dll
Normal file
BIN
src/IDeliverable/Packaging/Confuser/Confuser.Protections.dll
Normal file
BIN
src/IDeliverable/Packaging/Confuser/Confuser.Renamer.dll
Normal file
BIN
src/IDeliverable/Packaging/Confuser/Confuser.Runtime.dll
Normal file
BIN
src/IDeliverable/Packaging/Confuser/ConfuserEx.exe
Normal file
14
src/IDeliverable/Packaging/Confuser/ConfuserEx.exe.config
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<configuration>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Practices.ServiceLocation" publicKeyToken="31BF3856AD364E35"
|
||||
culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.2.0.0" newVersion="1.2.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
<loadFromRemoteSources enabled="true" />
|
||||
</runtime>
|
||||
</configuration>
|
BIN
src/IDeliverable/Packaging/Confuser/GalaSoft.MvvmLight.WPF4.dll
Normal file
BIN
src/IDeliverable/Packaging/Confuser/Ookii.Dialogs.Wpf.dll
Normal file
BIN
src/IDeliverable/Packaging/Confuser/System.Threading.dll
Normal file
BIN
src/IDeliverable/Packaging/Confuser/dnlib.dll
Normal file
BIN
src/IDeliverable/Packaging/ILMerge/ILMerge.doc
Normal file
BIN
src/IDeliverable/Packaging/ILMerge/ILMerge.exe
Normal file
@@ -33,16 +33,16 @@
|
||||
<Component Type="Orchard.Environment.Extensions.Compilers.DefaultProjectFileParser">
|
||||
<Properties>
|
||||
<!-- Set Value="true" to disable project files monitoring (/Modules/**/*.csproj) -->
|
||||
<Property Name="DisableMonitoring" Value="false"/>
|
||||
<Property Name="DisableMonitoring" Value="true"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
|
||||
<Component Type="Orchard.Environment.Extensions.Loaders.DynamicExtensionLoader">
|
||||
<Properties>
|
||||
<!-- Set Value="true" to disable source files monitoring -->
|
||||
<Property Name="DisableMonitoring" Value="false"/>
|
||||
<Property Name="DisableMonitoring" Value="true"/>
|
||||
<!-- Set Value="true" to completely disable the Dynamic Extension Loader -->
|
||||
<Property Name="Disabled" Value="false"/>
|
||||
<Property Name="Disabled" Value="true"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
|
||||
|
After Width: | Height: | Size: 192 KiB |
After Width: | Height: | Size: 192 KiB |
BIN
src/Orchard.Web/Media/Default/Images/DR2 Foto 5-229.jpeg
Normal file
After Width: | Height: | Size: 270 KiB |
BIN
src/Orchard.Web/Media/Default/Images/DR2 Foto 5-365.jpeg
Normal file
After Width: | Height: | Size: 221 KiB |
132
src/Orchard.Web/Media/Default/Images/Logo-Full-Color-Opaque.svg
Normal file
@@ -0,0 +1,132 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="171px" height="35px" viewBox="0 0 171 35" enable-background="new 0 0 171 35" xml:space="preserve">
|
||||
<path fill="#D3CFBC" d="M171,33c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V2c0-1.1,0.9-2,2-2h167c1.1,0,2,0.9,2,2V33z"/>
|
||||
<path fill="#1A1A1A" d="M4.134,25.18l1.689-0.465c0.144-0.046,0.257-0.117,0.34-0.216c0.083-0.099,0.125-0.23,0.125-0.396V11.675
|
||||
c0-0.159-0.045-0.287-0.136-0.386c-0.091-0.098-0.2-0.166-0.329-0.204l-1.689-0.476V9.884h6.587v0.726l-1.689,0.476
|
||||
c-0.136,0.038-0.25,0.106-0.34,0.204c-0.091,0.099-0.136,0.227-0.136,0.386v12.427c0,0.174,0.045,0.31,0.136,0.408
|
||||
c0.09,0.098,0.204,0.166,0.34,0.204l1.689,0.465v0.736H4.134V25.18z"/>
|
||||
<path fill="#1A1A1A" d="M12.536,25.18l1.633-0.465c0.128-0.038,0.238-0.108,0.329-0.21c0.091-0.103,0.136-0.236,0.136-0.402V11.675
|
||||
c0-0.159-0.045-0.287-0.136-0.386c-0.091-0.098-0.2-0.166-0.329-0.204l-1.633-0.476V9.884h7.098c0.529,0,1.094,0.049,1.695,0.147
|
||||
s1.198,0.268,1.792,0.51c0.593,0.242,1.164,0.563,1.712,0.964c0.548,0.4,1.03,0.899,1.446,1.497
|
||||
c0.416,0.597,0.749,1.306,0.998,2.126c0.249,0.82,0.374,1.767,0.374,2.84c0,1.368-0.212,2.551-0.635,3.548
|
||||
c-0.423,0.998-1,1.824-1.729,2.478c-0.729,0.654-1.583,1.138-2.563,1.451c-0.979,0.314-2.024,0.471-3.135,0.471h-7.052V25.18z
|
||||
M19.69,24.737c0.938,0,1.748-0.144,2.432-0.431c0.684-0.288,1.251-0.705,1.701-1.253c0.449-0.549,0.782-1.221,0.998-2.019
|
||||
s0.323-1.707,0.323-2.727c0-1.119-0.146-2.126-0.437-3.021c-0.291-0.896-0.705-1.657-1.242-2.285s-1.185-1.109-1.944-1.446
|
||||
s-1.601-0.504-2.523-0.504h-2.098v13.686H19.69z"/>
|
||||
<path fill="#1A1A1A" d="M39.749,23.161v1.134c-0.265,0.227-0.571,0.453-0.918,0.681c-0.348,0.227-0.729,0.429-1.145,0.606
|
||||
c-0.416,0.178-0.856,0.323-1.321,0.437s-0.943,0.17-1.435,0.17c-0.793,0-1.529-0.133-2.205-0.396
|
||||
c-0.677-0.265-1.263-0.656-1.758-1.174s-0.882-1.154-1.162-1.911c-0.28-0.756-0.419-1.629-0.419-2.619
|
||||
c0-0.861,0.134-1.672,0.402-2.432c0.269-0.76,0.646-1.423,1.134-1.99c0.488-0.567,1.077-1.017,1.769-1.35
|
||||
c0.691-0.333,1.457-0.499,2.296-0.499c0.764,0,1.442,0.128,2.036,0.385c0.593,0.257,1.094,0.599,1.502,1.026
|
||||
s0.718,0.922,0.93,1.485c0.211,0.563,0.317,1.147,0.317,1.752c0,0.075-0.002,0.161-0.006,0.255
|
||||
c-0.004,0.095-0.007,0.193-0.011,0.294c-0.004,0.103-0.013,0.2-0.028,0.295s-0.03,0.18-0.045,0.255h-8.062
|
||||
c0.007,1.655,0.361,2.912,1.06,3.771c0.699,0.857,1.71,1.287,3.033,1.287c0.431,0,0.837-0.052,1.219-0.153
|
||||
c0.381-0.103,0.733-0.227,1.054-0.374s0.608-0.305,0.862-0.471s0.471-0.321,0.652-0.465H39.749z M37.492,18.535
|
||||
c0-0.529-0.045-1.017-0.136-1.463c-0.091-0.446-0.242-0.831-0.454-1.156c-0.212-0.325-0.484-0.579-0.816-0.76
|
||||
c-0.333-0.182-0.741-0.272-1.225-0.272c-0.438,0-0.839,0.083-1.202,0.249c-0.363,0.167-0.682,0.407-0.958,0.72
|
||||
c-0.276,0.314-0.501,0.697-0.674,1.151c-0.174,0.454-0.288,0.964-0.34,1.531H37.492z"/>
|
||||
<path fill="#1A1A1A" d="M41.166,25.202l1.53-0.397c0.144-0.037,0.259-0.104,0.346-0.198c0.086-0.094,0.13-0.221,0.13-0.38V10.825
|
||||
c0-0.174-0.049-0.315-0.147-0.425c-0.099-0.109-0.238-0.194-0.419-0.255l-1.497-0.556V8.954l4.207-0.431v15.704
|
||||
c0,0.159,0.047,0.288,0.142,0.386c0.094,0.099,0.206,0.163,0.334,0.192l1.451,0.397v0.714h-6.077V25.202z"/>
|
||||
<path fill="#1A1A1A" d="M48.445,25.202l1.565-0.397c0.144-0.037,0.261-0.104,0.352-0.198c0.09-0.094,0.136-0.221,0.136-0.38v-7.755
|
||||
c0-0.174-0.049-0.316-0.147-0.425s-0.242-0.195-0.431-0.255l-1.44-0.499v-0.635l4.15-0.669v10.238c0,0.159,0.047,0.288,0.142,0.386
|
||||
c0.095,0.099,0.206,0.163,0.334,0.192l1.508,0.397v0.714h-6.168V25.202z M51.393,11.573c-0.212,0-0.41-0.036-0.595-0.108
|
||||
c-0.186-0.072-0.348-0.168-0.488-0.289c-0.14-0.121-0.251-0.27-0.334-0.448s-0.125-0.376-0.125-0.595s0.042-0.419,0.125-0.601
|
||||
c0.083-0.181,0.195-0.334,0.334-0.459c0.14-0.125,0.302-0.221,0.488-0.29c0.185-0.068,0.383-0.102,0.595-0.102
|
||||
c0.227,0,0.438,0.032,0.635,0.097s0.365,0.157,0.505,0.278c0.14,0.121,0.249,0.266,0.329,0.437c0.08,0.17,0.119,0.365,0.119,0.584
|
||||
c0,0.227-0.04,0.431-0.119,0.612c-0.08,0.181-0.191,0.338-0.334,0.47c-0.144,0.132-0.314,0.234-0.51,0.306
|
||||
C51.82,11.538,51.612,11.573,51.393,11.573z"/>
|
||||
<path fill="#1A1A1A" d="M56.506,15.757c-0.061-0.151-0.146-0.269-0.255-0.352c-0.11-0.083-0.24-0.151-0.391-0.204l-0.862-0.352
|
||||
v-0.703h5.284v0.703l-1.667,0.487l2.687,6.338l0.533,1.61h0.125l3.005-7.71l-1.576-0.726v-0.703h4.331v0.703l-0.896,0.556
|
||||
c-0.151,0.076-0.284,0.155-0.397,0.238c-0.113,0.083-0.2,0.193-0.261,0.329l-3.107,7.585l-1.236,2.472h-0.975L56.506,15.757z"/>
|
||||
<path fill="#1A1A1A" d="M78.696,23.161v1.134c-0.265,0.227-0.571,0.453-0.918,0.681c-0.348,0.227-0.729,0.429-1.145,0.606
|
||||
c-0.416,0.178-0.856,0.323-1.321,0.437s-0.943,0.17-1.435,0.17c-0.793,0-1.529-0.133-2.205-0.396
|
||||
c-0.677-0.265-1.263-0.656-1.758-1.174s-0.882-1.154-1.162-1.911c-0.28-0.756-0.419-1.629-0.419-2.619
|
||||
c0-0.861,0.134-1.672,0.402-2.432c0.269-0.76,0.646-1.423,1.134-1.99c0.488-0.567,1.077-1.017,1.769-1.35
|
||||
c0.691-0.333,1.457-0.499,2.296-0.499c0.764,0,1.442,0.128,2.036,0.385c0.593,0.257,1.094,0.599,1.502,1.026
|
||||
s0.718,0.922,0.93,1.485c0.211,0.563,0.317,1.147,0.317,1.752c0,0.075-0.002,0.161-0.006,0.255
|
||||
c-0.004,0.095-0.007,0.193-0.011,0.294c-0.004,0.103-0.013,0.2-0.028,0.295s-0.03,0.18-0.045,0.255h-8.062
|
||||
c0.007,1.655,0.361,2.912,1.06,3.771c0.699,0.857,1.71,1.287,3.033,1.287c0.431,0,0.837-0.052,1.219-0.153
|
||||
c0.381-0.103,0.733-0.227,1.054-0.374s0.608-0.305,0.862-0.471s0.471-0.321,0.652-0.465H78.696z M76.439,18.535
|
||||
c0-0.529-0.045-1.017-0.136-1.463c-0.091-0.446-0.242-0.831-0.454-1.156c-0.212-0.325-0.484-0.579-0.816-0.76
|
||||
c-0.333-0.182-0.741-0.272-1.225-0.272c-0.438,0-0.839,0.083-1.202,0.249c-0.363,0.167-0.682,0.407-0.958,0.72
|
||||
c-0.276,0.314-0.501,0.697-0.674,1.151c-0.174,0.454-0.288,0.964-0.34,1.531H76.439z"/>
|
||||
<path fill="#1A1A1A" d="M80.385,25.202l1.349-0.397c0.136-0.037,0.248-0.104,0.334-0.198c0.087-0.094,0.13-0.221,0.13-0.38v-7.732
|
||||
c0-0.196-0.055-0.355-0.164-0.476c-0.11-0.121-0.248-0.212-0.414-0.272l-1.281-0.521v-0.635l3.844-0.669v2.585h0.08
|
||||
c0.287-0.423,0.568-0.801,0.845-1.134c0.275-0.333,0.561-0.614,0.856-0.845s0.597-0.406,0.907-0.527
|
||||
c0.31-0.121,0.643-0.181,0.998-0.181c0.189,0,0.372,0.009,0.55,0.028s0.346,0.049,0.505,0.091c0.159,0.042,0.312,0.098,0.459,0.17
|
||||
s0.293,0.157,0.437,0.255v2.767h-1.1l-0.34-0.896c-0.038-0.091-0.102-0.17-0.193-0.238c-0.091-0.068-0.195-0.126-0.312-0.176
|
||||
c-0.118-0.049-0.244-0.086-0.38-0.113c-0.136-0.026-0.265-0.04-0.386-0.04c-0.302,0-0.584,0.049-0.845,0.147
|
||||
s-0.503,0.229-0.726,0.391c-0.223,0.163-0.433,0.35-0.629,0.561c-0.197,0.212-0.385,0.435-0.567,0.669v6.792
|
||||
c0,0.159,0.043,0.288,0.13,0.386c0.087,0.099,0.199,0.163,0.334,0.192l1.656,0.397v0.714h-6.078V25.202z"/>
|
||||
<path fill="#1A1A1A" d="M98.096,24.159c-0.294,0.431-0.617,0.776-0.969,1.037s-0.707,0.463-1.066,0.606
|
||||
c-0.358,0.144-0.71,0.238-1.054,0.283c-0.345,0.046-0.656,0.068-0.936,0.068c-0.515,0-0.974-0.091-1.378-0.272
|
||||
c-0.404-0.181-0.748-0.419-1.032-0.714c-0.283-0.295-0.5-0.639-0.651-1.032c-0.151-0.393-0.227-0.801-0.227-1.225
|
||||
c0-0.498,0.086-0.944,0.261-1.338c0.174-0.393,0.408-0.736,0.702-1.031c0.295-0.295,0.636-0.546,1.021-0.754
|
||||
c0.386-0.208,0.784-0.378,1.196-0.511c0.412-0.132,0.828-0.229,1.248-0.289c0.419-0.061,0.811-0.091,1.173-0.091
|
||||
c0.076,0,0.193,0.008,0.352,0.022c0.159,0.016,0.325,0.03,0.499,0.045s0.338,0.03,0.493,0.045c0.155,0.016,0.274,0.027,0.357,0.034
|
||||
v-1.802c0-0.408-0.048-0.749-0.142-1.021c-0.095-0.272-0.229-0.489-0.402-0.652c-0.175-0.162-0.388-0.277-0.641-0.346
|
||||
c-0.254-0.068-0.543-0.102-0.868-0.102c-0.378,0-0.754,0.066-1.128,0.199s-0.731,0.293-1.071,0.481
|
||||
c-0.34,0.189-0.654,0.386-0.941,0.59s-0.533,0.378-0.737,0.521H91.78L91.6,14.839c0.294-0.121,0.597-0.242,0.906-0.363
|
||||
c0.311-0.121,0.643-0.23,0.998-0.329c0.355-0.098,0.733-0.177,1.134-0.238s0.835-0.091,1.304-0.091c0.522,0,1.04,0.059,1.554,0.176
|
||||
s0.974,0.319,1.378,0.606c0.404,0.288,0.731,0.677,0.98,1.168c0.25,0.491,0.374,1.111,0.374,1.859l-0.034,6.168
|
||||
c0,0.136,0.026,0.257,0.08,0.363c0.053,0.105,0.124,0.196,0.215,0.271c0.091,0.076,0.2,0.135,0.329,0.176
|
||||
c0.129,0.042,0.265,0.063,0.408,0.063c0.061,0,0.134-0.01,0.221-0.028s0.182-0.041,0.284-0.068c0.102-0.026,0.202-0.058,0.3-0.096
|
||||
c0.099-0.038,0.189-0.076,0.272-0.113h0.159v0.816c-0.114,0.083-0.26,0.18-0.437,0.289c-0.178,0.109-0.373,0.215-0.584,0.317
|
||||
c-0.212,0.102-0.428,0.188-0.646,0.261c-0.22,0.071-0.424,0.107-0.612,0.107c-0.333,0-0.624-0.038-0.873-0.113
|
||||
c-0.25-0.075-0.458-0.192-0.624-0.352s-0.291-0.364-0.374-0.618c-0.083-0.253-0.125-0.557-0.125-0.912H98.096z M98.085,19.93
|
||||
c-0.756,0-1.444,0.039-2.063,0.119c-0.62,0.079-1.147,0.215-1.582,0.408c-0.435,0.192-0.773,0.455-1.015,0.788
|
||||
c-0.242,0.332-0.363,0.748-0.363,1.247c0,0.416,0.066,0.762,0.198,1.037c0.133,0.276,0.299,0.497,0.499,0.663
|
||||
c0.2,0.167,0.428,0.286,0.681,0.357c0.253,0.072,0.497,0.107,0.731,0.107s0.487-0.024,0.76-0.073
|
||||
c0.271-0.049,0.54-0.125,0.805-0.227c0.265-0.103,0.512-0.232,0.743-0.392c0.23-0.158,0.425-0.352,0.584-0.578L98.085,19.93z"/>
|
||||
<path fill="#1A1A1A" d="M104.468,10.825c0-0.174-0.051-0.313-0.152-0.419c-0.103-0.106-0.24-0.193-0.414-0.261l-1.304-0.556V8.954
|
||||
l4.002-0.431v6.724v0.612c0.317-0.469,0.658-0.839,1.021-1.111c0.363-0.272,0.716-0.476,1.061-0.612
|
||||
c0.344-0.136,0.665-0.223,0.964-0.261c0.298-0.038,0.55-0.057,0.754-0.057c0.733,0,1.387,0.144,1.961,0.431
|
||||
c0.575,0.288,1.061,0.686,1.457,1.196c0.397,0.51,0.701,1.117,0.913,1.82s0.317,1.467,0.317,2.291c0,0.922-0.129,1.785-0.386,2.591
|
||||
c-0.257,0.805-0.635,1.51-1.134,2.114s-1.109,1.081-1.831,1.429s-1.548,0.521-2.478,0.521c-0.393,0-0.793-0.019-1.201-0.057
|
||||
s-0.813-0.099-1.214-0.182s-0.798-0.19-1.19-0.323c-0.393-0.132-0.774-0.296-1.146-0.493V10.825z M106.6,24.113
|
||||
c0.129,0.136,0.301,0.267,0.516,0.392c0.216,0.124,0.442,0.234,0.681,0.328c0.238,0.095,0.473,0.169,0.703,0.222
|
||||
s0.429,0.079,0.596,0.079c0.635,0,1.185-0.13,1.649-0.391c0.465-0.262,0.849-0.612,1.15-1.055c0.303-0.442,0.527-0.953,0.675-1.531
|
||||
s0.222-1.188,0.222-1.831c0-0.71-0.068-1.368-0.204-1.973c-0.137-0.604-0.35-1.13-0.641-1.576
|
||||
c-0.291-0.446-0.664-0.796-1.117-1.049c-0.453-0.253-0.994-0.38-1.621-0.38c-0.189,0-0.399,0.021-0.63,0.062
|
||||
c-0.23,0.042-0.463,0.112-0.697,0.21s-0.463,0.229-0.686,0.391c-0.224,0.163-0.422,0.365-0.596,0.606V24.113z"/>
|
||||
<path fill="#1A1A1A" d="M116.396,25.202l1.53-0.397c0.144-0.037,0.259-0.104,0.346-0.198c0.087-0.094,0.131-0.221,0.131-0.38
|
||||
V10.825c0-0.174-0.05-0.315-0.147-0.425c-0.099-0.109-0.238-0.194-0.42-0.255l-1.497-0.556V8.954l4.207-0.431v15.704
|
||||
c0,0.159,0.047,0.288,0.142,0.386c0.095,0.099,0.206,0.163,0.335,0.192l1.451,0.397v0.714h-6.077V25.202z"/>
|
||||
<path fill="#1A1A1A" d="M134.175,23.161v1.134c-0.265,0.227-0.571,0.453-0.919,0.681c-0.348,0.227-0.729,0.429-1.145,0.606
|
||||
c-0.416,0.178-0.856,0.323-1.321,0.437s-0.943,0.17-1.435,0.17c-0.793,0-1.528-0.133-2.205-0.396
|
||||
c-0.677-0.265-1.263-0.656-1.758-1.174s-0.882-1.154-1.162-1.911c-0.279-0.756-0.419-1.629-0.419-2.619
|
||||
c0-0.861,0.134-1.672,0.402-2.432s0.646-1.423,1.134-1.99s1.077-1.017,1.769-1.35c0.691-0.333,1.457-0.499,2.296-0.499
|
||||
c0.764,0,1.442,0.128,2.036,0.385c0.593,0.257,1.094,0.599,1.502,1.026s0.718,0.922,0.93,1.485s0.317,1.147,0.317,1.752
|
||||
c0,0.075-0.002,0.161-0.006,0.255c-0.004,0.095-0.007,0.193-0.011,0.294c-0.004,0.103-0.014,0.2-0.028,0.295
|
||||
c-0.016,0.095-0.03,0.18-0.046,0.255h-8.062c0.008,1.655,0.361,2.912,1.061,3.771c0.699,0.857,1.71,1.287,3.032,1.287
|
||||
c0.432,0,0.838-0.052,1.22-0.153c0.381-0.103,0.732-0.227,1.054-0.374s0.608-0.305,0.862-0.471
|
||||
c0.253-0.166,0.471-0.321,0.651-0.465H134.175z M131.918,18.535c0-0.529-0.045-1.017-0.136-1.463
|
||||
c-0.091-0.446-0.242-0.831-0.453-1.156c-0.212-0.325-0.484-0.579-0.816-0.76c-0.333-0.182-0.741-0.272-1.225-0.272
|
||||
c-0.438,0-0.84,0.083-1.202,0.249c-0.363,0.167-0.683,0.407-0.958,0.72c-0.276,0.314-0.501,0.697-0.675,1.151
|
||||
s-0.287,0.964-0.34,1.531H131.918z"/>
|
||||
<path fill="#D35320" d="M143.755,21.993c0-0.667-0.093-1.225-0.277-1.672c-0.185-0.446-0.445-0.809-0.781-1.086
|
||||
s-0.745-0.487-1.229-0.628s-1.019-0.235-1.606-0.282v-1.34c0.597-0.057,1.136-0.153,1.619-0.29
|
||||
c0.483-0.136,0.893-0.343,1.229-0.621s0.594-0.637,0.774-1.08c0.181-0.442,0.271-1.002,0.271-1.679v-3.302
|
||||
c0-0.988,0.136-1.832,0.409-2.533c0.272-0.701,0.661-1.272,1.165-1.714c0.504-0.442,1.111-0.764,1.82-0.967
|
||||
c0.71-0.202,1.502-0.303,2.375-0.303v1.256c-0.386,0.028-0.787,0.083-1.203,0.162c-0.416,0.08-0.794,0.231-1.134,0.452
|
||||
c-0.34,0.221-0.619,0.536-0.838,0.945s-0.327,0.958-0.327,1.644v3.02c0,0.988-0.101,1.801-0.303,2.441
|
||||
c-0.201,0.64-0.483,1.162-0.844,1.566c-0.361,0.405-0.79,0.715-1.285,0.931c-0.496,0.217-1.042,0.391-1.638,0.522v0.438
|
||||
c0.596,0.132,1.142,0.306,1.638,0.522c0.495,0.217,0.924,0.525,1.285,0.924c0.36,0.4,0.643,0.923,0.844,1.566
|
||||
c0.202,0.645,0.303,1.461,0.303,2.448v3.006c0,0.687,0.108,1.234,0.327,1.644s0.498,0.727,0.838,0.952s0.718,0.379,1.134,0.459
|
||||
s0.817,0.134,1.203,0.162v1.27c-0.873,0-1.665-0.099-2.375-0.296c-0.709-0.197-1.316-0.518-1.82-0.959
|
||||
c-0.504-0.442-0.893-1.015-1.165-1.715c-0.273-0.701-0.409-1.56-0.409-2.575V21.993z"/>
|
||||
<path fill="#D35320" d="M156.387,29.557c0.395-0.028,0.798-0.082,1.21-0.162c0.411-0.08,0.789-0.233,1.134-0.459
|
||||
c0.344-0.226,0.625-0.543,0.844-0.952s0.327-0.957,0.327-1.644v-3.006c0-0.987,0.102-1.804,0.303-2.448
|
||||
c0.201-0.644,0.48-1.166,0.838-1.566c0.356-0.399,0.785-0.707,1.285-0.924c0.499-0.216,1.048-0.39,1.644-0.522v-0.438
|
||||
c-0.596-0.131-1.145-0.305-1.644-0.522c-0.5-0.216-0.929-0.526-1.285-0.931c-0.357-0.404-0.637-0.926-0.838-1.566
|
||||
c-0.201-0.64-0.303-1.453-0.303-2.441v-3.02c0-0.687-0.108-1.235-0.327-1.644s-0.5-0.724-0.844-0.945
|
||||
c-0.345-0.221-0.723-0.372-1.134-0.452c-0.412-0.08-0.815-0.134-1.21-0.162V4.497c0.882,0,1.678,0.101,2.388,0.303
|
||||
c0.709,0.203,1.316,0.525,1.82,0.967c0.504,0.442,0.893,1.014,1.165,1.714c0.273,0.701,0.41,1.545,0.41,2.533v3.302
|
||||
c0,0.677,0.09,1.237,0.271,1.679c0.181,0.442,0.438,0.802,0.774,1.08s0.743,0.484,1.223,0.621c0.479,0.137,1.021,0.233,1.625,0.29
|
||||
v1.34c-0.597,0.047-1.134,0.141-1.612,0.282c-0.479,0.141-0.889,0.351-1.229,0.628c-0.341,0.277-0.601,0.64-0.781,1.086
|
||||
c-0.181,0.447-0.271,1.005-0.271,1.672v3.288c0,1.016-0.137,1.874-0.41,2.575c-0.272,0.7-0.661,1.272-1.165,1.715
|
||||
c-0.504,0.441-1.111,0.762-1.82,0.959c-0.71,0.197-1.506,0.296-2.388,0.296V29.557z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 14 KiB |
BIN
src/Orchard.Web/Media/Default/Images/Marina-Wide.jpg
Normal file
After Width: | Height: | Size: 3.1 MiB |
BIN
src/Orchard.Web/Media/Default/Images/bar-refaeli-33.jpg
Normal file
After Width: | Height: | Size: 418 KiB |
After Width: | Height: | Size: 310 KiB |
BIN
src/Orchard.Web/Media/Default/Images/hq-landscape-041.jpg
Normal file
After Width: | Height: | Size: 331 KiB |
BIN
src/Orchard.Web/Media/Default/Slides/IMG_2812.JPG
Normal file
After Width: | Height: | Size: 2.9 MiB |
BIN
src/Orchard.Web/Media/Default/Slides/IMG_2819.JPG
Normal file
After Width: | Height: | Size: 3.1 MiB |
BIN
src/Orchard.Web/Media/Default/Slides/IMG_2834.JPG
Normal file
After Width: | Height: | Size: 3.3 MiB |
BIN
src/Orchard.Web/Media/Default/Slides/IMG_2836.JPG
Normal file
After Width: | Height: | Size: 2.6 MiB |
BIN
src/Orchard.Web/Media/Default/Slides/IMG_2838.JPG
Normal file
After Width: | Height: | Size: 2.4 MiB |
BIN
src/Orchard.Web/Media/Default/Slides/IMG_2841.JPG
Normal file
After Width: | Height: | Size: 2.3 MiB |
BIN
src/Orchard.Web/Media/Default/Slides/IMG_2844.JPG
Normal file
After Width: | Height: | Size: 3.4 MiB |
BIN
src/Orchard.Web/Media/Default/Slides/IMG_2847.JPG
Normal file
After Width: | Height: | Size: 2.7 MiB |
24
src/Orchard.Web/Modules/IDeliverable.Slides/AdminMenu.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using Orchard;
|
||||
using Orchard.Security;
|
||||
using Orchard.UI.Navigation;
|
||||
|
||||
namespace IDeliverable.Slides
|
||||
{
|
||||
public class AdminMenu : Component, INavigationProvider
|
||||
{
|
||||
public string MenuName => "admin";
|
||||
|
||||
public void GetNavigation(NavigationBuilder builder)
|
||||
{
|
||||
builder.Add(T("Settings"),
|
||||
menu => menu
|
||||
.Add(T("Slides"), "7", slides => slides
|
||||
.Action("Index", "SlideShowProfile", new { area = "IDeliverable.Slides" })
|
||||
.Permission(StandardPermissions.SiteOwner)
|
||||
.Add(T("Profiles"), "1", profiles => profiles
|
||||
.Action("Index", "SlideShowProfile", new { area = "IDeliverable.Slides" })
|
||||
.Permission(StandardPermissions.SiteOwner)
|
||||
.LocalNav())));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,840 @@
|
||||
#: ~/Modules/IDeliverable.Slides/Module.txt
|
||||
#| msgid "Name"
|
||||
msgid "Slides"
|
||||
msgstr "Slides"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Module.txt
|
||||
#| msgid "Author"
|
||||
msgid "IDeliverable"
|
||||
msgstr "IDeliverable"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Module.txt
|
||||
#| msgid "Website"
|
||||
msgid "http://www.ideliverable.com"
|
||||
msgstr "http://www.ideliverable.com"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Module.txt
|
||||
#| msgid "Description"
|
||||
msgid "Provides slide show features, enabling users to turn content items into slide shows and add slide show elements to layouts."
|
||||
msgstr "Provides slide show features, enabling users to turn content items into slide shows and add slide show elements to layouts."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Module.txt
|
||||
#| msgid "IDeliverable.Slides.Name"
|
||||
msgid "Slides"
|
||||
msgstr "Slides"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Module.txt
|
||||
#| msgid "IDeliverable.Slides.Description"
|
||||
msgid "Turn content items into slide shows."
|
||||
msgstr "Turn content items into slide shows."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Module.txt
|
||||
#| msgid "IDeliverable.Slides.Category"
|
||||
msgid "Content"
|
||||
msgstr "Content"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Module.txt
|
||||
#| msgid "IDeliverable.Slides.Projections.Name"
|
||||
msgid "Projection Slides"
|
||||
msgstr "Projection Slides"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Module.txt
|
||||
#| msgid "IDeliverable.Slides.Projections.Description"
|
||||
msgid "Adds a Projection Slides Provider to the system."
|
||||
msgstr "Adds a Projection Slides Provider to the system."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Module.txt
|
||||
#| msgid "IDeliverable.Slides.Projections.Category"
|
||||
msgid "Content"
|
||||
msgstr "Content"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Module.txt
|
||||
#| msgid "IDeliverable.Slides.Lists.Name"
|
||||
msgid "List Slides"
|
||||
msgstr "List Slides"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Module.txt
|
||||
#| msgid "IDeliverable.Slides.Lists.Description"
|
||||
msgid "Adds a List Slides Provider to the system."
|
||||
msgstr "Adds a List Slides Provider to the system."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Module.txt
|
||||
#| msgid "IDeliverable.Slides.Lists.Category"
|
||||
msgid "Content"
|
||||
msgstr "Content"
|
||||
|
||||
#: IDeliverable.Slides.AdminMenu
|
||||
#| msgid "Settings"
|
||||
msgid "Settings"
|
||||
msgstr "Settings"
|
||||
|
||||
#: IDeliverable.Slides.AdminMenu
|
||||
#| msgid "Slides"
|
||||
msgid "Slides"
|
||||
msgstr "Slides"
|
||||
|
||||
#: IDeliverable.Slides.AdminMenu
|
||||
#| msgid "Profiles"
|
||||
msgid "Profiles"
|
||||
msgstr "Profiles"
|
||||
|
||||
#: IDeliverable.Slides.Controllers.SlideController
|
||||
#| msgid "That slide has been updated."
|
||||
msgid "That slide has been updated."
|
||||
msgstr "That slide has been updated."
|
||||
|
||||
#: IDeliverable.Slides.Controllers.SlideFactoryController
|
||||
#| msgid "No images were selected."
|
||||
msgid "No images were selected."
|
||||
msgstr "No images were selected."
|
||||
|
||||
#: IDeliverable.Slides.Controllers.SlideFactoryController
|
||||
#| msgid "No content items were selected."
|
||||
msgid "No content items were selected."
|
||||
msgstr "No content items were selected."
|
||||
|
||||
#: IDeliverable.Slides.Controllers.SlideShowElementController
|
||||
#| msgid "That slide has been deleted."
|
||||
msgid "That slide has been deleted."
|
||||
msgstr "That slide has been deleted."
|
||||
|
||||
#: IDeliverable.Slides.Controllers.SlideShowPartController
|
||||
#| msgid "That slide has been deleted."
|
||||
msgid "That slide has been deleted."
|
||||
msgstr "That slide has been deleted."
|
||||
|
||||
#: IDeliverable.Slides.Controllers.SlideShowProfileController
|
||||
#| msgid "That slide show profile has been created."
|
||||
msgid "That slide show profile has been created."
|
||||
msgstr "That slide show profile has been created."
|
||||
|
||||
#: IDeliverable.Slides.Controllers.SlideShowProfileController
|
||||
#| msgid "That slide show profile has been updated."
|
||||
msgid "That slide show profile has been updated."
|
||||
msgstr "That slide show profile has been updated."
|
||||
|
||||
#: IDeliverable.Slides.Controllers.SlideShowProfileController
|
||||
#| msgid "That slide show profile has been deleted."
|
||||
msgid "That slide show profile has been deleted."
|
||||
msgstr "That slide show profile has been deleted."
|
||||
|
||||
#: IDeliverable.Slides.Providers.DefaultSlidesProvider
|
||||
#| msgid "Default"
|
||||
msgid "Default"
|
||||
msgstr "Default"
|
||||
|
||||
#: IDeliverable.Slides.Providers.ListSlidesProvider
|
||||
#| msgid "List"
|
||||
msgid "List"
|
||||
msgstr "List"
|
||||
|
||||
#: IDeliverable.Slides.Providers.ProjectionSlidesProvider
|
||||
#| msgid "Projection"
|
||||
msgid "Projection"
|
||||
msgstr "Projection"
|
||||
|
||||
#: IDeliverable.Slides.SlideShowPlayerEngines.Bootstrap.Bootstrap
|
||||
#| msgid "Bootstrap"
|
||||
msgid "Bootstrap"
|
||||
msgstr "Bootstrap"
|
||||
|
||||
#: IDeliverable.Slides.SlideShowPlayerEngines.JCarousel.JCarousel
|
||||
#| msgid "JCarousel"
|
||||
msgid "JCarousel"
|
||||
msgstr "JCarousel"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/Engines.Bootstrap.cshtml
|
||||
#| msgid "Previous"
|
||||
msgid "Previous"
|
||||
msgstr "Previous"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/Engines.Bootstrap.cshtml
|
||||
#| msgid "Next"
|
||||
msgid "Next"
|
||||
msgstr "Next"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/Engines.JCarousel.cshtml
|
||||
#| msgid "‹"
|
||||
msgid "‹"
|
||||
msgstr "‹"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/Engines.JCarousel.cshtml
|
||||
#| msgid "›"
|
||||
msgid "›"
|
||||
msgstr "›"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/Parts.SlideShow.Summary.cshtml
|
||||
#| msgid "Prev"
|
||||
msgid "Prev"
|
||||
msgstr "Prev"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/Parts.SlideShow.Summary.cshtml
|
||||
#| msgid "Next"
|
||||
msgid "Next"
|
||||
msgstr "Next"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/Slides.InvalidLicense.cshtml
|
||||
#| msgid "No license key or an invalid license key for IDeliverable.Slides was provided."
|
||||
msgid "No license key or an invalid license key for IDeliverable.Slides was provided."
|
||||
msgstr "No license key or an invalid license key for IDeliverable.Slides was provided."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlidesFactorySelector.cshtml
|
||||
#| msgid "Add Slides"
|
||||
msgid "Add Slides"
|
||||
msgstr "Add Slides"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlidesFactorySelector.cshtml
|
||||
#| msgid "Create Slide"
|
||||
msgid "Create Slide"
|
||||
msgstr "Create Slide"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlidesFactorySelector.cshtml
|
||||
#| msgid "Create a new regular, free-form slide."
|
||||
msgid "Create a new regular, free-form slide."
|
||||
msgstr "Create a new regular, free-form slide."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlidesFactorySelector.cshtml
|
||||
#| msgid "Create Slides From Media"
|
||||
msgid "Create Slides From Media"
|
||||
msgstr "Create Slides From Media"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlidesFactorySelector.cshtml
|
||||
#| msgid "Creates multiple slides from media elements."
|
||||
msgid "Creates multiple slides from media elements."
|
||||
msgstr "Creates multiple slides from media elements."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlidesFactorySelector.cshtml
|
||||
#| msgid "Create Slides From Content Items"
|
||||
msgid "Create Slides From Content Items"
|
||||
msgstr "Create Slides From Content Items"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlidesFactorySelector.cshtml
|
||||
#| msgid "Creates multiple slides from content item elements."
|
||||
msgid "Creates multiple slides from content item elements."
|
||||
msgstr "Creates multiple slides from content item elements."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/DefinitionTemplates/SlideShowSettings.cshtml
|
||||
#| msgid "Engine"
|
||||
msgid "Engine"
|
||||
msgstr "Engine"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/DefinitionTemplates/SlideShowSettings.cshtml
|
||||
#| msgid "The slide show engine to use to present the slides."
|
||||
msgid "The slide show engine to use to present the slides."
|
||||
msgstr "The slide show engine to use to present the slides."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Elements.SlideShow.cshtml
|
||||
#| msgid "Slide Show Profile"
|
||||
msgid "Slide Show Profile"
|
||||
msgstr "Slide Show Profile"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Elements.SlideShow.cshtml
|
||||
#| msgid "(Default)"
|
||||
msgid "(Default)"
|
||||
msgstr "(Default)"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Elements.SlideShow.cshtml
|
||||
#| msgid "Select the slide show player profile to use when presenting the slides."
|
||||
msgid "Select the slide show player profile to use when presenting the slides."
|
||||
msgstr "Select the slide show player profile to use when presenting the slides."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Elements.SlideShow.cshtml
|
||||
#| msgid "Slides Provider"
|
||||
msgid "Slides Provider"
|
||||
msgstr "Slides Provider"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Elements.SlideShow.cshtml
|
||||
#| msgid "Select the provider that will provide the slides to the slide show."
|
||||
msgid "Select the provider that will provide the slides to the slide show."
|
||||
msgstr "Select the provider that will provide the slides to the slide show."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.Bootstrap.cshtml
|
||||
#| msgid "Interval"
|
||||
msgid "Interval"
|
||||
msgstr "Interval"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.Bootstrap.cshtml
|
||||
#| msgid "The interval in milliseconds to wait before showing the next slide."
|
||||
msgid "The interval in milliseconds to wait before showing the next slide."
|
||||
msgstr "The interval in milliseconds to wait before showing the next slide."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.Bootstrap.cshtml
|
||||
#| msgid "Show Controls"
|
||||
msgid "Show Controls"
|
||||
msgstr "Show Controls"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.Bootstrap.cshtml
|
||||
#| msgid "Check this option to show the next and prev control buttons."
|
||||
msgid "Check this option to show the next and prev control buttons."
|
||||
msgstr "Check this option to show the next and prev control buttons."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.Bootstrap.cshtml
|
||||
#| msgid "Show Indicators"
|
||||
msgid "Show Indicators"
|
||||
msgstr "Show Indicators"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.Bootstrap.cshtml
|
||||
#| msgid "Check this option to the show indicators."
|
||||
msgid "Check this option to the show indicators."
|
||||
msgstr "Check this option to the show indicators."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.Bootstrap.cshtml
|
||||
#| msgid "Wrap"
|
||||
msgid "Wrap"
|
||||
msgstr "Wrap"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.Bootstrap.cshtml
|
||||
#| msgid "Whether the carousel should cycle continuously or have hard stops."
|
||||
msgid "Whether the carousel should cycle continuously or have hard stops."
|
||||
msgstr "Whether the carousel should cycle continuously or have hard stops."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.Bootstrap.cshtml
|
||||
#| msgid "Keyboard"
|
||||
msgid "Keyboard"
|
||||
msgstr "Keyboard"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.Bootstrap.cshtml
|
||||
#| msgid "Whether the carousel should react to keyboard events."
|
||||
msgid "Whether the carousel should react to keyboard events."
|
||||
msgstr "Whether the carousel should react to keyboard events."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.Bootstrap.cshtml
|
||||
#| msgid "Pause"
|
||||
msgid "Pause"
|
||||
msgstr "Pause"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.Bootstrap.cshtml
|
||||
#| msgid "Pauses the cycling of the carousel on mouseenter and resumes the cycling of the carousel on mouseleave."
|
||||
msgid "Pauses the cycling of the carousel on mouseenter and resumes the cycling of the carousel on mouseleave."
|
||||
msgstr "Pauses the cycling of the carousel on mouseenter and resumes the cycling of the carousel on mouseleave."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.JCarousel.cshtml
|
||||
#| msgid "Auto Start"
|
||||
msgid "Auto Start"
|
||||
msgstr "Auto Start"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.JCarousel.cshtml
|
||||
#| msgid "Check this option to have the slide show start automatically."
|
||||
msgid "Check this option to have the slide show start automatically."
|
||||
msgstr "Check this option to have the slide show start automatically."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.JCarousel.cshtml
|
||||
#| msgid "Interval"
|
||||
msgid "Interval"
|
||||
msgstr "Interval"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.JCarousel.cshtml
|
||||
#| msgid "The interval in milliseconds to wait before showing the next slide."
|
||||
msgid "The interval in milliseconds to wait before showing the next slide."
|
||||
msgstr "The interval in milliseconds to wait before showing the next slide."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.JCarousel.cshtml
|
||||
#| msgid "Show Controls"
|
||||
msgid "Show Controls"
|
||||
msgstr "Show Controls"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.JCarousel.cshtml
|
||||
#| msgid "Check this option to show the next and prev control buttons."
|
||||
msgid "Check this option to show the next and prev control buttons."
|
||||
msgstr "Check this option to show the next and prev control buttons."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.JCarousel.cshtml
|
||||
#| msgid "Show Pagination"
|
||||
msgid "Show Pagination"
|
||||
msgstr "Show Pagination"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.JCarousel.cshtml
|
||||
#| msgid "Check this option to the show pager buttons."
|
||||
msgid "Check this option to the show pager buttons."
|
||||
msgstr "Check this option to the show pager buttons."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.JCarousel.cshtml
|
||||
#| msgid "Use Transitions"
|
||||
msgid "Use Transitions"
|
||||
msgstr "Use Transitions"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.JCarousel.cshtml
|
||||
#| msgid "Check this option to use transitions. Note: this only works for browsers that support CSS transforms."
|
||||
msgid "Check this option to use transitions. Note: this only works for browsers that support CSS transforms."
|
||||
msgstr "Check this option to use transitions. Note: this only works for browsers that support CSS transforms."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.JCarousel.cshtml
|
||||
#| msgid "Vertical"
|
||||
msgid "Vertical"
|
||||
msgstr "Vertical"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.JCarousel.cshtml
|
||||
#| msgid "Whether the carousel appears in vertical orientation. Changes the carousel from a left/right style to a up/down style carousel."
|
||||
msgid "Whether the carousel appears in vertical orientation. Changes the carousel from a left/right style to a up/down style carousel."
|
||||
msgstr "Whether the carousel appears in vertical orientation. Changes the carousel from a left/right style to a up/down style carousel."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.JCarousel.cshtml
|
||||
#| msgid "Center"
|
||||
msgid "Center"
|
||||
msgstr "Center"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.JCarousel.cshtml
|
||||
#| msgid "Wether the targeted item should be centered inside the root element. Note: This feature is experimental and may not work with all setups."
|
||||
msgid "Wether the targeted item should be centered inside the root element. Note: This feature is experimental and may not work with all setups."
|
||||
msgstr "Wether the targeted item should be centered inside the root element. Note: This feature is experimental and may not work with all setups."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.JCarousel.cshtml
|
||||
#| msgid "Easing"
|
||||
msgid "Easing"
|
||||
msgstr "Easing"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.JCarousel.cshtml
|
||||
#| msgid "The transition-timing-function."
|
||||
msgid "The transition-timing-function."
|
||||
msgstr "The transition-timing-function."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.JCarousel.cshtml
|
||||
#| msgid "Wrap"
|
||||
msgid "Wrap"
|
||||
msgstr "Wrap"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Engines.JCarousel.cshtml
|
||||
#| msgid "Specify whether to wrap at the first or last item (or both) and jump back to the start/end."
|
||||
msgid "Specify whether to wrap at the first or last item (or both) and jump back to the start/end."
|
||||
msgstr "Specify whether to wrap at the first or last item (or both) and jump back to the start/end."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Parts.Slides.License.cshtml
|
||||
#| msgid "Slide Show License"
|
||||
msgid "Slide Show License"
|
||||
msgstr "Slide Show License"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Parts.Slides.License.cshtml
|
||||
#| msgid "License Key"
|
||||
msgid "License Key"
|
||||
msgstr "License Key"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Parts.Slides.License.cshtml
|
||||
#| msgid "The license key associated with the public hostname of this website."
|
||||
msgid "The license key associated with the public hostname of this website."
|
||||
msgstr "The license key associated with the public hostname of this website."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Parts.Slides.License.cshtml
|
||||
#| msgid "For pricing and licensing options, please visit our <a href=\"http://www.ideliverable.com/products/ideliverable-slides\">product page</a>."
|
||||
msgid "For pricing and licensing options, please visit our <a href=\"http://www.ideliverable.com/products/ideliverable-slides\">product page</a>."
|
||||
msgstr "For pricing and licensing options, please visit our <a href=\"http://www.ideliverable.com/products/ideliverable-slides\">product page</a>."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Parts.Slides.License.cshtml
|
||||
#| msgid "For technical support, please visit our <a href=\"http://www.ideliverable.com/support\">support page</a>."
|
||||
msgid "For technical support, please visit our <a href=\"http://www.ideliverable.com/support\">support page</a>."
|
||||
msgstr "For technical support, please visit our <a href=\"http://www.ideliverable.com/support\">support page</a>."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Parts.SlideShow.cshtml
|
||||
#| msgid "Slide Show Profile"
|
||||
msgid "Slide Show Profile"
|
||||
msgstr "Slide Show Profile"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Parts.SlideShow.cshtml
|
||||
#| msgid "(Default)"
|
||||
msgid "(Default)"
|
||||
msgstr "(Default)"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Parts.SlideShow.cshtml
|
||||
#| msgid "Slides Provider"
|
||||
msgid "Slides Provider"
|
||||
msgstr "Slides Provider"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/Parts.SlideShow.cshtml
|
||||
#| msgid "Select the provider that will provide the slides to the slide show."
|
||||
msgid "Select the provider that will provide the slides to the slide show."
|
||||
msgstr "Select the provider that will provide the slides to the slide show."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlideShowProfileViewModel.cshtml
|
||||
#| msgid "Profile Name"
|
||||
msgid "Profile Name"
|
||||
msgstr "Profile Name"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlideShowProfileViewModel.cshtml
|
||||
#| msgid "Engine"
|
||||
msgid "Engine"
|
||||
msgstr "Engine"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlideShowProfileViewModel.cshtml
|
||||
#| msgid "The slide show engine to use to present the slides."
|
||||
msgid "The slide show engine to use to present the slides."
|
||||
msgstr "The slide show engine to use to present the slides."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlidesProviders.List.cshtml
|
||||
#| msgid "List"
|
||||
msgid "List"
|
||||
msgstr "List"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlidesProviders.List.cshtml
|
||||
#| msgid "Select the list to project as slides."
|
||||
msgid "Select the list to project as slides."
|
||||
msgstr "Select the list to project as slides."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlidesProviders.List.cshtml
|
||||
#| msgid "Display Type"
|
||||
msgid "Display Type"
|
||||
msgstr "Display Type"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlidesProviders.List.cshtml
|
||||
#| msgid "The display type to use when rendering each content item slide."
|
||||
msgid "The display type to use when rendering each content item slide."
|
||||
msgstr "The display type to use when rendering each content item slide."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlidesProviders.Projection.cshtml
|
||||
#| msgid "No Queryies have been created yet."
|
||||
msgid "No Queryies have been created yet."
|
||||
msgstr "No Queryies have been created yet."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlidesProviders.Projection.cshtml
|
||||
#| msgid "Query"
|
||||
msgid "Query"
|
||||
msgstr "Query"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlidesProviders.Projection.cshtml
|
||||
#| msgid "Select the query to render as a projection of slides."
|
||||
msgid "Select the query to render as a projection of slides."
|
||||
msgstr "Select the query to render as a projection of slides."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlidesProviders.Projection.cshtml
|
||||
#| msgid "Display Type"
|
||||
msgid "Display Type"
|
||||
msgstr "Display Type"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlidesProviders.Projection.cshtml
|
||||
#| msgid "The display type to use when rendering each content item slide."
|
||||
msgid "The display type to use when rendering each content item slide."
|
||||
msgstr "The display type to use when rendering each content item slide."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlidesProviders.Slides.Element.cshtml
|
||||
#| msgid "No slides have been added yet."
|
||||
msgid "No slides have been added yet."
|
||||
msgstr "No slides have been added yet."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlidesProviders.Slides.Element.cshtml
|
||||
#| msgid "You have unsaved changes."
|
||||
msgid "You have unsaved changes."
|
||||
msgstr "You have unsaved changes."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlidesProviders.Slides.Element.cshtml
|
||||
#| msgid "Edit"
|
||||
msgid "Edit"
|
||||
msgstr "Edit"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlidesProviders.Slides.Element.cshtml
|
||||
#| msgid " | "
|
||||
msgid " | "
|
||||
msgstr " | "
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlidesProviders.Slides.Element.cshtml
|
||||
#| msgid "Delete"
|
||||
msgid "Delete"
|
||||
msgstr "Delete"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlidesProviders.Slides.Element.cshtml
|
||||
#| msgid "Are you sure you want to delete this slide?"
|
||||
msgid "Are you sure you want to delete this slide?"
|
||||
msgstr "Are you sure you want to delete this slide?"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlidesProviders.Slides.Part.cshtml
|
||||
#| msgid "You need to save your content item before you can add slides."
|
||||
msgid "You need to save your content item before you can add slides."
|
||||
msgstr "You need to save your content item before you can add slides."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlidesProviders.Slides.Part.cshtml
|
||||
#| msgid "No slides have been added yet."
|
||||
msgid "No slides have been added yet."
|
||||
msgstr "No slides have been added yet."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlidesProviders.Slides.Part.cshtml
|
||||
#| msgid "You have unsaved changes."
|
||||
msgid "You have unsaved changes."
|
||||
msgstr "You have unsaved changes."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlidesProviders.Slides.Part.cshtml
|
||||
#| msgid "Edit"
|
||||
msgid "Edit"
|
||||
msgstr "Edit"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlidesProviders.Slides.Part.cshtml
|
||||
#| msgid " | "
|
||||
msgid " | "
|
||||
msgstr " | "
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlidesProviders.Slides.Part.cshtml
|
||||
#| msgid "Delete"
|
||||
msgid "Delete"
|
||||
msgstr "Delete"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/EditorTemplates/SlidesProviders.Slides.Part.cshtml
|
||||
#| msgid "Are you sure you want to delete this slide?"
|
||||
msgid "Are you sure you want to delete this slide?"
|
||||
msgstr "Are you sure you want to delete this slide?"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/Elements/SlideShow.Design.cshtml
|
||||
#| msgid "No slides have been added yet."
|
||||
msgid "No slides have been added yet."
|
||||
msgstr "No slides have been added yet."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/Slide/Edit.cshtml
|
||||
#| msgid "Edit Slide"
|
||||
msgid "Edit Slide"
|
||||
msgstr "Edit Slide"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/Slide/Edit.cshtml
|
||||
#| msgid "Save"
|
||||
msgid "Save"
|
||||
msgstr "Save"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/Slide/Edit.cshtml
|
||||
#| msgid "Cancel"
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideFactory/ContentSlides.cshtml
|
||||
#| msgid "Create Content Slides"
|
||||
msgid "Create Content Slides"
|
||||
msgstr "Create Content Slides"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideFactory/ContentSlides.cshtml
|
||||
#| msgid "Content"
|
||||
msgid "Content"
|
||||
msgstr "Content"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideFactory/ContentSlides.cshtml
|
||||
#| msgid "Display Type"
|
||||
msgid "Display Type"
|
||||
msgstr "Display Type"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideFactory/ContentSlides.cshtml
|
||||
#| msgid "The display type to use when rendering the selected content items. The default Detail display type will be used when left empty."
|
||||
msgid "The display type to use when rendering the selected content items. The default Detail display type will be used when left empty."
|
||||
msgstr "The display type to use when rendering the selected content items. The default Detail display type will be used when left empty."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideFactory/ContentSlides.cshtml
|
||||
#| msgid "Save"
|
||||
msgid "Save"
|
||||
msgstr "Save"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideFactory/ContentSlides.cshtml
|
||||
#| msgid "Cancel"
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideFactory/Create.cshtml
|
||||
#| msgid "Create Slide"
|
||||
msgid "Create Slide"
|
||||
msgstr "Create Slide"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideFactory/Create.cshtml
|
||||
#| msgid "Create"
|
||||
msgid "Create"
|
||||
msgstr "Create"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideFactory/Create.cshtml
|
||||
#| msgid "Cancel"
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideFactory/ImageSlides.cshtml
|
||||
#| msgid "Create Image Slides"
|
||||
msgid "Create Image Slides"
|
||||
msgstr "Create Image Slides"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideFactory/ImageSlides.cshtml
|
||||
#| msgid "Images"
|
||||
msgid "Images"
|
||||
msgstr "Images"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideFactory/ImageSlides.cshtml
|
||||
#| msgid "Save"
|
||||
msgid "Save"
|
||||
msgstr "Save"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideFactory/ImageSlides.cshtml
|
||||
#| msgid "Cancel"
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideFactory/MediaSlides.cshtml
|
||||
#| msgid "Create Image Slides"
|
||||
msgid "Create Image Slides"
|
||||
msgstr "Create Image Slides"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideFactory/MediaSlides.cshtml
|
||||
#| msgid "Images"
|
||||
msgid "Images"
|
||||
msgstr "Images"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideFactory/MediaSlides.cshtml
|
||||
#| msgid "Save"
|
||||
msgid "Save"
|
||||
msgstr "Save"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideFactory/MediaSlides.cshtml
|
||||
#| msgid "Cancel"
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowElement/Browse.cshtml
|
||||
#| msgid "Add Slides"
|
||||
msgid "Add Slides"
|
||||
msgstr "Add Slides"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowElement/Browse.cshtml
|
||||
#| msgid "Create Slide"
|
||||
msgid "Create Slide"
|
||||
msgstr "Create Slide"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowElement/Browse.cshtml
|
||||
#| msgid "Create a new regular, free-form slide."
|
||||
msgid "Create a new regular, free-form slide."
|
||||
msgstr "Create a new regular, free-form slide."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowElement/Browse.cshtml
|
||||
#| msgid "Create Image Slides"
|
||||
msgid "Create Image Slides"
|
||||
msgstr "Create Image Slides"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowElement/Browse.cshtml
|
||||
#| msgid "Creates multiple slides based on image elements."
|
||||
msgid "Creates multiple slides based on image elements."
|
||||
msgstr "Creates multiple slides based on image elements."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowElement/Browse.cshtml
|
||||
#| msgid "Create Content Slides"
|
||||
msgid "Create Content Slides"
|
||||
msgstr "Create Content Slides"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowElement/Browse.cshtml
|
||||
#| msgid "Creates multiple slides based on content item elements."
|
||||
msgid "Creates multiple slides based on content item elements."
|
||||
msgstr "Creates multiple slides based on content item elements."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowElement/Browse.cshtml
|
||||
#| msgid "Cancel"
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowElement/Create.cshtml
|
||||
#| msgid "Create Slide"
|
||||
msgid "Create Slide"
|
||||
msgstr "Create Slide"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowElement/Create.cshtml
|
||||
#| msgid "Create"
|
||||
msgid "Create"
|
||||
msgstr "Create"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowElement/Create.cshtml
|
||||
#| msgid "Cancel"
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowElement/Edit.cshtml
|
||||
#| msgid "Edit Slide {0}"
|
||||
msgid "Edit Slide {0}"
|
||||
msgstr "Edit Slide {0}"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowElement/Edit.cshtml
|
||||
#| msgid "Save"
|
||||
msgid "Save"
|
||||
msgstr "Save"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowElement/Edit.cshtml
|
||||
#| msgid "Cancel"
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowProfile/Create.cshtml
|
||||
#| msgid "Create Slide Show Profile"
|
||||
msgid "Create Slide Show Profile"
|
||||
msgstr "Create Slide Show Profile"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowProfile/Create.cshtml
|
||||
#| msgid "Create"
|
||||
msgid "Create"
|
||||
msgstr "Create"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowProfile/Create.cshtml
|
||||
#| msgid "Cancel"
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowProfile/Edit.cshtml
|
||||
#| msgid "Edit Slide Show Profile"
|
||||
msgid "Edit Slide Show Profile"
|
||||
msgstr "Edit Slide Show Profile"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowProfile/Edit.cshtml
|
||||
#| msgid "Save"
|
||||
msgid "Save"
|
||||
msgstr "Save"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowProfile/Edit.cshtml
|
||||
#| msgid "Back"
|
||||
msgid "Back"
|
||||
msgstr "Back"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowProfile/Index.cshtml
|
||||
#| msgid "Slide Show Profiles"
|
||||
msgid "Slide Show Profiles"
|
||||
msgstr "Slide Show Profiles"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowProfile/Index.cshtml
|
||||
#| msgid "Create Profile"
|
||||
msgid "Create Profile"
|
||||
msgstr "Create Profile"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowProfile/Index.cshtml
|
||||
#| msgid "Profile Name"
|
||||
msgid "Profile Name"
|
||||
msgstr "Profile Name"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowProfile/Index.cshtml
|
||||
#| msgid "Engine"
|
||||
msgid "Engine"
|
||||
msgstr "Engine"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowProfile/Index.cshtml
|
||||
#| msgid "No profiles have been defined yet."
|
||||
msgid "No profiles have been defined yet."
|
||||
msgstr "No profiles have been defined yet."
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowProfile/Index.cshtml
|
||||
#| msgid "Edit"
|
||||
msgid "Edit"
|
||||
msgstr "Edit"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowProfile/Index.cshtml
|
||||
#| msgid " | "
|
||||
msgid " | "
|
||||
msgstr " | "
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowProfile/Index.cshtml
|
||||
#| msgid "Delete"
|
||||
msgid "Delete"
|
||||
msgstr "Delete"
|
||||
|
||||
#: ~/Modules/IDeliverable.Slides/Views/SlideShowProfile/Index.cshtml
|
||||
#| msgid "Are you sure you want to delete this profile?"
|
||||
msgid "Are you sure you want to delete this profile?"
|
||||
msgstr "Are you sure you want to delete this profile?"
|
||||
|
||||
#: IDeliverable.Slides.Controllers.SlideShowElementController
|
||||
#| msgid "That slide has been added."
|
||||
msgid "That slide has been added."
|
||||
msgstr "That slide has been added."
|
||||
|
||||
#: IDeliverable.Slides.Controllers.SlideShowElementController
|
||||
#| msgid "Those slides have been added."
|
||||
msgid "Those slides have been added."
|
||||
msgstr "Those slides have been added."
|
||||
|
||||
#: IDeliverable.Slides.Controllers.SlideShowPartController
|
||||
#| msgid "That slide has been added."
|
||||
msgid "That slide has been added."
|
||||
msgstr "That slide has been added."
|
||||
|
||||
#: IDeliverable.Slides.Controllers.SlideShowPartController
|
||||
#| msgid "Those slides have been added."
|
||||
msgid "Those slides have been added."
|
||||
msgstr "Those slides have been added."
|
||||
|
@@ -0,0 +1,87 @@
|
||||
(function ($)
|
||||
{
|
||||
// Slides preview.
|
||||
var applyCssScale = function (element, scale, translate)
|
||||
{
|
||||
var browserPrefixes = ["", "-ms-", "-moz-", "-webkit-", "-o-"],
|
||||
offset = ((1 - scale) * 50) + "%",
|
||||
scaleString = (translate !== false ? "translate(-" + offset + ", -" + offset + ") " : "") + "scale(" + scale + "," + scale + ")";
|
||||
$(browserPrefixes).each(function ()
|
||||
{
|
||||
element
|
||||
.css(this + "transform", scaleString);
|
||||
});
|
||||
element
|
||||
.data({ scale: scale })
|
||||
.addClass("scaled");
|
||||
};
|
||||
|
||||
var scaleSlides = function ()
|
||||
{
|
||||
$(".slides")
|
||||
.css("display", "block")
|
||||
.each(function ()
|
||||
{
|
||||
var slideshow = $(this),
|
||||
slide = slideshow.find(".slide-preview"),
|
||||
parent = slide.parent(),
|
||||
width = 150,
|
||||
height = 150,
|
||||
boundingDimension = 150,
|
||||
slideStyle = slide.attr("style");
|
||||
|
||||
if ((slideStyle != null && slideStyle.indexOf("width:") == -1)) width = 1024;
|
||||
if ((slideStyle != null && slideStyle.indexOf("height:") == -1)) height = 768;
|
||||
|
||||
slide.css({
|
||||
width: width + "px",
|
||||
height: height + "px",
|
||||
position: "absolute"
|
||||
});
|
||||
var scaledForWidth = width > height,
|
||||
largestDimension = (scaledForWidth ? width : height),
|
||||
scale = boundingDimension / largestDimension;
|
||||
|
||||
parent.css({
|
||||
width: Math.floor(width * scale) + "px",
|
||||
height: Math.floor(height * scale) + "px",
|
||||
position: "relative",
|
||||
overflow: "hidden"
|
||||
});
|
||||
|
||||
applyCssScale(slide, scale);
|
||||
slideshow.parent(".slides-wrapper").css("overflow", "visible");
|
||||
});
|
||||
};
|
||||
|
||||
$(window).load(function ()
|
||||
{
|
||||
scaleSlides();
|
||||
});
|
||||
|
||||
// Sortable slides.
|
||||
$(function ()
|
||||
{
|
||||
$(".slides-wrapper.interactive").each(function ()
|
||||
{
|
||||
var wrapper = $(this);
|
||||
|
||||
var showChangedMessage = function ()
|
||||
{
|
||||
wrapper.find(".dirty-message").show();
|
||||
};
|
||||
|
||||
var onSlideIndexChanged = function (e, ui)
|
||||
{
|
||||
showChangedMessage();
|
||||
};
|
||||
|
||||
var slidesList = wrapper.find("ul.slides");
|
||||
slidesList.sortable({
|
||||
placeholder: "sortable-placeholder",
|
||||
stop: onSlideIndexChanged
|
||||
});
|
||||
slidesList.disableSelection();
|
||||
});
|
||||
});
|
||||
})(jQuery);
|
@@ -0,0 +1,13 @@
|
||||
(function ($)
|
||||
{
|
||||
$(function ()
|
||||
{
|
||||
$(".engine-picker").on("change", function (e)
|
||||
{
|
||||
var engine = $(this).val();
|
||||
|
||||
$(".engine-settings-editor").hide();
|
||||
$("[data-engine='" + engine + "']").show();
|
||||
}).trigger("change");
|
||||
});
|
||||
})(jQuery);
|
@@ -0,0 +1,53 @@
|
||||
.slides-wrapper
|
||||
{
|
||||
margin-bottom: 2em;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.slides-wrapper .sortable-placeholder
|
||||
{
|
||||
display: block;
|
||||
height: 125px;
|
||||
}
|
||||
|
||||
.slides-wrapper .dirty-message
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.slides-wrapper ul
|
||||
{
|
||||
display: none;
|
||||
float: left;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.slides-wrapper ul.slides li
|
||||
{
|
||||
float: left;
|
||||
width: 150px;
|
||||
margin: 0 1em 0.2em 0;
|
||||
border: none;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.slides-wrapper ul.slides li .slide-wrapper
|
||||
{
|
||||
background: #ebebeb;
|
||||
border: 1px solid #ebebeb;
|
||||
}
|
||||
|
||||
.slides-wrapper.interactive ul.slides li:hover .slide-wrapper
|
||||
{
|
||||
border-color: #aeaeae;
|
||||
}
|
||||
|
||||
.slides-wrapper ul.slides li img
|
||||
{
|
||||
vertical-align: middle;
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
.engine-settings-editor {
|
||||
display: none;
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
.style-type-browser ul {
|
||||
background: none repeat scroll 0 0 #f3f4f5;
|
||||
border: 1px solid #e4e5e6;
|
||||
padding: 0 5px 0 5px;
|
||||
}
|
||||
|
||||
.style-type-browser ul li {
|
||||
margin: 5px 0;
|
||||
background: #fff;
|
||||
color: #aec3ce;
|
||||
}
|
||||
|
||||
.style-type-browser ul li a {
|
||||
border: 1px solid #eaeaea;
|
||||
display: block;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
.style-type-browser ul li a:hover {
|
||||
border-color: #487328;
|
||||
}
|
||||
|
||||
.style-type-browser ul li a h2 {
|
||||
font-size: 1.231em;
|
||||
}
|
@@ -0,0 +1,5 @@
|
||||
<project outputDir="confused\.." baseDir="bin" xmlns="http://confuser.codeplex.com">
|
||||
<module path="IDeliverable.Slides.dll">
|
||||
<rule pattern="true" preset="minimum" inherit="false" />
|
||||
</module>
|
||||
</project>
|
@@ -0,0 +1,93 @@
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using IDeliverable.Slides.Filters;
|
||||
using IDeliverable.Slides.Models;
|
||||
using IDeliverable.Slides.ViewModels;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Layouts.Framework.Elements;
|
||||
using Orchard.Layouts.Services;
|
||||
using Orchard.Localization;
|
||||
using Orchard.UI.Admin;
|
||||
using Orchard.UI.Notify;
|
||||
using Orchard.Layouts.Helpers;
|
||||
|
||||
namespace IDeliverable.Slides.Controllers
|
||||
{
|
||||
[Admin]
|
||||
[Dialog]
|
||||
public class SlideController : Controller, IUpdateModel
|
||||
{
|
||||
private readonly INotifier _notifier;
|
||||
private readonly IObjectStore _objectStore;
|
||||
private readonly IElementManager _elementManager;
|
||||
private readonly ILayoutModelMapper _mapper;
|
||||
private readonly ILayoutSerializer _serializer;
|
||||
private readonly ILayoutEditorFactory _layoutEditorFactory;
|
||||
|
||||
public SlideController(
|
||||
INotifier notifier,
|
||||
IObjectStore objectStore,
|
||||
IElementManager elementManager,
|
||||
ILayoutModelMapper mapper,
|
||||
ILayoutSerializer serializer,
|
||||
ILayoutEditorFactory layoutEditorFactory)
|
||||
{
|
||||
_notifier = notifier;
|
||||
_objectStore = objectStore;
|
||||
_elementManager = elementManager;
|
||||
_mapper = mapper;
|
||||
_serializer = serializer;
|
||||
_layoutEditorFactory = layoutEditorFactory;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public Localizer T { get; set; }
|
||||
|
||||
public ActionResult Edit(string id, string returnUrl)
|
||||
{
|
||||
var slide = _objectStore.Get<Slide>(id);
|
||||
var viewModel = new SlideEditorViewModel
|
||||
{
|
||||
ReturnUrl = returnUrl,
|
||||
LayoutEditor = _layoutEditorFactory.Create(slide.LayoutData, id, slide.TemplateId)
|
||||
};
|
||||
return View(viewModel);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateInput(false)]
|
||||
public ActionResult Edit(SlideEditorViewModel viewModel)
|
||||
{
|
||||
var elementInstances = _mapper.ToLayoutModel(viewModel.LayoutEditor.Data, DescribeElementsContext.Empty).ToArray();
|
||||
var context = new LayoutSavingContext {
|
||||
Updater = this,
|
||||
Elements = elementInstances,
|
||||
};
|
||||
|
||||
_elementManager.Saving(context);
|
||||
var slide = new Slide {
|
||||
LayoutData = _serializer.Serialize(elementInstances),
|
||||
TemplateId = viewModel.LayoutEditor.TemplateId
|
||||
};
|
||||
_objectStore.Set(viewModel.LayoutEditor.SessionKey, slide);
|
||||
|
||||
return RedirectToEditor(viewModel.ReturnUrl, T("That slide has been updated."));
|
||||
}
|
||||
|
||||
private RedirectResult RedirectToEditor(string returnUrl, LocalizedString notification)
|
||||
{
|
||||
_notifier.Information(notification);
|
||||
return Redirect(returnUrl);
|
||||
}
|
||||
|
||||
bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties)
|
||||
{
|
||||
return TryUpdateModel(model, prefix, includeProperties, excludeProperties);
|
||||
}
|
||||
|
||||
void IUpdateModel.AddModelError(string key, LocalizedString errorMessage)
|
||||
{
|
||||
ModelState.AddModelError(key, errorMessage.Text);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,197 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using IDeliverable.Slides.Filters;
|
||||
using IDeliverable.Slides.Helpers;
|
||||
using IDeliverable.Slides.Models;
|
||||
using IDeliverable.Slides.ViewModels;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Layouts.Elements;
|
||||
using Orchard.Layouts.Framework.Elements;
|
||||
using Orchard.Layouts.Services;
|
||||
using Orchard.Localization;
|
||||
using Orchard.MediaLibrary.Models;
|
||||
using Orchard.UI.Admin;
|
||||
|
||||
namespace IDeliverable.Slides.Controllers
|
||||
{
|
||||
using ContentItemElement = Orchard.Layouts.Elements.ContentItem;
|
||||
|
||||
[Admin]
|
||||
[Dialog]
|
||||
public class SlideFactoryController : Controller
|
||||
{
|
||||
private readonly IContentManager _contentManager;
|
||||
private readonly IElementFactory _elementFactory;
|
||||
private readonly ILayoutSerializer _layoutSerializer;
|
||||
private readonly IElementManager _elementManager;
|
||||
private readonly IObjectStore _objectStore;
|
||||
private readonly ILayoutEditorFactory _layoutEditorFactory;
|
||||
private readonly ILayoutModelMapper _layoutModelMapper;
|
||||
|
||||
public SlideFactoryController(
|
||||
IContentManager contentManager,
|
||||
IElementFactory elementFactory,
|
||||
ILayoutSerializer layoutSerializer,
|
||||
IElementManager elementManager,
|
||||
IObjectStore objectStore,
|
||||
ILayoutEditorFactory layoutEditorFactory,
|
||||
ILayoutModelMapper layoutModelMapper)
|
||||
{
|
||||
_contentManager = contentManager;
|
||||
_elementFactory = elementFactory;
|
||||
_layoutSerializer = layoutSerializer;
|
||||
_elementManager = elementManager;
|
||||
_objectStore = objectStore;
|
||||
_layoutEditorFactory = layoutEditorFactory;
|
||||
_layoutModelMapper = layoutModelMapper;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public Localizer T { get; set; }
|
||||
|
||||
public ActionResult Create(string returnUrl)
|
||||
{
|
||||
var viewModel = new SlideEditorViewModel
|
||||
{
|
||||
ReturnUrl = returnUrl,
|
||||
LayoutEditor = _layoutEditorFactory.Create(null, _objectStore.GenerateKey())
|
||||
};
|
||||
return View(viewModel);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateInput(false)]
|
||||
public ActionResult Create(SlideEditorViewModel viewModel)
|
||||
{
|
||||
var slides = new[] { new Slide { LayoutData = _layoutSerializer.Serialize(_layoutModelMapper.ToLayoutModel(viewModel.LayoutEditor.Data, DescribeElementsContext.Empty)) } };
|
||||
var slidesKey = viewModel.LayoutEditor.SessionKey;
|
||||
|
||||
_objectStore.Set(slidesKey, slides);
|
||||
return RedirectToEditor(viewModel.ReturnUrl, slidesKey);
|
||||
}
|
||||
|
||||
public ActionResult MediaSlides(string returnUrl)
|
||||
{
|
||||
var viewModel = new ImageSlidesFactoryViewModel
|
||||
{
|
||||
ReturnUrl = returnUrl
|
||||
};
|
||||
return View(viewModel);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult MediaSlides(string returnUrl, string imageIds)
|
||||
{
|
||||
if (imageIds == null)
|
||||
{
|
||||
ModelState.AddModelError("imageIds", T("No images were selected.").Text);
|
||||
return View(new ImageSlidesFactoryViewModel
|
||||
{
|
||||
ReturnUrl = returnUrl
|
||||
});
|
||||
}
|
||||
|
||||
var mediaItems = LoadContentItems<MediaPart>(imageIds).ToList();
|
||||
var slides = mediaItems.Select(CreateSlide).ToList();
|
||||
var slidesKey = _objectStore.GenerateKey();
|
||||
|
||||
_objectStore.Set(slidesKey, slides);
|
||||
return RedirectToEditor(returnUrl, slidesKey);
|
||||
}
|
||||
|
||||
public ActionResult ContentSlides(string returnUrl)
|
||||
{
|
||||
var viewModel = new ContentSlidesFactoryViewModel
|
||||
{
|
||||
ReturnUrl = returnUrl
|
||||
};
|
||||
return View(viewModel);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult ContentSlides(ContentSlidesFactoryViewModel viewModel)
|
||||
{
|
||||
if (viewModel.ContentIds == null)
|
||||
{
|
||||
ModelState.AddModelError("contentIds", T("No content items were selected.").Text);
|
||||
return View(viewModel);
|
||||
}
|
||||
|
||||
var contentItems = LoadContentItems<IContent>(viewModel.ContentIds).ToList();
|
||||
var slides = contentItems.Select(x => CreateSlide(x, viewModel.DisplayType)).ToList();
|
||||
var slidesKey = _objectStore.GenerateKey();
|
||||
|
||||
_objectStore.Set(slidesKey, slides);
|
||||
return RedirectToEditor(viewModel.ReturnUrl, slidesKey);
|
||||
}
|
||||
|
||||
private Slide CreateSlide(MediaPart mediaItem)
|
||||
{
|
||||
var element = CreateElementFromMediaItem(mediaItem);
|
||||
|
||||
return new Slide
|
||||
{
|
||||
LayoutData = _layoutSerializer.Serialize(new[] { CreateCanvas(element) }),
|
||||
};
|
||||
}
|
||||
|
||||
private Element CreateElementFromMediaItem(MediaPart mediaItem)
|
||||
{
|
||||
if (mediaItem.Is<ImagePart>())
|
||||
{
|
||||
return _elementManager.ActivateElement<Image>(x => x.MediaId = mediaItem.Id);
|
||||
}
|
||||
else if (mediaItem.Is<VectorImagePart>())
|
||||
{
|
||||
return _elementManager.ActivateElement<VectorImage>(x => x.MediaId = mediaItem.Id);
|
||||
}
|
||||
|
||||
return _elementManager.ActivateElement<MediaItem>(x => x.MediaItemIds = new[] { mediaItem.Id });
|
||||
}
|
||||
|
||||
private Slide CreateSlide(IContent content, string displayType)
|
||||
{
|
||||
var elementDescriptor = _elementManager.GetElementDescriptorByType<ContentItemElement>();
|
||||
var element = (ContentItemElement)_elementFactory.Activate(elementDescriptor);
|
||||
|
||||
element.ContentItemIds = new[] { content.Id };
|
||||
element.DisplayType = displayType;
|
||||
|
||||
return new Slide
|
||||
{
|
||||
LayoutData = _layoutSerializer.Serialize(new[] { CreateCanvas(element) }),
|
||||
};
|
||||
}
|
||||
|
||||
private IEnumerable<TPart> LoadContentItems<TPart>(string ids) where TPart : class, IContent
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(ids))
|
||||
{
|
||||
return Enumerable.Empty<TPart>();
|
||||
}
|
||||
|
||||
var itemIds = ids.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(Int32.Parse);
|
||||
return _contentManager.GetMany<TPart>(itemIds, VersionOptions.Latest, QueryHints.Empty);
|
||||
}
|
||||
|
||||
private RedirectResult RedirectToEditor(string returnUrl, string slidesSessionKey)
|
||||
{
|
||||
var url = returnUrl.AppendQueryString(new { slides = slidesSessionKey });
|
||||
return Redirect(url);
|
||||
}
|
||||
|
||||
private Canvas CreateCanvas(params Element[] elements)
|
||||
{
|
||||
var canvasDescriptor = _elementManager.GetElementDescriptorByType<Canvas>();
|
||||
var canvas = (Canvas)_elementFactory.Activate(canvasDescriptor);
|
||||
|
||||
foreach (var element in elements) {
|
||||
canvas.Elements.Add(element);
|
||||
}
|
||||
|
||||
return canvas;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,130 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using IDeliverable.Slides.Elements;
|
||||
using IDeliverable.Slides.Filters;
|
||||
using IDeliverable.Slides.Helpers;
|
||||
using IDeliverable.Slides.Models;
|
||||
using IDeliverable.Slides.Services;
|
||||
using Orchard.Layouts.Helpers;
|
||||
using Orchard.Layouts.Models;
|
||||
using Orchard.Layouts.Services;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Mvc.Html;
|
||||
using Orchard.UI.Admin;
|
||||
using Orchard.UI.Notify;
|
||||
|
||||
namespace IDeliverable.Slides.Controllers
|
||||
{
|
||||
[Admin]
|
||||
[Dialog]
|
||||
public class SlideShowElementController : Controller
|
||||
{
|
||||
private readonly IObjectStore _objectStore;
|
||||
private readonly INotifier _notifier;
|
||||
private readonly IElementManager _elementManager;
|
||||
private readonly ISlidesSerializer _serializer;
|
||||
|
||||
public SlideShowElementController(IObjectStore objectStore, INotifier notifier, IElementManager elementManager, ISlidesSerializer serializer)
|
||||
{
|
||||
_objectStore = objectStore;
|
||||
_notifier = notifier;
|
||||
_elementManager = elementManager;
|
||||
_serializer = serializer;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public Localizer T { get; set; }
|
||||
|
||||
public ActionResult AddSlides(string session, string slides)
|
||||
{
|
||||
var addedSlides = _objectStore.Get<IList<Slide>>(slides);
|
||||
var slideShowElementState = _objectStore.Get<ElementSessionState>(session);
|
||||
var slideShowElementDescriptor = _elementManager.GetElementDescriptorByType<SlideShow>();
|
||||
var slideShowElement = _elementManager.ActivateElement<SlideShow>(slideShowElementDescriptor, x => x.Data = ElementDataHelper.Deserialize(slideShowElementState.ElementData));
|
||||
var slideShowSlides = GetSlides(slideShowElement);
|
||||
var currentSlides = slideShowSlides.ToList();
|
||||
|
||||
currentSlides.AddRange(addedSlides);
|
||||
SetSlides(slideShowElement, currentSlides);
|
||||
slideShowElementState.ElementData = slideShowElement.Data.Serialize();
|
||||
|
||||
_objectStore.Set(session, slideShowElementState);
|
||||
|
||||
return RedirectToEditor(session, T.Plural("That slide has been added.", "Those slides have been added.", addedSlides.Count));
|
||||
}
|
||||
|
||||
public ActionResult EditSlide(string session, int index, bool dialog)
|
||||
{
|
||||
var slideShowElementState = _objectStore.Get<ElementSessionState>(session);
|
||||
var slideShowElement = GetSlideShow(slideShowElementState);
|
||||
var slides = GetSlides(slideShowElement);
|
||||
var slide = slides.ElementAt(index);
|
||||
var key = _objectStore.GenerateKey();
|
||||
var returnUrl = Url.Action("UpdateSlide", new { session = session, key = key, index = index, dialog = dialog });
|
||||
|
||||
_objectStore.Set(key, slide);
|
||||
return RedirectToAction("Edit", "Slide", new { id = key, returnUrl = returnUrl, dialog = dialog });
|
||||
}
|
||||
|
||||
public ActionResult UpdateSlide(string session, string key, int index, bool dialog)
|
||||
{
|
||||
var slideShowElementState = _objectStore.Get<ElementSessionState>(session);
|
||||
var slideShowElement = GetSlideShow(slideShowElementState);
|
||||
var slide = _objectStore.Get<Slide>(key);
|
||||
var slides = GetSlides(slideShowElement).ToList();
|
||||
|
||||
slides[index] = slide;
|
||||
SetSlides(slideShowElement, slides);
|
||||
slideShowElementState.ElementData = slideShowElement.Data.Serialize();
|
||||
|
||||
_objectStore.Set(session, slideShowElementState);
|
||||
return RedirectToEditor(session, dialog: dialog);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult DeleteSlide(string session, int index, bool dialog)
|
||||
{
|
||||
var slideShowElementState = _objectStore.Get<ElementSessionState>(session);
|
||||
var slideShowElement = GetSlideShow(slideShowElementState);
|
||||
var currentSlides = GetSlides(slideShowElement).ToList();
|
||||
|
||||
currentSlides.RemoveAt(index);
|
||||
SetSlides(slideShowElement, currentSlides);
|
||||
slideShowElementState.ElementData = slideShowElement.Data.Serialize();
|
||||
|
||||
_objectStore.Set(session, slideShowElementState);
|
||||
return RedirectToEditor(session, T("That slide has been deleted."), dialog: dialog);
|
||||
}
|
||||
|
||||
private RedirectToRouteResult RedirectToEditor(string session, LocalizedString message = null, bool dialog = false)
|
||||
{
|
||||
if(message != null)
|
||||
_notifier.Information(message);
|
||||
|
||||
return RedirectToAction("Edit", "Element", new { session = session, dialog = dialog, area = "Orchard.Layouts" });
|
||||
}
|
||||
|
||||
private SlideShow GetSlideShow(ElementSessionState sessionState)
|
||||
{
|
||||
var slideShowElementDescriptor = _elementManager.GetElementDescriptorByType<SlideShow>();
|
||||
var slideShowElement = _elementManager.ActivateElement<SlideShow>(slideShowElementDescriptor, x => x.Data = ElementDataHelper.Deserialize(sessionState.ElementData));
|
||||
|
||||
return slideShowElement;
|
||||
}
|
||||
|
||||
private IEnumerable<Slide> GetSlides(SlideShow element)
|
||||
{
|
||||
var storage = new ElementStorage(element);
|
||||
var slidesData = storage.RetrieveSlidesData();
|
||||
return _serializer.Deserialize(slidesData);
|
||||
}
|
||||
|
||||
private void SetSlides(SlideShow element, IEnumerable<Slide> slides)
|
||||
{
|
||||
var storage = new ElementStorage(element);
|
||||
var slidesData = _serializer.Serialize(slides);
|
||||
storage.StoreSlidesData(slidesData);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,110 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using IDeliverable.Slides.Helpers;
|
||||
using IDeliverable.Slides.Models;
|
||||
using IDeliverable.Slides.Services;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Layouts.Services;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Mvc.Html;
|
||||
using Orchard.UI.Admin;
|
||||
using Orchard.UI.Notify;
|
||||
using Orchard.Layouts.Helpers;
|
||||
|
||||
namespace IDeliverable.Slides.Controllers
|
||||
{
|
||||
[Admin]
|
||||
public class SlideShowPartController : Controller
|
||||
{
|
||||
private readonly IObjectStore _objectStore;
|
||||
private readonly IContentManager _contentManager;
|
||||
private readonly INotifier _notifier;
|
||||
private readonly ISlidesSerializer _serializer;
|
||||
|
||||
public SlideShowPartController(IObjectStore objectStore, IContentManager contentManager, INotifier notifier, ISlidesSerializer serializer)
|
||||
{
|
||||
_objectStore = objectStore;
|
||||
_contentManager = contentManager;
|
||||
_notifier = notifier;
|
||||
_serializer = serializer;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public Localizer T { get; set; }
|
||||
|
||||
public ActionResult AddSlides(int id, string slides)
|
||||
{
|
||||
var part = _contentManager.Get<SlideShowPart>(id, VersionOptions.DraftRequired);
|
||||
|
||||
if (slides == null)
|
||||
{
|
||||
return RedirectToEditor(part);
|
||||
}
|
||||
|
||||
var addedSlides = _objectStore.Get<IList<Slide>>(slides);
|
||||
var currentSlides = GetSlides(part).ToList();
|
||||
|
||||
currentSlides.AddRange(addedSlides);
|
||||
SetSlides(part, currentSlides);
|
||||
|
||||
return RedirectToEditor(part, T.Plural("That slide has been added.", "Those slides have been added.", addedSlides.Count));
|
||||
}
|
||||
|
||||
public ActionResult EditSlide(int id, int index)
|
||||
{
|
||||
var slidesPart = _contentManager.Get<SlideShowPart>(id, VersionOptions.Latest);
|
||||
var slides = GetSlides(slidesPart).ToList();
|
||||
var slide = slides.ElementAt(index);
|
||||
var key = _objectStore.GenerateKey();
|
||||
var returnUrl = Url.Action("UpdateSlide", new { id = id, key = key, index = index });
|
||||
|
||||
_objectStore.Set(key, slide);
|
||||
return RedirectToAction("Edit", "Slide", new { id = key, returnUrl = returnUrl });
|
||||
}
|
||||
|
||||
public ActionResult UpdateSlide(int id, int index, string key)
|
||||
{
|
||||
var slidesPart = _contentManager.Get<SlideShowPart>(id, VersionOptions.Latest);
|
||||
var slide = _objectStore.Get<Slide>(key);
|
||||
var slides = GetSlides(slidesPart).ToList();
|
||||
|
||||
slides[index] = slide;
|
||||
SetSlides(slidesPart, slides);
|
||||
|
||||
return Redirect(Url.ItemEditUrl(slidesPart));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult DeleteSlide(int id, int index)
|
||||
{
|
||||
var slidesPart = _contentManager.Get<SlideShowPart>(id, VersionOptions.DraftRequired);
|
||||
var slides = GetSlides(slidesPart).ToList();
|
||||
|
||||
slides.RemoveAt(index);
|
||||
SetSlides(slidesPart, slides);
|
||||
|
||||
return RedirectToEditor(slidesPart, T("That slide has been deleted."));
|
||||
}
|
||||
|
||||
private RedirectToRouteResult RedirectToEditor(SlideShowPart part, LocalizedString message = null)
|
||||
{
|
||||
if (message != null)
|
||||
_notifier.Information(message);
|
||||
|
||||
return RedirectToRoute(_contentManager.GetItemMetadata(part).EditorRouteValues);
|
||||
}
|
||||
|
||||
private IEnumerable<Slide> GetSlides(SlideShowPart part) {
|
||||
var storage = new ContentPartStorage(part);
|
||||
var slidesData = storage.RetrieveSlidesData();
|
||||
return _serializer.Deserialize(slidesData);
|
||||
}
|
||||
|
||||
private void SetSlides(SlideShowPart part, IEnumerable<Slide> slides) {
|
||||
var storage = new ContentPartStorage(part);
|
||||
var slidesData = _serializer.Serialize(slides);
|
||||
storage.StoreSlidesData(slidesData);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,169 @@
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using IDeliverable.Licensing.Orchard;
|
||||
using IDeliverable.Slides.Licensing;
|
||||
using IDeliverable.Slides.Models;
|
||||
using IDeliverable.Slides.Services;
|
||||
using IDeliverable.Slides.ViewModels;
|
||||
using Orchard;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Layouts.Framework.Elements;
|
||||
using Orchard.Layouts.Helpers;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Security;
|
||||
using Orchard.UI.Admin;
|
||||
using Orchard.UI.Notify;
|
||||
|
||||
namespace IDeliverable.Slides.Controllers
|
||||
{
|
||||
[Admin]
|
||||
public class SlideShowProfileController : Controller, IUpdateModel
|
||||
{
|
||||
public SlideShowProfileController(IOrchardServices services, ISlideShowPlayerEngineManager engineManager)
|
||||
{
|
||||
_services = services;
|
||||
_engineManager = engineManager;
|
||||
}
|
||||
|
||||
public Localizer T { get; set; } = NullLocalizer.Instance;
|
||||
|
||||
private readonly IOrchardServices _services;
|
||||
private readonly ISlideShowPlayerEngineManager _engineManager;
|
||||
|
||||
|
||||
public ActionResult Index()
|
||||
{
|
||||
if (!LicenseValidationHelper.GetLicenseIsValid(LicensedProductManifest.ProductId))
|
||||
return View("InvalidLicense");
|
||||
|
||||
var viewModel = new SlideShowProfileIndexViewModel
|
||||
{
|
||||
Profiles = _services.WorkContext.CurrentSite.As<SlideShowSettingsPart>().Profiles.ToList()
|
||||
};
|
||||
return View(viewModel);
|
||||
}
|
||||
|
||||
public ActionResult Create()
|
||||
{
|
||||
var engines = _engineManager.GetEngines().ToList();
|
||||
var viewModel = new SlideShowProfileViewModel
|
||||
{
|
||||
AvailableEngines = engines,
|
||||
EngineSettingsEditors = engines.ToDictionary(x => x.Name, x => x.BuildSettingsEditor(_services.New))
|
||||
};
|
||||
|
||||
return View(viewModel);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Create(SlideShowProfileViewModel viewModel)
|
||||
{
|
||||
var engines = _engineManager.GetEngines().ToList();
|
||||
|
||||
viewModel.AvailableEngines = engines;
|
||||
viewModel.EngineSettingsEditors = engines.ToDictionary(x => x.Name, x => x.UpdateSettingsEditor(_services.New, this));
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
_services.TransactionManager.Cancel();
|
||||
return View(viewModel);
|
||||
}
|
||||
|
||||
var settingsPart = _services.WorkContext.CurrentSite.As<SlideShowSettingsPart>();
|
||||
var profile = new SlideShowProfile
|
||||
{
|
||||
Id = settingsPart.NextId(),
|
||||
Name = viewModel.Name.TrimSafe(),
|
||||
SelectedEngine = viewModel.SelectedEngine,
|
||||
EngineStates = new ElementDataDictionary()
|
||||
};
|
||||
|
||||
foreach (var engine in engines)
|
||||
{
|
||||
profile.EngineStates[engine.Name] = engine.Data.Serialize();
|
||||
}
|
||||
|
||||
settingsPart.StoreProfile(profile);
|
||||
_services.Notifier.Information(T("That slide show profile has been created."));
|
||||
|
||||
return RedirectToAction("Edit", new { id = profile.Id });
|
||||
}
|
||||
|
||||
public ActionResult Edit(int id)
|
||||
{
|
||||
var settingsPart = _services.WorkContext.CurrentSite.As<SlideShowSettingsPart>();
|
||||
var profile = settingsPart.GetProfile(id);
|
||||
var engines = _engineManager.GetEngines().ToList();
|
||||
|
||||
foreach (var engine in engines)
|
||||
{
|
||||
engine.Data = ElementDataHelper.Deserialize(profile.EngineStates[engine.Name]);
|
||||
}
|
||||
|
||||
var viewModel = new SlideShowProfileViewModel
|
||||
{
|
||||
Name = profile.Name,
|
||||
AvailableEngines = engines,
|
||||
EngineSettingsEditors = engines.ToDictionary(x => x.Name, x => x.BuildSettingsEditor(_services.New)),
|
||||
SelectedEngine = profile.SelectedEngine
|
||||
};
|
||||
|
||||
return View(viewModel);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Edit(int id, SlideShowProfileViewModel viewModel)
|
||||
{
|
||||
var settingsPart = _services.WorkContext.CurrentSite.As<SlideShowSettingsPart>();
|
||||
var profile = settingsPart.GetProfile(id);
|
||||
var engines = _engineManager.GetEngines().ToList();
|
||||
|
||||
viewModel.AvailableEngines = engines;
|
||||
viewModel.EngineSettingsEditors = engines.ToDictionary(x => x.Name, x => x.UpdateSettingsEditor(_services.New, this));
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
_services.TransactionManager.Cancel();
|
||||
return View(viewModel);
|
||||
}
|
||||
|
||||
foreach (var engine in engines)
|
||||
{
|
||||
profile.EngineStates[engine.Name] = engine.Data.Serialize();
|
||||
}
|
||||
|
||||
profile.SelectedEngine = viewModel.SelectedEngine;
|
||||
settingsPart.StoreProfile(profile);
|
||||
_services.Notifier.Information(T("That slide show profile has been updated."));
|
||||
|
||||
return RedirectToAction("Edit", new { id = id });
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Delete(int id)
|
||||
{
|
||||
var settingsPart = _services.WorkContext.CurrentSite.As<SlideShowSettingsPart>();
|
||||
|
||||
settingsPart.DeleteProfile(id);
|
||||
_services.Notifier.Information(T("That slide show profile has been deleted."));
|
||||
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
protected override void OnAuthorization(AuthorizationContext filterContext)
|
||||
{
|
||||
if (!_services.Authorizer.Authorize(StandardPermissions.SiteOwner))
|
||||
filterContext.Result = new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties)
|
||||
{
|
||||
return TryUpdateModel(model, prefix, includeProperties, excludeProperties);
|
||||
}
|
||||
|
||||
void IUpdateModel.AddModelError(string key, LocalizedString errorMessage)
|
||||
{
|
||||
ModelState.AddModelError(key, errorMessage.Text);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,143 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using IDeliverable.Licensing.Orchard;
|
||||
using IDeliverable.Slides.Elements;
|
||||
using IDeliverable.Slides.Helpers;
|
||||
using IDeliverable.Slides.Licensing;
|
||||
using IDeliverable.Slides.Models;
|
||||
using IDeliverable.Slides.Services;
|
||||
using IDeliverable.Slides.ViewModels;
|
||||
using Orchard;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Layouts.Framework.Display;
|
||||
using Orchard.Layouts.Framework.Drivers;
|
||||
using Orchard.Layouts.Helpers;
|
||||
using Orchard.Services;
|
||||
|
||||
namespace IDeliverable.Slides.Drivers
|
||||
{
|
||||
public class SlideShowElementDriver : ElementDriver<SlideShow>
|
||||
{
|
||||
private readonly IOrchardServices _services;
|
||||
private readonly ISlideShowPlayerEngineManager _engineManager;
|
||||
private readonly IClock _clock;
|
||||
private readonly ISlidesProviderService _providerService;
|
||||
private readonly ISlideShowProfileService _slideShowProfileService;
|
||||
|
||||
public SlideShowElementDriver(
|
||||
IOrchardServices services,
|
||||
ISlideShowPlayerEngineManager engineManager,
|
||||
IClock clock,
|
||||
ISlidesProviderService providerService,
|
||||
ISlideShowProfileService slideShowProfileService)
|
||||
{
|
||||
_services = services;
|
||||
_engineManager = engineManager;
|
||||
_clock = clock;
|
||||
_providerService = providerService;
|
||||
_slideShowProfileService = slideShowProfileService;
|
||||
}
|
||||
|
||||
public string Prefix => "SlideShowElement";
|
||||
|
||||
protected override EditorResult OnBuildEditor(SlideShow element, ElementEditorContext context)
|
||||
{
|
||||
if (!LicenseValidationHelper.GetLicenseIsValid(LicensedProductManifest.ProductId))
|
||||
return Editor(context, context.ShapeFactory.Slides_InvalidLicense());
|
||||
|
||||
var storage = new ElementStorage(element);
|
||||
var slidesProvidercontext = new SlidesProviderContext(context.Content, element, storage, context.Session);
|
||||
var providerShapes = Enumerable.ToDictionary(_providerService.BuildEditors(context.ShapeFactory, slidesProvidercontext), (Func<dynamic, string>)(x => (string)x.Provider.Name));
|
||||
|
||||
var viewModel = new SlideShowElementViewModel
|
||||
{
|
||||
Element = element,
|
||||
ProfileId = element.ProfileId,
|
||||
SessionKey = context.Session,
|
||||
AvailableProfiles = _services.WorkContext.CurrentSite.As<SlideShowSettingsPart>().Profiles.ToList(),
|
||||
ProviderName = element.ProviderName,
|
||||
AvailableProviders = providerShapes,
|
||||
};
|
||||
|
||||
if (context.Updater != null)
|
||||
{
|
||||
if (context.Updater.TryUpdateModel(viewModel, Prefix, new[] { "ProfileId", "ProviderName", "SlidesData" }, null))
|
||||
{
|
||||
// The element editor only provides the posted form values (for the ValueProvider), so we need to fetch the slides data ourselves in order to not lose it.
|
||||
if (context.ElementData.ContainsKey("SlideShowSlides"))
|
||||
storage.StoreSlidesData(context.ElementData["SlideShowSlides"]);
|
||||
|
||||
providerShapes = Enumerable.ToDictionary(_providerService.UpdateEditors(context.ShapeFactory, slidesProvidercontext, new Updater(context.Updater, Prefix)), (Func<dynamic, string>)(x => (string)x.Provider.Name));
|
||||
element.ProfileId = viewModel.ProfileId;
|
||||
element.ProviderName = viewModel.ProviderName;
|
||||
viewModel.AvailableProviders = providerShapes;
|
||||
}
|
||||
}
|
||||
|
||||
var slidesEditor = context.ShapeFactory.EditorTemplate(TemplateName: "Elements.SlideShow", Prefix: Prefix, Model: viewModel);
|
||||
|
||||
//viewModel.Slides = element.Slides.Select(x => _layoutManager.RenderLayout(x.LayoutData)).ToArray();
|
||||
slidesEditor.Metadata.Position = "Slides:0";
|
||||
return Editor(context, slidesEditor);
|
||||
}
|
||||
|
||||
protected override void OnDisplaying(SlideShow element, ElementDisplayContext context)
|
||||
{
|
||||
if (!LicenseValidationHelper.GetLicenseIsValid(LicensedProductManifest.ProductId))
|
||||
{
|
||||
context.ElementShape.Metadata.Alternates.Clear();
|
||||
context.ElementShape.Metadata.Alternates.Add($"Elements_SlideShow_InvalidLicense");
|
||||
context.ElementShape.Metadata.Alternates.Add($"Elements_SlideShow_InvalidLicense_{context.DisplayType}");
|
||||
return;
|
||||
}
|
||||
|
||||
var slideShapes = GetSlides(element, context);
|
||||
var engine = _engineManager.GetEngine(element.Profile);
|
||||
var engineShape = engine.BuildDisplay(_services.New);
|
||||
|
||||
engineShape.Engine = engine;
|
||||
engineShape.Slides = slideShapes;
|
||||
engineShape.SlideShowId = _clock.UtcNow.Ticks + "[" + element.Index + "]"; // TODO: Come up with a better, deterministic way to determine the slide show id. Perhaps elements should have a unique ID (unique within the layout, at least).
|
||||
|
||||
context.ElementShape.Slides = slideShapes;
|
||||
context.ElementShape.Engine = engineShape;
|
||||
}
|
||||
|
||||
protected override void OnExporting(SlideShow element, ExportElementContext context)
|
||||
{
|
||||
context.ExportableData["Profile"] = element.Profile?.Name;
|
||||
context.ExportableData["Provider"] = element.ProviderName;
|
||||
|
||||
var storage = new ElementStorage(element);
|
||||
var providersElement = _providerService.Export(storage, context.Layout);
|
||||
|
||||
context.ExportableData["Providers"] = providersElement.ToString(SaveOptions.DisableFormatting);
|
||||
}
|
||||
|
||||
protected override void OnImporting(SlideShow element, ImportElementContext context)
|
||||
{
|
||||
element.ProfileId = _slideShowProfileService.FindByName(context.ExportableData.Get("Profile"))?.Id;
|
||||
element.ProviderName = _providerService.GetProvider(context.ExportableData.Get("Provider"))?.Name;
|
||||
|
||||
var providersData = context.ExportableData.Get("Providers");
|
||||
|
||||
if (String.IsNullOrWhiteSpace(providersData))
|
||||
return;
|
||||
|
||||
var storage = new ElementStorage(element);
|
||||
var providersElement = XElement.Parse(providersData);
|
||||
|
||||
_providerService.Import(storage, providersElement, context.Session, context.Layout);
|
||||
}
|
||||
|
||||
private IList<dynamic> GetSlides(SlideShow element, ElementDisplayContext context)
|
||||
{
|
||||
var provider = !String.IsNullOrWhiteSpace(element.ProviderName) ? _providerService.GetProvider(element.ProviderName) : default(ISlidesProvider);
|
||||
var storage = new ElementStorage(element);
|
||||
var slidesProviderContext = new SlidesProviderContext(context.Content, element, storage);
|
||||
return provider == null ? new List<dynamic>() : new List<dynamic>(provider.BuildSlides(_services.New, slidesProviderContext));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,137 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using IDeliverable.Licensing.Orchard;
|
||||
using IDeliverable.Slides.Licensing;
|
||||
using IDeliverable.Slides.Models;
|
||||
using IDeliverable.Slides.Services;
|
||||
using IDeliverable.Slides.ViewModels;
|
||||
using Orchard;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Layouts.Framework.Drivers;
|
||||
|
||||
namespace IDeliverable.Slides.Drivers
|
||||
{
|
||||
public class SlideShowPartDriver : ContentPartDriver<SlideShowPart>
|
||||
{
|
||||
private readonly IOrchardServices _services;
|
||||
private readonly ISlideShowPlayerEngineManager _engineManager;
|
||||
private readonly ISlidesProviderService _providerService;
|
||||
private readonly ISlideShowProfileService _slideShowProfileService;
|
||||
|
||||
public SlideShowPartDriver(
|
||||
IOrchardServices services,
|
||||
ISlideShowPlayerEngineManager engineManager,
|
||||
ISlidesProviderService providerService,
|
||||
ISlideShowProfileService slideShowProfileService)
|
||||
{
|
||||
_services = services;
|
||||
_engineManager = engineManager;
|
||||
_providerService = providerService;
|
||||
_slideShowProfileService = slideShowProfileService;
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(SlideShowPart part, dynamic shapeHelper)
|
||||
{
|
||||
return Editor(part, null, shapeHelper);
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(SlideShowPart part, IUpdateModel updater, dynamic shapeHelper)
|
||||
{
|
||||
if (!LicenseValidationHelper.GetLicenseIsValid(LicensedProductManifest.ProductId))
|
||||
return ContentShape("Parts_SlideShow_Edit_InvalidLicense", () => shapeHelper.Parts_SlideShow_Edit_InvalidLicense());
|
||||
|
||||
return ContentShape("Parts_SlideShow_Edit", () =>
|
||||
{
|
||||
var storage = new ContentPartStorage(part);
|
||||
var slidesProviderContext = new SlidesProviderContext(part, part, storage);
|
||||
var providerShapes = Enumerable.ToDictionary(_providerService.BuildEditors(shapeHelper, slidesProviderContext), (Func<dynamic, string>)(x => (string)x.Provider.Name));
|
||||
|
||||
var viewModel = new SlideShowPartViewModel
|
||||
{
|
||||
Part = part,
|
||||
ProfileId = part.ProfileId,
|
||||
AvailableProfiles = _services.WorkContext.CurrentSite.As<SlideShowSettingsPart>().Profiles.ToList(),
|
||||
ProviderName = part.ProviderName,
|
||||
AvailableProviders = providerShapes,
|
||||
};
|
||||
|
||||
if (updater != null)
|
||||
{
|
||||
if (updater.TryUpdateModel(viewModel, Prefix, new[] { "ProfileId", "ProviderName" }, null))
|
||||
{
|
||||
providerShapes = Enumerable.ToDictionary(_providerService.UpdateEditors(shapeHelper, slidesProviderContext, new Updater(updater, Prefix)), (Func<dynamic, string>)(x => (string)x.Provider.Name));
|
||||
part.ProfileId = viewModel.ProfileId;
|
||||
part.ProviderName = viewModel.ProviderName;
|
||||
viewModel.AvailableProviders = providerShapes;
|
||||
}
|
||||
}
|
||||
|
||||
return shapeHelper.EditorTemplate(TemplateName: "Parts.SlideShow", Prefix: Prefix, Model: viewModel);
|
||||
});
|
||||
}
|
||||
|
||||
protected override DriverResult Display(SlideShowPart part, string displayType, dynamic shapeHelper)
|
||||
{
|
||||
if (!LicenseValidationHelper.GetLicenseIsValid(LicensedProductManifest.ProductId))
|
||||
return ContentShape("Parts_SlideShow_InvalidLicense", () => shapeHelper.Parts_SlideShow_InvalidLicense());
|
||||
|
||||
return Combined(
|
||||
ContentShape("Parts_SlideShow", () =>
|
||||
{
|
||||
var slideShapes = GetSlides(part, shapeHelper);
|
||||
var engine = _engineManager.GetEngine(part.Profile);
|
||||
var engineShape = engine.BuildDisplay(shapeHelper);
|
||||
|
||||
engineShape.Engine = engine;
|
||||
engineShape.Slides = slideShapes;
|
||||
engineShape.SlideShowId = part.Id.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
return shapeHelper.Parts_SlideShow(Slides: slideShapes, Engine: engineShape);
|
||||
}),
|
||||
ContentShape("Parts_SlideShow_Summary", () =>
|
||||
{
|
||||
var slideShapes = GetSlides(part, shapeHelper);
|
||||
return shapeHelper.Parts_SlideShow_Summary(Slides: slideShapes);
|
||||
}),
|
||||
ContentShape("Parts_SlideShow_SummaryAdmin", () =>
|
||||
{
|
||||
var slideShapes = GetSlides(part, shapeHelper);
|
||||
return shapeHelper.Parts_SlideShow_SummaryAdmin(Slides: slideShapes);
|
||||
}));
|
||||
}
|
||||
|
||||
protected override void Exporting(SlideShowPart part, ExportContentContext context)
|
||||
{
|
||||
context.Element(part.PartDefinition.Name).SetAttributeValue("Profile", part.Profile?.Name);
|
||||
context.Element(part.PartDefinition.Name).SetAttributeValue("Provider", part.ProviderName);
|
||||
|
||||
var storage = new ContentPartStorage(part);
|
||||
var providersElement = _providerService.Export(storage, part);
|
||||
|
||||
context.Element(part.PartDefinition.Name).Add(providersElement);
|
||||
}
|
||||
|
||||
protected override void Importing(SlideShowPart part, ImportContentContext context)
|
||||
{
|
||||
context.ImportAttribute(part.PartDefinition.Name, "Profile", profileName => part.ProfileId = _slideShowProfileService.FindByName(profileName)?.Id);
|
||||
context.ImportAttribute(part.PartDefinition.Name, "Provider", providerName => part.ProviderName = _providerService.GetProvider(providerName)?.Name);
|
||||
|
||||
var storage = new ContentPartStorage(part);
|
||||
var providersElement = context.Data.Element(part.PartDefinition.Name)?.Element("Providers");
|
||||
|
||||
_providerService.Import(storage, providersElement, new ImportContentContextWrapper(context), part);
|
||||
}
|
||||
|
||||
private IList<dynamic> GetSlides(SlideShowPart part, dynamic shapeHelper)
|
||||
{
|
||||
var provider = !String.IsNullOrWhiteSpace(part.ProviderName) ? _providerService.GetProvider(part.ProviderName) : default(ISlidesProvider);
|
||||
var storage = new ContentPartStorage(part);
|
||||
var slidesProviderContext = new SlidesProviderContext(part, part, storage);
|
||||
return provider == null ? new List<dynamic>() : new List<dynamic>(provider.BuildSlides(shapeHelper, slidesProviderContext));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
using IDeliverable.Licensing.Orchard;
|
||||
using IDeliverable.Slides.Models;
|
||||
|
||||
namespace IDeliverable.Slides.Drivers
|
||||
{
|
||||
public class SlidesLicenseSettingsPartDriver : LicenseSettingsPartDriverBase<SlidesLicenseSettingsPart>
|
||||
{
|
||||
protected override string EditorShapeName => "Parts_Slides_License_Edit";
|
||||
protected override string EditorShapeTemplateName => "Parts.Slides.License";
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
using IDeliverable.Slides.Models;
|
||||
using Orchard.ContentManagement.Utilities;
|
||||
using Orchard.Layouts.Framework.Elements;
|
||||
using Orchard.Layouts.Helpers;
|
||||
|
||||
namespace IDeliverable.Slides.Elements
|
||||
{
|
||||
public class SlideShow : Element, ISlideShow
|
||||
{
|
||||
internal readonly LazyField<SlideShowProfile> _profileField = new LazyField<SlideShowProfile>();
|
||||
|
||||
public override string Category => "Media";
|
||||
public override bool HasEditor => true;
|
||||
|
||||
public int? ProfileId
|
||||
{
|
||||
get { return this.Retrieve(x => x.ProfileId); }
|
||||
set { this.Store(x => x.ProfileId, value); }
|
||||
}
|
||||
|
||||
public SlideShowProfile Profile => _profileField.Value;
|
||||
|
||||
public string ProviderName
|
||||
{
|
||||
get { return this.Retrieve(x => x.ProviderName); }
|
||||
set { this.Store(x => x.ProviderName, value); }
|
||||
}
|
||||
}
|
||||
}
|