diff --git a/Orchard.proj b/Orchard.proj index 5f1ae878d..f84846d28 100644 --- a/Orchard.proj +++ b/Orchard.proj @@ -8,6 +8,7 @@ $(MSBuildProjectDirectory)\src $(MSBuildProjectDirectory)\build $(MSBuildProjectDirectory)\buildtasks + $(LibFolder)\msbuild $(MSBuildProjectDirectory)\artifacts $(MSBuildProjectDirectory)\lib\sqlce $(ArtifactsFolder)\Source @@ -33,7 +34,7 @@ $(BUILD_NUMBER) - + @@ -156,7 +157,7 @@ - + @@ -338,6 +339,7 @@ $(MSBuildProjectDirectory)\src\**\bin\**\*; $(MSBuildProjectDirectory)\src\**\obj\**\*; $(MSBuildProjectDirectory)\**\App_Data\**\*; + $(MSBuildProjectDirectory)\**\node_modules\**\*; $(MSBuildProjectDirectory)\**\_ReSharper*\**\*; $(MSBuildProjectDirectory)\**\*.sln.cache; $(MSBuildProjectDirectory)\**\*.suo; @@ -369,8 +371,8 @@ - - + + diff --git a/lib/msbuild/ICSharpCode.SharpZipLib.dll b/lib/msbuild/ICSharpCode.SharpZipLib.dll deleted file mode 100644 index bcdb00ea3..000000000 Binary files a/lib/msbuild/ICSharpCode.SharpZipLib.dll and /dev/null differ diff --git a/lib/msbuild/Ionic.Zip.Reduced.dll b/lib/msbuild/Ionic.Zip.Reduced.dll new file mode 100644 index 000000000..9622cc53e Binary files /dev/null and b/lib/msbuild/Ionic.Zip.Reduced.dll differ diff --git a/lib/msbuild/MSBuild.Community.Tasks.Targets b/lib/msbuild/MSBuild.Community.Tasks.Targets index a04f036a0..b7ad52d62 100644 --- a/lib/msbuild/MSBuild.Community.Tasks.Targets +++ b/lib/msbuild/MSBuild.Community.Tasks.Targets @@ -1,116 +1,158 @@ - + - - - . - $(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.dll - + + $(MSBuildThisFileDirectory) + $([MSBUILD]::Unescape($(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.dll)) + - + - - - - - - - - - - - + + + + + + + + + + + + + + + - - - + + + - - - - - + + + + + - - + + - + - - - - - - - - - - + + + + + + + + + + + - - - - - - - + + + + + + + - - + + - + - + - - - - - - - - - + + + + + + + + + - - - - - - - - + + + + + + + - + + + + + + + + + - - - - - + - - + + + + + + - - - - + + - + + + + - - + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/msbuild/MSBuild.Community.Tasks.dll b/lib/msbuild/MSBuild.Community.Tasks.dll index ee8046a1d..1288d54c1 100644 Binary files a/lib/msbuild/MSBuild.Community.Tasks.dll and b/lib/msbuild/MSBuild.Community.Tasks.dll differ diff --git a/lib/msdeploy/createlogin.sql b/lib/msdeploy/createlogin.sql new file mode 100644 index 000000000..f9679c4e8 --- /dev/null +++ b/lib/msdeploy/createlogin.sql @@ -0,0 +1,9 @@ +/**********************************************************************/ +/* Install.SQL */ +/* Creates a login and makes the user a member of db roles */ +/* */ +/* Modifications for SQL AZURE - ON MASTER */ +/**********************************************************************/ + + +CREATE LOGIN PlaceHolderForUser WITH PASSWORD = 'PlaceHolderForPassword' \ No newline at end of file diff --git a/lib/msdeploy/createuser.sql b/lib/msdeploy/createuser.sql new file mode 100644 index 000000000..1db827770 --- /dev/null +++ b/lib/msdeploy/createuser.sql @@ -0,0 +1,15 @@ +/**********************************************************************/ +/* CreateUser.SQL */ +/* Creates a user and makes the user a member of db roles */ +/* This script runs against the User database and requires connection string */ +/* Supports SQL Server and SQL AZURE */ +/**********************************************************************/ + +-- Create database user and map to login +-- and add user to the datareader, datawriter, ddladmin and securityadmin roles +-- + +CREATE USER PlaceHolderForUser FOR LOGIN PlaceHolderForUser; +GO +EXEC sp_addrolemember 'db_owner', PlaceHolderForUser; +GO diff --git a/lib/msdeploy/install.sql b/lib/msdeploy/install.sql deleted file mode 100644 index c998bcbfc..000000000 --- a/lib/msdeploy/install.sql +++ /dev/null @@ -1,45 +0,0 @@ -/**********************************************************************/ -/* Install.SQL */ -/* Creates a login and makes the user a member of db roles */ -/* */ -/**********************************************************************/ - --- Declare variables for database name, username and password -DECLARE @dbName sysname, - @dbUser sysname, - @dbPwd nvarchar(max); - --- Set variables for database name, username and password -SET @dbName = 'PlaceHolderForDb'; -SET @dbUser = 'PlaceHolderForUser'; -SET @dbPwd = 'PlaceHolderForPassword'; - -DECLARE @cmd nvarchar(max) - --- Create login -IF( SUSER_SID(@dbUser) is null ) -BEGIN - print '-- Creating login ' - SET @cmd = N'CREATE LOGIN ' + quotename(@dbUser) + N' WITH PASSWORD ='''+ replace(@dbPwd, '''', '''''') + N'''' - EXEC(@cmd) -END - --- Create database user and map to login --- and add user to the datareader, datawriter, ddladmin and securityadmin roles --- -SET @cmd = N'USE ' + quotename(@DBName) + N'; -IF( NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = ''' + replace(@dbUser, '''', '''''') + N''')) -BEGIN - print ''-- Creating user''; - CREATE USER ' + quotename(@dbUser) + N' FOR LOGIN ' + quotename(@dbUser) + N'; - print ''-- Adding user''; - EXEC sp_addrolemember ''db_ddladmin'', ''' + replace(@dbUser, '''', '''''') + N'''; - print ''-- Adding user''; - EXEC sp_addrolemember ''db_securityadmin'', ''' + replace(@dbUser, '''', '''''') + N'''; - print ''-- Adding user''; - EXEC sp_addrolemember ''db_datareader'', ''' + replace(@dbUser, '''', '''''') + N'''; - print ''-- Adding user''; - EXEC sp_addrolemember ''db_datawriter'', ''' + replace(@dbUser, '''', '''''') + N'''; -END' -EXEC(@cmd) -GO \ No newline at end of file diff --git a/lib/msdeploy/manifest.xml b/lib/msdeploy/manifest.xml index 8c0bcb819..670d2c3e3 100644 --- a/lib/msdeploy/manifest.xml +++ b/lib/msdeploy/manifest.xml @@ -1,7 +1,13 @@ - + - - + + + + + + \ No newline at end of file diff --git a/lib/msdeploy/parameters.xml b/lib/msdeploy/parameters.xml index 3a2e494c9..db78a9991 100644 --- a/lib/msdeploy/parameters.xml +++ b/lib/msdeploy/parameters.xml @@ -47,19 +47,17 @@ - + - - + + - + + + diff --git a/src/Gulpfile.js b/src/Gulpfile.js index fce38f9fe..b602f5ca4 100644 --- a/src/Gulpfile.js +++ b/src/Gulpfile.js @@ -1,4 +1,5 @@ -var glob = require("glob"), +var fs = require("fs"), + glob = require("glob"), path = require("path-posix"), merge = require("merge-stream"), gulpif = require("gulp-if"), @@ -42,14 +43,24 @@ gulp.task("watch", function () { var pathWin32 = require("path"); getAssetGroups().forEach(function (assetGroup) { var watchPaths = assetGroup.inputPaths.concat(assetGroup.watchPaths); - gulp.watch(watchPaths, function (event) { - var isConcat = path.basename(assetGroup.outputFileName, path.extname(assetGroup.outputFileName)) !== "@"; - if (isConcat) - console.log("Asset file '" + event.path + "' was " + event.type + ", rebuilding asset group with output '" + assetGroup.outputPath + "'."); - else - console.log("Asset file '" + event.path + "' was " + event.type + ", rebuilding asset group."); - var doRebuild = true; - var task = createAssetGroupTask(assetGroup, doRebuild); + var inputWatcher; + function createWatcher() { + inputWatcher = gulp.watch(watchPaths, function (event) { + var isConcat = path.basename(assetGroup.outputFileName, path.extname(assetGroup.outputFileName)) !== "@"; + if (isConcat) + console.log("Asset file '" + event.path + "' was " + event.type + ", rebuilding asset group with output '" + assetGroup.outputPath + "'."); + else + console.log("Asset file '" + event.path + "' was " + event.type + ", rebuilding asset group."); + var doRebuild = true; + var task = createAssetGroupTask(assetGroup, doRebuild); + }); + } + createWatcher(); + gulp.watch(assetGroup.manifestPath, function (event) { + console.log("Asset manifest file '" + event.path + "' was " + event.type + ", restarting watcher."); + inputWatcher.remove(); + inputWatcher.end(); + createWatcher(); }); }); }); @@ -72,6 +83,7 @@ function getAssetGroups() { } function resolveAssetGroupPaths(assetGroup, assetManifestPath) { + assetGroup.manifestPath = assetManifestPath; assetGroup.basePath = path.dirname(assetManifestPath); assetGroup.inputPaths = assetGroup.inputs.map(function (inputPath) { return path.resolve(path.join(assetGroup.basePath, inputPath)); @@ -89,11 +101,18 @@ function resolveAssetGroupPaths(assetGroup, assetManifestPath) { function createAssetGroupTask(assetGroup, doRebuild) { var outputExt = path.extname(assetGroup.output).toLowerCase(); + var doConcat = path.basename(assetGroup.outputFileName, outputExt) !== "@"; + if (doConcat && !doRebuild) { + // Force a rebuild of this asset group is the asset manifest file itself is newer than the output. + var assetManifestStats = fs.statSync(assetGroup.manifestPath); + var outputStats = fs.existsSync(assetGroup.outputPath) ? fs.statSync(assetGroup.outputPath) : null; + doRebuild = !outputStats || assetManifestStats.mtime > outputStats.mtime; + } switch (outputExt) { case ".css": - return buildCssPipeline(assetGroup, doRebuild); + return buildCssPipeline(assetGroup, doConcat, doRebuild); case ".js": - return buildJsPipeline(assetGroup, doRebuild); + return buildJsPipeline(assetGroup, doConcat, doRebuild); } } @@ -101,13 +120,12 @@ function createAssetGroupTask(assetGroup, doRebuild) { ** PROCESSING PIPELINES */ -function buildCssPipeline(assetGroup, doRebuild) { +function buildCssPipeline(assetGroup, doConcat, doRebuild) { assetGroup.inputPaths.forEach(function (inputPath) { var ext = path.extname(inputPath).toLowerCase(); if (ext !== ".less" && ext !== ".css") throw "Input file '" + inputPath + "' is not of a valid type for output file '" + assetGroup.outputPath + "'."; }); - var doConcat = path.basename(assetGroup.outputFileName, ".css") !== "@"; var generateSourceMaps = assetGroup.hasOwnProperty("generateSourceMaps") ? assetGroup.generateSourceMaps : true; return gulp.src(assetGroup.inputPaths) .pipe(gulpif(!doRebuild, @@ -138,13 +156,12 @@ function buildCssPipeline(assetGroup, doRebuild) { .pipe(gulp.dest(assetGroup.outputDir)); } -function buildJsPipeline(assetGroup, doRebuild) { +function buildJsPipeline(assetGroup, doConcat, doRebuild) { assetGroup.inputPaths.forEach(function (inputPath) { var ext = path.extname(inputPath).toLowerCase(); if (ext !== ".ts" && ext !== ".js") throw "Input file '" + inputPath + "' is not of a valid type for output file '" + assetGroup.outputPath + "'."; }); - var doConcat = path.basename(assetGroup.outputFileName, ".js") !== "@"; var generateSourceMaps = assetGroup.hasOwnProperty("generateSourceMaps") ? assetGroup.generateSourceMaps : true; return gulp.src(assetGroup.inputPaths) .pipe(gulpif(!doRebuild, diff --git a/src/Orchard.Azure/.vs/config/applicationhost.config b/src/Orchard.Azure/.vs/config/applicationhost.config new file mode 100644 index 000000000..c5660c9a1 --- /dev/null +++ b/src/Orchard.Azure/.vs/config/applicationhost.config @@ -0,0 +1,1038 @@ + + + + + + + + +
+
+
+
+
+
+
+
+ + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+
+ + +
+
+
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Azure/Orchard.Azure.CloudService/Orchard.Azure.CloudService.ccproj b/src/Orchard.Azure/Orchard.Azure.CloudService/Orchard.Azure.CloudService.ccproj index 66bb61da8..0008ce829 100644 --- a/src/Orchard.Azure/Orchard.Azure.CloudService/Orchard.Azure.CloudService.ccproj +++ b/src/Orchard.Azure/Orchard.Azure.CloudService/Orchard.Azure.CloudService.ccproj @@ -35,8 +35,9 @@ + - + diff --git a/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceConfiguration.cscfg b/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceConfiguration.Cloud.cscfg similarity index 99% rename from src/Orchard.Azure/Orchard.Azure.CloudService/ServiceConfiguration.cscfg rename to src/Orchard.Azure/Orchard.Azure.CloudService/ServiceConfiguration.Cloud.cscfg index f61f4bfc9..be5261216 100644 --- a/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceConfiguration.cscfg +++ b/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceConfiguration.Cloud.cscfg @@ -1,21 +1,21 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceConfiguration.Local.cscfg b/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceConfiguration.Local.cscfg new file mode 100644 index 000000000..be5261216 --- /dev/null +++ b/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceConfiguration.Local.cscfg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Orchard.Azure/Orchard.Azure.CloudService/ecf/Orchard.Azure.WebContent/diagnostics.wadcfgx b/src/Orchard.Azure/Orchard.Azure.CloudService/ecf/Orchard.Azure.WebContent/diagnostics.wadcfgx new file mode 100644 index 000000000..99fad34fd --- /dev/null +++ b/src/Orchard.Azure/Orchard.Azure.CloudService/ecf/Orchard.Azure.WebContent/diagnostics.wadcfgx @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + devstoreaccount1 + + + + + true + \ No newline at end of file diff --git a/src/Orchard.Azure/Orchard.Azure.Web/Config/Host.config b/src/Orchard.Azure/Orchard.Azure.Web/Config/Host.config index 1593a1e2c..827c5a9ab 100644 --- a/src/Orchard.Azure/Orchard.Azure.Web/Config/Host.config +++ b/src/Orchard.Azure/Orchard.Azure.Web/Config/Host.config @@ -15,7 +15,7 @@ - + diff --git a/src/Orchard.Azure/Orchard.Azure.Web/Config/HostComponents.config b/src/Orchard.Azure/Orchard.Azure.Web/Config/HostComponents.config index 2da96521c..91ea6a690 100644 --- a/src/Orchard.Azure/Orchard.Azure.Web/Config/HostComponents.config +++ b/src/Orchard.Azure/Orchard.Azure.Web/Config/HostComponents.config @@ -1,98 +1,110 @@  - + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Azure/Orchard.Azure.Web/Config/Sites.config b/src/Orchard.Azure/Orchard.Azure.Web/Config/Sites.config index a9b061b5c..52ff25006 100644 --- a/src/Orchard.Azure/Orchard.Azure.Web/Config/Sites.config +++ b/src/Orchard.Azure/Orchard.Azure.Web/Config/Sites.config @@ -1,31 +1,50 @@  - -
- + +
+ + + - - + + - - - + Uncomment to use ReadUncommitted as the default isolation level. Please not that + Sql Server Ce doesn't support ReadUncommitted. - \ No newline at end of file + Isolation level for all database transaction. + See http://msdn.microsoft.com/en-us/library/system.transactions.isolationlevel.aspx + --> + + + + + + + diff --git a/src/Orchard.Azure/Orchard.Azure.Web/Orchard.Azure.Web.csproj b/src/Orchard.Azure/Orchard.Azure.Web/Orchard.Azure.Web.csproj index cff6ebb0b..aceb7edb8 100644 --- a/src/Orchard.Azure/Orchard.Azure.Web/Orchard.Azure.Web.csproj +++ b/src/Orchard.Azure/Orchard.Azure.Web/Orchard.Azure.Web.csproj @@ -20,7 +20,7 @@ - true + true @@ -91,11 +91,11 @@ False ..\..\..\lib\windowsazure\Microsoft.WindowsAzure.Configuration.dll - + ..\..\..\lib\windowsazure\Microsoft.WindowsAzure.Diagnostics.dll True - + ..\..\..\lib\windowsazure\Microsoft.WindowsAzure.ServiceRuntime.dll False diff --git a/src/Orchard.Core.Tests/Properties/AssemblyInfo.cs b/src/Orchard.Core.Tests/Properties/AssemblyInfo.cs index b36a0684f..eb3081530 100644 --- a/src/Orchard.Core.Tests/Properties/AssemblyInfo.cs +++ b/src/Orchard.Core.Tests/Properties/AssemblyInfo.cs @@ -30,5 +30,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Profile/Properties/AssemblyInfo.cs b/src/Orchard.Profile/Properties/AssemblyInfo.cs index c23f2ddb7..c26e4ba29 100644 --- a/src/Orchard.Profile/Properties/AssemblyInfo.cs +++ b/src/Orchard.Profile/Properties/AssemblyInfo.cs @@ -30,5 +30,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Specs/Autoroute.feature b/src/Orchard.Specs/Autoroute.feature index 605d324ec..35311ab19 100644 --- a/src/Orchard.Specs/Autoroute.feature +++ b/src/Orchard.Specs/Autoroute.feature @@ -19,7 +19,7 @@ Scenario: I can create and publish a new Home Page And I fill in | name | value | | Title.Title | Foo | - | Autoroute.PromoteToHomePage | True | + | AutoroutePart.PromoteToHomePage | True | And I hit "Publish Now" And I go to "/" Then I should see "]*>.*?Foo.*?" diff --git a/src/Orchard.Specs/Autoroute.feature.cs b/src/Orchard.Specs/Autoroute.feature.cs index 9acc565f4..c21be5298 100644 --- a/src/Orchard.Specs/Autoroute.feature.cs +++ b/src/Orchard.Specs/Autoroute.feature.cs @@ -3,7 +3,7 @@ // This code was generated by SpecFlow (http://www.specflow.org/). // SpecFlow Version:1.9.0.77 // SpecFlow Generator Version:1.9.0.0 -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -114,7 +114,7 @@ this.ScenarioSetup(scenarioInfo); "Title.Title", "Foo"}); table2.AddRow(new string[] { - "Autoroute.PromoteToHomePage", + "AutoroutePart.PromoteToHomePage", "True"}); #line 19 testRunner.And("I fill in", ((string)(null)), table2, "And "); diff --git a/src/Orchard.Specs/Blogs.feature b/src/Orchard.Specs/Blogs.feature index c3e87d12f..237384d14 100644 --- a/src/Orchard.Specs/Blogs.feature +++ b/src/Orchard.Specs/Blogs.feature @@ -67,7 +67,7 @@ Scenario: I can create a new blog with multiple blog posts each with the same ti And I fill in | name | value | | Title.Title | My Post | - | Autoroute.CurrentUrl | my-blog/my-post | + | AutoroutePart.CurrentUrl | my-blog/my-post | | Body.Text | Are you still there? | And I hit "Publish Now" And I go to "my-blog/my-post-3" @@ -141,7 +141,7 @@ Scenario: I set my blog to be the content for the home page and the posts for th And I fill in | name | value | | Title.Title | My Blog | - | Autoroute.PromoteToHomePage | true | + | AutoroutePart.PromoteToHomePage | true | And I hit "Save" And I go to "admin/blogs" And I follow "My Blog" @@ -275,20 +275,20 @@ Scenario: I can create browse blog posts on several pages And I should not see "]*>.*?My Post 3.*?" Scenario: I can create a new blog with a percent sign in the title and it gets stripped out of the slug - Given I have installed Orchard - When I go to "admin/blogs/create" - And I fill in - | name | value | - | Title.Title | My Blog | - And I hit "Save" - And I go to "admin/blogs" - And I follow "My Blog" - And I follow "New Post" where class name has "primaryAction" - And I fill in - | name | value | - | Title.Title | My Post with a % Sign | - | Body.Text | Hi there. | - And I hit "Publish Now" - And I go to "my-blog/my-post-with-a-sign" - Then I should see "]*>.*?My Post with a % Sign.*?" - And I should see "Hi there." \ No newline at end of file + Given I have installed Orchard + When I go to "admin/blogs/create" + And I fill in + | name | value | + | Title.Title | My Blog | + And I hit "Save" + And I go to "admin/blogs" + And I follow "My Blog" + And I follow "New Post" where class name has "primaryAction" + And I fill in + | name | value | + | Title.Title | My Post with a % Sign | + | Body.Text | Hi there. | + And I hit "Publish Now" + And I go to "my-blog/my-post-with-a-sign" + Then I should see "]*>.*?My Post with a % Sign.*?" + And I should see "Hi there." \ No newline at end of file diff --git a/src/Orchard.Specs/Blogs.feature.cs b/src/Orchard.Specs/Blogs.feature.cs index f420e7133..74fabba3f 100644 --- a/src/Orchard.Specs/Blogs.feature.cs +++ b/src/Orchard.Specs/Blogs.feature.cs @@ -3,7 +3,7 @@ // This code was generated by SpecFlow (http://www.specflow.org/). // SpecFlow Version:1.9.0.77 // SpecFlow Generator Version:1.9.0.0 -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -234,7 +234,7 @@ this.ScenarioSetup(scenarioInfo); "Title.Title", "My Post"}); table6.AddRow(new string[] { - "Autoroute.CurrentUrl", + "AutoroutePart.CurrentUrl", "my-blog/my-post"}); table6.AddRow(new string[] { "Body.Text", @@ -449,7 +449,7 @@ this.ScenarioSetup(scenarioInfo); "Title.Title", "My Blog"}); table12.AddRow(new string[] { - "Autoroute.PromoteToHomePage", + "AutoroutePart.PromoteToHomePage", "true"}); #line 141 testRunner.And("I fill in", ((string)(null)), table12, "And "); @@ -779,9 +779,9 @@ this.ScenarioSetup(scenarioInfo); #line 277 this.ScenarioSetup(scenarioInfo); #line 278 - testRunner.Given("I have installed Orchard", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); + testRunner.Given("I have installed Orchard", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); #line 279 - testRunner.When("I go to \"admin/blogs/create\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"admin/blogs/create\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table27 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -790,15 +790,15 @@ this.ScenarioSetup(scenarioInfo); "Title.Title", "My Blog"}); #line 280 - testRunner.And("I fill in", ((string)(null)), table27, "And "); + testRunner.And("I fill in", ((string)(null)), table27, "And "); #line 283 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 284 - testRunner.And("I go to \"admin/blogs\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"admin/blogs\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 285 - testRunner.And("I follow \"My Blog\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I follow \"My Blog\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 286 - testRunner.And("I follow \"New Post\" where class name has \"primaryAction\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I follow \"New Post\" where class name has \"primaryAction\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden TechTalk.SpecFlow.Table table28 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -810,15 +810,15 @@ this.ScenarioSetup(scenarioInfo); "Body.Text", "Hi there."}); #line 287 - testRunner.And("I fill in", ((string)(null)), table28, "And "); + testRunner.And("I fill in", ((string)(null)), table28, "And "); #line 291 - testRunner.And("I hit \"Publish Now\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Publish Now\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 292 - testRunner.And("I go to \"my-blog/my-post-with-a-sign\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"my-blog/my-post-with-a-sign\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 293 - testRunner.Then("I should see \"]*>.*?My Post with a % Sign.*?\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"]*>.*?My Post with a % Sign.*?\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 294 - testRunner.And("I should see \"Hi there.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I should see \"Hi there.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden this.ScenarioCleanup(); } diff --git a/src/Orchard.Specs/Boolean.feature b/src/Orchard.Specs/Boolean.feature index 25c5a21e8..c36d964ba 100644 --- a/src/Orchard.Specs/Boolean.feature +++ b/src/Orchard.Specs/Boolean.feature @@ -1,13 +1,13 @@ Feature: Boolean Field In order to add boolean content to my types - As an administrator + As an administrator I want to create, edit and publish boolean fields Scenario: Creating and using Boolean fields - - # Creating an Event content type + + # Creating an Event content type Given I have installed Orchard - And I have installed "Orchard.Fields" + And I have installed "Orchard.Fields" When I go to "Admin/ContentTypes" Then I should see "]*>.*?Create new type" When I go to "Admin/ContentTypes/Create" @@ -18,65 +18,65 @@ Scenario: Creating and using Boolean fields And I hit "Create" And I go to "Admin/ContentTypes/" Then I should see "Event" - - # Adding a Boolean field - When I go to "Admin/ContentTypes/Edit/Event" - And I follow "Add Field" - And I fill in + + # Adding a Boolean field + When I go to "Admin/ContentTypes/Edit/Event" + And I follow "Add Field" + And I fill in | name | value | | DisplayName | Active | | Name | Active | | FieldTypeName | BooleanField | - And I hit "Save" - And I am redirected - Then I should see "The \"Active\" field has been added." + And I hit "Save" + And I am redirected + Then I should see "The \"Active\" field has been added." - # Creating an Event content item - When I go to "Admin/Contents/Create/Event" - Then I should see "Active" - When I fill in - | name | value | - | Event.Active.Value | true | - And I hit "Save" - And I am redirected - Then I should see "Your Event has been created." - When I go to "Admin/Contents/List" - Then I should see "Active:" - And I should see "Yes" + # Creating an Event content item + When I go to "Admin/Contents/Create/Event" + Then I should see "Active" + When I fill in + | name | value | + | Event.Active.Value | true | + And I hit "Save" + And I am redirected + Then I should see "Your Event has been created." + When I go to "Admin/Contents/List" + Then I should see "Active:" + And I should see "Yes" - # The hint should be displayed - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].BooleanFieldSettings.Hint | Check if the event is active | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "Check if the event is active" - - # The default value should be selected - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].BooleanFieldSettings.DefaultValue | True | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "checked=\"checked\"" + # The hint should be displayed + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].BooleanFieldSettings.Hint | Check if the event is active | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "Check if the event is active" + + # The default value should be selected + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].BooleanFieldSettings.DefaultValue | True | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "checked=\"checked\"" - # The value should be required - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].BooleanFieldSettings.Optional | false | - And I fill in - | name | value | - | Fields[0].BooleanFieldSettings.NotSetLabel | May be | - And I fill in - | name | value | - | Fields[0].BooleanFieldSettings.SelectionMode | Radiobutton | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - And I fill in - | name | value | - | Event.Active.Value | | - And I hit "Save" - Then I should see "The field Active is mandatory." \ No newline at end of file + # The value should be required + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].BooleanFieldSettings.Optional | false | + And I fill in + | name | value | + | Fields[0].BooleanFieldSettings.NotSetLabel | May be | + And I fill in + | name | value | + | Fields[0].BooleanFieldSettings.SelectionMode | Radiobutton | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + And I fill in + | name | value | + | Event.Active.Value | | + And I hit "Save" + Then I should see "The field Active is mandatory." \ No newline at end of file diff --git a/src/Orchard.Specs/Boolean.feature.cs b/src/Orchard.Specs/Boolean.feature.cs index 6d95a877a..f074e5cb2 100644 --- a/src/Orchard.Specs/Boolean.feature.cs +++ b/src/Orchard.Specs/Boolean.feature.cs @@ -3,7 +3,7 @@ // This code was generated by SpecFlow (http://www.specflow.org/). // SpecFlow Version:1.9.0.77 // SpecFlow Generator Version:1.9.0.0 -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -32,8 +32,8 @@ namespace Orchard.Specs public virtual void FeatureSetup() { testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner(); - TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Boolean Field", " In order to add boolean content to my types\r\nAs an administrator\r\n I want to c" + - "reate, edit and publish boolean fields", ProgrammingLanguage.CSharp, ((string[])(null))); + TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Boolean Field", " In order to add boolean content to my types\r\n As an administrator\r\n I want to" + + " create, edit and publish boolean fields", ProgrammingLanguage.CSharp, ((string[])(null))); testRunner.OnFeatureStart(featureInfo); } @@ -75,7 +75,7 @@ this.ScenarioSetup(scenarioInfo); #line 9 testRunner.Given("I have installed Orchard", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); #line 10 - testRunner.And("I have installed \"Orchard.Fields\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I have installed \"Orchard.Fields\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 11 testRunner.When("I go to \"Admin/ContentTypes\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 12 @@ -101,9 +101,9 @@ this.ScenarioSetup(scenarioInfo); #line 20 testRunner.Then("I should see \"Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 23 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 24 - testRunner.And("I follow \"Add Field\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I follow \"Add Field\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden TechTalk.SpecFlow.Table table2 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -118,17 +118,17 @@ this.ScenarioSetup(scenarioInfo); "FieldTypeName", "BooleanField"}); #line 25 - testRunner.And("I fill in", ((string)(null)), table2, "And "); + testRunner.And("I fill in", ((string)(null)), table2, "And "); #line 30 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 31 - testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 32 - testRunner.Then("I should see \"The \\\"Active\\\" field has been added.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"The \\\"Active\\\" field has been added.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 35 - testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 36 - testRunner.Then("I should see \"Active\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Active\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden TechTalk.SpecFlow.Table table3 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -137,21 +137,21 @@ this.ScenarioSetup(scenarioInfo); "Event.Active.Value", "true"}); #line 37 - testRunner.When("I fill in", ((string)(null)), table3, "When "); + testRunner.When("I fill in", ((string)(null)), table3, "When "); #line 40 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 41 - testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 42 - testRunner.Then("I should see \"Your Event has been created.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Your Event has been created.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 43 - testRunner.When("I go to \"Admin/Contents/List\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/Contents/List\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 44 - testRunner.Then("I should see \"Active:\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Active:\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 45 - testRunner.And("I should see \"Yes\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I should see \"Yes\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 48 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table4 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -160,15 +160,15 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].BooleanFieldSettings.Hint", "Check if the event is active"}); #line 49 - testRunner.And("I fill in", ((string)(null)), table4, "And "); + testRunner.And("I fill in", ((string)(null)), table4, "And "); #line 52 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 53 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 54 - testRunner.Then("I should see \"Check if the event is active\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Check if the event is active\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 57 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table5 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -177,15 +177,15 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].BooleanFieldSettings.DefaultValue", "True"}); #line 58 - testRunner.And("I fill in", ((string)(null)), table5, "And "); + testRunner.And("I fill in", ((string)(null)), table5, "And "); #line 61 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 62 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 63 - testRunner.Then("I should see \"checked=\\\"checked\\\"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"checked=\\\"checked\\\"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 66 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table6 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -194,7 +194,7 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].BooleanFieldSettings.Optional", "false"}); #line 67 - testRunner.And("I fill in", ((string)(null)), table6, "And "); + testRunner.And("I fill in", ((string)(null)), table6, "And "); #line hidden TechTalk.SpecFlow.Table table7 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -203,7 +203,7 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].BooleanFieldSettings.NotSetLabel", "May be"}); #line 70 - testRunner.And("I fill in", ((string)(null)), table7, "And "); + testRunner.And("I fill in", ((string)(null)), table7, "And "); #line hidden TechTalk.SpecFlow.Table table8 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -212,11 +212,11 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].BooleanFieldSettings.SelectionMode", "Radiobutton"}); #line 73 - testRunner.And("I fill in", ((string)(null)), table8, "And "); + testRunner.And("I fill in", ((string)(null)), table8, "And "); #line 76 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 77 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden TechTalk.SpecFlow.Table table9 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -225,11 +225,11 @@ this.ScenarioSetup(scenarioInfo); "Event.Active.Value", ""}); #line 78 - testRunner.And("I fill in", ((string)(null)), table9, "And "); + testRunner.And("I fill in", ((string)(null)), table9, "And "); #line 81 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 82 - testRunner.Then("I should see \"The field Active is mandatory.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"The field Active is mandatory.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden this.ScenarioCleanup(); } diff --git a/src/Orchard.Specs/Comments.feature b/src/Orchard.Specs/Comments.feature index 22ca0eb1b..16072c89f 100644 --- a/src/Orchard.Specs/Comments.feature +++ b/src/Orchard.Specs/Comments.feature @@ -39,12 +39,12 @@ Scenario: HTML markup in any given comment is encoded And I hit "Submit Comment" And I am redirected # because the ToUrlString extension method breaks in this specific (test) environment, the returnUrl is broken... - And I go to "my-blog/my-post" + And I go to "my-blog/my-post" # And I go to "my-blog/my-post" Then I should see "This is<br id="bad-anon-br" />a <a href" And I should not see "
" - # Moderated comments are not displayed + # Moderated comments are not displayed When I go to "users/account/logon" And I fill in | name | value | @@ -52,15 +52,15 @@ Scenario: HTML markup in any given comment is encoded | password | 6655321 | And I hit "Sign In" And I am redirected - And I go to "admin/settings/comments" - And I fill in + And I go to "admin/settings/comments" + And I fill in | name | value | | CommentSettings.ModerateComments | true | - And I hit "Save" - And I am redirected - Then I should see "Settings updated" - When I go to "users/account/logoff" - And I go to "my-blog/my-post" + And I hit "Save" + And I am redirected + Then I should see "Settings updated" + When I go to "users/account/logoff" + And I go to "my-blog/my-post" And I fill in | name | value | | Comments.Author | Bill | diff --git a/src/Orchard.Specs/Comments.feature.cs b/src/Orchard.Specs/Comments.feature.cs index 4c48a16bb..d7c9de2d7 100644 --- a/src/Orchard.Specs/Comments.feature.cs +++ b/src/Orchard.Specs/Comments.feature.cs @@ -3,7 +3,7 @@ // This code was generated by SpecFlow (http://www.specflow.org/). // SpecFlow Version:1.9.0.77 // SpecFlow Generator Version:1.9.0.0 -// Runtime Version:4.0.30319.0 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -151,7 +151,7 @@ this.ScenarioSetup(scenarioInfo); #line 40 testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 42 - testRunner.And("I go to \"my-blog/my-post\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"my-blog/my-post\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 44 testRunner.Then("I should see \"This is<br id="bad-anon-br" />a <a href\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 45 @@ -175,7 +175,7 @@ this.ScenarioSetup(scenarioInfo); #line 54 testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 55 - testRunner.And("I go to \"admin/settings/comments\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"admin/settings/comments\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden TechTalk.SpecFlow.Table table6 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -184,17 +184,17 @@ this.ScenarioSetup(scenarioInfo); "CommentSettings.ModerateComments", "true"}); #line 56 - testRunner.And("I fill in", ((string)(null)), table6, "And "); + testRunner.And("I fill in", ((string)(null)), table6, "And "); #line 59 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 60 - testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 61 - testRunner.Then("I should see \"Settings updated\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Settings updated\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 62 - testRunner.When("I go to \"users/account/logoff\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"users/account/logoff\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 63 - testRunner.And("I go to \"my-blog/my-post\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"my-blog/my-post\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden TechTalk.SpecFlow.Table table7 = new TechTalk.SpecFlow.Table(new string[] { "name", diff --git a/src/Orchard.Specs/DateTime.feature b/src/Orchard.Specs/DateTime.feature index de1f61881..ac4c8d2d8 100644 --- a/src/Orchard.Specs/DateTime.feature +++ b/src/Orchard.Specs/DateTime.feature @@ -1,13 +1,13 @@ Feature: DateTime Field In order to add Date content to my types - As an administrator + As an administrator I want to create, edit and publish DateTime fields Scenario: Creating and using Date fields - - # Creating an Event content type + + # Creating an Event content type Given I have installed Orchard - And I have installed "Orchard.Fields" + And I have installed "Orchard.Fields" When I go to "Admin/ContentTypes" Then I should see "]*>.*?Create new type" When I go to "Admin/ContentTypes/Create" @@ -18,133 +18,133 @@ Scenario: Creating and using Date fields And I hit "Create" And I go to "Admin/ContentTypes/" Then I should see "Event" - - # Adding a Date field - When I go to "Admin/ContentTypes/Edit/Event" - And I follow "Add Field" - And I fill in + + # Adding a Date field + When I go to "Admin/ContentTypes/Edit/Event" + And I follow "Add Field" + And I fill in | name | value | | DisplayName | Date of the event | | Name | EventDate | | FieldTypeName | DateTimeField | - And I hit "Save" - And I am redirected - Then I should see "The \"Date of the event\" field has been added." + And I hit "Save" + And I am redirected + Then I should see "The \"Date of the event\" field has been added." - # Invalid Date - When I go to "Admin/Contents/Create/Event" - Then I should see "Date of the event" - When I fill in - | name | value | - | Event.EventDate.Editor.Date | 31/01/2012 | - | Event.EventDate.Editor.Time | 12:00 AM | - And I hit "Save" - Then I should see "Date of the event could not be parsed as a valid date and time" + # Invalid Date + When I go to "Admin/Contents/Create/Event" + Then I should see "Date of the event" + When I fill in + | name | value | + | Event.EventDate.Editor.Date | 31/01/2012 | + | Event.EventDate.Editor.Time | 12:00 AM | + And I hit "Save" + Then I should see "Date of the event could not be parsed as a valid date and time" - # Creating an Event content item - When I go to "Admin/Contents/Create/Event" - Then I should see "Date of the event" - When I fill in - | name | value | - | Event.EventDate.Editor.Date | 01/31/2012 | - And I fill in - | name | value | - | Event.EventDate.Editor.Time | 12:00 AM | - And I hit "Save" - And I am redirected - Then I should see "Your Event has been created." - When I go to "Admin/Contents/List" - Then I should see "Date of the event" - And I should see "1/31/2012 12:00" + # Creating an Event content item + When I go to "Admin/Contents/Create/Event" + Then I should see "Date of the event" + When I fill in + | name | value | + | Event.EventDate.Editor.Date | 01/31/2012 | + And I fill in + | name | value | + | Event.EventDate.Editor.Time | 12:00 AM | + And I hit "Save" + And I am redirected + Then I should see "Your Event has been created." + When I go to "Admin/Contents/List" + Then I should see "Date of the event" + And I should see "1/31/2012 12:00" - # The hint should be displayed - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].DateTimeFieldSettings.Hint | Enter the date of the event | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "Enter the date of the event" - - # Display = DateOnly - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].DateTimeFieldSettings.Display | DateOnly | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "Event.EventDate.Editor.Date" - And I should not see "Event.EventDate.Editor.Time" - - # Display = TimeOnly - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].DateTimeFieldSettings.Display | TimeOnly | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "Event.EventDate.Editor.Time" - And I should not see "Event.EventDate.Editor.Date" + # The hint should be displayed + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].DateTimeFieldSettings.Hint | Enter the date of the event | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "Enter the date of the event" + + # Display = DateOnly + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].DateTimeFieldSettings.Display | DateOnly | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "Event.EventDate.Editor.Date" + And I should not see "Event.EventDate.Editor.Time" + + # Display = TimeOnly + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].DateTimeFieldSettings.Display | TimeOnly | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "Event.EventDate.Editor.Time" + And I should not see "Event.EventDate.Editor.Date" - # Required & Date and Time - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].DateTimeFieldSettings.Display | DateAndTime | - | Fields[0].DateTimeFieldSettings.Required | true | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "Event.EventDate.Editor.Date" - When I fill in - | name | value | - | Event.EventDate.Editor.Date | 01/31/2012 | - | Event.EventDate.Editor.Time | 12:00 AM | - And I hit "Save" - And I am redirected - Then I should see "Your Event has been created." - When I go to "Admin/Contents/Create/Event" - And I fill in - | name | value | - | Event.EventDate.Editor.Date | 01/31/2012 | - And I hit "Save" - Then I should see "Date of the event is required." - When I go to "Admin/Contents/Create/Event" - And I fill in - | name | value | - | Event.EventDate.Editor.Time | 12:00 AM | - And I hit "Save" - Then I should see "Date of the event is required." + # Required & Date and Time + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].DateTimeFieldSettings.Display | DateAndTime | + | Fields[0].DateTimeFieldSettings.Required | true | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "Event.EventDate.Editor.Date" + When I fill in + | name | value | + | Event.EventDate.Editor.Date | 01/31/2012 | + | Event.EventDate.Editor.Time | 12:00 AM | + And I hit "Save" + And I am redirected + Then I should see "Your Event has been created." + When I go to "Admin/Contents/Create/Event" + And I fill in + | name | value | + | Event.EventDate.Editor.Date | 01/31/2012 | + And I hit "Save" + Then I should see "Date of the event is required." + When I go to "Admin/Contents/Create/Event" + And I fill in + | name | value | + | Event.EventDate.Editor.Time | 12:00 AM | + And I hit "Save" + Then I should see "Date of the event is required." - # Required & Date only - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].DateTimeFieldSettings.Display | DateOnly | - | Fields[0].DateTimeFieldSettings.Required | true | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "Event.EventDate.Editor.Date" - When I hit "Save" - Then I should see "Date of the event is required." + # Required & Date only + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].DateTimeFieldSettings.Display | DateOnly | + | Fields[0].DateTimeFieldSettings.Required | true | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "Event.EventDate.Editor.Date" + When I hit "Save" + Then I should see "Date of the event is required." - # Required & Time only - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].DateTimeFieldSettings.Display | TimeOnly | - | Fields[0].DateTimeFieldSettings.Required | true | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "Event.EventDate.Editor.Date" - When I hit "Save" - Then I should see "Date of the event is required." + # Required & Time only + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].DateTimeFieldSettings.Display | TimeOnly | + | Fields[0].DateTimeFieldSettings.Required | true | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "Event.EventDate.Editor.Date" + When I hit "Save" + Then I should see "Date of the event is required." Scenario: Creating and using date time fields in another culture - # Creating an Event content type + # Creating an Event content type Given I have installed Orchard - And I have installed "Orchard.Fields" - And I have the file "Content\orchard.core.po" in "Core\App_Data\Localization\fr-FR\orchard.core.po" + And I have installed "Orchard.Fields" + And I have the file "Content\orchard.core.po" in "Core\App_Data\Localization\fr-FR\orchard.core.po" When I go to "Admin/ContentTypes" Then I should see "]*>.*?Create new type" When I go to "Admin/ContentTypes/Create" @@ -155,39 +155,39 @@ Scenario: Creating and using date time fields in another culture And I hit "Create" And I go to "Admin/ContentTypes/" Then I should see "Event" - - # Adding a Date field - When I go to "Admin/ContentTypes/Edit/Event" - And I follow "Add Field" - And I fill in + + # Adding a Date field + When I go to "Admin/ContentTypes/Edit/Event" + And I follow "Add Field" + And I fill in | name | value | | DisplayName | Date of the event | | Name | EventDate | | FieldTypeName | DateTimeField | - And I hit "Save" - And I am redirected - Then I should see "The \"Date of the event\" field has been added." + And I hit "Save" + And I am redirected + Then I should see "The \"Date of the event\" field has been added." - # Date & Time are inputted based on current culture - When I have "fr-FR" as the default culture - And I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].DateTimeFieldSettings.Display | DateAndTime | - | Fields[0].DateTimeFieldSettings.Required | true | - And I hit "Save" - When I go to "Admin/Contents/Create/Event" - And I fill in - | name | value | - | Event.EventDate.Editor.Date | 01/31/2012 | - | Event.EventDate.Editor.Time | 12:00 AM | - And I hit "Save" - Then I should see "Date of the event could not be parsed as a valid date and time" - When I go to "Admin/Contents/Create/Event" - And I fill in - | name | value | - | Event.EventDate.Editor.Date | 31/01/2012 | - | Event.EventDate.Editor.Time | 18:00 | - And I hit "Save" - And I am redirected - Then I should see "Your Event has been created." + # Date & Time are inputted based on current culture + When I have "fr-FR" as the default culture + And I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].DateTimeFieldSettings.Display | DateAndTime | + | Fields[0].DateTimeFieldSettings.Required | true | + And I hit "Save" + When I go to "Admin/Contents/Create/Event" + And I fill in + | name | value | + | Event.EventDate.Editor.Date | 01/31/2012 | + | Event.EventDate.Editor.Time | 12:00 AM | + And I hit "Save" + Then I should see "Date of the event could not be parsed as a valid date and time" + When I go to "Admin/Contents/Create/Event" + And I fill in + | name | value | + | Event.EventDate.Editor.Date | 31/01/2012 | + | Event.EventDate.Editor.Time | 18:00 | + And I hit "Save" + And I am redirected + Then I should see "Your Event has been created." diff --git a/src/Orchard.Specs/DateTime.feature.cs b/src/Orchard.Specs/DateTime.feature.cs index 635470931..8439bf756 100644 --- a/src/Orchard.Specs/DateTime.feature.cs +++ b/src/Orchard.Specs/DateTime.feature.cs @@ -3,7 +3,7 @@ // This code was generated by SpecFlow (http://www.specflow.org/). // SpecFlow Version:1.9.0.77 // SpecFlow Generator Version:1.9.0.0 -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -32,8 +32,8 @@ namespace Orchard.Specs public virtual void FeatureSetup() { testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner(); - TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "DateTime Field", " In order to add Date content to my types\r\nAs an administrator\r\n I want to crea" + - "te, edit and publish DateTime fields", ProgrammingLanguage.CSharp, ((string[])(null))); + TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "DateTime Field", " In order to add Date content to my types\r\n As an administrator\r\n I want to cr" + + "eate, edit and publish DateTime fields", ProgrammingLanguage.CSharp, ((string[])(null))); testRunner.OnFeatureStart(featureInfo); } @@ -75,7 +75,7 @@ this.ScenarioSetup(scenarioInfo); #line 9 testRunner.Given("I have installed Orchard", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); #line 10 - testRunner.And("I have installed \"Orchard.Fields\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I have installed \"Orchard.Fields\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 11 testRunner.When("I go to \"Admin/ContentTypes\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 12 @@ -101,9 +101,9 @@ this.ScenarioSetup(scenarioInfo); #line 20 testRunner.Then("I should see \"Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 23 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 24 - testRunner.And("I follow \"Add Field\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I follow \"Add Field\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden TechTalk.SpecFlow.Table table2 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -118,17 +118,17 @@ this.ScenarioSetup(scenarioInfo); "FieldTypeName", "DateTimeField"}); #line 25 - testRunner.And("I fill in", ((string)(null)), table2, "And "); + testRunner.And("I fill in", ((string)(null)), table2, "And "); #line 30 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 31 - testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 32 - testRunner.Then("I should see \"The \\\"Date of the event\\\" field has been added.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"The \\\"Date of the event\\\" field has been added.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 35 - testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 36 - testRunner.Then("I should see \"Date of the event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Date of the event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden TechTalk.SpecFlow.Table table3 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -140,15 +140,15 @@ this.ScenarioSetup(scenarioInfo); "Event.EventDate.Editor.Time", "12:00 AM"}); #line 37 - testRunner.When("I fill in", ((string)(null)), table3, "When "); + testRunner.When("I fill in", ((string)(null)), table3, "When "); #line 41 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 42 - testRunner.Then("I should see \"Date of the event could not be parsed as a valid date and time\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Date of the event could not be parsed as a valid date and time\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 45 - testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 46 - testRunner.Then("I should see \"Date of the event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Date of the event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden TechTalk.SpecFlow.Table table4 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -157,7 +157,7 @@ this.ScenarioSetup(scenarioInfo); "Event.EventDate.Editor.Date", "01/31/2012"}); #line 47 - testRunner.When("I fill in", ((string)(null)), table4, "When "); + testRunner.When("I fill in", ((string)(null)), table4, "When "); #line hidden TechTalk.SpecFlow.Table table5 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -166,21 +166,21 @@ this.ScenarioSetup(scenarioInfo); "Event.EventDate.Editor.Time", "12:00 AM"}); #line 50 - testRunner.And("I fill in", ((string)(null)), table5, "And "); + testRunner.And("I fill in", ((string)(null)), table5, "And "); #line 53 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 54 - testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 55 - testRunner.Then("I should see \"Your Event has been created.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Your Event has been created.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 56 - testRunner.When("I go to \"Admin/Contents/List\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/Contents/List\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 57 - testRunner.Then("I should see \"Date of the event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Date of the event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 58 - testRunner.And("I should see \"1/31/2012 12:00\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I should see \"1/31/2012 12:00\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 61 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table6 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -189,15 +189,15 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].DateTimeFieldSettings.Hint", "Enter the date of the event"}); #line 62 - testRunner.And("I fill in", ((string)(null)), table6, "And "); + testRunner.And("I fill in", ((string)(null)), table6, "And "); #line 65 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 66 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 67 - testRunner.Then("I should see \"Enter the date of the event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Enter the date of the event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 70 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table7 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -206,17 +206,17 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].DateTimeFieldSettings.Display", "DateOnly"}); #line 71 - testRunner.And("I fill in", ((string)(null)), table7, "And "); + testRunner.And("I fill in", ((string)(null)), table7, "And "); #line 74 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 75 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 76 - testRunner.Then("I should see \"Event.EventDate.Editor.Date\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Event.EventDate.Editor.Date\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 77 - testRunner.And("I should not see \"Event.EventDate.Editor.Time\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I should not see \"Event.EventDate.Editor.Time\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 80 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table8 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -225,17 +225,17 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].DateTimeFieldSettings.Display", "TimeOnly"}); #line 81 - testRunner.And("I fill in", ((string)(null)), table8, "And "); + testRunner.And("I fill in", ((string)(null)), table8, "And "); #line 84 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 85 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 86 - testRunner.Then("I should see \"Event.EventDate.Editor.Time\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Event.EventDate.Editor.Time\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 87 - testRunner.And("I should not see \"Event.EventDate.Editor.Date\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I should not see \"Event.EventDate.Editor.Date\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 90 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table9 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -247,13 +247,13 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].DateTimeFieldSettings.Required", "true"}); #line 91 - testRunner.And("I fill in", ((string)(null)), table9, "And "); + testRunner.And("I fill in", ((string)(null)), table9, "And "); #line 95 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 96 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 97 - testRunner.Then("I should see \"Event.EventDate.Editor.Date\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Event.EventDate.Editor.Date\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden TechTalk.SpecFlow.Table table10 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -265,15 +265,15 @@ this.ScenarioSetup(scenarioInfo); "Event.EventDate.Editor.Time", "12:00 AM"}); #line 98 - testRunner.When("I fill in", ((string)(null)), table10, "When "); + testRunner.When("I fill in", ((string)(null)), table10, "When "); #line 102 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 103 - testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 104 - testRunner.Then("I should see \"Your Event has been created.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Your Event has been created.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 105 - testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table11 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -282,13 +282,13 @@ this.ScenarioSetup(scenarioInfo); "Event.EventDate.Editor.Date", "01/31/2012"}); #line 106 - testRunner.And("I fill in", ((string)(null)), table11, "And "); + testRunner.And("I fill in", ((string)(null)), table11, "And "); #line 109 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 110 - testRunner.Then("I should see \"Date of the event is required.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Date of the event is required.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 111 - testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table12 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -297,13 +297,13 @@ this.ScenarioSetup(scenarioInfo); "Event.EventDate.Editor.Time", "12:00 AM"}); #line 112 - testRunner.And("I fill in", ((string)(null)), table12, "And "); + testRunner.And("I fill in", ((string)(null)), table12, "And "); #line 115 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 116 - testRunner.Then("I should see \"Date of the event is required.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Date of the event is required.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 119 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table13 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -315,19 +315,19 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].DateTimeFieldSettings.Required", "true"}); #line 120 - testRunner.And("I fill in", ((string)(null)), table13, "And "); + testRunner.And("I fill in", ((string)(null)), table13, "And "); #line 124 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 125 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 126 - testRunner.Then("I should see \"Event.EventDate.Editor.Date\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Event.EventDate.Editor.Date\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 127 - testRunner.When("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 128 - testRunner.Then("I should see \"Date of the event is required.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Date of the event is required.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 131 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table14 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -339,17 +339,17 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].DateTimeFieldSettings.Required", "true"}); #line 132 - testRunner.And("I fill in", ((string)(null)), table14, "And "); + testRunner.And("I fill in", ((string)(null)), table14, "And "); #line 136 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 137 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 138 - testRunner.Then("I should see \"Event.EventDate.Editor.Date\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Event.EventDate.Editor.Date\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 139 - testRunner.When("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 140 - testRunner.Then("I should see \"Date of the event is required.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Date of the event is required.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden this.ScenarioCleanup(); } @@ -364,9 +364,9 @@ this.ScenarioSetup(scenarioInfo); #line 145 testRunner.Given("I have installed Orchard", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); #line 146 - testRunner.And("I have installed \"Orchard.Fields\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I have installed \"Orchard.Fields\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 147 - testRunner.And("I have the file \"Content\\orchard.core.po\" in \"Core\\App_Data\\Localization\\fr-FR\\or" + + testRunner.And("I have the file \"Content\\orchard.core.po\" in \"Core\\App_Data\\Localization\\fr-FR\\or" + "chard.core.po\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 148 testRunner.When("I go to \"Admin/ContentTypes\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); @@ -393,9 +393,9 @@ this.ScenarioSetup(scenarioInfo); #line 157 testRunner.Then("I should see \"Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 160 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 161 - testRunner.And("I follow \"Add Field\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I follow \"Add Field\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden TechTalk.SpecFlow.Table table16 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -410,17 +410,17 @@ this.ScenarioSetup(scenarioInfo); "FieldTypeName", "DateTimeField"}); #line 162 - testRunner.And("I fill in", ((string)(null)), table16, "And "); + testRunner.And("I fill in", ((string)(null)), table16, "And "); #line 167 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 168 - testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 169 - testRunner.Then("I should see \"The \\\"Date of the event\\\" field has been added.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"The \\\"Date of the event\\\" field has been added.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 172 - testRunner.When("I have \"fr-FR\" as the default culture", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I have \"fr-FR\" as the default culture", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 173 - testRunner.And("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden TechTalk.SpecFlow.Table table17 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -432,11 +432,11 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].DateTimeFieldSettings.Required", "true"}); #line 174 - testRunner.And("I fill in", ((string)(null)), table17, "And "); + testRunner.And("I fill in", ((string)(null)), table17, "And "); #line 178 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 179 - testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table18 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -448,13 +448,13 @@ this.ScenarioSetup(scenarioInfo); "Event.EventDate.Editor.Time", "12:00 AM"}); #line 180 - testRunner.And("I fill in", ((string)(null)), table18, "And "); + testRunner.And("I fill in", ((string)(null)), table18, "And "); #line 184 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 185 - testRunner.Then("I should see \"Date of the event could not be parsed as a valid date and time\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Date of the event could not be parsed as a valid date and time\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 186 - testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table19 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -466,13 +466,13 @@ this.ScenarioSetup(scenarioInfo); "Event.EventDate.Editor.Time", "18:00"}); #line 187 - testRunner.And("I fill in", ((string)(null)), table19, "And "); + testRunner.And("I fill in", ((string)(null)), table19, "And "); #line 191 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 192 - testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 193 - testRunner.Then("I should see \"Your Event has been created.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Your Event has been created.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden this.ScenarioCleanup(); } diff --git a/src/Orchard.Specs/Enumeration.feature b/src/Orchard.Specs/Enumeration.feature index 9201b36c4..6864b9a83 100644 --- a/src/Orchard.Specs/Enumeration.feature +++ b/src/Orchard.Specs/Enumeration.feature @@ -1,13 +1,13 @@ Feature: Enumeration Field In order to add a list of elements to my types - As an administrator + As an administrator I want to create, edit and publish Enumeration fields Scenario: Creating and using Enumeration fields - - # Creating an Event content type + + # Creating an Event content type Given I have installed Orchard - And I have installed "Orchard.Fields" + And I have installed "Orchard.Fields" When I go to "Admin/ContentTypes" Then I should see "]*>.*?Create new type" When I go to "Admin/ContentTypes/Create" @@ -18,92 +18,92 @@ Scenario: Creating and using Enumeration fields And I hit "Create" And I go to "Admin/ContentTypes/" Then I should see "Event" - - # Adding a Enumeration field - When I go to "Admin/ContentTypes/Edit/Event" - And I follow "Add Field" - And I fill in + + # Adding a Enumeration field + When I go to "Admin/ContentTypes/Edit/Event" + And I follow "Add Field" + And I fill in | name | value | | DisplayName | Location | | Name | Location | | FieldTypeName | EnumerationField | - And I hit "Save" - And I am redirected - Then I should see "The \"Location\" field has been added." + And I hit "Save" + And I am redirected + Then I should see "The \"Location\" field has been added." - # Specifying Options - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].EnumerationFieldSettings.Options | Seattle | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "" + # Specifying Options + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].EnumerationFieldSettings.Options | Seattle | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "" - # Creating an Event content item - When I go to "Admin/Contents/Create/Event" - Then I should see "Location" - When I fill in - | name | value | - | Event.Location.Value | Seattle | - And I hit "Save" - And I am redirected - Then I should see "Your Event has been created." - When I go to "Admin/Contents/List" - Then I should see "Location:" - And I should see "Seattle" + # Creating an Event content item + When I go to "Admin/Contents/Create/Event" + Then I should see "Location" + When I fill in + | name | value | + | Event.Location.Value | Seattle | + And I hit "Save" + And I am redirected + Then I should see "Your Event has been created." + When I go to "Admin/Contents/List" + Then I should see "Location:" + And I should see "Seattle" - # The hint should be displayed - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].EnumerationFieldSettings.Hint | Please select a location | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "Please select a location" + # The hint should be displayed + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].EnumerationFieldSettings.Hint | Please select a location | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "Please select a location" - # The List Mode Dropdown - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].EnumerationFieldSettings.ListMode | Dropdown | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "select id=\"Event_Location_Value\" name=\"Event.Location.Value\"" - - # The List Mode Radiobutton - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].EnumerationFieldSettings.ListMode | Radiobutton | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "input id=\"Event_Location_Value\" name=\"Event.Location.Value\" type=\"radio\"" - - # The List Mode Listbox - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].EnumerationFieldSettings.ListMode | Listbox | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "select id=\"Event_Location_SelectedValues\" multiple=\"multiple\" name=\"Event.Location.SelectedValues\"" - - # The List Mode Checkbox - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].EnumerationFieldSettings.ListMode | Checkbox | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "input type=\"checkbox\" name=\"Event.Location.SelectedValues\"" - - # The value should be required - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].EnumerationFieldSettings.Required | true | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - And I hit "Save" - Then I should see "The field Location is mandatory." + # The List Mode Dropdown + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].EnumerationFieldSettings.ListMode | Dropdown | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "select id=\"Event_Location_Value\" name=\"Event.Location.Value\"" + + # The List Mode Radiobutton + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].EnumerationFieldSettings.ListMode | Radiobutton | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "input id=\"Event_Location_Value\" name=\"Event.Location.Value\" type=\"radio\"" + + # The List Mode Listbox + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].EnumerationFieldSettings.ListMode | Listbox | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "select id=\"Event_Location_SelectedValues\" multiple=\"multiple\" name=\"Event.Location.SelectedValues\"" + + # The List Mode Checkbox + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].EnumerationFieldSettings.ListMode | Checkbox | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "input type=\"checkbox\" name=\"Event.Location.SelectedValues\"" + + # The value should be required + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].EnumerationFieldSettings.Required | true | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + And I hit "Save" + Then I should see "The field Location is mandatory." diff --git a/src/Orchard.Specs/Enumeration.feature.cs b/src/Orchard.Specs/Enumeration.feature.cs index 2241d667c..88a011d4f 100644 --- a/src/Orchard.Specs/Enumeration.feature.cs +++ b/src/Orchard.Specs/Enumeration.feature.cs @@ -3,7 +3,7 @@ // This code was generated by SpecFlow (http://www.specflow.org/). // SpecFlow Version:1.9.0.77 // SpecFlow Generator Version:1.9.0.0 -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -32,8 +32,8 @@ namespace Orchard.Specs public virtual void FeatureSetup() { testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner(); - TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Enumeration Field", " In order to add a list of elements to my types\r\nAs an administrator\r\n I want t" + - "o create, edit and publish Enumeration fields", ProgrammingLanguage.CSharp, ((string[])(null))); + TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Enumeration Field", " In order to add a list of elements to my types\r\n As an administrator\r\n I want" + + " to create, edit and publish Enumeration fields", ProgrammingLanguage.CSharp, ((string[])(null))); testRunner.OnFeatureStart(featureInfo); } @@ -75,7 +75,7 @@ this.ScenarioSetup(scenarioInfo); #line 9 testRunner.Given("I have installed Orchard", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); #line 10 - testRunner.And("I have installed \"Orchard.Fields\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I have installed \"Orchard.Fields\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 11 testRunner.When("I go to \"Admin/ContentTypes\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 12 @@ -101,9 +101,9 @@ this.ScenarioSetup(scenarioInfo); #line 20 testRunner.Then("I should see \"Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 23 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 24 - testRunner.And("I follow \"Add Field\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I follow \"Add Field\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden TechTalk.SpecFlow.Table table2 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -118,15 +118,15 @@ this.ScenarioSetup(scenarioInfo); "FieldTypeName", "EnumerationField"}); #line 25 - testRunner.And("I fill in", ((string)(null)), table2, "And "); + testRunner.And("I fill in", ((string)(null)), table2, "And "); #line 30 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 31 - testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 32 - testRunner.Then("I should see \"The \\\"Location\\\" field has been added.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"The \\\"Location\\\" field has been added.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 35 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table3 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -135,17 +135,17 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].EnumerationFieldSettings.Options", "Seattle"}); #line 36 - testRunner.And("I fill in", ((string)(null)), table3, "And "); + testRunner.And("I fill in", ((string)(null)), table3, "And "); #line 39 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 40 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 41 - testRunner.Then("I should see \"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 44 - testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 45 - testRunner.Then("I should see \"Location\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Location\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden TechTalk.SpecFlow.Table table4 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -154,21 +154,21 @@ this.ScenarioSetup(scenarioInfo); "Event.Location.Value", "Seattle"}); #line 46 - testRunner.When("I fill in", ((string)(null)), table4, "When "); + testRunner.When("I fill in", ((string)(null)), table4, "When "); #line 49 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 50 - testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 51 - testRunner.Then("I should see \"Your Event has been created.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Your Event has been created.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 52 - testRunner.When("I go to \"Admin/Contents/List\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/Contents/List\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 53 - testRunner.Then("I should see \"Location:\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Location:\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 54 - testRunner.And("I should see \"Seattle\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I should see \"Seattle\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 57 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table5 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -177,15 +177,15 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].EnumerationFieldSettings.Hint", "Please select a location"}); #line 58 - testRunner.And("I fill in", ((string)(null)), table5, "And "); + testRunner.And("I fill in", ((string)(null)), table5, "And "); #line 61 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 62 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 63 - testRunner.Then("I should see \"Please select a location\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Please select a location\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 66 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table6 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -194,15 +194,15 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].EnumerationFieldSettings.ListMode", "Dropdown"}); #line 67 - testRunner.And("I fill in", ((string)(null)), table6, "And "); + testRunner.And("I fill in", ((string)(null)), table6, "And "); #line 70 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 71 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 72 - testRunner.Then("I should see \"select id=\\\"Event_Location_Value\\\" name=\\\"Event.Location.Value\\\"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"select id=\\\"Event_Location_Value\\\" name=\\\"Event.Location.Value\\\"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 75 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table7 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -211,16 +211,16 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].EnumerationFieldSettings.ListMode", "Radiobutton"}); #line 76 - testRunner.And("I fill in", ((string)(null)), table7, "And "); + testRunner.And("I fill in", ((string)(null)), table7, "And "); #line 79 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 80 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 81 - testRunner.Then("I should see \"input id=\\\"Event_Location_Value\\\" name=\\\"Event.Location.Value\\\" typ" + + testRunner.Then("I should see \"input id=\\\"Event_Location_Value\\\" name=\\\"Event.Location.Value\\\" typ" + "e=\\\"radio\\\"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 84 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table8 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -229,16 +229,16 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].EnumerationFieldSettings.ListMode", "Listbox"}); #line 85 - testRunner.And("I fill in", ((string)(null)), table8, "And "); + testRunner.And("I fill in", ((string)(null)), table8, "And "); #line 88 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 89 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 90 - testRunner.Then("I should see \"select id=\\\"Event_Location_SelectedValues\\\" multiple=\\\"multiple\\\" n" + + testRunner.Then("I should see \"select id=\\\"Event_Location_SelectedValues\\\" multiple=\\\"multiple\\\" n" + "ame=\\\"Event.Location.SelectedValues\\\"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 93 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table9 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -247,15 +247,15 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].EnumerationFieldSettings.ListMode", "Checkbox"}); #line 94 - testRunner.And("I fill in", ((string)(null)), table9, "And "); + testRunner.And("I fill in", ((string)(null)), table9, "And "); #line 97 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 98 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 99 - testRunner.Then("I should see \"input type=\\\"checkbox\\\" name=\\\"Event.Location.SelectedValues\\\"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"input type=\\\"checkbox\\\" name=\\\"Event.Location.SelectedValues\\\"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 102 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table10 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -264,15 +264,15 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].EnumerationFieldSettings.Required", "true"}); #line 103 - testRunner.And("I fill in", ((string)(null)), table10, "And "); + testRunner.And("I fill in", ((string)(null)), table10, "And "); #line 106 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 107 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 108 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 109 - testRunner.Then("I should see \"The field Location is mandatory.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"The field Location is mandatory.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden this.ScenarioCleanup(); } diff --git a/src/Orchard.Specs/Hosting/Orchard.Web/Config/Host.config b/src/Orchard.Specs/Hosting/Orchard.Web/Config/Host.config index 27f896868..89797fb2d 100644 --- a/src/Orchard.Specs/Hosting/Orchard.Web/Config/Host.config +++ b/src/Orchard.Specs/Hosting/Orchard.Web/Config/Host.config @@ -7,7 +7,7 @@ - + @@ -190,6 +191,7 @@ + @@ -198,24 +200,34 @@ - - + + - + - + - + - + + + + + + + + + + + diff --git a/src/Orchard.Specs/Hosting/Simple.Web/Web.config b/src/Orchard.Specs/Hosting/Simple.Web/Web.config index 99931ccb3..1042a64d6 100644 --- a/src/Orchard.Specs/Hosting/Simple.Web/Web.config +++ b/src/Orchard.Specs/Hosting/Simple.Web/Web.config @@ -195,7 +195,7 @@ - + diff --git a/src/Orchard.Specs/Input.feature b/src/Orchard.Specs/Input.feature index e7e37fd2e..35a8e761c 100644 --- a/src/Orchard.Specs/Input.feature +++ b/src/Orchard.Specs/Input.feature @@ -1,13 +1,13 @@ Feature: Input Field In order to add an input to my types - As an administrator + As an administrator I want to create, edit and publish input fields Scenario: Creating and using Input fields - - # Creating an Event content type + + # Creating an Event content type Given I have installed Orchard - And I have installed "Orchard.Fields" + And I have installed "Orchard.Fields" When I go to "Admin/ContentTypes" Then I should see "]*>.*?Create new type" When I go to "Admin/ContentTypes/Create" @@ -18,113 +18,113 @@ Scenario: Creating and using Input fields And I hit "Create" And I go to "Admin/ContentTypes/" Then I should see "Event" - - # Adding a Input field - When I go to "Admin/ContentTypes/Edit/Event" - And I follow "Add Field" - And I fill in + + # Adding a Input field + When I go to "Admin/ContentTypes/Edit/Event" + And I follow "Add Field" + And I fill in | name | value | | DisplayName | Contact | | Name | Contact | | FieldTypeName | InputField | - And I hit "Save" - And I am redirected - Then I should see "The \"Contact\" field has been added." + And I hit "Save" + And I am redirected + Then I should see "The \"Contact\" field has been added." - # The hint should be displayed - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].InputFieldSettings.Hint | Enter the contact email address | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "Enter the contact email address" - - # The pattern should be effective - #When I go to "Admin/ContentTypes/Edit/Event" - # And I fill in - # | name | value | - # | Fields[0].InputFieldSettings.Pattern | [^@]*@[^@]* | - # And I hit "Save" - # And I go to "Admin/Contents/Create/Event" - #Then I should see "pattern=\"[^@]*@[^@]*\"" - - # The input type should be effective - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].InputFieldSettings.Type | Email | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "type=\"email\"" - - # The title should be displayed - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].InputFieldSettings.Title | Enter an email address | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "title=\"Enter an email address\"" - - # The auto focus should be effective - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].InputFieldSettings.AutoFocus | true | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "autofocus=\"autofocus\"" - - # The auto complete should be effective - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].InputFieldSettings.AutoComplete | true | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "autocomplete=\"on\"" - - # The watermark should be displayed - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].InputFieldSettings.Placeholder | email@domain.com | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "placeholder=\"email@domain.com\"" - - # The maxlength should be effective - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].InputFieldSettings.MaxLength | 100 | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "maxlength=\"100\"" - - # The value should be required - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].InputFieldSettings.Required | true | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - And I fill in - | name | value | - | Event.Contact.Value | | - And I hit "Save" - Then I should see "The field Contact is mandatory." - - # Creating an Event content item - When I go to "Admin/Contents/Create/Event" - Then I should see "Contact" - When I fill in - | name | value | - | Event.Contact.Value | contact@orchardproject.net | - And I hit "Save" - And I am redirected - Then I should see "Your Event has been created." - When I go to "Admin/Contents/List" - Then I should see "Contact:" - And I should see "contact@orchardproject.net" + # The hint should be displayed + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].InputFieldSettings.Hint | Enter the contact email address | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "Enter the contact email address" + + # The pattern should be effective + #When I go to "Admin/ContentTypes/Edit/Event" + # And I fill in + # | name | value | + # | Fields[0].InputFieldSettings.Pattern | [^@]*@[^@]* | + # And I hit "Save" + # And I go to "Admin/Contents/Create/Event" + #Then I should see "pattern=\"[^@]*@[^@]*\"" + + # The input type should be effective + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].InputFieldSettings.Type | Email | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "type=\"email\"" + + # The title should be displayed + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].InputFieldSettings.Title | Enter an email address | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "title=\"Enter an email address\"" + + # The auto focus should be effective + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].InputFieldSettings.AutoFocus | true | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "autofocus=\"autofocus\"" + + # The auto complete should be effective + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].InputFieldSettings.AutoComplete | true | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "autocomplete=\"on\"" + + # The watermark should be displayed + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].InputFieldSettings.Placeholder | email@domain.com | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "placeholder=\"email@domain.com\"" + + # The maxlength should be effective + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].InputFieldSettings.MaxLength | 100 | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "maxlength=\"100\"" + + # The value should be required + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].InputFieldSettings.Required | true | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + And I fill in + | name | value | + | Event.Contact.Value | | + And I hit "Save" + Then I should see "The field Contact is mandatory." + + # Creating an Event content item + When I go to "Admin/Contents/Create/Event" + Then I should see "Contact" + When I fill in + | name | value | + | Event.Contact.Value | contact@orchardproject.net | + And I hit "Save" + And I am redirected + Then I should see "Your Event has been created." + When I go to "Admin/Contents/List" + Then I should see "Contact:" + And I should see "contact@orchardproject.net" diff --git a/src/Orchard.Specs/Input.feature.cs b/src/Orchard.Specs/Input.feature.cs index ade6902bf..2e9c54158 100644 --- a/src/Orchard.Specs/Input.feature.cs +++ b/src/Orchard.Specs/Input.feature.cs @@ -3,7 +3,7 @@ // This code was generated by SpecFlow (http://www.specflow.org/). // SpecFlow Version:1.9.0.77 // SpecFlow Generator Version:1.9.0.0 -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -32,8 +32,8 @@ namespace Orchard.Specs public virtual void FeatureSetup() { testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner(); - TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Input Field", " In order to add an input to my types\r\nAs an administrator\r\n I want to create, " + - "edit and publish input fields", ProgrammingLanguage.CSharp, ((string[])(null))); + TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Input Field", " In order to add an input to my types\r\n As an administrator\r\n I want to create" + + ", edit and publish input fields", ProgrammingLanguage.CSharp, ((string[])(null))); testRunner.OnFeatureStart(featureInfo); } @@ -75,7 +75,7 @@ this.ScenarioSetup(scenarioInfo); #line 9 testRunner.Given("I have installed Orchard", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); #line 10 - testRunner.And("I have installed \"Orchard.Fields\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I have installed \"Orchard.Fields\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 11 testRunner.When("I go to \"Admin/ContentTypes\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 12 @@ -101,9 +101,9 @@ this.ScenarioSetup(scenarioInfo); #line 20 testRunner.Then("I should see \"Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 23 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 24 - testRunner.And("I follow \"Add Field\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I follow \"Add Field\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden TechTalk.SpecFlow.Table table2 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -118,15 +118,15 @@ this.ScenarioSetup(scenarioInfo); "FieldTypeName", "InputField"}); #line 25 - testRunner.And("I fill in", ((string)(null)), table2, "And "); + testRunner.And("I fill in", ((string)(null)), table2, "And "); #line 30 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 31 - testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 32 - testRunner.Then("I should see \"The \\\"Contact\\\" field has been added.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"The \\\"Contact\\\" field has been added.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 35 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table3 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -135,15 +135,15 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].InputFieldSettings.Hint", "Enter the contact email address"}); #line 36 - testRunner.And("I fill in", ((string)(null)), table3, "And "); + testRunner.And("I fill in", ((string)(null)), table3, "And "); #line 39 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 40 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 41 - testRunner.Then("I should see \"Enter the contact email address\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Enter the contact email address\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 53 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table4 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -152,15 +152,15 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].InputFieldSettings.Type", "Email"}); #line 54 - testRunner.And("I fill in", ((string)(null)), table4, "And "); + testRunner.And("I fill in", ((string)(null)), table4, "And "); #line 57 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 58 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 59 - testRunner.Then("I should see \"type=\\\"email\\\"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"type=\\\"email\\\"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 62 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table5 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -169,15 +169,15 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].InputFieldSettings.Title", "Enter an email address"}); #line 63 - testRunner.And("I fill in", ((string)(null)), table5, "And "); + testRunner.And("I fill in", ((string)(null)), table5, "And "); #line 66 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 67 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 68 - testRunner.Then("I should see \"title=\\\"Enter an email address\\\"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"title=\\\"Enter an email address\\\"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 71 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table6 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -186,15 +186,15 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].InputFieldSettings.AutoFocus", "true"}); #line 72 - testRunner.And("I fill in", ((string)(null)), table6, "And "); + testRunner.And("I fill in", ((string)(null)), table6, "And "); #line 75 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 76 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 77 - testRunner.Then("I should see \"autofocus=\\\"autofocus\\\"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"autofocus=\\\"autofocus\\\"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 80 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table7 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -203,15 +203,15 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].InputFieldSettings.AutoComplete", "true"}); #line 81 - testRunner.And("I fill in", ((string)(null)), table7, "And "); + testRunner.And("I fill in", ((string)(null)), table7, "And "); #line 84 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 85 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 86 - testRunner.Then("I should see \"autocomplete=\\\"on\\\"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"autocomplete=\\\"on\\\"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 89 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table8 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -220,15 +220,15 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].InputFieldSettings.Placeholder", "email@domain.com"}); #line 90 - testRunner.And("I fill in", ((string)(null)), table8, "And "); + testRunner.And("I fill in", ((string)(null)), table8, "And "); #line 93 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 94 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 95 - testRunner.Then("I should see \"placeholder=\\\"email@domain.com\\\"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"placeholder=\\\"email@domain.com\\\"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 98 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table9 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -237,15 +237,15 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].InputFieldSettings.MaxLength", "100"}); #line 99 - testRunner.And("I fill in", ((string)(null)), table9, "And "); + testRunner.And("I fill in", ((string)(null)), table9, "And "); #line 102 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 103 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 104 - testRunner.Then("I should see \"maxlength=\\\"100\\\"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"maxlength=\\\"100\\\"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 107 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table10 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -254,11 +254,11 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].InputFieldSettings.Required", "true"}); #line 108 - testRunner.And("I fill in", ((string)(null)), table10, "And "); + testRunner.And("I fill in", ((string)(null)), table10, "And "); #line 111 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 112 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden TechTalk.SpecFlow.Table table11 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -267,15 +267,15 @@ this.ScenarioSetup(scenarioInfo); "Event.Contact.Value", ""}); #line 113 - testRunner.And("I fill in", ((string)(null)), table11, "And "); + testRunner.And("I fill in", ((string)(null)), table11, "And "); #line 116 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 117 - testRunner.Then("I should see \"The field Contact is mandatory.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"The field Contact is mandatory.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 120 - testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 121 - testRunner.Then("I should see \"Contact\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Contact\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden TechTalk.SpecFlow.Table table12 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -284,19 +284,19 @@ this.ScenarioSetup(scenarioInfo); "Event.Contact.Value", "contact@orchardproject.net"}); #line 122 - testRunner.When("I fill in", ((string)(null)), table12, "When "); + testRunner.When("I fill in", ((string)(null)), table12, "When "); #line 125 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 126 - testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 127 - testRunner.Then("I should see \"Your Event has been created.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Your Event has been created.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 128 - testRunner.When("I go to \"Admin/Contents/List\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/Contents/List\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 129 - testRunner.Then("I should see \"Contact:\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Contact:\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 130 - testRunner.And("I should see \"contact@orchardproject.net\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I should see \"contact@orchardproject.net\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden this.ScenarioCleanup(); } diff --git a/src/Orchard.Specs/Link.feature b/src/Orchard.Specs/Link.feature index cf7d8d04f..9ae1de538 100644 --- a/src/Orchard.Specs/Link.feature +++ b/src/Orchard.Specs/Link.feature @@ -1,13 +1,13 @@ Feature: Link Field In order to add Link content to my types - As an administrator + As an administrator I want to create, edit and publish Link fields Scenario: Creating and using Link fields - - # Creating an Event content type + + # Creating an Event content type Given I have installed Orchard - And I have installed "Orchard.Fields" + And I have installed "Orchard.Fields" When I go to "Admin/ContentTypes" Then I should see "]*>.*?Create new type" When I go to "Admin/ContentTypes/Create" @@ -18,53 +18,53 @@ Scenario: Creating and using Link fields And I hit "Create" And I go to "Admin/ContentTypes/" Then I should see "Event" - - # Adding a Link field - When I go to "Admin/ContentTypes/Edit/Event" - And I follow "Add Field" - And I fill in + + # Adding a Link field + When I go to "Admin/ContentTypes/Edit/Event" + And I follow "Add Field" + And I fill in | name | value | | DisplayName | Site Url | | Name | SiteUrl | | FieldTypeName | LinkField | - And I hit "Save" - And I am redirected - Then I should see "The \"Site Url\" field has been added." + And I hit "Save" + And I am redirected + Then I should see "The \"Site Url\" field has been added." - # Creating an Event content item - When I go to "Admin/Contents/Create/Event" - Then I should see "Site Url" - When I fill in - | name | value | - | Event.SiteUrl.Value | http://www.orchardproject.net | - And I fill in - | name | value | - | Event.SiteUrl.Text | Orchard | - And I hit "Save" - And I am redirected - Then I should see "Your Event has been created." - When I go to "Admin/Contents/List" - Then I should see "Site Url:" - And I should see "Orchard" + # Creating an Event content item + When I go to "Admin/Contents/Create/Event" + Then I should see "Site Url" + When I fill in + | name | value | + | Event.SiteUrl.Value | http://www.orchardproject.net | + And I fill in + | name | value | + | Event.SiteUrl.Text | Orchard | + And I hit "Save" + And I am redirected + Then I should see "Your Event has been created." + When I go to "Admin/Contents/List" + Then I should see "Site Url:" + And I should see "Orchard" - # The hint should be displayed - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].LinkFieldSettings.Hint | Enter the url of the web site | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "Enter the url of the web site" - - # The value should be required - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].LinkFieldSettings.Required | true | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - And I fill in - | name | value | - | Event.SiteUrl.Value | | - And I hit "Save" - Then I should see "Url is required for Site Url." \ No newline at end of file + # The hint should be displayed + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].LinkFieldSettings.Hint | Enter the url of the web site | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "Enter the url of the web site" + + # The value should be required + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].LinkFieldSettings.Required | true | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + And I fill in + | name | value | + | Event.SiteUrl.Value | | + And I hit "Save" + Then I should see "Url is required for Site Url." \ No newline at end of file diff --git a/src/Orchard.Specs/Link.feature.cs b/src/Orchard.Specs/Link.feature.cs index e226372db..84b100ed4 100644 --- a/src/Orchard.Specs/Link.feature.cs +++ b/src/Orchard.Specs/Link.feature.cs @@ -3,7 +3,7 @@ // This code was generated by SpecFlow (http://www.specflow.org/). // SpecFlow Version:1.9.0.77 // SpecFlow Generator Version:1.9.0.0 -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -32,8 +32,8 @@ namespace Orchard.Specs public virtual void FeatureSetup() { testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner(); - TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Link Field", " In order to add Link content to my types\r\nAs an administrator\r\n I want to crea" + - "te, edit and publish Link fields", ProgrammingLanguage.CSharp, ((string[])(null))); + TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Link Field", " In order to add Link content to my types\r\n As an administrator\r\n I want to cr" + + "eate, edit and publish Link fields", ProgrammingLanguage.CSharp, ((string[])(null))); testRunner.OnFeatureStart(featureInfo); } @@ -75,7 +75,7 @@ this.ScenarioSetup(scenarioInfo); #line 9 testRunner.Given("I have installed Orchard", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); #line 10 - testRunner.And("I have installed \"Orchard.Fields\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I have installed \"Orchard.Fields\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 11 testRunner.When("I go to \"Admin/ContentTypes\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 12 @@ -101,9 +101,9 @@ this.ScenarioSetup(scenarioInfo); #line 20 testRunner.Then("I should see \"Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 23 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 24 - testRunner.And("I follow \"Add Field\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I follow \"Add Field\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden TechTalk.SpecFlow.Table table2 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -118,17 +118,17 @@ this.ScenarioSetup(scenarioInfo); "FieldTypeName", "LinkField"}); #line 25 - testRunner.And("I fill in", ((string)(null)), table2, "And "); + testRunner.And("I fill in", ((string)(null)), table2, "And "); #line 30 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 31 - testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 32 - testRunner.Then("I should see \"The \\\"Site Url\\\" field has been added.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"The \\\"Site Url\\\" field has been added.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 35 - testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 36 - testRunner.Then("I should see \"Site Url\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Site Url\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden TechTalk.SpecFlow.Table table3 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -137,7 +137,7 @@ this.ScenarioSetup(scenarioInfo); "Event.SiteUrl.Value", "http://www.orchardproject.net"}); #line 37 - testRunner.When("I fill in", ((string)(null)), table3, "When "); + testRunner.When("I fill in", ((string)(null)), table3, "When "); #line hidden TechTalk.SpecFlow.Table table4 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -146,21 +146,21 @@ this.ScenarioSetup(scenarioInfo); "Event.SiteUrl.Text", "Orchard"}); #line 40 - testRunner.And("I fill in", ((string)(null)), table4, "And "); + testRunner.And("I fill in", ((string)(null)), table4, "And "); #line 43 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 44 - testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 45 - testRunner.Then("I should see \"Your Event has been created.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Your Event has been created.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 46 - testRunner.When("I go to \"Admin/Contents/List\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/Contents/List\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 47 - testRunner.Then("I should see \"Site Url:\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Site Url:\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 48 - testRunner.And("I should see \"Orchard\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I should see \"Orchard\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 51 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table5 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -169,15 +169,15 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].LinkFieldSettings.Hint", "Enter the url of the web site"}); #line 52 - testRunner.And("I fill in", ((string)(null)), table5, "And "); + testRunner.And("I fill in", ((string)(null)), table5, "And "); #line 55 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 56 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 57 - testRunner.Then("I should see \"Enter the url of the web site\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Enter the url of the web site\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 60 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table6 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -186,11 +186,11 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].LinkFieldSettings.Required", "true"}); #line 61 - testRunner.And("I fill in", ((string)(null)), table6, "And "); + testRunner.And("I fill in", ((string)(null)), table6, "And "); #line 64 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 65 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden TechTalk.SpecFlow.Table table7 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -199,11 +199,11 @@ this.ScenarioSetup(scenarioInfo); "Event.SiteUrl.Value", ""}); #line 66 - testRunner.And("I fill in", ((string)(null)), table7, "And "); + testRunner.And("I fill in", ((string)(null)), table7, "And "); #line 69 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 70 - testRunner.Then("I should see \"Url is required for Site Url.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Url is required for Site Url.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden this.ScenarioCleanup(); } diff --git a/src/Orchard.Specs/Lists.feature b/src/Orchard.Specs/Lists.feature index 5074e822c..e68f3ccac 100644 --- a/src/Orchard.Specs/Lists.feature +++ b/src/Orchard.Specs/Lists.feature @@ -5,19 +5,19 @@ Scenario: I can create a new list Given I have installed Orchard - And I have installed "Orchard.Lists" + And I have installed "Orchard.Lists" When I go to "Admin/ContentTypes" - And I go to "Admin/ContentTypes/Create" + And I go to "Admin/ContentTypes/Create" And I fill in | name | value | | DisplayName | Event | | Name | Event | And I hit "Create" - And I am redirected + And I am redirected And I fill in | name | value | | PartSelections[5].IsSelected | True | - And I hit "Save" + And I hit "Save" And I go to "Admin/ContentTypes/" Then I should see "Event" @@ -27,8 +27,8 @@ Scenario: I can create a new list | Title.Title | MyList | | Container.SelectedItemContentTypes | Event | And I hit "Save" - And I am redirected - Then I should see "Your List has been created" + And I am redirected + Then I should see "Your List has been created" When I go to "Admin/Lists" Then I should see "MyList" When I follow "Contained Items (0)" diff --git a/src/Orchard.Specs/Lists.feature.cs b/src/Orchard.Specs/Lists.feature.cs index a5bd6ef8b..ec41dafc7 100644 --- a/src/Orchard.Specs/Lists.feature.cs +++ b/src/Orchard.Specs/Lists.feature.cs @@ -3,7 +3,7 @@ // This code was generated by SpecFlow (http://www.specflow.org/). // SpecFlow Version:1.9.0.77 // SpecFlow Generator Version:1.9.0.0 -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -75,11 +75,11 @@ this.ScenarioSetup(scenarioInfo); #line 7 testRunner.Given("I have installed Orchard", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); #line 8 - testRunner.And("I have installed \"Orchard.Lists\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I have installed \"Orchard.Lists\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 9 testRunner.When("I go to \"Admin/ContentTypes\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 10 - testRunner.And("I go to \"Admin/ContentTypes/Create\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/ContentTypes/Create\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden TechTalk.SpecFlow.Table table1 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -95,7 +95,7 @@ this.ScenarioSetup(scenarioInfo); #line 15 testRunner.And("I hit \"Create\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 16 - testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden TechTalk.SpecFlow.Table table2 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -106,7 +106,7 @@ this.ScenarioSetup(scenarioInfo); #line 17 testRunner.And("I fill in", ((string)(null)), table2, "And "); #line 20 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 21 testRunner.And("I go to \"Admin/ContentTypes/\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 22 @@ -128,9 +128,9 @@ this.ScenarioSetup(scenarioInfo); #line 29 testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 30 - testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 31 - testRunner.Then("I should see \"Your List has been created\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Your List has been created\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 32 testRunner.When("I go to \"Admin/Lists\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 33 diff --git a/src/Orchard.Specs/Media.feature b/src/Orchard.Specs/Media.feature index dd018ab39..5e1193fbf 100644 --- a/src/Orchard.Specs/Media.feature +++ b/src/Orchard.Specs/Media.feature @@ -5,14 +5,14 @@ Scenario: Media admin is available Given I have installed Orchard - And I have installed "Orchard.Media" + And I have installed "Orchard.Media" - # Accessing the media page + # Accessing the media page When I go to "admin/media" Then I should see "Media" And the status should be 200 "OK" - # Creating a folder + # Creating a folder When I go to "admin/media/create" And I fill in | name | value | @@ -23,7 +23,7 @@ Scenario: Media admin is available And I should see "Hello World" And the status should be 200 "OK" - # Editing a media with limited rights + # Editing a media with limited rights When I go to "admin/media/edit?name=..\..\bin&mediaPath=..\..\bin" And I am redirected Then I should see "Media" diff --git a/src/Orchard.Specs/Media.feature.cs b/src/Orchard.Specs/Media.feature.cs index a9da6dd42..2c1d61c13 100644 --- a/src/Orchard.Specs/Media.feature.cs +++ b/src/Orchard.Specs/Media.feature.cs @@ -3,7 +3,7 @@ // This code was generated by SpecFlow (http://www.specflow.org/). // SpecFlow Version:1.9.0.77 // SpecFlow Generator Version:1.9.0.0 -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -75,7 +75,7 @@ this.ScenarioSetup(scenarioInfo); #line 7 testRunner.Given("I have installed Orchard", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); #line 8 - testRunner.And("I have installed \"Orchard.Media\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I have installed \"Orchard.Media\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 11 testRunner.When("I go to \"admin/media\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 12 diff --git a/src/Orchard.Specs/MediaPicker.feature b/src/Orchard.Specs/MediaPicker.feature index 3c1008de6..eba7506a1 100644 --- a/src/Orchard.Specs/MediaPicker.feature +++ b/src/Orchard.Specs/MediaPicker.feature @@ -1,14 +1,14 @@ Feature: Media Picker Field In order to add a media content to my types - As an administrator + As an administrator I want to create, edit and publish media fields Scenario: Creating and using media fields - - # Creating an Event content type + + # Creating an Event content type Given I have installed Orchard - And I have installed "Orchard.Media" - And I have installed "Orchard.MediaPicker" + And I have installed "Orchard.Media" + And I have installed "Orchard.MediaPicker" When I go to "Admin/ContentTypes" Then I should see "]*>.*?Create new type" @@ -20,61 +20,61 @@ Scenario: Creating and using media fields And I hit "Create" And I go to "Admin/ContentTypes/" Then I should see "Event" - - # Adding a media field - When I go to "Admin/ContentTypes/Edit/Event" - And I follow "Add Field" - And I fill in + + # Adding a media field + When I go to "Admin/ContentTypes/Edit/Event" + And I follow "Add Field" + And I fill in | name | value | | DisplayName | File | | Name | File | | FieldTypeName | MediaPickerField | - And I hit "Save" - And I am redirected - Then I should see "The \"File\" field has been added." + And I hit "Save" + And I am redirected + Then I should see "The \"File\" field has been added." - # Creating an Event content item - When I go to "Admin/Contents/Create/Event" - Then I should see "File" - When I fill in - | name | value | - | Event.File.Url | | - And I hit "Save" - And I am redirected - Then I should see "Your Event has been created." + # Creating an Event content item + When I go to "Admin/Contents/Create/Event" + Then I should see "File" + When I fill in + | name | value | + | Event.File.Url | | + And I hit "Save" + And I am redirected + Then I should see "Your Event has been created." - # The hint should be displayed - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].MediaPickerFieldSettings.Hint | Please select a file | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "Please select a file" + # The hint should be displayed + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].MediaPickerFieldSettings.Hint | Please select a file | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "Please select a file" - # The value should be required - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].MediaPickerFieldSettings.Required | true | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - And I fill in - | name | value | - | Event.File.Url | | - And I hit "Save" - Then I should see "The field File is mandatory." + # The value should be required + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].MediaPickerFieldSettings.Required | true | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + And I fill in + | name | value | + | Event.File.Url | | + And I hit "Save" + Then I should see "The field File is mandatory." - # The value should be bound - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | ext-Fields[0].MediaPickerFieldSettings | true | - | Fields[0].MediaPickerFieldSettings.AllowedExtensions | jpg | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - And I fill in - | name | value | - | Event.File.Url | ~/Media/Default/images/Image.png | - And I hit "Save" - Then I should see "The field File must have one of these extensions: jpg" \ No newline at end of file + # The value should be bound + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | ext-Fields[0].MediaPickerFieldSettings | true | + | Fields[0].MediaPickerFieldSettings.AllowedExtensions | jpg | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + And I fill in + | name | value | + | Event.File.Url | ~/Media/Default/images/Image.png | + And I hit "Save" + Then I should see "The field File must have one of these extensions: jpg" \ No newline at end of file diff --git a/src/Orchard.Specs/MediaPicker.feature.cs b/src/Orchard.Specs/MediaPicker.feature.cs index 9ff2adb90..3189f9308 100644 --- a/src/Orchard.Specs/MediaPicker.feature.cs +++ b/src/Orchard.Specs/MediaPicker.feature.cs @@ -3,7 +3,7 @@ // This code was generated by SpecFlow (http://www.specflow.org/). // SpecFlow Version:1.9.0.77 // SpecFlow Generator Version:1.9.0.0 -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -32,8 +32,8 @@ namespace Orchard.Specs public virtual void FeatureSetup() { testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner(); - TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Media Picker Field", " In order to add a media content to my types\r\nAs an administrator\r\n I want to c" + - "reate, edit and publish media fields", ProgrammingLanguage.CSharp, ((string[])(null))); + TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Media Picker Field", " In order to add a media content to my types\r\n As an administrator\r\n I want to" + + " create, edit and publish media fields", ProgrammingLanguage.CSharp, ((string[])(null))); testRunner.OnFeatureStart(featureInfo); } @@ -75,9 +75,9 @@ this.ScenarioSetup(scenarioInfo); #line 9 testRunner.Given("I have installed Orchard", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); #line 10 - testRunner.And("I have installed \"Orchard.Media\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I have installed \"Orchard.Media\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 11 - testRunner.And("I have installed \"Orchard.MediaPicker\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I have installed \"Orchard.MediaPicker\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 13 testRunner.When("I go to \"Admin/ContentTypes\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 14 @@ -103,9 +103,9 @@ this.ScenarioSetup(scenarioInfo); #line 22 testRunner.Then("I should see \"Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 25 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 26 - testRunner.And("I follow \"Add Field\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I follow \"Add Field\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden TechTalk.SpecFlow.Table table2 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -120,17 +120,17 @@ this.ScenarioSetup(scenarioInfo); "FieldTypeName", "MediaPickerField"}); #line 27 - testRunner.And("I fill in", ((string)(null)), table2, "And "); + testRunner.And("I fill in", ((string)(null)), table2, "And "); #line 32 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 33 - testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 34 - testRunner.Then("I should see \"The \\\"File\\\" field has been added.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"The \\\"File\\\" field has been added.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 37 - testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 38 - testRunner.Then("I should see \"File\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"File\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden TechTalk.SpecFlow.Table table3 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -139,15 +139,15 @@ this.ScenarioSetup(scenarioInfo); "Event.File.Url", ""}); #line 39 - testRunner.When("I fill in", ((string)(null)), table3, "When "); + testRunner.When("I fill in", ((string)(null)), table3, "When "); #line 42 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 43 - testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 44 - testRunner.Then("I should see \"Your Event has been created.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Your Event has been created.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 47 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table4 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -156,15 +156,15 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].MediaPickerFieldSettings.Hint", "Please select a file"}); #line 48 - testRunner.And("I fill in", ((string)(null)), table4, "And "); + testRunner.And("I fill in", ((string)(null)), table4, "And "); #line 51 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 52 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 53 - testRunner.Then("I should see \"Please select a file\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Please select a file\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 56 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table5 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -173,11 +173,11 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].MediaPickerFieldSettings.Required", "true"}); #line 57 - testRunner.And("I fill in", ((string)(null)), table5, "And "); + testRunner.And("I fill in", ((string)(null)), table5, "And "); #line 60 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 61 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden TechTalk.SpecFlow.Table table6 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -186,13 +186,13 @@ this.ScenarioSetup(scenarioInfo); "Event.File.Url", ""}); #line 62 - testRunner.And("I fill in", ((string)(null)), table6, "And "); + testRunner.And("I fill in", ((string)(null)), table6, "And "); #line 65 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 66 - testRunner.Then("I should see \"The field File is mandatory.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"The field File is mandatory.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 69 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table7 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -204,11 +204,11 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].MediaPickerFieldSettings.AllowedExtensions", "jpg"}); #line 70 - testRunner.And("I fill in", ((string)(null)), table7, "And "); + testRunner.And("I fill in", ((string)(null)), table7, "And "); #line 74 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 75 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden TechTalk.SpecFlow.Table table8 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -217,11 +217,11 @@ this.ScenarioSetup(scenarioInfo); "Event.File.Url", "~/Media/Default/images/Image.png"}); #line 76 - testRunner.And("I fill in", ((string)(null)), table8, "And "); + testRunner.And("I fill in", ((string)(null)), table8, "And "); #line 79 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 80 - testRunner.Then("I should see \"The field File must have one of these extensions: jpg\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"The field File must have one of these extensions: jpg\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden this.ScenarioCleanup(); } diff --git a/src/Orchard.Specs/MultiTenancy.feature b/src/Orchard.Specs/MultiTenancy.feature index ae586c309..909569d7f 100644 --- a/src/Orchard.Specs/MultiTenancy.feature +++ b/src/Orchard.Specs/MultiTenancy.feature @@ -168,7 +168,7 @@ Scenario: A running tenant can be disabled And I go to "/Admin/MultiTenancy" on host localhost And I hit "Suspend" And I am redirected - Then I should see "
tenant list Then I should see "Name: Alpha" - And I should see "Request Url Host: example.org" \ No newline at end of file + And I should see "Request URL host: example.org" \ No newline at end of file diff --git a/src/Orchard.Specs/MultiTenancy.feature.cs b/src/Orchard.Specs/MultiTenancy.feature.cs index d1d54d065..1c6466f64 100644 --- a/src/Orchard.Specs/MultiTenancy.feature.cs +++ b/src/Orchard.Specs/MultiTenancy.feature.cs @@ -3,7 +3,7 @@ // This code was generated by SpecFlow (http://www.specflow.org/). // SpecFlow Version:1.9.0.77 // SpecFlow Generator Version:1.9.0.0 -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -525,7 +525,7 @@ this.ScenarioSetup(scenarioInfo); #line 170 testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 171 - testRunner.Then("I should see \"]*>.*?Create new type" When I go to "Admin/ContentTypes/Create" @@ -18,82 +18,82 @@ Scenario: Creating and using numeric fields And I hit "Create" And I go to "Admin/ContentTypes/" Then I should see "Event" - - # Adding a numeric field - When I go to "Admin/ContentTypes/Edit/Event" - And I follow "Add Field" - And I fill in + + # Adding a numeric field + When I go to "Admin/ContentTypes/Edit/Event" + And I follow "Add Field" + And I fill in | name | value | | DisplayName | Guests | | Name | Guests | | FieldTypeName | NumericField | - And I hit "Save" - And I am redirected - Then I should see "The \"Guests\" field has been added." + And I hit "Save" + And I am redirected + Then I should see "The \"Guests\" field has been added." - # Creating an Event content item - When I go to "Admin/Contents/Create/Event" - Then I should see "Guests" - When I fill in - | name | value | - | Event.Guests.Value | 3 | - And I hit "Save" - And I am redirected - Then I should see "Your Event has been created." - When I go to "Admin/Contents/List" - Then I should see "Guests:" - And I should see "3" + # Creating an Event content item + When I go to "Admin/Contents/Create/Event" + Then I should see "Guests" + When I fill in + | name | value | + | Event.Guests.Value | 3 | + And I hit "Save" + And I am redirected + Then I should see "Your Event has been created." + When I go to "Admin/Contents/List" + Then I should see "Guests:" + And I should see "3" - # The hint should be displayed - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].NumericFieldSettings.Hint | Please enter a number | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "Please enter a number" + # The hint should be displayed + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].NumericFieldSettings.Hint | Please enter a number | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "Please enter a number" - # The value should be required - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].NumericFieldSettings.Required | true | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - And I fill in - | name | value | - | Event.Guests.Value | | - And I hit "Save" - Then I should see "The field Guests is mandatory." + # The value should be required + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].NumericFieldSettings.Required | true | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + And I fill in + | name | value | + | Event.Guests.Value | | + And I hit "Save" + Then I should see "The field Guests is mandatory." - # The value should be bound - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].NumericFieldSettings.Minimum | -10 | - | Fields[0].NumericFieldSettings.Maximum | 100 | - And I hit "Save" - And I go to "Admin/Contents/Create/Event" - Then I should see "min=\"-10\"" - And I should see "max=\"100\"" - When I fill in - | name | value | - | Event.Guests.Value | -20 | - And I hit "Save" - Then I should see "The value must be greater than -10" - When I go to "Admin/Contents/Create/Event" - And I fill in - | name | value | - | Event.Guests.Value | 101 | - And I hit "Save" - Then I should see "The value must be less than 100" - - # Settings should be validated - When I go to "Admin/ContentTypes/Edit/Event" - And I fill in - | name | value | - | Fields[0].NumericFieldSettings.Minimum | a | - | Fields[0].NumericFieldSettings.Maximum | b | - And I hit "Save" - Then I should see "The value 'a' is not valid for Minimum." - And I should see "The value 'b' is not valid for Maximum." \ No newline at end of file + # The value should be bound + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].NumericFieldSettings.Minimum | -10 | + | Fields[0].NumericFieldSettings.Maximum | 100 | + And I hit "Save" + And I go to "Admin/Contents/Create/Event" + Then I should see "min=\"-10\"" + And I should see "max=\"100\"" + When I fill in + | name | value | + | Event.Guests.Value | -20 | + And I hit "Save" + Then I should see "The value must be greater than -10" + When I go to "Admin/Contents/Create/Event" + And I fill in + | name | value | + | Event.Guests.Value | 101 | + And I hit "Save" + Then I should see "The value must be less than 100" + + # Settings should be validated + When I go to "Admin/ContentTypes/Edit/Event" + And I fill in + | name | value | + | Fields[0].NumericFieldSettings.Minimum | a | + | Fields[0].NumericFieldSettings.Maximum | b | + And I hit "Save" + Then I should see "The value 'a' is not valid for Minimum." + And I should see "The value 'b' is not valid for Maximum." \ No newline at end of file diff --git a/src/Orchard.Specs/Numeric.feature.cs b/src/Orchard.Specs/Numeric.feature.cs index a676279cd..e90b2c1bf 100644 --- a/src/Orchard.Specs/Numeric.feature.cs +++ b/src/Orchard.Specs/Numeric.feature.cs @@ -3,7 +3,7 @@ // This code was generated by SpecFlow (http://www.specflow.org/). // SpecFlow Version:1.9.0.77 // SpecFlow Generator Version:1.9.0.0 -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -32,8 +32,8 @@ namespace Orchard.Specs public virtual void FeatureSetup() { testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner(); - TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Numeric Field", " In order to add numeric content to my types\r\nAs an administrator\r\n I want to c" + - "reate, edit and publish numeric fields", ProgrammingLanguage.CSharp, ((string[])(null))); + TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Numeric Field", " In order to add numeric content to my types\r\n As an administrator\r\n I want to" + + " create, edit and publish numeric fields", ProgrammingLanguage.CSharp, ((string[])(null))); testRunner.OnFeatureStart(featureInfo); } @@ -75,7 +75,7 @@ this.ScenarioSetup(scenarioInfo); #line 9 testRunner.Given("I have installed Orchard", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); #line 10 - testRunner.And("I have installed \"Orchard.Fields\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I have installed \"Orchard.Fields\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 11 testRunner.When("I go to \"Admin/ContentTypes\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 12 @@ -101,9 +101,9 @@ this.ScenarioSetup(scenarioInfo); #line 20 testRunner.Then("I should see \"Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 23 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 24 - testRunner.And("I follow \"Add Field\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I follow \"Add Field\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden TechTalk.SpecFlow.Table table2 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -118,17 +118,17 @@ this.ScenarioSetup(scenarioInfo); "FieldTypeName", "NumericField"}); #line 25 - testRunner.And("I fill in", ((string)(null)), table2, "And "); + testRunner.And("I fill in", ((string)(null)), table2, "And "); #line 30 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 31 - testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 32 - testRunner.Then("I should see \"The \\\"Guests\\\" field has been added.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"The \\\"Guests\\\" field has been added.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 35 - testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 36 - testRunner.Then("I should see \"Guests\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Guests\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden TechTalk.SpecFlow.Table table3 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -137,21 +137,21 @@ this.ScenarioSetup(scenarioInfo); "Event.Guests.Value", "3"}); #line 37 - testRunner.When("I fill in", ((string)(null)), table3, "When "); + testRunner.When("I fill in", ((string)(null)), table3, "When "); #line 40 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 41 - testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 42 - testRunner.Then("I should see \"Your Event has been created.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Your Event has been created.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 43 - testRunner.When("I go to \"Admin/Contents/List\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/Contents/List\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line 44 - testRunner.Then("I should see \"Guests:\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Guests:\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 45 - testRunner.And("I should see \"3\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I should see \"3\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 48 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table4 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -160,15 +160,15 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].NumericFieldSettings.Hint", "Please enter a number"}); #line 49 - testRunner.And("I fill in", ((string)(null)), table4, "And "); + testRunner.And("I fill in", ((string)(null)), table4, "And "); #line 52 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 53 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 54 - testRunner.Then("I should see \"Please enter a number\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"Please enter a number\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 57 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table5 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -177,11 +177,11 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].NumericFieldSettings.Required", "true"}); #line 58 - testRunner.And("I fill in", ((string)(null)), table5, "And "); + testRunner.And("I fill in", ((string)(null)), table5, "And "); #line 61 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 62 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden TechTalk.SpecFlow.Table table6 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -190,13 +190,13 @@ this.ScenarioSetup(scenarioInfo); "Event.Guests.Value", ""}); #line 63 - testRunner.And("I fill in", ((string)(null)), table6, "And "); + testRunner.And("I fill in", ((string)(null)), table6, "And "); #line 66 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 67 - testRunner.Then("I should see \"The field Guests is mandatory.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"The field Guests is mandatory.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 70 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table7 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -208,15 +208,15 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].NumericFieldSettings.Maximum", "100"}); #line 71 - testRunner.And("I fill in", ((string)(null)), table7, "And "); + testRunner.And("I fill in", ((string)(null)), table7, "And "); #line 75 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 76 - testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 77 - testRunner.Then("I should see \"min=\\\"-10\\\"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"min=\\\"-10\\\"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 78 - testRunner.And("I should see \"max=\\\"100\\\"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I should see \"max=\\\"100\\\"\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden TechTalk.SpecFlow.Table table8 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -225,13 +225,13 @@ this.ScenarioSetup(scenarioInfo); "Event.Guests.Value", "-20"}); #line 79 - testRunner.When("I fill in", ((string)(null)), table8, "When "); + testRunner.When("I fill in", ((string)(null)), table8, "When "); #line 82 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 83 - testRunner.Then("I should see \"The value must be greater than -10\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"The value must be greater than -10\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 84 - testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/Contents/Create/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table9 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -240,13 +240,13 @@ this.ScenarioSetup(scenarioInfo); "Event.Guests.Value", "101"}); #line 85 - testRunner.And("I fill in", ((string)(null)), table9, "And "); + testRunner.And("I fill in", ((string)(null)), table9, "And "); #line 88 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 89 - testRunner.Then("I should see \"The value must be less than 100\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"The value must be less than 100\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 92 - testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("I go to \"Admin/ContentTypes/Edit/Event\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden TechTalk.SpecFlow.Table table10 = new TechTalk.SpecFlow.Table(new string[] { "name", @@ -258,13 +258,13 @@ this.ScenarioSetup(scenarioInfo); "Fields[0].NumericFieldSettings.Maximum", "b"}); #line 93 - testRunner.And("I fill in", ((string)(null)), table10, "And "); + testRunner.And("I fill in", ((string)(null)), table10, "And "); #line 97 - testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I hit \"Save\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 98 - testRunner.Then("I should see \"The value 'a' is not valid for Minimum.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I should see \"The value 'a' is not valid for Minimum.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line 99 - testRunner.And("I should see \"The value 'b' is not valid for Maximum.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I should see \"The value 'b' is not valid for Maximum.\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden this.ScenarioCleanup(); } diff --git a/src/Orchard.Specs/Pages.feature b/src/Orchard.Specs/Pages.feature index 5352b3df9..382d20e2d 100644 --- a/src/Orchard.Specs/Pages.feature +++ b/src/Orchard.Specs/Pages.feature @@ -25,7 +25,7 @@ Scenario: In the admin (menu) there is a link to create a Page And I fill in | name | value | | Title.Title | Super Duper | - | LayoutPart.LayoutEditor.Data | { "type": "Content", "data": "TypeName=Orchard.Layouts.Elements.Text&Content=This+is+super+number+two", "isTemplated": false, "contentType": "Orchard.Layouts.Elements.Text", "contentTypeLabel": "Text", "contentTypeClass": "text", "html": "This is super number two", "hasEditor": true } | + | AutoroutePart.LayoutEditor.Data | { "type": "Content", "data": "TypeName=Orchard.Layouts.Elements.Text&Content=This+is+super+number+two", "isTemplated": false, "contentType": "Orchard.Layouts.Elements.Text", "contentTypeLabel": "Text", "contentTypeClass": "text", "html": "This is super number two", "hasEditor": true } | And I hit "Publish Now" And I go to "super-duper-2" Then I should see "]*>.*?Super Duper.*?" @@ -36,7 +36,7 @@ Scenario: In the admin (menu) there is a link to create a Page And I fill in | name | value | | Title.Title | Another | - | Autoroute.PromoteToHomePage | true | + | AutoroutePart.PromoteToHomePage | true | And I hit "Publish Now" And I go to "/" Then I should see "

Another

" @@ -48,7 +48,7 @@ Scenario: In the admin (menu) there is a link to create a Page And I fill in | name | value | | Title.Title | Drafty | - | Autoroute.PromoteToHomePage | true | + | AutoroutePart.PromoteToHomePage | true | And I hit "Save" And I go to "/" Then I should see "

Another

" diff --git a/src/Orchard.Specs/Pages.feature.cs b/src/Orchard.Specs/Pages.feature.cs index 7ea3cf7d5..5a60be007 100644 --- a/src/Orchard.Specs/Pages.feature.cs +++ b/src/Orchard.Specs/Pages.feature.cs @@ -3,7 +3,7 @@ // This code was generated by SpecFlow (http://www.specflow.org/). // SpecFlow Version:1.9.0.77 // SpecFlow Generator Version:1.9.0.0 -// Runtime Version:4.0.30319.0 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -110,7 +110,7 @@ this.ScenarioSetup(scenarioInfo); "Title.Title", "Super Duper"}); table2.AddRow(new string[] { - "LayoutPart.LayoutEditor.Data", + "AutoroutePart.LayoutEditor.Data", @"{ ""type"": ""Content"", ""data"": ""TypeName=Orchard.Layouts.Elements.Text&Content=This+is+super+number+two"", ""isTemplated"": false, ""contentType"": ""Orchard.Layouts.Elements.Text"", ""contentTypeLabel"": ""Text"", ""contentTypeClass"": ""text"", ""html"": ""This is super number two"", ""hasEditor"": true }"}); #line 25 testRunner.And("I fill in", ((string)(null)), table2, "And "); @@ -132,7 +132,7 @@ this.ScenarioSetup(scenarioInfo); "Title.Title", "Another"}); table3.AddRow(new string[] { - "Autoroute.PromoteToHomePage", + "AutoroutePart.PromoteToHomePage", "true"}); #line 36 testRunner.And("I fill in", ((string)(null)), table3, "And "); @@ -156,7 +156,7 @@ this.ScenarioSetup(scenarioInfo); "Title.Title", "Drafty"}); table4.AddRow(new string[] { - "Autoroute.PromoteToHomePage", + "AutoroutePart.PromoteToHomePage", "true"}); #line 48 testRunner.And("I fill in", ((string)(null)), table4, "And "); diff --git a/src/Orchard.Specs/PermissionModel.feature b/src/Orchard.Specs/PermissionModel.feature index aa480a614..e010048bb 100644 --- a/src/Orchard.Specs/PermissionModel.feature +++ b/src/Orchard.Specs/PermissionModel.feature @@ -25,5 +25,4 @@ Scenario: Anonymous user can see the home page but not the dashboard When I sign in as "bob" And I go to "/" Then I should see "this is the homepage of your new site" - And I should be denied access when I go to "admin" - + And I should be denied access when I go to "admin" \ No newline at end of file diff --git a/src/Orchard.Specs/PermissionModel.feature.cs b/src/Orchard.Specs/PermissionModel.feature.cs index 5d5cdd391..c58cf66f7 100644 --- a/src/Orchard.Specs/PermissionModel.feature.cs +++ b/src/Orchard.Specs/PermissionModel.feature.cs @@ -3,7 +3,7 @@ // This code was generated by SpecFlow (http://www.specflow.org/). // SpecFlow Version:1.9.0.77 // SpecFlow Generator Version:1.9.0.0 -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. diff --git a/src/Orchard.Specs/Properties/AssemblyInfo.cs b/src/Orchard.Specs/Properties/AssemblyInfo.cs index 44da55c06..be2431218 100644 --- a/src/Orchard.Specs/Properties/AssemblyInfo.cs +++ b/src/Orchard.Specs/Properties/AssemblyInfo.cs @@ -30,5 +30,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Specs/Tags.feature b/src/Orchard.Specs/Tags.feature index af72b03e6..71440522a 100644 --- a/src/Orchard.Specs/Tags.feature +++ b/src/Orchard.Specs/Tags.feature @@ -26,5 +26,5 @@ Scenario: I can't add a tag with disallowed chars to a new Page | LayoutPart.LayoutEditor.Data | { "elements": [ { "typeName": "Orchard.Layouts.Elements.Text", "state": "Content=This+is+super."} ] } | | Tags.Tags | Foo, I <3 Orchard | And I hit "Publish Now" - And I am redirected + And I am redirected Then I should see "forbidden chars" diff --git a/src/Orchard.Specs/Tags.feature.cs b/src/Orchard.Specs/Tags.feature.cs index ef767cd61..71de7b3b9 100644 --- a/src/Orchard.Specs/Tags.feature.cs +++ b/src/Orchard.Specs/Tags.feature.cs @@ -3,7 +3,7 @@ // This code was generated by SpecFlow (http://www.specflow.org/). // SpecFlow Version:1.9.0.77 // SpecFlow Generator Version:1.9.0.0 -// Runtime Version:4.0.30319.0 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -136,7 +136,7 @@ this.ScenarioSetup(scenarioInfo); #line 28 testRunner.And("I hit \"Publish Now\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 29 - testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); + testRunner.And("I am redirected", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line 30 testRunner.Then("I should see \"forbidden chars\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden diff --git a/src/Orchard.Specs/Users.feature b/src/Orchard.Specs/Users.feature index dafcf1ebd..2378eddff 100644 --- a/src/Orchard.Specs/Users.feature +++ b/src/Orchard.Specs/Users.feature @@ -261,7 +261,7 @@ Scenario: I should be able to filter users by status Then I should see "User user1 disabled" When I fill in | name | value | - | Options.Search | | + | Options.Search | | | Options.Filter | Pending | And I hit "Filter" Then I should see "]*>user1" @@ -270,7 +270,7 @@ Scenario: I should be able to filter users by status When I fill in | name | value | | Options.Search | | - | Options.Filter | EmailPending | + | Options.Filter | EmailPending | And I hit "Filter" Then I should not see "]*>user1" And I should not see "]*>user2" @@ -278,14 +278,14 @@ Scenario: I should be able to filter users by status When I fill in | name | value | | Options.Search | | - | Options.Filter | Approved | + | Options.Filter | Approved | And I hit "Filter" Then I should not see "]*>user1" And I should see "]*>user2" And I should see "]*>admin" When I fill in | name | value | - | Options.Search | | + | Options.Search | | | Options.Filter | All | And I hit "Filter" Then I should see "]*>user1" diff --git a/src/Orchard.Specs/Users.feature.cs b/src/Orchard.Specs/Users.feature.cs index e1d2337e2..172ba791f 100644 --- a/src/Orchard.Specs/Users.feature.cs +++ b/src/Orchard.Specs/Users.feature.cs @@ -3,7 +3,7 @@ // This code was generated by SpecFlow (http://www.specflow.org/). // SpecFlow Version:1.9.0.77 // SpecFlow Generator Version:1.9.0.0 -// Runtime Version:4.0.30319.0 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. diff --git a/src/Orchard.Tests.Modules/App.config b/src/Orchard.Tests.Modules/App.config index a14743e2d..4febd68c7 100644 --- a/src/Orchard.Tests.Modules/App.config +++ b/src/Orchard.Tests.Modules/App.config @@ -24,7 +24,7 @@ - + diff --git a/src/Orchard.Tests.Modules/DesignerTools/Services/ObjectDumperTests.cs b/src/Orchard.Tests.Modules/DesignerTools/Services/ObjectDumperTests.cs index d78cd52bb..22b162ac1 100644 --- a/src/Orchard.Tests.Modules/DesignerTools/Services/ObjectDumperTests.cs +++ b/src/Orchard.Tests.Modules/DesignerTools/Services/ObjectDumperTests.cs @@ -264,9 +264,6 @@ namespace Orchard.Tests.Modules.DesignerTools.Services new JProperty("name", "TestingPart"), new JProperty("value", "ContentPart"), new JProperty("children", new JArray( - new JObject( - new JProperty("name", "Zones"), - new JProperty("value", "ZoneCollection")), new JObject( new JProperty("name", "Id"), new JProperty("value", "0")), @@ -327,9 +324,6 @@ namespace Orchard.Tests.Modules.DesignerTools.Services new JProperty("name", "TestingPart"), new JProperty("value", "ContentPart"), new JProperty("children", new JArray( - new JObject( - new JProperty("name", "Zones"), - new JProperty("value", "ZoneCollection")), new JObject( new JProperty("name", "Id"), new JProperty("value", "0")), diff --git a/src/Orchard.Tests.Modules/Indexing/LuceneIndexProviderTests.cs b/src/Orchard.Tests.Modules/Indexing/LuceneIndexProviderTests.cs index 41c6239fb..d7008dd6a 100644 --- a/src/Orchard.Tests.Modules/Indexing/LuceneIndexProviderTests.cs +++ b/src/Orchard.Tests.Modules/Indexing/LuceneIndexProviderTests.cs @@ -303,5 +303,24 @@ namespace Orchard.Tests.Modules.Indexing { _provider.Store("default", _provider.New(1).Add("field", "value2")); Assert.That(searchBuilder.WithField("id", "1").Count(), Is.EqualTo(1)); } + + [Test] + public void IndexProviderShouldDeleteMoreThanMaxTermsCount() { + _provider.CreateIndex("default"); + + var documents = Enumerable.Range(1, 1025).Select(i => _provider.New(i).Add("field", "value1")); + _provider.Store("default", documents); + + var searchBuilder = _provider.CreateSearchBuilder("default"); + + Assert.That(searchBuilder.Count(), Is.EqualTo(1025)); + Assert.That(searchBuilder.Get(1).ContentItemId, Is.EqualTo(1)); + Assert.That(searchBuilder.Get(1025).ContentItemId, Is.EqualTo(1025)); + + _provider.Delete("default", Enumerable.Range(1, 1025)); + + + Assert.That(searchBuilder.Count(), Is.EqualTo(0)); + } } } diff --git a/src/Orchard.Tests.Modules/Properties/AssemblyInfo.cs b/src/Orchard.Tests.Modules/Properties/AssemblyInfo.cs index 1ed9e5a14..569ed6ab3 100644 --- a/src/Orchard.Tests.Modules/Properties/AssemblyInfo.cs +++ b/src/Orchard.Tests.Modules/Properties/AssemblyInfo.cs @@ -30,5 +30,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Tests.Modules/Recipes/Services/RecipeManagerTests.cs b/src/Orchard.Tests.Modules/Recipes/Services/RecipeManagerTests.cs index c522aae81..7844dc917 100644 --- a/src/Orchard.Tests.Modules/Recipes/Services/RecipeManagerTests.cs +++ b/src/Orchard.Tests.Modules/Recipes/Services/RecipeManagerTests.cs @@ -110,23 +110,23 @@ namespace Orchard.Tests.Modules.Recipes.Services { [Test] public void HarvestRecipesFailsToFindRecipesWhenCalledWithNotExistingExtension() { - var recipes = (List)_recipeHarvester.HarvestRecipes("cantfindme"); + var recipes = _recipeHarvester.HarvestRecipes("cantfindme"); - Assert.That(recipes.Count, Is.EqualTo(0)); + Assert.That(recipes.Count(), Is.EqualTo(0)); } [Test] public void HarvestRecipesShouldHarvestRecipeXmlFiles() { - var recipes = (List)_recipeHarvester.HarvestRecipes("Sample1"); - Assert.That(recipes.Count, Is.EqualTo(1)); + var recipes = _recipeHarvester.HarvestRecipes("Sample1"); + Assert.That(recipes.Count(), Is.EqualTo(1)); } [Test] public void ParseRecipeLoadsRecipeMetaDataIntoModel() { - var recipes = (List)_recipeHarvester.HarvestRecipes("Sample1"); - Assert.That(recipes.Count, Is.EqualTo(1)); + var recipes = _recipeHarvester.HarvestRecipes("Sample1"); + Assert.That(recipes.Count(), Is.EqualTo(1)); - var sampleRecipe = recipes[0]; + var sampleRecipe = recipes.First(); Assert.That(sampleRecipe.Name, Is.EqualTo("cms")); Assert.That(sampleRecipe.Description, Is.EqualTo("a sample Orchard recipe describing a cms")); Assert.That(sampleRecipe.Author, Is.EqualTo("orchard")); diff --git a/src/Orchard.Tests/App.config b/src/Orchard.Tests/App.config index c8a59d19c..bbab85258 100644 --- a/src/Orchard.Tests/App.config +++ b/src/Orchard.Tests/App.config @@ -24,7 +24,7 @@ - + diff --git a/src/Orchard.Tests/Caching/CacheTests.cs b/src/Orchard.Tests/Caching/CacheTests.cs index 13af703fb..0201d3b26 100644 --- a/src/Orchard.Tests/Caching/CacheTests.cs +++ b/src/Orchard.Tests/Caching/CacheTests.cs @@ -1,4 +1,6 @@ using System; +using System.Linq; +using System.Threading; using Autofac; using NUnit.Framework; using Orchard.Caching; @@ -78,6 +80,42 @@ namespace Orchard.Tests.Caching { Is.Not.SameAs(c2.CacheManager.GetCache())); } + [Test] + public void CacheManagerIsNotBlocking() { + var hits = 0; + string result = ""; + + Enumerable.Range(0, 5).AsParallel().ForAll(x => + result = _cacheManager.Get("testItem", ctx => { + // by waiting for 100ms we expect all the calls to Get + // to enter this lambda + Thread.Sleep(100); + hits++; + return "testResult"; + }) + ); + + Assert.That(result, Is.EqualTo("testResult")); + Assert.That(hits, Is.GreaterThan(1)); + } + + [Test] + public void CacheManagerIsBlocking() { + var hits = 0; + string result = ""; + + Enumerable.Range(0, 5).AsParallel().ForAll(x => + result = _cacheManager.Get("testItem", true, ctx => { + Thread.Sleep(100); + hits++; + return "testResult"; + }) + ); + + Assert.That(result, Is.EqualTo("testResult")); + Assert.That(hits, Is.EqualTo(1)); + } + class ComponentOne { public ICacheManager CacheManager { get; set; } diff --git a/src/Orchard.Tests/DatabaseEnabledTestsBase.cs b/src/Orchard.Tests/DatabaseEnabledTestsBase.cs index e2f1fda3c..51e467618 100644 --- a/src/Orchard.Tests/DatabaseEnabledTestsBase.cs +++ b/src/Orchard.Tests/DatabaseEnabledTestsBase.cs @@ -24,7 +24,7 @@ namespace Orchard.Tests { protected string _databaseFilePath; protected ISessionFactory _sessionFactory; protected StubClock _clock; - + protected ShellSettings _shellSettings; [TestFixtureSetUp] public void InitFixture() { @@ -48,7 +48,7 @@ namespace Orchard.Tests { builder.RegisterInstance(new StubLocator(_session)).As(); builder.RegisterInstance(_clock).As(); builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)).InstancePerLifetimeScope(); - builder.RegisterInstance(new ShellSettings { Name = ShellSettings.DefaultName, DataProvider = "SqlCe" }); + builder.RegisterInstance(_shellSettings = new ShellSettings { Name = ShellSettings.DefaultName, DataProvider = "SqlCe" }); builder.RegisterType().As().InstancePerLifetimeScope(); builder.Register(context => _sessionFactory.OpenSession()).As().InstancePerLifetimeScope(); diff --git a/src/Orchard.Tests/DisplayManagement/DefaultDisplayManagerTests.cs b/src/Orchard.Tests/DisplayManagement/DefaultDisplayManagerTests.cs index 82fb2f86c..c3e32d490 100644 --- a/src/Orchard.Tests/DisplayManagement/DefaultDisplayManagerTests.cs +++ b/src/Orchard.Tests/DisplayManagement/DefaultDisplayManagerTests.cs @@ -97,10 +97,18 @@ namespace Orchard.Tests.DisplayManagement { throw new NotImplementedException(); } + public override object Resolve(Type serviceType) { + throw new NotImplementedException(); + } + public override bool TryResolve(out T service) { throw new NotImplementedException(); } + public override bool TryResolve(Type serviceType, out object service) { + throw new NotImplementedException(); + } + public override T GetState(string name) { object value; return _state.TryGetValue(name, out value) ? (T)value : default(T); diff --git a/src/Orchard.Tests/Environment/DefaultOrchardHostTests.cs b/src/Orchard.Tests/Environment/DefaultOrchardHostTests.cs index 24594d570..8cfc8fbc5 100644 --- a/src/Orchard.Tests/Environment/DefaultOrchardHostTests.cs +++ b/src/Orchard.Tests/Environment/DefaultOrchardHostTests.cs @@ -95,6 +95,10 @@ namespace Orchard.Tests.Environment { var ext = new ExtensionDescriptor { Id = "Orchard.Framework" }; ext.Features = new[] { new FeatureDescriptor { Extension = ext, Id = ext.Id } }; yield return ext; + + var settings = new ExtensionDescriptor { Id = "Settings" }; + settings.Features = new[] { new FeatureDescriptor { Extension = settings, Id = settings.Id } }; + yield return settings; } public IEnumerable AvailableFeatures() { @@ -177,6 +181,7 @@ namespace Orchard.Tests.Environment { Assert.That(again2a, Is.SameAs(dep2a)); Assert.That(again2b, Is.SameAs(dep2b)); } + [Test] public void SingletonDependenciesShouldBeUniquePerShell() { var host = _lifetime.Resolve(); @@ -200,6 +205,7 @@ namespace Orchard.Tests.Environment { Assert.That(dep2, Is.SameAs(dep2a)); Assert.That(dep2, Is.SameAs(dep2b)); } + [Test] public void TransientDependenciesShouldBeUniquePerResolve() { var host = _lifetime.Resolve(); diff --git a/src/Orchard.Tests/Environment/DefaultWorkContextAccessorTests.cs b/src/Orchard.Tests/Environment/DefaultWorkContextAccessorTests.cs index 47f72ecb6..27ab4873b 100644 --- a/src/Orchard.Tests/Environment/DefaultWorkContextAccessorTests.cs +++ b/src/Orchard.Tests/Environment/DefaultWorkContextAccessorTests.cs @@ -28,13 +28,6 @@ namespace Orchard.Tests.Environment { container.Mock() .Setup(x => x.Current()) .Returns(() => _httpContextCurrent); - - container.Mock() - .Setup(x => x.CreateContext(It.IsAny())) - .Returns(() => new StubHttpContext()); - - container.Mock() - .Setup(x => x.Started()); } [Test] diff --git a/src/Orchard.Tests/Environment/Extensions/ExtensionManagerTests.cs b/src/Orchard.Tests/Environment/Extensions/ExtensionManagerTests.cs index 75a1d8ece..22e96abf9 100644 --- a/src/Orchard.Tests/Environment/Extensions/ExtensionManagerTests.cs +++ b/src/Orchard.Tests/Environment/Extensions/ExtensionManagerTests.cs @@ -512,7 +512,7 @@ Features: Dependencies: Beta "); - moduleExtensionFolder.Manifests.Add("Classic", @" + themeExtensionFolder.Manifests.Add("Classic", @" Name: Classic Version: 1.0.3 OrchardVersion: 1 diff --git a/src/Orchard.Tests/Environment/ShellBuilders/CompositionStrategyTests.cs b/src/Orchard.Tests/Environment/ShellBuilders/CompositionStrategyTests.cs index bb6780415..f36b467ae 100644 --- a/src/Orchard.Tests/Environment/ShellBuilders/CompositionStrategyTests.cs +++ b/src/Orchard.Tests/Environment/ShellBuilders/CompositionStrategyTests.cs @@ -9,6 +9,7 @@ using Orchard.Environment.Descriptor.Models; using Orchard.Environment.Extensions; using Orchard.Environment.Extensions.Models; using Orchard.Environment.ShellBuilders; +using Orchard.Logging; using Orchard.Tests.Environment.TestDependencies; using Orchard.Utility.Extensions; @@ -17,16 +18,22 @@ namespace Orchard.Tests.Environment.ShellBuilders { public class CompositionStrategyTests : ContainerTestBase { private CompositionStrategy _compositionStrategy; private Mock _extensionManager; + private IEnumerable _availableExtensions; + private IEnumerable _installedFeatures; + private Mock _loggerMock; protected override void Register(ContainerBuilder builder) { - _extensionManager = new Mock(MockBehavior.Loose); + _extensionManager = new Mock(); + _loggerMock = new Mock(); builder.RegisterType().AsSelf(); builder.RegisterInstance(_extensionManager.Object); + builder.RegisterInstance(_loggerMock.Object); } protected override void Resolve(ILifetimeScope container) { _compositionStrategy = container.Resolve(); + _compositionStrategy.Logger = container.Resolve(); var alphaExtension = new ExtensionDescriptor { Id = "Alpha", @@ -54,7 +61,11 @@ namespace Orchard.Tests.Environment.ShellBuilders { betaFeatureDescriptor }; - var features = new List { + _availableExtensions = new[] { + alphaExtension + }; + + _installedFeatures = new List { new Feature { Descriptor = alphaFeatureDescriptor, ExportedTypes = new List { @@ -69,16 +80,16 @@ namespace Orchard.Tests.Environment.ShellBuilders { } }; - _extensionManager.Setup(x => x.AvailableExtensions()).Returns(new List { - alphaExtension - }); + _loggerMock.Setup(x => x.IsEnabled(It.IsAny())).Returns(true); - _extensionManager.Setup(x => x.AvailableFeatures()).Returns( + _extensionManager.Setup(x => x.AvailableExtensions()).Returns(() => _availableExtensions); + + _extensionManager.Setup(x => x.AvailableFeatures()).Returns(() => _extensionManager.Object.AvailableExtensions() .SelectMany(ext => ext.Features) .ToReadOnlyCollection()); - _extensionManager.Setup(x => x.LoadFeatures(It.IsAny>())).Returns(features); + _extensionManager.Setup(x => x.LoadFeatures(It.IsAny>())).Returns(() => _installedFeatures); } [Test] @@ -87,7 +98,7 @@ namespace Orchard.Tests.Environment.ShellBuilders { var shellDescriptor = CreateShellDescriptor("Alpha", "Beta"); var shellBlueprint = _compositionStrategy.Compose(shellSettings, shellDescriptor); - Assert.That(shellBlueprint.Dependencies.Count(x => x.Type == typeof (AlphaDependency)), Is.EqualTo(1)); + Assert.That(shellBlueprint.Dependencies.Count(x => x.Type == typeof(AlphaDependency)), Is.EqualTo(1)); Assert.That(shellBlueprint.Dependencies.Count(x => x.Type == typeof(BetaDependency)), Is.EqualTo(1)); } @@ -101,6 +112,34 @@ namespace Orchard.Tests.Environment.ShellBuilders { Assert.That(shellDescriptor.Features.Count(x => x.Name == "Alpha"), Is.EqualTo(1)); } + [Test] + public void ComposeDoesNotThrowWhenFeatureStateRecordDoesNotExist() { + var shellSettings = CreateShell(); + var shellDescriptor = CreateShellDescriptor("MyFeature"); + + Assert.DoesNotThrow(() => _compositionStrategy.Compose(shellSettings, shellDescriptor)); + _loggerMock.Verify(x => x.Log(LogLevel.Warning, null, It.IsAny(), It.IsAny())); + } + + [Test] + public void ComposeThrowsWhenAutoEnabledDependencyDoesNotExist() { + var myModule = _availableExtensions.First(); + + myModule.Features = myModule.Features.Concat(new[] { + new FeatureDescriptor { + Extension = myModule, + Name = "MyFeature", + Id = "MyFeature", + Dependencies = new[] { "NonExistingFeature" } + } + }); + + var shellSettings = CreateShell(); + var shellDescriptor = CreateShellDescriptor("MyFeature"); + + Assert.Throws(() => _compositionStrategy.Compose(shellSettings, shellDescriptor)); + } + private ShellSettings CreateShell() { return new ShellSettings(); } diff --git a/src/Orchard.Tests/Environment/ShellBuilders/DefaultShellContextFactoryTests.cs b/src/Orchard.Tests/Environment/ShellBuilders/DefaultShellContextFactoryTests.cs index 7f3b1784e..dc0b13a26 100644 --- a/src/Orchard.Tests/Environment/ShellBuilders/DefaultShellContextFactoryTests.cs +++ b/src/Orchard.Tests/Environment/ShellBuilders/DefaultShellContextFactoryTests.cs @@ -56,11 +56,7 @@ namespace Orchard.Tests.Environment.ShellBuilders { _container.Mock() .Setup(x => x.Current()) - .Returns(httpContext); - - _container.Mock() - .Setup(x => x.CreateContext(It.IsAny())) - .Returns(httpContext); + .Returns(default(HttpContextBase)); var factory = _container.Resolve(); diff --git a/src/Orchard.Tests/Environment/State/DefaultProcessingEngineTests.cs b/src/Orchard.Tests/Environment/State/DefaultProcessingEngineTests.cs index c788e4b21..fb50ba290 100644 --- a/src/Orchard.Tests/Environment/State/DefaultProcessingEngineTests.cs +++ b/src/Orchard.Tests/Environment/State/DefaultProcessingEngineTests.cs @@ -43,10 +43,6 @@ namespace Orchard.Tests.Environment.State { _container.Mock() .Setup(x=>x.Current()) .Returns(httpContext); - _container.Mock() - .Setup(x => x.CreateContext(It.IsAny())) - .Returns(httpContext); - } [TearDown] diff --git a/src/Orchard.Tests/Localization/DateTimePartsTests.cs b/src/Orchard.Tests/Localization/DateTimePartsTests.cs index 4532b0448..6a3ee09e4 100644 --- a/src/Orchard.Tests/Localization/DateTimePartsTests.cs +++ b/src/Orchard.Tests/Localization/DateTimePartsTests.cs @@ -4,7 +4,7 @@ using Orchard.Localization.Models; namespace Orchard.Tests.Localization { - [TestFixture] + [TestFixture()] public class DateTimePartsTests { [Test] diff --git a/src/Orchard.Tests/Localization/DefaultDateFormatterTests.cs b/src/Orchard.Tests/Localization/DefaultDateFormatterTests.cs index 8a4226c84..a2135f09c 100644 --- a/src/Orchard.Tests/Localization/DefaultDateFormatterTests.cs +++ b/src/Orchard.Tests/Localization/DefaultDateFormatterTests.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Concurrent; -using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; @@ -13,7 +12,8 @@ using Orchard.Localization.Services; namespace Orchard.Tests.Localization { - [TestFixture] + [TestFixture()] + [Category("longrunning")] public class DefaultDateFormatterTests { [SetUp] diff --git a/src/Orchard.Tests/Localization/TestHelpers.cs b/src/Orchard.Tests/Localization/TestHelpers.cs index d9d268762..34cebb5fd 100644 --- a/src/Orchard.Tests/Localization/TestHelpers.cs +++ b/src/Orchard.Tests/Localization/TestHelpers.cs @@ -42,10 +42,18 @@ namespace Orchard.Tests.Localization { throw new NotImplementedException(); } + public override object Resolve(Type serviceType) { + throw new NotImplementedException(); + } + public override bool TryResolve(out T service) { throw new NotImplementedException(); } + public override bool TryResolve(Type serviceType, out object service) { + throw new NotImplementedException(); + } + public override T GetState(string name) { if (name == "CurrentCulture") return (T)((object)CultureName); if (name == "CurrentCalendar") return (T)((object)CalendarName); diff --git a/src/Orchard.Tests/Orchard.Framework.Tests.csproj b/src/Orchard.Tests/Orchard.Framework.Tests.csproj index 5dd02f1f0..924481c65 100644 --- a/src/Orchard.Tests/Orchard.Framework.Tests.csproj +++ b/src/Orchard.Tests/Orchard.Framework.Tests.csproj @@ -272,8 +272,7 @@ - - + @@ -295,7 +294,7 @@ - + diff --git a/src/Orchard.Tests/Properties/AssemblyInfo.cs b/src/Orchard.Tests/Properties/AssemblyInfo.cs index 41f87fe43..c3bb0f4b3 100644 --- a/src/Orchard.Tests/Properties/AssemblyInfo.cs +++ b/src/Orchard.Tests/Properties/AssemblyInfo.cs @@ -33,5 +33,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Tests/Stubs/StubMachineNameProvider.cs b/src/Orchard.Tests/Stubs/StubApplicationEnvironment.cs similarity index 56% rename from src/Orchard.Tests/Stubs/StubMachineNameProvider.cs rename to src/Orchard.Tests/Stubs/StubApplicationEnvironment.cs index c453ac6f7..2849ef6af 100644 --- a/src/Orchard.Tests/Stubs/StubMachineNameProvider.cs +++ b/src/Orchard.Tests/Stubs/StubApplicationEnvironment.cs @@ -1,12 +1,12 @@ using Orchard.Environment; namespace Orchard.Tests.Stubs { - public class StubMachineNameProvider : IMachineNameProvider { - public StubMachineNameProvider() { + public class StubApplicationEnvironment : IApplicationEnvironment { + public StubApplicationEnvironment() { MachineName = "Orchard Machine"; } public string MachineName { get; set; } - public string GetMachineName() { + public string GetEnvironmentIdentifier() { return MachineName; } } diff --git a/src/Orchard.Tests/Stubs/StubHttpContextAccessor.cs b/src/Orchard.Tests/Stubs/StubHttpContextAccessor.cs index b0368b6a7..892707b2f 100644 --- a/src/Orchard.Tests/Stubs/StubHttpContextAccessor.cs +++ b/src/Orchard.Tests/Stubs/StubHttpContextAccessor.cs @@ -1,5 +1,4 @@ using System.Web; -using Autofac; using Orchard.Mvc; namespace Orchard.Tests.Stubs { @@ -17,10 +16,6 @@ namespace Orchard.Tests.Stubs { return _httpContext; } - public HttpContextBase CreateContext(ILifetimeScope lifetimeScope) { - return _httpContext; - } - public void Set(HttpContextBase httpContext) { _httpContext = httpContext; } diff --git a/src/Orchard.Tests/Stubs/StubThreadProvider.cs b/src/Orchard.Tests/Stubs/StubThreadProvider.cs deleted file mode 100644 index 73d6ebcaf..000000000 --- a/src/Orchard.Tests/Stubs/StubThreadProvider.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Orchard.Environment; - -namespace Orchard.Tests.Stubs { - public class StubThreadProvider : IThreadProvider { - public StubThreadProvider() { - ManagedThreadId = 1; - } - - public int ManagedThreadId { get; set; } - - public int GetCurrentThreadId() { - return ManagedThreadId; - } - } -} diff --git a/src/Orchard.Tests/Stubs/StubWorkContextAccessor.cs b/src/Orchard.Tests/Stubs/StubWorkContextAccessor.cs index b5fcdeeb6..76bbc5e22 100644 --- a/src/Orchard.Tests/Stubs/StubWorkContextAccessor.cs +++ b/src/Orchard.Tests/Stubs/StubWorkContextAccessor.cs @@ -13,7 +13,7 @@ namespace Orchard.Tests.Stubs { public StubWorkContextAccessor(ILifetimeScope lifetimeScope) { _lifetimeScope = lifetimeScope; - _workContext = new WorkContextImpl(_lifetimeScope); + _workContext = new WorkContextImpl(lifetimeScope); } public class WorkContextImpl : WorkContext { @@ -123,10 +123,18 @@ namespace Orchard.Tests.Stubs { return _lifetimeScope.Resolve(); } + public override object Resolve(Type serviceType) { + return _lifetimeScope.Resolve(serviceType); + } + public override bool TryResolve(out T service) { return _lifetimeScope.TryResolve(out service); } + public override bool TryResolve(Type serviceType, out object service) { + return _lifetimeScope.TryResolve(serviceType, out service); + } + public override T GetState(string name) { return (T) _contextDictonary[name]; } @@ -149,7 +157,9 @@ namespace Orchard.Tests.Stubs { } public IWorkContextScope CreateWorkContextScope() { - throw new NotSupportedException(); + var workLifetime = _lifetimeScope.BeginLifetimeScope("work"); + var workContext = new WorkContextImpl(workLifetime); + return new StubWorkContextScope(workContext, workLifetime); } } } diff --git a/src/Orchard.Tests/Stubs/StubWorkContextScope.cs b/src/Orchard.Tests/Stubs/StubWorkContextScope.cs new file mode 100644 index 000000000..a63c75957 --- /dev/null +++ b/src/Orchard.Tests/Stubs/StubWorkContextScope.cs @@ -0,0 +1,26 @@ +using Autofac; + +namespace Orchard.Tests.Stubs { + public class StubWorkContextScope : IWorkContextScope { + private readonly ILifetimeScope _lifetimeScope; + + public StubWorkContextScope(WorkContext workContext, ILifetimeScope lifetimeScope) { + _lifetimeScope = lifetimeScope; + WorkContext = workContext; + } + + public WorkContext WorkContext { get; private set; } + + public void Dispose() { + _lifetimeScope.Dispose(); + } + + public TService Resolve() { + return WorkContext.Resolve(); + } + + public bool TryResolve(out TService service) { + return WorkContext.TryResolve(out service); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Tests/Tasks/DistributedLockServiceTests.cs b/src/Orchard.Tests/Tasks/DistributedLockServiceTests.cs index 5b0074c27..a0664bd60 100644 --- a/src/Orchard.Tests/Tasks/DistributedLockServiceTests.cs +++ b/src/Orchard.Tests/Tasks/DistributedLockServiceTests.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Autofac; using NUnit.Framework; using Orchard.Data; using Orchard.Environment; +using Orchard.Environment.Configuration; using Orchard.Services; using Orchard.Tasks.Locking.Records; using Orchard.Tasks.Locking.Services; @@ -15,11 +17,9 @@ namespace Orchard.Tests.Tasks { public class DistributedLockServiceTests : DatabaseEnabledTestsBase { private const string LockName = "Orchard Test Lock"; private DistributedLockService _distributedLockService; - private StubMachineNameProvider _machineNameProvider; - private StubThreadProvider _threadProvider; + private StubApplicationEnvironment _applicationEnvironment; private IRepository _distributedLockRepository; private ITransactionManager _transactionManager; - protected override IEnumerable DatabaseTypes { get { yield return typeof(DistributedLockRecord); } @@ -27,83 +27,71 @@ namespace Orchard.Tests.Tasks { public override void Register(ContainerBuilder builder) { builder.RegisterType().As(); - builder.RegisterType().As().SingleInstance(); - builder.RegisterType().As().SingleInstance(); + builder.RegisterType().As().SingleInstance(); builder.RegisterType().AsSelf(); } public override void Init() { base.Init(); _distributedLockService = _container.Resolve(); - _machineNameProvider = (StubMachineNameProvider)_container.Resolve(); - _threadProvider = (StubThreadProvider)_container.Resolve(); + _applicationEnvironment = (StubApplicationEnvironment)_container.Resolve(); _distributedLockRepository = _container.Resolve>(); _transactionManager = _container.Resolve(); } - [Test] - public void TryAcquiringLockSucceeds() { - DistributedLock @lock; - var lockAcquired = _distributedLockService.TryAcquireLockForMachine(LockName, TimeSpan.FromSeconds(60), null, out @lock); - - Assert.That(lockAcquired, Is.True); - } - [Test] public void TryAcquiringLockTwiceOnSameMachineSucceeds() { - DistributedLock @lock; - var attempt1 = _distributedLockService.TryAcquireLockForMachine(LockName, TimeSpan.FromSeconds(60), null, out @lock); - var attempt2 = _distributedLockService.TryAcquireLockForMachine(LockName, TimeSpan.FromSeconds(60), null, out @lock); + IDistributedLock @lock; + var attempt1 = _distributedLockService.TryAcquireLock(LockName, TimeSpan.FromSeconds(60), out @lock); + var attempt2 = _distributedLockService.TryAcquireLock(LockName, TimeSpan.FromSeconds(60), out @lock); Assert.That(attempt1, Is.True); Assert.That(attempt2, Is.True); } - [Test] - public void TryAcquiringLockTwiceOnSameMachineIncreasesLockCountTwice() { - DistributedLock @lock; - _distributedLockService.TryAcquireLockForMachine(LockName, TimeSpan.FromSeconds(60), null, out @lock); - _distributedLockService.TryAcquireLockForMachine(LockName, TimeSpan.FromSeconds(60), null, out @lock); - var lockId = Int32.Parse(@lock.Id); - var lockRecord = _distributedLockRepository.Get(lockId); - Assert.That(lockRecord.Count, Is.EqualTo(2)); + [Test] + public void AcquiringTheLockOnTheSameMachineReturnsTheSameLock() { + IDistributedLock lock1, lock2; + _distributedLockService.TryAcquireLock(LockName, TimeSpan.FromSeconds(60), out lock1); + _distributedLockService.TryAcquireLock(LockName, TimeSpan.FromSeconds(60), out lock2); + + Assert.AreEqual(lock1, lock2); } [Test] - public void ReleasingLockDecreasesLockCount() { - DistributedLock @lock; - _distributedLockService.TryAcquireLockForMachine(LockName, TimeSpan.FromSeconds(60), null, out @lock); - _distributedLockService.TryAcquireLockForMachine(LockName, TimeSpan.FromSeconds(60), null, out @lock); + public void ReleasingSingleLockDeletesRecord() { + IDistributedLock lock1; + _distributedLockService.TryAcquireLock(LockName, TimeSpan.FromSeconds(60), out lock1); - var lockId = Int32.Parse(@lock.Id); - var lockRecord = _distributedLockRepository.Get(lockId); - - _distributedLockService.ReleaseLock(@lock); - _session.Refresh(lockRecord); - Assert.That(lockRecord.Count, Is.EqualTo(1)); - } - - [Test] - public void ReleasingLockAndCountReachesZeroDeletesLock() - { - DistributedLock @lock; - _distributedLockService.TryAcquireLockForMachine(LockName, TimeSpan.FromSeconds(60), null, out @lock); - - var lockId = Int32.Parse(@lock.Id); - _distributedLockService.ReleaseLock(@lock); - var lockRecord = _distributedLockRepository.Get(lockId); + lock1.Dispose(); + var lockRecord = _distributedLockRepository.Table.FirstOrDefault(); Assert.That(lockRecord, Is.Null); } + [Test] + public void ReleasingFirstLockDoesntDeleteRecord() { + IDistributedLock lock1, lock2; + _distributedLockService.TryAcquireLock(LockName, TimeSpan.FromSeconds(60), out lock1); + _distributedLockService.TryAcquireLock(LockName, TimeSpan.FromSeconds(60), out lock2); + + lock1.Dispose(); + var lockRecord = _distributedLockRepository.Table.FirstOrDefault(); + Assert.That(lockRecord, Is.Not.Null); + + lock2.Dispose(); + lockRecord = _distributedLockRepository.Table.FirstOrDefault(); + Assert.That(lockRecord, Is.Null); + } + [Test] public void TryAcquiringLockTwiceFails() { - DistributedLock @lock; - _machineNameProvider.MachineName = "Orchard Test Machine 1"; - var attempt1 = _distributedLockService.TryAcquireLockForMachine(LockName, TimeSpan.FromSeconds(60), null, out @lock); - _machineNameProvider.MachineName = "Orchard Test Machine 2"; - var attempt2 = _distributedLockService.TryAcquireLockForMachine(LockName, TimeSpan.FromSeconds(60), null, out @lock); + IDistributedLock @lock; + _applicationEnvironment.MachineName = "Orchard Test Machine 1"; + var attempt1 = _distributedLockService.TryAcquireLock(LockName, TimeSpan.FromSeconds(60), out @lock); + _applicationEnvironment.MachineName = "Orchard Test Machine 2"; + var attempt2 = _distributedLockService.TryAcquireLock(LockName, TimeSpan.FromSeconds(60), out @lock); Assert.That(attempt1, Is.True); Assert.That(attempt2, Is.False); @@ -111,66 +99,88 @@ namespace Orchard.Tests.Tasks { [Test] public void TryAcquiringNonExpiredActiveLockFails() { - DistributedLock @lock; - CreateNonExpiredActiveLock("Other Machine", threadId: null); - var success = _distributedLockService.TryAcquireLockForMachine(LockName, TimeSpan.FromHours(1), null, out @lock); + IDistributedLock @lock; + CreateNonExpiredActiveLock("Other Machine"); + var success = _distributedLockService.TryAcquireLock(LockName, TimeSpan.FromHours(1), out @lock); Assert.That(success, Is.False); } [Test] - public void TryAcquiringNonExpiredButInactiveLockSucceeds() { - DistributedLock @lock; - CreateNonExpiredButInactiveLock("Other Machine", threadId: null); - var success = _distributedLockService.TryAcquireLockForMachine(LockName, TimeSpan.FromHours(1), null, out @lock); + public void TryAcquiringNonExpiredButInactiveLockFromOtherMachineFails() { + IDistributedLock @lock; + CreateNonExpiredActiveLock("Other Machine"); + var success = _distributedLockService.TryAcquireLock(LockName, TimeSpan.FromHours(1), out @lock); + + Assert.That(success, Is.False); + } + + [Test] + public void TryAcquiringNonExpiredButInactiveLockFromSameMachineSucceeds() { + IDistributedLock @lock; + CreateNonExpiredActiveLock("Orchard Machine"); + var success = _distributedLockService.TryAcquireLock(LockName, TimeSpan.FromHours(1), out @lock); Assert.That(success, Is.True); } [Test] public void TryAcquiringExpiredButActiveLockSucceeds() { - DistributedLock @lock; - CreateExpiredButActiveLock("Other Machine", threadId: null); - var success = _distributedLockService.TryAcquireLockForMachine(LockName, TimeSpan.FromHours(1), null, out @lock); + IDistributedLock @lock; + CreateExpiredButActiveLock("Other Machine"); + var success = _distributedLockService.TryAcquireLock(LockName, TimeSpan.FromHours(1), out @lock); Assert.That(success, Is.True); } [Test] public void TryAcquiringNonExpiredAndActiveLockFromCurrentOwnerSucceeds() { - DistributedLock @lock; - CreateNonExpiredActiveLock(GetMachineName(), threadId: null); - var success = _distributedLockService.TryAcquireLockForMachine(LockName, TimeSpan.FromHours(1), null, out @lock); + IDistributedLock @lock; + CreateNonExpiredActiveLock(GetMachineName()); + var success = _distributedLockService.TryAcquireLock(LockName, TimeSpan.FromHours(1), out @lock); Assert.That(success, Is.True); } [Test] public void AcquiringNonExpiredAndActiveLockFromDifferentOwnerThrowsTimeoutException() { - CreateNonExpiredActiveLock("Other Machine", threadId: null); - Assert.Throws(() => _distributedLockService.AcquireLockForMachine(LockName, TimeSpan.FromHours(1), TimeSpan.Zero)); + CreateNonExpiredActiveLock("Other Machine"); + Assert.Throws(() => _distributedLockService.AcquireLock(LockName, TimeSpan.FromHours(1), TimeSpan.Zero)); } [Test] public void MultipleAcquisitionsFromDifferentMachinesShouldFail() { - DistributedLock @lock; - _machineNameProvider.MachineName = "Orchard Test Machine 1"; - var attempt1 = _distributedLockService.TryAcquireLockForMachine(LockName, TimeSpan.FromSeconds(60), null, out @lock); - _machineNameProvider.MachineName = "Orchard Test Machine 2"; - var attempt2 = _distributedLockService.TryAcquireLockForMachine(LockName, TimeSpan.FromSeconds(60), null, out @lock); + IDistributedLock @lock; + _applicationEnvironment.MachineName = "Orchard Test Machine 1"; + var attempt1 = _distributedLockService.TryAcquireLock(LockName, TimeSpan.FromMinutes(60), out @lock); + _applicationEnvironment.MachineName = "Orchard Test Machine 2"; + var attempt2 = _distributedLockService.TryAcquireLock(LockName, TimeSpan.FromMinutes(60), out @lock); Assert.That(attempt1, Is.True); Assert.That(attempt2, Is.False); } + [Test] + public void MultipleAcquisitionsFromDifferentMachinesOnDifferentTenantShouldSucceed() { + IDistributedLock @lock; + _applicationEnvironment.MachineName = "Orchard Test Machine 1"; + var attempt1 = _distributedLockService.TryAcquireLock(LockName, TimeSpan.FromSeconds(60), out @lock); + _applicationEnvironment.MachineName = "Orchard Test Machine 2"; + _shellSettings.Name = "Foo"; + var attempt2 = _distributedLockService.TryAcquireLock(LockName, TimeSpan.FromSeconds(60), out @lock); + + Assert.That(attempt1, Is.True); + Assert.That(attempt2, Is.True); + } + [Test] public void MultithreadedAcquisitionsShouldNotCauseTransactionErrors() { var tasks = new List(); for (var i = 0; i < 10; i++) { var task = Task.Factory.StartNew(() => { - DistributedLock @lock; - Assert.DoesNotThrow(() => _distributedLockService.TryAcquireLockForMachine(LockName, TimeSpan.FromHours(1), null, out @lock)); + IDistributedLock @lock; + Assert.DoesNotThrow(() => _distributedLockService.TryAcquireLock(LockName, TimeSpan.FromHours(1), out @lock)); }); tasks.Add(task); @@ -179,61 +189,53 @@ namespace Orchard.Tests.Tasks { Task.WaitAll(tasks.ToArray()); } - [Test] - public void MixedScopeAcquisitionsShouldThrow() { - DistributedLock @lock; - Assert.DoesNotThrow(() => _distributedLockService.TryAcquireLockForMachine(LockName, TimeSpan.FromSeconds(60), null, out @lock)); - Assert.Throws(() => _distributedLockService.TryAcquireLockForThread(LockName, TimeSpan.FromSeconds(60), null, out @lock)); - } - [Test] public void TryAcquireActiveLockWithNullTimeoutReturnsFalseImmediately() { - CreateNonExpiredActiveLock("Other Machine", null); + CreateNonExpiredActiveLock("Other Machine"); - DistributedLock @lock; - var acquired = _distributedLockService.TryAcquireLockForThread(LockName, TimeSpan.FromMinutes(1), null, out @lock); + IDistributedLock @lock; + var acquired = _distributedLockService.TryAcquireLock(LockName, TimeSpan.FromMinutes(1), out @lock); Assert.That(acquired, Is.False); } [Test] public void ActiveLockWithUndefinedValidUntilNeverExpires() { - CreateNonExpiredActiveLockThatNeverExpires("Other Machine", null); + CreateNonExpiredActiveLockThatNeverExpires("Other Machine"); + _clock.Advance(DateTime.MaxValue - _clock.UtcNow); // Fast forward to the End of Time. - DistributedLock @lock; - var acquired = _distributedLockService.TryAcquireLockForThread(LockName, TimeSpan.FromMinutes(1), null, out @lock); + IDistributedLock @lock; + var acquired = _distributedLockService.TryAcquireLock(LockName, TimeSpan.FromMinutes(1), out @lock); Assert.That(acquired, Is.False); } [Test] public void ActiveLockWithUndefinedValidUntilNeverExpiresUntilReleased() { - DistributedLock @lock; + IDistributedLock @lock; // Create a never expiring lock. - _machineNameProvider.MachineName = "Orchard Test Machine 1"; - var attempt1 = _distributedLockService.TryAcquireLockForThread(LockName, maxValidFor: null, timeout: null, @lock: out @lock); - + _applicationEnvironment.MachineName = "Orchard Test Machine 1"; + var attempt1 = _distributedLockService.TryAcquireLock(LockName, maxValidFor: null, timeout: null, dLock: out @lock); + // Release the lock. - _distributedLockService.ReleaseLock(@lock); + @lock.Dispose(); // Acquire the lock from another machine. - _machineNameProvider.MachineName = "Orchard Test Machine 2"; - var attempt2 = _distributedLockService.TryAcquireLockForThread(LockName, maxValidFor: null, timeout: null, @lock: out @lock); + _applicationEnvironment.MachineName = "Orchard Test Machine 2"; + var attempt2 = _distributedLockService.TryAcquireLock(LockName, maxValidFor: null, timeout: null, dLock: out @lock); // Validate the results. Assert.That(attempt1, Is.True); Assert.That(attempt2, Is.True); } - private DistributedLockRecord CreateLockRecord(int count, DateTime createdUtc, DateTime? validUntilUtc, string machineName, int? threadId) { + private DistributedLockRecord CreateLockRecord(DateTime createdUtc, DateTime? validUntilUtc, string machineName) { var record = new DistributedLockRecord { - Name = LockName, - Count = count, + Name = String.Format("DistributedLock:{0}:{1}", ShellSettings.DefaultName, LockName), CreatedUtc = createdUtc, ValidUntilUtc = validUntilUtc, MachineName = machineName, - ThreadId = threadId }; _distributedLockRepository.Create(record); @@ -241,32 +243,23 @@ namespace Orchard.Tests.Tasks { return record; } - private DistributedLockRecord CreateNonExpiredActiveLock(string machineName, int? threadId) { + private DistributedLockRecord CreateNonExpiredActiveLock(string machineName) { var now = _clock.UtcNow; - return CreateLockRecord(1, now, now + TimeSpan.FromHours(1), machineName, threadId); + return CreateLockRecord(now, now + TimeSpan.FromHours(1), machineName); } - private DistributedLockRecord CreateNonExpiredButInactiveLock(string machineName, int? threadId) { + private DistributedLockRecord CreateExpiredButActiveLock(string machineName) { var now = _clock.UtcNow; - return CreateLockRecord(0, now, now + TimeSpan.FromHours(1), machineName, threadId); + return CreateLockRecord(now, now - TimeSpan.FromHours(1), machineName); } - private DistributedLockRecord CreateExpiredButActiveLock(string machineName, int? threadId) { + private DistributedLockRecord CreateNonExpiredActiveLockThatNeverExpires(string machineName) { var now = _clock.UtcNow; - return CreateLockRecord(1, now, now - TimeSpan.FromHours(1), machineName, threadId); - } - - private DistributedLockRecord CreateNonExpiredActiveLockThatNeverExpires(string machineName, int? threadId) { - var now = _clock.UtcNow; - return CreateLockRecord(1, now, null, machineName, threadId); + return CreateLockRecord(now, null, machineName); } private string GetMachineName() { - return _machineNameProvider.GetMachineName(); - } - - private int GetThreadId() { - return _threadProvider.GetCurrentThreadId(); + return _applicationEnvironment.GetEnvironmentIdentifier(); } } } diff --git a/src/Orchard.Tests/Tasks/LockTests.cs b/src/Orchard.Tests/Tasks/LockTests.cs deleted file mode 100644 index d94218428..000000000 --- a/src/Orchard.Tests/Tasks/LockTests.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Autofac; -using Moq; -using NUnit.Framework; -using Orchard.Tasks.Locking.Services; - -namespace Orchard.Tests.Tasks { - [TestFixture] - public class LockTests : ContainerTestBase { - private const string LockName = "Orchard Test Lock"; - private const string LockId = "1"; - private Mock _distributedLockServiceMock; - private DistributedLock _lock; - - protected override void Register(ContainerBuilder builder) { - _distributedLockServiceMock = new Mock(); - builder.RegisterInstance(_distributedLockServiceMock.Object); - } - - protected override void Resolve(ILifetimeScope container) { - _lock = DistributedLock.ForMachine(_distributedLockServiceMock.Object, LockName, "Orchard Test Machine", LockId); - } - - [Test] - public void DisposeInvokesDistributedLockServiceDisposeLock() { - _lock.Dispose(); - - _distributedLockServiceMock.Verify(service => service.ReleaseLock(_lock), Times.Exactly(1)); - } - - [Test] - public void DisposingMultipleTimesInvokesDistributedLockServiceDisposeLockOnce() { - _lock.Dispose(); - _lock.Dispose(); - _lock.Dispose(); - - _distributedLockServiceMock.Verify(service => service.ReleaseLock(_lock), Times.Exactly(1)); - } - } -} \ No newline at end of file diff --git a/src/Orchard.Tests/Tasks/SweepGeneratorTests.cs b/src/Orchard.Tests/Tasks/SweepGeneratorTests.cs index e851df66c..8e468800a 100644 --- a/src/Orchard.Tests/Tasks/SweepGeneratorTests.cs +++ b/src/Orchard.Tests/Tasks/SweepGeneratorTests.cs @@ -23,10 +23,6 @@ namespace Orchard.Tests.Tasks { .Setup(x => x.Current()) .Returns(() => null); - container.Mock() - .Setup(x => x.CreateContext(It.IsAny())) - .Returns(() => new StubHttpContext()); - container.Mock() .Setup(x => x.Started()); } diff --git a/src/Orchard.Tests/Time/TimeZoneSelectorTests.cs b/src/Orchard.Tests/Time/TimeZoneSelectorTests.cs index b0cee916b..18b089be0 100644 --- a/src/Orchard.Tests/Time/TimeZoneSelectorTests.cs +++ b/src/Orchard.Tests/Time/TimeZoneSelectorTests.cs @@ -69,10 +69,18 @@ namespace Orchard.Tests.Time { throw new NotImplementedException(); } + public override object Resolve(Type serviceType) { + throw new NotImplementedException(); + } + public override bool TryResolve(out T service) { throw new NotImplementedException(); } + public override bool TryResolve(Type serviceType, out object service) { + throw new NotImplementedException(); + } + public override T GetState(string name) { return default(T); } diff --git a/src/Orchard.WarmupStarter/Properties/AssemblyInfo.cs b/src/Orchard.WarmupStarter/Properties/AssemblyInfo.cs index 4f4ee0785..3bf0779c8 100644 --- a/src/Orchard.WarmupStarter/Properties/AssemblyInfo.cs +++ b/src/Orchard.WarmupStarter/Properties/AssemblyInfo.cs @@ -32,8 +32,8 @@ using System.Security; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] // Enable web application to call this assembly in Full Trust [assembly: AllowPartiallyTrustedCallers] diff --git a/src/Orchard.WarmupStarter/Starter.cs b/src/Orchard.WarmupStarter/Starter.cs index ffa1f0763..b0b328da4 100644 --- a/src/Orchard.WarmupStarter/Starter.cs +++ b/src/Orchard.WarmupStarter/Starter.cs @@ -89,9 +89,9 @@ namespace Orchard.WarmupStarter { var result = _initialization(application); _initializationResult = result; } - catch (Exception e) { + catch (Exception ex) { lock (_synLock) { - _error = e; + _error = ex; _previousError = null; } } diff --git a/src/Orchard.Web.Tests/Properties/AssemblyInfo.cs b/src/Orchard.Web.Tests/Properties/AssemblyInfo.cs index 788066b9f..0338f1a5b 100644 --- a/src/Orchard.Web.Tests/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web.Tests/Properties/AssemblyInfo.cs @@ -33,5 +33,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Config/Host.config b/src/Orchard.Web/Config/Host.config index 9e6b2d119..94eefe177 100644 --- a/src/Orchard.Web/Config/Host.config +++ b/src/Orchard.Web/Config/Host.config @@ -8,7 +8,7 @@ - + diff --git a/src/Orchard.Web/Config/HostComponents.config b/src/Orchard.Web/Config/HostComponents.config index dd1a321d6..f91398632 100644 --- a/src/Orchard.Web/Config/HostComponents.config +++ b/src/Orchard.Web/Config/HostComponents.config @@ -106,5 +106,19 @@ + + + + + + + + + + + + + + diff --git a/src/Orchard.Web/Config/Sites.config b/src/Orchard.Web/Config/Sites.config index b64e22c3f..852db503e 100644 --- a/src/Orchard.Web/Config/Sites.config +++ b/src/Orchard.Web/Config/Sites.config @@ -8,7 +8,7 @@ /,o=/(^[\s]+|[\s]+$)/g,a=[];t=t.split(r),n=t.length;for(var s=0;n>s;s++){var u=t[s];if(u.length>0&&"WEBVTT"!==u&&u.match(i)){var l=u.split(i),d=t[s+1];a.push({start:e(l[0].replace(o,"")),end:e(l[1].replace(o,"")),data:d})}}return Q.when(a)}}},MediaPlayer.rules.BaseRulesCollection=function(){ +"use strict";var e=[];return{downloadRatioRule:void 0,insufficientBufferRule:void 0,getRules:function(){return Q.when(e)},setup:function(){var e=this;e.getRules().then(function(t){t.push(e.downloadRatioRule),t.push(e.insufficientBufferRule)})}}},MediaPlayer.rules.BaseRulesCollection.prototype={constructor:MediaPlayer.rules.BaseRulesCollection},MediaPlayer.rules.DownloadRatioRule=function(){"use strict";var e=function(e,t,n){var r=this,i=Q.defer();return r.manifestExt.getRepresentationFor(e,n).then(function(e){r.manifestExt.getBandwidth(e).then(function(e){i.resolve(e/t)})}),i.promise};return{debug:void 0,manifestExt:void 0,checkIndex:function(t,n,r){var i,o,a,s,u,l,d,c,f,g,h=this,p=n.HttpList,m=.75;return h.debug.log("Checking download ratio rule..."),n?null===p||void 0===p||0===p.length?(h.debug.log("No requests made for this stream yet, bailing."),Q.when(new MediaPlayer.rules.SwitchRequest)):(i=p[p.length-1],a=(i.tfinish.getTime()-i.trequest.getTime())/1e3,o=(i.tfinish.getTime()-i.tresponse.getTime())/1e3,0>=a?(h.debug.log("Don't know how long the download of the last fragment took, bailing."),Q.when(new MediaPlayer.rules.SwitchRequest)):null===i.mediaduration||void 0===i.mediaduration||i.mediaduration<=0?(h.debug.log("Don't know the duration of the last media fragment, bailing."),Q.when(new MediaPlayer.rules.SwitchRequest)):(d=Q.defer(),u=i.mediaduration/a,s=i.mediaduration/o*m,isNaN(s)||isNaN(u)?(h.debug.log("Total time: "+a+"s"),h.debug.log("Download time: "+o+"s"),h.debug.log("The ratios are NaN, bailing."),Q.when(new MediaPlayer.rules.SwitchRequest)):(h.debug.log("Total ratio: "+u),h.debug.log("Download ratio: "+s),h.debug.log("Download ratio: "+s),isNaN(s)?(h.debug.log("Invalid ratio, bailing."),d.resolve(new MediaPlayer.rules.SwitchRequest)):1>s?(h.debug.log("Download ratio is poor."),t>0?(h.debug.log("We are not at the lowest bitrate, so switch down."),h.manifestExt.getRepresentationFor(t-1,r).then(function(e){h.manifestExt.getBandwidth(e).then(function(e){h.manifestExt.getRepresentationFor(t,r).then(function(n){h.manifestExt.getBandwidth(n).then(function(n){l=e/n,h.debug.log("Switch ratio: "+l),l>s?(h.debug.log("Things must be going pretty bad, switch all the way down."),d.resolve(new MediaPlayer.rules.SwitchRequest(0))):(h.debug.log("Things could be better, so just switch down one index."),d.resolve(new MediaPlayer.rules.SwitchRequest(t-1)))})})})})):(h.debug.log("We are at the lowest bitrate and cannot switch down, use current."),d.resolve(new MediaPlayer.rules.SwitchRequest(t)))):(h.debug.log("Download ratio is good."),h.manifestExt.getRepresentationCount(r).then(function(n){n-=1,n>t?(h.debug.log("We are not at the highest bitrate, so switch up."),h.manifestExt.getRepresentationFor(t+1,r).then(function(i){h.manifestExt.getBandwidth(i).then(function(i){h.manifestExt.getRepresentationFor(t,r).then(function(o){h.manifestExt.getBandwidth(o).then(function(o){if(l=i/o,h.debug.log("Switch ratio: "+l),s>=l)if(s>1e3)h.debug.log("Tons of bandwidth available, go all the way up."),d.resolve(new MediaPlayer.rules.SwitchRequest(n-1));else if(s>100)h.debug.log("Just enough bandwidth available, switch up one."),d.resolve(new MediaPlayer.rules.SwitchRequest(t+1));else{for(h.debug.log("Not exactly sure where to go, so do some math."),f=-1,c=[];(f+=1)f&&!(st&&(u=MediaPlayer.rules.SwitchRequest.prototype.STRONG,a.debug.log("Apply STRONG to buffer rule.")),s?(a.debug.log("The buffer ran dry recently, switch down."),Q.when(new MediaPlayer.rules.SwitchRequest(n-1,u))):e>t?(a.debug.log("Too many dry buffer hits, quit switching bitrates."),Q.when(new MediaPlayer.rules.SwitchRequest(n,u))):Q.when(new MediaPlayer.rules.SwitchRequest(MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE,u)))))}}},MediaPlayer.rules.InsufficientBufferRule.prototype={constructor:MediaPlayer.rules.InsufficientBufferRule},MediaPlayer.rules.LimitSwitchesRule=function(){"use strict";var e=10,t=2e4,n=5,r=0;return{debug:void 0,checkIndex:function(i,o){if(r>0)return r-=1,Q.when(new MediaPlayer.rules.SwitchRequest(i,MediaPlayer.rules.SwitchRequest.prototype.STRONG));var a,s,u,l=this,d=!1,c=(new Date).getTime(),f=o.RepSwitchList.length;for(l.debug.log("Checking limit switches rule..."),u=f-1;u>=0;u-=1){if(a=o.RepSwitchList[u],s=c-a.t.getTime(),s>=t){l.debug.log("Reached time limit, bailing.");break}if(u>=e){l.debug.log("Found too many switches within validation time, force the stream to not change."),d=!0;break}}return d?(l.debug.log("Wait some time before allowing another switch."),r=n,Q.when(new MediaPlayer.rules.SwitchRequest(i,MediaPlayer.rules.SwitchRequest.prototype.STRONG))):Q.when(new MediaPlayer.rules.SwitchRequest(MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE,MediaPlayer.rules.SwitchRequest.prototype.STRONG))}}},MediaPlayer.rules.LimitSwitchesRule.prototype={constructor:MediaPlayer.rules.LimitSwitchesRule},MediaPlayer.rules.SwitchRequest=function(e,t){"use strict";this.quality=e,this.priority=t,void 0===this.quality&&(this.quality=999),void 0===this.priority&&(this.priority=.5)},MediaPlayer.rules.SwitchRequest.prototype={constructor:MediaPlayer.rules.SwitchRequest,NO_CHANGE:999,DEFAULT:.5,STRONG:1,WEAK:0},MediaPlayer.models.MetricsList=function(){"use strict";return{TcpList:[],HttpList:[],RepSwitchList:[],BufferLevel:[],PlayList:[],DroppedFrames:[]}},MediaPlayer.models.MetricsList.prototype={constructor:MediaPlayer.models.MetricsList},MediaPlayer.vo.SegmentRequest=function(){"use strict";this.action="download",this.startTime=0/0,this.streamType=null,this.type=null,this.duration=0/0,this.timescale=0/0,this.range=null,this.url=null,this.requestStartDate=null,this.firstByteDate=null,this.requestEndDate=null,this.deferred=null,this.quality=0/0,this.index=0/0},MediaPlayer.vo.SegmentRequest.prototype={constructor:MediaPlayer.vo.SegmentRequest,ACTION_DOWNLOAD:"download",ACTION_COMPLETE:"complete"},MediaPlayer.vo.metrics.BufferLevel=function(){"use strict";this.t=null,this.level=null},MediaPlayer.vo.metrics.BufferLevel.prototype={constructor:MediaPlayer.vo.metrics.BufferLevel},MediaPlayer.vo.metrics.DroppedFrames=function(){"use strict";this.time=null,this.droppedFrames=null},MediaPlayer.vo.metrics.DroppedFrames.prototype={constructor:MediaPlayer.vo.metrics.DroppedFrames},MediaPlayer.vo.metrics.HTTPRequest=function(){"use strict";this.tcpid=null,this.type=null,this.url=null,this.actualurl=null,this.range=null,this.trequest=null,this.tresponse=null,this.tfinish=null,this.responsecode=null,this.interval=null,this.mediaduration=null,this.trace=[]},MediaPlayer.vo.metrics.HTTPRequest.prototype={constructor:MediaPlayer.vo.metrics.HTTPRequest},MediaPlayer.vo.metrics.HTTPRequest.Trace=function(){"use strict";this.s=null,this.d=null,this.b=[]},MediaPlayer.vo.metrics.HTTPRequest.Trace.prototype={constructor:MediaPlayer.vo.metrics.HTTPRequest.Trace},MediaPlayer.vo.metrics.PlayList=function(){"use strict";this.start=null,this.mstart=null,this.starttype=null,this.trace=[]},MediaPlayer.vo.metrics.PlayList.Trace=function(){"use strict";this.representationid=null,this.subreplevel=null,this.start=null,this.mstart=null,this.duration=null,this.playbackspeed=null,this.stopreason=null},MediaPlayer.vo.metrics.PlayList.prototype={constructor:MediaPlayer.vo.metrics.PlayList},MediaPlayer.vo.metrics.PlayList.INITIAL_PLAY_START_REASON="initial_start",MediaPlayer.vo.metrics.PlayList.SEEK_START_REASON="seek",MediaPlayer.vo.metrics.PlayList.Trace.prototype={constructor:MediaPlayer.vo.metrics.PlayList.Trace()},MediaPlayer.vo.metrics.PlayList.Trace.USER_REQUEST_STOP_REASON="user_request",MediaPlayer.vo.metrics.PlayList.Trace.REPRESENTATION_SWITCH_STOP_REASON="representation_switch",MediaPlayer.vo.metrics.PlayList.Trace.END_OF_CONTENT_STOP_REASON="end_of_content",MediaPlayer.vo.metrics.PlayList.Trace.REBUFFERING_REASON="rebuffering",MediaPlayer.vo.metrics.RepresentationSwitch=function(){"use strict";this.t=null,this.mt=null,this.to=null,this.lto=null},MediaPlayer.vo.metrics.RepresentationSwitch.prototype={constructor:MediaPlayer.vo.metrics.RepresentationSwitch},MediaPlayer.vo.metrics.TCPConnection=function(){"use strict";this.tcpid=null,this.dest=null,this.topen=null,this.tclose=null,this.tconnect=null},MediaPlayer.vo.metrics.TCPConnection.prototype={constructor:MediaPlayer.vo.metrics.TCPConnection}; \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Services/Jobs/JobProcessor.cs b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Services/Jobs/JobProcessor.cs index 4a066e68a..4fd8487fe 100644 --- a/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Services/Jobs/JobProcessor.cs +++ b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Services/Jobs/JobProcessor.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading; using Microsoft.WindowsAzure.MediaServices.Client; using Orchard.Azure.MediaServices.Helpers; using Orchard.Azure.MediaServices.Models; @@ -18,8 +17,6 @@ using Orchard.Tasks.Locking.Services; namespace Orchard.Azure.MediaServices.Services.Jobs { public class JobProcessor : Component, IBackgroundTask { - private static readonly object _sweepLock = new object(); - private readonly IWamsClient _wamsClient; private readonly IAssetManager _assetManager; private readonly IJobManager _jobManager; @@ -41,126 +38,125 @@ namespace Orchard.Azure.MediaServices.Services.Jobs { } public void Sweep() { - if (Monitor.TryEnter(_sweepLock)) { - try { - Logger.Debug("Beginning sweep."); + Logger.Debug("Beginning sweep."); - if (!_orchardServices.WorkContext.CurrentSite.As().IsValid()) { - Logger.Debug("Settings are invalid; going back to sleep."); - return; - } + try { + if (!_orchardServices.WorkContext.CurrentSite.As().IsValid()) { + Logger.Debug("Settings are invalid; going back to sleep."); + return; + } - // Only allow this task to run on one farm node at a time. - DistributedLock @lock; - if (_distributedLockService.TryAcquireLockForMachine(GetType().FullName, TimeSpan.FromHours(1), out @lock)) { - using (@lock) { - var jobs = _jobManager.GetActiveJobs().ToDictionary(job => job.WamsJobId); + // Only allow this task to run on one farm node at a time. + IDistributedLock @lock; + if (_distributedLockService.TryAcquireLock(GetType().FullName, TimeSpan.FromHours(1), out @lock)) { + using (@lock) { + var jobs = _jobManager.GetActiveJobs().ToDictionary(job => job.WamsJobId); - if (!jobs.Any()) { - Logger.Debug("No open jobs were found; going back to sleep."); - return; + if (!jobs.Any()) { + Logger.Debug("No open jobs were found; going back to sleep."); + return; + } + + Logger.Information("Beginning processing of {0} open jobs.", jobs.Count()); + + var wamsJobs = _wamsClient.GetJobsById(jobs.Keys); + + foreach (var wamsJob in wamsJobs) { + Logger.Information("Processing job '{0}'...", wamsJob.Name); + + var job = jobs[wamsJob.Id]; + var tasks = job.Tasks.ToDictionary(task => task.WamsTaskId); + var wamsTasks = wamsJob.Tasks.ToArray(); + + foreach (var wamsTask in wamsTasks) { + var task = tasks[wamsTask.Id]; + task.Status = MapWamsJobState(wamsTask.State); + task.PercentComplete = (int)wamsTask.Progress; } - Logger.Information("Beginning processing of {0} open jobs.", jobs.Count()); + var previousStatus = job.Status; + var wamsJobErrors = HarvestWamsJobErrors(wamsJob).ToArray(); - var wamsJobs = _wamsClient.GetJobsById(jobs.Keys); + job.CreatedUtc = wamsJob.Created; + job.StartedUtc = wamsJob.StartTime; + job.FinishedUtc = wamsJob.EndTime; + job.Status = MapWamsJobState(wamsJob.State); + job.ErrorMessage = GetAggregateErrorMessage(wamsJobErrors); - foreach (var wamsJob in wamsJobs) { - Logger.Information("Processing job '{0}'...", wamsJob.Name); + LogWamsJobErrors(wamsJobErrors); - var job = jobs[wamsJob.Id]; - var tasks = job.Tasks.ToDictionary(task => task.WamsTaskId); - var wamsTasks = wamsJob.Tasks.ToArray(); + if (job.Status != previousStatus) { + if (job.Status == JobStatus.Finished) { + Logger.Information("Job '{0}' was finished in WAMS; creating locators.", wamsJob.Name); - foreach (var wamsTask in wamsTasks) { - var task = tasks[wamsTask.Id]; - task.Status = MapWamsJobState(wamsTask.State); - task.PercentComplete = (int)wamsTask.Progress; - } + var lastTask = job.Tasks.Last(); + var lastWamsTask = wamsTasks.Single(task => task.Id == lastTask.WamsTaskId); + var outputAsset = lastWamsTask.OutputAssets.First(); + var outputAssetName = !String.IsNullOrWhiteSpace(job.OutputAssetName) ? job.OutputAssetName : lastWamsTask.Name; + var outputAssetDescription = job.OutputAssetDescription.TrimSafe(); + var encoderMetadataXml = _wamsClient.GetEncoderMetadataXml(outputAsset).Result; + var cloudVideoPart = job.CloudVideoPart; + var wamsLocators = _wamsClient.CreateLocatorsAsync(outputAsset, WamsLocatorCategory.Private).Result; - var previousStatus = job.Status; - var wamsJobErrors = HarvestWamsJobErrors(wamsJob).ToArray(); + // HACK: Temporary workaround to disable dynamic packaging for VC1-based assets. In future versions + // this will be implemented more robustly by testing all the dynamic URLs to see which ones work + // and only store and use the working ones. + var forceNonDynamicAsset = lastWamsTask.Configuration.StartsWith("VC1"); - job.CreatedUtc = wamsJob.Created; - job.StartedUtc = wamsJob.StartTime; - job.FinishedUtc = wamsJob.EndTime; - job.Status = MapWamsJobState(wamsJob.State); - job.ErrorMessage = GetAggregateErrorMessage(wamsJobErrors); + if (wamsLocators.OnDemandLocator != null && !forceNonDynamicAsset) { + _assetManager.CreateAssetFor(cloudVideoPart, asset => { + asset.IncludeInPlayer = true; + asset.Name = outputAssetName; + asset.Description = outputAssetDescription; + asset.EncodingPreset = lastTask.HarvestAssetName; + asset.WamsPrivateLocatorId = wamsLocators.SasLocator.Id; + asset.WamsPrivateLocatorUrl = wamsLocators.SasLocator.Url; + asset.WamsPrivateOnDemandLocatorId = wamsLocators.OnDemandLocator.Id; + asset.WamsPrivateOnDemandLocatorUrl = wamsLocators.OnDemandLocator.Url; + asset.WamsManifestFilename = wamsLocators.OnDemandManifestFilename; + asset.WamsAssetId = outputAsset.Id; + asset.WamsEncoderMetadataXml = encoderMetadataXml; + asset.UploadState.Status = AssetUploadStatus.Uploaded; + asset.PublishState.Status = AssetPublishStatus.None; + }); + } + else { + _assetManager.CreateAssetFor(cloudVideoPart, asset => { + asset.IncludeInPlayer = true; + asset.Name = outputAssetName; + asset.Description = outputAssetDescription; + asset.EncodingPreset = lastTask.HarvestAssetName; + asset.WamsPrivateLocatorId = wamsLocators.SasLocator.Id; + asset.WamsPrivateLocatorUrl = wamsLocators.SasLocator.Url; + asset.WamsAssetId = outputAsset.Id; + asset.WamsEncoderMetadataXml = encoderMetadataXml; + asset.UploadState.Status = AssetUploadStatus.Uploaded; + asset.PublishState.Status = AssetPublishStatus.None; + }); + } - LogWamsJobErrors(wamsJobErrors); - - if (job.Status != previousStatus) { - if (job.Status == JobStatus.Finished) { - Logger.Information("Job '{0}' was finished in WAMS; creating locators.", wamsJob.Name); - - var lastTask = job.Tasks.Last(); - var lastWamsTask = wamsTasks.Single(task => task.Id == lastTask.WamsTaskId); - var outputAsset = lastWamsTask.OutputAssets.First(); - var outputAssetName = !String.IsNullOrWhiteSpace(job.OutputAssetName) ? job.OutputAssetName : lastWamsTask.Name; - var outputAssetDescription = job.OutputAssetDescription.TrimSafe(); - var encoderMetadataXml = _wamsClient.GetEncoderMetadataXml(outputAsset).Result; - var cloudVideoPart = job.CloudVideoPart; - var wamsLocators = _wamsClient.CreateLocatorsAsync(outputAsset, WamsLocatorCategory.Private).Result; - - // HACK: Temporary workaround to disable dynamic packaging for VC1-based assets. In future versions - // this will be implemented more robustly by testing all the dynamic URLs to see which ones work - // and only store and use the working ones. - var forceNonDynamicAsset = lastWamsTask.Configuration.StartsWith("VC1"); - - if (wamsLocators.OnDemandLocator != null && !forceNonDynamicAsset) { - _assetManager.CreateAssetFor(cloudVideoPart, asset => { - asset.IncludeInPlayer = true; - asset.Name = outputAssetName; - asset.Description = outputAssetDescription; - asset.EncodingPreset = lastTask.HarvestAssetName; - asset.WamsPrivateLocatorId = wamsLocators.SasLocator.Id; - asset.WamsPrivateLocatorUrl = wamsLocators.SasLocator.Url; - asset.WamsPrivateOnDemandLocatorId = wamsLocators.OnDemandLocator.Id; - asset.WamsPrivateOnDemandLocatorUrl = wamsLocators.OnDemandLocator.Url; - asset.WamsManifestFilename = wamsLocators.OnDemandManifestFilename; - asset.WamsAssetId = outputAsset.Id; - asset.WamsEncoderMetadataXml = encoderMetadataXml; - asset.UploadState.Status = AssetUploadStatus.Uploaded; - asset.PublishState.Status = AssetPublishStatus.None; - }); - } - else { - _assetManager.CreateAssetFor(cloudVideoPart, asset => { - asset.IncludeInPlayer = true; - asset.Name = outputAssetName; - asset.Description = outputAssetDescription; - asset.EncodingPreset = lastTask.HarvestAssetName; - asset.WamsPrivateLocatorId = wamsLocators.SasLocator.Id; - asset.WamsPrivateLocatorUrl = wamsLocators.SasLocator.Url; - asset.WamsAssetId = outputAsset.Id; - asset.WamsEncoderMetadataXml = encoderMetadataXml; - asset.UploadState.Status = AssetUploadStatus.Uploaded; - asset.PublishState.Status = AssetPublishStatus.None; - }); - } - - try { - if (cloudVideoPart.IsPublished()) - _assetManager.PublishAssetsFor(cloudVideoPart); - } - catch (Exception ex) { - Logger.Warning(ex, "Processing of job '{0}' was completed but an error occurred while publishing the cloud video item with ID {1} after processing.", wamsJob.Name, cloudVideoPart.Id); - } + try { + if (cloudVideoPart.IsPublished()) + _assetManager.PublishAssetsFor(cloudVideoPart); + } + catch (Exception ex) { + Logger.Warning(ex, "Processing of job '{0}' was completed but an error occurred while publishing the cloud video item with ID {1} after processing.", wamsJob.Name, cloudVideoPart.Id); } } - - Logger.Information("Processing of job '{0}' was successfully completed.", wamsJob.Name); } + + Logger.Information("Processing of job '{0}' was successfully completed.", wamsJob.Name); } } } - catch (Exception ex) { - Logger.Error(ex, "Error during sweep."); - } - finally { - Monitor.Exit(_sweepLock); - Logger.Debug("Ending sweep."); - } + else + Logger.Debug("Distributed lock could not be acquired; going back to sleep."); + } + catch (Exception ex) { + Logger.Error(ex, "Error during sweep."); + } + finally { + Logger.Debug("Ending sweep."); } } diff --git a/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Web.config b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Web.config index f585f8311..c3a205ab2 100644 --- a/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Web.config +++ b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Web.config @@ -45,7 +45,7 @@ - + @@ -57,15 +57,15 @@ - + - + - + diff --git a/src/Orchard.Web/Modules/Orchard.Azure/Module.txt b/src/Orchard.Web/Modules/Orchard.Azure/Module.txt index 9c8eb1aac..c8016dd21 100644 --- a/src/Orchard.Web/Modules/Orchard.Azure/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Azure/Module.txt @@ -2,7 +2,7 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: Provides a set of Orchard service implementations targeting Microsoft Azure services. Category: Hosting diff --git a/src/Orchard.Web/Modules/Orchard.Azure/Orchard.Azure.csproj b/src/Orchard.Web/Modules/Orchard.Azure/Orchard.Azure.csproj index 8587c2796..12d87b822 100644 --- a/src/Orchard.Web/Modules/Orchard.Azure/Orchard.Azure.csproj +++ b/src/Orchard.Web/Modules/Orchard.Azure/Orchard.Azure.csproj @@ -107,7 +107,7 @@ - + diff --git a/src/Orchard.Web/Modules/Orchard.Azure/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Azure/Properties/AssemblyInfo.cs index 5edcbfb73..39c27bbae 100644 --- a/src/Orchard.Web/Modules/Orchard.Azure/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Azure/Properties/AssemblyInfo.cs @@ -31,6 +31,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.Azure/Services/Environment/AzureApplicationEnvironment.cs b/src/Orchard.Web/Modules/Orchard.Azure/Services/Environment/AzureApplicationEnvironment.cs new file mode 100644 index 000000000..0b6c5bc0d --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Azure/Services/Environment/AzureApplicationEnvironment.cs @@ -0,0 +1,10 @@ +using Microsoft.WindowsAzure.ServiceRuntime; +using Orchard.Environment; + +namespace Orchard.Azure.Services.Environment { + public class AzureApplicationEnvironment : IApplicationEnvironment { + public string GetEnvironmentIdentifier() { + return RoleEnvironment.CurrentRoleInstance.Id; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Azure/Services/Environment/Configuration/AzureBlobShellSettingsManager.cs b/src/Orchard.Web/Modules/Orchard.Azure/Services/Environment/Configuration/AzureBlobShellSettingsManager.cs index 2e1ad499f..6e11a98d9 100644 --- a/src/Orchard.Web/Modules/Orchard.Azure/Services/Environment/Configuration/AzureBlobShellSettingsManager.cs +++ b/src/Orchard.Web/Modules/Orchard.Azure/Services/Environment/Configuration/AzureBlobShellSettingsManager.cs @@ -2,11 +2,11 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using Microsoft.Azure; using Orchard.Azure.Services.FileSystems; using Orchard.Environment.Configuration; using Orchard.FileSystems.Media; using Orchard.Logging; +using Microsoft.Azure; namespace Orchard.Azure.Services.Environment.Configuration { diff --git a/src/Orchard.Web/Modules/Orchard.Azure/Services/Environment/Configuration/DefaultPlatformConfigurationAccessor.cs b/src/Orchard.Web/Modules/Orchard.Azure/Services/Environment/Configuration/DefaultPlatformConfigurationAccessor.cs index ba596ce66..71639b174 100644 --- a/src/Orchard.Web/Modules/Orchard.Azure/Services/Environment/Configuration/DefaultPlatformConfigurationAccessor.cs +++ b/src/Orchard.Web/Modules/Orchard.Azure/Services/Environment/Configuration/DefaultPlatformConfigurationAccessor.cs @@ -1,6 +1,6 @@ -using Microsoft.Azure; -using System.Configuration; +using System.Configuration; using System; +using Microsoft.Azure; namespace Orchard.Azure.Services.Environment.Configuration { diff --git a/src/Orchard.Web/Modules/Orchard.Azure/Services/TaskLease/AzureMachineNameProvider.cs b/src/Orchard.Web/Modules/Orchard.Azure/Services/TaskLease/AzureMachineNameProvider.cs deleted file mode 100644 index 52a6dd2ab..000000000 --- a/src/Orchard.Web/Modules/Orchard.Azure/Services/TaskLease/AzureMachineNameProvider.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.WindowsAzure.ServiceRuntime; -using Orchard.Environment; - -namespace Orchard.Azure.Services.TaskLease { - public class AzureMachineNameProvider : IMachineNameProvider { - public string GetMachineName() { - return RoleEnvironment.CurrentRoleInstance.Id; - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Azure/Web.config b/src/Orchard.Web/Modules/Orchard.Azure/Web.config index 15d8508e3..254f46733 100644 --- a/src/Orchard.Web/Modules/Orchard.Azure/Web.config +++ b/src/Orchard.Web/Modules/Orchard.Azure/Web.config @@ -41,7 +41,7 @@ - + @@ -53,15 +53,15 @@ - + - + - + diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Drivers/BlogArchivesPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Drivers/BlogArchivesPartDriver.cs index 640c11181..f2783f000 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Drivers/BlogArchivesPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Drivers/BlogArchivesPartDriver.cs @@ -53,10 +53,14 @@ namespace Orchard.Blogs.Drivers { } protected override void Importing(BlogArchivesPart part, ImportContentContext context) { - var blog = context.Attribute(part.PartDefinition.Name, "Blog"); - if (blog != null) { - part.BlogId = context.GetItemFromSession(blog).Id; + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; } + + context.ImportAttribute(part.PartDefinition.Name, "Blog", blog => + part.BlogId = context.GetItemFromSession(blog).Id + ); } protected override void Exporting(BlogArchivesPart part, ExportContentContext context) { diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Drivers/BlogPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Drivers/BlogPartDriver.cs index db0030450..2fdc29313 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Drivers/BlogPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Drivers/BlogPartDriver.cs @@ -43,20 +43,22 @@ namespace Orchard.Blogs.Drivers { } protected override void Importing(BlogPart part, ContentManagement.Handlers.ImportContentContext context) { - var description = context.Attribute(part.PartDefinition.Name, "Description"); - if (description != null) { - part.Description = description; + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; } - var postCount = context.Attribute(part.PartDefinition.Name, "PostCount"); - if (postCount != null) { - part.PostCount = Convert.ToInt32(postCount); - } + context.ImportAttribute(part.PartDefinition.Name, "Description", description => + part.Description = description + ); - var feedProxyUrl = context.Attribute(part.PartDefinition.Name, "FeedProxyUrl"); - if (feedProxyUrl != null) { - part.FeedProxyUrl = feedProxyUrl; - } + context.ImportAttribute(part.PartDefinition.Name, "PostCount", postCount => + part.PostCount = Convert.ToInt32(postCount) + ); + + context.ImportAttribute(part.PartDefinition.Name, "FeedProxyUrl", feedProxyUrl => + part.FeedProxyUrl = feedProxyUrl + ); } protected override void Exporting(BlogPart part, ContentManagement.Handlers.ExportContentContext context) { diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Drivers/RecentBlogPostsPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Drivers/RecentBlogPostsPartDriver.cs index 8ab1b9268..e44f6fce6 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Drivers/RecentBlogPostsPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Drivers/RecentBlogPostsPartDriver.cs @@ -66,22 +66,25 @@ namespace Orchard.Blogs.Drivers { } protected override void Importing(RecentBlogPostsPart part, ImportContentContext context) { - var blog = context.Attribute(part.PartDefinition.Name, "Blog"); - if (blog != null) { - part.BlogId = context.GetItemFromSession(blog).Id; + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; } - var count = context.Attribute(part.PartDefinition.Name, "Count"); - if (count != null) { - part.Count = Convert.ToInt32(count); - } + context.ImportAttribute(part.PartDefinition.Name, "Blog", blog => + part.BlogId = context.GetItemFromSession(blog).Id + ); + + context.ImportAttribute(part.PartDefinition.Name, "Count", count => + part.Count = Convert.ToInt32(count) + ); } protected override void Exporting(RecentBlogPostsPart part, ExportContentContext context) { var blog = _contentManager.Get(part.BlogId); var blogIdentity = _contentManager.GetItemMetadata(blog).Identity; - context.Element(part.PartDefinition.Name).SetAttributeValue("Blog", blogIdentity); + context.Element(part.PartDefinition.Name).SetAttributeValue("Blog", blogIdentity); context.Element(part.PartDefinition.Name).SetAttributeValue("Count", part.Count); } } diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Module.txt b/src/Orchard.Web/Modules/Orchard.Blogs/Module.txt index 37df5063f..c5d8c1e48 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Module.txt @@ -2,7 +2,7 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: The Orchard Blogs module is implementing basic blogging features. FeatureDescription: A simple web log. diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Properties/AssemblyInfo.cs index 51684d725..669976e1b 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Properties/AssemblyInfo.cs @@ -29,6 +29,6 @@ using System.Runtime.InteropServices; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.Caching/Module.txt b/src/Orchard.Web/Modules/Orchard.Caching/Module.txt index d047dcf80..dd1e26e2b 100644 --- a/src/Orchard.Web/Modules/Orchard.Caching/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Caching/Module.txt @@ -2,7 +2,7 @@ AntiForgery: enabled Author: Sébastien Ros Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: Provides an API to cache business data. Features: diff --git a/src/Orchard.Web/Modules/Orchard.Caching/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Caching/Properties/AssemblyInfo.cs index be2a0894d..94e0fe6a8 100644 --- a/src/Orchard.Web/Modules/Orchard.Caching/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Caching/Properties/AssemblyInfo.cs @@ -31,6 +31,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.CodeGeneration/Module.txt b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Module.txt index 53f661672..b268ada56 100644 --- a/src/Orchard.Web/Modules/Orchard.CodeGeneration/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Module.txt @@ -2,7 +2,7 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: Tools to create Orchard components. FeatureDescription: Tools to create Orchard components. diff --git a/src/Orchard.Web/Modules/Orchard.CodeGeneration/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Properties/AssemblyInfo.cs index a21dc27e2..285c3afa6 100644 --- a/src/Orchard.Web/Modules/Orchard.CodeGeneration/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Drivers/CommentPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Comments/Drivers/CommentPartDriver.cs index a2488a61f..b27c3ced1 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Drivers/CommentPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Comments/Drivers/CommentPartDriver.cs @@ -117,7 +117,7 @@ namespace Orchard.Comments.Drivers { // prevent users from commenting on a closed thread by hijacking the commentedOn property var commentsPart = commentedOn.As(); - if (!commentsPart.CommentsActive) { + if (commentsPart == null || !commentsPart.CommentsActive) { _orchardServices.TransactionManager.Cancel(); return Editor(part, shapeHelper); } @@ -132,71 +132,65 @@ namespace Orchard.Comments.Drivers { } protected override void Importing(CommentPart part, ContentManagement.Handlers.ImportContentContext context) { - var author = context.Attribute(part.PartDefinition.Name, "Author"); - if (author != null) { - part.Record.Author = author; + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; } - var siteName = context.Attribute(part.PartDefinition.Name, "SiteName"); - if (siteName != null) { - part.Record.SiteName = siteName; - } + context.ImportAttribute(part.PartDefinition.Name, "Author", author => + part.Record.Author = author + ); - var userName = context.Attribute(part.PartDefinition.Name, "UserName"); - if (userName != null) { - part.Record.UserName = userName; - } + context.ImportAttribute(part.PartDefinition.Name, "SiteName", siteName => + part.Record.SiteName = siteName + ); - var email = context.Attribute(part.PartDefinition.Name, "Email"); - if (email != null) { - part.Record.Email = email; - } + context.ImportAttribute(part.PartDefinition.Name, "UserName", userName => + part.Record.UserName = userName + ); - var position = context.Attribute(part.PartDefinition.Name, "Position"); - if (position != null) { - part.Record.Position = decimal.Parse(position, CultureInfo.InvariantCulture); - } + context.ImportAttribute(part.PartDefinition.Name, "Email", email => + part.Record.Email = email + ); - var status = context.Attribute(part.PartDefinition.Name, "Status"); - if (status != null) { - part.Record.Status = (CommentStatus)Enum.Parse(typeof(CommentStatus), status); - } + context.ImportAttribute(part.PartDefinition.Name, "Position", position => + part.Record.Position = decimal.Parse(position, CultureInfo.InvariantCulture) + ); - var commentDate = context.Attribute(part.PartDefinition.Name, "CommentDateUtc"); - if (commentDate != null) { - part.Record.CommentDateUtc = XmlConvert.ToDateTime(commentDate, XmlDateTimeSerializationMode.Utc); - } + context.ImportAttribute(part.PartDefinition.Name, "Status", status => + part.Record.Status = (CommentStatus)Enum.Parse(typeof(CommentStatus), status) + ); - var text = context.Attribute(part.PartDefinition.Name, "CommentText"); - if (text != null) { - part.Record.CommentText = text; - } + context.ImportAttribute(part.PartDefinition.Name, "CommentDateUtc", commentDate => + part.Record.CommentDateUtc = XmlConvert.ToDateTime(commentDate, XmlDateTimeSerializationMode.Utc) + ); - var commentedOn = context.Attribute(part.PartDefinition.Name, "CommentedOn"); - if (commentedOn != null) { + context.ImportAttribute(part.PartDefinition.Name, "CommentText", text => + part.Record.CommentText = text + ); + + context.ImportAttribute(part.PartDefinition.Name, "CommentedOn", commentedOn => { var contentItem = context.GetItemFromSession(commentedOn); if (contentItem != null) { part.Record.CommentedOn = contentItem.Id; } contentItem.As().Record.CommentPartRecords.Add(part.Record); - } + }); - var repliedOn = context.Attribute(part.PartDefinition.Name, "RepliedOn"); - if (repliedOn != null) { + context.ImportAttribute(part.PartDefinition.Name, "RepliedOn", repliedOn => { var contentItem = context.GetItemFromSession(repliedOn); if (contentItem != null) { part.Record.RepliedOn = contentItem.Id; } - } + }); - var commentedOnContainer = context.Attribute(part.PartDefinition.Name, "CommentedOnContainer"); - if (commentedOnContainer != null) { + context.ImportAttribute(part.PartDefinition.Name, "CommentedOnContainer", commentedOnContainer => { var container = context.GetItemFromSession(commentedOnContainer); if (container != null) { part.Record.CommentedOnContainer = container.Id; } - } + }); } protected override void Exporting(CommentPart part, ContentManagement.Handlers.ExportContentContext context) { diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Drivers/CommentsPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Comments/Drivers/CommentsPartDriver.cs index 97966f3f9..d7175898a 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Drivers/CommentsPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Comments/Drivers/CommentsPartDriver.cs @@ -111,20 +111,22 @@ namespace Orchard.Comments.Drivers { } protected override void Importing(CommentsPart part, ContentManagement.Handlers.ImportContentContext context) { - var commentsShown = context.Attribute(part.PartDefinition.Name, "CommentsShown"); - if (commentsShown != null) { - part.CommentsShown = Convert.ToBoolean(commentsShown); + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; } - var commentsActive = context.Attribute(part.PartDefinition.Name, "CommentsActive"); - if (commentsActive != null) { - part.CommentsActive = Convert.ToBoolean(commentsActive); - } + context.ImportAttribute(part.PartDefinition.Name, "CommentsShown", commentsShown => + part.CommentsShown = Convert.ToBoolean(commentsShown) + ); - var threadedComments = context.Attribute(part.PartDefinition.Name, "ThreadedComments"); - if (threadedComments != null) { - part.ThreadedComments = Convert.ToBoolean(threadedComments); - } + context.ImportAttribute(part.PartDefinition.Name, "CommentsActive", commentsActive => + part.CommentsActive = Convert.ToBoolean(commentsActive) + ); + + context.ImportAttribute(part.PartDefinition.Name, "ThreadedComments", threadedComments => + part.ThreadedComments = Convert.ToBoolean(threadedComments) + ); } protected override void Exporting(CommentsPart part, ContentManagement.Handlers.ExportContentContext context) { diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Module.txt b/src/Orchard.Web/Modules/Orchard.Comments/Module.txt index db08b140b..d474d622a 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Comments/Module.txt @@ -2,7 +2,7 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: The comments system implemented by this module can be applied to arbitrary Orchard content types, such as blogs and pages. It includes comment validation and spam protection through the Akismet service. Features: diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Comments/Properties/AssemblyInfo.cs index decf91004..d7cd0582f 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Comments/Properties/AssemblyInfo.cs @@ -30,5 +30,5 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Services/CommentService.cs b/src/Orchard.Web/Modules/Orchard.Comments/Services/CommentService.cs index 816f2720a..18d288fa1 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Services/CommentService.cs +++ b/src/Orchard.Web/Modules/Orchard.Comments/Services/CommentService.cs @@ -118,7 +118,8 @@ namespace Orchard.Comments.Services { } public void DeleteComment(int commentId) { - _orchardServices.ContentManager.Remove(_orchardServices.ContentManager.Get(commentId).ContentItem); + // Get latest because the comment may be unpublished if the anti-spam module has caught it + _orchardServices.ContentManager.Remove(_orchardServices.ContentManager.Get(commentId, VersionOptions.Latest).ContentItem); } public bool CommentsDisabledForCommentedContent(int id) { diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Drivers/ContentPermissionsPartDriver.cs b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Drivers/ContentPermissionsPartDriver.cs index 444d72ac3..22e6f9998 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Drivers/ContentPermissionsPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Drivers/ContentPermissionsPartDriver.cs @@ -162,6 +162,11 @@ namespace Orchard.ContentPermissions.Drivers { } protected override void Importing(ContentPermissionsPart part, ImportContentContext context) { + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; + } + context.ImportAttribute(part.PartDefinition.Name, "Enabled", s => part.Enabled = XmlConvert.ToBoolean(s)); context.ImportAttribute(part.PartDefinition.Name, "ViewContent", s => part.ViewContent = s); context.ImportAttribute(part.PartDefinition.Name, "EditContent", s => part.EditContent = s); diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Module.txt b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Module.txt index 7d895333c..ae22aa617 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Module.txt @@ -2,7 +2,7 @@ Name: Orchard.ContentPermissions AntiForgery: enabled Author: Chris Pyle, Sbastien Ros Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: Allows item-level front end view permissions. Features: diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Properties/AssemblyInfo.cs index 41952f985..9d53413a9 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.ContentPicker/Drivers/ContentMenuItemPartDriver.cs b/src/Orchard.Web/Modules/Orchard.ContentPicker/Drivers/ContentMenuItemPartDriver.cs index 4a6808484..ee75f144a 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentPicker/Drivers/ContentMenuItemPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentPicker/Drivers/ContentMenuItemPartDriver.cs @@ -60,14 +60,18 @@ namespace Orchard.ContentPicker.Drivers { } protected override void Importing(ContentMenuItemPart part, ImportContentContext context) { - var contentItemId = context.Attribute(part.PartDefinition.Name, "ContentItem"); - if (contentItemId != null) { - var contentItem = context.GetItemFromSession(contentItemId); - part.Content = contentItem; - } - else { - part.Content = null; + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; } + + context.ImportAttribute(part.PartDefinition.Name, "ContentItem", + contentItemId => { + var contentItem = context.GetItemFromSession(contentItemId); + part.Content = contentItem; + }, () => + part.Content = null + ); } protected override void Exporting(ContentMenuItemPart part, ExportContentContext context) { diff --git a/src/Orchard.Web/Modules/Orchard.ContentPicker/Fields/ContentPickerField.cs b/src/Orchard.Web/Modules/Orchard.ContentPicker/Fields/ContentPickerField.cs index b08c95247..8b7c15194 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentPicker/Fields/ContentPickerField.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentPicker/Fields/ContentPickerField.cs @@ -17,7 +17,7 @@ namespace Orchard.ContentPicker.Fields { public IEnumerable ContentItems { get { - return _contentItems.Value; + return _contentItems.Value ?? Enumerable.Empty(); } } diff --git a/src/Orchard.Web/Modules/Orchard.ContentPicker/Module.txt b/src/Orchard.Web/Modules/Orchard.ContentPicker/Module.txt index 1feba3586..42a678254 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentPicker/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.ContentPicker/Module.txt @@ -2,7 +2,7 @@ Name: Orchard.ContentPicker AntiForgery: enabled Author: The Orchard Team Website: http://orchardcontentpicker.codeplex.com -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: UI for selecting Content Items. Features: diff --git a/src/Orchard.Web/Modules/Orchard.ContentPicker/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.ContentPicker/Properties/AssemblyInfo.cs index ca5eacf22..c9a2beb06 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentPicker/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentPicker/Properties/AssemblyInfo.cs @@ -31,6 +31,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Module.txt b/src/Orchard.Web/Modules/Orchard.ContentTypes/Module.txt index c1db7247b..c7fb423a5 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Module.txt @@ -2,7 +2,7 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: ContentTypes modules enables the creation and alteration of content types not based on code. Dependencies: Contents diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.ContentTypes/Properties/AssemblyInfo.cs index 904c28a48..06128c3bf 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/StereotypeService.cs b/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/StereotypeService.cs index c00221328..4b4e8471a 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/StereotypeService.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/StereotypeService.cs @@ -22,7 +22,7 @@ namespace Orchard.ContentTypes.Services { } public IEnumerable GetStereotypes() { - return _cacheManager.Get("ContentType.Stereotypes", context => { + return _cacheManager.Get("ContentType.Stereotypes", true, context => { // TODO: Implement a signal in ContentDefinitionManager that gets raised whenever a type definition is updated. // For now, we'll just cache the stereotypes for 1 minute. diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/EditPlacement.cshtml b/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/EditPlacement.cshtml index 4cd178cc0..e9b798834 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/EditPlacement.cshtml +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/EditPlacement.cshtml @@ -43,7 +43,7 @@
- +
} diff --git a/src/Orchard.Web/Modules/Orchard.CustomForms/Drivers/CustomFormPartDriver.cs b/src/Orchard.Web/Modules/Orchard.CustomForms/Drivers/CustomFormPartDriver.cs index ee942bd46..109675fb7 100644 --- a/src/Orchard.Web/Modules/Orchard.CustomForms/Drivers/CustomFormPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.CustomForms/Drivers/CustomFormPartDriver.cs @@ -59,21 +59,20 @@ namespace Orchard.CustomForms.Drivers { } protected override void Importing(CustomFormPart part, ImportContentContext context) { - IfNotNull(context.Attribute(part.PartDefinition.Name, "ContentType"), x => part.Record.ContentType = x); - IfNotNull(context.Attribute(part.PartDefinition.Name, "SaveContentItem"), x => part.Record.SaveContentItem = Boolean.Parse(x)); - IfNotNull(context.Attribute(part.PartDefinition.Name, "CustomMessage"), x => part.Record.CustomMessage = Boolean.Parse(x)); - IfNotNull(context.Attribute(part.PartDefinition.Name, "Message"), x => part.Record.Message = x); - IfNotNull(context.Attribute(part.PartDefinition.Name, "Redirect"), x => part.Record.Redirect = Boolean.Parse(x)); - IfNotNull(context.Attribute(part.PartDefinition.Name, "RedirectUrl"), x => part.Record.RedirectUrl = x); - IfNotNull(context.Attribute(part.PartDefinition.Name, "SubmitButtonText"), x => part.Record.SubmitButtonText = x); - } - - private static void IfNotNull(T value, Action then) { - if (value != null) { - then(value); + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; } - } + context.ImportAttribute(part.PartDefinition.Name, "ContentType", x => part.Record.ContentType = x); + context.ImportAttribute(part.PartDefinition.Name, "SaveContentItem", x => part.Record.SaveContentItem = Boolean.Parse(x)); + context.ImportAttribute(part.PartDefinition.Name, "CustomMessage", x => part.Record.CustomMessage = Boolean.Parse(x)); + context.ImportAttribute(part.PartDefinition.Name, "Message", x => part.Record.Message = x); + context.ImportAttribute(part.PartDefinition.Name, "Redirect", x => part.Record.Redirect = Boolean.Parse(x)); + context.ImportAttribute(part.PartDefinition.Name, "RedirectUrl", x => part.Record.RedirectUrl = x); + context.ImportAttribute(part.PartDefinition.Name, "SubmitButtonText", x => part.Record.SubmitButtonText = x); + } + protected override void Exporting(CustomFormPart part, ExportContentContext context) { context.Element(part.PartDefinition.Name).SetAttributeValue("ContentType", part.Record.ContentType); context.Element(part.PartDefinition.Name).SetAttributeValue("SaveContentItem", part.Record.SaveContentItem); diff --git a/src/Orchard.Web/Modules/Orchard.CustomForms/Module.txt b/src/Orchard.Web/Modules/Orchard.CustomForms/Module.txt index 3fff3687d..af58241ea 100644 --- a/src/Orchard.Web/Modules/Orchard.CustomForms/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.CustomForms/Module.txt @@ -2,7 +2,7 @@ Name: Custom Forms AntiForgery: enabled Author: The Orchard Team Website: http://orchardcustomforms.codeplex.com -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 LifecycleStatus: Deprecated Description: Create custom forms like contact forms or content contributions. diff --git a/src/Orchard.Web/Modules/Orchard.CustomForms/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.CustomForms/Properties/AssemblyInfo.cs index 32c55e753..5095e0451 100644 --- a/src/Orchard.Web/Modules/Orchard.CustomForms/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.CustomForms/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.Dashboards/Orchard.Dashboards.csproj b/src/Orchard.Web/Modules/Orchard.Dashboards/Orchard.Dashboards.csproj index ec35906e7..2914e7645 100644 --- a/src/Orchard.Web/Modules/Orchard.Dashboards/Orchard.Dashboards.csproj +++ b/src/Orchard.Web/Modules/Orchard.Dashboards/Orchard.Dashboards.csproj @@ -72,7 +72,7 @@ - + diff --git a/src/Orchard.Web/Modules/Orchard.Dashboards/Services/DefaultDashboardSelector.cs b/src/Orchard.Web/Modules/Orchard.Dashboards/Services/DefaultDashboardSelector.cs index 55b7ca415..f303de0ed 100644 --- a/src/Orchard.Web/Modules/Orchard.Dashboards/Services/DefaultDashboardSelector.cs +++ b/src/Orchard.Web/Modules/Orchard.Dashboards/Services/DefaultDashboardSelector.cs @@ -6,7 +6,7 @@ using Orchard.Layouts.Models; namespace Orchard.Dashboards.Services { public class DefaultDashboardSelector : IDashboardSelector { private readonly IOrchardServices _services; - public const string DefaultLayout = "{\"elements\":[{\"typeName\":\"Orchard.Layouts.Elements.Canvas\",\"data\":\"\",\"exportableData\":\"\",\"index\":0,\"elements\":[{\"typeName\":\"Orchard.Layouts.Elements.Grid\",\"data\":\"\",\"exportableData\":\"\",\"index\":0,\"elements\":[{\"typeName\":\"Orchard.Layouts.Elements.Row\",\"data\":\"\",\"exportableData\":\"\",\"index\":0,\"elements\":[{\"typeName\":\"Orchard.Layouts.Elements.Column\",\"data\":\"Width=2&Offset=0&Collapsible=null\",\"exportableData\":\"\",\"index\":0,\"elements\":[{\"typeName\":\"Orchard.Layouts.Elements.Html\",\"data\":\"TypeName=Orchard.Layouts.Elements.Html&Text=%3ch2%3e%3ci+class%3d%22fa+fa-cog%22%3e%3c%2fi%3e+Get+up+and+running%3c%2fh2%3e%0d%0a%3cp%3eStart+by+exploring+the+menu+on+the+left+and+familiarize+yourself+with+Orchard.+As+for+the+basics%2c+we+suggest+%3ca+href%3d%22%23%7bUrl.Action%3aIndex%2cAdmin%2carea%3dOrchard.Themes%7d%22%3echanging+the+theme%3c%2fa%3e%2c+%3ca+href%3d%22%23%7bUrl.Action%3aCreate%2cAdmin%2carea%3dContents%2cid%3dPage%7d%22%3eadding+some+pages%3c%2fa%3e%2c+%3ca+href%3d%22%23%7bUrl.Action%3aCreate%2cBlogAdmin%2carea%3dOrchard.Blogs%7d%22%3esetup+up+a+blog%3c%2fa%3e%2c+and+%3ca+href%3d%22%23%7bUrl.Action%3aIndex%2cAdmin%2carea%3dSettings%2cgroupInfoId%3dIndex%7d%22%3econfiguring+basic+settings%3c%2fa%3e.%3c%2fp%3e&Content=%3ch2%3e%3ci+class%3d%22fa+fa-cog%22%3e%3c%2fi%3e+Get+up+and+running%3c%2fh2%3e%0d%0a%3cp%3eStart+by+exploring+the+menu+on+the+left+and+familiarize+yourself+with+Orchard.+As+for+the+basics%2c+we+suggest+%3ca+href%3d%22%23%7bUrl.Action%3aIndex%2cAdmin%2carea%3dOrchard.Themes%7d%22%3echanging+the+theme%3c%2fa%3e%2c+%3ca+href%3d%22%23%7bUrl.Action%3aCreate%2cAdmin%2carea%3dContents%2cid%3dPage%7d%22%3eadding+some+pages%3c%2fa%3e%2c+%3ca+href%3d%22%23%7bUrl.Action%3aCreate%2cBlogAdmin%2carea%3dOrchard.Blogs%7d%22%3esetup+up+a+blog%3c%2fa%3e%2c+and+%3ca+href%3d%22%23%7bUrl.Action%3aIndex%2cAdmin%2carea%3dSettings%2cgroupInfoId%3dIndex%7d%22%3econfiguring+basic+settings%3c%2fa%3e.%3c%2fp%3e\",\"exportableData\":\"\",\"index\":0,\"elements\":[],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"}],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"},{\"typeName\":\"Orchard.Layouts.Elements.Column\",\"data\":\"Width=2&Offset=0&Collapsible=null\",\"exportableData\":\"\",\"index\":1,\"elements\":[{\"typeName\":\"Orchard.Layouts.Elements.Html\",\"data\":\"TypeName=Orchard.Layouts.Elements.Html&Text=%3ch2%3e%3ci+class%3d%22fa+fa-th-large%22%3e%3c%2fi%3eGet+more+goodies%3c%2fh2%3e%0d%0a%3cp%3eChange+the+way+your+site+works+and+looks+with+%3ca+href%3d%22%23%7bUrl.Action%3aThemes%2cGallery%2carea%3dOrchard.Packaging%7d%22%3ethemes%3c%2fa%3e+and+%3ca+href%3d%22%23%7bUrl.Action%3aModules%2cGallery%2carea%3dOrchard.Packaging%7d%22%3emodules%3c%2fa%3e.+There%26rsquo%3bs+plenty+to+choose+from+in+the+%3ca+href%3d%22http%3a%2f%2fgallery.orchardproject.net%22%3eOrchard+Gallery%3c%2fa%3e.+We%26rsquo%3bre+always+adding+things%2c+so+be+sure+to+check+back+often+to+see+what%26rsquo%3bs+new.%3c%2fp%3e&Content=%3ch2%3e%3ci+class%3d%22fa+fa-th-large%22%3e%3c%2fi%3eGet+more+goodies%3c%2fh2%3e%0d%0a%3cp%3eChange+the+way+your+site+works+and+looks+with+%3ca+href%3d%22%23%7bUrl.Action%3aThemes%2cGallery%2carea%3dOrchard.Packaging%7d%22%3ethemes%3c%2fa%3e+and+%3ca+href%3d%22%23%7bUrl.Action%3aModules%2cGallery%2carea%3dOrchard.Packaging%7d%22%3emodules%3c%2fa%3e.+There%26rsquo%3bs+plenty+to+choose+from+in+the+%3ca+href%3d%22http%3a%2f%2fgallery.orchardproject.net%22%3eOrchard+Gallery%3c%2fa%3e.+We%26rsquo%3bre+always+adding+things%2c+so+be+sure+to+check+back+often+to+see+what%26rsquo%3bs+new.%3c%2fp%3e\",\"exportableData\":\"\",\"index\":0,\"elements\":[],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"}],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"},{\"typeName\":\"Orchard.Layouts.Elements.Column\",\"data\":\"Width=2&Offset=0&Collapsible=null\",\"exportableData\":\"\",\"index\":2,\"elements\":[{\"typeName\":\"Orchard.Layouts.Elements.Html\",\"data\":\"TypeName=Orchard.Layouts.Elements.Html&Text=%3ch2%3e%3ci+class%3d%22fa+fa-book%22%3e%3c%2fi%3eRead+the+Docs%3c%2fh2%3e%0d%0a%3cp%3eAre+you+ready+to+go+deeper+and+become+an+Orchard+expert%3f+Take+a+look+at+the+%3ca+href%3d%22http%3a%2f%2fdocs.orchardproject.net%22%3eOrchard+Documentation%3c%2fa%3e+to+learn+about+how+everything+connects+together+and+what+makes+Orchard+tick.%3c%2fp%3e&Content=%3ch2%3e%3ci+class%3d%22fa+fa-book%22%3e%3c%2fi%3eRead+the+Docs%3c%2fh2%3e%0d%0a%3cp%3eAre+you+ready+to+go+deeper+and+become+an+Orchard+expert%3f+Take+a+look+at+the+%3ca+href%3d%22http%3a%2f%2fdocs.orchardproject.net%22%3eOrchard+Documentation%3c%2fa%3e+to+learn+about+how+everything+connects+together+and+what+makes+Orchard+tick.%3c%2fp%3e\",\"exportableData\":\"\",\"index\":0,\"elements\":[],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"}],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"},{\"typeName\":\"Orchard.Layouts.Elements.Column\",\"data\":\"Width=2&Offset=0&Collapsible=null\",\"exportableData\":\"\",\"index\":3,\"elements\":[{\"typeName\":\"Orchard.Layouts.Elements.Html\",\"data\":\"TypeName=Orchard.Layouts.Elements.Html&Text=%3ch2%3e%3ci+class%3d%22fa+fa-users%22%3e%3c%2fi%3eMake+friends%3c%2fh2%3e%0d%0a%3cp%3eFind+friends+that+share+your+interest+of+Orchard.+There+are+a+couple+ways+that+you+can%26nbsp%3b%3ca+href%3d%22http%3a%2f%2forchardproject.net%2fdiscussions%22%3ediscuss+and+get+connected%3c%2fa%3e+to+the+project+including+mailing+lists%2c+forums+and+IRC.%3c%2fp%3e&Content=%3ch2%3e%3ci+class%3d%22fa+fa-users%22%3e%3c%2fi%3eMake+friends%3c%2fh2%3e%0d%0a%3cp%3eFind+friends+that+share+your+interest+of+Orchard.+There+are+a+couple+ways+that+you+can%26nbsp%3b%3ca+href%3d%22http%3a%2f%2forchardproject.net%2fdiscussions%22%3ediscuss+and+get+connected%3c%2fa%3e+to+the+project+including+mailing+lists%2c+forums+and+IRC.%3c%2fp%3e\",\"exportableData\":\"\",\"index\":0,\"elements\":[],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"}],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"},{\"typeName\":\"Orchard.Layouts.Elements.Column\",\"data\":\"Width=2&Offset=0&Collapsible=null\",\"exportableData\":\"\",\"index\":4,\"elements\":[{\"typeName\":\"Orchard.Layouts.Elements.Html\",\"data\":\"TypeName=Orchard.Layouts.Elements.Html&Text=%3ch2%3e%3ci+class%3d%22fa+fa-pencil%22%3e%3c%2fi%3eContribute+back%3c%2fh2%3e%0d%0a%3cp%3eHelp+grow+Orchard.+We+encourage+contributions+of+all+sorts%2c+including+code+submissions%2c+documentation%2c+translations%2c+feature+recommendations%2c+and+more.Here+are+some+ways+to+%3ca+href%3d%22http%3a%2f%2forchardproject.net%2fcontribution%22%3egive+back+to+the+project%3c%2fa%3e.%3c%2fp%3e&Content=%3ch2%3e%3ci+class%3d%22fa+fa-pencil%22%3e%3c%2fi%3eContribute+back%3c%2fh2%3e%0d%0a%3cp%3eHelp+grow+Orchard.+We+encourage+contributions+of+all+sorts%2c+including+code+submissions%2c+documentation%2c+translations%2c+feature+recommendations%2c+and+more.Here+are+some+ways+to+%3ca+href%3d%22http%3a%2f%2forchardproject.net%2fcontribution%22%3egive+back+to+the+project%3c%2fa%3e.%3c%2fp%3e\",\"exportableData\":\"\",\"index\":0,\"elements\":[],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"}],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"},{\"typeName\":\"Orchard.Layouts.Elements.Column\",\"data\":\"Width=2&Offset=0&Collapsible=null\",\"exportableData\":\"\",\"index\":5,\"elements\":[],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"}],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"},{\"typeName\":\"Orchard.Layouts.Elements.Row\",\"data\":\"\",\"exportableData\":\"\",\"index\":1,\"elements\":[{\"typeName\":\"Orchard.Layouts.Elements.Column\",\"data\":\"Width=10&Offset=0&Collapsible=null\",\"exportableData\":\"\",\"index\":0,\"elements\":[{\"typeName\":\"Orchard.Layouts.Elements.Html\",\"data\":\"TypeName=Orchard.Layouts.Elements.Html&Text=%3ch2%3e%3ci+class%3d%22fa+fa-clock-o%22%3e%3c%2fi%3eStay+up+to+date%3c%2fh2%3e%0d%0a%3cp%3e%3ciframe+width%3d%22100%25%22+height%3d%22100%25%22+scrolling%3d%22no%22+frameborder%3d%220%22+src%3d%22http%3a%2f%2fwww.orchardproject.net%2fadvisory%22+id%3d%22advisory%22%3e%0d%0a+%26lt%3bp%26gt%3bYour+browser+does+not+support+iframes.+You+can%27t+see+advisory+messages.%26lt%3b%2fp%26gt%3b%3c%2fiframe%3e%3c%2fp%3e&Content=%3ch2%3e%3ci+class%3d%22fa+fa-clock-o%22%3e%3c%2fi%3eStay+up+to+date%3c%2fh2%3e%0d%0a%3cp%3e%3ciframe+width%3d%22100%25%22+height%3d%22100%25%22+scrolling%3d%22no%22+frameborder%3d%220%22+src%3d%22http%3a%2f%2fwww.orchardproject.net%2fadvisory%22+id%3d%22advisory%22%3e%0d%0a+%26lt%3bp%26gt%3bYour+browser+does+not+support+iframes.+You+can%27t+see+advisory+messages.%26lt%3b%2fp%26gt%3b%3c%2fiframe%3e%3c%2fp%3e\",\"exportableData\":\"\",\"index\":0,\"elements\":[],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"}],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"},{\"typeName\":\"Orchard.Layouts.Elements.Column\",\"data\":\"Width=2&Offset=0&Collapsible=null\",\"exportableData\":\"\",\"index\":1,\"elements\":[],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"}],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"}],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"}],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"}]}"; + public const string DefaultLayout = "{\"elements\":[{\"typeName\":\"Orchard.Layouts.Elements.Canvas\",\"data\":\"\",\"exportableData\":\"\",\"index\":0,\"elements\":[{\"typeName\":\"Orchard.Layouts.Elements.Grid\",\"data\":\"\",\"exportableData\":\"\",\"index\":0,\"elements\":[{\"typeName\":\"Orchard.Layouts.Elements.Row\",\"data\":\"\",\"exportableData\":\"\",\"index\":0,\"elements\":[{\"typeName\":\"Orchard.Layouts.Elements.Column\",\"data\":\"Width=2&Offset=0&Collapsible=null\",\"exportableData\":\"\",\"index\":0,\"elements\":[{\"typeName\":\"Orchard.Layouts.Elements.Html\",\"data\":\"TypeName=Orchard.Layouts.Elements.Html&Text=%3ch2%3e%3ci+class%3d%22fa+fa-cog%22%3e%3c%2fi%3e+Get+up+and+running%3c%2fh2%3e%0d%0a%3cp%3eStart+by+exploring+the+menu+on+the+left+and+familiarize+yourself+with+Orchard.+As+for+the+basics%2c+we+suggest+%3ca+href%3d%22%23%7bUrl.Action%3aIndex%2cAdmin%2carea%3dOrchard.Themes%7d%22%3echanging+the+theme%3c%2fa%3e%2c+%3ca+href%3d%22%23%7bUrl.Action%3aCreate%2cAdmin%2carea%3dContents%2cid%3dPage%7d%22%3eadding+some+pages%3c%2fa%3e%2c+%3ca+href%3d%22%23%7bUrl.Action%3aCreate%2cBlogAdmin%2carea%3dOrchard.Blogs%7d%22%3esetup+up+a+blog%3c%2fa%3e%2c+and+%3ca+href%3d%22%23%7bUrl.Action%3aIndex%2cAdmin%2carea%3dSettings%2cgroupInfoId%3dIndex%7d%22%3econfiguring+basic+settings%3c%2fa%3e.%3c%2fp%3e&Content=%3ch2%3e%3ci+class%3d%22fa+fa-cog%22%3e%3c%2fi%3e+Get+up+and+running%3c%2fh2%3e%0d%0a%3cp%3eStart+by+exploring+the+menu+on+the+left+and+familiarize+yourself+with+Orchard.+As+for+the+basics%2c+we+suggest+%3ca+href%3d%22%23%7bUrl.Action%3aIndex%2cAdmin%2carea%3dOrchard.Themes%7d%22%3echanging+the+theme%3c%2fa%3e%2c+%3ca+href%3d%22%23%7bUrl.Action%3aCreate%2cAdmin%2carea%3dContents%2cid%3dPage%7d%22%3eadding+some+pages%3c%2fa%3e%2c+%3ca+href%3d%22%23%7bUrl.Action%3aCreate%2cBlogAdmin%2carea%3dOrchard.Blogs%7d%22%3esetup+up+a+blog%3c%2fa%3e%2c+and+%3ca+href%3d%22%23%7bUrl.Action%3aIndex%2cAdmin%2carea%3dSettings%2cgroupInfoId%3dIndex%7d%22%3econfiguring+basic+settings%3c%2fa%3e.%3c%2fp%3e\",\"exportableData\":\"\",\"index\":0,\"elements\":[],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"}],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"},{\"typeName\":\"Orchard.Layouts.Elements.Column\",\"data\":\"Width=2&Offset=0&Collapsible=null\",\"exportableData\":\"\",\"index\":1,\"elements\":[{\"typeName\":\"Orchard.Layouts.Elements.Html\",\"data\":\"TypeName=Orchard.Layouts.Elements.Html&Text=%3ch2%3e%3ci+class%3d%22fa+fa-th-large%22%3e%3c%2fi%3eGet+more+goodies%3c%2fh2%3e%0d%0a%3cp%3eChange+the+way+your+site+works+and+looks+with+%3ca+href%3d%22%23%7bUrl.Action%3aThemes%2cGallery%2carea%3dOrchard.Packaging%7d%22%3ethemes%3c%2fa%3e+and+%3ca+href%3d%22%23%7bUrl.Action%3aModules%2cGallery%2carea%3dOrchard.Packaging%7d%22%3emodules%3c%2fa%3e.+There%26rsquo%3bs+plenty+to+choose+from+in+the+%3ca+href%3d%22http%3a%2f%2fgallery.orchardproject.net%22%3eOrchard+Gallery%3c%2fa%3e.+We%26rsquo%3bre+always+adding+things%2c+so+be+sure+to+check+back+often+to+see+what%26rsquo%3bs+new.%3c%2fp%3e&Content=%3ch2%3e%3ci+class%3d%22fa+fa-th-large%22%3e%3c%2fi%3eGet+more+goodies%3c%2fh2%3e%0d%0a%3cp%3eChange+the+way+your+site+works+and+looks+with+%3ca+href%3d%22%23%7bUrl.Action%3aThemes%2cGallery%2carea%3dOrchard.Packaging%7d%22%3ethemes%3c%2fa%3e+and+%3ca+href%3d%22%23%7bUrl.Action%3aModules%2cGallery%2carea%3dOrchard.Packaging%7d%22%3emodules%3c%2fa%3e.+There%26rsquo%3bs+plenty+to+choose+from+in+the+%3ca+href%3d%22http%3a%2f%2fgallery.orchardproject.net%22%3eOrchard+Gallery%3c%2fa%3e.+We%26rsquo%3bre+always+adding+things%2c+so+be+sure+to+check+back+often+to+see+what%26rsquo%3bs+new.%3c%2fp%3e\",\"exportableData\":\"\",\"index\":0,\"elements\":[],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"}],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"},{\"typeName\":\"Orchard.Layouts.Elements.Column\",\"data\":\"Width=2&Offset=0&Collapsible=null\",\"exportableData\":\"\",\"index\":2,\"elements\":[{\"typeName\":\"Orchard.Layouts.Elements.Html\",\"data\":\"TypeName=Orchard.Layouts.Elements.Html&Text=%3ch2%3e%3ci+class%3d%22fa+fa-book%22%3e%3c%2fi%3eRead+the+Docs%3c%2fh2%3e%0d%0a%3cp%3eAre+you+ready+to+go+deeper+and+become+an+Orchard+expert%3f+Take+a+look+at+the+%3ca+href%3d%22http%3a%2f%2fdocs.orchardproject.net%22%3eOrchard+Documentation%3c%2fa%3e+to+learn+about+how+everything+connects+together+and+what+makes+Orchard+tick.%3c%2fp%3e&Content=%3ch2%3e%3ci+class%3d%22fa+fa-book%22%3e%3c%2fi%3eRead+the+Docs%3c%2fh2%3e%0d%0a%3cp%3eAre+you+ready+to+go+deeper+and+become+an+Orchard+expert%3f+Take+a+look+at+the+%3ca+href%3d%22http%3a%2f%2fdocs.orchardproject.net%22%3eOrchard+Documentation%3c%2fa%3e+to+learn+about+how+everything+connects+together+and+what+makes+Orchard+tick.%3c%2fp%3e\",\"exportableData\":\"\",\"index\":0,\"elements\":[],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"}],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"},{\"typeName\":\"Orchard.Layouts.Elements.Column\",\"data\":\"Width=2&Offset=0&Collapsible=null\",\"exportableData\":\"\",\"index\":3,\"elements\":[{\"typeName\":\"Orchard.Layouts.Elements.Html\",\"data\":\"TypeName=Orchard.Layouts.Elements.Html&Text=%3ch2%3e%3ci+class%3d%22fa+fa-users%22%3e%3c%2fi%3eMake+friends%3c%2fh2%3e%0d%0a%3cp%3eFind+friends+that+share+your+interest+of+Orchard.+There+are+a+couple+ways+that+you+can%26nbsp%3b%3ca+href%3d%22http%3a%2f%2forchardproject.net%2fdiscussions%22%3ediscuss+and+get+connected%3c%2fa%3e+to+the+project+including+mailing+lists%2c+forums+and+IRC.%3c%2fp%3e&Content=%3ch2%3e%3ci+class%3d%22fa+fa-users%22%3e%3c%2fi%3eMake+friends%3c%2fh2%3e%0d%0a%3cp%3eFind+friends+that+share+your+interest+of+Orchard.+There+are+a+couple+ways+that+you+can%26nbsp%3b%3ca+href%3d%22http%3a%2f%2forchardproject.net%2fdiscussions%22%3ediscuss+and+get+connected%3c%2fa%3e+to+the+project+including+mailing+lists%2c+forums+and+IRC.%3c%2fp%3e\",\"exportableData\":\"\",\"index\":0,\"elements\":[],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"}],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"},{\"typeName\":\"Orchard.Layouts.Elements.Column\",\"data\":\"Width=2&Offset=0&Collapsible=null\",\"exportableData\":\"\",\"index\":4,\"elements\":[{\"typeName\":\"Orchard.Layouts.Elements.Html\",\"data\":\"TypeName=Orchard.Layouts.Elements.Html&Text=%3ch2%3e%3ci+class%3d%22fa+fa-pencil%22%3e%3c%2fi%3eContribute+back%3c%2fh2%3e%0d%0a%3cp%3eHelp+grow+Orchard.+We+encourage+contributions+of+all+sorts%2c+including+code+submissions%2c+documentation%2c+translations%2c+feature+recommendations%2c+and+more.Here+are+some+ways+to+%3ca+href%3d%22http%3a%2f%2forchardproject.net%2fcontribution%22%3egive+back+to+the+project%3c%2fa%3e.%3c%2fp%3e&Content=%3ch2%3e%3ci+class%3d%22fa+fa-pencil%22%3e%3c%2fi%3eContribute+back%3c%2fh2%3e%0d%0a%3cp%3eHelp+grow+Orchard.+We+encourage+contributions+of+all+sorts%2c+including+code+submissions%2c+documentation%2c+translations%2c+feature+recommendations%2c+and+more.Here+are+some+ways+to+%3ca+href%3d%22http%3a%2f%2forchardproject.net%2fcontribution%22%3egive+back+to+the+project%3c%2fa%3e.%3c%2fp%3e\",\"exportableData\":\"\",\"index\":0,\"elements\":[],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"}],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"},{\"typeName\":\"Orchard.Layouts.Elements.Column\",\"data\":\"Width=2&Offset=0&Collapsible=null\",\"exportableData\":\"\",\"index\":5,\"elements\":[],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"}],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"},{\"typeName\":\"Orchard.Layouts.Elements.Row\",\"data\":\"\",\"exportableData\":\"\",\"index\":1,\"elements\":[{\"typeName\":\"Orchard.Layouts.Elements.Column\",\"data\":\"Width=10&Offset=0&Collapsible=null\",\"exportableData\":\"\",\"index\":0,\"elements\":[{\"typeName\":\"Orchard.Layouts.Elements.Html\",\"data\":\"TypeName=Orchard.Layouts.Elements.Html&Text=%3ch2%3e%3ci+class%3d%22fa+fa-clock-o%22%3e%3c%2fi%3eStay+up+to+date%3c%2fh2%3e%0d%0a%3cp%3e%3ciframe+width%3d%22100%25%22+height%3d%22100%25%22+scrolling%3d%22no%22+frameborder%3d%220%22+src%3d%22http%3a%2f%2fwww.orchardproject.net%2fadvisory%22+id%3d%22advisory%22%3e%0d%0a+%26lt%3bp%26gt%3bYour+browser+does+not+support+iframes.+You+can%27t+see+advisory+messages.%26lt%3b%2fp%26gt%3b%3c%2fiframe%3e%3c%2fp%3e&Content=%3ch2%3e%3ci+class%3d%22fa+fa-clock-o%22%3e%3c%2fi%3eStay+up+to+date%3c%2fh2%3e%0d%0a%3cp%3e%3ciframe+width%3d%22100%25%22+height%3d%22100%25%22+scrolling%3d%22no%22+frameborder%3d%220%22+src%3d%22http%3a%2f%2fwww.orchardproject.net%2fadvisory%22+id%3d%22advisory%22%3e%0d%0a+%26lt%3bp%26gt%3bYour+browser+does+not+support+iframes.+You+can%27t+see+advisory+messages.%26lt%3b%2fp%26gt%3b%3c%2fiframe%3e%3c%2fp%3e\",\"exportableData\":\"\",\"index\":0,\"elements\":[],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"}],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"},{\"typeName\":\"Orchard.Layouts.Elements.Column\",\"data\":\"Width=2&Offset=0&Collapsible=null\",\"exportableData\":\"\",\"index\":1,\"elements\":[],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"}],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"}],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"}],\"isTemplated\":false,\"htmlId\":\"\",\"htmlClass\":\"\",\"htmlStyle\":\"\",\"rule\":\"\"}]}"; public DefaultDashboardSelector(IOrchardServices services) { _services = services; diff --git a/src/Orchard.Web/Modules/Orchard.DesignerTools/Module.txt b/src/Orchard.Web/Modules/Orchard.DesignerTools/Module.txt index 9cf6763e0..6cd2a40b2 100644 --- a/src/Orchard.Web/Modules/Orchard.DesignerTools/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.DesignerTools/Module.txt @@ -2,7 +2,7 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: Contains designer tools to ease the Themes development process FeatureName: Shape Tracing diff --git a/src/Orchard.Web/Modules/Orchard.DesignerTools/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.DesignerTools/Properties/AssemblyInfo.cs index e7d9be4bd..c725f836f 100644 --- a/src/Orchard.Web/Modules/Orchard.DesignerTools/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.DesignerTools/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.DesignerTools/Services/ShapeTracingFactory.cs b/src/Orchard.Web/Modules/Orchard.DesignerTools/Services/ShapeTracingFactory.cs index cec0f009a..ae80ad879 100644 --- a/src/Orchard.Web/Modules/Orchard.DesignerTools/Services/ShapeTracingFactory.cs +++ b/src/Orchard.Web/Modules/Orchard.DesignerTools/Services/ShapeTracingFactory.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Text; using System.Web.Routing; +using System.Xml.Linq; using Orchard.DisplayManagement.Descriptors; using Orchard.DisplayManagement.Implementation; using Orchard.DisplayManagement.Shapes; @@ -11,15 +12,16 @@ using Orchard.Security; using Orchard.Themes; using Orchard.UI; using Orchard.UI.Admin; +using System.Web; namespace Orchard.DesignerTools.Services { [OrchardFeature("Orchard.DesignerTools")] public class ShapeTracingFactory : IShapeFactoryEvents, IShapeDisplayEvents { + private readonly WorkContext _workContext; private readonly IShapeTableManager _shapeTableManager; private readonly IThemeManager _themeManager; private readonly IWebSiteFolder _webSiteFolder; private readonly IAuthorizer _authorizer; - private readonly IWorkContextAccessor _workContextAccessor; private bool _processing; private int _shapeId; @@ -31,7 +33,7 @@ namespace Orchard.DesignerTools.Services { IWebSiteFolder webSiteFolder, IAuthorizer authorizer ) { - _workContextAccessor = workContextAccessor; + _workContext = workContextAccessor.GetContext(); _shapeTableManager = shapeTableManager; _themeManager = themeManager; _webSiteFolder = webSiteFolder; @@ -39,17 +41,13 @@ namespace Orchard.DesignerTools.Services { } private bool IsActivable() { - var workContext = _workContextAccessor.GetContext(); - // activate on front-end only - if (AdminFilter.IsApplied(new RequestContext(workContext.HttpContext, new RouteData()))) + if (AdminFilter.IsApplied(new RequestContext(_workContext.HttpContext, new RouteData()))) return false; // if not logged as a site owner, still activate if it's a local request (development machine) - if (!_authorizer.Authorize(StandardPermissions.SiteOwner)) { - - return workContext.HttpContext.Request.IsLocal; - } + if (!_authorizer.Authorize(StandardPermissions.SiteOwner)) + return _workContext.HttpContext.Request.IsLocal; return true; } @@ -78,8 +76,7 @@ namespace Orchard.DesignerTools.Services { && context.ShapeType != "DateTimeRelative") { var shapeMetadata = (ShapeMetadata)context.Shape.Metadata; - var workContext = _workContextAccessor.GetContext(); - var currentTheme = workContext.CurrentTheme; + var currentTheme = _workContext.CurrentTheme; var shapeTable = _shapeTableManager.GetShapeTable(currentTheme.Id); if (!shapeTable.Descriptors.ContainsKey(shapeMetadata.Type)) { @@ -102,8 +99,7 @@ namespace Orchard.DesignerTools.Services { var shape = context.Shape; var shapeMetadata = (ShapeMetadata) context.Shape.Metadata; - var workContext = _workContextAccessor.GetContext(); - var currentTheme = _themeManager.GetRequestTheme(workContext.HttpContext.Request.RequestContext); + var currentTheme = _themeManager.GetRequestTheme(_workContext.HttpContext.Request.RequestContext); var shapeTable = _shapeTableManager.GetShapeTable(currentTheme.Id); if (!shapeMetadata.Wrappers.Contains("ShapeTracingWrapper")) { diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Drivers/QueryElementDriver.cs b/src/Orchard.Web/Modules/Orchard.DynamicForms/Drivers/QueryElementDriver.cs index f5a492657..0b284e293 100644 --- a/src/Orchard.Web/Modules/Orchard.DynamicForms/Drivers/QueryElementDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Drivers/QueryElementDriver.cs @@ -136,7 +136,7 @@ namespace Orchard.DynamicForms.Drivers { var runtimeValues = GetRuntimeValues(element); if (!String.IsNullOrWhiteSpace(optionLabel)) { - yield return new SelectListItem { Text = displayType != "Design" ? _tokenizer.Replace(optionLabel, tokenData) : optionLabel }; + yield return new SelectListItem { Text = displayType != "Design" ? _tokenizer.Replace(optionLabel, tokenData) : optionLabel, Value = string.Empty }; } if (queryId == null) diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Drivers/TaxonomyElementDriver.cs b/src/Orchard.Web/Modules/Orchard.DynamicForms/Drivers/TaxonomyElementDriver.cs index c398f5726..806e72c0a 100644 --- a/src/Orchard.Web/Modules/Orchard.DynamicForms/Drivers/TaxonomyElementDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Drivers/TaxonomyElementDriver.cs @@ -138,7 +138,7 @@ namespace Orchard.DynamicForms.Drivers { var runtimeValues = GetRuntimeValues(element); if (!String.IsNullOrWhiteSpace(optionLabel)) { - yield return new SelectListItem { Text = displayType != "Design" ? _tokenizer.Replace(optionLabel, tokenData) : optionLabel }; + yield return new SelectListItem { Text = displayType != "Design" ? _tokenizer.Replace(optionLabel, tokenData) : optionLabel, Value = string.Empty }; } if (taxonomyId == null) diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Migrations.cs b/src/Orchard.Web/Modules/Orchard.DynamicForms/Migrations.cs index e65035a55..16acf01e1 100644 --- a/src/Orchard.Web/Modules/Orchard.DynamicForms/Migrations.cs +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Migrations.cs @@ -1,10 +1,15 @@ using System; +using System.Linq; +using System.Security.Cryptography; using Orchard.ContentManagement.MetaData; using Orchard.Core.Contents.Extensions; +using Orchard.Data; using Orchard.Data.Migration; namespace Orchard.DynamicForms { public class Migrations : DataMigrationImpl { + private readonly byte[] _oldLayoutHash = new byte[] { 0x91, 0x10, 0x3b, 0x97, 0xce, 0x1e, 0x1e, 0xc7, 0x7a, 0x41, 0xf7, 0x82, 0xe8, 0x58, 0x85, 0x91 }; + private const string DefaultFormLayoutData = @"{ ""elements"": [ @@ -59,7 +64,52 @@ namespace Orchard.DynamicForms { .WithSetting("LayoutTypePartSettings.DefaultLayoutData", DefaultFormLayoutData)) .WithSetting("Stereotype", "Widget") .DisplayedAs("Form Widget")); - return 1; + return 2; + } + + public int UpdateFrom1() { + // if the default layout data was unchanged, fix it with the new default + + var formLayoutPart = ContentDefinitionManager + .GetTypeDefinition("Form") + .Parts + .FirstOrDefault(x => x.PartDefinition.Name == "LayoutPart"); + + if (formLayoutPart != null && + formLayoutPart.Settings["LayoutTypePartSettings.DefaultLayoutData"] != null) { + var layout = formLayoutPart.Settings["LayoutTypePartSettings.DefaultLayoutData"]; + + if(GetMD5(layout) == _oldLayoutHash) { + ContentDefinitionManager.AlterTypeDefinition("Form", type => type + .WithPart("LayoutPart", p => p + .WithSetting("LayoutTypePartSettings.DefaultLayoutData", DefaultFormLayoutData)) + ); + } + } + + var formWidgetLayoutPart = ContentDefinitionManager + .GetTypeDefinition("FormWidget") + .Parts + .FirstOrDefault(x => x.PartDefinition.Name == "LayoutPart"); + + if (formWidgetLayoutPart != null && + formWidgetLayoutPart.Settings["LayoutTypePartSettings.DefaultLayoutData"] != null) { + var layout = formWidgetLayoutPart.Settings["LayoutTypePartSettings.DefaultLayoutData"]; + + if (GetMD5(layout) == _oldLayoutHash) { + ContentDefinitionManager.AlterTypeDefinition("FormWidget", type => type + .WithPart("LayoutPart", p => p + .WithSetting("LayoutTypePartSettings.DefaultLayoutData", DefaultFormLayoutData)) + ); + } + } + + return 2; + } + + private byte[] GetMD5(string text) { + byte[] encodedText = System.Text.Encoding.UTF8.GetBytes(text); + return ((HashAlgorithm)CryptoConfig.CreateFromName("MD5")).ComputeHash(encodedText); } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Module.txt b/src/Orchard.Web/Modules/Orchard.DynamicForms/Module.txt index 50a66b14d..130adc262 100644 --- a/src/Orchard.Web/Modules/Orchard.DynamicForms/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Module.txt @@ -1,8 +1,8 @@ -Name: Custom Forms +Name: Dynamic Forms AntiForgery: enabled Author: The Orchard Team -Website: http://orchardcustomforms.codeplex.com -Version: 1.9.1 +Website: http://www.orchardproject.net/ +Version: 1.9.2 OrchardVersion: 1.9 Description: Create custom forms like contact forms using layouts. Features: diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Tokens/FormTokens.cs b/src/Orchard.Web/Modules/Orchard.DynamicForms/Tokens/FormTokens.cs index e26cb2626..68fbdb5c4 100644 --- a/src/Orchard.Web/Modules/Orchard.DynamicForms/Tokens/FormTokens.cs +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Tokens/FormTokens.cs @@ -7,7 +7,7 @@ namespace Orchard.DynamicForms.Tokens { public void Describe(DescribeContext context) { context.For("FormSubmission", T("Dynamic Form submission"), T("Dynamic Form Submission tokens for use in workflows handling the Dynamic Form Submitted event.")) - .Token("Field:*", T("Field:"), T("The posted field value to access.")) + .Token("Field:*", T("Field:"), T("The posted field value to access."), "Text") .Token("IsValid:*", T("IsValid:"), T("The posted field validation status.")) ; } @@ -15,10 +15,20 @@ namespace Orchard.DynamicForms.Tokens { public void Evaluate(EvaluateContext context) { context.For("FormSubmission") .Token(token => token.StartsWith("Field:", StringComparison.OrdinalIgnoreCase) ? token.Substring("Field:".Length) : null, GetFieldValue) + .Chain(FilterChainParam, "Text", GetFieldValue) .Token(token => token.StartsWith("IsValid:", StringComparison.OrdinalIgnoreCase) ? token.Substring("IsValid:".Length) : null, GetFieldValidationStatus); } - private object GetFieldValue(string fieldName, FormSubmissionTokenContext context) { + private static Tuple FilterChainParam(string token) { + int tokenLength = "Field:".Length; + int chainIndex = token.IndexOf('.'); + if (token.StartsWith("Field:", StringComparison.OrdinalIgnoreCase) && chainIndex > tokenLength) + return new Tuple(token.Substring(tokenLength, chainIndex - tokenLength), token.Substring(chainIndex + 1)); + else + return null; + } + + private string GetFieldValue(string fieldName, FormSubmissionTokenContext context) { return context.PostedValues[fieldName]; } diff --git a/src/Orchard.Web/Modules/Orchard.Email/Module.txt b/src/Orchard.Web/Modules/Orchard.Email/Module.txt index 58fedf6d9..d81676eca 100644 --- a/src/Orchard.Web/Modules/Orchard.Email/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Email/Module.txt @@ -2,7 +2,7 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: The Email Messaging module adds Email sending functionalities. Features: diff --git a/src/Orchard.Web/Modules/Orchard.Email/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Email/Properties/AssemblyInfo.cs index 56a441495..165086d69 100644 --- a/src/Orchard.Web/Modules/Orchard.Email/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Email/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/BooleanFieldDriver.cs b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/BooleanFieldDriver.cs index 4e0afb916..50d0b98af 100644 --- a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/BooleanFieldDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/BooleanFieldDriver.cs @@ -61,7 +61,8 @@ namespace Orchard.Fields.Drivers { } protected override void Exporting(ContentPart part, BooleanField field, ExportContentContext context) { - context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Value", field.Value); + if (field.Value.HasValue) + context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Value", field.Value); } protected override void Describe(DescribeMembersContext context) { diff --git a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/DateTimeFieldDriver.cs b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/DateTimeFieldDriver.cs index 1cda2654a..85b59a5d1 100644 --- a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/DateTimeFieldDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/DateTimeFieldDriver.cs @@ -167,7 +167,9 @@ namespace Orchard.Fields.Drivers { } protected override void Exporting(ContentPart part, DateTimeField field, ExportContentContext context) { - context.Element(GetPrefix(field, part)).SetAttributeValue("Value", XmlConvert.ToString(field.Storage.Get(null), XmlDateTimeSerializationMode.Utc)); + var value = field.Storage.Get(null); + if (value != DateTime.MinValue) + context.Element(GetPrefix(field, part)).SetAttributeValue("Value", XmlConvert.ToString(value, XmlDateTimeSerializationMode.Utc)); } protected override void Describe(DescribeMembersContext context) { diff --git a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/EnumerationFieldDriver.cs b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/EnumerationFieldDriver.cs index 3d1607f39..4ba91fbbe 100644 --- a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/EnumerationFieldDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/EnumerationFieldDriver.cs @@ -4,6 +4,7 @@ using Orchard.ContentManagement.Handlers; using Orchard.Fields.Settings; using Orchard.Fields.Fields; using Orchard.Localization; +using System; namespace Orchard.Fields.Drivers { public class EnumerationFieldDriver : ContentFieldDriver { @@ -51,7 +52,8 @@ namespace Orchard.Fields.Drivers { } protected override void Exporting(ContentPart part, EnumerationField field, ExportContentContext context) { - context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Value", field.Value); + if (!String.IsNullOrEmpty(field.Value)) + context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Value", field.Value); } protected override void Describe(DescribeMembersContext context) { diff --git a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/InputFieldDriver.cs b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/InputFieldDriver.cs index aefd92b55..8a85cf904 100644 --- a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/InputFieldDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/InputFieldDriver.cs @@ -56,7 +56,8 @@ namespace Orchard.Fields.Drivers { } protected override void Exporting(ContentPart part, InputField field, ExportContentContext context) { - context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Value", field.Value); + if (!String.IsNullOrEmpty(field.Value)) + context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Value", field.Value); } protected override void Describe(DescribeMembersContext context) { diff --git a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/LinkFieldDriver.cs b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/LinkFieldDriver.cs index 24727c63f..ef92dd6e0 100644 --- a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/LinkFieldDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/LinkFieldDriver.cs @@ -62,9 +62,11 @@ namespace Orchard.Fields.Drivers { } protected override void Exporting(ContentPart part, LinkField field, ExportContentContext context) { - context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Text", field.Text); - context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Url", field.Value); - context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Target", field.Target); + if (!String.IsNullOrEmpty(field.Text) || !String.IsNullOrEmpty(field.Value) || !String.IsNullOrEmpty(field.Target)) { + context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Text", field.Text); + context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Url", field.Value); + context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Target", field.Target); + } } protected override void Describe(DescribeMembersContext context) { diff --git a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/NumericFieldDriver.cs b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/NumericFieldDriver.cs index 95114fe2b..326c25a97 100644 --- a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/NumericFieldDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/NumericFieldDriver.cs @@ -104,7 +104,8 @@ namespace Orchard.Fields.Drivers { } protected override void Exporting(ContentPart part, NumericField field, ExportContentContext context) { - context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Value", !field.Value.HasValue ? String.Empty : field.Value.Value.ToString(CultureInfo.InvariantCulture)); + if (field.Value.HasValue) + context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Value", field.Value.Value.ToString(CultureInfo.InvariantCulture)); } protected override void Describe(DescribeMembersContext context) { diff --git a/src/Orchard.Web/Modules/Orchard.Fields/Module.txt b/src/Orchard.Web/Modules/Orchard.Fields/Module.txt index 5e8bec54d..bda7b95f0 100644 --- a/src/Orchard.Web/Modules/Orchard.Fields/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Fields/Module.txt @@ -2,7 +2,7 @@ Name: Fields AntiForgery: enabled Author: Antoine Griffard, Sbastien Ros Website: http://orchardfields.codeplex.com -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: Some content fields Features: diff --git a/src/Orchard.Web/Modules/Orchard.Fields/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Fields/Properties/AssemblyInfo.cs index 0243b4fab..4ed61055a 100644 --- a/src/Orchard.Web/Modules/Orchard.Fields/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Fields/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.Fields/Views/EditorTemplates/Fields/Enumeration.Edit.cshtml b/src/Orchard.Web/Modules/Orchard.Fields/Views/EditorTemplates/Fields/Enumeration.Edit.cshtml index b5fec779d..ca39d9ade 100644 --- a/src/Orchard.Web/Modules/Orchard.Fields/Views/EditorTemplates/Fields/Enumeration.Edit.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Fields/Views/EditorTemplates/Fields/Enumeration.Edit.cshtml @@ -8,34 +8,34 @@ @switch (settings.ListMode) { case ListMode.Dropdown: - @Html.DropDownListFor(m => m.Value, new SelectList(options, Model.Value)) + @Html.DropDownListFor(m => m.Value, new SelectList(options, Model.Value), settings.Required ? new {required = "required"} : null) break; case ListMode.Radiobutton: foreach (var option in options) { - if (string.IsNullOrWhiteSpace(option)) { - - } + if (string.IsNullOrWhiteSpace(option)) { + + } else { - - } + + } } break; case ListMode.Listbox: - @Html.ListBoxFor(m => m.SelectedValues, new MultiSelectList(options, Model.SelectedValues)) - break; + @Html.ListBoxFor(m => m.SelectedValues, new MultiSelectList(options, Model.SelectedValues), settings.Required ? new {required = "required"} : null) + break; case ListMode.Checkbox: - int index = 0; + int index = 0; foreach (var option in options) { index++; if (!string.IsNullOrWhiteSpace(option)) {
- - + required="required" } /> +
} } diff --git a/src/Orchard.Web/Modules/Orchard.Fields/Views/EditorTemplates/Fields/Numeric.Edit.cshtml b/src/Orchard.Web/Modules/Orchard.Fields/Views/EditorTemplates/Fields/Numeric.Edit.cshtml index 369dd5658..9a7a400a9 100644 --- a/src/Orchard.Web/Modules/Orchard.Fields/Views/EditorTemplates/Fields/Numeric.Edit.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Fields/Views/EditorTemplates/Fields/Numeric.Edit.cshtml @@ -4,7 +4,9 @@
- @Html.TextBoxFor(m => m.Value, new { @class = "text small", type = "text", min = (Model.Settings.Minimum.HasValue) ? Model.Settings.Minimum.Value : 0, max = (Model.Settings.Maximum.HasValue) ? Model.Settings.Maximum.Value : 1000000, step = Math.Pow(10, 0 - Model.Settings.Scale).ToString(CultureInfo.InvariantCulture) }) + @(Model.Settings.Required + ? Html.TextBoxFor(m => m.Value, new {@class = "text-small", type = "text", min = (Model.Settings.Minimum.HasValue) ? Model.Settings.Minimum.Value : 0, max = (Model.Settings.Maximum.HasValue) ? Model.Settings.Maximum.Value : 1000000, step = Math.Pow(10, 0 - Model.Settings.Scale).ToString(CultureInfo.InvariantCulture), required = "required"}) + : Html.TextBoxFor(m => m.Value, new {@class = "text-small", type = "text", min = (Model.Settings.Minimum.HasValue) ? Model.Settings.Minimum.Value : 0, max = (Model.Settings.Maximum.HasValue) ? Model.Settings.Maximum.Value : 1000000, step = Math.Pow(10, 0 - Model.Settings.Scale).ToString(CultureInfo.InvariantCulture)})) @Html.ValidationMessageFor(m => m.Value) @if (HasText(Model.Settings.Hint)) { @Model.Settings.Hint diff --git a/src/Orchard.Web/Modules/Orchard.Forms/Module.txt b/src/Orchard.Web/Modules/Orchard.Forms/Module.txt index 2e0319fd3..4a8fed3d7 100644 --- a/src/Orchard.Web/Modules/Orchard.Forms/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Forms/Module.txt @@ -2,7 +2,7 @@ Name: Forms AntiForgery: enabled Author: The Orchard Team Website: http://orchardforms.codeplex.com -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: Provides a system to publish and alter html forms. Features: diff --git a/src/Orchard.Web/Modules/Orchard.Forms/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Forms/Properties/AssemblyInfo.cs index 5cbaaaa4d..1fc377313 100644 --- a/src/Orchard.Web/Modules/Orchard.Forms/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Forms/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.ImageEditor/Controllers/AdminController.cs index 595db7cf3..ffe66206d 100644 --- a/src/Orchard.Web/Modules/Orchard.ImageEditor/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Controllers/AdminController.cs @@ -45,6 +45,15 @@ namespace Orchard.ImageEditor.Controllers { [Themed(false)] public ActionResult Edit(string folderPath, string filename) { + if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia)) + return new HttpUnauthorizedResult(); + + // Check permission. + var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder(); + if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) { + return new HttpUnauthorizedResult(); + } + var media = Services.ContentManager.Query().Where(x => x.FolderPath == folderPath && x.FileName == filename).Slice(0, 1).FirstOrDefault(); if (media == null) { @@ -64,12 +73,21 @@ namespace Orchard.ImageEditor.Controllers { [HttpPost] public ActionResult Upload(int id, string content, int width, int height) { + if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia)) + return new HttpUnauthorizedResult(); + var media = Services.ContentManager.Get(id).As(); if (media == null) { return HttpNotFound(); } + // Check permission. + var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder(); + if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(media.FolderPath)) { + return new HttpUnauthorizedResult(); + } + const string signature = "data:image/jpeg;base64,"; if (!content.StartsWith(signature, StringComparison.OrdinalIgnoreCase)) { @@ -96,7 +114,7 @@ namespace Orchard.ImageEditor.Controllers { } public ActionResult Proxy(string url) { - if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent)) + if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia)) return HttpNotFound(); var sslFailureCallback = new RemoteCertificateValidationCallback((o, cert, chain, errors) => true); diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Module.txt b/src/Orchard.Web/Modules/Orchard.ImageEditor/Module.txt index fde3fe0df..24825db85 100644 --- a/src/Orchard.Web/Modules/Orchard.ImageEditor/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Module.txt @@ -2,7 +2,7 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: Adds a client side image editor for Media Library Features: diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.ImageEditor/Properties/AssemblyInfo.cs index db9ee8615..0ff254799 100644 --- a/src/Orchard.Web/Modules/Orchard.ImageEditor/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Properties/AssemblyInfo.cs @@ -31,6 +31,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.ImportExport/Models/ExportContext.cs b/src/Orchard.Web/Modules/Orchard.ImportExport/Models/ExportContext.cs index 6d702593b..f829d360f 100644 --- a/src/Orchard.Web/Modules/Orchard.ImportExport/Models/ExportContext.cs +++ b/src/Orchard.Web/Modules/Orchard.ImportExport/Models/ExportContext.cs @@ -1,8 +1,10 @@ -using System.Xml.Linq; +using System; +using System.Xml.Linq; namespace Orchard.ImportExport.Models { public class ExportContext { public XDocument Document { get; set; } + [Obsolete] public ExportOptions ExportOptions { get; set; } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ImportExport/Models/SetupContext.cs b/src/Orchard.Web/Modules/Orchard.ImportExport/Models/SetupContext.cs deleted file mode 100644 index 0727bd888..000000000 --- a/src/Orchard.Web/Modules/Orchard.ImportExport/Models/SetupContext.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.Generic; -using System.Xml.Linq; - -namespace Orchard.ImportExport.Models { - public class SetupContext { - public string SiteName { get; set; } - public string AdminUsername { get; set; } - public string AdminPassword { get; set; } - public string DatabaseProvider { get; set; } - public string DatabaseConnectionString { get; set; } - public string DatabaseTablePrefix { get; set; } - public IEnumerable EnabledFeatures { get; set; } - public XDocument RecipeDocument { get; set; } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ImportExport/Module.txt b/src/Orchard.Web/Modules/Orchard.ImportExport/Module.txt index 3b6960348..7275d2c0d 100644 --- a/src/Orchard.Web/Modules/Orchard.ImportExport/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.ImportExport/Module.txt @@ -3,7 +3,7 @@ Path: ImportExport AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: Provides content item data import and export capability. Features: @@ -11,4 +11,4 @@ Features: Name: Import Export Description: Imports and exports content item data. Category: Content - Dependencies: Orchard.jQuery, Orchard.Recipes \ No newline at end of file + Dependencies: Orchard.jQuery, Orchard.Recipes, Orchard.Setup.Services diff --git a/src/Orchard.Web/Modules/Orchard.ImportExport/Orchard.ImportExport.csproj b/src/Orchard.Web/Modules/Orchard.ImportExport/Orchard.ImportExport.csproj index 74c14c623..df4c6767f 100644 --- a/src/Orchard.Web/Modules/Orchard.ImportExport/Orchard.ImportExport.csproj +++ b/src/Orchard.Web/Modules/Orchard.ImportExport/Orchard.ImportExport.csproj @@ -90,9 +90,6 @@ - - - @@ -139,6 +136,10 @@ {fc1d74e8-7a4d-48f4-83de-95c6173780c4} Orchard.Recipes + + {8c7fcbc2-e6e1-405e-bfb5-d8d9e67a09c4} + Orchard.Setup + diff --git a/src/Orchard.Web/Modules/Orchard.ImportExport/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.ImportExport/Properties/AssemblyInfo.cs index 6f1259ddc..f0aa0453b 100644 --- a/src/Orchard.Web/Modules/Orchard.ImportExport/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.ImportExport/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.ImportExport/Providers/ImportActions/ExecuteRecipeAction.cs b/src/Orchard.Web/Modules/Orchard.ImportExport/Providers/ImportActions/ExecuteRecipeAction.cs index 9b52d8678..fa3cdb7cd 100644 --- a/src/Orchard.Web/Modules/Orchard.ImportExport/Providers/ImportActions/ExecuteRecipeAction.cs +++ b/src/Orchard.Web/Modules/Orchard.ImportExport/Providers/ImportActions/ExecuteRecipeAction.cs @@ -12,6 +12,7 @@ using Orchard.ImportExport.ViewModels; using Orchard.Mvc; using Orchard.Recipes.Models; using Orchard.Recipes.Services; +using Orchard.Setup.Services; using Orchard.Tasks; using Orchard.UI.Notify; @@ -50,13 +51,16 @@ namespace Orchard.ImportExport.Providers.ImportActions { _sweepGenerator = sweepGenerator; _recipeStepQueue = recipeStepQueue; _recipeStepResultRepository = recipeStepResultRepository; - } + + RecipeExecutionTimeout = 600; + } public override string Name { get { return "ExecuteRecipe"; } } public XDocument RecipeDocument { get; set; } public bool ResetSite { get; set; } public string SuperUserPassword { get; set; } + public int RecipeExecutionTimeout { get; set; } public override dynamic BuildEditor(dynamic shapeFactory) { return UpdateEditor(shapeFactory, null); @@ -148,8 +152,8 @@ namespace Orchard.ImportExport.Providers.ImportActions { // Give each execution step a chance to augment the recipe step before it will be scheduled. PrepareRecipe(recipeDocument); - // Sets the request timeout to 10 minutes to give enough time to execute custom recipes. - _orchardServices.WorkContext.HttpContext.Server.ScriptTimeout = 600; + // Sets the request timeout to a configurable amount of seconds to give enough time to execute custom recipes. + _orchardServices.WorkContext.HttpContext.Server.ScriptTimeout = RecipeExecutionTimeout; // Suspend background task execution. _sweepGenerator.Terminate(); @@ -181,7 +185,7 @@ namespace Orchard.ImportExport.Providers.ImportActions { private string Setup(XDocument recipeDocument) { // Prepare Setup. var setupContext = new SetupContext { - RecipeDocument = recipeDocument, + Recipe = _recipeParser.ParseRecipe(recipeDocument), AdminPassword = SuperUserPassword, AdminUsername = _orchardServices.WorkContext.CurrentSite.SuperUser, DatabaseConnectionString = _shellSettings.DataConnectionString, diff --git a/src/Orchard.Web/Modules/Orchard.ImportExport/Services/ISetupService.cs b/src/Orchard.Web/Modules/Orchard.ImportExport/Services/ISetupService.cs deleted file mode 100644 index 176bf128c..000000000 --- a/src/Orchard.Web/Modules/Orchard.ImportExport/Services/ISetupService.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Orchard.ImportExport.Models; - -namespace Orchard.ImportExport.Services { - public interface ISetupService : IDependency { - string Setup(SetupContext context); - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ImportExport/Services/SetupService.cs b/src/Orchard.Web/Modules/Orchard.ImportExport/Services/SetupService.cs deleted file mode 100644 index c125a21c9..000000000 --- a/src/Orchard.Web/Modules/Orchard.ImportExport/Services/SetupService.cs +++ /dev/null @@ -1,180 +0,0 @@ -using System; -using System.Linq; -using System.Security.Cryptography; -using System.Web; -using Orchard.ContentManagement; -using Orchard.Core.Settings.Models; -using Orchard.Data; -using Orchard.Data.Migration; -using Orchard.Data.Migration.Interpreters; -using Orchard.Data.Migration.Schema; -using Orchard.Environment; -using Orchard.Environment.Configuration; -using Orchard.Environment.Descriptor; -using Orchard.Environment.Descriptor.Models; -using Orchard.Environment.ShellBuilders; -using Orchard.Environment.State; -using Orchard.ImportExport.Models; -using Orchard.Localization.Services; -using Orchard.Logging; -using Orchard.Recipes.Services; -using Orchard.Security; -using Orchard.Settings; -using Orchard.Utility.Extensions; - -namespace Orchard.ImportExport.Services -{ - public class SetupService : Component, ISetupService { - private readonly ShellSettings _shellSettings; - private readonly IOrchardHost _orchardHost; - private readonly IShellSettingsManager _shellSettingsManager; - private readonly IShellContainerFactory _shellContainerFactory; - private readonly ICompositionStrategy _compositionStrategy; - private readonly IProcessingEngine _processingEngine; - - public SetupService( - ShellSettings shellSettings, - IOrchardHost orchardHost, - IShellSettingsManager shellSettingsManager, - IShellContainerFactory shellContainerFactory, - ICompositionStrategy compositionStrategy, - IProcessingEngine processingEngine) { - - _shellSettings = shellSettings; - _orchardHost = orchardHost; - _shellSettingsManager = shellSettingsManager; - _shellContainerFactory = shellContainerFactory; - _compositionStrategy = compositionStrategy; - _processingEngine = processingEngine; - } - - public string Setup(SetupContext context) { - string executionId; - - Logger.Information("Running setup for tenant '{0}'.", _shellSettings.Name); - - // The vanilla Orchard distibution has the following features enabled. - string[] hardcoded = { - // Framework - "Orchard.Framework", - // Core - "Common", "Containers", "Contents", "Dashboard", "Feeds", "Navigation","Scheduling", "Settings", "Shapes", "Title", - // Modules - "Orchard.Pages", "Orchard.ContentPicker", "Orchard.Themes", "Orchard.Users", "Orchard.Roles", "Orchard.Modules", - "PackagingServices", "Orchard.Packaging", "Gallery", "Orchard.Recipes" - }; - - context.EnabledFeatures = hardcoded.Union(context.EnabledFeatures ?? Enumerable.Empty()).Distinct().ToList(); - - var shellSettings = new ShellSettings(_shellSettings); - - if (String.IsNullOrEmpty(shellSettings.DataProvider)) { - shellSettings.DataProvider = context.DatabaseProvider; - shellSettings.DataConnectionString = context.DatabaseConnectionString; - shellSettings.DataTablePrefix = context.DatabaseTablePrefix; - } - - shellSettings.EncryptionAlgorithm = "AES"; - shellSettings.EncryptionKey = SymmetricAlgorithm.Create(shellSettings.EncryptionAlgorithm).Key.ToHexString(); - shellSettings.HashAlgorithm = "HMACSHA256"; - shellSettings.HashKey = HMAC.Create(shellSettings.HashAlgorithm).Key.ToHexString(); - - var shellDescriptor = new ShellDescriptor { - Features = context.EnabledFeatures.Select(name => new ShellFeature { Name = name }) - }; - - var shellBlueprint = _compositionStrategy.Compose(shellSettings, shellDescriptor); - - // Initialize database explicitly, and store shell descriptor. - using (var bootstrapLifetimeScope = _shellContainerFactory.CreateContainer(shellSettings, shellBlueprint)) { - using (var environment = bootstrapLifetimeScope.CreateWorkContextScope()) { - // Workaround to avoid a Transaction issue with PostgreSQL. - environment.Resolve().RequireNew(); - - var schemaBuilder = new SchemaBuilder(environment.Resolve()); - - schemaBuilder.CreateTable("Orchard_Framework_DataMigrationRecord", table => table - .Column("Id", column => column.PrimaryKey().Identity()) - .Column("DataMigrationClass") - .Column("Version")); - - schemaBuilder.AlterTable("Orchard_Framework_DataMigrationRecord", - table => table.AddUniqueConstraint("UC_DMR_DataMigrationClass_Version", "DataMigrationClass", "Version")); - - var dataMigrationManager = environment.Resolve(); - dataMigrationManager.Update("Settings"); - - foreach (var feature in context.EnabledFeatures) { - dataMigrationManager.Update(feature); - } - - var descriptorManager = environment.Resolve(); - descriptorManager.UpdateShellDescriptor(0, shellDescriptor.Features, shellDescriptor.Parameters); - } - } - - // In effect "pump messages" see PostMessage circa 1980. - while ( _processingEngine.AreTasksPending() ) - _processingEngine.ExecuteNextTask(); - - // Create a standalone environment. - // Must mark state as Running - otherwise standalone environment is created "for setup". - shellSettings.State = TenantState.Running; - using (var environment = _orchardHost.CreateStandaloneEnvironment(shellSettings)) { - try { - executionId = CreateTenantData(context, environment); - } - catch { - environment.Resolve().Cancel(); - throw; - } - } - - _shellSettingsManager.SaveSettings(shellSettings); - - return executionId; - } - - private string CreateTenantData(SetupContext context, IWorkContextScope environment) { - // Create superuser. - var membershipService = environment.Resolve(); - var user = membershipService.CreateUser( - new CreateUserParams( - context.AdminUsername, - context.AdminPassword, - email: String.Empty, - passwordQuestion: String.Empty, - passwordAnswer: String.Empty, - isApproved: true)); - - // Set superuser as current user for request (it will be set as the owner of all content items). - var authenticationService = environment.Resolve(); - authenticationService.SetAuthenticatedUserForRequest(user); - - // Set site name and settings. - var siteService = environment.Resolve(); - var siteSettings = siteService.GetSiteSettings().As(); - siteSettings.SiteSalt = Guid.NewGuid().ToString("N"); - siteSettings.SiteName = context.SiteName; - siteSettings.SuperUser = context.AdminUsername; - siteSettings.SiteCulture = "en-US"; - - // Add default culture. - var cultureManager = environment.Resolve(); - cultureManager.AddCulture("en-US"); - - // Execute recipe - var recipeParser = environment.Resolve(); - var recipe = recipeParser.ParseRecipe(context.RecipeDocument); - var recipeManager = environment.Resolve(); - var executionId = recipeManager.Execute(recipe); - - // Null check: temporary fix for running setup in command line. - if (HttpContext.Current != null) { - authenticationService.SignIn(user, true); - } - - return executionId; - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Module.txt b/src/Orchard.Web/Modules/Orchard.Indexing/Module.txt index 99ab8cfca..122669177 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Module.txt @@ -2,7 +2,7 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: The Indexing module enables the site to be indexed. The index generated by this module can then be used by the search module to provide an integrated full-text search experience to a web site. FeatureDescription: Indexing infrastructure. Requires an index implementation like the Lucene module. diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Properties/AssemblyInfo.cs index 999336b2c..eefbb569d 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.JobsQueue/Module.txt b/src/Orchard.Web/Modules/Orchard.JobsQueue/Module.txt index 05186f82d..48b0c9042 100644 --- a/src/Orchard.Web/Modules/Orchard.JobsQueue/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.JobsQueue/Module.txt @@ -2,7 +2,7 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: This module provides a jobs queue to process jobs asynchronously. Features: diff --git a/src/Orchard.Web/Modules/Orchard.JobsQueue/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.JobsQueue/Properties/AssemblyInfo.cs index 43830bba5..fa1bc9edb 100644 --- a/src/Orchard.Web/Modules/Orchard.JobsQueue/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.JobsQueue/Properties/AssemblyInfo.cs @@ -31,6 +31,6 @@ using System.Security; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.JobsQueue/Services/JobsQueueProcessor.cs b/src/Orchard.Web/Modules/Orchard.JobsQueue/Services/JobsQueueProcessor.cs index 039bfbc75..74bec9bb6 100644 --- a/src/Orchard.Web/Modules/Orchard.JobsQueue/Services/JobsQueueProcessor.cs +++ b/src/Orchard.Web/Modules/Orchard.JobsQueue/Services/JobsQueueProcessor.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading; using Newtonsoft.Json.Linq; using Orchard.Environment; using Orchard.Events; @@ -13,12 +12,11 @@ namespace Orchard.JobsQueue.Services { public class JobsQueueProcessor : IJobsQueueProcessor { private readonly Work _jobsQueueManager; private readonly Work _eventBus; - private readonly ReaderWriterLockSlim _rwl = new ReaderWriterLockSlim(); private readonly IDistributedLockService _distributedLockService; public JobsQueueProcessor( Work jobsQueueManager, - Work eventBus, + Work eventBus, IDistributedLockService distributedLockService) { _jobsQueueManager = jobsQueueManager; @@ -28,26 +26,19 @@ namespace Orchard.JobsQueue.Services { } public ILogger Logger { get; set; } - public void ProcessQueue() { - // prevent two threads on the same machine to process the message queue - if (_rwl.TryEnterWriteLock(0)) { - try { - DistributedLock @lock; - if(_distributedLockService.TryAcquireLockForMachine(GetType().FullName, TimeSpan.FromMinutes(5), out @lock)){ - using (@lock) { - IEnumerable messages; - while ((messages = _jobsQueueManager.Value.GetJobs(0, 10).ToArray()).Any()) { - foreach (var message in messages) { - ProcessMessage(message); - } - } + public void ProcessQueue() { + IDistributedLock @lock; + if (_distributedLockService.TryAcquireLock(GetType().FullName, TimeSpan.FromMinutes(5), out @lock)) { + using (@lock) { + IEnumerable messages; + + while ((messages = _jobsQueueManager.Value.GetJobs(0, 10).ToArray()).Any()) { + foreach (var message in messages) { + ProcessMessage(message); } } } - finally { - _rwl.ExitWriteLock(); - } } } diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/AdminMenu.cs b/src/Orchard.Web/Modules/Orchard.Layouts/AdminMenu.cs index 35db9afee..0a675af3d 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/AdminMenu.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/AdminMenu.cs @@ -11,9 +11,9 @@ namespace Orchard.Layouts { builder .AddImageSet("layouts") .Add(T("Layouts"), "8.5", layouts => layouts - .Action("List", "Admin", new {id = "Layout", area = "Contents"}) + .Action("List", "Admin", new {id = "Layout", area = "Contents"}).Permission(Permissions.ManageLayouts) .LinkToFirstChild(false) - .Add(T("Elements"), "1", elements => elements.Action("Index", "BlueprintAdmin", new {area = "Orchard.Layouts"}))); + .Add(T("Elements"), "1", elements => elements.Action("Index", "BlueprintAdmin", new {area = "Orchard.Layouts"}).Permission(Permissions.ManageLayouts))); } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Assets/JavaScript/LayoutEditor/Directives/Editor.js b/src/Orchard.Web/Modules/Orchard.Layouts/Assets/JavaScript/LayoutEditor/Directives/Editor.js index 8595615e8..b7dcde8aa 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Assets/JavaScript/LayoutEditor/Directives/Editor.js +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Assets/JavaScript/LayoutEditor/Directives/Editor.js @@ -74,45 +74,6 @@ return host.addElement(contentType); }; - $scope.toggleInlineEditing = function () { - if (!$scope.element.inlineEditingIsActive) { - $scope.element.inlineEditingIsActive = true; - $element.find(".layout-toolbar-container").show(); - var selector = "#layout-editor-" + $scope.$id + " .layout-html .layout-content-markup[data-templated=false]"; - var firstContentEditorId = $(selector).first().attr("id"); - tinymce.init({ - selector: selector, - theme: "modern", - schema: "html5", - plugins: [ - "advlist autolink lists link image charmap print preview hr anchor pagebreak", - "searchreplace wordcount visualblocks visualchars code fullscreen", - "insertdatetime media nonbreaking table contextmenu directionality", - "emoticons template paste textcolor colorpicker textpattern", - "fullscreen autoresize" - ], - toolbar: "undo redo cut copy paste | bold italic | bullist numlist outdent indent formatselect | alignleft aligncenter alignright alignjustify ltr rtl | link unlink charmap | code fullscreen close", - convert_urls: false, - valid_elements: "*[*]", - // Shouldn't be needed due to the valid_elements setting, but TinyMCE would strip script.src without it. - extended_valid_elements: "script[type|defer|src|language]", - statusbar: false, - skin: "orchardlightgray", - inline: true, - fixed_toolbar_container: "#layout-editor-" + $scope.$id + " .layout-toolbar-container", - init_instance_callback: function (editor) { - if (editor.id == firstContentEditorId) - tinymce.execCommand("mceFocus", false, editor.id); - } - }); - } - else { - tinymce.remove("#layout-editor-" + $scope.$id + " .layout-content-markup"); - $element.find(".layout-toolbar-container").hide(); - $scope.element.inlineEditingIsActive = false; - } - }; - $(document).on("cut copy paste", function (e) { // If the pseudo clipboard was already invoked (which happens on the first clipboard // operation after page load even if native clipboard support exists) then sit this @@ -164,23 +125,12 @@ element.find(".layout-toolbar-container").click(function (e) { e.stopPropagation(); }); - // Intercept mousedown on editor while in inline editing mode to - // prevent current editor from losing focus. - element.mousedown(function (e) { - if (scope.element.inlineEditingIsActive) { - e.preventDefault(); - e.stopPropagation(); - } - }) // Unfocus and unselect everything on click outside of canvas. $(window).click(function (e) { - // Except when in inline editing mode. - if (!scope.element.inlineEditingIsActive) { - scope.$apply(function () { - scope.element.activeElement = null; - scope.element.focusedElement = null; - }); - } + scope.$apply(function () { + scope.element.activeElement = null; + scope.element.focusedElement = null; + }); }); } }; diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Assets/JavaScript/LayoutEditor/Directives/Html.js b/src/Orchard.Web/Modules/Orchard.Layouts/Assets/JavaScript/LayoutEditor/Directives/Html.js index 4dc6a4f1e..94890f1d6 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Assets/JavaScript/LayoutEditor/Directives/Html.js +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Assets/JavaScript/LayoutEditor/Directives/Html.js @@ -35,13 +35,6 @@ templateUrl: environment.templateUrl("Html"), replace: true, link: function (scope, element) { - // Mouse down events must not be intercepted by drag and drop while inline editing is active, - // otherwise clicks in inline editors will have no effect. - element.find(".layout-content-markup").mousedown(function (e) { - if (scope.element.editor.inlineEditingIsActive) { - e.stopPropagation(); - } - }); } }; } diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Assets/JavaScript/LayoutEditor/Services/ScopeConfigurator.js b/src/Orchard.Web/Modules/Orchard.Layouts/Assets/JavaScript/LayoutEditor/Services/ScopeConfigurator.js index 988fdde43..a2ce3a6ba 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Assets/JavaScript/LayoutEditor/Services/ScopeConfigurator.js +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Assets/JavaScript/LayoutEditor/Services/ScopeConfigurator.js @@ -15,7 +15,7 @@ var resetFocus = false; var element = $scope.element; - if (element.editor.isDragging || element.editor.inlineEditingIsActive) + if (element.editor.isDragging) return; // If native clipboard support exists, the pseudo-clipboard will have been disabled. diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Assets/JavaScript/Models/Editor.js b/src/Orchard.Web/Modules/Orchard.Layouts/Assets/JavaScript/Models/Editor.js index a93081991..86b664804 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Assets/JavaScript/Models/Editor.js +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Assets/JavaScript/Models/Editor.js @@ -9,7 +9,6 @@ this.focusedElement = null; this.dropTargetElement = null; this.isDragging = false; - this.inlineEditingIsActive = false; this.isResizing = false; this.resetToolboxElements = function () { diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Assets/JavaScript/Models/Element.js b/src/Orchard.Web/Modules/Orchard.Layouts/Assets/JavaScript/Models/Element.js index 6f30d5508..6a983cf25 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Assets/JavaScript/Models/Element.js +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Assets/JavaScript/Models/Element.js @@ -57,7 +57,7 @@ this.setIsActive = function (value) { if (!this.editor) return; - if (this.editor.isDragging || this.editor.inlineEditingIsActive || this.editor.isResizing) + if (this.editor.isDragging || this.editor.isResizing) return; if (value) @@ -77,7 +77,7 @@ return; if (!this.children && this.isTemplated) return; - if (this.editor.isDragging || this.editor.inlineEditingIsActive || this.editor.isResizing) + if (this.editor.isDragging || this.editor.isResizing) return; this.editor.focusedElement = this; diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Assets/Less/LayoutEditor/Canvas.less b/src/Orchard.Web/Modules/Orchard.Layouts/Assets/Less/LayoutEditor/Canvas.less index aab898205..ec7aba16f 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Assets/Less/LayoutEditor/Canvas.less +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Assets/Less/LayoutEditor/Canvas.less @@ -6,4 +6,4 @@ display: none; } } -} +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Controllers/BlueprintAdminController.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Controllers/BlueprintAdminController.cs index 1dcac2e31..6c5b8ae36 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Controllers/BlueprintAdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Controllers/BlueprintAdminController.cs @@ -34,7 +34,8 @@ namespace Orchard.Layouts.Controllers { ICultureAccessor cultureAccessor, IShapeFactory shapeFactory, ITransactionManager transactionManager, - ISignals signals) { + ISignals signals, + IOrchardServices orchardServices) { _elementBlueprintService = elementBlueprintService; _notifier = notifier; @@ -43,12 +44,19 @@ namespace Orchard.Layouts.Controllers { _shapeFactory = shapeFactory; _transactionManager = transactionManager; _signals = signals; + Services = orchardServices; + T = NullLocalizer.Instance; } + public IOrchardServices Services { get; set; } public Localizer T { get; set; } public ActionResult Index() { + if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) { + return new HttpUnauthorizedResult(); + } + var blueprints = _elementBlueprintService.GetBlueprints().ToArray(); var viewModel = new BlueprintsIndexViewModel { Blueprints = blueprints @@ -57,6 +65,10 @@ namespace Orchard.Layouts.Controllers { } public ActionResult Browse() { + if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) { + return new HttpUnauthorizedResult(); + } + var categories = RemoveBlueprints(_elementManager.GetCategories(DescribeElementsContext.Empty)).ToArray(); var viewModel = new BrowseElementsViewModel { Categories = categories @@ -65,6 +77,10 @@ namespace Orchard.Layouts.Controllers { } public ActionResult Create(string id) { + if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) { + return new HttpUnauthorizedResult(); + } + if (String.IsNullOrWhiteSpace(id)) return RedirectToAction("Browse"); @@ -80,6 +96,10 @@ namespace Orchard.Layouts.Controllers { [HttpPost] public ActionResult Create(string id, CreateElementBlueprintViewModel model) { + if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) { + return new HttpUnauthorizedResult(); + } + var describeContext = DescribeElementsContext.Empty; var descriptor = _elementManager.GetElementDescriptorByTypeName(describeContext, id); var baseElement = _elementManager.ActivateElement(descriptor); @@ -100,7 +120,11 @@ namespace Orchard.Layouts.Controllers { return RedirectToAction("Edit", new { id = blueprint.Id }); } - public ViewResult Edit(int id) { + public ActionResult Edit(int id) { + if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) { + return new HttpUnauthorizedResult(); + } + var blueprint = _elementBlueprintService.GetBlueprint(id); var describeContext = DescribeElementsContext.Empty; var descriptor = _elementManager.GetElementDescriptorByTypeName(describeContext, blueprint.BaseElementTypeName); @@ -125,6 +149,10 @@ namespace Orchard.Layouts.Controllers { [HttpPost] [ValidateInput(false)] public ActionResult Edit(int id, ElementDataViewModel model) { + if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) { + return new HttpUnauthorizedResult(); + } + var blueprint = _elementBlueprintService.GetBlueprint(id); var describeContext = DescribeElementsContext.Empty; var descriptor = _elementManager.GetElementDescriptorByTypeName(describeContext, blueprint.BaseElementTypeName); @@ -154,6 +182,10 @@ namespace Orchard.Layouts.Controllers { } public ActionResult Properties(int id) { + if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) { + return new HttpUnauthorizedResult(); + } + var blueprint = _elementBlueprintService.GetBlueprint(id); var describeContext = DescribeElementsContext.Empty; var descriptor = _elementManager.GetElementDescriptorByTypeName(describeContext, blueprint.BaseElementTypeName); @@ -171,6 +203,10 @@ namespace Orchard.Layouts.Controllers { [HttpPost] public ActionResult Properties(int id, ElementBlueprintPropertiesViewModel model) { + if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) { + return new HttpUnauthorizedResult(); + } + var blueprint = _elementBlueprintService.GetBlueprint(id); var describeContext = DescribeElementsContext.Empty; var descriptor = _elementManager.GetElementDescriptorByTypeName(describeContext, blueprint.BaseElementTypeName); @@ -191,7 +227,12 @@ namespace Orchard.Layouts.Controllers { return RedirectToAction("Index"); } + [HttpPost] public ActionResult Delete(int id) { + if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) { + return new HttpUnauthorizedResult(); + } + var blueprint = _elementBlueprintService.GetBlueprint(id); if (blueprint == null) @@ -204,7 +245,12 @@ namespace Orchard.Layouts.Controllers { [FormValueRequired("submit.BulkEdit")] [ActionName("Index")] + [HttpPost] public ActionResult BulkDelete(IEnumerable blueprintIds) { + if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) { + return new HttpUnauthorizedResult(); + } + if (blueprintIds == null || !blueprintIds.Any()) { _notifier.Error(T("Please select the blueprints to delete.")); } diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Controllers/ElementController.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Controllers/ElementController.cs index 170bdfb19..38dffa4ce 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Controllers/ElementController.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Controllers/ElementController.cs @@ -142,18 +142,7 @@ namespace Orchard.Layouts.Controllers { _objectStore.Set(session, state); return RedirectToAction("Edit", new {session = session}); } - - public RedirectToRouteResult Add(string session, string typeName, int? contentId = null, string contentType = null) { - var state = new ElementSessionState { - TypeName = typeName, - ContentId = contentId, - ContentType = contentType - }; - - _objectStore.Set(session, state); - return RedirectToAction("Edit", new { session = session }); - } - + public ViewResult Edit(string session) { var sessionState = _objectStore.Get(session); var contentId = sessionState.ContentId; diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Controllers/LayoutController.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Controllers/LayoutController.cs index 753bd9aa8..a72f1783b 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Controllers/LayoutController.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Controllers/LayoutController.cs @@ -6,6 +6,7 @@ using Orchard.ContentManagement; using Orchard.Layouts.Elements; using Orchard.Layouts.Framework.Elements; using Orchard.Layouts.Services; +using Orchard.Localization; using Orchard.UI.Admin; namespace Orchard.Layouts.Controllers { @@ -15,15 +16,25 @@ namespace Orchard.Layouts.Controllers { private readonly ILayoutManager _layoutManager; private readonly ILayoutModelMapper _mapper; - public LayoutController(IContentManager contentManager, ILayoutManager layoutManager, ILayoutModelMapper mapper) { + public LayoutController( + IContentManager contentManager, + ILayoutManager layoutManager, + ILayoutModelMapper mapper, + IOrchardServices orchardServices) { _contentManager = contentManager; _layoutManager = layoutManager; _mapper = mapper; + Services = orchardServices; + + T = NullLocalizer.Instance; } + public IOrchardServices Services { get; set; } + public Localizer T { get; set; } + [HttpPost, ValidateInput(enableValidation: false)] - public ContentResult ApplyTemplate(int? templateId = null, string layoutData = null, int? contentId = null, string contentType = null) { + public ActionResult ApplyTemplate(int? templateId = null, string layoutData = null, int? contentId = null, string contentType = null) { var template = templateId != null ? _layoutManager.GetLayout(templateId.Value) : null; var templateElements = template != null ? _layoutManager.LoadElements(template).ToList() : default(IEnumerable); var describeContext = CreateDescribeElementsContext(contentId, contentType); diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Drivers/LayoutPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Drivers/LayoutPartDriver.cs index 116ab44bc..ace0e73fa 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Drivers/LayoutPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Drivers/LayoutPartDriver.cs @@ -90,9 +90,18 @@ namespace Orchard.Layouts.Drivers { protected override DriverResult Editor(LayoutPart part, IUpdateModel updater, dynamic shapeHelper) { return ContentShape("Parts_Layout_Edit", () => { - if (part.Id == 0 && String.IsNullOrWhiteSpace(part.LayoutData)) { - part.LayoutData = part.TypePartDefinition.Settings.GetModel().DefaultLayoutData; + + var settings = part.TypePartDefinition.Settings.GetModel(); + + // If the default layout setting is left empty, use the one from the service + if (String.IsNullOrWhiteSpace(settings.DefaultLayoutData)) { + var defaultData = _serializer.Serialize(_layoutManager.CreateDefaultLayout()); + part.LayoutData = defaultData; + } + else { + part.LayoutData = settings.DefaultLayoutData; + } } var viewModel = new LayoutPartViewModel { @@ -140,6 +149,11 @@ namespace Orchard.Layouts.Drivers { } protected override void Importing(LayoutPart part, ImportContentContext context) { + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; + } + context.ImportChildEl(part.PartDefinition.Name, "LayoutData", s => { part.LayoutData = s; _layoutManager.Importing(new ImportLayoutContext { diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Drivers/ProjectionElementDriver.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Drivers/ProjectionElementDriver.cs index d42f56128..ec8f4631c 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Drivers/ProjectionElementDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Drivers/ProjectionElementDriver.cs @@ -290,11 +290,11 @@ namespace Orchard.Layouts.Drivers { var query = element.QueryId != null ? _contentManager.Get(element.QueryId.Value) : default(QueryPart); var layout = query != null && element.LayoutId != null ? _layoutRepository.Get(element.LayoutId.Value) : default(LayoutRecord); var queryIdentity = query != null ? _contentManager.GetItemMetadata(query).Identity.ToString() : default(string); - var layoutIndex = layout != null ? query.Layouts.IndexOf(layout) : default(int?); + var layoutIndex = layout != null ? query.Layouts.IndexOf(layout) : -1; // -1 is the Default Layout. - if (queryIdentity != null && layoutIndex != null) { + if (queryIdentity != null) { context.ExportableData["QueryId"] = queryIdentity; - context.ExportableData["LayoutIndex"] = layoutIndex.Value.ToString(); + context.ExportableData["LayoutIndex"] = layoutIndex.ToString(); } } @@ -307,10 +307,9 @@ namespace Orchard.Layouts.Drivers { var queryPart = query.As(); var layoutIndex = XmlHelper.Parse(context.ExportableData.Get("LayoutIndex")); - var layout = queryPart.Layouts[layoutIndex]; element.QueryId = queryPart.Id; - element.LayoutId = layout.Id; + element.LayoutId = layoutIndex != -1 ? queryPart.Layouts[layoutIndex].Id : -1; } private static string GetLayoutDescription(IEnumerable layouts, LayoutRecord l) { diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Elements/Column.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Elements/Column.cs index 7f87b3e0d..f0b8d3e0a 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Elements/Column.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Elements/Column.cs @@ -21,7 +21,7 @@ namespace Orchard.Layouts.Elements { } public int? Width { - get { return this.Retrieve("Width") ?? this.Retrieve("ColumnSpan") ?? 0; } // Falling back on "ColumnSpan" for backward compatibility. + get { return this.Retrieve("Width") ?? this.Retrieve("ColumnSpan") ?? 12; } // Falling back on "ColumnSpan" for backward compatibility. set { this.Store(x => x.Width, value); } } diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Framework/Elements/Element.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Framework/Elements/Element.cs index 87959efaf..16aa590e6 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Framework/Elements/Element.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Framework/Elements/Element.cs @@ -3,7 +3,7 @@ using Orchard.Localization; using Orchard.Utility.Extensions; namespace Orchard.Layouts.Framework.Elements { - public abstract class Element { + public abstract class Element : IElement { protected Element() { T = NullLocalizer.Instance; Data = new ElementDataDictionary(); diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Framework/Elements/IElement.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Framework/Elements/IElement.cs new file mode 100644 index 000000000..0cf0c8f1f --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Framework/Elements/IElement.cs @@ -0,0 +1,3 @@ +namespace Orchard.Layouts.Framework.Elements { + public interface IElement : ITransientDependency {} +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Handlers/LayoutPartHandler.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Handlers/LayoutPartHandler.cs index 78f9a595b..0e2c3b37a 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Handlers/LayoutPartHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Handlers/LayoutPartHandler.cs @@ -16,7 +16,6 @@ namespace Orchard.Layouts.Handlers { private readonly IContentPartDisplay _contentPartDisplay; private readonly IShapeDisplay _shapeDisplay; private readonly ILayoutSerializer _serializer; - private readonly IStaticHttpContextScopeFactory _staticHttpContextScopeFactory; private readonly IAliasService _aliasService; public LayoutPartHandler( @@ -26,7 +25,6 @@ namespace Orchard.Layouts.Handlers { IContentPartDisplay contentPartDisplay, IShapeDisplay shapeDisplay, ILayoutSerializer serializer, - IStaticHttpContextScopeFactory staticHttpContextScopeFactory, IAliasService aliasService) { _layoutManager = layoutManager; @@ -34,7 +32,6 @@ namespace Orchard.Layouts.Handlers { _contentPartDisplay = contentPartDisplay; _shapeDisplay = shapeDisplay; _serializer = serializer; - _staticHttpContextScopeFactory = staticHttpContextScopeFactory; _aliasService = aliasService; Filters.Add(StorageFilter.For(repository)); @@ -44,22 +41,13 @@ namespace Orchard.Layouts.Handlers { private void IndexLayout(IndexContentContext context, LayoutPart part) { var layoutShape = _contentPartDisplay.BuildDisplay(part); - var layoutHtml = RenderShape(layoutShape); + var layoutHtml = _shapeDisplay.Display(layoutShape); context.DocumentIndex .Add("body", layoutHtml).RemoveTags().Analyze() .Add("format", "html").Store(); } - /// - /// This method of rendering is safe even in background tasks. - /// - private string RenderShape(dynamic shape) { - using (_staticHttpContextScopeFactory.CreateStaticScope()) { - return _shapeDisplay.Display(shape); - } - } - private void UpdateTemplateClients(PublishContentContext context, LayoutPart part) { UpdateTemplateClients(part); } diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Migrations.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Migrations.cs index c87ade13c..746120763 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Migrations.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Migrations.cs @@ -33,7 +33,6 @@ namespace Orchard.Layouts { .WithPart("LayoutPart", p => p .WithSetting("LayoutTypePartSettings.IsTemplate", "True")) .DisplayedAs("Layout") - .Listable() .Draftable()); ContentDefinitionManager.AlterTypeDefinition("LayoutWidget", type => type diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Models/ElementSessionState.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Models/ElementSessionState.cs index 26859a51f..6fcff6c7f 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Models/ElementSessionState.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Models/ElementSessionState.cs @@ -1,9 +1,12 @@ +using System; + namespace Orchard.Layouts.Models { - public class ElementSessionState { + [Serializable] + public class ElementSessionState { public string TypeName { get; set; } public string ElementData { get; set; } public string ElementEditorData { get; set; } public int? ContentId { get; set; } public string ContentType { get; set; } } -} \ No newline at end of file +} diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Module.txt b/src/Orchard.Web/Modules/Orchard.Layouts/Module.txt index 6e61893e6..4f21508df 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Module.txt @@ -10,7 +10,7 @@ Features: Orchard.Layouts: Name: Layouts Description: Provides tools to create layouts. - Dependencies: Common, Orchard.jQuery, Orchard.Forms, Orchard.Tokens, Orchard.MediaLibrary, TinyMce, Orchard.Widgets + Dependencies: Common, Orchard.jQuery, Orchard.Forms, Orchard.Tokens, Orchard.MediaLibrary, Orchard.Widgets Category: Layout Orchard.Layouts.Snippets: Name: Layout Snippets diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Orchard.Layouts.csproj b/src/Orchard.Web/Modules/Orchard.Layouts/Orchard.Layouts.csproj index 39ace50e4..c25bf3fb8 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Orchard.Layouts.csproj +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Orchard.Layouts.csproj @@ -358,6 +358,7 @@ + @@ -367,6 +368,7 @@ + diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Permissions.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Permissions.cs new file mode 100644 index 000000000..a7905be9b --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Permissions.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using Orchard.Environment.Extensions.Models; +using Orchard.Security.Permissions; + +namespace Orchard.Layouts { + public class Permissions : IPermissionProvider { + public static readonly Permission ManageLayouts = new Permission { Description = "Managing Layouts", Name = "ManageLayouts" }; + + public virtual Feature Feature { get; set; } + + public IEnumerable GetPermissions() { + return new[] { + ManageLayouts, + }; + } + + public IEnumerable GetDefaultStereotypes() { + return new[] { + new PermissionStereotype { + Name = "Administrator", + Permissions = new[] { ManageLayouts } + }, + new PermissionStereotype { + Name = "Editor", + Permissions = new[] { ManageLayouts } + }, + new PermissionStereotype { + Name = "Moderator", + }, + new PermissionStereotype { + Name = "Author" + }, + new PermissionStereotype { + Name = "Contributor", + }, + }; + } + + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Scripts/LayoutEditor.js b/src/Orchard.Web/Modules/Orchard.Layouts/Scripts/LayoutEditor.js index 405a8f9e7..2be99a094 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Scripts/LayoutEditor.js +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Scripts/LayoutEditor.js @@ -62,7 +62,7 @@ angular var resetFocus = false; var element = $scope.element; - if (element.editor.isDragging || element.editor.inlineEditingIsActive) + if (element.editor.isDragging) return; // If native clipboard support exists, the pseudo-clipboard will have been disabled. @@ -443,45 +443,6 @@ angular return host.addElement(contentType); }; - $scope.toggleInlineEditing = function () { - if (!$scope.element.inlineEditingIsActive) { - $scope.element.inlineEditingIsActive = true; - $element.find(".layout-toolbar-container").show(); - var selector = "#layout-editor-" + $scope.$id + " .layout-html .layout-content-markup[data-templated=false]"; - var firstContentEditorId = $(selector).first().attr("id"); - tinymce.init({ - selector: selector, - theme: "modern", - schema: "html5", - plugins: [ - "advlist autolink lists link image charmap print preview hr anchor pagebreak", - "searchreplace wordcount visualblocks visualchars code fullscreen", - "insertdatetime media nonbreaking table contextmenu directionality", - "emoticons template paste textcolor colorpicker textpattern", - "fullscreen autoresize" - ], - toolbar: "undo redo cut copy paste | bold italic | bullist numlist outdent indent formatselect | alignleft aligncenter alignright alignjustify ltr rtl | link unlink charmap | code fullscreen close", - convert_urls: false, - valid_elements: "*[*]", - // Shouldn't be needed due to the valid_elements setting, but TinyMCE would strip script.src without it. - extended_valid_elements: "script[type|defer|src|language]", - statusbar: false, - skin: "orchardlightgray", - inline: true, - fixed_toolbar_container: "#layout-editor-" + $scope.$id + " .layout-toolbar-container", - init_instance_callback: function (editor) { - if (editor.id == firstContentEditorId) - tinymce.execCommand("mceFocus", false, editor.id); - } - }); - } - else { - tinymce.remove("#layout-editor-" + $scope.$id + " .layout-content-markup"); - $element.find(".layout-toolbar-container").hide(); - $scope.element.inlineEditingIsActive = false; - } - }; - $(document).on("cut copy paste", function (e) { // If the pseudo clipboard was already invoked (which happens on the first clipboard // operation after page load even if native clipboard support exists) then sit this @@ -533,23 +494,12 @@ angular element.find(".layout-toolbar-container").click(function (e) { e.stopPropagation(); }); - // Intercept mousedown on editor while in inline editing mode to - // prevent current editor from losing focus. - element.mousedown(function (e) { - if (scope.element.inlineEditingIsActive) { - e.preventDefault(); - e.stopPropagation(); - } - }) // Unfocus and unselect everything on click outside of canvas. $(window).click(function (e) { - // Except when in inline editing mode. - if (!scope.element.inlineEditingIsActive) { - scope.$apply(function () { - scope.element.activeElement = null; - scope.element.focusedElement = null; - }); - } + scope.$apply(function () { + scope.element.activeElement = null; + scope.element.focusedElement = null; + }); }); } }; @@ -730,13 +680,6 @@ angular templateUrl: environment.templateUrl("Html"), replace: true, link: function (scope, element) { - // Mouse down events must not be intercepted by drag and drop while inline editing is active, - // otherwise clicks in inline editors will have no effect. - element.find(".layout-content-markup").mousedown(function (e) { - if (scope.element.editor.inlineEditingIsActive) { - e.stopPropagation(); - } - }); } }; } @@ -1051,4 +994,4 @@ angular }; } ]); -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIk1vZHVsZS5qcyIsIkNsaXBib2FyZC5qcyIsIlNjb3BlQ29uZmlndXJhdG9yLmpzIiwiRWRpdG9yLmpzIiwiQ2FudmFzLmpzIiwiQ2hpbGQuanMiLCJDb2x1bW4uanMiLCJDb250ZW50LmpzIiwiSHRtbC5qcyIsIkdyaWQuanMiLCJSb3cuanMiLCJQb3B1cC5qcyIsIlRvb2xib3guanMiLCJUb29sYm94R3JvdXAuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQzdDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ2pVQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDM0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDbEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ2RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNuRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDbkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQy9DQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ2xCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDbkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDdkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQzlNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiTGF5b3V0RWRpdG9yLmpzIiwic291cmNlc0NvbnRlbnQiOlsiYW5ndWxhci5tb2R1bGUoXCJMYXlvdXRFZGl0b3JcIiwgW1wibmdTYW5pdGl6ZVwiLCBcIm5nUmVzb3VyY2VcIiwgXCJ1aS5zb3J0YWJsZVwiXSk7IiwidmFyIExheW91dEVkaXRvcjtcclxuKGZ1bmN0aW9uKExheW91dEVkaXRvcikge1xyXG5cclxuICAgIHZhciBDbGlwYm9hcmQgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xyXG4gICAgICAgIHRoaXMuX2NsaXBib2FyZERhdGEgPSB7fTtcclxuICAgICAgICB0aGlzLl9pc0Rpc2FibGVkID0gZmFsc2U7XHJcbiAgICAgICAgdGhpcy5fd2FzSW52b2tlZCA9IGZhbHNlO1xyXG5cclxuICAgICAgICB0aGlzLnNldERhdGEgPSBmdW5jdGlvbihjb250ZW50VHlwZSwgZGF0YSkge1xyXG4gICAgICAgICAgICBzZWxmLl9jbGlwYm9hcmREYXRhW2NvbnRlbnRUeXBlXSA9IGRhdGE7XHJcbiAgICAgICAgICAgIHNlbGYuX3dhc0ludm9rZWQgPSB0cnVlO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgdGhpcy5nZXREYXRhID0gZnVuY3Rpb24gKGNvbnRlbnRUeXBlKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBzZWxmLl9jbGlwYm9hcmREYXRhW2NvbnRlbnRUeXBlXTtcclxuICAgICAgICAgICAgc2VsZi5fd2FzSW52b2tlZCA9IHRydWU7XHJcbiAgICAgICAgfTtcclxuICAgICAgICB0aGlzLmRpc2FibGUgPSBmdW5jdGlvbigpIHtcclxuICAgICAgICAgICAgc2VsZi5faXNEaXNhYmxlZCA9IHRydWU7XHJcbiAgICAgICAgICAgIHNlbGYuX3dhc0ludm9rZWQgPSBmYWxzZTtcclxuICAgICAgICAgICAgc2VsZi5fY2xpcGJvYXJkRGF0YSA9IHt9O1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgdGhpcy5pc0Rpc2FibGVkID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gc2VsZi5faXNEaXNhYmxlZDtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy53YXNJbnZva2VkID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gc2VsZi5fd2FzSW52b2tlZDtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgTGF5b3V0RWRpdG9yLkNsaXBib2FyZCA9IG5ldyBDbGlwYm9hcmQoKTtcclxuXHJcbiAgICBhbmd1bGFyXHJcbiAgICAgICAgLm1vZHVsZShcIkxheW91dEVkaXRvclwiKVxyXG4gICAgICAgIC5mYWN0b3J5KFwiY2xpcGJvYXJkXCIsIFtcclxuICAgICAgICAgICAgZnVuY3Rpb24oKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHNldERhdGE6IExheW91dEVkaXRvci5DbGlwYm9hcmQuc2V0RGF0YSxcclxuICAgICAgICAgICAgICAgICAgICBnZXREYXRhOiBMYXlvdXRFZGl0b3IuQ2xpcGJvYXJkLmdldERhdGEsXHJcbiAgICAgICAgICAgICAgICAgICAgZGlzYWJsZTogTGF5b3V0RWRpdG9yLkNsaXBib2FyZC5kaXNhYmxlLFxyXG4gICAgICAgICAgICAgICAgICAgIGlzRGlzYWJsZWQ6IExheW91dEVkaXRvci5DbGlwYm9hcmQuaXNEaXNhYmxlZCxcclxuICAgICAgICAgICAgICAgICAgICB3YXNJbnZva2VkOiBMYXlvdXRFZGl0b3IuQ2xpcGJvYXJkLndhc0ludm9rZWRcclxuICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICBdKTtcclxufSkoTGF5b3V0RWRpdG9yIHx8IChMYXlvdXRFZGl0b3IgPSB7fSkpOyIsImFuZ3VsYXJcclxuICAgIC5tb2R1bGUoXCJMYXlvdXRFZGl0b3JcIilcclxuICAgIC5mYWN0b3J5KFwic2NvcGVDb25maWd1cmF0b3JcIiwgW1wiJHRpbWVvdXRcIiwgXCJjbGlwYm9hcmRcIixcclxuICAgICAgICBmdW5jdGlvbiAoJHRpbWVvdXQsIGNsaXBib2FyZCkge1xyXG4gICAgICAgICAgICByZXR1cm4ge1xyXG5cclxuICAgICAgICAgICAgICAgIGNvbmZpZ3VyZUZvckVsZW1lbnQ6IGZ1bmN0aW9uICgkc2NvcGUsICRlbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgICAgICAkZWxlbWVudC5maW5kKFwiLmxheW91dC1wYW5lbFwiKS5jbGljayhmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICAgICAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAkZWxlbWVudC5wYXJlbnQoKS5rZXlkb3duKGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBoYW5kbGVkID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciByZXNldEZvY3VzID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBlbGVtZW50ID0gJHNjb3BlLmVsZW1lbnQ7XHJcbiAgICAgICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbGVtZW50LmVkaXRvci5pc0RyYWdnaW5nIHx8IGVsZW1lbnQuZWRpdG9yLmlubGluZUVkaXRpbmdJc0FjdGl2ZSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIG5hdGl2ZSBjbGlwYm9hcmQgc3VwcG9ydCBleGlzdHMsIHRoZSBwc2V1ZG8tY2xpcGJvYXJkIHdpbGwgaGF2ZSBiZWVuIGRpc2FibGVkLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNsaXBib2FyZC5pc0Rpc2FibGVkKCkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBmb2N1c2VkRWxlbWVudCA9IGVsZW1lbnQuZWRpdG9yLmZvY3VzZWRFbGVtZW50O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhZm9jdXNlZEVsZW1lbnQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBQc2V1ZG8gY2xpcGJvYXJkIGhhbmRsaW5nIGZvciBicm93c2VycyBub3QgYWxsb3dpbmcgcmVhbCBjbGlwYm9hcmQgb3BlcmF0aW9ucy5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZS5jdHJsS2V5KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoZS53aGljaCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDY3OiAvLyBDXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb2N1c2VkRWxlbWVudC5jb3B5KGNsaXBib2FyZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSA4ODogLy8gWFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9jdXNlZEVsZW1lbnQuY3V0KGNsaXBib2FyZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSA4NjogLy8gVlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9jdXNlZEVsZW1lbnQucGFzdGUoY2xpcGJvYXJkKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWUuY3RybEtleSAmJiAhZS5zaGlmdEtleSAmJiAhZS5hbHRLZXkgJiYgZS53aGljaCA9PSA0NikgeyAvLyBEZWxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS5kZWxldGUoZWxlbWVudCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYW5kbGVkID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghZS5jdHJsS2V5ICYmICFlLnNoaWZ0S2V5ICYmICFlLmFsdEtleSAmJiAoZS53aGljaCA9PSAzMiB8fCBlLndoaWNoID09IDI3KSkgeyAvLyBTcGFjZSBvciBFc2NcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRlbGVtZW50LmZpbmQoXCIubGF5b3V0LXBhbmVsLWFjdGlvbi1wcm9wZXJ0aWVzXCIpLmZpcnN0KCkuY2xpY2soKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhbmRsZWQgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbWVudC50eXBlID09IFwiQ29udGVudFwiKSB7IC8vIFRoaXMgaXMgYSBjb250ZW50IGVsZW1lbnQuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWUuY3RybEtleSAmJiAhZS5zaGlmdEtleSAmJiAhZS5hbHRLZXkgJiYgZS53aGljaCA9PSAxMykgeyAvLyBFbnRlclxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRlbGVtZW50LmZpbmQoXCIubGF5b3V0LXBhbmVsLWFjdGlvbi1lZGl0XCIpLmZpcnN0KCkuY2xpY2soKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYW5kbGVkID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhZWxlbWVudC5jaGlsZHJlbikgeyAvLyBUaGlzIGlzIGEgY29udGFpbmVyLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFlLmN0cmxLZXkgJiYgIWUuc2hpZnRLZXkgJiYgZS5hbHRLZXkgJiYgZS53aGljaCA9PSA0MCkgeyAvLyBBbHQrRG93blxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbGVtZW50LmNoaWxkcmVuLmxlbmd0aCA+IDApXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuY2hpbGRyZW5bMF0uc2V0SXNGb2N1c2VkKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFuZGxlZCA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQudHlwZSA9PSBcIkNvbHVtblwiKSB7IC8vIFRoaXMgaXMgYSBjb2x1bW4uXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNvbm5lY3RBZGphY2VudCA9ICFlLmN0cmxLZXk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGUud2hpY2ggPT0gMzcpIHsgLy8gTGVmdFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZS5hbHRLZXkpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmV4cGFuZExlZnQoY29ubmVjdEFkamFjZW50KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGUuc2hpZnRLZXkpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmNvbnRyYWN0UmlnaHQoY29ubmVjdEFkamFjZW50KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFuZGxlZCA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlLndoaWNoID09IDM5KSB7IC8vIFJpZ2h0XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlLmFsdEtleSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuY29udHJhY3RMZWZ0KGNvbm5lY3RBZGphY2VudCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlLnNoaWZ0S2V5KVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5leHBhbmRSaWdodChjb25uZWN0QWRqYWNlbnQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYW5kbGVkID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWVsZW1lbnQucGFyZW50KSB7IC8vIFRoaXMgaXMgYSBjaGlsZC5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlLmFsdEtleSAmJiBlLndoaWNoID09IDM4KSB7IC8vIEFsdCtVcFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQucGFyZW50LnNldElzRm9jdXNlZCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhbmRsZWQgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbGVtZW50LnBhcmVudC50eXBlID09IFwiUm93XCIpIHsgLy8gUGFyZW50IGlzIGEgaG9yaXpvbnRhbCBjb250YWluZXIuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFlLmN0cmxLZXkgJiYgIWUuc2hpZnRLZXkgJiYgIWUuYWx0S2V5ICYmIGUud2hpY2ggPT0gMzcpIHsgLy8gTGVmdFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnBhcmVudC5tb3ZlRm9jdXNQcmV2Q2hpbGQoZWxlbWVudCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhbmRsZWQgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICghZS5jdHJsS2V5ICYmICFlLnNoaWZ0S2V5ICYmICFlLmFsdEtleSAmJiBlLndoaWNoID09IDM5KSB7IC8vIFJpZ2h0XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQucGFyZW50Lm1vdmVGb2N1c05leHRDaGlsZChlbGVtZW50KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFuZGxlZCA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKGUuY3RybEtleSAmJiAhZS5zaGlmdEtleSAmJiAhZS5hbHRLZXkgJiYgZS53aGljaCA9PSAzNykgeyAvLyBDdHJsK0xlZnRcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5tb3ZlVXAoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzZXRGb2N1cyA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhbmRsZWQgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChlLmN0cmxLZXkgJiYgIWUuc2hpZnRLZXkgJiYgIWUuYWx0S2V5ICYmIGUud2hpY2ggPT0gMzkpIHsgLy8gQ3RybCtSaWdodFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50Lm1vdmVEb3duKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhbmRsZWQgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgeyAvLyBQYXJlbnQgaXMgYSB2ZXJ0aWNhbCBjb250YWluZXIuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFlLmN0cmxLZXkgJiYgIWUuc2hpZnRLZXkgJiYgIWUuYWx0S2V5ICYmIGUud2hpY2ggPT0gMzgpIHsgLy8gVXBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5wYXJlbnQubW92ZUZvY3VzUHJldkNoaWxkKGVsZW1lbnQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYW5kbGVkID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoIWUuY3RybEtleSAmJiAhZS5zaGlmdEtleSAmJiAhZS5hbHRLZXkgJiYgZS53aGljaCA9PSA0MCkgeyAvLyBEb3duXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQucGFyZW50Lm1vdmVGb2N1c05leHRDaGlsZChlbGVtZW50KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFuZGxlZCA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKGUuY3RybEtleSAmJiAhZS5zaGlmdEtleSAmJiAhZS5hbHRLZXkgJiYgZS53aGljaCA9PSAzOCkgeyAvLyBDdHJsK1VwXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQubW92ZVVwKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc2V0Rm9jdXMgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYW5kbGVkID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoZS5jdHJsS2V5ICYmICFlLnNoaWZ0S2V5ICYmICFlLmFsdEtleSAmJiBlLndoaWNoID09IDQwKSB7IC8vIEN0cmwrRG93blxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50Lm1vdmVEb3duKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhbmRsZWQgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGhhbmRsZWQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS4kYXBwbHkoKTsgLy8gRXZlbnQgaXMgbm90IHRyaWdnZXJlZCBieSBBbmd1bGFyIGRpcmVjdGl2ZSBidXQgcmF3IGV2ZW50IGhhbmRsZXIgb24gZWxlbWVudC5cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEhBQ0s6IFdvcmthcm91bmQgYmVjYXVzZSBvZiBob3cgQW5ndWxhciB0cmVhdHMgdGhlIERPTSB3aGVuIGVsZW1lbnRzIGFyZSBzaGlmdGVkIGFyb3VuZCAtIGlucHV0IGZvY3VzIGlzIHNvbWV0aW1lcyBsb3N0LlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzZXRGb2N1cykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS4kYXBwbHkoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmVkaXRvci5mb2N1c2VkRWxlbWVudC5zZXRJc0ZvY3VzZWQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIDEwMCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmVsZW1lbnQuc2V0SXNGb2N1c2VkRXZlbnRIYW5kbGVycy5wdXNoKGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgJGVsZW1lbnQucGFyZW50KCkuZm9jdXMoKTtcclxuICAgICAgICAgICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmRlbGV0ZSA9IGZ1bmN0aW9uIChlbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuZGVsZXRlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgICAgICBjb25maWd1cmVGb3JDb250YWluZXI6IGZ1bmN0aW9uICgkc2NvcGUsICRlbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVsZW1lbnQgPSAkc2NvcGUuZWxlbWVudDtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgLy8kc2NvcGUuaXNSZWNlaXZpbmcgPSBmYWxzZTsgLy8gVHJ1ZSB3aGVuIGNvbnRhaW5lciBpcyByZWNlaXZpbmcgYW4gZXh0ZXJuYWwgZWxlbWVudCB2aWEgZHJhZy9kcm9wLlxyXG4gICAgICAgICAgICAgICAgICAgICRzY29wZS5nZXRTaG93Q2hpbGRyZW5QbGFjZWhvbGRlciA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICRzY29wZS5lbGVtZW50LmNoaWxkcmVuLmxlbmd0aCA9PT0gMCAmJiAhJHNjb3BlLmVsZW1lbnQuZ2V0SXNEcm9wVGFyZ2V0KCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgJHNjb3BlLnNvcnRhYmxlT3B0aW9ucyA9IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY3Vyc29yOiBcIm1vdmVcIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgZGVsYXk6IDE1MCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgZGlzYWJsZWQ6IGVsZW1lbnQuZ2V0SXNTZWFsZWQoKSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgZGlzdGFuY2U6IDUsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vaGFuZGxlOiBlbGVtZW50LmNoaWxkcmVuLmxlbmd0aCA8IDIgPyBcIi5pbWFnaW5hcnktY2xhc3NcIiA6IGZhbHNlLCAvLyBGb3Igc29tZSByZWFzb24gZG9lc24ndCBnZXQgcmUtZXZhbHVhdGVkIGFmdGVyIGFkZGluZyBtb3JlIGNoaWxkcmVuLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBzdGFydDogZnVuY3Rpb24gKGUsIHVpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuJGFwcGx5KGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnNldElzRHJvcFRhcmdldCh0cnVlKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmVkaXRvci5pc0RyYWdnaW5nID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSB0aGUgZHJvcCB0YXJnZXQgcGxhY2Vob2xkZXIgYXMgaGlnaCBhcyB0aGUgaXRlbSBiZWluZyBkcmFnZ2VkLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdWkucGxhY2Vob2xkZXIuaGVpZ2h0KHVpLml0ZW0uaGVpZ2h0KCkgLSA0KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVpLnBsYWNlaG9sZGVyLmNzcyhcIm1pbi1oZWlnaHRcIiwgMCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0b3A6IGZ1bmN0aW9uIChlLCB1aSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLiRhcHBseShmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5lZGl0b3IuaXNEcmFnZ2luZyA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuc2V0SXNEcm9wVGFyZ2V0KGZhbHNlKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBvdmVyOiBmdW5jdGlvbiAoZSwgdWkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIXVpLnNlbmRlciAmJiAhIXVpLnNlbmRlclswXS5pc1Rvb2xib3gpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoISF1aS5zZW5kZXJbMF0uZHJvcFRhcmdldFRpbWVvdXQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHRpbWVvdXQuY2FuY2VsKHVpLnNlbmRlclswXS5kcm9wVGFyZ2V0VGltZW91dCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVpLnNlbmRlclswXS5kcm9wVGFyZ2V0VGltZW91dCA9IG51bGw7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0aW1lb3V0KGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQudHlwZSA9PSBcIlJvd1wiKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGVyZSB3YXMgYSBwcmV2aW91cyBkcm9wIHRhcmdldCBhbmQgaXQgd2FzIGEgcm93LCByb2xsIGJhY2sgYW55IHBlbmRpbmcgY29sdW1uIGFkZHMgdG8gaXQuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJldmlvdXNEcm9wVGFyZ2V0ID0gZWxlbWVudC5lZGl0b3IuZHJvcFRhcmdldEVsZW1lbnQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFwcmV2aW91c0Ryb3BUYXJnZXQgJiYgcHJldmlvdXNEcm9wVGFyZ2V0LnR5cGUgPT0gXCJSb3dcIilcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmV2aW91c0Ryb3BUYXJnZXQucm9sbGJhY2tBZGRDb2x1bW4oKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnNldElzRHJvcFRhcmdldChmYWxzZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdWkuc2VuZGVyWzBdLmRyb3BUYXJnZXRUaW1lb3V0ID0gJHRpbWVvdXQoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbWVudC50eXBlID09IFwiUm93XCIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciByZWNlaXZlZENvbHVtbiA9IHVpLml0ZW0uc29ydGFibGUubW9kZWw7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmVjZWl2ZWRDb2x1bW5XaWR0aCA9IE1hdGguZmxvb3IoMTIgLyAoZWxlbWVudC5jaGlsZHJlbi5sZW5ndGggKyAxKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWNlaXZlZENvbHVtbi53aWR0aCA9IHJlY2VpdmVkQ29sdW1uV2lkdGg7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWNlaXZlZENvbHVtbi5vZmZzZXQgPSAwO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5iZWdpbkFkZENvbHVtbihyZWNlaXZlZENvbHVtbldpZHRoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1ha2UgdGhlIGRyb3AgdGFyZ2V0IHBsYWNlaG9sZGVyIHRoZSBjb3JyZWN0IHdpZHRoIGFuZCBhcyBoaWdoIGFzIHRoZSBoaWdoZXN0IGV4aXN0aW5nIGNvbHVtbiBpbiB0aGUgcm93LlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG1heEhlaWdodCA9IF8ubWF4KF8oJGVsZW1lbnQuZmluZChcIj4gLmxheW91dC1jaGlsZHJlbiA+IC5sYXlvdXQtY29sdW1uOm5vdCgudWktc29ydGFibGUtcGxhY2Vob2xkZXIpXCIpKS5tYXAoZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJChlKS5oZWlnaHQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoaSA9IDE7IGkgPD0gMTI7IGkrKylcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1aS5wbGFjZWhvbGRlci5yZW1vdmVDbGFzcyhcImNvbC14cy1cIiArIGkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdWkucGxhY2Vob2xkZXIuYWRkQ2xhc3MoXCJjb2wteHMtXCIgKyByZWNlaXZlZENvbHVtbi53aWR0aCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF4SGVpZ2h0ID4gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVpLnBsYWNlaG9sZGVyLmhlaWdodChtYXhIZWlnaHQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVpLnBsYWNlaG9sZGVyLmNzcyhcIm1pbi1oZWlnaHRcIiwgMCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1aS5wbGFjZWhvbGRlci5oZWlnaHQoMCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdWkucGxhY2Vob2xkZXIuY3NzKFwibWluLWhlaWdodFwiLCBcIlwiKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnNldElzRHJvcFRhcmdldCh0cnVlKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCAxNTApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICByZWNlaXZlOiBmdW5jdGlvbiAoZSwgdWkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIXVpLnNlbmRlciAmJiAhIXVpLnNlbmRlclswXS5pc1Rvb2xib3gpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuJGFwcGx5KGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJlY2VpdmVkRWxlbWVudCA9IHVpLml0ZW0uc29ydGFibGUubW9kZWw7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIXJlY2VpdmVkRWxlbWVudCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQudHlwZSA9PSBcIlJvd1wiKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuY29tbWl0QWRkQ29sdW1uKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTaG91bGQgaWRlYWxseSBjYWxsIExheW91dEVkaXRvci5Db250YWluZXIuYWRkQ2hpbGQoKSBpbnN0ZWFkLCBidXQgc2luY2UgdGhpcyBoYW5kbGVyXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpcyBydW4gKmJlZm9yZSogdGhlIHVpLXNvcnRhYmxlIGRpcmVjdGl2ZSdzIGhhbmRsZXIsIGlmIHdlIHRyeSB0byBhZGQgdGhlIGNoaWxkIHRvIHRoZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXJyYXkgdGhhdCBoYW5kbGVyIHdpbGwgZ2V0IGFuIGV4Y2VwdGlvbiB3aGVuIHRyeWluZyB0byBkbyB0aGUgc2FtZS5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJlY2F1c2Ugb2YgdGhpcywgd2UgbmVlZCB0byBpbnZva2UgXCJzZXRQYXJlbnRcIiBzbyB0aGF0IHNwZWNpZmljIGNvbnRhaW5lciB0eXBlcyBjYW4gcGVyZm9ybSBlbGVtZW50IHNwZWZpY2ljIGluaXRpYWxpemF0aW9uLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjZWl2ZWRFbGVtZW50LnNldEVkaXRvcihlbGVtZW50LmVkaXRvcik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWNlaXZlZEVsZW1lbnQuc2V0UGFyZW50KGVsZW1lbnQpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIXJlY2VpdmVkRWxlbWVudC5oYXNFZGl0b3IpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuJHJvb3QuZWRpdEVsZW1lbnQocmVjZWl2ZWRFbGVtZW50KS50aGVuKGZ1bmN0aW9uIChhcmdzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYXJncy5jYW5jZWwpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY2VpdmVkRWxlbWVudC5kYXRhID0gYXJncy5lbGVtZW50LmRhdGE7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWNlaXZlZEVsZW1lbnQuYXBwbHlFbGVtZW50RWRpdG9yTW9kZWwoYXJncy5lbGVtZW50RWRpdG9yTW9kZWwpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIXJlY2VpdmVkRWxlbWVudC5zZXRIdG1sKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY2VpdmVkRWxlbWVudC5zZXRIdG1sKGFyZ3MuZWxlbWVudC5odG1sKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdGltZW91dChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFhcmdzLmNhbmNlbClcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWNlaXZlZEVsZW1lbnQuZGVsZXRlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjZWl2ZWRFbGVtZW50LnNldElzRm9jdXNlZCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8kc2NvcGUuaXNSZWNlaXZpbmcgPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuc2V0SXNEcm9wVGFyZ2V0KGZhbHNlKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHRpbWVvdXQoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8kc2NvcGUuaXNSZWNlaXZpbmcgPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuc2V0SXNEcm9wVGFyZ2V0KGZhbHNlKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIXJlY2VpdmVkRWxlbWVudClcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWNlaXZlZEVsZW1lbnQuc2V0SXNGb2N1c2VkKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmNsaWNrID0gZnVuY3Rpb24gKGNoaWxkLCBlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY2hpbGQuZWRpdG9yLmlzRHJhZ2dpbmcpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGlsZC5zZXRJc0ZvY3VzZWQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgICAgICAgICAgICAgICAgICB9O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAkc2NvcGUuZ2V0Q2xhc3NlcyA9IGZ1bmN0aW9uIChjaGlsZCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gW1wibGF5b3V0LWVsZW1lbnRcIl07XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFjaGlsZC5jaGlsZHJlbikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goXCJsYXlvdXQtY29udGFpbmVyXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLmdldElzU2VhbGVkKCkpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goXCJsYXlvdXQtY29udGFpbmVyLXNlYWxlZFwiKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goXCJsYXlvdXQtXCIgKyBjaGlsZC50eXBlLnRvTG93ZXJDYXNlKCkpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhY2hpbGQuZHJvcFRhcmdldENsYXNzKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goY2hpbGQuZHJvcFRhcmdldENsYXNzKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRPRE86IE1vdmUgdGhlc2UgdG8gZWl0aGVyIHRoZSBDb2x1bW4gZGlyZWN0aXZlIG9yIHRoZSBDb2x1bW4gbW9kZWwgY2xhc3MuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC50eXBlID09IFwiUm93XCIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKFwicm93XCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjaGlsZC5jYW5BZGRDb2x1bW4oKSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChcImxheW91dC1yb3ctZnVsbFwiKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGQudHlwZSA9PSBcIkNvbHVtblwiKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChcImNvbC14cy1cIiArIGNoaWxkLndpZHRoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKFwiY29sLXhzLW9mZnNldC1cIiArIGNoaWxkLm9mZnNldCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLnR5cGUgPT0gXCJDb250ZW50XCIpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChcImxheW91dC1jb250ZW50LVwiICsgY2hpbGQuY29udGVudFR5cGVDbGFzcyk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGQuZ2V0SXNBY3RpdmUoKSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKFwibGF5b3V0LWVsZW1lbnQtYWN0aXZlXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGQuZ2V0SXNGb2N1c2VkKCkpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChcImxheW91dC1lbGVtZW50LWZvY3VzZWRcIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5nZXRJc1NlbGVjdGVkKCkpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChcImxheW91dC1lbGVtZW50LXNlbGVjdGVkXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGQuZ2V0SXNEcm9wVGFyZ2V0KCkpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChcImxheW91dC1lbGVtZW50LWRyb3B0YXJnZXRcIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5pc1RlbXBsYXRlZClcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKFwibGF5b3V0LWVsZW1lbnQtdGVtcGxhdGVkXCIpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgICAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH1cclxuICAgIF0pOyIsImFuZ3VsYXJcclxuICAgIC5tb2R1bGUoXCJMYXlvdXRFZGl0b3JcIilcclxuICAgIC5kaXJlY3RpdmUoXCJvcmNMYXlvdXRFZGl0b3JcIiwgW1wiZW52aXJvbm1lbnRcIixcclxuICAgICAgICBmdW5jdGlvbiAoZW52aXJvbm1lbnQpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgICAgIHJlc3RyaWN0OiBcIkVcIixcclxuICAgICAgICAgICAgICAgIHNjb3BlOiB7fSxcclxuICAgICAgICAgICAgICAgIGNvbnRyb2xsZXI6IFtcIiRzY29wZVwiLCBcIiRlbGVtZW50XCIsIFwiJGF0dHJzXCIsIFwiJGNvbXBpbGVcIiwgXCJjbGlwYm9hcmRcIixcclxuICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiAoJHNjb3BlLCAkZWxlbWVudCwgJGF0dHJzLCAkY29tcGlsZSwgY2xpcGJvYXJkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghISRhdHRycy5tb2RlbClcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS5lbGVtZW50ID0gZXZhbCgkYXR0cnMubW9kZWwpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGUgJ21vZGVsJyBhdHRyaWJ1dGUgbXVzdCBldmFsdWF0ZSB0byBhIExheW91dEVkaXRvci5FZGl0b3Igb2JqZWN0LlwiKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS5jbGljayA9IGZ1bmN0aW9uIChjYW52YXMsIGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY2FudmFzLmVkaXRvci5pc0RyYWdnaW5nKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbnZhcy5zZXRJc0ZvY3VzZWQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuZ2V0Q2xhc3NlcyA9IGZ1bmN0aW9uIChjYW52YXMpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSBbXCJsYXlvdXQtZWxlbWVudFwiLCBcImxheW91dC1jb250YWluZXJcIiwgXCJsYXlvdXQtY2FudmFzXCJdO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjYW52YXMuZ2V0SXNBY3RpdmUoKSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChcImxheW91dC1lbGVtZW50LWFjdGl2ZVwiKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjYW52YXMuZ2V0SXNGb2N1c2VkKCkpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goXCJsYXlvdXQtZWxlbWVudC1mb2N1c2VkXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNhbnZhcy5nZXRJc1NlbGVjdGVkKCkpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goXCJsYXlvdXQtZWxlbWVudC1zZWxlY3RlZFwiKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjYW52YXMuZ2V0SXNEcm9wVGFyZ2V0KCkpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goXCJsYXlvdXQtZWxlbWVudC1kcm9wdGFyZ2V0XCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNhbnZhcy5pc1RlbXBsYXRlZClcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChcImxheW91dC1lbGVtZW50LXRlbXBsYXRlZFwiKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQW4gdW5mb3J0dW5hdGUgc2lkZS1lZmZlY3Qgb2YgdGhlIG5leHQgaGFjayBvbiBsaW5lIDU0IGlzIHRoYXQgdGhlIGNyZWF0ZWQgZWxlbWVudHMgYXJlbid0IGFkZGVkIHRvIHRoZSBET00geWV0LCBzbyB3ZSBjYW4ndCB1c2UgaXQgdG8gZ2V0IHRvIHRoZSBwYXJlbnQgXCIubGF5b3V0LWRlc2lnZXJcIiBlbGVtZW50LlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBXb3JrIGFyb3VuZDogYWNjZXNzIHRoYXQgZWxlbWVudCBkaXJlY3RseSAod2hpY2ggZWZlY3RpdmVseSB0dXJucyBtdWx0aXBsZSBsYXlvdXQgZWRpdG9ycyBvbiBhIHNpbmdsZSBwYWdlIGltcG9zc2libGUpLiBcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gLy92YXIgbGF5b3V0RGVzaWduZXJIb3N0ID0gJGVsZW1lbnQuY2xvc2VzdChcIi5sYXlvdXQtZGVzaWduZXJcIikuZGF0YShcImxheW91dC1kZXNpZ25lci1ob3N0XCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbGF5b3V0RGVzaWduZXJIb3N0ID0gJChcIi5sYXlvdXQtZGVzaWduZXJcIikuZGF0YShcImxheW91dC1kZXNpZ25lci1ob3N0XCIpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLiRyb290LmxheW91dERlc2lnbmVySG9zdCA9IGxheW91dERlc2lnbmVySG9zdDtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxheW91dERlc2lnbmVySG9zdC5lbGVtZW50Lm9uKFwicmVwbGFjZWNhbnZhc1wiLCBmdW5jdGlvbiAoZSwgYXJncykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGVkaXRvciA9ICRzY29wZS5lbGVtZW50O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNhbnZhc0RhdGEgPSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTogYXJncy5jYW52YXMuZGF0YSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBodG1sSWQ6IGFyZ3MuY2FudmFzLmh0bWxJZCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBodG1sQ2xhc3M6IGFyZ3MuY2FudmFzLmh0bWxDbGFzcyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBodG1sU3R5bGU6IGFyZ3MuY2FudmFzLmh0bWxTdHlsZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1RlbXBsYXRlZDogYXJncy5jYW52YXMuaXNUZW1wbGF0ZWQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGFyZ3MuY2FudmFzLmNoaWxkcmVuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEhBQ0s6IEluc3RlYWQgb2Ygc2ltcGx5IHVwZGF0aW5nIHRoZSAkc2NvcGUuZWxlbWVudCB3aXRoIGEgbmV3IGluc3RhbmNlLCB3ZSBuZWVkIHRvIHJlcGxhY2UgdGhlIGVudGlyZSBvcmMtbGF5b3V0LWVkaXRvciBtYXJrdXBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluIG9yZGVyIGZvciBhbmd1bGFyIHRvIHJlYmluZCBzdGFydGluZyB3aXRoIHRoZSBDYW52YXMgZWxlbWVudC4gT3RoZXJ3aXNlLCBmb3Igc29tZSByZWFzb24sIGl0IHdpbGwgcmViaW5kIHN0YXJ0aW5nIHdpdGggdGhlIGZpcnN0IGNoaWxkIG9mIENhbnZhcy5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFlvdSBjYW4gc2VlIHRoaXMgaGFwcGVuaW5nIHdoZW4gc2V0dGluZyBhIGJyZWFrcG9pbnQgaW4gU2NvcGVDb25maWd1cmF0b3Igd2hlcmUgY29udGFpbmVycyBhcmUgaW5pdGlhbGl6ZWQgd2l0aCBkcmFnICYgZHJvcDogb24gcGFnZSBsb2FkLCB0aGUgZmlyc3QgZWxlbWVudFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXMgYSBDYW52YXMgKGdvb2QpLCBidXQgYWZ0ZXIgaGF2aW5nIHNlbGVjdGVkIGFub3RoZXIgdGVtcGxhdGUsIHRoZSBmaXJzdCBlbGVtZW50IGlzICh0eXBpY2FsbHkpIGEgR3JpZCAoYmFkKS5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNpbXBseSByZWNvbXBpbGluZyB0aGUgb3JjLWxheW91dC1lZGl0b3IgZGlyZWN0aXZlIHdpbGwgY2F1c2UgdGhlIGVudGlyZSB0aGluZyB0byBiZSBnZW5lcmF0ZWQsIHdoaWNoIHdvcmtzIGp1c3QgZmluZSBhcyB3ZWxsIChldmVuIHRob3VnaCBub3QgaXMgbmljZSBhcyBzaW1wbHkgbGV2ZXJhZ2luZyBtb2RlbCBiaW5kaW5nKS5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxheW91dERlc2lnbmVySG9zdC5lZGl0b3IgPSB3aW5kb3cubGF5b3V0RWRpdG9yID0gbmV3IExheW91dEVkaXRvci5FZGl0b3IoZWRpdG9yLmNvbmZpZywgY2FudmFzRGF0YSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdGVtcGxhdGUgPSBcIjxvcmMtbGF5b3V0LWVkaXRvclwiICsgXCIgbW9kZWw9J3dpbmRvdy5sYXlvdXRFZGl0b3InIC8+XCI7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgaHRtbCA9ICRjb21waWxlKHRlbXBsYXRlKSgkc2NvcGUpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJChcIi5sYXlvdXQtZWRpdG9yLWhvbGRlclwiKS5odG1sKGh0bWwpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS4kcm9vdC5lZGl0RWxlbWVudCA9IGZ1bmN0aW9uIChlbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgaG9zdCA9ICRzY29wZS4kcm9vdC5sYXlvdXREZXNpZ25lckhvc3Q7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaG9zdC5lZGl0RWxlbWVudChlbGVtZW50KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS4kcm9vdC5hZGRFbGVtZW50ID0gZnVuY3Rpb24gKGNvbnRlbnRUeXBlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgaG9zdCA9ICRzY29wZS4kcm9vdC5sYXlvdXREZXNpZ25lckhvc3Q7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaG9zdC5hZGRFbGVtZW50KGNvbnRlbnRUeXBlKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS50b2dnbGVJbmxpbmVFZGl0aW5nID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEkc2NvcGUuZWxlbWVudC5pbmxpbmVFZGl0aW5nSXNBY3RpdmUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuZWxlbWVudC5pbmxpbmVFZGl0aW5nSXNBY3RpdmUgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRlbGVtZW50LmZpbmQoXCIubGF5b3V0LXRvb2xiYXItY29udGFpbmVyXCIpLnNob3coKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgc2VsZWN0b3IgPSBcIiNsYXlvdXQtZWRpdG9yLVwiICsgJHNjb3BlLiRpZCArIFwiIC5sYXlvdXQtaHRtbCAubGF5b3V0LWNvbnRlbnQtbWFya3VwW2RhdGEtdGVtcGxhdGVkPWZhbHNlXVwiO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBmaXJzdENvbnRlbnRFZGl0b3JJZCA9ICQoc2VsZWN0b3IpLmZpcnN0KCkuYXR0cihcImlkXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpbnltY2UuaW5pdCh7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdG9yOiBzZWxlY3RvcixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWU6IFwibW9kZXJuXCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjaGVtYTogXCJodG1sNVwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbHVnaW5zOiBbXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImFkdmxpc3QgYXV0b2xpbmsgbGlzdHMgbGluayBpbWFnZSBjaGFybWFwIHByaW50IHByZXZpZXcgaHIgYW5jaG9yIHBhZ2VicmVha1wiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJzZWFyY2hyZXBsYWNlIHdvcmRjb3VudCB2aXN1YWxibG9ja3MgdmlzdWFsY2hhcnMgY29kZSBmdWxsc2NyZWVuXCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImluc2VydGRhdGV0aW1lIG1lZGlhIG5vbmJyZWFraW5nIHRhYmxlIGNvbnRleHRtZW51IGRpcmVjdGlvbmFsaXR5XCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImVtb3RpY29ucyB0ZW1wbGF0ZSBwYXN0ZSB0ZXh0Y29sb3IgY29sb3JwaWNrZXIgdGV4dHBhdHRlcm5cIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiZnVsbHNjcmVlbiBhdXRvcmVzaXplXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJhcjogXCJ1bmRvIHJlZG8gY3V0IGNvcHkgcGFzdGUgfCBib2xkIGl0YWxpYyB8IGJ1bGxpc3QgbnVtbGlzdCBvdXRkZW50IGluZGVudCBmb3JtYXRzZWxlY3QgfCBhbGlnbmxlZnQgYWxpZ25jZW50ZXIgYWxpZ25yaWdodCBhbGlnbmp1c3RpZnkgbHRyIHJ0bCB8IGxpbmsgdW5saW5rIGNoYXJtYXAgfCBjb2RlIGZ1bGxzY3JlZW4gY2xvc2VcIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udmVydF91cmxzOiBmYWxzZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRfZWxlbWVudHM6IFwiKlsqXVwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTaG91bGRuJ3QgYmUgbmVlZGVkIGR1ZSB0byB0aGUgdmFsaWRfZWxlbWVudHMgc2V0dGluZywgYnV0IFRpbnlNQ0Ugd291bGQgc3RyaXAgc2NyaXB0LnNyYyB3aXRob3V0IGl0LlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHRlbmRlZF92YWxpZF9lbGVtZW50czogXCJzY3JpcHRbdHlwZXxkZWZlcnxzcmN8bGFuZ3VhZ2VdXCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXR1c2JhcjogZmFsc2UsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNraW46IFwib3JjaGFyZGxpZ2h0Z3JheVwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmxpbmU6IHRydWUsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpeGVkX3Rvb2xiYXJfY29udGFpbmVyOiBcIiNsYXlvdXQtZWRpdG9yLVwiICsgJHNjb3BlLiRpZCArIFwiIC5sYXlvdXQtdG9vbGJhci1jb250YWluZXJcIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5pdF9pbnN0YW5jZV9jYWxsYmFjazogZnVuY3Rpb24gKGVkaXRvcikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVkaXRvci5pZCA9PSBmaXJzdENvbnRlbnRFZGl0b3JJZClcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aW55bWNlLmV4ZWNDb21tYW5kKFwibWNlRm9jdXNcIiwgZmFsc2UsIGVkaXRvci5pZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpbnltY2UucmVtb3ZlKFwiI2xheW91dC1lZGl0b3ItXCIgKyAkc2NvcGUuJGlkICsgXCIgLmxheW91dC1jb250ZW50LW1hcmt1cFwiKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZWxlbWVudC5maW5kKFwiLmxheW91dC10b29sYmFyLWNvbnRhaW5lclwiKS5oaWRlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmVsZW1lbnQuaW5saW5lRWRpdGluZ0lzQWN0aXZlID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAkKGRvY3VtZW50KS5vbihcImN1dCBjb3B5IHBhc3RlXCIsIGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgcHNldWRvIGNsaXBib2FyZCB3YXMgYWxyZWFkeSBpbnZva2VkICh3aGljaCBoYXBwZW5zIG9uIHRoZSBmaXJzdCBjbGlwYm9hcmRcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG9wZXJhdGlvbiBhZnRlciBwYWdlIGxvYWQgZXZlbiBpZiBuYXRpdmUgY2xpcGJvYXJkIHN1cHBvcnQgZXhpc3RzKSB0aGVuIHNpdCB0aGlzXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBvbmUgb3BlcmF0aW9uIG91dCwgYnV0IG1ha2Ugc3VyZSB3aGF0ZXZlciBpcyBvbiB0aGUgcHNldWRvIGNsaXBib2FyZCBnZXRzIG1pZ3JhdGVkXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0byB0aGUgbmF0aXZlIGNsaXBib2FyZCBmb3Igc3Vic2VxdWVudCBvcGVyYXRpb25zLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNsaXBib2FyZC53YXNJbnZva2VkKCkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLm9yaWdpbmFsRXZlbnQuY2xpcGJvYXJkRGF0YS5zZXREYXRhKFwidGV4dC9wbGFpblwiLCBjbGlwYm9hcmQuZ2V0RGF0YShcInRleHQvcGxhaW5cIikpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUub3JpZ2luYWxFdmVudC5jbGlwYm9hcmREYXRhLnNldERhdGEoXCJ0ZXh0L2pzb25cIiwgY2xpcGJvYXJkLmdldERhdGEoXCJ0ZXh0L2pzb25cIikpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBmb2N1c2VkRWxlbWVudCA9ICRzY29wZS5lbGVtZW50LmZvY3VzZWRFbGVtZW50O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWZvY3VzZWRFbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS4kYXBwbHkoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChlLnR5cGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiY29weVwiOlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb2N1c2VkRWxlbWVudC5jb3B5KGUub3JpZ2luYWxFdmVudC5jbGlwYm9hcmREYXRhKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImN1dFwiOlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb2N1c2VkRWxlbWVudC5jdXQoZS5vcmlnaW5hbEV2ZW50LmNsaXBib2FyZERhdGEpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwicGFzdGVcIjpcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9jdXNlZEVsZW1lbnQucGFzdGUoZS5vcmlnaW5hbEV2ZW50LmNsaXBib2FyZERhdGEpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIQUNLOiBXb3JrYXJvdW5kIGJlY2F1c2Ugb2YgaG93IEFuZ3VsYXIgdHJlYXRzIHRoZSBET00gd2hlbiBlbGVtZW50cyBhcmUgc2hpZnRlZCBhcm91bmQgLSBpbnB1dCBmb2N1cyBpcyBzb21ldGltZXMgbG9zdC5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLiRhcHBseShmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhJHNjb3BlLmVsZW1lbnQuZm9jdXNlZEVsZW1lbnQpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS5lbGVtZW50LmZvY3VzZWRFbGVtZW50LnNldElzRm9jdXNlZCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIDEwMCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5hdGl2ZSBjbGlwYm9hcmQgc3VwcG9ydCBvYnZpb3VzbHkgZXhpc3RzLCBzbyBkaXNhYmxlIHRoZSBwZXVkbyBjbGlwYm9hcmQgZnJvbSBub3cgb24uXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGlwYm9hcmQuZGlzYWJsZSgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBdLFxyXG4gICAgICAgICAgICAgICAgdGVtcGxhdGVVcmw6IGVudmlyb25tZW50LnRlbXBsYXRlVXJsKFwiRWRpdG9yXCIpLFxyXG4gICAgICAgICAgICAgICAgcmVwbGFjZTogdHJ1ZSxcclxuICAgICAgICAgICAgICAgIGxpbms6IGZ1bmN0aW9uIChzY29wZSwgZWxlbWVudCkge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIE5vIGNsaWNrcyBzaG91bGQgcHJvcGFnYXRlIGZyb20gdGhlIFRpbnlNQ0UgdG9vbGJhcnMuXHJcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5maW5kKFwiLmxheW91dC10b29sYmFyLWNvbnRhaW5lclwiKS5jbGljayhmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIEludGVyY2VwdCBtb3VzZWRvd24gb24gZWRpdG9yIHdoaWxlIGluIGlubGluZSBlZGl0aW5nIG1vZGUgdG8gXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gcHJldmVudCBjdXJyZW50IGVkaXRvciBmcm9tIGxvc2luZyBmb2N1cy5cclxuICAgICAgICAgICAgICAgICAgICBlbGVtZW50Lm1vdXNlZG93bihmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2NvcGUuZWxlbWVudC5pbmxpbmVFZGl0aW5nSXNBY3RpdmUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICAgICAgICAgIC8vIFVuZm9jdXMgYW5kIHVuc2VsZWN0IGV2ZXJ5dGhpbmcgb24gY2xpY2sgb3V0c2lkZSBvZiBjYW52YXMuXHJcbiAgICAgICAgICAgICAgICAgICAgJCh3aW5kb3cpLmNsaWNrKGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEV4Y2VwdCB3aGVuIGluIGlubGluZSBlZGl0aW5nIG1vZGUuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc2NvcGUuZWxlbWVudC5pbmxpbmVFZGl0aW5nSXNBY3RpdmUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlLiRhcHBseShmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NvcGUuZWxlbWVudC5hY3RpdmVFbGVtZW50ID0gbnVsbDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY29wZS5lbGVtZW50LmZvY3VzZWRFbGVtZW50ID0gbnVsbDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgfVxyXG4gICAgXSk7IiwiYW5ndWxhclxyXG4gICAgLm1vZHVsZShcIkxheW91dEVkaXRvclwiKVxyXG4gICAgLmRpcmVjdGl2ZShcIm9yY0xheW91dENhbnZhc1wiLCBbXCJzY29wZUNvbmZpZ3VyYXRvclwiLCBcImVudmlyb25tZW50XCIsXHJcbiAgICAgICAgZnVuY3Rpb24gKHNjb3BlQ29uZmlndXJhdG9yLCBlbnZpcm9ubWVudCkge1xyXG4gICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgcmVzdHJpY3Q6IFwiRVwiLFxyXG4gICAgICAgICAgICAgICAgc2NvcGU6IHsgZWxlbWVudDogXCI9XCIgfSxcclxuICAgICAgICAgICAgICAgIGNvbnRyb2xsZXI6IFtcIiRzY29wZVwiLCBcIiRlbGVtZW50XCIsIFwiJGF0dHJzXCIsXHJcbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gKCRzY29wZSwgJGVsZW1lbnQsICRhdHRycykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBzY29wZUNvbmZpZ3VyYXRvci5jb25maWd1cmVGb3JFbGVtZW50KCRzY29wZSwgJGVsZW1lbnQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBzY29wZUNvbmZpZ3VyYXRvci5jb25maWd1cmVGb3JDb250YWluZXIoJHNjb3BlLCAkZWxlbWVudCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS5zb3J0YWJsZU9wdGlvbnNbXCJheGlzXCJdID0gXCJ5XCI7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgXSxcclxuICAgICAgICAgICAgICAgIHRlbXBsYXRlVXJsOiBlbnZpcm9ubWVudC50ZW1wbGF0ZVVybChcIkNhbnZhc1wiKSxcclxuICAgICAgICAgICAgICAgIHJlcGxhY2U6IHRydWVcclxuICAgICAgICAgICAgfTtcclxuICAgICAgICB9XHJcbiAgICBdKTsiLCJhbmd1bGFyXHJcbiAgICAubW9kdWxlKFwiTGF5b3V0RWRpdG9yXCIpXHJcbiAgICAuZGlyZWN0aXZlKFwib3JjTGF5b3V0Q2hpbGRcIiwgW1wiJGNvbXBpbGVcIixcclxuICAgICAgICBmdW5jdGlvbiAoJGNvbXBpbGUpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgICAgIHJlc3RyaWN0OiBcIkVcIixcclxuICAgICAgICAgICAgICAgIHNjb3BlOiB7IGVsZW1lbnQ6IFwiPVwiIH0sXHJcbiAgICAgICAgICAgICAgICBsaW5rOiBmdW5jdGlvbiAoc2NvcGUsIGVsZW1lbnQpIHtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgdGVtcGxhdGUgPSBcIjxvcmMtbGF5b3V0LVwiICsgc2NvcGUuZWxlbWVudC50eXBlLnRvTG93ZXJDYXNlKCkgKyBcIiBlbGVtZW50PSdlbGVtZW50JyAvPlwiO1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBodG1sID0gJGNvbXBpbGUodGVtcGxhdGUpKHNjb3BlKTtcclxuICAgICAgICAgICAgICAgICAgICAkKGVsZW1lbnQpLnJlcGxhY2VXaXRoKGh0bWwpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH1cclxuICAgIF0pOyIsImFuZ3VsYXJcclxuICAgIC5tb2R1bGUoXCJMYXlvdXRFZGl0b3JcIilcclxuICAgIC5kaXJlY3RpdmUoXCJvcmNMYXlvdXRDb2x1bW5cIiwgW1wiJGNvbXBpbGVcIiwgXCJzY29wZUNvbmZpZ3VyYXRvclwiLCBcImVudmlyb25tZW50XCIsXHJcbiAgICAgICAgZnVuY3Rpb24gKCRjb21waWxlLCBzY29wZUNvbmZpZ3VyYXRvciwgZW52aXJvbm1lbnQpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgICAgIHJlc3RyaWN0OiBcIkVcIixcclxuICAgICAgICAgICAgICAgIHNjb3BlOiB7IGVsZW1lbnQ6IFwiPVwiIH0sXHJcbiAgICAgICAgICAgICAgICBjb250cm9sbGVyOiBbXCIkc2NvcGVcIiwgXCIkZWxlbWVudFwiLFxyXG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uICgkc2NvcGUsICRlbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlQ29uZmlndXJhdG9yLmNvbmZpZ3VyZUZvckVsZW1lbnQoJHNjb3BlLCAkZWxlbWVudCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlQ29uZmlndXJhdG9yLmNvbmZpZ3VyZUZvckNvbnRhaW5lcigkc2NvcGUsICRlbGVtZW50KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLnNvcnRhYmxlT3B0aW9uc1tcImF4aXNcIl0gPSBcInlcIjtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBdLFxyXG4gICAgICAgICAgICAgICAgdGVtcGxhdGVVcmw6IGVudmlyb25tZW50LnRlbXBsYXRlVXJsKFwiQ29sdW1uXCIpLFxyXG4gICAgICAgICAgICAgICAgcmVwbGFjZTogdHJ1ZSxcclxuICAgICAgICAgICAgICAgIGxpbms6IGZ1bmN0aW9uIChzY29wZSwgZWxlbWVudCwgYXR0cnMpIHtcclxuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmZpbmQoXCIubGF5b3V0LWNvbHVtbi1yZXNpemUtYmFyXCIpLmRyYWdnYWJsZSh7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXM6IFwieFwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBoZWxwZXI6IFwiY2xvbmVcIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV2ZXJ0OiB0cnVlLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBzdGFydDogZnVuY3Rpb24gKGUsIHVpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY29wZS4kYXBwbHkoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlLmVsZW1lbnQuZWRpdG9yLmlzUmVzaXppbmcgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGRyYWc6IGZ1bmN0aW9uIChlLCB1aSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNvbHVtbkVsZW1lbnQgPSBlbGVtZW50LnBhcmVudCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNvbHVtblNpemUgPSBjb2x1bW5FbGVtZW50LndpZHRoKCkgLyBzY29wZS5lbGVtZW50LndpZHRoO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNvbm5lY3RBZGphY2VudCA9ICFlLmN0cmxLZXk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoJChlLnRhcmdldCkuaGFzQ2xhc3MoXCJsYXlvdXQtY29sdW1uLXJlc2l6ZS1iYXItbGVmdFwiKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkZWx0YSA9IHVpLm9mZnNldC5sZWZ0IC0gY29sdW1uRWxlbWVudC5vZmZzZXQoKS5sZWZ0O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkZWx0YSA8IC1jb2x1bW5TaXplICYmIHNjb3BlLmVsZW1lbnQuY2FuRXhwYW5kTGVmdChjb25uZWN0QWRqYWNlbnQpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlLiRhcHBseShmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY29wZS5lbGVtZW50LmV4cGFuZExlZnQoY29ubmVjdEFkamFjZW50KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKGRlbHRhID4gY29sdW1uU2l6ZSAmJiBzY29wZS5lbGVtZW50LmNhbkNvbnRyYWN0TGVmdChjb25uZWN0QWRqYWNlbnQpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlLiRhcHBseShmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY29wZS5lbGVtZW50LmNvbnRyYWN0TGVmdChjb25uZWN0QWRqYWNlbnQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICgkKGUudGFyZ2V0KS5oYXNDbGFzcyhcImxheW91dC1jb2x1bW4tcmVzaXplLWJhci1yaWdodFwiKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkZWx0YSA9IHVpLm9mZnNldC5sZWZ0IC0gY29sdW1uRWxlbWVudC53aWR0aCgpIC0gY29sdW1uRWxlbWVudC5vZmZzZXQoKS5sZWZ0O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkZWx0YSA+IGNvbHVtblNpemUgJiYgc2NvcGUuZWxlbWVudC5jYW5FeHBhbmRSaWdodChjb25uZWN0QWRqYWNlbnQpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlLiRhcHBseShmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY29wZS5lbGVtZW50LmV4cGFuZFJpZ2h0KGNvbm5lY3RBZGphY2VudCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChkZWx0YSA8IC1jb2x1bW5TaXplICYmIHNjb3BlLmVsZW1lbnQuY2FuQ29udHJhY3RSaWdodChjb25uZWN0QWRqYWNlbnQpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlLiRhcHBseShmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY29wZS5lbGVtZW50LmNvbnRyYWN0UmlnaHQoY29ubmVjdEFkamFjZW50KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgc3RvcDogZnVuY3Rpb24gKGUsIHVpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY29wZS4kYXBwbHkoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY29wZS5lbGVtZW50LmVkaXRvci5pc1Jlc2l6aW5nID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH1cclxuICAgIF0pOyIsImFuZ3VsYXJcclxuICAgIC5tb2R1bGUoXCJMYXlvdXRFZGl0b3JcIilcclxuICAgIC5kaXJlY3RpdmUoXCJvcmNMYXlvdXRDb250ZW50XCIsIFtcIiRzY2VcIiwgXCJzY29wZUNvbmZpZ3VyYXRvclwiLCBcImVudmlyb25tZW50XCIsXHJcbiAgICAgICAgZnVuY3Rpb24gKCRzY2UsIHNjb3BlQ29uZmlndXJhdG9yLCBlbnZpcm9ubWVudCkge1xyXG4gICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgcmVzdHJpY3Q6IFwiRVwiLFxyXG4gICAgICAgICAgICAgICAgc2NvcGU6IHsgZWxlbWVudDogXCI9XCIgfSxcclxuICAgICAgICAgICAgICAgIGNvbnRyb2xsZXI6IFtcIiRzY29wZVwiLCBcIiRlbGVtZW50XCIsXHJcbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gKCRzY29wZSwgJGVsZW1lbnQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgc2NvcGVDb25maWd1cmF0b3IuY29uZmlndXJlRm9yRWxlbWVudCgkc2NvcGUsICRlbGVtZW50KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmVkaXQgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuJHJvb3QuZWRpdEVsZW1lbnQoJHNjb3BlLmVsZW1lbnQpLnRoZW4oZnVuY3Rpb24gKGFyZ3MpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuJGFwcGx5KGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFyZ3MuY2FuY2VsKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmVsZW1lbnQuZGF0YSA9IGFyZ3MuZWxlbWVudC5kYXRhO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuZWxlbWVudC5zZXRIdG1sKGFyZ3MuZWxlbWVudC5odG1sKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3ZlcndyaXRlIHRoZSBzZXRIdG1sIGZ1bmN0aW9uIHNvIHRoYXQgd2UgY2FuIHVzZSB0aGUgJHNjZSBzZXJ2aWNlIHRvIHRydXN0IHRoZSBodG1sIChhbmQgbm90IGhhdmUgdGhlIGh0bWwgYmluZGluZyBzdHJpcCBjZXJ0YWluIHRhZ3MpLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuZWxlbWVudC5zZXRIdG1sID0gZnVuY3Rpb24gKGh0bWwpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS5lbGVtZW50Lmh0bWwgPSBodG1sO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmVsZW1lbnQuaHRtbFVuc2FmZSA9ICRzY2UudHJ1c3RBc0h0bWwoaHRtbCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuZWxlbWVudC5zZXRIdG1sKCRzY29wZS5lbGVtZW50Lmh0bWwpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIF0sXHJcbiAgICAgICAgICAgICAgICB0ZW1wbGF0ZVVybDogZW52aXJvbm1lbnQudGVtcGxhdGVVcmwoXCJDb250ZW50XCIpLFxyXG4gICAgICAgICAgICAgICAgcmVwbGFjZTogdHJ1ZVxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH1cclxuICAgIF0pOyIsImFuZ3VsYXJcclxuICAgIC5tb2R1bGUoXCJMYXlvdXRFZGl0b3JcIilcclxuICAgIC5kaXJlY3RpdmUoXCJvcmNMYXlvdXRIdG1sXCIsIFtcIiRzY2VcIiwgXCJzY29wZUNvbmZpZ3VyYXRvclwiLCBcImVudmlyb25tZW50XCIsXHJcbiAgICAgICAgZnVuY3Rpb24gKCRzY2UsIHNjb3BlQ29uZmlndXJhdG9yLCBlbnZpcm9ubWVudCkge1xyXG4gICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgcmVzdHJpY3Q6IFwiRVwiLFxyXG4gICAgICAgICAgICAgICAgc2NvcGU6IHsgZWxlbWVudDogXCI9XCIgfSxcclxuICAgICAgICAgICAgICAgIGNvbnRyb2xsZXI6IFtcIiRzY29wZVwiLCBcIiRlbGVtZW50XCIsXHJcbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gKCRzY29wZSwgJGVsZW1lbnQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgc2NvcGVDb25maWd1cmF0b3IuY29uZmlndXJlRm9yRWxlbWVudCgkc2NvcGUsICRlbGVtZW50KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmVkaXQgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuJHJvb3QuZWRpdEVsZW1lbnQoJHNjb3BlLmVsZW1lbnQpLnRoZW4oZnVuY3Rpb24gKGFyZ3MpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuJGFwcGx5KGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFyZ3MuY2FuY2VsKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmVsZW1lbnQuZGF0YSA9IGFyZ3MuZWxlbWVudC5kYXRhO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuZWxlbWVudC5zZXRIdG1sKGFyZ3MuZWxlbWVudC5odG1sKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUudXBkYXRlQ29udGVudCA9IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuZWxlbWVudC5zZXRIdG1sKGUudGFyZ2V0LmlubmVySFRNTCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBPdmVyd3JpdGUgdGhlIHNldEh0bWwgZnVuY3Rpb24gc28gdGhhdCB3ZSBjYW4gdXNlIHRoZSAkc2NlIHNlcnZpY2UgdG8gdHJ1c3QgdGhlIGh0bWwgKGFuZCBub3QgaGF2ZSB0aGUgaHRtbCBiaW5kaW5nIHN0cmlwIGNlcnRhaW4gdGFncykuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS5lbGVtZW50LnNldEh0bWwgPSBmdW5jdGlvbiAoaHRtbCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmVsZW1lbnQuaHRtbCA9IGh0bWw7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuZWxlbWVudC5odG1sVW5zYWZlID0gJHNjZS50cnVzdEFzSHRtbChodG1sKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS5lbGVtZW50LnNldEh0bWwoJHNjb3BlLmVsZW1lbnQuaHRtbCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgXSxcclxuICAgICAgICAgICAgICAgIHRlbXBsYXRlVXJsOiBlbnZpcm9ubWVudC50ZW1wbGF0ZVVybChcIkh0bWxcIiksXHJcbiAgICAgICAgICAgICAgICByZXBsYWNlOiB0cnVlLFxyXG4gICAgICAgICAgICAgICAgbGluazogZnVuY3Rpb24gKHNjb3BlLCBlbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gTW91c2UgZG93biBldmVudHMgbXVzdCBub3QgYmUgaW50ZXJjZXB0ZWQgYnkgZHJhZyBhbmQgZHJvcCB3aGlsZSBpbmxpbmUgZWRpdGluZyBpcyBhY3RpdmUsXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gb3RoZXJ3aXNlIGNsaWNrcyBpbiBpbmxpbmUgZWRpdG9ycyB3aWxsIGhhdmUgbm8gZWZmZWN0LlxyXG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuZmluZChcIi5sYXlvdXQtY29udGVudC1tYXJrdXBcIikubW91c2Vkb3duKGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzY29wZS5lbGVtZW50LmVkaXRvci5pbmxpbmVFZGl0aW5nSXNBY3RpdmUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfTtcclxuICAgICAgICB9XHJcbiAgICBdKTsiLCJhbmd1bGFyXHJcbiAgICAubW9kdWxlKFwiTGF5b3V0RWRpdG9yXCIpXHJcbiAgICAuZGlyZWN0aXZlKFwib3JjTGF5b3V0R3JpZFwiLCBbXCIkY29tcGlsZVwiLCBcInNjb3BlQ29uZmlndXJhdG9yXCIsIFwiZW52aXJvbm1lbnRcIixcclxuICAgICAgICBmdW5jdGlvbiAoJGNvbXBpbGUsIHNjb3BlQ29uZmlndXJhdG9yLCBlbnZpcm9ubWVudCkge1xyXG4gICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgcmVzdHJpY3Q6IFwiRVwiLFxyXG4gICAgICAgICAgICAgICAgc2NvcGU6IHsgZWxlbWVudDogXCI9XCIgfSxcclxuICAgICAgICAgICAgICAgIGNvbnRyb2xsZXI6IFtcIiRzY29wZVwiLCBcIiRlbGVtZW50XCIsXHJcbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gKCRzY29wZSwgJGVsZW1lbnQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgc2NvcGVDb25maWd1cmF0b3IuY29uZmlndXJlRm9yRWxlbWVudCgkc2NvcGUsICRlbGVtZW50KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgc2NvcGVDb25maWd1cmF0b3IuY29uZmlndXJlRm9yQ29udGFpbmVyKCRzY29wZSwgJGVsZW1lbnQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuc29ydGFibGVPcHRpb25zW1wiYXhpc1wiXSA9IFwieVwiO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIF0sXHJcbiAgICAgICAgICAgICAgICB0ZW1wbGF0ZVVybDogZW52aXJvbm1lbnQudGVtcGxhdGVVcmwoXCJHcmlkXCIpLFxyXG4gICAgICAgICAgICAgICAgcmVwbGFjZTogdHJ1ZVxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH1cclxuICAgIF0pOyIsImFuZ3VsYXJcclxuICAgIC5tb2R1bGUoXCJMYXlvdXRFZGl0b3JcIilcclxuICAgIC5kaXJlY3RpdmUoXCJvcmNMYXlvdXRSb3dcIiwgW1wiJGNvbXBpbGVcIiwgXCJzY29wZUNvbmZpZ3VyYXRvclwiLCBcImVudmlyb25tZW50XCIsXHJcbiAgICAgICAgZnVuY3Rpb24gKCRjb21waWxlLCBzY29wZUNvbmZpZ3VyYXRvciwgZW52aXJvbm1lbnQpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgICAgIHJlc3RyaWN0OiBcIkVcIixcclxuICAgICAgICAgICAgICAgIHNjb3BlOiB7IGVsZW1lbnQ6IFwiPVwiIH0sXHJcbiAgICAgICAgICAgICAgICBjb250cm9sbGVyOiBbXCIkc2NvcGVcIiwgXCIkZWxlbWVudFwiLFxyXG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uICgkc2NvcGUsICRlbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlQ29uZmlndXJhdG9yLmNvbmZpZ3VyZUZvckVsZW1lbnQoJHNjb3BlLCAkZWxlbWVudCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlQ29uZmlndXJhdG9yLmNvbmZpZ3VyZUZvckNvbnRhaW5lcigkc2NvcGUsICRlbGVtZW50KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLnNvcnRhYmxlT3B0aW9uc1tcImF4aXNcIl0gPSBcInhcIjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLnNvcnRhYmxlT3B0aW9uc1tcInVpLWZsb2F0aW5nXCJdID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBdLFxyXG4gICAgICAgICAgICAgICAgdGVtcGxhdGVVcmw6IGVudmlyb25tZW50LnRlbXBsYXRlVXJsKFwiUm93XCIpLFxyXG4gICAgICAgICAgICAgICAgcmVwbGFjZTogdHJ1ZVxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH1cclxuICAgIF0pOyIsImFuZ3VsYXJcclxuICAgIC5tb2R1bGUoXCJMYXlvdXRFZGl0b3JcIilcclxuICAgIC5kaXJlY3RpdmUoXCJvcmNMYXlvdXRQb3B1cFwiLCBbXHJcbiAgICAgICAgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgcmVzdHJpY3Q6IFwiQVwiLFxyXG4gICAgICAgICAgICAgICAgbGluazogZnVuY3Rpb24gKHNjb3BlLCBlbGVtZW50LCBhdHRycykge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBwb3B1cCA9ICQoZWxlbWVudCk7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRyaWdnZXIgPSBwb3B1cC5jbG9zZXN0KFwiLmxheW91dC1wb3B1cC10cmlnZ2VyXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBwYXJlbnRFbGVtZW50ID0gcG9wdXAuY2xvc2VzdChcIi5sYXlvdXQtZWxlbWVudFwiKTtcclxuICAgICAgICAgICAgICAgICAgICB0cmlnZ2VyLmNsaWNrKGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcG9wdXAudG9nZ2xlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwb3B1cC5pcyhcIjp2aXNpYmxlXCIpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3B1cC5wb3NpdGlvbih7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbXk6IGF0dHJzLm9yY0xheW91dFBvcHVwTXkgfHwgXCJsZWZ0IHRvcFwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF0OiBhdHRycy5vcmNMYXlvdXRQb3B1cEF0IHx8IFwibGVmdCBib3R0b20rNHB4XCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Y6IHRyaWdnZXJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9wdXAuZmluZChcImlucHV0XCIpLmZpcnN0KCkuZm9jdXMoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgIHBvcHVwLmNsaWNrKGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50RWxlbWVudC5jbGljayhmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBwb3B1cC5oaWRlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgcG9wdXAua2V5ZG93bihmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWUuY3RybEtleSAmJiAhZS5zaGlmdEtleSAmJiAhZS5hbHRLZXkgJiYgZS53aGljaCA9PSAyNykgLy8gRXNjXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3B1cC5oaWRlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgcG9wdXAub24oXCJjdXQgY29weSBwYXN0ZVwiLCBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBbGxvdyBjbGlwYm9hcmQgb3BlcmF0aW9ucyBpbiBwb3B1cCB3aXRob3V0IGludm9raW5nIGNsaXBib2FyZCBldmVudCBoYW5kbGVycyBvbiBwYXJlbnQgZWxlbWVudC5cclxuICAgICAgICAgICAgICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfTtcclxuICAgICAgICB9XHJcbiAgICBdKTsiLCJhbmd1bGFyXHJcbiAgICAubW9kdWxlKFwiTGF5b3V0RWRpdG9yXCIpXHJcbiAgICAuZGlyZWN0aXZlKFwib3JjTGF5b3V0VG9vbGJveFwiLCBbXCIkY29tcGlsZVwiLCBcImVudmlyb25tZW50XCIsXHJcbiAgICAgICAgZnVuY3Rpb24gKCRjb21waWxlLCBlbnZpcm9ubWVudCkge1xyXG4gICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgcmVzdHJpY3Q6IFwiRVwiLFxyXG4gICAgICAgICAgICAgICAgY29udHJvbGxlcjogW1wiJHNjb3BlXCIsIFwiJGVsZW1lbnRcIixcclxuICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiAoJHNjb3BlLCAkZWxlbWVudCkge1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLnJlc2V0RWxlbWVudHMgPSBmdW5jdGlvbiAoKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmdyaWRFbGVtZW50cyA9IFtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMYXlvdXRFZGl0b3IuR3JpZC5mcm9tKHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJveEljb246IFwiXFx1ZjAwYVwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b29sYm94TGFiZWw6IFwiR3JpZFwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b29sYm94RGVzY3JpcHRpb246IFwiRW1wdHkgZ3JpZC5cIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IFtdXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF07XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLnJvd0VsZW1lbnRzID0gW1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExheW91dEVkaXRvci5Sb3cuZnJvbSh7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3hJY29uOiBcIlxcdWYwYzlcIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJveExhYmVsOiBcIlJvdyAoMSBjb2x1bW4pXCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3hEZXNjcmlwdGlvbjogXCJSb3cgd2l0aCAxIGNvbHVtbi5cIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IExheW91dEVkaXRvci5Db2x1bW4udGltZXMoMSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMYXlvdXRFZGl0b3IuUm93LmZyb20oe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b29sYm94SWNvbjogXCJcXHVmMGM5XCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3hMYWJlbDogXCJSb3cgKDIgY29sdW1ucylcIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJveERlc2NyaXB0aW9uOiBcIlJvdyB3aXRoIDIgY29sdW1ucy5cIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IExheW91dEVkaXRvci5Db2x1bW4udGltZXMoMilcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMYXlvdXRFZGl0b3IuUm93LmZyb20oe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b29sYm94SWNvbjogXCJcXHVmMGM5XCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3hMYWJlbDogXCJSb3cgKDMgY29sdW1ucylcIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJveERlc2NyaXB0aW9uOiBcIlJvdyB3aXRoIDMgY29sdW1ucy5cIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IExheW91dEVkaXRvci5Db2x1bW4udGltZXMoMylcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMYXlvdXRFZGl0b3IuUm93LmZyb20oe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b29sYm94SWNvbjogXCJcXHVmMGM5XCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3hMYWJlbDogXCJSb3cgKDQgY29sdW1ucylcIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJveERlc2NyaXB0aW9uOiBcIlJvdyB3aXRoIDQgY29sdW1ucy5cIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IExheW91dEVkaXRvci5Db2x1bW4udGltZXMoNClcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMYXlvdXRFZGl0b3IuUm93LmZyb20oe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b29sYm94SWNvbjogXCJcXHVmMGM5XCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3hMYWJlbDogXCJSb3cgKDYgY29sdW1ucylcIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJveERlc2NyaXB0aW9uOiBcIlJvdyB3aXRoIDYgY29sdW1ucy5cIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IExheW91dEVkaXRvci5Db2x1bW4udGltZXMoNilcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMYXlvdXRFZGl0b3IuUm93LmZyb20oe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b29sYm94SWNvbjogXCJcXHVmMGM5XCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3hMYWJlbDogXCJSb3cgKDEyIGNvbHVtbnMpXCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3hEZXNjcmlwdGlvbjogXCJSb3cgd2l0aCAxMiBjb2x1bW5zLlwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogTGF5b3V0RWRpdG9yLkNvbHVtbi50aW1lcygxMilcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSwgTGF5b3V0RWRpdG9yLlJvdy5mcm9tKHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJveEljb246IFwiXFx1ZjBjOVwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b29sYm94TGFiZWw6IFwiUm93IChlbXB0eSlcIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJveERlc2NyaXB0aW9uOiBcIkVtcHR5IHJvdy5cIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IFtdXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF07XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmNvbHVtbkVsZW1lbnRzID0gW1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExheW91dEVkaXRvci5Db2x1bW4uZnJvbSh7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3hJY29uOiBcIlxcdWYwZGJcIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJveExhYmVsOiBcIkNvbHVtblwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b29sYm94RGVzY3JpcHRpb246IFwiRW1wdHkgY29sdW1uLlwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogMSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0OiAwLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogW11cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuY2FudmFzRWxlbWVudHMgPSBbXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTGF5b3V0RWRpdG9yLkNhbnZhcy5mcm9tKHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJveEljb246IFwiXFx1ZjA0NFwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b29sYm94TGFiZWw6IFwiQ2FudmFzXCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3hEZXNjcmlwdGlvbjogXCJFbXB0eSBjYW52YXMuXCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBbXVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBdO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS5jb250ZW50RWxlbWVudENhdGVnb3JpZXMgPSBfKCRzY29wZS5lbGVtZW50LmNvbmZpZy5jYXRlZ29yaWVzKS5tYXAoZnVuY3Rpb24gKGNhdGVnb3J5KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogY2F0ZWdvcnkubmFtZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudHM6IF8oY2F0ZWdvcnkuY29udGVudFR5cGVzKS5tYXAoZnVuY3Rpb24gKGNvbnRlbnRUeXBlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IGNvbnRlbnRUeXBlLnR5cGU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZmFjdG9yeSA9IExheW91dEVkaXRvci5mYWN0b3JpZXNbdHlwZV0gfHwgTGF5b3V0RWRpdG9yLmZhY3Rvcmllc1tcIkNvbnRlbnRcIl07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgaXRlbSA9IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1RlbXBsYXRlZDogZmFsc2UsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudFR5cGU6IGNvbnRlbnRUeXBlLmlkLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnRUeXBlTGFiZWw6IGNvbnRlbnRUeXBlLmxhYmVsLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnRUeXBlQ2xhc3M6IGNvbnRlbnRUeXBlLnR5cGVDbGFzcyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhOiBudWxsLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc0VkaXRvcjogY29udGVudFR5cGUuaGFzRWRpdG9yLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGh0bWw6IGNvbnRlbnRUeXBlLmh0bWxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZWxlbWVudCA9IGZhY3RvcnkoaXRlbSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnRvb2xib3hJY29uID0gY29udGVudFR5cGUuaWNvbiB8fCBcIlxcdWYxYzlcIjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQudG9vbGJveExhYmVsID0gY29udGVudFR5cGUubGFiZWw7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnRvb2xib3hEZXNjcmlwdGlvbiA9IGNvbnRlbnRUeXBlLmRlc2NyaXB0aW9uO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGVsZW1lbnQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS5yZXNldEVsZW1lbnRzKCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuZ2V0U29ydGFibGVPcHRpb25zID0gZnVuY3Rpb24gKHR5cGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBlZGl0b3JJZCA9ICRlbGVtZW50LmNsb3Nlc3QoXCIubGF5b3V0LWVkaXRvclwiKS5hdHRyKFwiaWRcIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Q2xhc3NlcztcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwbGFjZWhvbGRlckNsYXNzZXM7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZmxvYXRpbmcgPSBmYWxzZTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiR3JpZFwiOlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRDbGFzc2VzID0gW1wiLmxheW91dC1jYW52YXNcIiwgXCIubGF5b3V0LWNvbHVtblwiLCBcIi5sYXlvdXQtY29tbW9uLWhvbGRlclwiXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXJDbGFzc2VzID0gXCJsYXlvdXQtZWxlbWVudCBsYXlvdXQtY29udGFpbmVyIGxheW91dC1ncmlkIHVpLXNvcnRhYmxlLXBsYWNlaG9sZGVyXCI7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJSb3dcIjpcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Q2xhc3NlcyA9IFtcIi5sYXlvdXQtZ3JpZFwiXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXJDbGFzc2VzID0gXCJsYXlvdXQtZWxlbWVudCBsYXlvdXQtY29udGFpbmVyIGxheW91dC1yb3cgcm93IHVpLXNvcnRhYmxlLXBsYWNlaG9sZGVyXCI7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJDb2x1bW5cIjpcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Q2xhc3NlcyA9IFtcIi5sYXlvdXQtcm93Om5vdCgubGF5b3V0LXJvdy1mdWxsKVwiXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXJDbGFzc2VzID0gXCJsYXlvdXQtZWxlbWVudCBsYXlvdXQtY29udGFpbmVyIGxheW91dC1jb2x1bW4gdWktc29ydGFibGUtcGxhY2Vob2xkZXJcIjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmxvYXRpbmcgPSB0cnVlOyAvLyBUbyBlbnN1cmUgYSBzbW9vdGggaG9yaXpvbnRhbC1saXN0IHJlb3JkZXJpbmcuIGh0dHBzOi8vZ2l0aHViLmNvbS9hbmd1bGFyLXVpL3VpLXNvcnRhYmxlI2Zsb2F0aW5nXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJDb250ZW50XCI6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudENsYXNzZXMgPSBbXCIubGF5b3V0LWNhbnZhc1wiLCBcIi5sYXlvdXQtY29sdW1uXCIsIFwiLmxheW91dC1jb21tb24taG9sZGVyXCJdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlckNsYXNzZXMgPSBcImxheW91dC1lbGVtZW50IGxheW91dC1jb250ZW50IHVpLXNvcnRhYmxlLXBsYWNlaG9sZGVyXCI7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJDYW52YXNcIjpcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Q2xhc3NlcyA9IFtcIi5sYXlvdXQtY2FudmFzXCIsIFwiLmxheW91dC1jb2x1bW5cIiwgXCIubGF5b3V0LWNvbW1vbi1ob2xkZXJcIl07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyQ2xhc3NlcyA9IFwibGF5b3V0LWVsZW1lbnQgbGF5b3V0LWNvbnRhaW5lciBsYXlvdXQtZ3JpZCB1aS1zb3J0YWJsZS1wbGFjZWhvbGRlclwiO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnNvcjogXCJtb3ZlXCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29ubmVjdFdpdGg6IF8ocGFyZW50Q2xhc3NlcykubWFwKGZ1bmN0aW9uIChlKSB7IHJldHVybiBcIiNcIiArIGVkaXRvcklkICsgXCIgXCIgKyBlICsgXCI6bm90KC5sYXlvdXQtY29udGFpbmVyLXNlYWxlZCkgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciA+IC5sYXlvdXQtY2hpbGRyZW5cIjsgfSkuam9pbihcIiwgXCIpLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBwbGFjZWhvbGRlckNsYXNzZXMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJ1aS1mbG9hdGluZ1wiOiBmbG9hdGluZyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcmVhdGU6IGZ1bmN0aW9uIChlLCB1aSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLnRhcmdldC5pc1Rvb2xib3ggPSB0cnVlOyAvLyBXaWxsIGluZGljYXRlIHRvIGNvbm5lY3RlZCBzb3J0YWJsZXMgdGhhdCBkcm9wcGVkIGl0ZW1zIHdlcmUgc2VudCBmcm9tIHRvb2xib3guXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydDogZnVuY3Rpb24gKGUsIHVpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS4kYXBwbHkoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmVsZW1lbnQuaXNEcmFnZ2luZyA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RvcDogZnVuY3Rpb24gKGUsIHVpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS4kYXBwbHkoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmVsZW1lbnQuaXNEcmFnZ2luZyA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLnJlc2V0RWxlbWVudHMoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdmVyOiBmdW5jdGlvbiAoZSwgdWkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLiRhcHBseShmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuZWxlbWVudC5jYW52YXMuc2V0SXNEcm9wVGFyZ2V0KGZhbHNlKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsYXlvdXRJc0NvbGxhcHNlZENvb2tpZU5hbWUgPSBcImxheW91dFRvb2xib3hDYXRlZ29yeV9MYXlvdXRfSXNDb2xsYXBzZWRcIjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmxheW91dElzQ29sbGFwc2VkID0gJC5jb29raWUobGF5b3V0SXNDb2xsYXBzZWRDb29raWVOYW1lKSA9PT0gXCJ0cnVlXCI7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUudG9nZ2xlTGF5b3V0SXNDb2xsYXBzZWQgPSBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmxheW91dElzQ29sbGFwc2VkID0gISRzY29wZS5sYXlvdXRJc0NvbGxhcHNlZDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQuY29va2llKGxheW91dElzQ29sbGFwc2VkQ29va2llTmFtZSwgJHNjb3BlLmxheW91dElzQ29sbGFwc2VkLCB7IGV4cGlyZXM6IDM2NSB9KTsgLy8gUmVtZW1iZXIgY29sbGFwc2VkIHN0YXRlIGZvciBhIHllYXIuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIF0sXHJcbiAgICAgICAgICAgICAgICB0ZW1wbGF0ZVVybDogZW52aXJvbm1lbnQudGVtcGxhdGVVcmwoXCJUb29sYm94XCIpLFxyXG4gICAgICAgICAgICAgICAgcmVwbGFjZTogdHJ1ZSxcclxuICAgICAgICAgICAgICAgIGxpbms6IGZ1bmN0aW9uIChzY29wZSwgZWxlbWVudCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciB0b29sYm94ID0gZWxlbWVudC5maW5kKFwiLmxheW91dC10b29sYm94XCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICQod2luZG93KS5vbihcInJlc2l6ZSBzY3JvbGxcIiwgZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNhbnZhcyA9IGVsZW1lbnQucGFyZW50KCkuZmluZChcIi5sYXlvdXQtY2FudmFzXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgY2FudmFzIGlzIHRhbGxlciB0aGFuIHRoZSB0b29sYm94LCBtYWtlIHRoZSB0b29sYm94IHN0aWNreS1wb3NpdGlvbmVkIHdpdGhpbiB0aGUgZWRpdG9yXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRvIGhlbHAgdGhlIHVzZXIgYXZvaWQgZXhjZXNzaXZlIHZlcnRpY2FsIHNjcm9sbGluZy5cclxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNhbnZhc0lzVGFsbGVyID0gISFjYW52YXMgJiYgY2FudmFzLmhlaWdodCgpID4gdG9vbGJveC5oZWlnaHQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHdpbmRvd1BvcyA9ICQod2luZG93KS5zY3JvbGxUb3AoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNhbnZhc0lzVGFsbGVyICYmIHdpbmRvd1BvcyA+IGVsZW1lbnQub2Zmc2V0KCkudG9wICsgZWxlbWVudC5oZWlnaHQoKSAtIHRvb2xib3guaGVpZ2h0KCkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3guYWRkQ2xhc3MoXCJzdGlja3ktYm90dG9tXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJveC5yZW1vdmVDbGFzcyhcInN0aWNreS10b3BcIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoY2FudmFzSXNUYWxsZXIgJiYgd2luZG93UG9zID4gZWxlbWVudC5vZmZzZXQoKS50b3ApIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3guYWRkQ2xhc3MoXCJzdGlja3ktdG9wXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJveC5yZW1vdmVDbGFzcyhcInN0aWNreS1ib3R0b21cIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b29sYm94LnJlbW92ZUNsYXNzKFwic3RpY2t5LXRvcFwiKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3gucmVtb3ZlQ2xhc3MoXCJzdGlja3ktYm90dG9tXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgfVxyXG4gICAgXSk7IiwiYW5ndWxhclxyXG4gICAgLm1vZHVsZShcIkxheW91dEVkaXRvclwiKVxyXG4gICAgLmRpcmVjdGl2ZShcIm9yY0xheW91dFRvb2xib3hHcm91cFwiLCBbXCIkY29tcGlsZVwiLCBcImVudmlyb25tZW50XCIsXHJcbiAgICAgICAgZnVuY3Rpb24gKCRjb21waWxlLCBlbnZpcm9ubWVudCkge1xyXG4gICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgcmVzdHJpY3Q6IFwiRVwiLFxyXG4gICAgICAgICAgICAgICAgc2NvcGU6IHsgY2F0ZWdvcnk6IFwiPVwiIH0sXHJcbiAgICAgICAgICAgICAgICBjb250cm9sbGVyOiBbXCIkc2NvcGVcIiwgXCIkZWxlbWVudFwiLFxyXG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uICgkc2NvcGUsICRlbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpc0NvbGxhcHNlZENvb2tpZU5hbWUgPSBcImxheW91dFRvb2xib3hDYXRlZ29yeV9cIiArICRzY29wZS5jYXRlZ29yeS5uYW1lICsgXCJfSXNDb2xsYXBzZWRcIjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmlzQ29sbGFwc2VkID0gJC5jb29raWUoaXNDb2xsYXBzZWRDb29raWVOYW1lKSA9PT0gXCJ0cnVlXCI7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS50b2dnbGVJc0NvbGxhcHNlZCA9IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuaXNDb2xsYXBzZWQgPSAhJHNjb3BlLmlzQ29sbGFwc2VkO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJC5jb29raWUoaXNDb2xsYXBzZWRDb29raWVOYW1lLCAkc2NvcGUuaXNDb2xsYXBzZWQsIHsgZXhwaXJlczogMzY1IH0pOyAvLyBSZW1lbWJlciBjb2xsYXBzZWQgc3RhdGUgZm9yIGEgeWVhci5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgXSxcclxuICAgICAgICAgICAgICAgIHRlbXBsYXRlVXJsOiBlbnZpcm9ubWVudC50ZW1wbGF0ZVVybChcIlRvb2xib3hHcm91cFwiKSxcclxuICAgICAgICAgICAgICAgIHJlcGxhY2U6IHRydWVcclxuICAgICAgICAgICAgfTtcclxuICAgICAgICB9XHJcbiAgICBdKTsiXSwic291cmNlUm9vdCI6Ii9zb3VyY2UvIn0= \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIk1vZHVsZS5qcyIsIkNsaXBib2FyZC5qcyIsIlNjb3BlQ29uZmlndXJhdG9yLmpzIiwiRWRpdG9yLmpzIiwiQ2FudmFzLmpzIiwiQ2hpbGQuanMiLCJDb2x1bW4uanMiLCJDb250ZW50LmpzIiwiSHRtbC5qcyIsIkdyaWQuanMiLCJSb3cuanMiLCJQb3B1cC5qcyIsIlRvb2xib3guanMiLCJUb29sYm94R3JvdXAuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQzdDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ2pVQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUN6SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNsQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ25FQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNuQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ3hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ2xCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDbkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDdkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQzlNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiTGF5b3V0RWRpdG9yLmpzIiwic291cmNlc0NvbnRlbnQiOlsiYW5ndWxhci5tb2R1bGUoXCJMYXlvdXRFZGl0b3JcIiwgW1wibmdTYW5pdGl6ZVwiLCBcIm5nUmVzb3VyY2VcIiwgXCJ1aS5zb3J0YWJsZVwiXSk7IiwidmFyIExheW91dEVkaXRvcjtcclxuKGZ1bmN0aW9uKExheW91dEVkaXRvcikge1xyXG5cclxuICAgIHZhciBDbGlwYm9hcmQgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xyXG4gICAgICAgIHRoaXMuX2NsaXBib2FyZERhdGEgPSB7fTtcclxuICAgICAgICB0aGlzLl9pc0Rpc2FibGVkID0gZmFsc2U7XHJcbiAgICAgICAgdGhpcy5fd2FzSW52b2tlZCA9IGZhbHNlO1xyXG5cclxuICAgICAgICB0aGlzLnNldERhdGEgPSBmdW5jdGlvbihjb250ZW50VHlwZSwgZGF0YSkge1xyXG4gICAgICAgICAgICBzZWxmLl9jbGlwYm9hcmREYXRhW2NvbnRlbnRUeXBlXSA9IGRhdGE7XHJcbiAgICAgICAgICAgIHNlbGYuX3dhc0ludm9rZWQgPSB0cnVlO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgdGhpcy5nZXREYXRhID0gZnVuY3Rpb24gKGNvbnRlbnRUeXBlKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBzZWxmLl9jbGlwYm9hcmREYXRhW2NvbnRlbnRUeXBlXTtcclxuICAgICAgICAgICAgc2VsZi5fd2FzSW52b2tlZCA9IHRydWU7XHJcbiAgICAgICAgfTtcclxuICAgICAgICB0aGlzLmRpc2FibGUgPSBmdW5jdGlvbigpIHtcclxuICAgICAgICAgICAgc2VsZi5faXNEaXNhYmxlZCA9IHRydWU7XHJcbiAgICAgICAgICAgIHNlbGYuX3dhc0ludm9rZWQgPSBmYWxzZTtcclxuICAgICAgICAgICAgc2VsZi5fY2xpcGJvYXJkRGF0YSA9IHt9O1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgdGhpcy5pc0Rpc2FibGVkID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gc2VsZi5faXNEaXNhYmxlZDtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy53YXNJbnZva2VkID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gc2VsZi5fd2FzSW52b2tlZDtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgTGF5b3V0RWRpdG9yLkNsaXBib2FyZCA9IG5ldyBDbGlwYm9hcmQoKTtcclxuXHJcbiAgICBhbmd1bGFyXHJcbiAgICAgICAgLm1vZHVsZShcIkxheW91dEVkaXRvclwiKVxyXG4gICAgICAgIC5mYWN0b3J5KFwiY2xpcGJvYXJkXCIsIFtcclxuICAgICAgICAgICAgZnVuY3Rpb24oKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHNldERhdGE6IExheW91dEVkaXRvci5DbGlwYm9hcmQuc2V0RGF0YSxcclxuICAgICAgICAgICAgICAgICAgICBnZXREYXRhOiBMYXlvdXRFZGl0b3IuQ2xpcGJvYXJkLmdldERhdGEsXHJcbiAgICAgICAgICAgICAgICAgICAgZGlzYWJsZTogTGF5b3V0RWRpdG9yLkNsaXBib2FyZC5kaXNhYmxlLFxyXG4gICAgICAgICAgICAgICAgICAgIGlzRGlzYWJsZWQ6IExheW91dEVkaXRvci5DbGlwYm9hcmQuaXNEaXNhYmxlZCxcclxuICAgICAgICAgICAgICAgICAgICB3YXNJbnZva2VkOiBMYXlvdXRFZGl0b3IuQ2xpcGJvYXJkLndhc0ludm9rZWRcclxuICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICBdKTtcclxufSkoTGF5b3V0RWRpdG9yIHx8IChMYXlvdXRFZGl0b3IgPSB7fSkpOyIsImFuZ3VsYXJcclxuICAgIC5tb2R1bGUoXCJMYXlvdXRFZGl0b3JcIilcclxuICAgIC5mYWN0b3J5KFwic2NvcGVDb25maWd1cmF0b3JcIiwgW1wiJHRpbWVvdXRcIiwgXCJjbGlwYm9hcmRcIixcclxuICAgICAgICBmdW5jdGlvbiAoJHRpbWVvdXQsIGNsaXBib2FyZCkge1xyXG4gICAgICAgICAgICByZXR1cm4ge1xyXG5cclxuICAgICAgICAgICAgICAgIGNvbmZpZ3VyZUZvckVsZW1lbnQ6IGZ1bmN0aW9uICgkc2NvcGUsICRlbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgICAgICAkZWxlbWVudC5maW5kKFwiLmxheW91dC1wYW5lbFwiKS5jbGljayhmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICAgICAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAkZWxlbWVudC5wYXJlbnQoKS5rZXlkb3duKGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBoYW5kbGVkID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciByZXNldEZvY3VzID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBlbGVtZW50ID0gJHNjb3BlLmVsZW1lbnQ7XHJcbiAgICAgICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbGVtZW50LmVkaXRvci5pc0RyYWdnaW5nKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgbmF0aXZlIGNsaXBib2FyZCBzdXBwb3J0IGV4aXN0cywgdGhlIHBzZXVkby1jbGlwYm9hcmQgd2lsbCBoYXZlIGJlZW4gZGlzYWJsZWQuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY2xpcGJvYXJkLmlzRGlzYWJsZWQoKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGZvY3VzZWRFbGVtZW50ID0gZWxlbWVudC5lZGl0b3IuZm9jdXNlZEVsZW1lbnQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFmb2N1c2VkRWxlbWVudCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBzZXVkbyBjbGlwYm9hcmQgaGFuZGxpbmcgZm9yIGJyb3dzZXJzIG5vdCBhbGxvd2luZyByZWFsIGNsaXBib2FyZCBvcGVyYXRpb25zLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlLmN0cmxLZXkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChlLndoaWNoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgNjc6IC8vIENcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvY3VzZWRFbGVtZW50LmNvcHkoY2xpcGJvYXJkKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDg4OiAvLyBYXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb2N1c2VkRWxlbWVudC5jdXQoY2xpcGJvYXJkKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDg2OiAvLyBWXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb2N1c2VkRWxlbWVudC5wYXN0ZShjbGlwYm9hcmQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZS5jdHJsS2V5ICYmICFlLnNoaWZ0S2V5ICYmICFlLmFsdEtleSAmJiBlLndoaWNoID09IDQ2KSB7IC8vIERlbFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmRlbGV0ZShlbGVtZW50KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhbmRsZWQgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFlLmN0cmxLZXkgJiYgIWUuc2hpZnRLZXkgJiYgIWUuYWx0S2V5ICYmIChlLndoaWNoID09IDMyIHx8IGUud2hpY2ggPT0gMjcpKSB7IC8vIFNwYWNlIG9yIEVzY1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGVsZW1lbnQuZmluZChcIi5sYXlvdXQtcGFuZWwtYWN0aW9uLXByb3BlcnRpZXNcIikuZmlyc3QoKS5jbGljaygpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFuZGxlZCA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbGVtZW50LnR5cGUgPT0gXCJDb250ZW50XCIpIHsgLy8gVGhpcyBpcyBhIGNvbnRlbnQgZWxlbWVudC5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZS5jdHJsS2V5ICYmICFlLnNoaWZ0S2V5ICYmICFlLmFsdEtleSAmJiBlLndoaWNoID09IDEzKSB7IC8vIEVudGVyXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGVsZW1lbnQuZmluZChcIi5sYXlvdXQtcGFuZWwtYWN0aW9uLWVkaXRcIikuZmlyc3QoKS5jbGljaygpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhbmRsZWQgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFlbGVtZW50LmNoaWxkcmVuKSB7IC8vIFRoaXMgaXMgYSBjb250YWluZXIuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWUuY3RybEtleSAmJiAhZS5zaGlmdEtleSAmJiBlLmFsdEtleSAmJiBlLndoaWNoID09IDQwKSB7IC8vIEFsdCtEb3duXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQuY2hpbGRyZW4ubGVuZ3RoID4gMClcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5jaGlsZHJlblswXS5zZXRJc0ZvY3VzZWQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYW5kbGVkID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbWVudC50eXBlID09IFwiQ29sdW1uXCIpIHsgLy8gVGhpcyBpcyBhIGNvbHVtbi5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY29ubmVjdEFkamFjZW50ID0gIWUuY3RybEtleTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZS53aGljaCA9PSAzNykgeyAvLyBMZWZ0XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlLmFsdEtleSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuZXhwYW5kTGVmdChjb25uZWN0QWRqYWNlbnQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZS5zaGlmdEtleSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuY29udHJhY3RSaWdodChjb25uZWN0QWRqYWNlbnQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYW5kbGVkID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGUud2hpY2ggPT0gMzkpIHsgLy8gUmlnaHRcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGUuYWx0S2V5KVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5jb250cmFjdExlZnQoY29ubmVjdEFkamFjZW50KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGUuc2hpZnRLZXkpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmV4cGFuZFJpZ2h0KGNvbm5lY3RBZGphY2VudCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhbmRsZWQgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhZWxlbWVudC5wYXJlbnQpIHsgLy8gVGhpcyBpcyBhIGNoaWxkLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGUuYWx0S2V5ICYmIGUud2hpY2ggPT0gMzgpIHsgLy8gQWx0K1VwXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5wYXJlbnQuc2V0SXNGb2N1c2VkKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFuZGxlZCA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQucGFyZW50LnR5cGUgPT0gXCJSb3dcIikgeyAvLyBQYXJlbnQgaXMgYSBob3Jpem9udGFsIGNvbnRhaW5lci5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWUuY3RybEtleSAmJiAhZS5zaGlmdEtleSAmJiAhZS5hbHRLZXkgJiYgZS53aGljaCA9PSAzNykgeyAvLyBMZWZ0XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQucGFyZW50Lm1vdmVGb2N1c1ByZXZDaGlsZChlbGVtZW50KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFuZGxlZCA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKCFlLmN0cmxLZXkgJiYgIWUuc2hpZnRLZXkgJiYgIWUuYWx0S2V5ICYmIGUud2hpY2ggPT0gMzkpIHsgLy8gUmlnaHRcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5wYXJlbnQubW92ZUZvY3VzTmV4dENoaWxkKGVsZW1lbnQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYW5kbGVkID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoZS5jdHJsS2V5ICYmICFlLnNoaWZ0S2V5ICYmICFlLmFsdEtleSAmJiBlLndoaWNoID09IDM3KSB7IC8vIEN0cmwrTGVmdFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50Lm1vdmVVcCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNldEZvY3VzID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFuZGxlZCA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKGUuY3RybEtleSAmJiAhZS5zaGlmdEtleSAmJiAhZS5hbHRLZXkgJiYgZS53aGljaCA9PSAzOSkgeyAvLyBDdHJsK1JpZ2h0XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQubW92ZURvd24oKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFuZGxlZCA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7IC8vIFBhcmVudCBpcyBhIHZlcnRpY2FsIGNvbnRhaW5lci5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWUuY3RybEtleSAmJiAhZS5zaGlmdEtleSAmJiAhZS5hbHRLZXkgJiYgZS53aGljaCA9PSAzOCkgeyAvLyBVcFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnBhcmVudC5tb3ZlRm9jdXNQcmV2Q2hpbGQoZWxlbWVudCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhbmRsZWQgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICghZS5jdHJsS2V5ICYmICFlLnNoaWZ0S2V5ICYmICFlLmFsdEtleSAmJiBlLndoaWNoID09IDQwKSB7IC8vIERvd25cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5wYXJlbnQubW92ZUZvY3VzTmV4dENoaWxkKGVsZW1lbnQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYW5kbGVkID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoZS5jdHJsS2V5ICYmICFlLnNoaWZ0S2V5ICYmICFlLmFsdEtleSAmJiBlLndoaWNoID09IDM4KSB7IC8vIEN0cmwrVXBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5tb3ZlVXAoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzZXRGb2N1cyA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhbmRsZWQgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChlLmN0cmxLZXkgJiYgIWUuc2hpZnRLZXkgJiYgIWUuYWx0S2V5ICYmIGUud2hpY2ggPT0gNDApIHsgLy8gQ3RybCtEb3duXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQubW92ZURvd24oKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFuZGxlZCA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaGFuZGxlZCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLiRhcHBseSgpOyAvLyBFdmVudCBpcyBub3QgdHJpZ2dlcmVkIGJ5IEFuZ3VsYXIgZGlyZWN0aXZlIGJ1dCByYXcgZXZlbnQgaGFuZGxlciBvbiBlbGVtZW50LlxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSEFDSzogV29ya2Fyb3VuZCBiZWNhdXNlIG9mIGhvdyBBbmd1bGFyIHRyZWF0cyB0aGUgRE9NIHdoZW4gZWxlbWVudHMgYXJlIHNoaWZ0ZWQgYXJvdW5kIC0gaW5wdXQgZm9jdXMgaXMgc29tZXRpbWVzIGxvc3QuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXNldEZvY3VzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLiRhcHBseShmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuZWRpdG9yLmZvY3VzZWRFbGVtZW50LnNldElzRm9jdXNlZCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgMTAwKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAkc2NvcGUuZWxlbWVudC5zZXRJc0ZvY3VzZWRFdmVudEhhbmRsZXJzLnB1c2goZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAkZWxlbWVudC5wYXJlbnQoKS5mb2N1cygpO1xyXG4gICAgICAgICAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAkc2NvcGUuZGVsZXRlID0gZnVuY3Rpb24gKGVsZW1lbnQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5kZWxldGUoKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9LFxyXG5cclxuICAgICAgICAgICAgICAgIGNvbmZpZ3VyZUZvckNvbnRhaW5lcjogZnVuY3Rpb24gKCRzY29wZSwgJGVsZW1lbnQpIHtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgZWxlbWVudCA9ICRzY29wZS5lbGVtZW50O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAvLyRzY29wZS5pc1JlY2VpdmluZyA9IGZhbHNlOyAvLyBUcnVlIHdoZW4gY29udGFpbmVyIGlzIHJlY2VpdmluZyBhbiBleHRlcm5hbCBlbGVtZW50IHZpYSBkcmFnL2Ryb3AuXHJcbiAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmdldFNob3dDaGlsZHJlblBsYWNlaG9sZGVyID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJHNjb3BlLmVsZW1lbnQuY2hpbGRyZW4ubGVuZ3RoID09PSAwICYmICEkc2NvcGUuZWxlbWVudC5nZXRJc0Ryb3BUYXJnZXQoKTtcclxuICAgICAgICAgICAgICAgICAgICB9O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAkc2NvcGUuc29ydGFibGVPcHRpb25zID0ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjdXJzb3I6IFwibW92ZVwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBkZWxheTogMTUwLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBkaXNhYmxlZDogZWxlbWVudC5nZXRJc1NlYWxlZCgpLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBkaXN0YW5jZTogNSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy9oYW5kbGU6IGVsZW1lbnQuY2hpbGRyZW4ubGVuZ3RoIDwgMiA/IFwiLmltYWdpbmFyeS1jbGFzc1wiIDogZmFsc2UsIC8vIEZvciBzb21lIHJlYXNvbiBkb2Vzbid0IGdldCByZS1ldmFsdWF0ZWQgYWZ0ZXIgYWRkaW5nIG1vcmUgY2hpbGRyZW4uXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0OiBmdW5jdGlvbiAoZSwgdWkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS4kYXBwbHkoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuc2V0SXNEcm9wVGFyZ2V0KHRydWUpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuZWRpdG9yLmlzRHJhZ2dpbmcgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYWtlIHRoZSBkcm9wIHRhcmdldCBwbGFjZWhvbGRlciBhcyBoaWdoIGFzIHRoZSBpdGVtIGJlaW5nIGRyYWdnZWQuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1aS5wbGFjZWhvbGRlci5oZWlnaHQodWkuaXRlbS5oZWlnaHQoKSAtIDQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdWkucGxhY2Vob2xkZXIuY3NzKFwibWluLWhlaWdodFwiLCAwKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgc3RvcDogZnVuY3Rpb24gKGUsIHVpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuJGFwcGx5KGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmVkaXRvci5pc0RyYWdnaW5nID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5zZXRJc0Ryb3BUYXJnZXQoZmFsc2UpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG92ZXI6IGZ1bmN0aW9uIChlLCB1aSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhdWkuc2VuZGVyICYmICEhdWkuc2VuZGVyWzBdLmlzVG9vbGJveCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIXVpLnNlbmRlclswXS5kcm9wVGFyZ2V0VGltZW91dCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdGltZW91dC5jYW5jZWwodWkuc2VuZGVyWzBdLmRyb3BUYXJnZXRUaW1lb3V0KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdWkuc2VuZGVyWzBdLmRyb3BUYXJnZXRUaW1lb3V0ID0gbnVsbDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHRpbWVvdXQoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbWVudC50eXBlID09IFwiUm93XCIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZXJlIHdhcyBhIHByZXZpb3VzIGRyb3AgdGFyZ2V0IGFuZCBpdCB3YXMgYSByb3csIHJvbGwgYmFjayBhbnkgcGVuZGluZyBjb2x1bW4gYWRkcyB0byBpdC5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c0Ryb3BUYXJnZXQgPSBlbGVtZW50LmVkaXRvci5kcm9wVGFyZ2V0RWxlbWVudDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIXByZXZpb3VzRHJvcFRhcmdldCAmJiBwcmV2aW91c0Ryb3BUYXJnZXQudHlwZSA9PSBcIlJvd1wiKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZXZpb3VzRHJvcFRhcmdldC5yb2xsYmFja0FkZENvbHVtbigpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuc2V0SXNEcm9wVGFyZ2V0KGZhbHNlKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1aS5zZW5kZXJbMF0uZHJvcFRhcmdldFRpbWVvdXQgPSAkdGltZW91dChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbGVtZW50LnR5cGUgPT0gXCJSb3dcIikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJlY2VpdmVkQ29sdW1uID0gdWkuaXRlbS5zb3J0YWJsZS5tb2RlbDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciByZWNlaXZlZENvbHVtbldpZHRoID0gTWF0aC5mbG9vcigxMiAvIChlbGVtZW50LmNoaWxkcmVuLmxlbmd0aCArIDEpKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY2VpdmVkQ29sdW1uLndpZHRoID0gcmVjZWl2ZWRDb2x1bW5XaWR0aDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY2VpdmVkQ29sdW1uLm9mZnNldCA9IDA7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmJlZ2luQWRkQ29sdW1uKHJlY2VpdmVkQ29sdW1uV2lkdGgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSB0aGUgZHJvcCB0YXJnZXQgcGxhY2Vob2xkZXIgdGhlIGNvcnJlY3Qgd2lkdGggYW5kIGFzIGhpZ2ggYXMgdGhlIGhpZ2hlc3QgZXhpc3RpbmcgY29sdW1uIGluIHRoZSByb3cuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbWF4SGVpZ2h0ID0gXy5tYXgoXygkZWxlbWVudC5maW5kKFwiPiAubGF5b3V0LWNoaWxkcmVuID4gLmxheW91dC1jb2x1bW46bm90KC51aS1zb3J0YWJsZS1wbGFjZWhvbGRlcilcIikpLm1hcChmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAkKGUpLmhlaWdodCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChpID0gMTsgaSA8PSAxMjsgaSsrKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVpLnBsYWNlaG9sZGVyLnJlbW92ZUNsYXNzKFwiY29sLXhzLVwiICsgaSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1aS5wbGFjZWhvbGRlci5hZGRDbGFzcyhcImNvbC14cy1cIiArIHJlY2VpdmVkQ29sdW1uLndpZHRoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXhIZWlnaHQgPiAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdWkucGxhY2Vob2xkZXIuaGVpZ2h0KG1heEhlaWdodCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdWkucGxhY2Vob2xkZXIuY3NzKFwibWluLWhlaWdodFwiLCAwKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVpLnBsYWNlaG9sZGVyLmhlaWdodCgwKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1aS5wbGFjZWhvbGRlci5jc3MoXCJtaW4taGVpZ2h0XCIsIFwiXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuc2V0SXNEcm9wVGFyZ2V0KHRydWUpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIDE1MCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY2VpdmU6IGZ1bmN0aW9uIChlLCB1aSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhdWkuc2VuZGVyICYmICEhdWkuc2VuZGVyWzBdLmlzVG9vbGJveCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS4kYXBwbHkoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmVjZWl2ZWRFbGVtZW50ID0gdWkuaXRlbS5zb3J0YWJsZS5tb2RlbDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhcmVjZWl2ZWRFbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbWVudC50eXBlID09IFwiUm93XCIpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5jb21taXRBZGRDb2x1bW4oKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNob3VsZCBpZGVhbGx5IGNhbGwgTGF5b3V0RWRpdG9yLkNvbnRhaW5lci5hZGRDaGlsZCgpIGluc3RlYWQsIGJ1dCBzaW5jZSB0aGlzIGhhbmRsZXJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlzIHJ1biAqYmVmb3JlKiB0aGUgdWktc29ydGFibGUgZGlyZWN0aXZlJ3MgaGFuZGxlciwgaWYgd2UgdHJ5IHRvIGFkZCB0aGUgY2hpbGQgdG8gdGhlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhcnJheSB0aGF0IGhhbmRsZXIgd2lsbCBnZXQgYW4gZXhjZXB0aW9uIHdoZW4gdHJ5aW5nIHRvIGRvIHRoZSBzYW1lLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQmVjYXVzZSBvZiB0aGlzLCB3ZSBuZWVkIHRvIGludm9rZSBcInNldFBhcmVudFwiIHNvIHRoYXQgc3BlY2lmaWMgY29udGFpbmVyIHR5cGVzIGNhbiBwZXJmb3JtIGVsZW1lbnQgc3BlZmljaWMgaW5pdGlhbGl6YXRpb24uXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWNlaXZlZEVsZW1lbnQuc2V0RWRpdG9yKGVsZW1lbnQuZWRpdG9yKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY2VpdmVkRWxlbWVudC5zZXRQYXJlbnQoZWxlbWVudCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhcmVjZWl2ZWRFbGVtZW50Lmhhc0VkaXRvcikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS4kcm9vdC5lZGl0RWxlbWVudChyZWNlaXZlZEVsZW1lbnQpLnRoZW4oZnVuY3Rpb24gKGFyZ3MpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFhcmdzLmNhbmNlbCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjZWl2ZWRFbGVtZW50LmRhdGEgPSBhcmdzLmVsZW1lbnQuZGF0YTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY2VpdmVkRWxlbWVudC5hcHBseUVsZW1lbnRFZGl0b3JNb2RlbChhcmdzLmVsZW1lbnRFZGl0b3JNb2RlbCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhcmVjZWl2ZWRFbGVtZW50LnNldEh0bWwpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjZWl2ZWRFbGVtZW50LnNldEh0bWwoYXJncy5lbGVtZW50Lmh0bWwpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0aW1lb3V0KGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWFyZ3MuY2FuY2VsKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY2VpdmVkRWxlbWVudC5kZWxldGUoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWNlaXZlZEVsZW1lbnQuc2V0SXNGb2N1c2VkKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyRzY29wZS5pc1JlY2VpdmluZyA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5zZXRJc0Ryb3BUYXJnZXQoZmFsc2UpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdGltZW91dChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyRzY29wZS5pc1JlY2VpdmluZyA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5zZXRJc0Ryb3BUYXJnZXQoZmFsc2UpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhcmVjZWl2ZWRFbGVtZW50KVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY2VpdmVkRWxlbWVudC5zZXRJc0ZvY3VzZWQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAkc2NvcGUuY2xpY2sgPSBmdW5jdGlvbiAoY2hpbGQsIGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjaGlsZC5lZGl0b3IuaXNEcmFnZ2luZylcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkLnNldElzRm9jdXNlZCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICAgICAgICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICRzY29wZS5nZXRDbGFzc2VzID0gZnVuY3Rpb24gKGNoaWxkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSBbXCJsYXlvdXQtZWxlbWVudFwiXTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWNoaWxkLmNoaWxkcmVuKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChcImxheW91dC1jb250YWluZXJcIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGQuZ2V0SXNTZWFsZWQoKSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChcImxheW91dC1jb250YWluZXItc2VhbGVkXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChcImxheW91dC1cIiArIGNoaWxkLnR5cGUudG9Mb3dlckNhc2UoKSk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFjaGlsZC5kcm9wVGFyZ2V0Q2xhc3MpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChjaGlsZC5kcm9wVGFyZ2V0Q2xhc3MpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVE9ETzogTW92ZSB0aGVzZSB0byBlaXRoZXIgdGhlIENvbHVtbiBkaXJlY3RpdmUgb3IgdGhlIENvbHVtbiBtb2RlbCBjbGFzcy5cclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLnR5cGUgPT0gXCJSb3dcIikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goXCJyb3dcIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNoaWxkLmNhbkFkZENvbHVtbigpKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKFwibGF5b3V0LXJvdy1mdWxsXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC50eXBlID09IFwiQ29sdW1uXCIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKFwiY29sLXhzLVwiICsgY2hpbGQud2lkdGgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goXCJjb2wteHMtb2Zmc2V0LVwiICsgY2hpbGQub2Zmc2V0KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGQudHlwZSA9PSBcIkNvbnRlbnRcIilcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKFwibGF5b3V0LWNvbnRlbnQtXCIgKyBjaGlsZC5jb250ZW50VHlwZUNsYXNzKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5nZXRJc0FjdGl2ZSgpKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goXCJsYXlvdXQtZWxlbWVudC1hY3RpdmVcIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5nZXRJc0ZvY3VzZWQoKSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKFwibGF5b3V0LWVsZW1lbnQtZm9jdXNlZFwiKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLmdldElzU2VsZWN0ZWQoKSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKFwibGF5b3V0LWVsZW1lbnQtc2VsZWN0ZWRcIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5nZXRJc0Ryb3BUYXJnZXQoKSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKFwibGF5b3V0LWVsZW1lbnQtZHJvcHRhcmdldFwiKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLmlzVGVtcGxhdGVkKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goXCJsYXlvdXQtZWxlbWVudC10ZW1wbGF0ZWRcIik7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgfVxyXG4gICAgXSk7IiwiYW5ndWxhclxyXG4gICAgLm1vZHVsZShcIkxheW91dEVkaXRvclwiKVxyXG4gICAgLmRpcmVjdGl2ZShcIm9yY0xheW91dEVkaXRvclwiLCBbXCJlbnZpcm9ubWVudFwiLFxyXG4gICAgICAgIGZ1bmN0aW9uIChlbnZpcm9ubWVudCkge1xyXG4gICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgcmVzdHJpY3Q6IFwiRVwiLFxyXG4gICAgICAgICAgICAgICAgc2NvcGU6IHt9LFxyXG4gICAgICAgICAgICAgICAgY29udHJvbGxlcjogW1wiJHNjb3BlXCIsIFwiJGVsZW1lbnRcIiwgXCIkYXR0cnNcIiwgXCIkY29tcGlsZVwiLCBcImNsaXBib2FyZFwiLFxyXG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uICgkc2NvcGUsICRlbGVtZW50LCAkYXR0cnMsICRjb21waWxlLCBjbGlwYm9hcmQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhJGF0dHJzLm1vZGVsKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmVsZW1lbnQgPSBldmFsKCRhdHRycy5tb2RlbCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSAnbW9kZWwnIGF0dHJpYnV0ZSBtdXN0IGV2YWx1YXRlIHRvIGEgTGF5b3V0RWRpdG9yLkVkaXRvciBvYmplY3QuXCIpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmNsaWNrID0gZnVuY3Rpb24gKGNhbnZhcywgZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjYW52YXMuZWRpdG9yLmlzRHJhZ2dpbmcpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FudmFzLnNldElzRm9jdXNlZCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS5nZXRDbGFzc2VzID0gZnVuY3Rpb24gKGNhbnZhcykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IFtcImxheW91dC1lbGVtZW50XCIsIFwibGF5b3V0LWNvbnRhaW5lclwiLCBcImxheW91dC1jYW52YXNcIl07XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNhbnZhcy5nZXRJc0FjdGl2ZSgpKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKFwibGF5b3V0LWVsZW1lbnQtYWN0aXZlXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNhbnZhcy5nZXRJc0ZvY3VzZWQoKSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChcImxheW91dC1lbGVtZW50LWZvY3VzZWRcIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2FudmFzLmdldElzU2VsZWN0ZWQoKSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChcImxheW91dC1lbGVtZW50LXNlbGVjdGVkXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNhbnZhcy5nZXRJc0Ryb3BUYXJnZXQoKSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChcImxheW91dC1lbGVtZW50LWRyb3B0YXJnZXRcIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2FudmFzLmlzVGVtcGxhdGVkKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKFwibGF5b3V0LWVsZW1lbnQtdGVtcGxhdGVkXCIpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBbiB1bmZvcnR1bmF0ZSBzaWRlLWVmZmVjdCBvZiB0aGUgbmV4dCBoYWNrIG9uIGxpbmUgNTQgaXMgdGhhdCB0aGUgY3JlYXRlZCBlbGVtZW50cyBhcmVuJ3QgYWRkZWQgdG8gdGhlIERPTSB5ZXQsIHNvIHdlIGNhbid0IHVzZSBpdCB0byBnZXQgdG8gdGhlIHBhcmVudCBcIi5sYXlvdXQtZGVzaWdlclwiIGVsZW1lbnQuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdvcmsgYXJvdW5kOiBhY2Nlc3MgdGhhdCBlbGVtZW50IGRpcmVjdGx5ICh3aGljaCBlZmVjdGl2ZWx5IHR1cm5zIG11bHRpcGxlIGxheW91dCBlZGl0b3JzIG9uIGEgc2luZ2xlIHBhZ2UgaW1wb3NzaWJsZSkuIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAvL3ZhciBsYXlvdXREZXNpZ25lckhvc3QgPSAkZWxlbWVudC5jbG9zZXN0KFwiLmxheW91dC1kZXNpZ25lclwiKS5kYXRhKFwibGF5b3V0LWRlc2lnbmVyLWhvc3RcIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsYXlvdXREZXNpZ25lckhvc3QgPSAkKFwiLmxheW91dC1kZXNpZ25lclwiKS5kYXRhKFwibGF5b3V0LWRlc2lnbmVyLWhvc3RcIik7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuJHJvb3QubGF5b3V0RGVzaWduZXJIb3N0ID0gbGF5b3V0RGVzaWduZXJIb3N0O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgbGF5b3V0RGVzaWduZXJIb3N0LmVsZW1lbnQub24oXCJyZXBsYWNlY2FudmFzXCIsIGZ1bmN0aW9uIChlLCBhcmdzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZWRpdG9yID0gJHNjb3BlLmVsZW1lbnQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2FudmFzRGF0YSA9IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhOiBhcmdzLmNhbnZhcy5kYXRhLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGh0bWxJZDogYXJncy5jYW52YXMuaHRtbElkLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGh0bWxDbGFzczogYXJncy5jYW52YXMuaHRtbENsYXNzLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGh0bWxTdHlsZTogYXJncy5jYW52YXMuaHRtbFN0eWxlLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzVGVtcGxhdGVkOiBhcmdzLmNhbnZhcy5pc1RlbXBsYXRlZCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYXJncy5jYW52YXMuY2hpbGRyZW5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSEFDSzogSW5zdGVhZCBvZiBzaW1wbHkgdXBkYXRpbmcgdGhlICRzY29wZS5lbGVtZW50IHdpdGggYSBuZXcgaW5zdGFuY2UsIHdlIG5lZWQgdG8gcmVwbGFjZSB0aGUgZW50aXJlIG9yYy1sYXlvdXQtZWRpdG9yIG1hcmt1cFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW4gb3JkZXIgZm9yIGFuZ3VsYXIgdG8gcmViaW5kIHN0YXJ0aW5nIHdpdGggdGhlIENhbnZhcyBlbGVtZW50LiBPdGhlcndpc2UsIGZvciBzb21lIHJlYXNvbiwgaXQgd2lsbCByZWJpbmQgc3RhcnRpbmcgd2l0aCB0aGUgZmlyc3QgY2hpbGQgb2YgQ2FudmFzLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gWW91IGNhbiBzZWUgdGhpcyBoYXBwZW5pbmcgd2hlbiBzZXR0aW5nIGEgYnJlYWtwb2ludCBpbiBTY29wZUNvbmZpZ3VyYXRvciB3aGVyZSBjb250YWluZXJzIGFyZSBpbml0aWFsaXplZCB3aXRoIGRyYWcgJiBkcm9wOiBvbiBwYWdlIGxvYWQsIHRoZSBmaXJzdCBlbGVtZW50XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpcyBhIENhbnZhcyAoZ29vZCksIGJ1dCBhZnRlciBoYXZpbmcgc2VsZWN0ZWQgYW5vdGhlciB0ZW1wbGF0ZSwgdGhlIGZpcnN0IGVsZW1lbnQgaXMgKHR5cGljYWxseSkgYSBHcmlkIChiYWQpLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2ltcGx5IHJlY29tcGlsaW5nIHRoZSBvcmMtbGF5b3V0LWVkaXRvciBkaXJlY3RpdmUgd2lsbCBjYXVzZSB0aGUgZW50aXJlIHRoaW5nIHRvIGJlIGdlbmVyYXRlZCwgd2hpY2ggd29ya3MganVzdCBmaW5lIGFzIHdlbGwgKGV2ZW4gdGhvdWdoIG5vdCBpcyBuaWNlIGFzIHNpbXBseSBsZXZlcmFnaW5nIG1vZGVsIGJpbmRpbmcpLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF5b3V0RGVzaWduZXJIb3N0LmVkaXRvciA9IHdpbmRvdy5sYXlvdXRFZGl0b3IgPSBuZXcgTGF5b3V0RWRpdG9yLkVkaXRvcihlZGl0b3IuY29uZmlnLCBjYW52YXNEYXRhKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0ZW1wbGF0ZSA9IFwiPG9yYy1sYXlvdXQtZWRpdG9yXCIgKyBcIiBtb2RlbD0nd2luZG93LmxheW91dEVkaXRvcicgLz5cIjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBodG1sID0gJGNvbXBpbGUodGVtcGxhdGUpKCRzY29wZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKFwiLmxheW91dC1lZGl0b3ItaG9sZGVyXCIpLmh0bWwoaHRtbCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLiRyb290LmVkaXRFbGVtZW50ID0gZnVuY3Rpb24gKGVsZW1lbnQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBob3N0ID0gJHNjb3BlLiRyb290LmxheW91dERlc2lnbmVySG9zdDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBob3N0LmVkaXRFbGVtZW50KGVsZW1lbnQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLiRyb290LmFkZEVsZW1lbnQgPSBmdW5jdGlvbiAoY29udGVudFR5cGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBob3N0ID0gJHNjb3BlLiRyb290LmxheW91dERlc2lnbmVySG9zdDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBob3N0LmFkZEVsZW1lbnQoY29udGVudFR5cGUpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgJChkb2N1bWVudCkub24oXCJjdXQgY29weSBwYXN0ZVwiLCBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhlIHBzZXVkbyBjbGlwYm9hcmQgd2FzIGFscmVhZHkgaW52b2tlZCAod2hpY2ggaGFwcGVucyBvbiB0aGUgZmlyc3QgY2xpcGJvYXJkXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBvcGVyYXRpb24gYWZ0ZXIgcGFnZSBsb2FkIGV2ZW4gaWYgbmF0aXZlIGNsaXBib2FyZCBzdXBwb3J0IGV4aXN0cykgdGhlbiBzaXQgdGhpc1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gb25lIG9wZXJhdGlvbiBvdXQsIGJ1dCBtYWtlIHN1cmUgd2hhdGV2ZXIgaXMgb24gdGhlIHBzZXVkbyBjbGlwYm9hcmQgZ2V0cyBtaWdyYXRlZFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdG8gdGhlIG5hdGl2ZSBjbGlwYm9hcmQgZm9yIHN1YnNlcXVlbnQgb3BlcmF0aW9ucy5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjbGlwYm9hcmQud2FzSW52b2tlZCgpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZS5vcmlnaW5hbEV2ZW50LmNsaXBib2FyZERhdGEuc2V0RGF0YShcInRleHQvcGxhaW5cIiwgY2xpcGJvYXJkLmdldERhdGEoXCJ0ZXh0L3BsYWluXCIpKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLm9yaWdpbmFsRXZlbnQuY2xpcGJvYXJkRGF0YS5zZXREYXRhKFwidGV4dC9qc29uXCIsIGNsaXBib2FyZC5nZXREYXRhKFwidGV4dC9qc29uXCIpKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZm9jdXNlZEVsZW1lbnQgPSAkc2NvcGUuZWxlbWVudC5mb2N1c2VkRWxlbWVudDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFmb2N1c2VkRWxlbWVudCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuJGFwcGx5KGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoZS50eXBlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImNvcHlcIjpcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9jdXNlZEVsZW1lbnQuY29weShlLm9yaWdpbmFsRXZlbnQuY2xpcGJvYXJkRGF0YSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJjdXRcIjpcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9jdXNlZEVsZW1lbnQuY3V0KGUub3JpZ2luYWxFdmVudC5jbGlwYm9hcmREYXRhKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcInBhc3RlXCI6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvY3VzZWRFbGVtZW50LnBhc3RlKGUub3JpZ2luYWxFdmVudC5jbGlwYm9hcmREYXRhKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSEFDSzogV29ya2Fyb3VuZCBiZWNhdXNlIG9mIGhvdyBBbmd1bGFyIHRyZWF0cyB0aGUgRE9NIHdoZW4gZWxlbWVudHMgYXJlIHNoaWZ0ZWQgYXJvdW5kIC0gaW5wdXQgZm9jdXMgaXMgc29tZXRpbWVzIGxvc3QuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpbmRvdy5zZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS4kYXBwbHkoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghISRzY29wZS5lbGVtZW50LmZvY3VzZWRFbGVtZW50KVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuZWxlbWVudC5mb2N1c2VkRWxlbWVudC5zZXRJc0ZvY3VzZWQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCAxMDApO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBOYXRpdmUgY2xpcGJvYXJkIHN1cHBvcnQgb2J2aW91c2x5IGV4aXN0cywgc28gZGlzYWJsZSB0aGUgcGV1ZG8gY2xpcGJvYXJkIGZyb20gbm93IG9uLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xpcGJvYXJkLmRpc2FibGUoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgXSxcclxuICAgICAgICAgICAgICAgIHRlbXBsYXRlVXJsOiBlbnZpcm9ubWVudC50ZW1wbGF0ZVVybChcIkVkaXRvclwiKSxcclxuICAgICAgICAgICAgICAgIHJlcGxhY2U6IHRydWUsXHJcbiAgICAgICAgICAgICAgICBsaW5rOiBmdW5jdGlvbiAoc2NvcGUsIGVsZW1lbnQpIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBObyBjbGlja3Mgc2hvdWxkIHByb3BhZ2F0ZSBmcm9tIHRoZSBUaW55TUNFIHRvb2xiYXJzLlxyXG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuZmluZChcIi5sYXlvdXQtdG9vbGJhci1jb250YWluZXJcIikuY2xpY2soZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICAvLyBVbmZvY3VzIGFuZCB1bnNlbGVjdCBldmVyeXRoaW5nIG9uIGNsaWNrIG91dHNpZGUgb2YgY2FudmFzLlxyXG4gICAgICAgICAgICAgICAgICAgICQod2luZG93KS5jbGljayhmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBzY29wZS4kYXBwbHkoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NvcGUuZWxlbWVudC5hY3RpdmVFbGVtZW50ID0gbnVsbDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlLmVsZW1lbnQuZm9jdXNlZEVsZW1lbnQgPSBudWxsO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfTtcclxuICAgICAgICB9XHJcbiAgICBdKTsiLCJhbmd1bGFyXHJcbiAgICAubW9kdWxlKFwiTGF5b3V0RWRpdG9yXCIpXHJcbiAgICAuZGlyZWN0aXZlKFwib3JjTGF5b3V0Q2FudmFzXCIsIFtcInNjb3BlQ29uZmlndXJhdG9yXCIsIFwiZW52aXJvbm1lbnRcIixcclxuICAgICAgICBmdW5jdGlvbiAoc2NvcGVDb25maWd1cmF0b3IsIGVudmlyb25tZW50KSB7XHJcbiAgICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgICAgICByZXN0cmljdDogXCJFXCIsXHJcbiAgICAgICAgICAgICAgICBzY29wZTogeyBlbGVtZW50OiBcIj1cIiB9LFxyXG4gICAgICAgICAgICAgICAgY29udHJvbGxlcjogW1wiJHNjb3BlXCIsIFwiJGVsZW1lbnRcIiwgXCIkYXR0cnNcIixcclxuICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiAoJHNjb3BlLCAkZWxlbWVudCwgJGF0dHJzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlQ29uZmlndXJhdG9yLmNvbmZpZ3VyZUZvckVsZW1lbnQoJHNjb3BlLCAkZWxlbWVudCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlQ29uZmlndXJhdG9yLmNvbmZpZ3VyZUZvckNvbnRhaW5lcigkc2NvcGUsICRlbGVtZW50KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLnNvcnRhYmxlT3B0aW9uc1tcImF4aXNcIl0gPSBcInlcIjtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBdLFxyXG4gICAgICAgICAgICAgICAgdGVtcGxhdGVVcmw6IGVudmlyb25tZW50LnRlbXBsYXRlVXJsKFwiQ2FudmFzXCIpLFxyXG4gICAgICAgICAgICAgICAgcmVwbGFjZTogdHJ1ZVxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH1cclxuICAgIF0pOyIsImFuZ3VsYXJcclxuICAgIC5tb2R1bGUoXCJMYXlvdXRFZGl0b3JcIilcclxuICAgIC5kaXJlY3RpdmUoXCJvcmNMYXlvdXRDaGlsZFwiLCBbXCIkY29tcGlsZVwiLFxyXG4gICAgICAgIGZ1bmN0aW9uICgkY29tcGlsZSkge1xyXG4gICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgcmVzdHJpY3Q6IFwiRVwiLFxyXG4gICAgICAgICAgICAgICAgc2NvcGU6IHsgZWxlbWVudDogXCI9XCIgfSxcclxuICAgICAgICAgICAgICAgIGxpbms6IGZ1bmN0aW9uIChzY29wZSwgZWxlbWVudCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciB0ZW1wbGF0ZSA9IFwiPG9yYy1sYXlvdXQtXCIgKyBzY29wZS5lbGVtZW50LnR5cGUudG9Mb3dlckNhc2UoKSArIFwiIGVsZW1lbnQ9J2VsZW1lbnQnIC8+XCI7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIGh0bWwgPSAkY29tcGlsZSh0ZW1wbGF0ZSkoc2NvcGUpO1xyXG4gICAgICAgICAgICAgICAgICAgICQoZWxlbWVudCkucmVwbGFjZVdpdGgoaHRtbCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgfVxyXG4gICAgXSk7IiwiYW5ndWxhclxyXG4gICAgLm1vZHVsZShcIkxheW91dEVkaXRvclwiKVxyXG4gICAgLmRpcmVjdGl2ZShcIm9yY0xheW91dENvbHVtblwiLCBbXCIkY29tcGlsZVwiLCBcInNjb3BlQ29uZmlndXJhdG9yXCIsIFwiZW52aXJvbm1lbnRcIixcclxuICAgICAgICBmdW5jdGlvbiAoJGNvbXBpbGUsIHNjb3BlQ29uZmlndXJhdG9yLCBlbnZpcm9ubWVudCkge1xyXG4gICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgcmVzdHJpY3Q6IFwiRVwiLFxyXG4gICAgICAgICAgICAgICAgc2NvcGU6IHsgZWxlbWVudDogXCI9XCIgfSxcclxuICAgICAgICAgICAgICAgIGNvbnRyb2xsZXI6IFtcIiRzY29wZVwiLCBcIiRlbGVtZW50XCIsXHJcbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gKCRzY29wZSwgJGVsZW1lbnQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgc2NvcGVDb25maWd1cmF0b3IuY29uZmlndXJlRm9yRWxlbWVudCgkc2NvcGUsICRlbGVtZW50KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgc2NvcGVDb25maWd1cmF0b3IuY29uZmlndXJlRm9yQ29udGFpbmVyKCRzY29wZSwgJGVsZW1lbnQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuc29ydGFibGVPcHRpb25zW1wiYXhpc1wiXSA9IFwieVwiO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIF0sXHJcbiAgICAgICAgICAgICAgICB0ZW1wbGF0ZVVybDogZW52aXJvbm1lbnQudGVtcGxhdGVVcmwoXCJDb2x1bW5cIiksXHJcbiAgICAgICAgICAgICAgICByZXBsYWNlOiB0cnVlLFxyXG4gICAgICAgICAgICAgICAgbGluazogZnVuY3Rpb24gKHNjb3BlLCBlbGVtZW50LCBhdHRycykge1xyXG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuZmluZChcIi5sYXlvdXQtY29sdW1uLXJlc2l6ZS1iYXJcIikuZHJhZ2dhYmxlKHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgYXhpczogXCJ4XCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGhlbHBlcjogXCJjbG9uZVwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXZlcnQ6IHRydWUsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0OiBmdW5jdGlvbiAoZSwgdWkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlLiRhcHBseShmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NvcGUuZWxlbWVudC5lZGl0b3IuaXNSZXNpemluZyA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgZHJhZzogZnVuY3Rpb24gKGUsIHVpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY29sdW1uRWxlbWVudCA9IGVsZW1lbnQucGFyZW50KCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY29sdW1uU2l6ZSA9IGNvbHVtbkVsZW1lbnQud2lkdGgoKSAvIHNjb3BlLmVsZW1lbnQud2lkdGg7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY29ubmVjdEFkamFjZW50ID0gIWUuY3RybEtleTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgkKGUudGFyZ2V0KS5oYXNDbGFzcyhcImxheW91dC1jb2x1bW4tcmVzaXplLWJhci1sZWZ0XCIpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGRlbHRhID0gdWkub2Zmc2V0LmxlZnQgLSBjb2x1bW5FbGVtZW50Lm9mZnNldCgpLmxlZnQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRlbHRhIDwgLWNvbHVtblNpemUgJiYgc2NvcGUuZWxlbWVudC5jYW5FeHBhbmRMZWZ0KGNvbm5lY3RBZGphY2VudCkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NvcGUuJGFwcGx5KGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlLmVsZW1lbnQuZXhwYW5kTGVmdChjb25uZWN0QWRqYWNlbnQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoZGVsdGEgPiBjb2x1bW5TaXplICYmIHNjb3BlLmVsZW1lbnQuY2FuQ29udHJhY3RMZWZ0KGNvbm5lY3RBZGphY2VudCkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NvcGUuJGFwcGx5KGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlLmVsZW1lbnQuY29udHJhY3RMZWZ0KGNvbm5lY3RBZGphY2VudCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKCQoZS50YXJnZXQpLmhhc0NsYXNzKFwibGF5b3V0LWNvbHVtbi1yZXNpemUtYmFyLXJpZ2h0XCIpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGRlbHRhID0gdWkub2Zmc2V0LmxlZnQgLSBjb2x1bW5FbGVtZW50LndpZHRoKCkgLSBjb2x1bW5FbGVtZW50Lm9mZnNldCgpLmxlZnQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRlbHRhID4gY29sdW1uU2l6ZSAmJiBzY29wZS5lbGVtZW50LmNhbkV4cGFuZFJpZ2h0KGNvbm5lY3RBZGphY2VudCkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NvcGUuJGFwcGx5KGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlLmVsZW1lbnQuZXhwYW5kUmlnaHQoY29ubmVjdEFkamFjZW50KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKGRlbHRhIDwgLWNvbHVtblNpemUgJiYgc2NvcGUuZWxlbWVudC5jYW5Db250cmFjdFJpZ2h0KGNvbm5lY3RBZGphY2VudCkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NvcGUuJGFwcGx5KGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlLmVsZW1lbnQuY29udHJhY3RSaWdodChjb25uZWN0QWRqYWNlbnQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBzdG9wOiBmdW5jdGlvbiAoZSwgdWkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlLiRhcHBseShmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlLmVsZW1lbnQuZWRpdG9yLmlzUmVzaXppbmcgPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgfVxyXG4gICAgXSk7IiwiYW5ndWxhclxyXG4gICAgLm1vZHVsZShcIkxheW91dEVkaXRvclwiKVxyXG4gICAgLmRpcmVjdGl2ZShcIm9yY0xheW91dENvbnRlbnRcIiwgW1wiJHNjZVwiLCBcInNjb3BlQ29uZmlndXJhdG9yXCIsIFwiZW52aXJvbm1lbnRcIixcclxuICAgICAgICBmdW5jdGlvbiAoJHNjZSwgc2NvcGVDb25maWd1cmF0b3IsIGVudmlyb25tZW50KSB7XHJcbiAgICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgICAgICByZXN0cmljdDogXCJFXCIsXHJcbiAgICAgICAgICAgICAgICBzY29wZTogeyBlbGVtZW50OiBcIj1cIiB9LFxyXG4gICAgICAgICAgICAgICAgY29udHJvbGxlcjogW1wiJHNjb3BlXCIsIFwiJGVsZW1lbnRcIixcclxuICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiAoJHNjb3BlLCAkZWxlbWVudCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBzY29wZUNvbmZpZ3VyYXRvci5jb25maWd1cmVGb3JFbGVtZW50KCRzY29wZSwgJGVsZW1lbnQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuZWRpdCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS4kcm9vdC5lZGl0RWxlbWVudCgkc2NvcGUuZWxlbWVudCkudGhlbihmdW5jdGlvbiAoYXJncykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS4kYXBwbHkoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJncy5jYW5jZWwpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuZWxlbWVudC5kYXRhID0gYXJncy5lbGVtZW50LmRhdGE7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS5lbGVtZW50LnNldEh0bWwoYXJncy5lbGVtZW50Lmh0bWwpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBPdmVyd3JpdGUgdGhlIHNldEh0bWwgZnVuY3Rpb24gc28gdGhhdCB3ZSBjYW4gdXNlIHRoZSAkc2NlIHNlcnZpY2UgdG8gdHJ1c3QgdGhlIGh0bWwgKGFuZCBub3QgaGF2ZSB0aGUgaHRtbCBiaW5kaW5nIHN0cmlwIGNlcnRhaW4gdGFncykuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS5lbGVtZW50LnNldEh0bWwgPSBmdW5jdGlvbiAoaHRtbCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmVsZW1lbnQuaHRtbCA9IGh0bWw7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuZWxlbWVudC5odG1sVW5zYWZlID0gJHNjZS50cnVzdEFzSHRtbChodG1sKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS5lbGVtZW50LnNldEh0bWwoJHNjb3BlLmVsZW1lbnQuaHRtbCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgXSxcclxuICAgICAgICAgICAgICAgIHRlbXBsYXRlVXJsOiBlbnZpcm9ubWVudC50ZW1wbGF0ZVVybChcIkNvbnRlbnRcIiksXHJcbiAgICAgICAgICAgICAgICByZXBsYWNlOiB0cnVlXHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgfVxyXG4gICAgXSk7IiwiYW5ndWxhclxyXG4gICAgLm1vZHVsZShcIkxheW91dEVkaXRvclwiKVxyXG4gICAgLmRpcmVjdGl2ZShcIm9yY0xheW91dEh0bWxcIiwgW1wiJHNjZVwiLCBcInNjb3BlQ29uZmlndXJhdG9yXCIsIFwiZW52aXJvbm1lbnRcIixcclxuICAgICAgICBmdW5jdGlvbiAoJHNjZSwgc2NvcGVDb25maWd1cmF0b3IsIGVudmlyb25tZW50KSB7XHJcbiAgICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgICAgICByZXN0cmljdDogXCJFXCIsXHJcbiAgICAgICAgICAgICAgICBzY29wZTogeyBlbGVtZW50OiBcIj1cIiB9LFxyXG4gICAgICAgICAgICAgICAgY29udHJvbGxlcjogW1wiJHNjb3BlXCIsIFwiJGVsZW1lbnRcIixcclxuICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiAoJHNjb3BlLCAkZWxlbWVudCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBzY29wZUNvbmZpZ3VyYXRvci5jb25maWd1cmVGb3JFbGVtZW50KCRzY29wZSwgJGVsZW1lbnQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuZWRpdCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS4kcm9vdC5lZGl0RWxlbWVudCgkc2NvcGUuZWxlbWVudCkudGhlbihmdW5jdGlvbiAoYXJncykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS4kYXBwbHkoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJncy5jYW5jZWwpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuZWxlbWVudC5kYXRhID0gYXJncy5lbGVtZW50LmRhdGE7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS5lbGVtZW50LnNldEh0bWwoYXJncy5lbGVtZW50Lmh0bWwpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS51cGRhdGVDb250ZW50ID0gZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS5lbGVtZW50LnNldEh0bWwoZS50YXJnZXQuaW5uZXJIVE1MKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE92ZXJ3cml0ZSB0aGUgc2V0SHRtbCBmdW5jdGlvbiBzbyB0aGF0IHdlIGNhbiB1c2UgdGhlICRzY2Ugc2VydmljZSB0byB0cnVzdCB0aGUgaHRtbCAoYW5kIG5vdCBoYXZlIHRoZSBodG1sIGJpbmRpbmcgc3RyaXAgY2VydGFpbiB0YWdzKS5cclxuICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmVsZW1lbnQuc2V0SHRtbCA9IGZ1bmN0aW9uIChodG1sKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuZWxlbWVudC5odG1sID0gaHRtbDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS5lbGVtZW50Lmh0bWxVbnNhZmUgPSAkc2NlLnRydXN0QXNIdG1sKGh0bWwpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmVsZW1lbnQuc2V0SHRtbCgkc2NvcGUuZWxlbWVudC5odG1sKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBdLFxyXG4gICAgICAgICAgICAgICAgdGVtcGxhdGVVcmw6IGVudmlyb25tZW50LnRlbXBsYXRlVXJsKFwiSHRtbFwiKSxcclxuICAgICAgICAgICAgICAgIHJlcGxhY2U6IHRydWUsXHJcbiAgICAgICAgICAgICAgICBsaW5rOiBmdW5jdGlvbiAoc2NvcGUsIGVsZW1lbnQpIHtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfTtcclxuICAgICAgICB9XHJcbiAgICBdKTsiLCJhbmd1bGFyXHJcbiAgICAubW9kdWxlKFwiTGF5b3V0RWRpdG9yXCIpXHJcbiAgICAuZGlyZWN0aXZlKFwib3JjTGF5b3V0R3JpZFwiLCBbXCIkY29tcGlsZVwiLCBcInNjb3BlQ29uZmlndXJhdG9yXCIsIFwiZW52aXJvbm1lbnRcIixcclxuICAgICAgICBmdW5jdGlvbiAoJGNvbXBpbGUsIHNjb3BlQ29uZmlndXJhdG9yLCBlbnZpcm9ubWVudCkge1xyXG4gICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgcmVzdHJpY3Q6IFwiRVwiLFxyXG4gICAgICAgICAgICAgICAgc2NvcGU6IHsgZWxlbWVudDogXCI9XCIgfSxcclxuICAgICAgICAgICAgICAgIGNvbnRyb2xsZXI6IFtcIiRzY29wZVwiLCBcIiRlbGVtZW50XCIsXHJcbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gKCRzY29wZSwgJGVsZW1lbnQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgc2NvcGVDb25maWd1cmF0b3IuY29uZmlndXJlRm9yRWxlbWVudCgkc2NvcGUsICRlbGVtZW50KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgc2NvcGVDb25maWd1cmF0b3IuY29uZmlndXJlRm9yQ29udGFpbmVyKCRzY29wZSwgJGVsZW1lbnQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuc29ydGFibGVPcHRpb25zW1wiYXhpc1wiXSA9IFwieVwiO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIF0sXHJcbiAgICAgICAgICAgICAgICB0ZW1wbGF0ZVVybDogZW52aXJvbm1lbnQudGVtcGxhdGVVcmwoXCJHcmlkXCIpLFxyXG4gICAgICAgICAgICAgICAgcmVwbGFjZTogdHJ1ZVxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH1cclxuICAgIF0pOyIsImFuZ3VsYXJcclxuICAgIC5tb2R1bGUoXCJMYXlvdXRFZGl0b3JcIilcclxuICAgIC5kaXJlY3RpdmUoXCJvcmNMYXlvdXRSb3dcIiwgW1wiJGNvbXBpbGVcIiwgXCJzY29wZUNvbmZpZ3VyYXRvclwiLCBcImVudmlyb25tZW50XCIsXHJcbiAgICAgICAgZnVuY3Rpb24gKCRjb21waWxlLCBzY29wZUNvbmZpZ3VyYXRvciwgZW52aXJvbm1lbnQpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgICAgIHJlc3RyaWN0OiBcIkVcIixcclxuICAgICAgICAgICAgICAgIHNjb3BlOiB7IGVsZW1lbnQ6IFwiPVwiIH0sXHJcbiAgICAgICAgICAgICAgICBjb250cm9sbGVyOiBbXCIkc2NvcGVcIiwgXCIkZWxlbWVudFwiLFxyXG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uICgkc2NvcGUsICRlbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlQ29uZmlndXJhdG9yLmNvbmZpZ3VyZUZvckVsZW1lbnQoJHNjb3BlLCAkZWxlbWVudCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlQ29uZmlndXJhdG9yLmNvbmZpZ3VyZUZvckNvbnRhaW5lcigkc2NvcGUsICRlbGVtZW50KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLnNvcnRhYmxlT3B0aW9uc1tcImF4aXNcIl0gPSBcInhcIjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLnNvcnRhYmxlT3B0aW9uc1tcInVpLWZsb2F0aW5nXCJdID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBdLFxyXG4gICAgICAgICAgICAgICAgdGVtcGxhdGVVcmw6IGVudmlyb25tZW50LnRlbXBsYXRlVXJsKFwiUm93XCIpLFxyXG4gICAgICAgICAgICAgICAgcmVwbGFjZTogdHJ1ZVxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH1cclxuICAgIF0pOyIsImFuZ3VsYXJcclxuICAgIC5tb2R1bGUoXCJMYXlvdXRFZGl0b3JcIilcclxuICAgIC5kaXJlY3RpdmUoXCJvcmNMYXlvdXRQb3B1cFwiLCBbXHJcbiAgICAgICAgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgcmVzdHJpY3Q6IFwiQVwiLFxyXG4gICAgICAgICAgICAgICAgbGluazogZnVuY3Rpb24gKHNjb3BlLCBlbGVtZW50LCBhdHRycykge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBwb3B1cCA9ICQoZWxlbWVudCk7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRyaWdnZXIgPSBwb3B1cC5jbG9zZXN0KFwiLmxheW91dC1wb3B1cC10cmlnZ2VyXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBwYXJlbnRFbGVtZW50ID0gcG9wdXAuY2xvc2VzdChcIi5sYXlvdXQtZWxlbWVudFwiKTtcclxuICAgICAgICAgICAgICAgICAgICB0cmlnZ2VyLmNsaWNrKGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcG9wdXAudG9nZ2xlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwb3B1cC5pcyhcIjp2aXNpYmxlXCIpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3B1cC5wb3NpdGlvbih7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbXk6IGF0dHJzLm9yY0xheW91dFBvcHVwTXkgfHwgXCJsZWZ0IHRvcFwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF0OiBhdHRycy5vcmNMYXlvdXRQb3B1cEF0IHx8IFwibGVmdCBib3R0b20rNHB4XCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Y6IHRyaWdnZXJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9wdXAuZmluZChcImlucHV0XCIpLmZpcnN0KCkuZm9jdXMoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgIHBvcHVwLmNsaWNrKGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50RWxlbWVudC5jbGljayhmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBwb3B1cC5oaWRlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgcG9wdXAua2V5ZG93bihmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWUuY3RybEtleSAmJiAhZS5zaGlmdEtleSAmJiAhZS5hbHRLZXkgJiYgZS53aGljaCA9PSAyNykgLy8gRXNjXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3B1cC5oaWRlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgcG9wdXAub24oXCJjdXQgY29weSBwYXN0ZVwiLCBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBbGxvdyBjbGlwYm9hcmQgb3BlcmF0aW9ucyBpbiBwb3B1cCB3aXRob3V0IGludm9raW5nIGNsaXBib2FyZCBldmVudCBoYW5kbGVycyBvbiBwYXJlbnQgZWxlbWVudC5cclxuICAgICAgICAgICAgICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfTtcclxuICAgICAgICB9XHJcbiAgICBdKTsiLCJhbmd1bGFyXHJcbiAgICAubW9kdWxlKFwiTGF5b3V0RWRpdG9yXCIpXHJcbiAgICAuZGlyZWN0aXZlKFwib3JjTGF5b3V0VG9vbGJveFwiLCBbXCIkY29tcGlsZVwiLCBcImVudmlyb25tZW50XCIsXHJcbiAgICAgICAgZnVuY3Rpb24gKCRjb21waWxlLCBlbnZpcm9ubWVudCkge1xyXG4gICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgcmVzdHJpY3Q6IFwiRVwiLFxyXG4gICAgICAgICAgICAgICAgY29udHJvbGxlcjogW1wiJHNjb3BlXCIsIFwiJGVsZW1lbnRcIixcclxuICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiAoJHNjb3BlLCAkZWxlbWVudCkge1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLnJlc2V0RWxlbWVudHMgPSBmdW5jdGlvbiAoKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmdyaWRFbGVtZW50cyA9IFtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMYXlvdXRFZGl0b3IuR3JpZC5mcm9tKHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJveEljb246IFwiXFx1ZjAwYVwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b29sYm94TGFiZWw6IFwiR3JpZFwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b29sYm94RGVzY3JpcHRpb246IFwiRW1wdHkgZ3JpZC5cIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IFtdXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF07XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLnJvd0VsZW1lbnRzID0gW1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExheW91dEVkaXRvci5Sb3cuZnJvbSh7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3hJY29uOiBcIlxcdWYwYzlcIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJveExhYmVsOiBcIlJvdyAoMSBjb2x1bW4pXCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3hEZXNjcmlwdGlvbjogXCJSb3cgd2l0aCAxIGNvbHVtbi5cIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IExheW91dEVkaXRvci5Db2x1bW4udGltZXMoMSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMYXlvdXRFZGl0b3IuUm93LmZyb20oe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b29sYm94SWNvbjogXCJcXHVmMGM5XCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3hMYWJlbDogXCJSb3cgKDIgY29sdW1ucylcIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJveERlc2NyaXB0aW9uOiBcIlJvdyB3aXRoIDIgY29sdW1ucy5cIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IExheW91dEVkaXRvci5Db2x1bW4udGltZXMoMilcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMYXlvdXRFZGl0b3IuUm93LmZyb20oe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b29sYm94SWNvbjogXCJcXHVmMGM5XCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3hMYWJlbDogXCJSb3cgKDMgY29sdW1ucylcIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJveERlc2NyaXB0aW9uOiBcIlJvdyB3aXRoIDMgY29sdW1ucy5cIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IExheW91dEVkaXRvci5Db2x1bW4udGltZXMoMylcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMYXlvdXRFZGl0b3IuUm93LmZyb20oe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b29sYm94SWNvbjogXCJcXHVmMGM5XCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3hMYWJlbDogXCJSb3cgKDQgY29sdW1ucylcIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJveERlc2NyaXB0aW9uOiBcIlJvdyB3aXRoIDQgY29sdW1ucy5cIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IExheW91dEVkaXRvci5Db2x1bW4udGltZXMoNClcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMYXlvdXRFZGl0b3IuUm93LmZyb20oe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b29sYm94SWNvbjogXCJcXHVmMGM5XCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3hMYWJlbDogXCJSb3cgKDYgY29sdW1ucylcIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJveERlc2NyaXB0aW9uOiBcIlJvdyB3aXRoIDYgY29sdW1ucy5cIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IExheW91dEVkaXRvci5Db2x1bW4udGltZXMoNilcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMYXlvdXRFZGl0b3IuUm93LmZyb20oe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b29sYm94SWNvbjogXCJcXHVmMGM5XCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3hMYWJlbDogXCJSb3cgKDEyIGNvbHVtbnMpXCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3hEZXNjcmlwdGlvbjogXCJSb3cgd2l0aCAxMiBjb2x1bW5zLlwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogTGF5b3V0RWRpdG9yLkNvbHVtbi50aW1lcygxMilcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSwgTGF5b3V0RWRpdG9yLlJvdy5mcm9tKHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJveEljb246IFwiXFx1ZjBjOVwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b29sYm94TGFiZWw6IFwiUm93IChlbXB0eSlcIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJveERlc2NyaXB0aW9uOiBcIkVtcHR5IHJvdy5cIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IFtdXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF07XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmNvbHVtbkVsZW1lbnRzID0gW1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExheW91dEVkaXRvci5Db2x1bW4uZnJvbSh7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3hJY29uOiBcIlxcdWYwZGJcIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJveExhYmVsOiBcIkNvbHVtblwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b29sYm94RGVzY3JpcHRpb246IFwiRW1wdHkgY29sdW1uLlwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogMSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0OiAwLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogW11cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuY2FudmFzRWxlbWVudHMgPSBbXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTGF5b3V0RWRpdG9yLkNhbnZhcy5mcm9tKHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJveEljb246IFwiXFx1ZjA0NFwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b29sYm94TGFiZWw6IFwiQ2FudmFzXCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3hEZXNjcmlwdGlvbjogXCJFbXB0eSBjYW52YXMuXCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBbXVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBdO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS5jb250ZW50RWxlbWVudENhdGVnb3JpZXMgPSBfKCRzY29wZS5lbGVtZW50LmNvbmZpZy5jYXRlZ29yaWVzKS5tYXAoZnVuY3Rpb24gKGNhdGVnb3J5KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogY2F0ZWdvcnkubmFtZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudHM6IF8oY2F0ZWdvcnkuY29udGVudFR5cGVzKS5tYXAoZnVuY3Rpb24gKGNvbnRlbnRUeXBlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IGNvbnRlbnRUeXBlLnR5cGU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZmFjdG9yeSA9IExheW91dEVkaXRvci5mYWN0b3JpZXNbdHlwZV0gfHwgTGF5b3V0RWRpdG9yLmZhY3Rvcmllc1tcIkNvbnRlbnRcIl07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgaXRlbSA9IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1RlbXBsYXRlZDogZmFsc2UsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudFR5cGU6IGNvbnRlbnRUeXBlLmlkLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnRUeXBlTGFiZWw6IGNvbnRlbnRUeXBlLmxhYmVsLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnRUeXBlQ2xhc3M6IGNvbnRlbnRUeXBlLnR5cGVDbGFzcyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhOiBudWxsLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc0VkaXRvcjogY29udGVudFR5cGUuaGFzRWRpdG9yLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGh0bWw6IGNvbnRlbnRUeXBlLmh0bWxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZWxlbWVudCA9IGZhY3RvcnkoaXRlbSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnRvb2xib3hJY29uID0gY29udGVudFR5cGUuaWNvbiB8fCBcIlxcdWYxYzlcIjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQudG9vbGJveExhYmVsID0gY29udGVudFR5cGUubGFiZWw7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnRvb2xib3hEZXNjcmlwdGlvbiA9IGNvbnRlbnRUeXBlLmRlc2NyaXB0aW9uO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGVsZW1lbnQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS5yZXNldEVsZW1lbnRzKCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuZ2V0U29ydGFibGVPcHRpb25zID0gZnVuY3Rpb24gKHR5cGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBlZGl0b3JJZCA9ICRlbGVtZW50LmNsb3Nlc3QoXCIubGF5b3V0LWVkaXRvclwiKS5hdHRyKFwiaWRcIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Q2xhc3NlcztcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwbGFjZWhvbGRlckNsYXNzZXM7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZmxvYXRpbmcgPSBmYWxzZTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiR3JpZFwiOlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRDbGFzc2VzID0gW1wiLmxheW91dC1jYW52YXNcIiwgXCIubGF5b3V0LWNvbHVtblwiLCBcIi5sYXlvdXQtY29tbW9uLWhvbGRlclwiXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXJDbGFzc2VzID0gXCJsYXlvdXQtZWxlbWVudCBsYXlvdXQtY29udGFpbmVyIGxheW91dC1ncmlkIHVpLXNvcnRhYmxlLXBsYWNlaG9sZGVyXCI7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJSb3dcIjpcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Q2xhc3NlcyA9IFtcIi5sYXlvdXQtZ3JpZFwiXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXJDbGFzc2VzID0gXCJsYXlvdXQtZWxlbWVudCBsYXlvdXQtY29udGFpbmVyIGxheW91dC1yb3cgcm93IHVpLXNvcnRhYmxlLXBsYWNlaG9sZGVyXCI7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJDb2x1bW5cIjpcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Q2xhc3NlcyA9IFtcIi5sYXlvdXQtcm93Om5vdCgubGF5b3V0LXJvdy1mdWxsKVwiXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXJDbGFzc2VzID0gXCJsYXlvdXQtZWxlbWVudCBsYXlvdXQtY29udGFpbmVyIGxheW91dC1jb2x1bW4gdWktc29ydGFibGUtcGxhY2Vob2xkZXJcIjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmxvYXRpbmcgPSB0cnVlOyAvLyBUbyBlbnN1cmUgYSBzbW9vdGggaG9yaXpvbnRhbC1saXN0IHJlb3JkZXJpbmcuIGh0dHBzOi8vZ2l0aHViLmNvbS9hbmd1bGFyLXVpL3VpLXNvcnRhYmxlI2Zsb2F0aW5nXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJDb250ZW50XCI6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudENsYXNzZXMgPSBbXCIubGF5b3V0LWNhbnZhc1wiLCBcIi5sYXlvdXQtY29sdW1uXCIsIFwiLmxheW91dC1jb21tb24taG9sZGVyXCJdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlckNsYXNzZXMgPSBcImxheW91dC1lbGVtZW50IGxheW91dC1jb250ZW50IHVpLXNvcnRhYmxlLXBsYWNlaG9sZGVyXCI7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJDYW52YXNcIjpcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Q2xhc3NlcyA9IFtcIi5sYXlvdXQtY2FudmFzXCIsIFwiLmxheW91dC1jb2x1bW5cIiwgXCIubGF5b3V0LWNvbW1vbi1ob2xkZXJcIl07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyQ2xhc3NlcyA9IFwibGF5b3V0LWVsZW1lbnQgbGF5b3V0LWNvbnRhaW5lciBsYXlvdXQtZ3JpZCB1aS1zb3J0YWJsZS1wbGFjZWhvbGRlclwiO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnNvcjogXCJtb3ZlXCIsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29ubmVjdFdpdGg6IF8ocGFyZW50Q2xhc3NlcykubWFwKGZ1bmN0aW9uIChlKSB7IHJldHVybiBcIiNcIiArIGVkaXRvcklkICsgXCIgXCIgKyBlICsgXCI6bm90KC5sYXlvdXQtY29udGFpbmVyLXNlYWxlZCkgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciA+IC5sYXlvdXQtY2hpbGRyZW5cIjsgfSkuam9pbihcIiwgXCIpLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBwbGFjZWhvbGRlckNsYXNzZXMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJ1aS1mbG9hdGluZ1wiOiBmbG9hdGluZyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcmVhdGU6IGZ1bmN0aW9uIChlLCB1aSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLnRhcmdldC5pc1Rvb2xib3ggPSB0cnVlOyAvLyBXaWxsIGluZGljYXRlIHRvIGNvbm5lY3RlZCBzb3J0YWJsZXMgdGhhdCBkcm9wcGVkIGl0ZW1zIHdlcmUgc2VudCBmcm9tIHRvb2xib3guXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydDogZnVuY3Rpb24gKGUsIHVpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS4kYXBwbHkoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmVsZW1lbnQuaXNEcmFnZ2luZyA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RvcDogZnVuY3Rpb24gKGUsIHVpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS4kYXBwbHkoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmVsZW1lbnQuaXNEcmFnZ2luZyA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLnJlc2V0RWxlbWVudHMoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdmVyOiBmdW5jdGlvbiAoZSwgdWkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLiRhcHBseShmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuZWxlbWVudC5jYW52YXMuc2V0SXNEcm9wVGFyZ2V0KGZhbHNlKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsYXlvdXRJc0NvbGxhcHNlZENvb2tpZU5hbWUgPSBcImxheW91dFRvb2xib3hDYXRlZ29yeV9MYXlvdXRfSXNDb2xsYXBzZWRcIjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmxheW91dElzQ29sbGFwc2VkID0gJC5jb29raWUobGF5b3V0SXNDb2xsYXBzZWRDb29raWVOYW1lKSA9PT0gXCJ0cnVlXCI7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUudG9nZ2xlTGF5b3V0SXNDb2xsYXBzZWQgPSBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmxheW91dElzQ29sbGFwc2VkID0gISRzY29wZS5sYXlvdXRJc0NvbGxhcHNlZDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQuY29va2llKGxheW91dElzQ29sbGFwc2VkQ29va2llTmFtZSwgJHNjb3BlLmxheW91dElzQ29sbGFwc2VkLCB7IGV4cGlyZXM6IDM2NSB9KTsgLy8gUmVtZW1iZXIgY29sbGFwc2VkIHN0YXRlIGZvciBhIHllYXIuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIF0sXHJcbiAgICAgICAgICAgICAgICB0ZW1wbGF0ZVVybDogZW52aXJvbm1lbnQudGVtcGxhdGVVcmwoXCJUb29sYm94XCIpLFxyXG4gICAgICAgICAgICAgICAgcmVwbGFjZTogdHJ1ZSxcclxuICAgICAgICAgICAgICAgIGxpbms6IGZ1bmN0aW9uIChzY29wZSwgZWxlbWVudCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciB0b29sYm94ID0gZWxlbWVudC5maW5kKFwiLmxheW91dC10b29sYm94XCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICQod2luZG93KS5vbihcInJlc2l6ZSBzY3JvbGxcIiwgZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNhbnZhcyA9IGVsZW1lbnQucGFyZW50KCkuZmluZChcIi5sYXlvdXQtY2FudmFzXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgY2FudmFzIGlzIHRhbGxlciB0aGFuIHRoZSB0b29sYm94LCBtYWtlIHRoZSB0b29sYm94IHN0aWNreS1wb3NpdGlvbmVkIHdpdGhpbiB0aGUgZWRpdG9yXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRvIGhlbHAgdGhlIHVzZXIgYXZvaWQgZXhjZXNzaXZlIHZlcnRpY2FsIHNjcm9sbGluZy5cclxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNhbnZhc0lzVGFsbGVyID0gISFjYW52YXMgJiYgY2FudmFzLmhlaWdodCgpID4gdG9vbGJveC5oZWlnaHQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHdpbmRvd1BvcyA9ICQod2luZG93KS5zY3JvbGxUb3AoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNhbnZhc0lzVGFsbGVyICYmIHdpbmRvd1BvcyA+IGVsZW1lbnQub2Zmc2V0KCkudG9wICsgZWxlbWVudC5oZWlnaHQoKSAtIHRvb2xib3guaGVpZ2h0KCkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3guYWRkQ2xhc3MoXCJzdGlja3ktYm90dG9tXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJveC5yZW1vdmVDbGFzcyhcInN0aWNreS10b3BcIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoY2FudmFzSXNUYWxsZXIgJiYgd2luZG93UG9zID4gZWxlbWVudC5vZmZzZXQoKS50b3ApIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3guYWRkQ2xhc3MoXCJzdGlja3ktdG9wXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9vbGJveC5yZW1vdmVDbGFzcyhcInN0aWNreS1ib3R0b21cIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b29sYm94LnJlbW92ZUNsYXNzKFwic3RpY2t5LXRvcFwiKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2xib3gucmVtb3ZlQ2xhc3MoXCJzdGlja3ktYm90dG9tXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgfVxyXG4gICAgXSk7IiwiYW5ndWxhclxyXG4gICAgLm1vZHVsZShcIkxheW91dEVkaXRvclwiKVxyXG4gICAgLmRpcmVjdGl2ZShcIm9yY0xheW91dFRvb2xib3hHcm91cFwiLCBbXCIkY29tcGlsZVwiLCBcImVudmlyb25tZW50XCIsXHJcbiAgICAgICAgZnVuY3Rpb24gKCRjb21waWxlLCBlbnZpcm9ubWVudCkge1xyXG4gICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgcmVzdHJpY3Q6IFwiRVwiLFxyXG4gICAgICAgICAgICAgICAgc2NvcGU6IHsgY2F0ZWdvcnk6IFwiPVwiIH0sXHJcbiAgICAgICAgICAgICAgICBjb250cm9sbGVyOiBbXCIkc2NvcGVcIiwgXCIkZWxlbWVudFwiLFxyXG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uICgkc2NvcGUsICRlbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpc0NvbGxhcHNlZENvb2tpZU5hbWUgPSBcImxheW91dFRvb2xib3hDYXRlZ29yeV9cIiArICRzY29wZS5jYXRlZ29yeS5uYW1lICsgXCJfSXNDb2xsYXBzZWRcIjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgJHNjb3BlLmlzQ29sbGFwc2VkID0gJC5jb29raWUoaXNDb2xsYXBzZWRDb29raWVOYW1lKSA9PT0gXCJ0cnVlXCI7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICRzY29wZS50b2dnbGVJc0NvbGxhcHNlZCA9IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2NvcGUuaXNDb2xsYXBzZWQgPSAhJHNjb3BlLmlzQ29sbGFwc2VkO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJC5jb29raWUoaXNDb2xsYXBzZWRDb29raWVOYW1lLCAkc2NvcGUuaXNDb2xsYXBzZWQsIHsgZXhwaXJlczogMzY1IH0pOyAvLyBSZW1lbWJlciBjb2xsYXBzZWQgc3RhdGUgZm9yIGEgeWVhci5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgXSxcclxuICAgICAgICAgICAgICAgIHRlbXBsYXRlVXJsOiBlbnZpcm9ubWVudC50ZW1wbGF0ZVVybChcIlRvb2xib3hHcm91cFwiKSxcclxuICAgICAgICAgICAgICAgIHJlcGxhY2U6IHRydWVcclxuICAgICAgICAgICAgfTtcclxuICAgICAgICB9XHJcbiAgICBdKTsiXSwic291cmNlUm9vdCI6Ii9zb3VyY2UvIn0= \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Scripts/LayoutEditor.min.js b/src/Orchard.Web/Modules/Orchard.Layouts/Scripts/LayoutEditor.min.js index d92fdf698..b31866784 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Scripts/LayoutEditor.min.js +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Scripts/LayoutEditor.min.js @@ -1 +1 @@ -angular.module("LayoutEditor",["ngSanitize","ngResource","ui.sortable"]);var LayoutEditor;!function(e){var t=function(){var e=this;this._clipboardData={},this._isDisabled=!1,this._wasInvoked=!1,this.setData=function(t,o){e._clipboardData[t]=o,e._wasInvoked=!0},this.getData=function(t){return e._clipboardData[t]},this.disable=function(){e._isDisabled=!0,e._wasInvoked=!1,e._clipboardData={}},this.isDisabled=function(){return e._isDisabled},this.wasInvoked=function(){return e._wasInvoked}};e.Clipboard=new t,angular.module("LayoutEditor").factory("clipboard",[function(){return{setData:e.Clipboard.setData,getData:e.Clipboard.getData,disable:e.Clipboard.disable,isDisabled:e.Clipboard.isDisabled,wasInvoked:e.Clipboard.wasInvoked}}])}(LayoutEditor||(LayoutEditor={})),angular.module("LayoutEditor").factory("scopeConfigurator",["$timeout","clipboard",function(e,t){return{configureForElement:function(e,o){o.find(".layout-panel").click(function(e){e.stopPropagation()}),o.parent().keydown(function(n){var l=!1,a=!1,i=e.element;if(!i.editor.isDragging&&!i.editor.inlineEditingIsActive){if(!t.isDisabled()){var r=i.editor.focusedElement;if(r&&n.ctrlKey)switch(n.which){case 67:r.copy(t);break;case 88:r.cut(t);break;case 86:r.paste(t)}}if(n.ctrlKey||n.shiftKey||n.altKey||46!=n.which?n.ctrlKey||n.shiftKey||n.altKey||32!=n.which&&27!=n.which||(o.find(".layout-panel-action-properties").first().click(),l=!0):(e["delete"](i),l=!0),"Content"==i.type&&(n.ctrlKey||n.shiftKey||n.altKey||13!=n.which||(o.find(".layout-panel-action-edit").first().click(),l=!0)),i.children&&(n.ctrlKey||n.shiftKey||!n.altKey||40!=n.which||(i.children.length>0&&i.children[0].setIsFocused(),l=!0),"Column"==i.type)){var c=!n.ctrlKey;37==n.which?(n.altKey&&i.expandLeft(c),n.shiftKey&&i.contractRight(c),l=!0):39==n.which&&(n.altKey&&i.contractLeft(c),n.shiftKey&&i.expandRight(c),l=!0)}i.parent&&(n.altKey&&38==n.which&&(i.parent.setIsFocused(),l=!0),"Row"==i.parent.type?n.ctrlKey||n.shiftKey||n.altKey||37!=n.which?n.ctrlKey||n.shiftKey||n.altKey||39!=n.which?!n.ctrlKey||n.shiftKey||n.altKey||37!=n.which?!n.ctrlKey||n.shiftKey||n.altKey||39!=n.which||(i.moveDown(),l=!0):(i.moveUp(),a=!0,l=!0):(i.parent.moveFocusNextChild(i),l=!0):(i.parent.moveFocusPrevChild(i),l=!0):n.ctrlKey||n.shiftKey||n.altKey||38!=n.which?n.ctrlKey||n.shiftKey||n.altKey||40!=n.which?!n.ctrlKey||n.shiftKey||n.altKey||38!=n.which?!n.ctrlKey||n.shiftKey||n.altKey||40!=n.which||(i.moveDown(),l=!0):(i.moveUp(),a=!0,l=!0):(i.parent.moveFocusNextChild(i),l=!0):(i.parent.moveFocusPrevChild(i),l=!0)),l&&n.preventDefault(),n.stopPropagation(),e.$apply(),a&&window.setTimeout(function(){e.$apply(function(){i.editor.focusedElement.setIsFocused()})},100)}}),e.element.setIsFocusedEventHandlers.push(function(){o.parent().focus()}),e["delete"]=function(e){e["delete"]()}},configureForContainer:function(t,o){var n=t.element;t.getShowChildrenPlaceholder=function(){return 0===t.element.children.length&&!t.element.getIsDropTarget()},t.sortableOptions={cursor:"move",delay:150,disabled:n.getIsSealed(),distance:5,start:function(e,o){t.$apply(function(){n.setIsDropTarget(!0),n.editor.isDragging=!0}),o.placeholder.height(o.item.height()-4),o.placeholder.css("min-height",0)},stop:function(e,o){t.$apply(function(){n.editor.isDragging=!1,n.setIsDropTarget(!1)})},over:function(t,l){l.sender&&l.sender[0].isToolbox&&(l.sender[0].dropTargetTimeout&&(e.cancel(l.sender[0].dropTargetTimeout),l.sender[0].dropTargetTimeout=null),e(function(){if("Row"==n.type){var e=n.editor.dropTargetElement;e&&"Row"==e.type&&e.rollbackAddColumn()}n.setIsDropTarget(!1)}),l.sender[0].dropTargetTimeout=e(function(){if("Row"==n.type){var e=l.item.sortable.model,t=Math.floor(12/(n.children.length+1));e.width=t,e.offset=0,n.beginAddColumn(t);var a=_.max(_(o.find("> .layout-children > .layout-column:not(.ui-sortable-placeholder)")).map(function(e){return $(e).height()}));for(i=1;i<=12;i++)l.placeholder.removeClass("col-xs-"+i);l.placeholder.addClass("col-xs-"+e.width),a>0?(l.placeholder.height(a),l.placeholder.css("min-height",0)):(l.placeholder.height(0),l.placeholder.css("min-height",""))}n.setIsDropTarget(!0)},150))},receive:function(o,l){l.sender&&l.sender[0].isToolbox&&t.$apply(function(){var o=l.item.sortable.model;o&&("Row"==n.type&&n.commitAddColumn(),o.setEditor(n.editor),o.setParent(n),o.hasEditor&&t.$root.editElement(o).then(function(t){t.cancel||(o.data=t.element.data,o.applyElementEditorModel(t.elementEditorModel),o.setHtml&&o.setHtml(t.element.html)),e(function(){t.cancel?o["delete"]():o.setIsFocused(),n.setIsDropTarget(!1)})})),e(function(){n.setIsDropTarget(!1),o&&o.setIsFocused()})})}},t.click=function(e,t){e.editor.isDragging||e.setIsFocused(),t.stopPropagation()},t.getClasses=function(e){var t=["layout-element"];return e.children&&(t.push("layout-container"),e.getIsSealed()&&t.push("layout-container-sealed")),t.push("layout-"+e.type.toLowerCase()),e.dropTargetClass&&t.push(e.dropTargetClass),"Row"==e.type&&(t.push("row"),e.canAddColumn()||t.push("layout-row-full")),"Column"==e.type&&(t.push("col-xs-"+e.width),t.push("col-xs-offset-"+e.offset)),"Content"==e.type&&t.push("layout-content-"+e.contentTypeClass),e.getIsActive()&&t.push("layout-element-active"),e.getIsFocused()&&t.push("layout-element-focused"),e.getIsSelected()&&t.push("layout-element-selected"),e.getIsDropTarget()&&t.push("layout-element-droptarget"),e.isTemplated&&t.push("layout-element-templated"),t}}}}]),angular.module("LayoutEditor").directive("orcLayoutEditor",["environment",function(environment){return{restrict:"E",scope:{},controller:["$scope","$element","$attrs","$compile","clipboard",function($scope,$element,$attrs,$compile,clipboard){if(!$attrs.model)throw new Error("The 'model' attribute must evaluate to a LayoutEditor.Editor object.");$scope.element=eval($attrs.model),$scope.click=function(e,t){e.editor.isDragging||e.setIsFocused(),t.stopPropagation()},$scope.getClasses=function(e){var t=["layout-element","layout-container","layout-canvas"];return e.getIsActive()&&t.push("layout-element-active"),e.getIsFocused()&&t.push("layout-element-focused"),e.getIsSelected()&&t.push("layout-element-selected"),e.getIsDropTarget()&&t.push("layout-element-droptarget"),e.isTemplated&&t.push("layout-element-templated"),t};var layoutDesignerHost=$(".layout-designer").data("layout-designer-host");$scope.$root.layoutDesignerHost=layoutDesignerHost,layoutDesignerHost.element.on("replacecanvas",function(e,t){var o=$scope.element,n={data:t.canvas.data,htmlId:t.canvas.htmlId,htmlClass:t.canvas.htmlClass,htmlStyle:t.canvas.htmlStyle,isTemplated:t.canvas.isTemplated,children:t.canvas.children};layoutDesignerHost.editor=window.layoutEditor=new LayoutEditor.Editor(o.config,n);var l="",a=$compile(l)($scope);$(".layout-editor-holder").html(a)}),$scope.$root.editElement=function(e){var t=$scope.$root.layoutDesignerHost;return t.editElement(e)},$scope.$root.addElement=function(e){var t=$scope.$root.layoutDesignerHost;return t.addElement(e)},$scope.toggleInlineEditing=function(){if($scope.element.inlineEditingIsActive)tinymce.remove("#layout-editor-"+$scope.$id+" .layout-content-markup"),$element.find(".layout-toolbar-container").hide(),$scope.element.inlineEditingIsActive=!1;else{$scope.element.inlineEditingIsActive=!0,$element.find(".layout-toolbar-container").show();var e="#layout-editor-"+$scope.$id+" .layout-html .layout-content-markup[data-templated=false]",t=$(e).first().attr("id");tinymce.init({selector:e,theme:"modern",schema:"html5",plugins:["advlist autolink lists link image charmap print preview hr anchor pagebreak","searchreplace wordcount visualblocks visualchars code fullscreen","insertdatetime media nonbreaking table contextmenu directionality","emoticons template paste textcolor colorpicker textpattern","fullscreen autoresize"],toolbar:"undo redo cut copy paste | bold italic | bullist numlist outdent indent formatselect | alignleft aligncenter alignright alignjustify ltr rtl | link unlink charmap | code fullscreen close",convert_urls:!1,valid_elements:"*[*]",extended_valid_elements:"script[type|defer|src|language]",statusbar:!1,skin:"orchardlightgray",inline:!0,fixed_toolbar_container:"#layout-editor-"+$scope.$id+" .layout-toolbar-container",init_instance_callback:function(e){e.id==t&&tinymce.execCommand("mceFocus",!1,e.id)}})}},$(document).on("cut copy paste",function(e){if(clipboard.wasInvoked())e.originalEvent.clipboardData.setData("text/plain",clipboard.getData("text/plain")),e.originalEvent.clipboardData.setData("text/json",clipboard.getData("text/json")),e.preventDefault();else{var t=$scope.element.focusedElement;t&&($scope.$apply(function(){switch(e.type){case"copy":t.copy(e.originalEvent.clipboardData);break;case"cut":t.cut(e.originalEvent.clipboardData);break;case"paste":t.paste(e.originalEvent.clipboardData)}}),window.setTimeout(function(){$scope.$apply(function(){$scope.element.focusedElement&&$scope.element.focusedElement.setIsFocused()})},100),e.preventDefault())}clipboard.disable()})}],templateUrl:environment.templateUrl("Editor"),replace:!0,link:function(e,t){t.find(".layout-toolbar-container").click(function(e){e.stopPropagation()}),t.mousedown(function(t){e.element.inlineEditingIsActive&&(t.preventDefault(),t.stopPropagation())}),$(window).click(function(t){e.element.inlineEditingIsActive||e.$apply(function(){e.element.activeElement=null,e.element.focusedElement=null})})}}}]),angular.module("LayoutEditor").directive("orcLayoutCanvas",["scopeConfigurator","environment",function(e,t){return{restrict:"E",scope:{element:"="},controller:["$scope","$element","$attrs",function(t,o,n){e.configureForElement(t,o),e.configureForContainer(t,o),t.sortableOptions.axis="y"}],templateUrl:t.templateUrl("Canvas"),replace:!0}}]),angular.module("LayoutEditor").directive("orcLayoutChild",["$compile",function(e){return{restrict:"E",scope:{element:"="},link:function(t,o){var n="",l=e(n)(t);$(o).replaceWith(l)}}}]),angular.module("LayoutEditor").directive("orcLayoutColumn",["$compile","scopeConfigurator","environment",function(e,t,o){return{restrict:"E",scope:{element:"="},controller:["$scope","$element",function(e,o){t.configureForElement(e,o),t.configureForContainer(e,o),e.sortableOptions.axis="y"}],templateUrl:o.templateUrl("Column"),replace:!0,link:function(e,t,o){t.find(".layout-column-resize-bar").draggable({axis:"x",helper:"clone",revert:!0,start:function(t,o){e.$apply(function(){e.element.editor.isResizing=!0})},drag:function(o,n){var l=t.parent(),a=l.width()/e.element.width,i=!o.ctrlKey;if($(o.target).hasClass("layout-column-resize-bar-left")){var r=n.offset.left-l.offset().left;-a>r&&e.element.canExpandLeft(i)?e.$apply(function(){e.element.expandLeft(i)}):r>a&&e.element.canContractLeft(i)&&e.$apply(function(){e.element.contractLeft(i)})}else if($(o.target).hasClass("layout-column-resize-bar-right")){var r=n.offset.left-l.width()-l.offset().left;r>a&&e.element.canExpandRight(i)?e.$apply(function(){e.element.expandRight(i)}):-a>r&&e.element.canContractRight(i)&&e.$apply(function(){e.element.contractRight(i)})}},stop:function(t,o){e.$apply(function(){e.element.editor.isResizing=!1})}})}}}]),angular.module("LayoutEditor").directive("orcLayoutContent",["$sce","scopeConfigurator","environment",function(e,t,o){return{restrict:"E",scope:{element:"="},controller:["$scope","$element",function(o,n){t.configureForElement(o,n),o.edit=function(){o.$root.editElement(o.element).then(function(e){o.$apply(function(){e.cancel||(o.element.data=e.element.data,o.element.setHtml(e.element.html))})})},o.element.setHtml=function(t){o.element.html=t,o.element.htmlUnsafe=e.trustAsHtml(t)},o.element.setHtml(o.element.html)}],templateUrl:o.templateUrl("Content"),replace:!0}}]),angular.module("LayoutEditor").directive("orcLayoutHtml",["$sce","scopeConfigurator","environment",function(e,t,o){return{restrict:"E",scope:{element:"="},controller:["$scope","$element",function(o,n){t.configureForElement(o,n),o.edit=function(){o.$root.editElement(o.element).then(function(e){o.$apply(function(){e.cancel||(o.element.data=e.element.data,o.element.setHtml(e.element.html))})})},o.updateContent=function(e){o.element.setHtml(e.target.innerHTML)},o.element.setHtml=function(t){o.element.html=t,o.element.htmlUnsafe=e.trustAsHtml(t)},o.element.setHtml(o.element.html)}],templateUrl:o.templateUrl("Html"),replace:!0,link:function(e,t){t.find(".layout-content-markup").mousedown(function(t){e.element.editor.inlineEditingIsActive&&t.stopPropagation()})}}}]),angular.module("LayoutEditor").directive("orcLayoutGrid",["$compile","scopeConfigurator","environment",function(e,t,o){return{restrict:"E",scope:{element:"="},controller:["$scope","$element",function(e,o){t.configureForElement(e,o),t.configureForContainer(e,o),e.sortableOptions.axis="y"}],templateUrl:o.templateUrl("Grid"),replace:!0}}]),angular.module("LayoutEditor").directive("orcLayoutRow",["$compile","scopeConfigurator","environment",function(e,t,o){return{restrict:"E",scope:{element:"="},controller:["$scope","$element",function(e,o){t.configureForElement(e,o),t.configureForContainer(e,o),e.sortableOptions.axis="x",e.sortableOptions["ui-floating"]=!0}],templateUrl:o.templateUrl("Row"),replace:!0}}]),angular.module("LayoutEditor").directive("orcLayoutPopup",[function(){return{restrict:"A",link:function(e,t,o){var n=$(t),l=n.closest(".layout-popup-trigger"),a=n.closest(".layout-element");l.click(function(){n.toggle(),n.is(":visible")&&(n.position({my:o.orcLayoutPopupMy||"left top",at:o.orcLayoutPopupAt||"left bottom+4px",of:l}),n.find("input").first().focus())}),n.click(function(e){e.stopPropagation()}),a.click(function(e){n.hide()}),n.keydown(function(e){e.ctrlKey||e.shiftKey||e.altKey||27!=e.which||n.hide(),e.stopPropagation()}),n.on("cut copy paste",function(e){e.stopPropagation()})}}}]),angular.module("LayoutEditor").directive("orcLayoutToolbox",["$compile","environment",function(e,t){return{restrict:"E",controller:["$scope","$element",function(e,t){e.resetElements=function(){e.gridElements=[LayoutEditor.Grid.from({toolboxIcon:"",toolboxLabel:"Grid",toolboxDescription:"Empty grid.",children:[]})],e.rowElements=[LayoutEditor.Row.from({toolboxIcon:"",toolboxLabel:"Row (1 column)",toolboxDescription:"Row with 1 column.",children:LayoutEditor.Column.times(1)}),LayoutEditor.Row.from({toolboxIcon:"",toolboxLabel:"Row (2 columns)",toolboxDescription:"Row with 2 columns.",children:LayoutEditor.Column.times(2)}),LayoutEditor.Row.from({toolboxIcon:"",toolboxLabel:"Row (3 columns)",toolboxDescription:"Row with 3 columns.",children:LayoutEditor.Column.times(3)}),LayoutEditor.Row.from({toolboxIcon:"",toolboxLabel:"Row (4 columns)",toolboxDescription:"Row with 4 columns.",children:LayoutEditor.Column.times(4)}),LayoutEditor.Row.from({toolboxIcon:"",toolboxLabel:"Row (6 columns)",toolboxDescription:"Row with 6 columns.",children:LayoutEditor.Column.times(6)}),LayoutEditor.Row.from({toolboxIcon:"",toolboxLabel:"Row (12 columns)",toolboxDescription:"Row with 12 columns.",children:LayoutEditor.Column.times(12)}),LayoutEditor.Row.from({toolboxIcon:"",toolboxLabel:"Row (empty)",toolboxDescription:"Empty row.",children:[]})],e.columnElements=[LayoutEditor.Column.from({toolboxIcon:"",toolboxLabel:"Column",toolboxDescription:"Empty column.",width:1,offset:0,children:[]})],e.canvasElements=[LayoutEditor.Canvas.from({toolboxIcon:"",toolboxLabel:"Canvas",toolboxDescription:"Empty canvas.",children:[]})],e.contentElementCategories=_(e.element.config.categories).map(function(e){return{name:e.name,elements:_(e.contentTypes).map(function(e){var t=e.type,o=LayoutEditor.factories[t]||LayoutEditor.factories.Content,n={isTemplated:!1,contentType:e.id,contentTypeLabel:e.label,contentTypeClass:e.typeClass,data:null,hasEditor:e.hasEditor,html:e.html},l=o(n);return l.toolboxIcon=e.icon||"",l.toolboxLabel=e.label,l.toolboxDescription=e.description,l})}})},e.resetElements(),e.getSortableOptions=function(o){var n,l,a=t.closest(".layout-editor").attr("id"),i=!1;switch(o){case"Grid":n=[".layout-canvas",".layout-column",".layout-common-holder"],l="layout-element layout-container layout-grid ui-sortable-placeholder";break;case"Row":n=[".layout-grid"],l="layout-element layout-container layout-row row ui-sortable-placeholder";break;case"Column":n=[".layout-row:not(.layout-row-full)"],l="layout-element layout-container layout-column ui-sortable-placeholder",i=!0;break;case"Content":n=[".layout-canvas",".layout-column",".layout-common-holder"],l="layout-element layout-content ui-sortable-placeholder";break;case"Canvas":n=[".layout-canvas",".layout-column",".layout-common-holder"],l="layout-element layout-container layout-grid ui-sortable-placeholder"}return{cursor:"move",connectWith:_(n).map(function(e){return"#"+a+" "+e+":not(.layout-container-sealed) > .layout-element-wrapper > .layout-children"}).join(", "),placeholder:l,"ui-floating":i,create:function(e,t){e.target.isToolbox=!0},start:function(t,o){e.$apply(function(){e.element.isDragging=!0})},stop:function(t,o){e.$apply(function(){e.element.isDragging=!1,e.resetElements()})},over:function(t,o){e.$apply(function(){e.element.canvas.setIsDropTarget(!1)})}}};var o="layoutToolboxCategory_Layout_IsCollapsed";e.layoutIsCollapsed="true"===$.cookie(o),e.toggleLayoutIsCollapsed=function(t){e.layoutIsCollapsed=!e.layoutIsCollapsed,$.cookie(o,e.layoutIsCollapsed,{expires:365}),t.preventDefault(),t.stopPropagation()}}],templateUrl:t.templateUrl("Toolbox"),replace:!0,link:function(e,t){var o=t.find(".layout-toolbox");$(window).on("resize scroll",function(e){var n=t.parent().find(".layout-canvas"),l=!!n&&n.height()>o.height(),a=$(window).scrollTop();l&&a>t.offset().top+t.height()-o.height()?(o.addClass("sticky-bottom"),o.removeClass("sticky-top")):l&&a>t.offset().top?(o.addClass("sticky-top"),o.removeClass("sticky-bottom")):(o.removeClass("sticky-top"),o.removeClass("sticky-bottom"))})}}}]),angular.module("LayoutEditor").directive("orcLayoutToolboxGroup",["$compile","environment",function(e,t){return{restrict:"E",scope:{category:"="},controller:["$scope","$element",function(e,t){var o="layoutToolboxCategory_"+e.category.name+"_IsCollapsed";e.isCollapsed="true"===$.cookie(o),e.toggleIsCollapsed=function(t){e.isCollapsed=!e.isCollapsed,$.cookie(o,e.isCollapsed,{expires:365}),t.preventDefault(),t.stopPropagation()}}],templateUrl:t.templateUrl("ToolboxGroup"),replace:!0}}]); \ No newline at end of file +angular.module("LayoutEditor",["ngSanitize","ngResource","ui.sortable"]);var LayoutEditor;!function(e){var t=function(){var e=this;this._clipboardData={},this._isDisabled=!1,this._wasInvoked=!1,this.setData=function(t,o){e._clipboardData[t]=o,e._wasInvoked=!0},this.getData=function(t){return e._clipboardData[t]},this.disable=function(){e._isDisabled=!0,e._wasInvoked=!1,e._clipboardData={}},this.isDisabled=function(){return e._isDisabled},this.wasInvoked=function(){return e._wasInvoked}};e.Clipboard=new t,angular.module("LayoutEditor").factory("clipboard",[function(){return{setData:e.Clipboard.setData,getData:e.Clipboard.getData,disable:e.Clipboard.disable,isDisabled:e.Clipboard.isDisabled,wasInvoked:e.Clipboard.wasInvoked}}])}(LayoutEditor||(LayoutEditor={})),angular.module("LayoutEditor").factory("scopeConfigurator",["$timeout","clipboard",function(e,t){return{configureForElement:function(e,o){o.find(".layout-panel").click(function(e){e.stopPropagation()}),o.parent().keydown(function(n){var l=!1,a=!1,r=e.element;if(!r.editor.isDragging){if(!t.isDisabled()){var i=r.editor.focusedElement;if(i&&n.ctrlKey)switch(n.which){case 67:i.copy(t);break;case 88:i.cut(t);break;case 86:i.paste(t)}}if(n.ctrlKey||n.shiftKey||n.altKey||46!=n.which?n.ctrlKey||n.shiftKey||n.altKey||32!=n.which&&27!=n.which||(o.find(".layout-panel-action-properties").first().click(),l=!0):(e["delete"](r),l=!0),"Content"==r.type&&(n.ctrlKey||n.shiftKey||n.altKey||13!=n.which||(o.find(".layout-panel-action-edit").first().click(),l=!0)),r.children&&(n.ctrlKey||n.shiftKey||!n.altKey||40!=n.which||(r.children.length>0&&r.children[0].setIsFocused(),l=!0),"Column"==r.type)){var c=!n.ctrlKey;37==n.which?(n.altKey&&r.expandLeft(c),n.shiftKey&&r.contractRight(c),l=!0):39==n.which&&(n.altKey&&r.contractLeft(c),n.shiftKey&&r.expandRight(c),l=!0)}r.parent&&(n.altKey&&38==n.which&&(r.parent.setIsFocused(),l=!0),"Row"==r.parent.type?n.ctrlKey||n.shiftKey||n.altKey||37!=n.which?n.ctrlKey||n.shiftKey||n.altKey||39!=n.which?!n.ctrlKey||n.shiftKey||n.altKey||37!=n.which?!n.ctrlKey||n.shiftKey||n.altKey||39!=n.which||(r.moveDown(),l=!0):(r.moveUp(),a=!0,l=!0):(r.parent.moveFocusNextChild(r),l=!0):(r.parent.moveFocusPrevChild(r),l=!0):n.ctrlKey||n.shiftKey||n.altKey||38!=n.which?n.ctrlKey||n.shiftKey||n.altKey||40!=n.which?!n.ctrlKey||n.shiftKey||n.altKey||38!=n.which?!n.ctrlKey||n.shiftKey||n.altKey||40!=n.which||(r.moveDown(),l=!0):(r.moveUp(),a=!0,l=!0):(r.parent.moveFocusNextChild(r),l=!0):(r.parent.moveFocusPrevChild(r),l=!0)),l&&n.preventDefault(),n.stopPropagation(),e.$apply(),a&&window.setTimeout(function(){e.$apply(function(){r.editor.focusedElement.setIsFocused()})},100)}}),e.element.setIsFocusedEventHandlers.push(function(){o.parent().focus()}),e["delete"]=function(e){e["delete"]()}},configureForContainer:function(t,o){var n=t.element;t.getShowChildrenPlaceholder=function(){return 0===t.element.children.length&&!t.element.getIsDropTarget()},t.sortableOptions={cursor:"move",delay:150,disabled:n.getIsSealed(),distance:5,start:function(e,o){t.$apply(function(){n.setIsDropTarget(!0),n.editor.isDragging=!0}),o.placeholder.height(o.item.height()-4),o.placeholder.css("min-height",0)},stop:function(e,o){t.$apply(function(){n.editor.isDragging=!1,n.setIsDropTarget(!1)})},over:function(t,l){l.sender&&l.sender[0].isToolbox&&(l.sender[0].dropTargetTimeout&&(e.cancel(l.sender[0].dropTargetTimeout),l.sender[0].dropTargetTimeout=null),e(function(){if("Row"==n.type){var e=n.editor.dropTargetElement;e&&"Row"==e.type&&e.rollbackAddColumn()}n.setIsDropTarget(!1)}),l.sender[0].dropTargetTimeout=e(function(){if("Row"==n.type){var e=l.item.sortable.model,t=Math.floor(12/(n.children.length+1));e.width=t,e.offset=0,n.beginAddColumn(t);var a=_.max(_(o.find("> .layout-children > .layout-column:not(.ui-sortable-placeholder)")).map(function(e){return $(e).height()}));for(i=1;i<=12;i++)l.placeholder.removeClass("col-xs-"+i);l.placeholder.addClass("col-xs-"+e.width),a>0?(l.placeholder.height(a),l.placeholder.css("min-height",0)):(l.placeholder.height(0),l.placeholder.css("min-height",""))}n.setIsDropTarget(!0)},150))},receive:function(o,l){l.sender&&l.sender[0].isToolbox&&t.$apply(function(){var o=l.item.sortable.model;o&&("Row"==n.type&&n.commitAddColumn(),o.setEditor(n.editor),o.setParent(n),o.hasEditor&&t.$root.editElement(o).then(function(t){t.cancel||(o.data=t.element.data,o.applyElementEditorModel(t.elementEditorModel),o.setHtml&&o.setHtml(t.element.html)),e(function(){t.cancel?o["delete"]():o.setIsFocused(),n.setIsDropTarget(!1)})})),e(function(){n.setIsDropTarget(!1),o&&o.setIsFocused()})})}},t.click=function(e,t){e.editor.isDragging||e.setIsFocused(),t.stopPropagation()},t.getClasses=function(e){var t=["layout-element"];return e.children&&(t.push("layout-container"),e.getIsSealed()&&t.push("layout-container-sealed")),t.push("layout-"+e.type.toLowerCase()),e.dropTargetClass&&t.push(e.dropTargetClass),"Row"==e.type&&(t.push("row"),e.canAddColumn()||t.push("layout-row-full")),"Column"==e.type&&(t.push("col-xs-"+e.width),t.push("col-xs-offset-"+e.offset)),"Content"==e.type&&t.push("layout-content-"+e.contentTypeClass),e.getIsActive()&&t.push("layout-element-active"),e.getIsFocused()&&t.push("layout-element-focused"),e.getIsSelected()&&t.push("layout-element-selected"),e.getIsDropTarget()&&t.push("layout-element-droptarget"),e.isTemplated&&t.push("layout-element-templated"),t}}}}]),angular.module("LayoutEditor").directive("orcLayoutEditor",["environment",function(environment){return{restrict:"E",scope:{},controller:["$scope","$element","$attrs","$compile","clipboard",function($scope,$element,$attrs,$compile,clipboard){if(!$attrs.model)throw new Error("The 'model' attribute must evaluate to a LayoutEditor.Editor object.");$scope.element=eval($attrs.model),$scope.click=function(e,t){e.editor.isDragging||e.setIsFocused(),t.stopPropagation()},$scope.getClasses=function(e){var t=["layout-element","layout-container","layout-canvas"];return e.getIsActive()&&t.push("layout-element-active"),e.getIsFocused()&&t.push("layout-element-focused"),e.getIsSelected()&&t.push("layout-element-selected"),e.getIsDropTarget()&&t.push("layout-element-droptarget"),e.isTemplated&&t.push("layout-element-templated"),t};var layoutDesignerHost=$(".layout-designer").data("layout-designer-host");$scope.$root.layoutDesignerHost=layoutDesignerHost,layoutDesignerHost.element.on("replacecanvas",function(e,t){var o=$scope.element,n={data:t.canvas.data,htmlId:t.canvas.htmlId,htmlClass:t.canvas.htmlClass,htmlStyle:t.canvas.htmlStyle,isTemplated:t.canvas.isTemplated,children:t.canvas.children};layoutDesignerHost.editor=window.layoutEditor=new LayoutEditor.Editor(o.config,n);var l="",a=$compile(l)($scope);$(".layout-editor-holder").html(a)}),$scope.$root.editElement=function(e){var t=$scope.$root.layoutDesignerHost;return t.editElement(e)},$scope.$root.addElement=function(e){var t=$scope.$root.layoutDesignerHost;return t.addElement(e)},$(document).on("cut copy paste",function(e){if(clipboard.wasInvoked())e.originalEvent.clipboardData.setData("text/plain",clipboard.getData("text/plain")),e.originalEvent.clipboardData.setData("text/json",clipboard.getData("text/json")),e.preventDefault();else{var t=$scope.element.focusedElement;t&&($scope.$apply(function(){switch(e.type){case"copy":t.copy(e.originalEvent.clipboardData);break;case"cut":t.cut(e.originalEvent.clipboardData);break;case"paste":t.paste(e.originalEvent.clipboardData)}}),window.setTimeout(function(){$scope.$apply(function(){$scope.element.focusedElement&&$scope.element.focusedElement.setIsFocused()})},100),e.preventDefault())}clipboard.disable()})}],templateUrl:environment.templateUrl("Editor"),replace:!0,link:function(e,t){t.find(".layout-toolbar-container").click(function(e){e.stopPropagation()}),$(window).click(function(t){e.$apply(function(){e.element.activeElement=null,e.element.focusedElement=null})})}}}]),angular.module("LayoutEditor").directive("orcLayoutCanvas",["scopeConfigurator","environment",function(e,t){return{restrict:"E",scope:{element:"="},controller:["$scope","$element","$attrs",function(t,o,n){e.configureForElement(t,o),e.configureForContainer(t,o),t.sortableOptions.axis="y"}],templateUrl:t.templateUrl("Canvas"),replace:!0}}]),angular.module("LayoutEditor").directive("orcLayoutChild",["$compile",function(e){return{restrict:"E",scope:{element:"="},link:function(t,o){var n="",l=e(n)(t);$(o).replaceWith(l)}}}]),angular.module("LayoutEditor").directive("orcLayoutColumn",["$compile","scopeConfigurator","environment",function(e,t,o){return{restrict:"E",scope:{element:"="},controller:["$scope","$element",function(e,o){t.configureForElement(e,o),t.configureForContainer(e,o),e.sortableOptions.axis="y"}],templateUrl:o.templateUrl("Column"),replace:!0,link:function(e,t,o){t.find(".layout-column-resize-bar").draggable({axis:"x",helper:"clone",revert:!0,start:function(t,o){e.$apply(function(){e.element.editor.isResizing=!0})},drag:function(o,n){var l=t.parent(),a=l.width()/e.element.width,r=!o.ctrlKey;if($(o.target).hasClass("layout-column-resize-bar-left")){var i=n.offset.left-l.offset().left;-a>i&&e.element.canExpandLeft(r)?e.$apply(function(){e.element.expandLeft(r)}):i>a&&e.element.canContractLeft(r)&&e.$apply(function(){e.element.contractLeft(r)})}else if($(o.target).hasClass("layout-column-resize-bar-right")){var i=n.offset.left-l.width()-l.offset().left;i>a&&e.element.canExpandRight(r)?e.$apply(function(){e.element.expandRight(r)}):-a>i&&e.element.canContractRight(r)&&e.$apply(function(){e.element.contractRight(r)})}},stop:function(t,o){e.$apply(function(){e.element.editor.isResizing=!1})}})}}}]),angular.module("LayoutEditor").directive("orcLayoutContent",["$sce","scopeConfigurator","environment",function(e,t,o){return{restrict:"E",scope:{element:"="},controller:["$scope","$element",function(o,n){t.configureForElement(o,n),o.edit=function(){o.$root.editElement(o.element).then(function(e){o.$apply(function(){e.cancel||(o.element.data=e.element.data,o.element.setHtml(e.element.html))})})},o.element.setHtml=function(t){o.element.html=t,o.element.htmlUnsafe=e.trustAsHtml(t)},o.element.setHtml(o.element.html)}],templateUrl:o.templateUrl("Content"),replace:!0}}]),angular.module("LayoutEditor").directive("orcLayoutHtml",["$sce","scopeConfigurator","environment",function(e,t,o){return{restrict:"E",scope:{element:"="},controller:["$scope","$element",function(o,n){t.configureForElement(o,n),o.edit=function(){o.$root.editElement(o.element).then(function(e){o.$apply(function(){e.cancel||(o.element.data=e.element.data,o.element.setHtml(e.element.html))})})},o.updateContent=function(e){o.element.setHtml(e.target.innerHTML)},o.element.setHtml=function(t){o.element.html=t,o.element.htmlUnsafe=e.trustAsHtml(t)},o.element.setHtml(o.element.html)}],templateUrl:o.templateUrl("Html"),replace:!0,link:function(e,t){}}}]),angular.module("LayoutEditor").directive("orcLayoutGrid",["$compile","scopeConfigurator","environment",function(e,t,o){return{restrict:"E",scope:{element:"="},controller:["$scope","$element",function(e,o){t.configureForElement(e,o),t.configureForContainer(e,o),e.sortableOptions.axis="y"}],templateUrl:o.templateUrl("Grid"),replace:!0}}]),angular.module("LayoutEditor").directive("orcLayoutRow",["$compile","scopeConfigurator","environment",function(e,t,o){return{restrict:"E",scope:{element:"="},controller:["$scope","$element",function(e,o){t.configureForElement(e,o),t.configureForContainer(e,o),e.sortableOptions.axis="x",e.sortableOptions["ui-floating"]=!0}],templateUrl:o.templateUrl("Row"),replace:!0}}]),angular.module("LayoutEditor").directive("orcLayoutPopup",[function(){return{restrict:"A",link:function(e,t,o){var n=$(t),l=n.closest(".layout-popup-trigger"),a=n.closest(".layout-element");l.click(function(){n.toggle(),n.is(":visible")&&(n.position({my:o.orcLayoutPopupMy||"left top",at:o.orcLayoutPopupAt||"left bottom+4px",of:l}),n.find("input").first().focus())}),n.click(function(e){e.stopPropagation()}),a.click(function(e){n.hide()}),n.keydown(function(e){e.ctrlKey||e.shiftKey||e.altKey||27!=e.which||n.hide(),e.stopPropagation()}),n.on("cut copy paste",function(e){e.stopPropagation()})}}}]),angular.module("LayoutEditor").directive("orcLayoutToolbox",["$compile","environment",function(e,t){return{restrict:"E",controller:["$scope","$element",function(e,t){e.resetElements=function(){e.gridElements=[LayoutEditor.Grid.from({toolboxIcon:"",toolboxLabel:"Grid",toolboxDescription:"Empty grid.",children:[]})],e.rowElements=[LayoutEditor.Row.from({toolboxIcon:"",toolboxLabel:"Row (1 column)",toolboxDescription:"Row with 1 column.",children:LayoutEditor.Column.times(1)}),LayoutEditor.Row.from({toolboxIcon:"",toolboxLabel:"Row (2 columns)",toolboxDescription:"Row with 2 columns.",children:LayoutEditor.Column.times(2)}),LayoutEditor.Row.from({toolboxIcon:"",toolboxLabel:"Row (3 columns)",toolboxDescription:"Row with 3 columns.",children:LayoutEditor.Column.times(3)}),LayoutEditor.Row.from({toolboxIcon:"",toolboxLabel:"Row (4 columns)",toolboxDescription:"Row with 4 columns.",children:LayoutEditor.Column.times(4)}),LayoutEditor.Row.from({toolboxIcon:"",toolboxLabel:"Row (6 columns)",toolboxDescription:"Row with 6 columns.",children:LayoutEditor.Column.times(6)}),LayoutEditor.Row.from({toolboxIcon:"",toolboxLabel:"Row (12 columns)",toolboxDescription:"Row with 12 columns.",children:LayoutEditor.Column.times(12)}),LayoutEditor.Row.from({toolboxIcon:"",toolboxLabel:"Row (empty)",toolboxDescription:"Empty row.",children:[]})],e.columnElements=[LayoutEditor.Column.from({toolboxIcon:"",toolboxLabel:"Column",toolboxDescription:"Empty column.",width:1,offset:0,children:[]})],e.canvasElements=[LayoutEditor.Canvas.from({toolboxIcon:"",toolboxLabel:"Canvas",toolboxDescription:"Empty canvas.",children:[]})],e.contentElementCategories=_(e.element.config.categories).map(function(e){return{name:e.name,elements:_(e.contentTypes).map(function(e){var t=e.type,o=LayoutEditor.factories[t]||LayoutEditor.factories.Content,n={isTemplated:!1,contentType:e.id,contentTypeLabel:e.label,contentTypeClass:e.typeClass,data:null,hasEditor:e.hasEditor,html:e.html},l=o(n);return l.toolboxIcon=e.icon||"",l.toolboxLabel=e.label,l.toolboxDescription=e.description,l})}})},e.resetElements(),e.getSortableOptions=function(o){var n,l,a=t.closest(".layout-editor").attr("id"),r=!1;switch(o){case"Grid":n=[".layout-canvas",".layout-column",".layout-common-holder"],l="layout-element layout-container layout-grid ui-sortable-placeholder";break;case"Row":n=[".layout-grid"],l="layout-element layout-container layout-row row ui-sortable-placeholder";break;case"Column":n=[".layout-row:not(.layout-row-full)"],l="layout-element layout-container layout-column ui-sortable-placeholder",r=!0;break;case"Content":n=[".layout-canvas",".layout-column",".layout-common-holder"],l="layout-element layout-content ui-sortable-placeholder";break;case"Canvas":n=[".layout-canvas",".layout-column",".layout-common-holder"],l="layout-element layout-container layout-grid ui-sortable-placeholder"}return{cursor:"move",connectWith:_(n).map(function(e){return"#"+a+" "+e+":not(.layout-container-sealed) > .layout-element-wrapper > .layout-children"}).join(", "),placeholder:l,"ui-floating":r,create:function(e,t){e.target.isToolbox=!0},start:function(t,o){e.$apply(function(){e.element.isDragging=!0})},stop:function(t,o){e.$apply(function(){e.element.isDragging=!1,e.resetElements()})},over:function(t,o){e.$apply(function(){e.element.canvas.setIsDropTarget(!1)})}}};var o="layoutToolboxCategory_Layout_IsCollapsed";e.layoutIsCollapsed="true"===$.cookie(o),e.toggleLayoutIsCollapsed=function(t){e.layoutIsCollapsed=!e.layoutIsCollapsed,$.cookie(o,e.layoutIsCollapsed,{expires:365}),t.preventDefault(),t.stopPropagation()}}],templateUrl:t.templateUrl("Toolbox"),replace:!0,link:function(e,t){var o=t.find(".layout-toolbox");$(window).on("resize scroll",function(e){var n=t.parent().find(".layout-canvas"),l=!!n&&n.height()>o.height(),a=$(window).scrollTop();l&&a>t.offset().top+t.height()-o.height()?(o.addClass("sticky-bottom"),o.removeClass("sticky-top")):l&&a>t.offset().top?(o.addClass("sticky-top"),o.removeClass("sticky-bottom")):(o.removeClass("sticky-top"),o.removeClass("sticky-bottom"))})}}}]),angular.module("LayoutEditor").directive("orcLayoutToolboxGroup",["$compile","environment",function(e,t){return{restrict:"E",scope:{category:"="},controller:["$scope","$element",function(e,t){var o="layoutToolboxCategory_"+e.category.name+"_IsCollapsed";e.isCollapsed="true"===$.cookie(o),e.toggleIsCollapsed=function(t){e.isCollapsed=!e.isCollapsed,$.cookie(o,e.isCollapsed,{expires:365}),t.preventDefault(),t.stopPropagation()}}],templateUrl:t.templateUrl("ToolboxGroup"),replace:!0}}]); \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Scripts/Models.js b/src/Orchard.Web/Modules/Orchard.Layouts/Scripts/Models.js index c79c8401e..4e7f4a183 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Scripts/Models.js +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Scripts/Models.js @@ -52,7 +52,6 @@ var LayoutEditor; this.focusedElement = null; this.dropTargetElement = null; this.isDragging = false; - this.inlineEditingIsActive = false; this.isResizing = false; this.resetToolboxElements = function () { @@ -133,7 +132,7 @@ var LayoutEditor; this.setIsActive = function (value) { if (!this.editor) return; - if (this.editor.isDragging || this.editor.inlineEditingIsActive || this.editor.isResizing) + if (this.editor.isDragging || this.editor.isResizing) return; if (value) @@ -153,7 +152,7 @@ var LayoutEditor; return; if (!this.children && this.isTemplated) return; - if (this.editor.isDragging || this.editor.inlineEditingIsActive || this.editor.isResizing) + if (this.editor.isDragging || this.editor.isResizing) return; this.editor.focusedElement = this; @@ -1050,4 +1049,4 @@ var LayoutEditor; LayoutEditor.registerFactory("Html", function(value) { return LayoutEditor.Html.from(value); }); })(jQuery, LayoutEditor || (LayoutEditor = {})); -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkhlbHBlcnMuanMiLCJFZGl0b3IuanMiLCJFbGVtZW50LmpzIiwiQ29udGFpbmVyLmpzIiwiQ2FudmFzLmpzIiwiR3JpZC5qcyIsIlJvdy5qcyIsIkNvbHVtbi5qcyIsIkNvbnRlbnQuanMiLCJIdG1sLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDMUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ2hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ25NQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDOUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNsQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDN0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDN1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDNUpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUMxREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiTW9kZWxzLmpzIiwic291cmNlc0NvbnRlbnQiOlsidmFyIExheW91dEVkaXRvcjtcclxuKGZ1bmN0aW9uIChMYXlvdXRFZGl0b3IpIHtcclxuXHJcbiAgICBBcnJheS5wcm90b3R5cGUubW92ZSA9IGZ1bmN0aW9uIChmcm9tLCB0bykge1xyXG4gICAgICAgIHRoaXMuc3BsaWNlKHRvLCAwLCB0aGlzLnNwbGljZShmcm9tLCAxKVswXSk7XHJcbiAgICB9O1xyXG5cclxuICAgIExheW91dEVkaXRvci5jaGlsZHJlbkZyb20gPSBmdW5jdGlvbih2YWx1ZXMpIHtcclxuICAgICAgICByZXR1cm4gXyh2YWx1ZXMpLm1hcChmdW5jdGlvbih2YWx1ZSkge1xyXG4gICAgICAgICAgICByZXR1cm4gTGF5b3V0RWRpdG9yLmVsZW1lbnRGcm9tKHZhbHVlKTtcclxuICAgICAgICB9KTtcclxuICAgIH07XHJcblxyXG4gICAgdmFyIHJlZ2lzdGVyRmFjdG9yeSA9IExheW91dEVkaXRvci5yZWdpc3RlckZhY3RvcnkgPSBmdW5jdGlvbih0eXBlLCBmYWN0b3J5KSB7XHJcbiAgICAgICAgdmFyIGZhY3RvcmllcyA9IExheW91dEVkaXRvci5mYWN0b3JpZXMgPSBMYXlvdXRFZGl0b3IuZmFjdG9yaWVzIHx8IHt9O1xyXG4gICAgICAgIGZhY3Rvcmllc1t0eXBlXSA9IGZhY3Rvcnk7XHJcbiAgICB9O1xyXG5cclxuICAgIHJlZ2lzdGVyRmFjdG9yeShcIkNhbnZhc1wiLCBmdW5jdGlvbiAodmFsdWUpIHsgcmV0dXJuIExheW91dEVkaXRvci5DYW52YXMuZnJvbSh2YWx1ZSk7IH0pO1xyXG4gICAgcmVnaXN0ZXJGYWN0b3J5KFwiR3JpZFwiLCBmdW5jdGlvbih2YWx1ZSkgeyByZXR1cm4gTGF5b3V0RWRpdG9yLkdyaWQuZnJvbSh2YWx1ZSk7IH0pO1xyXG4gICAgcmVnaXN0ZXJGYWN0b3J5KFwiUm93XCIsIGZ1bmN0aW9uKHZhbHVlKSB7IHJldHVybiBMYXlvdXRFZGl0b3IuUm93LmZyb20odmFsdWUpOyB9KTtcclxuICAgIHJlZ2lzdGVyRmFjdG9yeShcIkNvbHVtblwiLCBmdW5jdGlvbih2YWx1ZSkgeyByZXR1cm4gTGF5b3V0RWRpdG9yLkNvbHVtbi5mcm9tKHZhbHVlKTsgfSk7XHJcbiAgICByZWdpc3RlckZhY3RvcnkoXCJDb250ZW50XCIsIGZ1bmN0aW9uKHZhbHVlKSB7IHJldHVybiBMYXlvdXRFZGl0b3IuQ29udGVudC5mcm9tKHZhbHVlKTsgfSk7XHJcblxyXG4gICAgTGF5b3V0RWRpdG9yLmVsZW1lbnRGcm9tID0gZnVuY3Rpb24gKHZhbHVlKSB7XHJcbiAgICAgICAgdmFyIGZhY3RvcnkgPSBMYXlvdXRFZGl0b3IuZmFjdG9yaWVzW3ZhbHVlLnR5cGVdO1xyXG5cclxuICAgICAgICBpZiAoIWZhY3RvcnkpXHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGVsZW1lbnQgd2l0aCB0eXBlIFxcXCJcIiArIHZhbHVlLnR5cGUgKyBcIlxcXCIgd2FzIGZvdW5kLlwiKTtcclxuXHJcbiAgICAgICAgdmFyIGVsZW1lbnQgPSBmYWN0b3J5KHZhbHVlKTtcclxuICAgICAgICByZXR1cm4gZWxlbWVudDtcclxuICAgIH07XHJcblxyXG4gICAgTGF5b3V0RWRpdG9yLnNldE1vZGVsID0gZnVuY3Rpb24gKGVsZW1lbnRTZWxlY3RvciwgbW9kZWwpIHtcclxuICAgICAgICAkKGVsZW1lbnRTZWxlY3Rvcikuc2NvcGUoKS5lbGVtZW50ID0gbW9kZWw7XHJcbiAgICB9O1xyXG5cclxuICAgIExheW91dEVkaXRvci5nZXRNb2RlbCA9IGZ1bmN0aW9uIChlbGVtZW50U2VsZWN0b3IpIHtcclxuICAgICAgICByZXR1cm4gJChlbGVtZW50U2VsZWN0b3IpLnNjb3BlKCkuZWxlbWVudDtcclxuICAgIH07XHJcblxyXG59KShMYXlvdXRFZGl0b3IgfHwgKExheW91dEVkaXRvciA9IHt9KSk7IiwidmFyIExheW91dEVkaXRvcjtcclxuKGZ1bmN0aW9uIChMYXlvdXRFZGl0b3IpIHtcclxuXHJcbiAgICBMYXlvdXRFZGl0b3IuRWRpdG9yID0gZnVuY3Rpb24gKGNvbmZpZywgY2FudmFzRGF0YSkge1xyXG4gICAgICAgIHRoaXMuY29uZmlnID0gY29uZmlnO1xyXG4gICAgICAgIHRoaXMuY2FudmFzID0gTGF5b3V0RWRpdG9yLkNhbnZhcy5mcm9tKGNhbnZhc0RhdGEpO1xyXG4gICAgICAgIHRoaXMuaW5pdGlhbFN0YXRlID0gSlNPTi5zdHJpbmdpZnkodGhpcy5jYW52YXMudG9PYmplY3QoKSk7XHJcbiAgICAgICAgdGhpcy5hY3RpdmVFbGVtZW50ID0gbnVsbDtcclxuICAgICAgICB0aGlzLmZvY3VzZWRFbGVtZW50ID0gbnVsbDtcclxuICAgICAgICB0aGlzLmRyb3BUYXJnZXRFbGVtZW50ID0gbnVsbDtcclxuICAgICAgICB0aGlzLmlzRHJhZ2dpbmcgPSBmYWxzZTtcclxuICAgICAgICB0aGlzLmlubGluZUVkaXRpbmdJc0FjdGl2ZSA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMuaXNSZXNpemluZyA9IGZhbHNlO1xyXG5cclxuICAgICAgICB0aGlzLnJlc2V0VG9vbGJveEVsZW1lbnRzID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICB0aGlzLnRvb2xib3hFbGVtZW50cyA9IFtcclxuICAgICAgICAgICAgICAgIExheW91dEVkaXRvci5Sb3cuZnJvbSh7XHJcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IFtdXHJcbiAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICBdO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuaXNEaXJ0eSA9IGZ1bmN0aW9uKCkge1xyXG4gICAgICAgICAgICB2YXIgY3VycmVudFN0YXRlID0gSlNPTi5zdHJpbmdpZnkodGhpcy5jYW52YXMudG9PYmplY3QoKSk7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmluaXRpYWxTdGF0ZSAhPSBjdXJyZW50U3RhdGU7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5yZXNldFRvb2xib3hFbGVtZW50cygpO1xyXG4gICAgICAgIHRoaXMuY2FudmFzLnNldEVkaXRvcih0aGlzKTtcclxuICAgIH07XHJcblxyXG59KShMYXlvdXRFZGl0b3IgfHwgKExheW91dEVkaXRvciA9IHt9KSk7XHJcbiIsInZhciBMYXlvdXRFZGl0b3I7XHJcbihmdW5jdGlvbiAoTGF5b3V0RWRpdG9yKSB7XHJcblxyXG4gICAgTGF5b3V0RWRpdG9yLkVsZW1lbnQgPSBmdW5jdGlvbiAodHlwZSwgZGF0YSwgaHRtbElkLCBodG1sQ2xhc3MsIGh0bWxTdHlsZSwgaXNUZW1wbGF0ZWQsIHJ1bGUpIHtcclxuICAgICAgICBpZiAoIXR5cGUpXHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlBhcmFtZXRlciAndHlwZScgaXMgcmVxdWlyZWQuXCIpO1xyXG5cclxuICAgICAgICB0aGlzLnR5cGUgPSB0eXBlO1xyXG4gICAgICAgIHRoaXMuZGF0YSA9IGRhdGE7XHJcbiAgICAgICAgdGhpcy5odG1sSWQgPSBodG1sSWQ7XHJcbiAgICAgICAgdGhpcy5odG1sQ2xhc3MgPSBodG1sQ2xhc3M7XHJcbiAgICAgICAgdGhpcy5odG1sU3R5bGUgPSBodG1sU3R5bGU7XHJcbiAgICAgICAgdGhpcy5pc1RlbXBsYXRlZCA9IGlzVGVtcGxhdGVkO1xyXG4gICAgICAgIHRoaXMucnVsZSA9IHJ1bGU7XHJcblxyXG4gICAgICAgIHRoaXMuZWRpdG9yID0gbnVsbDtcclxuICAgICAgICB0aGlzLnBhcmVudCA9IG51bGw7XHJcbiAgICAgICAgdGhpcy5zZXRJc0ZvY3VzZWRFdmVudEhhbmRsZXJzID0gW107XHJcblxyXG4gICAgICAgIHRoaXMuc2V0RWRpdG9yID0gZnVuY3Rpb24gKGVkaXRvcikge1xyXG4gICAgICAgICAgICB0aGlzLmVkaXRvciA9IGVkaXRvcjtcclxuICAgICAgICAgICAgaWYgKCEhdGhpcy5jaGlsZHJlbiAmJiBfLmlzQXJyYXkodGhpcy5jaGlsZHJlbikpIHtcclxuICAgICAgICAgICAgICAgIF8odGhpcy5jaGlsZHJlbikuZWFjaChmdW5jdGlvbiAoY2hpbGQpIHtcclxuICAgICAgICAgICAgICAgICAgICBjaGlsZC5zZXRFZGl0b3IoZWRpdG9yKTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5zZXRQYXJlbnQgPSBmdW5jdGlvbihwYXJlbnRFbGVtZW50KSB7XHJcbiAgICAgICAgICAgIHRoaXMucGFyZW50ID0gcGFyZW50RWxlbWVudDtcclxuICAgICAgICAgICAgdGhpcy5wYXJlbnQub25DaGlsZEFkZGVkKHRoaXMpO1xyXG5cclxuICAgICAgICAgICAgdmFyIGN1cnJlbnRBbmNlc3RvciA9IHBhcmVudEVsZW1lbnQ7XHJcbiAgICAgICAgICAgIHdoaWxlICghIWN1cnJlbnRBbmNlc3Rvcikge1xyXG4gICAgICAgICAgICAgICAgY3VycmVudEFuY2VzdG9yLm9uRGVzY2VuZGFudEFkZGVkKHRoaXMsIHBhcmVudEVsZW1lbnQpO1xyXG4gICAgICAgICAgICAgICAgY3VycmVudEFuY2VzdG9yID0gY3VycmVudEFuY2VzdG9yLnBhcmVudDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuc2V0SXNUZW1wbGF0ZWQgPSBmdW5jdGlvbiAodmFsdWUpIHtcclxuICAgICAgICAgICAgdGhpcy5pc1RlbXBsYXRlZCA9IHZhbHVlO1xyXG4gICAgICAgICAgICBpZiAoISF0aGlzLmNoaWxkcmVuICYmIF8uaXNBcnJheSh0aGlzLmNoaWxkcmVuKSkge1xyXG4gICAgICAgICAgICAgICAgXyh0aGlzLmNoaWxkcmVuKS5lYWNoKGZ1bmN0aW9uIChjaGlsZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNoaWxkLnNldElzVGVtcGxhdGVkKHZhbHVlKTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5hcHBseUVsZW1lbnRFZGl0b3JNb2RlbCA9IGZ1bmN0aW9uKCkgeyAvKiBWaXJ0dWFsICovIH07XHJcblxyXG4gICAgICAgIHRoaXMuZ2V0SXNBY3RpdmUgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy5lZGl0b3IpXHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVkaXRvci5hY3RpdmVFbGVtZW50ID09PSB0aGlzICYmICF0aGlzLmdldElzRm9jdXNlZCgpO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuc2V0SXNBY3RpdmUgPSBmdW5jdGlvbiAodmFsdWUpIHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLmVkaXRvcilcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgaWYgKHRoaXMuZWRpdG9yLmlzRHJhZ2dpbmcgfHwgdGhpcy5lZGl0b3IuaW5saW5lRWRpdGluZ0lzQWN0aXZlIHx8IHRoaXMuZWRpdG9yLmlzUmVzaXppbmcpXHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgICAgICBpZiAodmFsdWUpXHJcbiAgICAgICAgICAgICAgICB0aGlzLmVkaXRvci5hY3RpdmVFbGVtZW50ID0gdGhpcztcclxuICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAgdGhpcy5lZGl0b3IuYWN0aXZlRWxlbWVudCA9IHRoaXMucGFyZW50O1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuZ2V0SXNGb2N1c2VkID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMuZWRpdG9yKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lZGl0b3IuZm9jdXNlZEVsZW1lbnQgPT09IHRoaXM7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5zZXRJc0ZvY3VzZWQgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy5lZGl0b3IpXHJcbiAgICAgICAgICAgIFx0cmV0dXJuO1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMuY2hpbGRyZW4gJiYgdGhpcy5pc1RlbXBsYXRlZClcclxuICAgICAgICAgICAgXHRyZXR1cm47XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmVkaXRvci5pc0RyYWdnaW5nIHx8IHRoaXMuZWRpdG9yLmlubGluZUVkaXRpbmdJc0FjdGl2ZSB8fCB0aGlzLmVkaXRvci5pc1Jlc2l6aW5nKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5lZGl0b3IuZm9jdXNlZEVsZW1lbnQgPSB0aGlzO1xyXG4gICAgICAgICAgICBfKHRoaXMuc2V0SXNGb2N1c2VkRXZlbnRIYW5kbGVycykuZWFjaChmdW5jdGlvbiAoaXRlbSkge1xyXG4gICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICBpdGVtKCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBjYXRjaCAoZXgpIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBJZ25vcmUuXHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuZ2V0SXNTZWxlY3RlZCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuZ2V0SXNGb2N1c2VkKCkpXHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuXHJcbiAgICAgICAgICAgIGlmICghIXRoaXMuY2hpbGRyZW4gJiYgXy5pc0FycmF5KHRoaXMuY2hpbGRyZW4pKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gXyh0aGlzLmNoaWxkcmVuKS5hbnkoZnVuY3Rpb24oY2hpbGQpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2hpbGQuZ2V0SXNTZWxlY3RlZCgpO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLmdldElzRHJvcFRhcmdldCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLmVkaXRvcilcclxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZWRpdG9yLmRyb3BUYXJnZXRFbGVtZW50ID09PSB0aGlzO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5zZXRJc0Ryb3BUYXJnZXQgPSBmdW5jdGlvbiAodmFsdWUpIHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLmVkaXRvcilcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgaWYgKHZhbHVlKVxyXG4gICAgICAgICAgICAgICAgdGhpcy5lZGl0b3IuZHJvcFRhcmdldEVsZW1lbnQgPSB0aGlzO1xyXG4gICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICB0aGlzLmVkaXRvci5kcm9wVGFyZ2V0RWxlbWVudCA9IG51bGw7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jYW5EZWxldGUgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmlzVGVtcGxhdGVkIHx8ICF0aGlzLnBhcmVudClcclxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5kZWxldGUgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy5jYW5EZWxldGUoKSlcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgdGhpcy5wYXJlbnQuZGVsZXRlQ2hpbGQodGhpcyk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jYW5Nb3ZlVXAgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmlzVGVtcGxhdGVkIHx8ICF0aGlzLnBhcmVudClcclxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMucGFyZW50LmNhbk1vdmVDaGlsZFVwKHRoaXMpO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMubW92ZVVwID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMuY2FuTW92ZVVwKCkpXHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIHRoaXMucGFyZW50Lm1vdmVDaGlsZFVwKHRoaXMpO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuY2FuTW92ZURvd24gPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmlzVGVtcGxhdGVkIHx8ICF0aGlzLnBhcmVudClcclxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMucGFyZW50LmNhbk1vdmVDaGlsZERvd24odGhpcyk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5tb3ZlRG93biA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLmNhbk1vdmVEb3duKCkpXHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIHRoaXMucGFyZW50Lm1vdmVDaGlsZERvd24odGhpcyk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5lbGVtZW50VG9PYmplY3QgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgICAgICB0eXBlOiB0aGlzLnR5cGUsXHJcbiAgICAgICAgICAgICAgICBkYXRhOiB0aGlzLmRhdGEsXHJcbiAgICAgICAgICAgICAgICBodG1sSWQ6IHRoaXMuaHRtbElkLFxyXG4gICAgICAgICAgICAgICAgaHRtbENsYXNzOiB0aGlzLmh0bWxDbGFzcyxcclxuICAgICAgICAgICAgICAgIGh0bWxTdHlsZTogdGhpcy5odG1sU3R5bGUsXHJcbiAgICAgICAgICAgICAgICBpc1RlbXBsYXRlZDogdGhpcy5pc1RlbXBsYXRlZCxcclxuICAgICAgICAgICAgICAgIHJ1bGU6IHRoaXMucnVsZVxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuZ2V0RWRpdG9yT2JqZWN0ID0gZnVuY3Rpb24oKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB7fTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLmNvcHkgPSBmdW5jdGlvbiAoY2xpcGJvYXJkRGF0YSkge1xyXG4gICAgICAgICAgICB2YXIgdGV4dCA9IHRoaXMuZ2V0SW5uZXJUZXh0KCk7XHJcbiAgICAgICAgICAgIGNsaXBib2FyZERhdGEuc2V0RGF0YShcInRleHQvcGxhaW5cIiwgdGV4dCk7XHJcblxyXG4gICAgICAgICAgICB2YXIgZGF0YSA9IHRoaXMudG9PYmplY3QoKTtcclxuICAgICAgICAgICAgdmFyIGpzb24gPSBKU09OLnN0cmluZ2lmeShkYXRhLCBudWxsLCBcIlxcdFwiKTtcclxuICAgICAgICAgICAgY2xpcGJvYXJkRGF0YS5zZXREYXRhKFwidGV4dC9qc29uXCIsIGpzb24pO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuY3V0ID0gZnVuY3Rpb24gKGNsaXBib2FyZERhdGEpIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuY2FuRGVsZXRlKCkpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuY29weShjbGlwYm9hcmREYXRhKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuZGVsZXRlKCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLnBhc3RlID0gZnVuY3Rpb24gKGNsaXBib2FyZERhdGEpIHtcclxuICAgICAgICAgICAgaWYgKCEhdGhpcy5wYXJlbnQpXHJcbiAgICAgICAgICAgICAgICB0aGlzLnBhcmVudC5wYXN0ZShjbGlwYm9hcmREYXRhKTtcclxuICAgICAgICB9O1xyXG4gICAgfTtcclxuXHJcbn0pKExheW91dEVkaXRvciB8fCAoTGF5b3V0RWRpdG9yID0ge30pKTsiLCJ2YXIgTGF5b3V0RWRpdG9yO1xyXG4oZnVuY3Rpb24gKExheW91dEVkaXRvcikge1xyXG5cclxuICAgIExheW91dEVkaXRvci5Db250YWluZXIgPSBmdW5jdGlvbiAoYWxsb3dlZENoaWxkVHlwZXMsIGNoaWxkcmVuKSB7XHJcblxyXG4gICAgICAgIHRoaXMuYWxsb3dlZENoaWxkVHlwZXMgPSBhbGxvd2VkQ2hpbGRUeXBlcztcclxuICAgICAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW47XHJcbiAgICAgICAgdGhpcy5pc0NvbnRhaW5lciA9IHRydWU7XHJcblxyXG4gICAgICAgIHZhciBzZWxmID0gdGhpcztcclxuXHJcbiAgICAgICAgdGhpcy5vbkNoaWxkQWRkZWQgPSBmdW5jdGlvbiAoZWxlbWVudCkgeyAvKiBWaXJ0dWFsICovIH07XHJcbiAgICAgICAgdGhpcy5vbkRlc2NlbmRhbnRBZGRlZCA9IGZ1bmN0aW9uIChlbGVtZW50LCBwYXJlbnRFbGVtZW50KSB7IC8qIFZpcnR1YWwgKi8gfTtcclxuXHJcbiAgICAgICAgdGhpcy5zZXRDaGlsZHJlbiA9IGZ1bmN0aW9uIChjaGlsZHJlbikge1xyXG4gICAgICAgICAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW47XHJcbiAgICAgICAgICAgIF8odGhpcy5jaGlsZHJlbikuZWFjaChmdW5jdGlvbiAoY2hpbGQpIHtcclxuICAgICAgICAgICAgICAgIGNoaWxkLnNldFBhcmVudChzZWxmKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5zZXRDaGlsZHJlbihjaGlsZHJlbik7XHJcblxyXG4gICAgICAgIHRoaXMuZ2V0SXNTZWFsZWQgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfKHRoaXMuY2hpbGRyZW4pLmFueShmdW5jdGlvbiAoY2hpbGQpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBjaGlsZC5pc1RlbXBsYXRlZDtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdmFyIF9iYXNlU2V0SXNGb2N1c2VkID0gdGhpcy5zZXRJc0ZvY3VzZWQ7XHJcbiAgICAgICAgdGhpcy5zZXRJc0ZvY3VzZWQgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmdldElzU2VhbGVkKCkpXHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIF9iYXNlU2V0SXNGb2N1c2VkLmNhbGwodGhpcyk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5hZGRDaGlsZCA9IGZ1bmN0aW9uIChjaGlsZCkge1xyXG4gICAgICAgICAgICBpZiAoIV8odGhpcy5jaGlsZHJlbikuY29udGFpbnMoY2hpbGQpICYmIChfKHRoaXMuYWxsb3dlZENoaWxkVHlwZXMpLmNvbnRhaW5zKGNoaWxkLnR5cGUpIHx8IGNoaWxkLmlzQ29udGFpbmFibGUpKVxyXG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbi5wdXNoKGNoaWxkKTtcclxuICAgICAgICAgICAgY2hpbGQuc2V0RWRpdG9yKHRoaXMuZWRpdG9yKTtcclxuICAgICAgICAgICAgY2hpbGQuc2V0SXNUZW1wbGF0ZWQoZmFsc2UpO1xyXG4gICAgICAgICAgICBjaGlsZC5zZXRQYXJlbnQodGhpcyk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5kZWxldGVDaGlsZCA9IGZ1bmN0aW9uIChjaGlsZCkge1xyXG4gICAgICAgICAgICB2YXIgaW5kZXggPSBfKHRoaXMuY2hpbGRyZW4pLmluZGV4T2YoY2hpbGQpO1xyXG4gICAgICAgICAgICBpZiAoaW5kZXggPj0gMCkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbi5zcGxpY2UoaW5kZXgsIDEpO1xyXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkLmdldElzQWN0aXZlKCkpXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZGl0b3IuYWN0aXZlRWxlbWVudCA9IG51bGw7XHJcbiAgICAgICAgICAgICAgICBpZiAoY2hpbGQuZ2V0SXNGb2N1c2VkKCkpIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgZGVsZXRlZCBjaGlsZCB3YXMgZm9jdXNlZCwgdHJ5IHRvIHNldCBuZXcgZm9jdXMgdG8gdGhlIG1vc3QgYXBwcm9wcmlhdGUgc2libGluZyBvciBwYXJlbnQuXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuY2hpbGRyZW4ubGVuZ3RoID4gaW5kZXgpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2hpbGRyZW5baW5kZXhdLnNldElzRm9jdXNlZCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKGluZGV4ID4gMClcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbltpbmRleCAtIDFdLnNldElzRm9jdXNlZCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRJc0ZvY3VzZWQoKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMubW92ZUZvY3VzUHJldkNoaWxkID0gZnVuY3Rpb24gKGNoaWxkKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmNoaWxkcmVuLmxlbmd0aCA8IDIpXHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIHZhciBpbmRleCA9IF8odGhpcy5jaGlsZHJlbikuaW5kZXhPZihjaGlsZCk7XHJcbiAgICAgICAgICAgIGlmIChpbmRleCA+IDApXHJcbiAgICAgICAgICAgICAgICB0aGlzLmNoaWxkcmVuW2luZGV4IC0gMV0uc2V0SXNGb2N1c2VkKCk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5tb3ZlRm9jdXNOZXh0Q2hpbGQgPSBmdW5jdGlvbiAoY2hpbGQpIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuY2hpbGRyZW4ubGVuZ3RoIDwgMilcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgdmFyIGluZGV4ID0gXyh0aGlzLmNoaWxkcmVuKS5pbmRleE9mKGNoaWxkKTtcclxuICAgICAgICAgICAgaWYgKGluZGV4IDwgdGhpcy5jaGlsZHJlbi5sZW5ndGggLSAxKVxyXG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbltpbmRleCArIDFdLnNldElzRm9jdXNlZCgpO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuaW5zZXJ0Q2hpbGQgPSBmdW5jdGlvbiAoY2hpbGQsIGFmdGVyQ2hpbGQpIHtcclxuICAgICAgICAgICAgaWYgKCFfKHRoaXMuY2hpbGRyZW4pLmNvbnRhaW5zKGNoaWxkKSkge1xyXG4gICAgICAgICAgICAgICAgdmFyIGluZGV4ID0gTWF0aC5tYXgoXyh0aGlzLmNoaWxkcmVuKS5pbmRleE9mKGFmdGVyQ2hpbGQpLCAwKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuY2hpbGRyZW4uc3BsaWNlKGluZGV4ICsgMSwgMCwgY2hpbGQpO1xyXG4gICAgICAgICAgICAgICAgY2hpbGQuc2V0RWRpdG9yKHRoaXMuZWRpdG9yKTtcclxuICAgICAgICAgICAgICAgIGNoaWxkLnBhcmVudCA9IHRoaXM7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLm1vdmVDaGlsZFVwID0gZnVuY3Rpb24gKGNoaWxkKSB7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy5jYW5Nb3ZlQ2hpbGRVcChjaGlsZCkpXHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIHZhciBpbmRleCA9IF8odGhpcy5jaGlsZHJlbikuaW5kZXhPZihjaGlsZCk7XHJcbiAgICAgICAgICAgIHRoaXMuY2hpbGRyZW4ubW92ZShpbmRleCwgaW5kZXggLSAxKTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLm1vdmVDaGlsZERvd24gPSBmdW5jdGlvbiAoY2hpbGQpIHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLmNhbk1vdmVDaGlsZERvd24oY2hpbGQpKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB2YXIgaW5kZXggPSBfKHRoaXMuY2hpbGRyZW4pLmluZGV4T2YoY2hpbGQpO1xyXG4gICAgICAgICAgICB0aGlzLmNoaWxkcmVuLm1vdmUoaW5kZXgsIGluZGV4ICsgMSk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jYW5Nb3ZlQ2hpbGRVcCA9IGZ1bmN0aW9uIChjaGlsZCkge1xyXG4gICAgICAgICAgICB2YXIgaW5kZXggPSBfKHRoaXMuY2hpbGRyZW4pLmluZGV4T2YoY2hpbGQpO1xyXG4gICAgICAgICAgICByZXR1cm4gaW5kZXggPiAwO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuY2FuTW92ZUNoaWxkRG93biA9IGZ1bmN0aW9uIChjaGlsZCkge1xyXG4gICAgICAgICAgICB2YXIgaW5kZXggPSBfKHRoaXMuY2hpbGRyZW4pLmluZGV4T2YoY2hpbGQpO1xyXG4gICAgICAgICAgICByZXR1cm4gaW5kZXggPCB0aGlzLmNoaWxkcmVuLmxlbmd0aCAtIDE7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jaGlsZHJlblRvT2JqZWN0ID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gXyh0aGlzLmNoaWxkcmVuKS5tYXAoZnVuY3Rpb24gKGNoaWxkKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gY2hpbGQudG9PYmplY3QoKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5nZXRJbm5lclRleHQgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfKHRoaXMuY2hpbGRyZW4pLnJlZHVjZShmdW5jdGlvbiAobWVtbywgY2hpbGQpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBtZW1vICsgXCJcXG5cIiArIGNoaWxkLmdldElubmVyVGV4dCgpO1xyXG4gICAgICAgICAgICB9LCBcIlwiKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMucGFzdGUgPSBmdW5jdGlvbiAoY2xpcGJvYXJkRGF0YSkge1xyXG4gICAgICAgICAgICB2YXIganNvbiA9IGNsaXBib2FyZERhdGEuZ2V0RGF0YShcInRleHQvanNvblwiKTtcclxuICAgICAgICAgICAgaWYgKCEhanNvbikge1xyXG4gICAgICAgICAgICAgICAgdmFyIGRhdGEgPSBKU09OLnBhcnNlKGpzb24pO1xyXG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gTGF5b3V0RWRpdG9yLmVsZW1lbnRGcm9tKGRhdGEpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5wYXN0ZUNoaWxkKGNoaWxkKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMucGFzdGVDaGlsZCA9IGZ1bmN0aW9uIChjaGlsZCkge1xyXG4gICAgICAgICAgICBpZiAoXyh0aGlzLmFsbG93ZWRDaGlsZFR5cGVzKS5jb250YWlucyhjaGlsZC50eXBlKSB8fCBjaGlsZC5pc0NvbnRhaW5hYmxlKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmFkZENoaWxkKGNoaWxkKTtcclxuICAgICAgICAgICAgICAgIGNoaWxkLnNldElzRm9jdXNlZCgpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2UgaWYgKCEhdGhpcy5wYXJlbnQpXHJcbiAgICAgICAgICAgICAgICB0aGlzLnBhcmVudC5wYXN0ZUNoaWxkKGNoaWxkKTtcclxuICAgICAgICB9XHJcbiAgICB9O1xyXG5cclxufSkoTGF5b3V0RWRpdG9yIHx8IChMYXlvdXRFZGl0b3IgPSB7fSkpOyIsInZhciBMYXlvdXRFZGl0b3I7XHJcbihmdW5jdGlvbiAoTGF5b3V0RWRpdG9yKSB7XHJcblxyXG4gICAgTGF5b3V0RWRpdG9yLkNhbnZhcyA9IGZ1bmN0aW9uIChkYXRhLCBodG1sSWQsIGh0bWxDbGFzcywgaHRtbFN0eWxlLCBpc1RlbXBsYXRlZCwgcnVsZSwgY2hpbGRyZW4pIHtcclxuICAgICAgICBMYXlvdXRFZGl0b3IuRWxlbWVudC5jYWxsKHRoaXMsIFwiQ2FudmFzXCIsIGRhdGEsIGh0bWxJZCwgaHRtbENsYXNzLCBodG1sU3R5bGUsIGlzVGVtcGxhdGVkLCBydWxlKTtcclxuICAgICAgICBMYXlvdXRFZGl0b3IuQ29udGFpbmVyLmNhbGwodGhpcywgW1wiQ2FudmFzXCIsIFwiR3JpZFwiLCBcIkNvbnRlbnRcIl0sIGNoaWxkcmVuKTtcclxuXHJcbiAgICAgICAgdGhpcy5pc0NvbnRhaW5hYmxlID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgdGhpcy50b09iamVjdCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHRoaXMuZWxlbWVudFRvT2JqZWN0KCk7XHJcbiAgICAgICAgICAgIHJlc3VsdC5jaGlsZHJlbiA9IHRoaXMuY2hpbGRyZW5Ub09iamVjdCgpO1xyXG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgICAgIH07XHJcbiAgICB9O1xyXG5cclxuICAgIExheW91dEVkaXRvci5DYW52YXMuZnJvbSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xyXG4gICAgICAgIHZhciByZXN1bHQgPSBuZXcgTGF5b3V0RWRpdG9yLkNhbnZhcyhcclxuICAgICAgICAgICAgdmFsdWUuZGF0YSxcclxuICAgICAgICAgICAgdmFsdWUuaHRtbElkLFxyXG4gICAgICAgICAgICB2YWx1ZS5odG1sQ2xhc3MsXHJcbiAgICAgICAgICAgIHZhbHVlLmh0bWxTdHlsZSxcclxuICAgICAgICAgICAgdmFsdWUuaXNUZW1wbGF0ZWQsXHJcbiAgICAgICAgICAgIHZhbHVlLnJ1bGUsXHJcbiAgICAgICAgICAgIExheW91dEVkaXRvci5jaGlsZHJlbkZyb20odmFsdWUuY2hpbGRyZW4pKTtcclxuXHJcbiAgICAgICAgcmVzdWx0LnRvb2xib3hJY29uID0gdmFsdWUudG9vbGJveEljb247XHJcbiAgICAgICAgcmVzdWx0LnRvb2xib3hMYWJlbCA9IHZhbHVlLnRvb2xib3hMYWJlbDtcclxuICAgICAgICByZXN1bHQudG9vbGJveERlc2NyaXB0aW9uID0gdmFsdWUudG9vbGJveERlc2NyaXB0aW9uO1xyXG5cclxuICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgfTtcclxuXHJcbn0pKExheW91dEVkaXRvciB8fCAoTGF5b3V0RWRpdG9yID0ge30pKTtcclxuIiwidmFyIExheW91dEVkaXRvcjtcclxuKGZ1bmN0aW9uIChMYXlvdXRFZGl0b3IpIHtcclxuXHJcbiAgICBMYXlvdXRFZGl0b3IuR3JpZCA9IGZ1bmN0aW9uIChkYXRhLCBodG1sSWQsIGh0bWxDbGFzcywgaHRtbFN0eWxlLCBpc1RlbXBsYXRlZCwgcnVsZSwgY2hpbGRyZW4pIHtcclxuICAgICAgICBMYXlvdXRFZGl0b3IuRWxlbWVudC5jYWxsKHRoaXMsIFwiR3JpZFwiLCBkYXRhLCBodG1sSWQsIGh0bWxDbGFzcywgaHRtbFN0eWxlLCBpc1RlbXBsYXRlZCwgcnVsZSk7XHJcbiAgICAgICAgTGF5b3V0RWRpdG9yLkNvbnRhaW5lci5jYWxsKHRoaXMsIFtcIlJvd1wiXSwgY2hpbGRyZW4pO1xyXG5cclxuICAgICAgICB0aGlzLnRvT2JqZWN0ID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gdGhpcy5lbGVtZW50VG9PYmplY3QoKTtcclxuICAgICAgICAgICAgcmVzdWx0LmNoaWxkcmVuID0gdGhpcy5jaGlsZHJlblRvT2JqZWN0KCk7XHJcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICAgICAgfTtcclxuICAgIH07XHJcblxyXG4gICAgTGF5b3V0RWRpdG9yLkdyaWQuZnJvbSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xyXG4gICAgICAgIHZhciByZXN1bHQgPSBuZXcgTGF5b3V0RWRpdG9yLkdyaWQoXHJcbiAgICAgICAgICAgIHZhbHVlLmRhdGEsXHJcbiAgICAgICAgICAgIHZhbHVlLmh0bWxJZCxcclxuICAgICAgICAgICAgdmFsdWUuaHRtbENsYXNzLFxyXG4gICAgICAgICAgICB2YWx1ZS5odG1sU3R5bGUsXHJcbiAgICAgICAgICAgIHZhbHVlLmlzVGVtcGxhdGVkLFxyXG4gICAgICAgICAgICB2YWx1ZS5ydWxlLFxyXG4gICAgICAgICAgICBMYXlvdXRFZGl0b3IuY2hpbGRyZW5Gcm9tKHZhbHVlLmNoaWxkcmVuKSk7XHJcbiAgICAgICAgcmVzdWx0LnRvb2xib3hJY29uID0gdmFsdWUudG9vbGJveEljb247XHJcbiAgICAgICAgcmVzdWx0LnRvb2xib3hMYWJlbCA9IHZhbHVlLnRvb2xib3hMYWJlbDtcclxuICAgICAgICByZXN1bHQudG9vbGJveERlc2NyaXB0aW9uID0gdmFsdWUudG9vbGJveERlc2NyaXB0aW9uO1xyXG4gICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICB9O1xyXG5cclxufSkoTGF5b3V0RWRpdG9yIHx8IChMYXlvdXRFZGl0b3IgPSB7fSkpOyIsInZhciBMYXlvdXRFZGl0b3I7XHJcbihmdW5jdGlvbiAoTGF5b3V0RWRpdG9yKSB7XHJcblxyXG4gICAgTGF5b3V0RWRpdG9yLlJvdyA9IGZ1bmN0aW9uIChkYXRhLCBodG1sSWQsIGh0bWxDbGFzcywgaHRtbFN0eWxlLCBpc1RlbXBsYXRlZCwgcnVsZSwgY2hpbGRyZW4pIHtcclxuICAgICAgICBMYXlvdXRFZGl0b3IuRWxlbWVudC5jYWxsKHRoaXMsIFwiUm93XCIsIGRhdGEsIGh0bWxJZCwgaHRtbENsYXNzLCBodG1sU3R5bGUsIGlzVGVtcGxhdGVkLCBydWxlKTtcclxuICAgICAgICBMYXlvdXRFZGl0b3IuQ29udGFpbmVyLmNhbGwodGhpcywgW1wiQ29sdW1uXCJdLCBjaGlsZHJlbik7XHJcblxyXG4gICAgICAgIHZhciBfc2VsZiA9IHRoaXM7XHJcblxyXG4gICAgICAgIGZ1bmN0aW9uIF9nZXRUb3RhbENvbHVtbnNXaWR0aCgpIHtcclxuICAgICAgICAgICAgcmV0dXJuIF8oX3NlbGYuY2hpbGRyZW4pLnJlZHVjZShmdW5jdGlvbiAobWVtbywgY2hpbGQpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBtZW1vICsgY2hpbGQub2Zmc2V0ICsgY2hpbGQud2lkdGg7XHJcbiAgICAgICAgICAgIH0sIDApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gSW1wbGVtZW50cyBhIHNpbXBsZSBhbGdvcml0aG0gdG8gZGlzdHJpYnV0ZSBzcGFjZSAoZWl0aGVyIHBvc2l0aXZlIG9yIG5lZ2F0aXZlKVxyXG4gICAgICAgIC8vIGJldHdlZW4gdGhlIGNoaWxkIGNvbHVtbnMgb2YgdGhlIHJvdy4gTmVnYXRpdmUgc3BhY2UgaXMgZGlzdHJpYnV0ZWQgd2hlbiBtYWtpbmdcclxuICAgICAgICAvLyByb29tIGZvciBhIG5ldyBjb2x1bW4gKGUuYy4gY2xpcGJvYXJkIHBhc3RlIG9yIGRyb3BwaW5nIGZyb20gdGhlIHRvb2xib3gpIHdoaWxlXHJcbiAgICAgICAgLy8gcG9zaXRpdmUgc3BhY2UgaXMgZGlzdHJpYnV0ZWQgd2hlbiBmaWxsaW5nIHRoZSBncmFwIG9mIGEgcmVtb3ZlZCBjb2x1bW4uXHJcbiAgICAgICAgZnVuY3Rpb24gX2Rpc3RyaWJ1dGVTcGFjZShzcGFjZSkge1xyXG4gICAgICAgICAgICBpZiAoc3BhY2UgPT0gMClcclxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIHZhciB1bmRpc3RyaWJ1dGVkU3BhY2UgPSBzcGFjZTtcclxuXHJcbiAgICAgICAgICAgIGlmICh1bmRpc3RyaWJ1dGVkU3BhY2UgPCAwKSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgdmFjYW50U3BhY2UgPSAxMiAtIF9nZXRUb3RhbENvbHVtbnNXaWR0aCgpO1xyXG4gICAgICAgICAgICAgICAgdW5kaXN0cmlidXRlZFNwYWNlICs9IHZhY2FudFNwYWNlO1xyXG4gICAgICAgICAgICAgICAgaWYgKHVuZGlzdHJpYnV0ZWRTcGFjZSA+IDApXHJcbiAgICAgICAgICAgICAgICAgICAgdW5kaXN0cmlidXRlZFNwYWNlID0gMDtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gSWYgc3BhY2UgaXMgbmVnYXRpdmUsIHRyeSB0byBkZWNyZWFzZSBvZmZzZXRzIGZpcnN0LlxyXG4gICAgICAgICAgICB3aGlsZSAodW5kaXN0cmlidXRlZFNwYWNlIDwgMCAmJiBfKF9zZWxmLmNoaWxkcmVuKS5hbnkoZnVuY3Rpb24gKGNvbHVtbikgeyByZXR1cm4gY29sdW1uLm9mZnNldCA+IDA7IH0pKSB7IC8vIFdoaWxlIHRoZXJlIGlzIHN0aWxsIG9mZnNldCBsZWZ0IHRvIHJlbW92ZS5cclxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBfc2VsZi5jaGlsZHJlbi5sZW5ndGggJiYgdW5kaXN0cmlidXRlZFNwYWNlIDwgMDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNvbHVtbiA9IF9zZWxmLmNoaWxkcmVuW2ldO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChjb2x1bW4ub2Zmc2V0ID4gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb2x1bW4ub2Zmc2V0LS07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHVuZGlzdHJpYnV0ZWRTcGFjZSsrO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgZnVuY3Rpb24gaGFzV2lkdGgoY29sdW1uKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAodW5kaXN0cmlidXRlZFNwYWNlID4gMClcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29sdW1uLndpZHRoIDwgMTI7XHJcbiAgICAgICAgICAgICAgICBlbHNlIGlmICh1bmRpc3RyaWJ1dGVkU3BhY2UgPCAwKVxyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjb2x1bW4ud2lkdGggPiAxO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBUcnkgdG8gZGlzdHJpYnV0ZSByZW1haW5pbmcgc3BhY2UgKGNvdWxkIGJlIG5lZ2F0aXZlIG9yIHBvc2l0aXZlKSB1c2luZyB3aWR0aHMuXHJcbiAgICAgICAgICAgIHdoaWxlICh1bmRpc3RyaWJ1dGVkU3BhY2UgIT0gMCkge1xyXG4gICAgICAgICAgICAgICAgLy8gQW55IG1vcmUgY29sdW1uIHdpZHRoIGF2YWlsYWJsZSBmb3IgZGlzdHJpYnV0aW9uP1xyXG4gICAgICAgICAgICAgICAgaWYgKCFfKF9zZWxmLmNoaWxkcmVuKS5hbnkoaGFzV2lkdGgpKVxyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IF9zZWxmLmNoaWxkcmVuLmxlbmd0aCAmJiB1bmRpc3RyaWJ1dGVkU3BhY2UgIT0gMDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNvbHVtbiA9IF9zZWxmLmNoaWxkcmVuW2kgJSBfc2VsZi5jaGlsZHJlbi5sZW5ndGhdO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChoYXNXaWR0aChjb2x1bW4pKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkZWx0YSA9IHVuZGlzdHJpYnV0ZWRTcGFjZSAvIE1hdGguYWJzKHVuZGlzdHJpYnV0ZWRTcGFjZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbHVtbi53aWR0aCArPSBkZWx0YTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdW5kaXN0cmlidXRlZFNwYWNlIC09IGRlbHRhO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0gICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHJldHVybiB1bmRpc3RyaWJ1dGVkU3BhY2UgPT0gMDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHZhciBfaXNBZGRpbmdDb2x1bW4gPSBmYWxzZTtcclxuXHJcbiAgICAgICAgdGhpcy5jYW5BZGRDb2x1bW4gPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNoaWxkcmVuLmxlbmd0aCA8IDEyO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuYmVnaW5BZGRDb2x1bW4gPSBmdW5jdGlvbiAobmV3Q29sdW1uV2lkdGgpIHtcclxuICAgICAgICAgICAgaWYgKCEhX2lzQWRkaW5nQ29sdW1uKVxyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ29sdW1uIGFkZCBvcGVyYXRpb24gaXMgYWxyZWFkeSBpbiBwcm9ncmVzcy5cIilcclxuICAgICAgICAgICAgXyh0aGlzLmNoaWxkcmVuKS5lYWNoKGZ1bmN0aW9uIChjb2x1bW4pIHtcclxuICAgICAgICAgICAgICAgIGNvbHVtbi5iZWdpbkNoYW5nZSgpO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgaWYgKF9kaXN0cmlidXRlU3BhY2UoLW5ld0NvbHVtbldpZHRoKSkge1xyXG4gICAgICAgICAgICAgICAgX2lzQWRkaW5nQ29sdW1uID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIF8odGhpcy5jaGlsZHJlbikuZWFjaChmdW5jdGlvbiAoY29sdW1uKSB7XHJcbiAgICAgICAgICAgICAgICBjb2x1bW4ucm9sbGJhY2tDaGFuZ2UoKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLmNvbW1pdEFkZENvbHVtbiA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKCFfaXNBZGRpbmdDb2x1bW4pXHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBjb2x1bW4gYWRkIG9wZXJhdGlvbiBpbiBwcm9ncmVzcy5cIilcclxuICAgICAgICAgICAgXyh0aGlzLmNoaWxkcmVuKS5lYWNoKGZ1bmN0aW9uIChjb2x1bW4pIHtcclxuICAgICAgICAgICAgICAgIGNvbHVtbi5jb21taXRDaGFuZ2UoKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIF9pc0FkZGluZ0NvbHVtbiA9IGZhbHNlO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMucm9sbGJhY2tBZGRDb2x1bW4gPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmICghX2lzQWRkaW5nQ29sdW1uKVxyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gY29sdW1uIGFkZCBvcGVyYXRpb24gaW4gcHJvZ3Jlc3MuXCIpXHJcbiAgICAgICAgICAgIF8odGhpcy5jaGlsZHJlbikuZWFjaChmdW5jdGlvbiAoY29sdW1uKSB7XHJcbiAgICAgICAgICAgICAgICBjb2x1bW4ucm9sbGJhY2tDaGFuZ2UoKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIF9pc0FkZGluZ0NvbHVtbiA9IGZhbHNlO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHZhciBfYmFzZURlbGV0ZUNoaWxkID0gdGhpcy5kZWxldGVDaGlsZDtcclxuICAgICAgICB0aGlzLmRlbGV0ZUNoaWxkID0gZnVuY3Rpb24gKGNvbHVtbikgeyBcclxuICAgICAgICAgICAgdmFyIHdpZHRoID0gY29sdW1uLndpZHRoO1xyXG4gICAgICAgICAgICBfYmFzZURlbGV0ZUNoaWxkLmNhbGwodGhpcywgY29sdW1uKTtcclxuICAgICAgICAgICAgX2Rpc3RyaWJ1dGVTcGFjZSh3aWR0aCk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jYW5Db250cmFjdENvbHVtblJpZ2h0ID0gZnVuY3Rpb24gKGNvbHVtbiwgY29ubmVjdEFkamFjZW50KSB7XHJcbiAgICAgICAgICAgIHZhciBpbmRleCA9IF8odGhpcy5jaGlsZHJlbikuaW5kZXhPZihjb2x1bW4pO1xyXG4gICAgICAgICAgICBpZiAoaW5kZXggPj0gMClcclxuICAgICAgICAgICAgICAgIHJldHVybiBjb2x1bW4ud2lkdGggPiAxO1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jb250cmFjdENvbHVtblJpZ2h0ID0gZnVuY3Rpb24gKGNvbHVtbiwgY29ubmVjdEFkamFjZW50KSB7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy5jYW5Db250cmFjdENvbHVtblJpZ2h0KGNvbHVtbiwgY29ubmVjdEFkamFjZW50KSlcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgICAgIHZhciBpbmRleCA9IF8odGhpcy5jaGlsZHJlbikuaW5kZXhPZihjb2x1bW4pO1xyXG4gICAgICAgICAgICBpZiAoaW5kZXggPj0gMCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKGNvbHVtbi53aWR0aCA+IDEpIHtcclxuICAgICAgICAgICAgICAgICAgICBjb2x1bW4ud2lkdGgtLTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5jaGlsZHJlbi5sZW5ndGggPiBpbmRleCArIDEpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5leHRDb2x1bW4gPSB0aGlzLmNoaWxkcmVuW2luZGV4ICsgMV07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb25uZWN0QWRqYWNlbnQgJiYgbmV4dENvbHVtbi5vZmZzZXQgPT0gMClcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5leHRDb2x1bW4ud2lkdGgrKztcclxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV4dENvbHVtbi5vZmZzZXQrKztcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLmNhbkV4cGFuZENvbHVtblJpZ2h0ID0gZnVuY3Rpb24gKGNvbHVtbiwgY29ubmVjdEFkamFjZW50KSB7XHJcbiAgICAgICAgICAgIHZhciBpbmRleCA9IF8odGhpcy5jaGlsZHJlbikuaW5kZXhPZihjb2x1bW4pO1xyXG4gICAgICAgICAgICBpZiAoaW5kZXggPj0gMCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKGNvbHVtbi53aWR0aCA+PSAxMilcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jaGlsZHJlbi5sZW5ndGggPiBpbmRleCArIDEpIHtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dENvbHVtbiA9IHRoaXMuY2hpbGRyZW5baW5kZXggKyAxXTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoY29ubmVjdEFkamFjZW50ICYmIG5leHRDb2x1bW4ub2Zmc2V0ID09IDApXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXh0Q29sdW1uLndpZHRoID4gMTtcclxuICAgICAgICAgICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXh0Q29sdW1uLm9mZnNldCA+IDA7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gX2dldFRvdGFsQ29sdW1uc1dpZHRoKCkgPCAxMjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5leHBhbmRDb2x1bW5SaWdodCA9IGZ1bmN0aW9uIChjb2x1bW4sIGNvbm5lY3RBZGphY2VudCkge1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMuY2FuRXhwYW5kQ29sdW1uUmlnaHQoY29sdW1uLCBjb25uZWN0QWRqYWNlbnQpKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICAgICAgdmFyIGluZGV4ID0gXyh0aGlzLmNoaWxkcmVuKS5pbmRleE9mKGNvbHVtbik7XHJcbiAgICAgICAgICAgIGlmIChpbmRleCA+PSAwKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jaGlsZHJlbi5sZW5ndGggPiBpbmRleCArIDEpIHtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dENvbHVtbiA9IHRoaXMuY2hpbGRyZW5baW5kZXggKyAxXTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoY29ubmVjdEFkamFjZW50ICYmIG5leHRDb2x1bW4ub2Zmc2V0ID09IDApXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG5leHRDb2x1bW4ud2lkdGgtLTtcclxuICAgICAgICAgICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG5leHRDb2x1bW4ub2Zmc2V0LS07XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBjb2x1bW4ud2lkdGgrKztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuY2FuRXhwYW5kQ29sdW1uTGVmdCA9IGZ1bmN0aW9uIChjb2x1bW4sIGNvbm5lY3RBZGphY2VudCkge1xyXG4gICAgICAgICAgICB2YXIgaW5kZXggPSBfKHRoaXMuY2hpbGRyZW4pLmluZGV4T2YoY29sdW1uKTtcclxuICAgICAgICAgICAgaWYgKGluZGV4ID49IDApIHtcclxuICAgICAgICAgICAgICAgIGlmIChjb2x1bW4ud2lkdGggPj0gMTIpXHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgaWYgKGluZGV4ID4gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2Q29sdW1uID0gdGhpcy5jaGlsZHJlbltpbmRleCAtIDFdO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChjb25uZWN0QWRqYWNlbnQgJiYgY29sdW1uLm9mZnNldCA9PSAwKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcHJldkNvbHVtbi53aWR0aCA+IDE7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gY29sdW1uLm9mZnNldCA+IDA7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuZXhwYW5kQ29sdW1uTGVmdCA9IGZ1bmN0aW9uIChjb2x1bW4sIGNvbm5lY3RBZGphY2VudCkge1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMuY2FuRXhwYW5kQ29sdW1uTGVmdChjb2x1bW4sIGNvbm5lY3RBZGphY2VudCkpXHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgICAgICB2YXIgaW5kZXggPSBfKHRoaXMuY2hpbGRyZW4pLmluZGV4T2YoY29sdW1uKTtcclxuICAgICAgICAgICAgaWYgKGluZGV4ID49IDApIHtcclxuICAgICAgICAgICAgICAgIGlmIChpbmRleCA+IDApIHtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgcHJldkNvbHVtbiA9IHRoaXMuY2hpbGRyZW5baW5kZXggLSAxXTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoY29ubmVjdEFkamFjZW50ICYmIGNvbHVtbi5vZmZzZXQgPT0gMClcclxuICAgICAgICAgICAgICAgICAgICAgICAgcHJldkNvbHVtbi53aWR0aC0tO1xyXG4gICAgICAgICAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29sdW1uLm9mZnNldC0tO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbi5vZmZzZXQtLTtcclxuICAgICAgICAgICAgICAgIGNvbHVtbi53aWR0aCsrO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jYW5Db250cmFjdENvbHVtbkxlZnQgPSBmdW5jdGlvbiAoY29sdW1uLCBjb25uZWN0QWRqYWNlbnQpIHtcclxuICAgICAgICAgICAgdmFyIGluZGV4ID0gXyh0aGlzLmNoaWxkcmVuKS5pbmRleE9mKGNvbHVtbik7XHJcbiAgICAgICAgICAgIGlmIChpbmRleCA+PSAwKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvbHVtbi53aWR0aCA+IDE7XHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLmNvbnRyYWN0Q29sdW1uTGVmdCA9IGZ1bmN0aW9uIChjb2x1bW4sIGNvbm5lY3RBZGphY2VudCkge1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMuY2FuQ29udHJhY3RDb2x1bW5MZWZ0KGNvbHVtbiwgY29ubmVjdEFkamFjZW50KSlcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgICAgIHZhciBpbmRleCA9IF8odGhpcy5jaGlsZHJlbikuaW5kZXhPZihjb2x1bW4pO1xyXG4gICAgICAgICAgICBpZiAoaW5kZXggPj0gMCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKGluZGV4ID4gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2Q29sdW1uID0gdGhpcy5jaGlsZHJlbltpbmRleCAtIDFdO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChjb25uZWN0QWRqYWNlbnQgJiYgY29sdW1uLm9mZnNldCA9PSAwKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2Q29sdW1uLndpZHRoKys7XHJcbiAgICAgICAgICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb2x1bW4ub2Zmc2V0Kys7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uLm9mZnNldCsrO1xyXG4gICAgICAgICAgICAgICAgY29sdW1uLndpZHRoLS07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLmV2ZW5Db2x1bW5zID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5jaGlsZHJlbi5sZW5ndGggPT0gMClcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgICAgIHZhciBldmVuV2lkdGggPSBNYXRoLmZsb29yKDEyIC8gdGhpcy5jaGlsZHJlbi5sZW5ndGgpO1xyXG4gICAgICAgICAgICBfKHRoaXMuY2hpbGRyZW4pLmVhY2goZnVuY3Rpb24gKGNvbHVtbikge1xyXG4gICAgICAgICAgICAgICAgY29sdW1uLndpZHRoID0gZXZlbldpZHRoO1xyXG4gICAgICAgICAgICAgICAgY29sdW1uLm9mZnNldCA9IDA7XHJcbiAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgdmFyIHJlc3QgPSAxMiAlIHRoaXMuY2hpbGRyZW4ubGVuZ3RoO1xyXG4gICAgICAgICAgICBpZiAocmVzdCA+IDApXHJcbiAgICAgICAgICAgICAgICBfZGlzdHJpYnV0ZVNwYWNlKHJlc3QpO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHZhciBfYmFzZVBhc3RlQ2hpbGQgPSB0aGlzLnBhc3RlQ2hpbGQ7XHJcbiAgICAgICAgdGhpcy5wYXN0ZUNoaWxkID0gZnVuY3Rpb24gKGNoaWxkKSB7XHJcbiAgICAgICAgICAgIGlmIChjaGlsZC50eXBlID09IFwiQ29sdW1uXCIpIHtcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmJlZ2luQWRkQ29sdW1uKGNoaWxkLndpZHRoKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29tbWl0QWRkQ29sdW1uKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgX2Jhc2VQYXN0ZUNoaWxkLmNhbGwodGhpcywgY2hpbGQpXHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSBpZiAoISF0aGlzLnBhcmVudClcclxuICAgICAgICAgICAgICAgIHRoaXMucGFyZW50LnBhc3RlQ2hpbGQoY2hpbGQpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy50b09iamVjdCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHRoaXMuZWxlbWVudFRvT2JqZWN0KCk7XHJcbiAgICAgICAgICAgIHJlc3VsdC5jaGlsZHJlbiA9IHRoaXMuY2hpbGRyZW5Ub09iamVjdCgpO1xyXG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgICAgIH07XHJcbiAgICB9O1xyXG5cclxuICAgIExheW91dEVkaXRvci5Sb3cuZnJvbSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xyXG4gICAgICAgIHZhciByZXN1bHQgPSBuZXcgTGF5b3V0RWRpdG9yLlJvdyhcclxuICAgICAgICAgICAgdmFsdWUuZGF0YSxcclxuICAgICAgICAgICAgdmFsdWUuaHRtbElkLFxyXG4gICAgICAgICAgICB2YWx1ZS5odG1sQ2xhc3MsXHJcbiAgICAgICAgICAgIHZhbHVlLmh0bWxTdHlsZSxcclxuICAgICAgICAgICAgdmFsdWUuaXNUZW1wbGF0ZWQsXHJcbiAgICAgICAgICAgIHZhbHVlLnJ1bGUsXHJcbiAgICAgICAgICAgIExheW91dEVkaXRvci5jaGlsZHJlbkZyb20odmFsdWUuY2hpbGRyZW4pKTtcclxuICAgICAgICByZXN1bHQudG9vbGJveEljb24gPSB2YWx1ZS50b29sYm94SWNvbjtcclxuICAgICAgICByZXN1bHQudG9vbGJveExhYmVsID0gdmFsdWUudG9vbGJveExhYmVsO1xyXG4gICAgICAgIHJlc3VsdC50b29sYm94RGVzY3JpcHRpb24gPSB2YWx1ZS50b29sYm94RGVzY3JpcHRpb247XHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgIH07XHJcblxyXG59KShMYXlvdXRFZGl0b3IgfHwgKExheW91dEVkaXRvciA9IHt9KSk7IiwidmFyIExheW91dEVkaXRvcjtcclxuKGZ1bmN0aW9uIChMYXlvdXRFZGl0b3IpIHtcclxuICAgIExheW91dEVkaXRvci5Db2x1bW4gPSBmdW5jdGlvbiAoZGF0YSwgaHRtbElkLCBodG1sQ2xhc3MsIGh0bWxTdHlsZSwgaXNUZW1wbGF0ZWQsIHdpZHRoLCBvZmZzZXQsIGNvbGxhcHNpYmxlLCBydWxlLCBjaGlsZHJlbikge1xyXG4gICAgICAgIExheW91dEVkaXRvci5FbGVtZW50LmNhbGwodGhpcywgXCJDb2x1bW5cIiwgZGF0YSwgaHRtbElkLCBodG1sQ2xhc3MsIGh0bWxTdHlsZSwgaXNUZW1wbGF0ZWQsIHJ1bGUpO1xyXG4gICAgICAgIExheW91dEVkaXRvci5Db250YWluZXIuY2FsbCh0aGlzLCBbXCJHcmlkXCIsIFwiQ29udGVudFwiXSwgY2hpbGRyZW4pO1xyXG5cclxuICAgICAgICB0aGlzLndpZHRoID0gd2lkdGg7XHJcbiAgICAgICAgdGhpcy5vZmZzZXQgPSBvZmZzZXQ7XHJcbiAgICAgICAgdGhpcy5jb2xsYXBzaWJsZSA9IGNvbGxhcHNpYmxlO1xyXG5cclxuICAgICAgICB2YXIgX2hhc1BlbmRpbmdDaGFuZ2UgPSBmYWxzZTtcclxuICAgICAgICB2YXIgX29yaWdXaWR0aCA9IDA7XHJcbiAgICAgICAgdmFyIF9vcmlnT2Zmc2V0ID0gMDtcclxuXHJcbiAgICAgICAgdGhpcy5iZWdpbkNoYW5nZSA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKCEhX2hhc1BlbmRpbmdDaGFuZ2UpXHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb2x1bW4gYWxyZWFkeSBoYXMgYSBwZW5kaW5nIGNoYW5nZS5cIik7XHJcbiAgICAgICAgICAgIF9oYXNQZW5kaW5nQ2hhbmdlID0gdHJ1ZTtcclxuICAgICAgICAgICAgX29yaWdXaWR0aCA9IHRoaXMud2lkdGg7XHJcbiAgICAgICAgICAgIF9vcmlnT2Zmc2V0ID0gdGhpcy5vZmZzZXQ7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jb21taXRDaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmICghX2hhc1BlbmRpbmdDaGFuZ2UpXHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb2x1bW4gaGFzIG5vIHBlbmRpbmcgY2hhbmdlLlwiKTtcclxuICAgICAgICAgICAgX29yaWdXaWR0aCA9IDA7XHJcbiAgICAgICAgICAgIF9vcmlnT2Zmc2V0ID0gMDtcclxuICAgICAgICAgICAgX2hhc1BlbmRpbmdDaGFuZ2UgPSBmYWxzZTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLnJvbGxiYWNrQ2hhbmdlID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICBpZiAoIV9oYXNQZW5kaW5nQ2hhbmdlKVxyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ29sdW1uIGhhcyBubyBwZW5kaW5nIGNoYW5nZS5cIik7XHJcbiAgICAgICAgICAgIHRoaXMud2lkdGggPSBfb3JpZ1dpZHRoO1xyXG4gICAgICAgICAgICB0aGlzLm9mZnNldCA9IF9vcmlnT2Zmc2V0O1xyXG4gICAgICAgICAgICBfb3JpZ1dpZHRoID0gMDtcclxuICAgICAgICAgICAgX29yaWdPZmZzZXQgPSAwO1xyXG4gICAgICAgICAgICBfaGFzUGVuZGluZ0NoYW5nZSA9IGZhbHNlO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuY2FuU3BsaXQgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmlzVGVtcGxhdGVkKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy53aWR0aCA+IDE7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5zcGxpdCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLmNhblNwbGl0KCkpXHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgICAgICB2YXIgbmV3Q29sdW1uV2lkdGggPSBNYXRoLmZsb29yKHRoaXMud2lkdGggLyAyKTtcclxuICAgICAgICAgICAgdmFyIG5ld0NvbHVtbiA9IExheW91dEVkaXRvci5Db2x1bW4uZnJvbSh7XHJcbiAgICAgICAgICAgICAgICBkYXRhOiBudWxsLFxyXG4gICAgICAgICAgICAgICAgaHRtbElkOiBudWxsLFxyXG4gICAgICAgICAgICAgICAgaHRtbENsYXNzOiBudWxsLFxyXG4gICAgICAgICAgICAgICAgaHRtbFN0eWxlOiBudWxsLFxyXG4gICAgICAgICAgICAgICAgd2lkdGg6IG5ld0NvbHVtbldpZHRoLFxyXG4gICAgICAgICAgICAgICAgb2Zmc2V0OiAwLFxyXG4gICAgICAgICAgICAgICAgY2hpbGRyZW46IFtdXHJcbiAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgdGhpcy53aWR0aCA9IHRoaXMud2lkdGggLSBuZXdDb2x1bW5XaWR0aDtcclxuICAgICAgICAgICAgdGhpcy5wYXJlbnQuaW5zZXJ0Q2hpbGQobmV3Q29sdW1uLCB0aGlzKTtcclxuICAgICAgICAgICAgbmV3Q29sdW1uLnNldElzRm9jdXNlZCgpO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuY2FuQ29udHJhY3RSaWdodCA9IGZ1bmN0aW9uIChjb25uZWN0QWRqYWNlbnQpIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuaXNUZW1wbGF0ZWQpXHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnBhcmVudC5jYW5Db250cmFjdENvbHVtblJpZ2h0KHRoaXMsIGNvbm5lY3RBZGphY2VudCk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jb250cmFjdFJpZ2h0ID0gZnVuY3Rpb24gKGNvbm5lY3RBZGphY2VudCkge1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMuY2FuQ29udHJhY3RSaWdodChjb25uZWN0QWRqYWNlbnQpKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB0aGlzLnBhcmVudC5jb250cmFjdENvbHVtblJpZ2h0KHRoaXMsIGNvbm5lY3RBZGphY2VudCk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jYW5FeHBhbmRSaWdodCA9IGZ1bmN0aW9uIChjb25uZWN0QWRqYWNlbnQpIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuaXNUZW1wbGF0ZWQpXHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnBhcmVudC5jYW5FeHBhbmRDb2x1bW5SaWdodCh0aGlzLCBjb25uZWN0QWRqYWNlbnQpO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuZXhwYW5kUmlnaHQgPSBmdW5jdGlvbiAoY29ubmVjdEFkamFjZW50KSB7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy5jYW5FeHBhbmRSaWdodChjb25uZWN0QWRqYWNlbnQpKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB0aGlzLnBhcmVudC5leHBhbmRDb2x1bW5SaWdodCh0aGlzLCBjb25uZWN0QWRqYWNlbnQpO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuY2FuRXhwYW5kTGVmdCA9IGZ1bmN0aW9uIChjb25uZWN0QWRqYWNlbnQpIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuaXNUZW1wbGF0ZWQpXHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnBhcmVudC5jYW5FeHBhbmRDb2x1bW5MZWZ0KHRoaXMsIGNvbm5lY3RBZGphY2VudCk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5leHBhbmRMZWZ0ID0gZnVuY3Rpb24gKGNvbm5lY3RBZGphY2VudCkge1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMuY2FuRXhwYW5kTGVmdChjb25uZWN0QWRqYWNlbnQpKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB0aGlzLnBhcmVudC5leHBhbmRDb2x1bW5MZWZ0KHRoaXMsIGNvbm5lY3RBZGphY2VudCk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jYW5Db250cmFjdExlZnQgPSBmdW5jdGlvbiAoY29ubmVjdEFkamFjZW50KSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmlzVGVtcGxhdGVkKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5wYXJlbnQuY2FuQ29udHJhY3RDb2x1bW5MZWZ0KHRoaXMsIGNvbm5lY3RBZGphY2VudCk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jb250cmFjdExlZnQgPSBmdW5jdGlvbiAoY29ubmVjdEFkamFjZW50KSB7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy5jYW5Db250cmFjdExlZnQoY29ubmVjdEFkamFjZW50KSlcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgdGhpcy5wYXJlbnQuY29udHJhY3RDb2x1bW5MZWZ0KHRoaXMsIGNvbm5lY3RBZGphY2VudCk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy50b09iamVjdCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHRoaXMuZWxlbWVudFRvT2JqZWN0KCk7XHJcbiAgICAgICAgICAgIHJlc3VsdC53aWR0aCA9IHRoaXMud2lkdGg7XHJcbiAgICAgICAgICAgIHJlc3VsdC5vZmZzZXQgPSB0aGlzLm9mZnNldDtcclxuICAgICAgICAgICAgcmVzdWx0LmNvbGxhcHNpYmxlID0gdGhpcy5jb2xsYXBzaWJsZTtcclxuICAgICAgICAgICAgcmVzdWx0LmNoaWxkcmVuID0gdGhpcy5jaGlsZHJlblRvT2JqZWN0KCk7XHJcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICAgICAgfTtcclxuICAgIH07XHJcblxyXG4gICAgTGF5b3V0RWRpdG9yLkNvbHVtbi5mcm9tID0gZnVuY3Rpb24gKHZhbHVlKSB7XHJcbiAgICAgICAgdmFyIHJlc3VsdCA9IG5ldyBMYXlvdXRFZGl0b3IuQ29sdW1uKFxyXG4gICAgICAgICAgICB2YWx1ZS5kYXRhLFxyXG4gICAgICAgICAgICB2YWx1ZS5odG1sSWQsXHJcbiAgICAgICAgICAgIHZhbHVlLmh0bWxDbGFzcyxcclxuICAgICAgICAgICAgdmFsdWUuaHRtbFN0eWxlLFxyXG4gICAgICAgICAgICB2YWx1ZS5pc1RlbXBsYXRlZCxcclxuICAgICAgICAgICAgdmFsdWUud2lkdGgsXHJcbiAgICAgICAgICAgIHZhbHVlLm9mZnNldCxcclxuICAgICAgICAgICAgdmFsdWUuY29sbGFwc2libGUsXHJcbiAgICAgICAgICAgIHZhbHVlLnJ1bGUsXHJcbiAgICAgICAgICAgIExheW91dEVkaXRvci5jaGlsZHJlbkZyb20odmFsdWUuY2hpbGRyZW4pKTtcclxuICAgICAgICByZXN1bHQudG9vbGJveEljb24gPSB2YWx1ZS50b29sYm94SWNvbjtcclxuICAgICAgICByZXN1bHQudG9vbGJveExhYmVsID0gdmFsdWUudG9vbGJveExhYmVsO1xyXG4gICAgICAgIHJlc3VsdC50b29sYm94RGVzY3JpcHRpb24gPSB2YWx1ZS50b29sYm94RGVzY3JpcHRpb247XHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgIH07XHJcblxyXG4gICAgTGF5b3V0RWRpdG9yLkNvbHVtbi50aW1lcyA9IGZ1bmN0aW9uICh2YWx1ZSkge1xyXG4gICAgICAgIHJldHVybiBfLnRpbWVzKHZhbHVlLCBmdW5jdGlvbiAobikge1xyXG4gICAgICAgICAgICByZXR1cm4gTGF5b3V0RWRpdG9yLkNvbHVtbi5mcm9tKHtcclxuICAgICAgICAgICAgICAgIGRhdGE6IG51bGwsXHJcbiAgICAgICAgICAgICAgICBodG1sSWQ6IG51bGwsXHJcbiAgICAgICAgICAgICAgICBodG1sQ2xhc3M6IG51bGwsXHJcbiAgICAgICAgICAgICAgICBpc1RlbXBsYXRlZDogZmFsc2UsXHJcbiAgICAgICAgICAgICAgICB3aWR0aDogMTIgLyB2YWx1ZSxcclxuICAgICAgICAgICAgICAgIG9mZnNldDogMCxcclxuICAgICAgICAgICAgICAgIGNvbGxhcHNpYmxlOiBudWxsLFxyXG4gICAgICAgICAgICAgICAgY2hpbGRyZW46IFtdXHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfTtcclxufSkoTGF5b3V0RWRpdG9yIHx8IChMYXlvdXRFZGl0b3IgPSB7fSkpOyIsInZhciBMYXlvdXRFZGl0b3I7XHJcbihmdW5jdGlvbiAoTGF5b3V0RWRpdG9yKSB7XHJcblxyXG4gICAgTGF5b3V0RWRpdG9yLkNvbnRlbnQgPSBmdW5jdGlvbiAoZGF0YSwgaHRtbElkLCBodG1sQ2xhc3MsIGh0bWxTdHlsZSwgaXNUZW1wbGF0ZWQsIGNvbnRlbnRUeXBlLCBjb250ZW50VHlwZUxhYmVsLCBjb250ZW50VHlwZUNsYXNzLCBodG1sLCBoYXNFZGl0b3IsIHJ1bGUpIHtcclxuICAgICAgICBMYXlvdXRFZGl0b3IuRWxlbWVudC5jYWxsKHRoaXMsIFwiQ29udGVudFwiLCBkYXRhLCBodG1sSWQsIGh0bWxDbGFzcywgaHRtbFN0eWxlLCBpc1RlbXBsYXRlZCwgcnVsZSk7XHJcblxyXG4gICAgICAgIHRoaXMuY29udGVudFR5cGUgPSBjb250ZW50VHlwZTtcclxuICAgICAgICB0aGlzLmNvbnRlbnRUeXBlTGFiZWwgPSBjb250ZW50VHlwZUxhYmVsO1xyXG4gICAgICAgIHRoaXMuY29udGVudFR5cGVDbGFzcyA9IGNvbnRlbnRUeXBlQ2xhc3M7XHJcbiAgICAgICAgdGhpcy5odG1sID0gaHRtbDtcclxuICAgICAgICB0aGlzLmhhc0VkaXRvciA9IGhhc0VkaXRvcjtcclxuXHJcbiAgICAgICAgdGhpcy5nZXRJbm5lclRleHQgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiAkKCQucGFyc2VIVE1MKFwiPGRpdj5cIiArIHRoaXMuaHRtbCArIFwiPC9kaXY+XCIpKS50ZXh0KCk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgLy8gVGhpcyBmdW5jdGlvbiB3aWxsIGJlIG92ZXJ3cml0dGVuIGJ5IHRoZSBDb250ZW50IGRpcmVjdGl2ZS5cclxuICAgICAgICB0aGlzLnNldEh0bWwgPSBmdW5jdGlvbiAoaHRtbCkge1xyXG4gICAgICAgICAgICB0aGlzLmh0bWwgPSBodG1sO1xyXG4gICAgICAgICAgICB0aGlzLmh0bWxVbnNhZmUgPSBodG1sO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy50b09iamVjdCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgICAgIFwidHlwZVwiOiBcIkNvbnRlbnRcIlxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMudG9PYmplY3QgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHZhciByZXN1bHQgPSB0aGlzLmVsZW1lbnRUb09iamVjdCgpO1xyXG4gICAgICAgICAgICByZXN1bHQuY29udGVudFR5cGUgPSB0aGlzLmNvbnRlbnRUeXBlO1xyXG4gICAgICAgICAgICByZXN1bHQuY29udGVudFR5cGVMYWJlbCA9IHRoaXMuY29udGVudFR5cGVMYWJlbDtcclxuICAgICAgICAgICAgcmVzdWx0LmNvbnRlbnRUeXBlQ2xhc3MgPSB0aGlzLmNvbnRlbnRUeXBlQ2xhc3M7XHJcbiAgICAgICAgICAgIHJlc3VsdC5odG1sID0gdGhpcy5odG1sO1xyXG4gICAgICAgICAgICByZXN1bHQuaGFzRWRpdG9yID0gaGFzRWRpdG9yO1xyXG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuc2V0SHRtbChodG1sKTtcclxuICAgIH07XHJcblxyXG4gICAgTGF5b3V0RWRpdG9yLkNvbnRlbnQuZnJvbSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xyXG4gICAgICAgIHZhciByZXN1bHQgPSBuZXcgTGF5b3V0RWRpdG9yLkNvbnRlbnQoXHJcbiAgICAgICAgICAgIHZhbHVlLmRhdGEsXHJcbiAgICAgICAgICAgIHZhbHVlLmh0bWxJZCxcclxuICAgICAgICAgICAgdmFsdWUuaHRtbENsYXNzLFxyXG4gICAgICAgICAgICB2YWx1ZS5odG1sU3R5bGUsXHJcbiAgICAgICAgICAgIHZhbHVlLmlzVGVtcGxhdGVkLFxyXG4gICAgICAgICAgICB2YWx1ZS5jb250ZW50VHlwZSxcclxuICAgICAgICAgICAgdmFsdWUuY29udGVudFR5cGVMYWJlbCxcclxuICAgICAgICAgICAgdmFsdWUuY29udGVudFR5cGVDbGFzcyxcclxuICAgICAgICAgICAgdmFsdWUuaHRtbCxcclxuICAgICAgICAgICAgdmFsdWUuaGFzRWRpdG9yLFxyXG4gICAgICAgICAgICB2YWx1ZS5ydWxlKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgIH07XHJcblxyXG59KShMYXlvdXRFZGl0b3IgfHwgKExheW91dEVkaXRvciA9IHt9KSk7IiwidmFyIExheW91dEVkaXRvcjtcclxuKGZ1bmN0aW9uICgkLCBMYXlvdXRFZGl0b3IpIHtcclxuXHJcbiAgICBMYXlvdXRFZGl0b3IuSHRtbCA9IGZ1bmN0aW9uIChkYXRhLCBodG1sSWQsIGh0bWxDbGFzcywgaHRtbFN0eWxlLCBpc1RlbXBsYXRlZCwgY29udGVudFR5cGUsIGNvbnRlbnRUeXBlTGFiZWwsIGNvbnRlbnRUeXBlQ2xhc3MsIGh0bWwsIGhhc0VkaXRvciwgcnVsZSkge1xyXG4gICAgICAgIExheW91dEVkaXRvci5FbGVtZW50LmNhbGwodGhpcywgXCJIdG1sXCIsIGRhdGEsIGh0bWxJZCwgaHRtbENsYXNzLCBodG1sU3R5bGUsIGlzVGVtcGxhdGVkLCBydWxlKTtcclxuXHJcbiAgICAgICAgdGhpcy5jb250ZW50VHlwZSA9IGNvbnRlbnRUeXBlO1xyXG4gICAgICAgIHRoaXMuY29udGVudFR5cGVMYWJlbCA9IGNvbnRlbnRUeXBlTGFiZWw7XHJcbiAgICAgICAgdGhpcy5jb250ZW50VHlwZUNsYXNzID0gY29udGVudFR5cGVDbGFzcztcclxuICAgICAgICB0aGlzLmh0bWwgPSBodG1sO1xyXG4gICAgICAgIHRoaXMuaGFzRWRpdG9yID0gaGFzRWRpdG9yO1xyXG4gICAgICAgIHRoaXMuaXNDb250YWluYWJsZSA9IHRydWU7XHJcblxyXG4gICAgICAgIHRoaXMuZ2V0SW5uZXJUZXh0ID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gJCgkLnBhcnNlSFRNTChcIjxkaXY+XCIgKyB0aGlzLmh0bWwgKyBcIjwvZGl2PlwiKSkudGV4dCgpO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIC8vIFRoaXMgZnVuY3Rpb24gd2lsbCBiZSBvdmVyd3JpdHRlbiBieSB0aGUgQ29udGVudCBkaXJlY3RpdmUuXHJcbiAgICAgICAgdGhpcy5zZXRIdG1sID0gZnVuY3Rpb24gKGh0bWwpIHtcclxuICAgICAgICAgICAgdGhpcy5odG1sID0gaHRtbDtcclxuICAgICAgICAgICAgdGhpcy5odG1sVW5zYWZlID0gaHRtbDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMudG9PYmplY3QgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgICAgICBcInR5cGVcIjogXCJIdG1sXCJcclxuICAgICAgICAgICAgfTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLnRvT2JqZWN0ID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gdGhpcy5lbGVtZW50VG9PYmplY3QoKTtcclxuICAgICAgICAgICAgcmVzdWx0LmNvbnRlbnRUeXBlID0gdGhpcy5jb250ZW50VHlwZTtcclxuICAgICAgICAgICAgcmVzdWx0LmNvbnRlbnRUeXBlTGFiZWwgPSB0aGlzLmNvbnRlbnRUeXBlTGFiZWw7XHJcbiAgICAgICAgICAgIHJlc3VsdC5jb250ZW50VHlwZUNsYXNzID0gdGhpcy5jb250ZW50VHlwZUNsYXNzO1xyXG4gICAgICAgICAgICByZXN1bHQuaHRtbCA9IHRoaXMuaHRtbDtcclxuICAgICAgICAgICAgcmVzdWx0Lmhhc0VkaXRvciA9IGhhc0VkaXRvcjtcclxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB2YXIgZ2V0RWRpdG9yT2JqZWN0ID0gdGhpcy5nZXRFZGl0b3JPYmplY3Q7XHJcbiAgICAgICAgdGhpcy5nZXRFZGl0b3JPYmplY3QgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHZhciBkdG8gPSBnZXRFZGl0b3JPYmplY3QoKTtcclxuICAgICAgICAgICAgcmV0dXJuICQuZXh0ZW5kKGR0bywge1xyXG4gICAgICAgICAgICAgICAgQ29udGVudDogdGhpcy5odG1sXHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5zZXRIdG1sKGh0bWwpO1xyXG4gICAgfTtcclxuXHJcbiAgICBMYXlvdXRFZGl0b3IuSHRtbC5mcm9tID0gZnVuY3Rpb24gKHZhbHVlKSB7XHJcbiAgICAgICAgdmFyIHJlc3VsdCA9IG5ldyBMYXlvdXRFZGl0b3IuSHRtbChcclxuICAgICAgICAgICAgdmFsdWUuZGF0YSxcclxuICAgICAgICAgICAgdmFsdWUuaHRtbElkLFxyXG4gICAgICAgICAgICB2YWx1ZS5odG1sQ2xhc3MsXHJcbiAgICAgICAgICAgIHZhbHVlLmh0bWxTdHlsZSxcclxuICAgICAgICAgICAgdmFsdWUuaXNUZW1wbGF0ZWQsXHJcbiAgICAgICAgICAgIHZhbHVlLmNvbnRlbnRUeXBlLFxyXG4gICAgICAgICAgICB2YWx1ZS5jb250ZW50VHlwZUxhYmVsLFxyXG4gICAgICAgICAgICB2YWx1ZS5jb250ZW50VHlwZUNsYXNzLFxyXG4gICAgICAgICAgICB2YWx1ZS5odG1sLFxyXG4gICAgICAgICAgICB2YWx1ZS5oYXNFZGl0b3IsXHJcbiAgICAgICAgICAgIHZhbHVlLnJ1bGUpO1xyXG5cclxuICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgfTtcclxuXHJcbiAgICBMYXlvdXRFZGl0b3IucmVnaXN0ZXJGYWN0b3J5KFwiSHRtbFwiLCBmdW5jdGlvbih2YWx1ZSkgeyByZXR1cm4gTGF5b3V0RWRpdG9yLkh0bWwuZnJvbSh2YWx1ZSk7IH0pO1xyXG5cclxufSkoalF1ZXJ5LCBMYXlvdXRFZGl0b3IgfHwgKExheW91dEVkaXRvciA9IHt9KSk7Il0sInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkhlbHBlcnMuanMiLCJFZGl0b3IuanMiLCJFbGVtZW50LmpzIiwiQ29udGFpbmVyLmpzIiwiQ2FudmFzLmpzIiwiR3JpZC5qcyIsIlJvdy5qcyIsIkNvbHVtbi5qcyIsIkNvbnRlbnQuanMiLCJIdG1sLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDMUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUMvQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNuTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQzlJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDbENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQzdCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQzdSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQzVKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDMURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6Ik1vZGVscy5qcyIsInNvdXJjZXNDb250ZW50IjpbInZhciBMYXlvdXRFZGl0b3I7XHJcbihmdW5jdGlvbiAoTGF5b3V0RWRpdG9yKSB7XHJcblxyXG4gICAgQXJyYXkucHJvdG90eXBlLm1vdmUgPSBmdW5jdGlvbiAoZnJvbSwgdG8pIHtcclxuICAgICAgICB0aGlzLnNwbGljZSh0bywgMCwgdGhpcy5zcGxpY2UoZnJvbSwgMSlbMF0pO1xyXG4gICAgfTtcclxuXHJcbiAgICBMYXlvdXRFZGl0b3IuY2hpbGRyZW5Gcm9tID0gZnVuY3Rpb24odmFsdWVzKSB7XHJcbiAgICAgICAgcmV0dXJuIF8odmFsdWVzKS5tYXAoZnVuY3Rpb24odmFsdWUpIHtcclxuICAgICAgICAgICAgcmV0dXJuIExheW91dEVkaXRvci5lbGVtZW50RnJvbSh2YWx1ZSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9O1xyXG5cclxuICAgIHZhciByZWdpc3RlckZhY3RvcnkgPSBMYXlvdXRFZGl0b3IucmVnaXN0ZXJGYWN0b3J5ID0gZnVuY3Rpb24odHlwZSwgZmFjdG9yeSkge1xyXG4gICAgICAgIHZhciBmYWN0b3JpZXMgPSBMYXlvdXRFZGl0b3IuZmFjdG9yaWVzID0gTGF5b3V0RWRpdG9yLmZhY3RvcmllcyB8fCB7fTtcclxuICAgICAgICBmYWN0b3JpZXNbdHlwZV0gPSBmYWN0b3J5O1xyXG4gICAgfTtcclxuXHJcbiAgICByZWdpc3RlckZhY3RvcnkoXCJDYW52YXNcIiwgZnVuY3Rpb24gKHZhbHVlKSB7IHJldHVybiBMYXlvdXRFZGl0b3IuQ2FudmFzLmZyb20odmFsdWUpOyB9KTtcclxuICAgIHJlZ2lzdGVyRmFjdG9yeShcIkdyaWRcIiwgZnVuY3Rpb24odmFsdWUpIHsgcmV0dXJuIExheW91dEVkaXRvci5HcmlkLmZyb20odmFsdWUpOyB9KTtcclxuICAgIHJlZ2lzdGVyRmFjdG9yeShcIlJvd1wiLCBmdW5jdGlvbih2YWx1ZSkgeyByZXR1cm4gTGF5b3V0RWRpdG9yLlJvdy5mcm9tKHZhbHVlKTsgfSk7XHJcbiAgICByZWdpc3RlckZhY3RvcnkoXCJDb2x1bW5cIiwgZnVuY3Rpb24odmFsdWUpIHsgcmV0dXJuIExheW91dEVkaXRvci5Db2x1bW4uZnJvbSh2YWx1ZSk7IH0pO1xyXG4gICAgcmVnaXN0ZXJGYWN0b3J5KFwiQ29udGVudFwiLCBmdW5jdGlvbih2YWx1ZSkgeyByZXR1cm4gTGF5b3V0RWRpdG9yLkNvbnRlbnQuZnJvbSh2YWx1ZSk7IH0pO1xyXG5cclxuICAgIExheW91dEVkaXRvci5lbGVtZW50RnJvbSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xyXG4gICAgICAgIHZhciBmYWN0b3J5ID0gTGF5b3V0RWRpdG9yLmZhY3Rvcmllc1t2YWx1ZS50eXBlXTtcclxuXHJcbiAgICAgICAgaWYgKCFmYWN0b3J5KVxyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBlbGVtZW50IHdpdGggdHlwZSBcXFwiXCIgKyB2YWx1ZS50eXBlICsgXCJcXFwiIHdhcyBmb3VuZC5cIik7XHJcblxyXG4gICAgICAgIHZhciBlbGVtZW50ID0gZmFjdG9yeSh2YWx1ZSk7XHJcbiAgICAgICAgcmV0dXJuIGVsZW1lbnQ7XHJcbiAgICB9O1xyXG5cclxuICAgIExheW91dEVkaXRvci5zZXRNb2RlbCA9IGZ1bmN0aW9uIChlbGVtZW50U2VsZWN0b3IsIG1vZGVsKSB7XHJcbiAgICAgICAgJChlbGVtZW50U2VsZWN0b3IpLnNjb3BlKCkuZWxlbWVudCA9IG1vZGVsO1xyXG4gICAgfTtcclxuXHJcbiAgICBMYXlvdXRFZGl0b3IuZ2V0TW9kZWwgPSBmdW5jdGlvbiAoZWxlbWVudFNlbGVjdG9yKSB7XHJcbiAgICAgICAgcmV0dXJuICQoZWxlbWVudFNlbGVjdG9yKS5zY29wZSgpLmVsZW1lbnQ7XHJcbiAgICB9O1xyXG5cclxufSkoTGF5b3V0RWRpdG9yIHx8IChMYXlvdXRFZGl0b3IgPSB7fSkpOyIsInZhciBMYXlvdXRFZGl0b3I7XHJcbihmdW5jdGlvbiAoTGF5b3V0RWRpdG9yKSB7XHJcblxyXG4gICAgTGF5b3V0RWRpdG9yLkVkaXRvciA9IGZ1bmN0aW9uIChjb25maWcsIGNhbnZhc0RhdGEpIHtcclxuICAgICAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZztcclxuICAgICAgICB0aGlzLmNhbnZhcyA9IExheW91dEVkaXRvci5DYW52YXMuZnJvbShjYW52YXNEYXRhKTtcclxuICAgICAgICB0aGlzLmluaXRpYWxTdGF0ZSA9IEpTT04uc3RyaW5naWZ5KHRoaXMuY2FudmFzLnRvT2JqZWN0KCkpO1xyXG4gICAgICAgIHRoaXMuYWN0aXZlRWxlbWVudCA9IG51bGw7XHJcbiAgICAgICAgdGhpcy5mb2N1c2VkRWxlbWVudCA9IG51bGw7XHJcbiAgICAgICAgdGhpcy5kcm9wVGFyZ2V0RWxlbWVudCA9IG51bGw7XHJcbiAgICAgICAgdGhpcy5pc0RyYWdnaW5nID0gZmFsc2U7XHJcbiAgICAgICAgdGhpcy5pc1Jlc2l6aW5nID0gZmFsc2U7XHJcblxyXG4gICAgICAgIHRoaXMucmVzZXRUb29sYm94RWxlbWVudHMgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHRoaXMudG9vbGJveEVsZW1lbnRzID0gW1xyXG4gICAgICAgICAgICAgICAgTGF5b3V0RWRpdG9yLlJvdy5mcm9tKHtcclxuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogW11cclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgIF07XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5pc0RpcnR5ID0gZnVuY3Rpb24oKSB7XHJcbiAgICAgICAgICAgIHZhciBjdXJyZW50U3RhdGUgPSBKU09OLnN0cmluZ2lmeSh0aGlzLmNhbnZhcy50b09iamVjdCgpKTtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaW5pdGlhbFN0YXRlICE9IGN1cnJlbnRTdGF0ZTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLnJlc2V0VG9vbGJveEVsZW1lbnRzKCk7XHJcbiAgICAgICAgdGhpcy5jYW52YXMuc2V0RWRpdG9yKHRoaXMpO1xyXG4gICAgfTtcclxuXHJcbn0pKExheW91dEVkaXRvciB8fCAoTGF5b3V0RWRpdG9yID0ge30pKTtcclxuIiwidmFyIExheW91dEVkaXRvcjtcclxuKGZ1bmN0aW9uIChMYXlvdXRFZGl0b3IpIHtcclxuXHJcbiAgICBMYXlvdXRFZGl0b3IuRWxlbWVudCA9IGZ1bmN0aW9uICh0eXBlLCBkYXRhLCBodG1sSWQsIGh0bWxDbGFzcywgaHRtbFN0eWxlLCBpc1RlbXBsYXRlZCwgcnVsZSkge1xyXG4gICAgICAgIGlmICghdHlwZSlcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUGFyYW1ldGVyICd0eXBlJyBpcyByZXF1aXJlZC5cIik7XHJcblxyXG4gICAgICAgIHRoaXMudHlwZSA9IHR5cGU7XHJcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcclxuICAgICAgICB0aGlzLmh0bWxJZCA9IGh0bWxJZDtcclxuICAgICAgICB0aGlzLmh0bWxDbGFzcyA9IGh0bWxDbGFzcztcclxuICAgICAgICB0aGlzLmh0bWxTdHlsZSA9IGh0bWxTdHlsZTtcclxuICAgICAgICB0aGlzLmlzVGVtcGxhdGVkID0gaXNUZW1wbGF0ZWQ7XHJcbiAgICAgICAgdGhpcy5ydWxlID0gcnVsZTtcclxuXHJcbiAgICAgICAgdGhpcy5lZGl0b3IgPSBudWxsO1xyXG4gICAgICAgIHRoaXMucGFyZW50ID0gbnVsbDtcclxuICAgICAgICB0aGlzLnNldElzRm9jdXNlZEV2ZW50SGFuZGxlcnMgPSBbXTtcclxuXHJcbiAgICAgICAgdGhpcy5zZXRFZGl0b3IgPSBmdW5jdGlvbiAoZWRpdG9yKSB7XHJcbiAgICAgICAgICAgIHRoaXMuZWRpdG9yID0gZWRpdG9yO1xyXG4gICAgICAgICAgICBpZiAoISF0aGlzLmNoaWxkcmVuICYmIF8uaXNBcnJheSh0aGlzLmNoaWxkcmVuKSkge1xyXG4gICAgICAgICAgICAgICAgXyh0aGlzLmNoaWxkcmVuKS5lYWNoKGZ1bmN0aW9uIChjaGlsZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNoaWxkLnNldEVkaXRvcihlZGl0b3IpO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLnNldFBhcmVudCA9IGZ1bmN0aW9uKHBhcmVudEVsZW1lbnQpIHtcclxuICAgICAgICAgICAgdGhpcy5wYXJlbnQgPSBwYXJlbnRFbGVtZW50O1xyXG4gICAgICAgICAgICB0aGlzLnBhcmVudC5vbkNoaWxkQWRkZWQodGhpcyk7XHJcblxyXG4gICAgICAgICAgICB2YXIgY3VycmVudEFuY2VzdG9yID0gcGFyZW50RWxlbWVudDtcclxuICAgICAgICAgICAgd2hpbGUgKCEhY3VycmVudEFuY2VzdG9yKSB7XHJcbiAgICAgICAgICAgICAgICBjdXJyZW50QW5jZXN0b3Iub25EZXNjZW5kYW50QWRkZWQodGhpcywgcGFyZW50RWxlbWVudCk7XHJcbiAgICAgICAgICAgICAgICBjdXJyZW50QW5jZXN0b3IgPSBjdXJyZW50QW5jZXN0b3IucGFyZW50O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5zZXRJc1RlbXBsYXRlZCA9IGZ1bmN0aW9uICh2YWx1ZSkge1xyXG4gICAgICAgICAgICB0aGlzLmlzVGVtcGxhdGVkID0gdmFsdWU7XHJcbiAgICAgICAgICAgIGlmICghIXRoaXMuY2hpbGRyZW4gJiYgXy5pc0FycmF5KHRoaXMuY2hpbGRyZW4pKSB7XHJcbiAgICAgICAgICAgICAgICBfKHRoaXMuY2hpbGRyZW4pLmVhY2goZnVuY3Rpb24gKGNoaWxkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY2hpbGQuc2V0SXNUZW1wbGF0ZWQodmFsdWUpO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLmFwcGx5RWxlbWVudEVkaXRvck1vZGVsID0gZnVuY3Rpb24oKSB7IC8qIFZpcnR1YWwgKi8gfTtcclxuXHJcbiAgICAgICAgdGhpcy5nZXRJc0FjdGl2ZSA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLmVkaXRvcilcclxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZWRpdG9yLmFjdGl2ZUVsZW1lbnQgPT09IHRoaXMgJiYgIXRoaXMuZ2V0SXNGb2N1c2VkKCk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5zZXRJc0FjdGl2ZSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMuZWRpdG9yKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICBpZiAodGhpcy5lZGl0b3IuaXNEcmFnZ2luZyB8fCB0aGlzLmVkaXRvci5pc1Jlc2l6aW5nKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICAgICAgaWYgKHZhbHVlKVxyXG4gICAgICAgICAgICAgICAgdGhpcy5lZGl0b3IuYWN0aXZlRWxlbWVudCA9IHRoaXM7XHJcbiAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgIHRoaXMuZWRpdG9yLmFjdGl2ZUVsZW1lbnQgPSB0aGlzLnBhcmVudDtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLmdldElzRm9jdXNlZCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLmVkaXRvcilcclxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZWRpdG9yLmZvY3VzZWRFbGVtZW50ID09PSB0aGlzO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuc2V0SXNGb2N1c2VkID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMuZWRpdG9yKVxyXG4gICAgICAgICAgICBcdHJldHVybjtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLmNoaWxkcmVuICYmIHRoaXMuaXNUZW1wbGF0ZWQpXHJcbiAgICAgICAgICAgIFx0cmV0dXJuO1xyXG4gICAgICAgICAgICBpZiAodGhpcy5lZGl0b3IuaXNEcmFnZ2luZyB8fCB0aGlzLmVkaXRvci5pc1Jlc2l6aW5nKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5lZGl0b3IuZm9jdXNlZEVsZW1lbnQgPSB0aGlzO1xyXG4gICAgICAgICAgICBfKHRoaXMuc2V0SXNGb2N1c2VkRXZlbnRIYW5kbGVycykuZWFjaChmdW5jdGlvbiAoaXRlbSkge1xyXG4gICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICBpdGVtKCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBjYXRjaCAoZXgpIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBJZ25vcmUuXHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuZ2V0SXNTZWxlY3RlZCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuZ2V0SXNGb2N1c2VkKCkpXHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuXHJcbiAgICAgICAgICAgIGlmICghIXRoaXMuY2hpbGRyZW4gJiYgXy5pc0FycmF5KHRoaXMuY2hpbGRyZW4pKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gXyh0aGlzLmNoaWxkcmVuKS5hbnkoZnVuY3Rpb24oY2hpbGQpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2hpbGQuZ2V0SXNTZWxlY3RlZCgpO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLmdldElzRHJvcFRhcmdldCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLmVkaXRvcilcclxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZWRpdG9yLmRyb3BUYXJnZXRFbGVtZW50ID09PSB0aGlzO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5zZXRJc0Ryb3BUYXJnZXQgPSBmdW5jdGlvbiAodmFsdWUpIHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLmVkaXRvcilcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgaWYgKHZhbHVlKVxyXG4gICAgICAgICAgICAgICAgdGhpcy5lZGl0b3IuZHJvcFRhcmdldEVsZW1lbnQgPSB0aGlzO1xyXG4gICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICB0aGlzLmVkaXRvci5kcm9wVGFyZ2V0RWxlbWVudCA9IG51bGw7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jYW5EZWxldGUgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmlzVGVtcGxhdGVkIHx8ICF0aGlzLnBhcmVudClcclxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5kZWxldGUgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy5jYW5EZWxldGUoKSlcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgdGhpcy5wYXJlbnQuZGVsZXRlQ2hpbGQodGhpcyk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jYW5Nb3ZlVXAgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmlzVGVtcGxhdGVkIHx8ICF0aGlzLnBhcmVudClcclxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMucGFyZW50LmNhbk1vdmVDaGlsZFVwKHRoaXMpO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMubW92ZVVwID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMuY2FuTW92ZVVwKCkpXHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIHRoaXMucGFyZW50Lm1vdmVDaGlsZFVwKHRoaXMpO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuY2FuTW92ZURvd24gPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmlzVGVtcGxhdGVkIHx8ICF0aGlzLnBhcmVudClcclxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMucGFyZW50LmNhbk1vdmVDaGlsZERvd24odGhpcyk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5tb3ZlRG93biA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLmNhbk1vdmVEb3duKCkpXHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIHRoaXMucGFyZW50Lm1vdmVDaGlsZERvd24odGhpcyk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5lbGVtZW50VG9PYmplY3QgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgICAgICB0eXBlOiB0aGlzLnR5cGUsXHJcbiAgICAgICAgICAgICAgICBkYXRhOiB0aGlzLmRhdGEsXHJcbiAgICAgICAgICAgICAgICBodG1sSWQ6IHRoaXMuaHRtbElkLFxyXG4gICAgICAgICAgICAgICAgaHRtbENsYXNzOiB0aGlzLmh0bWxDbGFzcyxcclxuICAgICAgICAgICAgICAgIGh0bWxTdHlsZTogdGhpcy5odG1sU3R5bGUsXHJcbiAgICAgICAgICAgICAgICBpc1RlbXBsYXRlZDogdGhpcy5pc1RlbXBsYXRlZCxcclxuICAgICAgICAgICAgICAgIHJ1bGU6IHRoaXMucnVsZVxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuZ2V0RWRpdG9yT2JqZWN0ID0gZnVuY3Rpb24oKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB7fTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLmNvcHkgPSBmdW5jdGlvbiAoY2xpcGJvYXJkRGF0YSkge1xyXG4gICAgICAgICAgICB2YXIgdGV4dCA9IHRoaXMuZ2V0SW5uZXJUZXh0KCk7XHJcbiAgICAgICAgICAgIGNsaXBib2FyZERhdGEuc2V0RGF0YShcInRleHQvcGxhaW5cIiwgdGV4dCk7XHJcblxyXG4gICAgICAgICAgICB2YXIgZGF0YSA9IHRoaXMudG9PYmplY3QoKTtcclxuICAgICAgICAgICAgdmFyIGpzb24gPSBKU09OLnN0cmluZ2lmeShkYXRhLCBudWxsLCBcIlxcdFwiKTtcclxuICAgICAgICAgICAgY2xpcGJvYXJkRGF0YS5zZXREYXRhKFwidGV4dC9qc29uXCIsIGpzb24pO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuY3V0ID0gZnVuY3Rpb24gKGNsaXBib2FyZERhdGEpIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuY2FuRGVsZXRlKCkpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuY29weShjbGlwYm9hcmREYXRhKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuZGVsZXRlKCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLnBhc3RlID0gZnVuY3Rpb24gKGNsaXBib2FyZERhdGEpIHtcclxuICAgICAgICAgICAgaWYgKCEhdGhpcy5wYXJlbnQpXHJcbiAgICAgICAgICAgICAgICB0aGlzLnBhcmVudC5wYXN0ZShjbGlwYm9hcmREYXRhKTtcclxuICAgICAgICB9O1xyXG4gICAgfTtcclxuXHJcbn0pKExheW91dEVkaXRvciB8fCAoTGF5b3V0RWRpdG9yID0ge30pKTsiLCJ2YXIgTGF5b3V0RWRpdG9yO1xyXG4oZnVuY3Rpb24gKExheW91dEVkaXRvcikge1xyXG5cclxuICAgIExheW91dEVkaXRvci5Db250YWluZXIgPSBmdW5jdGlvbiAoYWxsb3dlZENoaWxkVHlwZXMsIGNoaWxkcmVuKSB7XHJcblxyXG4gICAgICAgIHRoaXMuYWxsb3dlZENoaWxkVHlwZXMgPSBhbGxvd2VkQ2hpbGRUeXBlcztcclxuICAgICAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW47XHJcbiAgICAgICAgdGhpcy5pc0NvbnRhaW5lciA9IHRydWU7XHJcblxyXG4gICAgICAgIHZhciBzZWxmID0gdGhpcztcclxuXHJcbiAgICAgICAgdGhpcy5vbkNoaWxkQWRkZWQgPSBmdW5jdGlvbiAoZWxlbWVudCkgeyAvKiBWaXJ0dWFsICovIH07XHJcbiAgICAgICAgdGhpcy5vbkRlc2NlbmRhbnRBZGRlZCA9IGZ1bmN0aW9uIChlbGVtZW50LCBwYXJlbnRFbGVtZW50KSB7IC8qIFZpcnR1YWwgKi8gfTtcclxuXHJcbiAgICAgICAgdGhpcy5zZXRDaGlsZHJlbiA9IGZ1bmN0aW9uIChjaGlsZHJlbikge1xyXG4gICAgICAgICAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW47XHJcbiAgICAgICAgICAgIF8odGhpcy5jaGlsZHJlbikuZWFjaChmdW5jdGlvbiAoY2hpbGQpIHtcclxuICAgICAgICAgICAgICAgIGNoaWxkLnNldFBhcmVudChzZWxmKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5zZXRDaGlsZHJlbihjaGlsZHJlbik7XHJcblxyXG4gICAgICAgIHRoaXMuZ2V0SXNTZWFsZWQgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfKHRoaXMuY2hpbGRyZW4pLmFueShmdW5jdGlvbiAoY2hpbGQpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBjaGlsZC5pc1RlbXBsYXRlZDtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdmFyIF9iYXNlU2V0SXNGb2N1c2VkID0gdGhpcy5zZXRJc0ZvY3VzZWQ7XHJcbiAgICAgICAgdGhpcy5zZXRJc0ZvY3VzZWQgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmdldElzU2VhbGVkKCkpXHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIF9iYXNlU2V0SXNGb2N1c2VkLmNhbGwodGhpcyk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5hZGRDaGlsZCA9IGZ1bmN0aW9uIChjaGlsZCkge1xyXG4gICAgICAgICAgICBpZiAoIV8odGhpcy5jaGlsZHJlbikuY29udGFpbnMoY2hpbGQpICYmIChfKHRoaXMuYWxsb3dlZENoaWxkVHlwZXMpLmNvbnRhaW5zKGNoaWxkLnR5cGUpIHx8IGNoaWxkLmlzQ29udGFpbmFibGUpKVxyXG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbi5wdXNoKGNoaWxkKTtcclxuICAgICAgICAgICAgY2hpbGQuc2V0RWRpdG9yKHRoaXMuZWRpdG9yKTtcclxuICAgICAgICAgICAgY2hpbGQuc2V0SXNUZW1wbGF0ZWQoZmFsc2UpO1xyXG4gICAgICAgICAgICBjaGlsZC5zZXRQYXJlbnQodGhpcyk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5kZWxldGVDaGlsZCA9IGZ1bmN0aW9uIChjaGlsZCkge1xyXG4gICAgICAgICAgICB2YXIgaW5kZXggPSBfKHRoaXMuY2hpbGRyZW4pLmluZGV4T2YoY2hpbGQpO1xyXG4gICAgICAgICAgICBpZiAoaW5kZXggPj0gMCkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbi5zcGxpY2UoaW5kZXgsIDEpO1xyXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkLmdldElzQWN0aXZlKCkpXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZGl0b3IuYWN0aXZlRWxlbWVudCA9IG51bGw7XHJcbiAgICAgICAgICAgICAgICBpZiAoY2hpbGQuZ2V0SXNGb2N1c2VkKCkpIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgZGVsZXRlZCBjaGlsZCB3YXMgZm9jdXNlZCwgdHJ5IHRvIHNldCBuZXcgZm9jdXMgdG8gdGhlIG1vc3QgYXBwcm9wcmlhdGUgc2libGluZyBvciBwYXJlbnQuXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuY2hpbGRyZW4ubGVuZ3RoID4gaW5kZXgpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2hpbGRyZW5baW5kZXhdLnNldElzRm9jdXNlZCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKGluZGV4ID4gMClcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbltpbmRleCAtIDFdLnNldElzRm9jdXNlZCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRJc0ZvY3VzZWQoKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMubW92ZUZvY3VzUHJldkNoaWxkID0gZnVuY3Rpb24gKGNoaWxkKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmNoaWxkcmVuLmxlbmd0aCA8IDIpXHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIHZhciBpbmRleCA9IF8odGhpcy5jaGlsZHJlbikuaW5kZXhPZihjaGlsZCk7XHJcbiAgICAgICAgICAgIGlmIChpbmRleCA+IDApXHJcbiAgICAgICAgICAgICAgICB0aGlzLmNoaWxkcmVuW2luZGV4IC0gMV0uc2V0SXNGb2N1c2VkKCk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5tb3ZlRm9jdXNOZXh0Q2hpbGQgPSBmdW5jdGlvbiAoY2hpbGQpIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuY2hpbGRyZW4ubGVuZ3RoIDwgMilcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgdmFyIGluZGV4ID0gXyh0aGlzLmNoaWxkcmVuKS5pbmRleE9mKGNoaWxkKTtcclxuICAgICAgICAgICAgaWYgKGluZGV4IDwgdGhpcy5jaGlsZHJlbi5sZW5ndGggLSAxKVxyXG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbltpbmRleCArIDFdLnNldElzRm9jdXNlZCgpO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuaW5zZXJ0Q2hpbGQgPSBmdW5jdGlvbiAoY2hpbGQsIGFmdGVyQ2hpbGQpIHtcclxuICAgICAgICAgICAgaWYgKCFfKHRoaXMuY2hpbGRyZW4pLmNvbnRhaW5zKGNoaWxkKSkge1xyXG4gICAgICAgICAgICAgICAgdmFyIGluZGV4ID0gTWF0aC5tYXgoXyh0aGlzLmNoaWxkcmVuKS5pbmRleE9mKGFmdGVyQ2hpbGQpLCAwKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuY2hpbGRyZW4uc3BsaWNlKGluZGV4ICsgMSwgMCwgY2hpbGQpO1xyXG4gICAgICAgICAgICAgICAgY2hpbGQuc2V0RWRpdG9yKHRoaXMuZWRpdG9yKTtcclxuICAgICAgICAgICAgICAgIGNoaWxkLnBhcmVudCA9IHRoaXM7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLm1vdmVDaGlsZFVwID0gZnVuY3Rpb24gKGNoaWxkKSB7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy5jYW5Nb3ZlQ2hpbGRVcChjaGlsZCkpXHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIHZhciBpbmRleCA9IF8odGhpcy5jaGlsZHJlbikuaW5kZXhPZihjaGlsZCk7XHJcbiAgICAgICAgICAgIHRoaXMuY2hpbGRyZW4ubW92ZShpbmRleCwgaW5kZXggLSAxKTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLm1vdmVDaGlsZERvd24gPSBmdW5jdGlvbiAoY2hpbGQpIHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLmNhbk1vdmVDaGlsZERvd24oY2hpbGQpKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB2YXIgaW5kZXggPSBfKHRoaXMuY2hpbGRyZW4pLmluZGV4T2YoY2hpbGQpO1xyXG4gICAgICAgICAgICB0aGlzLmNoaWxkcmVuLm1vdmUoaW5kZXgsIGluZGV4ICsgMSk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jYW5Nb3ZlQ2hpbGRVcCA9IGZ1bmN0aW9uIChjaGlsZCkge1xyXG4gICAgICAgICAgICB2YXIgaW5kZXggPSBfKHRoaXMuY2hpbGRyZW4pLmluZGV4T2YoY2hpbGQpO1xyXG4gICAgICAgICAgICByZXR1cm4gaW5kZXggPiAwO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuY2FuTW92ZUNoaWxkRG93biA9IGZ1bmN0aW9uIChjaGlsZCkge1xyXG4gICAgICAgICAgICB2YXIgaW5kZXggPSBfKHRoaXMuY2hpbGRyZW4pLmluZGV4T2YoY2hpbGQpO1xyXG4gICAgICAgICAgICByZXR1cm4gaW5kZXggPCB0aGlzLmNoaWxkcmVuLmxlbmd0aCAtIDE7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jaGlsZHJlblRvT2JqZWN0ID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gXyh0aGlzLmNoaWxkcmVuKS5tYXAoZnVuY3Rpb24gKGNoaWxkKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gY2hpbGQudG9PYmplY3QoKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5nZXRJbm5lclRleHQgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBfKHRoaXMuY2hpbGRyZW4pLnJlZHVjZShmdW5jdGlvbiAobWVtbywgY2hpbGQpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBtZW1vICsgXCJcXG5cIiArIGNoaWxkLmdldElubmVyVGV4dCgpO1xyXG4gICAgICAgICAgICB9LCBcIlwiKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMucGFzdGUgPSBmdW5jdGlvbiAoY2xpcGJvYXJkRGF0YSkge1xyXG4gICAgICAgICAgICB2YXIganNvbiA9IGNsaXBib2FyZERhdGEuZ2V0RGF0YShcInRleHQvanNvblwiKTtcclxuICAgICAgICAgICAgaWYgKCEhanNvbikge1xyXG4gICAgICAgICAgICAgICAgdmFyIGRhdGEgPSBKU09OLnBhcnNlKGpzb24pO1xyXG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gTGF5b3V0RWRpdG9yLmVsZW1lbnRGcm9tKGRhdGEpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5wYXN0ZUNoaWxkKGNoaWxkKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMucGFzdGVDaGlsZCA9IGZ1bmN0aW9uIChjaGlsZCkge1xyXG4gICAgICAgICAgICBpZiAoXyh0aGlzLmFsbG93ZWRDaGlsZFR5cGVzKS5jb250YWlucyhjaGlsZC50eXBlKSB8fCBjaGlsZC5pc0NvbnRhaW5hYmxlKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmFkZENoaWxkKGNoaWxkKTtcclxuICAgICAgICAgICAgICAgIGNoaWxkLnNldElzRm9jdXNlZCgpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2UgaWYgKCEhdGhpcy5wYXJlbnQpXHJcbiAgICAgICAgICAgICAgICB0aGlzLnBhcmVudC5wYXN0ZUNoaWxkKGNoaWxkKTtcclxuICAgICAgICB9XHJcbiAgICB9O1xyXG5cclxufSkoTGF5b3V0RWRpdG9yIHx8IChMYXlvdXRFZGl0b3IgPSB7fSkpOyIsInZhciBMYXlvdXRFZGl0b3I7XHJcbihmdW5jdGlvbiAoTGF5b3V0RWRpdG9yKSB7XHJcblxyXG4gICAgTGF5b3V0RWRpdG9yLkNhbnZhcyA9IGZ1bmN0aW9uIChkYXRhLCBodG1sSWQsIGh0bWxDbGFzcywgaHRtbFN0eWxlLCBpc1RlbXBsYXRlZCwgcnVsZSwgY2hpbGRyZW4pIHtcclxuICAgICAgICBMYXlvdXRFZGl0b3IuRWxlbWVudC5jYWxsKHRoaXMsIFwiQ2FudmFzXCIsIGRhdGEsIGh0bWxJZCwgaHRtbENsYXNzLCBodG1sU3R5bGUsIGlzVGVtcGxhdGVkLCBydWxlKTtcclxuICAgICAgICBMYXlvdXRFZGl0b3IuQ29udGFpbmVyLmNhbGwodGhpcywgW1wiQ2FudmFzXCIsIFwiR3JpZFwiLCBcIkNvbnRlbnRcIl0sIGNoaWxkcmVuKTtcclxuXHJcbiAgICAgICAgdGhpcy5pc0NvbnRhaW5hYmxlID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgdGhpcy50b09iamVjdCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHRoaXMuZWxlbWVudFRvT2JqZWN0KCk7XHJcbiAgICAgICAgICAgIHJlc3VsdC5jaGlsZHJlbiA9IHRoaXMuY2hpbGRyZW5Ub09iamVjdCgpO1xyXG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgICAgIH07XHJcbiAgICB9O1xyXG5cclxuICAgIExheW91dEVkaXRvci5DYW52YXMuZnJvbSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xyXG4gICAgICAgIHZhciByZXN1bHQgPSBuZXcgTGF5b3V0RWRpdG9yLkNhbnZhcyhcclxuICAgICAgICAgICAgdmFsdWUuZGF0YSxcclxuICAgICAgICAgICAgdmFsdWUuaHRtbElkLFxyXG4gICAgICAgICAgICB2YWx1ZS5odG1sQ2xhc3MsXHJcbiAgICAgICAgICAgIHZhbHVlLmh0bWxTdHlsZSxcclxuICAgICAgICAgICAgdmFsdWUuaXNUZW1wbGF0ZWQsXHJcbiAgICAgICAgICAgIHZhbHVlLnJ1bGUsXHJcbiAgICAgICAgICAgIExheW91dEVkaXRvci5jaGlsZHJlbkZyb20odmFsdWUuY2hpbGRyZW4pKTtcclxuXHJcbiAgICAgICAgcmVzdWx0LnRvb2xib3hJY29uID0gdmFsdWUudG9vbGJveEljb247XHJcbiAgICAgICAgcmVzdWx0LnRvb2xib3hMYWJlbCA9IHZhbHVlLnRvb2xib3hMYWJlbDtcclxuICAgICAgICByZXN1bHQudG9vbGJveERlc2NyaXB0aW9uID0gdmFsdWUudG9vbGJveERlc2NyaXB0aW9uO1xyXG5cclxuICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgfTtcclxuXHJcbn0pKExheW91dEVkaXRvciB8fCAoTGF5b3V0RWRpdG9yID0ge30pKTtcclxuIiwidmFyIExheW91dEVkaXRvcjtcclxuKGZ1bmN0aW9uIChMYXlvdXRFZGl0b3IpIHtcclxuXHJcbiAgICBMYXlvdXRFZGl0b3IuR3JpZCA9IGZ1bmN0aW9uIChkYXRhLCBodG1sSWQsIGh0bWxDbGFzcywgaHRtbFN0eWxlLCBpc1RlbXBsYXRlZCwgcnVsZSwgY2hpbGRyZW4pIHtcclxuICAgICAgICBMYXlvdXRFZGl0b3IuRWxlbWVudC5jYWxsKHRoaXMsIFwiR3JpZFwiLCBkYXRhLCBodG1sSWQsIGh0bWxDbGFzcywgaHRtbFN0eWxlLCBpc1RlbXBsYXRlZCwgcnVsZSk7XHJcbiAgICAgICAgTGF5b3V0RWRpdG9yLkNvbnRhaW5lci5jYWxsKHRoaXMsIFtcIlJvd1wiXSwgY2hpbGRyZW4pO1xyXG5cclxuICAgICAgICB0aGlzLnRvT2JqZWN0ID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gdGhpcy5lbGVtZW50VG9PYmplY3QoKTtcclxuICAgICAgICAgICAgcmVzdWx0LmNoaWxkcmVuID0gdGhpcy5jaGlsZHJlblRvT2JqZWN0KCk7XHJcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICAgICAgfTtcclxuICAgIH07XHJcblxyXG4gICAgTGF5b3V0RWRpdG9yLkdyaWQuZnJvbSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xyXG4gICAgICAgIHZhciByZXN1bHQgPSBuZXcgTGF5b3V0RWRpdG9yLkdyaWQoXHJcbiAgICAgICAgICAgIHZhbHVlLmRhdGEsXHJcbiAgICAgICAgICAgIHZhbHVlLmh0bWxJZCxcclxuICAgICAgICAgICAgdmFsdWUuaHRtbENsYXNzLFxyXG4gICAgICAgICAgICB2YWx1ZS5odG1sU3R5bGUsXHJcbiAgICAgICAgICAgIHZhbHVlLmlzVGVtcGxhdGVkLFxyXG4gICAgICAgICAgICB2YWx1ZS5ydWxlLFxyXG4gICAgICAgICAgICBMYXlvdXRFZGl0b3IuY2hpbGRyZW5Gcm9tKHZhbHVlLmNoaWxkcmVuKSk7XHJcbiAgICAgICAgcmVzdWx0LnRvb2xib3hJY29uID0gdmFsdWUudG9vbGJveEljb247XHJcbiAgICAgICAgcmVzdWx0LnRvb2xib3hMYWJlbCA9IHZhbHVlLnRvb2xib3hMYWJlbDtcclxuICAgICAgICByZXN1bHQudG9vbGJveERlc2NyaXB0aW9uID0gdmFsdWUudG9vbGJveERlc2NyaXB0aW9uO1xyXG4gICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICB9O1xyXG5cclxufSkoTGF5b3V0RWRpdG9yIHx8IChMYXlvdXRFZGl0b3IgPSB7fSkpOyIsInZhciBMYXlvdXRFZGl0b3I7XHJcbihmdW5jdGlvbiAoTGF5b3V0RWRpdG9yKSB7XHJcblxyXG4gICAgTGF5b3V0RWRpdG9yLlJvdyA9IGZ1bmN0aW9uIChkYXRhLCBodG1sSWQsIGh0bWxDbGFzcywgaHRtbFN0eWxlLCBpc1RlbXBsYXRlZCwgcnVsZSwgY2hpbGRyZW4pIHtcclxuICAgICAgICBMYXlvdXRFZGl0b3IuRWxlbWVudC5jYWxsKHRoaXMsIFwiUm93XCIsIGRhdGEsIGh0bWxJZCwgaHRtbENsYXNzLCBodG1sU3R5bGUsIGlzVGVtcGxhdGVkLCBydWxlKTtcclxuICAgICAgICBMYXlvdXRFZGl0b3IuQ29udGFpbmVyLmNhbGwodGhpcywgW1wiQ29sdW1uXCJdLCBjaGlsZHJlbik7XHJcblxyXG4gICAgICAgIHZhciBfc2VsZiA9IHRoaXM7XHJcblxyXG4gICAgICAgIGZ1bmN0aW9uIF9nZXRUb3RhbENvbHVtbnNXaWR0aCgpIHtcclxuICAgICAgICAgICAgcmV0dXJuIF8oX3NlbGYuY2hpbGRyZW4pLnJlZHVjZShmdW5jdGlvbiAobWVtbywgY2hpbGQpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBtZW1vICsgY2hpbGQub2Zmc2V0ICsgY2hpbGQud2lkdGg7XHJcbiAgICAgICAgICAgIH0sIDApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gSW1wbGVtZW50cyBhIHNpbXBsZSBhbGdvcml0aG0gdG8gZGlzdHJpYnV0ZSBzcGFjZSAoZWl0aGVyIHBvc2l0aXZlIG9yIG5lZ2F0aXZlKVxyXG4gICAgICAgIC8vIGJldHdlZW4gdGhlIGNoaWxkIGNvbHVtbnMgb2YgdGhlIHJvdy4gTmVnYXRpdmUgc3BhY2UgaXMgZGlzdHJpYnV0ZWQgd2hlbiBtYWtpbmdcclxuICAgICAgICAvLyByb29tIGZvciBhIG5ldyBjb2x1bW4gKGUuYy4gY2xpcGJvYXJkIHBhc3RlIG9yIGRyb3BwaW5nIGZyb20gdGhlIHRvb2xib3gpIHdoaWxlXHJcbiAgICAgICAgLy8gcG9zaXRpdmUgc3BhY2UgaXMgZGlzdHJpYnV0ZWQgd2hlbiBmaWxsaW5nIHRoZSBncmFwIG9mIGEgcmVtb3ZlZCBjb2x1bW4uXHJcbiAgICAgICAgZnVuY3Rpb24gX2Rpc3RyaWJ1dGVTcGFjZShzcGFjZSkge1xyXG4gICAgICAgICAgICBpZiAoc3BhY2UgPT0gMClcclxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIHZhciB1bmRpc3RyaWJ1dGVkU3BhY2UgPSBzcGFjZTtcclxuXHJcbiAgICAgICAgICAgIGlmICh1bmRpc3RyaWJ1dGVkU3BhY2UgPCAwKSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgdmFjYW50U3BhY2UgPSAxMiAtIF9nZXRUb3RhbENvbHVtbnNXaWR0aCgpO1xyXG4gICAgICAgICAgICAgICAgdW5kaXN0cmlidXRlZFNwYWNlICs9IHZhY2FudFNwYWNlO1xyXG4gICAgICAgICAgICAgICAgaWYgKHVuZGlzdHJpYnV0ZWRTcGFjZSA+IDApXHJcbiAgICAgICAgICAgICAgICAgICAgdW5kaXN0cmlidXRlZFNwYWNlID0gMDtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gSWYgc3BhY2UgaXMgbmVnYXRpdmUsIHRyeSB0byBkZWNyZWFzZSBvZmZzZXRzIGZpcnN0LlxyXG4gICAgICAgICAgICB3aGlsZSAodW5kaXN0cmlidXRlZFNwYWNlIDwgMCAmJiBfKF9zZWxmLmNoaWxkcmVuKS5hbnkoZnVuY3Rpb24gKGNvbHVtbikgeyByZXR1cm4gY29sdW1uLm9mZnNldCA+IDA7IH0pKSB7IC8vIFdoaWxlIHRoZXJlIGlzIHN0aWxsIG9mZnNldCBsZWZ0IHRvIHJlbW92ZS5cclxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBfc2VsZi5jaGlsZHJlbi5sZW5ndGggJiYgdW5kaXN0cmlidXRlZFNwYWNlIDwgMDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNvbHVtbiA9IF9zZWxmLmNoaWxkcmVuW2ldO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChjb2x1bW4ub2Zmc2V0ID4gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb2x1bW4ub2Zmc2V0LS07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHVuZGlzdHJpYnV0ZWRTcGFjZSsrO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgZnVuY3Rpb24gaGFzV2lkdGgoY29sdW1uKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAodW5kaXN0cmlidXRlZFNwYWNlID4gMClcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29sdW1uLndpZHRoIDwgMTI7XHJcbiAgICAgICAgICAgICAgICBlbHNlIGlmICh1bmRpc3RyaWJ1dGVkU3BhY2UgPCAwKVxyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjb2x1bW4ud2lkdGggPiAxO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBUcnkgdG8gZGlzdHJpYnV0ZSByZW1haW5pbmcgc3BhY2UgKGNvdWxkIGJlIG5lZ2F0aXZlIG9yIHBvc2l0aXZlKSB1c2luZyB3aWR0aHMuXHJcbiAgICAgICAgICAgIHdoaWxlICh1bmRpc3RyaWJ1dGVkU3BhY2UgIT0gMCkge1xyXG4gICAgICAgICAgICAgICAgLy8gQW55IG1vcmUgY29sdW1uIHdpZHRoIGF2YWlsYWJsZSBmb3IgZGlzdHJpYnV0aW9uP1xyXG4gICAgICAgICAgICAgICAgaWYgKCFfKF9zZWxmLmNoaWxkcmVuKS5hbnkoaGFzV2lkdGgpKVxyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IF9zZWxmLmNoaWxkcmVuLmxlbmd0aCAmJiB1bmRpc3RyaWJ1dGVkU3BhY2UgIT0gMDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNvbHVtbiA9IF9zZWxmLmNoaWxkcmVuW2kgJSBfc2VsZi5jaGlsZHJlbi5sZW5ndGhdO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChoYXNXaWR0aChjb2x1bW4pKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkZWx0YSA9IHVuZGlzdHJpYnV0ZWRTcGFjZSAvIE1hdGguYWJzKHVuZGlzdHJpYnV0ZWRTcGFjZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbHVtbi53aWR0aCArPSBkZWx0YTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdW5kaXN0cmlidXRlZFNwYWNlIC09IGRlbHRhO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0gICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHJldHVybiB1bmRpc3RyaWJ1dGVkU3BhY2UgPT0gMDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHZhciBfaXNBZGRpbmdDb2x1bW4gPSBmYWxzZTtcclxuXHJcbiAgICAgICAgdGhpcy5jYW5BZGRDb2x1bW4gPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNoaWxkcmVuLmxlbmd0aCA8IDEyO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuYmVnaW5BZGRDb2x1bW4gPSBmdW5jdGlvbiAobmV3Q29sdW1uV2lkdGgpIHtcclxuICAgICAgICAgICAgaWYgKCEhX2lzQWRkaW5nQ29sdW1uKVxyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ29sdW1uIGFkZCBvcGVyYXRpb24gaXMgYWxyZWFkeSBpbiBwcm9ncmVzcy5cIilcclxuICAgICAgICAgICAgXyh0aGlzLmNoaWxkcmVuKS5lYWNoKGZ1bmN0aW9uIChjb2x1bW4pIHtcclxuICAgICAgICAgICAgICAgIGNvbHVtbi5iZWdpbkNoYW5nZSgpO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgaWYgKF9kaXN0cmlidXRlU3BhY2UoLW5ld0NvbHVtbldpZHRoKSkge1xyXG4gICAgICAgICAgICAgICAgX2lzQWRkaW5nQ29sdW1uID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIF8odGhpcy5jaGlsZHJlbikuZWFjaChmdW5jdGlvbiAoY29sdW1uKSB7XHJcbiAgICAgICAgICAgICAgICBjb2x1bW4ucm9sbGJhY2tDaGFuZ2UoKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLmNvbW1pdEFkZENvbHVtbiA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKCFfaXNBZGRpbmdDb2x1bW4pXHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBjb2x1bW4gYWRkIG9wZXJhdGlvbiBpbiBwcm9ncmVzcy5cIilcclxuICAgICAgICAgICAgXyh0aGlzLmNoaWxkcmVuKS5lYWNoKGZ1bmN0aW9uIChjb2x1bW4pIHtcclxuICAgICAgICAgICAgICAgIGNvbHVtbi5jb21taXRDaGFuZ2UoKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIF9pc0FkZGluZ0NvbHVtbiA9IGZhbHNlO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMucm9sbGJhY2tBZGRDb2x1bW4gPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmICghX2lzQWRkaW5nQ29sdW1uKVxyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gY29sdW1uIGFkZCBvcGVyYXRpb24gaW4gcHJvZ3Jlc3MuXCIpXHJcbiAgICAgICAgICAgIF8odGhpcy5jaGlsZHJlbikuZWFjaChmdW5jdGlvbiAoY29sdW1uKSB7XHJcbiAgICAgICAgICAgICAgICBjb2x1bW4ucm9sbGJhY2tDaGFuZ2UoKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIF9pc0FkZGluZ0NvbHVtbiA9IGZhbHNlO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHZhciBfYmFzZURlbGV0ZUNoaWxkID0gdGhpcy5kZWxldGVDaGlsZDtcclxuICAgICAgICB0aGlzLmRlbGV0ZUNoaWxkID0gZnVuY3Rpb24gKGNvbHVtbikgeyBcclxuICAgICAgICAgICAgdmFyIHdpZHRoID0gY29sdW1uLndpZHRoO1xyXG4gICAgICAgICAgICBfYmFzZURlbGV0ZUNoaWxkLmNhbGwodGhpcywgY29sdW1uKTtcclxuICAgICAgICAgICAgX2Rpc3RyaWJ1dGVTcGFjZSh3aWR0aCk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jYW5Db250cmFjdENvbHVtblJpZ2h0ID0gZnVuY3Rpb24gKGNvbHVtbiwgY29ubmVjdEFkamFjZW50KSB7XHJcbiAgICAgICAgICAgIHZhciBpbmRleCA9IF8odGhpcy5jaGlsZHJlbikuaW5kZXhPZihjb2x1bW4pO1xyXG4gICAgICAgICAgICBpZiAoaW5kZXggPj0gMClcclxuICAgICAgICAgICAgICAgIHJldHVybiBjb2x1bW4ud2lkdGggPiAxO1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jb250cmFjdENvbHVtblJpZ2h0ID0gZnVuY3Rpb24gKGNvbHVtbiwgY29ubmVjdEFkamFjZW50KSB7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy5jYW5Db250cmFjdENvbHVtblJpZ2h0KGNvbHVtbiwgY29ubmVjdEFkamFjZW50KSlcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgICAgIHZhciBpbmRleCA9IF8odGhpcy5jaGlsZHJlbikuaW5kZXhPZihjb2x1bW4pO1xyXG4gICAgICAgICAgICBpZiAoaW5kZXggPj0gMCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKGNvbHVtbi53aWR0aCA+IDEpIHtcclxuICAgICAgICAgICAgICAgICAgICBjb2x1bW4ud2lkdGgtLTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5jaGlsZHJlbi5sZW5ndGggPiBpbmRleCArIDEpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5leHRDb2x1bW4gPSB0aGlzLmNoaWxkcmVuW2luZGV4ICsgMV07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb25uZWN0QWRqYWNlbnQgJiYgbmV4dENvbHVtbi5vZmZzZXQgPT0gMClcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5leHRDb2x1bW4ud2lkdGgrKztcclxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV4dENvbHVtbi5vZmZzZXQrKztcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLmNhbkV4cGFuZENvbHVtblJpZ2h0ID0gZnVuY3Rpb24gKGNvbHVtbiwgY29ubmVjdEFkamFjZW50KSB7XHJcbiAgICAgICAgICAgIHZhciBpbmRleCA9IF8odGhpcy5jaGlsZHJlbikuaW5kZXhPZihjb2x1bW4pO1xyXG4gICAgICAgICAgICBpZiAoaW5kZXggPj0gMCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKGNvbHVtbi53aWR0aCA+PSAxMilcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jaGlsZHJlbi5sZW5ndGggPiBpbmRleCArIDEpIHtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dENvbHVtbiA9IHRoaXMuY2hpbGRyZW5baW5kZXggKyAxXTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoY29ubmVjdEFkamFjZW50ICYmIG5leHRDb2x1bW4ub2Zmc2V0ID09IDApXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXh0Q29sdW1uLndpZHRoID4gMTtcclxuICAgICAgICAgICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXh0Q29sdW1uLm9mZnNldCA+IDA7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gX2dldFRvdGFsQ29sdW1uc1dpZHRoKCkgPCAxMjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5leHBhbmRDb2x1bW5SaWdodCA9IGZ1bmN0aW9uIChjb2x1bW4sIGNvbm5lY3RBZGphY2VudCkge1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMuY2FuRXhwYW5kQ29sdW1uUmlnaHQoY29sdW1uLCBjb25uZWN0QWRqYWNlbnQpKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICAgICAgdmFyIGluZGV4ID0gXyh0aGlzLmNoaWxkcmVuKS5pbmRleE9mKGNvbHVtbik7XHJcbiAgICAgICAgICAgIGlmIChpbmRleCA+PSAwKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jaGlsZHJlbi5sZW5ndGggPiBpbmRleCArIDEpIHtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dENvbHVtbiA9IHRoaXMuY2hpbGRyZW5baW5kZXggKyAxXTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoY29ubmVjdEFkamFjZW50ICYmIG5leHRDb2x1bW4ub2Zmc2V0ID09IDApXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG5leHRDb2x1bW4ud2lkdGgtLTtcclxuICAgICAgICAgICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG5leHRDb2x1bW4ub2Zmc2V0LS07XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBjb2x1bW4ud2lkdGgrKztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuY2FuRXhwYW5kQ29sdW1uTGVmdCA9IGZ1bmN0aW9uIChjb2x1bW4sIGNvbm5lY3RBZGphY2VudCkge1xyXG4gICAgICAgICAgICB2YXIgaW5kZXggPSBfKHRoaXMuY2hpbGRyZW4pLmluZGV4T2YoY29sdW1uKTtcclxuICAgICAgICAgICAgaWYgKGluZGV4ID49IDApIHtcclxuICAgICAgICAgICAgICAgIGlmIChjb2x1bW4ud2lkdGggPj0gMTIpXHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgaWYgKGluZGV4ID4gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2Q29sdW1uID0gdGhpcy5jaGlsZHJlbltpbmRleCAtIDFdO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChjb25uZWN0QWRqYWNlbnQgJiYgY29sdW1uLm9mZnNldCA9PSAwKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcHJldkNvbHVtbi53aWR0aCA+IDE7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gY29sdW1uLm9mZnNldCA+IDA7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuZXhwYW5kQ29sdW1uTGVmdCA9IGZ1bmN0aW9uIChjb2x1bW4sIGNvbm5lY3RBZGphY2VudCkge1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMuY2FuRXhwYW5kQ29sdW1uTGVmdChjb2x1bW4sIGNvbm5lY3RBZGphY2VudCkpXHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgICAgICB2YXIgaW5kZXggPSBfKHRoaXMuY2hpbGRyZW4pLmluZGV4T2YoY29sdW1uKTtcclxuICAgICAgICAgICAgaWYgKGluZGV4ID49IDApIHtcclxuICAgICAgICAgICAgICAgIGlmIChpbmRleCA+IDApIHtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgcHJldkNvbHVtbiA9IHRoaXMuY2hpbGRyZW5baW5kZXggLSAxXTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoY29ubmVjdEFkamFjZW50ICYmIGNvbHVtbi5vZmZzZXQgPT0gMClcclxuICAgICAgICAgICAgICAgICAgICAgICAgcHJldkNvbHVtbi53aWR0aC0tO1xyXG4gICAgICAgICAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29sdW1uLm9mZnNldC0tO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbi5vZmZzZXQtLTtcclxuICAgICAgICAgICAgICAgIGNvbHVtbi53aWR0aCsrO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jYW5Db250cmFjdENvbHVtbkxlZnQgPSBmdW5jdGlvbiAoY29sdW1uLCBjb25uZWN0QWRqYWNlbnQpIHtcclxuICAgICAgICAgICAgdmFyIGluZGV4ID0gXyh0aGlzLmNoaWxkcmVuKS5pbmRleE9mKGNvbHVtbik7XHJcbiAgICAgICAgICAgIGlmIChpbmRleCA+PSAwKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvbHVtbi53aWR0aCA+IDE7XHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLmNvbnRyYWN0Q29sdW1uTGVmdCA9IGZ1bmN0aW9uIChjb2x1bW4sIGNvbm5lY3RBZGphY2VudCkge1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMuY2FuQ29udHJhY3RDb2x1bW5MZWZ0KGNvbHVtbiwgY29ubmVjdEFkamFjZW50KSlcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgICAgIHZhciBpbmRleCA9IF8odGhpcy5jaGlsZHJlbikuaW5kZXhPZihjb2x1bW4pO1xyXG4gICAgICAgICAgICBpZiAoaW5kZXggPj0gMCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKGluZGV4ID4gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2Q29sdW1uID0gdGhpcy5jaGlsZHJlbltpbmRleCAtIDFdO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChjb25uZWN0QWRqYWNlbnQgJiYgY29sdW1uLm9mZnNldCA9PSAwKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2Q29sdW1uLndpZHRoKys7XHJcbiAgICAgICAgICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb2x1bW4ub2Zmc2V0Kys7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uLm9mZnNldCsrO1xyXG4gICAgICAgICAgICAgICAgY29sdW1uLndpZHRoLS07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLmV2ZW5Db2x1bW5zID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5jaGlsZHJlbi5sZW5ndGggPT0gMClcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgICAgIHZhciBldmVuV2lkdGggPSBNYXRoLmZsb29yKDEyIC8gdGhpcy5jaGlsZHJlbi5sZW5ndGgpO1xyXG4gICAgICAgICAgICBfKHRoaXMuY2hpbGRyZW4pLmVhY2goZnVuY3Rpb24gKGNvbHVtbikge1xyXG4gICAgICAgICAgICAgICAgY29sdW1uLndpZHRoID0gZXZlbldpZHRoO1xyXG4gICAgICAgICAgICAgICAgY29sdW1uLm9mZnNldCA9IDA7XHJcbiAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgdmFyIHJlc3QgPSAxMiAlIHRoaXMuY2hpbGRyZW4ubGVuZ3RoO1xyXG4gICAgICAgICAgICBpZiAocmVzdCA+IDApXHJcbiAgICAgICAgICAgICAgICBfZGlzdHJpYnV0ZVNwYWNlKHJlc3QpO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHZhciBfYmFzZVBhc3RlQ2hpbGQgPSB0aGlzLnBhc3RlQ2hpbGQ7XHJcbiAgICAgICAgdGhpcy5wYXN0ZUNoaWxkID0gZnVuY3Rpb24gKGNoaWxkKSB7XHJcbiAgICAgICAgICAgIGlmIChjaGlsZC50eXBlID09IFwiQ29sdW1uXCIpIHtcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmJlZ2luQWRkQ29sdW1uKGNoaWxkLndpZHRoKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29tbWl0QWRkQ29sdW1uKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgX2Jhc2VQYXN0ZUNoaWxkLmNhbGwodGhpcywgY2hpbGQpXHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSBpZiAoISF0aGlzLnBhcmVudClcclxuICAgICAgICAgICAgICAgIHRoaXMucGFyZW50LnBhc3RlQ2hpbGQoY2hpbGQpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy50b09iamVjdCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHRoaXMuZWxlbWVudFRvT2JqZWN0KCk7XHJcbiAgICAgICAgICAgIHJlc3VsdC5jaGlsZHJlbiA9IHRoaXMuY2hpbGRyZW5Ub09iamVjdCgpO1xyXG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgICAgIH07XHJcbiAgICB9O1xyXG5cclxuICAgIExheW91dEVkaXRvci5Sb3cuZnJvbSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xyXG4gICAgICAgIHZhciByZXN1bHQgPSBuZXcgTGF5b3V0RWRpdG9yLlJvdyhcclxuICAgICAgICAgICAgdmFsdWUuZGF0YSxcclxuICAgICAgICAgICAgdmFsdWUuaHRtbElkLFxyXG4gICAgICAgICAgICB2YWx1ZS5odG1sQ2xhc3MsXHJcbiAgICAgICAgICAgIHZhbHVlLmh0bWxTdHlsZSxcclxuICAgICAgICAgICAgdmFsdWUuaXNUZW1wbGF0ZWQsXHJcbiAgICAgICAgICAgIHZhbHVlLnJ1bGUsXHJcbiAgICAgICAgICAgIExheW91dEVkaXRvci5jaGlsZHJlbkZyb20odmFsdWUuY2hpbGRyZW4pKTtcclxuICAgICAgICByZXN1bHQudG9vbGJveEljb24gPSB2YWx1ZS50b29sYm94SWNvbjtcclxuICAgICAgICByZXN1bHQudG9vbGJveExhYmVsID0gdmFsdWUudG9vbGJveExhYmVsO1xyXG4gICAgICAgIHJlc3VsdC50b29sYm94RGVzY3JpcHRpb24gPSB2YWx1ZS50b29sYm94RGVzY3JpcHRpb247XHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgIH07XHJcblxyXG59KShMYXlvdXRFZGl0b3IgfHwgKExheW91dEVkaXRvciA9IHt9KSk7IiwidmFyIExheW91dEVkaXRvcjtcclxuKGZ1bmN0aW9uIChMYXlvdXRFZGl0b3IpIHtcclxuICAgIExheW91dEVkaXRvci5Db2x1bW4gPSBmdW5jdGlvbiAoZGF0YSwgaHRtbElkLCBodG1sQ2xhc3MsIGh0bWxTdHlsZSwgaXNUZW1wbGF0ZWQsIHdpZHRoLCBvZmZzZXQsIGNvbGxhcHNpYmxlLCBydWxlLCBjaGlsZHJlbikge1xyXG4gICAgICAgIExheW91dEVkaXRvci5FbGVtZW50LmNhbGwodGhpcywgXCJDb2x1bW5cIiwgZGF0YSwgaHRtbElkLCBodG1sQ2xhc3MsIGh0bWxTdHlsZSwgaXNUZW1wbGF0ZWQsIHJ1bGUpO1xyXG4gICAgICAgIExheW91dEVkaXRvci5Db250YWluZXIuY2FsbCh0aGlzLCBbXCJHcmlkXCIsIFwiQ29udGVudFwiXSwgY2hpbGRyZW4pO1xyXG5cclxuICAgICAgICB0aGlzLndpZHRoID0gd2lkdGg7XHJcbiAgICAgICAgdGhpcy5vZmZzZXQgPSBvZmZzZXQ7XHJcbiAgICAgICAgdGhpcy5jb2xsYXBzaWJsZSA9IGNvbGxhcHNpYmxlO1xyXG5cclxuICAgICAgICB2YXIgX2hhc1BlbmRpbmdDaGFuZ2UgPSBmYWxzZTtcclxuICAgICAgICB2YXIgX29yaWdXaWR0aCA9IDA7XHJcbiAgICAgICAgdmFyIF9vcmlnT2Zmc2V0ID0gMDtcclxuXHJcbiAgICAgICAgdGhpcy5iZWdpbkNoYW5nZSA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKCEhX2hhc1BlbmRpbmdDaGFuZ2UpXHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb2x1bW4gYWxyZWFkeSBoYXMgYSBwZW5kaW5nIGNoYW5nZS5cIik7XHJcbiAgICAgICAgICAgIF9oYXNQZW5kaW5nQ2hhbmdlID0gdHJ1ZTtcclxuICAgICAgICAgICAgX29yaWdXaWR0aCA9IHRoaXMud2lkdGg7XHJcbiAgICAgICAgICAgIF9vcmlnT2Zmc2V0ID0gdGhpcy5vZmZzZXQ7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jb21taXRDaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmICghX2hhc1BlbmRpbmdDaGFuZ2UpXHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb2x1bW4gaGFzIG5vIHBlbmRpbmcgY2hhbmdlLlwiKTtcclxuICAgICAgICAgICAgX29yaWdXaWR0aCA9IDA7XHJcbiAgICAgICAgICAgIF9vcmlnT2Zmc2V0ID0gMDtcclxuICAgICAgICAgICAgX2hhc1BlbmRpbmdDaGFuZ2UgPSBmYWxzZTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLnJvbGxiYWNrQ2hhbmdlID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICBpZiAoIV9oYXNQZW5kaW5nQ2hhbmdlKVxyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ29sdW1uIGhhcyBubyBwZW5kaW5nIGNoYW5nZS5cIik7XHJcbiAgICAgICAgICAgIHRoaXMud2lkdGggPSBfb3JpZ1dpZHRoO1xyXG4gICAgICAgICAgICB0aGlzLm9mZnNldCA9IF9vcmlnT2Zmc2V0O1xyXG4gICAgICAgICAgICBfb3JpZ1dpZHRoID0gMDtcclxuICAgICAgICAgICAgX29yaWdPZmZzZXQgPSAwO1xyXG4gICAgICAgICAgICBfaGFzUGVuZGluZ0NoYW5nZSA9IGZhbHNlO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuY2FuU3BsaXQgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmlzVGVtcGxhdGVkKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy53aWR0aCA+IDE7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5zcGxpdCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLmNhblNwbGl0KCkpXHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgICAgICB2YXIgbmV3Q29sdW1uV2lkdGggPSBNYXRoLmZsb29yKHRoaXMud2lkdGggLyAyKTtcclxuICAgICAgICAgICAgdmFyIG5ld0NvbHVtbiA9IExheW91dEVkaXRvci5Db2x1bW4uZnJvbSh7XHJcbiAgICAgICAgICAgICAgICBkYXRhOiBudWxsLFxyXG4gICAgICAgICAgICAgICAgaHRtbElkOiBudWxsLFxyXG4gICAgICAgICAgICAgICAgaHRtbENsYXNzOiBudWxsLFxyXG4gICAgICAgICAgICAgICAgaHRtbFN0eWxlOiBudWxsLFxyXG4gICAgICAgICAgICAgICAgd2lkdGg6IG5ld0NvbHVtbldpZHRoLFxyXG4gICAgICAgICAgICAgICAgb2Zmc2V0OiAwLFxyXG4gICAgICAgICAgICAgICAgY2hpbGRyZW46IFtdXHJcbiAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgdGhpcy53aWR0aCA9IHRoaXMud2lkdGggLSBuZXdDb2x1bW5XaWR0aDtcclxuICAgICAgICAgICAgdGhpcy5wYXJlbnQuaW5zZXJ0Q2hpbGQobmV3Q29sdW1uLCB0aGlzKTtcclxuICAgICAgICAgICAgbmV3Q29sdW1uLnNldElzRm9jdXNlZCgpO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuY2FuQ29udHJhY3RSaWdodCA9IGZ1bmN0aW9uIChjb25uZWN0QWRqYWNlbnQpIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuaXNUZW1wbGF0ZWQpXHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnBhcmVudC5jYW5Db250cmFjdENvbHVtblJpZ2h0KHRoaXMsIGNvbm5lY3RBZGphY2VudCk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jb250cmFjdFJpZ2h0ID0gZnVuY3Rpb24gKGNvbm5lY3RBZGphY2VudCkge1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMuY2FuQ29udHJhY3RSaWdodChjb25uZWN0QWRqYWNlbnQpKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB0aGlzLnBhcmVudC5jb250cmFjdENvbHVtblJpZ2h0KHRoaXMsIGNvbm5lY3RBZGphY2VudCk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jYW5FeHBhbmRSaWdodCA9IGZ1bmN0aW9uIChjb25uZWN0QWRqYWNlbnQpIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuaXNUZW1wbGF0ZWQpXHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnBhcmVudC5jYW5FeHBhbmRDb2x1bW5SaWdodCh0aGlzLCBjb25uZWN0QWRqYWNlbnQpO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuZXhwYW5kUmlnaHQgPSBmdW5jdGlvbiAoY29ubmVjdEFkamFjZW50KSB7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy5jYW5FeHBhbmRSaWdodChjb25uZWN0QWRqYWNlbnQpKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB0aGlzLnBhcmVudC5leHBhbmRDb2x1bW5SaWdodCh0aGlzLCBjb25uZWN0QWRqYWNlbnQpO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuY2FuRXhwYW5kTGVmdCA9IGZ1bmN0aW9uIChjb25uZWN0QWRqYWNlbnQpIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuaXNUZW1wbGF0ZWQpXHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnBhcmVudC5jYW5FeHBhbmRDb2x1bW5MZWZ0KHRoaXMsIGNvbm5lY3RBZGphY2VudCk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5leHBhbmRMZWZ0ID0gZnVuY3Rpb24gKGNvbm5lY3RBZGphY2VudCkge1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMuY2FuRXhwYW5kTGVmdChjb25uZWN0QWRqYWNlbnQpKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB0aGlzLnBhcmVudC5leHBhbmRDb2x1bW5MZWZ0KHRoaXMsIGNvbm5lY3RBZGphY2VudCk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jYW5Db250cmFjdExlZnQgPSBmdW5jdGlvbiAoY29ubmVjdEFkamFjZW50KSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmlzVGVtcGxhdGVkKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5wYXJlbnQuY2FuQ29udHJhY3RDb2x1bW5MZWZ0KHRoaXMsIGNvbm5lY3RBZGphY2VudCk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy5jb250cmFjdExlZnQgPSBmdW5jdGlvbiAoY29ubmVjdEFkamFjZW50KSB7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy5jYW5Db250cmFjdExlZnQoY29ubmVjdEFkamFjZW50KSlcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgdGhpcy5wYXJlbnQuY29udHJhY3RDb2x1bW5MZWZ0KHRoaXMsIGNvbm5lY3RBZGphY2VudCk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgdGhpcy50b09iamVjdCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHRoaXMuZWxlbWVudFRvT2JqZWN0KCk7XHJcbiAgICAgICAgICAgIHJlc3VsdC53aWR0aCA9IHRoaXMud2lkdGg7XHJcbiAgICAgICAgICAgIHJlc3VsdC5vZmZzZXQgPSB0aGlzLm9mZnNldDtcclxuICAgICAgICAgICAgcmVzdWx0LmNvbGxhcHNpYmxlID0gdGhpcy5jb2xsYXBzaWJsZTtcclxuICAgICAgICAgICAgcmVzdWx0LmNoaWxkcmVuID0gdGhpcy5jaGlsZHJlblRvT2JqZWN0KCk7XHJcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICAgICAgfTtcclxuICAgIH07XHJcblxyXG4gICAgTGF5b3V0RWRpdG9yLkNvbHVtbi5mcm9tID0gZnVuY3Rpb24gKHZhbHVlKSB7XHJcbiAgICAgICAgdmFyIHJlc3VsdCA9IG5ldyBMYXlvdXRFZGl0b3IuQ29sdW1uKFxyXG4gICAgICAgICAgICB2YWx1ZS5kYXRhLFxyXG4gICAgICAgICAgICB2YWx1ZS5odG1sSWQsXHJcbiAgICAgICAgICAgIHZhbHVlLmh0bWxDbGFzcyxcclxuICAgICAgICAgICAgdmFsdWUuaHRtbFN0eWxlLFxyXG4gICAgICAgICAgICB2YWx1ZS5pc1RlbXBsYXRlZCxcclxuICAgICAgICAgICAgdmFsdWUud2lkdGgsXHJcbiAgICAgICAgICAgIHZhbHVlLm9mZnNldCxcclxuICAgICAgICAgICAgdmFsdWUuY29sbGFwc2libGUsXHJcbiAgICAgICAgICAgIHZhbHVlLnJ1bGUsXHJcbiAgICAgICAgICAgIExheW91dEVkaXRvci5jaGlsZHJlbkZyb20odmFsdWUuY2hpbGRyZW4pKTtcclxuICAgICAgICByZXN1bHQudG9vbGJveEljb24gPSB2YWx1ZS50b29sYm94SWNvbjtcclxuICAgICAgICByZXN1bHQudG9vbGJveExhYmVsID0gdmFsdWUudG9vbGJveExhYmVsO1xyXG4gICAgICAgIHJlc3VsdC50b29sYm94RGVzY3JpcHRpb24gPSB2YWx1ZS50b29sYm94RGVzY3JpcHRpb247XHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgIH07XHJcblxyXG4gICAgTGF5b3V0RWRpdG9yLkNvbHVtbi50aW1lcyA9IGZ1bmN0aW9uICh2YWx1ZSkge1xyXG4gICAgICAgIHJldHVybiBfLnRpbWVzKHZhbHVlLCBmdW5jdGlvbiAobikge1xyXG4gICAgICAgICAgICByZXR1cm4gTGF5b3V0RWRpdG9yLkNvbHVtbi5mcm9tKHtcclxuICAgICAgICAgICAgICAgIGRhdGE6IG51bGwsXHJcbiAgICAgICAgICAgICAgICBodG1sSWQ6IG51bGwsXHJcbiAgICAgICAgICAgICAgICBodG1sQ2xhc3M6IG51bGwsXHJcbiAgICAgICAgICAgICAgICBpc1RlbXBsYXRlZDogZmFsc2UsXHJcbiAgICAgICAgICAgICAgICB3aWR0aDogMTIgLyB2YWx1ZSxcclxuICAgICAgICAgICAgICAgIG9mZnNldDogMCxcclxuICAgICAgICAgICAgICAgIGNvbGxhcHNpYmxlOiBudWxsLFxyXG4gICAgICAgICAgICAgICAgY2hpbGRyZW46IFtdXHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfTtcclxufSkoTGF5b3V0RWRpdG9yIHx8IChMYXlvdXRFZGl0b3IgPSB7fSkpOyIsInZhciBMYXlvdXRFZGl0b3I7XHJcbihmdW5jdGlvbiAoTGF5b3V0RWRpdG9yKSB7XHJcblxyXG4gICAgTGF5b3V0RWRpdG9yLkNvbnRlbnQgPSBmdW5jdGlvbiAoZGF0YSwgaHRtbElkLCBodG1sQ2xhc3MsIGh0bWxTdHlsZSwgaXNUZW1wbGF0ZWQsIGNvbnRlbnRUeXBlLCBjb250ZW50VHlwZUxhYmVsLCBjb250ZW50VHlwZUNsYXNzLCBodG1sLCBoYXNFZGl0b3IsIHJ1bGUpIHtcclxuICAgICAgICBMYXlvdXRFZGl0b3IuRWxlbWVudC5jYWxsKHRoaXMsIFwiQ29udGVudFwiLCBkYXRhLCBodG1sSWQsIGh0bWxDbGFzcywgaHRtbFN0eWxlLCBpc1RlbXBsYXRlZCwgcnVsZSk7XHJcblxyXG4gICAgICAgIHRoaXMuY29udGVudFR5cGUgPSBjb250ZW50VHlwZTtcclxuICAgICAgICB0aGlzLmNvbnRlbnRUeXBlTGFiZWwgPSBjb250ZW50VHlwZUxhYmVsO1xyXG4gICAgICAgIHRoaXMuY29udGVudFR5cGVDbGFzcyA9IGNvbnRlbnRUeXBlQ2xhc3M7XHJcbiAgICAgICAgdGhpcy5odG1sID0gaHRtbDtcclxuICAgICAgICB0aGlzLmhhc0VkaXRvciA9IGhhc0VkaXRvcjtcclxuXHJcbiAgICAgICAgdGhpcy5nZXRJbm5lclRleHQgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiAkKCQucGFyc2VIVE1MKFwiPGRpdj5cIiArIHRoaXMuaHRtbCArIFwiPC9kaXY+XCIpKS50ZXh0KCk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgLy8gVGhpcyBmdW5jdGlvbiB3aWxsIGJlIG92ZXJ3cml0dGVuIGJ5IHRoZSBDb250ZW50IGRpcmVjdGl2ZS5cclxuICAgICAgICB0aGlzLnNldEh0bWwgPSBmdW5jdGlvbiAoaHRtbCkge1xyXG4gICAgICAgICAgICB0aGlzLmh0bWwgPSBodG1sO1xyXG4gICAgICAgICAgICB0aGlzLmh0bWxVbnNhZmUgPSBodG1sO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy50b09iamVjdCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgICAgIFwidHlwZVwiOiBcIkNvbnRlbnRcIlxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMudG9PYmplY3QgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHZhciByZXN1bHQgPSB0aGlzLmVsZW1lbnRUb09iamVjdCgpO1xyXG4gICAgICAgICAgICByZXN1bHQuY29udGVudFR5cGUgPSB0aGlzLmNvbnRlbnRUeXBlO1xyXG4gICAgICAgICAgICByZXN1bHQuY29udGVudFR5cGVMYWJlbCA9IHRoaXMuY29udGVudFR5cGVMYWJlbDtcclxuICAgICAgICAgICAgcmVzdWx0LmNvbnRlbnRUeXBlQ2xhc3MgPSB0aGlzLmNvbnRlbnRUeXBlQ2xhc3M7XHJcbiAgICAgICAgICAgIHJlc3VsdC5odG1sID0gdGhpcy5odG1sO1xyXG4gICAgICAgICAgICByZXN1bHQuaGFzRWRpdG9yID0gaGFzRWRpdG9yO1xyXG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMuc2V0SHRtbChodG1sKTtcclxuICAgIH07XHJcblxyXG4gICAgTGF5b3V0RWRpdG9yLkNvbnRlbnQuZnJvbSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xyXG4gICAgICAgIHZhciByZXN1bHQgPSBuZXcgTGF5b3V0RWRpdG9yLkNvbnRlbnQoXHJcbiAgICAgICAgICAgIHZhbHVlLmRhdGEsXHJcbiAgICAgICAgICAgIHZhbHVlLmh0bWxJZCxcclxuICAgICAgICAgICAgdmFsdWUuaHRtbENsYXNzLFxyXG4gICAgICAgICAgICB2YWx1ZS5odG1sU3R5bGUsXHJcbiAgICAgICAgICAgIHZhbHVlLmlzVGVtcGxhdGVkLFxyXG4gICAgICAgICAgICB2YWx1ZS5jb250ZW50VHlwZSxcclxuICAgICAgICAgICAgdmFsdWUuY29udGVudFR5cGVMYWJlbCxcclxuICAgICAgICAgICAgdmFsdWUuY29udGVudFR5cGVDbGFzcyxcclxuICAgICAgICAgICAgdmFsdWUuaHRtbCxcclxuICAgICAgICAgICAgdmFsdWUuaGFzRWRpdG9yLFxyXG4gICAgICAgICAgICB2YWx1ZS5ydWxlKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgIH07XHJcblxyXG59KShMYXlvdXRFZGl0b3IgfHwgKExheW91dEVkaXRvciA9IHt9KSk7IiwidmFyIExheW91dEVkaXRvcjtcclxuKGZ1bmN0aW9uICgkLCBMYXlvdXRFZGl0b3IpIHtcclxuXHJcbiAgICBMYXlvdXRFZGl0b3IuSHRtbCA9IGZ1bmN0aW9uIChkYXRhLCBodG1sSWQsIGh0bWxDbGFzcywgaHRtbFN0eWxlLCBpc1RlbXBsYXRlZCwgY29udGVudFR5cGUsIGNvbnRlbnRUeXBlTGFiZWwsIGNvbnRlbnRUeXBlQ2xhc3MsIGh0bWwsIGhhc0VkaXRvciwgcnVsZSkge1xyXG4gICAgICAgIExheW91dEVkaXRvci5FbGVtZW50LmNhbGwodGhpcywgXCJIdG1sXCIsIGRhdGEsIGh0bWxJZCwgaHRtbENsYXNzLCBodG1sU3R5bGUsIGlzVGVtcGxhdGVkLCBydWxlKTtcclxuXHJcbiAgICAgICAgdGhpcy5jb250ZW50VHlwZSA9IGNvbnRlbnRUeXBlO1xyXG4gICAgICAgIHRoaXMuY29udGVudFR5cGVMYWJlbCA9IGNvbnRlbnRUeXBlTGFiZWw7XHJcbiAgICAgICAgdGhpcy5jb250ZW50VHlwZUNsYXNzID0gY29udGVudFR5cGVDbGFzcztcclxuICAgICAgICB0aGlzLmh0bWwgPSBodG1sO1xyXG4gICAgICAgIHRoaXMuaGFzRWRpdG9yID0gaGFzRWRpdG9yO1xyXG4gICAgICAgIHRoaXMuaXNDb250YWluYWJsZSA9IHRydWU7XHJcblxyXG4gICAgICAgIHRoaXMuZ2V0SW5uZXJUZXh0ID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gJCgkLnBhcnNlSFRNTChcIjxkaXY+XCIgKyB0aGlzLmh0bWwgKyBcIjwvZGl2PlwiKSkudGV4dCgpO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIC8vIFRoaXMgZnVuY3Rpb24gd2lsbCBiZSBvdmVyd3JpdHRlbiBieSB0aGUgQ29udGVudCBkaXJlY3RpdmUuXHJcbiAgICAgICAgdGhpcy5zZXRIdG1sID0gZnVuY3Rpb24gKGh0bWwpIHtcclxuICAgICAgICAgICAgdGhpcy5odG1sID0gaHRtbDtcclxuICAgICAgICAgICAgdGhpcy5odG1sVW5zYWZlID0gaHRtbDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMudG9PYmplY3QgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgICAgICBcInR5cGVcIjogXCJIdG1sXCJcclxuICAgICAgICAgICAgfTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB0aGlzLnRvT2JqZWN0ID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gdGhpcy5lbGVtZW50VG9PYmplY3QoKTtcclxuICAgICAgICAgICAgcmVzdWx0LmNvbnRlbnRUeXBlID0gdGhpcy5jb250ZW50VHlwZTtcclxuICAgICAgICAgICAgcmVzdWx0LmNvbnRlbnRUeXBlTGFiZWwgPSB0aGlzLmNvbnRlbnRUeXBlTGFiZWw7XHJcbiAgICAgICAgICAgIHJlc3VsdC5jb250ZW50VHlwZUNsYXNzID0gdGhpcy5jb250ZW50VHlwZUNsYXNzO1xyXG4gICAgICAgICAgICByZXN1bHQuaHRtbCA9IHRoaXMuaHRtbDtcclxuICAgICAgICAgICAgcmVzdWx0Lmhhc0VkaXRvciA9IGhhc0VkaXRvcjtcclxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB2YXIgZ2V0RWRpdG9yT2JqZWN0ID0gdGhpcy5nZXRFZGl0b3JPYmplY3Q7XHJcbiAgICAgICAgdGhpcy5nZXRFZGl0b3JPYmplY3QgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHZhciBkdG8gPSBnZXRFZGl0b3JPYmplY3QoKTtcclxuICAgICAgICAgICAgcmV0dXJuICQuZXh0ZW5kKGR0bywge1xyXG4gICAgICAgICAgICAgICAgQ29udGVudDogdGhpcy5odG1sXHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5zZXRIdG1sKGh0bWwpO1xyXG4gICAgfTtcclxuXHJcbiAgICBMYXlvdXRFZGl0b3IuSHRtbC5mcm9tID0gZnVuY3Rpb24gKHZhbHVlKSB7XHJcbiAgICAgICAgdmFyIHJlc3VsdCA9IG5ldyBMYXlvdXRFZGl0b3IuSHRtbChcclxuICAgICAgICAgICAgdmFsdWUuZGF0YSxcclxuICAgICAgICAgICAgdmFsdWUuaHRtbElkLFxyXG4gICAgICAgICAgICB2YWx1ZS5odG1sQ2xhc3MsXHJcbiAgICAgICAgICAgIHZhbHVlLmh0bWxTdHlsZSxcclxuICAgICAgICAgICAgdmFsdWUuaXNUZW1wbGF0ZWQsXHJcbiAgICAgICAgICAgIHZhbHVlLmNvbnRlbnRUeXBlLFxyXG4gICAgICAgICAgICB2YWx1ZS5jb250ZW50VHlwZUxhYmVsLFxyXG4gICAgICAgICAgICB2YWx1ZS5jb250ZW50VHlwZUNsYXNzLFxyXG4gICAgICAgICAgICB2YWx1ZS5odG1sLFxyXG4gICAgICAgICAgICB2YWx1ZS5oYXNFZGl0b3IsXHJcbiAgICAgICAgICAgIHZhbHVlLnJ1bGUpO1xyXG5cclxuICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgfTtcclxuXHJcbiAgICBMYXlvdXRFZGl0b3IucmVnaXN0ZXJGYWN0b3J5KFwiSHRtbFwiLCBmdW5jdGlvbih2YWx1ZSkgeyByZXR1cm4gTGF5b3V0RWRpdG9yLkh0bWwuZnJvbSh2YWx1ZSk7IH0pO1xyXG5cclxufSkoalF1ZXJ5LCBMYXlvdXRFZGl0b3IgfHwgKExheW91dEVkaXRvciA9IHt9KSk7Il0sInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Scripts/Models.min.js b/src/Orchard.Web/Modules/Orchard.Layouts/Scripts/Models.min.js index de69e3feb..9f7d3923c 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Scripts/Models.min.js +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Scripts/Models.min.js @@ -1 +1 @@ -var LayoutEditor;!function(t){Array.prototype.move=function(t,i){this.splice(i,0,this.splice(t,1)[0])},t.childrenFrom=function(i){return _(i).map(function(i){return t.elementFrom(i)})};var i=t.registerFactory=function(i,n){var e=t.factories=t.factories||{};e[i]=n};i("Canvas",function(i){return t.Canvas.from(i)}),i("Grid",function(i){return t.Grid.from(i)}),i("Row",function(i){return t.Row.from(i)}),i("Column",function(i){return t.Column.from(i)}),i("Content",function(i){return t.Content.from(i)}),t.elementFrom=function(i){var n=t.factories[i.type];if(!n)throw new Error('No element with type "'+i.type+'" was found.');var e=n(i);return e},t.setModel=function(t,i){$(t).scope().element=i},t.getModel=function(t){return $(t).scope().element}}(LayoutEditor||(LayoutEditor={}));var LayoutEditor;!function(t){t.Editor=function(i,n){this.config=i,this.canvas=t.Canvas.from(n),this.initialState=JSON.stringify(this.canvas.toObject()),this.activeElement=null,this.focusedElement=null,this.dropTargetElement=null,this.isDragging=!1,this.inlineEditingIsActive=!1,this.isResizing=!1,this.resetToolboxElements=function(){this.toolboxElements=[t.Row.from({children:[]})]},this.isDirty=function(){var t=JSON.stringify(this.canvas.toObject());return this.initialState!=t},this.resetToolboxElements(),this.canvas.setEditor(this)}}(LayoutEditor||(LayoutEditor={}));var LayoutEditor;!function(t){t.Element=function(t,i,n,e,o,s,h){if(!t)throw new Error("Parameter 'type' is required.");this.type=t,this.data=i,this.htmlId=n,this.htmlClass=e,this.htmlStyle=o,this.isTemplated=s,this.rule=h,this.editor=null,this.parent=null,this.setIsFocusedEventHandlers=[],this.setEditor=function(t){this.editor=t,this.children&&_.isArray(this.children)&&_(this.children).each(function(i){i.setEditor(t)})},this.setParent=function(t){this.parent=t,this.parent.onChildAdded(this);for(var i=t;i;)i.onDescendantAdded(this,t),i=i.parent},this.setIsTemplated=function(t){this.isTemplated=t,this.children&&_.isArray(this.children)&&_(this.children).each(function(i){i.setIsTemplated(t)})},this.applyElementEditorModel=function(){},this.getIsActive=function(){return this.editor?this.editor.activeElement===this&&!this.getIsFocused():!1},this.setIsActive=function(t){this.editor&&(this.editor.isDragging||this.editor.inlineEditingIsActive||this.editor.isResizing||(this.editor.activeElement=t?this:this.parent))},this.getIsFocused=function(){return this.editor?this.editor.focusedElement===this:!1},this.setIsFocused=function(){this.editor&&(this.children||!this.isTemplated)&&(this.editor.isDragging||this.editor.inlineEditingIsActive||this.editor.isResizing||(this.editor.focusedElement=this,_(this.setIsFocusedEventHandlers).each(function(t){try{t()}catch(i){}})))},this.getIsSelected=function(){return this.getIsFocused()?!0:this.children&&_.isArray(this.children)?_(this.children).any(function(t){return t.getIsSelected()}):!1},this.getIsDropTarget=function(){return this.editor?this.editor.dropTargetElement===this:!1},this.setIsDropTarget=function(t){this.editor&&(this.editor.dropTargetElement=t?this:null)},this.canDelete=function(){return this.isTemplated||!this.parent?!1:!0},this["delete"]=function(){this.canDelete()&&this.parent.deleteChild(this)},this.canMoveUp=function(){return this.isTemplated||!this.parent?!1:this.parent.canMoveChildUp(this)},this.moveUp=function(){this.canMoveUp()&&this.parent.moveChildUp(this)},this.canMoveDown=function(){return this.isTemplated||!this.parent?!1:this.parent.canMoveChildDown(this)},this.moveDown=function(){this.canMoveDown()&&this.parent.moveChildDown(this)},this.elementToObject=function(){return{type:this.type,data:this.data,htmlId:this.htmlId,htmlClass:this.htmlClass,htmlStyle:this.htmlStyle,isTemplated:this.isTemplated,rule:this.rule}},this.getEditorObject=function(){return{}},this.copy=function(t){var i=this.getInnerText();t.setData("text/plain",i);var n=this.toObject(),e=JSON.stringify(n,null," ");t.setData("text/json",e)},this.cut=function(t){this.canDelete()&&(this.copy(t),this["delete"]())},this.paste=function(t){this.parent&&this.parent.paste(t)}}}(LayoutEditor||(LayoutEditor={}));var LayoutEditor;!function(t){t.Container=function(i,n){this.allowedChildTypes=i,this.children=n,this.isContainer=!0;var e=this;this.onChildAdded=function(t){},this.onDescendantAdded=function(t,i){},this.setChildren=function(t){this.children=t,_(this.children).each(function(t){t.setParent(e)})},this.setChildren(n),this.getIsSealed=function(){return _(this.children).any(function(t){return t.isTemplated})};var o=this.setIsFocused;this.setIsFocused=function(){this.getIsSealed()||o.call(this)},this.addChild=function(t){_(this.children).contains(t)||!_(this.allowedChildTypes).contains(t.type)&&!t.isContainable||this.children.push(t),t.setEditor(this.editor),t.setIsTemplated(!1),t.setParent(this)},this.deleteChild=function(t){var i=_(this.children).indexOf(t);i>=0&&(this.children.splice(i,1),t.getIsActive()&&(this.editor.activeElement=null),t.getIsFocused()&&(this.children.length>i?this.children[i].setIsFocused():i>0?this.children[i-1].setIsFocused():this.setIsFocused()))},this.moveFocusPrevChild=function(t){if(!(this.children.length<2)){var i=_(this.children).indexOf(t);i>0&&this.children[i-1].setIsFocused()}},this.moveFocusNextChild=function(t){if(!(this.children.length<2)){var i=_(this.children).indexOf(t);i0},this.canMoveChildDown=function(t){var i=_(this.children).indexOf(t);return i0?t.width<12:0>e?t.width>1:!1}if(0==t)return!0;var e=t;if(0>e){var o=12-c();e+=o,e>0&&(e=0)}for(;0>e&&_(d.children).any(function(t){return t.offset>0});)for(i=0;ie;i++){var s=d.children[i];s.offset>0&&(s.offset--,e++)}for(;0!=e&&_(d.children).any(n);)for(i=0;i=0?t.width>1:!1},this.contractColumnRight=function(t,i){if(this.canContractColumnRight(t,i)){var n=_(this.children).indexOf(t);if(n>=0&&t.width>1&&(t.width--,this.children.length>n+1)){var e=this.children[n+1];i&&0==e.offset?e.width++:e.offset++}}},this.canExpandColumnRight=function(t,i){var n=_(this.children).indexOf(t);if(n>=0){if(t.width>=12)return!1;if(this.children.length>n+1){var e=this.children[n+1];return i&&0==e.offset?e.width>1:e.offset>0}return c()<12}return!1},this.expandColumnRight=function(t,i){if(this.canExpandColumnRight(t,i)){var n=_(this.children).indexOf(t);if(n>=0){if(this.children.length>n+1){var e=this.children[n+1];i&&0==e.offset?e.width--:e.offset--}t.width++}}},this.canExpandColumnLeft=function(t,i){var n=_(this.children).indexOf(t);if(n>=0){if(t.width>=12)return!1;if(n>0){var e=this.children[n-1];if(i&&0==t.offset)return e.width>1}return t.offset>0}return!1},this.expandColumnLeft=function(t,i){if(this.canExpandColumnLeft(t,i)){var n=_(this.children).indexOf(t);if(n>=0){if(n>0){var e=this.children[n-1];i&&0==t.offset?e.width--:t.offset--}else t.offset--;t.width++}}},this.canContractColumnLeft=function(t,i){var n=_(this.children).indexOf(t);return n>=0?t.width>1:!1},this.contractColumnLeft=function(t,i){if(this.canContractColumnLeft(t,i)){var n=_(this.children).indexOf(t);if(n>=0){if(n>0){var e=this.children[n-1];i&&0==t.offset?e.width++:t.offset++}else t.offset++;t.width--}}},this.evenColumns=function(){if(0!=this.children.length){var t=Math.floor(12/this.children.length);_(this.children).each(function(i){i.width=t,i.offset=0});var i=12%this.children.length;i>0&&a(i)}};var m=this.pasteChild;this.pasteChild=function(t){"Column"==t.type?this.beginAddColumn(t.width)&&(this.commitAddColumn(),m.call(this,t)):this.parent&&this.parent.pasteChild(t)},this.toObject=function(){var t=this.elementToObject();return t.children=this.childrenToObject(),t}},t.Row.from=function(i){var n=new t.Row(i.data,i.htmlId,i.htmlClass,i.htmlStyle,i.isTemplated,i.rule,t.childrenFrom(i.children));return n.toolboxIcon=i.toolboxIcon,n.toolboxLabel=i.toolboxLabel,n.toolboxDescription=i.toolboxDescription,n}}(LayoutEditor||(LayoutEditor={}));var LayoutEditor;!function(t){t.Column=function(i,n,e,o,s,h,r,l,c,a){t.Element.call(this,"Column",i,n,e,o,s,c),t.Container.call(this,["Grid","Content"],a),this.width=h,this.offset=r,this.collapsible=l;var d=!1,u=0,f=0;this.beginChange=function(){if(d)throw new Error("Column already has a pending change.");d=!0,u=this.width,f=this.offset},this.commitChange=function(){if(!d)throw new Error("Column has no pending change.");u=0,f=0,d=!1},this.rollbackChange=function(){if(!d)throw new Error("Column has no pending change.");this.width=u,this.offset=f,u=0,f=0,d=!1},this.canSplit=function(){return this.isTemplated?!1:this.width>1},this.split=function(){if(this.canSplit()){var i=Math.floor(this.width/2),n=t.Column.from({data:null,htmlId:null,htmlClass:null,htmlStyle:null,width:i,offset:0,children:[]});this.width=this.width-i,this.parent.insertChild(n,this),n.setIsFocused()}},this.canContractRight=function(t){return this.isTemplated?!1:this.parent.canContractColumnRight(this,t)},this.contractRight=function(t){this.canContractRight(t)&&this.parent.contractColumnRight(this,t)},this.canExpandRight=function(t){return this.isTemplated?!1:this.parent.canExpandColumnRight(this,t)},this.expandRight=function(t){this.canExpandRight(t)&&this.parent.expandColumnRight(this,t)},this.canExpandLeft=function(t){return this.isTemplated?!1:this.parent.canExpandColumnLeft(this,t)},this.expandLeft=function(t){this.canExpandLeft(t)&&this.parent.expandColumnLeft(this,t)},this.canContractLeft=function(t){return this.isTemplated?!1:this.parent.canContractColumnLeft(this,t)},this.contractLeft=function(t){this.canContractLeft(t)&&this.parent.contractColumnLeft(this,t)},this.toObject=function(){var t=this.elementToObject();return t.width=this.width,t.offset=this.offset,t.collapsible=this.collapsible,t.children=this.childrenToObject(),t}},t.Column.from=function(i){var n=new t.Column(i.data,i.htmlId,i.htmlClass,i.htmlStyle,i.isTemplated,i.width,i.offset,i.collapsible,i.rule,t.childrenFrom(i.children));return n.toolboxIcon=i.toolboxIcon,n.toolboxLabel=i.toolboxLabel,n.toolboxDescription=i.toolboxDescription,n},t.Column.times=function(i){return _.times(i,function(n){return t.Column.from({data:null,htmlId:null,htmlClass:null,isTemplated:!1,width:12/i,offset:0,collapsible:null,children:[]})})}}(LayoutEditor||(LayoutEditor={}));var LayoutEditor;!function(t){t.Content=function(i,n,e,o,s,h,r,l,c,a,d){t.Element.call(this,"Content",i,n,e,o,s,d),this.contentType=h,this.contentTypeLabel=r,this.contentTypeClass=l,this.html=c,this.hasEditor=a,this.getInnerText=function(){return $($.parseHTML("
"+this.html+"
")).text()},this.setHtml=function(t){this.html=t,this.htmlUnsafe=t},this.toObject=function(){return{type:"Content"}},this.toObject=function(){var t=this.elementToObject();return t.contentType=this.contentType,t.contentTypeLabel=this.contentTypeLabel,t.contentTypeClass=this.contentTypeClass,t.html=this.html,t.hasEditor=a,t},this.setHtml(c)},t.Content.from=function(i){var n=new t.Content(i.data,i.htmlId,i.htmlClass,i.htmlStyle,i.isTemplated,i.contentType,i.contentTypeLabel,i.contentTypeClass,i.html,i.hasEditor,i.rule);return n}}(LayoutEditor||(LayoutEditor={}));var LayoutEditor;!function(t,i){i.Html=function(n,e,o,s,h,r,l,c,a,d,u){i.Element.call(this,"Html",n,e,o,s,h,u),this.contentType=r,this.contentTypeLabel=l,this.contentTypeClass=c,this.html=a,this.hasEditor=d,this.isContainable=!0,this.getInnerText=function(){return t(t.parseHTML("
"+this.html+"
")).text()},this.setHtml=function(t){this.html=t,this.htmlUnsafe=t},this.toObject=function(){return{type:"Html"}},this.toObject=function(){var t=this.elementToObject();return t.contentType=this.contentType,t.contentTypeLabel=this.contentTypeLabel,t.contentTypeClass=this.contentTypeClass,t.html=this.html,t.hasEditor=d,t};var f=this.getEditorObject;this.getEditorObject=function(){var i=f();return t.extend(i,{Content:this.html})},this.setHtml(a)},i.Html.from=function(t){var n=new i.Html(t.data,t.htmlId,t.htmlClass,t.htmlStyle,t.isTemplated,t.contentType,t.contentTypeLabel,t.contentTypeClass,t.html,t.hasEditor,t.rule);return n},i.registerFactory("Html",function(t){return i.Html.from(t)})}(jQuery,LayoutEditor||(LayoutEditor={})); \ No newline at end of file +var LayoutEditor;!function(t){Array.prototype.move=function(t,i){this.splice(i,0,this.splice(t,1)[0])},t.childrenFrom=function(i){return _(i).map(function(i){return t.elementFrom(i)})};var i=t.registerFactory=function(i,n){var e=t.factories=t.factories||{};e[i]=n};i("Canvas",function(i){return t.Canvas.from(i)}),i("Grid",function(i){return t.Grid.from(i)}),i("Row",function(i){return t.Row.from(i)}),i("Column",function(i){return t.Column.from(i)}),i("Content",function(i){return t.Content.from(i)}),t.elementFrom=function(i){var n=t.factories[i.type];if(!n)throw new Error('No element with type "'+i.type+'" was found.');var e=n(i);return e},t.setModel=function(t,i){$(t).scope().element=i},t.getModel=function(t){return $(t).scope().element}}(LayoutEditor||(LayoutEditor={}));var LayoutEditor;!function(t){t.Editor=function(i,n){this.config=i,this.canvas=t.Canvas.from(n),this.initialState=JSON.stringify(this.canvas.toObject()),this.activeElement=null,this.focusedElement=null,this.dropTargetElement=null,this.isDragging=!1,this.isResizing=!1,this.resetToolboxElements=function(){this.toolboxElements=[t.Row.from({children:[]})]},this.isDirty=function(){var t=JSON.stringify(this.canvas.toObject());return this.initialState!=t},this.resetToolboxElements(),this.canvas.setEditor(this)}}(LayoutEditor||(LayoutEditor={}));var LayoutEditor;!function(t){t.Element=function(t,i,n,e,o,s,h){if(!t)throw new Error("Parameter 'type' is required.");this.type=t,this.data=i,this.htmlId=n,this.htmlClass=e,this.htmlStyle=o,this.isTemplated=s,this.rule=h,this.editor=null,this.parent=null,this.setIsFocusedEventHandlers=[],this.setEditor=function(t){this.editor=t,this.children&&_.isArray(this.children)&&_(this.children).each(function(i){i.setEditor(t)})},this.setParent=function(t){this.parent=t,this.parent.onChildAdded(this);for(var i=t;i;)i.onDescendantAdded(this,t),i=i.parent},this.setIsTemplated=function(t){this.isTemplated=t,this.children&&_.isArray(this.children)&&_(this.children).each(function(i){i.setIsTemplated(t)})},this.applyElementEditorModel=function(){},this.getIsActive=function(){return this.editor?this.editor.activeElement===this&&!this.getIsFocused():!1},this.setIsActive=function(t){this.editor&&(this.editor.isDragging||this.editor.isResizing||(this.editor.activeElement=t?this:this.parent))},this.getIsFocused=function(){return this.editor?this.editor.focusedElement===this:!1},this.setIsFocused=function(){this.editor&&(this.children||!this.isTemplated)&&(this.editor.isDragging||this.editor.isResizing||(this.editor.focusedElement=this,_(this.setIsFocusedEventHandlers).each(function(t){try{t()}catch(i){}})))},this.getIsSelected=function(){return this.getIsFocused()?!0:this.children&&_.isArray(this.children)?_(this.children).any(function(t){return t.getIsSelected()}):!1},this.getIsDropTarget=function(){return this.editor?this.editor.dropTargetElement===this:!1},this.setIsDropTarget=function(t){this.editor&&(this.editor.dropTargetElement=t?this:null)},this.canDelete=function(){return this.isTemplated||!this.parent?!1:!0},this["delete"]=function(){this.canDelete()&&this.parent.deleteChild(this)},this.canMoveUp=function(){return this.isTemplated||!this.parent?!1:this.parent.canMoveChildUp(this)},this.moveUp=function(){this.canMoveUp()&&this.parent.moveChildUp(this)},this.canMoveDown=function(){return this.isTemplated||!this.parent?!1:this.parent.canMoveChildDown(this)},this.moveDown=function(){this.canMoveDown()&&this.parent.moveChildDown(this)},this.elementToObject=function(){return{type:this.type,data:this.data,htmlId:this.htmlId,htmlClass:this.htmlClass,htmlStyle:this.htmlStyle,isTemplated:this.isTemplated,rule:this.rule}},this.getEditorObject=function(){return{}},this.copy=function(t){var i=this.getInnerText();t.setData("text/plain",i);var n=this.toObject(),e=JSON.stringify(n,null," ");t.setData("text/json",e)},this.cut=function(t){this.canDelete()&&(this.copy(t),this["delete"]())},this.paste=function(t){this.parent&&this.parent.paste(t)}}}(LayoutEditor||(LayoutEditor={}));var LayoutEditor;!function(t){t.Container=function(i,n){this.allowedChildTypes=i,this.children=n,this.isContainer=!0;var e=this;this.onChildAdded=function(t){},this.onDescendantAdded=function(t,i){},this.setChildren=function(t){this.children=t,_(this.children).each(function(t){t.setParent(e)})},this.setChildren(n),this.getIsSealed=function(){return _(this.children).any(function(t){return t.isTemplated})};var o=this.setIsFocused;this.setIsFocused=function(){this.getIsSealed()||o.call(this)},this.addChild=function(t){_(this.children).contains(t)||!_(this.allowedChildTypes).contains(t.type)&&!t.isContainable||this.children.push(t),t.setEditor(this.editor),t.setIsTemplated(!1),t.setParent(this)},this.deleteChild=function(t){var i=_(this.children).indexOf(t);i>=0&&(this.children.splice(i,1),t.getIsActive()&&(this.editor.activeElement=null),t.getIsFocused()&&(this.children.length>i?this.children[i].setIsFocused():i>0?this.children[i-1].setIsFocused():this.setIsFocused()))},this.moveFocusPrevChild=function(t){if(!(this.children.length<2)){var i=_(this.children).indexOf(t);i>0&&this.children[i-1].setIsFocused()}},this.moveFocusNextChild=function(t){if(!(this.children.length<2)){var i=_(this.children).indexOf(t);i0},this.canMoveChildDown=function(t){var i=_(this.children).indexOf(t);return i0?t.width<12:0>e?t.width>1:!1}if(0==t)return!0;var e=t;if(0>e){var o=12-c();e+=o,e>0&&(e=0)}for(;0>e&&_(d.children).any(function(t){return t.offset>0});)for(i=0;ie;i++){var s=d.children[i];s.offset>0&&(s.offset--,e++)}for(;0!=e&&_(d.children).any(n);)for(i=0;i=0?t.width>1:!1},this.contractColumnRight=function(t,i){if(this.canContractColumnRight(t,i)){var n=_(this.children).indexOf(t);if(n>=0&&t.width>1&&(t.width--,this.children.length>n+1)){var e=this.children[n+1];i&&0==e.offset?e.width++:e.offset++}}},this.canExpandColumnRight=function(t,i){var n=_(this.children).indexOf(t);if(n>=0){if(t.width>=12)return!1;if(this.children.length>n+1){var e=this.children[n+1];return i&&0==e.offset?e.width>1:e.offset>0}return c()<12}return!1},this.expandColumnRight=function(t,i){if(this.canExpandColumnRight(t,i)){var n=_(this.children).indexOf(t);if(n>=0){if(this.children.length>n+1){var e=this.children[n+1];i&&0==e.offset?e.width--:e.offset--}t.width++}}},this.canExpandColumnLeft=function(t,i){var n=_(this.children).indexOf(t);if(n>=0){if(t.width>=12)return!1;if(n>0){var e=this.children[n-1];if(i&&0==t.offset)return e.width>1}return t.offset>0}return!1},this.expandColumnLeft=function(t,i){if(this.canExpandColumnLeft(t,i)){var n=_(this.children).indexOf(t);if(n>=0){if(n>0){var e=this.children[n-1];i&&0==t.offset?e.width--:t.offset--}else t.offset--;t.width++}}},this.canContractColumnLeft=function(t,i){var n=_(this.children).indexOf(t);return n>=0?t.width>1:!1},this.contractColumnLeft=function(t,i){if(this.canContractColumnLeft(t,i)){var n=_(this.children).indexOf(t);if(n>=0){if(n>0){var e=this.children[n-1];i&&0==t.offset?e.width++:t.offset++}else t.offset++;t.width--}}},this.evenColumns=function(){if(0!=this.children.length){var t=Math.floor(12/this.children.length);_(this.children).each(function(i){i.width=t,i.offset=0});var i=12%this.children.length;i>0&&a(i)}};var m=this.pasteChild;this.pasteChild=function(t){"Column"==t.type?this.beginAddColumn(t.width)&&(this.commitAddColumn(),m.call(this,t)):this.parent&&this.parent.pasteChild(t)},this.toObject=function(){var t=this.elementToObject();return t.children=this.childrenToObject(),t}},t.Row.from=function(i){var n=new t.Row(i.data,i.htmlId,i.htmlClass,i.htmlStyle,i.isTemplated,i.rule,t.childrenFrom(i.children));return n.toolboxIcon=i.toolboxIcon,n.toolboxLabel=i.toolboxLabel,n.toolboxDescription=i.toolboxDescription,n}}(LayoutEditor||(LayoutEditor={}));var LayoutEditor;!function(t){t.Column=function(i,n,e,o,s,h,r,l,c,a){t.Element.call(this,"Column",i,n,e,o,s,c),t.Container.call(this,["Grid","Content"],a),this.width=h,this.offset=r,this.collapsible=l;var d=!1,u=0,f=0;this.beginChange=function(){if(d)throw new Error("Column already has a pending change.");d=!0,u=this.width,f=this.offset},this.commitChange=function(){if(!d)throw new Error("Column has no pending change.");u=0,f=0,d=!1},this.rollbackChange=function(){if(!d)throw new Error("Column has no pending change.");this.width=u,this.offset=f,u=0,f=0,d=!1},this.canSplit=function(){return this.isTemplated?!1:this.width>1},this.split=function(){if(this.canSplit()){var i=Math.floor(this.width/2),n=t.Column.from({data:null,htmlId:null,htmlClass:null,htmlStyle:null,width:i,offset:0,children:[]});this.width=this.width-i,this.parent.insertChild(n,this),n.setIsFocused()}},this.canContractRight=function(t){return this.isTemplated?!1:this.parent.canContractColumnRight(this,t)},this.contractRight=function(t){this.canContractRight(t)&&this.parent.contractColumnRight(this,t)},this.canExpandRight=function(t){return this.isTemplated?!1:this.parent.canExpandColumnRight(this,t)},this.expandRight=function(t){this.canExpandRight(t)&&this.parent.expandColumnRight(this,t)},this.canExpandLeft=function(t){return this.isTemplated?!1:this.parent.canExpandColumnLeft(this,t)},this.expandLeft=function(t){this.canExpandLeft(t)&&this.parent.expandColumnLeft(this,t)},this.canContractLeft=function(t){return this.isTemplated?!1:this.parent.canContractColumnLeft(this,t)},this.contractLeft=function(t){this.canContractLeft(t)&&this.parent.contractColumnLeft(this,t)},this.toObject=function(){var t=this.elementToObject();return t.width=this.width,t.offset=this.offset,t.collapsible=this.collapsible,t.children=this.childrenToObject(),t}},t.Column.from=function(i){var n=new t.Column(i.data,i.htmlId,i.htmlClass,i.htmlStyle,i.isTemplated,i.width,i.offset,i.collapsible,i.rule,t.childrenFrom(i.children));return n.toolboxIcon=i.toolboxIcon,n.toolboxLabel=i.toolboxLabel,n.toolboxDescription=i.toolboxDescription,n},t.Column.times=function(i){return _.times(i,function(n){return t.Column.from({data:null,htmlId:null,htmlClass:null,isTemplated:!1,width:12/i,offset:0,collapsible:null,children:[]})})}}(LayoutEditor||(LayoutEditor={}));var LayoutEditor;!function(t){t.Content=function(i,n,e,o,s,h,r,l,c,a,d){t.Element.call(this,"Content",i,n,e,o,s,d),this.contentType=h,this.contentTypeLabel=r,this.contentTypeClass=l,this.html=c,this.hasEditor=a,this.getInnerText=function(){return $($.parseHTML("
"+this.html+"
")).text()},this.setHtml=function(t){this.html=t,this.htmlUnsafe=t},this.toObject=function(){return{type:"Content"}},this.toObject=function(){var t=this.elementToObject();return t.contentType=this.contentType,t.contentTypeLabel=this.contentTypeLabel,t.contentTypeClass=this.contentTypeClass,t.html=this.html,t.hasEditor=a,t},this.setHtml(c)},t.Content.from=function(i){var n=new t.Content(i.data,i.htmlId,i.htmlClass,i.htmlStyle,i.isTemplated,i.contentType,i.contentTypeLabel,i.contentTypeClass,i.html,i.hasEditor,i.rule);return n}}(LayoutEditor||(LayoutEditor={}));var LayoutEditor;!function(t,i){i.Html=function(n,e,o,s,h,r,l,c,a,d,u){i.Element.call(this,"Html",n,e,o,s,h,u),this.contentType=r,this.contentTypeLabel=l,this.contentTypeClass=c,this.html=a,this.hasEditor=d,this.isContainable=!0,this.getInnerText=function(){return t(t.parseHTML("
"+this.html+"
")).text()},this.setHtml=function(t){this.html=t,this.htmlUnsafe=t},this.toObject=function(){return{type:"Html"}},this.toObject=function(){var t=this.elementToObject();return t.contentType=this.contentType,t.contentTypeLabel=this.contentTypeLabel,t.contentTypeClass=this.contentTypeClass,t.html=this.html,t.hasEditor=d,t};var f=this.getEditorObject;this.getEditorObject=function(){var i=f();return t.extend(i,{Content:this.html})},this.setHtml(a)},i.Html.from=function(t){var n=new i.Html(t.data,t.htmlId,t.htmlClass,t.htmlStyle,t.isTemplated,t.contentType,t.contentTypeLabel,t.contentTypeClass,t.html,t.hasEditor,t.rule);return n},i.registerFactory("Html",function(t){return i.Html.from(t)})}(jQuery,LayoutEditor||(LayoutEditor={})); \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Services/ElementFactory.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Services/ElementFactory.cs index 4793ce28b..e58930309 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Services/ElementFactory.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Services/ElementFactory.cs @@ -5,16 +5,19 @@ using Orchard.Localization; namespace Orchard.Layouts.Services { public class ElementFactory : IElementFactory { private readonly IElementEventHandler _elementEventHandler; + private readonly IWorkContextAccessor _workContextAccessor; - public ElementFactory(IElementEventHandler elementEventHandler) { + public ElementFactory(IElementEventHandler elementEventHandler, IWorkContextAccessor workContextAccessor) { _elementEventHandler = elementEventHandler; + _workContextAccessor = workContextAccessor; T = NullLocalizer.Instance; } public Localizer T { get; set; } public Element Activate(Type elementType, Action initialize = null) { - var element = (Element)Activator.CreateInstance(elementType); + var workContext = _workContextAccessor.GetContext(); + var element = (Element)workContext.Resolve(elementType); if (initialize != null) initialize(element); @@ -23,7 +26,8 @@ namespace Orchard.Layouts.Services { } public T Activate(Action initialize = null) where T : Element { - var element = (T)Activator.CreateInstance(typeof(T)); + var workContext = _workContextAccessor.GetContext(); + var element = workContext.Resolve(); if (initialize != null) initialize(element); diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Services/ElementManager.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Services/ElementManager.cs index fa535ef78..1ff94d067 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Services/ElementManager.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Services/ElementManager.cs @@ -38,7 +38,7 @@ namespace Orchard.Layouts.Services { public IEnumerable DescribeElements(DescribeElementsContext context) { var contentType = context.Content != null ? context.Content.ContentItem.ContentType : default(string); var cacheKey = String.Format("LayoutElementTypes-{0}-{1}", contentType ?? "AnyType", context.CacheVaryParam); - return _cacheManager.Get(cacheKey, acquireContext => { + return _cacheManager.Get(cacheKey, true, acquireContext => { var harvesterContext = new HarvestElementsContext { Content = context.Content }; @@ -55,7 +55,7 @@ namespace Orchard.Layouts.Services { public IEnumerable GetCategories(DescribeElementsContext context) { var contentType = context.Content != null ? context.Content.ContentItem.ContentType : default(string); - return _cacheManager.Get(String.Format("ElementCategories-{0}-{1}", contentType ?? "AnyType", context.CacheVaryParam), acquireContext => { + return _cacheManager.Get(String.Format("ElementCategories-{0}-{1}", contentType ?? "AnyType", context.CacheVaryParam), true, acquireContext => { var elements = DescribeElements(context); var categoryDictionary = GetCategories(); var categoryDescriptorDictionary = new Dictionary(); diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Settings/LayoutSettingsHooks.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Settings/LayoutSettingsHooks.cs index fb7804c2d..c39e4fe42 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Settings/LayoutSettingsHooks.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Settings/LayoutSettingsHooks.cs @@ -22,12 +22,7 @@ namespace Orchard.Layouts.Settings { yield break; var model = definition.Settings.GetModel(); - - if (String.IsNullOrWhiteSpace(model.DefaultLayoutData)) { - var defaultData = _serializer.Serialize(_layoutManager.CreateDefaultLayout()); - model.DefaultLayoutData = defaultData; - } - + yield return DefinitionTemplate(model); } diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Styles/LayoutEditor.css b/src/Orchard.Web/Modules/Orchard.Layouts/Styles/LayoutEditor.css index 56edf88f7..04dd49724 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Styles/LayoutEditor.css +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Styles/LayoutEditor.css @@ -1114,4 +1114,4 @@ table[rules=all i] > tfoot > tr > td, table[rules=all i] > tfoot > tr > th { font-size: 0.9em; } -/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkVkaXRvci5sZXNzIiwiTGF5b3V0RWRpdG9yLmNzcyIsIkVsZW1lbnQubGVzcyIsIkNvbnRhaW5lci5sZXNzIiwiQ2FudmFzLmxlc3MiLCJSb3cubGVzcyIsIkNvbHVtbi5sZXNzIiwiQ29udGVudC5sZXNzIiwiUmVzZXQubGVzcyIsIlRvb2xib3gubGVzcyIsIlBvcHVwLmxlc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUE7RUFDSSxzQkFBQTtFQUFBLHFCQUFBO0VBQUEsY0FBQTtFQUNBLHVDQUFBO01BQUEsdUJBQUE7VUFBQSwrQkFBQTtFQUNBLG1CQUFBO0VBQ0EsVUFBQTtDQ0RIO0FESEQ7RUFPUSxzQkFBQTtFQUFBLHFCQUFBO0VBQUEsY0FBQTtDQ0RQO0FETkQ7RUFVWSxrQkFBQTtDQ0RYO0FETUQ7RUFDSSxzQkFBQTtFQUFBLHFCQUFBO0VBQUEsY0FBQTtFQUNBLGdCQUFBO0VBQ0EsZ0JBQUE7RUFDQSw2QkFBQTtNQUFBLHdCQUFBO1VBQUEscUJBQUE7Q0NKSDtBREFEO0VBT1EscUJBQUE7TUFBQSxxQkFBQTtVQUFBLGFBQUE7RUFDQSwwQkFBQTtFQUNBLDBCQUFBO0NDSlA7QURMRDtFQVlZLGNBQUE7RUFDQSxvQkFBQTtFQUNBLGlCQUFBO0NDSlg7QURWRDtFQWlCZ0IsdUJBQUE7Q0NKZjtBRGJEO0VBc0JZLHdCQUFBO0VBQ0EscUJBQUE7RUFDQSxvQkFBQTtDQ05YO0FEbEJEO0VBNkJRLG9CQUFBO0NDUlA7QURZRDtFQUNJLGNBQUE7Q0NWSDtBRGFPOztFQUNJLGFBQUE7RUFDQSxlQUFBO0NDVlg7QURhTztFQUNJLFlBQUE7Q0NYWDtBRENEOztFQWNZLGdCQUFBO0NDWFg7QURIRDtFQWtCWSx1QkFBQTtFQUNBLFlBQUE7RUFDQSxXQUFBO0NDWlg7QURjVztFQUNJLG9CQUFBO0VBQ0EsWUFBQTtDQ1pmO0FEWkQ7RUE2QlksZ0JBQUE7Q0NkWDtBRGZEO0VBa0NRLG1CQUFBO0VBQ0EsMEJBQUE7RUFDQSxpQkFBQTtFQUNBLHVCQUFBO0NDaEJQO0FEckJEO0VBeUNRLHFCQUFBO0VBQ0EsbUJBQUE7Q0NqQlA7QUR6QkQ7RUE4Q1Esb0JBQUE7Q0NsQlA7O0FDNUVEO0VBRVEsbUJBQUE7RUFDQSxjQUFBO0VBQ0EsZ0JBQUE7RUFDQSxpQkFBQTtFQUNBLFdBQUE7Q0Q4RVA7QUMzRU87RUFDSSxlQUFBO0NENkVYO0FDdkZEO0VBZWdCLGNBQUE7RUFDQSxtQkFBQTtFQUNBLFVBQUE7RUFDQSxZQUFBO0VBQ0EsYUFBQTtFQUNBLGVBQUE7RUFDQSxpQkFBQTtFQUNBLG9CQUFBO0VBQ0Esa0JBQUE7RUFDQSx1QkFBQTtDRDJFZjtBQ25HRDtFQTJCb0Isc0JBQUE7RUFDQSxhQUFBO0VBQ0EsbUJBQUE7Q0QyRW5CO0FDeEdEO0VBaUNvQixnQkFBQTtDRDBFbkI7QUMzR0Q7RUFxQ29CLGNBQUE7RUFDQSxZQUFBO0VBQ0EsZ0JBQUE7RUFDQSxtQkFBQTtDRHlFbkI7QUNqSEQ7RUE2Q2dCLFdBQUE7RUFDQSxXQUFBO0NEdUVmO0FDckhEO0VBcURRLGlCQUFBO0NEbUVQO0FDaEVHOztFQUdRLGtCQUFBO0VBQ0Esb0JBQUE7Q0RpRVg7QUNyRUc7O0VBT1ksYUFBQTtDRGtFZjtBQ3pFRztFQWNRLHVDQUFBO0NEOERYO0FDNUVHO0VBaUJZLGVBQUE7RUFDQSxZQUFBO0VBQ0EsMkNBQUE7Q0Q4RGY7QUNqRkc7RUEyQlEsc0JBQUE7Q0R5RFg7QUNwRkc7RUE4QlksZUFBQTtFQUNBLDBCQUFBO0VBQ0EsZUFBQTtDRHlEZjtBQ3pGRztFQW1DZ0Isc0JBQUE7Q0R5RG5CO0FDeERtQjtFQUNJLDBCQUFBO0NEMER2QjtBQ3ZEbUI7RUFDSSxnQkFBQTtFQUNBLGdDQUFBO0NEeUR2QjtBQ3ZEdUI7RUFDSSwwQkFBQTtDRHlEM0I7QUNyRG1CO0VBQ0ksZUFBQTtFQUNBLDBCQUFBO0NEdUR2QjtBQ3JEdUI7RUFDSSwwQkFBQTtDRHVEM0I7QUM3R0c7RUErRFEsMkNBQUE7Q0RpRFg7QUN4S0Q7RUE0SFEsY0FBQTtDRCtDUDtBQzNLRDtFQWlJUSx1REFBQTtDRDZDUDtBQzlLRDtFQW9JWSxlQUFBO0VBQ0EsK0JBQUE7RUFDQSxpQkFBQTtFQUNBLHNDQUFBO0VBQ0EsMkNBQUE7Q0Q2Q1g7QUNyTEQ7RUErSVksZ0JBQUE7RUFDQSxpQkFBQTtDRHlDWDs7QUV6TEQ7RUFNZ0IsY0FBQTtFQUNBLCtCQUFBO01BQUEsMkJBQUE7VUFBQSx1QkFBQTtFQUNBLGFBQUE7RUFDQSxpQkFBQTtFQUNBLDRDQUFBO0VBQ0EsbUJBQUE7RUFDQSxjQUFBO0VBQ0EsZ0NBQUE7TUFBQSxzQkFBQTtVQUFBLHdCQUFBO0VBQ0EsZ0JBQUE7RUFDQSxtQkFBQTtFQUNBLGFBQUE7RUFDQSxtQkFBQTtDRnVMZjtBRXhNRDtFQXFCZ0IsY0FBQTtDRnNMZjtBRTNNRDtFQXlCb0IsaUJBQUE7Q0ZxTG5CO0FFOU1EO0VBOEJvQixjQUFBO0NGbUxuQjtBRS9LVztFQUVRLHNCQUFBO0VBQUEscUJBQUE7RUFBQSxjQUFBO0NGZ0xuQjtBRWxMVztFQU1RLG1CQUFBO0VBQ0EsT0FBQTtFQUNBLFNBQUE7RUFDQSxVQUFBO0VBQ0EsUUFBQTtDRitLbkI7QUV6S0c7RUFHWSw0Q0FBQTtDRnlLZjtBRTVLRztFQU1nQixhQUFBO0NGeUtuQjtBRS9LRztFQVdZLGNBQUE7Q0Z1S2Y7QUVsTEc7RUFjZ0IsY0FBQTtDRnVLbkI7O0FHdk9EO0VBR1ksY0FBQTtDSHdPWDs7QUl6T087RUFFUSwyREFBQTtDSjJPZjtBSTdPTztFQUlZLDRCQUFBO0NKNE9uQjtBSWhQTztFQVNRLDBCQUFBO0NKME9mO0FJblBPO0VBV1ksMEJBQUE7Q0oyT25COztBS3hQRDtFQUlnQixjQUFBO0VBQ0EsbUJBQUE7RUFDQSxZQUFBO0VBQ0EsT0FBQTtFQUNBLFlBQUE7RUFDQSxhQUFBO0VBQ0EsbUJBQUE7Q0x3UGY7QUtsUUQ7RUFjZ0IsV0FBQTtDTHVQZjtBS3JRRDtFQWtCZ0IsWUFBQTtDTHNQZjtBS2xQTztFQUNJLGVBQUE7Q0xvUFg7O0FNMVFEOztFQUVRLGdCQUFBO0NONlFQO0FNL1FEOztFQU9nQixhQUFBO0VBQ0EsbUJBQUE7RUFDQSxvQkFBQTtFTjRRZCx5RkFBeUY7RUFDekYscUNBQXFDO0VBQ3JDLHFDQUFxQztFQUNyQyx1REFBdUQ7RUFDdkQsd0RBQXdEO0VBQ3hEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTBCQztDQUNGO0FNclREOztFQ0FRLFVBQUE7RUFDQSxXQUFBO0VBQ0Esd0JBQUE7Q1B5VFA7QU0zVEQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0VDT1EsZUFBQTtDUHNWUDtBTTdWRDs7Ozs7Ozs7Ozs7Ozs7RUNXUSxnQkFBQTtFQUNBLG1CQUFBO0NQa1dQO0FNOVdEOzs7O0VDZ0JRLGtCQUFBO0VBQ0EsbUJBQUE7Q1BvV1A7QU1yWEQ7O0VDcUJRLG1CQUFBO0NQb1dQO0FNelhEOzs7Ozs7OztFQ3lCUSx1QkFBQTtFQUNBLGlCQUFBO0NQMFdQO0FNcFlEOzs7Ozs7Ozs7O0VDOEJRLG1CQUFBO0NQa1hQO0FNaFpEOzs7O0VDa0NRLG9CQUFBO0NQb1hQO0FNdFpEOzs7Ozs7OztFQ3NDUSx1QkFBQTtDUDBYUDtBTWhhRDs7RUMwQ1Esa0JBQUE7Q1AwWFA7QU1wYUQ7O0VDOENRLG1CQUFBO0NQMFhQO0FNeGFEOztFQ2tEUSxvQkFBQTtDUDBYUDtBTTVhRDs7RUNzRFEsc0JBQUE7Q1AwWFA7QU1oYkQ7Ozs7RUMwRFEsb0JBQUE7RUFDQSxtQkFBQTtDUDRYUDtBTXZiRDs7RUNnRVEsY0FBQTtDUDJYUDtBTTNiRDs7RUNvRVEsbUJBQUE7RUFDQSxvQkFBQTtDUDJYUDtBTWhjRDs7RUN5RVEsbUJBQUE7RUFDQSxvQkFBQTtFQUNBLGVBQUE7RUFDQSw4QkFBQTtFQUNBLDRCQUFBO1VBQUEsb0JBQUE7Q1AyWFA7QU14Y0Q7O0VDaUZRLDZCQUFBO0NQMlhQO0FNNWNEOztFQ3FGUSw2QkFBQTtDUDJYUDtBTWhkRDs7Ozs7Ozs7OztFQ3lGUSxzQkFBQTtDUG1ZUDtBTTVkRDs7RUM4RlEsZUFBQTtDUGtZUDtBTWhlRDs7RUNrR1EsZUFBQTtDUGtZUDtBTXBlRDs7OztFQ3NHUSwyQkFBQTtDUG9ZUDtBTTFlRDs7Ozs7Ozs7RUMyR1EsYUFBQTtDUHlZUDtBTXBmRDs7RUMrR1EsY0FBQTtDUHlZUDtBTXhmRDs7RUNtSFEsbUJBQUE7RUFDQSxhQUFBO0NQeVlQO0FNN2ZEOzs7O0VDd0hRLGtDQUFBO0NQMllQO0FNbmdCRDs7OztFQzRIUSwyQkFBQTtDUDZZUDtBTXpnQkQ7Ozs7OztFQ2dJUSw4QkFBQTtDUGlaUDtBTWpoQkQ7O0VDb0lRLHVCQUFBO0NQaVpQO0FNcmhCRDs7RUN3SVEsb0JBQUE7Q1BpWlA7QU16aEJEOztFQzRJUSxxQkFBQTtDUGlaUDtBTTdoQkQ7O0VDZ0pRLGNBQUE7RUFDQSxpQkFBQTtDUGlaUDtBTWxpQkQ7O0VDcUpRLG9CQUFBO0NQaVpQO0FNdGlCRDs7RUN5SlEsaUJBQUE7Q1BpWlA7QU0xaUJEOztFQzZKUSxvQkFBQTtDUGlaUDtBTTlpQkQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7RUNpS1EsZUFBQTtDUHFhUDtBTXRrQkQ7O0VDcUtRLG1CQUFBO0VBQ0Esc0JBQUE7RUFDQSxrQkFBQTtFQUNBLGtCQUFBO0NQcWFQO0FNN2tCRDs7RUM0S1EsbUJBQUE7RUFDQSxzQkFBQTtFQUNBLGtCQUFBO0VBQ0Esa0JBQUE7Q1BxYVA7QU1wbEJEOztFQ21MUSxtQkFBQTtFQUNBLHNCQUFBO0VBQ0Esa0JBQUE7RUFDQSxrQkFBQTtDUHFhUDtBTTNsQkQ7O0VDMExRLG1CQUFBO0VBQ0Esc0JBQUE7RUFDQSxrQkFBQTtFQUNBLGtCQUFBO0NQcWFQO0FNbG1CRDs7RUNpTVEsbUJBQUE7RUFDQSxzQkFBQTtFQUNBLGtCQUFBO0VBQ0Esa0JBQUE7Q1BxYVA7QU16bUJEOztFQ3dNUSxtQkFBQTtFQUNBLHNCQUFBO0VBQ0Esa0JBQUE7RUFDQSxrQkFBQTtDUHFhUDtBTWhuQkQ7Ozs7Ozs7Ozs7OztFQytNUSxlQUFBO0NQK2FQO0FNOW5CRDs7RUNtTlEsbUJBQUE7Q1ArYVA7QU1sb0JEOzs7Ozs7OztFQ3VOUSxnQkFBQTtFQUNBLG1CQUFBO0NQcWJQO0FNN29CRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7RUMrTlksY0FBQTtFQUNBLGlCQUFBO0NQZ2RYO0FNaHJCRDs7RUNvT1Esa0JBQUE7Q1BnZFA7QU1wckJEOzs7Ozs7RUN3T1EsbUJBQUE7Q1BvZFA7QU01ckJEOztFQzRPUSx5QkFBQTtDUG9kUDtBTWhzQkQ7Ozs7RUNnUFEsc0JBQUE7Q1BzZFA7QU10c0JEOzs7Ozs7Ozs7Ozs7RUNzUFksd0JBQUE7Q1A4ZFg7QU1wdEJEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7RUNrUWdCLHdCQUFBO0NQd2ZmO0FNMXZCRDs7RUNzUVEsZUFBQTtDUHdmUDtBTTl2QkQ7O0VDMFFRLHVCQUFBO0NQd2ZQO0FNbHdCRDs7OztFQzhRUSw0QkFBQTtDUDBmUDtBTXh3QkQ7Ozs7RUNrUlEsc0JBQUE7Q1A0ZlA7QU05d0JEOzs7O0VDc1JRLDRCQUFBO0NQOGZQO0FNcHhCRDs7OztFQzBSUSx5QkFBQTtDUGdnQlA7QU0xeEJEOzs7O0VDOFJRLDRCQUFBO0NQa2dCUDtBTWh5QkQ7Ozs7RUNrU1EsbUJBQUE7Q1BvZ0JQO0FNdHlCRDs7Ozs7Ozs7RUNzU1Esb0JBQUE7Q1AwZ0JQO0FNaHpCRDs7Ozs7Ozs7Ozs7Ozs7OztFQzJTWSxxQkFBQTtDUHVoQlg7QU1sMEJEOztFQytTUSx1QkFBQTtFQUNBLG9CQUFBO0VBQ0EsMEJBQUE7RUFDQSxxQkFBQTtDUHVoQlA7QU16MEJEOzs7O0VDc1RRLGFBQUE7Q1B5aEJQO0FNLzBCRDs7RUMwVFEsa0JBQUE7Q1B5aEJQO0FNbjFCRDs7Ozs7Ozs7RUM4VFEsdUJBQUE7Q1AraEJQO0FNNzFCRDs7Ozs7O0VDa1VRLHdCQUFBO0NQbWlCUDtBTXIyQkQ7Ozs7OztFQ3NVUSxtQkFBQTtDUHVpQlA7QU03MkJEOzs7Ozs7OztFQzBVUSxzQkFBQTtDUDZpQlA7QU12M0JEOzs7Ozs7Ozs7Ozs7OztFQ3dXUSxxQkFBQTtDUCtoQlA7QU12NEJEOztFQzRXUSxzQkFBQTtDUCtoQlA7QU0zNEJEOzs7Ozs7Ozs7Ozs7OztFQ2lYUSx1QkFBQTtDUDBpQlA7QU0zNUJEOzs7O0VDcVhRLHFCQUFBO0NQNGlCUDtBTWo2QkQ7O0VDeVhRLFlBQUE7RUFDQSxvQkFBQTtFQUNBLGtCQUFBO0VBQ0EsbUJBQUE7Q1A0aUJQO0FNeDZCRDs7RUNnWVEsaUJBQUE7RUFDQSxrQkFBQTtFQUNBLDhCQUFBO0VBQ0EsK0JBQUE7Q1A0aUJQO0FNLzZCRDs7RUN1WVEsa0JBQUE7RUFDQSxtQkFBQTtDUDRpQlA7QU1wN0JEOztFQWVvQix5QkFBQTtDTnk2Qm5CO0FNeDdCRDs7RUFtQm9CLDRCQUFBO0NOeTZCbkI7QU1wNkJPOzs7O0VBRVEsZUFBQTtFQUNBLFlBQUE7RUFDQSxnQkFBQTtFQUNBLGFBQUE7Q053NkJmO0FNcjhCRDs7RUFtQ1EsZUFBQTtFQUNBLFlBQUE7RUFDQSxnQkFBQTtFQUNBLGFBQUE7Q05zNkJQOztBUTc4QkQ7RUFFUSxtQkFBQTtFQUNBLGtCQUFBO0VBQ0EsYUFBQTtFQUNBLHVCQUFBO01BQUEscUJBQUE7VUFBQSxlQUFBO0NSKzhCUDtBUXA5QkQ7RUFRWSwwQkFBQTtFQUNBLGFBQUE7RUFDQSxrQkFBQTtFQUNBLGFBQUE7RUFDQSwwQkFBQTtDUis4Qlg7QVE3OEJXO0VBQ0ksZ0JBQUE7RUFDQSxPQUFBO0VBQ0EsaUJBQUE7RUFDQSxpQkFBQTtDUis4QmY7QVE1OEJXO0VBQ0ksbUJBQUE7RUFDQSxVQUFBO0NSODhCZjtBUXIrQkQ7RUEyQmdCLGlCQUFBO0NSNjhCZjtBUXgrQkQ7RUE4Qm9CLGVBQUE7RUFDQSxtQkFBQTtFQUNBLHNCQUFBO0NSNjhCbkI7QVEzOEJtQjtFQUNJLHNCQUFBO0VBQ0EsWUFBQTtFQUNBLGtCQUFBO0VBQ0EsOENBQUE7RUFDQSxtQkFBQTtFQUNBLGlCQUFBO0NSNjhCdkI7QVF6OEJlO0VBRVEsaUJBQUE7Q1IwOEJ2QjtBUTU4QmU7RUFNUSxjQUFBO0NSeThCdkI7QVEzL0JEO0VBdURvQixnQkFBQTtDUnU4Qm5CO0FROS9CRDtFQTJEb0IsMEJBQUE7RUFDQSx1QkFBQTtFQUNBLGtCQUFBO0VBQ0EsZ0JBQUE7Q1JzOEJuQjtBUXBnQ0Q7RUFpRXdCLHNCQUFBO0VBQ0EsWUFBQTtFQUNBLDhDQUFBO0NSczhCdkI7QVF6Z0NEO0VBdUV3QixnQkFBQTtDUnE4QnZCO0FRNWdDRDtFQTRFb0IsZ0JBQUE7Q1JtOEJuQjs7QVMvZ0NEO0VBRVEsY0FBQTtFQUNBLG1CQUFBO0VBQ0EsVUFBQTtFQUdBLGlEQUFBO0VBQ0EsMEJBQUE7RUFDQSxlQUFBO0VBQ0EsMEJBQUE7RUFDQSxpQkFBQTtFQUNBLFlBQUE7RUFDQSxlQUFBO0VBQ0EsaUJBQUE7RUFDQSxnQkFBQTtFQUNBLG9CQUFBO0VBQ0Esb0JBQUE7RUFDQSxpQkFBQTtDVGloQ1A7QVMvZ0NPO0VBQ0ksYUFBQTtDVGloQ1g7QVN0aUNEO0VBeUJZLHNCQUFBO0VBQUEscUJBQUE7RUFBQSxjQUFBO0VBQ0EsaUJBQUE7Q1RnaENYO0FTMWlDRDtFQTZCZ0IsaUJBQUE7RUFDQSxpREFBQTtFQUNBLGtCQUFBO0NUZ2hDZjtBUy9pQ0Q7RUFvQ1ksaUJBQUE7Q1Q4Z0NYO0FTbGpDRDtFQXdDWSxpQkFBQTtFQUNBLGtCQUFBO0VBQ0EsZUFBQTtDVDZnQ1g7QVN2akNEO0VBOENZLDBCQUFBO0VBQ0EsZ0JBQUE7Q1Q0Z0NYO0FTM2pDRDs7RUFvRGdCLFlBQUE7Q1QyZ0NmO0FTL2pDRDtFQXdEZ0IsZUFBQTtFQUNBLGlCQUFBO0NUMGdDZiIsImZpbGUiOiJMYXlvdXRFZGl0b3IuY3NzIiwic291cmNlc0NvbnRlbnQiOlsiQGltcG9ydCBcIlZhcmlhYmxlcy5sZXNzXCI7XHJcblxyXG4ubGF5b3V0LWVkaXRvci10b29sYmFyIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcbiAgICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcbiAgICB0b3A6IDEwcHg7XHJcblxyXG4gICAgLmxheW91dC1lZGl0b3ItdG9vbGJhci1ncm91cCB7XHJcbiAgICAgICAgZGlzcGxheTogZmxleDtcclxuXHJcbiAgICAgICAgPiBsaSArIGxpIHtcclxuICAgICAgICAgICAgbWFyZ2luLWxlZnQ6IDEycHg7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcblxyXG4ubGF5b3V0LWVkaXRvciB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgbWFyZ2luLXRvcDogMWVtO1xyXG4gICAgZm9udC1zaXplOiBAZm9udC1zaXplO1xyXG4gICAgYWxpZ24taXRlbXM6IHN0cmV0Y2g7XHJcblxyXG4gICAgPiAubGF5b3V0LWNhbnZhcy13cmFwcGVyIHtcclxuICAgICAgICBmbGV4LWdyb3c6IDE7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogQGdyYXktYmc7XHJcbiAgICAgICAgYm9yZGVyOiAxcHggc29saWQgQGdyYXktYm9yZGVyO1xyXG5cclxuICAgICAgICA+IC5sYXlvdXQtdG9vbGJhci1jb250YWluZXIge1xyXG4gICAgICAgICAgICBkaXNwbGF5OiBub25lO1xyXG4gICAgICAgICAgICBtYXJnaW46IEBjb250YWluZXItcGFkZGluZyBAY29udGFpbmVyLXBhZGRpbmcgMDtcclxuICAgICAgICAgICAgbWluLWhlaWdodDogNzFweDtcclxuXHJcbiAgICAgICAgICAgID4gLm1jZS1wYW5lbCB7XHJcbiAgICAgICAgICAgICAgICB3aWR0aDogMTAwJSAhaW1wb3J0YW50O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwID4gLmxheW91dC1wbGFjZWhvbGRlciB7XHJcbiAgICAgICAgICAgIGJvcmRlcjogMXB4IGRhc2hlZCAjY2NjO1xyXG4gICAgICAgICAgICBwYWRkaW5nOiAwLjJlbSAwLjRlbTtcclxuICAgICAgICAgICAgYmFja2dyb3VuZDogI2U4ZThlODtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLmxheW91dC1zbmlwcGV0IHtcclxuICAgICAgICBiYWNrZ3JvdW5kOiAjZThlOGU4O1xyXG4gICAgfVxyXG59XHJcblxyXG4ubGF5b3V0LWVkaXRvci1oZWxwLWRpYWxvZyB7XHJcbiAgICBkaXNwbGF5OiBub25lO1xyXG5cclxuICAgIC5oZWxwLXJvdyB7XHJcbiAgICAgICAgJjpiZWZvcmUsICY6YWZ0ZXIge1xyXG4gICAgICAgICAgICBjb250ZW50OiBcIiBcIjsgLy8gMVxyXG4gICAgICAgICAgICBkaXNwbGF5OiB0YWJsZTsgLy8gMlxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgJjphZnRlciB7XHJcbiAgICAgICAgICAgIGNsZWFyOiBib3RoO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgPiAuaGVscC1jb2x1bW4tZnVsbCwgPiAuaGVscC1jb2x1bW4taGFsZiB7XHJcbiAgICAgICAgICAgIG1hcmdpbjogMC41ZW0gMDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgID4gLmhlbHAtY29sdW1uLWhhbGYge1xyXG4gICAgICAgICAgICBib3gtc2l6aW5nOiBib3JkZXItYm94O1xyXG4gICAgICAgICAgICBmbG9hdDogbGVmdDtcclxuICAgICAgICAgICAgd2lkdGg6IDUwJTtcclxuXHJcbiAgICAgICAgICAgICY6bnRoLWNoaWxkKDJuKSB7XHJcbiAgICAgICAgICAgICAgICBwYWRkaW5nLXJpZ2h0OiAxMHB4O1xyXG4gICAgICAgICAgICAgICAgY2xlYXI6IGxlZnQ7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICsgLmhlbHAtcm93IHtcclxuICAgICAgICAgICAgbWFyZ2luLXRvcDogMWVtO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBjb2RlIHtcclxuICAgICAgICBib3JkZXItcmFkaXVzOiA0cHg7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2YzZjRmNTtcclxuICAgICAgICBwYWRkaW5nOiAycHggNHB4O1xyXG4gICAgICAgIGZvbnQtZmFtaWx5OiBtb25vc3BhY2U7XHJcbiAgICB9XHJcblxyXG4gICAgcCB7XHJcbiAgICAgICAgbWFyZ2luLWJvdHRvbTogMC41ZW07XHJcbiAgICAgICAgbGluZS1oZWlnaHQ6IDEuNmVtO1xyXG4gICAgfVxyXG5cclxuICAgIHRhYmxlID4gdGJvZHkgPiB0ciA+IHRkOmZpcnN0LWNoaWxkIHtcclxuICAgICAgICBwYWRkaW5nLXJpZ2h0OiAxMHB4O1xyXG4gICAgfVxyXG59XHJcbiIsIi5sYXlvdXQtZWRpdG9yLXRvb2xiYXIge1xuICBkaXNwbGF5OiBmbGV4O1xuICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XG4gIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgdG9wOiAxMHB4O1xufVxuLmxheW91dC1lZGl0b3ItdG9vbGJhciAubGF5b3V0LWVkaXRvci10b29sYmFyLWdyb3VwIHtcbiAgZGlzcGxheTogZmxleDtcbn1cbi5sYXlvdXQtZWRpdG9yLXRvb2xiYXIgLmxheW91dC1lZGl0b3ItdG9vbGJhci1ncm91cCA+IGxpICsgbGkge1xuICBtYXJnaW4tbGVmdDogMTJweDtcbn1cbi5sYXlvdXQtZWRpdG9yIHtcbiAgZGlzcGxheTogZmxleDtcbiAgbWFyZ2luLXRvcDogMWVtO1xuICBmb250LXNpemU6IDE0cHg7XG4gIGFsaWduLWl0ZW1zOiBzdHJldGNoO1xufVxuLmxheW91dC1lZGl0b3IgPiAubGF5b3V0LWNhbnZhcy13cmFwcGVyIHtcbiAgZmxleC1ncm93OiAxO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjNmNGY1O1xuICBib3JkZXI6IDFweCBzb2xpZCAjZTRlNWU2O1xufVxuLmxheW91dC1lZGl0b3IgPiAubGF5b3V0LWNhbnZhcy13cmFwcGVyID4gLmxheW91dC10b29sYmFyLWNvbnRhaW5lciB7XG4gIGRpc3BsYXk6IG5vbmU7XG4gIG1hcmdpbjogMTJweCAxMnB4IDA7XG4gIG1pbi1oZWlnaHQ6IDcxcHg7XG59XG4ubGF5b3V0LWVkaXRvciA+IC5sYXlvdXQtY2FudmFzLXdyYXBwZXIgPiAubGF5b3V0LXRvb2xiYXItY29udGFpbmVyID4gLm1jZS1wYW5lbCB7XG4gIHdpZHRoOiAxMDAlICFpbXBvcnRhbnQ7XG59XG4ubGF5b3V0LWVkaXRvciA+IC5sYXlvdXQtY2FudmFzLXdyYXBwZXIgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCA+IC5sYXlvdXQtcGxhY2Vob2xkZXIge1xuICBib3JkZXI6IDFweCBkYXNoZWQgI2NjYztcbiAgcGFkZGluZzogMC4yZW0gMC40ZW07XG4gIGJhY2tncm91bmQ6ICNlOGU4ZTg7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LXNuaXBwZXQge1xuICBiYWNrZ3JvdW5kOiAjZThlOGU4O1xufVxuLmxheW91dC1lZGl0b3ItaGVscC1kaWFsb2cge1xuICBkaXNwbGF5OiBub25lO1xufVxuLmxheW91dC1lZGl0b3ItaGVscC1kaWFsb2cgLmhlbHAtcm93OmJlZm9yZSxcbi5sYXlvdXQtZWRpdG9yLWhlbHAtZGlhbG9nIC5oZWxwLXJvdzphZnRlciB7XG4gIGNvbnRlbnQ6IFwiIFwiO1xuICBkaXNwbGF5OiB0YWJsZTtcbn1cbi5sYXlvdXQtZWRpdG9yLWhlbHAtZGlhbG9nIC5oZWxwLXJvdzphZnRlciB7XG4gIGNsZWFyOiBib3RoO1xufVxuLmxheW91dC1lZGl0b3ItaGVscC1kaWFsb2cgLmhlbHAtcm93ID4gLmhlbHAtY29sdW1uLWZ1bGwsXG4ubGF5b3V0LWVkaXRvci1oZWxwLWRpYWxvZyAuaGVscC1yb3cgPiAuaGVscC1jb2x1bW4taGFsZiB7XG4gIG1hcmdpbjogMC41ZW0gMDtcbn1cbi5sYXlvdXQtZWRpdG9yLWhlbHAtZGlhbG9nIC5oZWxwLXJvdyA+IC5oZWxwLWNvbHVtbi1oYWxmIHtcbiAgYm94LXNpemluZzogYm9yZGVyLWJveDtcbiAgZmxvYXQ6IGxlZnQ7XG4gIHdpZHRoOiA1MCU7XG59XG4ubGF5b3V0LWVkaXRvci1oZWxwLWRpYWxvZyAuaGVscC1yb3cgPiAuaGVscC1jb2x1bW4taGFsZjpudGgtY2hpbGQoMm4pIHtcbiAgcGFkZGluZy1yaWdodDogMTBweDtcbiAgY2xlYXI6IGxlZnQ7XG59XG4ubGF5b3V0LWVkaXRvci1oZWxwLWRpYWxvZyAuaGVscC1yb3cgKyAuaGVscC1yb3cge1xuICBtYXJnaW4tdG9wOiAxZW07XG59XG4ubGF5b3V0LWVkaXRvci1oZWxwLWRpYWxvZyBjb2RlIHtcbiAgYm9yZGVyLXJhZGl1czogNHB4O1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjNmNGY1O1xuICBwYWRkaW5nOiAycHggNHB4O1xuICBmb250LWZhbWlseTogbW9ub3NwYWNlO1xufVxuLmxheW91dC1lZGl0b3ItaGVscC1kaWFsb2cgcCB7XG4gIG1hcmdpbi1ib3R0b206IDAuNWVtO1xuICBsaW5lLWhlaWdodDogMS42ZW07XG59XG4ubGF5b3V0LWVkaXRvci1oZWxwLWRpYWxvZyB0YWJsZSA+IHRib2R5ID4gdHIgPiB0ZDpmaXJzdC1jaGlsZCB7XG4gIHBhZGRpbmctcmlnaHQ6IDEwcHg7XG59XG5cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtZWxlbWVudCB7XG4gIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgbWFyZ2luLXRvcDogMDtcbiAgbWFyZ2luLXJpZ2h0OiAwO1xuICBtYXJnaW4tYm90dG9tOiAwO1xuICBwYWRkaW5nOiAwO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1lbGVtZW50Om5vdCgubGF5b3V0LWNvbHVtbikge1xuICBtYXJnaW4tbGVmdDogMDtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtZWxlbWVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1wYW5lbCB7XG4gIGRpc3BsYXk6IG5vbmU7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgbWFyZ2luOiAwO1xuICB6LWluZGV4OiAyMDtcbiAgaGVpZ2h0OiAyNXB4O1xuICBwYWRkaW5nOiAwIDZweDtcbiAgbGlzdC1zdHlsZTogbm9uZTtcbiAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcbiAgbGluZS1oZWlnaHQ6IDI1cHg7XG4gIHZlcnRpY2FsLWFsaWduOiBtaWRkbGU7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWVsZW1lbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciA+IC5sYXlvdXQtcGFuZWwgPiAubGF5b3V0LXBhbmVsLWl0ZW0ge1xuICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7XG4gIGhlaWdodDogMjVweDtcbiAgcGFkZGluZzogMXB4IDZweCAwO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1lbGVtZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgPiAubGF5b3V0LXBhbmVsID4gLmxheW91dC1wYW5lbC1sYWJlbCB7XG4gIGZvbnQtc2l6ZTogMTNweDtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtZWxlbWVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1wYW5lbCA+IC5sYXlvdXQtcGFuZWwtYWN0aW9uIHtcbiAgZGlzcGxheTogbm9uZTtcbiAgd2lkdGg6IDI4cHg7XG4gIGN1cnNvcjogcG9pbnRlcjtcbiAgdGV4dC1hbGlnbjogY2VudGVyO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1lbGVtZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgPiAubGF5b3V0LXBhbmVsLW1haW4ge1xuICB0b3A6IC0yN3B4O1xuICBsZWZ0OiAtMnB4O1xufVxuLmxheW91dC1lZGl0b3IgbGkubGF5b3V0LWVsZW1lbnQge1xuICBsaXN0LXN0eWxlOiBub25lO1xufVxuLmxheW91dC1lZGl0b3I6bm90KC5sYXlvdXQtZWRpdG9yLWRyYWdnaW5nKSAubGF5b3V0LWVsZW1lbnQtYWN0aXZlLFxuLmxheW91dC1lZGl0b3I6bm90KC5sYXlvdXQtZWRpdG9yLWRyYWdnaW5nKSAubGF5b3V0LWVsZW1lbnQtZm9jdXNlZCB7XG4gIGJvcmRlci13aWR0aDogMnB4O1xuICBib3JkZXItc3R5bGU6IHNvbGlkO1xufVxuLmxheW91dC1lZGl0b3I6bm90KC5sYXlvdXQtZWRpdG9yLWRyYWdnaW5nKSAubGF5b3V0LWVsZW1lbnQtYWN0aXZlID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIsXG4ubGF5b3V0LWVkaXRvcjpub3QoLmxheW91dC1lZGl0b3ItZHJhZ2dpbmcpIC5sYXlvdXQtZWxlbWVudC1mb2N1c2VkID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIge1xuICBtYXJnaW46IC0ycHg7XG59XG4ubGF5b3V0LWVkaXRvcjpub3QoLmxheW91dC1lZGl0b3ItZHJhZ2dpbmcpIC5sYXlvdXQtZWxlbWVudC1hY3RpdmUge1xuICBib3JkZXItY29sb3I6IHJnYmEoMTA0LCAxMDQsIDEwNCwgMC4xKTtcbn1cbi5sYXlvdXQtZWRpdG9yOm5vdCgubGF5b3V0LWVkaXRvci1kcmFnZ2luZykgLmxheW91dC1lbGVtZW50LWFjdGl2ZSA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1wYW5lbC1tYWluIHtcbiAgZGlzcGxheTogYmxvY2s7XG4gIHotaW5kZXg6IDMwO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDEwNCwgMTA0LCAxMDQsIDAuMSk7XG59XG4ubGF5b3V0LWVkaXRvcjpub3QoLmxheW91dC1lZGl0b3ItZHJhZ2dpbmcpIC5sYXlvdXQtZWxlbWVudC1mb2N1c2VkIHtcbiAgYm9yZGVyLWNvbG9yOiAjNjQ4NzIxO1xufVxuLmxheW91dC1lZGl0b3I6bm90KC5sYXlvdXQtZWRpdG9yLWRyYWdnaW5nKSAubGF5b3V0LWVsZW1lbnQtZm9jdXNlZCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1wYW5lbCB7XG4gIGRpc3BsYXk6IGJsb2NrO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNjQ4NzIxO1xuICBjb2xvcjogI2ZlZmVmZTtcbn1cbi5sYXlvdXQtZWRpdG9yOm5vdCgubGF5b3V0LWVkaXRvci1kcmFnZ2luZykgLmxheW91dC1lbGVtZW50LWZvY3VzZWQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciA+IC5sYXlvdXQtcGFuZWwgPiAubGF5b3V0LXBhbmVsLWFjdGlvbiB7XG4gIGRpc3BsYXk6IGlubGluZS1ibG9jaztcbn1cbi5sYXlvdXQtZWRpdG9yOm5vdCgubGF5b3V0LWVkaXRvci1kcmFnZ2luZykgLmxheW91dC1lbGVtZW50LWZvY3VzZWQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciA+IC5sYXlvdXQtcGFuZWwgPiAubGF5b3V0LXBhbmVsLWFjdGlvbjpob3ZlciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM4MmIwMmI7XG59XG4ubGF5b3V0LWVkaXRvcjpub3QoLmxheW91dC1lZGl0b3ItZHJhZ2dpbmcpIC5sYXlvdXQtZWxlbWVudC1mb2N1c2VkID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgPiAubGF5b3V0LXBhbmVsID4gLmxheW91dC1wYW5lbC1hY3Rpb24uZGlzYWJsZWQge1xuICBjdXJzb3I6IGRlZmF1bHQ7XG4gIGNvbG9yOiByZ2JhKDI1NCwgMjU0LCAyNTQsIDAuNCk7XG59XG4ubGF5b3V0LWVkaXRvcjpub3QoLmxheW91dC1lZGl0b3ItZHJhZ2dpbmcpIC5sYXlvdXQtZWxlbWVudC1mb2N1c2VkID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgPiAubGF5b3V0LXBhbmVsID4gLmxheW91dC1wYW5lbC1hY3Rpb24uZGlzYWJsZWQ6aG92ZXIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNjQ4NzIxO1xufVxuLmxheW91dC1lZGl0b3I6bm90KC5sYXlvdXQtZWRpdG9yLWRyYWdnaW5nKSAubGF5b3V0LWVsZW1lbnQtZm9jdXNlZCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1wYW5lbCA+IC5sYXlvdXQtcGFuZWwtYWN0aW9uLmFjdGl2ZSB7XG4gIGNvbG9yOiAjZGVmZjQyO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNzM5YjI2O1xufVxuLmxheW91dC1lZGl0b3I6bm90KC5sYXlvdXQtZWRpdG9yLWRyYWdnaW5nKSAubGF5b3V0LWVsZW1lbnQtZm9jdXNlZCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1wYW5lbCA+IC5sYXlvdXQtcGFuZWwtYWN0aW9uLmFjdGl2ZTpob3ZlciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM4MmIwMmI7XG59XG4ubGF5b3V0LWVkaXRvcjpub3QoLmxheW91dC1lZGl0b3ItZHJhZ2dpbmcpIC5sYXlvdXQtZWxlbWVudC1zZWxlY3RlZCB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMTAwLCAxMzUsIDMzLCAwLjA4KTtcbn1cbi5sYXlvdXQtZWRpdG9yIC51aS1zb3J0YWJsZS1wbGFjZWhvbGRlciB7XG4gIGRpc3BsYXk6IG5vbmU7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWVsZW1lbnQtZHJvcHRhcmdldCB7XG4gIGJveC1zaGFkb3c6IGluc2V0IDAgMCAxMnB4IDZweCByZ2JhKDEwMCwgMTM1LCAzMywgMC41KTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtZWxlbWVudC1kcm9wdGFyZ2V0IC51aS1zb3J0YWJsZS1wbGFjZWhvbGRlciB7XG4gIGRpc3BsYXk6IGJsb2NrO1xuICB2aXNpYmlsaXR5OiB2aXNpYmxlICFpbXBvcnRhbnQ7XG4gIG1pbi1oZWlnaHQ6IDc4cHg7XG4gIGJvcmRlcjogMnB4IGRhc2hlZCAjNjQ4NzIxICFpbXBvcnRhbnQ7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMTAwLCAxMzUsIDMzLCAwLjE2KTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5tZWRpYS10aHVtYm5haWwgaW1nIHtcbiAgbWF4LXdpZHRoOiAxMDAlO1xuICBtYXgtaGVpZ2h0OiAxMDAlO1xufVxuXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRhaW5lciA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1jb250YWluZXItY2hpbGRyZW4tcGxhY2Vob2xkZXIge1xuICBkaXNwbGF5OiBub25lO1xuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICBtYXJnaW46IDExcHg7XG4gIG1pbi1oZWlnaHQ6IDgwcHg7XG4gIGJvcmRlcjogMXB4IGRhc2hlZCByZ2JhKDEyNCwgMTI0LCAxMjQsIDAuNCk7XG4gIGJvcmRlci1yYWRpdXM6IDRweDtcbiAgcGFkZGluZzogMTJweDtcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG4gIGZvbnQtc2l6ZTogMTNweDtcbiAgZm9udC1zdHlsZTogaXRhbGljO1xuICBvcGFjaXR5OiAwLjY7XG4gIHRleHQtYWxpZ246IGNlbnRlcjtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGFpbmVyID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgPiAubGF5b3V0LWNoaWxkcmVuIHtcbiAgcGFkZGluZzogMTJweDtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGFpbmVyID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgPiAubGF5b3V0LWNoaWxkcmVuID4gLmxheW91dC1lbGVtZW50Om5vdCgubGF5b3V0LWNvbnRhaW5lcikgKyAubGF5b3V0LWVsZW1lbnQ6bm90KC5sYXlvdXQtY29udGFpbmVyKSB7XG4gIG1hcmdpbi10b3A6IDEycHg7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRhaW5lciA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1jaGlsZHJlbiA+IC51aS1zb3J0YWJsZS1oZWxwZXI6Zmlyc3QtY2hpbGQgKyAubGF5b3V0LWVsZW1lbnQ6bm90KC5sYXlvdXQtY29udGFpbmVyKSB7XG4gIG1hcmdpbi10b3A6IDA7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRhaW5lciA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyLmxheW91dC1jb250YWluZXItZW1wdHkgPiAubGF5b3V0LWNvbnRhaW5lci1jaGlsZHJlbi1wbGFjZWhvbGRlciB7XG4gIGRpc3BsYXk6IGZsZXg7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRhaW5lciA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyLmxheW91dC1jb250YWluZXItZW1wdHkgPiAubGF5b3V0LWNoaWxkcmVuIHtcbiAgcG9zaXRpb246IGFic29sdXRlO1xuICB0b3A6IDA7XG4gIHJpZ2h0OiAwO1xuICBib3R0b206IDA7XG4gIGxlZnQ6IDA7XG59XG4ubGF5b3V0LWVkaXRvcjpub3QoLmxheW91dC1lZGl0b3ItZHJhZ2dpbmcpIC5sYXlvdXQtY29udGFpbmVyLmxheW91dC1lbGVtZW50LWZvY3VzZWQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciA+IC5sYXlvdXQtY2hpbGRyZW4gPiAubGF5b3V0LWVsZW1lbnQ6bm90KC5sYXlvdXQtZWxlbWVudC1hY3RpdmUpIHtcbiAgYm9yZGVyOiAxcHggZGFzaGVkIHJnYmEoMTI0LCAxMjQsIDEyNCwgMC42KTtcbn1cbi5sYXlvdXQtZWRpdG9yOm5vdCgubGF5b3V0LWVkaXRvci1kcmFnZ2luZykgLmxheW91dC1jb250YWluZXIubGF5b3V0LWVsZW1lbnQtZm9jdXNlZCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1jaGlsZHJlbiA+IC5sYXlvdXQtZWxlbWVudDpub3QoLmxheW91dC1lbGVtZW50LWFjdGl2ZSkgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciB7XG4gIG1hcmdpbjogLTFweDtcbn1cbi5sYXlvdXQtZWRpdG9yOm5vdCgubGF5b3V0LWVkaXRvci1kcmFnZ2luZykgLmxheW91dC1jb250YWluZXIubGF5b3V0LWVsZW1lbnQtZm9jdXNlZCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1jaGlsZHJlbiA+IC5sYXlvdXQtY29udGFpbmVyICsgLmxheW91dC1jb250YWluZXI6bm90KC5sYXlvdXQtZWxlbWVudC1hY3RpdmUpIHtcbiAgYm9yZGVyLXRvcDogMDtcbn1cbi5sYXlvdXQtZWRpdG9yOm5vdCgubGF5b3V0LWVkaXRvci1kcmFnZ2luZykgLmxheW91dC1jb250YWluZXIubGF5b3V0LWVsZW1lbnQtZm9jdXNlZCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1jaGlsZHJlbiA+IC5sYXlvdXQtY29udGFpbmVyICsgLmxheW91dC1jb250YWluZXI6bm90KC5sYXlvdXQtZWxlbWVudC1hY3RpdmUpID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIge1xuICBtYXJnaW4tdG9wOiAwO1xufVxuXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNhbnZhcyAjZHVtbXkge1xuICBkaXNwbGF5OiBub25lO1xufVxuXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LXJvdy5sYXlvdXQtZWxlbWVudC1mb2N1c2VkOm5vdCgubGF5b3V0LWVsZW1lbnQtZHJvcHRhcmdldCkgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciA+IC5sYXlvdXQtY2hpbGRyZW4gPiAubGF5b3V0LWVsZW1lbnQ6bm90KC5sYXlvdXQtZWxlbWVudC1hY3RpdmUpIHtcbiAgYm9yZGVyLXRvcDogMXB4IGRhc2hlZCByZ2JhKDEyNCwgMTI0LCAxMjQsIDAuNikgIWltcG9ydGFudDtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtcm93LmxheW91dC1lbGVtZW50LWZvY3VzZWQ6bm90KC5sYXlvdXQtZWxlbWVudC1kcm9wdGFyZ2V0KSA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1jaGlsZHJlbiA+IC5sYXlvdXQtZWxlbWVudDpub3QoLmxheW91dC1lbGVtZW50LWFjdGl2ZSkgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciB7XG4gIG1hcmdpbi10b3A6IC0xcHggIWltcG9ydGFudDtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtcm93LmxheW91dC1lbGVtZW50LWZvY3VzZWQ6bm90KC5sYXlvdXQtZWxlbWVudC1kcm9wdGFyZ2V0KSA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1jaGlsZHJlbiA+IC5sYXlvdXQtZWxlbWVudCArIC5sYXlvdXQtZWxlbWVudDpub3QoLmxheW91dC1lbGVtZW50LWFjdGl2ZSkge1xuICBib3JkZXItbGVmdDogMCAhaW1wb3J0YW50O1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1yb3cubGF5b3V0LWVsZW1lbnQtZm9jdXNlZDpub3QoLmxheW91dC1lbGVtZW50LWRyb3B0YXJnZXQpID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgPiAubGF5b3V0LWNoaWxkcmVuID4gLmxheW91dC1lbGVtZW50ICsgLmxheW91dC1lbGVtZW50Om5vdCgubGF5b3V0LWVsZW1lbnQtYWN0aXZlKSA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIHtcbiAgbWFyZ2luLWxlZnQ6IDAgIWltcG9ydGFudDtcbn1cblxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb2x1bW4gPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciA+IC5sYXlvdXQtY29sdW1uLXJlc2l6ZS1iYXIge1xuICBkaXNwbGF5OiBub25lO1xuICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gIHotaW5kZXg6IDMwO1xuICB0b3A6IDA7XG4gIHdpZHRoOiAxNnB4O1xuICBoZWlnaHQ6IDEwMCU7XG4gIGN1cnNvcjogY29sLXJlc2l6ZTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29sdW1uID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgPiAubGF5b3V0LWNvbHVtbi1yZXNpemUtYmFyLWxlZnQge1xuICBsZWZ0OiAtNnB4O1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb2x1bW4gPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciA+IC5sYXlvdXQtY29sdW1uLXJlc2l6ZS1iYXItcmlnaHQge1xuICByaWdodDogLTZweDtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29sdW1uLmxheW91dC1lbGVtZW50LWZvY3VzZWQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciA+IC5sYXlvdXQtY29sdW1uLXJlc2l6ZS1iYXIge1xuICBkaXNwbGF5OiBibG9jaztcbn1cblxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sIHtcbiAgbWluLWhlaWdodDogMWVtO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAge1xuICBwYWRkaW5nOiAycHg7XG4gIG92ZXJmbG93LXg6IGhpZGRlbjtcbiAgbGluZS1oZWlnaHQ6IG5vcm1hbDtcbiAgLyogdGhpcyBjb2xvciBpcyBqdXN0IGEgc3VnZ2VzdGlvbiBhbmQgY2FuIGJlIGNoYW5nZWQgYmFzZWQgb24gaW1wbGVtZW50YXRpb24gZmVlZGJhY2sgKi9cbiAgLyogdGhpcyBhbHNvIGhhcyBiaWRpIGltcGxpY2F0aW9ucyAqL1xuICAvKiB0aGlzIGFsc28gaGFzIGJpZGkgaW1wbGljYXRpb25zICovXG4gIC8qIExUUi1zcGVjaWZpYzogdXNlICdtYXJnaW4tcmlnaHQnIGZvciBydGwgZWxlbWVudHMgKi9cbiAgLyogTFRSLXNwZWNpZmljOiB1c2UgJ3BhZGRpbmctcmlnaHQnIGZvciBydGwgZWxlbWVudHMgKi9cbiAgLyp0YWJsZVtydWxlcz1ub25lIGldLCB0YWJsZVtydWxlcz1ncm91cHMgaV0sIHRhYmxlW3J1bGVzPXJvd3MgaV0sXG50YWJsZVtydWxlcz1jb2xzIGldLCB0YWJsZVtydWxlcz1hbGwgaV0sIHRhYmxlW2ZyYW1lPXZvaWQgaV0sXG50YWJsZVtmcmFtZT1hYm92ZSBpXSwgdGFibGVbZnJhbWU9YmVsb3cgaV0sIHRhYmxlW2ZyYW1lPWhzaWRlcyBpXSxcbnRhYmxlW2ZyYW1lPWxocyBpXSwgdGFibGVbZnJhbWU9cmhzIGldLCB0YWJsZVtmcmFtZT12c2lkZXMgaV0sXG50YWJsZVtmcmFtZT1ib3ggaV0sIHRhYmxlW2ZyYW1lPWJvcmRlciBpXSxcbnRhYmxlW3J1bGVzPW5vbmUgaV0gPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1ub25lIGldID4gdHIgPiB0aCxcbnRhYmxlW3J1bGVzPWdyb3VwcyBpXSA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPWdyb3VwcyBpXSA+IHRyID4gdGgsXG50YWJsZVtydWxlcz1yb3dzIGldID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9cm93cyBpXSA+IHRyID4gdGgsXG50YWJsZVtydWxlcz1jb2xzIGldID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9Y29scyBpXSA+IHRyID4gdGgsXG50YWJsZVtydWxlcz1hbGwgaV0gPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1hbGwgaV0gPiB0ciA+IHRoLFxudGFibGVbcnVsZXM9bm9uZSBpXSA+IHRoZWFkID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9bm9uZSBpXSA+IHRoZWFkID4gdHIgPiB0aCxcbnRhYmxlW3J1bGVzPWdyb3VwcyBpXSA+IHRoZWFkID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9Z3JvdXBzIGldID4gdGhlYWQgPiB0ciA+IHRoLFxudGFibGVbcnVsZXM9cm93cyBpXSA+IHRoZWFkID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9cm93cyBpXSA+IHRoZWFkID4gdHIgPiB0aCxcbnRhYmxlW3J1bGVzPWNvbHMgaV0gPiB0aGVhZCA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPWNvbHMgaV0gPiB0aGVhZCA+IHRyID4gdGgsXG50YWJsZVtydWxlcz1hbGwgaV0gPiB0aGVhZCA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPWFsbCBpXSA+IHRoZWFkID4gdHIgPiB0aCxcbnRhYmxlW3J1bGVzPW5vbmUgaV0gPiB0Ym9keSA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPW5vbmUgaV0gPiB0Ym9keSA+IHRyID4gdGgsXG50YWJsZVtydWxlcz1ncm91cHMgaV0gPiB0Ym9keSA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPWdyb3VwcyBpXSA+IHRib2R5ID4gdHIgPiB0aCxcbnRhYmxlW3J1bGVzPXJvd3MgaV0gPiB0Ym9keSA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPXJvd3MgaV0gPiB0Ym9keSA+IHRyID4gdGgsXG50YWJsZVtydWxlcz1jb2xzIGldID4gdGJvZHkgPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1jb2xzIGldID4gdGJvZHkgPiB0ciA+IHRoLFxudGFibGVbcnVsZXM9YWxsIGldID4gdGJvZHkgPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1hbGwgaV0gPiB0Ym9keSA+IHRyID4gdGgsXG50YWJsZVtydWxlcz1ub25lIGldID4gdGZvb3QgPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1ub25lIGldID4gdGZvb3QgPiB0ciA+IHRoLFxudGFibGVbcnVsZXM9Z3JvdXBzIGldID4gdGZvb3QgPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1ncm91cHMgaV0gPiB0Zm9vdCA+IHRyID4gdGgsXG50YWJsZVtydWxlcz1yb3dzIGldID4gdGZvb3QgPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1yb3dzIGldID4gdGZvb3QgPiB0ciA+IHRoLFxudGFibGVbcnVsZXM9Y29scyBpXSA+IHRmb290ID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9Y29scyBpXSA+IHRmb290ID4gdHIgPiB0aCxcbnRhYmxlW3J1bGVzPWFsbCBpXSA+IHRmb290ID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9YWxsIGldID4gdGZvb3QgPiB0ciA+IHRoIHtcbiAgICBib3JkZXItY29sb3I6IGJsYWNrO1xufSovXG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwICosXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwICoge1xuICBtYXJnaW46IDA7XG4gIHBhZGRpbmc6IDA7XG4gIGJveC1zaXppbmc6IGNvbnRlbnQtYm94O1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBhZGRyZXNzLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBhZGRyZXNzLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBibG9ja3F1b3RlLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBibG9ja3F1b3RlLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBjZW50ZXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGNlbnRlcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGl2LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkaXYsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGZpZ3VyZSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZmlndXJlLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBmaWdjYXB0aW9uLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBmaWdjYXB0aW9uLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBmb290ZXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGZvb3Rlcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZm9ybSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZm9ybSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgaGVhZGVyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBoZWFkZXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGhyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBocixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgbGVnZW5kLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBsZWdlbmQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGxpc3RpbmcsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGxpc3RpbmcsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHAsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHAsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHBsYWludGV4dCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgcGxhaW50ZXh0LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBwcmUsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHByZSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgeG1wLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB4bXAge1xuICBkaXNwbGF5OiBibG9jaztcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYmxvY2txdW90ZSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYmxvY2txdW90ZSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZmlndXJlLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBmaWd1cmUsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGxpc3RpbmcsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGxpc3RpbmcsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHAsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHAsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHBsYWludGV4dCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgcGxhaW50ZXh0LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBwcmUsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHByZSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgeG1wLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB4bXAge1xuICBtYXJnaW4tdG9wOiAxZW07XG4gIG1hcmdpbi1ib3R0b206IDFlbTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYmxvY2txdW90ZSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYmxvY2txdW90ZSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZmlndXJlLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBmaWd1cmUge1xuICBtYXJnaW4tbGVmdDogNDBweDtcbiAgbWFyZ2luLXJpZ2h0OiA0MHB4O1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBhZGRyZXNzLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBhZGRyZXNzIHtcbiAgZm9udC1zdHlsZTogaXRhbGljO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBsaXN0aW5nLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBsaXN0aW5nLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBwbGFpbnRleHQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHBsYWludGV4dCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgcHJlLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBwcmUsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHhtcCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgeG1wIHtcbiAgZm9udC1mYW1pbHk6IG1vbm9zcGFjZTtcbiAgd2hpdGUtc3BhY2U6IHByZTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgY2l0ZSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgY2l0ZSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGZuLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkZm4sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGVtLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBlbSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgaSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgaSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdmFyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB2YXIge1xuICBmb250LXN0eWxlOiBpdGFsaWM7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHN0cm9uZyxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgc3Ryb25nIHtcbiAgZm9udC13ZWlnaHQ6IGJvbGRlcjtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgY29kZSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgY29kZSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAga2JkLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBrYmQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHNhbXAsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHNhbXAsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHR0LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0dCB7XG4gIGZvbnQtZmFtaWx5OiBtb25vc3BhY2U7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGJpZyxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYmlnIHtcbiAgZm9udC1zaXplOiBsYXJnZXI7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHNtYWxsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBzbWFsbCB7XG4gIGZvbnQtc2l6ZTogc21hbGxlcjtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgc3ViLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBzdWIge1xuICB2ZXJ0aWNhbC1hbGlnbjogc3ViO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBzdXAsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHN1cCB7XG4gIHZlcnRpY2FsLWFsaWduOiBzdXBlcjtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgc3ViLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBzdWIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHN1cCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgc3VwIHtcbiAgbGluZS1oZWlnaHQ6IG5vcm1hbDtcbiAgZm9udC1zaXplOiBzbWFsbGVyO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBydWJ5LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBydWJ5IHtcbiAgZGlzcGxheTogcnVieTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgcmIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHJiIHtcbiAgZGlzcGxheTogcnVieS1iYXNlO1xuICB3aGl0ZS1zcGFjZTogbm93cmFwO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBydCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgcnQge1xuICBkaXNwbGF5OiBydWJ5LXRleHQ7XG4gIHdoaXRlLXNwYWNlOiBub3dyYXA7XG4gIGZvbnQtc2l6ZTogNTAlO1xuICBmb250LXZhcmlhbnQtZWFzdC1hc2lhbjogcnVieTtcbiAgdGV4dC1lbXBoYXNpczogbm9uZTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgcmJjLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCByYmMge1xuICBkaXNwbGF5OiBydWJ5LWJhc2UtY29udGFpbmVyO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBydGMsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHJ0YyB7XG4gIGRpc3BsYXk6IHJ1YnktdGV4dC1jb250YWluZXI7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHJ1YnksXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHJ1YnksXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHJiLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCByYixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgcnQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHJ0LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCByYmMsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHJiYyxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgcnRjLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBydGMge1xuICB1bmljb2RlLWJpZGk6IGlzb2xhdGU7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIDpsaW5rLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCA6bGluayB7XG4gIGNvbG9yOiAjMDAwMEVFO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCA6dmlzaXRlZCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgOnZpc2l0ZWQge1xuICBjb2xvcjogIzU1MUE4Qjtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgOmxpbmssXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIDpsaW5rLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCA6dmlzaXRlZCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgOnZpc2l0ZWQge1xuICB0ZXh0LWRlY29yYXRpb246IHVuZGVybGluZTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYTpsaW5rW3JlbH49aGVscF0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGE6bGlua1tyZWx+PWhlbHBdLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBhOnZpc2l0ZWRbcmVsfj1oZWxwXSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYTp2aXNpdGVkW3JlbH49aGVscF0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGFyZWE6bGlua1tyZWx+PWhlbHBdLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBhcmVhOmxpbmtbcmVsfj1oZWxwXSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYXJlYTp2aXNpdGVkW3JlbH49aGVscF0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGFyZWE6dmlzaXRlZFtyZWx+PWhlbHBdIHtcbiAgY3Vyc29yOiBoZWxwO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCA6Zm9jdXMsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIDpmb2N1cyB7XG4gIG91dGxpbmU6IGF1dG87XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG1hcmssXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG1hcmsge1xuICBiYWNrZ3JvdW5kOiB5ZWxsb3c7XG4gIGNvbG9yOiBibGFjaztcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYWJiclt0aXRsZV0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGFiYnJbdGl0bGVdLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBhY3JvbnltW3RpdGxlXSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYWNyb255bVt0aXRsZV0ge1xuICB0ZXh0LWRlY29yYXRpb246IGRvdHRlZCB1bmRlcmxpbmU7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGlucyxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgaW5zLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB1LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB1IHtcbiAgdGV4dC1kZWNvcmF0aW9uOiB1bmRlcmxpbmU7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRlbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGVsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBzLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBzLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBzdHJpa2UsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHN0cmlrZSB7XG4gIHRleHQtZGVjb3JhdGlvbjogbGluZS10aHJvdWdoO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBibGluayxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYmxpbmsge1xuICB0ZXh0LWRlY29yYXRpb246IGJsaW5rO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBxOjpiZWZvcmUsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHE6OmJlZm9yZSB7XG4gIGNvbnRlbnQ6IG9wZW4tcXVvdGU7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHE6OmFmdGVyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBxOjphZnRlciB7XG4gIGNvbnRlbnQ6IGNsb3NlLXF1b3RlO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBicixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYnIge1xuICBjb250ZW50OiAnXFxBJztcbiAgd2hpdGUtc3BhY2U6IHByZTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgbm9icixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgbm9iciB7XG4gIHdoaXRlLXNwYWNlOiBub3dyYXA7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHdicixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgd2JyIHtcbiAgY29udGVudDogJ1xcMjAwQic7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG5vYnIgd2JyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBub2JyIHdiciB7XG4gIHdoaXRlLXNwYWNlOiBub3JtYWw7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGFydGljbGUsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGFydGljbGUsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGFzaWRlLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBhc2lkZSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgaDEsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGgxLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBoMixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgaDIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGgzLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBoMyxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgaDQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGg0LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBoNSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgaDUsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGg2LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBoNixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgaGdyb3VwLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBoZ3JvdXAsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG5hdixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgbmF2LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBzZWN0aW9uLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBzZWN0aW9uIHtcbiAgZGlzcGxheTogYmxvY2s7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGgxLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBoMSB7XG4gIG1hcmdpbi10b3A6IDAuNjdlbTtcbiAgbWFyZ2luLWJvdHRvbTogMC42N2VtO1xuICBmb250LXNpemU6IDIuMDBlbTtcbiAgZm9udC13ZWlnaHQ6IGJvbGQ7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGgyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBoMiB7XG4gIG1hcmdpbi10b3A6IDAuODNlbTtcbiAgbWFyZ2luLWJvdHRvbTogMC44M2VtO1xuICBmb250LXNpemU6IDEuNTBlbTtcbiAgZm9udC13ZWlnaHQ6IGJvbGQ7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGgzLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBoMyB7XG4gIG1hcmdpbi10b3A6IDEuMDBlbTtcbiAgbWFyZ2luLWJvdHRvbTogMS4wMGVtO1xuICBmb250LXNpemU6IDEuMTdlbTtcbiAgZm9udC13ZWlnaHQ6IGJvbGQ7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGg0LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBoNCB7XG4gIG1hcmdpbi10b3A6IDEuMzNlbTtcbiAgbWFyZ2luLWJvdHRvbTogMS4zM2VtO1xuICBmb250LXNpemU6IDEuMDBlbTtcbiAgZm9udC13ZWlnaHQ6IGJvbGQ7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGg1LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBoNSB7XG4gIG1hcmdpbi10b3A6IDEuNjdlbTtcbiAgbWFyZ2luLWJvdHRvbTogMS42N2VtO1xuICBmb250LXNpemU6IDAuODNlbTtcbiAgZm9udC13ZWlnaHQ6IGJvbGQ7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGg2LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBoNiB7XG4gIG1hcmdpbi10b3A6IDIuMzNlbTtcbiAgbWFyZ2luLWJvdHRvbTogMi4zM2VtO1xuICBmb250LXNpemU6IDAuNjdlbTtcbiAgZm9udC13ZWlnaHQ6IGJvbGQ7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkZCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZHQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGR0LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgb2wsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHVsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB1bCB7XG4gIGRpc3BsYXk6IGJsb2NrO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBsaSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgbGkge1xuICBkaXNwbGF5OiBsaXN0LWl0ZW07XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG9sLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHVsIHtcbiAgbWFyZ2luLXRvcDogMWVtO1xuICBtYXJnaW4tYm90dG9tOiAxZW07XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpciBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpciBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpciBkbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyIGRsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkaXIgb2wsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpciBvbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyIHVsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkaXIgdWwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRsIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGwgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkbCBkbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGwgZGwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRsIG9sLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkbCBvbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGwgdWwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRsIHVsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG9sIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgb2wgZGwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG9sIGRsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCBvbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgb2wgb2wsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG9sIHVsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCB1bCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB1bCBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHVsIGRsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB1bCBkbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwgb2wsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHVsIG9sLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB1bCB1bCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwgdWwge1xuICBtYXJnaW4tdG9wOiAwO1xuICBtYXJnaW4tYm90dG9tOiAwO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkZCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGQge1xuICBtYXJnaW4tbGVmdDogNDBweDtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG9sLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHVsIHtcbiAgcGFkZGluZy1sZWZ0OiA0MHB4O1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgb2wge1xuICBsaXN0LXN0eWxlLXR5cGU6IGRlY2ltYWw7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB1bCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwge1xuICBsaXN0LXN0eWxlLXR5cGU6IGRpc2M7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpciBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpciBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpciB1bCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyIHVsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG9sIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgb2wgdWwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG9sIHVsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB1bCBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHVsIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwgdWwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHVsIHVsIHtcbiAgbGlzdC1zdHlsZS10eXBlOiBjaXJjbGU7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpciBkaXIgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkaXIgZGlyIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyIGRpciB1bCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyIGRpciB1bCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyIG9sIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyIG9sIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyIG9sIHVsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkaXIgb2wgdWwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpciB1bCBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpciB1bCBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpciB1bCB1bCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyIHVsIHVsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCBkaXIgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCBkaXIgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCBkaXIgdWwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG9sIGRpciB1bCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgb2wgb2wgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCBvbCBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG9sIG9sIHVsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCBvbCB1bCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgb2wgdWwgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCB1bCBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG9sIHVsIHVsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCB1bCB1bCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwgZGlyIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwgZGlyIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwgZGlyIHVsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB1bCBkaXIgdWwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHVsIG9sIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwgb2wgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB1bCBvbCB1bCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwgb2wgdWwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHVsIHVsIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwgdWwgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB1bCB1bCB1bCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwgdWwgdWwge1xuICBsaXN0LXN0eWxlLXR5cGU6IHNxdWFyZTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGFibGUsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRhYmxlIHtcbiAgZGlzcGxheTogdGFibGU7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGNhcHRpb24sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGNhcHRpb24ge1xuICBkaXNwbGF5OiB0YWJsZS1jYXB0aW9uO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBjb2xncm91cCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgY29sZ3JvdXAsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGNvbGdyb3VwW2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGNvbGdyb3VwW2hpZGRlbl0ge1xuICBkaXNwbGF5OiB0YWJsZS1jb2x1bW4tZ3JvdXA7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGNvbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgY29sLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBjb2xbaGlkZGVuXSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgY29sW2hpZGRlbl0ge1xuICBkaXNwbGF5OiB0YWJsZS1jb2x1bW47XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRoZWFkLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0aGVhZCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGhlYWRbaGlkZGVuXSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGhlYWRbaGlkZGVuXSB7XG4gIGRpc3BsYXk6IHRhYmxlLWhlYWRlci1ncm91cDtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGJvZHksXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRib2R5LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0Ym9keVtoaWRkZW5dLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0Ym9keVtoaWRkZW5dIHtcbiAgZGlzcGxheTogdGFibGUtcm93LWdyb3VwO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0Zm9vdCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGZvb3QsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRmb290W2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRmb290W2hpZGRlbl0ge1xuICBkaXNwbGF5OiB0YWJsZS1mb290ZXItZ3JvdXA7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0cixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdHJbaGlkZGVuXSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdHJbaGlkZGVuXSB7XG4gIGRpc3BsYXk6IHRhYmxlLXJvdztcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRkLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0aCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGgsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRkW2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRkW2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRoW2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRoW2hpZGRlbl0ge1xuICBkaXNwbGF5OiB0YWJsZS1jZWxsO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBjb2xncm91cFtoaWRkZW5dLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBjb2xncm91cFtoaWRkZW5dLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBjb2xbaGlkZGVuXSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgY29sW2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRoZWFkW2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRoZWFkW2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRib2R5W2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRib2R5W2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRmb290W2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRmb290W2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRyW2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRyW2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRkW2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRkW2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRoW2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRoW2hpZGRlbl0ge1xuICB2aXNpYmlsaXR5OiBjb2xsYXBzZTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGFibGUsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRhYmxlIHtcbiAgYm94LXNpemluZzogYm9yZGVyLWJveDtcbiAgYm9yZGVyLXNwYWNpbmc6IDJweDtcbiAgYm9yZGVyLWNvbGxhcHNlOiBzZXBhcmF0ZTtcbiAgdGV4dC1pbmRlbnQ6IGluaXRpYWw7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRkLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0ZCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGgsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRoIHtcbiAgcGFkZGluZzogMXB4O1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0aCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGgge1xuICBmb250LXdlaWdodDogYm9sZDtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGhlYWQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRoZWFkLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0Ym9keSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGJvZHksXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRmb290LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0Zm9vdCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGFibGUgPiB0cixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGFibGUgPiB0ciB7XG4gIHZlcnRpY2FsLWFsaWduOiBtaWRkbGU7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0cixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRkLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0aCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGgge1xuICB2ZXJ0aWNhbC1hbGlnbjogaW5oZXJpdDtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGFibGUsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRhYmxlLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0ZCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRoLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0aCB7XG4gIGJvcmRlci1jb2xvcjogZ3JheTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGhlYWQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRoZWFkLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0Ym9keSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGJvZHksXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRmb290LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0Zm9vdCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdHIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRyIHtcbiAgYm9yZGVyLWNvbG9yOiBpbmhlcml0O1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBpbnB1dCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgaW5wdXQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHNlbGVjdCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgc2VsZWN0LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvcHRpb24sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG9wdGlvbixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgb3B0Z3JvdXAsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG9wdGdyb3VwLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBidXR0b24sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGJ1dHRvbixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGV4dGFyZWEsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRleHRhcmVhLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBrZXlnZW4sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGtleWdlbiB7XG4gIHRleHQtaW5kZW50OiBpbml0aWFsO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0ZXh0YXJlYSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGV4dGFyZWEge1xuICB3aGl0ZS1zcGFjZTogcHJlLXdyYXA7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGlucHV0W3R5cGU9XCJyYWRpb1wiXSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgaW5wdXRbdHlwZT1cInJhZGlvXCJdLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBpbnB1dFt0eXBlPVwiY2hlY2tib3hcIl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGlucHV0W3R5cGU9XCJjaGVja2JveFwiXSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgaW5wdXRbdHlwZT1cInJlc2V0XCJdLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBpbnB1dFt0eXBlPVwicmVzZXRcIl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGlucHV0W3R5cGU9XCJidXR0b25cIl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGlucHV0W3R5cGU9XCJidXR0b25cIl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGlucHV0W3R5cGU9XCJzdWJtaXRcIl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGlucHV0W3R5cGU9XCJzdWJtaXRcIl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHNlbGVjdCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgc2VsZWN0LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBidXR0b24sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGJ1dHRvbiB7XG4gIGJveC1zaXppbmc6IGJvcmRlci1ib3g7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGlucHV0W3R5cGU9XCJidXR0b25cIl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGlucHV0W3R5cGU9XCJidXR0b25cIl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGJ1dHRvbixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYnV0dG9uIHtcbiAgcGFkZGluZzogMC4zZW0gMC41ZW07XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGhyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBociB7XG4gIGNvbG9yOiBncmF5O1xuICBib3JkZXItc3R5bGU6IGluc2V0O1xuICBib3JkZXItd2lkdGg6IDFweDtcbiAgbWFyZ2luOiAwLjVlbSBhdXRvO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBmaWVsZHNldCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZmllbGRzZXQge1xuICBtYXJnaW4tbGVmdDogMnB4O1xuICBtYXJnaW4tcmlnaHQ6IDJweDtcbiAgYm9yZGVyOiBncm9vdmUgMnB4IFRocmVlREZhY2U7XG4gIHBhZGRpbmc6IDAuMzVlbSAwLjYyNWVtIDAuNzVlbTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgbGVnZW5kLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBsZWdlbmQge1xuICBwYWRkaW5nLWxlZnQ6IDJweDtcbiAgcGFkZGluZy1yaWdodDogMnB4O1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCA+ICo6Zmlyc3QtY2hpbGQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwID4gKjpmaXJzdC1jaGlsZCB7XG4gIG1hcmdpbi10b3A6IDAgIWltcG9ydGFudDtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgPiAqOmxhc3QtY2hpbGQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwID4gKjpsYXN0LWNoaWxkIHtcbiAgbWFyZ2luLWJvdHRvbTogMCAhaW1wb3J0YW50O1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50LmxheW91dC1jb250ZW50LWltYWdlID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgPiAubGF5b3V0LWNvbnRlbnQtbWFya3VwID4gaW1nLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sLmxheW91dC1jb250ZW50LWltYWdlID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgPiAubGF5b3V0LWNvbnRlbnQtbWFya3VwID4gaW1nLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50LmxheW91dC1jb250ZW50LXZlY3Rvci1pbWFnZSA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1jb250ZW50LW1hcmt1cCA+IGltZyxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbC5sYXlvdXQtY29udGVudC12ZWN0b3ItaW1hZ2UgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciA+IC5sYXlvdXQtY29udGVudC1tYXJrdXAgPiBpbWcge1xuICBkaXNwbGF5OiBibG9jaztcbiAgd2lkdGg6IDEwMCU7XG4gIG1heC13aWR0aDogMTAwJTtcbiAgaGVpZ2h0OiBhdXRvO1xufVxuLmxheW91dC1lZGl0b3IgLmltZy1yZXNwb25zaXZlLFxuLmxheW91dC1lZGl0b3IgLmltZy1yZXNwb25zaXZlIGltZyB7XG4gIGRpc3BsYXk6IGJsb2NrO1xuICB3aWR0aDogMTAwJTtcbiAgbWF4LXdpZHRoOiAxMDAlO1xuICBoZWlnaHQ6IGF1dG87XG59XG5cbi5sYXlvdXQtZWRpdG9yID4gLmxheW91dC10b29sYm94LXdyYXBwZXIge1xuICBwb3NpdGlvbjogcmVsYXRpdmU7XG4gIG1hcmdpbi1sZWZ0OiAxMnB4O1xuICB3aWR0aDogMjIwcHg7XG4gIGZsZXgtc2hyaW5rOiAwO1xufVxuLmxheW91dC1lZGl0b3IgPiAubGF5b3V0LXRvb2xib3gtd3JhcHBlciA+IC5sYXlvdXQtdG9vbGJveCB7XG4gIGJvcmRlcjogMXB4IHNvbGlkICNlNGU1ZTY7XG4gIHdpZHRoOiAyMjBweDtcbiAgbWluLWhlaWdodDogNDAwcHg7XG4gIHBhZGRpbmc6IDZweDtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2YzZjRmNTtcbn1cbi5sYXlvdXQtZWRpdG9yID4gLmxheW91dC10b29sYm94LXdyYXBwZXIgPiAubGF5b3V0LXRvb2xib3guc3RpY2t5LXRvcCB7XG4gIHBvc2l0aW9uOiBmaXhlZDtcbiAgdG9wOiAwO1xuICBtYXgtaGVpZ2h0OiAxMDAlO1xuICBvdmVyZmxvdy15OiBhdXRvO1xufVxuLmxheW91dC1lZGl0b3IgPiAubGF5b3V0LXRvb2xib3gtd3JhcHBlciA+IC5sYXlvdXQtdG9vbGJveC5zdGlja3ktYm90dG9tIHtcbiAgcG9zaXRpb246IGFic29sdXRlO1xuICBib3R0b206IDA7XG59XG4ubGF5b3V0LWVkaXRvciA+IC5sYXlvdXQtdG9vbGJveC13cmFwcGVyID4gLmxheW91dC10b29sYm94IC5sYXlvdXQtdG9vbGJveC1ncm91cCB7XG4gIG1hcmdpbi10b3A6IDEycHg7XG59XG4ubGF5b3V0LWVkaXRvciA+IC5sYXlvdXQtdG9vbGJveC13cmFwcGVyID4gLmxheW91dC10b29sYm94IC5sYXlvdXQtdG9vbGJveC1ncm91cCAubGF5b3V0LXRvb2xib3gtZ3JvdXAtaGVhZGluZyB7XG4gIGRpc3BsYXk6IGJsb2NrO1xuICBtYXJnaW4tYm90dG9tOiA0cHg7XG4gIHRleHQtZGVjb3JhdGlvbjogbm9uZTtcbn1cbi5sYXlvdXQtZWRpdG9yID4gLmxheW91dC10b29sYm94LXdyYXBwZXIgPiAubGF5b3V0LXRvb2xib3ggLmxheW91dC10b29sYm94LWdyb3VwIC5sYXlvdXQtdG9vbGJveC1ncm91cC1oZWFkaW5nOmJlZm9yZSB7XG4gIGRpc3BsYXk6IGlubGluZS1ibG9jaztcbiAgd2lkdGg6IDEwcHg7XG4gIG1hcmdpbi1yaWdodDogNHB4O1xuICBmb250OiBub3JtYWwgbm9ybWFsIG5vcm1hbCAxNHB4LzEgRm9udEF3ZXNvbWU7XG4gIHRleHQtYWxpZ246IGNlbnRlcjtcbiAgY29udGVudDogXCJcXGYwZDdcIjtcbn1cbi5sYXlvdXQtZWRpdG9yID4gLmxheW91dC10b29sYm94LXdyYXBwZXIgPiAubGF5b3V0LXRvb2xib3ggLmxheW91dC10b29sYm94LWdyb3VwLmNvbGxhcHNlZCAubGF5b3V0LXRvb2xib3gtZ3JvdXAtaGVhZGluZzpiZWZvcmUge1xuICBjb250ZW50OiBcIlxcZjBkYVwiO1xufVxuLmxheW91dC1lZGl0b3IgPiAubGF5b3V0LXRvb2xib3gtd3JhcHBlciA+IC5sYXlvdXQtdG9vbGJveCAubGF5b3V0LXRvb2xib3gtZ3JvdXAuY29sbGFwc2VkIC5sYXlvdXQtdG9vbGJveC1pdGVtcyB7XG4gIGRpc3BsYXk6IG5vbmU7XG59XG4ubGF5b3V0LWVkaXRvciA+IC5sYXlvdXQtdG9vbGJveC13cmFwcGVyID4gLmxheW91dC10b29sYm94IC5sYXlvdXQtdG9vbGJveC1ncm91cCAubGF5b3V0LXRvb2xib3gtc2VjdGlvbiArIC5sYXlvdXQtdG9vbGJveC1zZWN0aW9uIHtcbiAgbWFyZ2luLXRvcDogNHB4O1xufVxuLmxheW91dC1lZGl0b3IgPiAubGF5b3V0LXRvb2xib3gtd3JhcHBlciA+IC5sYXlvdXQtdG9vbGJveCAubGF5b3V0LXRvb2xib3gtZ3JvdXAgLmxheW91dC10b29sYm94LWl0ZW0ge1xuICBib3JkZXI6IDFweCBzb2xpZCAjZTRlNWU2O1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmO1xuICBwYWRkaW5nOiA5cHggMTJweDtcbiAgY3Vyc29yOiBkZWZhdWx0O1xufVxuLmxheW91dC1lZGl0b3IgPiAubGF5b3V0LXRvb2xib3gtd3JhcHBlciA+IC5sYXlvdXQtdG9vbGJveCAubGF5b3V0LXRvb2xib3gtZ3JvdXAgLmxheW91dC10b29sYm94LWl0ZW0gaSB7XG4gIGRpc3BsYXk6IGlubGluZS1ibG9jaztcbiAgd2lkdGg6IDE2cHg7XG4gIGZvbnQ6IG5vcm1hbCBub3JtYWwgbm9ybWFsIDE0cHgvMSBGb250QXdlc29tZTtcbn1cbi5sYXlvdXQtZWRpdG9yID4gLmxheW91dC10b29sYm94LXdyYXBwZXIgPiAubGF5b3V0LXRvb2xib3ggLmxheW91dC10b29sYm94LWdyb3VwIC5sYXlvdXQtdG9vbGJveC1pdGVtICsgLmxheW91dC10b29sYm94LWl0ZW0ge1xuICBtYXJnaW4tdG9wOiA0cHg7XG59XG4ubGF5b3V0LWVkaXRvciA+IC5sYXlvdXQtdG9vbGJveC13cmFwcGVyID4gLmxheW91dC10b29sYm94IC5sYXlvdXQtdG9vbGJveC1ncm91cCArIC5sYXlvdXQtdG9vbGJveC1ncm91cCB7XG4gIG1hcmdpbi10b3A6IDZweDtcbn1cblxuLmxheW91dC1lZGl0b3IgLmxheW91dC1wb3B1cCB7XG4gIGRpc3BsYXk6IG5vbmU7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgbWFyZ2luOiAwO1xuICAtbW96LWJveC1zaGFkb3c6IDNweCAzcHggMTFweCAwIHJnYmEoNTAsIDUwLCA1MCwgMC41KTtcbiAgLXdlYmtpdC1ib3gtc2hhZG93OiAzcHggM3B4IDExcHggMCByZ2JhKDUwLCA1MCwgNTAsIDAuNSk7XG4gIGJveC1zaGFkb3c6IDNweCAzcHggMTFweCAwIHJnYmEoNTAsIDUwLCA1MCwgMC41KTtcbiAgYm9yZGVyOiAxcHggc29saWQgI2U0ZTVlNjtcbiAgcGFkZGluZzogMnB4IDA7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmN2Y3Zjc7XG4gIGxpc3Qtc3R5bGU6IG5vbmU7XG4gIHotaW5kZXg6IDIwO1xuICBjb2xvcjogIzdjN2M3YztcbiAgdGV4dC1hbGlnbjogbGVmdDtcbiAgY3Vyc29yOiBkZWZhdWx0O1xuICB3aGl0ZS1zcGFjZTogbm93cmFwO1xuICBsaW5lLWhlaWdodDogbm9ybWFsO1xuICBtaW4td2lkdGg6IDMwMHB4O1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1wb3B1cC53aWRlIHtcbiAgd2lkdGg6IDYwMHB4O1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1wb3B1cCAubGF5b3V0LXBvcHVwLWZsZXgge1xuICBkaXNwbGF5OiBmbGV4O1xuICBwYWRkaW5nOiAycHggNXB4O1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1wb3B1cCAubGF5b3V0LXBvcHVwLWZsZXggLmxheW91dC1wb3B1cC1jb2x1bW4gKyAubGF5b3V0LXBvcHVwLWNvbHVtbiB7XG4gIG1hcmdpbi1sZWZ0OiA0cHg7XG4gIGJvcmRlci1sZWZ0OiAxcHggc29saWQgcmdiYSgxMjgsIDEyOCwgMTI4LCAwLjE1KTtcbiAgcGFkZGluZy1sZWZ0OiA0cHg7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LXBvcHVwIC5sYXlvdXQtcG9wdXAtaXRlbSB7XG4gIHBhZGRpbmc6IDRweCA2cHg7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LXBvcHVwIC5sYXlvdXQtcG9wdXAtbGFiZWwge1xuICBmb250LXNpemU6IDAuOWVtO1xuICBmb250LXdlaWdodDogYm9sZDtcbiAgY29sb3I6ICM3YzdjN2M7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LXBvcHVwIC5sYXlvdXQtcG9wdXAtYWN0aW9uOmhvdmVyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2YzZjRmNTtcbiAgY3Vyc29yOiBwb2ludGVyO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1wb3B1cCAubGF5b3V0LXBvcHVwLWlucHV0IGlucHV0W3R5cGU9J3RleHQnXSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtcG9wdXAgLmxheW91dC1wb3B1cC1pbnB1dCB0ZXh0YXJlYSB7XG4gIHdpZHRoOiAxMDAlO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1wb3B1cCAubGF5b3V0LXBvcHVwLWlucHV0ID4gbGFiZWwge1xuICBkaXNwbGF5OiBibG9jaztcbiAgZm9udC1zaXplOiAwLjllbTtcbn1cbiIsIkBpbXBvcnQgXCJWYXJpYWJsZXMubGVzc1wiO1xyXG5cclxuLmxheW91dC1lZGl0b3Ige1xyXG4gICAgLmxheW91dC1lbGVtZW50IHtcclxuICAgICAgICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcbiAgICAgICAgbWFyZ2luLXRvcDogMDtcclxuICAgICAgICBtYXJnaW4tcmlnaHQ6IDA7XHJcbiAgICAgICAgbWFyZ2luLWJvdHRvbTogMDtcclxuICAgICAgICBwYWRkaW5nOiAwO1xyXG5cclxuICAgICAgICAvLyBXZSBkb24ndCBmdWNrIHdpdGggdGhlIGxlZnQgbWFyZ2luIG9mIGNvbHVtbnMsIGJlY2F1c2UgQm9vdHN0cmFwIHVzZXMgdGhlc2UgdG8gcmVuZGVyIGNvbHVtbiBvZmZzZXRzLlxyXG4gICAgICAgICY6bm90KC5sYXlvdXQtY29sdW1uKSB7XHJcbiAgICAgICAgICAgIG1hcmdpbi1sZWZ0OiAwO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciB7XHJcbiAgICAgICAgICAgID4gLmxheW91dC1wYW5lbCB7XHJcbiAgICAgICAgICAgICAgICBkaXNwbGF5OiBub25lOyAvLyBTaG93biBvbmx5IGluIGFjdGl2ZSBvciBmb2N1c2VkIHN0YXRlcy5cclxuICAgICAgICAgICAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgICAgICAgICAgIG1hcmdpbjogMDtcclxuICAgICAgICAgICAgICAgIHotaW5kZXg6IDIwO1xyXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiAyNXB4O1xyXG4gICAgICAgICAgICAgICAgcGFkZGluZzogMCA2cHg7XHJcbiAgICAgICAgICAgICAgICBsaXN0LXN0eWxlOiBub25lO1xyXG4gICAgICAgICAgICAgICAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcclxuICAgICAgICAgICAgICAgIGxpbmUtaGVpZ2h0OiAyNXB4O1xyXG4gICAgICAgICAgICAgICAgdmVydGljYWwtYWxpZ246IG1pZGRsZTtcclxuXHJcbiAgICAgICAgICAgICAgICA+IC5sYXlvdXQtcGFuZWwtaXRlbSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZGlzcGxheTogaW5saW5lLWJsb2NrO1xyXG4gICAgICAgICAgICAgICAgICAgIGhlaWdodDogMjVweDtcclxuICAgICAgICAgICAgICAgICAgICBwYWRkaW5nOiAxcHggNnB4IDA7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgPiAubGF5b3V0LXBhbmVsLWxhYmVsIHtcclxuICAgICAgICAgICAgICAgICAgICBmb250LXNpemU6IEBmb250LXNpemUgLSAxO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgID4gLmxheW91dC1wYW5lbC1hY3Rpb24ge1xyXG4gICAgICAgICAgICAgICAgICAgIGRpc3BsYXk6IG5vbmU7IC8vIFNob3duIG9ubHkgaW4gZm9jdXNlZCBzdGF0ZS5cclxuICAgICAgICAgICAgICAgICAgICB3aWR0aDogMjhweDtcclxuICAgICAgICAgICAgICAgICAgICBjdXJzb3I6IHBvaW50ZXI7XHJcbiAgICAgICAgICAgICAgICAgICAgdGV4dC1hbGlnbjogY2VudGVyO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICA+IC5sYXlvdXQtcGFuZWwtbWFpbiB7XHJcbiAgICAgICAgICAgICAgICB0b3A6IC0yN3B4O1xyXG4gICAgICAgICAgICAgICAgbGVmdDogLTJweDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyBXaGVuIGRyYWdnaW5nIGZyb20gdG9vbGJveCwgZWxlbWVudHMgd2lsbCBiZSBsaSByYXRoZXIgdGhhbiBkaXYuXHJcbiAgICBsaS5sYXlvdXQtZWxlbWVudCB7XHJcbiAgICAgICAgbGlzdC1zdHlsZTogbm9uZTtcclxuICAgIH1cclxuXHJcbiAgICAmOm5vdCgubGF5b3V0LWVkaXRvci1kcmFnZ2luZykge1xyXG5cclxuICAgICAgICAubGF5b3V0LWVsZW1lbnQtYWN0aXZlLCAubGF5b3V0LWVsZW1lbnQtZm9jdXNlZCB7XHJcbiAgICAgICAgICAgIGJvcmRlci13aWR0aDogMnB4O1xyXG4gICAgICAgICAgICBib3JkZXItc3R5bGU6IHNvbGlkO1xyXG5cclxuICAgICAgICAgICAgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciB7XHJcbiAgICAgICAgICAgICAgICBtYXJnaW46IC0ycHg7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5sYXlvdXQtZWxlbWVudC1hY3RpdmUge1xyXG4gICAgICAgICAgICBAYWN0aXZlLWhpZ2hsaWdodDogZmFkZSgjNjg2ODY4LCAxMCUpO1xyXG5cclxuICAgICAgICAgICAgYm9yZGVyLWNvbG9yOiBAYWN0aXZlLWhpZ2hsaWdodDtcclxuXHJcbiAgICAgICAgICAgID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgPiAubGF5b3V0LXBhbmVsLW1haW4ge1xyXG4gICAgICAgICAgICAgICAgZGlzcGxheTogYmxvY2s7IC8vIFRvIHJldmVhbC5cclxuICAgICAgICAgICAgICAgIHotaW5kZXg6IDMwO1xyXG4gICAgICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogQGFjdGl2ZS1oaWdobGlnaHQ7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5sYXlvdXQtZWxlbWVudC1mb2N1c2VkIHtcclxuICAgICAgICAgICAgQGZvY3VzZWQtaGlnaGxpZ2h0OiAjNjQ4NzIxO1xyXG4gICAgICAgICAgICBAZm9jdXNlZC10ZXh0OiAjZmVmZWZlO1xyXG5cclxuICAgICAgICAgICAgYm9yZGVyLWNvbG9yOiBAZm9jdXNlZC1oaWdobGlnaHQ7XHJcblxyXG4gICAgICAgICAgICA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1wYW5lbCB7XHJcbiAgICAgICAgICAgICAgICBkaXNwbGF5OiBibG9jazsgLy8gVG8gcmV2ZWFsLlxyXG4gICAgICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogQGZvY3VzZWQtaGlnaGxpZ2h0O1xyXG4gICAgICAgICAgICAgICAgY29sb3I6IEBmb2N1c2VkLXRleHQ7XHJcblxyXG4gICAgICAgICAgICAgICAgPiAubGF5b3V0LXBhbmVsLWFjdGlvbiB7XHJcbiAgICAgICAgICAgICAgICAgICAgZGlzcGxheTogaW5saW5lLWJsb2NrOyAvLyBUbyByZXZlYWwuXHJcbiAgICAgICAgICAgICAgICAgICAgJjpob3ZlciB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IGxpZ2h0ZW4oQGZvY3VzZWQtaGlnaGxpZ2h0LCAxMCUpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgJi5kaXNhYmxlZCB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnNvcjogZGVmYXVsdDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29sb3I6IGZhZGUoQGZvY3VzZWQtdGV4dCwgNDAlKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICY6aG92ZXIge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogQGZvY3VzZWQtaGlnaGxpZ2h0O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAmLmFjdGl2ZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yOiBsaWdodGVuKHNhdHVyYXRlKHNwaW4oQGZvY3VzZWQtaGlnaGxpZ2h0LCAtMTApLCAxMDAlKSwgMzAlKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogbGlnaHRlbihAZm9jdXNlZC1oaWdobGlnaHQsIDUlKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICY6aG92ZXIge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogbGlnaHRlbihAZm9jdXNlZC1oaWdobGlnaHQsIDEwJSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5sYXlvdXQtZWxlbWVudC1zZWxlY3RlZCB7XHJcbiAgICAgICAgICAgIEBzZWxlY3RlZC1oaWdobGlnaHQ6ICM2NDg3MjE7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IGZhZGUoQHNlbGVjdGVkLWhpZ2hsaWdodCwgOCUpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAudWktc29ydGFibGUtcGxhY2Vob2xkZXIge1xyXG4gICAgICAgIGRpc3BsYXk6IG5vbmU7XHJcbiAgICB9XHJcblxyXG4gICAgLmxheW91dC1lbGVtZW50LWRyb3B0YXJnZXQge1xyXG4gICAgICAgIEBkcm9wdGFyZ2V0LWhpZ2hsaWdodDogIzY0ODcyMTtcclxuICAgICAgICBib3gtc2hhZG93OiBpbnNldCAwIDAgMTJweCA2cHggZmFkZShAZHJvcHRhcmdldC1oaWdobGlnaHQsIDUwJSk7XHJcblxyXG4gICAgICAgIC51aS1zb3J0YWJsZS1wbGFjZWhvbGRlciB7XHJcbiAgICAgICAgICAgIGRpc3BsYXk6IGJsb2NrOyAvLyBUbyByZXZlYWwuXHJcbiAgICAgICAgICAgIHZpc2liaWxpdHk6IHZpc2libGUgIWltcG9ydGFudDtcclxuICAgICAgICAgICAgbWluLWhlaWdodDogQGVsZW1lbnQtbWluLWhlaWdodCAtIDJweDtcclxuICAgICAgICAgICAgYm9yZGVyOiAycHggZGFzaGVkIEBkcm9wdGFyZ2V0LWhpZ2hsaWdodCAhaW1wb3J0YW50O1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiBmYWRlKEBkcm9wdGFyZ2V0LWhpZ2hsaWdodCwgMTYlKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQSBDU1MgZml4IGZvciBtZWRpYSBpdGVtIGVsZW1lbnRzLlxyXG4gICAgLm1lZGlhLXRodW1ibmFpbCB7XHJcbiAgICAgICAgaW1nIHtcclxuICAgICAgICAgICAgbWF4LXdpZHRoOjEwMCU7XHJcbiAgICAgICAgICAgIG1heC1oZWlnaHQ6IDEwMCU7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcbiIsIkBpbXBvcnQgXCJWYXJpYWJsZXMubGVzc1wiO1xyXG5cclxuLmxheW91dC1lZGl0b3Ige1xyXG4gICAgLmxheW91dC1jb250YWluZXIge1xyXG5cclxuICAgICAgICA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIHtcclxuXHJcbiAgICAgICAgICAgID4gLmxheW91dC1jb250YWluZXItY2hpbGRyZW4tcGxhY2Vob2xkZXIge1xyXG4gICAgICAgICAgICAgICAgZGlzcGxheTogbm9uZTtcclxuICAgICAgICAgICAgICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgICAgICAgICAgICAgICBtYXJnaW46IEBjb250YWluZXItcGFkZGluZyAtIDFweDtcclxuICAgICAgICAgICAgICAgIG1pbi1oZWlnaHQ6IEBlbGVtZW50LW1pbi1oZWlnaHQ7XHJcbiAgICAgICAgICAgICAgICBib3JkZXI6IDFweCBkYXNoZWQgZmFkZShAZ3JheS10ZXh0LCA0MCUpO1xyXG4gICAgICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogNHB4O1xyXG4gICAgICAgICAgICAgICAgcGFkZGluZzogQGNvbnRhaW5lci1wYWRkaW5nO1xyXG4gICAgICAgICAgICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgICAgICAgICAgICAgICBmb250LXNpemU6IEBmb250LXNpemUgLSAxO1xyXG4gICAgICAgICAgICAgICAgZm9udC1zdHlsZTogaXRhbGljO1xyXG4gICAgICAgICAgICAgICAgb3BhY2l0eTogMC42O1xyXG4gICAgICAgICAgICAgICAgdGV4dC1hbGlnbjogY2VudGVyO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICA+IC5sYXlvdXQtY2hpbGRyZW4ge1xyXG4gICAgICAgICAgICAgICAgcGFkZGluZzogQGNvbnRhaW5lci1wYWRkaW5nO1xyXG5cclxuICAgICAgICAgICAgICAgIC8vIEFsbCBhZGphY2VudCBub24tY29udGFpbmVyIGNoaWxkcmVuIG5lZWQgc29tZSBzcGFjZSBiZXR3ZWVuLi4uXHJcbiAgICAgICAgICAgICAgICA+IC5sYXlvdXQtZWxlbWVudDpub3QoLmxheW91dC1jb250YWluZXIpICsgLmxheW91dC1lbGVtZW50Om5vdCgubGF5b3V0LWNvbnRhaW5lcikge1xyXG4gICAgICAgICAgICAgICAgICAgIG1hcmdpbi10b3A6IEBjb250ZW50LXNwYWNpbmc7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gLi4uIGV4Y2VwdCB3aGVuIGpRdWVyeSBVSSBzb3J0YWJsZSBoZWxwZXIgaXMgdGhlIGZpcnN0IGVsZW1lbnQgKGJlY2F1c2UgdGhhdCBvbmUgaXMgYWJzb2x1dGVseSBwb3NpdGlvbmVkIGFuZCBcImZsb2F0aW5nXCIpLlxyXG4gICAgICAgICAgICAgICAgPiAudWktc29ydGFibGUtaGVscGVyOmZpcnN0LWNoaWxkICsgLmxheW91dC1lbGVtZW50Om5vdCgubGF5b3V0LWNvbnRhaW5lcikge1xyXG4gICAgICAgICAgICAgICAgICAgIG1hcmdpbi10b3A6IDA7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICYubGF5b3V0LWNvbnRhaW5lci1lbXB0eSB7XHJcbiAgICAgICAgICAgICAgICA+IC5sYXlvdXQtY29udGFpbmVyLWNoaWxkcmVuLXBsYWNlaG9sZGVyIHtcclxuICAgICAgICAgICAgICAgICAgICBkaXNwbGF5OiBmbGV4OyAvLyBUbyByZXZlYWwuXHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgPiAubGF5b3V0LWNoaWxkcmVuIHtcclxuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICAgICAgICAgICAgICAgICAgdG9wOiAwO1xyXG4gICAgICAgICAgICAgICAgICAgIHJpZ2h0OiAwO1xyXG4gICAgICAgICAgICAgICAgICAgIGJvdHRvbTogMDtcclxuICAgICAgICAgICAgICAgICAgICBsZWZ0OiAwO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgICY6bm90KC5sYXlvdXQtZWRpdG9yLWRyYWdnaW5nKSB7XHJcbiAgICAgICAgLmxheW91dC1jb250YWluZXIubGF5b3V0LWVsZW1lbnQtZm9jdXNlZCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1jaGlsZHJlbiB7XHJcbiAgICAgICAgICAgID4gLmxheW91dC1lbGVtZW50Om5vdCgubGF5b3V0LWVsZW1lbnQtYWN0aXZlKSB7XHJcbiAgICAgICAgICAgICAgICBib3JkZXI6IDFweCBkYXNoZWQgZmFkZShAZ3JheS10ZXh0LCA2MCUpO1xyXG5cclxuICAgICAgICAgICAgICAgID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIge1xyXG4gICAgICAgICAgICAgICAgICAgIG1hcmdpbjogLTFweDtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgPiAubGF5b3V0LWNvbnRhaW5lciArIC5sYXlvdXQtY29udGFpbmVyOm5vdCgubGF5b3V0LWVsZW1lbnQtYWN0aXZlKSB7XHJcbiAgICAgICAgICAgICAgICBib3JkZXItdG9wOiAwO1xyXG5cclxuICAgICAgICAgICAgICAgID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIge1xyXG4gICAgICAgICAgICAgICAgICAgIG1hcmdpbi10b3A6IDA7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcbn1cclxuIiwiQGltcG9ydCBcIlZhcmlhYmxlcy5sZXNzXCI7XHJcblxyXG4ubGF5b3V0LWVkaXRvciB7XHJcbiAgICAubGF5b3V0LWNhbnZhcyB7XHJcbiAgICAgICAgI2R1bW15IHsgLy8gT25seSBhZGRlZCBiZWNhdXNlIFdFIGRvZXNuJ3QgY29tcGlsZSBpZiB0aGVyZSBhcmUgbm8gcnVsZXMuXHJcbiAgICAgICAgICAgIGRpc3BsYXk6IG5vbmU7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcbiIsIkBpbXBvcnQgXCJWYXJpYWJsZXMubGVzc1wiO1xyXG5cclxuLmxheW91dC1lZGl0b3Ige1xyXG4gICAgLmxheW91dC1yb3cge1xyXG4gICAgICAgICYubGF5b3V0LWVsZW1lbnQtZm9jdXNlZDpub3QoLmxheW91dC1lbGVtZW50LWRyb3B0YXJnZXQpID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgPiAubGF5b3V0LWNoaWxkcmVuIHtcclxuICAgICAgICAgICAgPiAubGF5b3V0LWVsZW1lbnQ6bm90KC5sYXlvdXQtZWxlbWVudC1hY3RpdmUpIHtcclxuICAgICAgICAgICAgICAgIGJvcmRlci10b3A6IDFweCBkYXNoZWQgZmFkZShAZ3JheS10ZXh0LCA2MCUpICFpbXBvcnRhbnQ7XHJcbiAgICAgICAgICAgICAgICA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIHtcclxuICAgICAgICAgICAgICAgICAgICBtYXJnaW4tdG9wOiAtMXB4ICFpbXBvcnRhbnQ7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgID4gLmxheW91dC1lbGVtZW50ICsgLmxheW91dC1lbGVtZW50Om5vdCgubGF5b3V0LWVsZW1lbnQtYWN0aXZlKSB7XHJcbiAgICAgICAgICAgICAgICBib3JkZXItbGVmdDogMCAhaW1wb3J0YW50O1xyXG4gICAgICAgICAgICAgICAgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciB7XHJcbiAgICAgICAgICAgICAgICAgICAgbWFyZ2luLWxlZnQ6IDAgIWltcG9ydGFudDtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxufSIsIkBpbXBvcnQgXCJWYXJpYWJsZXMubGVzc1wiO1xyXG5cclxuLmxheW91dC1lZGl0b3Ige1xyXG4gICAgLmxheW91dC1jb2x1bW4ge1xyXG4gICAgICAgID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIge1xyXG4gICAgICAgICAgICA+IC5sYXlvdXQtY29sdW1uLXJlc2l6ZS1iYXIge1xyXG4gICAgICAgICAgICAgICAgZGlzcGxheTogbm9uZTtcclxuICAgICAgICAgICAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgICAgICAgICAgIHotaW5kZXg6IDMwO1xyXG4gICAgICAgICAgICAgICAgdG9wOiAwO1xyXG4gICAgICAgICAgICAgICAgd2lkdGg6IDE2cHg7XHJcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IDEwMCU7XHJcbiAgICAgICAgICAgICAgICBjdXJzb3I6IGNvbC1yZXNpemU7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgID4gLmxheW91dC1jb2x1bW4tcmVzaXplLWJhci1sZWZ0IHtcclxuICAgICAgICAgICAgICAgIGxlZnQ6IC02cHg7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgID4gLmxheW91dC1jb2x1bW4tcmVzaXplLWJhci1yaWdodCB7XHJcbiAgICAgICAgICAgICAgICByaWdodDogLTZweDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgJi5sYXlvdXQtZWxlbWVudC1mb2N1c2VkID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgPiAubGF5b3V0LWNvbHVtbi1yZXNpemUtYmFyIHtcclxuICAgICAgICAgICAgZGlzcGxheTogYmxvY2s7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcbiIsIkBpbXBvcnQgXCJWYXJpYWJsZXMubGVzc1wiO1xyXG5AaW1wb3J0IFwiUmVzZXQubGVzc1wiO1xyXG5cclxuLmxheW91dC1lZGl0b3Ige1xyXG4gICAgLmxheW91dC1jb250ZW50LCAubGF5b3V0LWh0bWwge1xyXG4gICAgICAgIG1pbi1oZWlnaHQ6IDFlbTtcclxuXHJcbiAgICAgICAgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciB7XHJcbiAgICAgICAgICAgIC5sYXlvdXQtY29udGVudC1tYXJrdXAge1xyXG5cclxuICAgICAgICAgICAgICAgIHBhZGRpbmc6IDJweDtcclxuICAgICAgICAgICAgICAgIG92ZXJmbG93LXg6IGhpZGRlbjtcclxuICAgICAgICAgICAgICAgIGxpbmUtaGVpZ2h0OiBub3JtYWw7XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gUmVzZXQgdG8gSFRNTDUgVzNDIHN0YW5kYXJkIGRlZmF1bHQgc3R5bGluZyB3aXRoaW4gY29udGVudC5cclxuICAgICAgICAgICAgICAgIC5yZXNldCgpO1xyXG5cclxuICAgICAgICAgICAgICAgID4gKjpmaXJzdC1jaGlsZCB7XHJcbiAgICAgICAgICAgICAgICAgICAgbWFyZ2luLXRvcDogMCAhaW1wb3J0YW50OyAvLyBJbXBvcnRhbnQgYmVjYXVzZSBzaXRlLmNzcyBvZiB0aGUgYWRtaW4gdGhlbWUgc3R5bGVzIGhlYWRpbmcgbWFyZ2lucyB3aXRoIGEgdmVyeSBoaWdoIHNwZWNpZmljaXR5LlxyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgID4gKjpsYXN0LWNoaWxkIHtcclxuICAgICAgICAgICAgICAgICAgICBtYXJnaW4tYm90dG9tOiAwICFpbXBvcnRhbnQ7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYubGF5b3V0LWNvbnRlbnQtaW1hZ2UsICYubGF5b3V0LWNvbnRlbnQtdmVjdG9yLWltYWdlIHtcclxuICAgICAgICAgICAgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciA+IC5sYXlvdXQtY29udGVudC1tYXJrdXAgPiBpbWcge1xyXG4gICAgICAgICAgICAgICAgZGlzcGxheTogYmxvY2s7XHJcbiAgICAgICAgICAgICAgICB3aWR0aDogMTAwJTtcclxuICAgICAgICAgICAgICAgIG1heC13aWR0aDogMTAwJTtcclxuICAgICAgICAgICAgICAgIGhlaWdodDogYXV0bztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAuaW1nLXJlc3BvbnNpdmUsIC5pbWctcmVzcG9uc2l2ZSBpbWcge1xyXG4gICAgICAgIGRpc3BsYXk6IGJsb2NrO1xyXG4gICAgICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgICAgIG1heC13aWR0aDogMTAwJTtcclxuICAgICAgICBoZWlnaHQ6IGF1dG87XHJcbiAgICB9XHJcbn1cclxuIiwi77u/LnJlc2V0KCkge1xyXG5cclxuICAgICoge1xyXG4gICAgICAgIG1hcmdpbjogMDtcclxuICAgICAgICBwYWRkaW5nOiAwO1xyXG4gICAgICAgIGJveC1zaXppbmc6IGNvbnRlbnQtYm94O1xyXG4gICAgfVxyXG5cclxuICAgIGFkZHJlc3MsIGJsb2NrcXVvdGUsIGNlbnRlciwgZGl2LCBmaWd1cmUsIGZpZ2NhcHRpb24sIGZvb3RlciwgZm9ybSxcclxuICAgIGhlYWRlciwgaHIsIGxlZ2VuZCwgbGlzdGluZywgcCwgcGxhaW50ZXh0LCBwcmUsIHhtcCB7XHJcbiAgICAgICAgZGlzcGxheTogYmxvY2s7XHJcbiAgICB9XHJcblxyXG4gICAgYmxvY2txdW90ZSwgZmlndXJlLCBsaXN0aW5nLCBwLCBwbGFpbnRleHQsIHByZSwgeG1wIHtcclxuICAgICAgICBtYXJnaW4tdG9wOiAxZW07XHJcbiAgICAgICAgbWFyZ2luLWJvdHRvbTogMWVtO1xyXG4gICAgfVxyXG5cclxuICAgIGJsb2NrcXVvdGUsIGZpZ3VyZSB7XHJcbiAgICAgICAgbWFyZ2luLWxlZnQ6IDQwcHg7XHJcbiAgICAgICAgbWFyZ2luLXJpZ2h0OiA0MHB4O1xyXG4gICAgfVxyXG5cclxuICAgIGFkZHJlc3Mge1xyXG4gICAgICAgIGZvbnQtc3R5bGU6IGl0YWxpYztcclxuICAgIH1cclxuXHJcbiAgICBsaXN0aW5nLCBwbGFpbnRleHQsIHByZSwgeG1wIHtcclxuICAgICAgICBmb250LWZhbWlseTogbW9ub3NwYWNlO1xyXG4gICAgICAgIHdoaXRlLXNwYWNlOiBwcmU7XHJcbiAgICB9XHJcblxyXG4gICAgY2l0ZSwgZGZuLCBlbSwgaSwgdmFyIHtcclxuICAgICAgICBmb250LXN0eWxlOiBpdGFsaWM7XHJcbiAgICB9XHJcblxyXG4gICAgYiwgc3Ryb25nIHtcclxuICAgICAgICBmb250LXdlaWdodDogYm9sZGVyO1xyXG4gICAgfVxyXG5cclxuICAgIGNvZGUsIGtiZCwgc2FtcCwgdHQge1xyXG4gICAgICAgIGZvbnQtZmFtaWx5OiBtb25vc3BhY2U7XHJcbiAgICB9XHJcblxyXG4gICAgYmlnIHtcclxuICAgICAgICBmb250LXNpemU6IGxhcmdlcjtcclxuICAgIH1cclxuXHJcbiAgICBzbWFsbCB7XHJcbiAgICAgICAgZm9udC1zaXplOiBzbWFsbGVyO1xyXG4gICAgfVxyXG5cclxuICAgIHN1YiB7XHJcbiAgICAgICAgdmVydGljYWwtYWxpZ246IHN1YjtcclxuICAgIH1cclxuXHJcbiAgICBzdXAge1xyXG4gICAgICAgIHZlcnRpY2FsLWFsaWduOiBzdXBlcjtcclxuICAgIH1cclxuXHJcbiAgICBzdWIsIHN1cCB7XHJcbiAgICAgICAgbGluZS1oZWlnaHQ6IG5vcm1hbDtcclxuICAgICAgICBmb250LXNpemU6IHNtYWxsZXI7XHJcbiAgICB9XHJcblxyXG5cclxuICAgIHJ1Ynkge1xyXG4gICAgICAgIGRpc3BsYXk6IHJ1Ynk7XHJcbiAgICB9XHJcblxyXG4gICAgcmIge1xyXG4gICAgICAgIGRpc3BsYXk6IHJ1YnktYmFzZTtcclxuICAgICAgICB3aGl0ZS1zcGFjZTogbm93cmFwO1xyXG4gICAgfVxyXG5cclxuICAgIHJ0IHtcclxuICAgICAgICBkaXNwbGF5OiBydWJ5LXRleHQ7XHJcbiAgICAgICAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcclxuICAgICAgICBmb250LXNpemU6IDUwJTtcclxuICAgICAgICBmb250LXZhcmlhbnQtZWFzdC1hc2lhbjogcnVieTtcclxuICAgICAgICB0ZXh0LWVtcGhhc2lzOiBub25lO1xyXG4gICAgfVxyXG5cclxuICAgIHJiYyB7XHJcbiAgICAgICAgZGlzcGxheTogcnVieS1iYXNlLWNvbnRhaW5lcjtcclxuICAgIH1cclxuXHJcbiAgICBydGMge1xyXG4gICAgICAgIGRpc3BsYXk6IHJ1YnktdGV4dC1jb250YWluZXI7XHJcbiAgICB9XHJcblxyXG4gICAgcnVieSwgcmIsIHJ0LCByYmMsIHJ0YyB7XHJcbiAgICAgICAgdW5pY29kZS1iaWRpOiBpc29sYXRlO1xyXG4gICAgfVxyXG5cclxuXHJcbiAgICA6bGluayB7XHJcbiAgICAgICAgY29sb3I6ICMwMDAwRUU7XHJcbiAgICB9XHJcblxyXG4gICAgOnZpc2l0ZWQge1xyXG4gICAgICAgIGNvbG9yOiAjNTUxQThCO1xyXG4gICAgfVxyXG5cclxuICAgIDpsaW5rLCA6dmlzaXRlZCB7XHJcbiAgICAgICAgdGV4dC1kZWNvcmF0aW9uOiB1bmRlcmxpbmU7XHJcbiAgICB9XHJcblxyXG4gICAgYTpsaW5rW3JlbH49aGVscF0sIGE6dmlzaXRlZFtyZWx+PWhlbHBdLFxyXG4gICAgYXJlYTpsaW5rW3JlbH49aGVscF0sIGFyZWE6dmlzaXRlZFtyZWx+PWhlbHBdIHtcclxuICAgICAgICBjdXJzb3I6IGhlbHA7XHJcbiAgICB9XHJcblxyXG4gICAgOmZvY3VzIHtcclxuICAgICAgICBvdXRsaW5lOiBhdXRvO1xyXG4gICAgfVxyXG5cclxuICAgIG1hcmsge1xyXG4gICAgICAgIGJhY2tncm91bmQ6IHllbGxvdztcclxuICAgICAgICBjb2xvcjogYmxhY2s7XHJcbiAgICB9XHJcbiAgICAvKiB0aGlzIGNvbG9yIGlzIGp1c3QgYSBzdWdnZXN0aW9uIGFuZCBjYW4gYmUgY2hhbmdlZCBiYXNlZCBvbiBpbXBsZW1lbnRhdGlvbiBmZWVkYmFjayAqL1xyXG4gICAgYWJiclt0aXRsZV0sIGFjcm9ueW1bdGl0bGVdIHtcclxuICAgICAgICB0ZXh0LWRlY29yYXRpb246IGRvdHRlZCB1bmRlcmxpbmU7XHJcbiAgICB9XHJcblxyXG4gICAgaW5zLCB1IHtcclxuICAgICAgICB0ZXh0LWRlY29yYXRpb246IHVuZGVybGluZTtcclxuICAgIH1cclxuXHJcbiAgICBkZWwsIHMsIHN0cmlrZSB7XHJcbiAgICAgICAgdGV4dC1kZWNvcmF0aW9uOiBsaW5lLXRocm91Z2g7XHJcbiAgICB9XHJcblxyXG4gICAgYmxpbmsge1xyXG4gICAgICAgIHRleHQtZGVjb3JhdGlvbjogYmxpbms7XHJcbiAgICB9XHJcblxyXG4gICAgcTo6YmVmb3JlIHtcclxuICAgICAgICBjb250ZW50OiBvcGVuLXF1b3RlO1xyXG4gICAgfVxyXG5cclxuICAgIHE6OmFmdGVyIHtcclxuICAgICAgICBjb250ZW50OiBjbG9zZS1xdW90ZTtcclxuICAgIH1cclxuXHJcbiAgICBiciB7XHJcbiAgICAgICAgY29udGVudDogJ1xcQSc7XHJcbiAgICAgICAgd2hpdGUtc3BhY2U6IHByZTtcclxuICAgIH1cclxuICAgIC8qIHRoaXMgYWxzbyBoYXMgYmlkaSBpbXBsaWNhdGlvbnMgKi9cclxuICAgIG5vYnIge1xyXG4gICAgICAgIHdoaXRlLXNwYWNlOiBub3dyYXA7XHJcbiAgICB9XHJcblxyXG4gICAgd2JyIHtcclxuICAgICAgICBjb250ZW50OiAnXFwyMDBCJztcclxuICAgIH1cclxuICAgIC8qIHRoaXMgYWxzbyBoYXMgYmlkaSBpbXBsaWNhdGlvbnMgKi9cclxuICAgIG5vYnIgd2JyIHtcclxuICAgICAgICB3aGl0ZS1zcGFjZTogbm9ybWFsO1xyXG4gICAgfVxyXG5cclxuICAgIGFydGljbGUsIGFzaWRlLCBoMSwgaDIsIGgzLCBoNCwgaDUsIGg2LCBoZ3JvdXAsIG5hdiwgc2VjdGlvbiB7XHJcbiAgICAgICAgZGlzcGxheTogYmxvY2s7XHJcbiAgICB9XHJcblxyXG4gICAgaDEge1xyXG4gICAgICAgIG1hcmdpbi10b3A6IDAuNjdlbTtcclxuICAgICAgICBtYXJnaW4tYm90dG9tOiAwLjY3ZW07XHJcbiAgICAgICAgZm9udC1zaXplOiAyLjAwZW07XHJcbiAgICAgICAgZm9udC13ZWlnaHQ6IGJvbGQ7XHJcbiAgICB9XHJcblxyXG4gICAgaDIge1xyXG4gICAgICAgIG1hcmdpbi10b3A6IDAuODNlbTtcclxuICAgICAgICBtYXJnaW4tYm90dG9tOiAwLjgzZW07XHJcbiAgICAgICAgZm9udC1zaXplOiAxLjUwZW07XHJcbiAgICAgICAgZm9udC13ZWlnaHQ6IGJvbGQ7XHJcbiAgICB9XHJcblxyXG4gICAgaDMge1xyXG4gICAgICAgIG1hcmdpbi10b3A6IDEuMDBlbTtcclxuICAgICAgICBtYXJnaW4tYm90dG9tOiAxLjAwZW07XHJcbiAgICAgICAgZm9udC1zaXplOiAxLjE3ZW07XHJcbiAgICAgICAgZm9udC13ZWlnaHQ6IGJvbGQ7XHJcbiAgICB9XHJcblxyXG4gICAgaDQge1xyXG4gICAgICAgIG1hcmdpbi10b3A6IDEuMzNlbTtcclxuICAgICAgICBtYXJnaW4tYm90dG9tOiAxLjMzZW07XHJcbiAgICAgICAgZm9udC1zaXplOiAxLjAwZW07XHJcbiAgICAgICAgZm9udC13ZWlnaHQ6IGJvbGQ7XHJcbiAgICB9XHJcblxyXG4gICAgaDUge1xyXG4gICAgICAgIG1hcmdpbi10b3A6IDEuNjdlbTtcclxuICAgICAgICBtYXJnaW4tYm90dG9tOiAxLjY3ZW07XHJcbiAgICAgICAgZm9udC1zaXplOiAwLjgzZW07XHJcbiAgICAgICAgZm9udC13ZWlnaHQ6IGJvbGQ7XHJcbiAgICB9XHJcblxyXG4gICAgaDYge1xyXG4gICAgICAgIG1hcmdpbi10b3A6IDIuMzNlbTtcclxuICAgICAgICBtYXJnaW4tYm90dG9tOiAyLjMzZW07XHJcbiAgICAgICAgZm9udC1zaXplOiAwLjY3ZW07XHJcbiAgICAgICAgZm9udC13ZWlnaHQ6IGJvbGQ7XHJcbiAgICB9XHJcblxyXG4gICAgZGlyLCBkZCwgZGwsIGR0LCBvbCwgdWwge1xyXG4gICAgICAgIGRpc3BsYXk6IGJsb2NrO1xyXG4gICAgfVxyXG5cclxuICAgIGxpIHtcclxuICAgICAgICBkaXNwbGF5OiBsaXN0LWl0ZW07XHJcbiAgICB9XHJcblxyXG4gICAgZGlyLCBkbCwgb2wsIHVsIHtcclxuICAgICAgICBtYXJnaW4tdG9wOiAxZW07XHJcbiAgICAgICAgbWFyZ2luLWJvdHRvbTogMWVtO1xyXG4gICAgfVxyXG5cclxuICAgICAgICBkaXIgZGlyLCBkaXIgZGwsIGRpciBvbCwgZGlyIHVsLFxyXG4gICAgICAgIGRsIGRpciwgZGwgZGwsIGRsIG9sLCBkbCB1bCxcclxuICAgICAgICBvbCBkaXIsIG9sIGRsLCBvbCBvbCwgb2wgdWwsXHJcbiAgICAgICAgdWwgZGlyLCB1bCBkbCwgdWwgb2wsIHVsIHVsIHtcclxuICAgICAgICAgICAgbWFyZ2luLXRvcDogMDtcclxuICAgICAgICAgICAgbWFyZ2luLWJvdHRvbTogMDtcclxuICAgICAgICB9XHJcblxyXG4gICAgZGQge1xyXG4gICAgICAgIG1hcmdpbi1sZWZ0OiA0MHB4O1xyXG4gICAgfVxyXG4gICAgLyogTFRSLXNwZWNpZmljOiB1c2UgJ21hcmdpbi1yaWdodCcgZm9yIHJ0bCBlbGVtZW50cyAqL1xyXG4gICAgZGlyLCBvbCwgdWwge1xyXG4gICAgICAgIHBhZGRpbmctbGVmdDogNDBweDtcclxuICAgIH1cclxuICAgIC8qIExUUi1zcGVjaWZpYzogdXNlICdwYWRkaW5nLXJpZ2h0JyBmb3IgcnRsIGVsZW1lbnRzICovXHJcbiAgICBvbCB7XHJcbiAgICAgICAgbGlzdC1zdHlsZS10eXBlOiBkZWNpbWFsO1xyXG4gICAgfVxyXG5cclxuICAgIGRpciwgdWwge1xyXG4gICAgICAgIGxpc3Qtc3R5bGUtdHlwZTogZGlzYztcclxuICAgIH1cclxuXHJcbiAgICAgICAgZGlyIGRpciwgZGlyIHVsLFxyXG4gICAgICAgIG9sIGRpciwgb2wgdWwsXHJcbiAgICAgICAgdWwgZGlyLCB1bCB1bCB7XHJcbiAgICAgICAgICAgIGxpc3Qtc3R5bGUtdHlwZTogY2lyY2xlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGRpciBkaXIgZGlyLCBkaXIgZGlyIHVsLFxyXG4gICAgICAgICAgICBkaXIgb2wgZGlyLCBkaXIgb2wgdWwsXHJcbiAgICAgICAgICAgIGRpciB1bCBkaXIsIGRpciB1bCB1bCxcclxuICAgICAgICAgICAgb2wgZGlyIGRpciwgb2wgZGlyIHVsLFxyXG4gICAgICAgICAgICBvbCBvbCBkaXIsIG9sIG9sIHVsLFxyXG4gICAgICAgICAgICBvbCB1bCBkaXIsIG9sIHVsIHVsLFxyXG4gICAgICAgICAgICB1bCBkaXIgZGlyLCB1bCBkaXIgdWwsXHJcbiAgICAgICAgICAgIHVsIG9sIGRpciwgdWwgb2wgdWwsXHJcbiAgICAgICAgICAgIHVsIHVsIGRpciwgdWwgdWwgdWwge1xyXG4gICAgICAgICAgICAgICAgbGlzdC1zdHlsZS10eXBlOiBzcXVhcmU7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICB0YWJsZSB7XHJcbiAgICAgICAgZGlzcGxheTogdGFibGU7XHJcbiAgICB9XHJcblxyXG4gICAgY2FwdGlvbiB7XHJcbiAgICAgICAgZGlzcGxheTogdGFibGUtY2FwdGlvbjtcclxuICAgIH1cclxuXHJcbiAgICBjb2xncm91cCwgY29sZ3JvdXBbaGlkZGVuXSB7XHJcbiAgICAgICAgZGlzcGxheTogdGFibGUtY29sdW1uLWdyb3VwO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbCwgY29sW2hpZGRlbl0ge1xyXG4gICAgICAgIGRpc3BsYXk6IHRhYmxlLWNvbHVtbjtcclxuICAgIH1cclxuXHJcbiAgICB0aGVhZCwgdGhlYWRbaGlkZGVuXSB7XHJcbiAgICAgICAgZGlzcGxheTogdGFibGUtaGVhZGVyLWdyb3VwO1xyXG4gICAgfVxyXG5cclxuICAgIHRib2R5LCB0Ym9keVtoaWRkZW5dIHtcclxuICAgICAgICBkaXNwbGF5OiB0YWJsZS1yb3ctZ3JvdXA7XHJcbiAgICB9XHJcblxyXG4gICAgdGZvb3QsIHRmb290W2hpZGRlbl0ge1xyXG4gICAgICAgIGRpc3BsYXk6IHRhYmxlLWZvb3Rlci1ncm91cDtcclxuICAgIH1cclxuXHJcbiAgICB0ciwgdHJbaGlkZGVuXSB7XHJcbiAgICAgICAgZGlzcGxheTogdGFibGUtcm93O1xyXG4gICAgfVxyXG5cclxuICAgIHRkLCB0aCwgdGRbaGlkZGVuXSwgdGhbaGlkZGVuXSB7XHJcbiAgICAgICAgZGlzcGxheTogdGFibGUtY2VsbDtcclxuICAgIH1cclxuXHJcbiAgICAgICAgY29sZ3JvdXBbaGlkZGVuXSwgY29sW2hpZGRlbl0sIHRoZWFkW2hpZGRlbl0sIHRib2R5W2hpZGRlbl0sXHJcbiAgICAgICAgdGZvb3RbaGlkZGVuXSwgdHJbaGlkZGVuXSwgdGRbaGlkZGVuXSwgdGhbaGlkZGVuXSB7XHJcbiAgICAgICAgICAgIHZpc2liaWxpdHk6IGNvbGxhcHNlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICB0YWJsZSB7XHJcbiAgICAgICAgYm94LXNpemluZzogYm9yZGVyLWJveDtcclxuICAgICAgICBib3JkZXItc3BhY2luZzogMnB4O1xyXG4gICAgICAgIGJvcmRlci1jb2xsYXBzZTogc2VwYXJhdGU7XHJcbiAgICAgICAgdGV4dC1pbmRlbnQ6IGluaXRpYWw7XHJcbiAgICB9XHJcblxyXG4gICAgdGQsIHRoIHtcclxuICAgICAgICBwYWRkaW5nOiAxcHg7XHJcbiAgICB9XHJcblxyXG4gICAgdGgge1xyXG4gICAgICAgIGZvbnQtd2VpZ2h0OiBib2xkO1xyXG4gICAgfVxyXG5cclxuICAgIHRoZWFkLCB0Ym9keSwgdGZvb3QsIHRhYmxlID4gdHIge1xyXG4gICAgICAgIHZlcnRpY2FsLWFsaWduOiBtaWRkbGU7XHJcbiAgICB9XHJcblxyXG4gICAgdHIsIHRkLCB0aCB7XHJcbiAgICAgICAgdmVydGljYWwtYWxpZ246IGluaGVyaXQ7XHJcbiAgICB9XHJcblxyXG4gICAgdGFibGUsIHRkLCB0aCB7XHJcbiAgICAgICAgYm9yZGVyLWNvbG9yOiBncmF5O1xyXG4gICAgfVxyXG5cclxuICAgIHRoZWFkLCB0Ym9keSwgdGZvb3QsIHRyIHtcclxuICAgICAgICBib3JkZXItY29sb3I6IGluaGVyaXQ7XHJcbiAgICB9XHJcbiAgICAvKnRhYmxlW3J1bGVzPW5vbmUgaV0sIHRhYmxlW3J1bGVzPWdyb3VwcyBpXSwgdGFibGVbcnVsZXM9cm93cyBpXSxcclxudGFibGVbcnVsZXM9Y29scyBpXSwgdGFibGVbcnVsZXM9YWxsIGldLCB0YWJsZVtmcmFtZT12b2lkIGldLFxyXG50YWJsZVtmcmFtZT1hYm92ZSBpXSwgdGFibGVbZnJhbWU9YmVsb3cgaV0sIHRhYmxlW2ZyYW1lPWhzaWRlcyBpXSxcclxudGFibGVbZnJhbWU9bGhzIGldLCB0YWJsZVtmcmFtZT1yaHMgaV0sIHRhYmxlW2ZyYW1lPXZzaWRlcyBpXSxcclxudGFibGVbZnJhbWU9Ym94IGldLCB0YWJsZVtmcmFtZT1ib3JkZXIgaV0sXHJcbnRhYmxlW3J1bGVzPW5vbmUgaV0gPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1ub25lIGldID4gdHIgPiB0aCxcclxudGFibGVbcnVsZXM9Z3JvdXBzIGldID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9Z3JvdXBzIGldID4gdHIgPiB0aCxcclxudGFibGVbcnVsZXM9cm93cyBpXSA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPXJvd3MgaV0gPiB0ciA+IHRoLFxyXG50YWJsZVtydWxlcz1jb2xzIGldID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9Y29scyBpXSA+IHRyID4gdGgsXHJcbnRhYmxlW3J1bGVzPWFsbCBpXSA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPWFsbCBpXSA+IHRyID4gdGgsXHJcbnRhYmxlW3J1bGVzPW5vbmUgaV0gPiB0aGVhZCA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPW5vbmUgaV0gPiB0aGVhZCA+IHRyID4gdGgsXHJcbnRhYmxlW3J1bGVzPWdyb3VwcyBpXSA+IHRoZWFkID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9Z3JvdXBzIGldID4gdGhlYWQgPiB0ciA+IHRoLFxyXG50YWJsZVtydWxlcz1yb3dzIGldID4gdGhlYWQgPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1yb3dzIGldID4gdGhlYWQgPiB0ciA+IHRoLFxyXG50YWJsZVtydWxlcz1jb2xzIGldID4gdGhlYWQgPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1jb2xzIGldID4gdGhlYWQgPiB0ciA+IHRoLFxyXG50YWJsZVtydWxlcz1hbGwgaV0gPiB0aGVhZCA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPWFsbCBpXSA+IHRoZWFkID4gdHIgPiB0aCxcclxudGFibGVbcnVsZXM9bm9uZSBpXSA+IHRib2R5ID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9bm9uZSBpXSA+IHRib2R5ID4gdHIgPiB0aCxcclxudGFibGVbcnVsZXM9Z3JvdXBzIGldID4gdGJvZHkgPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1ncm91cHMgaV0gPiB0Ym9keSA+IHRyID4gdGgsXHJcbnRhYmxlW3J1bGVzPXJvd3MgaV0gPiB0Ym9keSA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPXJvd3MgaV0gPiB0Ym9keSA+IHRyID4gdGgsXHJcbnRhYmxlW3J1bGVzPWNvbHMgaV0gPiB0Ym9keSA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPWNvbHMgaV0gPiB0Ym9keSA+IHRyID4gdGgsXHJcbnRhYmxlW3J1bGVzPWFsbCBpXSA+IHRib2R5ID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9YWxsIGldID4gdGJvZHkgPiB0ciA+IHRoLFxyXG50YWJsZVtydWxlcz1ub25lIGldID4gdGZvb3QgPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1ub25lIGldID4gdGZvb3QgPiB0ciA+IHRoLFxyXG50YWJsZVtydWxlcz1ncm91cHMgaV0gPiB0Zm9vdCA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPWdyb3VwcyBpXSA+IHRmb290ID4gdHIgPiB0aCxcclxudGFibGVbcnVsZXM9cm93cyBpXSA+IHRmb290ID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9cm93cyBpXSA+IHRmb290ID4gdHIgPiB0aCxcclxudGFibGVbcnVsZXM9Y29scyBpXSA+IHRmb290ID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9Y29scyBpXSA+IHRmb290ID4gdHIgPiB0aCxcclxudGFibGVbcnVsZXM9YWxsIGldID4gdGZvb3QgPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1hbGwgaV0gPiB0Zm9vdCA+IHRyID4gdGgge1xyXG4gICAgYm9yZGVyLWNvbG9yOiBibGFjaztcclxufSovXHJcbiAgICBpbnB1dCwgc2VsZWN0LCBvcHRpb24sIG9wdGdyb3VwLCBidXR0b24sIHRleHRhcmVhLCBrZXlnZW4ge1xyXG4gICAgICAgIHRleHQtaW5kZW50OiBpbml0aWFsO1xyXG4gICAgfVxyXG5cclxuICAgIHRleHRhcmVhIHtcclxuICAgICAgICB3aGl0ZS1zcGFjZTogcHJlLXdyYXA7XHJcbiAgICB9XHJcblxyXG4gICAgaW5wdXRbdHlwZT1cInJhZGlvXCJdLCBpbnB1dFt0eXBlPVwiY2hlY2tib3hcIl0sIGlucHV0W3R5cGU9XCJyZXNldFwiXSwgaW5wdXRbdHlwZT1cImJ1dHRvblwiXSxcclxuICAgIGlucHV0W3R5cGU9XCJzdWJtaXRcIl0sIHNlbGVjdCwgYnV0dG9uIHtcclxuICAgICAgICBib3gtc2l6aW5nOiBib3JkZXItYm94O1xyXG4gICAgfVxyXG5cclxuICAgIGlucHV0W3R5cGU9XCJidXR0b25cIl0sIGJ1dHRvbiB7XHJcbiAgICAgICAgcGFkZGluZzogMC4zZW0gMC41ZW07XHJcbiAgICB9XHJcblxyXG4gICAgaHIge1xyXG4gICAgICAgIGNvbG9yOiBncmF5O1xyXG4gICAgICAgIGJvcmRlci1zdHlsZTogaW5zZXQ7XHJcbiAgICAgICAgYm9yZGVyLXdpZHRoOiAxcHg7XHJcbiAgICAgICAgbWFyZ2luOiAwLjVlbSBhdXRvO1xyXG4gICAgfVxyXG5cclxuICAgIGZpZWxkc2V0IHtcclxuICAgICAgICBtYXJnaW4tbGVmdDogMnB4O1xyXG4gICAgICAgIG1hcmdpbi1yaWdodDogMnB4O1xyXG4gICAgICAgIGJvcmRlcjogZ3Jvb3ZlIDJweCBUaHJlZURGYWNlO1xyXG4gICAgICAgIHBhZGRpbmc6IDAuMzVlbSAwLjYyNWVtIDAuNzVlbTtcclxuICAgIH1cclxuXHJcbiAgICBsZWdlbmQge1xyXG4gICAgICAgIHBhZGRpbmctbGVmdDogMnB4O1xyXG4gICAgICAgIHBhZGRpbmctcmlnaHQ6IDJweDtcclxuICAgIH1cclxufVxyXG4iLCJAaW1wb3J0IFwiVmFyaWFibGVzLmxlc3NcIjtcclxuXHJcbi5sYXlvdXQtZWRpdG9yIHtcclxuICAgID4gLmxheW91dC10b29sYm94LXdyYXBwZXIge1xyXG4gICAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxuICAgICAgICBtYXJnaW4tbGVmdDogQGNvbnRhaW5lci1wYWRkaW5nO1xyXG4gICAgICAgIHdpZHRoOiAyMjBweDtcclxuICAgICAgICBmbGV4LXNocmluazogMDtcclxuXHJcbiAgICAgICAgPiAubGF5b3V0LXRvb2xib3gge1xyXG4gICAgICAgICAgICBib3JkZXI6IDFweCBzb2xpZCBAZ3JheS1ib3JkZXI7XHJcbiAgICAgICAgICAgIHdpZHRoOiAyMjBweDtcclxuICAgICAgICAgICAgbWluLWhlaWdodDogNDAwcHg7XHJcbiAgICAgICAgICAgIHBhZGRpbmc6IEBjb250YWluZXItcGFkZGluZyAvIDI7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IEBncmF5LWJnO1xyXG5cclxuICAgICAgICAgICAgJi5zdGlja3ktdG9wIHtcclxuICAgICAgICAgICAgICAgIHBvc2l0aW9uOiBmaXhlZDtcclxuICAgICAgICAgICAgICAgIHRvcDogMDtcclxuICAgICAgICAgICAgICAgIG1heC1oZWlnaHQ6IDEwMCU7XHJcbiAgICAgICAgICAgICAgICBvdmVyZmxvdy15OiBhdXRvO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAmLnN0aWNreS1ib3R0b20ge1xyXG4gICAgICAgICAgICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICAgICAgICAgICAgYm90dG9tOiAwO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAubGF5b3V0LXRvb2xib3gtZ3JvdXAge1xyXG4gICAgICAgICAgICAgICAgbWFyZ2luLXRvcDogQGNvbnRhaW5lci1wYWRkaW5nO1xyXG5cclxuICAgICAgICAgICAgICAgIC5sYXlvdXQtdG9vbGJveC1ncm91cC1oZWFkaW5nIHtcclxuICAgICAgICAgICAgICAgICAgICBkaXNwbGF5OiBibG9jaztcclxuICAgICAgICAgICAgICAgICAgICBtYXJnaW4tYm90dG9tOiBAY29udGFpbmVyLXBhZGRpbmcgLyAzO1xyXG4gICAgICAgICAgICAgICAgICAgIHRleHQtZGVjb3JhdGlvbjogbm9uZTtcclxuICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgICAgICY6YmVmb3JlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGxheTogaW5saW5lLWJsb2NrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogMTBweDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbWFyZ2luLXJpZ2h0OiBAY29udGFpbmVyLXBhZGRpbmcgLyAzO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBmb250OiBub3JtYWwgbm9ybWFsIG5vcm1hbCAxNHB4LzEgRm9udEF3ZXNvbWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHQtYWxpZ246IGNlbnRlcjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudDogXCJcXGYwZDdcIjtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgJi5jb2xsYXBzZWQge1xyXG4gICAgICAgICAgICAgICAgICAgIC5sYXlvdXQtdG9vbGJveC1ncm91cC1oZWFkaW5nOmJlZm9yZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnQ6IFwiXFxmMGRhXCI7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAubGF5b3V0LXRvb2xib3gtaXRlbXMge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBkaXNwbGF5OiBub25lO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAubGF5b3V0LXRvb2xib3gtc2VjdGlvbiArIC5sYXlvdXQtdG9vbGJveC1zZWN0aW9uIHtcclxuICAgICAgICAgICAgICAgICAgICBtYXJnaW4tdG9wOiBAY29udGFpbmVyLXBhZGRpbmcgLyAzO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIC5sYXlvdXQtdG9vbGJveC1pdGVtIHtcclxuICAgICAgICAgICAgICAgICAgICBib3JkZXI6IDFweCBzb2xpZCBAZ3JheS1ib3JkZXI7XHJcbiAgICAgICAgICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2ZmZjtcclxuICAgICAgICAgICAgICAgICAgICBwYWRkaW5nOiAoQGNvbnRhaW5lci1wYWRkaW5nIC0gMykgQGNvbnRhaW5lci1wYWRkaW5nO1xyXG4gICAgICAgICAgICAgICAgICAgIGN1cnNvcjogZGVmYXVsdDtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgaSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BsYXk6IGlubGluZS1ibG9jaztcclxuICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGg6IDE2cHg7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvbnQ6IG5vcm1hbCBub3JtYWwgbm9ybWFsIDE0cHgvMSBGb250QXdlc29tZTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICsgLmxheW91dC10b29sYm94LWl0ZW0ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXJnaW4tdG9wOiBAY29udGFpbmVyLXBhZGRpbmcgLyAzO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICArIC5sYXlvdXQtdG9vbGJveC1ncm91cCB7XHJcbiAgICAgICAgICAgICAgICAgICAgbWFyZ2luLXRvcDogQGNvbnRhaW5lci1wYWRkaW5nIC8gMjtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxufVxyXG4iLCJAaW1wb3J0IFwiVmFyaWFibGVzLmxlc3NcIjtcclxuXHJcbi5sYXlvdXQtZWRpdG9yIHtcclxuICAgIC5sYXlvdXQtcG9wdXAge1xyXG4gICAgICAgIGRpc3BsYXk6IG5vbmU7IC8vIFNob3duIG9ubHkgaW4gYWN0aXZlIG9yIGZvY3VzZWQgc3RhdGVzLlxyXG4gICAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgICBtYXJnaW46IDA7XHJcbiAgICAgICAgLW1vei1ib3gtc2hhZG93OiAzcHggM3B4IDExcHggMCByZ2JhKDUwLCA1MCwgNTAsIDAuNSk7XHJcbiAgICAgICAgLXdlYmtpdC1ib3gtc2hhZG93OiAzcHggM3B4IDExcHggMCByZ2JhKDUwLCA1MCwgNTAsIDAuNSk7XHJcbiAgICAgICAgYm94LXNoYWRvdzogM3B4IDNweCAxMXB4IDAgcmdiYSg1MCwgNTAsIDUwLCAwLjUpO1xyXG4gICAgICAgIGJvcmRlcjogMXB4IHNvbGlkIEBncmF5LWJvcmRlcjtcclxuICAgICAgICBwYWRkaW5nOiAycHggMDtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjdmN2Y3O1xyXG4gICAgICAgIGxpc3Qtc3R5bGU6IG5vbmU7XHJcbiAgICAgICAgei1pbmRleDogMjA7XHJcbiAgICAgICAgY29sb3I6IEBncmF5LXRleHQ7XHJcbiAgICAgICAgdGV4dC1hbGlnbjogbGVmdDtcclxuICAgICAgICBjdXJzb3I6IGRlZmF1bHQ7XHJcbiAgICAgICAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcclxuICAgICAgICBsaW5lLWhlaWdodDogbm9ybWFsO1xyXG4gICAgICAgIG1pbi13aWR0aDogMzAwcHg7XHJcblxyXG4gICAgICAgICYud2lkZSB7XHJcbiAgICAgICAgICAgIHdpZHRoOiA2MDBweDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5sYXlvdXQtcG9wdXAtZmxleCB7XHJcbiAgICAgICAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgICAgICAgIHBhZGRpbmc6IDJweCA1cHg7XHJcblxyXG4gICAgICAgICAgICAubGF5b3V0LXBvcHVwLWNvbHVtbiArIC5sYXlvdXQtcG9wdXAtY29sdW1uIHtcclxuICAgICAgICAgICAgICAgIG1hcmdpbi1sZWZ0OiA0cHg7XHJcbiAgICAgICAgICAgICAgICBib3JkZXItbGVmdDogMXB4IHNvbGlkIGZhZGUoZ3JheSwgMTUlKTtcclxuICAgICAgICAgICAgICAgIHBhZGRpbmctbGVmdDogNHB4O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAubGF5b3V0LXBvcHVwLWl0ZW0ge1xyXG4gICAgICAgICAgICBwYWRkaW5nOiA0cHggNnB4O1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLmxheW91dC1wb3B1cC1sYWJlbCB7XHJcbiAgICAgICAgICAgIGZvbnQtc2l6ZTogMC45ZW07XHJcbiAgICAgICAgICAgIGZvbnQtd2VpZ2h0OiBib2xkO1xyXG4gICAgICAgICAgICBjb2xvcjogQGdyYXktdGV4dDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5sYXlvdXQtcG9wdXAtYWN0aW9uOmhvdmVyIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogQGdyYXktYmc7XHJcbiAgICAgICAgICAgIGN1cnNvcjogcG9pbnRlcjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5sYXlvdXQtcG9wdXAtaW5wdXQge1xyXG4gICAgICAgICAgICBpbnB1dFt0eXBlPSd0ZXh0J10sIHRleHRhcmVhIHtcclxuICAgICAgICAgICAgICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICA+IGxhYmVsIHtcclxuICAgICAgICAgICAgICAgIGRpc3BsYXk6IGJsb2NrO1xyXG4gICAgICAgICAgICAgICAgZm9udC1zaXplOiAwLjllbTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxufVxyXG4iXSwic291cmNlUm9vdCI6Ii9zb3VyY2UvIn0= */ \ No newline at end of file +/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkVkaXRvci5sZXNzIiwiTGF5b3V0RWRpdG9yLmNzcyIsIkVsZW1lbnQubGVzcyIsIkNvbnRhaW5lci5sZXNzIiwiQ2FudmFzLmxlc3MiLCJSb3cubGVzcyIsIkNvbHVtbi5sZXNzIiwiQ29udGVudC5sZXNzIiwiUmVzZXQubGVzcyIsIlRvb2xib3gubGVzcyIsIlBvcHVwLmxlc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUE7RUFDSSxzQkFBQTtFQUFBLHFCQUFBO0VBQUEsY0FBQTtFQUNBLHVDQUFBO01BQUEsdUJBQUE7VUFBQSwrQkFBQTtFQUNBLG1CQUFBO0VBQ0EsVUFBQTtDQ0RIO0FESEQ7RUFPUSxzQkFBQTtFQUFBLHFCQUFBO0VBQUEsY0FBQTtDQ0RQO0FETkQ7RUFVWSxrQkFBQTtDQ0RYO0FETUQ7RUFDSSxzQkFBQTtFQUFBLHFCQUFBO0VBQUEsY0FBQTtFQUNBLGdCQUFBO0VBQ0EsZ0JBQUE7RUFDQSw2QkFBQTtNQUFBLHdCQUFBO1VBQUEscUJBQUE7Q0NKSDtBREFEO0VBT1EscUJBQUE7TUFBQSxxQkFBQTtVQUFBLGFBQUE7RUFDQSwwQkFBQTtFQUNBLDBCQUFBO0NDSlA7QURMRDtFQVlZLGNBQUE7RUFDQSxvQkFBQTtFQUNBLGlCQUFBO0NDSlg7QURWRDtFQWlCZ0IsdUJBQUE7Q0NKZjtBRGJEO0VBc0JZLHdCQUFBO0VBQ0EscUJBQUE7RUFDQSxvQkFBQTtDQ05YO0FEbEJEO0VBNkJRLG9CQUFBO0NDUlA7QURZRDtFQUNJLGNBQUE7Q0NWSDtBRGFPOztFQUNJLGFBQUE7RUFDQSxlQUFBO0NDVlg7QURhTztFQUNJLFlBQUE7Q0NYWDtBRENEOztFQWNZLGdCQUFBO0NDWFg7QURIRDtFQWtCWSx1QkFBQTtFQUNBLFlBQUE7RUFDQSxXQUFBO0NDWlg7QURjVztFQUNJLG9CQUFBO0VBQ0EsWUFBQTtDQ1pmO0FEWkQ7RUE2QlksZ0JBQUE7Q0NkWDtBRGZEO0VBa0NRLG1CQUFBO0VBQ0EsMEJBQUE7RUFDQSxpQkFBQTtFQUNBLHVCQUFBO0NDaEJQO0FEckJEO0VBeUNRLHFCQUFBO0VBQ0EsbUJBQUE7Q0NqQlA7QUR6QkQ7RUE4Q1Esb0JBQUE7Q0NsQlA7O0FDNUVEO0VBRVEsbUJBQUE7RUFDQSxjQUFBO0VBQ0EsZ0JBQUE7RUFDQSxpQkFBQTtFQUNBLFdBQUE7Q0Q4RVA7QUMzRU87RUFDSSxlQUFBO0NENkVYO0FDdkZEO0VBZWdCLGNBQUE7RUFDQSxtQkFBQTtFQUNBLFVBQUE7RUFDQSxZQUFBO0VBQ0EsYUFBQTtFQUNBLGVBQUE7RUFDQSxpQkFBQTtFQUNBLG9CQUFBO0VBQ0Esa0JBQUE7RUFDQSx1QkFBQTtDRDJFZjtBQ25HRDtFQTJCb0Isc0JBQUE7RUFDQSxhQUFBO0VBQ0EsbUJBQUE7Q0QyRW5CO0FDeEdEO0VBaUNvQixnQkFBQTtDRDBFbkI7QUMzR0Q7RUFxQ29CLGNBQUE7RUFDQSxZQUFBO0VBQ0EsZ0JBQUE7RUFDQSxtQkFBQTtDRHlFbkI7QUNqSEQ7RUE2Q2dCLFdBQUE7RUFDQSxXQUFBO0NEdUVmO0FDckhEO0VBcURRLGlCQUFBO0NEbUVQO0FDaEVHOztFQUdRLGtCQUFBO0VBQ0Esb0JBQUE7Q0RpRVg7QUNyRUc7O0VBT1ksYUFBQTtDRGtFZjtBQ3pFRztFQWNRLHVDQUFBO0NEOERYO0FDNUVHO0VBaUJZLGVBQUE7RUFDQSxZQUFBO0VBQ0EsMkNBQUE7Q0Q4RGY7QUNqRkc7RUEyQlEsc0JBQUE7Q0R5RFg7QUNwRkc7RUE4QlksZUFBQTtFQUNBLDBCQUFBO0VBQ0EsZUFBQTtDRHlEZjtBQ3pGRztFQW1DZ0Isc0JBQUE7Q0R5RG5CO0FDeERtQjtFQUNJLDBCQUFBO0NEMER2QjtBQ3ZEbUI7RUFDSSxnQkFBQTtFQUNBLGdDQUFBO0NEeUR2QjtBQ3ZEdUI7RUFDSSwwQkFBQTtDRHlEM0I7QUNyRG1CO0VBQ0ksZUFBQTtFQUNBLDBCQUFBO0NEdUR2QjtBQ3JEdUI7RUFDSSwwQkFBQTtDRHVEM0I7QUM3R0c7RUErRFEsMkNBQUE7Q0RpRFg7QUN4S0Q7RUE0SFEsY0FBQTtDRCtDUDtBQzNLRDtFQWlJUSx1REFBQTtDRDZDUDtBQzlLRDtFQW9JWSxlQUFBO0VBQ0EsK0JBQUE7RUFDQSxpQkFBQTtFQUNBLHNDQUFBO0VBQ0EsMkNBQUE7Q0Q2Q1g7QUNyTEQ7RUErSVksZ0JBQUE7RUFDQSxpQkFBQTtDRHlDWDs7QUV6TEQ7RUFNZ0IsY0FBQTtFQUNBLCtCQUFBO01BQUEsMkJBQUE7VUFBQSx1QkFBQTtFQUNBLGFBQUE7RUFDQSxpQkFBQTtFQUNBLDRDQUFBO0VBQ0EsbUJBQUE7RUFDQSxjQUFBO0VBQ0EsZ0NBQUE7TUFBQSxzQkFBQTtVQUFBLHdCQUFBO0VBQ0EsZ0JBQUE7RUFDQSxtQkFBQTtFQUNBLGFBQUE7RUFDQSxtQkFBQTtDRnVMZjtBRXhNRDtFQXFCZ0IsY0FBQTtDRnNMZjtBRTNNRDtFQXlCb0IsaUJBQUE7Q0ZxTG5CO0FFOU1EO0VBOEJvQixjQUFBO0NGbUxuQjtBRS9LVztFQUVRLHNCQUFBO0VBQUEscUJBQUE7RUFBQSxjQUFBO0NGZ0xuQjtBRWxMVztFQU1RLG1CQUFBO0VBQ0EsT0FBQTtFQUNBLFNBQUE7RUFDQSxVQUFBO0VBQ0EsUUFBQTtDRitLbkI7QUV6S0c7RUFHWSw0Q0FBQTtDRnlLZjtBRTVLRztFQU1nQixhQUFBO0NGeUtuQjtBRS9LRztFQVdZLGNBQUE7Q0Z1S2Y7QUVsTEc7RUFjZ0IsY0FBQTtDRnVLbkI7O0FHdk9EO0VBR1ksY0FBQTtDSHdPWDs7QUl6T087RUFFUSwyREFBQTtDSjJPZjtBSTdPTztFQUlZLDRCQUFBO0NKNE9uQjtBSWhQTztFQVNRLDBCQUFBO0NKME9mO0FJblBPO0VBV1ksMEJBQUE7Q0oyT25COztBS3hQRDtFQUlnQixjQUFBO0VBQ0EsbUJBQUE7RUFDQSxZQUFBO0VBQ0EsT0FBQTtFQUNBLFlBQUE7RUFDQSxhQUFBO0VBQ0EsbUJBQUE7Q0x3UGY7QUtsUUQ7RUFjZ0IsV0FBQTtDTHVQZjtBS3JRRDtFQWtCZ0IsWUFBQTtDTHNQZjtBS2xQTztFQUNJLGVBQUE7Q0xvUFg7O0FNMVFEOztFQUVRLGdCQUFBO0NONlFQO0FNL1FEOztFQU9nQixhQUFBO0VBQ0EsbUJBQUE7RUFDQSxvQkFBQTtFTjRRZCx5RkFBeUY7RUFDekYscUNBQXFDO0VBQ3JDLHFDQUFxQztFQUNyQyx1REFBdUQ7RUFDdkQsd0RBQXdEO0VBQ3hEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTBCQztDQUNGO0FNclREOztFQ0FRLFVBQUE7RUFDQSxXQUFBO0VBQ0Esd0JBQUE7Q1B5VFA7QU0zVEQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0VDT1EsZUFBQTtDUHNWUDtBTTdWRDs7Ozs7Ozs7Ozs7Ozs7RUNXUSxnQkFBQTtFQUNBLG1CQUFBO0NQa1dQO0FNOVdEOzs7O0VDZ0JRLGtCQUFBO0VBQ0EsbUJBQUE7Q1BvV1A7QU1yWEQ7O0VDcUJRLG1CQUFBO0NQb1dQO0FNelhEOzs7Ozs7OztFQ3lCUSx1QkFBQTtFQUNBLGlCQUFBO0NQMFdQO0FNcFlEOzs7Ozs7Ozs7O0VDOEJRLG1CQUFBO0NQa1hQO0FNaFpEOzs7O0VDa0NRLG9CQUFBO0NQb1hQO0FNdFpEOzs7Ozs7OztFQ3NDUSx1QkFBQTtDUDBYUDtBTWhhRDs7RUMwQ1Esa0JBQUE7Q1AwWFA7QU1wYUQ7O0VDOENRLG1CQUFBO0NQMFhQO0FNeGFEOztFQ2tEUSxvQkFBQTtDUDBYUDtBTTVhRDs7RUNzRFEsc0JBQUE7Q1AwWFA7QU1oYkQ7Ozs7RUMwRFEsb0JBQUE7RUFDQSxtQkFBQTtDUDRYUDtBTXZiRDs7RUNnRVEsY0FBQTtDUDJYUDtBTTNiRDs7RUNvRVEsbUJBQUE7RUFDQSxvQkFBQTtDUDJYUDtBTWhjRDs7RUN5RVEsbUJBQUE7RUFDQSxvQkFBQTtFQUNBLGVBQUE7RUFDQSw4QkFBQTtFQUNBLDRCQUFBO1VBQUEsb0JBQUE7Q1AyWFA7QU14Y0Q7O0VDaUZRLDZCQUFBO0NQMlhQO0FNNWNEOztFQ3FGUSw2QkFBQTtDUDJYUDtBTWhkRDs7Ozs7Ozs7OztFQ3lGUSxzQkFBQTtDUG1ZUDtBTTVkRDs7RUM4RlEsZUFBQTtDUGtZUDtBTWhlRDs7RUNrR1EsZUFBQTtDUGtZUDtBTXBlRDs7OztFQ3NHUSwyQkFBQTtDUG9ZUDtBTTFlRDs7Ozs7Ozs7RUMyR1EsYUFBQTtDUHlZUDtBTXBmRDs7RUMrR1EsY0FBQTtDUHlZUDtBTXhmRDs7RUNtSFEsbUJBQUE7RUFDQSxhQUFBO0NQeVlQO0FNN2ZEOzs7O0VDd0hRLGtDQUFBO0NQMllQO0FNbmdCRDs7OztFQzRIUSwyQkFBQTtDUDZZUDtBTXpnQkQ7Ozs7OztFQ2dJUSw4QkFBQTtDUGlaUDtBTWpoQkQ7O0VDb0lRLHVCQUFBO0NQaVpQO0FNcmhCRDs7RUN3SVEsb0JBQUE7Q1BpWlA7QU16aEJEOztFQzRJUSxxQkFBQTtDUGlaUDtBTTdoQkQ7O0VDZ0pRLGNBQUE7RUFDQSxpQkFBQTtDUGlaUDtBTWxpQkQ7O0VDcUpRLG9CQUFBO0NQaVpQO0FNdGlCRDs7RUN5SlEsaUJBQUE7Q1BpWlA7QU0xaUJEOztFQzZKUSxvQkFBQTtDUGlaUDtBTTlpQkQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7RUNpS1EsZUFBQTtDUHFhUDtBTXRrQkQ7O0VDcUtRLG1CQUFBO0VBQ0Esc0JBQUE7RUFDQSxrQkFBQTtFQUNBLGtCQUFBO0NQcWFQO0FNN2tCRDs7RUM0S1EsbUJBQUE7RUFDQSxzQkFBQTtFQUNBLGtCQUFBO0VBQ0Esa0JBQUE7Q1BxYVA7QU1wbEJEOztFQ21MUSxtQkFBQTtFQUNBLHNCQUFBO0VBQ0Esa0JBQUE7RUFDQSxrQkFBQTtDUHFhUDtBTTNsQkQ7O0VDMExRLG1CQUFBO0VBQ0Esc0JBQUE7RUFDQSxrQkFBQTtFQUNBLGtCQUFBO0NQcWFQO0FNbG1CRDs7RUNpTVEsbUJBQUE7RUFDQSxzQkFBQTtFQUNBLGtCQUFBO0VBQ0Esa0JBQUE7Q1BxYVA7QU16bUJEOztFQ3dNUSxtQkFBQTtFQUNBLHNCQUFBO0VBQ0Esa0JBQUE7RUFDQSxrQkFBQTtDUHFhUDtBTWhuQkQ7Ozs7Ozs7Ozs7OztFQytNUSxlQUFBO0NQK2FQO0FNOW5CRDs7RUNtTlEsbUJBQUE7Q1ArYVA7QU1sb0JEOzs7Ozs7OztFQ3VOUSxnQkFBQTtFQUNBLG1CQUFBO0NQcWJQO0FNN29CRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7RUMrTlksY0FBQTtFQUNBLGlCQUFBO0NQZ2RYO0FNaHJCRDs7RUNvT1Esa0JBQUE7Q1BnZFA7QU1wckJEOzs7Ozs7RUN3T1EsbUJBQUE7Q1BvZFA7QU01ckJEOztFQzRPUSx5QkFBQTtDUG9kUDtBTWhzQkQ7Ozs7RUNnUFEsc0JBQUE7Q1BzZFA7QU10c0JEOzs7Ozs7Ozs7Ozs7RUNzUFksd0JBQUE7Q1A4ZFg7QU1wdEJEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7RUNrUWdCLHdCQUFBO0NQd2ZmO0FNMXZCRDs7RUNzUVEsZUFBQTtDUHdmUDtBTTl2QkQ7O0VDMFFRLHVCQUFBO0NQd2ZQO0FNbHdCRDs7OztFQzhRUSw0QkFBQTtDUDBmUDtBTXh3QkQ7Ozs7RUNrUlEsc0JBQUE7Q1A0ZlA7QU05d0JEOzs7O0VDc1JRLDRCQUFBO0NQOGZQO0FNcHhCRDs7OztFQzBSUSx5QkFBQTtDUGdnQlA7QU0xeEJEOzs7O0VDOFJRLDRCQUFBO0NQa2dCUDtBTWh5QkQ7Ozs7RUNrU1EsbUJBQUE7Q1BvZ0JQO0FNdHlCRDs7Ozs7Ozs7RUNzU1Esb0JBQUE7Q1AwZ0JQO0FNaHpCRDs7Ozs7Ozs7Ozs7Ozs7OztFQzJTWSxxQkFBQTtDUHVoQlg7QU1sMEJEOztFQytTUSx1QkFBQTtFQUNBLG9CQUFBO0VBQ0EsMEJBQUE7RUFDQSxxQkFBQTtDUHVoQlA7QU16MEJEOzs7O0VDc1RRLGFBQUE7Q1B5aEJQO0FNLzBCRDs7RUMwVFEsa0JBQUE7Q1B5aEJQO0FNbjFCRDs7Ozs7Ozs7RUM4VFEsdUJBQUE7Q1AraEJQO0FNNzFCRDs7Ozs7O0VDa1VRLHdCQUFBO0NQbWlCUDtBTXIyQkQ7Ozs7OztFQ3NVUSxtQkFBQTtDUHVpQlA7QU03MkJEOzs7Ozs7OztFQzBVUSxzQkFBQTtDUDZpQlA7QU12M0JEOzs7Ozs7Ozs7Ozs7OztFQ3dXUSxxQkFBQTtDUCtoQlA7QU12NEJEOztFQzRXUSxzQkFBQTtDUCtoQlA7QU0zNEJEOzs7Ozs7Ozs7Ozs7OztFQ2lYUSx1QkFBQTtDUDBpQlA7QU0zNUJEOzs7O0VDcVhRLHFCQUFBO0NQNGlCUDtBTWo2QkQ7O0VDeVhRLFlBQUE7RUFDQSxvQkFBQTtFQUNBLGtCQUFBO0VBQ0EsbUJBQUE7Q1A0aUJQO0FNeDZCRDs7RUNnWVEsaUJBQUE7RUFDQSxrQkFBQTtFQUNBLDhCQUFBO0VBQ0EsK0JBQUE7Q1A0aUJQO0FNLzZCRDs7RUN1WVEsa0JBQUE7RUFDQSxtQkFBQTtDUDRpQlA7QU1wN0JEOztFQWVvQix5QkFBQTtDTnk2Qm5CO0FNeDdCRDs7RUFtQm9CLDRCQUFBO0NOeTZCbkI7QU1wNkJPOzs7O0VBRVEsZUFBQTtFQUNBLFlBQUE7RUFDQSxnQkFBQTtFQUNBLGFBQUE7Q053NkJmO0FNcjhCRDs7RUFtQ1EsZUFBQTtFQUNBLFlBQUE7RUFDQSxnQkFBQTtFQUNBLGFBQUE7Q05zNkJQOztBUTc4QkQ7RUFFUSxtQkFBQTtFQUNBLGtCQUFBO0VBQ0EsYUFBQTtFQUNBLHVCQUFBO01BQUEscUJBQUE7VUFBQSxlQUFBO0NSKzhCUDtBUXA5QkQ7RUFRWSwwQkFBQTtFQUNBLGFBQUE7RUFDQSxrQkFBQTtFQUNBLGFBQUE7RUFDQSwwQkFBQTtDUis4Qlg7QVE3OEJXO0VBQ0ksZ0JBQUE7RUFDQSxPQUFBO0VBQ0EsaUJBQUE7RUFDQSxpQkFBQTtDUis4QmY7QVE1OEJXO0VBQ0ksbUJBQUE7RUFDQSxVQUFBO0NSODhCZjtBUXIrQkQ7RUEyQmdCLGlCQUFBO0NSNjhCZjtBUXgrQkQ7RUE4Qm9CLGVBQUE7RUFDQSxtQkFBQTtFQUNBLHNCQUFBO0NSNjhCbkI7QVEzOEJtQjtFQUNJLHNCQUFBO0VBQ0EsWUFBQTtFQUNBLGtCQUFBO0VBQ0EsOENBQUE7RUFDQSxtQkFBQTtFQUNBLGlCQUFBO0NSNjhCdkI7QVF6OEJlO0VBRVEsaUJBQUE7Q1IwOEJ2QjtBUTU4QmU7RUFNUSxjQUFBO0NSeThCdkI7QVEzL0JEO0VBdURvQixnQkFBQTtDUnU4Qm5CO0FROS9CRDtFQTJEb0IsMEJBQUE7RUFDQSx1QkFBQTtFQUNBLGtCQUFBO0VBQ0EsZ0JBQUE7Q1JzOEJuQjtBUXBnQ0Q7RUFpRXdCLHNCQUFBO0VBQ0EsWUFBQTtFQUNBLDhDQUFBO0NSczhCdkI7QVF6Z0NEO0VBdUV3QixnQkFBQTtDUnE4QnZCO0FRNWdDRDtFQTRFb0IsZ0JBQUE7Q1JtOEJuQjs7QVMvZ0NEO0VBRVEsY0FBQTtFQUNBLG1CQUFBO0VBQ0EsVUFBQTtFQUdBLGlEQUFBO0VBQ0EsMEJBQUE7RUFDQSxlQUFBO0VBQ0EsMEJBQUE7RUFDQSxpQkFBQTtFQUNBLFlBQUE7RUFDQSxlQUFBO0VBQ0EsaUJBQUE7RUFDQSxnQkFBQTtFQUNBLG9CQUFBO0VBQ0Esb0JBQUE7RUFDQSxpQkFBQTtDVGloQ1A7QVMvZ0NPO0VBQ0ksYUFBQTtDVGloQ1g7QVN0aUNEO0VBeUJZLHNCQUFBO0VBQUEscUJBQUE7RUFBQSxjQUFBO0VBQ0EsaUJBQUE7Q1RnaENYO0FTMWlDRDtFQTZCZ0IsaUJBQUE7RUFDQSxpREFBQTtFQUNBLGtCQUFBO0NUZ2hDZjtBUy9pQ0Q7RUFvQ1ksaUJBQUE7Q1Q4Z0NYO0FTbGpDRDtFQXdDWSxpQkFBQTtFQUNBLGtCQUFBO0VBQ0EsZUFBQTtDVDZnQ1g7QVN2akNEO0VBOENZLDBCQUFBO0VBQ0EsZ0JBQUE7Q1Q0Z0NYO0FTM2pDRDs7RUFvRGdCLFlBQUE7Q1QyZ0NmO0FTL2pDRDtFQXdEZ0IsZUFBQTtFQUNBLGlCQUFBO0NUMGdDZiIsImZpbGUiOiJMYXlvdXRFZGl0b3IuY3NzIiwic291cmNlc0NvbnRlbnQiOlsiQGltcG9ydCBcIlZhcmlhYmxlcy5sZXNzXCI7XHJcblxyXG4ubGF5b3V0LWVkaXRvci10b29sYmFyIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcbiAgICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcbiAgICB0b3A6IDEwcHg7XHJcblxyXG4gICAgLmxheW91dC1lZGl0b3ItdG9vbGJhci1ncm91cCB7XHJcbiAgICAgICAgZGlzcGxheTogZmxleDtcclxuXHJcbiAgICAgICAgPiBsaSArIGxpIHtcclxuICAgICAgICAgICAgbWFyZ2luLWxlZnQ6IDEycHg7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcblxyXG4ubGF5b3V0LWVkaXRvciB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgbWFyZ2luLXRvcDogMWVtO1xyXG4gICAgZm9udC1zaXplOiBAZm9udC1zaXplO1xyXG4gICAgYWxpZ24taXRlbXM6IHN0cmV0Y2g7XHJcblxyXG4gICAgPiAubGF5b3V0LWNhbnZhcy13cmFwcGVyIHtcclxuICAgICAgICBmbGV4LWdyb3c6IDE7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogQGdyYXktYmc7XHJcbiAgICAgICAgYm9yZGVyOiAxcHggc29saWQgQGdyYXktYm9yZGVyO1xyXG5cclxuICAgICAgICA+IC5sYXlvdXQtdG9vbGJhci1jb250YWluZXIge1xyXG4gICAgICAgICAgICBkaXNwbGF5OiBub25lO1xyXG4gICAgICAgICAgICBtYXJnaW46IEBjb250YWluZXItcGFkZGluZyBAY29udGFpbmVyLXBhZGRpbmcgMDtcclxuICAgICAgICAgICAgbWluLWhlaWdodDogNzFweDtcclxuXHJcbiAgICAgICAgICAgID4gLm1jZS1wYW5lbCB7XHJcbiAgICAgICAgICAgICAgICB3aWR0aDogMTAwJSAhaW1wb3J0YW50O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwID4gLmxheW91dC1wbGFjZWhvbGRlciB7XHJcbiAgICAgICAgICAgIGJvcmRlcjogMXB4IGRhc2hlZCAjY2NjO1xyXG4gICAgICAgICAgICBwYWRkaW5nOiAwLjJlbSAwLjRlbTtcclxuICAgICAgICAgICAgYmFja2dyb3VuZDogI2U4ZThlODtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLmxheW91dC1zbmlwcGV0IHtcclxuICAgICAgICBiYWNrZ3JvdW5kOiAjZThlOGU4O1xyXG4gICAgfVxyXG59XHJcblxyXG4ubGF5b3V0LWVkaXRvci1oZWxwLWRpYWxvZyB7XHJcbiAgICBkaXNwbGF5OiBub25lO1xyXG5cclxuICAgIC5oZWxwLXJvdyB7XHJcbiAgICAgICAgJjpiZWZvcmUsICY6YWZ0ZXIge1xyXG4gICAgICAgICAgICBjb250ZW50OiBcIiBcIjsgLy8gMVxyXG4gICAgICAgICAgICBkaXNwbGF5OiB0YWJsZTsgLy8gMlxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgJjphZnRlciB7XHJcbiAgICAgICAgICAgIGNsZWFyOiBib3RoO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgPiAuaGVscC1jb2x1bW4tZnVsbCwgPiAuaGVscC1jb2x1bW4taGFsZiB7XHJcbiAgICAgICAgICAgIG1hcmdpbjogMC41ZW0gMDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgID4gLmhlbHAtY29sdW1uLWhhbGYge1xyXG4gICAgICAgICAgICBib3gtc2l6aW5nOiBib3JkZXItYm94O1xyXG4gICAgICAgICAgICBmbG9hdDogbGVmdDtcclxuICAgICAgICAgICAgd2lkdGg6IDUwJTtcclxuXHJcbiAgICAgICAgICAgICY6bnRoLWNoaWxkKDJuKSB7XHJcbiAgICAgICAgICAgICAgICBwYWRkaW5nLXJpZ2h0OiAxMHB4O1xyXG4gICAgICAgICAgICAgICAgY2xlYXI6IGxlZnQ7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICsgLmhlbHAtcm93IHtcclxuICAgICAgICAgICAgbWFyZ2luLXRvcDogMWVtO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBjb2RlIHtcclxuICAgICAgICBib3JkZXItcmFkaXVzOiA0cHg7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2YzZjRmNTtcclxuICAgICAgICBwYWRkaW5nOiAycHggNHB4O1xyXG4gICAgICAgIGZvbnQtZmFtaWx5OiBtb25vc3BhY2U7XHJcbiAgICB9XHJcblxyXG4gICAgcCB7XHJcbiAgICAgICAgbWFyZ2luLWJvdHRvbTogMC41ZW07XHJcbiAgICAgICAgbGluZS1oZWlnaHQ6IDEuNmVtO1xyXG4gICAgfVxyXG5cclxuICAgIHRhYmxlID4gdGJvZHkgPiB0ciA+IHRkOmZpcnN0LWNoaWxkIHtcclxuICAgICAgICBwYWRkaW5nLXJpZ2h0OiAxMHB4O1xyXG4gICAgfVxyXG59XHJcbiIsIi5sYXlvdXQtZWRpdG9yLXRvb2xiYXIge1xuICBkaXNwbGF5OiBmbGV4O1xuICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XG4gIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgdG9wOiAxMHB4O1xufVxuLmxheW91dC1lZGl0b3ItdG9vbGJhciAubGF5b3V0LWVkaXRvci10b29sYmFyLWdyb3VwIHtcbiAgZGlzcGxheTogZmxleDtcbn1cbi5sYXlvdXQtZWRpdG9yLXRvb2xiYXIgLmxheW91dC1lZGl0b3ItdG9vbGJhci1ncm91cCA+IGxpICsgbGkge1xuICBtYXJnaW4tbGVmdDogMTJweDtcbn1cbi5sYXlvdXQtZWRpdG9yIHtcbiAgZGlzcGxheTogZmxleDtcbiAgbWFyZ2luLXRvcDogMWVtO1xuICBmb250LXNpemU6IDE0cHg7XG4gIGFsaWduLWl0ZW1zOiBzdHJldGNoO1xufVxuLmxheW91dC1lZGl0b3IgPiAubGF5b3V0LWNhbnZhcy13cmFwcGVyIHtcbiAgZmxleC1ncm93OiAxO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjNmNGY1O1xuICBib3JkZXI6IDFweCBzb2xpZCAjZTRlNWU2O1xufVxuLmxheW91dC1lZGl0b3IgPiAubGF5b3V0LWNhbnZhcy13cmFwcGVyID4gLmxheW91dC10b29sYmFyLWNvbnRhaW5lciB7XG4gIGRpc3BsYXk6IG5vbmU7XG4gIG1hcmdpbjogMTJweCAxMnB4IDA7XG4gIG1pbi1oZWlnaHQ6IDcxcHg7XG59XG4ubGF5b3V0LWVkaXRvciA+IC5sYXlvdXQtY2FudmFzLXdyYXBwZXIgPiAubGF5b3V0LXRvb2xiYXItY29udGFpbmVyID4gLm1jZS1wYW5lbCB7XG4gIHdpZHRoOiAxMDAlICFpbXBvcnRhbnQ7XG59XG4ubGF5b3V0LWVkaXRvciA+IC5sYXlvdXQtY2FudmFzLXdyYXBwZXIgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCA+IC5sYXlvdXQtcGxhY2Vob2xkZXIge1xuICBib3JkZXI6IDFweCBkYXNoZWQgI2NjYztcbiAgcGFkZGluZzogMC4yZW0gMC40ZW07XG4gIGJhY2tncm91bmQ6ICNlOGU4ZTg7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LXNuaXBwZXQge1xuICBiYWNrZ3JvdW5kOiAjZThlOGU4O1xufVxuLmxheW91dC1lZGl0b3ItaGVscC1kaWFsb2cge1xuICBkaXNwbGF5OiBub25lO1xufVxuLmxheW91dC1lZGl0b3ItaGVscC1kaWFsb2cgLmhlbHAtcm93OmJlZm9yZSxcbi5sYXlvdXQtZWRpdG9yLWhlbHAtZGlhbG9nIC5oZWxwLXJvdzphZnRlciB7XG4gIGNvbnRlbnQ6IFwiIFwiO1xuICBkaXNwbGF5OiB0YWJsZTtcbn1cbi5sYXlvdXQtZWRpdG9yLWhlbHAtZGlhbG9nIC5oZWxwLXJvdzphZnRlciB7XG4gIGNsZWFyOiBib3RoO1xufVxuLmxheW91dC1lZGl0b3ItaGVscC1kaWFsb2cgLmhlbHAtcm93ID4gLmhlbHAtY29sdW1uLWZ1bGwsXG4ubGF5b3V0LWVkaXRvci1oZWxwLWRpYWxvZyAuaGVscC1yb3cgPiAuaGVscC1jb2x1bW4taGFsZiB7XG4gIG1hcmdpbjogMC41ZW0gMDtcbn1cbi5sYXlvdXQtZWRpdG9yLWhlbHAtZGlhbG9nIC5oZWxwLXJvdyA+IC5oZWxwLWNvbHVtbi1oYWxmIHtcbiAgYm94LXNpemluZzogYm9yZGVyLWJveDtcbiAgZmxvYXQ6IGxlZnQ7XG4gIHdpZHRoOiA1MCU7XG59XG4ubGF5b3V0LWVkaXRvci1oZWxwLWRpYWxvZyAuaGVscC1yb3cgPiAuaGVscC1jb2x1bW4taGFsZjpudGgtY2hpbGQoMm4pIHtcbiAgcGFkZGluZy1yaWdodDogMTBweDtcbiAgY2xlYXI6IGxlZnQ7XG59XG4ubGF5b3V0LWVkaXRvci1oZWxwLWRpYWxvZyAuaGVscC1yb3cgKyAuaGVscC1yb3cge1xuICBtYXJnaW4tdG9wOiAxZW07XG59XG4ubGF5b3V0LWVkaXRvci1oZWxwLWRpYWxvZyBjb2RlIHtcbiAgYm9yZGVyLXJhZGl1czogNHB4O1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjNmNGY1O1xuICBwYWRkaW5nOiAycHggNHB4O1xuICBmb250LWZhbWlseTogbW9ub3NwYWNlO1xufVxuLmxheW91dC1lZGl0b3ItaGVscC1kaWFsb2cgcCB7XG4gIG1hcmdpbi1ib3R0b206IDAuNWVtO1xuICBsaW5lLWhlaWdodDogMS42ZW07XG59XG4ubGF5b3V0LWVkaXRvci1oZWxwLWRpYWxvZyB0YWJsZSA+IHRib2R5ID4gdHIgPiB0ZDpmaXJzdC1jaGlsZCB7XG4gIHBhZGRpbmctcmlnaHQ6IDEwcHg7XG59XG5cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtZWxlbWVudCB7XG4gIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgbWFyZ2luLXRvcDogMDtcbiAgbWFyZ2luLXJpZ2h0OiAwO1xuICBtYXJnaW4tYm90dG9tOiAwO1xuICBwYWRkaW5nOiAwO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1lbGVtZW50Om5vdCgubGF5b3V0LWNvbHVtbikge1xuICBtYXJnaW4tbGVmdDogMDtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtZWxlbWVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1wYW5lbCB7XG4gIGRpc3BsYXk6IG5vbmU7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgbWFyZ2luOiAwO1xuICB6LWluZGV4OiAyMDtcbiAgaGVpZ2h0OiAyNXB4O1xuICBwYWRkaW5nOiAwIDZweDtcbiAgbGlzdC1zdHlsZTogbm9uZTtcbiAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcbiAgbGluZS1oZWlnaHQ6IDI1cHg7XG4gIHZlcnRpY2FsLWFsaWduOiBtaWRkbGU7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWVsZW1lbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciA+IC5sYXlvdXQtcGFuZWwgPiAubGF5b3V0LXBhbmVsLWl0ZW0ge1xuICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7XG4gIGhlaWdodDogMjVweDtcbiAgcGFkZGluZzogMXB4IDZweCAwO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1lbGVtZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgPiAubGF5b3V0LXBhbmVsID4gLmxheW91dC1wYW5lbC1sYWJlbCB7XG4gIGZvbnQtc2l6ZTogMTNweDtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtZWxlbWVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1wYW5lbCA+IC5sYXlvdXQtcGFuZWwtYWN0aW9uIHtcbiAgZGlzcGxheTogbm9uZTtcbiAgd2lkdGg6IDI4cHg7XG4gIGN1cnNvcjogcG9pbnRlcjtcbiAgdGV4dC1hbGlnbjogY2VudGVyO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1lbGVtZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgPiAubGF5b3V0LXBhbmVsLW1haW4ge1xuICB0b3A6IC0yN3B4O1xuICBsZWZ0OiAtMnB4O1xufVxuLmxheW91dC1lZGl0b3IgbGkubGF5b3V0LWVsZW1lbnQge1xuICBsaXN0LXN0eWxlOiBub25lO1xufVxuLmxheW91dC1lZGl0b3I6bm90KC5sYXlvdXQtZWRpdG9yLWRyYWdnaW5nKSAubGF5b3V0LWVsZW1lbnQtYWN0aXZlLFxuLmxheW91dC1lZGl0b3I6bm90KC5sYXlvdXQtZWRpdG9yLWRyYWdnaW5nKSAubGF5b3V0LWVsZW1lbnQtZm9jdXNlZCB7XG4gIGJvcmRlci13aWR0aDogMnB4O1xuICBib3JkZXItc3R5bGU6IHNvbGlkO1xufVxuLmxheW91dC1lZGl0b3I6bm90KC5sYXlvdXQtZWRpdG9yLWRyYWdnaW5nKSAubGF5b3V0LWVsZW1lbnQtYWN0aXZlID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIsXG4ubGF5b3V0LWVkaXRvcjpub3QoLmxheW91dC1lZGl0b3ItZHJhZ2dpbmcpIC5sYXlvdXQtZWxlbWVudC1mb2N1c2VkID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIge1xuICBtYXJnaW46IC0ycHg7XG59XG4ubGF5b3V0LWVkaXRvcjpub3QoLmxheW91dC1lZGl0b3ItZHJhZ2dpbmcpIC5sYXlvdXQtZWxlbWVudC1hY3RpdmUge1xuICBib3JkZXItY29sb3I6IHJnYmEoMTA0LCAxMDQsIDEwNCwgMC4xKTtcbn1cbi5sYXlvdXQtZWRpdG9yOm5vdCgubGF5b3V0LWVkaXRvci1kcmFnZ2luZykgLmxheW91dC1lbGVtZW50LWFjdGl2ZSA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1wYW5lbC1tYWluIHtcbiAgZGlzcGxheTogYmxvY2s7XG4gIHotaW5kZXg6IDMwO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDEwNCwgMTA0LCAxMDQsIDAuMSk7XG59XG4ubGF5b3V0LWVkaXRvcjpub3QoLmxheW91dC1lZGl0b3ItZHJhZ2dpbmcpIC5sYXlvdXQtZWxlbWVudC1mb2N1c2VkIHtcbiAgYm9yZGVyLWNvbG9yOiAjNjQ4NzIxO1xufVxuLmxheW91dC1lZGl0b3I6bm90KC5sYXlvdXQtZWRpdG9yLWRyYWdnaW5nKSAubGF5b3V0LWVsZW1lbnQtZm9jdXNlZCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1wYW5lbCB7XG4gIGRpc3BsYXk6IGJsb2NrO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNjQ4NzIxO1xuICBjb2xvcjogI2ZlZmVmZTtcbn1cbi5sYXlvdXQtZWRpdG9yOm5vdCgubGF5b3V0LWVkaXRvci1kcmFnZ2luZykgLmxheW91dC1lbGVtZW50LWZvY3VzZWQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciA+IC5sYXlvdXQtcGFuZWwgPiAubGF5b3V0LXBhbmVsLWFjdGlvbiB7XG4gIGRpc3BsYXk6IGlubGluZS1ibG9jaztcbn1cbi5sYXlvdXQtZWRpdG9yOm5vdCgubGF5b3V0LWVkaXRvci1kcmFnZ2luZykgLmxheW91dC1lbGVtZW50LWZvY3VzZWQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciA+IC5sYXlvdXQtcGFuZWwgPiAubGF5b3V0LXBhbmVsLWFjdGlvbjpob3ZlciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM4MmIwMmI7XG59XG4ubGF5b3V0LWVkaXRvcjpub3QoLmxheW91dC1lZGl0b3ItZHJhZ2dpbmcpIC5sYXlvdXQtZWxlbWVudC1mb2N1c2VkID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgPiAubGF5b3V0LXBhbmVsID4gLmxheW91dC1wYW5lbC1hY3Rpb24uZGlzYWJsZWQge1xuICBjdXJzb3I6IGRlZmF1bHQ7XG4gIGNvbG9yOiByZ2JhKDI1NCwgMjU0LCAyNTQsIDAuNCk7XG59XG4ubGF5b3V0LWVkaXRvcjpub3QoLmxheW91dC1lZGl0b3ItZHJhZ2dpbmcpIC5sYXlvdXQtZWxlbWVudC1mb2N1c2VkID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgPiAubGF5b3V0LXBhbmVsID4gLmxheW91dC1wYW5lbC1hY3Rpb24uZGlzYWJsZWQ6aG92ZXIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNjQ4NzIxO1xufVxuLmxheW91dC1lZGl0b3I6bm90KC5sYXlvdXQtZWRpdG9yLWRyYWdnaW5nKSAubGF5b3V0LWVsZW1lbnQtZm9jdXNlZCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1wYW5lbCA+IC5sYXlvdXQtcGFuZWwtYWN0aW9uLmFjdGl2ZSB7XG4gIGNvbG9yOiAjZGVmZjQyO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNzM5YjI2O1xufVxuLmxheW91dC1lZGl0b3I6bm90KC5sYXlvdXQtZWRpdG9yLWRyYWdnaW5nKSAubGF5b3V0LWVsZW1lbnQtZm9jdXNlZCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1wYW5lbCA+IC5sYXlvdXQtcGFuZWwtYWN0aW9uLmFjdGl2ZTpob3ZlciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM4MmIwMmI7XG59XG4ubGF5b3V0LWVkaXRvcjpub3QoLmxheW91dC1lZGl0b3ItZHJhZ2dpbmcpIC5sYXlvdXQtZWxlbWVudC1zZWxlY3RlZCB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMTAwLCAxMzUsIDMzLCAwLjA4KTtcbn1cbi5sYXlvdXQtZWRpdG9yIC51aS1zb3J0YWJsZS1wbGFjZWhvbGRlciB7XG4gIGRpc3BsYXk6IG5vbmU7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWVsZW1lbnQtZHJvcHRhcmdldCB7XG4gIGJveC1zaGFkb3c6IGluc2V0IDAgMCAxMnB4IDZweCByZ2JhKDEwMCwgMTM1LCAzMywgMC41KTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtZWxlbWVudC1kcm9wdGFyZ2V0IC51aS1zb3J0YWJsZS1wbGFjZWhvbGRlciB7XG4gIGRpc3BsYXk6IGJsb2NrO1xuICB2aXNpYmlsaXR5OiB2aXNpYmxlICFpbXBvcnRhbnQ7XG4gIG1pbi1oZWlnaHQ6IDc4cHg7XG4gIGJvcmRlcjogMnB4IGRhc2hlZCAjNjQ4NzIxICFpbXBvcnRhbnQ7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMTAwLCAxMzUsIDMzLCAwLjE2KTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5tZWRpYS10aHVtYm5haWwgaW1nIHtcbiAgbWF4LXdpZHRoOiAxMDAlO1xuICBtYXgtaGVpZ2h0OiAxMDAlO1xufVxuXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRhaW5lciA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1jb250YWluZXItY2hpbGRyZW4tcGxhY2Vob2xkZXIge1xuICBkaXNwbGF5OiBub25lO1xuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICBtYXJnaW46IDExcHg7XG4gIG1pbi1oZWlnaHQ6IDgwcHg7XG4gIGJvcmRlcjogMXB4IGRhc2hlZCByZ2JhKDEyNCwgMTI0LCAxMjQsIDAuNCk7XG4gIGJvcmRlci1yYWRpdXM6IDRweDtcbiAgcGFkZGluZzogMTJweDtcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG4gIGZvbnQtc2l6ZTogMTNweDtcbiAgZm9udC1zdHlsZTogaXRhbGljO1xuICBvcGFjaXR5OiAwLjY7XG4gIHRleHQtYWxpZ246IGNlbnRlcjtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGFpbmVyID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgPiAubGF5b3V0LWNoaWxkcmVuIHtcbiAgcGFkZGluZzogMTJweDtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGFpbmVyID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgPiAubGF5b3V0LWNoaWxkcmVuID4gLmxheW91dC1lbGVtZW50Om5vdCgubGF5b3V0LWNvbnRhaW5lcikgKyAubGF5b3V0LWVsZW1lbnQ6bm90KC5sYXlvdXQtY29udGFpbmVyKSB7XG4gIG1hcmdpbi10b3A6IDEycHg7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRhaW5lciA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1jaGlsZHJlbiA+IC51aS1zb3J0YWJsZS1oZWxwZXI6Zmlyc3QtY2hpbGQgKyAubGF5b3V0LWVsZW1lbnQ6bm90KC5sYXlvdXQtY29udGFpbmVyKSB7XG4gIG1hcmdpbi10b3A6IDA7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRhaW5lciA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyLmxheW91dC1jb250YWluZXItZW1wdHkgPiAubGF5b3V0LWNvbnRhaW5lci1jaGlsZHJlbi1wbGFjZWhvbGRlciB7XG4gIGRpc3BsYXk6IGZsZXg7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRhaW5lciA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyLmxheW91dC1jb250YWluZXItZW1wdHkgPiAubGF5b3V0LWNoaWxkcmVuIHtcbiAgcG9zaXRpb246IGFic29sdXRlO1xuICB0b3A6IDA7XG4gIHJpZ2h0OiAwO1xuICBib3R0b206IDA7XG4gIGxlZnQ6IDA7XG59XG4ubGF5b3V0LWVkaXRvcjpub3QoLmxheW91dC1lZGl0b3ItZHJhZ2dpbmcpIC5sYXlvdXQtY29udGFpbmVyLmxheW91dC1lbGVtZW50LWZvY3VzZWQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciA+IC5sYXlvdXQtY2hpbGRyZW4gPiAubGF5b3V0LWVsZW1lbnQ6bm90KC5sYXlvdXQtZWxlbWVudC1hY3RpdmUpIHtcbiAgYm9yZGVyOiAxcHggZGFzaGVkIHJnYmEoMTI0LCAxMjQsIDEyNCwgMC42KTtcbn1cbi5sYXlvdXQtZWRpdG9yOm5vdCgubGF5b3V0LWVkaXRvci1kcmFnZ2luZykgLmxheW91dC1jb250YWluZXIubGF5b3V0LWVsZW1lbnQtZm9jdXNlZCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1jaGlsZHJlbiA+IC5sYXlvdXQtZWxlbWVudDpub3QoLmxheW91dC1lbGVtZW50LWFjdGl2ZSkgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciB7XG4gIG1hcmdpbjogLTFweDtcbn1cbi5sYXlvdXQtZWRpdG9yOm5vdCgubGF5b3V0LWVkaXRvci1kcmFnZ2luZykgLmxheW91dC1jb250YWluZXIubGF5b3V0LWVsZW1lbnQtZm9jdXNlZCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1jaGlsZHJlbiA+IC5sYXlvdXQtY29udGFpbmVyICsgLmxheW91dC1jb250YWluZXI6bm90KC5sYXlvdXQtZWxlbWVudC1hY3RpdmUpIHtcbiAgYm9yZGVyLXRvcDogMDtcbn1cbi5sYXlvdXQtZWRpdG9yOm5vdCgubGF5b3V0LWVkaXRvci1kcmFnZ2luZykgLmxheW91dC1jb250YWluZXIubGF5b3V0LWVsZW1lbnQtZm9jdXNlZCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1jaGlsZHJlbiA+IC5sYXlvdXQtY29udGFpbmVyICsgLmxheW91dC1jb250YWluZXI6bm90KC5sYXlvdXQtZWxlbWVudC1hY3RpdmUpID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIge1xuICBtYXJnaW4tdG9wOiAwO1xufVxuXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNhbnZhcyAjZHVtbXkge1xuICBkaXNwbGF5OiBub25lO1xufVxuXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LXJvdy5sYXlvdXQtZWxlbWVudC1mb2N1c2VkOm5vdCgubGF5b3V0LWVsZW1lbnQtZHJvcHRhcmdldCkgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciA+IC5sYXlvdXQtY2hpbGRyZW4gPiAubGF5b3V0LWVsZW1lbnQ6bm90KC5sYXlvdXQtZWxlbWVudC1hY3RpdmUpIHtcbiAgYm9yZGVyLXRvcDogMXB4IGRhc2hlZCByZ2JhKDEyNCwgMTI0LCAxMjQsIDAuNikgIWltcG9ydGFudDtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtcm93LmxheW91dC1lbGVtZW50LWZvY3VzZWQ6bm90KC5sYXlvdXQtZWxlbWVudC1kcm9wdGFyZ2V0KSA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1jaGlsZHJlbiA+IC5sYXlvdXQtZWxlbWVudDpub3QoLmxheW91dC1lbGVtZW50LWFjdGl2ZSkgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciB7XG4gIG1hcmdpbi10b3A6IC0xcHggIWltcG9ydGFudDtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtcm93LmxheW91dC1lbGVtZW50LWZvY3VzZWQ6bm90KC5sYXlvdXQtZWxlbWVudC1kcm9wdGFyZ2V0KSA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1jaGlsZHJlbiA+IC5sYXlvdXQtZWxlbWVudCArIC5sYXlvdXQtZWxlbWVudDpub3QoLmxheW91dC1lbGVtZW50LWFjdGl2ZSkge1xuICBib3JkZXItbGVmdDogMCAhaW1wb3J0YW50O1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1yb3cubGF5b3V0LWVsZW1lbnQtZm9jdXNlZDpub3QoLmxheW91dC1lbGVtZW50LWRyb3B0YXJnZXQpID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgPiAubGF5b3V0LWNoaWxkcmVuID4gLmxheW91dC1lbGVtZW50ICsgLmxheW91dC1lbGVtZW50Om5vdCgubGF5b3V0LWVsZW1lbnQtYWN0aXZlKSA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIHtcbiAgbWFyZ2luLWxlZnQ6IDAgIWltcG9ydGFudDtcbn1cblxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb2x1bW4gPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciA+IC5sYXlvdXQtY29sdW1uLXJlc2l6ZS1iYXIge1xuICBkaXNwbGF5OiBub25lO1xuICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gIHotaW5kZXg6IDMwO1xuICB0b3A6IDA7XG4gIHdpZHRoOiAxNnB4O1xuICBoZWlnaHQ6IDEwMCU7XG4gIGN1cnNvcjogY29sLXJlc2l6ZTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29sdW1uID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgPiAubGF5b3V0LWNvbHVtbi1yZXNpemUtYmFyLWxlZnQge1xuICBsZWZ0OiAtNnB4O1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb2x1bW4gPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciA+IC5sYXlvdXQtY29sdW1uLXJlc2l6ZS1iYXItcmlnaHQge1xuICByaWdodDogLTZweDtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29sdW1uLmxheW91dC1lbGVtZW50LWZvY3VzZWQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciA+IC5sYXlvdXQtY29sdW1uLXJlc2l6ZS1iYXIge1xuICBkaXNwbGF5OiBibG9jaztcbn1cblxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sIHtcbiAgbWluLWhlaWdodDogMWVtO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAge1xuICBwYWRkaW5nOiAycHg7XG4gIG92ZXJmbG93LXg6IGhpZGRlbjtcbiAgbGluZS1oZWlnaHQ6IG5vcm1hbDtcbiAgLyogdGhpcyBjb2xvciBpcyBqdXN0IGEgc3VnZ2VzdGlvbiBhbmQgY2FuIGJlIGNoYW5nZWQgYmFzZWQgb24gaW1wbGVtZW50YXRpb24gZmVlZGJhY2sgKi9cbiAgLyogdGhpcyBhbHNvIGhhcyBiaWRpIGltcGxpY2F0aW9ucyAqL1xuICAvKiB0aGlzIGFsc28gaGFzIGJpZGkgaW1wbGljYXRpb25zICovXG4gIC8qIExUUi1zcGVjaWZpYzogdXNlICdtYXJnaW4tcmlnaHQnIGZvciBydGwgZWxlbWVudHMgKi9cbiAgLyogTFRSLXNwZWNpZmljOiB1c2UgJ3BhZGRpbmctcmlnaHQnIGZvciBydGwgZWxlbWVudHMgKi9cbiAgLyp0YWJsZVtydWxlcz1ub25lIGldLCB0YWJsZVtydWxlcz1ncm91cHMgaV0sIHRhYmxlW3J1bGVzPXJvd3MgaV0sXG50YWJsZVtydWxlcz1jb2xzIGldLCB0YWJsZVtydWxlcz1hbGwgaV0sIHRhYmxlW2ZyYW1lPXZvaWQgaV0sXG50YWJsZVtmcmFtZT1hYm92ZSBpXSwgdGFibGVbZnJhbWU9YmVsb3cgaV0sIHRhYmxlW2ZyYW1lPWhzaWRlcyBpXSxcbnRhYmxlW2ZyYW1lPWxocyBpXSwgdGFibGVbZnJhbWU9cmhzIGldLCB0YWJsZVtmcmFtZT12c2lkZXMgaV0sXG50YWJsZVtmcmFtZT1ib3ggaV0sIHRhYmxlW2ZyYW1lPWJvcmRlciBpXSxcbnRhYmxlW3J1bGVzPW5vbmUgaV0gPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1ub25lIGldID4gdHIgPiB0aCxcbnRhYmxlW3J1bGVzPWdyb3VwcyBpXSA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPWdyb3VwcyBpXSA+IHRyID4gdGgsXG50YWJsZVtydWxlcz1yb3dzIGldID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9cm93cyBpXSA+IHRyID4gdGgsXG50YWJsZVtydWxlcz1jb2xzIGldID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9Y29scyBpXSA+IHRyID4gdGgsXG50YWJsZVtydWxlcz1hbGwgaV0gPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1hbGwgaV0gPiB0ciA+IHRoLFxudGFibGVbcnVsZXM9bm9uZSBpXSA+IHRoZWFkID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9bm9uZSBpXSA+IHRoZWFkID4gdHIgPiB0aCxcbnRhYmxlW3J1bGVzPWdyb3VwcyBpXSA+IHRoZWFkID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9Z3JvdXBzIGldID4gdGhlYWQgPiB0ciA+IHRoLFxudGFibGVbcnVsZXM9cm93cyBpXSA+IHRoZWFkID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9cm93cyBpXSA+IHRoZWFkID4gdHIgPiB0aCxcbnRhYmxlW3J1bGVzPWNvbHMgaV0gPiB0aGVhZCA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPWNvbHMgaV0gPiB0aGVhZCA+IHRyID4gdGgsXG50YWJsZVtydWxlcz1hbGwgaV0gPiB0aGVhZCA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPWFsbCBpXSA+IHRoZWFkID4gdHIgPiB0aCxcbnRhYmxlW3J1bGVzPW5vbmUgaV0gPiB0Ym9keSA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPW5vbmUgaV0gPiB0Ym9keSA+IHRyID4gdGgsXG50YWJsZVtydWxlcz1ncm91cHMgaV0gPiB0Ym9keSA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPWdyb3VwcyBpXSA+IHRib2R5ID4gdHIgPiB0aCxcbnRhYmxlW3J1bGVzPXJvd3MgaV0gPiB0Ym9keSA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPXJvd3MgaV0gPiB0Ym9keSA+IHRyID4gdGgsXG50YWJsZVtydWxlcz1jb2xzIGldID4gdGJvZHkgPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1jb2xzIGldID4gdGJvZHkgPiB0ciA+IHRoLFxudGFibGVbcnVsZXM9YWxsIGldID4gdGJvZHkgPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1hbGwgaV0gPiB0Ym9keSA+IHRyID4gdGgsXG50YWJsZVtydWxlcz1ub25lIGldID4gdGZvb3QgPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1ub25lIGldID4gdGZvb3QgPiB0ciA+IHRoLFxudGFibGVbcnVsZXM9Z3JvdXBzIGldID4gdGZvb3QgPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1ncm91cHMgaV0gPiB0Zm9vdCA+IHRyID4gdGgsXG50YWJsZVtydWxlcz1yb3dzIGldID4gdGZvb3QgPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1yb3dzIGldID4gdGZvb3QgPiB0ciA+IHRoLFxudGFibGVbcnVsZXM9Y29scyBpXSA+IHRmb290ID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9Y29scyBpXSA+IHRmb290ID4gdHIgPiB0aCxcbnRhYmxlW3J1bGVzPWFsbCBpXSA+IHRmb290ID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9YWxsIGldID4gdGZvb3QgPiB0ciA+IHRoIHtcbiAgICBib3JkZXItY29sb3I6IGJsYWNrO1xufSovXG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwICosXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwICoge1xuICBtYXJnaW46IDA7XG4gIHBhZGRpbmc6IDA7XG4gIGJveC1zaXppbmc6IGNvbnRlbnQtYm94O1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBhZGRyZXNzLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBhZGRyZXNzLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBibG9ja3F1b3RlLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBibG9ja3F1b3RlLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBjZW50ZXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGNlbnRlcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGl2LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkaXYsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGZpZ3VyZSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZmlndXJlLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBmaWdjYXB0aW9uLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBmaWdjYXB0aW9uLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBmb290ZXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGZvb3Rlcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZm9ybSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZm9ybSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgaGVhZGVyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBoZWFkZXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGhyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBocixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgbGVnZW5kLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBsZWdlbmQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGxpc3RpbmcsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGxpc3RpbmcsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHAsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHAsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHBsYWludGV4dCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgcGxhaW50ZXh0LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBwcmUsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHByZSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgeG1wLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB4bXAge1xuICBkaXNwbGF5OiBibG9jaztcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYmxvY2txdW90ZSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYmxvY2txdW90ZSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZmlndXJlLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBmaWd1cmUsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGxpc3RpbmcsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGxpc3RpbmcsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHAsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHAsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHBsYWludGV4dCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgcGxhaW50ZXh0LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBwcmUsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHByZSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgeG1wLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB4bXAge1xuICBtYXJnaW4tdG9wOiAxZW07XG4gIG1hcmdpbi1ib3R0b206IDFlbTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYmxvY2txdW90ZSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYmxvY2txdW90ZSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZmlndXJlLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBmaWd1cmUge1xuICBtYXJnaW4tbGVmdDogNDBweDtcbiAgbWFyZ2luLXJpZ2h0OiA0MHB4O1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBhZGRyZXNzLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBhZGRyZXNzIHtcbiAgZm9udC1zdHlsZTogaXRhbGljO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBsaXN0aW5nLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBsaXN0aW5nLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBwbGFpbnRleHQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHBsYWludGV4dCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgcHJlLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBwcmUsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHhtcCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgeG1wIHtcbiAgZm9udC1mYW1pbHk6IG1vbm9zcGFjZTtcbiAgd2hpdGUtc3BhY2U6IHByZTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgY2l0ZSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgY2l0ZSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGZuLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkZm4sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGVtLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBlbSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgaSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgaSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdmFyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB2YXIge1xuICBmb250LXN0eWxlOiBpdGFsaWM7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHN0cm9uZyxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgc3Ryb25nIHtcbiAgZm9udC13ZWlnaHQ6IGJvbGRlcjtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgY29kZSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgY29kZSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAga2JkLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBrYmQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHNhbXAsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHNhbXAsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHR0LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0dCB7XG4gIGZvbnQtZmFtaWx5OiBtb25vc3BhY2U7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGJpZyxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYmlnIHtcbiAgZm9udC1zaXplOiBsYXJnZXI7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHNtYWxsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBzbWFsbCB7XG4gIGZvbnQtc2l6ZTogc21hbGxlcjtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgc3ViLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBzdWIge1xuICB2ZXJ0aWNhbC1hbGlnbjogc3ViO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBzdXAsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHN1cCB7XG4gIHZlcnRpY2FsLWFsaWduOiBzdXBlcjtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgc3ViLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBzdWIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHN1cCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgc3VwIHtcbiAgbGluZS1oZWlnaHQ6IG5vcm1hbDtcbiAgZm9udC1zaXplOiBzbWFsbGVyO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBydWJ5LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBydWJ5IHtcbiAgZGlzcGxheTogcnVieTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgcmIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHJiIHtcbiAgZGlzcGxheTogcnVieS1iYXNlO1xuICB3aGl0ZS1zcGFjZTogbm93cmFwO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBydCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgcnQge1xuICBkaXNwbGF5OiBydWJ5LXRleHQ7XG4gIHdoaXRlLXNwYWNlOiBub3dyYXA7XG4gIGZvbnQtc2l6ZTogNTAlO1xuICBmb250LXZhcmlhbnQtZWFzdC1hc2lhbjogcnVieTtcbiAgdGV4dC1lbXBoYXNpczogbm9uZTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgcmJjLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCByYmMge1xuICBkaXNwbGF5OiBydWJ5LWJhc2UtY29udGFpbmVyO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBydGMsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHJ0YyB7XG4gIGRpc3BsYXk6IHJ1YnktdGV4dC1jb250YWluZXI7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHJ1YnksXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHJ1YnksXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHJiLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCByYixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgcnQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHJ0LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCByYmMsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHJiYyxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgcnRjLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBydGMge1xuICB1bmljb2RlLWJpZGk6IGlzb2xhdGU7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIDpsaW5rLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCA6bGluayB7XG4gIGNvbG9yOiAjMDAwMEVFO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCA6dmlzaXRlZCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgOnZpc2l0ZWQge1xuICBjb2xvcjogIzU1MUE4Qjtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgOmxpbmssXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIDpsaW5rLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCA6dmlzaXRlZCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgOnZpc2l0ZWQge1xuICB0ZXh0LWRlY29yYXRpb246IHVuZGVybGluZTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYTpsaW5rW3JlbH49aGVscF0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGE6bGlua1tyZWx+PWhlbHBdLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBhOnZpc2l0ZWRbcmVsfj1oZWxwXSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYTp2aXNpdGVkW3JlbH49aGVscF0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGFyZWE6bGlua1tyZWx+PWhlbHBdLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBhcmVhOmxpbmtbcmVsfj1oZWxwXSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYXJlYTp2aXNpdGVkW3JlbH49aGVscF0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGFyZWE6dmlzaXRlZFtyZWx+PWhlbHBdIHtcbiAgY3Vyc29yOiBoZWxwO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCA6Zm9jdXMsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIDpmb2N1cyB7XG4gIG91dGxpbmU6IGF1dG87XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG1hcmssXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG1hcmsge1xuICBiYWNrZ3JvdW5kOiB5ZWxsb3c7XG4gIGNvbG9yOiBibGFjaztcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYWJiclt0aXRsZV0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGFiYnJbdGl0bGVdLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBhY3JvbnltW3RpdGxlXSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYWNyb255bVt0aXRsZV0ge1xuICB0ZXh0LWRlY29yYXRpb246IGRvdHRlZCB1bmRlcmxpbmU7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGlucyxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgaW5zLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB1LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB1IHtcbiAgdGV4dC1kZWNvcmF0aW9uOiB1bmRlcmxpbmU7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRlbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGVsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBzLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBzLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBzdHJpa2UsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHN0cmlrZSB7XG4gIHRleHQtZGVjb3JhdGlvbjogbGluZS10aHJvdWdoO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBibGluayxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYmxpbmsge1xuICB0ZXh0LWRlY29yYXRpb246IGJsaW5rO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBxOjpiZWZvcmUsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHE6OmJlZm9yZSB7XG4gIGNvbnRlbnQ6IG9wZW4tcXVvdGU7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHE6OmFmdGVyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBxOjphZnRlciB7XG4gIGNvbnRlbnQ6IGNsb3NlLXF1b3RlO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBicixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYnIge1xuICBjb250ZW50OiAnXFxBJztcbiAgd2hpdGUtc3BhY2U6IHByZTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgbm9icixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgbm9iciB7XG4gIHdoaXRlLXNwYWNlOiBub3dyYXA7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHdicixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgd2JyIHtcbiAgY29udGVudDogJ1xcMjAwQic7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG5vYnIgd2JyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBub2JyIHdiciB7XG4gIHdoaXRlLXNwYWNlOiBub3JtYWw7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGFydGljbGUsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGFydGljbGUsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGFzaWRlLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBhc2lkZSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgaDEsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGgxLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBoMixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgaDIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGgzLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBoMyxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgaDQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGg0LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBoNSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgaDUsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGg2LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBoNixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgaGdyb3VwLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBoZ3JvdXAsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG5hdixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgbmF2LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBzZWN0aW9uLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBzZWN0aW9uIHtcbiAgZGlzcGxheTogYmxvY2s7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGgxLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBoMSB7XG4gIG1hcmdpbi10b3A6IDAuNjdlbTtcbiAgbWFyZ2luLWJvdHRvbTogMC42N2VtO1xuICBmb250LXNpemU6IDIuMDBlbTtcbiAgZm9udC13ZWlnaHQ6IGJvbGQ7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGgyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBoMiB7XG4gIG1hcmdpbi10b3A6IDAuODNlbTtcbiAgbWFyZ2luLWJvdHRvbTogMC44M2VtO1xuICBmb250LXNpemU6IDEuNTBlbTtcbiAgZm9udC13ZWlnaHQ6IGJvbGQ7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGgzLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBoMyB7XG4gIG1hcmdpbi10b3A6IDEuMDBlbTtcbiAgbWFyZ2luLWJvdHRvbTogMS4wMGVtO1xuICBmb250LXNpemU6IDEuMTdlbTtcbiAgZm9udC13ZWlnaHQ6IGJvbGQ7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGg0LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBoNCB7XG4gIG1hcmdpbi10b3A6IDEuMzNlbTtcbiAgbWFyZ2luLWJvdHRvbTogMS4zM2VtO1xuICBmb250LXNpemU6IDEuMDBlbTtcbiAgZm9udC13ZWlnaHQ6IGJvbGQ7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGg1LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBoNSB7XG4gIG1hcmdpbi10b3A6IDEuNjdlbTtcbiAgbWFyZ2luLWJvdHRvbTogMS42N2VtO1xuICBmb250LXNpemU6IDAuODNlbTtcbiAgZm9udC13ZWlnaHQ6IGJvbGQ7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGg2LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBoNiB7XG4gIG1hcmdpbi10b3A6IDIuMzNlbTtcbiAgbWFyZ2luLWJvdHRvbTogMi4zM2VtO1xuICBmb250LXNpemU6IDAuNjdlbTtcbiAgZm9udC13ZWlnaHQ6IGJvbGQ7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkZCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZHQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGR0LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgb2wsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHVsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB1bCB7XG4gIGRpc3BsYXk6IGJsb2NrO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBsaSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgbGkge1xuICBkaXNwbGF5OiBsaXN0LWl0ZW07XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG9sLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHVsIHtcbiAgbWFyZ2luLXRvcDogMWVtO1xuICBtYXJnaW4tYm90dG9tOiAxZW07XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpciBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpciBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpciBkbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyIGRsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkaXIgb2wsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpciBvbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyIHVsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkaXIgdWwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRsIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGwgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkbCBkbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGwgZGwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRsIG9sLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkbCBvbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGwgdWwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRsIHVsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG9sIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgb2wgZGwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG9sIGRsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCBvbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgb2wgb2wsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG9sIHVsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCB1bCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB1bCBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHVsIGRsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB1bCBkbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwgb2wsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHVsIG9sLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB1bCB1bCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwgdWwge1xuICBtYXJnaW4tdG9wOiAwO1xuICBtYXJnaW4tYm90dG9tOiAwO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkZCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGQge1xuICBtYXJnaW4tbGVmdDogNDBweDtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG9sLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHVsIHtcbiAgcGFkZGluZy1sZWZ0OiA0MHB4O1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgb2wge1xuICBsaXN0LXN0eWxlLXR5cGU6IGRlY2ltYWw7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB1bCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwge1xuICBsaXN0LXN0eWxlLXR5cGU6IGRpc2M7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpciBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpciBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpciB1bCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyIHVsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG9sIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgb2wgdWwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG9sIHVsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB1bCBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHVsIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwgdWwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHVsIHVsIHtcbiAgbGlzdC1zdHlsZS10eXBlOiBjaXJjbGU7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpciBkaXIgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkaXIgZGlyIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyIGRpciB1bCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyIGRpciB1bCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyIG9sIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyIG9sIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyIG9sIHVsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBkaXIgb2wgdWwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpciB1bCBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpciB1bCBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGRpciB1bCB1bCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZGlyIHVsIHVsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCBkaXIgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCBkaXIgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCBkaXIgdWwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG9sIGRpciB1bCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgb2wgb2wgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCBvbCBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG9sIG9sIHVsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCBvbCB1bCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgb2wgdWwgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCB1bCBkaXIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG9sIHVsIHVsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvbCB1bCB1bCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwgZGlyIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwgZGlyIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwgZGlyIHVsLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB1bCBkaXIgdWwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHVsIG9sIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwgb2wgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB1bCBvbCB1bCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwgb2wgdWwsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHVsIHVsIGRpcixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwgdWwgZGlyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB1bCB1bCB1bCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdWwgdWwgdWwge1xuICBsaXN0LXN0eWxlLXR5cGU6IHNxdWFyZTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGFibGUsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRhYmxlIHtcbiAgZGlzcGxheTogdGFibGU7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGNhcHRpb24sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGNhcHRpb24ge1xuICBkaXNwbGF5OiB0YWJsZS1jYXB0aW9uO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBjb2xncm91cCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgY29sZ3JvdXAsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGNvbGdyb3VwW2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGNvbGdyb3VwW2hpZGRlbl0ge1xuICBkaXNwbGF5OiB0YWJsZS1jb2x1bW4tZ3JvdXA7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGNvbCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgY29sLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBjb2xbaGlkZGVuXSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgY29sW2hpZGRlbl0ge1xuICBkaXNwbGF5OiB0YWJsZS1jb2x1bW47XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRoZWFkLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0aGVhZCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGhlYWRbaGlkZGVuXSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGhlYWRbaGlkZGVuXSB7XG4gIGRpc3BsYXk6IHRhYmxlLWhlYWRlci1ncm91cDtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGJvZHksXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRib2R5LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0Ym9keVtoaWRkZW5dLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0Ym9keVtoaWRkZW5dIHtcbiAgZGlzcGxheTogdGFibGUtcm93LWdyb3VwO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0Zm9vdCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGZvb3QsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRmb290W2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRmb290W2hpZGRlbl0ge1xuICBkaXNwbGF5OiB0YWJsZS1mb290ZXItZ3JvdXA7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0cixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdHJbaGlkZGVuXSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdHJbaGlkZGVuXSB7XG4gIGRpc3BsYXk6IHRhYmxlLXJvdztcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRkLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0aCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGgsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRkW2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRkW2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRoW2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRoW2hpZGRlbl0ge1xuICBkaXNwbGF5OiB0YWJsZS1jZWxsO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBjb2xncm91cFtoaWRkZW5dLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBjb2xncm91cFtoaWRkZW5dLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBjb2xbaGlkZGVuXSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgY29sW2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRoZWFkW2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRoZWFkW2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRib2R5W2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRib2R5W2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRmb290W2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRmb290W2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRyW2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRyW2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRkW2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRkW2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRoW2hpZGRlbl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRoW2hpZGRlbl0ge1xuICB2aXNpYmlsaXR5OiBjb2xsYXBzZTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGFibGUsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRhYmxlIHtcbiAgYm94LXNpemluZzogYm9yZGVyLWJveDtcbiAgYm9yZGVyLXNwYWNpbmc6IDJweDtcbiAgYm9yZGVyLWNvbGxhcHNlOiBzZXBhcmF0ZTtcbiAgdGV4dC1pbmRlbnQ6IGluaXRpYWw7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRkLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0ZCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGgsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRoIHtcbiAgcGFkZGluZzogMXB4O1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0aCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGgge1xuICBmb250LXdlaWdodDogYm9sZDtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGhlYWQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRoZWFkLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0Ym9keSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGJvZHksXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRmb290LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0Zm9vdCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGFibGUgPiB0cixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGFibGUgPiB0ciB7XG4gIHZlcnRpY2FsLWFsaWduOiBtaWRkbGU7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0cixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRkLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0aCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGgge1xuICB2ZXJ0aWNhbC1hbGlnbjogaW5oZXJpdDtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGFibGUsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRhYmxlLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0ZCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRoLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0aCB7XG4gIGJvcmRlci1jb2xvcjogZ3JheTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGhlYWQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRoZWFkLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0Ym9keSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGJvZHksXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRmb290LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0Zm9vdCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdHIsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRyIHtcbiAgYm9yZGVyLWNvbG9yOiBpbmhlcml0O1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBpbnB1dCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgaW5wdXQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHNlbGVjdCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgc2VsZWN0LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBvcHRpb24sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG9wdGlvbixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgb3B0Z3JvdXAsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIG9wdGdyb3VwLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBidXR0b24sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGJ1dHRvbixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGV4dGFyZWEsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHRleHRhcmVhLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBrZXlnZW4sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGtleWdlbiB7XG4gIHRleHQtaW5kZW50OiBpbml0aWFsO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCB0ZXh0YXJlYSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgdGV4dGFyZWEge1xuICB3aGl0ZS1zcGFjZTogcHJlLXdyYXA7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGlucHV0W3R5cGU9XCJyYWRpb1wiXSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgaW5wdXRbdHlwZT1cInJhZGlvXCJdLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBpbnB1dFt0eXBlPVwiY2hlY2tib3hcIl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGlucHV0W3R5cGU9XCJjaGVja2JveFwiXSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgaW5wdXRbdHlwZT1cInJlc2V0XCJdLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBpbnB1dFt0eXBlPVwicmVzZXRcIl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGlucHV0W3R5cGU9XCJidXR0b25cIl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGlucHV0W3R5cGU9XCJidXR0b25cIl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGlucHV0W3R5cGU9XCJzdWJtaXRcIl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGlucHV0W3R5cGU9XCJzdWJtaXRcIl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIHNlbGVjdCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgc2VsZWN0LFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBidXR0b24sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGJ1dHRvbiB7XG4gIGJveC1zaXppbmc6IGJvcmRlci1ib3g7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGlucHV0W3R5cGU9XCJidXR0b25cIl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGlucHV0W3R5cGU9XCJidXR0b25cIl0sXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGJ1dHRvbixcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgYnV0dG9uIHtcbiAgcGFkZGluZzogMC4zZW0gMC41ZW07XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWNvbnRlbnQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwIGhyLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBociB7XG4gIGNvbG9yOiBncmF5O1xuICBib3JkZXItc3R5bGU6IGluc2V0O1xuICBib3JkZXItd2lkdGg6IDFweDtcbiAgbWFyZ2luOiAwLjVlbSBhdXRvO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBmaWVsZHNldCxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgZmllbGRzZXQge1xuICBtYXJnaW4tbGVmdDogMnB4O1xuICBtYXJnaW4tcmlnaHQ6IDJweDtcbiAgYm9yZGVyOiBncm9vdmUgMnB4IFRocmVlREZhY2U7XG4gIHBhZGRpbmc6IDAuMzVlbSAwLjYyNWVtIDAuNzVlbTtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgbGVnZW5kLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCBsZWdlbmQge1xuICBwYWRkaW5nLWxlZnQ6IDJweDtcbiAgcGFkZGluZy1yaWdodDogMnB4O1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50ID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgLmxheW91dC1jb250ZW50LW1hcmt1cCA+ICo6Zmlyc3QtY2hpbGQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwID4gKjpmaXJzdC1jaGlsZCB7XG4gIG1hcmdpbi10b3A6IDAgIWltcG9ydGFudDtcbn1cbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtY29udGVudCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIC5sYXlvdXQtY29udGVudC1tYXJrdXAgPiAqOmxhc3QtY2hpbGQsXG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LWh0bWwgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciAubGF5b3V0LWNvbnRlbnQtbWFya3VwID4gKjpsYXN0LWNoaWxkIHtcbiAgbWFyZ2luLWJvdHRvbTogMCAhaW1wb3J0YW50O1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50LmxheW91dC1jb250ZW50LWltYWdlID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgPiAubGF5b3V0LWNvbnRlbnQtbWFya3VwID4gaW1nLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1odG1sLmxheW91dC1jb250ZW50LWltYWdlID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgPiAubGF5b3V0LWNvbnRlbnQtbWFya3VwID4gaW1nLFxuLmxheW91dC1lZGl0b3IgLmxheW91dC1jb250ZW50LmxheW91dC1jb250ZW50LXZlY3Rvci1pbWFnZSA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1jb250ZW50LW1hcmt1cCA+IGltZyxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtaHRtbC5sYXlvdXQtY29udGVudC12ZWN0b3ItaW1hZ2UgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciA+IC5sYXlvdXQtY29udGVudC1tYXJrdXAgPiBpbWcge1xuICBkaXNwbGF5OiBibG9jaztcbiAgd2lkdGg6IDEwMCU7XG4gIG1heC13aWR0aDogMTAwJTtcbiAgaGVpZ2h0OiBhdXRvO1xufVxuLmxheW91dC1lZGl0b3IgLmltZy1yZXNwb25zaXZlLFxuLmxheW91dC1lZGl0b3IgLmltZy1yZXNwb25zaXZlIGltZyB7XG4gIGRpc3BsYXk6IGJsb2NrO1xuICB3aWR0aDogMTAwJTtcbiAgbWF4LXdpZHRoOiAxMDAlO1xuICBoZWlnaHQ6IGF1dG87XG59XG5cbi5sYXlvdXQtZWRpdG9yID4gLmxheW91dC10b29sYm94LXdyYXBwZXIge1xuICBwb3NpdGlvbjogcmVsYXRpdmU7XG4gIG1hcmdpbi1sZWZ0OiAxMnB4O1xuICB3aWR0aDogMjIwcHg7XG4gIGZsZXgtc2hyaW5rOiAwO1xufVxuLmxheW91dC1lZGl0b3IgPiAubGF5b3V0LXRvb2xib3gtd3JhcHBlciA+IC5sYXlvdXQtdG9vbGJveCB7XG4gIGJvcmRlcjogMXB4IHNvbGlkICNlNGU1ZTY7XG4gIHdpZHRoOiAyMjBweDtcbiAgbWluLWhlaWdodDogNDAwcHg7XG4gIHBhZGRpbmc6IDZweDtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2YzZjRmNTtcbn1cbi5sYXlvdXQtZWRpdG9yID4gLmxheW91dC10b29sYm94LXdyYXBwZXIgPiAubGF5b3V0LXRvb2xib3guc3RpY2t5LXRvcCB7XG4gIHBvc2l0aW9uOiBmaXhlZDtcbiAgdG9wOiAwO1xuICBtYXgtaGVpZ2h0OiAxMDAlO1xuICBvdmVyZmxvdy15OiBhdXRvO1xufVxuLmxheW91dC1lZGl0b3IgPiAubGF5b3V0LXRvb2xib3gtd3JhcHBlciA+IC5sYXlvdXQtdG9vbGJveC5zdGlja3ktYm90dG9tIHtcbiAgcG9zaXRpb246IGFic29sdXRlO1xuICBib3R0b206IDA7XG59XG4ubGF5b3V0LWVkaXRvciA+IC5sYXlvdXQtdG9vbGJveC13cmFwcGVyID4gLmxheW91dC10b29sYm94IC5sYXlvdXQtdG9vbGJveC1ncm91cCB7XG4gIG1hcmdpbi10b3A6IDEycHg7XG59XG4ubGF5b3V0LWVkaXRvciA+IC5sYXlvdXQtdG9vbGJveC13cmFwcGVyID4gLmxheW91dC10b29sYm94IC5sYXlvdXQtdG9vbGJveC1ncm91cCAubGF5b3V0LXRvb2xib3gtZ3JvdXAtaGVhZGluZyB7XG4gIGRpc3BsYXk6IGJsb2NrO1xuICBtYXJnaW4tYm90dG9tOiA0cHg7XG4gIHRleHQtZGVjb3JhdGlvbjogbm9uZTtcbn1cbi5sYXlvdXQtZWRpdG9yID4gLmxheW91dC10b29sYm94LXdyYXBwZXIgPiAubGF5b3V0LXRvb2xib3ggLmxheW91dC10b29sYm94LWdyb3VwIC5sYXlvdXQtdG9vbGJveC1ncm91cC1oZWFkaW5nOmJlZm9yZSB7XG4gIGRpc3BsYXk6IGlubGluZS1ibG9jaztcbiAgd2lkdGg6IDEwcHg7XG4gIG1hcmdpbi1yaWdodDogNHB4O1xuICBmb250OiBub3JtYWwgbm9ybWFsIG5vcm1hbCAxNHB4LzEgRm9udEF3ZXNvbWU7XG4gIHRleHQtYWxpZ246IGNlbnRlcjtcbiAgY29udGVudDogXCJcXGYwZDdcIjtcbn1cbi5sYXlvdXQtZWRpdG9yID4gLmxheW91dC10b29sYm94LXdyYXBwZXIgPiAubGF5b3V0LXRvb2xib3ggLmxheW91dC10b29sYm94LWdyb3VwLmNvbGxhcHNlZCAubGF5b3V0LXRvb2xib3gtZ3JvdXAtaGVhZGluZzpiZWZvcmUge1xuICBjb250ZW50OiBcIlxcZjBkYVwiO1xufVxuLmxheW91dC1lZGl0b3IgPiAubGF5b3V0LXRvb2xib3gtd3JhcHBlciA+IC5sYXlvdXQtdG9vbGJveCAubGF5b3V0LXRvb2xib3gtZ3JvdXAuY29sbGFwc2VkIC5sYXlvdXQtdG9vbGJveC1pdGVtcyB7XG4gIGRpc3BsYXk6IG5vbmU7XG59XG4ubGF5b3V0LWVkaXRvciA+IC5sYXlvdXQtdG9vbGJveC13cmFwcGVyID4gLmxheW91dC10b29sYm94IC5sYXlvdXQtdG9vbGJveC1ncm91cCAubGF5b3V0LXRvb2xib3gtc2VjdGlvbiArIC5sYXlvdXQtdG9vbGJveC1zZWN0aW9uIHtcbiAgbWFyZ2luLXRvcDogNHB4O1xufVxuLmxheW91dC1lZGl0b3IgPiAubGF5b3V0LXRvb2xib3gtd3JhcHBlciA+IC5sYXlvdXQtdG9vbGJveCAubGF5b3V0LXRvb2xib3gtZ3JvdXAgLmxheW91dC10b29sYm94LWl0ZW0ge1xuICBib3JkZXI6IDFweCBzb2xpZCAjZTRlNWU2O1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmO1xuICBwYWRkaW5nOiA5cHggMTJweDtcbiAgY3Vyc29yOiBkZWZhdWx0O1xufVxuLmxheW91dC1lZGl0b3IgPiAubGF5b3V0LXRvb2xib3gtd3JhcHBlciA+IC5sYXlvdXQtdG9vbGJveCAubGF5b3V0LXRvb2xib3gtZ3JvdXAgLmxheW91dC10b29sYm94LWl0ZW0gaSB7XG4gIGRpc3BsYXk6IGlubGluZS1ibG9jaztcbiAgd2lkdGg6IDE2cHg7XG4gIGZvbnQ6IG5vcm1hbCBub3JtYWwgbm9ybWFsIDE0cHgvMSBGb250QXdlc29tZTtcbn1cbi5sYXlvdXQtZWRpdG9yID4gLmxheW91dC10b29sYm94LXdyYXBwZXIgPiAubGF5b3V0LXRvb2xib3ggLmxheW91dC10b29sYm94LWdyb3VwIC5sYXlvdXQtdG9vbGJveC1pdGVtICsgLmxheW91dC10b29sYm94LWl0ZW0ge1xuICBtYXJnaW4tdG9wOiA0cHg7XG59XG4ubGF5b3V0LWVkaXRvciA+IC5sYXlvdXQtdG9vbGJveC13cmFwcGVyID4gLmxheW91dC10b29sYm94IC5sYXlvdXQtdG9vbGJveC1ncm91cCArIC5sYXlvdXQtdG9vbGJveC1ncm91cCB7XG4gIG1hcmdpbi10b3A6IDZweDtcbn1cblxuLmxheW91dC1lZGl0b3IgLmxheW91dC1wb3B1cCB7XG4gIGRpc3BsYXk6IG5vbmU7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgbWFyZ2luOiAwO1xuICAtbW96LWJveC1zaGFkb3c6IDNweCAzcHggMTFweCAwIHJnYmEoNTAsIDUwLCA1MCwgMC41KTtcbiAgLXdlYmtpdC1ib3gtc2hhZG93OiAzcHggM3B4IDExcHggMCByZ2JhKDUwLCA1MCwgNTAsIDAuNSk7XG4gIGJveC1zaGFkb3c6IDNweCAzcHggMTFweCAwIHJnYmEoNTAsIDUwLCA1MCwgMC41KTtcbiAgYm9yZGVyOiAxcHggc29saWQgI2U0ZTVlNjtcbiAgcGFkZGluZzogMnB4IDA7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmN2Y3Zjc7XG4gIGxpc3Qtc3R5bGU6IG5vbmU7XG4gIHotaW5kZXg6IDIwO1xuICBjb2xvcjogIzdjN2M3YztcbiAgdGV4dC1hbGlnbjogbGVmdDtcbiAgY3Vyc29yOiBkZWZhdWx0O1xuICB3aGl0ZS1zcGFjZTogbm93cmFwO1xuICBsaW5lLWhlaWdodDogbm9ybWFsO1xuICBtaW4td2lkdGg6IDMwMHB4O1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1wb3B1cC53aWRlIHtcbiAgd2lkdGg6IDYwMHB4O1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1wb3B1cCAubGF5b3V0LXBvcHVwLWZsZXgge1xuICBkaXNwbGF5OiBmbGV4O1xuICBwYWRkaW5nOiAycHggNXB4O1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1wb3B1cCAubGF5b3V0LXBvcHVwLWZsZXggLmxheW91dC1wb3B1cC1jb2x1bW4gKyAubGF5b3V0LXBvcHVwLWNvbHVtbiB7XG4gIG1hcmdpbi1sZWZ0OiA0cHg7XG4gIGJvcmRlci1sZWZ0OiAxcHggc29saWQgcmdiYSgxMjgsIDEyOCwgMTI4LCAwLjE1KTtcbiAgcGFkZGluZy1sZWZ0OiA0cHg7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LXBvcHVwIC5sYXlvdXQtcG9wdXAtaXRlbSB7XG4gIHBhZGRpbmc6IDRweCA2cHg7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LXBvcHVwIC5sYXlvdXQtcG9wdXAtbGFiZWwge1xuICBmb250LXNpemU6IDAuOWVtO1xuICBmb250LXdlaWdodDogYm9sZDtcbiAgY29sb3I6ICM3YzdjN2M7XG59XG4ubGF5b3V0LWVkaXRvciAubGF5b3V0LXBvcHVwIC5sYXlvdXQtcG9wdXAtYWN0aW9uOmhvdmVyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2YzZjRmNTtcbiAgY3Vyc29yOiBwb2ludGVyO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1wb3B1cCAubGF5b3V0LXBvcHVwLWlucHV0IGlucHV0W3R5cGU9J3RleHQnXSxcbi5sYXlvdXQtZWRpdG9yIC5sYXlvdXQtcG9wdXAgLmxheW91dC1wb3B1cC1pbnB1dCB0ZXh0YXJlYSB7XG4gIHdpZHRoOiAxMDAlO1xufVxuLmxheW91dC1lZGl0b3IgLmxheW91dC1wb3B1cCAubGF5b3V0LXBvcHVwLWlucHV0ID4gbGFiZWwge1xuICBkaXNwbGF5OiBibG9jaztcbiAgZm9udC1zaXplOiAwLjllbTtcbn1cbiIsIkBpbXBvcnQgXCJWYXJpYWJsZXMubGVzc1wiO1xyXG5cclxuLmxheW91dC1lZGl0b3Ige1xyXG4gICAgLmxheW91dC1lbGVtZW50IHtcclxuICAgICAgICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcbiAgICAgICAgbWFyZ2luLXRvcDogMDtcclxuICAgICAgICBtYXJnaW4tcmlnaHQ6IDA7XHJcbiAgICAgICAgbWFyZ2luLWJvdHRvbTogMDtcclxuICAgICAgICBwYWRkaW5nOiAwO1xyXG5cclxuICAgICAgICAvLyBXZSBkb24ndCBmdWNrIHdpdGggdGhlIGxlZnQgbWFyZ2luIG9mIGNvbHVtbnMsIGJlY2F1c2UgQm9vdHN0cmFwIHVzZXMgdGhlc2UgdG8gcmVuZGVyIGNvbHVtbiBvZmZzZXRzLlxyXG4gICAgICAgICY6bm90KC5sYXlvdXQtY29sdW1uKSB7XHJcbiAgICAgICAgICAgIG1hcmdpbi1sZWZ0OiAwO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciB7XHJcbiAgICAgICAgICAgID4gLmxheW91dC1wYW5lbCB7XHJcbiAgICAgICAgICAgICAgICBkaXNwbGF5OiBub25lOyAvLyBTaG93biBvbmx5IGluIGFjdGl2ZSBvciBmb2N1c2VkIHN0YXRlcy5cclxuICAgICAgICAgICAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgICAgICAgICAgIG1hcmdpbjogMDtcclxuICAgICAgICAgICAgICAgIHotaW5kZXg6IDIwO1xyXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiAyNXB4O1xyXG4gICAgICAgICAgICAgICAgcGFkZGluZzogMCA2cHg7XHJcbiAgICAgICAgICAgICAgICBsaXN0LXN0eWxlOiBub25lO1xyXG4gICAgICAgICAgICAgICAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcclxuICAgICAgICAgICAgICAgIGxpbmUtaGVpZ2h0OiAyNXB4O1xyXG4gICAgICAgICAgICAgICAgdmVydGljYWwtYWxpZ246IG1pZGRsZTtcclxuXHJcbiAgICAgICAgICAgICAgICA+IC5sYXlvdXQtcGFuZWwtaXRlbSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZGlzcGxheTogaW5saW5lLWJsb2NrO1xyXG4gICAgICAgICAgICAgICAgICAgIGhlaWdodDogMjVweDtcclxuICAgICAgICAgICAgICAgICAgICBwYWRkaW5nOiAxcHggNnB4IDA7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgPiAubGF5b3V0LXBhbmVsLWxhYmVsIHtcclxuICAgICAgICAgICAgICAgICAgICBmb250LXNpemU6IEBmb250LXNpemUgLSAxO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgID4gLmxheW91dC1wYW5lbC1hY3Rpb24ge1xyXG4gICAgICAgICAgICAgICAgICAgIGRpc3BsYXk6IG5vbmU7IC8vIFNob3duIG9ubHkgaW4gZm9jdXNlZCBzdGF0ZS5cclxuICAgICAgICAgICAgICAgICAgICB3aWR0aDogMjhweDtcclxuICAgICAgICAgICAgICAgICAgICBjdXJzb3I6IHBvaW50ZXI7XHJcbiAgICAgICAgICAgICAgICAgICAgdGV4dC1hbGlnbjogY2VudGVyO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICA+IC5sYXlvdXQtcGFuZWwtbWFpbiB7XHJcbiAgICAgICAgICAgICAgICB0b3A6IC0yN3B4O1xyXG4gICAgICAgICAgICAgICAgbGVmdDogLTJweDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyBXaGVuIGRyYWdnaW5nIGZyb20gdG9vbGJveCwgZWxlbWVudHMgd2lsbCBiZSBsaSByYXRoZXIgdGhhbiBkaXYuXHJcbiAgICBsaS5sYXlvdXQtZWxlbWVudCB7XHJcbiAgICAgICAgbGlzdC1zdHlsZTogbm9uZTtcclxuICAgIH1cclxuXHJcbiAgICAmOm5vdCgubGF5b3V0LWVkaXRvci1kcmFnZ2luZykge1xyXG5cclxuICAgICAgICAubGF5b3V0LWVsZW1lbnQtYWN0aXZlLCAubGF5b3V0LWVsZW1lbnQtZm9jdXNlZCB7XHJcbiAgICAgICAgICAgIGJvcmRlci13aWR0aDogMnB4O1xyXG4gICAgICAgICAgICBib3JkZXItc3R5bGU6IHNvbGlkO1xyXG5cclxuICAgICAgICAgICAgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciB7XHJcbiAgICAgICAgICAgICAgICBtYXJnaW46IC0ycHg7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5sYXlvdXQtZWxlbWVudC1hY3RpdmUge1xyXG4gICAgICAgICAgICBAYWN0aXZlLWhpZ2hsaWdodDogZmFkZSgjNjg2ODY4LCAxMCUpO1xyXG5cclxuICAgICAgICAgICAgYm9yZGVyLWNvbG9yOiBAYWN0aXZlLWhpZ2hsaWdodDtcclxuXHJcbiAgICAgICAgICAgID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIgPiAubGF5b3V0LXBhbmVsLW1haW4ge1xyXG4gICAgICAgICAgICAgICAgZGlzcGxheTogYmxvY2s7IC8vIFRvIHJldmVhbC5cclxuICAgICAgICAgICAgICAgIHotaW5kZXg6IDMwO1xyXG4gICAgICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogQGFjdGl2ZS1oaWdobGlnaHQ7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5sYXlvdXQtZWxlbWVudC1mb2N1c2VkIHtcclxuICAgICAgICAgICAgQGZvY3VzZWQtaGlnaGxpZ2h0OiAjNjQ4NzIxO1xyXG4gICAgICAgICAgICBAZm9jdXNlZC10ZXh0OiAjZmVmZWZlO1xyXG5cclxuICAgICAgICAgICAgYm9yZGVyLWNvbG9yOiBAZm9jdXNlZC1oaWdobGlnaHQ7XHJcblxyXG4gICAgICAgICAgICA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1wYW5lbCB7XHJcbiAgICAgICAgICAgICAgICBkaXNwbGF5OiBibG9jazsgLy8gVG8gcmV2ZWFsLlxyXG4gICAgICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogQGZvY3VzZWQtaGlnaGxpZ2h0O1xyXG4gICAgICAgICAgICAgICAgY29sb3I6IEBmb2N1c2VkLXRleHQ7XHJcblxyXG4gICAgICAgICAgICAgICAgPiAubGF5b3V0LXBhbmVsLWFjdGlvbiB7XHJcbiAgICAgICAgICAgICAgICAgICAgZGlzcGxheTogaW5saW5lLWJsb2NrOyAvLyBUbyByZXZlYWwuXHJcbiAgICAgICAgICAgICAgICAgICAgJjpob3ZlciB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IGxpZ2h0ZW4oQGZvY3VzZWQtaGlnaGxpZ2h0LCAxMCUpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgJi5kaXNhYmxlZCB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnNvcjogZGVmYXVsdDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29sb3I6IGZhZGUoQGZvY3VzZWQtdGV4dCwgNDAlKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICY6aG92ZXIge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogQGZvY3VzZWQtaGlnaGxpZ2h0O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAmLmFjdGl2ZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yOiBsaWdodGVuKHNhdHVyYXRlKHNwaW4oQGZvY3VzZWQtaGlnaGxpZ2h0LCAtMTApLCAxMDAlKSwgMzAlKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogbGlnaHRlbihAZm9jdXNlZC1oaWdobGlnaHQsIDUlKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICY6aG92ZXIge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogbGlnaHRlbihAZm9jdXNlZC1oaWdobGlnaHQsIDEwJSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5sYXlvdXQtZWxlbWVudC1zZWxlY3RlZCB7XHJcbiAgICAgICAgICAgIEBzZWxlY3RlZC1oaWdobGlnaHQ6ICM2NDg3MjE7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IGZhZGUoQHNlbGVjdGVkLWhpZ2hsaWdodCwgOCUpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAudWktc29ydGFibGUtcGxhY2Vob2xkZXIge1xyXG4gICAgICAgIGRpc3BsYXk6IG5vbmU7XHJcbiAgICB9XHJcblxyXG4gICAgLmxheW91dC1lbGVtZW50LWRyb3B0YXJnZXQge1xyXG4gICAgICAgIEBkcm9wdGFyZ2V0LWhpZ2hsaWdodDogIzY0ODcyMTtcclxuICAgICAgICBib3gtc2hhZG93OiBpbnNldCAwIDAgMTJweCA2cHggZmFkZShAZHJvcHRhcmdldC1oaWdobGlnaHQsIDUwJSk7XHJcblxyXG4gICAgICAgIC51aS1zb3J0YWJsZS1wbGFjZWhvbGRlciB7XHJcbiAgICAgICAgICAgIGRpc3BsYXk6IGJsb2NrOyAvLyBUbyByZXZlYWwuXHJcbiAgICAgICAgICAgIHZpc2liaWxpdHk6IHZpc2libGUgIWltcG9ydGFudDtcclxuICAgICAgICAgICAgbWluLWhlaWdodDogQGVsZW1lbnQtbWluLWhlaWdodCAtIDJweDtcclxuICAgICAgICAgICAgYm9yZGVyOiAycHggZGFzaGVkIEBkcm9wdGFyZ2V0LWhpZ2hsaWdodCAhaW1wb3J0YW50O1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiBmYWRlKEBkcm9wdGFyZ2V0LWhpZ2hsaWdodCwgMTYlKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQSBDU1MgZml4IGZvciBtZWRpYSBpdGVtIGVsZW1lbnRzLlxyXG4gICAgLm1lZGlhLXRodW1ibmFpbCB7XHJcbiAgICAgICAgaW1nIHtcclxuICAgICAgICAgICAgbWF4LXdpZHRoOjEwMCU7XHJcbiAgICAgICAgICAgIG1heC1oZWlnaHQ6IDEwMCU7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcbiIsIkBpbXBvcnQgXCJWYXJpYWJsZXMubGVzc1wiO1xyXG5cclxuLmxheW91dC1lZGl0b3Ige1xyXG4gICAgLmxheW91dC1jb250YWluZXIge1xyXG5cclxuICAgICAgICA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIHtcclxuXHJcbiAgICAgICAgICAgID4gLmxheW91dC1jb250YWluZXItY2hpbGRyZW4tcGxhY2Vob2xkZXIge1xyXG4gICAgICAgICAgICAgICAgZGlzcGxheTogbm9uZTtcclxuICAgICAgICAgICAgICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgICAgICAgICAgICAgICBtYXJnaW46IEBjb250YWluZXItcGFkZGluZyAtIDFweDtcclxuICAgICAgICAgICAgICAgIG1pbi1oZWlnaHQ6IEBlbGVtZW50LW1pbi1oZWlnaHQ7XHJcbiAgICAgICAgICAgICAgICBib3JkZXI6IDFweCBkYXNoZWQgZmFkZShAZ3JheS10ZXh0LCA0MCUpO1xyXG4gICAgICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogNHB4O1xyXG4gICAgICAgICAgICAgICAgcGFkZGluZzogQGNvbnRhaW5lci1wYWRkaW5nO1xyXG4gICAgICAgICAgICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgICAgICAgICAgICAgICBmb250LXNpemU6IEBmb250LXNpemUgLSAxO1xyXG4gICAgICAgICAgICAgICAgZm9udC1zdHlsZTogaXRhbGljO1xyXG4gICAgICAgICAgICAgICAgb3BhY2l0eTogMC42O1xyXG4gICAgICAgICAgICAgICAgdGV4dC1hbGlnbjogY2VudGVyO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICA+IC5sYXlvdXQtY2hpbGRyZW4ge1xyXG4gICAgICAgICAgICAgICAgcGFkZGluZzogQGNvbnRhaW5lci1wYWRkaW5nO1xyXG5cclxuICAgICAgICAgICAgICAgIC8vIEFsbCBhZGphY2VudCBub24tY29udGFpbmVyIGNoaWxkcmVuIG5lZWQgc29tZSBzcGFjZSBiZXR3ZWVuLi4uXHJcbiAgICAgICAgICAgICAgICA+IC5sYXlvdXQtZWxlbWVudDpub3QoLmxheW91dC1jb250YWluZXIpICsgLmxheW91dC1lbGVtZW50Om5vdCgubGF5b3V0LWNvbnRhaW5lcikge1xyXG4gICAgICAgICAgICAgICAgICAgIG1hcmdpbi10b3A6IEBjb250ZW50LXNwYWNpbmc7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gLi4uIGV4Y2VwdCB3aGVuIGpRdWVyeSBVSSBzb3J0YWJsZSBoZWxwZXIgaXMgdGhlIGZpcnN0IGVsZW1lbnQgKGJlY2F1c2UgdGhhdCBvbmUgaXMgYWJzb2x1dGVseSBwb3NpdGlvbmVkIGFuZCBcImZsb2F0aW5nXCIpLlxyXG4gICAgICAgICAgICAgICAgPiAudWktc29ydGFibGUtaGVscGVyOmZpcnN0LWNoaWxkICsgLmxheW91dC1lbGVtZW50Om5vdCgubGF5b3V0LWNvbnRhaW5lcikge1xyXG4gICAgICAgICAgICAgICAgICAgIG1hcmdpbi10b3A6IDA7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICYubGF5b3V0LWNvbnRhaW5lci1lbXB0eSB7XHJcbiAgICAgICAgICAgICAgICA+IC5sYXlvdXQtY29udGFpbmVyLWNoaWxkcmVuLXBsYWNlaG9sZGVyIHtcclxuICAgICAgICAgICAgICAgICAgICBkaXNwbGF5OiBmbGV4OyAvLyBUbyByZXZlYWwuXHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgPiAubGF5b3V0LWNoaWxkcmVuIHtcclxuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICAgICAgICAgICAgICAgICAgdG9wOiAwO1xyXG4gICAgICAgICAgICAgICAgICAgIHJpZ2h0OiAwO1xyXG4gICAgICAgICAgICAgICAgICAgIGJvdHRvbTogMDtcclxuICAgICAgICAgICAgICAgICAgICBsZWZ0OiAwO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgICY6bm90KC5sYXlvdXQtZWRpdG9yLWRyYWdnaW5nKSB7XHJcbiAgICAgICAgLmxheW91dC1jb250YWluZXIubGF5b3V0LWVsZW1lbnQtZm9jdXNlZCA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1jaGlsZHJlbiB7XHJcbiAgICAgICAgICAgID4gLmxheW91dC1lbGVtZW50Om5vdCgubGF5b3V0LWVsZW1lbnQtYWN0aXZlKSB7XHJcbiAgICAgICAgICAgICAgICBib3JkZXI6IDFweCBkYXNoZWQgZmFkZShAZ3JheS10ZXh0LCA2MCUpO1xyXG5cclxuICAgICAgICAgICAgICAgID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIge1xyXG4gICAgICAgICAgICAgICAgICAgIG1hcmdpbjogLTFweDtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgPiAubGF5b3V0LWNvbnRhaW5lciArIC5sYXlvdXQtY29udGFpbmVyOm5vdCgubGF5b3V0LWVsZW1lbnQtYWN0aXZlKSB7XHJcbiAgICAgICAgICAgICAgICBib3JkZXItdG9wOiAwO1xyXG5cclxuICAgICAgICAgICAgICAgID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIge1xyXG4gICAgICAgICAgICAgICAgICAgIG1hcmdpbi10b3A6IDA7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcbn1cclxuIiwiQGltcG9ydCBcIlZhcmlhYmxlcy5sZXNzXCI7XHJcblxyXG4ubGF5b3V0LWVkaXRvciB7XHJcbiAgICAubGF5b3V0LWNhbnZhcyB7XHJcbiAgICAgICAgI2R1bW15IHsgLy8gT25seSBhZGRlZCBiZWNhdXNlIFdFIGRvZXNuJ3QgY29tcGlsZSBpZiB0aGVyZSBhcmUgbm8gcnVsZXMuXHJcbiAgICAgICAgICAgIGRpc3BsYXk6IG5vbmU7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59IiwiQGltcG9ydCBcIlZhcmlhYmxlcy5sZXNzXCI7XHJcblxyXG4ubGF5b3V0LWVkaXRvciB7XHJcbiAgICAubGF5b3V0LXJvdyB7XHJcbiAgICAgICAgJi5sYXlvdXQtZWxlbWVudC1mb2N1c2VkOm5vdCgubGF5b3V0LWVsZW1lbnQtZHJvcHRhcmdldCkgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciA+IC5sYXlvdXQtY2hpbGRyZW4ge1xyXG4gICAgICAgICAgICA+IC5sYXlvdXQtZWxlbWVudDpub3QoLmxheW91dC1lbGVtZW50LWFjdGl2ZSkge1xyXG4gICAgICAgICAgICAgICAgYm9yZGVyLXRvcDogMXB4IGRhc2hlZCBmYWRlKEBncmF5LXRleHQsIDYwJSkgIWltcG9ydGFudDtcclxuICAgICAgICAgICAgICAgID4gLmxheW91dC1lbGVtZW50LXdyYXBwZXIge1xyXG4gICAgICAgICAgICAgICAgICAgIG1hcmdpbi10b3A6IC0xcHggIWltcG9ydGFudDtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgPiAubGF5b3V0LWVsZW1lbnQgKyAubGF5b3V0LWVsZW1lbnQ6bm90KC5sYXlvdXQtZWxlbWVudC1hY3RpdmUpIHtcclxuICAgICAgICAgICAgICAgIGJvcmRlci1sZWZ0OiAwICFpbXBvcnRhbnQ7XHJcbiAgICAgICAgICAgICAgICA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIHtcclxuICAgICAgICAgICAgICAgICAgICBtYXJnaW4tbGVmdDogMCAhaW1wb3J0YW50O1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59IiwiQGltcG9ydCBcIlZhcmlhYmxlcy5sZXNzXCI7XHJcblxyXG4ubGF5b3V0LWVkaXRvciB7XHJcbiAgICAubGF5b3V0LWNvbHVtbiB7XHJcbiAgICAgICAgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciB7XHJcbiAgICAgICAgICAgID4gLmxheW91dC1jb2x1bW4tcmVzaXplLWJhciB7XHJcbiAgICAgICAgICAgICAgICBkaXNwbGF5OiBub25lO1xyXG4gICAgICAgICAgICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICAgICAgICAgICAgei1pbmRleDogMzA7XHJcbiAgICAgICAgICAgICAgICB0b3A6IDA7XHJcbiAgICAgICAgICAgICAgICB3aWR0aDogMTZweDtcclxuICAgICAgICAgICAgICAgIGhlaWdodDogMTAwJTtcclxuICAgICAgICAgICAgICAgIGN1cnNvcjogY29sLXJlc2l6ZTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgPiAubGF5b3V0LWNvbHVtbi1yZXNpemUtYmFyLWxlZnQge1xyXG4gICAgICAgICAgICAgICAgbGVmdDogLTZweDtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgPiAubGF5b3V0LWNvbHVtbi1yZXNpemUtYmFyLXJpZ2h0IHtcclxuICAgICAgICAgICAgICAgIHJpZ2h0OiAtNnB4O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLmxheW91dC1lbGVtZW50LWZvY3VzZWQgPiAubGF5b3V0LWVsZW1lbnQtd3JhcHBlciA+IC5sYXlvdXQtY29sdW1uLXJlc2l6ZS1iYXIge1xyXG4gICAgICAgICAgICBkaXNwbGF5OiBibG9jaztcclxuICAgICAgICB9XHJcbiAgICB9XHJcbn1cclxuIiwiQGltcG9ydCBcIlZhcmlhYmxlcy5sZXNzXCI7XHJcbkBpbXBvcnQgXCJSZXNldC5sZXNzXCI7XHJcblxyXG4ubGF5b3V0LWVkaXRvciB7XHJcbiAgICAubGF5b3V0LWNvbnRlbnQsIC5sYXlvdXQtaHRtbCB7XHJcbiAgICAgICAgbWluLWhlaWdodDogMWVtO1xyXG5cclxuICAgICAgICA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyIHtcclxuICAgICAgICAgICAgLmxheW91dC1jb250ZW50LW1hcmt1cCB7XHJcblxyXG4gICAgICAgICAgICAgICAgcGFkZGluZzogMnB4O1xyXG4gICAgICAgICAgICAgICAgb3ZlcmZsb3cteDogaGlkZGVuO1xyXG4gICAgICAgICAgICAgICAgbGluZS1oZWlnaHQ6IG5vcm1hbDtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBSZXNldCB0byBIVE1MNSBXM0Mgc3RhbmRhcmQgZGVmYXVsdCBzdHlsaW5nIHdpdGhpbiBjb250ZW50LlxyXG4gICAgICAgICAgICAgICAgLnJlc2V0KCk7XHJcblxyXG4gICAgICAgICAgICAgICAgPiAqOmZpcnN0LWNoaWxkIHtcclxuICAgICAgICAgICAgICAgICAgICBtYXJnaW4tdG9wOiAwICFpbXBvcnRhbnQ7IC8vIEltcG9ydGFudCBiZWNhdXNlIHNpdGUuY3NzIG9mIHRoZSBhZG1pbiB0aGVtZSBzdHlsZXMgaGVhZGluZyBtYXJnaW5zIHdpdGggYSB2ZXJ5IGhpZ2ggc3BlY2lmaWNpdHkuXHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgPiAqOmxhc3QtY2hpbGQge1xyXG4gICAgICAgICAgICAgICAgICAgIG1hcmdpbi1ib3R0b206IDAgIWltcG9ydGFudDtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgJi5sYXlvdXQtY29udGVudC1pbWFnZSwgJi5sYXlvdXQtY29udGVudC12ZWN0b3ItaW1hZ2Uge1xyXG4gICAgICAgICAgICA+IC5sYXlvdXQtZWxlbWVudC13cmFwcGVyID4gLmxheW91dC1jb250ZW50LW1hcmt1cCA+IGltZyB7XHJcbiAgICAgICAgICAgICAgICBkaXNwbGF5OiBibG9jaztcclxuICAgICAgICAgICAgICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgICAgICAgICAgICAgbWF4LXdpZHRoOiAxMDAlO1xyXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBhdXRvO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC5pbWctcmVzcG9uc2l2ZSwgLmltZy1yZXNwb25zaXZlIGltZyB7XHJcbiAgICAgICAgZGlzcGxheTogYmxvY2s7XHJcbiAgICAgICAgd2lkdGg6IDEwMCU7XHJcbiAgICAgICAgbWF4LXdpZHRoOiAxMDAlO1xyXG4gICAgICAgIGhlaWdodDogYXV0bztcclxuICAgIH1cclxufVxyXG4iLCLvu78ucmVzZXQoKSB7XHJcblxyXG4gICAgKiB7XHJcbiAgICAgICAgbWFyZ2luOiAwO1xyXG4gICAgICAgIHBhZGRpbmc6IDA7XHJcbiAgICAgICAgYm94LXNpemluZzogY29udGVudC1ib3g7XHJcbiAgICB9XHJcblxyXG4gICAgYWRkcmVzcywgYmxvY2txdW90ZSwgY2VudGVyLCBkaXYsIGZpZ3VyZSwgZmlnY2FwdGlvbiwgZm9vdGVyLCBmb3JtLFxyXG4gICAgaGVhZGVyLCBociwgbGVnZW5kLCBsaXN0aW5nLCBwLCBwbGFpbnRleHQsIHByZSwgeG1wIHtcclxuICAgICAgICBkaXNwbGF5OiBibG9jaztcclxuICAgIH1cclxuXHJcbiAgICBibG9ja3F1b3RlLCBmaWd1cmUsIGxpc3RpbmcsIHAsIHBsYWludGV4dCwgcHJlLCB4bXAge1xyXG4gICAgICAgIG1hcmdpbi10b3A6IDFlbTtcclxuICAgICAgICBtYXJnaW4tYm90dG9tOiAxZW07XHJcbiAgICB9XHJcblxyXG4gICAgYmxvY2txdW90ZSwgZmlndXJlIHtcclxuICAgICAgICBtYXJnaW4tbGVmdDogNDBweDtcclxuICAgICAgICBtYXJnaW4tcmlnaHQ6IDQwcHg7XHJcbiAgICB9XHJcblxyXG4gICAgYWRkcmVzcyB7XHJcbiAgICAgICAgZm9udC1zdHlsZTogaXRhbGljO1xyXG4gICAgfVxyXG5cclxuICAgIGxpc3RpbmcsIHBsYWludGV4dCwgcHJlLCB4bXAge1xyXG4gICAgICAgIGZvbnQtZmFtaWx5OiBtb25vc3BhY2U7XHJcbiAgICAgICAgd2hpdGUtc3BhY2U6IHByZTtcclxuICAgIH1cclxuXHJcbiAgICBjaXRlLCBkZm4sIGVtLCBpLCB2YXIge1xyXG4gICAgICAgIGZvbnQtc3R5bGU6IGl0YWxpYztcclxuICAgIH1cclxuXHJcbiAgICBiLCBzdHJvbmcge1xyXG4gICAgICAgIGZvbnQtd2VpZ2h0OiBib2xkZXI7XHJcbiAgICB9XHJcblxyXG4gICAgY29kZSwga2JkLCBzYW1wLCB0dCB7XHJcbiAgICAgICAgZm9udC1mYW1pbHk6IG1vbm9zcGFjZTtcclxuICAgIH1cclxuXHJcbiAgICBiaWcge1xyXG4gICAgICAgIGZvbnQtc2l6ZTogbGFyZ2VyO1xyXG4gICAgfVxyXG5cclxuICAgIHNtYWxsIHtcclxuICAgICAgICBmb250LXNpemU6IHNtYWxsZXI7XHJcbiAgICB9XHJcblxyXG4gICAgc3ViIHtcclxuICAgICAgICB2ZXJ0aWNhbC1hbGlnbjogc3ViO1xyXG4gICAgfVxyXG5cclxuICAgIHN1cCB7XHJcbiAgICAgICAgdmVydGljYWwtYWxpZ246IHN1cGVyO1xyXG4gICAgfVxyXG5cclxuICAgIHN1Yiwgc3VwIHtcclxuICAgICAgICBsaW5lLWhlaWdodDogbm9ybWFsO1xyXG4gICAgICAgIGZvbnQtc2l6ZTogc21hbGxlcjtcclxuICAgIH1cclxuXHJcblxyXG4gICAgcnVieSB7XHJcbiAgICAgICAgZGlzcGxheTogcnVieTtcclxuICAgIH1cclxuXHJcbiAgICByYiB7XHJcbiAgICAgICAgZGlzcGxheTogcnVieS1iYXNlO1xyXG4gICAgICAgIHdoaXRlLXNwYWNlOiBub3dyYXA7XHJcbiAgICB9XHJcblxyXG4gICAgcnQge1xyXG4gICAgICAgIGRpc3BsYXk6IHJ1YnktdGV4dDtcclxuICAgICAgICB3aGl0ZS1zcGFjZTogbm93cmFwO1xyXG4gICAgICAgIGZvbnQtc2l6ZTogNTAlO1xyXG4gICAgICAgIGZvbnQtdmFyaWFudC1lYXN0LWFzaWFuOiBydWJ5O1xyXG4gICAgICAgIHRleHQtZW1waGFzaXM6IG5vbmU7XHJcbiAgICB9XHJcblxyXG4gICAgcmJjIHtcclxuICAgICAgICBkaXNwbGF5OiBydWJ5LWJhc2UtY29udGFpbmVyO1xyXG4gICAgfVxyXG5cclxuICAgIHJ0YyB7XHJcbiAgICAgICAgZGlzcGxheTogcnVieS10ZXh0LWNvbnRhaW5lcjtcclxuICAgIH1cclxuXHJcbiAgICBydWJ5LCByYiwgcnQsIHJiYywgcnRjIHtcclxuICAgICAgICB1bmljb2RlLWJpZGk6IGlzb2xhdGU7XHJcbiAgICB9XHJcblxyXG5cclxuICAgIDpsaW5rIHtcclxuICAgICAgICBjb2xvcjogIzAwMDBFRTtcclxuICAgIH1cclxuXHJcbiAgICA6dmlzaXRlZCB7XHJcbiAgICAgICAgY29sb3I6ICM1NTFBOEI7XHJcbiAgICB9XHJcblxyXG4gICAgOmxpbmssIDp2aXNpdGVkIHtcclxuICAgICAgICB0ZXh0LWRlY29yYXRpb246IHVuZGVybGluZTtcclxuICAgIH1cclxuXHJcbiAgICBhOmxpbmtbcmVsfj1oZWxwXSwgYTp2aXNpdGVkW3JlbH49aGVscF0sXHJcbiAgICBhcmVhOmxpbmtbcmVsfj1oZWxwXSwgYXJlYTp2aXNpdGVkW3JlbH49aGVscF0ge1xyXG4gICAgICAgIGN1cnNvcjogaGVscDtcclxuICAgIH1cclxuXHJcbiAgICA6Zm9jdXMge1xyXG4gICAgICAgIG91dGxpbmU6IGF1dG87XHJcbiAgICB9XHJcblxyXG4gICAgbWFyayB7XHJcbiAgICAgICAgYmFja2dyb3VuZDogeWVsbG93O1xyXG4gICAgICAgIGNvbG9yOiBibGFjaztcclxuICAgIH1cclxuICAgIC8qIHRoaXMgY29sb3IgaXMganVzdCBhIHN1Z2dlc3Rpb24gYW5kIGNhbiBiZSBjaGFuZ2VkIGJhc2VkIG9uIGltcGxlbWVudGF0aW9uIGZlZWRiYWNrICovXHJcbiAgICBhYmJyW3RpdGxlXSwgYWNyb255bVt0aXRsZV0ge1xyXG4gICAgICAgIHRleHQtZGVjb3JhdGlvbjogZG90dGVkIHVuZGVybGluZTtcclxuICAgIH1cclxuXHJcbiAgICBpbnMsIHUge1xyXG4gICAgICAgIHRleHQtZGVjb3JhdGlvbjogdW5kZXJsaW5lO1xyXG4gICAgfVxyXG5cclxuICAgIGRlbCwgcywgc3RyaWtlIHtcclxuICAgICAgICB0ZXh0LWRlY29yYXRpb246IGxpbmUtdGhyb3VnaDtcclxuICAgIH1cclxuXHJcbiAgICBibGluayB7XHJcbiAgICAgICAgdGV4dC1kZWNvcmF0aW9uOiBibGluaztcclxuICAgIH1cclxuXHJcbiAgICBxOjpiZWZvcmUge1xyXG4gICAgICAgIGNvbnRlbnQ6IG9wZW4tcXVvdGU7XHJcbiAgICB9XHJcblxyXG4gICAgcTo6YWZ0ZXIge1xyXG4gICAgICAgIGNvbnRlbnQ6IGNsb3NlLXF1b3RlO1xyXG4gICAgfVxyXG5cclxuICAgIGJyIHtcclxuICAgICAgICBjb250ZW50OiAnXFxBJztcclxuICAgICAgICB3aGl0ZS1zcGFjZTogcHJlO1xyXG4gICAgfVxyXG4gICAgLyogdGhpcyBhbHNvIGhhcyBiaWRpIGltcGxpY2F0aW9ucyAqL1xyXG4gICAgbm9iciB7XHJcbiAgICAgICAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcclxuICAgIH1cclxuXHJcbiAgICB3YnIge1xyXG4gICAgICAgIGNvbnRlbnQ6ICdcXDIwMEInO1xyXG4gICAgfVxyXG4gICAgLyogdGhpcyBhbHNvIGhhcyBiaWRpIGltcGxpY2F0aW9ucyAqL1xyXG4gICAgbm9iciB3YnIge1xyXG4gICAgICAgIHdoaXRlLXNwYWNlOiBub3JtYWw7XHJcbiAgICB9XHJcblxyXG4gICAgYXJ0aWNsZSwgYXNpZGUsIGgxLCBoMiwgaDMsIGg0LCBoNSwgaDYsIGhncm91cCwgbmF2LCBzZWN0aW9uIHtcclxuICAgICAgICBkaXNwbGF5OiBibG9jaztcclxuICAgIH1cclxuXHJcbiAgICBoMSB7XHJcbiAgICAgICAgbWFyZ2luLXRvcDogMC42N2VtO1xyXG4gICAgICAgIG1hcmdpbi1ib3R0b206IDAuNjdlbTtcclxuICAgICAgICBmb250LXNpemU6IDIuMDBlbTtcclxuICAgICAgICBmb250LXdlaWdodDogYm9sZDtcclxuICAgIH1cclxuXHJcbiAgICBoMiB7XHJcbiAgICAgICAgbWFyZ2luLXRvcDogMC44M2VtO1xyXG4gICAgICAgIG1hcmdpbi1ib3R0b206IDAuODNlbTtcclxuICAgICAgICBmb250LXNpemU6IDEuNTBlbTtcclxuICAgICAgICBmb250LXdlaWdodDogYm9sZDtcclxuICAgIH1cclxuXHJcbiAgICBoMyB7XHJcbiAgICAgICAgbWFyZ2luLXRvcDogMS4wMGVtO1xyXG4gICAgICAgIG1hcmdpbi1ib3R0b206IDEuMDBlbTtcclxuICAgICAgICBmb250LXNpemU6IDEuMTdlbTtcclxuICAgICAgICBmb250LXdlaWdodDogYm9sZDtcclxuICAgIH1cclxuXHJcbiAgICBoNCB7XHJcbiAgICAgICAgbWFyZ2luLXRvcDogMS4zM2VtO1xyXG4gICAgICAgIG1hcmdpbi1ib3R0b206IDEuMzNlbTtcclxuICAgICAgICBmb250LXNpemU6IDEuMDBlbTtcclxuICAgICAgICBmb250LXdlaWdodDogYm9sZDtcclxuICAgIH1cclxuXHJcbiAgICBoNSB7XHJcbiAgICAgICAgbWFyZ2luLXRvcDogMS42N2VtO1xyXG4gICAgICAgIG1hcmdpbi1ib3R0b206IDEuNjdlbTtcclxuICAgICAgICBmb250LXNpemU6IDAuODNlbTtcclxuICAgICAgICBmb250LXdlaWdodDogYm9sZDtcclxuICAgIH1cclxuXHJcbiAgICBoNiB7XHJcbiAgICAgICAgbWFyZ2luLXRvcDogMi4zM2VtO1xyXG4gICAgICAgIG1hcmdpbi1ib3R0b206IDIuMzNlbTtcclxuICAgICAgICBmb250LXNpemU6IDAuNjdlbTtcclxuICAgICAgICBmb250LXdlaWdodDogYm9sZDtcclxuICAgIH1cclxuXHJcbiAgICBkaXIsIGRkLCBkbCwgZHQsIG9sLCB1bCB7XHJcbiAgICAgICAgZGlzcGxheTogYmxvY2s7XHJcbiAgICB9XHJcblxyXG4gICAgbGkge1xyXG4gICAgICAgIGRpc3BsYXk6IGxpc3QtaXRlbTtcclxuICAgIH1cclxuXHJcbiAgICBkaXIsIGRsLCBvbCwgdWwge1xyXG4gICAgICAgIG1hcmdpbi10b3A6IDFlbTtcclxuICAgICAgICBtYXJnaW4tYm90dG9tOiAxZW07XHJcbiAgICB9XHJcblxyXG4gICAgICAgIGRpciBkaXIsIGRpciBkbCwgZGlyIG9sLCBkaXIgdWwsXHJcbiAgICAgICAgZGwgZGlyLCBkbCBkbCwgZGwgb2wsIGRsIHVsLFxyXG4gICAgICAgIG9sIGRpciwgb2wgZGwsIG9sIG9sLCBvbCB1bCxcclxuICAgICAgICB1bCBkaXIsIHVsIGRsLCB1bCBvbCwgdWwgdWwge1xyXG4gICAgICAgICAgICBtYXJnaW4tdG9wOiAwO1xyXG4gICAgICAgICAgICBtYXJnaW4tYm90dG9tOiAwO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICBkZCB7XHJcbiAgICAgICAgbWFyZ2luLWxlZnQ6IDQwcHg7XHJcbiAgICB9XHJcbiAgICAvKiBMVFItc3BlY2lmaWM6IHVzZSAnbWFyZ2luLXJpZ2h0JyBmb3IgcnRsIGVsZW1lbnRzICovXHJcbiAgICBkaXIsIG9sLCB1bCB7XHJcbiAgICAgICAgcGFkZGluZy1sZWZ0OiA0MHB4O1xyXG4gICAgfVxyXG4gICAgLyogTFRSLXNwZWNpZmljOiB1c2UgJ3BhZGRpbmctcmlnaHQnIGZvciBydGwgZWxlbWVudHMgKi9cclxuICAgIG9sIHtcclxuICAgICAgICBsaXN0LXN0eWxlLXR5cGU6IGRlY2ltYWw7XHJcbiAgICB9XHJcblxyXG4gICAgZGlyLCB1bCB7XHJcbiAgICAgICAgbGlzdC1zdHlsZS10eXBlOiBkaXNjO1xyXG4gICAgfVxyXG5cclxuICAgICAgICBkaXIgZGlyLCBkaXIgdWwsXHJcbiAgICAgICAgb2wgZGlyLCBvbCB1bCxcclxuICAgICAgICB1bCBkaXIsIHVsIHVsIHtcclxuICAgICAgICAgICAgbGlzdC1zdHlsZS10eXBlOiBjaXJjbGU7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgZGlyIGRpciBkaXIsIGRpciBkaXIgdWwsXHJcbiAgICAgICAgICAgIGRpciBvbCBkaXIsIGRpciBvbCB1bCxcclxuICAgICAgICAgICAgZGlyIHVsIGRpciwgZGlyIHVsIHVsLFxyXG4gICAgICAgICAgICBvbCBkaXIgZGlyLCBvbCBkaXIgdWwsXHJcbiAgICAgICAgICAgIG9sIG9sIGRpciwgb2wgb2wgdWwsXHJcbiAgICAgICAgICAgIG9sIHVsIGRpciwgb2wgdWwgdWwsXHJcbiAgICAgICAgICAgIHVsIGRpciBkaXIsIHVsIGRpciB1bCxcclxuICAgICAgICAgICAgdWwgb2wgZGlyLCB1bCBvbCB1bCxcclxuICAgICAgICAgICAgdWwgdWwgZGlyLCB1bCB1bCB1bCB7XHJcbiAgICAgICAgICAgICAgICBsaXN0LXN0eWxlLXR5cGU6IHNxdWFyZTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgIHRhYmxlIHtcclxuICAgICAgICBkaXNwbGF5OiB0YWJsZTtcclxuICAgIH1cclxuXHJcbiAgICBjYXB0aW9uIHtcclxuICAgICAgICBkaXNwbGF5OiB0YWJsZS1jYXB0aW9uO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbGdyb3VwLCBjb2xncm91cFtoaWRkZW5dIHtcclxuICAgICAgICBkaXNwbGF5OiB0YWJsZS1jb2x1bW4tZ3JvdXA7XHJcbiAgICB9XHJcblxyXG4gICAgY29sLCBjb2xbaGlkZGVuXSB7XHJcbiAgICAgICAgZGlzcGxheTogdGFibGUtY29sdW1uO1xyXG4gICAgfVxyXG5cclxuICAgIHRoZWFkLCB0aGVhZFtoaWRkZW5dIHtcclxuICAgICAgICBkaXNwbGF5OiB0YWJsZS1oZWFkZXItZ3JvdXA7XHJcbiAgICB9XHJcblxyXG4gICAgdGJvZHksIHRib2R5W2hpZGRlbl0ge1xyXG4gICAgICAgIGRpc3BsYXk6IHRhYmxlLXJvdy1ncm91cDtcclxuICAgIH1cclxuXHJcbiAgICB0Zm9vdCwgdGZvb3RbaGlkZGVuXSB7XHJcbiAgICAgICAgZGlzcGxheTogdGFibGUtZm9vdGVyLWdyb3VwO1xyXG4gICAgfVxyXG5cclxuICAgIHRyLCB0cltoaWRkZW5dIHtcclxuICAgICAgICBkaXNwbGF5OiB0YWJsZS1yb3c7XHJcbiAgICB9XHJcblxyXG4gICAgdGQsIHRoLCB0ZFtoaWRkZW5dLCB0aFtoaWRkZW5dIHtcclxuICAgICAgICBkaXNwbGF5OiB0YWJsZS1jZWxsO1xyXG4gICAgfVxyXG5cclxuICAgICAgICBjb2xncm91cFtoaWRkZW5dLCBjb2xbaGlkZGVuXSwgdGhlYWRbaGlkZGVuXSwgdGJvZHlbaGlkZGVuXSxcclxuICAgICAgICB0Zm9vdFtoaWRkZW5dLCB0cltoaWRkZW5dLCB0ZFtoaWRkZW5dLCB0aFtoaWRkZW5dIHtcclxuICAgICAgICAgICAgdmlzaWJpbGl0eTogY29sbGFwc2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgIHRhYmxlIHtcclxuICAgICAgICBib3gtc2l6aW5nOiBib3JkZXItYm94O1xyXG4gICAgICAgIGJvcmRlci1zcGFjaW5nOiAycHg7XHJcbiAgICAgICAgYm9yZGVyLWNvbGxhcHNlOiBzZXBhcmF0ZTtcclxuICAgICAgICB0ZXh0LWluZGVudDogaW5pdGlhbDtcclxuICAgIH1cclxuXHJcbiAgICB0ZCwgdGgge1xyXG4gICAgICAgIHBhZGRpbmc6IDFweDtcclxuICAgIH1cclxuXHJcbiAgICB0aCB7XHJcbiAgICAgICAgZm9udC13ZWlnaHQ6IGJvbGQ7XHJcbiAgICB9XHJcblxyXG4gICAgdGhlYWQsIHRib2R5LCB0Zm9vdCwgdGFibGUgPiB0ciB7XHJcbiAgICAgICAgdmVydGljYWwtYWxpZ246IG1pZGRsZTtcclxuICAgIH1cclxuXHJcbiAgICB0ciwgdGQsIHRoIHtcclxuICAgICAgICB2ZXJ0aWNhbC1hbGlnbjogaW5oZXJpdDtcclxuICAgIH1cclxuXHJcbiAgICB0YWJsZSwgdGQsIHRoIHtcclxuICAgICAgICBib3JkZXItY29sb3I6IGdyYXk7XHJcbiAgICB9XHJcblxyXG4gICAgdGhlYWQsIHRib2R5LCB0Zm9vdCwgdHIge1xyXG4gICAgICAgIGJvcmRlci1jb2xvcjogaW5oZXJpdDtcclxuICAgIH1cclxuICAgIC8qdGFibGVbcnVsZXM9bm9uZSBpXSwgdGFibGVbcnVsZXM9Z3JvdXBzIGldLCB0YWJsZVtydWxlcz1yb3dzIGldLFxyXG50YWJsZVtydWxlcz1jb2xzIGldLCB0YWJsZVtydWxlcz1hbGwgaV0sIHRhYmxlW2ZyYW1lPXZvaWQgaV0sXHJcbnRhYmxlW2ZyYW1lPWFib3ZlIGldLCB0YWJsZVtmcmFtZT1iZWxvdyBpXSwgdGFibGVbZnJhbWU9aHNpZGVzIGldLFxyXG50YWJsZVtmcmFtZT1saHMgaV0sIHRhYmxlW2ZyYW1lPXJocyBpXSwgdGFibGVbZnJhbWU9dnNpZGVzIGldLFxyXG50YWJsZVtmcmFtZT1ib3ggaV0sIHRhYmxlW2ZyYW1lPWJvcmRlciBpXSxcclxudGFibGVbcnVsZXM9bm9uZSBpXSA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPW5vbmUgaV0gPiB0ciA+IHRoLFxyXG50YWJsZVtydWxlcz1ncm91cHMgaV0gPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1ncm91cHMgaV0gPiB0ciA+IHRoLFxyXG50YWJsZVtydWxlcz1yb3dzIGldID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9cm93cyBpXSA+IHRyID4gdGgsXHJcbnRhYmxlW3J1bGVzPWNvbHMgaV0gPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1jb2xzIGldID4gdHIgPiB0aCxcclxudGFibGVbcnVsZXM9YWxsIGldID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9YWxsIGldID4gdHIgPiB0aCxcclxudGFibGVbcnVsZXM9bm9uZSBpXSA+IHRoZWFkID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9bm9uZSBpXSA+IHRoZWFkID4gdHIgPiB0aCxcclxudGFibGVbcnVsZXM9Z3JvdXBzIGldID4gdGhlYWQgPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1ncm91cHMgaV0gPiB0aGVhZCA+IHRyID4gdGgsXHJcbnRhYmxlW3J1bGVzPXJvd3MgaV0gPiB0aGVhZCA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPXJvd3MgaV0gPiB0aGVhZCA+IHRyID4gdGgsXHJcbnRhYmxlW3J1bGVzPWNvbHMgaV0gPiB0aGVhZCA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPWNvbHMgaV0gPiB0aGVhZCA+IHRyID4gdGgsXHJcbnRhYmxlW3J1bGVzPWFsbCBpXSA+IHRoZWFkID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9YWxsIGldID4gdGhlYWQgPiB0ciA+IHRoLFxyXG50YWJsZVtydWxlcz1ub25lIGldID4gdGJvZHkgPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1ub25lIGldID4gdGJvZHkgPiB0ciA+IHRoLFxyXG50YWJsZVtydWxlcz1ncm91cHMgaV0gPiB0Ym9keSA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPWdyb3VwcyBpXSA+IHRib2R5ID4gdHIgPiB0aCxcclxudGFibGVbcnVsZXM9cm93cyBpXSA+IHRib2R5ID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9cm93cyBpXSA+IHRib2R5ID4gdHIgPiB0aCxcclxudGFibGVbcnVsZXM9Y29scyBpXSA+IHRib2R5ID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9Y29scyBpXSA+IHRib2R5ID4gdHIgPiB0aCxcclxudGFibGVbcnVsZXM9YWxsIGldID4gdGJvZHkgPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1hbGwgaV0gPiB0Ym9keSA+IHRyID4gdGgsXHJcbnRhYmxlW3J1bGVzPW5vbmUgaV0gPiB0Zm9vdCA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPW5vbmUgaV0gPiB0Zm9vdCA+IHRyID4gdGgsXHJcbnRhYmxlW3J1bGVzPWdyb3VwcyBpXSA+IHRmb290ID4gdHIgPiB0ZCwgdGFibGVbcnVsZXM9Z3JvdXBzIGldID4gdGZvb3QgPiB0ciA+IHRoLFxyXG50YWJsZVtydWxlcz1yb3dzIGldID4gdGZvb3QgPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1yb3dzIGldID4gdGZvb3QgPiB0ciA+IHRoLFxyXG50YWJsZVtydWxlcz1jb2xzIGldID4gdGZvb3QgPiB0ciA+IHRkLCB0YWJsZVtydWxlcz1jb2xzIGldID4gdGZvb3QgPiB0ciA+IHRoLFxyXG50YWJsZVtydWxlcz1hbGwgaV0gPiB0Zm9vdCA+IHRyID4gdGQsIHRhYmxlW3J1bGVzPWFsbCBpXSA+IHRmb290ID4gdHIgPiB0aCB7XHJcbiAgICBib3JkZXItY29sb3I6IGJsYWNrO1xyXG59Ki9cclxuICAgIGlucHV0LCBzZWxlY3QsIG9wdGlvbiwgb3B0Z3JvdXAsIGJ1dHRvbiwgdGV4dGFyZWEsIGtleWdlbiB7XHJcbiAgICAgICAgdGV4dC1pbmRlbnQ6IGluaXRpYWw7XHJcbiAgICB9XHJcblxyXG4gICAgdGV4dGFyZWEge1xyXG4gICAgICAgIHdoaXRlLXNwYWNlOiBwcmUtd3JhcDtcclxuICAgIH1cclxuXHJcbiAgICBpbnB1dFt0eXBlPVwicmFkaW9cIl0sIGlucHV0W3R5cGU9XCJjaGVja2JveFwiXSwgaW5wdXRbdHlwZT1cInJlc2V0XCJdLCBpbnB1dFt0eXBlPVwiYnV0dG9uXCJdLFxyXG4gICAgaW5wdXRbdHlwZT1cInN1Ym1pdFwiXSwgc2VsZWN0LCBidXR0b24ge1xyXG4gICAgICAgIGJveC1zaXppbmc6IGJvcmRlci1ib3g7XHJcbiAgICB9XHJcblxyXG4gICAgaW5wdXRbdHlwZT1cImJ1dHRvblwiXSwgYnV0dG9uIHtcclxuICAgICAgICBwYWRkaW5nOiAwLjNlbSAwLjVlbTtcclxuICAgIH1cclxuXHJcbiAgICBociB7XHJcbiAgICAgICAgY29sb3I6IGdyYXk7XHJcbiAgICAgICAgYm9yZGVyLXN0eWxlOiBpbnNldDtcclxuICAgICAgICBib3JkZXItd2lkdGg6IDFweDtcclxuICAgICAgICBtYXJnaW46IDAuNWVtIGF1dG87XHJcbiAgICB9XHJcblxyXG4gICAgZmllbGRzZXQge1xyXG4gICAgICAgIG1hcmdpbi1sZWZ0OiAycHg7XHJcbiAgICAgICAgbWFyZ2luLXJpZ2h0OiAycHg7XHJcbiAgICAgICAgYm9yZGVyOiBncm9vdmUgMnB4IFRocmVlREZhY2U7XHJcbiAgICAgICAgcGFkZGluZzogMC4zNWVtIDAuNjI1ZW0gMC43NWVtO1xyXG4gICAgfVxyXG5cclxuICAgIGxlZ2VuZCB7XHJcbiAgICAgICAgcGFkZGluZy1sZWZ0OiAycHg7XHJcbiAgICAgICAgcGFkZGluZy1yaWdodDogMnB4O1xyXG4gICAgfVxyXG59XHJcbiIsIkBpbXBvcnQgXCJWYXJpYWJsZXMubGVzc1wiO1xyXG5cclxuLmxheW91dC1lZGl0b3Ige1xyXG4gICAgPiAubGF5b3V0LXRvb2xib3gtd3JhcHBlciB7XHJcbiAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG4gICAgICAgIG1hcmdpbi1sZWZ0OiBAY29udGFpbmVyLXBhZGRpbmc7XHJcbiAgICAgICAgd2lkdGg6IDIyMHB4O1xyXG4gICAgICAgIGZsZXgtc2hyaW5rOiAwO1xyXG5cclxuICAgICAgICA+IC5sYXlvdXQtdG9vbGJveCB7XHJcbiAgICAgICAgICAgIGJvcmRlcjogMXB4IHNvbGlkIEBncmF5LWJvcmRlcjtcclxuICAgICAgICAgICAgd2lkdGg6IDIyMHB4O1xyXG4gICAgICAgICAgICBtaW4taGVpZ2h0OiA0MDBweDtcclxuICAgICAgICAgICAgcGFkZGluZzogQGNvbnRhaW5lci1wYWRkaW5nIC8gMjtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogQGdyYXktYmc7XHJcblxyXG4gICAgICAgICAgICAmLnN0aWNreS10b3Age1xyXG4gICAgICAgICAgICAgICAgcG9zaXRpb246IGZpeGVkO1xyXG4gICAgICAgICAgICAgICAgdG9wOiAwO1xyXG4gICAgICAgICAgICAgICAgbWF4LWhlaWdodDogMTAwJTtcclxuICAgICAgICAgICAgICAgIG92ZXJmbG93LXk6IGF1dG87XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICYuc3RpY2t5LWJvdHRvbSB7XHJcbiAgICAgICAgICAgICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICAgICAgICAgICAgICBib3R0b206IDA7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC5sYXlvdXQtdG9vbGJveC1ncm91cCB7XHJcbiAgICAgICAgICAgICAgICBtYXJnaW4tdG9wOiBAY29udGFpbmVyLXBhZGRpbmc7XHJcblxyXG4gICAgICAgICAgICAgICAgLmxheW91dC10b29sYm94LWdyb3VwLWhlYWRpbmcge1xyXG4gICAgICAgICAgICAgICAgICAgIGRpc3BsYXk6IGJsb2NrO1xyXG4gICAgICAgICAgICAgICAgICAgIG1hcmdpbi1ib3R0b206IEBjb250YWluZXItcGFkZGluZyAvIDM7XHJcbiAgICAgICAgICAgICAgICAgICAgdGV4dC1kZWNvcmF0aW9uOiBub25lO1xyXG4gICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAgICAgJjpiZWZvcmUge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiAxMHB4O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXJnaW4tcmlnaHQ6IEBjb250YWluZXItcGFkZGluZyAvIDM7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvbnQ6IG5vcm1hbCBub3JtYWwgbm9ybWFsIDE0cHgvMSBGb250QXdlc29tZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGV4dC1hbGlnbjogY2VudGVyO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb250ZW50OiBcIlxcZjBkN1wiO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAmLmNvbGxhcHNlZCB7XHJcbiAgICAgICAgICAgICAgICAgICAgLmxheW91dC10b29sYm94LWdyb3VwLWhlYWRpbmc6YmVmb3JlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudDogXCJcXGYwZGFcIjtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIC5sYXlvdXQtdG9vbGJveC1pdGVtcyB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BsYXk6IG5vbmU7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIC5sYXlvdXQtdG9vbGJveC1zZWN0aW9uICsgLmxheW91dC10b29sYm94LXNlY3Rpb24ge1xyXG4gICAgICAgICAgICAgICAgICAgIG1hcmdpbi10b3A6IEBjb250YWluZXItcGFkZGluZyAvIDM7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgLmxheW91dC10b29sYm94LWl0ZW0ge1xyXG4gICAgICAgICAgICAgICAgICAgIGJvcmRlcjogMXB4IHNvbGlkIEBncmF5LWJvcmRlcjtcclxuICAgICAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmO1xyXG4gICAgICAgICAgICAgICAgICAgIHBhZGRpbmc6IChAY29udGFpbmVyLXBhZGRpbmcgLSAzKSBAY29udGFpbmVyLXBhZGRpbmc7XHJcbiAgICAgICAgICAgICAgICAgICAgY3Vyc29yOiBkZWZhdWx0O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGxheTogaW5saW5lLWJsb2NrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogMTZweDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZm9udDogbm9ybWFsIG5vcm1hbCBub3JtYWwgMTRweC8xIEZvbnRBd2Vzb21lO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgKyAubGF5b3V0LXRvb2xib3gtaXRlbSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hcmdpbi10b3A6IEBjb250YWluZXItcGFkZGluZyAvIDM7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICsgLmxheW91dC10b29sYm94LWdyb3VwIHtcclxuICAgICAgICAgICAgICAgICAgICBtYXJnaW4tdG9wOiBAY29udGFpbmVyLXBhZGRpbmcgLyAyO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcbiIsIkBpbXBvcnQgXCJWYXJpYWJsZXMubGVzc1wiO1xyXG5cclxuLmxheW91dC1lZGl0b3Ige1xyXG4gICAgLmxheW91dC1wb3B1cCB7XHJcbiAgICAgICAgZGlzcGxheTogbm9uZTsgLy8gU2hvd24gb25seSBpbiBhY3RpdmUgb3IgZm9jdXNlZCBzdGF0ZXMuXHJcbiAgICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICAgIG1hcmdpbjogMDtcclxuICAgICAgICAtbW96LWJveC1zaGFkb3c6IDNweCAzcHggMTFweCAwIHJnYmEoNTAsIDUwLCA1MCwgMC41KTtcclxuICAgICAgICAtd2Via2l0LWJveC1zaGFkb3c6IDNweCAzcHggMTFweCAwIHJnYmEoNTAsIDUwLCA1MCwgMC41KTtcclxuICAgICAgICBib3gtc2hhZG93OiAzcHggM3B4IDExcHggMCByZ2JhKDUwLCA1MCwgNTAsIDAuNSk7XHJcbiAgICAgICAgYm9yZGVyOiAxcHggc29saWQgQGdyYXktYm9yZGVyO1xyXG4gICAgICAgIHBhZGRpbmc6IDJweCAwO1xyXG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNmN2Y3Zjc7XHJcbiAgICAgICAgbGlzdC1zdHlsZTogbm9uZTtcclxuICAgICAgICB6LWluZGV4OiAyMDtcclxuICAgICAgICBjb2xvcjogQGdyYXktdGV4dDtcclxuICAgICAgICB0ZXh0LWFsaWduOiBsZWZ0O1xyXG4gICAgICAgIGN1cnNvcjogZGVmYXVsdDtcclxuICAgICAgICB3aGl0ZS1zcGFjZTogbm93cmFwO1xyXG4gICAgICAgIGxpbmUtaGVpZ2h0OiBub3JtYWw7XHJcbiAgICAgICAgbWluLXdpZHRoOiAzMDBweDtcclxuXHJcbiAgICAgICAgJi53aWRlIHtcclxuICAgICAgICAgICAgd2lkdGg6IDYwMHB4O1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLmxheW91dC1wb3B1cC1mbGV4IHtcclxuICAgICAgICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgICAgICAgcGFkZGluZzogMnB4IDVweDtcclxuXHJcbiAgICAgICAgICAgIC5sYXlvdXQtcG9wdXAtY29sdW1uICsgLmxheW91dC1wb3B1cC1jb2x1bW4ge1xyXG4gICAgICAgICAgICAgICAgbWFyZ2luLWxlZnQ6IDRweDtcclxuICAgICAgICAgICAgICAgIGJvcmRlci1sZWZ0OiAxcHggc29saWQgZmFkZShncmF5LCAxNSUpO1xyXG4gICAgICAgICAgICAgICAgcGFkZGluZy1sZWZ0OiA0cHg7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5sYXlvdXQtcG9wdXAtaXRlbSB7XHJcbiAgICAgICAgICAgIHBhZGRpbmc6IDRweCA2cHg7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAubGF5b3V0LXBvcHVwLWxhYmVsIHtcclxuICAgICAgICAgICAgZm9udC1zaXplOiAwLjllbTtcclxuICAgICAgICAgICAgZm9udC13ZWlnaHQ6IGJvbGQ7XHJcbiAgICAgICAgICAgIGNvbG9yOiBAZ3JheS10ZXh0O1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLmxheW91dC1wb3B1cC1hY3Rpb246aG92ZXIge1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiBAZ3JheS1iZztcclxuICAgICAgICAgICAgY3Vyc29yOiBwb2ludGVyO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLmxheW91dC1wb3B1cC1pbnB1dCB7XHJcbiAgICAgICAgICAgIGlucHV0W3R5cGU9J3RleHQnXSwgdGV4dGFyZWEge1xyXG4gICAgICAgICAgICAgICAgd2lkdGg6IDEwMCU7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgID4gbGFiZWwge1xyXG4gICAgICAgICAgICAgICAgZGlzcGxheTogYmxvY2s7XHJcbiAgICAgICAgICAgICAgICBmb250LXNpemU6IDAuOWVtO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcbiJdLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== */ \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Views/EditorTemplates/LayoutEditor.cshtml b/src/Orchard.Web/Modules/Orchard.Layouts/Views/EditorTemplates/LayoutEditor.cshtml index 0d928d4f7..816ebed41 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Views/EditorTemplates/LayoutEditor.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Views/EditorTemplates/LayoutEditor.cshtml @@ -17,7 +17,6 @@ Script.Require("jQueryUI_Resizable"); Script.Require("jQueryUI_Position"); Script.Require("jQueryUI_Dialog"); - Script.Require("TinyMce"); Script.Require("Layouts.LayoutEditor"); Script.Include("jquery.deserialize.js"); diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Views/Elements/ContentItem.Design.cshtml b/src/Orchard.Web/Modules/Orchard.Layouts/Views/Elements/ContentItem.Design.cshtml index c732cef6b..d84b1abe7 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Views/Elements/ContentItem.Design.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Views/Elements/ContentItem.Design.cshtml @@ -2,7 +2,7 @@ @foreach (var contentItemShape in Model.ContentItems) { var contentItem = (ContentItem)contentItemShape.ContentItem; var displayTextHtmlString = Html.ItemDisplayText(contentItem); - var displayText = displayTextHtmlString != null ? displayTextHtmlString.ToString() : T("-").ToString(); + var displayText = displayTextHtmlString != null ? (IHtmlString)displayTextHtmlString : T("-");
@displayText
diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Views/LayoutEditor.Template.Toolbox.cshtml b/src/Orchard.Web/Modules/Orchard.Layouts/Views/LayoutEditor.Template.Toolbox.cshtml index 7ccbcd2cd..05374bd38 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Views/LayoutEditor.Template.Toolbox.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Views/LayoutEditor.Template.Toolbox.cshtml @@ -1,10 +1,6 @@ 
- -
    +
    • @T("Layout")
        diff --git a/src/Orchard.Web/Modules/Orchard.Lists/Module.txt b/src/Orchard.Web/Modules/Orchard.Lists/Module.txt index 010fa8caa..be8fc36a6 100644 --- a/src/Orchard.Web/Modules/Orchard.Lists/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Lists/Module.txt @@ -2,7 +2,7 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: Introduces a preconfigured container-enabled content type. FeatureDescription: A basic container-enabled content type. diff --git a/src/Orchard.Web/Modules/Orchard.Lists/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Lists/Properties/AssemblyInfo.cs index e6df16ec3..c729a5b99 100644 --- a/src/Orchard.Web/Modules/Orchard.Lists/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Lists/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.Lists/Views/Parts.Container.Manage.cshtml b/src/Orchard.Web/Modules/Orchard.Lists/Views/Parts.Container.Manage.cshtml index 10a69f805..636dff05e 100644 --- a/src/Orchard.Web/Modules/Orchard.Lists/Views/Parts.Container.Manage.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Lists/Views/Parts.Container.Manage.cshtml @@ -5,17 +5,17 @@ }

        - @Html.ActionLink(T("{0} Properties", (string)Model.ContainerDisplayName).ToString(), "Edit", new { Area = "Contents", Id = (int)Model.ContainerId, ReturnUrl = Html.ViewContext.HttpContext.Request.RawUrl }) + @Html.ActionLink(T("{0} Properties", (string)Model.ContainerDisplayName), "Edit", new { Area = "Contents", Id = (int)Model.ContainerId, ReturnUrl = Html.ViewContext.HttpContext.Request.RawUrl })

        @if (itemContentTypes.Any()) { foreach (var contentType in itemContentTypes) { - @Html.ActionLink(T("New {0}", contentType.DisplayName).ToString(), "Create", "Admin", new { area = "Contents", id = contentType.Name, containerId }, new { @class = "button primaryAction create-content" }) + @Html.ActionLink(T("New {0}", contentType.DisplayName), "Create", "Admin", new { area = "Contents", id = contentType.Name, containerId }, new { @class = "button primaryAction create-content" }) } } else { - @Html.ActionLink(T("New Content").ToString(), "Create", "Admin", new { area = "Contents", containerId }, new { @class = "button primaryAction create-content" }) + @Html.ActionLink(T("New Content"), "Create", "Admin", new { area = "Contents", containerId }, new { @class = "button primaryAction create-content" }) } @T("Choose Items")
        diff --git a/src/Orchard.Web/Modules/Orchard.Localization/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Localization/Controllers/AdminController.cs index b0e7726dd..597c39439 100644 --- a/src/Orchard.Web/Modules/Orchard.Localization/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Localization/Controllers/AdminController.cs @@ -53,10 +53,7 @@ namespace Orchard.Localization.Controllers { var contentItemTranslation = _contentManager.New(masterContentItem.ContentType); contentItemTranslation.MasterContentItem = masterContentItem; - // build the editor using the master content item so that - // the form is pre-populated with the original values - - var content = _contentManager.BuildEditor(masterContentItem); + var content = _contentManager.BuildEditor(contentItemTranslation); return View(content); } diff --git a/src/Orchard.Web/Modules/Orchard.Localization/Drivers/LocalizationPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Localization/Drivers/LocalizationPartDriver.cs index b6854a51d..2f59e3172 100644 --- a/src/Orchard.Web/Modules/Orchard.Localization/Drivers/LocalizationPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Localization/Drivers/LocalizationPartDriver.cs @@ -108,16 +108,19 @@ namespace Orchard.Localization.Drivers { } protected override void Importing(LocalizationPart part, ContentManagement.Handlers.ImportContentContext context) { - var masterContentItem = context.Attribute(part.PartDefinition.Name, "MasterContentItem"); - if (masterContentItem != null) { + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; + } + + context.ImportAttribute(part.PartDefinition.Name, "MasterContentItem", masterContentItem => { var contentItem = context.GetItemFromSession(masterContentItem); if (contentItem != null) { part.MasterContentItem = contentItem; } - } + }); - var culture = context.Attribute(part.PartDefinition.Name, "Culture"); - if (culture != null) { + context.ImportAttribute(part.PartDefinition.Name, "Culture", culture => { var targetCulture = _cultureManager.GetCultureByName(culture); // Add Culture. if (targetCulture == null && _cultureManager.IsValidCulture(culture)) { @@ -125,7 +128,7 @@ namespace Orchard.Localization.Drivers { targetCulture = _cultureManager.GetCultureByName(culture); } part.Culture = targetCulture; - } + }); } protected override void Exporting(LocalizationPart part, ContentManagement.Handlers.ExportContentContext context) { diff --git a/src/Orchard.Web/Modules/Orchard.Localization/Module.txt b/src/Orchard.Web/Modules/Orchard.Localization/Module.txt index 7e20add53..b019b5be1 100644 --- a/src/Orchard.Web/Modules/Orchard.Localization/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Localization/Module.txt @@ -2,7 +2,7 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: The localization module enables the localization of content items. Features: diff --git a/src/Orchard.Web/Modules/Orchard.Localization/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Localization/Properties/AssemblyInfo.cs index 08fde37af..cd3959a32 100644 --- a/src/Orchard.Web/Modules/Orchard.Localization/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Localization/Properties/AssemblyInfo.cs @@ -31,6 +31,6 @@ using System.Security; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.Media/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Media/Properties/AssemblyInfo.cs index 8d33e7cfb..b2b27b311 100644 --- a/src/Orchard.Web/Modules/Orchard.Media/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Media/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/AdminMenu.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/AdminMenu.cs index d83aff5e5..82c32328b 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/AdminMenu.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/AdminMenu.cs @@ -15,7 +15,7 @@ namespace Orchard.MediaLibrary { builder.AddImageSet("media-library") .Add(T("Media"), "6", menu => menu.Add(T("Media"), "0", item => item.Action("Index", "Admin", new { area = "Orchard.MediaLibrary" }) - .Permission(Permissions.ManageMediaContent))); + .Permission(Permissions.ManageOwnMedia))); } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/AdminController.cs index bd9ab44fa..c9158d4f7 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/AdminController.cs @@ -14,6 +14,7 @@ using Orchard.Themes; using Orchard.UI.Navigation; using Orchard.ContentManagement.MetaData; using Orchard.Validation; +using System.Collections.Generic; namespace Orchard.MediaLibrary.Controllers { [ValidateInput(false)] @@ -41,17 +42,21 @@ namespace Orchard.MediaLibrary.Controllers { public ILogger Logger { get; set; } public ActionResult Index(string folderPath = "", bool dialog = false) { - if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Cannot view media"))) + if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Cannot view media"))) return new HttpUnauthorizedResult(); + // If the user is trying to access a folder above his boundaries, redirect him to his home folder + var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder(); + if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) { + return RedirectToAction("Index", new { folderPath = rootMediaFolder.MediaPath, dialog }); + } + // let other modules enhance the ui by providing custom navigation and actions var explorer = Services.ContentManager.New("MediaLibraryExplorer"); explorer.Weld(new MediaLibraryExplorerPart()); var explorerShape = Services.ContentManager.BuildDisplay(explorer); - var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder(); - var viewModel = new MediaManagerIndexViewModel { DialogMode = dialog, FolderPath = folderPath, @@ -73,7 +78,7 @@ namespace Orchard.MediaLibrary.Controllers { } public ActionResult Import(string folderPath) { - if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Cannot import media"))) + if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Cannot import media"))) return new HttpUnauthorizedResult(); var mediaProviderMenu = _navigationManager.BuildMenu("mediaproviders"); @@ -91,9 +96,20 @@ namespace Orchard.MediaLibrary.Controllers { [Themed(false)] public ActionResult MediaItems(string folderPath, int skip = 0, int count = 0, string order = "created", string mediaType = "") { - if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Cannot view media"))) + if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Cannot view media"))) return new HttpUnauthorizedResult(); + // Check permission.var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder(); + if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) { + var model = new MediaManagerMediaItemsViewModel { + MediaItems = new List(), + MediaItemsCount = 0, + FolderPath = folderPath + }; + + return View(model); + } + var mediaParts = _mediaLibraryService.GetMediaContentItems(folderPath, skip, count, order, mediaType, VersionOptions.Latest); var mediaPartsCount = _mediaLibraryService.GetMediaContentItemsCount(folderPath, mediaType, VersionOptions.Latest); @@ -113,9 +129,19 @@ namespace Orchard.MediaLibrary.Controllers { [Themed(false)] public ActionResult ChildFolders(string folderPath = null) { - if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Cannot get child folder listing"))) + if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Cannot get child folder listing"))) return new HttpUnauthorizedResult(); + // Check permission. + var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder(); + if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) { + var model = new MediaManagerChildFoldersViewModel { + Children = new IMediaFolder[0] + }; + + return View(model); + } + var viewModel = new MediaManagerChildFoldersViewModel { Children = _mediaLibraryService.GetMediaFolders(folderPath) }; @@ -127,11 +153,13 @@ namespace Orchard.MediaLibrary.Controllers { [Themed(false)] public ActionResult RecentMediaItems(int skip = 0, int count = 0, string order = "created", string mediaType = "") { - if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Cannot view media"))) + if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Cannot view media"))) return new HttpUnauthorizedResult(); - var mediaParts = _mediaLibraryService.GetMediaContentItems(skip, count, order, mediaType); - var mediaPartsCount = _mediaLibraryService.GetMediaContentItemsCount(mediaType); + var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder().MediaPath; + + var mediaParts = _mediaLibraryService.GetMediaContentItems(rootMediaFolder, skip, count, order, mediaType); + var mediaPartsCount = _mediaLibraryService.GetMediaContentItemsCount(rootMediaFolder, mediaType); var mediaItems = mediaParts.Select(x => new MediaManagerMediaItemViewModel { @@ -149,12 +177,13 @@ namespace Orchard.MediaLibrary.Controllers { [Themed(false)] public ActionResult MediaItem(int id, string displayType = "SummaryAdmin") { - var contentItem = Services.ContentManager.Get(id, VersionOptions.Latest); + var contentItem = Services.ContentManager.Get(id, VersionOptions.Latest); if (contentItem == null) return HttpNotFound(); - if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, contentItem, T("Cannot view media"))) + if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, contentItem, T("Cannot view media")) + || !_mediaLibraryService.CanManageMediaFolder(contentItem.FolderPath)) return new HttpUnauthorizedResult(); dynamic model = Services.ContentManager.BuildDisplay(contentItem, displayType); @@ -164,13 +193,20 @@ namespace Orchard.MediaLibrary.Controllers { [HttpPost] public ActionResult Delete(int[] mediaItemIds) { - if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't delete media items"))) + if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Couldn't delete media items"))) return new HttpUnauthorizedResult(); + var mediaItems = Services.ContentManager + .Query(VersionOptions.Latest) + .ForContentItems(mediaItemIds) + .List() + .Select(x => x.As()) + .Where(x => x != null); + try { - foreach (var media in Services.ContentManager.Query(VersionOptions.Latest).ForContentItems(mediaItemIds).List()) { - if (media != null) { - Services.ContentManager.Remove(media); + foreach (var media in mediaItems) { + if (_mediaLibraryService.CanManageMediaFolder(media.FolderPath)) { + Services.ContentManager.Remove(media.ContentItem); } } @@ -184,12 +220,16 @@ namespace Orchard.MediaLibrary.Controllers { [HttpPost] public ActionResult Clone(int mediaItemId) { - if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't clone media items"))) + if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Couldn't clone media items"))) return new HttpUnauthorizedResult(); try { var media = Services.ContentManager.Get(mediaItemId).As(); + if(!_mediaLibraryService.CanManageMediaFolder(media.FolderPath)) { + return new HttpUnauthorizedResult(); + } + var newFileName = Path.GetFileNameWithoutExtension(media.FileName) + " Copy" + Path.GetExtension(media.FileName); _mediaLibraryService.CopyFile(media.FolderPath, media.FileName, media.FolderPath, newFileName); diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/ClientStorageController.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/ClientStorageController.cs index 607dd1564..aedba54df 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/ClientStorageController.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/ClientStorageController.cs @@ -17,10 +17,13 @@ namespace Orchard.MediaLibrary.Controllers { public class ClientStorageController : Controller { private readonly IMediaLibraryService _mediaLibraryService; - public ClientStorageController(IMediaLibraryService mediaManagerService, IOrchardServices orchardServices) { + public ClientStorageController( + IMediaLibraryService mediaManagerService, + IContentManager contentManager, + IOrchardServices orchardServices) { _mediaLibraryService = mediaManagerService; Services = orchardServices; - + Services = orchardServices; T = NullLocalizer.Instance; } @@ -42,7 +45,13 @@ namespace Orchard.MediaLibrary.Controllers { [HttpPost] public ActionResult Upload(string folderPath, string type) { - if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Cannot manage media"))) { + if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia)) { + return new HttpUnauthorizedResult(); + } + + // Check permission. + var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder(); + if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) { return new HttpUnauthorizedResult(); } diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/FolderController.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/FolderController.cs index b08662cf8..aae4fc56f 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/FolderController.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/FolderController.cs @@ -32,9 +32,15 @@ namespace Orchard.MediaLibrary.Controllers { public Localizer T { get; set; } public ActionResult Create(string folderPath) { - if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't create media folder"))) + if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Couldn't create media folder"))) return new HttpUnauthorizedResult(); + // If the user is trying to access a folder above his boundaries, redirect him to his home folder + var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder(); + if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) { + return RedirectToAction("Create", new { folderPath = rootMediaFolder.MediaPath }); + } + var viewModel = new MediaManagerFolderCreateViewModel { Hierarchy = _mediaLibraryService.GetMediaFolders(folderPath), FolderPath = folderPath @@ -45,12 +51,16 @@ namespace Orchard.MediaLibrary.Controllers { [HttpPost, ActionName("Create")] public ActionResult Create() { - if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't create media folder"))) + if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Couldn't create media folder"))) return new HttpUnauthorizedResult(); var viewModel = new MediaManagerFolderCreateViewModel(); UpdateModel(viewModel); + if (!_mediaLibraryService.CanManageMediaFolder(viewModel.FolderPath)) { + return new HttpUnauthorizedResult(); + } + try { _mediaLibraryService.CreateFolder(viewModel.FolderPath, viewModel.Name); Services.Notifier.Information(T("Media folder created")); @@ -66,9 +76,13 @@ namespace Orchard.MediaLibrary.Controllers { } public ActionResult Edit(string folderPath) { - if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't edit media folder"))) + if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Couldn't edit media folder"))) return new HttpUnauthorizedResult(); - + + if (!_mediaLibraryService.CanManageMediaFolder(folderPath)) { + return new HttpUnauthorizedResult(); + } + var viewModel = new MediaManagerFolderEditViewModel { FolderPath = folderPath, Name = folderPath.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar).Last() @@ -80,12 +94,16 @@ namespace Orchard.MediaLibrary.Controllers { [HttpPost, ActionName("Edit")] [FormValueRequired("submit.Save")] public ActionResult Edit() { - if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't edit media folder"))) + if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Couldn't edit media folder"))) return new HttpUnauthorizedResult(); var viewModel = new MediaManagerFolderEditViewModel(); UpdateModel(viewModel); + if (!_mediaLibraryService.CanManageMediaFolder(viewModel.FolderPath)) { + return new HttpUnauthorizedResult(); + } + try { _mediaLibraryService.RenameFolder(viewModel.FolderPath, viewModel.Name); Services.Notifier.Information(T("Media folder renamed")); @@ -101,12 +119,16 @@ namespace Orchard.MediaLibrary.Controllers { [HttpPost, ActionName("Edit")] [FormValueRequired("submit.Delete")] public ActionResult Delete() { - if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't delete media folder"))) + if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Couldn't delete media folder"))) return new HttpUnauthorizedResult(); var viewModel = new MediaManagerFolderEditViewModel(); UpdateModel(viewModel); + if (!_mediaLibraryService.CanManageMediaFolder(viewModel.FolderPath)) { + return new HttpUnauthorizedResult(); + + } try { _mediaLibraryService.DeleteFolder(viewModel.FolderPath); Services.Notifier.Information(T("Media folder deleted")); @@ -122,9 +144,13 @@ namespace Orchard.MediaLibrary.Controllers { [HttpPost] public ActionResult Move(string folderPath, int[] mediaItemIds) { - if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't move media items"))) + if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Couldn't move media items"))) return new HttpUnauthorizedResult(); + if (!_mediaLibraryService.CanManageMediaFolder(folderPath)) { + return new HttpUnauthorizedResult(); + } + foreach (var media in Services.ContentManager.Query().ForPart().ForContentItems(mediaItemIds).List()) { // don't try to rename the file if there is no associated media file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs index 0ed803cbe..e5368bd0a 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/OEmbedController.cs @@ -9,12 +9,18 @@ using Orchard.MediaLibrary.ViewModels; using Orchard.Themes; using Orchard.UI.Admin; using Orchard.ContentManagement; +using Orchard.MediaLibrary.Services; namespace Orchard.MediaLibrary.Controllers { [Admin, Themed(false)] public class OEmbedController : Controller { - public OEmbedController(IOrchardServices services) { + private readonly IMediaLibraryService _mediaLibraryService; + + public OEmbedController( + IOrchardServices services, + IMediaLibraryService mediaManagerService) { Services = services; + _mediaLibraryService = mediaManagerService; } public IOrchardServices Services { get; set; } @@ -32,6 +38,15 @@ namespace Orchard.MediaLibrary.Controllers { [ActionName("Index")] [ValidateInput(false)] public ActionResult IndexPOST(string folderPath, string url, string type, string title, string html, string thumbnail, string width, string height, string description) { + if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia)) + return new HttpUnauthorizedResult(); + + // Check permission. + var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder(); + if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) { + return new HttpUnauthorizedResult(); + } + var viewModel = new OEmbedViewModel { Url = url, FolderPath = folderPath diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/WebSearchController.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/WebSearchController.cs index 83154cf9c..23f7b576d 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/WebSearchController.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/WebSearchController.cs @@ -13,12 +13,19 @@ namespace Orchard.MediaLibrary.Controllers { public class WebSearchController : Controller { private readonly IMediaLibraryService _mediaLibraryService; private readonly IContentManager _contentManager; - - public WebSearchController(IMediaLibraryService mediaManagerService, IContentManager contentManager) { + + public WebSearchController( + IMediaLibraryService mediaManagerService, + IContentManager contentManager, + IOrchardServices orchardServices) { _mediaLibraryService = mediaManagerService; _contentManager = contentManager; + + Services = orchardServices; } + public IOrchardServices Services { get; set; } + public ActionResult Index(string folderPath, string type) { var viewModel = new ImportMediaViewModel { FolderPath = folderPath, @@ -30,7 +37,15 @@ namespace Orchard.MediaLibrary.Controllers { [HttpPost] - public JsonResult ImagePost(string folderPath, string type, string url) { + public ActionResult ImagePost(string folderPath, string type, string url) { + if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia)) + return new HttpUnauthorizedResult(); + + // Check permission. + var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder(); + if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) { + return new HttpUnauthorizedResult(); + } try { var buffer = new WebClient().DownloadData(url); diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/AudioPartDriver.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/AudioPartDriver.cs index 14f17ce73..32fdb65e7 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/AudioPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/AudioPartDriver.cs @@ -17,10 +17,14 @@ namespace Orchard.MediaLibrary.Drivers { } protected override void Importing(AudioPart part, ContentManagement.Handlers.ImportContentContext context) { - var length = context.Attribute(part.PartDefinition.Name, "Length"); - if (length != null) { - part.Length = int.Parse(length); + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; } + + context.ImportAttribute(part.PartDefinition.Name, "Length", length => + part.Length = int.Parse(length) + ); } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/DocumentPartDriver.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/DocumentPartDriver.cs index 2a0ac0d06..28d721d4b 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/DocumentPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/DocumentPartDriver.cs @@ -17,10 +17,14 @@ namespace Orchard.MediaLibrary.Drivers { } protected override void Importing(DocumentPart part, ContentManagement.Handlers.ImportContentContext context) { - var length = context.Attribute(part.PartDefinition.Name, "Length"); - if (length != null) { - part.Length = int.Parse(length); + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; } + + context.ImportAttribute(part.PartDefinition.Name, "Length", length => + part.Length = int.Parse(length) + ); } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/ImagePartDriver.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/ImagePartDriver.cs index 77163dbf4..5c12f4e34 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/ImagePartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/ImagePartDriver.cs @@ -20,15 +20,18 @@ namespace Orchard.MediaLibrary.Drivers { } protected override void Importing(ImagePart part, ContentManagement.Handlers.ImportContentContext context) { - var height = context.Attribute(part.PartDefinition.Name, "Height"); - if (height != null) { - part.Height = int.Parse(height); + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; } - var width = context.Attribute(part.PartDefinition.Name, "Width"); - if (width != null) { - part.Width = int.Parse(width); - } + context.ImportAttribute(part.PartDefinition.Name, "Height", height => + part.Height = int.Parse(height) + ); + + context.ImportAttribute(part.PartDefinition.Name, "Width", width => + part.Width = int.Parse(width) + ); } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/MediaPartDriver.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/MediaPartDriver.cs index 65df8c8d4..7ee9d8bf9 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/MediaPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/MediaPartDriver.cs @@ -36,30 +36,30 @@ namespace Orchard.MediaLibrary.Drivers { } protected override void Importing(MediaPart part, ContentManagement.Handlers.ImportContentContext context) { - var mimeType = context.Attribute(part.PartDefinition.Name, "MimeType"); - if (mimeType != null) { - part.MimeType = mimeType; + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; } - var caption = context.Attribute(part.PartDefinition.Name, "Caption"); - if (caption != null) { - part.Caption = caption; - } + context.ImportAttribute(part.PartDefinition.Name, "MimeType", mimeType => + part.MimeType = mimeType + ); - var alternateText = context.Attribute(part.PartDefinition.Name, "AlternateText"); - if (alternateText != null) { - part.AlternateText = alternateText; - } + context.ImportAttribute(part.PartDefinition.Name, "Caption", caption => + part.Caption = caption + ); - var folderPath = context.Attribute(part.PartDefinition.Name, "FolderPath"); - if (folderPath != null) { - part.FolderPath = folderPath; - } + context.ImportAttribute(part.PartDefinition.Name, "AlternateText", alternateText => + part.AlternateText = alternateText + ); - var fileName = context.Attribute(part.PartDefinition.Name, "FileName"); - if (fileName != null) { - part.FileName = fileName; - } + context.ImportAttribute(part.PartDefinition.Name, "FolderPath", folderPath => + part.FolderPath = folderPath + ); + + context.ImportAttribute(part.PartDefinition.Name, "FileName", fileName => + part.FileName = fileName + ); } protected override void Exporting(MediaPart part, ContentManagement.Handlers.ExportContentContext context) { diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/OEmbedPartDriver.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/OEmbedPartDriver.cs index 1ac59f54b..3f0fd1adf 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/OEmbedPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/OEmbedPartDriver.cs @@ -17,10 +17,14 @@ namespace Orchard.MediaLibrary.Drivers { } protected override void Importing(OEmbedPart part, ContentManagement.Handlers.ImportContentContext context) { - var source = context.Attribute(part.PartDefinition.Name, "Source"); - if (source != null) { - part.Source = source; + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; } + + context.ImportAttribute(part.PartDefinition.Name, "Source", source => + part.Source = source + ); } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/VideoPartDriver.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/VideoPartDriver.cs index 57ef97145..a9fdce3bb 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/VideoPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/VideoPartDriver.cs @@ -17,10 +17,14 @@ namespace Orchard.MediaLibrary.Drivers { } protected override void Importing(VideoPart part, ContentManagement.Handlers.ImportContentContext context) { - var length = context.Attribute(part.PartDefinition.Name, "Length"); - if (length != null) { - part.Length = int.Parse(length); + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; } + + context.ImportAttribute(part.PartDefinition.Name, "Length", length => + part.Length = int.Parse(length) + ); } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Module.txt b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Module.txt index b43640f3c..700b9f1a5 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Module.txt @@ -2,7 +2,7 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: Provides enhanced Media management tools. Features: diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Orchard.MediaLibrary.csproj b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Orchard.MediaLibrary.csproj index 5cc81bb4b..08b413e12 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Orchard.MediaLibrary.csproj +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Orchard.MediaLibrary.csproj @@ -178,6 +178,7 @@ + diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Permissions.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Permissions.cs index 3efd53f8e..8e9497683 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Permissions.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Permissions.cs @@ -4,13 +4,15 @@ using Orchard.Security.Permissions; namespace Orchard.MediaLibrary { public class Permissions : IPermissionProvider { - public static readonly Permission ManageMediaContent = new Permission { Description = "Managing Media", Name = "ManageMediaContent" }; + public static readonly Permission ManageMediaContent = new Permission { Description = "Manage Media", Name = "ManageMediaContent" }; + public static readonly Permission ManageOwnMedia = new Permission { Description = "Manage Own Media", Name = "ManageOwnMedia", ImpliedBy = new[] { ManageMediaContent } }; public virtual Feature Feature { get; set; } public IEnumerable GetPermissions() { return new[] { ManageMediaContent, + ManageOwnMedia, }; } @@ -33,6 +35,7 @@ namespace Orchard.MediaLibrary { }, new PermissionStereotype { Name = "Contributor", + Permissions = new[] {ManageOwnMedia} }, }; } diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Properties/AssemblyInfo.cs index d0375acf9..1b1728893 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Properties/AssemblyInfo.cs @@ -31,6 +31,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Providers/ClientStorageMenu.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Providers/ClientStorageMenu.cs index 7f8b8a973..005764bab 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Providers/ClientStorageMenu.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Providers/ClientStorageMenu.cs @@ -15,7 +15,7 @@ namespace Orchard.MediaLibrary.Providers { builder.AddImageSet("clientstorage") .Add(T("My Computer"), "5", menu => menu.Action("Index", "ClientStorage", new { area = "Orchard.MediaLibrary" }) - .Permission(Permissions.ManageMediaContent)); + .Permission(Permissions.ManageOwnMedia)); } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Providers/OEmbedMenu.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Providers/OEmbedMenu.cs index 82875e1fb..71aff8019 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Providers/OEmbedMenu.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Providers/OEmbedMenu.cs @@ -15,7 +15,7 @@ namespace Orchard.MediaLibrary.Providers { builder.AddImageSet("oembed") .Add(T("Media Url"), "10", menu => menu.Action("Index", "OEmbed", new { area = "Orchard.MediaLibrary" }) - .Permission(Permissions.ManageMediaContent)); + .Permission(Permissions.ManageOwnMedia)); } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Providers/WebSearchMenu.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Providers/WebSearchMenu.cs index 896205d0f..39fb04322 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Providers/WebSearchMenu.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Providers/WebSearchMenu.cs @@ -15,7 +15,7 @@ namespace Orchard.MediaLibrary.Providers { builder.AddImageSet("websearch") .Add(T("Web Search"), "7", menu => menu.Action("Index", "WebSearch", new { area = "Orchard.MediaLibrary" }) - .Permission(Permissions.ManageMediaContent)); + .Permission(Permissions.ManageOwnMedia)); } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Security/MediaAuthorizationEventHandler.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Security/MediaAuthorizationEventHandler.cs new file mode 100644 index 000000000..14bb48916 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Security/MediaAuthorizationEventHandler.cs @@ -0,0 +1,35 @@ +using Orchard.ContentManagement; +using Orchard.MediaLibrary.Models; +using Orchard.MediaLibrary.Services; +using Orchard.Security; + +namespace Orchard.MediaLibrary.Security { + public class MediaAuthorizationEventHandler : IAuthorizationServiceEventHandler { + private readonly IAuthorizer _authorizer; + private readonly IMediaLibraryService _mediaLibraryService; + + public MediaAuthorizationEventHandler( + IAuthorizer authorizer, + IMediaLibraryService mediaLibraryService) { + _authorizer = authorizer; + _mediaLibraryService = mediaLibraryService; + } + + public void Checking(CheckAccessContext context) { } + public void Complete(CheckAccessContext context) { } + + public void Adjust(CheckAccessContext context) { + var mediaPart = context.Content.As(); + if (mediaPart != null) { + if(_authorizer.Authorize(Permissions.ManageMediaContent)) { + context.Granted = true; + return; + } + + if(_authorizer.Authorize(Permissions.ManageOwnMedia)) { + context.Granted = _mediaLibraryService.CanManageMediaFolder(mediaPart.FolderPath); + } + } + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Services/IMediaLibraryService.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Services/IMediaLibraryService.cs index 7424c9fa5..2291f4c6f 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Services/IMediaLibraryService.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Services/IMediaLibraryService.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.IO; using System.Web; using Orchard.ContentManagement; @@ -36,7 +37,7 @@ namespace Orchard.MediaLibrary.Services { /// The public URL for the media. string GetMediaPublicUrl(string mediaPath, string fileName); - MediaFolder GetRootMediaFolder(); + IMediaFolder GetRootMediaFolder(); /// /// Retrieves the media folders within a given relative path. @@ -131,4 +132,30 @@ namespace Orchard.MediaLibrary.Services { /// The path to the uploaded file. string UploadMediaFile(string folderPath, string fileName, Stream inputStream); } + + public static class MediaLibrayServiceExtensions { + public static bool CanManageMediaFolder(this IMediaLibraryService service, string folderPath) { + // The current user can manage a media if he has access to the whole hierarchy + // or the media is under his personal storage folder. + + var rootMediaFolder = service.GetRootMediaFolder(); + if (rootMediaFolder == null) { + return true; + } + + var mediaPath = folderPath + "\\"; + var rootPath = rootMediaFolder.MediaPath + "\\"; + + return mediaPath.StartsWith(rootPath, StringComparison.OrdinalIgnoreCase); + } + + public static string GetRootedFolderPath(this IMediaLibraryService service, string folderPath) { + var rootMediaFolder = service.GetRootMediaFolder(); + if (rootMediaFolder != null) { + return Path.Combine(rootMediaFolder.MediaPath, folderPath ?? ""); + } + + return folderPath; + } + } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Services/MediaLibraryService.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Services/MediaLibraryService.cs index e7fb1a4fe..21949b99d 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Services/MediaLibraryService.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Services/MediaLibraryService.cs @@ -210,7 +210,21 @@ namespace Orchard.MediaLibrary.Services { return GetPublicUrl(Path.Combine(mediaPath, fileName)); } - public MediaFolder GetRootMediaFolder() { + public IMediaFolder GetRootMediaFolder() { + if (_orchardServices.Authorizer.Authorize(Permissions.ManageMediaContent)) { + return null; + } + + if (_orchardServices.Authorizer.Authorize(Permissions.ManageOwnMedia)) { + var currentUser = _orchardServices.WorkContext.CurrentUser; + var userPath = _storageProvider.Combine("Users", currentUser.UserName); + + return new MediaFolder() { + Name = currentUser.UserName, + MediaPath = userPath + }; + } + return null; } diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Services/XmlRpcHandler.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Services/XmlRpcHandler.cs index 88eb0be87..14a35ab00 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Services/XmlRpcHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Services/XmlRpcHandler.cs @@ -60,7 +60,7 @@ namespace Orchard.MediaLibrary.Services { UrlHelper url) { var user = _membershipService.ValidateUser(userName, password); - if (!_authorizationService.TryCheckAccess(Permissions.ManageMediaContent, user, null)) { + if (!_authorizationService.TryCheckAccess(Permissions.ManageOwnMedia, user, null)) { throw new OrchardCoreException(T("Access denied")); } @@ -72,6 +72,11 @@ namespace Orchard.MediaLibrary.Services { directoryName = "media"; } + // If the user only has access to his own folder, rewrite the folder name + if (!_authorizationService.TryCheckAccess(Permissions.ManageMediaContent, user, null)) { + directoryName = Path.Combine(_mediaLibraryService.GetRootedFolderPath(directoryName)); + } + try { // delete the file if it already exists, e.g. an updated image in a blog post // it's safe to delete the file as each content item gets a specific folder diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/Index.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/Index.cshtml index 5a9dce068..57eaa43e4 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/Index.cshtml +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/Index.cshtml @@ -112,7 +112,7 @@ var mediaLibrarySettings = {
        -
          +
diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Folder/Create.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Folder/Create.cshtml index 3ed81ac0f..c817607d0 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Folder/Create.cshtml +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Folder/Create.cshtml @@ -6,10 +6,12 @@
\ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Drivers/SslSettingsPartDriver.cs b/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Drivers/SslSettingsPartDriver.cs index 89dd0cd63..794df2d37 100644 --- a/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Drivers/SslSettingsPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Drivers/SslSettingsPartDriver.cs @@ -36,7 +36,6 @@ namespace Orchard.SecureSocketsLayer.Drivers { } protected override void Importing(SslSettingsPart part, ImportContentContext context) { - base.Importing(part, context); _signals.Trigger(SslSettingsPart.CacheKey); } } diff --git a/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Module.txt b/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Module.txt index 916d28c75..140f74b56 100644 --- a/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Module.txt @@ -2,7 +2,7 @@ Name: Secure Sockets Layer AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: This module will ensure SSL is used when accessing specific parts of the website like the dashboard, authentication pages or custom pages. FeatureName: Secure Sockets Layer diff --git a/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Properties/AssemblyInfo.cs index 168f1af0d..263450c07 100644 --- a/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Properties/AssemblyInfo.cs @@ -30,5 +30,5 @@ using System.Runtime.InteropServices; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Commands/SetupCommand.cs b/src/Orchard.Web/Modules/Orchard.Setup/Commands/SetupCommand.cs index e56c2cd61..306c626fe 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Commands/SetupCommand.cs +++ b/src/Orchard.Web/Modules/Orchard.Setup/Commands/SetupCommand.cs @@ -2,14 +2,17 @@ using System.Collections.Generic; using System.Linq; using Orchard.Commands; +using Orchard.Recipes.Services; using Orchard.Setup.Services; namespace Orchard.Setup.Commands { public class SetupCommand : DefaultOrchardCommandHandler { private readonly ISetupService _setupService; + private readonly IRecipeHarvester _recipeHarvester; - public SetupCommand(ISetupService setupService) { + public SetupCommand(ISetupService setupService, IRecipeHarvester recipeHarvester) { _setupService = setupService; + _recipeHarvester = recipeHarvester; } [OrchardSwitch] @@ -51,6 +54,7 @@ namespace Orchard.Setup.Commands { .Where(s => !String.IsNullOrEmpty(s)); } Recipe = String.IsNullOrEmpty(Recipe) ? "Default" : Recipe; + var recipe = _setupService.Recipes().GetRecipeByName(Recipe); var setupContext = new SetupContext { SiteName = SiteName, @@ -60,7 +64,7 @@ namespace Orchard.Setup.Commands { DatabaseConnectionString = DatabaseConnectionString, DatabaseTablePrefix = DatabaseTablePrefix, EnabledFeatures = enabledFeatures, - Recipe = Recipe, + Recipe = recipe, }; var executionId = _setupService.Setup(setupContext); diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Controllers/SetupController.cs b/src/Orchard.Web/Modules/Orchard.Setup/Controllers/SetupController.cs index fba6a53a5..8c2eb4687 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Controllers/SetupController.cs +++ b/src/Orchard.Web/Modules/Orchard.Setup/Controllers/SetupController.cs @@ -7,6 +7,7 @@ using Orchard.Logging; using Orchard.Setup.Services; using Orchard.Setup.ViewModels; using Orchard.Localization; +using Orchard.Recipes.Services; using Orchard.Themes; using Orchard.UI.Notify; @@ -20,10 +21,11 @@ namespace Orchard.Setup.Controllers { private const string DefaultRecipe = "Default"; public SetupController( - INotifier notifier, - ISetupService setupService, + INotifier notifier, + ISetupService setupService, IViewsBackgroundCompilation viewsBackgroundCompilation, ShellSettings shellSettings) { + _viewsBackgroundCompilation = viewsBackgroundCompilation; _shellSettings = shellSettings; _notifier = notifier; @@ -31,10 +33,12 @@ namespace Orchard.Setup.Controllers { T = NullLocalizer.Instance; Logger = NullLogger.Instance; + RecipeExecutionTimeout = 600; } public Localizer T { get; set; } public ILogger Logger { get; set; } + public int RecipeExecutionTimeout { get; set; } private ActionResult IndexViewResult(SetupViewModel model) { return View(model); @@ -44,10 +48,11 @@ namespace Orchard.Setup.Controllers { var initialSettings = _setupService.Prime(); var recipes = _setupService.Recipes().ToList(); string recipeDescription = null; + if (recipes.Count > 0) { recipeDescription = recipes[0].Description; } - + // On the first time installation of Orchard, the user gets to the setup screen, which // will take a while to finish (user inputting data and the setup process itself). // We use this opportunity to start a background task to "pre-compile" all the known @@ -56,10 +61,10 @@ namespace Orchard.Setup.Controllers { if (StringComparer.OrdinalIgnoreCase.Equals(initialSettings.Name, ShellSettings.DefaultName)) { _viewsBackgroundCompilation.Start(); } - + return IndexViewResult(new SetupViewModel { AdminUsername = "admin", - DatabaseIsPreconfigured = !string.IsNullOrEmpty(initialSettings.DataProvider), + DatabaseIsPreconfigured = !String.IsNullOrEmpty(initialSettings.DataProvider), Recipes = recipes, RecipeDescription = recipeDescription }); @@ -67,8 +72,8 @@ namespace Orchard.Setup.Controllers { [HttpPost, ActionName("Index")] public ActionResult IndexPOST(SetupViewModel model) { - // Sets the setup request timeout to 10 minutes to give enough time to execute custom recipes. - HttpContext.Server.ScriptTimeout = 600; + // Sets the setup request timeout to a configurable amount of seconds to give enough time to execute custom recipes. + HttpContext.Server.ScriptTimeout = RecipeExecutionTimeout; var recipes = _setupService.Recipes().ToList(); @@ -76,17 +81,17 @@ namespace Orchard.Setup.Controllers { if (model.DatabaseProvider != SetupDatabaseType.Builtin && string.IsNullOrEmpty(model.DatabaseConnectionString)) ModelState.AddModelError("DatabaseConnectionString", T("A connection string is required.").Text); - if (!string.IsNullOrWhiteSpace(model.ConfirmPassword) && model.AdminPassword != model.ConfirmPassword ) { + if (!String.IsNullOrWhiteSpace(model.ConfirmPassword) && model.AdminPassword != model.ConfirmPassword) { ModelState.AddModelError("ConfirmPassword", T("Password confirmation must match.").Text); } if (model.DatabaseProvider != SetupDatabaseType.Builtin && !string.IsNullOrWhiteSpace(model.DatabaseTablePrefix)) { model.DatabaseTablePrefix = model.DatabaseTablePrefix.Trim(); - if(!char.IsLetter(model.DatabaseTablePrefix[0])) { + if (!Char.IsLetter(model.DatabaseTablePrefix[0])) { ModelState.AddModelError("DatabaseTablePrefix", T("The table prefix must begin with a letter.").Text); } - if(model.DatabaseTablePrefix.Any(x => !Char.IsLetterOrDigit(x))) { + if (model.DatabaseTablePrefix.Any(x => !Char.IsLetterOrDigit(x))) { ModelState.AddModelError("DatabaseTablePrefix", T("The table prefix must contain letters or digits.").Text); } } @@ -103,16 +108,15 @@ namespace Orchard.Setup.Controllers { foreach (var recipe in recipes.Where(recipe => recipe.Name == model.Recipe)) { model.RecipeDescription = recipe.Description; } - model.DatabaseIsPreconfigured = !string.IsNullOrEmpty(_setupService.Prime().DataProvider); - + model.DatabaseIsPreconfigured = !String.IsNullOrEmpty(_setupService.Prime().DataProvider); + return IndexViewResult(model); } try { string providerName = null; - switch (model.DatabaseProvider) - { + switch (model.DatabaseProvider) { case SetupDatabaseType.Builtin: providerName = "SqlCe"; break; @@ -133,6 +137,7 @@ namespace Orchard.Setup.Controllers { throw new ApplicationException("Unknown database type: " + model.DatabaseProvider); } + var recipe = _setupService.Recipes().GetRecipeByName(model.Recipe); var setupContext = new SetupContext { SiteName = model.SiteName, AdminUsername = model.AdminUsername, @@ -140,11 +145,11 @@ namespace Orchard.Setup.Controllers { DatabaseProvider = providerName, DatabaseConnectionString = model.DatabaseConnectionString, DatabaseTablePrefix = model.DatabaseTablePrefix, - EnabledFeatures = null, // default list - Recipe = model.Recipe + EnabledFeatures = null, // Default list + Recipe = recipe }; - string executionId = _setupService.Setup(setupContext); + var executionId = _setupService.Setup(setupContext); // First time installation if finally done. Tell the background views compilation // process to stop, so that it doesn't interfere with the user (asp.net compilation @@ -153,7 +158,8 @@ namespace Orchard.Setup.Controllers { // Redirect to the welcome page. return Redirect("~/" + _shellSettings.RequestUrlPrefix); - } catch (Exception ex) { + } + catch (Exception ex) { Logger.Error(ex, "Setup failed"); _notifier.Error(T("Setup failed: {0}", ex.Message)); @@ -161,7 +167,7 @@ namespace Orchard.Setup.Controllers { foreach (var recipe in recipes.Where(recipe => recipe.Name == model.Recipe)) { model.RecipeDescription = recipe.Description; } - model.DatabaseIsPreconfigured = !string.IsNullOrEmpty(_setupService.Prime().DataProvider); + model.DatabaseIsPreconfigured = !String.IsNullOrEmpty(_setupService.Prime().DataProvider); return IndexViewResult(model); } diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Controllers/SetupDatabaseType.cs b/src/Orchard.Web/Modules/Orchard.Setup/Controllers/SetupDatabaseType.cs deleted file mode 100644 index 48265336c..000000000 --- a/src/Orchard.Web/Modules/Orchard.Setup/Controllers/SetupDatabaseType.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; - -namespace Orchard.Setup.Controllers -{ - public enum SetupDatabaseType - { - Builtin, - SqlServer, - MySql, - PostgreSql, - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Module.txt b/src/Orchard.Web/Modules/Orchard.Setup/Module.txt index 9895478e3..10e6b8582 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Setup/Module.txt @@ -1,8 +1,14 @@ Name: Setup Author: The Orchard Team Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: The setup module is creating the application's setup experience. FeatureDescription: Standard site setup. This feature is disabled automatically once setup is over. Category: Core +Dependencies: Orchard.Setup.Services +Features: + Orchard.Setup.Services + Name: Setup Services + Description: Provides programmatic APIs to the setup service. + Category: Core diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Orchard.Setup.csproj b/src/Orchard.Web/Modules/Orchard.Setup/Orchard.Setup.csproj index 94d8c676d..6e7182827 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Orchard.Setup.csproj +++ b/src/Orchard.Web/Modules/Orchard.Setup/Orchard.Setup.csproj @@ -25,6 +25,7 @@ + true @@ -78,7 +79,7 @@ - + diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Setup/Properties/AssemblyInfo.cs index b64d7d032..72f4c97ed 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Setup/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Routes.cs b/src/Orchard.Web/Modules/Orchard.Setup/Routes.cs index 2bc323f36..faafaa50e 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Routes.cs +++ b/src/Orchard.Web/Modules/Orchard.Setup/Routes.cs @@ -4,8 +4,7 @@ using System.Web.Routing; using Orchard.Mvc.Routes; namespace Orchard.Setup { - public class Routes : IRouteProvider - { + public class Routes : IRouteProvider { public void GetRoutes(ICollection routes) { foreach (var routeDescriptor in GetRoutes()) routes.Add(routeDescriptor); @@ -13,24 +12,24 @@ namespace Orchard.Setup { public IEnumerable GetRoutes() { return new[] { - new RouteDescriptor { - Route = new Route( - "{controller}/{action}", - new RouteValueDictionary { - {"area", "Orchard.Setup"}, - {"controller", "Setup"}, - {"action", "Index"} - }, - new RouteValueDictionary { - {"area", "Orchard.Setup"}, - {"controller", "Setup"}, - }, - new RouteValueDictionary { - {"area", "Orchard.Setup"} - }, - new MvcRouteHandler()) - } - }; + new RouteDescriptor { + Route = new Route( + "{controller}/{action}", + new RouteValueDictionary { + {"area", "Orchard.Setup"}, + {"controller", "Setup"}, + {"action", "Index"} + }, + new RouteValueDictionary { + {"area", "Orchard.Setup"}, + {"controller", "Setup"}, + }, + new RouteValueDictionary { + {"area", "Orchard.Setup"} + }, + new MvcRouteHandler()) + } + }; } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupContext.cs b/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupContext.cs index 06c32c914..0c87402bc 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupContext.cs +++ b/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupContext.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Orchard.Recipes.Models; namespace Orchard.Setup.Services { public class SetupContext { @@ -9,6 +10,6 @@ namespace Orchard.Setup.Services { public string DatabaseConnectionString { get; set; } public string DatabaseTablePrefix { get; set; } public IEnumerable EnabledFeatures { get; set; } - public string Recipe { get; set; } + public Recipe Recipe { get; set; } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs b/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs index 16b3e465b..7549405cb 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs +++ b/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Web; +using System.Xml.Linq; using Orchard.ContentManagement; using Orchard.Core.Settings.Models; using Orchard.Data; @@ -16,7 +17,6 @@ using Orchard.Environment.Descriptor.Models; using Orchard.Environment.Extensions; using Orchard.Environment.ShellBuilders; using Orchard.Environment.State; -using Orchard.Localization; using Orchard.Localization.Services; using Orchard.Logging; using Orchard.Recipes.Models; @@ -26,14 +26,14 @@ using Orchard.Settings; using Orchard.Utility.Extensions; namespace Orchard.Setup.Services { - public class SetupService : ISetupService { + [OrchardFeature("Orchard.Setup.Services")] + public class SetupService : Component, ISetupService { private readonly ShellSettings _shellSettings; private readonly IOrchardHost _orchardHost; private readonly IShellSettingsManager _shellSettingsManager; private readonly IShellContainerFactory _shellContainerFactory; private readonly ICompositionStrategy _compositionStrategy; private readonly IProcessingEngine _processingEngine; - private readonly IExtensionManager _extensionManager; private readonly IRecipeHarvester _recipeHarvester; private IEnumerable _recipes; @@ -44,23 +44,17 @@ namespace Orchard.Setup.Services { IShellContainerFactory shellContainerFactory, ICompositionStrategy compositionStrategy, IProcessingEngine processingEngine, - IExtensionManager extensionManager, IRecipeHarvester recipeHarvester) { + _shellSettings = shellSettings; _orchardHost = orchardHost; _shellSettingsManager = shellSettingsManager; _shellContainerFactory = shellContainerFactory; _compositionStrategy = compositionStrategy; _processingEngine = processingEngine; - _extensionManager = extensionManager; _recipeHarvester = recipeHarvester; - T = NullLocalizer.Instance; - Logger = NullLogger.Instance; } - public Localizer T { get; set; } - public ILogger Logger { get; set; } - public ShellSettings Prime() { return _shellSettings; } @@ -68,54 +62,60 @@ namespace Orchard.Setup.Services { public IEnumerable Recipes() { if (_recipes == null) { var recipes = new List(); - - foreach (var extension in _extensionManager.AvailableExtensions()) { - recipes.AddRange(_recipeHarvester.HarvestRecipes(extension.Id).Where(recipe => recipe.IsSetupRecipe)); - } - + recipes.AddRange(_recipeHarvester.HarvestRecipes().Where(recipe => recipe.IsSetupRecipe)); _recipes = recipes; } - return _recipes; } public string Setup(SetupContext context) { + var initialState = _shellSettings.State; + try { + return SetupInternal(context); + } + catch { + _shellSettings.State = initialState; + throw; + } + } + + private string SetupInternal(SetupContext context) { string executionId; Logger.Information("Running setup for tenant '{0}'.", _shellSettings.Name); // The vanilla Orchard distibution has the following features enabled. string[] hardcoded = { - // Framework - "Orchard.Framework", - // Core - "Common", "Containers", "Contents", "Dashboard", "Feeds", "Navigation","Scheduling", "Settings", "Shapes", "Title", - // Modules - "Orchard.Pages", "Orchard.ContentPicker", "Orchard.Themes", "Orchard.Users", "Orchard.Roles", "Orchard.Modules", - "PackagingServices", "Orchard.Packaging", "Gallery", "Orchard.Recipes" - }; + // Framework + "Orchard.Framework", + // Core + "Common", "Containers", "Contents", "Dashboard", "Feeds", "Navigation","Scheduling", "Settings", "Shapes", "Title", + // Modules + "Orchard.Pages", "Orchard.ContentPicker", "Orchard.Themes", "Orchard.Users", "Orchard.Roles", "Orchard.Modules", + "PackagingServices", "Orchard.Packaging", "Gallery", "Orchard.Recipes" + }; context.EnabledFeatures = hardcoded.Union(context.EnabledFeatures ?? Enumerable.Empty()).Distinct().ToList(); + // Set shell state to "Initializing" so that subsequent HTTP requests are responded to with "Service Unavailable" while Orchard is setting up. + _shellSettings.State = TenantState.Initializing; + var shellSettings = new ShellSettings(_shellSettings); - if (string.IsNullOrEmpty(shellSettings.DataProvider)) { + if (String.IsNullOrEmpty(shellSettings.DataProvider)) { shellSettings.DataProvider = context.DatabaseProvider; shellSettings.DataConnectionString = context.DatabaseConnectionString; shellSettings.DataTablePrefix = context.DatabaseTablePrefix; } - #region Encryption Settings - shellSettings.EncryptionAlgorithm = "AES"; - // randomly generated key + + // Randomly generated key. shellSettings.EncryptionKey = SymmetricAlgorithm.Create(shellSettings.EncryptionAlgorithm).Key.ToHexString(); - shellSettings.HashAlgorithm = "HMACSHA256"; - // randomly generated key - shellSettings.HashKey = HMAC.Create(shellSettings.HashAlgorithm).Key.ToHexString(); - #endregion + // Randomly generated key. + shellSettings.HashKey = HMAC.Create(shellSettings.HashAlgorithm).Key.ToHexString(); var shellDescriptor = new ShellDescriptor { Features = context.EnabledFeatures.Select(name => new ShellFeature { Name = name }) @@ -123,12 +123,12 @@ namespace Orchard.Setup.Services { var shellBlueprint = _compositionStrategy.Compose(shellSettings, shellDescriptor); - // initialize database explicitly, and store shell descriptor + // Initialize database explicitly, and store shell descriptor. using (var bootstrapLifetimeScope = _shellContainerFactory.CreateContainer(shellSettings, shellBlueprint)) { using (var environment = bootstrapLifetimeScope.CreateWorkContextScope()) { - // check if the database is already created (in case an exception occured in the second phase) + // Check if the database is already created (in case an exception occured in the second phase). var schemaBuilder = new SchemaBuilder(environment.Resolve()); var installationPresent = true; try { @@ -143,7 +143,7 @@ namespace Orchard.Setup.Services { throw new OrchardException(T("A previous Orchard installation was detected in this database with this table prefix.")); } - // Make a workaround to avoid the Transaction issue for PostgreSQL + // Workaround to avoid some Transaction issue for PostgreSQL. environment.Resolve().RequireNew(); schemaBuilder.CreateTable("Orchard_Framework_DataMigrationRecord", table => table @@ -168,16 +168,13 @@ namespace Orchard.Setup.Services { } } - // in effect "pump messages" see PostMessage circa 1980 + // In effect "pump messages" see PostMessage circa 1980. while (_processingEngine.AreTasksPending()) _processingEngine.ExecuteNextTask(); - // creating a standalone environment. + // Creating a standalone environment. // in theory this environment can be used to resolve any normal components by interface, and those - // components will exist entirely in isolation - no crossover between the safemode container currently in effect - - // must mark state as Running - otherwise standalone enviro is created "for setup" - shellSettings.State = TenantState.Running; + // components will exist entirely in isolation - no crossover between the safemode container currently in effect. using (var environment = _orchardHost.CreateStandaloneEnvironment(shellSettings)) { try { executionId = CreateTenantData(context, environment); @@ -189,23 +186,21 @@ namespace Orchard.Setup.Services { } _shellSettingsManager.SaveSettings(shellSettings); - return executionId; } private string CreateTenantData(SetupContext context, IWorkContextScope environment) { - // create superuser + // Create site owner. var membershipService = environment.Resolve(); - var user = - membershipService.CreateUser(new CreateUserParams(context.AdminUsername, context.AdminPassword, - String.Empty, String.Empty, String.Empty, - true)); + var user = membershipService.CreateUser( + new CreateUserParams(context.AdminUsername, context.AdminPassword, + String.Empty, String.Empty, String.Empty, true)); - // set superuser as current user for request (it will be set as the owner of all content items) + // Set site owner as current user for request (it will be set as the owner of all content items). var authenticationService = environment.Resolve(); authenticationService.SetAuthenticatedUserForRequest(user); - // set site name and settings + // Set site name and settings. var siteService = environment.Resolve(); var siteSettings = siteService.GetSiteSettings().As(); siteSettings.SiteSalt = Guid.NewGuid().ToString("N"); @@ -213,19 +208,27 @@ namespace Orchard.Setup.Services { siteSettings.SuperUser = context.AdminUsername; siteSettings.SiteCulture = "en-US"; - // add default culture + // Add default culture. var cultureManager = environment.Resolve(); cultureManager.AddCulture("en-US"); var recipeManager = environment.Resolve(); - var recipe = Recipes().FirstOrDefault(r => r.Name.Equals(context.Recipe, StringComparison.OrdinalIgnoreCase)); - - if (recipe == null) - throw new OrchardException(T("The recipe '{0}' could not be found.", context.Recipe)); - + var recipe = context.Recipe; var executionId = recipeManager.Execute(recipe); - // null check: temporary fix for running setup in command line + // Once the recipe has finished executing, we need to update the shell state to "Running", so add a recipe step that does exactly that. + var recipeStepQueue = environment.Resolve(); + var recipeStepResultRecordRepository = environment.Resolve>(); + var activateShellStep = new RecipeStep(Guid.NewGuid().ToString("N"), recipe.Name, "ActivateShell", new XElement("ActivateShell")); + recipeStepQueue.Enqueue(executionId, activateShellStep); + recipeStepResultRecordRepository.Create(new RecipeStepResultRecord { + ExecutionId = executionId, + RecipeName = recipe.Name, + StepId = activateShellStep.Id, + StepName = activateShellStep.Name + }); + + // Null check: temporary fix for running setup in command line. if (HttpContext.Current != null) { authenticationService.SignIn(user, true); } diff --git a/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs b/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs index ec675dac8..e0ee00076 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs +++ b/src/Orchard.Web/Modules/Orchard.Setup/SetupMode.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Web.Routing; using Autofac; using Orchard.Caching; diff --git a/src/Orchard.Web/Modules/Orchard.Setup/ViewModels/SetupDatabaseType.cs b/src/Orchard.Web/Modules/Orchard.Setup/ViewModels/SetupDatabaseType.cs new file mode 100644 index 000000000..f57a86748 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Setup/ViewModels/SetupDatabaseType.cs @@ -0,0 +1,10 @@ +namespace Orchard.Setup.ViewModels +{ + public enum SetupDatabaseType + { + Builtin, + SqlServer, + MySql, + PostgreSql, + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Views/Setup/Index.cshtml b/src/Orchard.Web/Modules/Orchard.Setup/Views/Setup/Index.cshtml index b1990c468..9f6fe9130 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Views/Setup/Index.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Setup/Views/Setup/Index.cshtml @@ -1,5 +1,6 @@ @model Orchard.Setup.ViewModels.SetupViewModel @using Orchard.Recipes.Models; +@using Orchard.Setup.ViewModels @{ Script.Require("jQuery"); Script.Require("ShapesBase"); @@ -47,19 +48,19 @@ if (!Model.DatabaseIsPreconfigured) { @T("How would you like to store your data?") @Html.ValidationMessage("DatabaseOptions", "Unable to setup data storage.")
- @Html.RadioButtonFor(svm => svm.DatabaseProvider, Orchard.Setup.Controllers.SetupDatabaseType.Builtin.ToString(), new { id = "builtin" }) + @Html.RadioButtonFor(svm => svm.DatabaseProvider, SetupDatabaseType.Builtin.ToString(), new { id = "builtin" })
- @Html.RadioButtonFor(svm => svm.DatabaseProvider, Orchard.Setup.Controllers.SetupDatabaseType.SqlServer.ToString(), new { id = "sqlserver" }) + @Html.RadioButtonFor(svm => svm.DatabaseProvider, SetupDatabaseType.SqlServer.ToString(), new { id = "sqlserver" })
- @Html.RadioButtonFor(svm => svm.DatabaseProvider, Orchard.Setup.Controllers.SetupDatabaseType.MySql.ToString(), new { id = "mysql" }) + @Html.RadioButtonFor(svm => svm.DatabaseProvider, SetupDatabaseType.MySql.ToString(), new { id = "mysql" })
- @Html.RadioButtonFor(svm => svm.DatabaseProvider, Orchard.Setup.Controllers.SetupDatabaseType.PostgreSql.ToString(), new { id = "postgresql" }) + @Html.RadioButtonFor(svm => svm.DatabaseProvider, SetupDatabaseType.PostgreSql.ToString(), new { id = "postgresql" })
diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Drivers/TagCloudDriver.cs b/src/Orchard.Web/Modules/Orchard.Tags/Drivers/TagCloudDriver.cs index 345c8f576..eb3fe1538 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Drivers/TagCloudDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Tags/Drivers/TagCloudDriver.cs @@ -43,6 +43,11 @@ namespace Orchard.Tags.Drivers { } protected override void Importing(TagCloudPart part, ImportContentContext context) { + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; + } + part.Slug = context.Attribute(part.PartDefinition.Name, "Slug"); part.Buckets = Convert.ToInt32(context.Attribute(part.PartDefinition.Name, "Buckets")); } diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Drivers/TagsPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Tags/Drivers/TagsPartDriver.cs index 2c42a27c8..669ed9df7 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Drivers/TagsPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Tags/Drivers/TagsPartDriver.cs @@ -70,6 +70,11 @@ namespace Orchard.Tags.Drivers { } protected override void Importing(TagsPart part, ImportContentContext context) { + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; + } + var tagString = context.Attribute(part.PartDefinition.Name, "Tags"); if (tagString != null) { var tags = tagString.Split(new[] {","}, StringSplitOptions.RemoveEmptyEntries); diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Module.txt b/src/Orchard.Web/Modules/Orchard.Tags/Module.txt index 5fedb9b0e..c29f0a14b 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Tags/Module.txt @@ -2,7 +2,7 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Features: Orchard.Tags: diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Tags/Properties/AssemblyInfo.cs index 62e65e560..2c420e1bd 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Tags/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Services/TagCloudService.cs b/src/Orchard.Web/Modules/Orchard.Tags/Services/TagCloudService.cs index 26dbf2c52..a05644f69 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Services/TagCloudService.cs +++ b/src/Orchard.Web/Modules/Orchard.Tags/Services/TagCloudService.cs @@ -32,7 +32,7 @@ namespace Orchard.Tags.Services { public IEnumerable GetPopularTags(int buckets, string slug) { var cacheKey = "Orchard.Tags.TagCloud." + (slug ?? "") + '.' + buckets; - return _cacheManager.Get(cacheKey, + return _cacheManager.Get(cacheKey, true, ctx => { ctx.Monitor(_signals.When(TagCloudTagsChanged)); IEnumerable tagCounts; diff --git a/src/Orchard.Web/Modules/Orchard.TaskLease/Models/TaskLeaseRecord.cs b/src/Orchard.Web/Modules/Orchard.TaskLease/Models/TaskLeaseRecord.cs index 3e28a67f3..039e0d27e 100644 --- a/src/Orchard.Web/Modules/Orchard.TaskLease/Models/TaskLeaseRecord.cs +++ b/src/Orchard.Web/Modules/Orchard.TaskLease/Models/TaskLeaseRecord.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; using Orchard.Data.Conventions; namespace Orchard.TaskLease.Models diff --git a/src/Orchard.Web/Modules/Orchard.TaskLease/Module.txt b/src/Orchard.Web/Modules/Orchard.TaskLease/Module.txt index 7748ef35a..868d44247 100644 --- a/src/Orchard.Web/Modules/Orchard.TaskLease/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.TaskLease/Module.txt @@ -2,7 +2,7 @@ Name: Task Lease AntiForgery: enabled Author: The Orchard Team Website: http://orchardtasklease.codeplex.com -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 LifecycleStatus: Deprecated Description: Provides services to synchronize tasks in a farm environment. diff --git a/src/Orchard.Web/Modules/Orchard.TaskLease/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.TaskLease/Properties/AssemblyInfo.cs index 3dabfb343..b2b8e12fd 100644 --- a/src/Orchard.Web/Modules/Orchard.TaskLease/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.TaskLease/Properties/AssemblyInfo.cs @@ -31,6 +31,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.TaskLease/Services/ITaskLeaseService.cs b/src/Orchard.Web/Modules/Orchard.TaskLease/Services/ITaskLeaseService.cs index 625472446..c32e3d37e 100644 --- a/src/Orchard.Web/Modules/Orchard.TaskLease/Services/ITaskLeaseService.cs +++ b/src/Orchard.Web/Modules/Orchard.TaskLease/Services/ITaskLeaseService.cs @@ -6,7 +6,7 @@ namespace Orchard.TaskLease.Services { /// Describes a service to save and acquire task leases. A task lease can't be acquired by two different machines, /// for a specific amount of time. Optionnally a State can be saved along with the lease. /// - [Obsolete("Use Orchard.Tasks.Locking.IDistributedLockService and the AcquireLockForMachine/TryAcquireLockForMachine methods instead.")] + [Obsolete("Use Orchard.Tasks.Locking.IDistributedLockService instead.")] public interface ITaskLeaseService : IDependency { /// diff --git a/src/Orchard.Web/Modules/Orchard.TaskLease/Services/TaskLeaseService.cs b/src/Orchard.Web/Modules/Orchard.TaskLease/Services/TaskLeaseService.cs index 8cf04b3fe..0c1025173 100644 --- a/src/Orchard.Web/Modules/Orchard.TaskLease/Services/TaskLeaseService.cs +++ b/src/Orchard.Web/Modules/Orchard.TaskLease/Services/TaskLeaseService.cs @@ -9,25 +9,25 @@ namespace Orchard.TaskLease.Services { /// /// Provides a database driven implementation of /// - [Obsolete("Use Orchard.Tasks.Locking.DistributedLockService and the AcquireLockForMachine/TryAcquireLockForMachine methods instead.")] + [Obsolete("Use Orchard.Tasks.Locking.DistributedLockService instead.")] public class TaskLeaseService : ITaskLeaseService { private readonly IRepository _repository; private readonly IClock _clock; - private readonly IMachineNameProvider _machineNameProvider; + private readonly IApplicationEnvironment _applicationEnvironment; public TaskLeaseService( IRepository repository, IClock clock, - IMachineNameProvider machineNameProvider) { + IApplicationEnvironment applicationEnvironment) { _repository = repository; _clock = clock; - _machineNameProvider = machineNameProvider; + _applicationEnvironment = applicationEnvironment; } public string Acquire(string taskName, DateTime expiredUtc) { - var machineName = _machineNameProvider.GetMachineName(); + var environmentIdentifier = _applicationEnvironment.GetEnvironmentIdentifier(); // retrieve current lease for the specified task var taskLease = _repository.Get(x => x.TaskName == taskName); @@ -36,7 +36,7 @@ namespace Orchard.TaskLease.Services { if (taskLease == null) { taskLease = new TaskLeaseRecord { TaskName = taskName, - MachineName = machineName, + MachineName = environmentIdentifier, State = String.Empty, UpdatedUtc = _clock.UtcNow, ExpiredUtc = expiredUtc @@ -49,12 +49,12 @@ namespace Orchard.TaskLease.Services { } // lease can't be aquired only if for a different machine and it has not expired - if (taskLease.MachineName != machineName && taskLease.ExpiredUtc >= _clock.UtcNow) { + if (taskLease.MachineName != environmentIdentifier && taskLease.ExpiredUtc >= _clock.UtcNow) { return null; } // otherwise update information - taskLease.MachineName = machineName; + taskLease.MachineName = environmentIdentifier; taskLease.UpdatedUtc = _clock.UtcNow; taskLease.ExpiredUtc = expiredUtc; @@ -64,10 +64,10 @@ namespace Orchard.TaskLease.Services { } public void Update(string taskName, string state) { - var machineName = _machineNameProvider.GetMachineName(); + var environmentIdentifier = _applicationEnvironment.GetEnvironmentIdentifier(); // retrieve current lease for the specified task - var taskLease = _repository.Get(x => x.TaskName == taskName && x.MachineName == machineName); + var taskLease = _repository.Get(x => x.TaskName == taskName && x.MachineName == environmentIdentifier); if (taskLease == null) { return; @@ -78,10 +78,10 @@ namespace Orchard.TaskLease.Services { } public void Update(string taskName, string state, DateTime expiredUtc) { - var machineName = _machineNameProvider.GetMachineName(); + var environmentIdentifier = _applicationEnvironment.GetEnvironmentIdentifier(); // retrieve current lease for the specified task - var taskLease = _repository.Get(x => x.TaskName == taskName && x.MachineName == machineName); + var taskLease = _repository.Get(x => x.TaskName == taskName && x.MachineName == environmentIdentifier); if (taskLease == null) { return; diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Controllers/TagsController.cs b/src/Orchard.Web/Modules/Orchard.Taxonomies/Controllers/TagsController.cs new file mode 100644 index 000000000..bc1d929f3 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Controllers/TagsController.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Web.Http; +using Orchard.ContentManagement; +using Orchard.Core.Title.Models; +using Orchard.Localization; +using Orchard.Logging; +using Orchard.Taxonomies.Helpers; +using Orchard.Taxonomies.Models; +using Orchard.Taxonomies.Services; +using System.Linq; +using Orchard.Security; +using Orchard.Taxonomies.ViewModels; + +namespace Orchard.Taxonomies.Controllers { + public class TagsController : ApiController { + private readonly ITaxonomyService _taxonomyService; + private readonly IContentManager _contentManager; + private readonly IAuthorizer _authorizer; + public Localizer T { get; set; } + protected ILogger Logger { get; set; } + + public TagsController( + ITaxonomyService taxonomyService, + IContentManager contentManager, + IAuthorizer authorizer) { + _taxonomyService = taxonomyService; + T = NullLocalizer.Instance; + _contentManager = contentManager; + _authorizer = authorizer; + Logger = NullLogger.Instance; + } + + public IEnumerable Get(int taxonomyId, bool leavesOnly, string query) { + if (!_authorizer.Authorize(StandardPermissions.AccessAdminPanel)) { + throw new UnauthorizedAccessException("Can't access the admin"); + } + if (string.IsNullOrEmpty(query)) return new List(); + var allTerms = leavesOnly + ? _taxonomyService.GetTerms(taxonomyId).ToList() + : new List(); + var matchingTerms = _contentManager.Query() + .Where(t => t.TaxonomyId == taxonomyId) + .Join() + .Where(r => r.Title.Contains(query)) + .List() + .Select(t => BuildTag(t, leavesOnly, allTerms)) + .OrderBy(t => t.Label) + .ToList(); + return matchingTerms; + } + + private static Tag BuildTag(TermPart term, bool leavesOnly, IEnumerable terms) { + return new Tag { + Value = term.Id, + Label = term.Name, + Disabled = !term.Selectable || (leavesOnly && terms.Any(t => t.Path.Contains(term.Path + term.Id))), + Levels = term.GetLevels() + }; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Drivers/TaxonomyFieldDriver.cs b/src/Orchard.Web/Modules/Orchard.Taxonomies/Drivers/TaxonomyFieldDriver.cs index 7cbc32363..eed4d476c 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Drivers/TaxonomyFieldDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Drivers/TaxonomyFieldDriver.cs @@ -60,7 +60,7 @@ namespace Orchard.Taxonomies.Drivers { var settings = field.PartFieldDefinition.Settings.GetModel(); var appliedTerms = GetAppliedTerms(part, field, VersionOptions.Latest).ToDictionary(t => t.Id, t => t); var taxonomy = _taxonomyService.GetTaxonomyByName(settings.Taxonomy); - var terms = taxonomy != null + var terms = taxonomy != null && !settings.Autocomplete ? _taxonomyService.GetTerms(taxonomy.Id).Where(t => !string.IsNullOrWhiteSpace(t.Name)).Select(t => t.CreateTermEntry()).ToList() : new List(0); @@ -70,9 +70,11 @@ namespace Orchard.Taxonomies.Drivers { DisplayName = field.DisplayName, Name = field.Name, Terms = terms, + SelectedTerms = appliedTerms.Select(t => t.Value), Settings = settings, - SingleTermId = terms.Where(t => t.IsChecked).Select(t => t.Id).FirstOrDefault(), - TaxonomyId = taxonomy != null ? taxonomy.Id : 0 + SingleTermId = appliedTerms.Select(t => t.Key).FirstOrDefault(), + TaxonomyId = taxonomy != null ? taxonomy.Id : 0, + HasTerms = taxonomy != null && _taxonomyService.GetTermsCount(taxonomy.Id) > 0 }; var templateName = settings.Autocomplete ? "Fields/TaxonomyField.Autocomplete" : "Fields/TaxonomyField"; @@ -108,10 +110,10 @@ namespace Orchard.Taxonomies.Drivers { var appliedTerms = _taxonomyService.GetTermsForContentItem(part.ContentItem.Id, field.Name); // stores all content items associated to this field - var termIdentities = appliedTerms.Select(x => Services.ContentManager.GetItemMetadata(x).Identity.ToString()) - .ToArray(); + var termIdentities = appliedTerms.Select(x => Services.ContentManager.GetItemMetadata(x).Identity.ToString()).ToArray(); - context.Element(XmlConvert.EncodeLocalName(field.FieldDefinition.Name + "." + field.Name)).SetAttributeValue("Terms", String.Join(",", termIdentities)); + if (termIdentities.Any()) + context.Element(XmlConvert.EncodeLocalName(field.FieldDefinition.Name + "." + field.Name)).SetAttributeValue("Terms", String.Join(",", termIdentities)); } protected override void Importing(ContentPart part, TaxonomyField field, ImportContentContext context) { diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Drivers/TaxonomyNavigationPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Taxonomies/Drivers/TaxonomyNavigationPartDriver.cs index 2e94695b4..58bf62dc9 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Drivers/TaxonomyNavigationPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Drivers/TaxonomyNavigationPartDriver.cs @@ -101,6 +101,11 @@ namespace Orchard.Taxonomies.Drivers { } protected override void Importing(TaxonomyNavigationPart part, ImportContentContext context) { + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; + } + part.DisplayContentCount = Boolean.Parse(context.Attribute(part.PartDefinition.Name, "DisplayContentCount")); part.DisplayRootTerm = Boolean.Parse(context.Attribute(part.PartDefinition.Name, "DisplayRootTerm")); part.HideEmptyTerms = Boolean.Parse(context.Attribute(part.PartDefinition.Name, "HideEmptyTerms")); diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Drivers/TaxonomyPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Taxonomies/Drivers/TaxonomyPartDriver.cs index 017664b74..e796aa789 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Drivers/TaxonomyPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Drivers/TaxonomyPartDriver.cs @@ -65,6 +65,11 @@ namespace Orchard.Taxonomies.Drivers { } protected override void Importing(TaxonomyPart part, ImportContentContext context) { + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; + } + part.TermTypeName = context.Attribute(part.PartDefinition.Name, "TermTypeName"); } } diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Drivers/TermPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Taxonomies/Drivers/TermPartDriver.cs index 10440230b..c99b638a6 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Drivers/TermPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Drivers/TermPartDriver.cs @@ -126,6 +126,11 @@ namespace Orchard.Taxonomies.Drivers { } protected override void Importing(TermPart part, ImportContentContext context) { + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; + } + part.Count = Int32.Parse(context.Attribute(part.PartDefinition.Name, "Count")); part.Selectable = Boolean.Parse(context.Attribute(part.PartDefinition.Name, "Selectable")); part.Weight = Int32.Parse(context.Attribute(part.PartDefinition.Name, "Weight")); diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Module.txt b/src/Orchard.Web/Modules/Orchard.Taxonomies/Module.txt index bf7079a4e..294a899c6 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Module.txt @@ -2,7 +2,7 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: The taxonomy module is providing custom categorization of arbitrary content types. Features: diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Orchard.Taxonomies.csproj b/src/Orchard.Web/Modules/Orchard.Taxonomies/Orchard.Taxonomies.csproj index 28d48a98d..b3725af1a 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Orchard.Taxonomies.csproj +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Orchard.Taxonomies.csproj @@ -50,6 +50,9 @@ + + ..\..\..\..\lib\newtonsoft.json\Newtonsoft.Json.dll + 3.5 @@ -59,6 +62,10 @@ + + False + ..\..\..\..\lib\aspnetwebapi\System.Web.Http.dll + False ..\..\..\..\lib\aspnetmvc\System.Web.Mvc.dll @@ -72,6 +79,8 @@ + + diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Taxonomies/Properties/AssemblyInfo.cs index 2e45f4835..92f4e3d3d 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Scripts/admin-taxonomy-tags.js b/src/Orchard.Web/Modules/Orchard.Taxonomies/Scripts/admin-taxonomy-tags.js index 26518b153..95033e84b 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Scripts/admin-taxonomy-tags.js +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Scripts/admin-taxonomy-tags.js @@ -2,49 +2,24 @@ /* Helper functions **********************************************************************/ - var addTag = function ($plugin, label) { - $plugin.tagit("add", label); - }; - - var removeTag = function ($plugin, label) { - var tags = $plugin.tagit("tags"); - var index = findTagIndexByLabel(tags, label); - - if (index == -1) - return; - - tags.splice(index, 1); - $plugin.tagit("fill", tags); - }; - - var findTagIndexByLabel = function (tags, label) { - for (var i = 0; i < tags.length; i++) { - var tag = tags[i]; - - if (tag.label == label) { - return i; - } - } - return -1; - }; - var createTermCheckbox = function ($wrapper, tag) { var $ul = $("ul.terms", $wrapper); var singleChoice = $(".terms-editor", $wrapper).data("singlechoice"); var namePrefix = $wrapper.data("name-prefix"); var idPrefix = $wrapper.data("id-prefix"); var nextIndex = $("li", $ul).length; + var id = isNaN(tag.value) ? -nextIndex : tag.value; var checkboxId = idPrefix + "_Terms_" + nextIndex + "__IsChecked"; var checkboxName = namePrefix + ".Terms[" + nextIndex + "].IsChecked"; var radioName = namePrefix + ".SingleTermId"; - var checkboxHtml = ""; - var radioHtml = ""; + var checkboxHtml = ""; + var radioHtml = ""; var inputHtml = singleChoice ? radioHtml : checkboxHtml; var $li = $("
  • " + inputHtml + - "" + - "" + - "" + + "" + + "" + + "" + "
  • ").hide(); if (singleChoice) { @@ -68,67 +43,20 @@ var $tagIt = $("ul.tagit", $wrapper); var singleChoice = $(".terms-editor", $wrapper).data("singlechoice"); var $terms = $("ul.terms", $wrapper); - var $termCheckbox = $("input[data-term-identity='" + tag.label.toLowerCase() + "']", $terms).filter(function () { - return $(this).siblings("input[value='" + tag.value + "']").length; - }); - - if ($termCheckbox.is(":disabled")) { - removeTag($tagIt, tagLabelOrValue); - return; - } - - if ($termCheckbox.length == 0 && action == "added") { - createTermCheckbox($wrapper, tag.label, this); - } - - $termCheckbox.prop("checked", action == "added"); if (singleChoice && action == "added") { - $tagIt.tagit("fill", [tag.label]); + $tagIt.tagit("fill", tag); } - if (singleChoice) { - if (action == "added") { - var $option = $("select.term-picker", $wrapper).find("option[data-term-identity='" + tag.label.toLowerCase() + "']"); - $option.remove(); - } else { - $("select.term-picker", $wrapper).append(""); - } - } + $terms.empty(); + + $($tagIt.tagit("tags")).each(function (index, tag) { + createTermCheckbox($wrapper, tag, this); + }); $(".no-terms", $wrapper).hide(); }; - $("fieldset.taxonomy-wrapper .expando").on("change", "input[data-term]:enabled", function(e) { - var $checkbox = $(this); - var term = $checkbox.data("term"); - var $wrapper = $checkbox.parents("fieldset.taxonomy-wrapper:first"); - var $tagIt = $("ul.tagit", $wrapper); - var isChecked = $checkbox.is(":checked"); - - isChecked ? addTag($tagIt, term) : removeTag($tagIt, term); - }); - - $("select.term-picker").change(function (e) { - var $select = $(this); - var $firstOption = $("option:first", $select); - - if ($firstOption.is(":selected")) - return; - - var $selecedOption = $("option:selected", $select); - var $wrapper = $select.parents("fieldset.taxonomy-wrapper:first"); - var $tagIt = $("ul.tagit", $wrapper); - var term = $selecedOption.text(); - var singleChoice = $(".terms-editor", $wrapper).data("singlechoice"); - - addTag($tagIt, term); - $select.val(""); - - if (!singleChoice) - $selecedOption.remove(); - }); - var renderAutocompleteItem = function (ul, item) { var label = item.label; @@ -148,20 +76,28 @@ /* Initialization **********************************************************************/ $(".terms-editor").each(function () { - var allTerms = $(this).data("all-terms"); var selectedTerms = $(this).data("selected-terms"); var $tagit = $("> ul", this).tagit({ - tagSource: allTerms, + tagSource: function (request, response) { + var termsEditor = $(this.element).parents(".terms-editor"); + $.getJSON("/api/taxonomies/tags", { taxonomyId: termsEditor.data("taxonomy-id"), leavesOnly: termsEditor.data("leaves-only"), query: request.term }, function (data, status, xhr) { + response(data); + }); + }, initialTags: selectedTerms, triggerKeys: ['enter', 'tab'], // default is ['enter', 'space', 'comma', 'tab'] but we remove comma and space to allow them in the terms allowNewTags: $(this).data("allow-new-terms"), tagsChanged: onTagsChanged, caseSensitive: false, - minLength: 0 - }).data("uiTagit"); + minLength: 0, + sortable: true + }).data("ui-tagit"); - $tagit.input.autocomplete().data("uiAutocomplete")._renderItem = renderAutocompleteItem; + $tagit.input.autocomplete().data("ui-autocomplete")._renderItem = renderAutocompleteItem; + $tagit.input.autocomplete().on("autocompletefocus", function (event, ui) { + event.preventDefault(); + }); }); diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Services/ITaxonomyService.cs b/src/Orchard.Web/Modules/Orchard.Taxonomies/Services/ITaxonomyService.cs index ab31ba19b..fd3cd01a7 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Services/ITaxonomyService.cs +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Services/ITaxonomyService.cs @@ -41,6 +41,7 @@ namespace Orchard.Taxonomies.Services { IEnumerable GetTerms(int taxonomyId); + int GetTermsCount(int taxonomyId); TermPart GetTerm(int id); TermPart GetTermByName(int taxonomyId, string name); void DeleteTerm(TermPart termPart); diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Services/TaxonomyService.cs b/src/Orchard.Web/Modules/Orchard.Taxonomies/Services/TaxonomyService.cs index a6d6b14d0..296f41a2b 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Services/TaxonomyService.cs +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Services/TaxonomyService.cs @@ -185,6 +185,12 @@ namespace Orchard.Taxonomies.Services { return TermPart.Sort(result); } + public int GetTermsCount(int taxonomyId) { + return _contentManager.Query() + .Where(x => x.TaxonomyId == taxonomyId) + .Count(); + } + public TermPart GetTerm(int id) { return _contentManager .Query() diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Services/TermCountProcessor.cs b/src/Orchard.Web/Modules/Orchard.Taxonomies/Services/TermCountProcessor.cs index b10459ea8..3d9251b07 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Services/TermCountProcessor.cs +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Services/TermCountProcessor.cs @@ -1,17 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; using Orchard.ContentManagement; using Orchard.Taxonomies.Models; namespace Orchard.Taxonomies.Services { public class TermCountProcessor : ITermCountProcessor { - private readonly IContentManager _contentManager; private readonly ITaxonomyService _taxonomyService; - public TermCountProcessor(IContentManager contentManager, ITaxonomyService taxonomyService) { - _contentManager = contentManager; + public TermCountProcessor(ITaxonomyService taxonomyService) { _taxonomyService = taxonomyService; } @@ -31,4 +25,4 @@ namespace Orchard.Taxonomies.Services { } } } -} \ No newline at end of file +} diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Styles/admin-taxonomy-tags.css b/src/Orchard.Web/Modules/Orchard.Taxonomies/Styles/admin-taxonomy-tags.css index 48db0b876..115a4fffd 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Styles/admin-taxonomy-tags.css +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Styles/admin-taxonomy-tags.css @@ -2,6 +2,10 @@ opacity: 0.3; } +.ui-autocomplete .ui-menu-item { + float: none; +} + .ui-autocomplete .ui-menu-item a { font-size: 0.8em; } diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Tokens/TaxonomyTokens.cs b/src/Orchard.Web/Modules/Orchard.Taxonomies/Tokens/TaxonomyTokens.cs index 3b2a9edc2..e921232ed 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Tokens/TaxonomyTokens.cs +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Tokens/TaxonomyTokens.cs @@ -31,21 +31,33 @@ namespace Orchard.Taxonomies.Tokens { context.For("TaxonomyField") .Token("Terms", field => String.Join(", ", field.Terms.Select(t => t.Name).ToArray())) - .Token( - token => { - var index = 0; - return (token.StartsWith("Terms:", StringComparison.OrdinalIgnoreCase) && int.TryParse(token.Substring("Terms:".Length), out index)) ? index.ToString() : null; - }, - (token, t) => { - var index = Convert.ToInt32(token); - return index + 1 > t.Terms.Count() ? null : t.Terms.ElementAt(index).Name; + .Token(FilterTokenParam, + (index, field) => { + var term = field.Terms.ElementAtOrDefault(Convert.ToInt32(index)); + return term != null ? term.Name : null; }) - // todo: extend Chain() in order to accept a filter like in Token() so that we can chain on an expression - .Chain("Terms:0", "Content", t => t.Terms.ElementAt(0)) - .Chain("Terms:1", "Content", t => t.Terms.ElementAt(1)) - .Chain("Terms:2", "Content", t => t.Terms.ElementAt(2)) - .Chain("Terms:3", "Content", t => t.Terms.ElementAt(3)) + .Chain(FilterChainParam, "Content", (index, field) => field.Terms.ElementAtOrDefault(Convert.ToInt32(index))) ; } + + private static string FilterTokenParam(string token) { + int index = 0; + return (token.StartsWith("Terms:", StringComparison.OrdinalIgnoreCase) && int.TryParse(token.Substring("Terms:".Length), out index)) ? index.ToString() : null; + } + + private static Tuple FilterChainParam(string token) { + int tokenLength = "Terms:".Length; + int index = 0; + int chainIndex = token.IndexOf('.'); + if (!token.StartsWith("Terms:", StringComparison.OrdinalIgnoreCase) || chainIndex <= tokenLength) + return null; + + if (int.TryParse(token.Substring(tokenLength, chainIndex - tokenLength), out index)) { + return new Tuple(index.ToString(), token.Substring(chainIndex + 1)); + } + else { + return null; + } + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/ViewModels/Tag.cs b/src/Orchard.Web/Modules/Orchard.Taxonomies/ViewModels/Tag.cs new file mode 100644 index 000000000..e379d0653 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/ViewModels/Tag.cs @@ -0,0 +1,17 @@ +using Newtonsoft.Json; + +namespace Orchard.Taxonomies.ViewModels { + public class Tag { + [JsonProperty("label")] + public string Label { get; set; } + + [JsonProperty("value")] + public int Value { get; set; } + + [JsonProperty("levels")] + public int Levels { get; set; } + + [JsonProperty("disabled")] + public bool Disabled { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/ViewModels/TaxonomyFieldViewModel.cs b/src/Orchard.Web/Modules/Orchard.Taxonomies/ViewModels/TaxonomyFieldViewModel.cs index 1eccb5eda..948227fe7 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/ViewModels/TaxonomyFieldViewModel.cs +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/ViewModels/TaxonomyFieldViewModel.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Orchard.Taxonomies.Models; using Orchard.Taxonomies.Settings; namespace Orchard.Taxonomies.ViewModels { @@ -8,6 +9,8 @@ namespace Orchard.Taxonomies.ViewModels { public string DisplayName { get; set; } public TaxonomyFieldSettings Settings { get; set; } public IList Terms { get; set; } + public IEnumerable SelectedTerms { get; set; } public int SingleTermId { get; set; } + public bool HasTerms { get; set; } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/EditorTemplates/Fields/TaxonomyField.Autocomplete.cshtml b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/EditorTemplates/Fields/TaxonomyField.Autocomplete.cshtml index 173b44a6e..11f5e0f1b 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/EditorTemplates/Fields/TaxonomyField.Autocomplete.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/EditorTemplates/Fields/TaxonomyField.Autocomplete.cshtml @@ -1,5 +1,6 @@ @model TaxonomyFieldViewModel @using Orchard.Taxonomies.Helpers; +@using Orchard.Taxonomies.Models @using Orchard.Utility.Extensions; @using Orchard.Taxonomies.ViewModels; @@ -18,60 +19,61 @@ Script.Include("~/Themes/TheAdmin/scripts/admin.js").AtFoot(); Script.Include("admin-taxonomy-expando.js").AtFoot(); - var termIndex = 0; } @functions { - bool IsTermDisabled(TermEntry term) { + bool IsTermDisabled(TermPart term) { return !term.Selectable || (Model.Settings.LeavesOnly && Model.Terms.Any(t => t.Path.Contains(term.Path + term.Id))); } } @{ - var allTerms = Newtonsoft.Json.JsonConvert.SerializeObject(Model.Terms.Select(x => new { label = x.Name, value = x.Id, levels = x.GetLevels(), disabled = IsTermDisabled(x) })); - var selectedTerms = Newtonsoft.Json.JsonConvert.SerializeObject(Model.Terms.Where(x => x.IsChecked).Select(x => new { label = x.Name, value = x.Id, levels = 0, disabled = true })); + var termIndex = 0; + var checkedTerms = Model.SelectedTerms.ToList(); + var selectedTerms = Newtonsoft.Json.JsonConvert.SerializeObject(checkedTerms.Select(x => new { label = x.Name, value = x.Id, levels = 0, disabled = true })); + }
    - class="required" }>@Model.DisplayName + @if (Model.Settings.Autocomplete) { -
    -
      - @if (Model.Settings.SingleChoice) { -
      @T("Enter a single term. Hit tab or enter to apply the term.") @if (!Model.Settings.AllowCustomTerms) { @T("This taxonomy does not allow you to create new terms.") }
      - } - else { -
      @T("Enter multiple terms. Hit tab, enter or , to add multiple terms.") @if (!Model.Settings.AllowCustomTerms) { @T("This taxonomy does not allow you to create new terms.") }
      - } -
      +
      +
        + @if (Model.Settings.SingleChoice) { +
        @T("Enter a single term. Hit tab or enter to apply the term.") @if (!Model.Settings.AllowCustomTerms) { @T("This taxonomy does not allow you to create new terms.") }
        + } + else { +
        @T("Enter multiple terms. Hit tab, enter or , to add multiple terms.") @if (!Model.Settings.AllowCustomTerms) { @T("This taxonomy does not allow you to create new terms.") }
        + } +
        } @if (!String.IsNullOrWhiteSpace(Model.Settings.Hint)) { - @Model.Settings.Hint + @Model.Settings.Hint }
          - @foreach (var entry in Model.Terms) { - var ti = termIndex; -
        • - @{ - var disabled = IsTermDisabled(entry); - if (Model.Settings.SingleChoice) { - disabled="disabled" } type="radio" value="@Model.Terms[ti].Id" @if (entry.Id == Model.SingleTermId) { checked="checked" } name="@Html.FieldNameFor(m => m.SingleTermId)" id="@Html.FieldIdFor(m => m.Terms[ti].IsChecked)" data-term="@entry.Name" data-term-identity="@entry.Name.ToLower()" /> + @foreach (var entry in checkedTerms) { + var ti = termIndex; +
        • + @{ + var disabled = IsTermDisabled(entry); + if (Model.Settings.SingleChoice) { + disabled="disabled" } type="radio" value="@entry.Id" @if (entry.Id == Model.SingleTermId){ checked="checked" } name="@Html.FieldNameFor(m => m.SingleTermId)" id="@Html.FieldIdFor(m => m.Terms[ti].IsChecked)" data-term="@entry.Name" data-term-identity="@entry.Name.ToLower()" /> + } + else { + disabled="disabled" } type="checkbox" value="true" checked="checked" name="@Html.FieldNameFor(m => m.Terms[ti].IsChecked)" id="@Html.FieldIdFor(m => m.Terms[ti].IsChecked)" data-term="@entry.Name" data-term-identity="@entry.Name.ToLower()" /> + } } - else { - disabled="disabled" } type="checkbox" value="true" @if (entry.IsChecked) { checked="checked" } name="@Html.FieldNameFor(m => m.Terms[ti].IsChecked)" id="@Html.FieldIdFor(m => m.Terms[ti].IsChecked)" data-term="@entry.Name" data-term-identity="@entry.Name.ToLower()" /> - } - } - - @Html.HiddenFor(m => m.Terms[ti].Id) -
        • - termIndex++; - } + + + + termIndex++; + }
        - @if (!Model.Terms.Any()) { -
        - @T("There are no terms defined for {0} yet.", Model.DisplayName) - @T("Create some terms") -
        + @if (!Model.HasTerms && AuthorizedFor(Orchard.Taxonomies.Permissions.CreateTerm)) { +
        + @T("There are no terms defined for {0} yet.", Model.DisplayName.CamelFriendly()) + @T("Create some terms") +
        } @Html.HiddenFor(m => m.TaxonomyId)
        diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/EditorTemplates/Fields/TaxonomyField.cshtml b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/EditorTemplates/Fields/TaxonomyField.cshtml index 4e5656b4d..376b7169c 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/EditorTemplates/Fields/TaxonomyField.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Views/EditorTemplates/Fields/TaxonomyField.cshtml @@ -42,7 +42,7 @@ } - @if (!Model.Terms.Any()) { + @if (!Model.Terms.Any() && AuthorizedFor(Orchard.Taxonomies.Permissions.CreateTerm)) {
        @T("There are no terms defined for {0} yet.", Model.DisplayName) @T("Create some terms") diff --git a/src/Orchard.Web/Modules/Orchard.Templates/Drivers/ShapePartDriver.cs b/src/Orchard.Web/Modules/Orchard.Templates/Drivers/ShapePartDriver.cs index 0cd70d87f..986760e0e 100644 --- a/src/Orchard.Web/Modules/Orchard.Templates/Drivers/ShapePartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Templates/Drivers/ShapePartDriver.cs @@ -58,6 +58,11 @@ namespace Orchard.Templates.Drivers { } protected override void Importing(ShapePart part, ImportContentContext context) { + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; + } + var shapeElement = context.Data.Element(part.PartDefinition.Name); if (shapeElement != null) diff --git a/src/Orchard.Web/Modules/Orchard.Templates/Module.txt b/src/Orchard.Web/Modules/Orchard.Templates/Module.txt index 31f31fbd3..04dd4a09c 100644 --- a/src/Orchard.Web/Modules/Orchard.Templates/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Templates/Module.txt @@ -2,7 +2,7 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: Provides a Template type that can be used to store template code and used as a shape. Features: diff --git a/src/Orchard.Web/Modules/Orchard.Templates/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Templates/Properties/AssemblyInfo.cs index 2e9f3d1ab..5f2092b87 100644 --- a/src/Orchard.Web/Modules/Orchard.Templates/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Templates/Properties/AssemblyInfo.cs @@ -31,6 +31,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.Templates/Services/RazorTemplateProcessor.cs b/src/Orchard.Web/Modules/Orchard.Templates/Services/RazorTemplateProcessor.cs index d752ca2e8..2aed18c8d 100644 --- a/src/Orchard.Web/Modules/Orchard.Templates/Services/RazorTemplateProcessor.cs +++ b/src/Orchard.Web/Modules/Orchard.Templates/Services/RazorTemplateProcessor.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Text; +using System.Web; using System.Web.Mvc; using System.Web.UI; using System.Web.WebPages; @@ -14,6 +15,7 @@ namespace Orchard.Templates.Services { [OrchardFeature("Orchard.Templates.Razor")] public class RazorTemplateProcessor : TemplateProcessorImpl { private readonly IRazorCompiler _compiler; + private readonly HttpContextBase _httpContextBase; private readonly IWorkContextAccessor _wca; public override string Type { @@ -22,9 +24,11 @@ namespace Orchard.Templates.Services { public RazorTemplateProcessor( IRazorCompiler compiler, + HttpContextBase httpContextBase, IWorkContextAccessor wca) { _compiler = compiler; + _httpContextBase = httpContextBase; _wca = wca; Logger = NullLogger.Instance; } @@ -37,7 +41,7 @@ namespace Orchard.Templates.Services { public override string Process(string template, string name, DisplayContext context = null, dynamic model = null) { if (String.IsNullOrEmpty(template)) - return String.Empty; + return string.Empty; var compiledTemplate = _compiler.CompileRazor(template, name, new Dictionary()); var result = ActivateAndRenderTemplate(compiledTemplate, context, null, model); @@ -69,10 +73,9 @@ namespace Orchard.Templates.Services { // Setup a fake view context in order to support razor syntax inside of HTML attributes, // for instance: Homepage. var viewData = new ViewDataDictionary(model); - var httpContext = _wca.GetContext().HttpContext; obj.ViewContext = new ViewContext( new ControllerContext( - httpContext.Request.RequestContext, + _httpContextBase.Request.RequestContext, new StubController()), new StubView(), viewData, @@ -80,7 +83,7 @@ namespace Orchard.Templates.Services { htmlWriter); obj.ViewData = viewData; - obj.WebPageContext = new WebPageContext(httpContext, obj as WebPageRenderingBase, model); + obj.WebPageContext = new WebPageContext(_httpContextBase, obj as WebPageRenderingBase, model); obj.WorkContext = _wca.GetContext(); } diff --git a/src/Orchard.Web/Modules/Orchard.Templates/Services/TemplateShapeBindingResolver.cs b/src/Orchard.Web/Modules/Orchard.Templates/Services/TemplateShapeBindingResolver.cs index 6d8e1743a..4fc5eb6a1 100644 --- a/src/Orchard.Web/Modules/Orchard.Templates/Services/TemplateShapeBindingResolver.cs +++ b/src/Orchard.Web/Modules/Orchard.Templates/Services/TemplateShapeBindingResolver.cs @@ -55,7 +55,7 @@ namespace Orchard.Templates.Services { } private IDictionary BuildShapeProcessors() { - return _cacheManager.Get("Template.ShapeProcessors", ctx => { + return _cacheManager.Get("Template.ShapeProcessors", true, ctx => { ctx.Monitor(_signals.When(DefaultTemplateService.TemplatesSignal)); // select all name of types which contains ShapePart diff --git a/src/Orchard.Web/Modules/Orchard.Themes/Module.txt b/src/Orchard.Web/Modules/Orchard.Themes/Module.txt index 0d11ff0e6..71eadea38 100644 --- a/src/Orchard.Web/Modules/Orchard.Themes/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Themes/Module.txt @@ -3,7 +3,7 @@ AntiForgery: enabled SessionState: required Author: The Orchard Team Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: The themes module makes it possible for Orchard applications to customize the look and feel of an Orchard web site. FeatureDescription: Basic theming capability. @@ -11,4 +11,4 @@ Category: Core Features: Orchard.Themes: Description: Basic theming capability. - Category: Core \ No newline at end of file + Category: Core diff --git a/src/Orchard.Web/Modules/Orchard.Themes/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Themes/Properties/AssemblyInfo.cs index bf91a7235..ae631558f 100644 --- a/src/Orchard.Web/Modules/Orchard.Themes/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Themes/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.Tokens/EvaluateFor.cs b/src/Orchard.Web/Modules/Orchard.Tokens/EvaluateFor.cs index 39bda24bc..70438592c 100644 --- a/src/Orchard.Web/Modules/Orchard.Tokens/EvaluateFor.cs +++ b/src/Orchard.Web/Modules/Orchard.Tokens/EvaluateFor.cs @@ -7,5 +7,6 @@ namespace Orchard.Tokens { public abstract EvaluateFor Chain(string token, string chainTarget, Func chainValue); public abstract EvaluateFor Token(Func tokenValue); public abstract EvaluateFor Token(Func filter, Func tokenValue); + public abstract EvaluateFor Chain(Func> filter, string chainTarget, Func chainValue); } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Tokens/Implementation/TokenManager.cs b/src/Orchard.Web/Modules/Orchard.Tokens/Implementation/TokenManager.cs index b87d6f353..c0a967914 100644 --- a/src/Orchard.Web/Modules/Orchard.Tokens/Implementation/TokenManager.cs +++ b/src/Orchard.Web/Modules/Orchard.Tokens/Implementation/TokenManager.cs @@ -153,6 +153,27 @@ namespace Orchard.Tokens.Implementation { } return this; } + + public override EvaluateFor Chain(Func> filter, string chainTarget, Func chainValue) { + var subTokens = _context.Tokens + .Where(kv => kv.Key.Contains('.')) + .Select(kv => { + var filterResult = filter(kv.Key); + return filterResult != null ? new Tuple(filterResult.Item1, filterResult.Item2, kv.Value) : null; + }) + .Where(st => st != null) + .ToList(); + if (!subTokens.Any()) { + return this; + } + foreach(var chainGroup in subTokens.GroupBy(st => st.Item1)) { + var subValues = _context._manager.Evaluate(chainTarget, chainGroup.ToDictionary(cg => cg.Item2, cg => cg.Item3), new Dictionary { { chainTarget, chainValue(chainGroup.Key, _data) } }); + foreach (var subValue in subValues) { + _context.Values[subValue.Key] = subValue.Value; + } + } + return this; + } } private class EvaluateForSilent : EvaluateFor { @@ -175,6 +196,10 @@ namespace Orchard.Tokens.Implementation { public override EvaluateFor Chain(string token, string chainTarget, Func chainValue) { return this; } + + public override EvaluateFor Chain(Func> filter, string chainTarget, Func chainValue) { + return this; + } } } diff --git a/src/Orchard.Web/Modules/Orchard.Tokens/Module.txt b/src/Orchard.Web/Modules/Orchard.Tokens/Module.txt index 52abb0e05..5d0ec1c24 100644 --- a/src/Orchard.Web/Modules/Orchard.Tokens/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Tokens/Module.txt @@ -2,7 +2,7 @@ Name: Tokens AntiForgery: enabled Author: The Orchard Team Website: http://orchardtokens.codeplex.com -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: Provides a system for performing string replacements with common site values. Features: diff --git a/src/Orchard.Web/Modules/Orchard.Tokens/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Tokens/Properties/AssemblyInfo.cs index fb3ec5952..bda12f596 100644 --- a/src/Orchard.Web/Modules/Orchard.Tokens/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Tokens/Properties/AssemblyInfo.cs @@ -31,6 +31,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.Tokens/Providers/ContentTokens.cs b/src/Orchard.Web/Modules/Orchard.Tokens/Providers/ContentTokens.cs index 257394d88..6e6dad645 100644 --- a/src/Orchard.Web/Modules/Orchard.Tokens/Providers/ContentTokens.cs +++ b/src/Orchard.Web/Modules/Orchard.Tokens/Providers/ContentTokens.cs @@ -36,7 +36,7 @@ namespace Orchard.Tokens.Providers { .Token("DisplayUrl", T("Display Url"), T("Url to display the content."), "Url") .Token("EditUrl", T("Edit Url"), T("Url to edit the content."), "Url") .Token("Container", T("Container"), T("The container Content Item."), "Content") - .Token("Body", T("Body"), T("The body text of the content item."), "Content") + .Token("Body", T("Body"), T("The body text of the content item."), "Text") ; // Token descriptors for fields diff --git a/src/Orchard.Web/Modules/Orchard.Tokens/Providers/TextTokens.cs b/src/Orchard.Web/Modules/Orchard.Tokens/Providers/TextTokens.cs index 89f77c018..255cee809 100644 --- a/src/Orchard.Web/Modules/Orchard.Tokens/Providers/TextTokens.cs +++ b/src/Orchard.Web/Modules/Orchard.Tokens/Providers/TextTokens.cs @@ -13,38 +13,45 @@ namespace Orchard.Tokens.Providers { public void Describe(DescribeContext context) { context.For("Text", T("Text"), T("Tokens for text strings")) .Token("Limit:*", T("Limit:[,]"), T("Limit text to specified length and append an optional ellipsis text.")) - .Token("Format:*", T("Format:"), T("Optional format specifier (e.g. foo{0}bar). See format strings at Standard Formats and Custom Formats"), "DateTime") - .Token("TrimEnd:*", T("TrimEnd:"), T("Trims the specified characters or number of them from the end of the string."), "Text") + .Token("Format:*", T("Format:"), T("Optional format specifier (e.g. foo{0}bar).")) + .Token("TrimEnd:*", T("TrimEnd:"), T("Trims the specified characters or number of them from the end of the string.")) .Token("UrlEncode", T("Url Encode"), T("Encodes a URL string."), "Text") .Token("HtmlEncode", T("Html Encode"), T("Encodes an HTML string."), "Text") - .Token("LineEncode", T("Line Encode"), T("Replaces new lines with
        tags.")) + .Token("JavaScriptEncode", T("JavaScript Encode"), T("Encodes a JavaScript string."), "Text") + .Token("LineEncode", T("Line Encode"), T("Replaces new lines with
        tags."), "Text") ; } public void Evaluate(EvaluateContext context) { context.For("Text", () => "") - .Token( // {Text} + // {Text} + .Token( token => token == String.Empty ? String.Empty : null, (token, d) => d.ToString()) - .Token( // {Text.Limit:[,]} - token => { - if (token.StartsWith("Limit:", StringComparison.OrdinalIgnoreCase)) { - var param = token.Substring("Limit:".Length); - return param; - } - return null; - }, + // {Text.Limit:[,]} + .Token( + token => FilterTokenParam("Limit:", token), (token, t) => Limit(t, token)) // {Text.Format:} .Token( - token => token.StartsWith("Format:", StringComparison.OrdinalIgnoreCase) ? token.Substring("Format:".Length) : null, - (token, d) => String.Format(d,token)) - .Token(token => token.StartsWith("TrimEnd:", StringComparison.OrdinalIgnoreCase) ? token.Substring("TrimEnd:".Length) : null, TrimEnd) + token => FilterTokenParam("Format:", token), + (token, d) => String.Format(d, token)) + // {Text.TrimEnd:} + .Token(token => FilterTokenParam("TrimEnd:", token), TrimEnd) .Token("UrlEncode", HttpUtility.UrlEncode) + .Chain("UrlEncode", "Text", HttpUtility.UrlEncode) .Token("HtmlEncode", HttpUtility.HtmlEncode) + .Chain("HtmlEncode", "Text", HttpUtility.HtmlEncode) + .Token("JavaScriptEncode", HttpUtility.JavaScriptStringEncode) + .Chain("JavaScriptEncode", "Text", HttpUtility.JavaScriptStringEncode) .Token("LineEncode", text => text.Replace(System.Environment.NewLine, "
        ")) + .Chain("LineEncode", "Text", text => text.Replace(System.Environment.NewLine, "
        ")) ; - + + } + + private static string FilterTokenParam(string tokenName, string token) { + return token.StartsWith(tokenName, StringComparison.OrdinalIgnoreCase) ? token.Substring(tokenName.Length) : null; } private static string TrimEnd(string token, string param) { diff --git a/src/Orchard.Web/Modules/Orchard.Tokens/Tests/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Tokens/Tests/Properties/AssemblyInfo.cs index 2238161de..27fa698fb 100644 --- a/src/Orchard.Web/Modules/Orchard.Tokens/Tests/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Tokens/Tests/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.Tokens/Tests/StubWorkContextAccessor.cs b/src/Orchard.Web/Modules/Orchard.Tokens/Tests/StubWorkContextAccessor.cs index b68a02f27..9a957179d 100644 --- a/src/Orchard.Web/Modules/Orchard.Tokens/Tests/StubWorkContextAccessor.cs +++ b/src/Orchard.Web/Modules/Orchard.Tokens/Tests/StubWorkContextAccessor.cs @@ -131,10 +131,18 @@ namespace Orchard.Tokens.Tests { return _lifetimeScope.Resolve(); } + public override object Resolve(Type serviceType) { + return _lifetimeScope.Resolve(serviceType); + } + public override bool TryResolve(out T service) { return _lifetimeScope.TryResolve(out service); } + public override bool TryResolve(Type serviceType, out object service) { + return _lifetimeScope.TryResolve(serviceType, out service); + } + public override T GetState(string name) { return (T)_contextDictonary[name]; } diff --git a/src/Orchard.Web/Modules/Orchard.Tokens/Tests/TestTokenProvider.cs b/src/Orchard.Web/Modules/Orchard.Tokens/Tests/TestTokenProvider.cs index 105f705d4..c65b76a65 100644 --- a/src/Orchard.Web/Modules/Orchard.Tokens/Tests/TestTokenProvider.cs +++ b/src/Orchard.Web/Modules/Orchard.Tokens/Tests/TestTokenProvider.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using Orchard.ContentManagement; using Orchard.Localization; using Orchard.Security; @@ -24,6 +25,9 @@ namespace Orchard.Tokens.Tests { context.For("Date") .Token("Now", T("Now"), T("Current system date in short date format. You can chain a .NET DateTime format string to customize.")); + + context.For("Users") + .Token("Users[*:]", T("Users"), T("A user by its username"), "User"); } public void Evaluate(EvaluateContext context) { @@ -36,6 +40,7 @@ namespace Orchard.Tokens.Tests { context.For("User", () => new TestUser { UserName = "CurrentUser" }) .Token("Name", u => u.UserName) + .Token("Email", u => u.Email) .Token("Birthdate", u => "Nov 15") .Chain("Birthdate", "DateTime", u => new DateTime(1978, 11, 15)); @@ -45,6 +50,29 @@ namespace Orchard.Tokens.Tests { context.For("DateTime") .Token((token, value) => value.ToString(token)); + + context.For("Users", () => new TestUser[] { + new TestUser { UserName = "User1", Email = "user1@test.com" }, + new TestUser { UserName = "User2", Email = "user2@test.com" }, + new TestUser { UserName = "User3", Email = "user3@test.com" } + }) + .Token( + (token) => token.StartsWith("User:", StringComparison.OrdinalIgnoreCase) ? token.Substring("User:".Length) : null, + (userName, users) => users.Where(u => u.UserName == userName).Select(u => u.UserName).FirstOrDefault() + ) + .Chain( + (token) => { + int tokenLength = "User:".Length; + int chainIndex = token.IndexOf('.'); + if (token.StartsWith("User:", StringComparison.OrdinalIgnoreCase) && chainIndex > tokenLength) + return new Tuple(token.Substring(tokenLength, chainIndex - tokenLength), token.Substring(chainIndex + 1)); + else + return null; + }, + "User", + (userName, users) => users.Where(u => u.UserName == userName).FirstOrDefault() + ); + } } diff --git a/src/Orchard.Web/Modules/Orchard.Tokens/Tests/TokenManagerTests.cs b/src/Orchard.Web/Modules/Orchard.Tokens/Tests/TokenManagerTests.cs index 341e5ed37..073442bb9 100644 --- a/src/Orchard.Web/Modules/Orchard.Tokens/Tests/TokenManagerTests.cs +++ b/src/Orchard.Web/Modules/Orchard.Tokens/Tests/TokenManagerTests.cs @@ -29,10 +29,11 @@ namespace Orchard.Tokens.Tests { [Test] public void TestDescribe() { var allTokens = _tokenManager.Describe(null); - Assert.That(allTokens.Count(), Is.EqualTo(3)); + Assert.That(allTokens.Count(), Is.EqualTo(4)); Assert.That(allTokens.Any(d => d.Target == "Site")); Assert.That(allTokens.Any(d => d.Target == "User")); Assert.That(allTokens.Any(d => d.Target == "Date")); + Assert.That(allTokens.Any(d => d.Target == "Users")); var tokens = allTokens.Single(d => d.Target == "Site").Tokens; Assert.That(string.Join(",", tokens.Select(td => td.Target)), Is.EqualTo("Site,Site,Site,Site")); @@ -59,7 +60,7 @@ namespace Orchard.Tokens.Tests { [Test] public void TestDescribeFilter() { var tokenDescriptors = _tokenManager.Describe(null); - Assert.That(tokenDescriptors.Count(), Is.EqualTo(3)); + Assert.That(tokenDescriptors.Count(), Is.EqualTo(4)); tokenDescriptors = _tokenManager.Describe(new[] { "Site" }); Assert.That(tokenDescriptors.Count(), Is.EqualTo(1)); Assert.That(tokenDescriptors.First().Target, Is.EqualTo("Site")); diff --git a/src/Orchard.Web/Modules/Orchard.Tokens/Tests/TokenizerTests.cs b/src/Orchard.Web/Modules/Orchard.Tokens/Tests/TokenizerTests.cs index 999c3d87b..8c976f8d0 100644 --- a/src/Orchard.Web/Modules/Orchard.Tokens/Tests/TokenizerTests.cs +++ b/src/Orchard.Web/Modules/Orchard.Tokens/Tests/TokenizerTests.cs @@ -40,6 +40,18 @@ namespace Orchard.Tokens.Tests { Assert.That(_tokenizer.Replace("{Site.CurrentUser.Birthdate.yyyy}", null), Is.EqualTo("1978")); } + [Test] + public void TestParameterizedTokens() { + Assert.That(_tokenizer.Replace("{Users.User:User2}", null), Is.EqualTo("User2")); + Assert.That(_tokenizer.Replace("{Users.User:FakeUser}", null), Is.EqualTo("")); + } + + [Test] + public void TestParameterizedChainedTokens() { + Assert.That(_tokenizer.Replace("{Users.User:User2.Email}", null), Is.EqualTo("user2@test.com")); + Assert.That(_tokenizer.Replace("{Users.User:FakeUser.Email}", null), Is.EqualTo("")); + } + [Test] public void TestMissingTokens() { Assert.That(_tokenizer.Replace("[{Site.NotAToken}]", null), Is.EqualTo("[]")); diff --git a/src/Orchard.Web/Modules/Orchard.Users/Drivers/UserPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Users/Drivers/UserPartDriver.cs index f9a4526d6..1990a03d9 100644 --- a/src/Orchard.Web/Modules/Orchard.Users/Drivers/UserPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Users/Drivers/UserPartDriver.cs @@ -11,6 +11,11 @@ namespace Orchard.Users.Drivers { public class UserPartDriver : ContentPartDriver { protected override void Importing(UserPart part, ContentManagement.Handlers.ImportContentContext context) { + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; + } + part.Email = context.Attribute(part.PartDefinition.Name, "Email"); part.EmailChallengeToken = context.Attribute(part.PartDefinition.Name, "EmailChallengeToken"); part.EmailStatus = (UserStatus)Enum.Parse(typeof(UserStatus), context.Attribute(part.PartDefinition.Name, "EmailStatus")); diff --git a/src/Orchard.Web/Modules/Orchard.Users/Module.txt b/src/Orchard.Web/Modules/Orchard.Users/Module.txt index 3abf74381..259aecc33 100644 --- a/src/Orchard.Web/Modules/Orchard.Users/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Users/Module.txt @@ -2,7 +2,7 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: The users module enables user management. Features: diff --git a/src/Orchard.Web/Modules/Orchard.Users/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Users/Properties/AssemblyInfo.cs index 80da788cb..95948dc3a 100644 --- a/src/Orchard.Web/Modules/Orchard.Users/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Users/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.Warmup/Module.txt b/src/Orchard.Web/Modules/Orchard.Warmup/Module.txt index 4a59ab9e3..661208a95 100644 --- a/src/Orchard.Web/Modules/Orchard.Warmup/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Warmup/Module.txt @@ -2,7 +2,7 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: Provides a mecanism to generate a static version of pages for being used during application warm up. FeatureDescription: Generates the static version of specific pages periodically. diff --git a/src/Orchard.Web/Modules/Orchard.Warmup/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Warmup/Properties/AssemblyInfo.cs index 31aeabb61..1bba58d73 100644 --- a/src/Orchard.Web/Modules/Orchard.Warmup/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Warmup/Properties/AssemblyInfo.cs @@ -34,6 +34,6 @@ using System.Security; // CHANGE ON THIS VERSION NEEDS TO BE APPLIED ON WEB.CONFIG TOO -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Controllers/AdminController.cs index c5ad05276..9431da0bc 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Controllers/AdminController.cs @@ -69,7 +69,8 @@ namespace Orchard.Widgets.Controllers { } LayerPart currentLayer = layerId == null - ? layers.FirstOrDefault(layer => layer.Name == "Default") ?? layers.FirstOrDefault() + // look for the "Default" layer, or take the first if it doesn't exist + ? layers.FirstOrDefault(x => x.Name == "Default") ?? layers.FirstOrDefault() : layers.FirstOrDefault(layer => layer.Id == layerId); if (currentLayer == null && layerId != null) { // Incorrect layer id passed diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/LayerPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/LayerPartDriver.cs index 09aea2464..202ea2692 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/LayerPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/LayerPartDriver.cs @@ -64,6 +64,11 @@ namespace Orchard.Widgets.Drivers { } protected override void Importing(LayerPart part, ImportContentContext context) { + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; + } + var name = context.Attribute(part.PartDefinition.Name, "Name"); if (name != null) { part.Name = name; diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/WidgetPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/WidgetPartDriver.cs index ccaaa0c44..098944941 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/WidgetPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/WidgetPartDriver.cs @@ -75,30 +75,25 @@ namespace Orchard.Widgets.Drivers { } protected override void Importing(WidgetPart part, ContentManagement.Handlers.ImportContentContext context) { - var title = context.Attribute(part.PartDefinition.Name, "Title"); - if (title != null) { - part.Title = title; + // Don't do anything if the tag is not specified. + if (context.Data.Element(part.PartDefinition.Name) == null) { + return; } - var position = context.Attribute(part.PartDefinition.Name, "Position"); - if (position != null) { - part.Position = position; - } - - var zone = context.Attribute(part.PartDefinition.Name, "Zone"); - if (zone != null) { - part.Zone = zone; - } - - var renderTitle = context.Attribute(part.PartDefinition.Name, "RenderTitle"); - if (!string.IsNullOrWhiteSpace(renderTitle)) { - part.RenderTitle = Convert.ToBoolean(renderTitle); - } - - var name = context.Attribute(part.PartDefinition.Name, "Name"); - if (name != null) { - part.Name = name; - } + context.ImportAttribute(part.PartDefinition.Name, "Title", x => part.Title = x); + context.ImportAttribute(part.PartDefinition.Name, "Position", x => part.Position = x); + context.ImportAttribute(part.PartDefinition.Name, "Zone", x => part.Zone = x); + context.ImportAttribute(part.PartDefinition.Name, "RenderTitle", x => { + if (!string.IsNullOrWhiteSpace(x)) { + part.RenderTitle = Convert.ToBoolean(x); + } + }); + context.ImportAttribute(part.PartDefinition.Name, "Name", x => part.Name = x); + context.ImportAttribute(part.PartDefinition.Name, "Title", x => { + if (!String.IsNullOrWhiteSpace(x)) + part.Title = x; + }); + context.ImportAttribute(part.PartDefinition.Name, "CssClasses", x => part.CssClasses = x); } protected override void Exporting(WidgetPart part, ContentManagement.Handlers.ExportContentContext context) { @@ -107,6 +102,7 @@ namespace Orchard.Widgets.Drivers { context.Element(part.PartDefinition.Name).SetAttributeValue("Zone", part.Zone); context.Element(part.PartDefinition.Name).SetAttributeValue("RenderTitle", part.RenderTitle); context.Element(part.PartDefinition.Name).SetAttributeValue("Name", part.Name); + context.Element(part.PartDefinition.Name).SetAttributeValue("CssClasses", part.CssClasses); } } -} \ No newline at end of file +} diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Module.txt b/src/Orchard.Web/Modules/Orchard.Widgets/Module.txt index f8e587adc..1a0eb5338 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Module.txt @@ -2,7 +2,7 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Description: An implementation of widgets for Orchard. FeatureDescription: An implementation of widgets. diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Properties/AssemblyInfo.cs index f75595450..bb6e1188a 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Properties/AssemblyInfo.cs @@ -30,6 +30,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.Workflows/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Workflows/Controllers/AdminController.cs index 12c8bb6f8..af02427bf 100644 --- a/src/Orchard.Web/Modules/Orchard.Workflows/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Workflows/Controllers/AdminController.cs @@ -23,6 +23,7 @@ using Orchard.UI.Notify; using Orchard.Workflows.Models; using Orchard.Workflows.Services; using Orchard.Workflows.ViewModels; +using Orchard.Workflows.Helpers; namespace Orchard.Workflows.Controllers { [ValidateInput(false)] @@ -298,7 +299,7 @@ namespace Orchard.Workflows.Controllers { dynamic activity = new JObject(); activity.Name = x.Name; activity.Id = x.Id; - activity.ClientId = x.Name + "_" + x.Id; + activity.ClientId = x.GetClientId(); activity.Left = x.X; activity.Top = x.Y; activity.Start = x.Start; @@ -323,7 +324,7 @@ namespace Orchard.Workflows.Controllers { [HttpPost, ActionName("Edit")] [FormValueRequired("submit.Save")] - public ActionResult EditPost(int id, string localId, string data) { + public ActionResult EditPost(int id, string localId, string data, bool clearWorkflows) { if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to edit workflows"))) return new HttpUnauthorizedResult(); @@ -339,7 +340,6 @@ namespace Orchard.Workflows.Controllers { var activitiesIndex = new Dictionary(); workflowDefinitionRecord.ActivityRecords.Clear(); - workflowDefinitionRecord.WorkflowRecords.Clear(); foreach (var activity in state.Activities) { ActivityRecord activityRecord; @@ -367,9 +367,32 @@ namespace Orchard.Workflows.Controllers { }); } + if (clearWorkflows) { + workflowDefinitionRecord.WorkflowRecords.Clear(); + } + else { + foreach (var workflowRecord in workflowDefinitionRecord.WorkflowRecords) { + // Update any awaiting activity records with the new activity record. + foreach (var awaitingActivityRecord in workflowRecord.AwaitingActivities) { + var clientId = awaitingActivityRecord.ActivityRecord.GetClientId(); + if (activitiesIndex.ContainsKey(clientId)) { + awaitingActivityRecord.ActivityRecord = activitiesIndex[clientId]; + } + else { + workflowRecord.AwaitingActivities.Remove(awaitingActivityRecord); + } + } + // Remove any workflows with no awaiting activities. + if (!workflowRecord.AwaitingActivities.Any()) { + workflowDefinitionRecord.WorkflowRecords.Remove(workflowRecord); + } + } + } + Services.Notifier.Information(T("Workflow saved successfully")); - return RedirectToAction("Edit", new { id, localId }); + // Don't pass the localId to force the activites to refresh and use the deterministic clientId. + return RedirectToAction("Edit", new { id }); } [HttpPost, ActionName("Edit")] diff --git a/src/Orchard.Web/Modules/Orchard.Workflows/Models/ActivityRecord.cs b/src/Orchard.Web/Modules/Orchard.Workflows/Models/ActivityRecord.cs index 8c45e5a19..9233d5bcd 100644 --- a/src/Orchard.Web/Modules/Orchard.Workflows/Models/ActivityRecord.cs +++ b/src/Orchard.Web/Modules/Orchard.Workflows/Models/ActivityRecord.cs @@ -38,5 +38,14 @@ namespace Orchard.Workflows.Models { /// containing this activity. ///
        public virtual WorkflowDefinitionRecord WorkflowDefinitionRecord { get; set; } + + + /// + /// Gets the Id which can be used on the client. + /// + /// An unique Id to represent this activity on the client. + public string GetClientId() { + return Name + "_" + Id; + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Workflows/Module.txt b/src/Orchard.Web/Modules/Orchard.Workflows/Module.txt index 83a7e0640..62fbcc260 100644 --- a/src/Orchard.Web/Modules/Orchard.Workflows/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Workflows/Module.txt @@ -2,7 +2,7 @@ AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.9.1 +Version: 1.9.2 OrchardVersion: 1.9 Category: Workflows Description: Provides tools to create custom workflows. diff --git a/src/Orchard.Web/Modules/Orchard.Workflows/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.Workflows/Properties/AssemblyInfo.cs index 1e36590ba..31c882f5f 100644 --- a/src/Orchard.Web/Modules/Orchard.Workflows/Properties/AssemblyInfo.cs +++ b/src/Orchard.Web/Modules/Orchard.Workflows/Properties/AssemblyInfo.cs @@ -31,6 +31,6 @@ using System.Security; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard.Web/Modules/Orchard.Workflows/Views/Admin/Edit.cshtml b/src/Orchard.Web/Modules/Orchard.Workflows/Views/Admin/Edit.cshtml index c1acd41b5..1ab7a4294 100644 --- a/src/Orchard.Web/Modules/Orchard.Workflows/Views/Admin/Edit.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Workflows/Views/Admin/Edit.cshtml @@ -7,6 +7,7 @@ Style.Require("WorkflowsAdmin"); Style.Require("WorkflowsActivities"); Style.Require("jQueryUI_Orchard"); + Script.Require("jQueryUI_Dialog").AtFoot(); Script.Require("jsPlumb").AtFoot(); Script.Include("orchard-workflows-serialize.js").AtFoot(); Script.Include("orchard-workflows.js").AtFoot(); @@ -74,23 +75,41 @@ @Html.Hidden("data", String.Empty) @Html.Hidden("confirm-delete-activity", T("Are you sure you want to remove this activity?")) -@Html.Hidden("confirm-delete-instances", T("Are you sure you want to remove running instances of this workflow?")) +@Html.Hidden("confirm-delete-instances", T("You have running instances of this workflow, do you want to stop them?")) using (Script.Foot()) { } \ No newline at end of file diff --git a/src/Orchard.Web/Themes/TheThemeMachine/Theme.txt b/src/Orchard.Web/Themes/TheThemeMachine/Theme.txt index 938ba92ec..b70d501be 100644 --- a/src/Orchard.Web/Themes/TheThemeMachine/Theme.txt +++ b/src/Orchard.Web/Themes/TheThemeMachine/Theme.txt @@ -1,7 +1,7 @@ Name: The Theme Machine Author: jowall, mibach, loudej, heskew Description: Orchard Theme Machine is a flexible multi-zone theme that provides a solid foundation to build your site. It features 20 collapsible widget zones and is flexible enough to cover a wide range of layouts. -Version: 1.9.1 +Version: 1.9.2 Tags: Awesome Website: http://orchardproject.net Zones: Header, Navigation, Featured, BeforeMain, AsideFirst, Messages, BeforeContent, Content, AfterContent, AsideSecond, AfterMain, TripelFirst, TripelSecond, TripelThird, FooterQuadFirst, FooterQuadSecond, FooterQuadThird, FooterQuadFourth, Footer diff --git a/src/Orchard.Web/Web.config b/src/Orchard.Web/Web.config index dcc846ed7..ea98388f4 100644 --- a/src/Orchard.Web/Web.config +++ b/src/Orchard.Web/Web.config @@ -1,219 +1,219 @@ - - -
        -
        - - + + +
        +
        + + - - - - - - + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.sln b/src/Orchard.sln index 40a51d6f3..ace52701a 100644 --- a/src/Orchard.sln +++ b/src/Orchard.sln @@ -255,14 +255,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Layouts", "Orchard. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.DynamicForms", "Orchard.Web\Modules\Orchard.DynamicForms\Orchard.DynamicForms.csproj", "{82190F52-2901-46D6-8A4C-34649959483F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Dashboards", "Orchard.Web\Modules\Orchard.Dashboards\Orchard.Dashboards.csproj", "{BAC82DB9-F4C4-4DD1-ABDB-F70E6229E6B0}" +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DF3909B0-1DDD-4D8A-9919-56FC438E25E2}" ProjectSection(SolutionItems) = preProject Rebracer.xml = Rebracer.xml WebEssentials-Settings.json = WebEssentials-Settings.json EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Dashboards", "Orchard.Web\Modules\Orchard.Dashboards\Orchard.Dashboards.csproj", "{BAC82DB9-F4C4-4DD1-ABDB-F70E6229E6B0}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Gulp", "Gulp", "{90EBEE36-B5CD-42A8-A21B-76270E2C5D24}" ProjectSection(SolutionItems) = preProject Gulpfile.js = Gulpfile.js diff --git a/src/Orchard/BackgroundHttpContextFactory.cs b/src/Orchard/BackgroundHttpContextFactory.cs new file mode 100644 index 000000000..9935e7dfc --- /dev/null +++ b/src/Orchard/BackgroundHttpContextFactory.cs @@ -0,0 +1,33 @@ +using System.IO; +using System.Web; +using Orchard.Settings; + +namespace Orchard { + /// + /// A factory class that creates an HttpContext instance and initializes the HttpContext.Current property with that instance. + /// This is useful when rendering views from a background thread, as some Html Helpers access HttpContext.Current directly, thus preventing a NullReferenceException. + /// + public class BackgroundHttpContextFactory : IBackgroundHttpContextFactory { + public const string IsBackgroundHttpContextKey = "IsBackgroundHttpContext"; + private readonly ISiteService _siteService; + public BackgroundHttpContextFactory(ISiteService siteService) { + _siteService = siteService; + } + + public HttpContext CreateHttpContext() { + var url = _siteService.GetSiteSettings().BaseUrl; + var httpContext = new HttpContext(new HttpRequest("", url, ""), new HttpResponse(new StringWriter())); + + httpContext.Items[IsBackgroundHttpContextKey] = true; + + return httpContext; + } + + public void InitializeHttpContext() { + if (HttpContext.Current != null) + return; + + HttpContext.Current = CreateHttpContext(); + } + } +} \ No newline at end of file diff --git a/src/Orchard/Caching/DefaultAsyncTokenProvider.cs b/src/Orchard/Caching/DefaultAsyncTokenProvider.cs index b6769ec82..9f13571c0 100644 --- a/src/Orchard/Caching/DefaultAsyncTokenProvider.cs +++ b/src/Orchard/Caching/DefaultAsyncTokenProvider.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using Orchard.Logging; +using Orchard.Exceptions; namespace Orchard.Caching { public class DefaultAsyncTokenProvider : IAsyncTokenProvider { @@ -37,9 +38,12 @@ namespace Orchard.Caching { try { _task(token => _taskTokens.Add(token)); } - catch (Exception e) { - Logger.Error(e, "Error while monitoring extension files. Assuming extensions are not current."); - _taskException = e; + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Error(ex, "Error while monitoring extension files. Assuming extensions are not current."); + _taskException = ex; } finally { _isTaskFinished = true; diff --git a/src/Orchard/Caching/ICacheManager.cs b/src/Orchard/Caching/ICacheManager.cs index c54902eb9..793b29a46 100644 --- a/src/Orchard/Caching/ICacheManager.cs +++ b/src/Orchard/Caching/ICacheManager.cs @@ -5,4 +5,17 @@ namespace Orchard.Caching { TResult Get(TKey key, Func, TResult> acquire); ICache GetCache(); } + + public static class CacheManagerExtensions { + public static TResult Get(this ICacheManager cacheManager, TKey key, bool preventConcurrentCalls, Func, TResult> acquire) { + if (preventConcurrentCalls) { + lock(key) { + return cacheManager.Get(key, acquire); + } + } + else { + return cacheManager.Get(key, acquire); + } + } + } } diff --git a/src/Orchard/Commands/CommandHostAgent.cs b/src/Orchard/Commands/CommandHostAgent.cs index 6c7a955aa..05b1122ef 100644 --- a/src/Orchard/Commands/CommandHostAgent.cs +++ b/src/Orchard/Commands/CommandHostAgent.cs @@ -15,6 +15,7 @@ using Orchard.FileSystems.VirtualPath; using Orchard.Localization; using Orchard.Logging; using Orchard.Tasks; +using Orchard.Exceptions; namespace Orchard.Commands { @@ -94,19 +95,21 @@ namespace Orchard.Commands { return CommandReturnCodes.Ok; } - catch (OrchardCommandHostRetryException e) { + catch (OrchardCommandHostRetryException ex) { // Special "Retry" return code for our host - output.WriteLine(T("{0} (Retrying...)", e.Message)); + output.WriteLine(T("{0} (Retrying...)", ex.Message)); return CommandReturnCodes.Retry; } - catch (Exception e) { - if (e is TargetInvocationException && - e.InnerException != null) { - // If this is an exception coming from reflection and there is an innerexception which is the actual one, redirect - e = e.InnerException; + catch (Exception ex) { + if (ex.IsFatal()) { + throw; } - - OutputException(output, T("Error executing command \"{0}\"", string.Join(" ", args)), e); + if (ex is TargetInvocationException && + ex.InnerException != null) { + // If this is an exception coming from reflection and there is an innerexception which is the actual one, redirect + ex = ex.InnerException; + } + OutputException(output, T("Error executing command \"{0}\"", string.Join(" ", args)), ex); return CommandReturnCodes.Fail; } } @@ -116,13 +119,16 @@ namespace Orchard.Commands { _hostContainer = CreateHostContainer(); return CommandReturnCodes.Ok; } - catch (OrchardCommandHostRetryException e) { + catch (OrchardCommandHostRetryException ex) { // Special "Retry" return code for our host - output.WriteLine(T("{0} (Retrying...)", e.Message)); + output.WriteLine(T("{0} (Retrying...)", ex.Message)); return CommandReturnCodes.Retry; } - catch (Exception e) { - OutputException(output, T("Error starting up Orchard command line host"), e); + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + OutputException(output, T("Error starting up Orchard command line host"), ex); return CommandReturnCodes.Fail; } } @@ -135,8 +141,11 @@ namespace Orchard.Commands { } return CommandReturnCodes.Ok; } - catch (Exception e) { - OutputException(output, T("Error shutting down Orchard command line host"), e); + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + OutputException(output, T("Error shutting down Orchard command line host"), ex); return CommandReturnCodes.Fail; } } @@ -184,13 +193,12 @@ namespace Orchard.Commands { [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")] private IContainer CreateHostContainer() { var hostContainer = OrchardStarter.CreateHostContainer(ContainerRegistrations); - var host = hostContainer.Resolve(); + host.Initialize(); return hostContainer; } - private IWorkContextScope CreateStandaloneEnvironment(string tenant) { var host = _hostContainer.Resolve(); var tenantManager = _hostContainer.Resolve(); @@ -207,13 +215,12 @@ namespace Orchard.Commands { return env; } else { - // In case of an unitiliazed site (no default settings yet), we create a default settings instance. + // In case of an uninitialized site (no default settings yet), we create a default settings instance. var settings = new ShellSettings { Name = ShellSettings.DefaultName, State = TenantState.Uninitialized }; return host.CreateStandaloneEnvironment(settings); } } - protected void ContainerRegistrations(ContainerBuilder builder) { MvcSingletons(builder); @@ -225,14 +232,14 @@ namespace Orchard.Commands { private CommandHostShellContainerRegistrations CreateShellRegistrations() { return new CommandHostShellContainerRegistrations { Registrations = shellBuilder => { - shellBuilder.RegisterType() - .As() - .As() - .InstancePerMatchingLifetimeScope("shell"); - shellBuilder.RegisterType() - .As() - .InstancePerLifetimeScope(); - } + shellBuilder.RegisterType() + .As() + .As() + .InstancePerMatchingLifetimeScope("shell"); + shellBuilder.RegisterType() + .As() + .InstancePerLifetimeScope(); + } }; } diff --git a/src/Orchard/Commands/DefaultOrchardCommandHandler.cs b/src/Orchard/Commands/DefaultOrchardCommandHandler.cs index a5e8a3d89..7936ddef1 100644 --- a/src/Orchard/Commands/DefaultOrchardCommandHandler.cs +++ b/src/Orchard/Commands/DefaultOrchardCommandHandler.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using Orchard.Localization; +using Orchard.Exceptions; namespace Orchard.Commands { public abstract class DefaultOrchardCommandHandler : ICommandHandler { @@ -41,12 +42,15 @@ namespace Orchard.Commands { object value = Convert.ChangeType(commandSwitch.Value, propertyInfo.PropertyType); propertyInfo.SetValue(this, value, null/*index*/); } - catch(Exception e) { + catch(Exception ex) { + if (ex.IsFatal()) { + throw; + } string message = T("Error converting value \"{0}\" to \"{1}\" for switch \"{2}\"", LocalizedString.TextOrDefault(commandSwitch.Value, T("(empty)")), propertyInfo.PropertyType.FullName, commandSwitch.Key).Text; - throw new InvalidOperationException(message, e); + throw new InvalidOperationException(message, ex); } } diff --git a/src/Orchard/ContentManagement/ContentPart.cs b/src/Orchard/ContentManagement/ContentPart.cs index cdb4bbfbe..16ed02311 100644 --- a/src/Orchard/ContentManagement/ContentPart.cs +++ b/src/Orchard/ContentManagement/ContentPart.cs @@ -21,14 +21,6 @@ namespace Orchard.ContentManagement { public virtual ContentItem ContentItem { get; set; } - //interesting thought, should/could parts also have zones (would then have zones on the page, content item and parts...)? - private readonly IZoneCollection _zones = new ZoneCollection(); - public virtual IZoneCollection Zones { - get { - return _zones; - } - } - /// /// The ContentItem's identifier. /// diff --git a/src/Orchard/ContentManagement/DefaultContentManager.cs b/src/Orchard/ContentManagement/DefaultContentManager.cs index 048ea4dc0..fc6fd7de6 100644 --- a/src/Orchard/ContentManagement/DefaultContentManager.cs +++ b/src/Orchard/ContentManagement/DefaultContentManager.cs @@ -817,7 +817,7 @@ namespace Orchard.ContentManagement { } private ContentTypeRecord AcquireContentTypeRecord(string contentType) { - var contentTypeId = _cacheManager.Get(contentType + "_Record", ctx => { + var contentTypeId = _cacheManager.Get(contentType + "_Record", true, ctx => { ctx.Monitor(_signals.When(contentType + "_Record")); var contentTypeRecord = _contentTypeRepository.Get(x => x.Name == contentType); diff --git a/src/Orchard/ContentManagement/DefaultContentQuery.cs b/src/Orchard/ContentManagement/DefaultContentQuery.cs index 468d105ef..befcd03aa 100644 --- a/src/Orchard/ContentManagement/DefaultContentQuery.cs +++ b/src/Orchard/ContentManagement/DefaultContentQuery.cs @@ -76,7 +76,7 @@ namespace Orchard.ContentManagement { } private int GetContentTypeRecordId(string contentType) { - return _cacheManager.Get(contentType + "_Record", ctx => { + return _cacheManager.Get(contentType + "_Record", true, ctx => { ctx.Monitor(_signals.When(contentType + "_Record")); var contentTypeRecord = _contentTypeRepository.Get(x => x.Name == contentType); diff --git a/src/Orchard/Data/Migration/AutomaticDataMigrations.cs b/src/Orchard/Data/Migration/AutomaticDataMigrations.cs index 50727d47f..797c77b80 100644 --- a/src/Orchard/Data/Migration/AutomaticDataMigrations.cs +++ b/src/Orchard/Data/Migration/AutomaticDataMigrations.cs @@ -1,9 +1,13 @@ using System; using System.Linq; +using Orchard.Data.Migration.Interpreters; +using Orchard.Data.Migration.Schema; using Orchard.Environment; +using Orchard.Environment.Configuration; using Orchard.Environment.Features; using Orchard.Logging; using Orchard.Tasks.Locking.Services; +using Orchard.Exceptions; namespace Orchard.Data.Migration { /// @@ -13,24 +17,35 @@ namespace Orchard.Data.Migration { private readonly IDataMigrationManager _dataMigrationManager; private readonly IFeatureManager _featureManager; private readonly IDistributedLockService _distributedLockService; + private readonly IDataMigrationInterpreter _dataMigrationInterpreter; + private readonly ShellSettings _shellSettings; + private readonly ITransactionManager _transactionManager; public AutomaticDataMigrations( IDataMigrationManager dataMigrationManager, + IDataMigrationInterpreter dataMigrationInterpreter, IFeatureManager featureManager, - IDistributedLockService distributedLockService) { + IDistributedLockService distributedLockService, + ITransactionManager transactionManager, + ShellSettings shellSettings) { _dataMigrationManager = dataMigrationManager; _featureManager = featureManager; _distributedLockService = distributedLockService; + _shellSettings = shellSettings; + _transactionManager = transactionManager; + _dataMigrationInterpreter = dataMigrationInterpreter; Logger = NullLogger.Instance; } - public ILogger Logger { get; set; } + public ILogger Logger { get; set; } public void Activated() { - DistributedLock @lock; - if(_distributedLockService.TryAcquireLockForThread(GetType().FullName, TimeSpan.FromMinutes(30), TimeSpan.FromMilliseconds(250), out @lock)) { + EnsureDistributedLockSchemaExists(); + + IDistributedLock @lock; + if (_distributedLockService.TryAcquireLock(GetType().FullName, TimeSpan.FromMinutes(30), TimeSpan.FromMilliseconds(250), out @lock)) { using (@lock) { // Let's make sure that the basic set of features is enabled. If there are any that are not enabled, then let's enable them first. var theseFeaturesShouldAlwaysBeActive = new[] { @@ -48,7 +63,10 @@ namespace Orchard.Data.Migration { _dataMigrationManager.Update(feature); } catch (Exception ex) { - Logger.Error(ex, "Could not run migrations automatically on {0}.", feature); + if (ex.IsFatal()) { + throw; + } + Logger.Error("Could not run migrations automatically on " + feature, ex); } } } @@ -58,5 +76,16 @@ namespace Orchard.Data.Migration { public void Terminating() { // No-op. } + + /// + /// This ensures that the framework migrations have run for the distributed locking feature, as existing Orchard installations will not have the required tables when upgrading. + /// + private void EnsureDistributedLockSchemaExists() { + // Ensure the distributed lock record schema exists. + var schemaBuilder = new SchemaBuilder(_dataMigrationInterpreter); + var distributedLockSchemaBuilder = new DistributedLockSchemaBuilder(_shellSettings, schemaBuilder); + if (distributedLockSchemaBuilder.EnsureSchema()) + _transactionManager.RequireNew(); + } } } diff --git a/src/Orchard/Data/Migration/DataMigrationManager.cs b/src/Orchard/Data/Migration/DataMigrationManager.cs index 1ef6e33d7..02c6204f0 100644 --- a/src/Orchard/Data/Migration/DataMigrationManager.cs +++ b/src/Orchard/Data/Migration/DataMigrationManager.cs @@ -9,6 +9,7 @@ using Orchard.Data.Migration.Schema; using Orchard.Environment.Extensions; using Orchard.Localization; using Orchard.Logging; +using Orchard.Exceptions; namespace Orchard.Data.Migration { /// @@ -123,6 +124,9 @@ namespace Orchard.Data.Migration { current = (int)lookupTable[current].Invoke(migration, new object[0]); } catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } Logger.Error(ex, "An unexpected error occurred while applying migration on {0} from version {1}.", feature, current); throw; } @@ -139,10 +143,13 @@ namespace Orchard.Data.Migration { dataMigrationRecord.Version = current; } } - catch (Exception e) { - Logger.Error(e, "Error while running migration version {0} for {1}.", current, feature); + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Error(ex, "Error while running migration version {0} for {1}.", current, feature); _transactionManager.Cancel(); - throw new OrchardException(T("Error while running migration version {0} for {1}.", current, feature), e); + throw new OrchardException(T("Error while running migration version {0} for {1}.", current, feature), ex); } } diff --git a/src/Orchard/Data/Migration/Interpreters/DefaultDataMigrationInterpreter.cs b/src/Orchard/Data/Migration/Interpreters/DefaultDataMigrationInterpreter.cs index e3f5d958c..fc75c61cb 100644 --- a/src/Orchard/Data/Migration/Interpreters/DefaultDataMigrationInterpreter.cs +++ b/src/Orchard/Data/Migration/Interpreters/DefaultDataMigrationInterpreter.cs @@ -382,7 +382,7 @@ namespace Orchard.Data.Migration.Interpreters { } } finally { - _sqlStatements.Clear(); + _sqlStatements.Clear(); } } diff --git a/src/Orchard/Data/Migration/Schema/SchemaBuilder.cs b/src/Orchard/Data/Migration/Schema/SchemaBuilder.cs index 627836efa..541c0619b 100644 --- a/src/Orchard/Data/Migration/Schema/SchemaBuilder.cs +++ b/src/Orchard/Data/Migration/Schema/SchemaBuilder.cs @@ -1,6 +1,7 @@ using System; using Orchard.Data.Migration.Interpreters; using Orchard.Localization; +using Orchard.Exceptions; namespace Orchard.Data.Migration.Schema { public class SchemaBuilder { @@ -72,6 +73,9 @@ namespace Orchard.Data.Migration.Schema { Run(sqlStatmentCommand); return this; } catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } throw new OrchardException(T("An unexpected error occured while executing the SQL statement: {0}", sql), ex); // Add the sql to the nested exception information } } diff --git a/src/Orchard/Data/SessionConfigurationCache.cs b/src/Orchard/Data/SessionConfigurationCache.cs index 037f80801..30bae0547 100644 --- a/src/Orchard/Data/SessionConfigurationCache.cs +++ b/src/Orchard/Data/SessionConfigurationCache.cs @@ -11,6 +11,7 @@ using Orchard.Environment.ShellBuilders.Models; using Orchard.FileSystems.AppData; using Orchard.Logging; using Orchard.Utility; +using Orchard.Exceptions; namespace Orchard.Data { public class SessionConfigurationCache : ISessionConfigurationCache { @@ -80,11 +81,11 @@ namespace Orchard.Data { formatter.Serialize(stream, cache.Configuration); } } - catch (SerializationException e) { + catch (SerializationException ex) { //Note: This can happen when multiple processes/AppDomains try to save // the cached configuration at the same time. Only one concurrent // writer will win, and it's harmless for the other ones to fail. - for (Exception scan = e; scan != null; scan = scan.InnerException) + for (Exception scan = ex; scan != null; scan = scan.InnerException) Logger.Warning("Error storing new NHibernate cache configuration: {0}", scan.Message); } } @@ -118,8 +119,11 @@ namespace Orchard.Data { }; } } - catch (Exception e) { - for (var scan = e; scan != null; scan = scan.InnerException) + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + for (var scan = ex; scan != null; scan = scan.InnerException) Logger.Warning("Error reading the cached NHibernate configuration: {0}", scan.Message); Logger.Information("A new one will be re-generated."); return null; diff --git a/src/Orchard/DisplayManagement/Descriptors/DefaultShapeTableManager.cs b/src/Orchard/DisplayManagement/Descriptors/DefaultShapeTableManager.cs index bc9eb0667..e1cfd57a7 100644 --- a/src/Orchard/DisplayManagement/Descriptors/DefaultShapeTableManager.cs +++ b/src/Orchard/DisplayManagement/Descriptors/DefaultShapeTableManager.cs @@ -37,7 +37,7 @@ namespace Orchard.DisplayManagement.Descriptors { public ILogger Logger { get; set; } public ShapeTable GetShapeTable(string themeName) { - return _cacheManager.Get(themeName ?? "", x => { + return _cacheManager.Get(themeName ?? "", true, x => { Logger.Information("Start building shape table"); var alterationSets = _parallelCacheContext.RunInParallel(_bindingStrategies, bindingStrategy => { diff --git a/src/Orchard/DisplayManagement/Descriptors/ShapePlacementStrategy/PlacementFileParser.cs b/src/Orchard/DisplayManagement/Descriptors/ShapePlacementStrategy/PlacementFileParser.cs index 8725ded54..9ce3454b9 100644 --- a/src/Orchard/DisplayManagement/Descriptors/ShapePlacementStrategy/PlacementFileParser.cs +++ b/src/Orchard/DisplayManagement/Descriptors/ShapePlacementStrategy/PlacementFileParser.cs @@ -30,7 +30,7 @@ namespace Orchard.DisplayManagement.Descriptors.ShapePlacementStrategy { public bool DisableMonitoring { get; set; } public PlacementFile Parse(string virtualPath) { - return _cacheManager.Get(virtualPath, context => { + return _cacheManager.Get(virtualPath, true, context => { if (!DisableMonitoring) { Logger.Debug("Monitoring virtual path \"{0}\"", virtualPath); diff --git a/src/Orchard/DisplayManagement/Descriptors/ShapeTemplateStrategy/ShapeTemplateBindingStrategy.cs b/src/Orchard/DisplayManagement/Descriptors/ShapeTemplateStrategy/ShapeTemplateBindingStrategy.cs index 2e3e841d0..95b0c6694 100644 --- a/src/Orchard/DisplayManagement/Descriptors/ShapeTemplateStrategy/ShapeTemplateBindingStrategy.cs +++ b/src/Orchard/DisplayManagement/Descriptors/ShapeTemplateStrategy/ShapeTemplateBindingStrategy.cs @@ -77,7 +77,7 @@ namespace Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy { var pathContexts = harvesterInfos.SelectMany(harvesterInfo => harvesterInfo.subPaths.Select(subPath => { var basePath = Path.Combine(extensionDescriptor.Location, extensionDescriptor.Id).Replace(Path.DirectorySeparatorChar, '/'); var virtualPath = Path.Combine(basePath, subPath).Replace(Path.DirectorySeparatorChar, '/'); - var fileNames = _cacheManager.Get(virtualPath, ctx => { + var fileNames = _cacheManager.Get(virtualPath, true, ctx => { if (!_virtualPathProvider.DirectoryExists(virtualPath)) return new List(); @@ -179,8 +179,8 @@ namespace Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy { private ControllerContext CreateControllerContext() { var controller = new StubController(); - var httpContext = _workContextAccessor.GetContext().HttpContext; - var requestContext = httpContext.Request.RequestContext; + var httpContext = _workContextAccessor.GetContext().Resolve(); + var requestContext = _workContextAccessor.GetContext().Resolve(); var routeData = requestContext.RouteData; routeData.DataTokens["IWorkContextAccessor"] = _workContextAccessor; diff --git a/src/Orchard/DisplayManagement/IPositioned.cs b/src/Orchard/DisplayManagement/IPositioned.cs new file mode 100644 index 000000000..898cdc76a --- /dev/null +++ b/src/Orchard/DisplayManagement/IPositioned.cs @@ -0,0 +1,5 @@ +namespace Orchard.DisplayManagement { + public interface IPositioned { + string Position { get; } + } +} \ No newline at end of file diff --git a/src/Orchard/DisplayManagement/IShape.cs b/src/Orchard/DisplayManagement/IShape.cs index 27ad21151..5ec1483cb 100644 --- a/src/Orchard/DisplayManagement/IShape.cs +++ b/src/Orchard/DisplayManagement/IShape.cs @@ -1,5 +1,4 @@ -using System.Diagnostics; -using Orchard.DisplayManagement.Shapes; +using Orchard.DisplayManagement.Shapes; namespace Orchard.DisplayManagement { /// diff --git a/src/Orchard/DisplayManagement/PositionWrapper.cs b/src/Orchard/DisplayManagement/PositionWrapper.cs new file mode 100644 index 000000000..e684bfdb5 --- /dev/null +++ b/src/Orchard/DisplayManagement/PositionWrapper.cs @@ -0,0 +1,26 @@ +using System.Web; + +namespace Orchard.DisplayManagement { + public class PositionWrapper : IHtmlString, IPositioned { + + private IHtmlString _value; + public string Position { get; private set; } + + public PositionWrapper(IHtmlString value, string position) { + _value = value; + Position = position; + } + + public PositionWrapper(string value, string position) + : this(new HtmlString(HttpUtility.HtmlEncode(value)), position) { + } + + public string ToHtmlString() { + return _value.ToHtmlString(); + } + + public override string ToString() { + return _value.ToString(); + } + } +} diff --git a/src/Orchard/DisplayManagement/ShapeDisplay.cs b/src/Orchard/DisplayManagement/ShapeDisplay.cs index a432adb51..1313d8a13 100644 --- a/src/Orchard/DisplayManagement/ShapeDisplay.cs +++ b/src/Orchard/DisplayManagement/ShapeDisplay.cs @@ -1,6 +1,8 @@ using System.Collections.Generic; using System.Linq; +using System.Web; using System.Web.Mvc; +using System.Web.Routing; using Orchard.DisplayManagement.Implementation; using Orchard.DisplayManagement.Shapes; @@ -8,24 +10,28 @@ namespace Orchard.DisplayManagement { public class ShapeDisplay : IShapeDisplay { private readonly IDisplayHelperFactory _displayHelperFactory; private readonly IWorkContextAccessor _workContextAccessor; + private readonly HttpContextBase _httpContextBase; + private readonly RequestContext _requestContext; public ShapeDisplay( - IDisplayHelperFactory displayHelperFactory, - IWorkContextAccessor workContextAccessor) { + IDisplayHelperFactory displayHelperFactory, + IWorkContextAccessor workContextAccessor, + HttpContextBase httpContextBase, + RequestContext requestContext) { _displayHelperFactory = displayHelperFactory; _workContextAccessor = workContextAccessor; + _httpContextBase = httpContextBase; + _requestContext = requestContext; } public string Display(Shape shape) { - return Display((object)shape); + return Display((object) shape); } public string Display(object shape) { - var workContext = _workContextAccessor.GetContext(); - var httpContext = workContext.HttpContext; var viewContext = new ViewContext { - HttpContext = httpContext, - RequestContext = httpContext.Request.RequestContext + HttpContext = _httpContextBase, + RequestContext = _requestContext }; viewContext.RouteData.DataTokens["IWorkContextAccessor"] = _workContextAccessor; var display = _displayHelperFactory.CreateHelper(viewContext, new ViewDataContainer()); diff --git a/src/Orchard/DisplayManagement/Shapes/Shape.cs b/src/Orchard/DisplayManagement/Shapes/Shape.cs index d009d1123..a3e30e6d8 100644 --- a/src/Orchard/DisplayManagement/Shapes/Shape.cs +++ b/src/Orchard/DisplayManagement/Shapes/Shape.cs @@ -4,11 +4,11 @@ using System.Dynamic; using System.Linq; using System.Collections; using System.Collections.Generic; -using System.Web.Mvc; +using System.Web; namespace Orchard.DisplayManagement.Shapes { [DebuggerTypeProxy(typeof(ShapeDebugView))] - public class Shape : Composite, IShape, IEnumerable { + public class Shape : Composite, IShape, IPositioned, IEnumerable { private const string DefaultPosition = "5"; private readonly IList _items = new List(); @@ -22,6 +22,12 @@ namespace Orchard.DisplayManagement.Shapes { public virtual IDictionary Attributes { get { return _attributes; } } public virtual IEnumerable Items { get { return _items; } } + public string Position { + get { + return Metadata.Position; + } + } + public Shape() { Metadata = new ShapeMetadata(); } @@ -33,13 +39,14 @@ namespace Orchard.DisplayManagement.Shapes { } try { - // todo: (sebros) this is a temporary implementation to prevent common known scenarios throwing exceptions. The final solution would need to filter based on the fact that it is a Shape instance - if (item is MvcHtmlString || - item is String) { - // need to implement positioned wrapper for non-shape objects + if (position != null && item is IHtmlString) { + item = new PositionWrapper((IHtmlString)item, position); + } + else if (position != null && item is string) { + item = new PositionWrapper((string)item, position); } else if (item is IShape) { - ((dynamic)item).Metadata.Position = position; + ((IShape)item).Metadata.Position = position; } } catch { diff --git a/src/Orchard/Environment/ApplicationEnvironment.cs b/src/Orchard/Environment/ApplicationEnvironment.cs new file mode 100644 index 000000000..ceff22c63 --- /dev/null +++ b/src/Orchard/Environment/ApplicationEnvironment.cs @@ -0,0 +1,12 @@ +using System; +using System.Diagnostics; + +namespace Orchard.Environment { + public class ApplicationEnvironment : IApplicationEnvironment { + public string GetEnvironmentIdentifier() { + // Add process ID to machine name because multiple web servers can + // be running on the same physical machine. + return String.Format("{0}:{1}", System.Environment.MachineName, Process.GetCurrentProcess().Id); + } + } +} \ No newline at end of file diff --git a/src/Orchard/Environment/Configuration/ShellSettingsManager.cs b/src/Orchard/Environment/Configuration/ShellSettingsManager.cs index 3b7422d41..6c391cc74 100644 --- a/src/Orchard/Environment/Configuration/ShellSettingsManager.cs +++ b/src/Orchard/Environment/Configuration/ShellSettingsManager.cs @@ -9,7 +9,7 @@ namespace Orchard.Environment.Configuration { public class ShellSettingsManager : Component, IShellSettingsManager { - private const string _settingsFileName = "Settings.txt"; + private const string SettingsFileName = "Settings.txt"; private readonly IAppDataFolder _appDataFolder; private readonly IShellSettingsManagerEventHandler _events; @@ -37,7 +37,7 @@ namespace Orchard.Environment.Configuration { throw new ArgumentException("The Name property of the supplied ShellSettings object is null or empty; the settings cannot be saved.", "settings"); Logger.Information("Saving ShellSettings for tenant '{0}'...", settings.Name); - var filePath = Path.Combine(Path.Combine("Sites", settings.Name), _settingsFileName); + var filePath = Path.Combine(Path.Combine("Sites", settings.Name), SettingsFileName); _appDataFolder.CreateFile(filePath, ShellSettingsSerializer.ComposeSettings(settings)); Logger.Information("ShellSettings saved successfully; flagging tenant '{0}' for restart.", settings.Name); @@ -48,7 +48,7 @@ namespace Orchard.Environment.Configuration { var filePaths = _appDataFolder .ListDirectories("Sites") .SelectMany(path => _appDataFolder.ListFiles(path)) - .Where(path => String.Equals(Path.GetFileName(path), _settingsFileName, StringComparison.OrdinalIgnoreCase)); + .Where(path => String.Equals(Path.GetFileName(path), SettingsFileName, StringComparison.OrdinalIgnoreCase)); foreach (var filePath in filePaths) { yield return ShellSettingsSerializer.ParseSettings(_appDataFolder.ReadFile(filePath)); diff --git a/src/Orchard/Environment/Configuration/TenantState.cs b/src/Orchard/Environment/Configuration/TenantState.cs index 5f1a79060..6ef9e1815 100644 --- a/src/Orchard/Environment/Configuration/TenantState.cs +++ b/src/Orchard/Environment/Configuration/TenantState.cs @@ -1,6 +1,7 @@ namespace Orchard.Environment.Configuration { public enum TenantState { Uninitialized, + Initializing, Running, Disabled, Invalid diff --git a/src/Orchard/Environment/DefaultOrchardHost.cs b/src/Orchard/Environment/DefaultOrchardHost.cs index 6bd9076a8..948142ee3 100644 --- a/src/Orchard/Environment/DefaultOrchardHost.cs +++ b/src/Orchard/Environment/DefaultOrchardHost.cs @@ -1,7 +1,6 @@ using System; using System.Linq; using System.Collections.Generic; -using System.Security.Cryptography; using System.Threading.Tasks; using Orchard.Caching; using Orchard.Environment.Configuration; @@ -12,7 +11,10 @@ using Orchard.Environment.Descriptor; using Orchard.Environment.Descriptor.Models; using Orchard.Localization; using Orchard.Logging; +using Orchard.Mvc; +using Orchard.Mvc.Extensions; using Orchard.Utility.Extensions; +using Orchard.Exceptions; namespace Orchard.Environment { // All the event handlers that DefaultOrchardHost implements have to be declared in OrchardStarter. @@ -25,12 +27,13 @@ namespace Orchard.Environment { private readonly IExtensionLoaderCoordinator _extensionLoaderCoordinator; private readonly IExtensionMonitoringCoordinator _extensionMonitoringCoordinator; private readonly ICacheManager _cacheManager; + private readonly IHttpContextAccessor _httpContextAccessor; private readonly static object _syncLock = new object(); private readonly static object _shellContextsWriteLock = new object(); private IEnumerable _shellContexts; - private readonly ContextState> _tenantsToRestart; + public DefaultOrchardHost( IShellSettingsManager shellSettingsManager, IShellContextFactory shellContextFactory, @@ -39,7 +42,9 @@ namespace Orchard.Environment { IExtensionLoaderCoordinator extensionLoaderCoordinator, IExtensionMonitoringCoordinator extensionMonitoringCoordinator, ICacheManager cacheManager, - IHostLocalRestart hostLocalRestart) { + IHostLocalRestart hostLocalRestart, + IHttpContextAccessor httpContextAccessor) { + _shellSettingsManager = shellSettingsManager; _shellContextFactory = shellContextFactory; _runningShellTable = runningShellTable; @@ -48,6 +53,7 @@ namespace Orchard.Environment { _extensionMonitoringCoordinator = extensionMonitoringCoordinator; _cacheManager = cacheManager; _hostLocalRestart = hostLocalRestart; + _httpContextAccessor = httpContextAccessor; _tenantsToRestart = new ContextState>("DefaultOrchardHost.TenantsToRestart", () => new List()); @@ -128,20 +134,23 @@ namespace Orchard.Environment { void CreateAndActivateShells() { Logger.Information("Start creation of shells"); - // is there any tenant right now ? + // Is there any tenant right now? var allSettings = _shellSettingsManager.LoadSettings() - .Where(settings => settings.State == TenantState.Running || settings.State == TenantState.Uninitialized) + .Where(settings => settings.State == TenantState.Running || settings.State == TenantState.Uninitialized || settings.State == TenantState.Initializing) .ToArray(); - // load all tenants, and activate their shell + // Load all tenants, and activate their shell. if (allSettings.Any()) { Parallel.ForEach(allSettings, settings => { try { var context = CreateShellContext(settings); ActivateShell(context); } - catch (Exception e) { - Logger.Error(e, "A tenant could not be started: " + settings.Name); + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Error(ex, "A tenant could not be started: " + settings.Name); } while (_processingEngine.AreTasksPending()) { Logger.Debug("Processing pending task after activate Shell"); @@ -149,7 +158,7 @@ namespace Orchard.Environment { } }); } - // no settings, run the Setup + // No settings, run the Setup. else { var setupContext = CreateSetupContext(); ActivateShell(setupContext); @@ -176,23 +185,23 @@ namespace Orchard.Environment { } /// - /// Creates a transient shell for the default tenant's setup + /// Creates a transient shell for the default tenant's setup. /// private ShellContext CreateSetupContext() { - Logger.Debug("Creating shell context for root setup"); + Logger.Debug("Creating shell context for root setup."); return _shellContextFactory.CreateSetupContext(new ShellSettings { Name = ShellSettings.DefaultName }); } /// - /// Creates a shell context based on shell settings + /// Creates a shell context based on shell settings. /// private ShellContext CreateShellContext(ShellSettings settings) { - if (settings.State == TenantState.Uninitialized) { - Logger.Debug("Creating shell context for tenant {0} setup", settings.Name); + if (settings.State == TenantState.Uninitialized || settings.State == TenantState.Invalid) { + Logger.Debug("Creating shell context for tenant {0} setup.", settings.Name); return _shellContextFactory.CreateSetupContext(settings); } - Logger.Debug("Creating shell context for tenant {0}", settings.Name); + Logger.Debug("Creating shell context for tenant {0}.", settings.Name); return _shellContextFactory.CreateShellContext(settings); } @@ -204,7 +213,7 @@ namespace Orchard.Environment { // This is a "fake" cache entry to allow the extension loader coordinator // notify us (by resetting _current to "null") when an extension has changed // on disk, and we need to reload new/updated extensions. - _cacheManager.Get("OrchardHost_Extensions", + _cacheManager.Get("OrchardHost_Extensions", true, ctx => { _extensionMonitoringCoordinator.MonitorExtensions(ctx.Monitor); _hostLocalRestart.Monitor(ctx.Monitor); @@ -234,6 +243,8 @@ namespace Orchard.Environment { } protected virtual void BeginRequest() { + BlockRequestsDuringSetup(); + // Ensure all shell contexts are loaded, or need to be reloaded if // extensions have changed MonitorExtensions(); @@ -341,6 +352,25 @@ namespace Orchard.Environment { _tenantsToRestart.GetState().Add(context.Settings); } + private void BlockRequestsDuringSetup() { + var httpContext = _httpContextAccessor.Current(); + if (httpContext.IsBackgroundContext()) + return; + + // Get the requested shell. + var runningShell = _runningShellTable.Match(httpContext); + if (runningShell == null) + return; + + // If the requested shell is currently initializing, return a Service Unavailable HTTP status code. + if (runningShell.State == TenantState.Initializing) { + var response = httpContext.Response; + response.StatusCode = 503; + response.StatusDescription = "This tenant is currently initializing. Please try again later."; + response.Write("This tenant is currently initializing. Please try again later."); + } + } + // To be used from CreateStandaloneEnvironment(), also disposes the ShellContext LifetimeScope. private class StandaloneEnvironmentWorkContextScopeWrapper : IWorkContextScope { private readonly ShellContext _shellContext; diff --git a/src/Orchard/Environment/DefaultOrchardShell.cs b/src/Orchard/Environment/DefaultOrchardShell.cs index 400c0399f..8b935499d 100644 --- a/src/Orchard/Environment/DefaultOrchardShell.cs +++ b/src/Orchard/Environment/DefaultOrchardShell.cs @@ -11,11 +11,12 @@ using Orchard.Owin; using Orchard.Tasks; using Orchard.UI; using Orchard.WebApi.Routes; +using Orchard.Exceptions; using IModelBinderProvider = Orchard.Mvc.ModelBinders.IModelBinderProvider; namespace Orchard.Environment { public class DefaultOrchardShell : IOrchardShell { - private readonly Func> _eventsFactory; + private readonly IWorkContextAccessor _workContextAccessor; private readonly IEnumerable _routeProviders; private readonly IEnumerable _httpRouteProviders; private readonly IRoutePublisher _routePublisher; @@ -26,7 +27,7 @@ namespace Orchard.Environment { private readonly ShellSettings _shellSettings; public DefaultOrchardShell( - Func> eventsFactory, + IWorkContextAccessor workContextAccessor, IEnumerable routeProviders, IEnumerable httpRouteProviders, IRoutePublisher routePublisher, @@ -35,8 +36,7 @@ namespace Orchard.Environment { ISweepGenerator sweepGenerator, IEnumerable owinMiddlewareProviders, ShellSettings shellSettings) { - - _eventsFactory = eventsFactory; + _workContextAccessor = workContextAccessor; _routeProviders = routeProviders; _httpRouteProviders = httpRouteProviders; _routePublisher = routePublisher; @@ -74,8 +74,10 @@ namespace Orchard.Environment { _routePublisher.Publish(allRoutes, pipeline); _modelBinderPublisher.Publish(_modelBinderProviders.SelectMany(provider => provider.GetModelBinders())); - using (var events = _eventsFactory()) { - events.Value.Activated(); + using (var scope = _workContextAccessor.CreateWorkContextScope()) { + using (var events = scope.Resolve>()) { + events.Value.Activated(); + } } _sweepGenerator.Activate(); @@ -83,22 +85,26 @@ namespace Orchard.Environment { public void Terminate() { SafelyTerminate(() => { - using (var events = _eventsFactory()) { - var localEvents = events; - SafelyTerminate(() => localEvents.Value.Terminating()); - } + using (var scope = _workContextAccessor.CreateWorkContextScope()) { + using (var events = scope.Resolve>()) { + SafelyTerminate(() => events.Value.Terminating()); + } + } }); SafelyTerminate(() => _sweepGenerator.Terminate()); } - private void SafelyTerminate(Action action) { try { action(); } - catch(Exception e) { - Logger.Error(e, "An unexcepted error occured while terminating the Shell"); + catch(Exception ex) { + if (ex.IsFatal()) { + throw; + } + + Logger.Error(ex, "An unexcepted error occured while terminating the Shell"); } } } diff --git a/src/Orchard/Environment/Extensions/Compilers/DefaultExtensionCompiler.cs b/src/Orchard/Environment/Extensions/Compilers/DefaultExtensionCompiler.cs index 3dfc2d6af..488dcb90a 100644 --- a/src/Orchard/Environment/Extensions/Compilers/DefaultExtensionCompiler.cs +++ b/src/Orchard/Environment/Extensions/Compilers/DefaultExtensionCompiler.cs @@ -8,6 +8,7 @@ using Orchard.FileSystems.Dependencies; using Orchard.FileSystems.VirtualPath; using Orchard.Localization; using Orchard.Logging; +using Orchard.Exceptions; namespace Orchard.Environment.Extensions.Compilers { /// @@ -106,10 +107,13 @@ namespace Orchard.Environment.Extensions.Compilers { } } } - catch (Exception e) { + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } //Note: we need to embed the "e.Message" in the exception text because // ASP.NET build manager "swallows" inner exceptions from this method. - throw new OrchardCoreException(T("Error compiling module \"{0}\" from file \"{1}\":\r\n{2}", moduleName, context.VirtualPath, e.Message), e); + throw new OrchardCoreException(T("Error compiling module \"{0}\" from file \"{1}\":\r\n{2}", moduleName, context.VirtualPath, ex.Message), ex); } } diff --git a/src/Orchard/Environment/Extensions/Compilers/DefaultProjectFileParser.cs b/src/Orchard/Environment/Extensions/Compilers/DefaultProjectFileParser.cs index 01a717b12..08adf43a1 100644 --- a/src/Orchard/Environment/Extensions/Compilers/DefaultProjectFileParser.cs +++ b/src/Orchard/Environment/Extensions/Compilers/DefaultProjectFileParser.cs @@ -23,7 +23,7 @@ namespace Orchard.Environment.Extensions.Compilers { public bool DisableMonitoring { get; set; } public ProjectFileDescriptor Parse(string virtualPath) { - return _cacheManager.Get(virtualPath, + return _cacheManager.Get(virtualPath, true, ctx => { if (!DisableMonitoring) { Logger.Debug("Monitoring virtual path \"{0}\"", virtualPath); diff --git a/src/Orchard/Environment/Extensions/ExtensionManager.cs b/src/Orchard/Environment/Extensions/ExtensionManager.cs index 3701c9764..40092fd21 100644 --- a/src/Orchard/Environment/Extensions/ExtensionManager.cs +++ b/src/Orchard/Environment/Extensions/ExtensionManager.cs @@ -9,6 +9,7 @@ using Orchard.Localization; using Orchard.Logging; using Orchard.Utility; using Orchard.Utility.Extensions; +using Orchard.Exceptions; namespace Orchard.Environment.Extensions { public class ExtensionManager : IExtensionManager { @@ -44,7 +45,7 @@ namespace Orchard.Environment.Extensions { } public IEnumerable AvailableExtensions() { - return _cacheManager.Get("AvailableExtensions", ctx => + return _cacheManager.Get("AvailableExtensions", true, ctx => _parallelCacheContext .RunInParallel(_folders, folder => folder.AvailableExtensions().ToList()) .SelectMany(descriptors => descriptors) @@ -52,7 +53,7 @@ namespace Orchard.Environment.Extensions { } public IEnumerable AvailableFeatures() { - return _cacheManager.Get("AvailableFeatures", ctx => + return _cacheManager.Get("AvailableFeatures", true, ctx => AvailableExtensions() .SelectMany(ext => ext.Features) .OrderByDependenciesAndPriorities(HasDependency, GetPriority) @@ -92,7 +93,7 @@ namespace Orchard.Environment.Extensions { var result = _parallelCacheContext - .RunInParallel(featureDescriptors, descriptor => _cacheManager.Get(descriptor.Id, ctx => LoadFeature(descriptor))) + .RunInParallel(featureDescriptors, descriptor => _cacheManager.Get(descriptor.Id, true, ctx => LoadFeature(descriptor))) .ToArray(); Logger.Information("Done loading features"); @@ -106,7 +107,7 @@ namespace Orchard.Environment.Extensions { ExtensionEntry extensionEntry; try { - extensionEntry = _cacheManager.Get(extensionId, ctx => { + extensionEntry = _cacheManager.Get(extensionId, true, ctx => { var entry = BuildEntry(extensionDescriptor); if (entry != null) { ctx.Monitor(_asyncTokenProvider.GetToken(monitor => { @@ -119,6 +120,9 @@ namespace Orchard.Environment.Extensions { }); } catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } Logger.Error(ex, "Error loading extension '{0}'", extensionId); throw new OrchardException(T("Error while loading extension '{0}'.", extensionId), ex); } diff --git a/src/Orchard/Environment/Extensions/Folders/ExtensionHarvester.cs b/src/Orchard/Environment/Extensions/Folders/ExtensionHarvester.cs index 6dfe8cf80..808aa6636 100644 --- a/src/Orchard/Environment/Extensions/Folders/ExtensionHarvester.cs +++ b/src/Orchard/Environment/Extensions/Folders/ExtensionHarvester.cs @@ -9,6 +9,7 @@ using Orchard.FileSystems.WebSite; using Orchard.Localization; using Orchard.Logging; using Orchard.Utility.Extensions; +using Orchard.Exceptions; namespace Orchard.Environment.Extensions.Folders { public class ExtensionHarvester : IExtensionHarvester { @@ -57,7 +58,7 @@ namespace Orchard.Environment.Extensions.Folders { private IEnumerable HarvestExtensions(string path, string extensionType, string manifestName, bool manifestIsOptional) { string key = string.Format("{0}-{1}-{2}", path, manifestName, extensionType); - return _cacheManager.Get(key, ctx => { + return _cacheManager.Get(key, true, ctx => { if (!DisableMonitoring) { Logger.Debug("Monitoring virtual path \"{0}\"", path); ctx.Monitor(_webSiteFolder.WhenPathChanges(path)); @@ -100,6 +101,9 @@ namespace Orchard.Environment.Extensions.Folders { } catch (Exception ex) { // Ignore invalid module manifests + if (ex.IsFatal()) { + throw; + } Logger.Error(ex, "The module '{0}' could not be loaded. It was ignored.", extensionId); _criticalErrorProvider.RegisterErrorMessage(T("The extension '{0}' manifest could not be loaded. It was ignored.", extensionId)); } @@ -134,7 +138,7 @@ namespace Orchard.Environment.Extensions.Folders { } private ExtensionDescriptor GetExtensionDescriptor(string locationPath, string extensionId, string extensionType, string manifestPath, bool manifestIsOptional) { - return _cacheManager.Get(manifestPath, context => { + return _cacheManager.Get(manifestPath, true, context => { if (!DisableMonitoring) { Logger.Debug("Monitoring virtual path \"{0}\"", manifestPath); context.Monitor(_webSiteFolder.WhenPathChanges(manifestPath)); diff --git a/src/Orchard/Environment/IApplicationEnvironment.cs b/src/Orchard/Environment/IApplicationEnvironment.cs new file mode 100644 index 000000000..cccd6fb53 --- /dev/null +++ b/src/Orchard/Environment/IApplicationEnvironment.cs @@ -0,0 +1,13 @@ +namespace Orchard.Environment { + + /// + /// Describes a service which returns the a machine identifier running the application. + /// + public interface IApplicationEnvironment { + + /// + /// Returns the machine identifier running the application. + /// + string GetEnvironmentIdentifier(); + } +} \ No newline at end of file diff --git a/src/Orchard/Environment/IAssemblyLoader.cs b/src/Orchard/Environment/IAssemblyLoader.cs index 410822a45..32722b5f1 100644 --- a/src/Orchard/Environment/IAssemblyLoader.cs +++ b/src/Orchard/Environment/IAssemblyLoader.cs @@ -4,6 +4,8 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using Orchard.Logging; +using Orchard.Exceptions; + namespace Orchard.Environment { public interface IAssemblyLoader { @@ -25,8 +27,11 @@ namespace Orchard.Environment { try { return _loadedAssemblies.GetOrAdd(this.ExtractAssemblyShortName(assemblyName), shortName => LoadWorker(shortName, assemblyName)); } - catch (Exception e) { - Logger.Error(e, "Error loading assembly '{0}'", assemblyName); + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Error(ex, "Error loading assembly '{0}'", assemblyName); return null; } } diff --git a/src/Orchard/Environment/IAssemblyNameResolver.cs b/src/Orchard/Environment/IAssemblyNameResolver.cs index f97631719..78d809ab7 100644 --- a/src/Orchard/Environment/IAssemblyNameResolver.cs +++ b/src/Orchard/Environment/IAssemblyNameResolver.cs @@ -37,7 +37,7 @@ namespace Orchard.Environment { public string Resolve(string shortName) { // A few common .net framework assemblies are referenced by the Orchard.Framework assembly. // Look into those to see if we can find the assembly we are looking for. - var orchardFrameworkReferences = _cacheManager.Get(typeof(IAssemblyLoader), ctx => + var orchardFrameworkReferences = _cacheManager.Get(typeof(IAssemblyLoader), true, ctx => ctx.Key.Assembly .GetReferencedAssemblies() .GroupBy(n => AssemblyLoaderExtensions.ExtractAssemblyShortName(n.FullName), StringComparer.OrdinalIgnoreCase) diff --git a/src/Orchard/Environment/IBuildManager.cs b/src/Orchard/Environment/IBuildManager.cs index d9ac231ab..40b8c9aa8 100644 --- a/src/Orchard/Environment/IBuildManager.cs +++ b/src/Orchard/Environment/IBuildManager.cs @@ -53,8 +53,9 @@ namespace Orchard.Environment { return BuildManager.GetCompiledAssembly(virtualPath); } catch (Exception ex) { - if (ex.IsFatal()) throw; - + if (ex.IsFatal()) { + throw; + } Logger.Warning(ex, "Error when compiling assembly under {0}.", virtualPath); return null; } diff --git a/src/Orchard/Environment/IHostLocalRestart.cs b/src/Orchard/Environment/IHostLocalRestart.cs index 90a2371d2..f801e6efe 100644 --- a/src/Orchard/Environment/IHostLocalRestart.cs +++ b/src/Orchard/Environment/IHostLocalRestart.cs @@ -5,6 +5,7 @@ using Orchard.Environment.Descriptor; using Orchard.Environment.Descriptor.Models; using Orchard.FileSystems.AppData; using Orchard.Logging; +using Orchard.Exceptions; namespace Orchard.Environment { public interface IHostLocalRestart { @@ -45,8 +46,11 @@ namespace Orchard.Environment { try { _appDataFolder.CreateFile(fileName, "Host Restart"); } - catch(Exception e) { - Logger.Warning(e, "Error updating file '{0}'", fileName); + catch(Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Warning(ex, "Error updating file '{0}'", fileName); } } } diff --git a/src/Orchard/Environment/IMachineNameProvider.cs b/src/Orchard/Environment/IMachineNameProvider.cs deleted file mode 100644 index 93391e934..000000000 --- a/src/Orchard/Environment/IMachineNameProvider.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Orchard.Environment { - - /// - /// Describes a service which returns the name of the machine running the application. - /// - public interface IMachineNameProvider { - - /// - /// Returns the name of the machine running the application. - /// - string GetMachineName(); - } -} \ No newline at end of file diff --git a/src/Orchard/Environment/IOrchardHost.cs b/src/Orchard/Environment/IOrchardHost.cs index aee8940e2..613176f2e 100644 --- a/src/Orchard/Environment/IOrchardHost.cs +++ b/src/Orchard/Environment/IOrchardHost.cs @@ -1,6 +1,5 @@ using Orchard.Environment.Configuration; using Orchard.Environment.ShellBuilders; -using Orchard.Localization; namespace Orchard.Environment { public interface IOrchardHost { diff --git a/src/Orchard/Environment/IThreadProvider.cs b/src/Orchard/Environment/IThreadProvider.cs deleted file mode 100644 index 29458bf27..000000000 --- a/src/Orchard/Environment/IThreadProvider.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Orchard.Environment { - - /// - /// Describes a service which returns the managed thread ID of the current thread. - /// - public interface IThreadProvider { - - /// - /// Returns the managed thread ID of the current thread. - /// - int GetCurrentThreadId(); - } -} \ No newline at end of file diff --git a/src/Orchard/Environment/MachineNameProvider.cs b/src/Orchard/Environment/MachineNameProvider.cs deleted file mode 100644 index 4c7543b0a..000000000 --- a/src/Orchard/Environment/MachineNameProvider.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Orchard.Environment { - public class MachineNameProvider : IMachineNameProvider { - public string GetMachineName() { - return System.Environment.MachineName; - } - } -} \ No newline at end of file diff --git a/src/Orchard/Environment/OrchardStarter.cs b/src/Orchard/Environment/OrchardStarter.cs index 1e0db5736..79736c0be 100644 --- a/src/Orchard/Environment/OrchardStarter.cs +++ b/src/Orchard/Environment/OrchardStarter.cs @@ -63,11 +63,10 @@ namespace Orchard.Environment { builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().SingleInstance(); - builder.RegisterType().As().SingleInstance(); + builder.RegisterType().As().InstancePerDependency(); builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().SingleInstance(); - builder.RegisterType().As().SingleInstance(); //builder.RegisterType().As().SingleInstance(); RegisterVolatileProvider(builder); @@ -80,7 +79,6 @@ namespace Orchard.Environment { RegisterVolatileProvider(builder); RegisterVolatileProvider(builder); - builder.RegisterType().As().As() .Named(typeof(IShellSettingsManagerEventHandler).Name) .Named(typeof(IShellDescriptorManagerEventHandler).Name) diff --git a/src/Orchard/Environment/ShellBuilders/CompositionStrategy.cs b/src/Orchard/Environment/ShellBuilders/CompositionStrategy.cs index 08988203d..5226f0a09 100644 --- a/src/Orchard/Environment/ShellBuilders/CompositionStrategy.cs +++ b/src/Orchard/Environment/ShellBuilders/CompositionStrategy.cs @@ -9,7 +9,6 @@ using Orchard.ContentManagement.Records; using Orchard.Environment.Configuration; using Orchard.Environment.Descriptor.Models; using Orchard.Environment.Extensions; -using Orchard.Environment.Extensions.Helpers; using Orchard.Environment.Extensions.Models; using Orchard.Environment.ShellBuilders.Models; using Orchard.Localization; @@ -34,7 +33,11 @@ namespace Orchard.Environment.ShellBuilders { var builtinFeatures = BuiltinFeatures().ToList(); var builtinFeatureDescriptors = builtinFeatures.Select(x => x.Descriptor).ToList(); - var availableFeatures = _extensionManager.AvailableFeatures().Concat(builtinFeatureDescriptors).ToDictionary(x => x.Id, StringComparer.OrdinalIgnoreCase); + var availableFeatures = _extensionManager.AvailableFeatures() + .Concat(builtinFeatureDescriptors) + .GroupBy(x => x.Id.ToLowerInvariant()) // prevent duplicates + .Select(x => x.FirstOrDefault()) + .ToDictionary(x => x.Id, StringComparer.OrdinalIgnoreCase); var enabledFeatures = _extensionManager.EnabledFeatures(descriptor).Select(x => x.Id).ToList(); var expandedFeatures = ExpandDependencies(availableFeatures, descriptor.Features.Select(x => x.Name)).ToList(); var autoEnabledDependencyFeatures = expandedFeatures.Except(enabledFeatures).Except(builtinFeatureDescriptors.Select(x => x.Id)).ToList(); @@ -72,19 +75,29 @@ namespace Orchard.Environment.ShellBuilders { } private IEnumerable ExpandDependencies(IDictionary availableFeatures, IEnumerable features) { - return ExpandDependenciesInternal(availableFeatures, features).Distinct(); + return ExpandDependenciesInternal(availableFeatures, features, dependentFeatureDescriptor: null).Distinct(); } - private IEnumerable ExpandDependenciesInternal(IDictionary availableFeatures, IEnumerable features) { + private IEnumerable ExpandDependenciesInternal(IDictionary availableFeatures, IEnumerable features, FeatureDescriptor dependentFeatureDescriptor = null) { foreach (var shellFeature in features) { if (!availableFeatures.ContainsKey(shellFeature)) { - throw new OrchardException(T("The feature {0} is not available", shellFeature)); + // If the feature comes from a list of feature dependencies it indicates a bug, so throw an exception. + if(dependentFeatureDescriptor != null) + throw new OrchardException( + T("The feature '{0}' was listed as a dependency of '{1}' of extension '{2}', but this feature could not be found. Please update your manifest file or install the module providing the missing feature.", + shellFeature, + dependentFeatureDescriptor.Name, + dependentFeatureDescriptor.Extension.Name)); + + // If the feature comes from the shell descriptor it means the feature is simply orphaned, so don't throw an exception. + Logger.Warning("Identified '{0}' as an orphaned feature state record in Settings_ShellFeatureRecord.", shellFeature); + continue; } var feature = availableFeatures[shellFeature]; - foreach (var childDependency in ExpandDependenciesInternal(availableFeatures, feature.Dependencies)) + foreach (var childDependency in ExpandDependenciesInternal(availableFeatures, feature.Dependencies, dependentFeatureDescriptor: feature)) yield return childDependency; foreach (var dependency in feature.Dependencies) diff --git a/src/Orchard/Environment/ShellBuilders/ShellContainerFactory.cs b/src/Orchard/Environment/ShellBuilders/ShellContainerFactory.cs index 145f40f98..e621c6a6b 100644 --- a/src/Orchard/Environment/ShellBuilders/ShellContainerFactory.cs +++ b/src/Orchard/Environment/ShellBuilders/ShellContainerFactory.cs @@ -135,6 +135,10 @@ namespace Orchard.Environment.ShellBuilders { if (File.Exists(optionalShellConfig)) builder.RegisterModule(new ConfigurationSettingsReader(ConfigurationSettingsReaderConstants.DefaultSectionName, optionalShellConfig)); } + + var optionalComponentsConfig = HostingEnvironment.MapPath("~/Config/HostComponents.config"); + if (File.Exists(optionalComponentsConfig)) + builder.RegisterModule(new HostComponentsConfigModule(optionalComponentsConfig)); }); } diff --git a/src/Orchard/Environment/ShellBuilders/ShellContextFactory.cs b/src/Orchard/Environment/ShellBuilders/ShellContextFactory.cs index 7df34f2fe..5646a3b3c 100644 --- a/src/Orchard/Environment/ShellBuilders/ShellContextFactory.cs +++ b/src/Orchard/Environment/ShellBuilders/ShellContextFactory.cs @@ -103,7 +103,7 @@ namespace Orchard.Environment.ShellBuilders { Features = new[] { new ShellFeature { Name = "Orchard.Setup" }, new ShellFeature { Name = "Shapes" }, - new ShellFeature { Name = "Orchard.jQuery" }, + new ShellFeature { Name = "Orchard.jQuery" } }, }; diff --git a/src/Orchard/Environment/ThreadProvider.cs b/src/Orchard/Environment/ThreadProvider.cs deleted file mode 100644 index d3a65d8fb..000000000 --- a/src/Orchard/Environment/ThreadProvider.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Threading; - -namespace Orchard.Environment { - public class ThreadProvider : IThreadProvider { - public int GetCurrentThreadId() { - return Thread.CurrentThread.ManagedThreadId; - } - } -} \ No newline at end of file diff --git a/src/Orchard/Environment/ViewsBackgroundCompilation.cs b/src/Orchard/Environment/ViewsBackgroundCompilation.cs index 919fc9bd2..e85526860 100644 --- a/src/Orchard/Environment/ViewsBackgroundCompilation.cs +++ b/src/Orchard/Environment/ViewsBackgroundCompilation.cs @@ -6,6 +6,7 @@ using System.Timers; using System.Web.Compilation; using Orchard.FileSystems.VirtualPath; using Orchard.Logging; +using Orchard.Exceptions; namespace Orchard.Environment { public interface IViewsBackgroundCompilation { @@ -136,10 +137,13 @@ namespace Orchard.Environment { if (firstFile != null) BuildManager.GetCompiledAssembly(firstFile); } - catch(Exception e) { + catch(Exception ex) { + if (ex.IsFatal()) { + throw; + } // Some views might not compile, this is ok and harmless in this // context of pre-compiling views. - Logger.Information(e, "Compilation of directory '{0}' skipped", viewDirectory); + Logger.Information(ex, "Compilation of directory '{0}' skipped", viewDirectory); } stopwatch.Stop(); Logger.Information("Directory '{0}' compiled in {1} msec", viewDirectory, stopwatch.ElapsedMilliseconds); diff --git a/src/Orchard/Environment/WorkContextAccessor.cs b/src/Orchard/Environment/WorkContextAccessor.cs index 7e6bd0ea3..af709d0d5 100644 --- a/src/Orchard/Environment/WorkContextAccessor.cs +++ b/src/Orchard/Environment/WorkContextAccessor.cs @@ -60,14 +60,11 @@ namespace Orchard.Environment { return CreateWorkContextScope(httpContext); var workLifetime = _lifetimeScope.BeginLifetimeScope("work"); - httpContext = _httpContextAccessor.CreateContext(workLifetime); - workLifetime.Resolve>().Value = httpContext; var events = workLifetime.Resolve>(); events.Invoke(e => e.Started(), NullLogger.Instance); return new ThreadStaticScopeImplementation( - httpContext, events, workLifetime, EnsureThreadStaticContexts(), @@ -116,9 +113,8 @@ namespace Orchard.Environment { readonly WorkContext _workContext; readonly Action _disposer; - public ThreadStaticScopeImplementation(HttpContextBase httpContext, IEnumerable events, ILifetimeScope lifetimeScope, ConcurrentDictionary contexts, object workContextKey) { + public ThreadStaticScopeImplementation(IEnumerable events, ILifetimeScope lifetimeScope, ConcurrentDictionary contexts, object workContextKey) { _workContext = lifetimeScope.Resolve(); - httpContext.Items[workContextKey] = _workContext; contexts.AddOrUpdate(workContextKey, _workContext, (a, b) => _workContext); _disposer = () => { @@ -127,11 +123,6 @@ namespace Orchard.Environment { WorkContext removedContext; contexts.TryRemove(workContextKey, out removedContext); lifetimeScope.Dispose(); - - var staticHttpContext = httpContext as IDisposable; - - if(staticHttpContext != null) - staticHttpContext.Dispose(); }; } diff --git a/src/Orchard/Environment/WorkContextImplementation.cs b/src/Orchard/Environment/WorkContextImplementation.cs index 85a5f9fda..63269e079 100644 --- a/src/Orchard/Environment/WorkContextImplementation.cs +++ b/src/Orchard/Environment/WorkContextImplementation.cs @@ -8,28 +8,36 @@ namespace Orchard.Environment { class WorkContextImplementation : WorkContext { readonly IComponentContext _componentContext; readonly ConcurrentDictionary> _stateResolvers = new ConcurrentDictionary>(); - readonly IEnumerable _workContextStateProviders; + readonly IEnumerable> _workContextStateProviders; public WorkContextImplementation(IComponentContext componentContext) { _componentContext = componentContext; - _workContextStateProviders = componentContext.Resolve>(); + _workContextStateProviders = componentContext.Resolve>>(); } public override T Resolve() { return _componentContext.Resolve(); } + public override object Resolve(Type serviceType) { + return _componentContext.Resolve(serviceType); + } + public override bool TryResolve(out T service) { return _componentContext.TryResolve(out service); } + public override bool TryResolve(Type serviceType, out object service) { + return _componentContext.TryResolve(serviceType, out service); + } + public override T GetState(string name) { var resolver = _stateResolvers.GetOrAdd(name, FindResolverForState); return (T)resolver(); } Func FindResolverForState(string name) { - var resolver = _workContextStateProviders.Select(wcsp => wcsp.Get(name)).FirstOrDefault(value => !Equals(value, default(T))); + var resolver = _workContextStateProviders.Select(wcsp => wcsp.Value.Get(name)).FirstOrDefault(value => !Equals(value, default(T))); if (resolver == null) { return () => default(T); diff --git a/src/Orchard/Environment/WorkContextModule.cs b/src/Orchard/Environment/WorkContextModule.cs index e9475bed3..89778a422 100644 --- a/src/Orchard/Environment/WorkContextModule.cs +++ b/src/Orchard/Environment/WorkContextModule.cs @@ -6,7 +6,6 @@ using System.Web; using Autofac; using Autofac.Builder; using Autofac.Core; -using Autofac.Features.Metadata; using Module = Autofac.Module; namespace Orchard.Environment { @@ -24,10 +23,6 @@ namespace Orchard.Environment { .As>() .InstancePerMatchingLifetimeScope("work"); - builder.Register(ctx => ctx.Resolve>().Value) - .As() - .InstancePerDependency(); - builder.RegisterGeneric(typeof(WorkValues<>)) .InstancePerMatchingLifetimeScope("work"); diff --git a/src/Orchard/Events/DefaultOrchardEventBus.cs b/src/Orchard/Events/DefaultOrchardEventBus.cs index d69d84023..2a5faf49e 100644 --- a/src/Orchard/Events/DefaultOrchardEventBus.cs +++ b/src/Orchard/Events/DefaultOrchardEventBus.cs @@ -53,6 +53,9 @@ namespace Orchard.Events { return TryInvoke(eventHandler, messageName, interfaceName, methodName, eventData, out returnValue); } catch (Exception exception) { + if (exception.IsFatal()) { + throw; + } if (!_exceptionPolicy.HandleException(this, exception)) { throw; } diff --git a/src/Orchard/Events/DelegateHelper.cs b/src/Orchard/Events/DelegateHelper.cs index cf3803828..98bc20489 100644 --- a/src/Orchard/Events/DelegateHelper.cs +++ b/src/Orchard/Events/DelegateHelper.cs @@ -100,7 +100,7 @@ namespace Orchard.Events { } static Func BuildFunc(MethodInfo method) { - var func = (Func)Delegate.CreateDelegate(typeof(Func), method); + var func = (Func)Delegate.CreateDelegate(typeof(Func), method); Func ret = (target, p) => func((T)target, (T1)p[0], (T2)p[1], (T3)p[2], (T4)p[3], (T5)p[4], (T6)p[5], (T7)p[6], (T8)p[7], (T9)p[8], (T10)p[9]); return ret; } diff --git a/src/Orchard/FileSystems/AppData/AppDataFolder.cs b/src/Orchard/FileSystems/AppData/AppDataFolder.cs index 02e60e283..092ca9b45 100644 --- a/src/Orchard/FileSystems/AppData/AppDataFolder.cs +++ b/src/Orchard/FileSystems/AppData/AppDataFolder.cs @@ -7,6 +7,7 @@ using Orchard.FileSystems.VirtualPath; using Orchard.Localization; using Orchard.Logging; using Orchard.Validation; +using Orchard.Exceptions; namespace Orchard.FileSystems.AppData { public class AppDataFolder : IAppDataFolder { @@ -78,8 +79,11 @@ namespace Orchard.FileSystems.AppData { try { File.Delete(destinationFileName); } - catch (Exception e) { - throw new OrchardCoreException(T("Unable to make room for file \"{0}\" in \"App_Data\" folder", destinationFileName), e); + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + throw new OrchardCoreException(T("Unable to make room for file \"{0}\" in \"App_Data\" folder", destinationFileName), ex); } } diff --git a/src/Orchard/FileSystems/Dependencies/DefaultDependenciesFolder.cs b/src/Orchard/FileSystems/Dependencies/DefaultDependenciesFolder.cs index de9c05869..ace5674fe 100644 --- a/src/Orchard/FileSystems/Dependencies/DefaultDependenciesFolder.cs +++ b/src/Orchard/FileSystems/Dependencies/DefaultDependenciesFolder.cs @@ -34,7 +34,7 @@ namespace Orchard.FileSystems.Dependencies { } public IEnumerable LoadDescriptors() { - return _cacheManager.Get(PersistencePath, + return _cacheManager.Get(PersistencePath, true, ctx => { _appDataFolder.CreateDirectory(BasePath); diff --git a/src/Orchard/FileSystems/Dependencies/DefaultExtensionDependenciesManager.cs b/src/Orchard/FileSystems/Dependencies/DefaultExtensionDependenciesManager.cs index c917c679d..afde10403 100644 --- a/src/Orchard/FileSystems/Dependencies/DefaultExtensionDependenciesManager.cs +++ b/src/Orchard/FileSystems/Dependencies/DefaultExtensionDependenciesManager.cs @@ -5,6 +5,7 @@ using System.Xml.Linq; using Orchard.Caching; using Orchard.FileSystems.AppData; using Orchard.Logging; +using Orchard.Exceptions; namespace Orchard.FileSystems.Dependencies { /// @@ -64,7 +65,7 @@ namespace Orchard.FileSystems.Dependencies { } public IEnumerable LoadDescriptors() { - return _cacheManager.Get(PersistencePath, ctx => { + return _cacheManager.Get(PersistencePath, true, ctx => { _appDataFolder.CreateDirectory(BasePath); if (!DisableMonitoring) { @@ -135,8 +136,11 @@ namespace Orchard.FileSystems.Dependencies { return XDocument.Load(stream); } } - catch (Exception e) { - Logger.Information(e, "Error reading file '{0}'. Assuming empty.", persistancePath); + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Information(ex, "Error reading file '{0}'. Assuming empty.", persistancePath); return new XDocument(); } } diff --git a/src/Orchard/FileSystems/Media/FileSystemStorageProvider.cs b/src/Orchard/FileSystems/Media/FileSystemStorageProvider.cs index e4ad40152..214de9205 100644 --- a/src/Orchard/FileSystems/Media/FileSystemStorageProvider.cs +++ b/src/Orchard/FileSystems/Media/FileSystemStorageProvider.cs @@ -6,6 +6,7 @@ using System.Web.Hosting; using Orchard.Environment.Configuration; using Orchard.Localization; using Orchard.Validation; +using Orchard.Exceptions; namespace Orchard.FileSystems.Media { public class FileSystemStorageProvider : IStorageProvider { @@ -155,6 +156,9 @@ namespace Orchard.FileSystems.Media { directoryInfo.Create(); } catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } throw new ArgumentException(T("The folder could not be created at path: {0}. {1}", path, ex).ToString()); } } diff --git a/src/Orchard/FileSystems/VirtualPath/DefaultVirtualPathProvider.cs b/src/Orchard/FileSystems/VirtualPath/DefaultVirtualPathProvider.cs index 85a295d1b..4c2941e91 100644 --- a/src/Orchard/FileSystems/VirtualPath/DefaultVirtualPathProvider.cs +++ b/src/Orchard/FileSystems/VirtualPath/DefaultVirtualPathProvider.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Web; using System.Web.Hosting; using Orchard.Logging; +using Orchard.Exceptions; namespace Orchard.FileSystems.VirtualPath { public class DefaultVirtualPathProvider : IVirtualPathProvider { @@ -59,9 +60,12 @@ namespace Orchard.FileSystems.VirtualPath { } return result; } - catch (Exception e) { + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } // The initial path might have been invalid (e.g. path indicates a path outside the application root) - Logger.Information(e, "Path '{0}' cannot be made app relative", virtualPath); + Logger.Information(ex, "Path '{0}' cannot be made app relative", virtualPath); return null; } } @@ -156,8 +160,11 @@ namespace Orchard.FileSystems.VirtualPath { try { return FileExists(virtualPath); } - catch (Exception e) { - Logger.Information(e, "File '{0}' can not be checked for existence. Assuming doesn't exist.", virtualPath); + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Information(ex, "File '{0}' can not be checked for existence. Assuming doesn't exist.", virtualPath); return false; } } diff --git a/src/Orchard/IBackgroundHttpContextFactory.cs b/src/Orchard/IBackgroundHttpContextFactory.cs new file mode 100644 index 000000000..1437518f8 --- /dev/null +++ b/src/Orchard/IBackgroundHttpContextFactory.cs @@ -0,0 +1,8 @@ +using System.Web; + +namespace Orchard { + public interface IBackgroundHttpContextFactory : IDependency { + HttpContext CreateHttpContext(); + void InitializeHttpContext(); + } +} diff --git a/src/Orchard/IStaticHttpContextScopeFactory.cs b/src/Orchard/IStaticHttpContextScopeFactory.cs deleted file mode 100644 index bec2219e5..000000000 --- a/src/Orchard/IStaticHttpContextScopeFactory.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; - -namespace Orchard { - /// - /// A factory class that creates an instance and initializes the HttpContext.Current property with that instance until the scope is disposed of. - /// This is useful when rendering views from a background thread, as some Html Helpers access HttpContext.Current directly, thus preventing a NullReferenceException. - /// - public interface IStaticHttpContextScopeFactory : IDependency { - /// - /// Creates a disposable static HttpContext scope. This is safe to use even if there is an actual HttpContext.Current instance. - /// - /// - IDisposable CreateStaticScope(); - } -} diff --git a/src/Orchard/Localization/Services/DefaultCultureManager.cs b/src/Orchard/Localization/Services/DefaultCultureManager.cs index 9026e4acb..19ffa05b8 100644 --- a/src/Orchard/Localization/Services/DefaultCultureManager.cs +++ b/src/Orchard/Localization/Services/DefaultCultureManager.cs @@ -26,7 +26,7 @@ namespace Orchard.Localization.Services { } public IEnumerable ListCultures() { - return _cacheManager.Get("Cultures", context => { + return _cacheManager.Get("Cultures", true, context => { context.Monitor(_signals.When("culturesChanged")); return _cultureRepository.Table.Select(o => o.Culture).ToList(); diff --git a/src/Orchard/Localization/Services/DefaultLocalizedStringManager.cs b/src/Orchard/Localization/Services/DefaultLocalizedStringManager.cs index cb9516399..e0a2a29de 100644 --- a/src/Orchard/Localization/Services/DefaultLocalizedStringManager.cs +++ b/src/Orchard/Localization/Services/DefaultLocalizedStringManager.cs @@ -90,7 +90,7 @@ namespace Orchard.Localization.Services { // Cache entry will be invalidated any time the directories hosting // the .po files are modified. private CultureDictionary LoadCulture(string culture) { - return _cacheManager.Get(culture, ctx => { + return _cacheManager.Get(culture, true, ctx => { ctx.Monitor(_signals.When("culturesChanged")); return new CultureDictionary { CultureName = culture, diff --git a/src/Orchard/Messaging/Services/DefaultMessageManager.cs b/src/Orchard/Messaging/Services/DefaultMessageManager.cs index 8e2911857..1495f9e37 100644 --- a/src/Orchard/Messaging/Services/DefaultMessageManager.cs +++ b/src/Orchard/Messaging/Services/DefaultMessageManager.cs @@ -5,6 +5,7 @@ using Orchard.Logging; using Orchard.Messaging.Events; using Orchard.Messaging.Models; using Orchard.ContentManagement.Records; +using Orchard.Exceptions; namespace Orchard.Messaging.Services { [Obsolete] @@ -40,8 +41,11 @@ namespace Orchard.Messaging.Services { PrepareAndSend(type, properties, context); } - catch ( Exception e ) { - Logger.Error(e, "An error occured while sending the message {0}", type); + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Error(ex, "An error occured while sending the message {0}", type); } } @@ -60,8 +64,11 @@ namespace Orchard.Messaging.Services { PrepareAndSend(type, properties, context); } - catch (Exception e) { - Logger.Error(e, "An error occured while sending the message {0}", type); + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Error(ex, "An error occured while sending the message {0}", type); } } diff --git a/src/Orchard/Mvc/Extensions/HttpContextBaseExtensions.cs b/src/Orchard/Mvc/Extensions/HttpContextBaseExtensions.cs new file mode 100644 index 000000000..9a7864887 --- /dev/null +++ b/src/Orchard/Mvc/Extensions/HttpContextBaseExtensions.cs @@ -0,0 +1,9 @@ +using System.Web; + +namespace Orchard.Mvc.Extensions { + public static class HttpContextBaseExtensions { + public static bool IsBackgroundContext(this HttpContextBase httpContextBase) { + return httpContextBase == null || httpContextBase is MvcModule.HttpContextPlaceholder; + } + } +} diff --git a/src/Orchard/Mvc/Extensions/HttpContextExtensions.cs b/src/Orchard/Mvc/Extensions/HttpContextExtensions.cs deleted file mode 100644 index f12ebe884..000000000 --- a/src/Orchard/Mvc/Extensions/HttpContextExtensions.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Web; - -namespace Orchard.Mvc.Extensions { - public static class HttpContextExtensions { - public static bool IsBackgroundContext(this HttpContextBase httpContext) { - return httpContext == null || httpContext is MvcModule.HttpContextPlaceholder; - } - - public static bool IsBackgroundContext(this HttpContext httpContext) { - return httpContext == null || httpContext.Items.Contains(StaticHttpContextScopeFactory.IsBackgroundHttpContextKey); - } - } -} diff --git a/src/Orchard/Mvc/Html/LinkExtensions.cs b/src/Orchard/Mvc/Html/LinkExtensions.cs new file mode 100644 index 000000000..34db0c758 --- /dev/null +++ b/src/Orchard/Mvc/Html/LinkExtensions.cs @@ -0,0 +1,144 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Web; +using System.Web.Mvc; +using System.Web.Routing; +using System.Web.WebPages; + +namespace Orchard.Mvc.Html { + public static class LinkExtensions { + public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName) { + return ActionLink(htmlHelper, linkText, actionName, null /* controllerName */, new RouteValueDictionary(), new RouteValueDictionary()); + } + + public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, object routeValues) { + return ActionLink(htmlHelper, linkText, actionName, null /* controllerName */, ObjectToDictionary(routeValues), new RouteValueDictionary()); + } + + public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, object routeValues, object htmlAttributes) { + return ActionLink(htmlHelper, linkText, actionName, null /* controllerName */, ObjectToDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); + } + + public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, RouteValueDictionary routeValues) { + return ActionLink(htmlHelper, linkText, actionName, null /* controllerName */, routeValues, new RouteValueDictionary()); + } + + public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, RouteValueDictionary routeValues, IDictionary htmlAttributes) { + return ActionLink(htmlHelper, linkText, actionName, null /* controllerName */, routeValues, htmlAttributes); + } + + public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, string controllerName) { + return ActionLink(htmlHelper, linkText, actionName, controllerName, new RouteValueDictionary(), new RouteValueDictionary()); + } + + public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, string controllerName, object routeValues, object htmlAttributes) { + return ActionLink(htmlHelper, linkText, actionName, controllerName, ObjectToDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); + } + + public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary htmlAttributes) { + if (String.IsNullOrEmpty(linkText.ToString())) { + throw new ArgumentException("Argument must be a non empty string", "linkText"); + } + return MvcHtmlString.Create(GenerateLink(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection, linkText, null /* routeName */, actionName, controllerName, routeValues, htmlAttributes)); + } + + public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, string controllerName, string protocol, string hostName, string fragment, object routeValues, object htmlAttributes) { + return ActionLink(htmlHelper, linkText, actionName, controllerName, protocol, hostName, fragment, ObjectToDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); + } + + public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, IHtmlString linkText, string actionName, string controllerName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, IDictionary htmlAttributes) { + if (String.IsNullOrEmpty(linkText.ToString())) { + throw new ArgumentException("Argument must be a non empty string", "linkText"); + } + return MvcHtmlString.Create(GenerateLink(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection, linkText, null /* routeName */, actionName, controllerName, protocol, hostName, fragment, routeValues, htmlAttributes)); + } + + public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, object routeValues) { + return RouteLink(htmlHelper, linkText, ObjectToDictionary(routeValues)); + } + + public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, RouteValueDictionary routeValues) { + return RouteLink(htmlHelper, linkText, routeValues, new RouteValueDictionary()); + } + + public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, string routeName) { + return RouteLink(htmlHelper, linkText, routeName, (object)null /* routeValues */); + } + + public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, string routeName, object routeValues) { + return RouteLink(htmlHelper, linkText, routeName, ObjectToDictionary(routeValues)); + } + + public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, string routeName, RouteValueDictionary routeValues) { + return RouteLink(htmlHelper, linkText, routeName, routeValues, new RouteValueDictionary()); + } + + public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, object routeValues, object htmlAttributes) { + return RouteLink(htmlHelper, linkText, ObjectToDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); + } + + public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, RouteValueDictionary routeValues, IDictionary htmlAttributes) { + return RouteLink(htmlHelper, linkText, null /* routeName */, routeValues, htmlAttributes); + } + + public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, string routeName, object routeValues, object htmlAttributes) { + return RouteLink(htmlHelper, linkText, routeName, ObjectToDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); + } + + public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, string routeName, RouteValueDictionary routeValues, IDictionary htmlAttributes) { + if (String.IsNullOrEmpty(linkText.ToString())) { + throw new ArgumentException("Argument must be a non empty string", "linkText"); + } + return MvcHtmlString.Create(GenerateRouteLink(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection, linkText, routeName, routeValues, htmlAttributes)); + } + + public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, string routeName, string protocol, string hostName, string fragment, object routeValues, object htmlAttributes) { + return RouteLink(htmlHelper, linkText, routeName, protocol, hostName, fragment, ObjectToDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); + } + + public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, IHtmlString linkText, string routeName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, IDictionary htmlAttributes) { + if (String.IsNullOrEmpty(linkText.ToString())) { + throw new ArgumentException("Argument must be a non empty string", "linkText"); + } + return MvcHtmlString.Create(GenerateRouteLink(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection, linkText, routeName, protocol, hostName, fragment, routeValues, htmlAttributes)); + } + + public static string GenerateLink(RequestContext requestContext, RouteCollection routeCollection, IHtmlString linkText, string routeName, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary htmlAttributes) { + return GenerateLink(requestContext, routeCollection, linkText, routeName, actionName, controllerName, null /* protocol */, null /* hostName */, null /* fragment */, routeValues, htmlAttributes); + } + + public static string GenerateLink(RequestContext requestContext, RouteCollection routeCollection, IHtmlString linkText, string routeName, string actionName, string controllerName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, IDictionary htmlAttributes) { + return GenerateLinkInternal(requestContext, routeCollection, linkText, routeName, actionName, controllerName, protocol, hostName, fragment, routeValues, htmlAttributes, true /* includeImplicitMvcValues */); + } + + public static string GenerateRouteLink(RequestContext requestContext, RouteCollection routeCollection, IHtmlString linkText, string routeName, RouteValueDictionary routeValues, IDictionary htmlAttributes) { + return GenerateRouteLink(requestContext, routeCollection, linkText, routeName, null /* protocol */, null /* hostName */, null /* fragment */, routeValues, htmlAttributes); + } + + public static string GenerateRouteLink(RequestContext requestContext, RouteCollection routeCollection, IHtmlString linkText, string routeName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, IDictionary htmlAttributes) { + return GenerateLinkInternal(requestContext, routeCollection, linkText, routeName, null /* actionName */, null /* controllerName */, protocol, hostName, fragment, routeValues, htmlAttributes, false /* includeImplicitMvcValues */); + } + private static string GenerateLinkInternal(RequestContext requestContext, RouteCollection routeCollection, IHtmlString linkText, string routeName, string actionName, string controllerName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, IDictionary htmlAttributes, bool includeImplicitMvcValues) { + string url = UrlHelper.GenerateUrl(routeName, actionName, controllerName, protocol, hostName, fragment, routeValues, routeCollection, requestContext, includeImplicitMvcValues); + TagBuilder tagBuilder = new TagBuilder("a") { + InnerHtml = linkText.ToString() + }; + tagBuilder.MergeAttributes(htmlAttributes); + tagBuilder.MergeAttribute("href", url); + return tagBuilder.ToString(TagRenderMode.Normal); + } + + private static RouteValueDictionary ObjectToDictionary(object value) { + RouteValueDictionary dictionary = new RouteValueDictionary(); + + if (value != null) { + foreach (var prop in value.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) { + dictionary.Add(prop.Name, prop.GetValue(value)); + } + } + + return dictionary; + } + } +} diff --git a/src/Orchard/Mvc/HttpContextAccessor.cs b/src/Orchard/Mvc/HttpContextAccessor.cs index 91c7c3b0d..b13d6fe25 100644 --- a/src/Orchard/Mvc/HttpContextAccessor.cs +++ b/src/Orchard/Mvc/HttpContextAccessor.cs @@ -1,40 +1,39 @@ using System; -using System.Collections.Concurrent; using System.Web; -using Autofac; -using Orchard.Mvc.Extensions; namespace Orchard.Mvc { public class HttpContextAccessor : IHttpContextAccessor { - readonly object _contextKey = new object(); - - [ThreadStatic] - static ConcurrentDictionary _threadStaticContexts; + private HttpContextBase _httpContext; public HttpContextBase Current() { - if (!HttpContext.Current.IsBackgroundContext()) - return new HttpContextWrapper(HttpContext.Current); - - return GetContext(); + var httpContext = GetStaticProperty(); + return !IsBackgroundHttpContext(httpContext) ? new HttpContextWrapper(httpContext) : _httpContext; } - public HttpContextBase CreateContext(ILifetimeScope lifetimeScope) { - return new MvcModule.HttpContextPlaceholder( - _threadStaticContexts, - _contextKey, - () => "http://localhost" // Use a valid URL always for the fake request. The value itself doesn't matter. - ); + public void Set(HttpContextBase httpContext) { + _httpContext = httpContext; } - private HttpContextBase GetContext() { - HttpContextBase context; - return ThreadStaticContexts.TryGetValue(_contextKey, out context) ? context : null; + private static bool IsBackgroundHttpContext(HttpContext httpContext) { + return httpContext == null || httpContext.Items.Contains(BackgroundHttpContextFactory.IsBackgroundHttpContextKey); } - static ConcurrentDictionary ThreadStaticContexts { - get { - return _threadStaticContexts ?? (_threadStaticContexts = new ConcurrentDictionary()); + private static HttpContext GetStaticProperty() { + var httpContext = HttpContext.Current; + if (httpContext == null) { + return null; } + + try { + // The "Request" property throws at application startup on IIS integrated pipeline mode. + if (httpContext.Request == null) { + return null; + } + } + catch (Exception) { + return null; + } + return httpContext; } } } \ No newline at end of file diff --git a/src/Orchard/Mvc/IHttpContextAccessor.cs b/src/Orchard/Mvc/IHttpContextAccessor.cs index f34462581..462887fee 100644 --- a/src/Orchard/Mvc/IHttpContextAccessor.cs +++ b/src/Orchard/Mvc/IHttpContextAccessor.cs @@ -1,9 +1,8 @@ using System.Web; -using Autofac; namespace Orchard.Mvc { public interface IHttpContextAccessor { HttpContextBase Current(); - HttpContextBase CreateContext(ILifetimeScope lifetimeScope); + void Set(HttpContextBase httpContext); } } diff --git a/src/Orchard/Mvc/MvcModule.cs b/src/Orchard/Mvc/MvcModule.cs index 5b0c3bbf4..f44c5cd4a 100644 --- a/src/Orchard/Mvc/MvcModule.cs +++ b/src/Orchard/Mvc/MvcModule.cs @@ -1,6 +1,5 @@ using System; using System.Collections; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Specialized; using System.Globalization; @@ -10,9 +9,9 @@ using System.Web.Instrumentation; using System.Web.Mvc; using System.Web.Routing; using Autofac; -using Orchard.Mvc.Extensions; using Orchard.Mvc.Routes; using Orchard.Settings; +using Orchard.Exceptions; namespace Orchard.Mvc { public class MvcModule : Module { @@ -33,7 +32,11 @@ namespace Orchard.Mvc { // The "Request" property throws at application startup on IIS integrated pipeline mode. var req = HttpContext.Current.Request; } - catch (Exception) { + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + return false; } @@ -52,21 +55,15 @@ namespace Orchard.Mvc { // which requires activating the Site content item, which in turn requires a UrlHelper, which in turn requires a RequestContext, // thus preventing a StackOverflowException. var baseUrl = new Func(() => siteService.GetSiteSettings().BaseUrl); - var httpContextBase = context.Resolve().Current(); + var httpContextBase = new HttpContextPlaceholder(baseUrl); - if (httpContextBase == null) { - context.Resolve().CreateWorkContextScope(); - return context.Resolve().Current(); - } - - context.Resolve().CreateWorkContextScope(httpContextBase); return httpContextBase; } static RequestContext RequestContextFactory(IComponentContext context) { var httpContextAccessor = context.Resolve(); var httpContext = httpContextAccessor.Current(); - if (!httpContext.IsBackgroundContext()) { + if (httpContext != null) { var mvcHandler = httpContext.Handler as MvcHandler; if (mvcHandler != null) { @@ -93,23 +90,16 @@ namespace Orchard.Mvc { /// /// Standin context for background tasks. /// - public class HttpContextPlaceholder : HttpContextBase, IDisposable { + public class HttpContextPlaceholder : HttpContextBase { private readonly Lazy _baseUrl; private readonly IDictionary _items = new Dictionary(); - readonly Action _disposer; - public HttpContextPlaceholder(ConcurrentDictionary contexts, object contextKey, Func baseUrl) { + public HttpContextPlaceholder(Func baseUrl) { _baseUrl = new Lazy(baseUrl); - contexts.AddOrUpdate(contextKey, this, (a, b) => this); - - _disposer = () => { - HttpContextBase removedContext; - contexts.TryRemove(contextKey, out removedContext); - }; } public override HttpRequestBase Request { - get { return new HttpRequestPlaceholder(this, new Uri(_baseUrl.Value)); } + get { return new HttpRequestPlaceholder(new Uri(_baseUrl.Value)); } } public override IHttpHandler Handler { get; set; } @@ -118,10 +108,6 @@ namespace Orchard.Mvc { get { return new HttpResponsePlaceholder(); } } - public override HttpSessionStateBase Session { - get { return null; } - } - public override IDictionary Items { get { return _items; } } @@ -141,10 +127,6 @@ namespace Orchard.Mvc { public override object GetService(Type serviceType) { return null; } - - public void Dispose() { - _disposer(); - } } public class HttpResponsePlaceholder : HttpResponseBase { @@ -163,12 +145,9 @@ namespace Orchard.Mvc { /// standin context for background tasks. /// public class HttpRequestPlaceholder : HttpRequestBase { - private readonly HttpContextBase _httpContext; private readonly Uri _uri; - private RequestContext _requestContext; - public HttpRequestPlaceholder(HttpContextBase httpContext, Uri uri) { - _httpContext = httpContext; + public HttpRequestPlaceholder(Uri uri) { _uri = uri; } @@ -227,7 +206,7 @@ namespace Orchard.Mvc { return new NameValueCollection { { "SERVER_PORT", _uri.Port.ToString(CultureInfo.InvariantCulture) }, { "HTTP_HOST", _uri.Authority.ToString(CultureInfo.InvariantCulture) }, - + }; } } @@ -269,16 +248,6 @@ namespace Orchard.Mvc { return new HttpBrowserCapabilitiesPlaceholder(); } } - - public override RequestContext RequestContext { - get { - if (_requestContext == null) { - _requestContext = new RequestContext(_httpContext, new RouteData()); - } - return _requestContext; - } - set { _requestContext = value; } - } } public class HttpBrowserCapabilitiesPlaceholder : HttpBrowserCapabilitiesBase { diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index 0cdfdf839..877afb7cf 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -56,6 +56,7 @@ 4 AllRules.ruleset false + 0436 @@ -149,12 +150,14 @@ + + + - - + @@ -186,12 +189,11 @@ + - - @@ -298,10 +300,10 @@ - + - + @@ -362,7 +364,7 @@ - + @@ -401,7 +403,8 @@ - + + @@ -695,7 +698,6 @@ - diff --git a/src/Orchard/Properties/AssemblyInfo.cs b/src/Orchard/Properties/AssemblyInfo.cs index 9bc9c300a..aef96e848 100644 --- a/src/Orchard/Properties/AssemblyInfo.cs +++ b/src/Orchard/Properties/AssemblyInfo.cs @@ -34,6 +34,6 @@ using System.Security; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Orchard/Recipes/Services/IRecipeHarvester.cs b/src/Orchard/Recipes/Services/IRecipeHarvester.cs index c566bed59..3cea30e98 100644 --- a/src/Orchard/Recipes/Services/IRecipeHarvester.cs +++ b/src/Orchard/Recipes/Services/IRecipeHarvester.cs @@ -1,8 +1,24 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Linq; using Orchard.Recipes.Models; namespace Orchard.Recipes.Services { public interface IRecipeHarvester : IDependency { + /// + /// Returns a collection of all recipes. + /// + IEnumerable HarvestRecipes(); + + /// + /// Returns a collection of all recipes found in the specified extension. + /// IEnumerable HarvestRecipes(string extensionId); } + + public static class RecipeHarvesterExtensions { + public static Recipe GetRecipeByName(this IEnumerable recipes, string recipeName) { + return recipes.FirstOrDefault(r => r.Name.Equals(recipeName, StringComparison.OrdinalIgnoreCase)); + } + } } diff --git a/src/Orchard/StaticHttpContextScope.cs b/src/Orchard/StaticHttpContextScope.cs deleted file mode 100644 index b22b181db..000000000 --- a/src/Orchard/StaticHttpContextScope.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Web; - -namespace Orchard { - public class StaticHttpContextScope : IDisposable { - private readonly HttpContext _previousHttpContext; - - public StaticHttpContextScope(HttpContext stub) { - _previousHttpContext = HttpContext.Current; - HttpContext.Current = stub; - } - - public void Dispose() { - HttpContext.Current = _previousHttpContext; - } - } -} \ No newline at end of file diff --git a/src/Orchard/StaticHttpContextScopeFactory.cs b/src/Orchard/StaticHttpContextScopeFactory.cs deleted file mode 100644 index 35aafda4d..000000000 --- a/src/Orchard/StaticHttpContextScopeFactory.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.IO; -using System.Web; -using Orchard.Settings; - -namespace Orchard { - public class StaticHttpContextScopeFactory : IStaticHttpContextScopeFactory { - private readonly Func _siteService; - public StaticHttpContextScopeFactory(Func siteService) { - _siteService = siteService; - } - - public const string IsBackgroundHttpContextKey = "IsBackgroundHttpContext"; - - public IDisposable CreateStaticScope() { - // If there already is a current HttpContext, use that one as the stub. - if(HttpContext.Current != null) - return new StaticHttpContextScope(HttpContext.Current); - - // We're in a background task (or some other static context like the console), - // so create a stub context so that Html Helpers can still be executed when rendering shapes in background tasks - // (sadly enought some Html Helpers access HttpContext.Current directly). - var url = _siteService().GetSiteSettings().BaseUrl; - var stub = new HttpContext(new HttpRequest("", url, ""), new HttpResponse(new StringWriter())); - - stub.Items[IsBackgroundHttpContextKey] = true; - - return new StaticHttpContextScope(stub); - } - } -} \ No newline at end of file diff --git a/src/Orchard/Tasks/BackgroundService.cs b/src/Orchard/Tasks/BackgroundService.cs index 18d231a3a..6093f917f 100644 --- a/src/Orchard/Tasks/BackgroundService.cs +++ b/src/Orchard/Tasks/BackgroundService.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using Orchard.Data; using Orchard.Environment.Configuration; using Orchard.Logging; +using Orchard.Exceptions; namespace Orchard.Tasks { @@ -18,7 +19,8 @@ namespace Orchard.Tasks { public BackgroundService( IEnumerable tasks, ITransactionManager transactionManager, - ShellSettings shellSettings) { + ShellSettings shellSettings, + IBackgroundHttpContextFactory backgroundHttpContextFactory) { _tasks = tasks; _transactionManager = transactionManager; @@ -38,9 +40,13 @@ namespace Orchard.Tasks { task.Sweep(); Logger.Information("Finished processing background task \"{0}\" on tenant \"{1}\".", taskName, _shellName); } - catch (Exception e) { + catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + _transactionManager.Cancel(); - Logger.Error(e, "Error while processing background task \"{0}\" on tenant \"{1}\".", taskName, _shellName); + Logger.Error(ex, "Error while processing background task \"{0}\" on tenant \"{1}\".", taskName, _shellName); } } } diff --git a/src/Orchard/Tasks/Locking/Migrations/FrameworkMigrations.cs b/src/Orchard/Tasks/Locking/Migrations/FrameworkMigrations.cs deleted file mode 100644 index ce27736a6..000000000 --- a/src/Orchard/Tasks/Locking/Migrations/FrameworkMigrations.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using Orchard.Data.Migration; - -namespace Orchard.Tasks.Locking.Migrations { - public class FrameworkMigrations : DataMigrationImpl { - - public int Create() { - SchemaBuilder.CreateTable("DistributedLockRecord", table => table - .Column("Id", column => column.PrimaryKey().Identity()) - .Column("Name", column => column.NotNull().WithLength(256)) - .Column("MachineName", column => column.WithLength(256)) - .Column("ThreadId", column => column.Nullable()) - .Column("Count") - .Column("CreatedUtc") - .Column("ValidUntilUtc", column => column.Nullable())); - - SchemaBuilder.AlterTable("DistributedLockRecord", table => { - table.CreateIndex("IDX_DistributedLockRecord_Name_ValidUntilUtc_Count", "Name", "ValidUntilUtc", "Count"); - }); - - return 1; - } - } -} \ No newline at end of file diff --git a/src/Orchard/Tasks/Locking/Records/DistributedLockRecord.cs b/src/Orchard/Tasks/Locking/Records/DistributedLockRecord.cs index ec8fbff96..5dee047b0 100644 --- a/src/Orchard/Tasks/Locking/Records/DistributedLockRecord.cs +++ b/src/Orchard/Tasks/Locking/Records/DistributedLockRecord.cs @@ -5,8 +5,6 @@ namespace Orchard.Tasks.Locking.Records { public virtual int Id { get; set; } public virtual string Name { get; set; } public virtual string MachineName { get; set; } - public virtual int? ThreadId { get; set; } - public virtual int Count { get; set; } public virtual DateTime CreatedUtc { get; set; } public virtual DateTime? ValidUntilUtc { get; set; } } diff --git a/src/Orchard/Tasks/Locking/Services/DistributedLock.cs b/src/Orchard/Tasks/Locking/Services/DistributedLock.cs index 05977bea4..2069c2181 100644 --- a/src/Orchard/Tasks/Locking/Services/DistributedLock.cs +++ b/src/Orchard/Tasks/Locking/Services/DistributedLock.cs @@ -1,46 +1,41 @@ using System; -using System.Threading; namespace Orchard.Tasks.Locking.Services { - /// - /// Represents a distributed lock. /> - /// - public class DistributedLock : IDisposable { - public static DistributedLock ForMachine(IDistributedLockService service, string name, string machineName, string lockId) { - return new DistributedLock { - _service = service, - Name = name, - MachineName = machineName, - Id = lockId - }; + public class DistributedLock : IDistributedLock { + + private readonly string _name; + private readonly string _internalName; + private readonly Action _releaseLockAction; + private int _count; + + internal DistributedLock(string name, string internalName, Action releaseLockAction) { + _name = name; + _internalName = internalName; + _releaseLockAction = releaseLockAction; + _count = 1; } - public static DistributedLock ForThread(IDistributedLockService service, string name, string machineName, int threadId, string lockId) { - return new DistributedLock { - _service = service, - Name = name, - MachineName = machineName, - ThreadId = threadId, - Id = lockId - }; + string IDistributedLock.Name { + get { + return _name; + } } - private IDistributedLockService _service; - private int _isDisposed; - - private DistributedLock() { + internal string InternalName { + get { + return _internalName; + } } - public string Id { get; private set; } - public string Name { get; private set; } - public string MachineName { get; private set; } - public int? ThreadId { get; private set; } + internal void Increment() { + _count++; + } - // This will be called at least and at the latest by the IoC container when the request ends. public void Dispose() { - if(Interlocked.CompareExchange(ref _isDisposed, 1, 0) == 0) - _service.ReleaseLock(this); + _count--; + if (_count == 0) + _releaseLockAction(); } } } \ No newline at end of file diff --git a/src/Orchard/Tasks/Locking/Services/DistributedLockSchemaBuilder.cs b/src/Orchard/Tasks/Locking/Services/DistributedLockSchemaBuilder.cs new file mode 100644 index 000000000..2f22f1220 --- /dev/null +++ b/src/Orchard/Tasks/Locking/Services/DistributedLockSchemaBuilder.cs @@ -0,0 +1,48 @@ +using System; +using Orchard.Data.Migration.Schema; +using Orchard.Environment.Configuration; + +namespace Orchard.Tasks.Locking.Services { + public class DistributedLockSchemaBuilder { + private readonly ShellSettings _shellSettings; + private readonly SchemaBuilder _schemaBuilder; + private const string TableName = "Orchard_Framework_DistributedLockRecord"; + + public DistributedLockSchemaBuilder(ShellSettings shellSettings, SchemaBuilder schemaBuilder) { + _shellSettings = shellSettings; + _schemaBuilder = schemaBuilder; + } + + public bool EnsureSchema() { + if (SchemaExists()) + return false; + + CreateSchema(); + return true; + } + + public void CreateSchema() { + _schemaBuilder.CreateTable(TableName, table => table + .Column("Id", column => column.PrimaryKey().Identity()) + .Column("Name", column => column.NotNull().WithLength(512).Unique()) + .Column("MachineName", column => column.WithLength(256)) + .Column("CreatedUtc") + .Column("ValidUntilUtc", column => column.Nullable())); + + _schemaBuilder.AlterTable(TableName, table => { + table.CreateIndex("IDX_DistributedLockRecord_Name", "Name"); + }); + } + + public bool SchemaExists() { + try { + var tablePrefix = String.IsNullOrEmpty(_shellSettings.DataTablePrefix) ? "" : _shellSettings.DataTablePrefix + "_"; + _schemaBuilder.ExecuteSql(String.Format("select * from {0}{1}", tablePrefix, TableName)); + return true; + } + catch { + return false; + } + } + } +} \ No newline at end of file diff --git a/src/Orchard/Tasks/Locking/Services/DistributedLockService.cs b/src/Orchard/Tasks/Locking/Services/DistributedLockService.cs index ed0fb21e0..fcd4a1c18 100644 --- a/src/Orchard/Tasks/Locking/Services/DistributedLockService.cs +++ b/src/Orchard/Tasks/Locking/Services/DistributedLockService.cs @@ -1,10 +1,13 @@ using System; +using System.Collections.Generic; using System.Data; using System.Linq; +using System.Threading; using System.Threading.Tasks; using Autofac; using Orchard.Data; using Orchard.Environment; +using Orchard.Environment.Configuration; using Orchard.Exceptions; using Orchard.Logging; using Orchard.Services; @@ -13,191 +16,199 @@ using Orchard.Tasks.Locking.Records; namespace Orchard.Tasks.Locking.Services { public class DistributedLockService : Component, IDistributedLockService { - private readonly IMachineNameProvider _machineNameProvider; + + private readonly IApplicationEnvironment _applicationEnvironment; private readonly ILifetimeScope _lifetimeScope; private readonly IClock _clock; - private readonly IThreadProvider _threadProvider; + private readonly ShellSettings _shellSettings; + private readonly Dictionary _locks; + private readonly TimeSpan _defaultRepeatInterval; - public DistributedLockService(IMachineNameProvider machineNameProvider, IThreadProvider threadProvider, ILifetimeScope lifetimeScope, IClock clock) { - _machineNameProvider = machineNameProvider; - _lifetimeScope = lifetimeScope; + public DistributedLockService( + IApplicationEnvironment applicationEnvironment, + ILifetimeScope lifetimeScope, + IClock clock, + ShellSettings shellSettings) { _clock = clock; - _threadProvider = threadProvider; + _lifetimeScope = lifetimeScope; + _shellSettings = shellSettings; + _applicationEnvironment = applicationEnvironment; + _locks = new Dictionary(); + _defaultRepeatInterval = TimeSpan.FromMilliseconds(500); } - public bool TryAcquireLockForMachine(string name, TimeSpan? maxValidFor, TimeSpan? timeout, out DistributedLock @lock) { - return TryAcquireLock(name, maxValidFor, timeout, GetMachineName(), null, out @lock); - } - - public DistributedLock AcquireLockForMachine(string name, TimeSpan? maxValidFor, TimeSpan? timeout) { - return AcquireLock(name, maxValidFor, timeout, GetMachineName(), null); - } - - public bool TryAcquireLockForThread(string name, TimeSpan? maxValidFor, TimeSpan? timeout, out DistributedLock @lock) { - return TryAcquireLock(name, maxValidFor, timeout, GetMachineName(), GetThreadId(), out @lock); - } - - public DistributedLock AcquireLockForThread(string name, TimeSpan? maxValidFor, TimeSpan? timeout) { - return AcquireLock(name, maxValidFor, timeout, GetMachineName(), GetThreadId()); - } - - public void ReleaseLock(DistributedLock @lock) { - var childLifetimeScope = CreateChildLifetimeScope(@lock.Name); - + public bool TryAcquireLock(string name, TimeSpan? maxValidFor, TimeSpan? timeout, out IDistributedLock dLock) { try { - var repository = childLifetimeScope.Resolve>(); - var transactionManager = childLifetimeScope.Resolve(); - transactionManager.RequireNew(IsolationLevel.ReadCommitted); - var lockId = Int32.Parse(@lock.Id); - var record = repository.Get(lockId); + dLock = AcquireLockInternal(name, maxValidFor, timeout, throwOnTimeout: false); - if (record == null) - throw new OrchardException(T("No lock record could be found for the specified lock to be released.")); - - if (record.Count <= 0) - throw new OrchardException(T("The specified lock has already been released.")); - - record.Count--; - - if(record.Count == 0) - repository.Delete(record); - } - catch (Exception ex) { - if (ex.IsFatal()) throw; - Logger.Error(ex, "An non-fatal error occurred while trying to dispose a distributed lock with name '{0}' and ID {1}.", @lock.Name, @lock.Id); - } - finally { - childLifetimeScope.Dispose(); - } - } - - private bool TryAcquireLock(string name, TimeSpan? maxValidFor, TimeSpan? timeout, string machineName, int? threadId, out DistributedLock @lock) { - @lock = AcquireLock(name, maxValidFor, machineName, threadId, timeout ?? TimeSpan.Zero); - return @lock != null; - } - - private DistributedLock AcquireLock(string name, TimeSpan? maxValidFor, TimeSpan? timeout, string machineName, int? threadId) { - var @lock = AcquireLock(name, maxValidFor, machineName, threadId, timeout); - if (@lock != null) - return @lock; - - throw new TimeoutException(String.Format("Failed to acquire a lock named '{0}' within the specified timeout ('{1}').", name, timeout)); - } - - private DistributedLock AcquireLock(string name, TimeSpan? maxValidFor, string machineName, int? threadId, TimeSpan? timeout = null) { - try { - DistributedLock @lock = null; - var acquired = Poll(() => (@lock = AcquireLockInternal(name, maxValidFor, machineName, threadId)) != null, timeout); - - if (acquired) { - Logger.Debug("Successfully acquired a lock named '{0}'.", name); - return @lock; + if (dLock != null) { + Logger.Debug("Successfully acquired lock '{0}'.", name); + return true; } + + Logger.Warning("Failed to acquire lock '{0}' within the specified timeout ({1}).", name, timeout); } catch (Exception ex) { - Logger.Error(ex, "Error while trying to acquire a lock named '{0}'.", name); + Logger.Error(ex, "Error while trying to acquire lock '{0}'.", name); + // TODO: Is it correct to not throw here? Should we instead ONLY swallow TimeoutException? + } + + dLock = null; + return false; + } + + public IDistributedLock AcquireLock(string name, TimeSpan? maxValidFor, TimeSpan? timeout) { + try { + DistributedLock result = AcquireLockInternal(name, maxValidFor, timeout, throwOnTimeout: true); + Logger.Debug("Successfully acquired lock '{0}'.", name); + return result; + } + catch (Exception ex) { + Logger.Error(ex, "Error while trying to acquire lock '{0}'.", name); throw; } - - Logger.Debug(timeout == null - ? "Failed to acquire a lock named '{0}'." - : "Failed to acquire a lock named '{0}' within the specified timeout ('{1}')." - , name, timeout); - - return null; } - private DistributedLock AcquireLockInternal(string name, TimeSpan? maxValidFor, string machineName, int? threadId) { - var childLifetimeScope = CreateChildLifetimeScope(name); + private DistributedLock AcquireLockInternal(string name, TimeSpan? maxValidFor, TimeSpan? timeout, bool throwOnTimeout) { + var internalName = GetInternalLockName(name); + var monitorTimeout = timeout.HasValue ? timeout.Value : TimeSpan.FromMilliseconds(-1); // -1 ms is .NET magic number for "infinite". + var monitorObj = String.Intern(String.Format("{0}:{1}", _applicationEnvironment.GetEnvironmentIdentifier(), internalName)); + + if (!Monitor.TryEnter(monitorObj, monitorTimeout)) { + Logger.Debug("Could not enter local monitor for lock '{0}' within the specified timeout ({1}).", internalName, timeout); + + if (throwOnTimeout) + throw new TimeoutException(String.Format("Failed to acquire lock '{0}' within the specified timeout ({1}).", internalName, timeout)); + + return null; + } + + Logger.Debug("Successfully entered local monitor for lock '{0}'.", internalName); try { - var transactionManager = childLifetimeScope.Resolve(); - transactionManager.RequireNew(IsolationLevel.ReadCommitted); + DistributedLock dLock = null; - // This way we can create a nested transaction scope instead of having the unwanted effect - // of manipulating the transaction of the caller. - var repository = childLifetimeScope.Resolve>(); - - // Find an existing, active lock, if any. - var record = repository.Table.FirstOrDefault(x => x.Name == name && (x.ValidUntilUtc == null || x.ValidUntilUtc >= _clock.UtcNow) && x.Count > 0); - - // The current owner name (based on machine name and current thread ID). - var canAcquireLock = false; - - // Check if there's already an active lock. - if (record != null) { - // Check if the machine name assigned to the lock is the one trying to acquire it. - if (record.MachineName == machineName) { - if (record.ThreadId != threadId) - throw new InvalidOperationException( - threadId == null - ? "An attempt to acquire a lock for a machine was detected while the requested lock is already assigned to a specific thread." - : "An attempt to acquire a lock for a thread was detected while the requested lock is already assigned to a machine."); - - record.Count++; - canAcquireLock = true; - } + // If there's already a distributed lock object in our dictionary, that means + // this acquisition is a reentrance. Use the existing lock object from the + // dictionary but increment its count. + if (_locks.TryGetValue(monitorObj, out dLock)) { + Logger.Debug("Current thread is re-entering lock '{0}'; incrementing count.", internalName); + dLock.Increment(); } else { - // No one has an active lock yet, so good to go. - record = new DistributedLockRecord { - Name = name, - MachineName = machineName, - ThreadId = threadId, - Count = 1, - CreatedUtc = _clock.UtcNow, - ValidUntilUtc = maxValidFor != null ? _clock.UtcNow + maxValidFor : null - }; - repository.Create(record); - canAcquireLock = true; + // No distributed lock object existed in our dictionary. Try to take ownership + // of database record until timeout expires, and if successful create a distributed + // lock object and add it to our dictionary. + var success = RepeatUntilTimeout(timeout, _defaultRepeatInterval, () => { + if (EnsureDistributedLockRecord(internalName, maxValidFor)) { + Logger.Debug("Record for lock '{0}' already owned by current machine or was successfully created; creating lock object.", internalName); + + dLock = new DistributedLock(name, internalName, releaseLockAction: () => { + Monitor.Exit(monitorObj); + DeleteDistributedLockRecord(internalName); + }); + + _locks.Add(monitorObj, dLock); + return true; + } + + return false; + }); + + if (!success) { + Logger.Debug("Record for lock '{0}' could not be created for current machine within the specified timeout ({1}).", internalName, timeout); + + if (throwOnTimeout) + throw new TimeoutException(String.Format("Failed to acquire lock '{0}' within the specified timeout ({1}).", internalName, timeout)); + + return null; + } } - if (!canAcquireLock) - return null; - - return threadId != null - ? DistributedLock.ForThread(this, name, machineName, threadId.Value, record.Id.ToString()) - : DistributedLock.ForMachine(this, name, machineName, record.Id.ToString()); + return dLock; } catch (Exception ex) { - Logger.Error(ex, "An error occurred while trying to acquire a lock."); + Monitor.Exit(monitorObj); + + Logger.Error(ex, "An error occurred while trying to acquire lock '{0}'.", internalName); throw; } - finally { - childLifetimeScope.Dispose(); + } + + private bool EnsureDistributedLockRecord(string internalName, TimeSpan? maxValidFor) { + var environmentIdentifier = _applicationEnvironment.GetEnvironmentIdentifier(); + var hasLockRecord = false; + + ExecuteOnSeparateTransaction(repository => { + // Try to find a valid lock record in the database. + var record = repository.Table.FirstOrDefault(x => x.Name == internalName && (x.ValidUntilUtc == null || x.ValidUntilUtc >= _clock.UtcNow)); + if (record == null) { + // No record existed, so we're good to create a new one. + Logger.Debug("No valid record was found for lock '{0}'; creating a new record.", internalName); + + repository.Create(new DistributedLockRecord { + Name = internalName, + MachineName = environmentIdentifier, + CreatedUtc = _clock.UtcNow, + ValidUntilUtc = maxValidFor.HasValue ? _clock.UtcNow + maxValidFor.Value : default(DateTime?) + }); + + hasLockRecord = true; + } + else if (record.MachineName == environmentIdentifier) { + // Existing lock was for correct machine name => lock record exists. + Logger.Debug("Found a valid record for lock '{0}' and current local machine name '{1}'.", internalName, environmentIdentifier); + hasLockRecord = true; + } + }); + + return hasLockRecord; + } + + private void DeleteDistributedLockRecord(string internalName) { + try { + ExecuteOnSeparateTransaction(repository => { + var record = repository.Table.FirstOrDefault(x => x.Name == internalName); + if (record == null) + throw new Exception(String.Format("No record could be found in the database for lock '{0}'.", internalName)); + repository.Delete(record); + Logger.Debug("Successfully deleted record for lock '{0}'.", internalName); + }); + } + catch (Exception ex) { + if (ex.IsFatal()) + throw; + Logger.Warning(ex, "An error occurred while deleting record for lock '{0}'.", internalName); } } - /// - /// Executes the specified function until it returns true, for the specified amount of time, or indefinitely if no timeout was given. - /// - /// The operation to repeatedly execute until it returns true. - /// The amount of time to retry executing the function. If null is specified, the specified function is executed indefinitely until it returns true. - /// Returns true if the specified function returned true within the specified timeout, false otherwise. - private bool Poll(Func operation, TimeSpan? timeout) { + private bool RepeatUntilTimeout(TimeSpan? timeout, TimeSpan repeatInterval, Func action) { + bool success; + var waitedTime = TimeSpan.Zero; - var waitTime = TimeSpan.FromMilliseconds(timeout.GetValueOrDefault().TotalMilliseconds / 10); - bool acquired; - - while (!(acquired = operation()) && (timeout == null || waitedTime < timeout.Value)) { - Task.Delay(waitTime).ContinueWith(t => { - waitedTime += waitTime; - }).Wait(); + while (!(success = action()) && (!timeout.HasValue || waitedTime < timeout.Value)) { + Task.Delay(repeatInterval).Wait(); + waitedTime += repeatInterval; } - return acquired; + return success; } - private string GetMachineName() { - return _machineNameProvider.GetMachineName(); + private void ExecuteOnSeparateTransaction(Action> action) { + if (action == null) + throw new ArgumentNullException(); + + using (var childLifetimeScope = _lifetimeScope.BeginLifetimeScope()) { + var repository = childLifetimeScope.Resolve>(); + var transactionManager = childLifetimeScope.Resolve(); + transactionManager.RequireNew(IsolationLevel.ReadCommitted); + action(repository); + } } - private int GetThreadId() { - return _threadProvider.GetCurrentThreadId(); - } - - private ILifetimeScope CreateChildLifetimeScope(string name) { - return _lifetimeScope.BeginLifetimeScope("Orchard.Tasks.Locking." + name); + private string GetInternalLockName(string name) { + // Prefix the requested lock name by a constant and the tenant name. + return String.Format("DistributedLock:{0}:{1}", _shellSettings.Name, name); } } } \ No newline at end of file diff --git a/src/Orchard/Tasks/Locking/Services/IDistributedLock.cs b/src/Orchard/Tasks/Locking/Services/IDistributedLock.cs new file mode 100644 index 000000000..a687728e1 --- /dev/null +++ b/src/Orchard/Tasks/Locking/Services/IDistributedLock.cs @@ -0,0 +1,13 @@ +using System; + +namespace Orchard.Tasks.Locking.Services { + + /// + /// Represents a distributed lock returned by IDistributedLockService. The owner of the + /// lock should call Dispose() on an instance of this interface to release the distributed + /// lock. + /// + public interface IDistributedLock : IDisposable { + string Name { get; } + } +} \ No newline at end of file diff --git a/src/Orchard/Tasks/Locking/Services/IDistributedLockService.cs b/src/Orchard/Tasks/Locking/Services/IDistributedLockService.cs index 31818f200..7de40e64f 100644 --- a/src/Orchard/Tasks/Locking/Services/IDistributedLockService.cs +++ b/src/Orchard/Tasks/Locking/Services/IDistributedLockService.cs @@ -1,128 +1,83 @@ using System; namespace Orchard.Tasks.Locking.Services { - /// - /// Provides distributed locking functionality. - /// - public interface IDistributedLockService : ISingletonDependency { - /// - /// Tries to acquire a lock on the specified name for the current machine. - /// - /// The name to use for the lock. - /// The maximum amount of time the lock is allowed. This is a safety net in case the caller fails to release the lock. - /// The amount of time to wait for the lock to be acquired before timing out. A null value will cause the method to return immedieately if no lock could be acquired. - /// The acquired lock. - /// Returns true if a lock was successfully acquired, false otherwise. - bool TryAcquireLockForMachine(string name, TimeSpan? maxValidFor, TimeSpan? timeout, out DistributedLock @lock); + + /// + /// Provides functionality to acquire and release tenant-wide locks which are + /// distributed across all instances in a web farm. + /// + /// + /// Distributed locks can be used to protect critical sections that should only ever + /// be executed by a single thread of execution across a whole web farm. The distributed + /// locks returned by this service are reentrant, i.e. the owner of a lock can reacquire it + /// multiple times, and must also release it (dispose of it) as many times as it was + /// acquired for the lock to be released. + /// + public interface IDistributedLockService : IDependency { /// - /// Acquires a lock with the specified parameters for the current machine. + /// Tries to acquire a named distributed lock within the current tenant. /// - /// The name to use for the lock. - /// The maximum amount of time the lock is allowed. This is a safety net in case the caller fails to release the lock. If null is specified, the lock never expires until it's released by the owner. - /// The amount of time to wait for the lock to be acquired before timing out. A null value will cause the method to block indefinitely until a lock can be acquired. - /// Returns a lock. - /// Throws a TimeoutException if no lock could be acquired in time. - DistributedLock AcquireLockForMachine(string name, TimeSpan? maxValidFor, TimeSpan? timeout); + /// The name of the lock to acquire. + /// The maximum amount of time the lock should be held before automatically expiring. This is a safeguard in case the owner fails to release the lock. If null is specified, the lock never automatically expires. + /// The amount of time to wait for the lock to be acquired. Passing TimeSpan.Zero will cause the method to return immediately. Passing null will cause the method to block indefinitely until a lock can be acquired. + /// This out parameter will be assigned the acquired lock if successful. + /// true if the lock was successfully acquired, otherwise false. + bool TryAcquireLock(string name, TimeSpan? maxValidFor, TimeSpan? timeout, out IDistributedLock @lock); - /// - /// Tries to acquire a lock on the specified name for the current thread. - /// - /// The name to use for the lock. - /// The maximum amount of time the lock is allowed. This is a safety net in case the caller fails to release the lock. If null is specified, the lock never expires until it's released by the owner. - /// The amount of time to wait for the lock to be acquired before timing out. A null value will cause the method to return immedieately if no lock could be acquired. - /// The acquired lock. - /// Returns true if a lock was successfully acquired, false otherwise. - bool TryAcquireLockForThread(string name, TimeSpan? maxValidFor, TimeSpan? timeout, out DistributedLock @lock); - - /// - /// Acquires a lock with the specified parameters for the current thread. - /// - /// The name to use for the lock. - /// The maximum amount of time the lock is allowed. This is a safety net in case the caller fails to release the lock. If null is specified, the lock never expires until it's released by the owner. - /// The amount of time to wait for the lock to be acquired before timing out. A null value will cause the method to block indefinitely until a lock can be acquired. - /// Returns a lock. - /// Throws a TimeoutException if no lock could be acquired in time. - DistributedLock AcquireLockForThread(string name, TimeSpan? maxValidFor, TimeSpan? timeout); - - /// - /// Disposes the specified lock. - /// - void ReleaseLock(DistributedLock @lock); + /// + /// Acquires a named distributed lock within the current tenant or throws if the lock cannot be acquired. + /// + /// The name of the lock to acquire. + /// The maximum amount of time the lock should be held before automatically expiring. This is a safeguard in case the owner fails to release the lock. If null is specified, the lock never automatically expires. + /// The amount of time to wait for the lock to be acquired. Passing TimeSpan.Zero will cause the method to return immediately. Passing null will cause the method to block indefinitely until a lock can be acquired. + /// The acquired lock. + /// This method throws a TimeoutException if the lock could not be acquired within the specified timeout period. + IDistributedLock AcquireLock(string name, TimeSpan? maxValidFor, TimeSpan? timeout); } public static class DistributedLockServiceExtensions { - /// - /// Tries to acquire a lock on the specified name for the current machine. - /// - /// The name to use for the lock. - /// The maximum amount of time the lock is allowed. This is a safety net in case the caller fails to release the lock. If null is specified, the lock never expires until it's released by the owner. - /// The acquired lock. - /// Returns true if a lock was successfully acquired, false otherwise. - public static bool TryAcquireLockForMachine(this IDistributedLockService service, string name, TimeSpan? maxValidFor, out DistributedLock @lock) { - return service.TryAcquireLockForMachine(name, maxValidFor, null, out @lock); + + /// + /// Tries to immediately acquire a named distributed lock with a given expiration time within the current tenant. + /// + /// The name of the lock to acquire. + /// The maximum amount of time the lock should be held before automatically expiring. This is a safeguard in case the owner fails to release the lock. If null is specified, the lock never automatically expires. + /// This out parameter will be assigned the acquired lock if successful. + /// true if the lock could be immediately acquired, otherwise false. + public static bool TryAcquireLock(this IDistributedLockService service, string name, TimeSpan? maxValidFor, out IDistributedLock @lock) { + return service.TryAcquireLock(name, maxValidFor, TimeSpan.Zero, out @lock); } - /// - /// Tries to acquire a lock on the specified name for the current machine. - /// - /// The name to use for the lock. - /// The acquired lock. - /// Returns true if a lock was successfully acquired, false otherwise. - public static bool TryAcquireLockForMachine(this IDistributedLockService service, string name, out DistributedLock @lock) { - return service.TryAcquireLockForMachine(name, null, null, out @lock); + /// + /// Tries to immediately acquire a named distributed lock with no expiration time within the current tenant. + /// + /// The name of the lock to acquire. + /// This out parameter will be assigned the acquired lock if successful. + /// true if the lock could be immediately acquired, otherwise false. + public static bool TryAcquireLock(this IDistributedLockService service, string name, out IDistributedLock @lock) { + return service.TryAcquireLock(name, null, TimeSpan.Zero, out @lock); } - /// - /// Acquires a lock with the specified parameters for the current machine. - /// - /// The name to use for the lock. - /// The maximum amount of time the lock is allowed. This is a safety net in case the caller fails to release the lock. If null is specified, the lock never expires until it's released by the owner. - /// Returns a lock. - /// Throws a TimeoutException if no lock could be acquired in time. - public static DistributedLock AcquireLockForMachine(this IDistributedLockService service, string name, TimeSpan? maxValidFor) { - return service.AcquireLockForMachine(name, maxValidFor, null); + /// + /// Acquires a named distributed lock with a given expiration time within the current tenant. + /// + /// The name of the lock to acquire. + /// The maximum amount of time the lock should be held before automatically expiring. This is a safeguard in case the owner fails to release the lock. If null is specified, the lock never automatically expires. + /// The acquired lock. + /// This method blocks indefinitely until the lock can be acquired. + public static IDistributedLock AcquireLock(this IDistributedLockService service, string name, TimeSpan? maxValidFor) { + return service.AcquireLock(name, maxValidFor, null); } - /// - /// Acquires a lock with the specified parameters for the current machine. - /// - /// The name to use for the lock. - /// Returns a lock. - /// Throws a TimeoutException if no lock could be acquired in time. - public static DistributedLock AcquireLockForMachine(this IDistributedLockService service, string name) { - return service.AcquireLockForMachine(name, null, null); - } - - /// - /// Tries to acquire a lock on the specified name for the current thread. - /// - /// The name to use for the lock. - /// The maximum amount of time the lock is allowed. This is a safety net in case the caller fails to release the lock. If null is specified, the lock never expires until it's released by the owner. - /// The acquired lock. - /// Returns true if a lock was successfully acquired, false otherwise. - public static bool TryAcquireLockForThread(this IDistributedLockService service, string name, TimeSpan? maxValidFor, out DistributedLock @lock) { - return service.TryAcquireLockForThread(name, maxValidFor, null, out @lock); - } - - /// - /// Tries to acquire a lock on the specified name for the current thread. - /// - /// The name to use for the lock. - /// The acquired lock. - /// Returns true if a lock was successfully acquired, false otherwise. - public static bool TryAcquireLockForThread(this IDistributedLockService service, string name, out DistributedLock @lock) { - return service.TryAcquireLockForThread(name, null, null, out @lock); - } - - /// - /// Acquires a lock with the specified parameters for the current thread. - /// - /// The name to use for the lock. - /// Returns a lock. - /// Throws a TimeoutException if no lock could be acquired in time. - public static DistributedLock AcquireLockForThread(this IDistributedLockService service, string name) { - return service.AcquireLockForThread(name, null, null); + /// + /// Acquires a named distributed lock with no expiration time within the current tenant. + /// + /// The name to use for the lock. + /// The acquired lock. + /// This method blocks indefinitely until the lock can be acquired. + public static IDistributedLock AcquireLock(this IDistributedLockService service, string name) { + return service.AcquireLock(name, null, null); } } } \ No newline at end of file diff --git a/src/Orchard/Tasks/SweepGenerator.cs b/src/Orchard/Tasks/SweepGenerator.cs index 9c61b6740..44429e50b 100644 --- a/src/Orchard/Tasks/SweepGenerator.cs +++ b/src/Orchard/Tasks/SweepGenerator.cs @@ -1,6 +1,7 @@ using System; using System.Timers; using Orchard.Logging; +using Orchard.Exceptions; namespace Orchard.Tasks { @@ -41,7 +42,7 @@ namespace Orchard.Tasks { } void Elapsed(object sender, ElapsedEventArgs e) { - // Current implementation disallows re-entrancy. + // current implementation disallows re-entrancy if (!System.Threading.Monitor.TryEnter(_timer)) return; @@ -51,6 +52,10 @@ namespace Orchard.Tasks { } } catch (Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Warning(ex, "Problem in background tasks"); } finally { @@ -60,7 +65,7 @@ namespace Orchard.Tasks { public void DoWork() { using (var scope = _workContextAccessor.CreateWorkContextScope()) { - // Resolve the manager and invoke it. + // resolve the manager and invoke it var manager = scope.Resolve(); manager.Sweep(); } diff --git a/src/Orchard/Time/SiteTimeZoneSelector.cs b/src/Orchard/Time/SiteTimeZoneSelector.cs index 28068b213..366718216 100644 --- a/src/Orchard/Time/SiteTimeZoneSelector.cs +++ b/src/Orchard/Time/SiteTimeZoneSelector.cs @@ -1,6 +1,7 @@ using System; using System.Web; using Orchard.Logging; +using Orchard.Exceptions; namespace Orchard.Time { /// @@ -31,8 +32,11 @@ namespace Orchard.Time { TimeZone = TimeZoneInfo.FindSystemTimeZoneById(siteTimeZoneId) }; } - catch(Exception e) { - Logger.Error(e, "TimeZone could not be loaded"); + catch(Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Error(ex, "TimeZone could not be loaded"); // if the database could not be updated in time, ignore this provider return null; diff --git a/src/Orchard/UI/Admin/Notification/NotificationManager.cs b/src/Orchard/UI/Admin/Notification/NotificationManager.cs index 327b4f1c1..d0529224c 100644 --- a/src/Orchard/UI/Admin/Notification/NotificationManager.cs +++ b/src/Orchard/UI/Admin/Notification/NotificationManager.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using Orchard.Logging; using Orchard.UI.Notify; +using Orchard.Exceptions; namespace Orchard.UI.Admin.Notification { public class NotificationManager : INotificationManager { @@ -22,8 +23,11 @@ namespace Orchard.UI.Admin.Notification { try { return n.GetNotifications(); } - catch(Exception e) { - Logger.Error("An unhandled exception was thrown while generating a notification: " + n.GetType(), e); + catch(Exception ex) { + if (ex.IsFatal()) { + throw; + } + Logger.Error("An unhandled exception was thrown while generating a notification: " + n.GetType(), ex); return Enumerable.Empty(); } }).ToList(); diff --git a/src/Orchard/UI/Resources/ResourceDefinition.cs b/src/Orchard/UI/Resources/ResourceDefinition.cs index f900661a1..6676a21eb 100644 --- a/src/Orchard/UI/Resources/ResourceDefinition.cs +++ b/src/Orchard/UI/Resources/ResourceDefinition.cs @@ -155,6 +155,10 @@ namespace Orchard.UI.Resources { return this; } + /// + /// Sets the version of the resource. + /// + /// The version to set, in the form of major.minor[.build[.revision]] public ResourceDefinition SetVersion(string version) { Version = version; return this; diff --git a/src/Orchard/Utility/Extensions/StringExtensions.cs b/src/Orchard/Utility/Extensions/StringExtensions.cs index 1e66a8248..08b43ea9a 100644 --- a/src/Orchard/Utility/Extensions/StringExtensions.cs +++ b/src/Orchard/Utility/Extensions/StringExtensions.cs @@ -16,8 +16,7 @@ namespace Orchard.Utility.Extensions { var sb = new StringBuilder(camel); for (int i = camel.Length-1; i>0; i--) { - var current = sb[i]; - if('A' <= current && current <= 'Z') { + if(char.IsUpper(sb[i])) { sb.Insert(i, ' '); } } @@ -357,4 +356,4 @@ namespace Orchard.Utility.Extensions { return Encoding.UTF8.GetString(Convert.FromBase64String(value)); } } -} \ No newline at end of file +} diff --git a/src/Orchard/WorkContext.cs b/src/Orchard/WorkContext.cs index 412278e2a..767719f3d 100644 --- a/src/Orchard/WorkContext.cs +++ b/src/Orchard/WorkContext.cs @@ -10,20 +10,35 @@ namespace Orchard { /// public abstract class WorkContext { /// - /// Resolves a registered dependency type + /// Resolves a registered dependency type. /// - /// The type of the dependency - /// An instance of the dependency if it could be resolved + /// The type of the dependency. + /// An instance of the dependency if it could be resolved. public abstract T Resolve(); /// - /// Tries to resolve a registered dependency type + /// Resolves a registered dependency type. /// - /// The type of the dependency - /// An instance of the dependency if it could be resolved - /// True if the dependency could be resolved, false otherwise + /// The type of the dependency. + /// An instance of the dependency if it could be resolved. + public abstract object Resolve(Type serviceType); + + /// + /// Tries to resolve a registered dependency type. + /// + /// The type of the dependency. + /// An instance of the dependency if it could be resolved. + /// True if the dependency could be resolved, false otherwise. public abstract bool TryResolve(out T service); + /// + /// Tries to resolve a registered dependency type. + /// + /// The type of the dependency. + /// An instance of the dependency if it could be resolved. + /// True if the dependency could be resolved, false otherwise. + public abstract bool TryResolve(Type serviceType, out object service); + public abstract T GetState(string name); public abstract void SetState(string name, T value); diff --git a/src/Package.json b/src/Package.json index 96a154825..577b26bf5 100644 --- a/src/Package.json +++ b/src/Package.json @@ -1,5 +1,7 @@ { + "private": true, "devDependencies": { + "fs": "^0.0.2", "glob": "^5.0.14", "path-posix": "^1.0.0", "merge-stream": "^0.1.8", diff --git a/src/Tools/MSBuild.Orchard.Tasks/Properties/AssemblyInfo.cs b/src/Tools/MSBuild.Orchard.Tasks/Properties/AssemblyInfo.cs index 76e1c21dc..c036003f8 100644 --- a/src/Tools/MSBuild.Orchard.Tasks/Properties/AssemblyInfo.cs +++ b/src/Tools/MSBuild.Orchard.Tasks/Properties/AssemblyInfo.cs @@ -30,5 +30,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Tools/Orchard.Tests/Properties/AssemblyInfo.cs b/src/Tools/Orchard.Tests/Properties/AssemblyInfo.cs index 52ea2beb4..b12d217b6 100644 --- a/src/Tools/Orchard.Tests/Properties/AssemblyInfo.cs +++ b/src/Tools/Orchard.Tests/Properties/AssemblyInfo.cs @@ -30,5 +30,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")] diff --git a/src/Tools/Orchard/Properties/AssemblyInfo.cs b/src/Tools/Orchard/Properties/AssemblyInfo.cs index fc9dad31d..ec5b96ed6 100644 --- a/src/Tools/Orchard/Properties/AssemblyInfo.cs +++ b/src/Tools/Orchard/Properties/AssemblyInfo.cs @@ -30,5 +30,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.9.1")] -[assembly: AssemblyFileVersion("1.9.1")] +[assembly: AssemblyVersion("1.9.2")] +[assembly: AssemblyFileVersion("1.9.2")]