Compare commits

...

166 Commits

Author SHA1 Message Date
Sipke Schoorstra
ce74a0e223 Added support for perpetual license keys. 2015-06-18 23:19:39 +03:00
Daniel Stolt
28c5214273 Made settings for Logentries and ApplicationInsights configurable in AppSettings and overridable in Azure portal. 2015-06-18 01:20:43 +03:00
Daniel Stolt
b7c3fc796f Changed text of retry link to "try again". 2015-06-17 23:48:41 +03:00
Daniel Stolt
4fb9768edf Added Logentries logging to licensing service. Made licensing service issue verification tokens in blanco on communication issues with SendOwl. 2015-06-17 23:22:21 +03:00
Sipke Schoorstra
0fd0956f02 Added assembly reference to Orchard.Layouts. 2015-06-17 14:07:03 +03:00
Sipke Schoorstra
4626b85129 Fixed profile name update bug. 2015-06-17 14:06:37 +03:00
Sipke Schoorstra
2992e41d09 Included correct view. 2015-06-17 14:06:20 +03:00
Daniel Stolt
fb9f45f6cc Merge branch '1.9.x' of https://ideliverable.visualstudio.com/defaultcollection/_git/IDeliverable.Star 2015-06-17 01:54:19 +03:00
Daniel Stolt
4e351c4d0b Removed logging from LicenseVerificationTokenStore. 2015-06-17 01:51:08 +03:00
Daniel Stolt
c852a88084 Fixed potential YSOD when reading corrupted license verification token from store. 2015-06-17 01:43:35 +03:00
Sipke Schoorstra
7e071beba4 Increased obfuscation strength. 2015-06-15 23:11:03 +03:00
Daniel Stolt
25f1047922 Added a bit of cleanup to the packaging script. 2015-06-15 22:58:16 +03:00
Daniel Stolt
34155919a6 Adding missing file. 2015-06-15 21:32:25 +03:00
Daniel Stolt
ca94b09e91 Merge branch '1.9.x' of https://ideliverable.visualstudio.com/defaultcollection/_git/IDeliverable.Star 2015-06-15 21:22:27 +03:00
Daniel Stolt
ceed3c27d8 Made merging work once again, with minimum confusion of the result. 2015-06-15 21:22:08 +03:00
Sipke Schoorstra
65e23d5859 Added missing TranslationManager dependencies. 2015-06-15 21:00:35 +03:00
Daniel Stolt
e245dd5ce1 Merge branch '1.9.x' of https://ideliverable.visualstudio.com/defaultcollection/_git/IDeliverable.Star 2015-06-15 20:36:57 +03:00
Daniel Stolt
14b13c026a Fixed AutoFuck fucking fuck. 2015-06-15 20:36:33 +03:00
Sipke Schoorstra
0169fa68ee Added PO files. 2015-06-15 20:31:28 +03:00
Sipke Schoorstra
cf9c6040d3 Merge branch '1.9.x' of https://ideliverable.visualstudio.com/DefaultCollection/_git/IDeliverable.Star into 1.9.x 2015-06-15 20:20:08 +03:00
Daniel Stolt
88e39407ef Integrated confusion into the publishing workflow. 2015-06-15 20:14:07 +03:00
Daniel Stolt
3ef5499d94 Merge branch '1.9.x' of https://ideliverable.visualstudio.com/defaultcollection/_git/IDeliverable.Star 2015-06-15 19:16:46 +03:00
Daniel Stolt
81503f4363 Corrected build action for some asset files. 2015-06-15 19:16:12 +03:00
Sipke Schoorstra
f194614296 Added Vandelay.TranslationManager. 2015-06-15 18:13:06 +03:00
Sipke Schoorstra
76af70e21d Implemented "Refresh" link on license key validation banner. 2015-06-15 15:56:43 +03:00
Sipke Schoorstra
a70b51eee0 Added Confuser to solution. 2015-06-15 13:49:36 +03:00
Sipke Schoorstra
d3249afaca Removed merge conflict artifacts. 2015-06-15 13:48:57 +03:00
Daniel Stolt
ee2e8c7a6d Improved licensing service to read signing certificate from both stores to increase portability. 2015-06-15 13:14:34 +03:00
Sipke Schoorstra
f9cf0b7fef Implemented subscription validity checking. 2015-06-15 13:10:21 +03:00
Daniel Stolt
21cf463c3b Made a bunch of non-exposed types internal. 2015-06-14 22:44:24 +03:00
Daniel Stolt
838fb79411 Improved styling of player engines. 2015-06-14 22:21:14 +03:00
Daniel Stolt
997a9cda0c Reformatted a bunch of inconsistently formatted code. 2015-06-14 21:42:26 +03:00
Daniel Stolt
94d87ff0eb Added API key authorization to licensing service. 2015-06-14 21:07:51 +03:00
Daniel Stolt
be01a7dac4 Merge branch '1.9.x' of https://ideliverable.visualstudio.com/defaultcollection/_git/IDeliverable.Star 2015-06-14 20:47:49 +03:00
Daniel Stolt
0c758b5492 Added ApplicationInsights to the licensing service. 2015-06-14 20:47:35 +03:00
Sipke Schoorstra
c5dcf58022 Set dependency references copy local = true for the obfuscation tool to be able to resolve dependencies. 2015-06-14 20:39:27 +03:00
Sipke Schoorstra
5facde1aee Fixed lifetime scope mismatch issue. 2015-06-14 20:38:37 +03:00
Daniel Stolt
7e07f2771f Fixed development recipe. 2015-06-14 19:15:33 +03:00
Daniel Stolt
8bab0d66ef Made verification token accessor logic more robust. 2015-06-14 18:36:16 +03:00
Daniel Stolt
5d28589afe Changed verification token store to clear existing token when license key changes. 2015-06-14 18:23:24 +03:00
Daniel Stolt
5e4518119f Added logging to LicenseValidationHelper. 2015-06-14 16:35:24 +03:00
Daniel Stolt
3c13172dea Added token age validation (with an allowable clock skew). 2015-06-14 16:17:05 +03:00
Daniel Stolt
efb70627fb Introduced static field for license validation cache duration. 2015-06-14 15:59:28 +03:00
Daniel Stolt
b88fc651f8 Removed unnecessary using statement. 2015-06-14 15:56:15 +03:00
Daniel Stolt
7b7b640e8d Fixed a couple of issues with the license validation result caching code. 2015-06-14 15:55:54 +03:00
Daniel Stolt
9f5db40605 Extended LicenseService to read signing certificate from either CurrentUser or LocalMachine stores for portability. 2015-06-14 15:48:01 +03:00
Sipke Schoorstra
8baf0ca550 Added support for caching exceptions and caching verification token. 2015-06-14 14:01:30 +03:00
Sipke Schoorstra
016cdc4489 Fixed serialization to exclude calculated properties, preventing signature validation from failing. 2015-06-14 13:41:22 +03:00
Sipke Schoorstra
e4e0f657f6 Fixed certificate base64 string, thumbprint and added exception handler condition. 2015-06-14 13:21:49 +03:00
Daniel Stolt
b301e04fe5 Merged Sipke's stuff. 2015-06-14 12:38:25 +03:00
Daniel Stolt
a3294affd2 Refactored validation error banner. 2015-06-14 12:35:38 +03:00
Sipke Schoorstra
0832e344d7 Fixed Slides license key banner. 2015-06-14 12:29:52 +03:00
Sipke Schoorstra
50db6acf45 Merged Daniel's refactoring and implemented Slides license key setting storage. 2015-06-14 12:09:07 +03:00
Daniel Stolt
3df91b51de Refactored module licensing code. 2015-06-14 12:00:27 +03:00
Daniel Stolt
d5ac015c12 Refactored a little more. 2015-06-14 01:13:02 +03:00
Daniel Stolt
07b11ecaab Merged Sipke's stuff. 2015-06-14 00:04:56 +03:00
Daniel Stolt
9154ecdf67 Refactored licensing framework. A little. 2015-06-13 23:56:35 +03:00
Sipke Schoorstra
d621232812 Simplified sample theme settings file. 2015-06-13 23:40:19 +03:00
Sipke Schoorstra
e7209d308b Added Widgets and ThemeSettings modules. 2015-06-13 20:21:07 +03:00
Sipke Schoorstra
e510b179f5 Merge branch '1.9.x' of https://ideliverable.visualstudio.com/DefaultCollection/_git/IDeliverable.Star into 1.9.x 2015-06-13 16:14:14 +03:00
Sipke Schoorstra
134b5e83a0 Implemented Import/Export for Slides. 2015-06-13 16:12:37 +03:00
Sipke Schoorstra
7f6672861b Fixed service factory.
The order of static properties is important when first accessing the Current static property.
2015-06-13 16:11:16 +03:00
Daniel Stolt
f0aa1aebc8 Removed unused stuff from licensing service. 2015-06-13 11:41:31 +03:00
Daniel Stolt
849a41df6c Removed and disabled the use of solution-specific applicationHost.config file. 2015-06-13 11:16:55 +03:00
Sipke Schoorstra
4462746c43 Merge branch '1.9.x' of https://ideliverable.visualstudio.com/DefaultCollection/_git/IDeliverable.Star into 1.9.x 2015-06-13 00:38:21 +03:00
Sipke Schoorstra
1ebc5a6f78 Refactored licensing code.
- Seperated license retrieval from license validation logic.
- Removed dependency on AutoFac injected services to avoid mocking attacks.
2015-06-13 00:37:08 +03:00
Sipke Schoorstra
5221c01ae3 Refactored licensing code.
- Separated license retrieval from license validation logic.
- Removed dependency on AutoFac injected services to avoid mocking attacks.
2015-06-13 00:01:19 +03:00
Daniel Stolt
88e7378165 Added an IDeliverable.Slides development recipe (not quite complete, needs import/export of profiles and slideshow items). 2015-06-12 21:23:21 +03:00
Daniel Stolt
80744b1633 Made licensing service more configurable. 2015-06-12 19:54:01 +03:00
Daniel Stolt
56315b92d1 Merge branch '1.9.x' of https://ideliverable.visualstudio.com/defaultcollection/_git/IDeliverable.Star 2015-06-12 17:54:10 +03:00
Daniel Stolt
bf9651e332 Fixed support for nested carousels. 2015-06-12 17:53:57 +03:00
Sipke Schoorstra
d721a0189b Renamed 'Engine' to 'SlideShowPlayerEngine'. 2015-06-12 17:13:39 +03:00
Daniel Stolt
75e5a5ee1c Merge branch '1.9.x' of https://ideliverable.visualstudio.com/defaultcollection/_git/IDeliverable.Star 2015-06-12 14:51:17 +03:00
Daniel Stolt
bc27d3d673 Added test action to licensing service for monitoring purposes. 2015-06-12 14:51:01 +03:00
Sipke Schoorstra
94c1e6b7b9 Pulled from orchard/1.9.x. 2015-06-12 14:35:23 +03:00
Sipke Schoorstra
9466d91438 #5379: Improved LayoutPartDriver to safely handle recursive layout rendering.
This prevents a SO exception when you for example have a Projection element that renders content including the content item rendering that Projection element.
2015-06-12 13:28:53 +03:00
Daniel Stolt
0d23e58f03 Improved styling of JCarousel player engine. 2015-06-12 13:14:46 +03:00
Bertrand Le Roy
e3a9758331 Add a break element that renders the hr tag. 2015-06-11 20:47:37 -07:00
Sipke Schoorstra
a5196b4940 Implemented invalid license key banner. 2015-06-12 01:31:03 +03:00
Daniel Stolt
e209571315 Merged Sipkes stuff. 2015-06-12 01:07:23 +03:00
Daniel Stolt
8a180b8b8f Gulpified all client-side assets in IDeliverable.Slides. 2015-06-12 01:04:16 +03:00
Sipke Schoorstra
3cc5c3b4c3 Included font files. 2015-06-12 00:26:26 +03:00
Sipke Schoorstra
acbf738327 Gulpified Slides and made Bootstrap engine work without requiring a bootstrap enabled theme. 2015-06-11 23:51:54 +03:00
Bertrand Le Roy
564eeacf04 Merge branch '1.9.x' of https://github.com/OrchardCMS/Orchard into 1.9.x 2015-06-11 10:03:57 -07:00
Daniel Stolt
50e4e5635f Fixed a incorrect assembly references. 2015-06-11 18:00:52 +03:00
Sipke Schoorstra
c648e5b2ae Merge branch '1.9.x' of https://ideliverable.visualstudio.com/DefaultCollection/_git/IDeliverable.Star into 1.9.x 2015-06-11 17:52:53 +03:00
Sipke Schoorstra
35f941cf4e Fixed Newtonsoft.Json references. 2015-06-11 17:50:51 +03:00
Daniel Stolt
d63703903c Added applicationHost.config. 2015-06-11 17:43:17 +03:00
Daniel Stolt
ea68f07d81 Merge branch '1.9.x' of https://github.com/OrchardCMS/Orchard into 1.9.x 2015-06-11 17:24:59 +03:00
Daniel Stolt
83429f4000 Restoring commit: Render fieldset as a fieldset in the editor canvas (by Bertrand Le Roy). 2015-06-11 16:11:30 +03:00
Sipke Schoorstra
042d87c309 Merge branch 'master' into 1.9.x
Conflicts:
	src/Orchard.Web/Modules/IDeliverable.Slides/Views/License/Index.cshtml
2015-06-11 15:08:19 +03:00
Sipke Schoorstra
55790a606f Updated Slides module code to latest. 2015-06-11 15:07:04 +03:00
Sipke Schoorstra
e942437481 Manually registering services. 2015-06-11 14:55:44 +03:00
Sipke Schoorstra
7d95f1184d Merge branch 'master' into 1.9.x 2015-06-11 14:22:50 +03:00
Sipke Schoorstra
32cd707bd0 Restructured IDeliverable Licensing folders a bit. 2015-06-11 14:22:26 +03:00
Sipke Schoorstra
abdb83a9c3 Merge branch '1.9.x' of https://github.com/OrchardCMS/Orchard into 1.9.x 2015-06-11 13:56:36 +03:00
Sipke Schoorstra
82daedee80 Fixed compilation errors and split Licensing Framework files into separate projects. 2015-06-11 13:54:44 +03:00
Daniel Stolt
add2e1c3b9 Added initial IDeliverable.Star projects. 2015-06-11 12:38:20 +03:00
Daniel Stolt
6ee3b0d2eb Removed bogus file. 2015-06-11 12:12:11 +03:00
Daniel Stolt
b1fb3900d9 Merge branch 'master' of https://github.com/OrchardCMS/Orchard 2015-06-11 11:59:41 +03:00
Daniel Stolt
cef0022df3 Added bogus file. 2015-06-11 11:51:17 +03:00
Bertrand Le Roy
47a0a87dc0 Render fieldset as a fieldset in the editor canvas. 2015-06-10 13:10:59 -07:00
Daniel Stolt
c8590fd934 Added missing NPM dependency in Orchard.Layouts. 2015-06-10 23:06:41 +03:00
Sipke Schoorstra
1ee4664c50 Removed two more non-existing files. 2015-06-10 22:36:34 +03:00
Daniel Stolt
e8de82b611 Added Gulp build to Orchard.DynamicForms. 2015-06-10 20:43:59 +03:00
Bertrand Le Roy
c16de7f20a Fix flashing popup when adding a fieldset to the layout canvas. 2015-06-10 10:26:47 -07:00
Daniel Stolt
c1eff70f4a Refactored client-side asset build automation to fix watch triggering. 2015-06-10 16:26:51 +03:00
Sipke Schoorstra
9fbaed9123 Removed non-existing files from Orchard.Layouts.csproj. 2015-06-10 11:04:17 +03:00
Bertrand Le Roy
ef3ca907c7 Remove editor completely when adding a fieldset to the layout editor. 2015-06-09 13:48:58 -07:00
Bertrand Le Roy
7a1983b47f Add a fieldset element 2015-06-09 13:08:57 -07:00
Sipke Schoorstra
230d1b5d5d Fixed missing view file issue. 2015-06-09 21:54:48 +03:00
Daniel Stolt
5d40be8390 Removing an MSBuild property that was not supposed to be committed. 2015-06-09 21:31:27 +03:00
Daniel Stolt
452b8cfeac Added sticky positioning to layout editor toolbox. 2015-06-09 19:38:44 +03:00
Daniel Stolt
d86a5ec8c5 Replaced Web Essentials with Gulp for Orchard.Layouts.
Starting with VS2015, Web Essentials will no longer perform tasks such as bundling, minification and LESS compilation. Developers are expected to use either Grunt or Gulp for front-end build automation. In order to enable working with the codebase in VS2015 going forward, this change is therefore necessary.
2015-06-09 14:09:03 +03:00
Sipke Schoorstra
711948fd64 Implemented import/export for VectorImage element. 2015-06-09 13:57:22 +03:00
Sipke Schoorstra
c4dacc1f62 Fixed that VectorImage would not render in TinyMCE. 2015-06-09 13:37:04 +03:00
Sipke Schoorstra
6a2b6d81f4 Formatted placement file. 2015-06-09 13:30:58 +03:00
Sipke Schoorstra
d6154078dc Fixed VectorImage placement. 2015-06-09 13:30:32 +03:00
Daniel Stolt
d9208bcc14 #5295: Fixed clipboard operations in layout element property popups. 2015-06-09 02:08:58 +03:00
Sipke Schoorstra
88679bd7ca Corrected bad merge. 2015-06-09 01:33:46 +03:00
Sipke Schoorstra
e03df31e50 Fixed unit tests. 2015-06-09 01:23:06 +03:00
Sipke Schoorstra
aba53e122d Cherry picked ce630f980c. 2015-06-09 01:22:41 +03:00
Sipke Schoorstra
c9887f4d39 Cherry picked 1e83068b8c. 2015-06-09 01:17:37 +03:00
Sipke Schoorstra
f0cd135993 Cherry picked 9bf6ac5718. 2015-06-09 01:14:49 +03:00
Daniel Stolt
d3ccd743e9 Added a missing MVC dependency assembly.
For people with MVC 4 installed on their local box, this DLL was in the GAC so this was not an issue. However, with only VS2015 installed and no pre-nuget version of MVC, this causes a YSOD.
2015-06-09 00:24:19 +03:00
Sipke Schoorstra
0b309677f8 #5367: Implemented import/export for the Projection Element. 2015-06-09 00:04:59 +03:00
Daniel Stolt
b2b6ea4bc2 Removed orphaned reference in Orchard.Layouts. 2015-06-08 23:49:39 +03:00
Sipke Schoorstra
e810d885a0 #5270: Fixed Shape type not found error. 2015-06-07 00:25:58 +02:00
Lombiq
0c7b52e1be #5355: Fixing that the selected terms in a TaxonomyField were cleared out when updating an editor group the field isn't displayed in 2015-06-06 00:34:55 +02:00
Lombiq
30411b6be5 #5348: Splitting ItemDisplayText in two (fixing the fix) 2015-06-06 00:32:29 +02:00
Sébastien Ros
c3379489d7 #5348: Splitting ItemDisplayText in two 2015-06-04 12:51:58 -07:00
Sébastien Ros
5c5ce99083 Merge pull request #5338 from qt1/IBN-Labs/Schemabuilder.TableDbName
Provide full table name prefix for migrations
2015-06-04 12:32:30 -07:00
Sébastien Ros
e709593197 Merge pull request #5321 from Xeevis/1.9.x
#5109: Email field shouldn't specify email type in design mode
2015-06-04 12:23:18 -07:00
Sébastien Ros
1b8e00a9c6 Merge pull request #5256 from jtkech/patch-4
#5235: Awaiting activities not cleared on saving
2015-06-04 12:04:31 -07:00
qt1
5b468b0ce0 remove fix for automatic addition of is null (maybe a different PR) 2015-06-01 03:33:14 +03:00
qt1
6e94264df2 Provide full table name prefix for migrations 2015-06-01 02:07:42 +03:00
Lombiq
917fd8425f Fixing ComponentNotRegisteredException during setup, fixes #4159
Added fix by jtkech.
2015-05-31 18:15:29 +02:00
Lombiq
ee0bd03c04 Fixing that Output Cache storage providers could fail with an ObjectDisposedException due to a deferred delegate execution causing the usage of dependencies from a disposed lifetime scope. 2015-05-30 01:37:31 +02:00
Sébastien Ros
3d25ca42c9 #5327: Fixing Orchard.Roles web.config file 2015-05-28 12:50:07 -07:00
jtkech
c2d18f216a Update AdminController.cs 2015-05-28 21:33:08 +02:00
Sébastien Ros
7b6e7deea7 Merge pull request #5314 from Skrypt/Fixing-#4963
Fixing #4963
2015-05-28 12:20:17 -07:00
Sébastien Ros
52038c677e Merge pull request #5313 from Skrypt/fixed-#5281
Fixing #5281
2015-05-28 12:19:48 -07:00
Sipke Schoorstra
53e58f60fe #5306: Minor refactoring of background http context factory. 2015-05-27 16:36:51 +02:00
jtkech
ff9d7aca51 Update Edit.cshtml 2015-05-25 21:42:00 +02:00
jtkech
1c81a77302 Update AdminController.cs 2015-05-25 21:37:37 +02:00
Xeevis
3b5de0679f #5109: Email field shouldn't specify email type in design mode
When email type is specified on an input it triggers browser validation on that field which prevents administrator from inserting tokens like {User.Email}.
2015-05-25 01:08:59 +02:00
Sipke Schoorstra
ef2abe14cb #5306: Implemented a background HttpContext factory.
This change instantiates an actual HttpContext object during background sweeps so that Razor templates using Html Helpers (that require HttpContext.Current to be not-null) won't fai lwhen being rendered.
2015-05-22 15:37:51 +02:00
Skrypt
754114c8e6 Rebase on 1.9.x since this is a bug fix
Fixing #4963
2015-05-21 16:23:27 -04:00
Skrypt
6eb9e0d457 Fixing #5281 2015-05-21 16:10:09 -04:00
Sébastien Ros
3e55c1649e Merge pull request #5273 from Xeevis/1.9.x
#5224: Fix for missing charset in response header for cached output
2015-05-21 12:21:59 -07:00
Sipke Schoorstra
ce36e115d0 Removed unnecessary field. 2015-05-21 17:25:50 +02:00
Sipke Schoorstra
4d242e83df #5306: Injecting HttpContextBase directly.
This will ensure that an actual HttpContext object will be available in case of background task operations thanks to the way HttpContextBase is registered (providing a placeholder object in case of background operations).
2015-05-21 17:24:45 +02:00
Sébastien Ros
475feb923d Merge pull request #5278 from mvarblow/1.9.x
Fix for Issue #5274 - Faulty import in SslSettingsPartDriver
2015-05-14 12:58:40 -07:00
mvarblow
ce728380a1 Merge pull request #1 from mvarblow/mvarblow-patch-5274
Update SslSettingsPartDriver.cs
2015-05-14 15:49:45 -04:00
Sébastien Ros
d53d7346ee Merge pull request #5276 from mvarblow/mvarblow-patch-5275
Mvarblow patch 5275
2015-05-14 12:42:12 -07:00
Sipke Schoorstra
f8c6feea86 #5216: Added call to *InitHelpers*.
This will cause various helpers to be initialized, such as the *Html* property.
2015-05-14 10:24:04 -07:00
Lombiq
b98d35305a Revert "Indexing task creation now happens gradually in a background task, preventing timeout/out of memory when editing a content type with many items. Fixes #4729."
Commit moved to dev branch as it's not a completely safe change.

This reverts commit 40243f2224.
2015-05-14 12:54:02 +02:00
mvarblow
fa7bf025b9 Update MediaItems.cshtml 2015-05-13 16:57:10 -04:00
mvarblow
f5862bd628 Update MediaController.cs
Fix for issue https://github.com/OrchardCMS/Orchard/issues/5275.  The fix is to return the FolderPath element in the response to the media search request so that the folderPath check in the javascript code succeeds.
2015-05-13 16:54:23 -04:00
mvarblow
2339bdc966 Update SslSettingsPartDriver.cs
Fixed issue 5274
2015-05-13 16:45:55 -04:00
Xeevis
7cdb984f4f #5224: Fix for missing charset in response header for cached output 2015-05-13 15:24:46 +02:00
Lombiq
40243f2224 Indexing task creation now happens gradually in a background task, preventing timeout/out of memory when editing a content type with many items. Fixes #4729. 2015-05-11 23:17:58 +02:00
Lombiq
91e040e684 Fixing that the technical names of widgets couldn't contain hyphens, see #4981 2015-05-11 16:52:54 +02:00
jtkech
ae18e0b817 #5235: Awaiting activities not cleared on saving 2015-05-07 21:37:04 +02:00
Sébastien Ros
73336e19ba Merge pull request #5255 from jtkech/patch-3
#5234 Duplicate lines in WorkflowManager
2015-05-07 12:30:58 -07:00
jtkech
61b8f82fd7 #5234 Duplicate lines in WorkflowManager 2015-05-07 21:24:08 +02:00
563 changed files with 66030 additions and 5344 deletions

16
.gitignore vendored
View File

@@ -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,7 +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
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/*/*.*

Binary file not shown.

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<doc>
<assembly>
<name>Microsoft.Web.Infrastructure</name>
</assembly>
<members>
<member name="T:Microsoft.Web.Infrastructure.HttpContextHelper"></member>
<member name="M:Microsoft.Web.Infrastructure.HttpContextHelper.ExecuteInNullContext(System.Action)"></member>
<member name="T:Microsoft.Web.Infrastructure.InfrastructureHelper"></member>
<member name="M:Microsoft.Web.Infrastructure.InfrastructureHelper.IsCodeDomDefinedExtension(System.String)"></member>
<member name="M:Microsoft.Web.Infrastructure.InfrastructureHelper.UnloadAppDomain"></member>
<member name="T:Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility"></member>
<member name="M:Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(System.Type)"></member>
<member name="T:Microsoft.Web.Infrastructure.DynamicValidationHelper.ValidationUtility"></member>
<member name="M:Microsoft.Web.Infrastructure.DynamicValidationHelper.ValidationUtility.EnableDynamicValidation(System.Web.HttpContext)"></member>
<member name="M:Microsoft.Web.Infrastructure.DynamicValidationHelper.ValidationUtility.GetUnvalidatedCollections(System.Web.HttpContext,System.Func`1@,System.Void)"></member>
<member name="M:Microsoft.Web.Infrastructure.DynamicValidationHelper.ValidationUtility.IsValidationEnabled(System.Web.HttpContext)"></member>
</members>
</doc>

View File

@@ -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>

View File

@@ -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; }
}
}

View File

@@ -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); }
}
}
}

View File

@@ -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");
}
}
}

View File

@@ -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;
}
}

View File

@@ -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 : "~/");
}
}
}

View File

@@ -0,0 +1,71 @@
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 retryResultUrl = mUrlHelper.Action("VerifyLicenseKey", "LicenseValidation", new { area = productManifest.ProductName });
var retryResultLink = T("<a href=\"{0}\">Try again</a>", retryResultUrl);
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, retryResultLink);
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, retryResultLink);
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, retryResultLink);
break;
case LicenseValidationError.LicenseRevoked:
message = T("The <a href=\"{0}\">configured license key</a> for the {1} module has been revoked. {2}", licenseSettingsUrl, productManifest.ProductName, retryResultLink);
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, retryResultLink);
break;
}
Logger.Warning(ex, "An error occurred while validating the configured license key for the {0} module. {1}", productManifest.ProductName, retryResultLink);
}
if (message != null)
yield return new NotifyEntry { Message = message, Type = NotifyType.Warning };
}
}
}

View File

@@ -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}";
}
}
}

View File

@@ -0,0 +1,63 @@
using System;
using IDeliverable.Licensing.VerificationTokens;
using Orchard.FileSystems.AppData;
using Orchard.Logging;
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;
LicenseVerificationToken token = null;
var tokenBase64 = mAppDataFolder.ReadFile(path);
try
{
token = LicenseVerificationToken.FromBase64(tokenBase64);
}
catch
{
// An exception while parsing the token indicates somebody probably
// tampered with it or it got corrupted. In this case, let's clear out
// the store and return nothing.
Clear(productId);
}
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";
}
}
}

View File

@@ -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")]

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,53 @@
<?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
-->
<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>
</ApplicationInsights>

View File

@@ -0,0 +1,89 @@
using System;
using System.Configuration;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using IDeliverable.Licensing.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, string productId, string hostname)
{
var service = GetLicenseService();
try
{
return service.VerifyLicense(licenseKey, productId, hostname, throwOnError: false);
}
catch (LicenseVerificationException ex)
{
switch (ex.Error)
{
case LicenseVerificationError.UnknownLicenseKey:
ThrowHttpResponseException(ex, HttpStatusCode.NotFound);
break;
case LicenseVerificationError.HostnameMismatch:
ThrowHttpResponseException(ex, HttpStatusCode.Forbidden);
break;
case LicenseVerificationError.NoActiveSubscription:
case LicenseVerificationError.LicenseRevoked:
ThrowHttpResponseException(ex, HttpStatusCode.Gone);
break;
default:
throw;
}
}
return null;
}
[HttpGet]
[Route("test")]
[ApiKeyAuthorization]
public HttpResponseMessage Test()
{
var testKey = ConfigurationManager.AppSettings["TestKey"];
var testProductId = ConfigurationManager.AppSettings["TestProductId"];
var testHostname = ConfigurationManager.AppSettings["TestHostname"];
var service = GetLicenseService();
try
{
service.VerifyLicense(testKey, testProductId, testHostname, throwOnError: true);
}
catch (Exception ex)
{
return new HttpResponseMessage(HttpStatusCode.InternalServerError) { ReasonPhrase = $"Verification for a supposedly valid license failed: {ex.Message}." };
}
return new HttpResponseMessage(HttpStatusCode.OK);
}
private static LicenseService GetLicenseService()
{
var sendOwlApiEndpoint = ConfigurationManager.AppSettings["SendOwlApiEndpoint"];
var sendOwlApiKey = ConfigurationManager.AppSettings["SendOwlApiKey"];
var sendOwlApiSecret = ConfigurationManager.AppSettings["SendOwlApiSecret"];
var tokenSigningCertificateThumbprint = ConfigurationManager.AppSettings["TokenSigningCertificateThumbprint"];
return new LicenseService(sendOwlApiEndpoint, sendOwlApiKey, sendOwlApiSecret, tokenSigningCertificateThumbprint);
}
private static void ThrowHttpResponseException(LicenseVerificationException ex, HttpStatusCode httpStatusCode)
{
var response = new HttpResponseMessage(httpStatusCode) { ReasonPhrase = ex.Message };
response.Headers.Add("LicensingErrorCode", ex.Error.ToString());
throw new HttpResponseException(response);
}
}
}

View File

@@ -0,0 +1 @@
<%@ Application Codebehind="Global.asax.cs" Inherits="IDeliverable.Licensing.Service.WebApiApplication" Language="C#" %>

View File

@@ -0,0 +1,22 @@
using System;
using System.Configuration;
using System.Web.Http;
using Microsoft.ApplicationInsights.Extensibility;
namespace IDeliverable.Licensing.Service
{
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
// Configure ApplicationInsights instrumentation key.
var instrumentationKey = ConfigurationManager.AppSettings["ApplicationInsights.InstrumentationKey"];
if (!String.IsNullOrWhiteSpace(instrumentationKey))
TelemetryConfiguration.Active.InstrumentationKey = instrumentationKey;
else
TelemetryConfiguration.Active.DisableTelemetry = true;
}
}
}

View File

@@ -0,0 +1,251 @@
<?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="log4net, Version=1.2.13.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\..\packages\log4net.2.0.3\lib\net40-full\log4net.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="LogentriesCore, Version=2.6.7.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\logentries.core.2.7.0\lib\net40\LogentriesCore.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="LogentriesLog4net, Version=2.6.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\logentries.log4net.2.7.0\lib\net40\LogentriesLog4net.dll</HintPath>
<Private>True</Private>
</Reference>
<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="Microsoft.WindowsAzure.Configuration, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.WindowsAzure.ConfigurationManager.3.1.0\lib\net40\Microsoft.WindowsAzure.Configuration.dll</HintPath>
<Private>True</Private>
</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="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="Services\Logger.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" />
<Content Include="Log4net.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>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<root>
<!-- Value of level may be ALL, DEBUG, INFO, WARN, ERROR, FATAL, OFF -->
<level value="DEBUG" />
<appender-ref ref="DebuggerAppender" />
<appender-ref ref="LeAppender" />
</root>
<appender name="LeAppender" type="log4net.Appender.LogentriesAppender, LogentriesLog4net">
<!-- Credentials are read from appSettings. -->
<immediateFlush value="true" />
<debug value="true" />
<useHttpPut value="false" />
<useSsl value="false" />
<layout type="log4net.Layout.PatternLayout">
<!-- The below pattern has been carefully formatted and optimized to work well with the Logentries.com entry parser. For reference see https://logentries.com/doc/search/. -->
<param name="ConversionPattern" value="%d %logger %level% %m%n%exceptionSessionId='%aspnet-request{ASP.NET_SessionId}'; Username='%aspnet-request{AUTH_USER}'; ClientIpAddress='%aspnet-request{REMOTE_ADDR}'; ClientUserAgent='%aspnet-request{HTTP_USER_AGENT}'; ServerName='%aspnet-request{SERVER_NAME}'; RequestMethod='%aspnet-request{REQUEST_METHOD}'; RequestUrl='%aspnet-request{URL}'; RequestQueryString='%aspnet-request{QUERY_STRING}'; RequestCookies='%aspnet-request{HTTP_COOKIE}'; MachineName='%property{log4net:HostName}';%n" />
</layout>
</appender>
<appender name="DebuggerAppender" type="log4net.Appender.DebugAppender">
<immediateFlush value="true" />
<layout type="log4net.Layout.SimpleLayout" />
</appender>
</log4net>

View File

@@ -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")]

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is used by the publish/package process of your Web project. You can customize the behavior of this process
by editing this MSBuild file. In order to learn more about this please visit http://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>MSDeploy</WebPublishMethod>
<ADUsesOwinOrOpenIdConnect>False</ADUsesOwinOrOpenIdConnect>
<LastUsedBuildConfiguration>Debug</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<SiteUrlToLaunchAfterPublish>http://ideliverable-licensing.azurewebsites.net</SiteUrlToLaunchAfterPublish>
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
<ExcludeApp_Data>False</ExcludeApp_Data>
<MSDeployServiceURL>ideliverable-licensing.scm.azurewebsites.net:443</MSDeployServiceURL>
<DeployIisAppPath>ideliverable-licensing</DeployIisAppPath>
<RemoteSitePhysicalPath />
<SkipExtraFilesOnServer>True</SkipExtraFilesOnServer>
<MSDeployPublishMethod>WMSVC</MSDeployPublishMethod>
<EnableMSDeployBackup>True</EnableMSDeployBackup>
<UserName>$ideliverable-licensing</UserName>
<_SavePWD>True</_SavePWD>
<_DestinationType>AzureWebSite</_DestinationType>
</PropertyGroup>
</Project>

View File

@@ -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; }
}
}

View File

@@ -0,0 +1,167 @@
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.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;
mLogger = new Logger(nameof(LicenseService));
}
private readonly string mSendOwlApiEndpoint;
private readonly string mSendOwlApiKey;
private readonly string mSendOwlApiSecret;
private readonly string mTokenSigningCertificateThumbprint;
private readonly Logger mLogger;
public LicenseVerificationToken VerifyLicense(string licenseKey, string productId, string hostname, bool throwOnError)
{
mLogger.Info($"Starting license verification... LicenseKey={licenseKey}; ProductId={productId}; Hostname={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)
{
if(order.SubscriptionId != null)
throw new LicenseVerificationException($"The license with key '{licenseKey}' is not associated with an active subscription.", LicenseVerificationError.NoActiveSubscription);
throw new LicenseVerificationException($"The license with key '{licenseKey}' has been revoked.", LicenseVerificationError.LicenseRevoked);
}
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);
}
}
catch (Exception ex) when (!(ex is LicenseVerificationException))
{
mLogger.Error($"An error occurred while verifying license with SendOwl. LicenseKey={licenseKey}; ProductId={productId}; Hostname={hostname};", ex);
if (throwOnError)
throw;
mLogger.Info("Ignoring error and issuing verification token anyway. LicenseKey={licenseKey}; ProductId={productId}; Hostname={hostname};");
}
mLogger.Info($"License verification finished. LicenseKey={licenseKey}; ProductId={productId}; Hostname={hostname};");
return CreateVerificationToken(productId, hostname, licenseKey);
}
private LicenseVerificationToken CreateVerificationToken(string 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 static OrderInfo ParseOrderInfo(string json)
{
var order = JObject.Parse(json)["order"];
var status = ReadOrderStatus(order);
var isAccessAllowed = (bool) order["access_allowed"];
var subscriptionId = (int?) order["subscription_id"];
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, subscriptionId, 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;
}
}
}

View File

@@ -0,0 +1,64 @@
using System;
using System.IO;
using log4net;
using log4net.Config;
namespace IDeliverable.Licensing.Service.Services
{
public class Logger
{
private const string ConfigFileName = "Log4net.config";
static Logger()
{
var basePath = AppDomain.CurrentDomain.BaseDirectory;
var configFilePath = Path.Combine(basePath, ConfigFileName);
if (File.Exists(configFilePath))
XmlConfigurator.Configure(new FileInfo(configFilePath));
else
throw new Exception($"The log4net configuration file could not be found at path '{configFilePath}'.");
}
public Logger(Type loggerType)
:this(loggerType.FullName)
{
}
public Logger(string loggerName)
{
mLog = LogManager.GetLogger(loggerName);
}
private ILog mLog;
public void Fatal(string message, Exception ex = null)
{
if (mLog.IsFatalEnabled)
mLog.Fatal(message, ex);
}
public void Error(string message, Exception ex = null)
{
if (mLog.IsErrorEnabled)
mLog.Error(message, ex);
}
public void Warn(string message, Exception ex = null)
{
if (mLog.IsWarnEnabled)
mLog.Warn(message, ex);
}
public void Info(string message, Exception ex = null)
{
if (mLog.IsInfoEnabled)
mLog.Info(message, ex);
}
public void Debug(string message, Exception ex = null)
{
if (mLog.IsDebugEnabled)
mLog.Debug(message, ex);
}
}
}

View File

@@ -0,0 +1,22 @@
using System.Collections.Generic;
namespace IDeliverable.Licensing.Service.Services
{
internal class OrderInfo
{
public OrderInfo(int orderId, OrderStatus status, bool isProductAccessAllowed, int? subscriptionId, IEnumerable<string> hostnames)
{
OrderId = orderId;
Hostnames = hostnames;
Status = status;
IsProductAccessAllowed = isProductAccessAllowed;
SubscriptionId = subscriptionId;
}
public int OrderId { get; }
public IEnumerable<string> Hostnames { get; }
public OrderStatus Status { get; }
public bool IsProductAccessAllowed { get; }
public int? SubscriptionId { get; }
}
}

View File

@@ -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,
}
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<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" />
<add key="Logentries.Token" value="5c73ab7f-39a3-4171-b730-03da5c3d4b24"/> <!-- Local -->
<add key="ApplicationInsights.InstrumentationKey" value="" /> <!-- Disabled -->
</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>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="log4net" version="2.0.3" targetFramework="net452" userInstalled="true" />
<package id="logentries.core" version="2.7.0" targetFramework="net452" userInstalled="true" />
<package id="logentries.log4net" version="2.7.0" targetFramework="net452" userInstalled="true" />
<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="Microsoft.WindowsAzure.ConfigurationManager" version="3.1.0" targetFramework="net452" userInstalled="true" />
<package id="Newtonsoft.Json" version="6.0.4" targetFramework="net452" userInstalled="true" />
</packages>

View File

@@ -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; }
}
}

View 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);
}
}
}

View File

@@ -0,0 +1,11 @@
namespace IDeliverable.Licensing.Exceptions
{
public enum LicenseVerificationError
{
UnknownLicenseKey,
NoActiveSubscription,
LicenseRevoked,
HostnameMismatch,
UnhandledException
}
}

View File

@@ -0,0 +1,29 @@
using System;
namespace IDeliverable.Licensing.Exceptions
{
public 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; }
}
}

View File

@@ -0,0 +1,12 @@
using System.Web;
namespace IDeliverable.Licensing
{
public class HttpContextAccessor
{
public HttpContextBase Current()
{
return new HttpContextWrapper(HttpContext.Current);
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,74 @@
<?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="Exceptions\LicenseVerificationError.cs" />
<Compile Include="Exceptions\LicenseVerificationException.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>

View File

@@ -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")]

View File

@@ -0,0 +1,15 @@
namespace IDeliverable.Licensing.Validation
{
public enum LicenseValidationError
{
UnknownLicenseKey,
HostnameMismatch,
NoActiveSubscription,
LicenseRevoked,
LicensingServiceError,
LicensingServiceUnreachable,
TokenAgeValidationFailed,
TokenSignatureValidationFailed,
UnexpectedError,
}
}

View File

@@ -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; }
}
}

View File

@@ -0,0 +1,12 @@
using System;
namespace IDeliverable.Licensing.Validation
{
[Flags]
public enum LicenseValidationOptions
{
Default = 0,
SkipForLocalRequests = 1,
ForceRenewToken = 2,
}
}

View File

@@ -0,0 +1,141 @@
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.LicenseRevoked:
error = LicenseValidationError.LicenseRevoked;
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;
}
}
}

View File

@@ -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);
}
}

View File

@@ -0,0 +1,36 @@
using System;
using Newtonsoft.Json;
namespace IDeliverable.Licensing.VerificationTokens
{
public class LicenseVerificationInfo
{
public LicenseVerificationInfo(string productId, string hostname, string licenseKey, long verifiedUtcTicks)
{
ProductId = productId;
Hostname = hostname;
LicenseKey = licenseKey;
VerifiedUtcTicks = verifiedUtcTicks;
}
public string 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
});
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,73 @@
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 ||
lvtex.Error == LicenseVerificationTokenError.LicenseRevoked)
{
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;
}
}
}

View File

@@ -0,0 +1,13 @@
namespace IDeliverable.Licensing.VerificationTokens
{
public enum LicenseVerificationTokenError
{
UnknownLicenseKey,
HostnameMismatch,
NoActiveSubscription,
LicenseRevoked,
LicenseServiceError,
LicenseServiceUnreachable,
UnexpectedError
}
}

View File

@@ -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; }
}
}

View File

@@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using IDeliverable.Licensing.Exceptions;
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;
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.IsSuccessStatusCode)
{
var licenseVerificationError = ReadLicenseVerificationError(response);
switch (licenseVerificationError)
{
case LicenseVerificationError.UnknownLicenseKey:
throw new LicenseVerificationTokenException(response.ReasonPhrase, LicenseVerificationTokenError.UnknownLicenseKey);
case LicenseVerificationError.HostnameMismatch:
throw new LicenseVerificationTokenException(response.ReasonPhrase, LicenseVerificationTokenError.HostnameMismatch);
case LicenseVerificationError.NoActiveSubscription:
throw new LicenseVerificationTokenException(response.ReasonPhrase, LicenseVerificationTokenError.NoActiveSubscription);
case LicenseVerificationError.LicenseRevoked:
throw new LicenseVerificationTokenException(response.ReasonPhrase, LicenseVerificationTokenError.LicenseRevoked);
default:
throw new LicenseVerificationTokenException(response.ReasonPhrase, LicenseVerificationTokenError.LicenseServiceError);
}
}
var responseText = response.Content.ReadAsStringAsync().Result;
var token = LicenseVerificationToken.Parse(responseText);
return token;
}
finally
{
ServicePointManager.ServerCertificateValidationCallback -= certValidationHandler;
}
}
}
private static LicenseVerificationError? ReadLicenseVerificationError(HttpResponseMessage response)
{
IEnumerable<string> values;
if (!response.Headers.TryGetValues("LicensingErrorCode", out values))
return null;
var value = values.First();
return (LicenseVerificationError)Enum.Parse(typeof(LicenseVerificationError), value);
}
}
}

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View 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>

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -24,5 +24,10 @@ namespace Orchard.Tests.DataMigration.Utilities {
public void Visit(DropForeignKeyCommand command) {
}
public string PrefixTableName(string tableName) {
return tableName;
}
}
}

View File

@@ -1,5 +1,6 @@
using System.Web;
using Autofac;
using Moq;
using NUnit.Framework;
using Orchard.Environment;
using Orchard.Mvc;
@@ -27,6 +28,13 @@ namespace Orchard.Tests.Environment {
container.Mock<IHttpContextAccessor>()
.Setup(x => x.Current())
.Returns(() => _httpContextCurrent);
container.Mock<IHttpContextAccessor>()
.Setup(x => x.CreateContext(It.IsAny<ILifetimeScope>()))
.Returns(() => new StubHttpContext());
container.Mock<IWorkContextEvents>()
.Setup(x => x.Started());
}
[Test]

View File

@@ -9,6 +9,7 @@ using Orchard.Environment.Descriptor;
using Orchard.Environment.Descriptor.Models;
using Orchard.Environment.ShellBuilders.Models;
using Orchard.Mvc;
using Orchard.Tests.Stubs;
using Orchard.Tests.Utility;
namespace Orchard.Tests.Environment.ShellBuilders {
@@ -32,6 +33,7 @@ namespace Orchard.Tests.Environment.ShellBuilders {
var descriptor = new ShellDescriptor { SerialNumber = 6655321 };
var blueprint = new ShellBlueprint();
var shellLifetimeScope = _container.BeginLifetimeScope("shell");
var httpContext = new StubHttpContext();
_container.Mock<IShellDescriptorCache>()
.Setup(x => x.Fetch(ShellSettings.DefaultName))
@@ -49,9 +51,16 @@ namespace Orchard.Tests.Environment.ShellBuilders {
.Setup(x => x.GetShellDescriptor())
.Returns(descriptor);
_container.Mock<IWorkContextEvents>()
.Setup(x => x.Started());
_container.Mock<IHttpContextAccessor>()
.Setup(x => x.Current())
.Returns(default(HttpContextBase));
.Returns(httpContext);
_container.Mock<IHttpContextAccessor>()
.Setup(x => x.CreateContext(It.IsAny<ILifetimeScope>()))
.Returns(httpContext);
var factory = _container.Resolve<IShellContextFactory>();

View File

@@ -11,6 +11,7 @@ using Orchard.Environment.State;
using Orchard.Environment.Descriptor.Models;
using Orchard.Events;
using Orchard.Mvc;
using Orchard.Tests.Stubs;
using Orchard.Tests.Utility;
namespace Orchard.Tests.Environment.State {
@@ -34,12 +35,17 @@ namespace Orchard.Tests.Environment.State {
LifetimeScope = _container.BeginLifetimeScope(),
};
var httpContext = new StubHttpContext();
_container.Mock<IShellContextFactory>()
.Setup(x => x.CreateDescribedContext(_shellContext.Settings, _shellContext.Descriptor))
.Returns(_shellContext);
_container.Mock<IHttpContextAccessor>()
.Setup(x=>x.Current())
.Returns(default(HttpContextBase));
.Returns(httpContext);
_container.Mock<IHttpContextAccessor>()
.Setup(x => x.CreateContext(It.IsAny<ILifetimeScope>()))
.Returns(httpContext);
}

View File

@@ -1,4 +1,5 @@
using System.Web;
using Autofac;
using Orchard.Mvc;
namespace Orchard.Tests.Stubs {
@@ -16,6 +17,10 @@ namespace Orchard.Tests.Stubs {
return _httpContext;
}
public HttpContextBase CreateContext(ILifetimeScope lifetimeScope) {
return _httpContext;
}
public void Set(HttpContextBase httpContext) {
_httpContext = httpContext;
}

View File

@@ -3,7 +3,9 @@ using Autofac;
using Moq;
using NUnit.Framework;
using Orchard.Environment;
using Orchard.Mvc;
using Orchard.Tasks;
using Orchard.Tests.Stubs;
using Orchard.Tests.Utility;
namespace Orchard.Tests.Tasks {
@@ -16,6 +18,19 @@ namespace Orchard.Tests.Tasks {
builder.RegisterType<SweepGenerator>();
}
protected override void Resolve(ILifetimeScope container) {
container.Mock<IHttpContextAccessor>()
.Setup(x => x.Current())
.Returns(() => null);
container.Mock<IHttpContextAccessor>()
.Setup(x => x.CreateContext(It.IsAny<ILifetimeScope>()))
.Returns(() => new StubHttpContext());
container.Mock<IWorkContextEvents>()
.Setup(x => x.Started());
}
[Test]
public void DoWorkShouldSendHeartbeatToTaskManager() {
var heartbeatSource = _container.Resolve<SweepGenerator>();

View 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>

View File

@@ -42,7 +42,7 @@
// display a message on leave if changes have been made
window.onbeforeunload = function (e) {
return leaveConfirmation;
return $("<div/>").html(leaveConfirmation).text();
};
// cancel leaving message on save

View File

@@ -22,7 +22,7 @@
<label for="menuId">@T("Current Menu:")</label>
<select id="menuId" name="menuId">
@foreach (var menu in Model.Menus) {
@Html.SelectOption(Model.CurrentMenu.Id, menu.Id, Convert.ToString(Html.ItemDisplayText(menu)))
@Html.SelectOption(Model.CurrentMenu.Id, menu.Id, Convert.ToString(Html.ItemDisplayText(menu, false)))
}
</select>
@if (hasPermission) {
@@ -134,12 +134,12 @@
@using (Script.Foot()) {
<script type="text/javascript">
//<![CDATA[
var leaveConfirmation = '@T("Some items where not saved.")';
//<![CDATA[
var leaveConfirmation = '@HttpUtility.JavaScriptStringEncode(T("Some items where not saved.").Text)';
$('#menuId').change(function () {
$(this).parents('form').submit();
});
//]]>
//]]>
</script>
}

View File

@@ -6,7 +6,7 @@
@Html.LabelFor(m => m.CurrentMenuId, T("For Menu"))
<select id="@Html.FieldIdFor(m => m.CurrentMenuId)" name="@Html.FieldNameFor(m => m.CurrentMenuId)">
@foreach(ContentItem menu in Model.Menus) {
@Html.SelectOption(Model.CurrentMenuId, menu.Id, Html.ItemDisplayText(menu).ToString())
@Html.SelectOption(Model.CurrentMenuId, menu.Id, Html.ItemDisplayText(menu, false).ToString())
}
</select>
<span class="hint">@T("Select which menu you want to display")</span>

View File

@@ -11,7 +11,7 @@
<div data-controllerid="@Html.FieldIdFor(m => m.OnMenu)" class="">
<select id="@Html.FieldIdFor(m => m.CurrentMenuId)" name="@Html.FieldNameFor(m => m.CurrentMenuId)">
@foreach (ContentItem menu in Model.Menus) {
@Html.SelectOption(Model.CurrentMenuId, menu.Id, Html.ItemDisplayText(menu).ToString())
@Html.SelectOption(Model.CurrentMenuId, menu.Id, Html.ItemDisplayText(menu, false).ToString())
}
</select>
<span class="hint">@T("Select which menu you want the content item to be displayed on.")</span>

View File

@@ -2,6 +2,7 @@
using Orchard.ContentManagement;
using Orchard.Core.Settings.Models;
using Orchard.Mvc;
using Orchard.Mvc.Extensions;
using Orchard.Settings;
using Orchard.Utility.Extensions;
@@ -38,7 +39,7 @@ namespace Orchard.Core.Settings.Commands {
// Retrieve request URL if BaseUrl not provided as a switch value
if (string.IsNullOrEmpty(BaseUrl)) {
if (_httpContextAccessor.Current() == null) {
if (_httpContextAccessor.Current().IsBackgroundContext()) {
Context.Output.WriteLine(T("No HTTP request available to determine the base url of the site"));
return;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 KiB

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

View 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())));
}
}
}

View File

@@ -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."

Some files were not shown because too many files have changed in this diff Show More