From 186d8846d482ec4fd81fa6d37d24f3e56e6a7b0a Mon Sep 17 00:00:00 2001
From: Dmitry Dzygin
Date: Mon, 12 Mar 2018 10:10:54 +0100
Subject: [PATCH 01/51] Code highlight when previewing files in System
perspective
---
Composite/Core/IO/MimeTypeInfo.cs | 10 ++-
.../services/Admin/DownloadFile.ashx | 52 +++++++++-----
.../services/Admin/HighlightJs/LICENSE | 24 +++++++
.../Admin/HighlightJs/highlight.pack.js | 2 +
.../services/Admin/HighlightJs/vs.css | 68 +++++++++++++++++++
5 files changed, 137 insertions(+), 19 deletions(-)
create mode 100644 Website/Composite/services/Admin/HighlightJs/LICENSE
create mode 100644 Website/Composite/services/Admin/HighlightJs/highlight.pack.js
create mode 100644 Website/Composite/services/Admin/HighlightJs/vs.css
diff --git a/Composite/Core/IO/MimeTypeInfo.cs b/Composite/Core/IO/MimeTypeInfo.cs
index f6148db8c5..7972ad8219 100644
--- a/Composite/Core/IO/MimeTypeInfo.cs
+++ b/Composite/Core/IO/MimeTypeInfo.cs
@@ -1,4 +1,4 @@
-using System.Collections.Concurrent;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics.CodeAnalysis;
@@ -28,7 +28,7 @@ public static class MimeTypeInfo
private static readonly ConcurrentDictionary _iisServeableExtensions = new ConcurrentDictionary();
private static List _textMimeTypes =
- new List { MimeTypeInfo.Css, MimeTypeInfo.Js, MimeTypeInfo.Xml, MimeTypeInfo.Text, MimeTypeInfo.Html, MimeTypeInfo.Sass,
+ new List { MimeTypeInfo.Css, MimeTypeInfo.Js, MimeTypeInfo.Json, MimeTypeInfo.Xml, MimeTypeInfo.Text, MimeTypeInfo.Html, MimeTypeInfo.Sass,
MimeTypeInfo.Ascx, MimeTypeInfo.Ashx, MimeTypeInfo.Asmx, MimeTypeInfo.Aspx, MimeTypeInfo.Asax, MimeTypeInfo.CSharp,
MimeTypeInfo.Resx, MimeTypeInfo.MasterPage, MimeTypeInfo.CsHtml, MimeTypeInfo.Svg };
@@ -67,6 +67,9 @@ private static ResourceHandle GetIconHandle(string name)
///
public static string Js => "text/js";
+ ///
+ public static string Json => "application/json";
+
///
public static string Xml => "text/xml";
@@ -161,7 +164,8 @@ static MimeTypeInfo()
_toCanonical.Add("application/x-javascript", MimeTypeInfo.Js);
RegisterMimeType(MimeTypeInfo.Js, "js", "mimetype-js", true);
- RegisterMimeType("text/html", new[] { "htm", "html", "xhtml" }, "mimetype-html", true);
+ RegisterMimeType(MimeTypeInfo.Json, new[] { "json" }, "mimetype-js");
+ RegisterMimeType(MimeTypeInfo.Html, new[] { "htm", "html", "xhtml" }, "mimetype-html", true);
// Audio/Video
RegisterMimeType("audio/x-wav", "wav", null, true);
diff --git a/Website/Composite/services/Admin/DownloadFile.ashx b/Website/Composite/services/Admin/DownloadFile.ashx
index b3c8117065..ff957eff70 100644
--- a/Website/Composite/services/Admin/DownloadFile.ashx
+++ b/Website/Composite/services/Admin/DownloadFile.ashx
@@ -56,24 +56,30 @@ public class DownloadFile : IHttpHandler
Verify.IsNotNull(fullFilePath, "Unexpected exception");
- bool isDllPreview = false;
-
if (isPreview)
{
- var extension = Path.GetExtension(fullFilePath);
- string mimeType = MimeTypeInfo.GetCanonicalFromExtension(extension);
+ var fileInfo = new FileInfo(fullFilePath);
+ string mimeType = MimeTypeInfo.GetCanonicalFromExtension(fileInfo.Extension);
if (!MimeTypeInfo.IsBrowserPreviewableFile(mimeType))
{
- if (extension.Equals(".dll", StringComparison.OrdinalIgnoreCase))
+ if (fileInfo.Extension.Equals(".dll", StringComparison.OrdinalIgnoreCase))
{
- isDllPreview = true;
+ OutputDllPreviewInformation(context, fullFilePath);
+ return;
}
- else if (!MimeTypeInfo.IsTextFile(mimeType))
+
+ if (!MimeTypeInfo.IsTextFile(mimeType))
{
return;
}
+ if (fileInfo.Length < 100*1024 && mimeType != "text/plain")
+ {
+ PreviewWithCodeHighlight(context, fullFilePath);
+ return;
+ }
+
mimeType = "text/plain";
}
@@ -85,15 +91,7 @@ public class DownloadFile : IHttpHandler
context.Response.AddHeader("Content-Disposition", "attachment;filename=" + fileName);
}
- if (isDllPreview)
- {
- OutputDllPreviewInformation(context, fullFilePath);
- }
- else
- {
- context.Response.TransmitFile(fullFilePath);
- }
-
+ context.Response.TransmitFile(fullFilePath);
context.ApplicationInstance.CompleteRequest();
}
@@ -213,9 +211,31 @@ public class DownloadFile : IHttpHandler
var text = string.Join(Environment.NewLine, lines);
+ context.Response.ContentType = "text/plain";
context.Response.Write(text);
}
+ private void PreviewWithCodeHighlight(HttpContext context, string fullFilePath)
+ {
+ context.Response.ContentType = "text/html";
+ context.Response.Write(@"
+
+
+
+
+
+
+ ");
+
+ var lines = File.ReadAllLines(fullFilePath);
+ foreach (var line in lines)
+ {
+ context.Response.Write(context.Server.HtmlEncode(line));
+ context.Response.Write(Environment.NewLine);
+ }
+
+ context.Response.Write(@"
");}
+
private bool UserHasRightToDownload(EntityToken file)
{
diff --git a/Website/Composite/services/Admin/HighlightJs/LICENSE b/Website/Composite/services/Admin/HighlightJs/LICENSE
new file mode 100644
index 0000000000..422deb7350
--- /dev/null
+++ b/Website/Composite/services/Admin/HighlightJs/LICENSE
@@ -0,0 +1,24 @@
+Copyright (c) 2006, Ivan Sagalaev
+All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of highlight.js nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Website/Composite/services/Admin/HighlightJs/highlight.pack.js b/Website/Composite/services/Admin/HighlightJs/highlight.pack.js
new file mode 100644
index 0000000000..b4a9208f20
--- /dev/null
+++ b/Website/Composite/services/Admin/HighlightJs/highlight.pack.js
@@ -0,0 +1,2 @@
+/*! highlight.js v9.12.0 | BSD3 License | git.io/hljslicense */
+!function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(e){function n(e){return e.replace(/&/g,"&").replace(//g,">")}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0===t.index}function a(e){return k.test(e)}function i(e){var n,t,r,i,o=e.className+" ";if(o+=e.parentNode?e.parentNode.className:"",t=B.exec(o))return w(t[1])?t[1]:"no-highlight";for(o=o.split(/\s+/),n=0,r=o.length;r>n;n++)if(i=o[n],a(i)||w(i))return i}function o(e){var n,t={},r=Array.prototype.slice.call(arguments,1);for(n in e)t[n]=e[n];return r.forEach(function(e){for(n in e)t[n]=e[n]}),t}function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3===i.nodeType?a+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!==r[0].offset?e[0].offset"}function u(e){s+=""+t(e)+">"}function c(e){("start"===e.event?o:u)(e.node)}for(var l=0,s="",f=[];e.length||r.length;){var g=i();if(s+=n(a.substring(l,g[0].offset)),l=g[0].offset,g===e){f.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g===e&&g.length&&g[0].offset===l);f.reverse().forEach(o)}else"start"===g[0].event?f.push(g[0].node):f.pop(),c(g.splice(0,1)[0])}return s+n(a.substr(l))}function l(e){return e.v&&!e.cached_variants&&(e.cached_variants=e.v.map(function(n){return o(e,{v:null},n)})),e.cached_variants||e.eW&&[o(e)]||[e]}function s(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var o={},u=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");o[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?u("keyword",a.k):x(a.k).forEach(function(e){u(e,a.k[e])}),a.k=o}a.lR=t(a.l||/\w+/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),null==a.r&&(a.r=1),a.c||(a.c=[]),a.c=Array.prototype.concat.apply([],a.c.map(function(e){return l("self"===e?a:e)})),a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var c=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=c.length?t(c.join("|"),!0):{exec:function(){return null}}}}r(e)}function f(e,t,a,i){function o(e,n){var t,a;for(t=0,a=n.c.length;a>t;t++)if(r(n.c[t].bR,e))return n.c[t]}function u(e,n){if(r(e.eR,n)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?u(e.parent,n):void 0}function c(e,n){return!a&&r(n.iR,e)}function l(e,n){var t=N.cI?n[0].toLowerCase():n[0];return e.k.hasOwnProperty(t)&&e.k[t]}function p(e,n,t,r){var a=r?"":I.classPrefix,i='',i+n+o}function h(){var e,t,r,a;if(!E.k)return n(k);for(a="",t=0,E.lR.lastIndex=0,r=E.lR.exec(k);r;)a+=n(k.substring(t,r.index)),e=l(E,r),e?(B+=e[1],a+=p(e[0],n(r[0]))):a+=n(r[0]),t=E.lR.lastIndex,r=E.lR.exec(k);return a+n(k.substr(t))}function d(){var e="string"==typeof E.sL;if(e&&!y[E.sL])return n(k);var t=e?f(E.sL,k,!0,x[E.sL]):g(k,E.sL.length?E.sL:void 0);return E.r>0&&(B+=t.r),e&&(x[E.sL]=t.top),p(t.language,t.value,!1,!0)}function b(){L+=null!=E.sL?d():h(),k=""}function v(e){L+=e.cN?p(e.cN,"",!0):"",E=Object.create(e,{parent:{value:E}})}function m(e,n){if(k+=e,null==n)return b(),0;var t=o(n,E);if(t)return t.skip?k+=n:(t.eB&&(k+=n),b(),t.rB||t.eB||(k=n)),v(t,n),t.rB?0:n.length;var r=u(E,n);if(r){var a=E;a.skip?k+=n:(a.rE||a.eE||(k+=n),b(),a.eE&&(k=n));do E.cN&&(L+=C),E.skip||(B+=E.r),E=E.parent;while(E!==r.parent);return r.starts&&v(r.starts,""),a.rE?0:n.length}if(c(n,E))throw new Error('Illegal lexeme "'+n+'" for mode "'+(E.cN||"")+'"');return k+=n,n.length||1}var N=w(e);if(!N)throw new Error('Unknown language: "'+e+'"');s(N);var R,E=i||N,x={},L="";for(R=E;R!==N;R=R.parent)R.cN&&(L=p(R.cN,"",!0)+L);var k="",B=0;try{for(var M,j,O=0;;){if(E.t.lastIndex=O,M=E.t.exec(t),!M)break;j=m(t.substring(O,M.index),M[0]),O=M.index+j}for(m(t.substr(O)),R=E;R.parent;R=R.parent)R.cN&&(L+=C);return{r:B,value:L,language:e,top:E}}catch(T){if(T.message&&-1!==T.message.indexOf("Illegal"))return{r:0,value:n(t)};throw T}}function g(e,t){t=t||I.languages||x(y);var r={r:0,value:n(e)},a=r;return t.filter(w).forEach(function(n){var t=f(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}),a.language&&(r.second_best=a),r}function p(e){return I.tabReplace||I.useBR?e.replace(M,function(e,n){return I.useBR&&"\n"===e?"
":I.tabReplace?n.replace(/\t/g,I.tabReplace):""}):e}function h(e,n,t){var r=n?L[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function d(e){var n,t,r,o,l,s=i(e);a(s)||(I.useBR?(n=document.createElementNS("http://www.w3.org/1999/xhtml","div"),n.innerHTML=e.innerHTML.replace(/\n/g,"").replace(/
/g,"\n")):n=e,l=n.textContent,r=s?f(s,l,!0):g(l),t=u(n),t.length&&(o=document.createElementNS("http://www.w3.org/1999/xhtml","div"),o.innerHTML=r.value,r.value=c(t,u(o),l)),r.value=p(r.value),e.innerHTML=r.value,e.className=h(e.className,s,r.language),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function b(e){I=o(I,e)}function v(){if(!v.called){v.called=!0;var e=document.querySelectorAll("pre code");E.forEach.call(e,d)}}function m(){addEventListener("DOMContentLoaded",v,!1),addEventListener("load",v,!1)}function N(n,t){var r=y[n]=t(e);r.aliases&&r.aliases.forEach(function(e){L[e]=n})}function R(){return x(y)}function w(e){return e=(e||"").toLowerCase(),y[e]||y[L[e]]}var E=[],x=Object.keys,y={},L={},k=/^(no-?highlight|plain|text)$/i,B=/\blang(?:uage)?-([\w-]+)\b/i,M=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,C="",I={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0};return e.highlight=f,e.highlightAuto=g,e.fixMarkup=p,e.highlightBlock=d,e.configure=b,e.initHighlighting=v,e.initHighlightingOnLoad=m,e.registerLanguage=N,e.listLanguages=R,e.getLanguage=w,e.inherit=o,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e.METHOD_GUARD={b:"\\.\\s*"+e.UIR,r:0},e});hljs.registerLanguage("cs",function(e){var i={keyword:"abstract as base bool break byte case catch char checked const continue decimal default delegate do double enum event explicit extern finally fixed float for foreach goto if implicit in int interface internal is lock long nameof object operator out override params private protected public readonly ref sbyte sealed short sizeof stackalloc static string struct switch this try typeof uint ulong unchecked unsafe ushort using virtual void volatile while add alias ascending async await by descending dynamic equals from get global group into join let on orderby partial remove select set value var where yield",literal:"null false true"},t={cN:"string",b:'@"',e:'"',c:[{b:'""'}]},r=e.inherit(t,{i:/\n/}),a={cN:"subst",b:"{",e:"}",k:i},c=e.inherit(a,{i:/\n/}),n={cN:"string",b:/\$"/,e:'"',i:/\n/,c:[{b:"{{"},{b:"}}"},e.BE,c]},s={cN:"string",b:/\$@"/,e:'"',c:[{b:"{{"},{b:"}}"},{b:'""'},a]},o=e.inherit(s,{i:/\n/,c:[{b:"{{"},{b:"}}"},{b:'""'},c]});a.c=[s,n,t,e.ASM,e.QSM,e.CNM,e.CBCM],c.c=[o,n,r,e.ASM,e.QSM,e.CNM,e.inherit(e.CBCM,{i:/\n/})];var l={v:[s,n,t,e.ASM,e.QSM]},b=e.IR+"(<"+e.IR+"(\\s*,\\s*"+e.IR+")*>)?(\\[\\])?";return{aliases:["csharp"],k:i,i:/::/,c:[e.C("///","$",{rB:!0,c:[{cN:"doctag",v:[{b:"///",r:0},{b:""},{b:"?",e:">"}]}]}),e.CLCM,e.CBCM,{cN:"meta",b:"#",e:"$",k:{"meta-keyword":"if else elif endif define undef warning error line region endregion pragma checksum"}},l,e.CNM,{bK:"class interface",e:/[{;=]/,i:/[^\s:]/,c:[e.TM,e.CLCM,e.CBCM]},{bK:"namespace",e:/[{;=]/,i:/[^\s:]/,c:[e.inherit(e.TM,{b:"[a-zA-Z](\\.?\\w)*"}),e.CLCM,e.CBCM]},{cN:"meta",b:"^\\s*\\[",eB:!0,e:"\\]",eE:!0,c:[{cN:"meta-string",b:/"/,e:/"/}]},{bK:"new return throw await else",r:0},{cN:"function",b:"("+b+"\\s+)+"+e.IR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:i,c:[{b:e.IR+"\\s*\\(",rB:!0,c:[e.TM],r:0},{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,k:i,r:0,c:[l,e.CNM,e.CBCM]},e.CLCM,e.CBCM]}]}});hljs.registerLanguage("http",function(e){var t="HTTP/[0-9\\.]+";return{aliases:["https"],i:"\\S",c:[{b:"^"+t,e:"$",c:[{cN:"number",b:"\\b\\d{3}\\b"}]},{b:"^[A-Z]+ (.*?) "+t+"$",rB:!0,e:"$",c:[{cN:"string",b:" ",e:" ",eB:!0,eE:!0},{b:t},{cN:"keyword",b:"[A-Z]+"}]},{cN:"attribute",b:"^\\w",e:": ",eE:!0,i:"\\n|\\s|=",starts:{e:"$",r:0}},{b:"\\n\\n",starts:{sL:[],eW:!0}}]}});hljs.registerLanguage("typescript",function(e){var r={keyword:"in if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const class public private protected get set super static implements enum export import declare type namespace abstract as from extends async await",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document any number boolean string void Promise"};return{aliases:["ts"],k:r,c:[{cN:"meta",b:/^\s*['"]use strict['"]/},e.ASM,e.QSM,{cN:"string",b:"`",e:"`",c:[e.BE,{cN:"subst",b:"\\$\\{",e:"\\}"}]},e.CLCM,e.CBCM,{cN:"number",v:[{b:"\\b(0[bB][01]+)"},{b:"\\b(0[oO][0-7]+)"},{b:e.CNR}],r:0},{b:"("+e.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[e.CLCM,e.CBCM,e.RM,{cN:"function",b:"(\\(.*?\\)|"+e.IR+")\\s*=>",rB:!0,e:"\\s*=>",c:[{cN:"params",v:[{b:e.IR},{b:/\(\s*\)/},{b:/\(/,e:/\)/,eB:!0,eE:!0,k:r,c:["self",e.CLCM,e.CBCM]}]}]}],r:0},{cN:"function",b:"function",e:/[\{;]/,eE:!0,k:r,c:["self",e.inherit(e.TM,{b:/[A-Za-z$_][0-9A-Za-z$_]*/}),{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,k:r,c:[e.CLCM,e.CBCM],i:/["'\(]/}],i:/%/,r:0},{bK:"constructor",e:/\{/,eE:!0,c:["self",{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,k:r,c:[e.CLCM,e.CBCM],i:/["'\(]/}]},{b:/module\./,k:{built_in:"module"},r:0},{bK:"module",e:/\{/,eE:!0},{bK:"interface",e:/\{/,eE:!0,k:"interface extends"},{b:/\$[(.]/},{b:"\\."+e.IR,r:0},{cN:"meta",b:"@[A-Za-z]+"}]}});hljs.registerLanguage("xml",function(s){var e="[A-Za-z0-9\\._:-]+",t={eW:!0,i:/,r:0,c:[{cN:"attr",b:e,r:0},{b:/=\s*/,r:0,c:[{cN:"string",endsParent:!0,v:[{b:/"/,e:/"/},{b:/'/,e:/'/},{b:/[^\s"'=<>`]+/}]}]}]};return{aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist"],cI:!0,c:[{cN:"meta",b:"",r:10,c:[{b:"\\[",e:"\\]"}]},s.C("",{r:10}),{b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{b:/<\?(php)?/,e:/\?>/,sL:"php",c:[{b:"/\\*",e:"\\*/",skip:!0}]},{cN:"tag",b:"",rE:!0,sL:["css","xml"]}},{cN:"tag",b:"",rE:!0,sL:["actionscript","javascript","handlebars","xml"]}},{cN:"meta",v:[{b:/<\?xml/,e:/\?>/,r:10},{b:/<\?\w+/,e:/\?>/}]},{cN:"tag",b:"?",e:"/?>",c:[{cN:"name",b:/[^\/><\s]+/,r:0},t]}]}});hljs.registerLanguage("markdown",function(e){return{aliases:["md","mkdown","mkd"],c:[{cN:"section",v:[{b:"^#{1,6}",e:"$"},{b:"^.+?\\n[=-]{2,}$"}]},{b:"<",e:">",sL:"xml",r:0},{cN:"bullet",b:"^([*+-]|(\\d+\\.))\\s+"},{cN:"strong",b:"[*_]{2}.+?[*_]{2}"},{cN:"emphasis",v:[{b:"\\*.+?\\*"},{b:"_.+?_",r:0}]},{cN:"quote",b:"^>\\s+",e:"$"},{cN:"code",v:[{b:"^```w*s*$",e:"^```s*$"},{b:"`.+?`"},{b:"^( {4}| )",e:"$",r:0}]},{b:"^[-\\*]{3,}",e:"$"},{b:"\\[.+?\\][\\(\\[].*?[\\)\\]]",rB:!0,c:[{cN:"string",b:"\\[",e:"\\]",eB:!0,rE:!0,r:0},{cN:"link",b:"\\]\\(",e:"\\)",eB:!0,eE:!0},{cN:"symbol",b:"\\]\\[",e:"\\]",eB:!0,eE:!0}],r:10},{b:/^\[[^\n]+\]:/,rB:!0,c:[{cN:"symbol",b:/\[/,e:/\]/,eB:!0,eE:!0},{cN:"link",b:/:\s*/,e:/$/,eB:!0}]}]}});hljs.registerLanguage("javascript",function(e){var r="[A-Za-z$_][0-9A-Za-z$_]*",t={keyword:"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await static import from as",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Promise"},a={cN:"number",v:[{b:"\\b(0[bB][01]+)"},{b:"\\b(0[oO][0-7]+)"},{b:e.CNR}],r:0},n={cN:"subst",b:"\\$\\{",e:"\\}",k:t,c:[]},c={cN:"string",b:"`",e:"`",c:[e.BE,n]};n.c=[e.ASM,e.QSM,c,a,e.RM];var s=n.c.concat([e.CBCM,e.CLCM]);return{aliases:["js","jsx"],k:t,c:[{cN:"meta",r:10,b:/^\s*['"]use (strict|asm)['"]/},{cN:"meta",b:/^#!/,e:/$/},e.ASM,e.QSM,c,e.CLCM,e.CBCM,a,{b:/[{,]\s*/,r:0,c:[{b:r+"\\s*:",rB:!0,r:0,c:[{cN:"attr",b:r,r:0}]}]},{b:"("+e.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[e.CLCM,e.CBCM,e.RM,{cN:"function",b:"(\\(.*?\\)|"+r+")\\s*=>",rB:!0,e:"\\s*=>",c:[{cN:"params",v:[{b:r},{b:/\(\s*\)/},{b:/\(/,e:/\)/,eB:!0,eE:!0,k:t,c:s}]}]},{b:/,e:/(\/\w+|\w+\/)>/,sL:"xml",c:[{b:/<\w+\s*\/>/,skip:!0},{b:/<\w+/,e:/(\/\w+|\w+\/)>/,skip:!0,c:[{b:/<\w+\s*\/>/,skip:!0},"self"]}]}],r:0},{cN:"function",bK:"function",e:/\{/,eE:!0,c:[e.inherit(e.TM,{b:r}),{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,c:s}],i:/\[|%/},{b:/\$[(.]/},e.METHOD_GUARD,{cN:"class",bK:"class",e:/[{;=]/,eE:!0,i:/[:"\[\]]/,c:[{bK:"extends"},e.UTM]},{bK:"constructor",e:/\{/,eE:!0}],i:/#(?!!)/}});hljs.registerLanguage("css",function(e){var c="[a-zA-Z-][a-zA-Z0-9_-]*",t={b:/[A-Z\_\.\-]+\s*:/,rB:!0,e:";",eW:!0,c:[{cN:"attribute",b:/\S/,e:":",eE:!0,starts:{eW:!0,eE:!0,c:[{b:/[\w-]+\(/,rB:!0,c:[{cN:"built_in",b:/[\w-]+/},{b:/\(/,e:/\)/,c:[e.ASM,e.QSM]}]},e.CSSNM,e.QSM,e.ASM,e.CBCM,{cN:"number",b:"#[0-9A-Fa-f]+"},{cN:"meta",b:"!important"}]}}]};return{cI:!0,i:/[=\/|'\$]/,c:[e.CBCM,{cN:"selector-id",b:/#[A-Za-z0-9_-]+/},{cN:"selector-class",b:/\.[A-Za-z0-9_-]+/},{cN:"selector-attr",b:/\[/,e:/\]/,i:"$"},{cN:"selector-pseudo",b:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{b:"@(font-face|page)",l:"[a-z-]+",k:"font-face page"},{b:"@",e:"[{;]",i:/:/,c:[{cN:"keyword",b:/\w+/},{b:/\s/,eW:!0,eE:!0,r:0,c:[e.ASM,e.QSM,e.CSSNM]}]},{cN:"selector-tag",b:c,r:0},{b:"{",e:"}",i:/\S/,c:[e.CBCM,t]}]}});hljs.registerLanguage("json",function(e){var i={literal:"true false null"},n=[e.QSM,e.CNM],r={e:",",eW:!0,eE:!0,c:n,k:i},t={b:"{",e:"}",c:[{cN:"attr",b:/"/,e:/"/,c:[e.BE],i:"\\n"},e.inherit(r,{b:/:/})],i:"\\S"},c={b:"\\[",e:"\\]",c:[e.inherit(r)],i:"\\S"};return n.splice(n.length,0,t,c),{c:n,k:i,i:"\\S"}});hljs.registerLanguage("less",function(e){var r="[\\w-]+",t="("+r+"|@{"+r+"})",a=[],c=[],s=function(e){return{cN:"string",b:"~?"+e+".*?"+e}},b=function(e,r,t){return{cN:e,b:r,r:t}},n={b:"\\(",e:"\\)",c:c,r:0};c.push(e.CLCM,e.CBCM,s("'"),s('"'),e.CSSNM,{b:"(url|data-uri)\\(",starts:{cN:"string",e:"[\\)\\n]",eE:!0}},b("number","#[0-9A-Fa-f]+\\b"),n,b("variable","@@?"+r,10),b("variable","@{"+r+"}"),b("built_in","~?`[^`]*?`"),{cN:"attribute",b:r+"\\s*:",e:":",rB:!0,eE:!0},{cN:"meta",b:"!important"});var i=c.concat({b:"{",e:"}",c:a}),o={bK:"when",eW:!0,c:[{bK:"and not"}].concat(c)},u={b:t+"\\s*:",rB:!0,e:"[;}]",r:0,c:[{cN:"attribute",b:t,e:":",eE:!0,starts:{eW:!0,i:"[<=$]",r:0,c:c}}]},l={cN:"keyword",b:"@(import|media|charset|font-face|(-[a-z]+-)?keyframes|supports|document|namespace|page|viewport|host)\\b",starts:{e:"[;{}]",rE:!0,c:c,r:0}},C={cN:"variable",v:[{b:"@"+r+"\\s*:",r:15},{b:"@"+r}],starts:{e:"[;}]",rE:!0,c:i}},p={v:[{b:"[\\.#:&\\[>]",e:"[;{}]"},{b:t,e:"{"}],rB:!0,rE:!0,i:"[<='$\"]",r:0,c:[e.CLCM,e.CBCM,o,b("keyword","all\\b"),b("variable","@{"+r+"}"),b("selector-tag",t+"%?",0),b("selector-id","#"+t),b("selector-class","\\."+t,0),b("selector-tag","&",0),{cN:"selector-attr",b:"\\[",e:"\\]"},{cN:"selector-pseudo",b:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{b:"\\(",e:"\\)",c:i},{b:"!important"}]};return a.push(e.CLCM,e.CBCM,l,C,u,p),{cI:!0,i:"[=>'/<($\"]",c:a}});
\ No newline at end of file
diff --git a/Website/Composite/services/Admin/HighlightJs/vs.css b/Website/Composite/services/Admin/HighlightJs/vs.css
new file mode 100644
index 0000000000..c5d07d3115
--- /dev/null
+++ b/Website/Composite/services/Admin/HighlightJs/vs.css
@@ -0,0 +1,68 @@
+/*
+
+Visual Studio-like style based on original C# coloring by Jason Diamond
+
+*/
+.hljs {
+ display: block;
+ overflow-x: auto;
+ padding: 0.5em;
+ background: white;
+ color: black;
+}
+
+.hljs-comment,
+.hljs-quote,
+.hljs-variable {
+ color: #008000;
+}
+
+.hljs-keyword,
+.hljs-selector-tag,
+.hljs-built_in,
+.hljs-name,
+.hljs-tag {
+ color: #00f;
+}
+
+.hljs-string,
+.hljs-title,
+.hljs-section,
+.hljs-attribute,
+.hljs-literal,
+.hljs-template-tag,
+.hljs-template-variable,
+.hljs-type,
+.hljs-addition {
+ color: #a31515;
+}
+
+.hljs-deletion,
+.hljs-selector-attr,
+.hljs-selector-pseudo,
+.hljs-meta {
+ color: #2b91af;
+}
+
+.hljs-doctag {
+ color: #808080;
+}
+
+.hljs-attr {
+ color: #f00;
+}
+
+.hljs-symbol,
+.hljs-bullet,
+.hljs-link {
+ color: #00b0e8;
+}
+
+
+.hljs-emphasis {
+ font-style: italic;
+}
+
+.hljs-strong {
+ font-weight: bold;
+}
From bfc711b3f41fbc00584e50d9a8b25776cc817374 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pauli=20=C3=98ster=C3=B8?=
Date: Mon, 19 Mar 2018 15:10:24 -0300
Subject: [PATCH 02/51] Updating WampSharp to current release version (18.3.1).
This makes it a more smooth experience to reference C1 via NuGet since things doesn't play so well when a release package is referencing beta packages.
---
.../Runtime/LoginSessionStoreResolver.cs | 2 +-
Composite/Composite.csproj | 19 +++++++++++++------
.../WampContextBasedBasedLoginSessionStore.cs | 2 +-
Composite/packages.config | 12 +++++++-----
Website/WebSite.csproj | 8 +++++---
Website/packages.config | 14 +++++++-------
6 files changed, 34 insertions(+), 23 deletions(-)
diff --git a/Composite/C1Console/Security/Plugins/LoginSessionStore/Runtime/LoginSessionStoreResolver.cs b/Composite/C1Console/Security/Plugins/LoginSessionStore/Runtime/LoginSessionStoreResolver.cs
index 195863827b..57e98ae067 100644
--- a/Composite/C1Console/Security/Plugins/LoginSessionStore/Runtime/LoginSessionStoreResolver.cs
+++ b/Composite/C1Console/Security/Plugins/LoginSessionStore/Runtime/LoginSessionStoreResolver.cs
@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
-using Castle.Core.Internal;
+using Composite.Core.Extensions;
namespace Composite.C1Console.Security.Plugins.LoginSessionStore.Runtime
{
diff --git a/Composite/Composite.csproj b/Composite/Composite.csproj
index 385e2e52ca..abdabb8ec8 100644
--- a/Composite/Composite.csproj
+++ b/Composite/Composite.csproj
@@ -68,8 +68,8 @@
false
-
- ..\packages\Castle.Core.3.3.1\lib\net45\Castle.Core.dll
+
+ ..\packages\Castle.Core.4.2.1\lib\net45\Castle.Core.dll
True
@@ -154,7 +154,14 @@
3.5
+
+ ..\packages\System.Threading.Tasks.Dataflow.4.7.0\lib\portable-net45+win8+wpa81\System.Threading.Tasks.Dataflow.dll
+
+
+ ..\packages\System.ValueTuple.4.4.0\lib\net47\System.ValueTuple.dll
+ True
+
..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll
@@ -190,19 +197,19 @@
..\bin\TidyNet.dll
- ..\packages\WampSharp.1.2.5.32-beta\lib\net45\WampSharp.dll
+ ..\packages\WampSharp.18.3.1\lib\net45\WampSharp.dll
True
- ..\packages\WampSharp.AspNet.WebSockets.Server.1.2.5.32-beta\lib\net45\WampSharp.AspNet.WebSockets.Server.dll
+ ..\packages\WampSharp.AspNet.WebSockets.Server.18.3.1\lib\net45\WampSharp.AspNet.WebSockets.Server.dll
True
- ..\packages\WampSharp.NewtonsoftJson.1.2.5.32-beta\lib\net45\WampSharp.NewtonsoftJson.dll
+ ..\packages\WampSharp.NewtonsoftJson.18.3.1\lib\net45\WampSharp.NewtonsoftJson.dll
True
- ..\packages\WampSharp.WebSockets.1.2.5.32-beta\lib\net45\WampSharp.WebSockets.dll
+ ..\packages\WampSharp.WebSockets.18.3.1\lib\net45\WampSharp.WebSockets.dll
True
diff --git a/Composite/Plugins/Security/LoginSessionStores/WampContextBasedLoginSessionStore/WampContextBasedBasedLoginSessionStore.cs b/Composite/Plugins/Security/LoginSessionStores/WampContextBasedLoginSessionStore/WampContextBasedBasedLoginSessionStore.cs
index f6f26a6b8d..3a55b0a7e2 100644
--- a/Composite/Plugins/Security/LoginSessionStores/WampContextBasedLoginSessionStore/WampContextBasedBasedLoginSessionStore.cs
+++ b/Composite/Plugins/Security/LoginSessionStores/WampContextBasedLoginSessionStore/WampContextBasedBasedLoginSessionStore.cs
@@ -31,7 +31,7 @@ public string StoredUsername
{
if (WampInvocationContext.Current != null)
{
- return WampInvocationContext.Current.InvocationDetails.AuthenticationId;
+ return WampInvocationContext.Current.InvocationDetails.CallerAuthenticationId;
}
return null;
diff --git a/Composite/packages.config b/Composite/packages.config
index 47ee7dc78c..8cf9432787 100644
--- a/Composite/packages.config
+++ b/Composite/packages.config
@@ -1,6 +1,6 @@
-
+
@@ -15,8 +15,10 @@
-
-
-
-
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Website/WebSite.csproj b/Website/WebSite.csproj
index 3f8d4aeeda..2667746362 100644
--- a/Website/WebSite.csproj
+++ b/Website/WebSite.csproj
@@ -53,9 +53,8 @@
false
-
- ..\packages\Castle.Core.3.3.1\lib\net45\Castle.Core.dll
- True
+
+ ..\packages\Castle.Core.4.2.1\lib\net45\Castle.Core.dll
False
@@ -111,6 +110,9 @@
False
..\Packages\System.Reflection.Metadata.1.4.2\lib\portable-net45+win8\System.Reflection.Metadata.dll
+
+ ..\packages\System.Threading.Tasks.Dataflow.4.7.0\lib\portable-net45+win8+wpa81\System.Threading.Tasks.Dataflow.dll
+
diff --git a/Website/packages.config b/Website/packages.config
index 889fa78b98..9da15a9e51 100644
--- a/Website/packages.config
+++ b/Website/packages.config
@@ -1,19 +1,19 @@
-
+
+
+
+
+
+
-
-
-
-
-
-
+
\ No newline at end of file
From fc751afe1523f814a9e068024318e21d83e3749b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pauli=20=C3=98ster=C3=B8?=
Date: Mon, 19 Mar 2018 15:42:28 -0300
Subject: [PATCH 03/51] Remove reference to Microsoft WebSockets package since
this is all handled by WampSharp
Code using this package was removed in changetset ffeb5e7f5053b231a48b0864af766e2df84d18fc
---
Composite/Composite.csproj | 4 ----
Composite/packages.config | 1 -
2 files changed, 5 deletions(-)
diff --git a/Composite/Composite.csproj b/Composite/Composite.csproj
index abdabb8ec8..33230fd2ad 100644
--- a/Composite/Composite.csproj
+++ b/Composite/Composite.csproj
@@ -97,10 +97,6 @@
False
..\bin\Microsoft.Practices.ObjectBuilder.dll
-
- ..\packages\Microsoft.WebSockets.0.2.3.1\lib\net45\Microsoft.WebSockets.dll
- True
-
..\packages\Newtonsoft.Json.6.0.5\lib\net45\Newtonsoft.Json.dll
True
diff --git a/Composite/packages.config b/Composite/packages.config
index 8cf9432787..bc9f316aab 100644
--- a/Composite/packages.config
+++ b/Composite/packages.config
@@ -6,7 +6,6 @@
-
From 913e16b170430fea0ea514d97b0db1a99630dca7 Mon Sep 17 00:00:00 2001
From: Dmitry Dzygin
Date: Fri, 23 Mar 2018 16:41:43 +0100
Subject: [PATCH 04/51] Fixing a media indexing not working if there's a media
file with empty FilePath and Label fields
---
.../MediaLibraryDocumentSource.cs | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/Composite/Search/DocumentSources/MediaLibraryDocumentSource.cs b/Composite/Search/DocumentSources/MediaLibraryDocumentSource.cs
index b52d93c46a..55e19a40e4 100644
--- a/Composite/Search/DocumentSources/MediaLibraryDocumentSource.cs
+++ b/Composite/Search/DocumentSources/MediaLibraryDocumentSource.cs
@@ -1,11 +1,12 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
-using Composite.Search.Crawling;
+using Composite.Core;
using Composite.Core.Linq;
using Composite.Data;
using Composite.Data.Types;
+using Composite.Search.Crawling;
namespace Composite.Search.DocumentSources
{
@@ -58,7 +59,7 @@ public IEnumerable GetSearchDocuments(CultureInfo
{
Document = FromMediaFile(m),
ContinuationToken = m.Id.ToString()
- });
+ }).Where(doc => doc.Document != null);
}
private SearchDocument FromMediaFile(IMediaFile mediaFile)
@@ -69,14 +70,19 @@ private SearchDocument FromMediaFile(IMediaFile mediaFile)
label = mediaFile.FileName;
}
- string documentId = mediaFile.Id.ToString();
+ if(string.IsNullOrEmpty(label))
+ {
+ Log.LogWarning(nameof(MediaLibraryDocumentSource),
+ $"A media file has neither FileName nor Label fields specified, Id: '{mediaFile.Id}', StoreId: '{mediaFile.StoreId}'.");
+ return null;
+ }
var docBuilder = new SearchDocumentBuilder(_docBuilderExtensions);
docBuilder.SetDataType(typeof(IMediaFile));
docBuilder.CrawlData(mediaFile);
- return docBuilder.BuildDocument(Name, documentId, label, null, mediaFile.GetDataEntityToken());
+ return docBuilder.BuildDocument(Name, mediaFile.Id.ToString(), label, null, mediaFile.GetDataEntityToken());
}
}
}
From 41f410f340e0359c4a043970577e3e522dc17996 Mon Sep 17 00:00:00 2001
From: Dmitry Dzygin
Date: Tue, 27 Mar 2018 16:21:48 +0200
Subject: [PATCH 05/51] Fix #554 It shouldn't be possible to add 2 data folders
for the same page at the same time via UI
---
.../AddDataFolderExWorkflow.cs | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/Composite.Workflows/C1Console/Elements/ElementProviderHelpers/AssociatedDataElementProviderHelper/AddDataFolderExWorkflow.cs b/Composite.Workflows/C1Console/Elements/ElementProviderHelpers/AssociatedDataElementProviderHelper/AddDataFolderExWorkflow.cs
index 80b8c9d6b3..4f54ed36c7 100644
--- a/Composite.Workflows/C1Console/Elements/ElementProviderHelpers/AssociatedDataElementProviderHelper/AddDataFolderExWorkflow.cs
+++ b/Composite.Workflows/C1Console/Elements/ElementProviderHelpers/AssociatedDataElementProviderHelper/AddDataFolderExWorkflow.cs
@@ -35,6 +35,8 @@ public sealed partial class AddDataFolderExWorkflow : Composite.C1Console.Workfl
private string HasLocalizationBindingName { get { return "HasLocalization"; } }
+ private static readonly object _lock = new object();
+
public AddDataFolderExWorkflow()
{
InitializeComponent();
@@ -228,7 +230,16 @@ private void finalizeCodeActivity_Finalize_ExecuteCode(object sender, EventArgs
IPage page = (IPage)dataEntityToken.Data;
- page.AddFolderDefinition(type.GetImmutableTypeId());
+ Guid dataTypeId = type.GetImmutableTypeId();
+
+ lock (_lock)
+ {
+ if (page.GetFolderDefinitionId(dataTypeId) == Guid.Empty)
+ {
+ page.AddFolderDefinition(dataTypeId);
+ }
+ }
+
SpecificTreeRefresher specificTreeRefresher = this.CreateSpecificTreeRefresher();
specificTreeRefresher.PostRefreshMesseges(this.EntityToken);
From 3e3bcc51e71b0dcf12f73f988e9c580226e9fdab Mon Sep 17 00:00:00 2001
From: Taras Nakonechnyi
Date: Thu, 5 Apr 2018 19:29:34 +0300
Subject: [PATCH 06/51] fix component for IE11 (#555)
* fix component for IE11
---
.../plugins/compositecomponent/plugin.min.js | 55 +++++++++++++++----
1 file changed, 44 insertions(+), 11 deletions(-)
diff --git a/Website/Composite/content/misc/editors/visualeditor/tinymce/plugins/compositecomponent/plugin.min.js b/Website/Composite/content/misc/editors/visualeditor/tinymce/plugins/compositecomponent/plugin.min.js
index 9e80e6f8a3..283f5b15c8 100644
--- a/Website/Composite/content/misc/editors/visualeditor/tinymce/plugins/compositecomponent/plugin.min.js
+++ b/Website/Composite/content/misc/editors/visualeditor/tinymce/plugins/compositecomponent/plugin.min.js
@@ -90,7 +90,7 @@ new function () {
handler: {
handleDialogResponse: function (response, result) {
if (response == Dialog.RESPONSE_ACCEPT) {
- var componentDocument = new DOMParser().parseFromString(result.FunctionMarkup, "text/xml");
+ var componentDocument = self.parse(result.FunctionMarkup);
var ffunction = self.resolver.resolve("/f:function", componentDocument);
if (ffunction == null) {
self._resolveParametersAndInsertHtml(componentDocument);
@@ -118,12 +118,12 @@ new function () {
if (ffunction != null) {
- FunctionService.TryExecute(ffunction.outerHTML, function(functionExecutionResult) {
+ FunctionService.TryExecute(self.getMarkup(ffunction), function (functionExecutionResult) {
if (functionExecutionResult.FunctionCallExecutable) {
- self._insertImagTagAndContinue(ffunction, ffunction.outerHTML, componentDocument);
+ self._insertImagTagAndContinue(ffunction, self.getMarkup(ffunction), componentDocument);
} else {
self._launchUpdateDialog(ffunction, {
- handleDialogResponse: function(response, result) {
+ handleDialogResponse: function (response, result) {
if (response == Dialog.RESPONSE_ACCEPT) {
self._insertImagTagAndContinue(ffunction, result, componentDocument);
} else {
@@ -135,19 +135,19 @@ new function () {
});
} else {
- self._insertResult(componentDocument.firstChild.outerHTML);
+ self._insertResult(self.getMarkup(componentDocument.lastChild));
}
},
-
+
/**
- * @param {string} markup
+ * @param {XMLElement} ffunction
*/
_resolveParametersAndInsertFunction: function (ffunction) {
var self = this;
- FunctionService.TryExecute(ffunction.outerHTML, function (functionExecutionResult) {
+ FunctionService.TryExecute(self.getMarkup(ffunction), function (functionExecutionResult) {
if (functionExecutionResult.FunctionParamsExist) {
self._launchUpdateDialog(ffunction, {
handleDialogResponse: function (response, result) {
@@ -182,7 +182,13 @@ new function () {
if (ffunction.parentNode == componentDocument) {
self._insertResult(functionhtml);
} else {
- ffunction.outerHTML = functionhtml; //TODO check
+
+ if (ffunction.outerHTML) {
+ ffunction.outerHTML = functionhtml;
+ } else {
+ var imgfunction = self.parse(functionhtml);
+ ffunction.parentNode.replaceChild(imgfunction.lastChild, ffunction);
+ }
self._resolveParametersAndInsertHtml(componentDocument);
}
},
@@ -197,12 +203,39 @@ new function () {
/**
* Launch update dialog.
- * @param {string} markup
+ * @param {XmlElement} ffunction
+ * @param {DialogHandler} dialogHandler
*/
_launchUpdateDialog: function (ffunction, dialogHandler) {
- EditorBinding.invokeFunctionEditorDialog(ffunction.outerHTML, dialogHandler, "Composite.Core.Xml.XhtmlDocument, Composite", this.editor.theme.editorBinding)
+ EditorBinding.invokeFunctionEditorDialog(this.getMarkup(ffunction), dialogHandler, "Composite.Core.Xml.XhtmlDocument, Composite", this.editor.theme.editorBinding)
+ },
+
+ /**
+ * Parse XML string into DOM document.
+ * @param {String} markup
+ * @return {XmlDocument}
+ */
+ parse: function (markup) {
+
+ var result = null;
+ if (window.DOMParser != null && window.XPathResult != null) {
+ result = new DOMParser().parseFromString(markup, 'text/xml');
+ } else {
+ result = new ActiveXObject('Msxml2.DOMDocument.3.0');
+ result.setProperty('SelectionLanguage', 'XPath');
+ result.loadXML(markup);
+ }
+ return result;
+ },
+
+ /**
+ * @param {XMLElement} element
+ */
+ getMarkup: function(element) {
+ return element.xml || element.outerHTML; // IE11 || Others browser
}
+
});
// Register plugin
From 42a51c44de06c756a81d6f69202f842e9639b9c9 Mon Sep 17 00:00:00 2001
From: Marcus Wendt
Date: Tue, 10 Apr 2018 14:43:18 +0200
Subject: [PATCH 07/51] Removing 403 HTTP status code (leaving 200) for
/Composite request responses that are blocked due to setting in C1ConsoleAccess.xml config. Motivation is IIS may
replace response with a generic 403 error page, leaving you clueless as to
the cause of the block.
---
.../HttpModules/AdministrativeAuthorizationHttpModule.cs | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/Composite/Core/WebClient/HttpModules/AdministrativeAuthorizationHttpModule.cs b/Composite/Core/WebClient/HttpModules/AdministrativeAuthorizationHttpModule.cs
index 7e52e1fc92..9a698e2822 100644
--- a/Composite/Core/WebClient/HttpModules/AdministrativeAuthorizationHttpModule.cs
+++ b/Composite/Core/WebClient/HttpModules/AdministrativeAuthorizationHttpModule.cs
@@ -1,4 +1,4 @@
-using Composite.C1Console.Security;
+using Composite.C1Console.Security;
using Composite.Core.Application;
using Composite.Core.Configuration;
using Composite.Core.IO;
@@ -120,7 +120,6 @@ private void context_AuthorizeRequest(object sender, EventArgs e)
if (!_allowC1ConsoleRequests)
{
- context.Response.StatusCode = 403;
context.Response.ContentType = "text/html";
string iePadding = new String('!', 512);
context.Response.Write(string.Format(c1ConsoleRequestsNotAllowedHtmlTemplate, iePadding));
From 2918dc406a6385bf276f8f324c4e9afa565a2ff6 Mon Sep 17 00:00:00 2001
From: Marcus Wendt
Date: Wed, 11 Apr 2018 16:29:34 +0200
Subject: [PATCH 08/51] Deveting informational readme.now.txt
Not relevant in these crazy modern times.
---
readme.now.txt | 7 -------
1 file changed, 7 deletions(-)
delete mode 100644 readme.now.txt
diff --git a/readme.now.txt b/readme.now.txt
deleted file mode 100644
index b6e3f94a58..0000000000
--- a/readme.now.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-
-Please note that Firefox, Safari and Chrome can be extremely slow when working
-with Visual Studio’s built-in development Web server (a.k.a. Cassini). This is
-related to an issue with IPv6 and DNS.
-
-For resolutions, please see:
-http://codepolice.net/2009/02/19/slow-iis-on-vista-with-firefox-chrome-or-safari/
From ff65ed53319d90cfa628cdd5c77beab8f7da59be Mon Sep 17 00:00:00 2001
From: Dmitry Dzygin
Date: Thu, 12 Apr 2018 15:24:42 +0200
Subject: [PATCH 09/51] Fix #560 Caching issue when using VersionPublication
package alongside LoadBalancing package
---
Composite/Data/Caching/DataCachingFacade.cs | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/Composite/Data/Caching/DataCachingFacade.cs b/Composite/Data/Caching/DataCachingFacade.cs
index a2b1c73a73..d85d36d753 100644
--- a/Composite/Data/Caching/DataCachingFacade.cs
+++ b/Composite/Data/Caching/DataCachingFacade.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
@@ -282,16 +282,16 @@ internal static void UpdateCachedTables(
internal static void ClearCache(Type interfaceType, DataScopeIdentifier dataScopeIdentifier, CultureInfo localizationScope)
{
- TypeData typeData;
- if (!_cachedData.TryGetValue(interfaceType, out typeData)) return;
+ if (!_cachedData.TryGetValue(interfaceType, out TypeData typeData)) return;
dataScopeIdentifier = dataScopeIdentifier ?? DataScopeManager.MapByType(interfaceType);
- localizationScope = localizationScope ?? LocalizationScopeManager.MapByType(interfaceType);
+ localizationScope = !DataLocalizationFacade.IsLocalized(interfaceType)
+ ? CultureInfo.InvariantCulture
+ : (localizationScope ?? LocalizationScopeManager.CurrentLocalizationScope);
var key = new Tuple(dataScopeIdentifier, localizationScope);
- CachedTable value;
- typeData.TryRemove(key, out value);
+ typeData.TryRemove(key, out _);
}
From c60df8de772f8c8dc0518336d5ff43c5a61c3198 Mon Sep 17 00:00:00 2001
From: Dmitry Dzygin
Date: Thu, 12 Apr 2018 15:53:35 +0200
Subject: [PATCH 10/51] Better logging and refactoring
---
.../DataPackageFragmentInstaller.cs | 40 +++++++------------
.../SqlDataProviderStoreManipulator.cs | 8 ++--
.../XmlDataProvider/XmlDataProvider_CRUD.cs | 22 +++++-----
3 files changed, 30 insertions(+), 40 deletions(-)
diff --git a/Composite/Core/PackageSystem/PackageFragmentInstallers/DataPackageFragmentInstaller.cs b/Composite/Core/PackageSystem/PackageFragmentInstallers/DataPackageFragmentInstaller.cs
index 38d299cb77..b23a922a01 100644
--- a/Composite/Core/PackageSystem/PackageFragmentInstallers/DataPackageFragmentInstaller.cs
+++ b/Composite/Core/PackageSystem/PackageFragmentInstallers/DataPackageFragmentInstaller.cs
@@ -36,7 +36,7 @@ public sealed class DataPackageFragmentInstaller : BasePackageFragmentInstaller
private Dictionary>> _missingDataReferences;
- private static Dictionary _pageVersionIds = new Dictionary();
+ private static readonly Dictionary _pageVersionIds = new Dictionary();
///
public override IEnumerable Validate()
@@ -208,15 +208,14 @@ private XElement AddData(DataType dataType, CultureInfo cultureInfo)
}
}
- ILocalizedControlled localizedControlled = data as ILocalizedControlled;
- if (localizedControlled != null)
+ if (data is ILocalizedControlled localizedControlled)
{
localizedControlled.SourceCultureName = LocalizationScopeManager.MapByType(interfaceType).Name;
}
- if (data is IVersioned)
+ if (data is IVersioned versionedData)
{
- UpdateVersionId((IVersioned)data);
+ UpdateVersionId(versionedData);
}
DataFacade.AddNew(data, false, true, false); // Ignore validation, this should have been done in the validation face
@@ -249,13 +248,9 @@ private void UpdateVersionId(IVersioned data)
return;
}
- if (data is IPage)
+ if (data is IPage page)
{
- var page = (IPage)data;
-
- Guid versionId;
-
- if (_pageVersionIds.TryGetValue(page.Id, out versionId))
+ if (_pageVersionIds.TryGetValue(page.Id, out Guid versionId))
{
page.VersionId = versionId;
}
@@ -266,22 +261,16 @@ private void UpdateVersionId(IVersioned data)
}
}
- else if (data is IPagePlaceholderContent)
+ else if (data is IPagePlaceholderContent pagePlaceholderContent)
{
- Guid pageId = ((IPagePlaceholderContent)data).PageId;
- Guid versionId;
-
- if (_pageVersionIds.TryGetValue(pageId, out versionId))
+ if (_pageVersionIds.TryGetValue(pagePlaceholderContent.PageId, out Guid versionId))
{
data.VersionId = versionId;
}
}
- else if (data is IPageData)
+ else if (data is IPageData pageData)
{
- Guid pageId = ((IPageData)data).PageId;
- Guid versionId;
-
- if (_pageVersionIds.TryGetValue(pageId, out versionId))
+ if (_pageVersionIds.TryGetValue(pageData.PageId, out Guid versionId))
{
data.VersionId = versionId;
}
@@ -681,7 +670,7 @@ private static Dictionary GetDataTypeProperties(Type type)
private static bool IsObsoleteProperty(PropertyInfo propertyInfo)
{
- return propertyInfo.Name == "PageId" && propertyInfo.DeclaringType == typeof(IPageData);
+ return propertyInfo.Name == nameof(IPageData.PageId) && propertyInfo.DeclaringType == typeof(IPageData);
}
private static bool IsObsoleteField(DataTypeDescriptor dataTypeDescriptor, string fieldName)
@@ -694,11 +683,11 @@ private static void MapReference(Type type, string propertyName, object key, out
{
if ((type == typeof(IImageFile) || type == typeof(IMediaFile))
&& ((string)key).StartsWith("MediaArchive:")
- && propertyName == "KeyPath")
+ && propertyName == nameof(IMediaFile.KeyPath))
{
referenceType = typeof(IMediaFileData);
referenceKey = new Guid(((string)key).Substring("MediaArchive:".Length));
- keyPropertyName = "Id";
+ keyPropertyName = nameof(IMediaFileData.Id);
return;
}
@@ -820,8 +809,7 @@ private void ValidateDynamicAddedType(DataType dataType)
// Checking foreign key references
foreach (var referenceField in dataTypeDescriptor.Fields.Where(f => f.ForeignKeyReferenceTypeName != null))
{
- object propertyValue;
- if (!fieldValues.TryGetValue(referenceField.Name, out propertyValue)
+ if (!fieldValues.TryGetValue(referenceField.Name, out object propertyValue)
|| propertyValue == null
|| (propertyValue is Guid guid && guid == Guid.Empty)
|| (propertyValue is string str && str == ""))
diff --git a/Composite/Plugins/Data/DataProviders/MSSqlServerDataProvider/Foundation/SqlDataProviderStoreManipulator.cs b/Composite/Plugins/Data/DataProviders/MSSqlServerDataProvider/Foundation/SqlDataProviderStoreManipulator.cs
index e544be056f..3e79480bfd 100644
--- a/Composite/Plugins/Data/DataProviders/MSSqlServerDataProvider/Foundation/SqlDataProviderStoreManipulator.cs
+++ b/Composite/Plugins/Data/DataProviders/MSSqlServerDataProvider/Foundation/SqlDataProviderStoreManipulator.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
@@ -411,9 +411,7 @@ private void AlterStore(UpdateDataTypeDescriptor updateDataTypeDescriptor, DataT
if (!tables.Contains(originalTableName))
{
throw new InvalidOperationException(
- string.Format(
- "Unable to alter data type store. The database does not contain expected table {0}",
- originalTableName));
+ $"Unable to alter data type store for type '{changeDescriptor.AlteredType.GetFullInterfaceName()}'. The database does not contain expected table '{originalTableName}'");
}
@@ -429,7 +427,7 @@ private void AlterStore(UpdateDataTypeDescriptor updateDataTypeDescriptor, DataT
{
if (tables.Contains(alteredTableName))
throw new InvalidOperationException(
- $"Can not rename table to {alteredTableName}. A table with that name already exists");
+ $"Can not rename table '{originalTableName}' to '{alteredTableName}'. A table with that name already exists");
RenameTable(originalTableName, alteredTableName);
}
diff --git a/Composite/Plugins/Data/DataProviders/XmlDataProvider/XmlDataProvider_CRUD.cs b/Composite/Plugins/Data/DataProviders/XmlDataProvider/XmlDataProvider_CRUD.cs
index 89d9b382f9..1356a06394 100644
--- a/Composite/Plugins/Data/DataProviders/XmlDataProvider/XmlDataProvider_CRUD.cs
+++ b/Composite/Plugins/Data/DataProviders/XmlDataProvider/XmlDataProvider_CRUD.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
@@ -6,7 +6,6 @@
using System.Xml.Linq;
using Composite.Core;
using Composite.Core.Collections.Generic;
-using Composite.Core.Extensions;
using Composite.Core.Threading;
using Composite.Data;
using Composite.Data.Caching;
@@ -116,16 +115,18 @@ public void Update(IEnumerable dataset)
XElement element = index[dataId];
- Verify.ArgumentCondition(element != null, "dataset", "No data element corresponds to the given data id");
+ if (element == null)
+ {
+ throw new ArgumentException($"Cannot update a data item, no data element corresponds to the given data id: '{dataId.Serialize(null)}'; Type: '{type}'; DataScope: '{dataScope}'; Culture: '{culture}'", nameof(dataset));
+ }
IXElementWrapper wrapper = data as IXElementWrapper;
- Verify.ArgumentCondition(wrapper != null, "dataset", "The type of data was expected to be of type {0}".FormatWith(typeof(IXElementWrapper)));
+ Verify.ArgumentCondition(wrapper != null, nameof(dataset), $"The type of data was expected to be of type {typeof(IXElementWrapper)}");
XElement updatedElement = CreateUpdatedXElement(wrapper, element);
validatedFileRecords.Add(data.DataSourceId, fileRecord);
validatedElements.Add(data.DataSourceId, updatedElement);
-
}
foreach (var key in validatedElements.Keys)
@@ -133,7 +134,6 @@ public void Update(IEnumerable dataset)
FileRecord fileRecord = validatedFileRecords[key];
fileRecord.Dirty = true;
fileRecord.RecordSet.Index[key.DataId] = validatedElements[key];
-
}
XmlDataProviderDocumentCache.SaveChanges();
@@ -212,17 +212,18 @@ public void Delete(IEnumerable dataSourceIds)
// verify phase
foreach (DataSourceId dataSourceId in dataSourceIds)
{
- Verify.ArgumentCondition(dataSourceId != null, "dataSourceIds", "The enumeration may not contain null values");
+ Verify.ArgumentCondition(dataSourceId != null, nameof(dataSourceIds), "The enumeration may not contain null values");
XmlDataTypeStore dataTypeStore = _xmlDataTypeStoresContainer.GetDataTypeStore(dataSourceId.InterfaceType);
var dataScope = dataSourceId.DataScopeIdentifier;
var culture = dataSourceId.LocaleScope;
var type = dataSourceId.InterfaceType;
+ var dataId = dataSourceId.DataId;
var dataTypeStoreScope = dataTypeStore.GetDataScope(dataScope, culture, type);
- if (dataTypeStore.Helper._DataIdType != dataSourceId.DataId.GetType())
+ if (dataTypeStore.Helper._DataIdType != dataId.GetType())
{
throw new ArgumentException("Only data ids from this provider is allowed to be deleted on on the provider");
}
@@ -231,7 +232,10 @@ public void Delete(IEnumerable dataSourceIds)
var index = fileRecord.RecordSet.Index;
- Verify.ArgumentCondition(index.ContainsKey(dataSourceId.DataId), "No data element corresponds to the given data id", "dataSourceIds");
+ if (!index.ContainsKey(dataId))
+ {
+ throw new ArgumentException($"Cannot delete a data item, no data element corresponds to the given data id: '{dataId.Serialize(null)}'; Type: '{type}'; DataScope: '{dataScope}'; Culture: '{culture}'", nameof(dataSourceIds));
+ }
validated.Add(dataSourceId, fileRecord);
}
From 1579efc54d75b701a3951279264811bddb9fee8e Mon Sep 17 00:00:00 2001
From: Dmitry Dzygin
Date: Wed, 18 Apr 2018 11:50:06 +0200
Subject: [PATCH 11/51] Fixing list of installed packages freezing for minutes
if connection to a package server times out
---
.../PackageElementProvider.cs | 135 ++++++------------
1 file changed, 43 insertions(+), 92 deletions(-)
diff --git a/Composite/Plugins/Elements/ElementProviders/PackageElementProvider/PackageElementProvider.cs b/Composite/Plugins/Elements/ElementProviders/PackageElementProvider/PackageElementProvider.cs
index 1fc54d17b0..37780a219c 100644
--- a/Composite/Plugins/Elements/ElementProviders/PackageElementProvider/PackageElementProvider.cs
+++ b/Composite/Plugins/Elements/ElementProviders/PackageElementProvider/PackageElementProvider.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using Composite.Data;
@@ -12,7 +12,6 @@
using Composite.C1Console.Workflow;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder;
-using Composite.Core.Extensions;
namespace Composite.Plugins.Elements.ElementProviders.PackageElementProvider
{
@@ -50,7 +49,7 @@ internal sealed class PackageElementProvider : IHooklessElementProvider, IAuxili
private static ResourceHandle AddPackageSourceIcon = GetIconHandle("package-add-source");
private static ResourceHandle DeletePackageSourceIcon = GetIconHandle("package-delete-source");
- private static PermissionType[] ActionPermissions = new PermissionType[] { PermissionType.Administrate, PermissionType.Configure };
+ private static PermissionType[] ActionPermissions = { PermissionType.Administrate, PermissionType.Configure };
private static readonly ActionGroup PrimaryActionGroup = new ActionGroup(ActionGroupPriority.PrimaryHigh);
@@ -113,37 +112,33 @@ private static void AddInstallLocalPackageAction(Element element)
public IEnumerable GetChildren(EntityToken entityToken, SearchToken seachToken)
{
- if ((entityToken is PackageElementProviderRootEntityToken))
+ if (entityToken is PackageElementProviderRootEntityToken)
{
return GetRootChildren(seachToken);
}
- if ((entityToken is PackageElementProviderAvailablePackagesFolderEntityToken))
+ if (entityToken is PackageElementProviderAvailablePackagesFolderEntityToken)
{
return GetAvailablePackagesFolderChildren(seachToken);
}
- if ((entityToken is PackageElementProviderAvailablePackagesGroupFolderEntityToken))
+ if (entityToken is PackageElementProviderAvailablePackagesGroupFolderEntityToken availableGroupEntityToken)
{
- var castedToken = entityToken as PackageElementProviderAvailablePackagesGroupFolderEntityToken;
-
- return GetAvailablePackageGroupFolderChildren(castedToken.GroupName, seachToken);
+ return GetAvailablePackageGroupFolderChildren(availableGroupEntityToken.GroupName, seachToken);
}
- if ((entityToken is PackageElementProviderInstalledPackageFolderEntityToken))
+ if (entityToken is PackageElementProviderInstalledPackageFolderEntityToken)
{
return GetInstalledPackageFolderChildren(seachToken);
}
- if ((entityToken is PackageElementProviderPackageSourcesFolderEntityToken))
+ if (entityToken is PackageElementProviderPackageSourcesFolderEntityToken)
{
return GetPackageSourcesFolderChildren(seachToken);
}
- if ((entityToken is PackageElementProviderInstalledPackageLocalPackagesFolderEntityToken))
+ if (entityToken is PackageElementProviderInstalledPackageLocalPackagesFolderEntityToken)
{
return GetInstalledLocalPackagesFolderChildren(seachToken);
}
- if ((entityToken is PackageElementProviderInstalledPackageGroupFolderEntityToken))
+ if (entityToken is PackageElementProviderInstalledPackageGroupFolderEntityToken installedGroupEntityToken)
{
- var castedToken = entityToken as PackageElementProviderInstalledPackageGroupFolderEntityToken;
-
- return GetInstalledPackageGroupFolderChildren(castedToken.GroupName, seachToken);
+ return GetInstalledPackageGroupFolderChildren(installedGroupEntityToken.GroupName, seachToken);
}
throw new InvalidOperationException("Unexpected entity token type: " + entityToken.GetType());
@@ -153,16 +148,16 @@ public IEnumerable GetChildren(EntityToken entityToken, SearchToken sea
public Dictionary> GetParents(IEnumerable entityTokens)
{
- Dictionary> result = new Dictionary>();
+ var result = new Dictionary>();
foreach (EntityToken entityToken in entityTokens)
{
- DataEntityToken dataEntityToken = entityToken as DataEntityToken;
+ var dataEntityToken = (DataEntityToken) entityToken ;
Type type = dataEntityToken.InterfaceType;
if (type != typeof(IPackageServerSource)) continue;
- PackageElementProviderPackageSourcesFolderEntityToken newEntityToken = new PackageElementProviderPackageSourcesFolderEntityToken();
+ var newEntityToken = new PackageElementProviderPackageSourcesFolderEntityToken();
result.Add(entityToken, new EntityToken[] { newEntityToken });
}
@@ -222,7 +217,7 @@ private IEnumerable GetRootChildren(SearchToken seachToken)
{
Label = StringResourceSystemFacade.GetString("Composite.Plugins.PackageElementProvider", "PackageSourcesFolderLabel"),
ToolTip = StringResourceSystemFacade.GetString("Composite.Plugins.PackageElementProvider", "PackageSourcesFolderToolTip"),
- HasChildren = DataFacade.GetData().Count() > 0,
+ HasChildren = DataFacade.GetData().Any(),
Icon = PackageSourcesClosedIcon,
OpenedIcon = PackageSourcesOpenedIcon
};
@@ -402,13 +397,15 @@ orderby a.Url
foreach (IPackageServerSource packageServerSource in packageServerSources)
{
- Element element = new Element(_context.CreateElementHandle(packageServerSource.GetDataEntityToken()));
- element.VisualData = new ElementVisualizedData
+ var element = new Element(_context.CreateElementHandle(packageServerSource.GetDataEntityToken()))
{
- Label = packageServerSource.Url,
- ToolTip = packageServerSource.Url,
- HasChildren = false,
- Icon = PackageSourceItemClosedIcon
+ VisualData = new ElementVisualizedData
+ {
+ Label = packageServerSource.Url,
+ ToolTip = packageServerSource.Url,
+ HasChildren = false,
+ Icon = PackageSourceItemClosedIcon
+ }
};
element.AddAction(new ElementAction(new ActionHandle(new WorkflowActionToken(WorkflowFacade.GetWorkflowType("Composite.Plugins.Elements.ElementProviders.PackageElementProvider.DeletePackageSourceWorkflow"), new PermissionType[] { PermissionType.Administrate })))
@@ -435,30 +432,41 @@ orderby a.Url
}
-
private IEnumerable GetInstalledLocalPackagesFolderChildren(SearchToken seachToken)
+ {
+ return GetInstalledPackagesElements(package => package.IsLocalInstalled);
+ }
+
+ private IEnumerable GetInstalledPackageGroupFolderChildren(string groupName, SearchToken seachToken)
+ {
+ return GetInstalledPackagesElements(package => package.GroupName == groupName && !package.IsLocalInstalled);
+ }
+
+
+ private IEnumerable GetInstalledPackagesElements(Predicate filter)
{
IEnumerable installedPackageInformations =
from info in PackageManager.GetInstalledPackages()
- where info.IsLocalInstalled
+ where filter(info)
orderby info.Name
select info;
- var allServerPackages = PackageSystemServices.GetAllAvailablePackages();
+ var serverPackagesPreviewUrls = PackageSystemServices.GetAllAvailablePackages()
+ .Where(p => !string.IsNullOrEmpty(p.ConsoleBrowserUrl))
+ .GroupBy(p => p.Id)
+ .ToDictionary(group => group.Key, group => group.First().ConsoleBrowserUrl);
- foreach (InstalledPackageInformation installedPackageInformation in installedPackageInformations)
+ foreach (var installedPackageInformation in installedPackageInformations)
{
- Element element = new Element(_context.CreateElementHandle(new PackageElementProviderInstalledPackageItemEntityToken(
+ var element = new Element(_context.CreateElementHandle(new PackageElementProviderInstalledPackageItemEntityToken(
installedPackageInformation.Id,
installedPackageInformation.GroupName,
installedPackageInformation.IsLocalInstalled,
installedPackageInformation.CanBeUninstalled)));
- PackageDescription serverPackageDescription = allServerPackages.Where(f => f.Id == installedPackageInformation.Id).FirstOrDefault();
-
- if (serverPackageDescription != null && !string.IsNullOrEmpty(serverPackageDescription.ConsoleBrowserUrl))
+ if (serverPackagesPreviewUrls.TryGetValue(installedPackageInformation.Id, out var previewUrl))
{
- element.PropertyBag.Add("BrowserUrl", serverPackageDescription.ConsoleBrowserUrl);
+ element.PropertyBag.Add("BrowserUrl", previewUrl);
element.PropertyBag.Add("BrowserToolingOn", "false");
}
@@ -506,63 +514,6 @@ private ResourceHandle GetIconForPackageItem(Guid packageId)
}
- private IEnumerable GetInstalledPackageGroupFolderChildren(string groupName, SearchToken seachToken)
- {
- IEnumerable installedPackageInformations =
- from info in PackageManager.GetInstalledPackages()
- where info.GroupName == groupName &&
- info.IsLocalInstalled == false
- orderby info.Name
- select info;
-
- var allServerPackages = PackageSystemServices.GetAllAvailablePackages();
-
- foreach (InstalledPackageInformation installedPackageInformation in installedPackageInformations)
- {
- Element element = new Element(_context.CreateElementHandle(new PackageElementProviderInstalledPackageItemEntityToken(
- installedPackageInformation.Id,
- installedPackageInformation.GroupName,
- installedPackageInformation.IsLocalInstalled,
- installedPackageInformation.CanBeUninstalled)));
-
- PackageDescription serverPackageDescription = allServerPackages.Where(f => f.Id == installedPackageInformation.Id).FirstOrDefault();
-
- if (serverPackageDescription != null && !string.IsNullOrEmpty(serverPackageDescription.ConsoleBrowserUrl))
- {
- element.PropertyBag.Add("BrowserUrl", serverPackageDescription.ConsoleBrowserUrl);
- element.PropertyBag.Add("BrowserToolingOn", "false");
- }
-
- element.VisualData = new ElementVisualizedData
- {
- Label = installedPackageInformation.Name,
- ToolTip = installedPackageInformation.Name,
- HasChildren = false,
- Icon = GetIconForPackageItem(installedPackageInformation.Id),
- };
-
- element.AddAction(new ElementAction(new ActionHandle(new WorkflowActionToken(WorkflowFacade.GetWorkflowType("Composite.Plugins.Elements.ElementProviders.PackageElementProvider.ViewInstalledPackageInfoWorkflow"), ActionPermissions)))
- {
- VisualData = new ActionVisualizedData
- {
- Label = StringResourceSystemFacade.GetString("Composite.Plugins.PackageElementProvider", "ViewInstalledInformationLabel"),
- ToolTip = StringResourceSystemFacade.GetString("Composite.Plugins.PackageElementProvider", "ViewInstalledInformationToolTip"),
- Icon = ViewInstalledInformationIcon,
- Disabled = false,
- ActionLocation = new ActionLocation
- {
- ActionType = ActionType.Edit,
- IsInFolder = false,
- IsInToolbar = true,
- ActionGroup = PrimaryActionGroup
- }
-
- }
- });
-
- yield return element;
- }
- }
From e2695fb47937ce41396d4f16c9e1920e093c7f91 Mon Sep 17 00:00:00 2001
From: Dmitry Dzygin
Date: Mon, 30 Apr 2018 15:47:29 +0200
Subject: [PATCH 12/51] Fixing incorrectly implemented 30 seconds delay on user
controls pre-loading and the other incorrectly implemented TimeSpan checks.
---
.../GlobalSettingsProvider/BuildinGlobalSettingsProvider.cs | 4 ++--
Composite/Core/Logging/DebugLoggingScope.cs | 4 ++--
Composite/Core/WebClient/BuildManagerHelper.cs | 4 ++--
Composite/Core/WebClient/XsltServices.cs | 4 ++--
4 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/Composite/Core/Configuration/BuildinPlugins/GlobalSettingsProvider/BuildinGlobalSettingsProvider.cs b/Composite/Core/Configuration/BuildinPlugins/GlobalSettingsProvider/BuildinGlobalSettingsProvider.cs
index ba4480c67b..5f6238a023 100644
--- a/Composite/Core/Configuration/BuildinPlugins/GlobalSettingsProvider/BuildinGlobalSettingsProvider.cs
+++ b/Composite/Core/Configuration/BuildinPlugins/GlobalSettingsProvider/BuildinGlobalSettingsProvider.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Threading;
using Composite.Core.Configuration.Plugins.GlobalSettingsProvider;
@@ -27,7 +27,7 @@ internal sealed class BuildinGlobalSettingsProvider : IGlobalSettingsProvider
private string _packageLicenseDirectory = "~/PackageLicenses";
private readonly ICachingSettings _cachingSettings = new BuildinCachingSettings();
private readonly List _nonProbableAssemblyNames = new List();
- private readonly int _consoleMessageQueueSecondToLive = TimeSpan.FromMinutes(10).Seconds;
+ private readonly int _consoleMessageQueueSecondToLive = (int) TimeSpan.FromMinutes(10).TotalSeconds;
private bool _enableDataTypesAutoUpdate = false;
private bool _broadcastConsoleElementChanges = true;
private bool _prettifyPublicMarkup = true;
diff --git a/Composite/Core/Logging/DebugLoggingScope.cs b/Composite/Core/Logging/DebugLoggingScope.cs
index bff952a137..7ba1323602 100644
--- a/Composite/Core/Logging/DebugLoggingScope.cs
+++ b/Composite/Core/Logging/DebugLoggingScope.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -87,7 +87,7 @@ private DebugLoggingScope(string scopeName, string actionInfo, bool logStart, Ti
public void Dispose()
{
int endTickCount = Environment.TickCount;
- if ((endTickCount - _startTickCount) >= _threshold.Milliseconds)
+ if ((endTickCount - _startTickCount) >= _threshold.TotalMilliseconds)
{
LoggingService.LogVerbose(_scopeName, string.Format("Finished {0} ({1} ms)", _actionInfo, endTickCount - _startTickCount));
}
diff --git a/Composite/Core/WebClient/BuildManagerHelper.cs b/Composite/Core/WebClient/BuildManagerHelper.cs
index f3fbde6023..687c6669a0 100644
--- a/Composite/Core/WebClient/BuildManagerHelper.cs
+++ b/Composite/Core/WebClient/BuildManagerHelper.cs
@@ -1,4 +1,4 @@
-using Composite.Core.IO;
+using Composite.Core.IO;
using System;
using System.Collections.Generic;
using System.Diagnostics;
@@ -41,7 +41,7 @@ private static void LoadAllControls()
try
{
const int waitSlice = 500;
- for (int i = 0; i < InitializationDelay.Milliseconds / waitSlice; i++)
+ for (int i = 0; i < InitializationDelay.TotalMilliseconds / waitSlice; i++)
{
if(IsRestarting) return;
Thread.Sleep(waitSlice);
diff --git a/Composite/Core/WebClient/XsltServices.cs b/Composite/Core/WebClient/XsltServices.cs
index ebf8d2e66e..d8f0335494 100644
--- a/Composite/Core/WebClient/XsltServices.cs
+++ b/Composite/Core/WebClient/XsltServices.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Linq;
@@ -25,7 +25,7 @@ public static XslCompiledTransform GetCompiledXsltTransform(string stylesheetPat
DateTime lastXsltFileWrite = C1File.GetLastWriteTime(stylesheetPath);
bool compiledVersionExists = _xsltLookup.ContainsKey(stylesheetPath);
- bool reloadFresh = (DateTime.Now - lastXsltFileWrite).Minutes < 30;
+ bool reloadFresh = (DateTime.Now - lastXsltFileWrite).TotalMinutes < 30;
if (compiledVersionExists == false || lastXsltFileWrite > _xsltFileTimestamps[stylesheetPath] || reloadFresh)
{
From 858ebefb3b4154a7a65f76174fe16434a82305ae Mon Sep 17 00:00:00 2001
From: Dmitry Dzygin
Date: Mon, 30 Apr 2018 16:57:37 +0200
Subject: [PATCH 13/51] Fixing setup failing randomly if the console for the
same website is already opened
---
Website/Composite/services/Setup/SetupService.asmx | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/Website/Composite/services/Setup/SetupService.asmx b/Website/Composite/services/Setup/SetupService.asmx
index 1fe90f9807..547a3e88e3 100644
--- a/Website/Composite/services/Setup/SetupService.asmx
+++ b/Website/Composite/services/Setup/SetupService.asmx
@@ -1,4 +1,4 @@
-<%@ WebService Language="C#" Class="Composite.Core.WebClient.Setup.SetupService" %>
+<%@ WebService Language="C#" Class="Composite.Core.WebClient.Setup.SetupService" %>
using System;
using System.IO;
@@ -146,20 +146,23 @@ namespace Composite.Core.WebClient.Setup
[WebMethod]
public bool SetUp(string setupDescriptionXML, string username, string email, string password, string language, string consolelanguage, bool newsletter)
{
- if (SystemSetupFacade.IsSystemFirstTimeInitialized) return true;
+ if (SystemSetupFacade.IsSystemFirstTimeInitialized || SystemSetupFacade.SetupIsRunning) return true;
SystemSetupFacade.SetupIsRunning = true;
- SystemSetupFacade.IsSystemFirstTimeInitialized = true;
try
{
return SetupServiceFacade.SetUp(setupDescriptionXML, username, password, email, language, consolelanguage, newsletter);
}
- catch(Exception ex)
+ catch (Exception ex)
{
Log.LogError(LogTitle, ex);
throw;
}
+ finally
+ {
+ SystemSetupFacade.IsSystemFirstTimeInitialized = true;
+ }
}
From c7cf4afc7fd41bb2c2bc8aae7420a6593208971c Mon Sep 17 00:00:00 2001
From: Marcus Wendt
Date: Fri, 4 May 2018 12:55:00 +0200
Subject: [PATCH 14/51] Fixed spelling in error message
---
Composite/C1Console/Trees/TreeElementAttachingProvider.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Composite/C1Console/Trees/TreeElementAttachingProvider.cs b/Composite/C1Console/Trees/TreeElementAttachingProvider.cs
index 5aed056b2f..d6c38b50ec 100644
--- a/Composite/C1Console/Trees/TreeElementAttachingProvider.cs
+++ b/Composite/C1Console/Trees/TreeElementAttachingProvider.cs
@@ -79,7 +79,7 @@ public IEnumerable GetAlternateElementLists(Enti
}
catch (Exception ex)
{
- LoggingService.LogError("TreeFacade", string.Format("Getting elements from the three '{0}' failed", tree.TreeId));
+ LoggingService.LogError("TreeFacade", string.Format("Getting elements from the tree '{0}' failed", tree.TreeId));
LoggingService.LogError("TreeFacade", ex);
Element errorElement = ShowErrorElementHelper.CreateErrorElement(
From e304b3621ad2945f85b5e45ac8a994d6583ad4c8 Mon Sep 17 00:00:00 2001
From: Dmitry Dzygin
Date: Wed, 9 May 2018 13:05:02 +0200
Subject: [PATCH 15/51] Function and template preview routes should return 403
response code if there's no logged in user
---
Composite/Core/WebClient/FunctionBoxRouteHandler.cs | 6 +++++-
Composite/Core/WebClient/TemplatePreviewRouteHandler.cs | 5 ++++-
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/Composite/Core/WebClient/FunctionBoxRouteHandler.cs b/Composite/Core/WebClient/FunctionBoxRouteHandler.cs
index a469bfa733..f68a4d7cbc 100644
--- a/Composite/Core/WebClient/FunctionBoxRouteHandler.cs
+++ b/Composite/Core/WebClient/FunctionBoxRouteHandler.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
@@ -12,6 +12,7 @@
using Composite.C1Console.Security;
using Composite.Core.Configuration;
using Composite.Core.Extensions;
+using Composite.Core.IO;
using Composite.Core.WebClient.Renderings;
@@ -45,6 +46,9 @@ public override async Task ProcessRequestAsync(HttpContext context)
{
if (!UserValidationFacade.IsLoggedIn())
{
+ context.Response.ContentType = MimeTypeInfo.Text;
+ context.Response.Write("No user logged in");
+ context.Response.StatusCode = 403;
return;
}
diff --git a/Composite/Core/WebClient/TemplatePreviewRouteHandler.cs b/Composite/Core/WebClient/TemplatePreviewRouteHandler.cs
index 0f2ac37eda..dbfd47bbbe 100644
--- a/Composite/Core/WebClient/TemplatePreviewRouteHandler.cs
+++ b/Composite/Core/WebClient/TemplatePreviewRouteHandler.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Web;
using System.Web.Routing;
using Composite.C1Console.Security;
@@ -34,6 +34,9 @@ public void ProcessRequest(HttpContext context)
{
if (!UserValidationFacade.IsLoggedIn())
{
+ context.Response.ContentType = MimeTypeInfo.Text;
+ context.Response.Write("No user logged in");
+ context.Response.StatusCode = 403;
return;
}
From f8adf51ffc53020cd2e7a93c535de42c1b4f80dd Mon Sep 17 00:00:00 2001
From: Dmitry Dzygin
Date: Tue, 15 May 2018 15:47:10 +0200
Subject: [PATCH 16/51] Refactoring and extra logging
---
Composite/Core/Logging/DebugLoggingScope.cs | 55 ++++++-------------
.../Core/WebClient/FunctionBoxRouteHandler.cs | 4 +-
.../WebClient/TemplatePreviewRouteHandler.cs | 14 ++---
.../PackageElementProvider.cs | 2 +-
.../Composite/services/Tree/TreeServices.asmx | 30 ++++++----
5 files changed, 45 insertions(+), 60 deletions(-)
diff --git a/Composite/Core/Logging/DebugLoggingScope.cs b/Composite/Core/Logging/DebugLoggingScope.cs
index 7ba1323602..b2c50cec93 100644
--- a/Composite/Core/Logging/DebugLoggingScope.cs
+++ b/Composite/Core/Logging/DebugLoggingScope.cs
@@ -1,7 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
using System.Diagnostics;
@@ -13,8 +10,6 @@ namespace Composite.Core.Logging
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public sealed class DebugLoggingScope : IDisposable
{
- private static IDisposable _noActionDisposable = new NoActionDisposable();
-
///
public static IDisposable CompletionTime( Type callingType, string actionInfo )
{
@@ -22,10 +17,8 @@ public static IDisposable CompletionTime( Type callingType, string actionInfo )
{
return new DebugLoggingScope(callingType.Name, actionInfo, false, TimeSpan.MinValue);
}
- else
- {
- return _noActionDisposable;
- }
+
+ return EmptyDisposable.Instance;
}
@@ -36,10 +29,8 @@ public static IDisposable CompletionTime(Type callingType, string actionInfo, Ti
{
return new DebugLoggingScope(callingType.Name, actionInfo, false, loggingThreshold);
}
- else
- {
- return _noActionDisposable;
- }
+
+ return EmptyDisposable.Instance;
}
@@ -50,24 +41,22 @@ public static IDisposable MethodInfoScope
{
if (RuntimeInformation.IsDebugBuild)
{
- StackTrace stackTrace = new StackTrace();
- StackFrame stackFrame = stackTrace.GetFrame(1);
- string scopeName = string.Format("{0}.{1}", stackFrame.GetMethod().DeclaringType.Name, stackFrame.GetMethod().Name);
+ var stackTrace = new StackTrace();
+ var method = stackTrace.GetFrame(1).GetMethod();
+ string scopeName = $"{method.DeclaringType.Name}.{method.Name}";
return new DebugLoggingScope(scopeName, "Method", true, TimeSpan.MinValue);
}
- else
- {
- return _noActionDisposable;
- }
+
+ return EmptyDisposable.Instance;
}
}
- private int _startTickCount;
- private string _scopeName;
- private string _actionInfo;
- private TimeSpan _threshold;
+ private readonly int _startTickCount;
+ private readonly string _scopeName;
+ private readonly string _actionInfo;
+ private readonly TimeSpan _threshold;
private DebugLoggingScope(string scopeName, string actionInfo, bool logStart, TimeSpan threshold)
{
@@ -76,9 +65,9 @@ private DebugLoggingScope(string scopeName, string actionInfo, bool logStart, Ti
_actionInfo = actionInfo;
_threshold = threshold;
- if (logStart==true)
+ if (logStart)
{
- LoggingService.LogVerbose(_scopeName, string.Format("Starting {0}", _actionInfo));
+ Log.LogVerbose(_scopeName, $"Starting {_actionInfo}");
}
}
@@ -87,9 +76,10 @@ private DebugLoggingScope(string scopeName, string actionInfo, bool logStart, Ti
public void Dispose()
{
int endTickCount = Environment.TickCount;
- if ((endTickCount - _startTickCount) >= _threshold.TotalMilliseconds)
+ var totalMilliseconds = endTickCount - _startTickCount;
+ if (totalMilliseconds >= _threshold.TotalMilliseconds)
{
- LoggingService.LogVerbose(_scopeName, string.Format("Finished {0} ({1} ms)", _actionInfo, endTickCount - _startTickCount));
+ Log.LogVerbose(_scopeName, $"Finished {_actionInfo} ({totalMilliseconds} ms)");
}
#if LeakCheck
GC.SuppressFinalize(this);
@@ -105,14 +95,5 @@ public void Dispose()
Composite.Core.Instrumentation.DisposableResourceTracer.RegisterFinalizerExecution(stack);
}
#endif
-
-
- private class NoActionDisposable : IDisposable
- {
- public void Dispose()
- {
- }
- }
-
}
}
diff --git a/Composite/Core/WebClient/FunctionBoxRouteHandler.cs b/Composite/Core/WebClient/FunctionBoxRouteHandler.cs
index f68a4d7cbc..d0df2f4806 100644
--- a/Composite/Core/WebClient/FunctionBoxRouteHandler.cs
+++ b/Composite/Core/WebClient/FunctionBoxRouteHandler.cs
@@ -40,7 +40,7 @@ public IHttpHandler GetHttpHandler(RequestContext requestContext)
internal class FunctionBoxHttpHandler : HttpTaskAsyncHandler
{
private const int MinCharsPerDescriptionLine = 55;
- private static readonly string LogTitle = typeof (FunctionBoxHttpHandler).Name;
+ private static readonly string LogTitle = nameof(FunctionBoxHttpHandler);
public override async Task ProcessRequestAsync(HttpContext context)
{
@@ -48,7 +48,7 @@ public override async Task ProcessRequestAsync(HttpContext context)
{
context.Response.ContentType = MimeTypeInfo.Text;
context.Response.Write("No user logged in");
- context.Response.StatusCode = 403;
+ context.Response.StatusCode = 401;
return;
}
diff --git a/Composite/Core/WebClient/TemplatePreviewRouteHandler.cs b/Composite/Core/WebClient/TemplatePreviewRouteHandler.cs
index dbfd47bbbe..3086adb894 100644
--- a/Composite/Core/WebClient/TemplatePreviewRouteHandler.cs
+++ b/Composite/Core/WebClient/TemplatePreviewRouteHandler.cs
@@ -36,7 +36,7 @@ public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = MimeTypeInfo.Text;
context.Response.Write("No user logged in");
- context.Response.StatusCode = 403;
+ context.Response.StatusCode = 401;
return;
}
@@ -52,10 +52,7 @@ public void ProcessRequest(HttpContext context)
Guid pageId = Guid.Parse(p);
- string filePath;
-
- PageTemplatePreview.PlaceholderInformation[] placeholders;
- PageTemplatePreview.GetPreviewInformation(context, pageId, templateId, out filePath, out placeholders);
+ PageTemplatePreview.GetPreviewInformation(context, pageId, templateId, out string filePath, out _);
Verify.That(C1File.Exists(filePath), "Preview file missing");
context.Response.ContentType = "image/png";
@@ -63,15 +60,12 @@ public void ProcessRequest(HttpContext context)
}
catch (Exception ex)
{
- Log.LogError(this.GetType().ToString(), ex.ToString());
+ Log.LogError(nameof(TemplatePreviewHttpHandler), ex);
throw;
}
}
- public bool IsReusable
- {
- get { return true; }
- }
+ public bool IsReusable => true;
}
}
diff --git a/Composite/Plugins/Elements/ElementProviders/PackageElementProvider/PackageElementProvider.cs b/Composite/Plugins/Elements/ElementProviders/PackageElementProvider/PackageElementProvider.cs
index 37780a219c..323a2e4dfc 100644
--- a/Composite/Plugins/Elements/ElementProviders/PackageElementProvider/PackageElementProvider.cs
+++ b/Composite/Plugins/Elements/ElementProviders/PackageElementProvider/PackageElementProvider.cs
@@ -304,7 +304,7 @@ orderby description.Name
{
Label = StringResourceSystemFacade.GetString("Composite.Plugins.PackageElementProvider", "ViewAvailableInformationLabel"),
ToolTip = StringResourceSystemFacade.GetString("Composite.Plugins.PackageElementProvider", "ViewAvailableInformationToolTip"),
- Icon = ViewInstalledInformationIcon,
+ Icon = ViewAvailableInformationIcon,
Disabled = false,
ActionLocation = new ActionLocation
{
diff --git a/Website/Composite/services/Tree/TreeServices.asmx b/Website/Composite/services/Tree/TreeServices.asmx
index 7802c2b50b..112fb43ac5 100644
--- a/Website/Composite/services/Tree/TreeServices.asmx
+++ b/Website/Composite/services/Tree/TreeServices.asmx
@@ -1,4 +1,4 @@
-<%@ WebService Language="C#" Class="Composite.Services.TreeServices" %>
+<%@ WebService Language="C#" Class="Composite.Services.TreeServices" %>
using System;
using System.Linq;
@@ -332,21 +332,31 @@ namespace Composite.Services
[WebMethod]
public ClientBrowserViewSettings GetBrowserUrlByEntityToken(string serializedEntityToken, bool showPublished)
{
-
- var entityToken = EntityTokenSerializer.Deserialize(serializedEntityToken);
-
- using (new DataScope(showPublished ? PublicationScope.Published : PublicationScope.Unpublished))
+ try
{
- var browserViewSettings = UrlToEntityTokenFacade.TryGetBrowserViewSettings(entityToken, showPublished);
+ var entityToken = EntityTokenSerializer.Deserialize(serializedEntityToken);
- if (browserViewSettings != null)
+ using (new DataScope(showPublished ? PublicationScope.Published : PublicationScope.Unpublished))
{
- return new ClientBrowserViewSettings { Url = browserViewSettings.Url, ToolingOn = browserViewSettings.ToolingOn };
+ var browserViewSettings = UrlToEntityTokenFacade.TryGetBrowserViewSettings(entityToken, showPublished);
+
+ if (browserViewSettings != null)
+ {
+ return new ClientBrowserViewSettings
+ {
+ Url = browserViewSettings.Url,
+ ToolingOn = browserViewSettings.ToolingOn
+ };
+ }
}
+ return null;
+ }
+ catch (Exception ex)
+ {
+ Log.LogError("GetBrowserUrlByEntityToken", ex);
+ throw;
}
-
- return null;
}
From df643608efdcb93ded40282455693245fa2cabca Mon Sep 17 00:00:00 2001
From: Dmitry Dzygin
Date: Tue, 22 May 2018 16:45:34 +0200
Subject: [PATCH 17/51] Fixing #563 incorrect resolved culture when accessing a
hostname if there's another culture with empty UrlMappingName
---
.../Routing/Pages/DefaultPageUrlProvider.cs | 49 ++++++++++++-------
1 file changed, 32 insertions(+), 17 deletions(-)
diff --git a/Composite/Plugins/Routing/Pages/DefaultPageUrlProvider.cs b/Composite/Plugins/Routing/Pages/DefaultPageUrlProvider.cs
index 03d982189c..3a0ec40b3a 100644
--- a/Composite/Plugins/Routing/Pages/DefaultPageUrlProvider.cs
+++ b/Composite/Plugins/Routing/Pages/DefaultPageUrlProvider.cs
@@ -301,33 +301,30 @@ public PageUrlData ParseUrl(string relativeUrl, UrlSpace urlSpace, out UrlKind u
var urlBuilder = new UrlBuilder(relativeUrl);
// Structure of a public url:
- // http://[/ApplicationVirtualPath]{/languageCode}[/Path to a page][/c1mode(unpublished)][/c1mode(relative)][UrlSuffix]{/PathInfo}
-
+ // http[s]://[/]{/}[/][/c1mode(unpublished)][/c1mode(relative)][][/]
string filePathAndPathInfo = HttpUtility.UrlDecode(urlBuilder.FullPath);
- filePathAndPathInfo = RemoveUrlMarkers(filePathAndPathInfo, urlSpace);
+ filePathAndPathInfo = RemoveForceRelativeUrlMarker(filePathAndPathInfo, urlSpace);
+ filePathAndPathInfo = ParseAndRemovePublicationScopeMarker(filePathAndPathInfo, out PublicationScope publicationScope);
+
+ CultureInfo locale;
string pathWithoutLanguageCode;
IHostnameBinding hostnameBinding = urlSpace.ForceRelativeUrls ? null : GetHostnameBindings().FirstOrDefault(b => b.Hostname == urlSpace.Hostname);
- CultureInfo locale = GetCultureInfo(filePathAndPathInfo, hostnameBinding, out pathWithoutLanguageCode);
- if (locale == null)
+ if (hostnameBinding != null && filePathAndPathInfo == "/")
{
- urlKind = UrlKind.Undefined;
- return null;
+ pathWithoutLanguageCode = "/";
+ locale = CultureInfo.GetCultureInfo(hostnameBinding.Culture);
}
-
- var publicationScope = PublicationScope.Published;
-
- if (filePathAndPathInfo.Contains(UrlMarker_Unpublished))
+ else
{
- publicationScope = PublicationScope.Unpublished;
-
- pathWithoutLanguageCode = pathWithoutLanguageCode.Replace(UrlMarker_Unpublished, string.Empty);
- if (pathWithoutLanguageCode == string.Empty)
+ locale = GetCultureInfo(filePathAndPathInfo, hostnameBinding, out pathWithoutLanguageCode);
+ if (locale == null)
{
- pathWithoutLanguageCode = "/";
+ urlKind = UrlKind.Undefined;
+ return null;
}
}
@@ -583,7 +580,7 @@ private static IEnumerable GetChildPages(Guid parentId)
}
- private static string RemoveUrlMarkers(string filePath, UrlSpace urlSpace)
+ private static string RemoveForceRelativeUrlMarker(string filePath, UrlSpace urlSpace)
{
if (urlSpace.ForceRelativeUrls && filePath.Contains(UrlMarker_RelativeUrl))
{
@@ -598,6 +595,24 @@ private static string RemoveUrlMarkers(string filePath, UrlSpace urlSpace)
return filePath;
}
+ private static string ParseAndRemovePublicationScopeMarker(string filePath, out PublicationScope publicationScope)
+ {
+ publicationScope = PublicationScope.Published;
+
+ if (filePath.Contains(UrlMarker_Unpublished))
+ {
+ publicationScope = PublicationScope.Unpublished;
+
+ filePath = filePath.Replace(UrlMarker_Unpublished, string.Empty);
+ if (filePath == string.Empty)
+ {
+ filePath = "/";
+ }
+ }
+
+ return filePath;
+ }
+
internal static CultureInfo GetCultureInfo(string requestPath, IHostnameBinding hostnameBinding, out string pathWithoutLanguageAndAppRoot)
{
int startIndex = requestPath.IndexOf('/', UrlUtils.PublicRootPath.Length) + 1;
From ab53bc489e46a9ea55213237c81b3d8e5bad3618 Mon Sep 17 00:00:00 2001
From: Taras Nakonechnyi
Date: Wed, 23 May 2018 16:22:44 +0300
Subject: [PATCH 18/51] Fix wrong validation browser access to the frame
document (#566)
Fix #561
---
.../source/top/ui/bindings/windows/PreviewWindowBinding.js | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/Website/Composite/scripts/source/top/ui/bindings/windows/PreviewWindowBinding.js b/Website/Composite/scripts/source/top/ui/bindings/windows/PreviewWindowBinding.js
index 5d4aa99b08..7034042203 100644
--- a/Website/Composite/scripts/source/top/ui/bindings/windows/PreviewWindowBinding.js
+++ b/Website/Composite/scripts/source/top/ui/bindings/windows/PreviewWindowBinding.js
@@ -283,9 +283,10 @@ PreviewWindowBinding.prototype.reset = function () {
if ( this._loadhandler != null ) {
if (this.getURL() != WindowBinding.DEFAULT_URL) {
- if (this.hasAccess(this._windowBinding)) {
+ var win = this.getContentWindow();
+ if (this.hasAccess(win)) {
DOMEvents.removeEventListener(
- this.getContentWindow(),
+ win,
DOMEvents.BEFOREUNLOAD,
this._loadhandler
);
From dca7f8ee71cb671729d01ac84251531898620430 Mon Sep 17 00:00:00 2001
From: Dmitry Dzygin
Date: Wed, 30 May 2018 13:21:44 +0200
Subject: [PATCH 19/51] Auto installed packages should be ordered
---
Composite/GlobalInitializerFacade.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Composite/GlobalInitializerFacade.cs b/Composite/GlobalInitializerFacade.cs
index 5965aa4030..4e3298908c 100644
--- a/Composite/GlobalInitializerFacade.cs
+++ b/Composite/GlobalInitializerFacade.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@@ -511,6 +511,7 @@ private static void DoAutoInstallPackages()
{
Log.LogVerbose(LogTitle, string.Format("Installing packages from: {0}", directory));
zipFiles.AddRange(C1Directory.GetFiles(directory, "*.zip")
+ .OrderBy(f => f)
.Select(f => new AutoInstallPackageInfo { FilePath = f, ToBeDeleted = true }));
}
else
From 2c94b05a1a34bea5ff35c725e0348d560b1bdeba Mon Sep 17 00:00:00 2001
From: Dmitry Dzygin
Date: Thu, 31 May 2018 15:55:23 +0200
Subject: [PATCH 20/51] Fixing a potential deadlock
---
Composite/C1Console/Workflow/WorkflowFacadeImpl.cs | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/Composite/C1Console/Workflow/WorkflowFacadeImpl.cs b/Composite/C1Console/Workflow/WorkflowFacadeImpl.cs
index 2f4f3504f0..d266f19814 100644
--- a/Composite/C1Console/Workflow/WorkflowFacadeImpl.cs
+++ b/Composite/C1Console/Workflow/WorkflowFacadeImpl.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@@ -501,8 +501,6 @@ private void SetWorkflowInstanceStatus(Guid instanceId, WorkflowInstanceStatus w
{
var resources = _resourceLocker.Resources;
- string identity = UserValidationFacade.IsLoggedIn() ? UserValidationFacade.GetUsername() : "(system process)";
-
Action releaseIdleWaitSemaphore = () =>
{
if (resources.WorkflowIdleWaitSemaphores.ContainsKey(instanceId))
@@ -539,9 +537,10 @@ private void SetWorkflowInstanceStatus(Guid instanceId, WorkflowInstanceStatus w
default:
throw new InvalidOperationException("This line should not be reachable.");
}
-
- Log.LogVerbose(LogTitle, "Workflow instance status changed to {0}. Id = {1}, User = {2}", workflowInstanceStatus, instanceId, identity);
}
+
+ string identity = UserValidationFacade.IsLoggedIn() ? UserValidationFacade.GetUsername() : "(system process)";
+ Log.LogVerbose(LogTitle, "Workflow instance status changed to {0}. Id = {1}, User = {2}", workflowInstanceStatus, instanceId, identity);
}
#endregion
From 83bde6509a8ec2bcdd216945ee034321078421a1 Mon Sep 17 00:00:00 2001
From: Dmitry Dzygin
Date: Thu, 31 May 2018 16:20:41 +0200
Subject: [PATCH 21/51] Code clean-up
---
.../C1Console/Workflow/WorkflowFacadeImpl.cs | 93 +++++--------------
.../Extensions/DictionaryExtensionMethods.cs | 32 ++++++-
Composite/GlobalInitializerFacade.cs | 78 +++++++---------
3 files changed, 86 insertions(+), 117 deletions(-)
diff --git a/Composite/C1Console/Workflow/WorkflowFacadeImpl.cs b/Composite/C1Console/Workflow/WorkflowFacadeImpl.cs
index d266f19814..3dfceec9f6 100644
--- a/Composite/C1Console/Workflow/WorkflowFacadeImpl.cs
+++ b/Composite/C1Console/Workflow/WorkflowFacadeImpl.cs
@@ -161,10 +161,9 @@ public WorkflowInstance CreateNewWorkflow(Type workflowType)
StringBuilder errors = new StringBuilder();
foreach (ValidationError error in exp.Errors)
{
-
errors.AppendLine(error.ToString());
}
- Log.LogError("WorkflowFacade", errors.ToString());
+ Log.LogError(LogTitle, errors.ToString());
throw;
}
}
@@ -182,14 +181,14 @@ public WorkflowInstance CreateNewWorkflow(Type workflowType, Dictionary attributes = workflowType.GetCustomAttributesRecursively().ToList();
- Verify.That(attributes.Count <= 1, "More than one attribute of type '{0}' found", typeof(AllowPersistingWorkflowAttribute).FullName);
+ Verify.That(attributes.Count <= 1, $"More than one attribute of type '{nameof(AllowPersistingWorkflowAttribute)}' found");
var persistenceType = attributes.Count == 1 ? attributes[0].WorkflowPersistingType : WorkflowPersistingType.Never;
@@ -337,10 +335,7 @@ private void RemovePersistingType(Guid instanceId)
{
using (_resourceLocker.Locker)
{
- if (_resourceLocker.Resources.WorkflowPersistingTypeDictionary.ContainsKey(instanceId))
- {
- _resourceLocker.Resources.WorkflowPersistingTypeDictionary.Remove(instanceId);
- }
+ _resourceLocker.Resources.WorkflowPersistingTypeDictionary.Remove(instanceId);
}
}
@@ -386,15 +381,8 @@ private void ReleaseAllLocks(Guid instanceId)
private bool HasEntityTokenLockAttribute(Type workflowType)
{
- bool hasEntityLockAttribute;
- if (!_hasEntityTokenLockAttributeCache.TryGetValue(workflowType, out hasEntityLockAttribute))
- {
- hasEntityLockAttribute = workflowType.GetCustomAttributesRecursively().Any();
-
- _hasEntityTokenLockAttributeCache.Add(workflowType, hasEntityLockAttribute);
- }
-
- return hasEntityLockAttribute;
+ return _hasEntityTokenLockAttributeCache.GetOrAdd(workflowType,
+ type => type.GetCustomAttributesRecursively().Any());
}
#endregion
@@ -407,14 +395,7 @@ public void SetFlowControllerServicesContainer(Guid instanceId, FlowControllerSe
using (_resourceLocker.Locker)
{
- if (!_resourceLocker.Resources.FlowControllerServicesContainers.ContainsKey(instanceId))
- {
- _resourceLocker.Resources.FlowControllerServicesContainers.Add(instanceId, flowControllerServicesContainer);
- }
- else
- {
- _resourceLocker.Resources.FlowControllerServicesContainers[instanceId] = flowControllerServicesContainer;
- }
+ _resourceLocker.Resources.FlowControllerServicesContainers[instanceId] = flowControllerServicesContainer;
}
}
@@ -442,10 +423,7 @@ public void RemoveFlowControllerServicesContainer(Guid instanceId)
using (_resourceLocker.Locker)
{
- if (_resourceLocker.Resources.FlowControllerServicesContainers.ContainsKey(instanceId))
- {
- _resourceLocker.Resources.FlowControllerServicesContainers.Remove(instanceId);
- }
+ _resourceLocker.Resources.FlowControllerServicesContainers.Remove(instanceId);
}
}
#endregion
@@ -481,11 +459,8 @@ public Semaphore WaitForIdleStatus(Guid instanceId)
{
return null;
}
-
- if (_resourceLocker.Resources.WorkflowIdleWaitSemaphores.ContainsKey(instanceId))
- {
- _resourceLocker.Resources.WorkflowIdleWaitSemaphores.Remove(instanceId);
- }
+
+ _resourceLocker.Resources.WorkflowIdleWaitSemaphores.Remove(instanceId);
Semaphore semaphore = new Semaphore(0, 1);
_resourceLocker.Resources.WorkflowIdleWaitSemaphores.Add(instanceId, semaphore);
@@ -503,9 +478,9 @@ private void SetWorkflowInstanceStatus(Guid instanceId, WorkflowInstanceStatus w
Action releaseIdleWaitSemaphore = () =>
{
- if (resources.WorkflowIdleWaitSemaphores.ContainsKey(instanceId))
+ if (resources.WorkflowIdleWaitSemaphores.TryGetValue(instanceId, out var semaphore))
{
- resources.WorkflowIdleWaitSemaphores[instanceId].Release();
+ semaphore.Release();
resources.WorkflowIdleWaitSemaphores.Remove(instanceId);
}
};
@@ -515,12 +490,7 @@ private void SetWorkflowInstanceStatus(Guid instanceId, WorkflowInstanceStatus w
case WorkflowInstanceStatus.Idle:
releaseIdleWaitSemaphore();
- if (!resources.WorkflowStatusDictionary.ContainsKey(instanceId) && newlyCreateOrLoaded)
- {
- resources.WorkflowStatusDictionary.Add(instanceId, WorkflowInstanceStatus.Idle);
- }
-
- resources.WorkflowStatusDictionary[instanceId] = WorkflowInstanceStatus.Idle;
+ resources.WorkflowStatusDictionary[instanceId] = WorkflowInstanceStatus.Idle;
PersistFormData(instanceId);
@@ -540,7 +510,7 @@ private void SetWorkflowInstanceStatus(Guid instanceId, WorkflowInstanceStatus w
}
string identity = UserValidationFacade.IsLoggedIn() ? UserValidationFacade.GetUsername() : "(system process)";
- Log.LogVerbose(LogTitle, "Workflow instance status changed to {0}. Id = {1}, User = {2}", workflowInstanceStatus, instanceId, identity);
+ Log.LogVerbose(LogTitle, $"Workflow instance status changed to {workflowInstanceStatus}. Id = {instanceId}, User = {identity}");
}
#endregion
@@ -717,7 +687,7 @@ public void FireCustomEvent(int customEventNumber, Guid instanceId, Dictionary 5) throw new ArgumentException("Number must be between 1 and 5", "customEventNumber");
+ if (customEventNumber < 1 || customEventNumber > 5) throw new ArgumentException("Number must be between 1 and 5", nameof(customEventNumber));
using (_resourceLocker.Locker)
{
@@ -802,10 +772,7 @@ private void RemoveIfExistFormData(Guid instanceId)
{
using (_resourceLocker.Locker)
{
- if (_resourceLocker.Resources.FormData.ContainsKey(instanceId))
- {
- _resourceLocker.Resources.FormData.Remove(instanceId);
- }
+ _resourceLocker.Resources.FormData.Remove(instanceId);
}
}
#endregion
@@ -1480,21 +1447,9 @@ public static void InitializeResources(Resources resources)
foreach (Guid instanceId in instanceIds)
{
- if (resources.WorkflowStatusDictionary.ContainsKey(instanceId))
- {
- resources.WorkflowStatusDictionary.Remove(instanceId);
- }
-
- if (resources.FormData.ContainsKey(instanceId))
- {
- resources.FormData.Remove(instanceId);
- }
-
- if (resources.FlowControllerServicesContainers.ContainsKey(instanceId))
- {
- resources.FlowControllerServicesContainers.Remove(instanceId);
- }
-
+ resources.WorkflowStatusDictionary.Remove(instanceId);
+ resources.FormData.Remove(instanceId);
+ resources.FlowControllerServicesContainers.Remove(instanceId);
resources.WorkflowPersistingTypeDictionary.Remove(instanceId);
}
diff --git a/Composite/Core/Extensions/DictionaryExtensionMethods.cs b/Composite/Core/Extensions/DictionaryExtensionMethods.cs
index 77872d9008..ceb284c4a8 100644
--- a/Composite/Core/Extensions/DictionaryExtensionMethods.cs
+++ b/Composite/Core/Extensions/DictionaryExtensionMethods.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
@@ -10,9 +10,8 @@ internal static class DictionaryExtensionMethods
{
public static TValue GetOrAdd(this IDictionary dictionary, TKey key, Func createValue)
{
- if (dictionary is ConcurrentDictionary)
+ if (dictionary is ConcurrentDictionary concurrentDictionary)
{
- var concurrentDictionary = dictionary as ConcurrentDictionary;
return concurrentDictionary.GetOrAdd(key, k => createValue());
}
@@ -36,6 +35,33 @@ public static TValue GetOrAdd(this IDictionary dicti
return value;
}
+ public static TValue GetOrAdd(this IDictionary dictionary, TKey key, Func createValue)
+ {
+ if (dictionary is ConcurrentDictionary concurrentDictionary)
+ {
+ return concurrentDictionary.GetOrAdd(key, createValue);
+ }
+
+ TValue value;
+ if (dictionary.TryGetValue(key, out value))
+ {
+ return value;
+ }
+
+ lock (dictionary)
+ {
+ if (dictionary.TryGetValue(key, out value))
+ {
+ return value;
+ }
+
+ value = createValue(key);
+ dictionary.Add(key, value);
+ }
+
+ return value;
+ }
+
public static List> SortByKeys(this Dictionary dictionary)
{
var result = dictionary.ToList();
diff --git a/Composite/GlobalInitializerFacade.cs b/Composite/GlobalInitializerFacade.cs
index 4e3298908c..37ca291adf 100644
--- a/Composite/GlobalInitializerFacade.cs
+++ b/Composite/GlobalInitializerFacade.cs
@@ -32,14 +32,14 @@
namespace Composite
{
- ///
+ ///
///
///
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public static class GlobalInitializerFacade
{
- private static readonly string LogTitle = "RGB(194, 252, 131)GlobalInitializerFacade";
- private static readonly string LogTitleNormal = "GlobalInitializerFacade";
+ private static readonly string LogTitle = "RGB(194, 252, 131)" + nameof(GlobalInitializerFacade);
+ private static readonly string LogTitleNormal = nameof(GlobalInitializerFacade);
private static bool _coreInitialized;
private static bool _initializing;
@@ -48,7 +48,7 @@ public static class GlobalInitializerFacade
private static bool _preInitHandlersRunning;
private static Exception _exceptionThrownDuringInitialization;
private static DateTime _exceptionThrownDuringInitializationTimeStamp;
- private static int _fatalErrorFlushCount = 0;
+ private static int _fatalErrorFlushCount;
private static readonly ReaderWriterLock _readerWriterLock = new ReaderWriterLock();
private static Thread _hookingFacadeThread; // This is used to wait on the the thread if a reinitialize is issued
private static Exception _hookingFacadeException; // This will hold the exception from the before the reinitialize was issued
@@ -57,13 +57,14 @@ public static class GlobalInitializerFacade
///
- public static bool DynamicTypesGenerated { get; private set; }
+ [Obsolete("Not used")]
+ public static bool DynamicTypesGenerated => false;
///
- public static bool SystemCoreInitializing { get { return _initializing; } }
+ public static bool SystemCoreInitializing => _initializing;
///
- public static bool SystemCoreInitialized { get { return _coreInitialized; } }
+ public static bool SystemCoreInitialized => _coreInitialized;
///
/// This is true during a total flush of the system (re-initialize).
@@ -96,15 +97,12 @@ public static void InitializeTheSystem()
{
Verify.That(!_preInitHandlersRunning, "DataFacade related methods should not be called in OnBeforeInitialize() method of a startup handler. Please move the code to OnInitialized() instead.");
- // if (AppDomain.CurrentDomain.Id == 3) SimpleDebug.AddEntry(string.Format("INITIALIZING {0} {1} {2}", Thread.CurrentThread.ManagedThreadId, _initializing, _coreInitialized));
-
-
if (_exceptionThrownDuringInitialization != null)
{
TimeSpan timeSpan = DateTime.Now - _exceptionThrownDuringInitializationTimeStamp;
if (timeSpan < TimeSpan.FromMinutes(5.0))
{
- Log.LogCritical(LogTitleNormal, "Exception recorded:" + timeSpan + " ago");
+ Log.LogCritical(LogTitleNormal, $"Exception recorded: {timeSpan} ago");
throw new Exception("Failed to initialize the system", _exceptionThrownDuringInitialization);
}
@@ -114,7 +112,7 @@ public static void InitializeTheSystem()
if (!_initializing && !_coreInitialized)
{
- using (GlobalInitializerFacade.CoreLockScope)
+ using (CoreLockScope)
{
if (!_initializing && !_coreInitialized)
{
@@ -298,7 +296,7 @@ private static void DoInitialize()
int executionTime = Environment.TickCount - startTime;
- Log.LogVerbose(LogTitle, "Done initializing of the system core. ({0} ms)".FormatWith(executionTime));
+ Log.LogVerbose(LogTitle, $"Done initializing of the system core. ({executionTime} ms)");
}
@@ -345,7 +343,7 @@ internal static void ReinitializeTheSystem(RunInWriterLockScopeDelegate runInWri
}
}
- using (GlobalInitializerFacade.CoreLockScope)
+ using (CoreLockScope)
{
IsReinitializingTheSystem = true;
@@ -384,7 +382,7 @@ internal static void ReinitializeTheSystem(RunInWriterLockScopeDelegate runInWri
private static void EnsureHookingFacade(object timeSpanToDelayStart)
{
// NOTE: Condition is made for unit-testing
- if (System.Web.Hosting.HostingEnvironment.IsHosted)
+ if (HostingEnvironment.IsHosted)
{
var kvp = (KeyValuePair)timeSpanToDelayStart;
_hookingFacadeException = null;
@@ -393,7 +391,7 @@ private static void EnsureHookingFacade(object timeSpanToDelayStart)
try
{
- using (GlobalInitializerFacade.CoreIsInitializedScope)
+ using (CoreIsInitializedScope)
{
using (ThreadDataManager.EnsureInitialize())
{
@@ -417,11 +415,7 @@ public static void WaitUntilAllIsInitialized()
{
using (CoreIsInitializedScope)
{
- Thread hookingFacadeThread = _hookingFacadeThread;
- if (hookingFacadeThread != null)
- {
- hookingFacadeThread.Join();
- }
+ _hookingFacadeThread?.Join();
}
}
@@ -432,7 +426,7 @@ public static void FatalResetTheSystem()
{
Log.LogWarning(LogTitle, "Unhandled error occurred, reinitializing the system!");
- ReinitializeTheSystem(delegate() { _fatalErrorFlushCount++; GlobalEventSystemFacade.FlushTheSystem(); });
+ ReinitializeTheSystem(delegate { _fatalErrorFlushCount++; GlobalEventSystemFacade.FlushTheSystem(); });
}
@@ -440,7 +434,7 @@ public static void FatalResetTheSystem()
///
public static void UninitializeTheSystem(RunInWriterLockScopeDelegate runInWriterLockScopeDelegate)
{
- using (GlobalInitializerFacade.CoreLockScope)
+ using (CoreLockScope)
{
using (new LogExecutionTime(LogTitle, "Uninitializing the system"))
{
@@ -509,14 +503,14 @@ private static void DoAutoInstallPackages()
string directory = PathUtil.Resolve(GlobalSettingsFacade.AutoPackageInstallDirectory);
if (C1Directory.Exists(directory))
{
- Log.LogVerbose(LogTitle, string.Format("Installing packages from: {0}", directory));
+ Log.LogVerbose(LogTitle, $"Installing packages from: {directory}");
zipFiles.AddRange(C1Directory.GetFiles(directory, "*.zip")
.OrderBy(f => f)
.Select(f => new AutoInstallPackageInfo { FilePath = f, ToBeDeleted = true }));
}
else
{
- Log.LogVerbose(LogTitle, string.Format("Auto install directory not found: {0}", directory));
+ Log.LogVerbose(LogTitle, $"Auto install directory not found: {directory}");
}
if (RuntimeInformation.IsDebugBuild)
@@ -524,7 +518,7 @@ private static void DoAutoInstallPackages()
string workflowTestDir = Path.Combine(PathUtil.Resolve(GlobalSettingsFacade.AutoPackageInstallDirectory), "WorkflowTesting");
if (C1Directory.Exists(workflowTestDir))
{
- Log.LogVerbose(LogTitle, string.Format("Installing packages from: {0}", workflowTestDir));
+ Log.LogVerbose(LogTitle, $"Installing packages from: {workflowTestDir}");
zipFiles.AddRange(C1Directory.GetFiles(workflowTestDir, "*.zip")
.OrderBy(f => f)
.Select(f => new AutoInstallPackageInfo { FilePath = f, ToBeDeleted = false }));
@@ -538,7 +532,7 @@ private static void DoAutoInstallPackages()
{
using (Stream zipFileStream = C1File.OpenRead(zipFile.FilePath))
{
- Log.LogVerbose(LogTitle, "Installing package: " + zipFile.FilePath);
+ Log.LogVerbose(LogTitle, $"Installing package: {zipFile.FilePath}");
PackageManagerInstallProcess packageManagerInstallProcess = PackageManager.Install(zipFileStream, true);
@@ -602,7 +596,7 @@ public static void ValidateIsOnlyCalledFromGlobalInitializerFacade(StackTrace st
if (methodInfo.DeclaringType != typeof(GlobalInitializerFacade))
{
- throw new SystemException(string.Format("The method {0} may only be called by the {1}", stackTrace.GetFrame(1).GetMethod(), typeof(GlobalInitializerFacade)));
+ throw new SystemException($"The method {methodInfo} may only be called by the {typeof(GlobalInitializerFacade)}");
}
}
@@ -625,7 +619,7 @@ private static void LogErrors(IEnumerable packa
private static void OnFlushEvent(FlushEventArgs args)
{
- using (GlobalInitializerFacade.CoreLockScope)
+ using (CoreLockScope)
{
_coreInitialized = false;
}
@@ -643,7 +637,7 @@ private static void OnFlushEvent(FlushEventArgs args)
///
public static void RunInWriterLockScope(RunInWriterLockScopeDelegate runInWriterLockScopeDelegate)
{
- using (GlobalInitializerFacade.CoreLockScope)
+ using (CoreLockScope)
{
runInWriterLockScopeDelegate();
}
@@ -658,9 +652,9 @@ internal static IDisposable CoreLockScope
get
{
var stackTrace = new StackTrace();
- StackFrame stackFrame = stackTrace.GetFrame(1);
- string lockSource = string.Format("{0}.{1}", stackFrame.GetMethod().DeclaringType.Name, stackFrame.GetMethod().Name);
- return new LockerToken(true, lockSource);
+ var method = stackTrace.GetFrame(1).GetMethod();
+
+ return new LockerToken(true, $"{method.DeclaringType.Name}.{method.Name}");
}
}
@@ -689,13 +683,7 @@ public static IDisposable CoreIsInitializedScope
/// Using this in a using-statement will ensure that the code is
/// executed AFTER any existing locks has been released.
///
- public static IDisposable CoreNotLockedScope
- {
- get
- {
- return new LockerToken();
- }
- }
+ public static IDisposable CoreNotLockedScope => new LockerToken();
private static void AcquireReaderLock()
@@ -747,8 +735,8 @@ private static void ReleaseWriterLock()
{
int threadId = Thread.CurrentThread.ManagedThreadId;
- if ((_threadLocking.WriterLocksPerThreadId[threadId] == 1) &&
- (_threadLocking.LockCookiesPerThreadId.ContainsKey(threadId)))
+ if (_threadLocking.WriterLocksPerThreadId[threadId] == 1 &&
+ _threadLocking.LockCookiesPerThreadId.ContainsKey(threadId))
{
LockCookie lockCookie = _threadLocking.LockCookiesPerThreadId[threadId];
@@ -803,7 +791,7 @@ internal LockerToken(bool writerLock, string lockSource)
return;
}
- Verify.ArgumentCondition(!lockSource.IsNullOrEmpty(), "lockSource", "Write locks must be obtained with a string identifying the source");
+ Verify.ArgumentCondition(!lockSource.IsNullOrEmpty(), nameof(lockSource), "Write locks must be obtained with a string identifying the source");
#region Logging the action
@@ -822,7 +810,7 @@ where sf.GetMethod().DeclaringType.Assembly.FullName.Contains("Composite.Test")
methodInfo = ", Method:" + stackFrame.GetMethod().Name;
}
}
- Log.LogVerbose(LogTitle, "Writer Lock Acquired (Managed Thread ID: {0}, Source: {1}{2})".FormatWith(Thread.CurrentThread.ManagedThreadId, lockSource, methodInfo));
+ Log.LogVerbose(LogTitle, $"Writer Lock Acquired (Managed Thread ID: {Thread.CurrentThread.ManagedThreadId}, Source: {lockSource}{methodInfo})");
#endregion Logging the action
@@ -860,7 +848,7 @@ where sf.GetMethod().DeclaringType.Assembly.FullName.Contains("Composite.Test")
methodInfo = ", Method: " + stackFrame.GetMethod().Name;
}
}
- Log.LogVerbose(LogTitle, "Writer Lock Releasing (Managed Thread ID: {0}, Source: {1}{2})".FormatWith(Thread.CurrentThread.ManagedThreadId, _lockSource, methodInfo));
+ Log.LogVerbose(LogTitle, $"Writer Lock Releasing (Managed Thread ID: {Thread.CurrentThread.ManagedThreadId}, Source: {_lockSource}{methodInfo})");
#endregion
From 67effa30b45570386b50d5b9e41baa5bb1c633eb Mon Sep 17 00:00:00 2001
From: Dmitry Dzygin
Date: Thu, 31 May 2018 17:06:05 +0200
Subject: [PATCH 22/51] UrlUtils - using '$' character instead of '|' when
encoding strings to avoid an ASP.NET exception when serving requests from
mobile devices
---
Composite/Core/WebClient/UrlUtils.cs | 29 +++++++++++++---------------
1 file changed, 13 insertions(+), 16 deletions(-)
diff --git a/Composite/Core/WebClient/UrlUtils.cs b/Composite/Core/WebClient/UrlUtils.cs
index 08c0e8e473..dca11c9d4b 100644
--- a/Composite/Core/WebClient/UrlUtils.cs
+++ b/Composite/Core/WebClient/UrlUtils.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;
@@ -18,8 +18,11 @@ namespace Composite.Core.WebClient
///
///
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
- public static class UrlUtils
- {
+ public static class UrlUtils
+ {
+ private const char UrlEncode_EscapeCharacter = '$';
+ private const char UrlEncode_SpaceReplacement = '-';
+
private static readonly string _adminFolderName = "Composite";
private static readonly string _renderersFolderName = "Renderers";
private static readonly string _applicationVirtualPath;
@@ -379,13 +382,10 @@ public static bool TryExpandGuid(string urlPart, out Guid guid)
///
public static string EncodeUrlInvalidCharacters(string value)
{
- const char separator = '|';
- const char spaceReplacement = '-';
-
var symbolsToEncode = new Hashset(new[] { '<', '>', '*', '%', '&', '\\', '?', '/' });
- symbolsToEncode.Add(separator);
- symbolsToEncode.Add(spaceReplacement);
+ symbolsToEncode.Add(UrlEncode_EscapeCharacter);
+ symbolsToEncode.Add(UrlEncode_SpaceReplacement);
var sb = new StringBuilder(value.Length);
@@ -400,31 +400,28 @@ public static string EncodeUrlInvalidCharacters(string value)
int code = (int)ch;
Verify.That(code <= 256, "1 byte ASCII code expected");
- sb.Append(separator).Append(code.ToString("X2"));
+ sb.Append(UrlEncode_EscapeCharacter).Append(code.ToString("X2"));
}
- return sb.Replace(' ', spaceReplacement).ToString();
+ return sb.Replace(' ', UrlEncode_SpaceReplacement).ToString();
}
///
public static string DecodeUrlInvalidCharacters(string value)
{
- const char separator = '|';
- const char spaceReplacement = '-';
-
var sb = new StringBuilder(value.Length);
- ;
+
for (int position = 0; position < value.Length; position++)
{
var ch = value[position];
- if (ch == spaceReplacement)
+ if (ch == UrlEncode_SpaceReplacement)
{
sb.Append(' ');
continue;
}
- if (ch == separator && position + 2 < value.Length)
+ if (ch == UrlEncode_EscapeCharacter && position + 2 < value.Length)
{
var hexCode = value.Substring(position + 1, 2).ToLowerInvariant();
const string hexadecimalDigits = "0123456789abcdef";
From 9ccf48bb9fd2e8d2ca1f07e80278b22e99400f4c Mon Sep 17 00:00:00 2001
From: Dmitry Dzygin
Date: Thu, 31 May 2018 17:37:10 +0200
Subject: [PATCH 23/51] Refactoring
---
.../FlowControllerServicesContainer.cs | 32 ++++----
.../FlowMediators/ActionExecutionMediator.cs | 26 +++---
.../FlowMediators/ActionExecutionService.cs | 21 +++--
.../FlowMediators/WebFlowUiMediator.cs | 27 +++----
Composite/Core/WebClient/UrlUtils.cs | 80 +++++++------------
5 files changed, 81 insertions(+), 105 deletions(-)
diff --git a/Composite/C1Console/Actions/FlowControllerServicesContainer.cs b/Composite/C1Console/Actions/FlowControllerServicesContainer.cs
index 10bbf44078..81de3e765e 100644
--- a/Composite/C1Console/Actions/FlowControllerServicesContainer.cs
+++ b/Composite/C1Console/Actions/FlowControllerServicesContainer.cs
@@ -1,16 +1,17 @@
using System;
using System.Collections.Generic;
+using Composite.Core.Extensions;
namespace Composite.C1Console.Actions
{
- ///
+ ///
///
///
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public sealed class FlowControllerServicesContainer
{
- private Dictionary> _services = new Dictionary>();
+ private readonly Dictionary> _services = new Dictionary>();
///
@@ -18,6 +19,15 @@ public FlowControllerServicesContainer()
{ }
+ ///
+ public FlowControllerServicesContainer(params IFlowControllerService[] services)
+ {
+ foreach (var service in services)
+ {
+ AddService(service);
+ }
+ }
+
// Creates a new service container and initialized it with the services from servicesContainerToClone.
///
public FlowControllerServicesContainer(FlowControllerServicesContainer servicesContainerToClone)
@@ -34,14 +44,7 @@ public void AddService(IFlowControllerService flowControllerService)
foreach (Type interfaceType in type.GetInterfaces())
{
- List
"+t],[/^(.*<\/p>)()$/,t+"$1"],[/\n/g,"
"]]),e.indexOf("
")!=-1&&(e=t+e)),s(e)}function c(){function t(e){var t,n,i,o=e.startContainer;if(t=e.getClientRects(),t.length)return t[0];if(e.collapsed&&1==o.nodeType){for(i=o.childNodes[S.startOffset];i&&3==i.nodeType&&!i.data.length;)i=i.nextSibling;if(i)return"BR"==i.tagName&&(n=r.doc.createTextNode("\ufeff"),i.parentNode.insertBefore(n,i),e=r.createRng(),e.setStartBefore(n),e.setEndAfter(n),t=e.getClientRects(),r.remove(n)),t.length?t[0]:void 0}}var n,r=a.dom,i=a.getBody(),o=a.dom.getViewPort(a.getWin()),s=o.y,l=20;if(S=a.selection.getRng(),a.inline&&(n=a.selection.getScrollContainer(),n&&n.scrollTop>0&&(s=n.scrollTop)),S.getClientRects){var c=t(S);if(c)l=s+(c.top-r.getPos(i).y);else{l=s;var u=S.startContainer;u&&(3==u.nodeType&&u.parentNode!=i&&(u=u.parentNode),1==u.nodeType&&(l=r.getPos(u,n||i).y))}}k=r.add(a.getBody(),"div",{id:"mcepastebin",contentEditable:!0,"data-mce-bogus":"all",style:"position: absolute; top: "+l+"px;width: 10px; height: 10px; overflow: hidden; opacity: 0"},A),(e.ie||e.gecko)&&r.setStyle(k,"left","rtl"==r.getStyle(i,"direction",!0)?65535:-65535),r.bind(k,"beforedeactivate focusin focusout",function(e){e.stopPropagation()}),k.focus(),a.selection.select(k,!0)}function u(){if(k){for(var e;e=a.dom.get("mcepastebin");)a.dom.remove(e),a.dom.unbind(e);S&&a.selection.setRng(S)}k=S=null}function d(){var e,t,n,r,i="";for(e=a.dom.select("div[id=mcepastebin]"),t=0;t0&&n.indexOf(B)==-1&&(t["text/plain"]=n)}if(e.types)for(var r=0;r')}else s('')}function b(e,t){function n(n){var r,i,o,a=!1;if(n)for(r=0;r0}function w(e){return n.metaKeyPressed(e)&&86==e.keyCode||e.shiftKey&&45==e.keyCode}function N(){function t(e,t,n){var i;return C(e,"text/html")?i=e["text/html"]:(i=d(),i==A&&(n=!0)),i=r.trimHtml(i),k&&k.firstChild&&"mcepastebin"===k.firstChild.id&&(n=!0),u(),i.length||(n=!0),n&&(i=C(e,"text/plain")&&i.indexOf("
")==-1?e["text/plain"]:r.innerText(i)),i==A?void(t||a.windowManager.alert("Please use Ctrl+V/Cmd+V keyboard shortcuts to paste contents.")):void(n?l(i):s(i))}function n(e){var t=e["text/plain"];return!!t&&0===t.indexOf("file://")}a.on("keydown",function(t){function n(e){w(e)&&!e.isDefaultPrevented()&&u()}if(w(t)&&!t.isDefaultPrevented()){if(_=t.shiftKey&&86==t.keyCode,_&&e.webkit&&navigator.userAgent.indexOf("Version/")!=-1)return;if(t.stopImmediatePropagation(),T=(new Date).getTime(),e.ie&&_)return t.preventDefault(),void a.fire("paste",{ieFake:!0});u(),c(),a.once("keyup",n),a.once("paste",function(){a.off("keyup",n)})}});var i=function(){return S||a.selection.getRng()};a.on("paste",function(n){var r=(new Date).getTime(),s=p(n),l=(new Date).getTime()-r,f=(new Date).getTime()-T-l<1e3,g="text"==E.pasteFormat||_;return _=!1,n.isDefaultPrevented()||y(n)?void u():!m(s)&&b(n,i())?void u():(f||n.preventDefault(),!e.ie||f&&!n.ieFake||(c(),a.dom.bind(k,"paste",function(e){e.stopPropagation()}),a.getDoc().execCommand("Paste",!1,null),s["text/html"]=d()),void(C(s,"text/html")?(n.preventDefault(),t(s,f,g)):o.setEditorTimeout(a,function(){t(s,f,g)},0)))}),a.on("dragstart dragend",function(e){R="dragstart"==e.type}),a.on("drop",function(e){var t,i;if(i=x(e),!e.isDefaultPrevented()&&!R&&(t=f(e.dataTransfer),(m(t)&&!n(t)||!b(e,i))&&i&&a.settings.paste_filter_drop!==!1)){var c=t["mce-internal"]||t["text/html"]||t["text/plain"];c&&(e.preventDefault(),o.setEditorTimeout(a,function(){a.undoManager.transact(function(){t["mce-internal"]&&a.execCommand("Delete"),a.selection.setRng(i),c=r.trimHtml(c),t["text/html"]?s(c):l(c)})}))}}),a.on("dragover dragend",function(e){a.settings.paste_data_images&&e.preventDefault()})}var k,S,_,E=this,T=0,R=!1,A="%MCEPASTEBIN%",B="data:text/mce-internal,",P=r.createIdGenerator("mceclip");E.pasteHtml=s,E.pasteText=l,E.pasteImageData=b,a.on("preInit",function(){N(),a.parser.addNodeFilter("img",function(t,n,r){function i(e){return e.data&&e.data.paste===!0}function o(t){t.attr("data-mce-object")||u===e.transparentSrc||t.remove()}function s(e){return 0===e.indexOf("webkit-fake-url")}function l(e){return 0===e.indexOf("data:")}if(!a.settings.paste_data_images&&i(r))for(var c=t.length;c--;){var u=t[c].attributes.map.src;u&&(s(u)?o(t[c]):!a.settings.allow_html_data_urls&&l(u)&&o(t[c]))}})})}}),r("tinymce/pasteplugin/WordFilter",["tinymce/util/Tools","tinymce/html/DomParser","tinymce/html/Schema","tinymce/html/Serializer","tinymce/html/Node","tinymce/pasteplugin/Utils"],function(e,t,n,r,i,o){function a(e){return/1&&a.attr("start",""+o),e.wrap(a)),e.name="li",s>u&&c&&c.lastChild.append(a),u=s,r(e),n(e,/^\u00a0+/),n(e,/^\s*([\u2022\u00b7\u00a7\u25CF]|\w+\.)/),n(e,/^\u00a0+/)}for(var a,c,u=1,d=[],f=e.firstChild;"undefined"!=typeof f&&null!==f;)if(d.push(f),f=f.walk(),null!==f)for(;"undefined"!=typeof f&&f.parent!==e;)f=f.walk();for(var p=0;p]+id="?docs-internal-[^>]*>/gi,""),h=h.replace(/
/gi,""),m=u.paste_retain_style_properties,m&&(g=e.makeMap(m.split(/[, ]/))),u.paste_enable_default_filters!==!1&&a(d.content)){d.wordContent=!0,h=o.filter(h,[//gi,/<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,[/<(\/?)s>/gi,"<$1strike>"],[/ /gi,"\xa0"],[/([\s\u00a0]*)<\/span>/gi,function(e,t){return t.length>0?t.replace(/./," ").slice(Math.floor(t.length/2)).split("").join("\xa0"):""}]]);var v=u.paste_word_valid_elements;v||(v="-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-h1,-h2,-h3,-h4,-h5,-h6,-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody");var b=new n({valid_elements:v,valid_children:"-li[p]"});e.each(b.elements,function(e){e.attributes["class"]||(e.attributes["class"]={},e.attributesOrder.push("class")),e.attributes.style||(e.attributes.style={},e.attributesOrder.push("style"))});var y=new t({},b);y.addAttributeFilter("style",function(e){for(var t,n=e.length;n--;)t=e[n],t.attr("style",p(t,t.attr("style"))),"span"==t.name&&t.parent&&!t.attributes.length&&t.unwrap()}),y.addAttributeFilter("class",function(e){for(var t,n,r=e.length;r--;)t=e[r],n=t.attr("class"),/^(MsoCommentReference|MsoCommentText|msoDel)$/i.test(n)&&t.remove(),t.attr("class",null)}),y.addNodeFilter("del",function(e){for(var t=e.length;t--;)e[t].remove()}),y.addNodeFilter("a",function(e){for(var t,n,r,i=e.length;i--;)if(t=e[i],n=t.attr("href"),r=t.attr("name"),n&&n.indexOf("#_msocom_")!=-1)t.remove();else if(n&&0===n.indexOf("file://")&&(n=n.split("#")[1],n&&(n="#"+n)),n||r){if(r&&!/^_?(?:toc|edn|ftn)/i.test(r)){t.unwrap();continue}t.attr({href:n,name:r})}else t.unwrap()});var x=y.parse(h);u.paste_convert_word_fake_lists!==!1&&f(x),d.content=new r({validate:u.validate},b).serialize(x)}})}return c.isWordContent=a,c}),r("tinymce/pasteplugin/Quirks",["tinymce/Env","tinymce/util/Tools","tinymce/pasteplugin/WordFilter","tinymce/pasteplugin/Utils"],function(e,t,n,r){return function(i){function o(e){i.on("BeforePastePreProcess",function(t){t.content=e(t.content)})}function a(e){i.on("PastePostProcess",function(t){e(t.node)})}function s(e){if(!n.isWordContent(e))return e;var o=[];t.each(i.schema.getBlockElements(),function(e,t){o.push(t)});var a=new RegExp("(?:
[\\s\\r\\n]+|
)*(<\\/?("+o.join("|")+")[^>]*>)(?:
[\\s\\r\\n]+|
)*","g");return e=r.filter(e,[[a,"$1"]]),e=r.filter(e,[[/
/g,"
"],[/
/g," "],[/
/g,"
"]])}function l(e){if(n.isWordContent(e))return e;var t=i.settings.paste_webkit_styles;if(i.settings.paste_remove_styles_if_webkit===!1||"all"==t)return e;if(t&&(t=t.split(/[, ]/)),t){var r=i.dom,o=i.selection.getNode();e=e.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi,function(e,n,i,a){var s=r.parseStyle(i,"span"),l={};if("none"===t)return n+a;for(var c=0;c]+) style="([^"]*)"([^>]*>)/gi,"$1$3");return e=e.replace(/(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi,function(e,t,n,r){return t+' style="'+n+'"'+r})}function c(e){i.$("a",e).find("font,u").each(function(e,t){i.dom.remove(t,!0)})}e.webkit&&o(l),e.ie&&(o(s),a(c))}}),r("tinymce/pasteplugin/Plugin",["tinymce/PluginManager","tinymce/pasteplugin/Clipboard","tinymce/pasteplugin/WordFilter","tinymce/pasteplugin/Quirks"],function(e,t,n,r){var i;e.add("paste",function(o){function a(){return i||o.settings.paste_plaintext_inform===!1}function s(){if("text"==c.pasteFormat)c.pasteFormat="html",o.fire("PastePlainTextToggle",{state:!1});else if(c.pasteFormat="text",o.fire("PastePlainTextToggle",{state:!0}),!a()){var e=o.translate("Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.");o.notificationManager.open({text:e,type:"info"}),i=!0}o.focus()}function l(){var e=this;e.active("text"===c.pasteFormat),o.on("PastePlainTextToggle",function(t){e.active(t.state)})}var c,u=this,d=o.settings;return/(^|[ ,])powerpaste([, ]|$)/.test(d.plugins)&&e.get("powerpaste")?void("undefined"!=typeof console&&console.log&&console.log("PowerPaste is incompatible with Paste plugin! Remove 'paste' from the 'plugins' option.")):(u.clipboard=c=new t(o),u.quirks=new r(o),u.wordFilter=new n(o),o.settings.paste_as_text&&(u.clipboard.pasteFormat="text"),d.paste_preprocess&&o.on("PastePreProcess",function(e){d.paste_preprocess.call(u,u,e)}),d.paste_postprocess&&o.on("PastePostProcess",function(e){d.paste_postprocess.call(u,u,e)}),o.addCommand("mceInsertClipboardContent",function(e,t){t.content&&u.clipboard.pasteHtml(t.content),t.text&&u.clipboard.pasteText(t.text)}),o.settings.paste_block_drop&&o.on("dragend dragover draggesture dragdrop drop drag",function(e){e.preventDefault(),e.stopPropagation()}),o.settings.paste_data_images||o.on("drop",function(e){var t=e.dataTransfer;t&&t.files&&t.files.length>0&&e.preventDefault()}),o.addCommand("mceTogglePlainTextPaste",s),o.addButton("pastetext",{icon:"pastetext",tooltip:"Paste as text",onclick:s,onPostRender:l}),void o.addMenuItem("pastetext",{text:"Paste as text",selectable:!0,active:c.pasteFormat,onclick:s,onPostRender:l}))})}),o(["tinymce/pasteplugin/Utils"])}(window);
\ No newline at end of file
diff --git a/Website/Composite/content/misc/editors/visualeditor/tinymce/plugins/table/plugin.min.js b/Website/Composite/content/misc/editors/visualeditor/tinymce/plugins/table/plugin.min.js
new file mode 100644
index 0000000000..f839dc1b95
--- /dev/null
+++ b/Website/Composite/content/misc/editors/visualeditor/tinymce/plugins/table/plugin.min.js
@@ -0,0 +1,2 @@
+!function(e,t){"use strict";function n(e,t){for(var n,r=[],a=0;a9)&&(t.hasChildNodes()||(t.innerHTML='
'))}var n=function(e){return function(t,n){t&&(n=parseInt(n,10),1===n||0===n?t.removeAttribute(e,1):t.setAttribute(e,n,1))}},r=function(e){return function(t){return parseInt(t.getAttribute(e)||1,10)}};return{setColSpan:n("colSpan"),setRowSpan:n("rowspan"),getColSpan:r("colSpan"),getRowSpan:r("rowSpan"),setSpanVal:function(e,t,r){n(t)(e,r)},getSpanVal:function(e,t){return r(t)(e)},paddCell:t}}),r("tinymce/tableplugin/SplitCols",["tinymce/util/Tools","tinymce/tableplugin/Utils"],function(e,t){var n=function(e,t,n){return e[n]?e[n][t]:null},r=function(e,t,r){var i=n(e,t,r);return i?i.elm:null},i=function(e,t,i,o){var a,s,l=0,c=r(e,t,i);for(a=i;(o>0?a=0)&&(s=n(e,t,a),c===s.elm);a+=o)l++;return l},o=function(e,t,n){for(var r,i=e[n],o=t;o'),!1},"childNodes"),t=v(t,!1),h(t),s(t,"rowSpan",1),s(t,"colSpan",1),i?t.appendChild(i):r.paddCell(t),t}function _(){var e,t=re.createRng();return o(re.select("tr",c),function(e){0===e.cells.length&&re.remove(e)}),0===re.select("tr",c).length?(t.setStartBefore(c),t.setEndBefore(c),ne.setRng(t),void re.remove(c)):(o(re.select("thead,tbody,tfoot",c),function(e){0===e.rows.length&&re.remove(e)}),m(),void(ee&&(e=Z[Math.min(Z.length-1,ee.y)],e&&(ne.select(e[Math.min(e.length-1,ee.x)].elm,!0),ne.collapse(!0)))))}function E(e,t,n,r){var i,o,a,s,l;for(i=Z[t][e].elm.parentNode,a=1;a<=n;a++)if(i=re.getNext(i,"tr")){for(o=e;o>=0;o--)if(l=Z[t+a][o].elm,l.parentNode==i){for(s=1;s<=r;s++)re.insertAfter(S(l),l);break}if(o==-1)for(s=1;s<=r;s++)i.insertBefore(S(i.cells[0]),i.cells[0])}}function T(){o(Z,function(e,t){o(e,function(e,n){var r,i,o;if(C(e)&&(e=e.elm,r=a(e,"colspan"),i=a(e,"rowspan"),r>1||i>1)){for(s(e,"rowSpan",1),s(e,"colSpan",1),o=0;on)&&r.push(e[i]);return r}function A(t){return e.grep(t,function(e){return e.real===!1})}function B(e){for(var t=[],n=0;n1&&(N=1),s(p,"colSpan",w),s(p,"rowSpan",N),f=l;f<=u;f++)for(d=a;d<=c;d++)Z[f]&&Z[f][d]&&(t=Z[f][d].elm,t!=p&&(h=e.grep(t.childNodes),o(h,function(e){p.appendChild(e)}),h.length&&(h=e.grep(p.childNodes),v=0,o(h,function(e){"BR"==e.nodeName&&v++0&&Z[n-1][l]&&(f=Z[n-1][l].elm,p=a(f,"rowSpan"),p>1)){s(f,"rowSpan",p+1);continue}}else if(p=a(r,"rowspan"),p>1){s(r,"rowSpan",p+1);continue}d=S(r),s(d,"colSpan",r.colSpan),u.appendChild(d),i=r}u.hasChildNodes()&&(e?c.parentNode.insertBefore(u,c):re.insertAfter(u,c))}}function I(e,t){t=t||w().length||1;for(var n=0;n1?s(n,"colSpan",t-1):re.remove(n)}),t.push(r))})}),_()}function U(){function e(e){var t,n;o(e.cells,function(e){var n=a(e,"rowSpan");n>1&&(s(e,"rowSpan",n-1),t=q(e),E(t.x,t.y,1,1))}),t=q(e.cells[0]),o(Z[t.y],function(e){var t;e=e.elm,e!=n&&(t=a(e,"rowSpan"),t<=1?re.remove(e):s(e,"rowSpan",t-1),n=e)})}var t;t=w(),f(c)&&t.length==c.rows.length||(o(t.reverse(),function(t){e(t)}),_())}function V(){var e=w();if(!f(c)||e.length!=c.rows.length)return re.remove(e),_(),e}function $(){var e=w();return o(e,function(t,n){e[n]=v(t,!0)}),e}function j(t,n){var r,a,l;t&&(r=i.splitAt(Z,ee.x,ee.y,n),a=r.row,e.each(r.cells,h),l=e.map(t,function(e){return e.cloneNode(!0)}),n||l.reverse(),o(l,function(e){var t,r,i=e.cells.length;for(g(e),t=0;te&&(e=i),r>t&&(t=r),n.real&&(o=n.colspan-1,a=n.rowspan-1,o&&i+o>e&&(e=i+o),a&&r+a>t&&(t=r+a)))})}),{x:e,y:t}}function K(e){var t,n,r,i,o,a,s,l,c,u;if(te=q(e),ee&&te){for(t=Math.min(ee.x,te.x),n=Math.min(ee.y,te.y),r=Math.max(ee.x,te.x),i=Math.max(ee.y,te.y),o=r,a=i,u=n;u<=i;u++)for(c=t;c<=r;c++)e=Z[u][c],e.real&&(s=e.colspan-1,l=e.rowspan-1,s&&c+s>o&&(o=c+s),l&&u+l>a&&(a=u+l));for(d(),u=n;u<=a;u++)for(c=t;c<=o;c++)Z[u][c]&&re.setAttrib(Z[u][c].elm,"data-mce-selected","1")}}function G(e,t){var n,r,i;n=q(e),r=n.y*Q+n.x;do{if(r+=t,i=b(r%Q,Math.floor(r/Q)),!i)break;if(i.elm!=e)return ne.select(i.elm,!0),re.isEmpty(i.elm)&&ne.collapse(!0),!0}while(i.elm==e);return!1}function J(t){if(ee){var n=i.splitAt(Z,ee.x,ee.y,t);e.each(n.cells,h)}}var Z,Q,ee,te,ne=l.selection,re=ne.dom;c=c||re.getParent(ne.getStart(!0),"table"),m(),u=u||re.getParent(ne.getStart(!0),"th,td"),u&&(ee=q(u),te=X(),u=b(ee.x,ee.y)),e.extend(this,{deleteTable:k,split:T,merge:M,insertRow:L,insertRows:I,insertCol:O,insertCols:H,splitCols:J,deleteCols:W,deleteRows:U,cutRows:V,copyRows:$,pasteRows:j,getPos:q,setStartCell:Y,setEndCell:K,moveRelIdx:G,refresh:m})}}),r("tinymce/tableplugin/Quirks",["tinymce/util/VK","tinymce/util/Delay","tinymce/Env","tinymce/util/Tools","tinymce/tableplugin/Utils"],function(e,t,n,r,i){var o=r.each,a=i.getSpanVal;return function(s){function l(){function n(n){function r(e,t){var r=e?"previousSibling":"nextSibling",o=s.dom.getParent(t,"tr"),a=o[r];if(a)return v(s,t,a,e),n.preventDefault(),!0;var l=s.dom.getParent(o,"table"),d=o.parentNode,f=d.nodeName.toLowerCase();if("tbody"===f||f===(e?"tfoot":"thead")){var p=i(e,l,d,"tbody");if(null!==p)return c(e,p,t)}return u(e,o,r,l)}function i(e,t,n,r){var i=s.dom.select(">"+r,t),o=i.indexOf(n);if(e&&0===o||!e&&o===i.length-1)return l(e,t);if(o===-1){var a="thead"===n.tagName.toLowerCase()?0:i.length-1;return i[a]}return i[o+(e?-1:1)]}function l(e,t){var n=e?"thead":"tfoot",r=s.dom.select(">"+n,t);return 0!==r.length?r[0]:null}function c(e,t,r){var i=d(t,e);return i&&v(s,r,i,e),n.preventDefault(),!0}function u(e,t,i,o){var a=o[i];if(a)return f(a),!0;var l=s.dom.getParent(o,"td,th");if(l)return r(e,l,n);var c=d(t,!e);return f(c),n.preventDefault(),!1}function d(e,t){var n=e&&e[t?"lastChild":"firstChild"];return n&&"BR"===n.nodeName?s.dom.getParent(n,"td,th"):n}function f(e){s.selection.setCursorLocation(e,0)}function p(){return x==e.UP||x==e.DOWN}function m(e){var t=e.selection.getNode(),n=e.dom.getParent(t,"tr");return null!==n}function g(e){for(var t=0,n=e;n.previousSibling;)n=n.previousSibling,t+=a(n,"colspan");return t}function h(e,t){var n=0,r=0;return o(e.children,function(e,i){if(n+=a(e,"colspan"),r=i,n>t)return!1}),r}function v(e,t,n,r){var i=g(s.dom.getParent(t,"td,th")),o=h(n,i),a=n.childNodes[o],l=d(a,r);f(l||a)}function b(e){var t=s.selection.getNode(),n=s.dom.getParent(t,"td,th"),r=s.dom.getParent(e,"td,th");return n&&n!==r&&y(n,r)}function y(e,t){return s.dom.getParent(e,"TABLE")===s.dom.getParent(t,"TABLE")}var x=n.keyCode;if(p()&&m(s)){var C=s.selection.getNode();t.setEditorTimeout(s,function(){b(C)&&r(!n.shiftKey&&x===e.UP,C,n)},0)}}s.on("KeyDown",function(e){n(e)})}function c(){function e(e,t){var n,r=t.ownerDocument,i=r.createRange();return i.setStartBefore(t),i.setEnd(e.endContainer,e.endOffset),n=r.createElement("body"),n.appendChild(i.cloneContents()),0===n.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi,"-").replace(/<[^>]+>/g,"").length}s.on("KeyDown",function(t){var n,r,i=s.dom;37!=t.keyCode&&38!=t.keyCode||(n=s.selection.getRng(),r=i.getParent(n.startContainer,"table"),r&&s.getBody().firstChild==r&&e(n,r)&&(n=i.createRng(),n.setStartBefore(r),n.setEndBefore(r),s.selection.setRng(n),t.preventDefault()))})}function u(){s.on("KeyDown SetContent VisualAid",function(){var e;for(e=s.getBody().lastChild;e;e=e.previousSibling)if(3==e.nodeType){if(e.nodeValue.length>0)break}else if(1==e.nodeType&&("BR"==e.tagName||!e.getAttribute("data-mce-bogus")))break;e&&"TABLE"==e.nodeName&&(s.settings.forced_root_block?s.dom.add(s.getBody(),s.settings.forced_root_block,s.settings.forced_root_block_attrs,n.ie&&n.ie<10?" ":'
'):s.dom.add(s.getBody(),"br",{"data-mce-bogus":"1"}))}),s.on("PreProcess",function(e){var t=e.node.lastChild;t&&("BR"==t.nodeName||1==t.childNodes.length&&("BR"==t.firstChild.nodeName||"\xa0"==t.firstChild.nodeValue))&&t.previousSibling&&"TABLE"==t.previousSibling.nodeName&&s.dom.remove(t)})}function d(){function e(e,t,n,r){var i,o,a,s=3,l=e.dom.getParent(t.startContainer,"TABLE");return l&&(i=l.parentNode),o=t.startContainer.nodeType==s&&0===t.startOffset&&0===t.endOffset&&r&&("TR"==n.nodeName||n==i),a=("TD"==n.nodeName||"TH"==n.nodeName)&&!r,o||a}function t(){var t=s.selection.getRng(),n=s.selection.getNode(),r=s.dom.getParent(t.startContainer,"TD,TH");if(e(s,t,n,r)){r||(r=n);for(var i=r.lastChild;i.lastChild;)i=i.lastChild;3==i.nodeType&&(t.setEnd(i,i.data.length),s.selection.setRng(t))}}s.on("KeyDown",function(){t()}),s.on("MouseDown",function(e){2!=e.button&&t()})}function f(){function t(e){s.selection.select(e,!0),s.selection.collapse(!0)}function n(e){s.$(e).empty(),i.paddCell(e)}s.on("keydown",function(i){if((i.keyCode==e.DELETE||i.keyCode==e.BACKSPACE)&&!i.isDefaultPrevented()){var o,a,l,c;if(o=s.dom.getParent(s.selection.getStart(),"table")){if(a=s.dom.select("td,th",o),l=r.grep(a,function(e){return!!s.dom.getAttrib(e,"data-mce-selected")}),0===l.length)return c=s.dom.getParent(s.selection.getStart(),"td,th"),void(s.selection.isCollapsed()&&c&&s.dom.isEmpty(c)&&(i.preventDefault(),n(c),t(c)));i.preventDefault(),s.undoManager.transact(function(){a.length==l.length?s.execCommand("mceTableDelete"):(r.each(l,n),t(l[0]))})}}})}function p(){var t=function(e){return e&&"CAPTION"==e.nodeName&&"TABLE"==e.parentNode.nodeName},r=function(e,t){var n=s.selection.getRng(),r=e.ownerDocument.createTextNode("\xa0");n.startOffset?e.insertBefore(r,e.firstChild):e.appendChild(r),t&&(s.selection.select(r,!0),s.selection.collapse(!0))},i=function(t){return(t.keyCode==e.DELETE||t.keyCode==e.BACKSPACE)&&!t.isDefaultPrevented()},o=function(e){return e.firstChild===e.lastChild&&e.firstChild},a=function(e){return e&&3===e.nodeType},l=function(e){var t=o(e);return a(t)&&1===t.data.length?t.data:null},c=function(e){var t=o(e),n=l(e);return t&&!a(t)||n&&!d(n)},u=function(e){return s.dom.isEmpty(e)||d(l(e))},d=function(e){return"\xa0"===e};s.on("keydown",function(e){if(i(e)){var o=s.dom.getParent(s.selection.getStart(),"caption");t(o)&&(n.ie&&(s.selection.isCollapsed()?c(o)&&r(o):(s.undoManager.transact(function(){s.execCommand("Delete"),u(o)&&r(o,!0)}),e.preventDefault())),u(o)&&e.preventDefault())}})}f(),p(),n.webkit&&(l(),d()),n.gecko&&(c(),u()),n.ie>9&&(c(),u())}}),r("tinymce/tableplugin/CellSelection",["tinymce/tableplugin/TableGrid","tinymce/dom/TreeWalker","tinymce/util/Tools"],function(e,t,n){return function(r,i){function o(e){r.getBody().style.webkitUserSelect="",(e||g)&&(r.$("td[data-mce-selected],th[data-mce-selected]").removeAttr("data-mce-selected"),g=!1)}function a(e,t){return!(!e||!t)&&e===m.getParent(t,"table")}function s(t){var n,o,s=t.target;if(!f&&!p&&s!==d&&(d=s,u&&c)){if(o=m.getParent(s,"td,th"),a(u,o)||(o=m.getParent(u,"td,th")),c===o&&!g)return;if(i(!0),a(u,o)){t.preventDefault(),l||(l=new e(r,u,c),r.getBody().style.webkitUserSelect="none"),l.setEndCell(o),g=!0,n=r.selection.getSel();try{n.removeAllRanges?n.removeAllRanges():n.empty()}catch(e){}}}}var l,c,u,d,f,p,m=r.dom,g=!0,h=function(){c=l=u=d=null,i(!1)};return r.on("SelectionChange",function(e){g&&e.stopImmediatePropagation()},!0),r.on("MouseDown",function(e){2==e.button||f||p||(o(),c=m.getParent(e.target,"td,th"),u=m.getParent(c,"table"))}),r.on("mouseover",s),r.on("remove",function(){m.unbind(r.getDoc(),"mouseover",s),o()}),r.on("MouseUp",function(){function e(e,r){var o=new t(e,e);do{if(3==e.nodeType&&0!==n.trim(e.nodeValue).length)return void(r?i.setStart(e,0):i.setEnd(e,e.nodeValue.length));if("BR"==e.nodeName)return void(r?i.setStartBefore(e):i.setEndBefore(e))}while(e=r?o.next():o.prev())}var i,o,a,s,u,d=r.selection;if(c){if(l&&(r.getBody().style.webkitUserSelect=""),o=m.select("td[data-mce-selected],th[data-mce-selected]"),o.length>0){i=m.createRng(),s=o[0],i.setStartBefore(s),i.setEndAfter(s),e(s,1),a=new t(s,m.getParent(o[0],"table"));do if("TD"==s.nodeName||"TH"==s.nodeName){if(!m.getAttrib(s,"data-mce-selected"))break;u=s}while(s=a.next());e(u),d.setRng(i)}r.nodeChanged(),h()}}),r.on("KeyUp Drop SetContent",function(e){o("setcontent"==e.type),h(),f=!1}),r.on("ObjectResizeStart ObjectResized",function(e){f="objectresized"!=e.type}),r.on("dragstart",function(){p=!0}),r.on("drop dragend",function(){p=!1}),{clear:o}}}),r("tinymce/tableplugin/Dialogs",["tinymce/util/Tools","tinymce/Env"],function(e,t){var n=e.each;return function(r){function i(){var e=r.settings.color_picker_callback;if(e)return function(){var t=this;e.call(r,function(e){t.value(e).fire("change")},t.value())}}function o(e){return{title:"Advanced",type:"form",defaults:{onchange:function(){d(e,this.parents().reverse()[0],"style"==this.name())}},items:[{label:"Style",name:"style",type:"textbox"},{type:"form",padding:0,formItemDefaults:{layout:"grid",alignH:["start","right"]},defaults:{size:7},items:[{label:"Border color",type:"colorbox",name:"borderColor",onaction:i()},{label:"Background color",type:"colorbox",name:"backgroundColor",onaction:i()}]}]}}function a(e){return e?e.replace(/px$/,""):""}function s(e){return/^[0-9]+$/.test(e)&&(e+="px"),e}function l(e){n("left center right".split(" "),function(t){r.formatter.remove("align"+t,{},e)})}function c(e){n("top middle bottom".split(" "),function(t){r.formatter.remove("valign"+t,{},e)})}function u(t,n,r){function i(t,r){return r=r||[],e.each(t,function(e){var t={text:e.text||e.title};e.menu?t.menu=i(e.menu):(t.value=e.value,n&&n(t)),r.push(t)}),r}return i(t,r||[])}function d(e,t,n){var r=t.toJSON(),i=e.parseStyle(r.style);n?(t.find("#borderColor").value(i["border-color"]||"")[0].fire("change"),t.find("#backgroundColor").value(i["background-color"]||"")[0].fire("change")):(i["border-color"]=r.borderColor,i["background-color"]=r.backgroundColor),t.find("#style").value(e.serializeStyle(e.parseStyle(e.serializeStyle(i))))}function f(e,t,n){var r=e.parseStyle(e.getAttrib(n,"style"));r["border-color"]&&(t.borderColor=r["border-color"]),r["background-color"]&&(t.backgroundColor=r["background-color"]),t.style=e.serializeStyle(r)}function p(e,t,r){var i=e.parseStyle(e.getAttrib(t,"style"));n(r,function(e){i[e.name]=e.value}),e.setAttrib(t,"style",e.serializeStyle(e.parseStyle(e.serializeStyle(i))))}var m=this;m.tableProps=function(){m.table(!0)},m.table=function(i){function c(){function n(e,t,r){if("TD"===e.tagName||"TH"===e.tagName)C.setStyle(e,t,r);else if(e.children)for(var i=0;i',g.insertBefore(i,g.firstChild)),l(g),w.align&&r.formatter.apply("align"+w.align,{},g),r.focus(),r.addVisual()})}function m(e,t){function n(e,n){for(var r=0;r1?g={width:"",height:"",scope:"","class":"",align:"",style:"",type:m.nodeName.toLowerCase()}:(g={width:a(v.getStyle(m,"width")||v.getAttrib(m,"width")),height:a(v.getStyle(m,"height")||v.getAttrib(m,"height")),scope:v.getAttrib(m,"scope"),"class":v.getAttrib(m,"class")},g.type=m.nodeName.toLowerCase(),n("left center right".split(" "),function(e){r.formatter.matchNode(m,"align"+e)&&(g.align=e)}),n("top middle bottom".split(" "),function(e){r.formatter.matchNode(m,"valign"+e)&&(g.valign=e)}),f(v,g,m)),r.settings.table_cell_class_list&&(h={name:"class",type:"listbox",label:"Class",values:u(r.settings.table_cell_class_list,function(e){e.value&&(e.textStyle=function(){return r.formatter.getCssText({block:"td",classes:[e.value]})})})});var y={type:"form",layout:"flex",direction:"column",labelGapCalc:"children",padding:0,items:[{type:"form",layout:"grid",columns:2,labelGapCalc:!1,padding:0,defaults:{type:"textbox",maxWidth:50},items:[{label:"Width",name:"width"},{label:"Height",name:"height"},{label:"Cell type",name:"type",type:"listbox",text:"None",minWidth:90,maxWidth:null,values:[{text:"Cell",value:"td"},{text:"Header cell",value:"th"}]},{label:"Scope",name:"scope",type:"listbox",text:"None",minWidth:90,maxWidth:null,values:[{text:"None",value:""},{text:"Row",value:"row"},{text:"Column",value:"col"},{text:"Row group",value:"rowgroup"},{text:"Column group",value:"colgroup"}]},{label:"H Align",name:"align",type:"listbox",text:"None",minWidth:90,maxWidth:null,values:[{text:"None",value:""},{text:"Left",value:"left"},{text:"Center",value:"center"},{text:"Right",value:"right"}]},{label:"V Align",name:"valign",type:"listbox",text:"None",minWidth:90,maxWidth:null,values:[{text:"None",value:""},{text:"Top",value:"top"},{text:"Middle",value:"middle"},{text:"Bottom",value:"bottom"}]}]},h]};r.settings.table_cell_advtab!==!1?r.windowManager.open({title:"Cell properties",bodyType:"tabpanel",data:g,body:[{title:"General",type:"form",items:y},o(v)],onsubmit:p}):r.windowManager.open({title:"Cell properties",data:g,body:y,onsubmit:p})}},m.row=function(){function t(e,t,n){(1===x.length||n)&&y.setAttrib(e,t,n)}function i(e,t,n){(1===x.length||n)&&y.setStyle(e,t,n)}function c(){var o,a,c;d(y,this),v=e.extend(v,this.toJSON()),r.undoManager.transact(function(){var e=v.type;n(x,function(n){t(n,"scope",v.scope),t(n,"style",v.style),t(n,"class",v["class"]),i(n,"height",s(v.height)),e!==n.parentNode.nodeName.toLowerCase()&&(o=y.getParent(n,"table"),a=n.parentNode,c=y.select(e,o)[0],c||(c=y.create(e),o.firstChild?o.insertBefore(c,o.firstChild):o.appendChild(c)),c.appendChild(n),a.hasChildNodes()||y.remove(a)),1===x.length&&l(n),v.align&&r.formatter.apply("align"+v.align,{},n)}),r.focus()})}var p,m,g,h,v,b,y=r.dom,x=[];p=r.dom.getParent(r.selection.getStart(),"table"),m=r.dom.getParent(r.selection.getStart(),"td,th"),n(p.rows,function(e){n(e.cells,function(t){if(y.getAttrib(t,"data-mce-selected")||t==m)return x.push(e),!1})}),g=x[0],g&&(x.length>1?v={height:"",scope:"","class":"",align:"",type:g.parentNode.nodeName.toLowerCase()}:(v={height:a(y.getStyle(g,"height")||y.getAttrib(g,"height")),scope:y.getAttrib(g,"scope"),"class":y.getAttrib(g,"class")},v.type=g.parentNode.nodeName.toLowerCase(),n("left center right".split(" "),function(e){r.formatter.matchNode(g,"align"+e)&&(v.align=e)}),f(y,v,g)),r.settings.table_row_class_list&&(h={name:"class",type:"listbox",label:"Class",values:u(r.settings.table_row_class_list,function(e){e.value&&(e.textStyle=function(){return r.formatter.getCssText({block:"tr",classes:[e.value]})})})}),b={type:"form",columns:2,padding:0,defaults:{type:"textbox"},items:[{type:"listbox",name:"type",label:"Row type",text:"Header",maxWidth:null,values:[{text:"Header",value:"thead"},{text:"Body",value:"tbody"},{text:"Footer",value:"tfoot"}]},{type:"listbox",name:"align",label:"Alignment",text:"None",maxWidth:null,values:[{text:"None",value:""},{text:"Left",value:"left"},{text:"Center",value:"center"},{text:"Right",value:"right"}]},{label:"Height",name:"height"},h]},r.settings.table_row_advtab!==!1?r.windowManager.open({title:"Row properties",data:v,bodyType:"tabpanel",body:[{title:"General",type:"form",items:b},o(y)],onsubmit:c}):r.windowManager.open({title:"Row properties",data:v,body:b,onsubmit:c}))}}}),r("tinymce/tableplugin/ResizeBars",["tinymce/util/Tools","tinymce/util/VK"],function(e,n){var r;return function(i){function o(e,t){return{index:e,y:i.dom.getPos(t).y}}function a(e,t){return{index:e,y:i.dom.getPos(t).y+t.offsetHeight}}function s(e,t){return{index:e,x:i.dom.getPos(t).x}}function l(e,t){return{index:e,x:i.dom.getPos(t).x+t.offsetWidth}}function c(){var e=i.getBody().dir;return"rtl"===e}function u(){return i.inline}function d(){return u?i.getBody().ownerDocument.body:i.getBody()}function f(e,t){return c()?l(e,t):s(e,t)}function p(e,t){return c()?s(e,t):l(e,t)}function m(e,t){return g(e,"width")/g(t,"width")*100}function g(e,t){var n=i.dom.getStyle(e,t,!0),r=parseInt(n,10);return r}function h(e){var t=g(e,"width"),n=g(e.parentElement,"width");return t/n*100}function v(e,t){var n=g(e,"width");return t/n*100}function b(e,t){var n=g(e.parentElement,"width");return t/n*100}function y(e,t,n){for(var r=[],i=1;i0?y(o,a,r):[],u=s.length>0?y(f,p,s):[];N(c,e.offsetWidth,l),k(u,e.offsetHeight,l)}function P(e,t,n,r){if(t<0||t>=e.length-1)return"";var i=e[t];if(i)i={value:i,delta:0};else for(var o=e.slice(0,t).reverse(),a=0;a0?i:o}function L(t,n,r){for(var i=R(t),o=e.map(i,function(e){return f(e.colIndex,e.element).x}),a=[],s=0;s1?P(o,s):M(i[s].element,n,r);c=c?c:we,a.push(c)}return a}function I(e){var t=D(e,"height"),n=parseInt(t,10);return V(t)&&(n=0),!isNaN(n)&&n>0?n:g(e,"height")}function O(t){for(var n=A(t),r=e.map(n,function(e){return o(e.rowIndex,e.element).y}),i=[],a=0;a1?P(r,a):I(n[a].element);l=l?l:Ne,i.push(l)}return i}function H(t,n,r,i,o){function a(t){return e.map(t,function(){return 0})}function s(){var e;if(o)e=[100-d[0]];else{var t=Math.max(i,d[0]+r);e=[t-d[0]]}return e}function l(e,t){var n,o=a(d.slice(0,e)),s=a(d.slice(t+1));if(r>=0){var l=Math.max(i,d[t]-r);n=o.concat([r,l-d[t]]).concat(s)}else{var c=Math.max(i,d[e]+r),u=d[e]-c;n=o.concat([c-d[e],u]).concat(s)}return n}function c(e,t){var n,o=a(d.slice(0,t));if(r>=0)n=o.concat([r]);else{var s=Math.max(i,d[t]+r);n=o.concat([s-d[t]])}return n}var u,d=t.slice(0);return u=0===t.length?[]:1===t.length?s():0===n?l(0,1):n>0&&n=1&&j(r,t,e)}else if(ee(ce)){var a=parseInt(i.dom.getAttrib(ce,he),10),s=i.dom.getPos(ce).y;e=parseInt(i.dom.getAttrib(ce,ge),10),t=s-a,Math.abs(t)>=1&&q(r,t,e)}C(r),i.nodeChanged()}}function Z(e,t){le=le?le:K(),se=!0,i.dom.addClass(e,ke),ce=e,G(le,t),i.dom.add(d(),le)}function Q(e){return i.dom.hasClass(e,ve)}function ee(e){return i.dom.hasClass(e,pe)}function te(e){ue=ue!==t?ue:e.clientX;var n=e.clientX-ue;ue=e.clientX;var r=i.dom.getPos(ce).x;i.dom.setStyle(ce,"left",r+n+"px")}function ne(e){de=de!==t?de:e.clientY;var n=e.clientY-de;de=e.clientY;var r=i.dom.getPos(ce).y;i.dom.setStyle(ce,"top",r+n+"px")}function re(e){ue=t,Z(e,te)}function ie(e){de=t,Z(e,ne)}function oe(e){var t=e.target,n=i.getBody();if(i.$.contains(n,r)||r===n)if(Q(t)){e.preventDefault();var o=i.dom.getPos(t).x;i.dom.setAttrib(t,xe,o),re(t)}else if(ee(t)){e.preventDefault();var a=i.dom.getPos(t).y;i.dom.setAttrib(t,he,a),ie(t)}else x()}var ae,se,le,ce,ue,de,fe="mce-resize-bar",pe="mce-resize-bar-row",me="row-resize",ge="data-row",he="data-initial-top",ve="mce-resize-bar-col",be="col-resize",ye="data-col",xe="data-initial-left",Ce=4,we=10,Ne=10,ke="mce-resize-bar-dragging",Se=new RegExp(/(\d+(\.\d+)?%)/),_e=new RegExp(/px|em/);return i.on("init",function(){i.dom.bind(d(),"mousedown",oe)}),i.on("ObjectResized",function(t){var n=t.target;if("TABLE"===n.nodeName){var r=[];e.each(n.rows,function(t){e.each(t.cells,function(e){var t=i.dom.getStyle(e,"width",!0);r.push({cell:e,width:t})})}),e.each(r,function(e){i.dom.setStyle(e.cell,"width",e.width),i.dom.setAttrib(e.cell,"width",null)})}}),i.on("mouseover",function(e){if(!se){var t=i.dom.getParent(e.target,"table");("TABLE"===e.target.nodeName||t)&&(r=t,C(t))}}),i.on("keydown",function(e){switch(e.keyCode){case n.LEFT:case n.RIGHT:case n.UP:case n.DOWN:x()}}),i.on("remove",function(){x(),i.dom.unbind(d(),"mousedown",oe)}),{adjustWidth:j,adjustHeight:q,clearBars:x,drawBars:B,determineDeltas:H,getTableGrid:_,getTableDetails:S,getWidths:L,getPixelHeights:O,isPercentageBasedSize:V,isPixelBasedSize:$,recalculateWidths:z,recalculateCellHeights:W,recalculateRowHeights:U}}}),r("tinymce/tableplugin/Plugin",["tinymce/tableplugin/TableGrid","tinymce/tableplugin/Quirks","tinymce/tableplugin/CellSelection","tinymce/tableplugin/Dialogs","tinymce/tableplugin/ResizeBars","tinymce/util/Tools","tinymce/dom/TreeWalker","tinymce/Env","tinymce/PluginManager"],function(e,t,n,r,i,o,a,s,l){function c(o){function a(e){return function(){o.execCommand(e)}}function l(e,t){var n,r,i,a;for(i='',n=0;n",r=0;r"+(s.ie&&s.ie<10?" ":"
")+"";i+=""}return i+="
",o.undoManager.transact(function(){o.insertContent(i),a=o.dom.get("__mce"),o.dom.setAttrib(a,"id",null),o.$("tr",a).each(function(e,t){o.fire("newrow",{node:t}),o.$("th,td",t).each(function(e,t){o.fire("newcell",{node:t})})}),o.dom.setAttribs(a,o.settings.table_default_attributes||{}),o.dom.setStyles(a,o.settings.table_default_styles||{})}),a}function c(e,t,n){function r(){var r,i,a,s={},l=0;i=o.dom.select("td[data-mce-selected],th[data-mce-selected]"),r=i[0],r||(r=o.selection.getStart()),n&&i.length>0?(u(i,function(e){return s[e.parentNode.parentNode.nodeName]=1}),u(s,function(e){l+=e}),a=1!==l):a=!o.dom.getParent(r,t),e.disabled(a),o.selection.selectorChanged(t,function(t){e.disabled(!t)})}o.initialized?r():o.on("init",r)}function d(){c(this,"table")}function f(){c(this,"td,th")}function p(){c(this,"td,th",!0)}function m(){var e="";e='';for(var t=0;t<10;t++){e+="";for(var n=0;n<10;n++)e+=' | ';e+="
"}return e+="
",e+='1 x 1
'}function g(e,t,n){var r,i,a,s,l,c=n.getEl().getElementsByTagName("table")[0],u=n.isRtl()||"tl-tr"==n.parent().rel;for(c.nextSibling.innerHTML=e+1+" x "+(t+1),u&&(e=9-e),i=0;i<10;i++)for(r=0;r<10;r++)s=c.rows[i].childNodes[r].firstChild,l=(u?r>=e:r<=e)&&i<=t,o.dom.toggleClass(s,"mce-active",l),l&&(a=s);return a.parentNode}function h(){o.addButton("tableprops",{title:"Table properties",onclick:k.tableProps,icon:"table"}),o.addButton("tabledelete",{title:"Delete table",onclick:a("mceTableDelete")}),o.addButton("tablecellprops",{title:"Cell properties",onclick:a("mceTableCellProps")}),o.addButton("tablemergecells",{title:"Merge cells",onclick:a("mceTableMergeCells")}),o.addButton("tablesplitcells",{title:"Split cell",onclick:a("mceTableSplitCells")}),o.addButton("tableinsertrowbefore",{title:"Insert row before",onclick:a("mceTableInsertRowBefore")}),o.addButton("tableinsertrowafter",{title:"Insert row after",onclick:a("mceTableInsertRowAfter")}),o.addButton("tabledeleterow",{title:"Delete row",onclick:a("mceTableDeleteRow")}),o.addButton("tablerowprops",{title:"Row properties",onclick:a("mceTableRowProps")}),o.addButton("tablecutrow",{title:"Cut row",onclick:a("mceTableCutRow")}),o.addButton("tablecopyrow",{title:"Copy row",onclick:a("mceTableCopyRow")}),o.addButton("tablepasterowbefore",{title:"Paste row before",onclick:a("mceTablePasteRowBefore")}),o.addButton("tablepasterowafter",{title:"Paste row after",onclick:a("mceTablePasteRowAfter")}),o.addButton("tableinsertcolbefore",{title:"Insert column before",onclick:a("mceTableInsertColBefore")}),o.addButton("tableinsertcolafter",{title:"Insert column after",onclick:a("mceTableInsertColAfter")}),o.addButton("tabledeletecol",{title:"Delete column",onclick:a("mceTableDeleteCol")})}function v(e){var t=o.dom.is(e,"table")&&o.getBody().contains(e);return t}function b(){var e=o.settings.table_toolbar;""!==e&&e!==!1&&(e||(e="tableprops tabledelete | tableinsertrowbefore tableinsertrowafter tabledeleterow | tableinsertcolbefore tableinsertcolafter tabledeletecol"),o.addContextToolbar(v,e))}function y(){return C}function x(e){C=e}var C,w,N=this,k=new r(o);!o.settings.object_resizing||o.settings.table_resize_bars===!1||o.settings.object_resizing!==!0&&"table"!==o.settings.object_resizing||(w=i(o)),o.settings.table_grid===!1?o.addMenuItem("inserttable",{text:"Table",icon:"table",context:"table",onclick:k.table}):o.addMenuItem("inserttable",{text:"Table",icon:"table",context:"table",ariaHideMenu:!0,onclick:function(e){e.aria&&(this.parent().hideAll(),e.stopImmediatePropagation(),k.table())},onshow:function(){g(0,0,this.menu.items()[0])},onhide:function(){var e=this.menu.items()[0].getEl().getElementsByTagName("a");o.dom.removeClass(e,"mce-active"),o.dom.addClass(e[0],"mce-active")},menu:[{type:"container",html:m(),onPostRender:function(){this.lastX=this.lastY=0},onmousemove:function(e){var t,n,r=e.target;"A"==r.tagName.toUpperCase()&&(t=parseInt(r.getAttribute("data-mce-x"),10),n=parseInt(r.getAttribute("data-mce-y"),10),(this.isRtl()||"tl-tr"==this.parent().rel)&&(t=9-t),t===this.lastX&&n===this.lastY||(g(t,n,e.control),this.lastX=t,this.lastY=n))},onclick:function(e){var t=this;"A"==e.target.tagName.toUpperCase()&&(e.preventDefault(),e.stopPropagation(),t.parent().cancel(),o.undoManager.transact(function(){l(t.lastX+1,t.lastY+1)}),o.addVisual())}}]}),o.addMenuItem("tableprops",{text:"Table properties",context:"table",onPostRender:d,onclick:k.tableProps}),o.addMenuItem("deletetable",{text:"Delete table",context:"table",onPostRender:d,cmd:"mceTableDelete"}),o.addMenuItem("cell",{separator:"before",text:"Cell",context:"table",menu:[{text:"Cell properties",onclick:a("mceTableCellProps"),onPostRender:f},{text:"Merge cells",onclick:a("mceTableMergeCells"),onPostRender:p},{text:"Split cell",onclick:a("mceTableSplitCells"),onPostRender:f}]}),o.addMenuItem("row",{text:"Row",context:"table",menu:[{text:"Insert row before",onclick:a("mceTableInsertRowBefore"),onPostRender:f},{text:"Insert row after",onclick:a("mceTableInsertRowAfter"),onPostRender:f},{text:"Delete row",onclick:a("mceTableDeleteRow"),onPostRender:f},{text:"Row properties",onclick:a("mceTableRowProps"),onPostRender:f},{text:"-"},{text:"Cut row",onclick:a("mceTableCutRow"),onPostRender:f},{text:"Copy row",onclick:a("mceTableCopyRow"),onPostRender:f},{text:"Paste row before",onclick:a("mceTablePasteRowBefore"),onPostRender:f},{text:"Paste row after",onclick:a("mceTablePasteRowAfter"),onPostRender:f}]}),o.addMenuItem("column",{text:"Column",context:"table",menu:[{text:"Insert column before",onclick:a("mceTableInsertColBefore"),onPostRender:f},{text:"Insert column after",onclick:a("mceTableInsertColAfter"),onPostRender:f},{text:"Delete column",onclick:a("mceTableDeleteCol"),onPostRender:f}]});var S=[];u("inserttable tableprops deletetable | cell row column".split(" "),function(e){"|"==e?S.push({text:"-"}):S.push(o.menuItems[e])}),o.addButton("table",{type:"menubutton",title:"Table",menu:S}),s.isIE||o.on("click",function(e){e=e.target,"TABLE"===e.nodeName&&(o.selection.select(e),o.nodeChanged())}),N.quirks=new t(o),o.on("Init",function(){N.cellSelection=new n(o,function(e){e&&w&&w.clearBars()}),N.resizeBars=w}),o.on("PreInit",function(){o.serializer.addAttributeFilter("data-mce-cell-padding,data-mce-border,data-mce-border-color",function(e,t){for(var n=e.length;n--;)e[n].attr(t,null)})}),u({mceTableSplitCells:function(e){e.split()},mceTableMergeCells:function(e){var t;t=o.dom.getParent(o.selection.getStart(),"th,td"),o.dom.select("td[data-mce-selected],th[data-mce-selected]").length?e.merge():k.merge(e,t)},mceTableInsertRowBefore:function(e){e.insertRows(!0)},mceTableInsertRowAfter:function(e){e.insertRows()},mceTableInsertColBefore:function(e){e.insertCols(!0)},mceTableInsertColAfter:function(e){e.insertCols()},mceTableDeleteCol:function(e){e.deleteCols()},mceTableDeleteRow:function(e){e.deleteRows()},mceTableCutRow:function(e){C=e.cutRows()},mceTableCopyRow:function(e){C=e.copyRows()},mceTablePasteRowBefore:function(e){e.pasteRows(C,!0)},mceTablePasteRowAfter:function(e){e.pasteRows(C)},mceSplitColsBefore:function(e){e.splitCols(!0)},mceSplitColsAfter:function(e){e.splitCols(!1)},mceTableDelete:function(e){w&&w.clearBars(),e.deleteTable()}},function(t,n){o.addCommand(n,function(){var n=new e(o);n&&(t(n),o.execCommand("mceRepaint"),N.cellSelection.clear())})}),u({mceInsertTable:k.table,mceTableProps:function(){k.table(!0)},mceTableRowProps:k.row,mceTableCellProps:k.cell},function(e,t){o.addCommand(t,function(t,n){e(n)})}),h(),b(),o.settings.table_tab_navigation!==!1&&o.on("keydown",function(t){var n,r,i;9==t.keyCode&&(n=o.dom.getParent(o.selection.getStart(),"th,td"),n&&(t.preventDefault(),r=new e(o),i=t.shiftKey?-1:1,o.undoManager.transact(function(){!r.moveRelIdx(n,i)&&i>0&&(r.insertRow(),r.refresh(),r.moveRelIdx(n,i))})))}),N.insertTable=l,N.setClipboardRows=x,N.getClipboardRows=y}var u=o.each;l.add("table",c)})}(window);
\ No newline at end of file
diff --git a/Website/Composite/content/misc/editors/visualeditor/tinymce/skins/lightgray/content.inline.min.css b/Website/Composite/content/misc/editors/visualeditor/tinymce/skins/lightgray/content.inline.min.css
new file mode 100644
index 0000000000..4030546c68
--- /dev/null
+++ b/Website/Composite/content/misc/editors/visualeditor/tinymce/skins/lightgray/content.inline.min.css
@@ -0,0 +1 @@
+.mce-content-body .mce-reset{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:black;font-family:Arial;font-size:11px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;line-height:normal;font-weight:normal;text-align:left;-webkit-tap-highlight-color:transparent;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr;max-width:none}.mce-object{border:1px dotted #3A3A3A;background:#D5D5D5 url(img/object.gif) no-repeat center}.mce-preview-object{display:inline-block;position:relative;margin:0 2px 0 2px;line-height:0;border:1px solid gray}.mce-preview-object[data-mce-selected="2"] .mce-shim{display:none}.mce-preview-object .mce-shim{position:absolute;top:0;left:0;width:100%;height:100%;background:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}figure.align-left{float:left}figure.align-right{float:right}figure.image.align-center{display:table;margin-left:auto;margin-right:auto}figure.image{display:inline-block;border:1px solid gray;margin:0 2px 0 1px;background:#f5f2f0}figure.image img{margin:8px 8px 0 8px}figure.image figcaption{margin:6px 8px 6px 8px;text-align:center}.mce-toc{border:1px solid gray}.mce-toc h2{margin:4px}.mce-toc li{list-style-type:none}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:15px;page-break-before:always}@media print{.mce-pagebreak{border:0}}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px !important;height:9px !important;border:1px dotted #3A3A3A;background:#D5D5D5 url(img/anchor.gif) no-repeat center}.mce-nbsp,.mce-shy{background:#AAA}.mce-shy::after{content:'-'}hr{cursor:default}.mce-match-marker{background:#AAA;color:#fff}.mce-match-marker-selected{background:#3399ff;color:#fff}.mce-spellchecker-word{border-bottom:2px solid #F00;cursor:default}.mce-spellchecker-grammar{border-bottom:2px solid #008000;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #BBB}td[data-mce-selected],th[data-mce-selected]{background-color:#3399ff !important}.mce-edit-focus{outline:1px dotted #333}.mce-content-body *[contentEditable=false] *[contentEditable=true]:focus{outline:2px solid #2d8ac7}.mce-content-body *[contentEditable=false] *[contentEditable=true]:hover{outline:2px solid #7ACAFF}.mce-content-body *[contentEditable=false][data-mce-selected]{outline:2px solid #2d8ac7}.mce-resize-bar-dragging{background-color:blue;opacity:.25;filter:alpha(opacity=25);zoom:1}
\ No newline at end of file
diff --git a/Website/Composite/content/misc/editors/visualeditor/tinymce/skins/lightgray/content.min.css b/Website/Composite/content/misc/editors/visualeditor/tinymce/skins/lightgray/content.min.css
new file mode 100644
index 0000000000..82beedb8f4
--- /dev/null
+++ b/Website/Composite/content/misc/editors/visualeditor/tinymce/skins/lightgray/content.min.css
@@ -0,0 +1 @@
+body{background-color:#FFFFFF;color:#000000;font-family:Verdana,Arial,Helvetica,sans-serif;font-size:14px;scrollbar-3dlight-color:#F0F0EE;scrollbar-arrow-color:#676662;scrollbar-base-color:#F0F0EE;scrollbar-darkshadow-color:#DDDDDD;scrollbar-face-color:#E0E0DD;scrollbar-highlight-color:#F0F0EE;scrollbar-shadow-color:#F0F0EE;scrollbar-track-color:#F5F5F5}td,th{font-family:Verdana,Arial,Helvetica,sans-serif;font-size:14px}.mce-content-body .mce-reset{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:black;font-family:Arial;font-size:11px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;line-height:normal;font-weight:normal;text-align:left;-webkit-tap-highlight-color:transparent;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr;max-width:none}.mce-object{border:1px dotted #3A3A3A;background:#D5D5D5 url(img/object.gif) no-repeat center}.mce-preview-object{display:inline-block;position:relative;margin:0 2px 0 2px;line-height:0;border:1px solid gray}.mce-preview-object[data-mce-selected="2"] .mce-shim{display:none}.mce-preview-object .mce-shim{position:absolute;top:0;left:0;width:100%;height:100%;background:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}figure.align-left{float:left}figure.align-right{float:right}figure.image.align-center{display:table;margin-left:auto;margin-right:auto}figure.image{display:inline-block;border:1px solid gray;margin:0 2px 0 1px;background:#f5f2f0}figure.image img{margin:8px 8px 0 8px}figure.image figcaption{margin:6px 8px 6px 8px;text-align:center}.mce-toc{border:1px solid gray}.mce-toc h2{margin:4px}.mce-toc li{list-style-type:none}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:15px;page-break-before:always}@media print{.mce-pagebreak{border:0}}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px !important;height:9px !important;border:1px dotted #3A3A3A;background:#D5D5D5 url(img/anchor.gif) no-repeat center}.mce-nbsp,.mce-shy{background:#AAA}.mce-shy::after{content:'-'}hr{cursor:default}.mce-match-marker{background:#AAA;color:#fff}.mce-match-marker-selected{background:#3399ff;color:#fff}.mce-spellchecker-word{border-bottom:2px solid #F00;cursor:default}.mce-spellchecker-grammar{border-bottom:2px solid #008000;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #BBB}td[data-mce-selected],th[data-mce-selected]{background-color:#3399ff !important}.mce-edit-focus{outline:1px dotted #333}.mce-content-body *[contentEditable=false] *[contentEditable=true]:focus{outline:2px solid #2d8ac7}.mce-content-body *[contentEditable=false] *[contentEditable=true]:hover{outline:2px solid #7ACAFF}.mce-content-body *[contentEditable=false][data-mce-selected]{outline:2px solid #2d8ac7}.mce-resize-bar-dragging{background-color:blue;opacity:.25;filter:alpha(opacity=25);zoom:1}
\ No newline at end of file
diff --git a/Website/Composite/content/misc/editors/visualeditor/tinymce/skins/lightgray/fonts/tinymce-small.eot b/Website/Composite/content/misc/editors/visualeditor/tinymce/skins/lightgray/fonts/tinymce-small.eot
new file mode 100644
index 0000000000000000000000000000000000000000..b144ba0bd949de3c0f87abdd78b517067169884f
GIT binary patch
literal 9492
zcmcgyYj7Lab-s5Oz=CfqL2yNo1o0rSA|ZkhKoF!Pk}Fb@EmM-IM`Za;N@gTQlt?}7
zN^YjzI+ml=>J6ee66+Gi(ljj5V?YXgkiHL~VwhLrW_=jFxj4b&}2FxhUJr
zGAxUpyHmmdVx*4QOl8^o5BBGpnpMn%-9VZ?c6w&v`+xksXECS)^||9S=NFKJUw#F-
z|M=Xc&)3`&`5x+58SC<#n4Nh-J1%~evFHovA3T8u?G5!8sK0}H_leUNF8)|){yo$`
zLjC64{IQw$x_|f(W3dlVzi@iy;sV>v-eW9&FY3`VGpA>rJwN#k)KB0Y?=H-rzW_dQ
zbq`TLQ`P^%o4t%FzpKz2zV7DypIM&Q(6|*B2ivPJi?N@ps#p@tQjyR}Yf-(TvOsU6
z)PX)XSLLV<=3!H458#j5Ig6GymU5-S&()>!(h^!2T3D&KG*D^bOaB=4MAfJgF5rok
zZ<2%2!tq?wiXI44aaaz#J^Jo#9-4(JR2w1^WD!E!2-{R5`|z)
zAL5&1NP0e@52O-uL_*Jp+)*Rk&{a_?Uyt?o$COg6-?1&rc5H6jRx0e+;gp4(Tj7*F
zrA(FjW96tEd0mLI&Dj#>5Kg7SOH8o^72dF&5aw)yHygaQfU^vi%*=52%@y9jiK#`n
zktjrX7Y|DQh)-Rzs~&u=d3)HICW49`PPI2@e6{MEwYv9mJKl=-DnEFxxjhvw%a<$B
z@b>0DuU`A6TI;)9UR1%BLo1CHToN9v5{}0(xF~=PvuJ7=-p>iWPlaT
zC=xIE;wUc~MRSyo@uZe83&p$<^01eE&2=Zv+QGCDSPU5Hpndj4U9<1yJ2X4OmKR_6
z41-tD2)K_C@3g-b_LpQ*!>MgzEEo%6fo>;DwQpgOZ`q1f7L>5=OU&jL-9h4RG^(_g
zX$S>tMrjR^yYRs)ye!k;*7}^>g+_Hg%QUKUTEhnB@)g#j{)#%yda*Kl0hNqru!F_y
zC{LL+ypc!vWC#8opNSY;iDUda>D!JP}WsDeB7Ss6#8pQ-y&+R6;Gj
z1cp#QBxL0fbvk~yXH0Z&sLwjW5!w0;-D0fgaD2F-zyI1$BI+3%^F$Lv*ZTV#h8?an
zH|ae=e~UlhkLW!uDAaiP%k9ZzJ0+e+L$F70YF4J>n1WIFS*X?tKKW;8ymL
zdpC*OMCtXnU-)2icOVe-`U4XYz1ich4g0_8(r!=wyWblO1iG93;ab0^S&vKvm{(#1
zL-vQ0PzKnY$LNTuCd+}DXYOT^g9L$RWs;5dYNBp`=Y!1nS&UMnU@8>6}Ap_xp%?U)iu59#UaZP))J%p
zP^7mv@=>JMmiOLB`R1EVp-_{&y=BqN2+AJ
zfgWuLa=Th`mP^cs<7i>777iDkZ^}=d4pfK<+FJV{S%+Flo
zv|3hf+cgUpw=iLnM_LEGRIWo4Yj#nsiX<{OG>bssHkdfz@RnUFt%L-HEiT@fUKLd+
z=b9nuRTs_$n02U;zOa}r`Rih1Sc_al3AHpTiFigSm;<9qJ`^W-(EuQ^yYz9kao0d3
zGO%l-iJWgc@mu#7pGf%|G=Gz(+^x@u7Vqm#-&c$xPj?=AVcxp1sn;K<;rxyr5XuEG
zjunC(z>=eciJ=-E8jNtCrij+=_~man*ZI`-cgF6YW0Q-|9`yW_Pw}ZAc`m*6@kN|N
z&Mj=mRrh&bsNscFBX2b_e3ToC#iyL>-?$v_Zk@Y-?49e%AO6U>?p*(==isx8lNUdJ
z>yn3dlAeDV&u3w_{yGQ(LLtOW+}F~@i)LzI45WauUA(oW2{4VL+K)YnplxuB4-S~J
z0t8;}%mAIxRe7pdrPs(|vvdLG<%6RHVIV}1K2YR?Iis~jBl7CYmjgYmMo-|iSWMla
zdcCiyn!+{pvMg~$Q*b>Yz$_^{{}h2dYG=tp26e=&P&aR$a8N
zuFes@MoszgW$Jk?_Gk>`y$yIPs9vrXz(}>*`RWeE<;WePYV^tlSzwBKwXiu>XgE`t|(zMu@5iWIWCx>!f
zgUEnwInWoEk71{axmG!_@)!vWL?X>y4gJg5)Bnbv+H!eu$BqgY(1Q)Ir>H1zW$R9(
zVDc@G`u`S&fAx87DSCAG`kt;Z2L?ElZbcD&|BizkQ5^&sQpn*@8Dz){&BVA~!}S<9
zH7H@YDfn|37o@`_CbK1sET@G~ey4m&o_z~=X~8q*Wuj|2ggM0A1Zx^>
zuBh7rD=pWIVa;r4U!83Mf8?g&Ky-2~Q79H-g_s#{RJ2Al)DlsQh?>uhD#cN?FpyEq
zjGEwhIcM$3n~w-si?--HynlBznvLsvJR6Pf-ha67(=C!Ek!*kcC1`3}+-2nQv(Sap
zOsI>BV6I%iZ-O4u;3jdtD9DJ(_xrWcy5gjnCUuGd=bE$!*(CK0j5>x1HSA*SC+_++6v3e&k`}
z;l}jfc-o5d*fe!P~;RpNr9z1-=>=utLNDYGiJr3ZLGF_8_dlf|Xq17r%~ki(mSJ?IVLi0O2T;o#*pI({*_jnGMyr_l?5
zNLa2B>c%)o+9^3gUJAq<0T3iAsjO@%!m(@|E*pUpT!L
zOZo~~;1UxowIng20r%3vafF!>3u~qbuSc{`~TrA1c-#JoC)x
z^1rZc#Udx(w#(LXD++i8T0542IyldD%z&jxwmjg5a8FHWW}*f<*vNC(*dQZ*a^=R2
zD>P-wmsl=mUE7AF9Jp~~39UD7kk%lY*h|dHrO8*&)c#MJ$}cKJa<}b;5#xDjNWo
z1sC|}$VfO0B}}YL255L24K%c92}KM)wj;Ug=~o_o^p&S~C3ieF3}muWV|{J?`%jOK
zp5EWz);E?S#IlpdJr8|hxQYqGUwG&qBRO6AFt~N{NOt_m2XeUwo*d5}ncN!uur$qF
zADZ~t0FAO0p6Y|xOc_7Gfvp4;q{T|-ys#F!HmfTgyV%MKpwFzFejIj%O@6sh7#b=R
zzC3xmM02UmiE@Cr>(TLL*U#GXrA;+`69@bI4^H&eZ2Hn3bzltf{rfX(QGxeBR)
zSExAV25h4sHX5-Cp2xfiy+Vjr;20q#yyU{?24VZ6N2j$>>7dDzp$ZXB`8DUSzjmO+
z!JjBoY!!=wHNeqj&Eaq})(3+GHK^3tdQ}xH%XM
z^T-xJ8}ehZZ#e7q(7lWd9`FV}z=@Zv9ojZBB1(WDS)C@K-EOWx*BF9Y&+J~+zt+Fj$cB>4W#EMyR+F;oNr>Ib533uC~^?~5HrU~XCW1|AkFm6#Z
z2Q7Jua6`V1=SS6i5Mj7{
zNU^GzaF3nK6$-hWeGf{hT+O#jrPu2AJ@w7c31}VFuAcYl>JS>7dVGM?*#55`--_5B
z_L-?batrpq1&tZS$0r8An~W|DbrjIv>|Rtp*CnrH}0mK?M^2~4rEF^nmI6%
zm>T=Hj+TjNUtje6E9YA}UZE0yzvEzkde2a-%wj`((&HzM@3eG~ZGY9tcC=ij5*V_<
z1O6bdj7ud<0t(%yT346YRmZ}owX0m;l)K?<1p3tjCq@EBI
z{^26jvSB11AKB0nva9wRiI@UVGWzsTYimgFGbo^0cy!msjk_L2q>F(i$PCUC_=76t
zu}sCA#UdDaGU-q!O@QzO8D>Dp2+Cy4nF(pD0R}32nlGrr`8fGle&XoSiJ=D@&-&7d
z)J&l;lj`Z~>*1>6e5~;F@TdBkn%?1}y<>adrtSTS)Xs26S64^Zp}x$aF0OE^VKBbB
zy*+PWiNN<_WnEiPsj4PKQsrME#%rZID)Yz&T!fwL980n3}T(y;e#e%d!|`GJb@zY28oh{i4upA6Yf!&azfB*d$o<)
zt4U=R08U;q!%d=DwFPzeUlFp2Fp(~pJF72Omo`iL$_pePl)5bj%^3s0#DcMvrj<`K
z;C)nL($aD%LcS5ROPR@KM+I`OE;`duXAx3z@ksQRZSg0}@oangzGFi}$L>peJc;KT
z8p*p@m}<|p&g=Q0H>k8Yf0N(6J5LFx+NK~w*>22_@83kv(6a#6YxAwSc6x4Vp|Rn)
z76lLH^~3H{`Q4R0hiuwd?-bTL3t7F(_ldxS;hXyuoPT3o630vGz-!u&BqcPD9^JvLoyiJOTL?gNzFb
zf2CnU%Rm^ubfAqwXeru)7&ZaeyWAIA9#7^M1=@-*LCuxMmj<&0cm(wk%90zMO1zzk
zhQpJm=pN0SnxuPYINYf$tl$3LNIE@2=|p-Yv#q(1*uHQ3NLm>`5zU-9HA(kO^u**T
zx~C@E+9pzW>}Yf8jHF*0N%wA5+YEJ7Nj`KWJ;HF|_)rQwGx6QWo3{NYtMgDRdp|ou
zUx{SCRKizWKfDZzcq-J23(v^!`Ou;0|HR{$l-xe|KI~F*EA$xZ7LrZvl`_?<=_@PB
zG=@^OkMac%<16Z%t?8deeP5;R=9<0^)G4iae!cQi3GX1fHj=1}U##TQZocxpkSDro
z<#+Zub{+BWEI+_6@E4V=@@vX}K&M_*7uB~tanHEts5j~x_f7j=_5F{wPdlUilmBV|
z>;8{xJT-$g(>1?Y^M37A?F+SkRkx{bs_xr$PW^cOv-Q7U|3O2x;XuO|8(wetS>u+*
z#l}yXo{=j(%-*GM(zvQSA}f_!Bm0xeesEaq?k>|vjlEcDSJ8fNrR+iZjY^rKO=hJ`
z*8Y5@TnoSWePArUoT4R+9=EIj?Y~tiBZ$a8S1Ef?ezQ{c;zu*NO4*0@FILL6@G<}8
z!pSq2P9K}?JAZm+Ztl*%#W_5C?)=I5GtteN?D{{z`HXZv$Df>=Ik)=PKcDg0
zUGrxyM32v&nLRgiVfKmW(M!?Y$L9CW&!5S#UGgVG7g!WODVoKPhv
+
+
\ No newline at end of file
diff --git a/Website/Composite/content/misc/editors/visualeditor/tinymce/skins/lightgray/fonts/tinymce-small.ttf b/Website/Composite/content/misc/editors/visualeditor/tinymce/skins/lightgray/fonts/tinymce-small.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..a983e2dc4cb30880fffe00e1f0879be4d95eb4cc
GIT binary patch
literal 9304
zcmcgyYj7Lab-s5Ozyf??34$wvB!~xr6$uf90D>SbkzA3IY?+cwJtDttQZgecqA2QN
zS8_A$#<3iwZW2{-ovAyiIrXDI+=r%r>Si?Q&5S4YbR3WCaoZ$KV@#^abf)c$o3^go
z5tjYVU4W!$N%fy*!MpdlXV1O&-0wV=j5EgSnaxy|yYIk2zPUy1LCZCynIk7>7r*~U
z-+PuZ-iiAB(b=<$$b+a~Lhe60f8q0iyQAMj{W4?So?~;fPiRNQuQC>U0sTYA(4f7c
z{sQ%PQ13Z*^4$3!D=oi^`bVf=pFeeE_Pw4TKEzo31Juu*oIStDcCq&uOWcEcY+?4~
zoU{8UUqbyD-tq3@sk7(6C$64h>SwC@UwE^ZG39p@dc!x|oc}W`@Boclb8)bJ^JOvi
zb5#|~f>|mOI%zFxS40VR
z&3M8W)?3>O@%&Jc7sAP6D6S9l&2c2Xkkkj$NjV~^7sBqSQEup}C|9n=2L|FwIX>Xn
zmSsCOw{0sOaqLLiLe8y7+MZUX%LDOBOpd%NM8)Q88FPrF(~)JS*n$dg*iIO8w!xbX
z-de#~7E5Mkx%=iSZ{Wn#qTEOpqr97kB!9%GF4-|1#g3#qTC%=6_02ln
zd$9v=#e0<>JlE2Zj#T8!l~`n3OTSmIdsD6RU92prV9TME#tJSA4_1lg*a)~Nf(^4|
zYFR$OlUftkOwDNG%{**?70oCSFNM+=FBv6sjF0n_mNbi{f)Vzxmwheu$4=X!j1gQ4
z8kvxN`dEF7@8#PxJHnP1U;GS%*U$*Mj}h;*zZUkFWKzSaZDuSK4`YE=lcm}>u*f%T
z#i|HOSodXSbBpdEaVHuzS}Qb!f;FSGj>sMO;8k8$XmIP+oZNv%Z9XeBYI9o02Ilfr
z)~o)CI>Y*~GJDt&>}M7`Sjvs@v>D({Jjyp4TH1$wHQI)-i)P92wP9yVLuu2C&2Hk!
zMA}SKS0PUwS}Bn(4i2FbZuKQGg!&;NYlo;ai9@~PqGv-x&Jm8tHEie+
zt-X5GALI!lBR1Xh2wuUh+#~mF601b%^{X#@u%#y$40-**$*A7q@z+KC-*Rbpr2gIS
z4F!WeE&fQI-_xQ;Cxgr@F#;k2Of%UgoC2T(FAk*AA=EHHcFjotQi_Y=}mSTC#7YkhbaR4Lc
zhN)E%{MHq2*G?Ga%dEEf>vPqz1%8UC$)0nI63&zjcoC2fm#@^#JgLQ`p2T(_g*7C~
zWxaSa8&DYdlb5ioZ{`bEIIWhI-+INu#Vt&jrZkNxI-r6DR=5KVx@cgGWV8Z$TM9B
zUpQr*+tlX|1~|WM2ZVAFjAMmh2e8x_VPZJI!$VQ-(-hIxleqXz=PIAR`p)=$^K5GA
z*#n-R@@YQ(BhQ7mK0c3g$hn2>xa>a9iveCtH}N(j%g4B(SbW;K`pt`pp0@e>#^1TB
z{K1c$tIpM*dJa6hGG*eu3
z)rh?M^2K0po6#G5Ego05t6uMGs-|#Fy(mju(Ntx-66`hF_)?CF1FPi?up
zxMN3!3+SOn*i%%Lw~BSUQ84*dM*V*a!@v5xwiG?Odwow=nF9kHO1G+rzJJ?6j;IZS
z3@PMrs0=dXg=S)04{$xsO$|yIZVG-5!eH@NAA-%(&gx8R8H=D!c
zf#KuUurjgr9Ksx8Zh|!pHrLc`ft8kP#;|5Kw6D(Y0)OPD;Xrh8Em