aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.stylelintrc.json1
-rw-r--r--interface/css/codejar-linenumbers.css17
-rw-r--r--interface/css/rspamd.css10
-rw-r--r--interface/index.html1
-rw-r--r--interface/js/app/config.js4
-rw-r--r--interface/js/lib/codejar-linenumbers.min.js6
-rw-r--r--interface/js/lib/codejar.min.js4
-rw-r--r--interface/js/lib/linenumbers.min.js5
-rw-r--r--interface/js/main.js2
-rw-r--r--src/libserver/hyperscan_tools.cxx16
-rw-r--r--src/libserver/hyperscan_tools.h11
-rw-r--r--src/libserver/rspamd_control.c65
-rw-r--r--test/functional/lib/rspamd.robot16
13 files changed, 104 insertions, 54 deletions
diff --git a/.stylelintrc.json b/.stylelintrc.json
index 040ffaa9e..6fd1323b9 100644
--- a/.stylelintrc.json
+++ b/.stylelintrc.json
@@ -10,6 +10,7 @@
"**/*.min.css",
"**/*.js",
"interface/css/d3evolution.css",
+ "interface/css/codejar-linenumbers.css",
"interface/css/nprogress.css",
"interface/css/prism.css"
],
diff --git a/interface/css/codejar-linenumbers.css b/interface/css/codejar-linenumbers.css
new file mode 100644
index 000000000..cc19f4117
--- /dev/null
+++ b/interface/css/codejar-linenumbers.css
@@ -0,0 +1,17 @@
+.codejar-linenumbers-inner-wrap {
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ bottom: 0px;
+ overflow: hidden;
+}
+
+.codejar-linenumbers {
+ mix-blend-mode: initial;
+ height: 100%;
+}
+
+.codejar-linenumber {
+ position: relative;
+ top: 0px;
+}
diff --git a/interface/css/rspamd.css b/interface/css/rspamd.css
index 47062f60d..5ddd4aa9c 100644
--- a/interface/css/rspamd.css
+++ b/interface/css/rspamd.css
@@ -548,15 +548,15 @@ table#symbolsTable input[type="number"] {
/* Fix line wrapping */
scrollbar-width: thin;
}
+.codejar-linenumbers-inner-wrap {
+ bottom: unset;
+}
.codejar-linenumbers {
background: rgba(255 255 255 / 0.07) !important;
- bottom: unset !important;
+}
+.codejar-linenumber {
color: rgba(120 120 120 / 1) !important;
- height: inherit;
- mix-blend-mode: unset !important;
text-align: right;
- overflow: unset !important;
- user-select: none;
}
.editor {
font-family: monospace;
diff --git a/interface/index.html b/interface/index.html
index 993d9e55b..2eddd2a77 100644
--- a/interface/index.html
+++ b/interface/index.html
@@ -22,6 +22,7 @@
<link rel="stylesheet" type="text/css" href="./css/d3evolution.css">
<link rel="stylesheet" type="text/css" href="./css/d3pie.css">
<link rel="stylesheet" type="text/css" href="./css/nprogress.css"/>
+ <link rel="stylesheet" type="text/css" href="./css/codejar-linenumbers.css"/>
<link rel="stylesheet" type="text/css" href="./css/prism.css"/>
<link href="./css/rspamd.css" rel="stylesheet">
</head>
diff --git a/interface/js/app/config.js b/interface/js/app/config.js
index 8d979f1f2..b3f4e5661 100644
--- a/interface/js/app/config.js
+++ b/interface/js/app/config.js
@@ -181,7 +181,6 @@ define(["jquery", "codejar", "linenumbers", "prism"],
mode = (new Blob([data[0].data]).size > 5120) ? "basic" : $("input[name=editorMode]:checked").val();
$("<" + editor[mode].elt + ' id="editor" class="' + editor[mode].class + '" data-id="' + item.map + '">' +
- rspamd.escapeHTML(data[0].data) +
"</" + editor[mode].elt + ">").appendTo("#modalBody");
if (editor[mode].codejar) {
@@ -189,6 +188,9 @@ define(["jquery", "codejar", "linenumbers", "prism"],
document.querySelector("#editor"),
withLineNumbers((el) => Prism.highlightElement(el))
);
+ jar.updateCode(data[0].data);
+ } else {
+ document.querySelector("#editor").innerHTML = rspamd.escapeHTML(data[0].data);
}
var icon = "fa-edit";
diff --git a/interface/js/lib/codejar-linenumbers.min.js b/interface/js/lib/codejar-linenumbers.min.js
new file mode 100644
index 000000000..e3ca168ce
--- /dev/null
+++ b/interface/js/lib/codejar-linenumbers.min.js
@@ -0,0 +1,6 @@
+/*!
+ * codejar-linenumbers v1.0.0 (https://github.com/julianpoemp/codejar-linenumbers)
+ * Copyright (c) 2023, Julian Poemp, MIT
+ */
+function withLineNumbers(r,e={}){const d={class:"codejar-linenumbers",wrapClass:"codejar-wrap",width:"35px",backgroundColor:"rgba(128, 128, 128, 0.15)",color:"",...e};let l;return function(e){r(e),l||(l=init(e,d),e.addEventListener("scroll",()=>l.style.top=`-${e.scrollTop}px`));var t=(e.textContent||"").replace(/\n\n$/g,"\n").split("\n").length;let o="";for(let e=0;e<t;e++)o+=e+1+`
+`;l.innerText=o}}function init(e,t){var o=getComputedStyle(e),r=document.createElement("div"),d=(r.className=t.wrapClass,r.style.position="relative",document.createElement("div")),l=(d.className="codejar-linenumbers-inner-wrap",d.style.background=o.background,d.style.marginTop=o.borderTopWidth,d.style.marginBottom=o.borderBottomWidth,d.style.marginLeft=o.borderLeftWidth,d.style.borderTopLeftRadius=o.borderTopLeftRadius,d.style.borderBottomLeftRadius=o.borderBottomLeftRadius,document.createElement("div")),d=(l.className=t.class,d.appendChild(l),r.appendChild(d),l.style.width=t.width,l.style.overflow="hidden",l.style.backgroundColor=t.backgroundColor,l.style.fontFamily=o.fontFamily,l.style.fontSize=o.fontSize,l.style.lineHeight=o.lineHeight,l.style.paddingTop=`calc(${o.paddingTop})`,l.style.paddingLeft=o.paddingLeft,l.style.borderTopLeftRadius=o.borderTopLeftRadius,l.style.borderBottomLeftRadius=o.borderBottomLeftRadius,document.createElement("div"));return d.setAttribute("class","codejar-linenumber"),d.style.color=t.color||o.color,d.style.setProperty("mix-blend-mode","unset"),l.appendChild(d),e.style.paddingLeft=`calc(${t.width} + ${l.style.paddingLeft} + 5px)`,e.style.whiteSpace="pre",e.parentNode.insertBefore(r,e),r.appendChild(e),d} \ No newline at end of file
diff --git a/interface/js/lib/codejar.min.js b/interface/js/lib/codejar.min.js
index d2b860deb..6326ea3fe 100644
--- a/interface/js/lib/codejar.min.js
+++ b/interface/js/lib/codejar.min.js
@@ -1,5 +1,5 @@
/*!
- * CodeJar 3.7.0 (https://github.com/antonmedv/codejar)
+ * CodeJar 4.2.0 (https://github.com/antonmedv/codejar)
* Copyright (c) 2020, Anton Medvedev, MIT
*/
-const globalWindow=window;function CodeJar(u,n,e={}){const f=Object.assign({tab:"\t",indentOn:/[({\[]$/,moveToNewLine:/^[)}\]]/,spellcheck:!1,catchTab:!0,preserveIdent:!0,addClosing:!0,history:!0,window:globalWindow},e),o=f.window,p=o.document;let r=[],h=[],g=-1,i=!1,s,y,v=(u.setAttribute("contenteditable","plaintext-only"),u.setAttribute("spellcheck",f.spellcheck?"true":"false"),u.style.outline="none",u.style.overflowWrap="break-word",u.style.overflowY="auto",!(u.style.whiteSpace="pre-wrap"));n(u),(v="plaintext-only"!==u.contentEditable?!0:v)&&u.setAttribute("contenteditable","true");const t=d(()=>{var e=T();n(u,e),b(e)},30);let C=!1;const N=e=>!O(e)&&!M(e)&&"Meta"!==e.key&&"Control"!==e.key&&"Alt"!==e.key&&!e.key.startsWith("Arrow"),a=d(e=>{N(e)&&(w(),C=!1)},300);e=(e,t)=>{r.push([e,t]),u.addEventListener(e,t)};function T(){var e=H();const t={start:0,end:0,dir:void 0};let{anchorNode:n,anchorOffset:r,focusNode:o,focusOffset:i}=e;if(n&&o)return n===u&&o===u?(t.start=0<r&&u.textContent?u.textContent.length:0,t.end=0<i&&u.textContent?u.textContent.length:0,t.dir=i>=r?"->":"<-"):(n.nodeType===Node.ELEMENT_NODE&&(e=p.createTextNode(""),n.insertBefore(e,n.childNodes[r]),n=e,r=0),o.nodeType===Node.ELEMENT_NODE&&(e=p.createTextNode(""),o.insertBefore(e,o.childNodes[i]),o=e,i=0),l(u,e=>{if(e===n&&e===o)return t.start+=r,t.end+=i,t.dir=r<=i?"->":"<-","stop";if(e===n){if(t.start+=r,t.dir)return"stop";t.dir="->"}else if(e===o){if(t.end+=i,t.dir)return"stop";t.dir="<-"}e.nodeType===Node.TEXT_NODE&&("->"!=t.dir&&(t.start+=e.nodeValue.length),"<-"!=t.dir)&&(t.end+=e.nodeValue.length)}),u.normalize()),t;throw"error1"}function b(n){var e,t,r=H();let o,i=0,s,a=0,d=(n.dir||(n.dir="->"),n.start<0&&(n.start=0),n.end<0&&(n.end=0),"<-"==n.dir&&({start:e,end:t}=n,n.start=t,n.end=e),0);l(u,e=>{var t;if(e.nodeType===Node.TEXT_NODE)return t=(e.nodeValue||"").length,d+t>n.start&&(o||(o=e,i=n.start-d),d+t>n.end)?(s=e,a=n.end-d,"stop"):void(d+=t)}),o||(o=u,i=u.childNodes.length),s||(s=u,a=u.childNodes.length),"<-"==n.dir&&([o,i,s,a]=[s,a,o,i]),r.setBaseAndExtent(o,i,s,a)}function E(){var e=H().getRangeAt(0),t=p.createRange();return t.selectNodeContents(u),t.setEnd(e.startContainer,e.startOffset),t.toString()}function m(){var e=H().getRangeAt(0),t=p.createRange();return t.selectNodeContents(u),t.setStart(e.endContainer,e.endOffset),t.toString()}function k(e){v&&"Enter"===e.key&&(_(e),e.stopPropagation(),""==m()?(S("\n "),(e=T()).start=--e.end,b(e)):S("\n"))}function w(){var e,t,n;i&&(e=u.innerHTML,t=T(),(n=h[g])&&n.html===e&&n.pos.start===t.start&&n.pos.end===t.end||(g++,h[g]={html:e,pos:t},h.splice(g+1),300<g&&(g=300,h.splice(0,1))))}function l(e,t){var n=[];e.firstChild&&n.push(e.firstChild);let r=n.pop();for(;r&&"stop"!==t(r);)r.nextSibling&&n.push(r.nextSibling),r.firstChild&&n.push(r.firstChild),r=n.pop()}function x(e){return e.metaKey||e.ctrlKey}function O(e){return x(e)&&!e.shiftKey&&"Z"===L(e)}function M(e){return x(e)&&e.shiftKey&&"Z"===L(e)}function L(e){e=e.key||e.keyCode||e.which;if(e)return("string"==typeof e?e:String.fromCharCode(e)).toUpperCase()}function S(e){e=e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;"),p.execCommand("insertHTML",!1,e)}function d(t,n){let r=0;return(...e)=>{clearTimeout(r),r=o.setTimeout(()=>t(...e),n)}}function A(e){let t=e.length-1;for(;0<=t&&"\n"!==e[t];)t--;let n=++t;for(;n<e.length&&/[ \t]/.test(e[n]);)n++;return[e.substring(t,n)||"",t,n]}function D(){return u.textContent||""}function _(e){e.preventDefault()}function H(){var e;return((null==(e=u.parentNode)?void 0:e.nodeType)==Node.DOCUMENT_FRAGMENT_NODE?u.parentNode:o).getSelection()}return e("keydown",e=>{if(!e.defaultPrevented){if(y=D(),f.preserveIdent){var t=e;if("Enter"===t.key){var n=E(),r=m(),[o]=A(n);let e=o;f.indentOn.test(n)&&(e+=f.tab),0<e.length?(_(t),t.stopPropagation(),S("\n"+e)):k(t),e!==o&&f.moveToNewLine.test(r)&&(n=T(),S("\n"+o),b(n))}}else k(e);if(f.catchTab){t=e;"Tab"===t.key&&(_(t),t.shiftKey?([t,r]=A(E()),0<t.length&&(o=T(),t=Math.min(f.tab.length,t.length),b({start:r,end:r+t}),p.execCommand("delete"),o.start-=t,o.end-=t,b(o))):S(f.tab))}if(f.addClosing){var i,n=e,s=`([{'"`,a=`)]}'"`,d=m(),l="\\"===(l=E()).substr(l.length-1),d=d.substr(0,1);a.includes(n.key)&&!l&&d===n.key?(i=T(),_(n),i.start=++i.end,b(i)):s.includes(n.key)&&!l&&(`"'`.includes(n.key)||[""," ","\n"].includes(d))&&(_(n),i=T(),l=i.start==i.end?"":H().toString(),S(n.key+l+a[s.indexOf(n.key)]),i.start++,i.end++,b(i))}var c;f.history&&(O(d=e)&&(_(d),g--,(c=h[g])&&(u.innerHTML=c.html,b(c.pos)),g<0)&&(g=0),M(d)&&(_(d),g++,(c=h[g])&&(u.innerHTML=c.html,b(c.pos)),g>=h.length)&&g--,N(e))&&!C&&(w(),C=!0),v&&(!x(l=e)||"C"!==L(l))&&b(T())}}),e("keyup",e=>{e.defaultPrevented||e.isComposing||(y!==D()&&t(),a(e),s&&s(D()))}),e("focus",e=>{i=!0}),e("blur",e=>{i=!1}),e("paste",e=>{var t;w(),_(e=e),e=(e.originalEvent||e).clipboardData.getData("text/plain").replace(/\r/g,""),t=T(),S(e),n(u),b({start:Math.min(t.start,t.end)+e.length,end:Math.min(t.start,t.end)+e.length,dir:"<-"}),w(),s&&s(D())}),{updateOptions(e){Object.assign(f,e)},updateCode(e){u.textContent=e,n(u)},onUpdate(e){s=e},toString:D,save:T,restore:b,recordHistory:w,destroy(){for(var[e,t]of r)u.removeEventListener(e,t)}}} \ No newline at end of file
+const globalWindow=window;function CodeJar(l,n,e={}){const c={tab:"\t",indentOn:/[({\[]$/,moveToNewLine:/^[)}\]]/,spellcheck:!1,catchTab:!0,preserveIdent:!0,addClosing:!0,history:!0,window:globalWindow,...e},o=c.window,f=o.document,r=[],u=[];let p=-1,a=!1,i=()=>{},h;l.setAttribute("contenteditable","plaintext-only"),l.setAttribute("spellcheck",c.spellcheck?"true":"false"),l.style.outline="none",l.style.overflowWrap="break-word",l.style.overflowY="auto",l.style.whiteSpace="pre-wrap";const d=(e,t)=>{n(e,t)};let g=!1;(g="plaintext-only"!==l.contentEditable?!0:g)&&l.setAttribute("contenteditable","true");const t=S(()=>{var e=v();d(l,e),T(e)},30);let y=!1;const N=e=>!O(e)&&!M(e)&&"Meta"!==e.key&&"Control"!==e.key&&"Alt"!==e.key&&!e.key.startsWith("Arrow"),s=S(e=>{N(e)&&(x(),y=!1)},300);e=(e,t)=>{r.push([e,t]),l.addEventListener(e,t)};function v(){var e=H();const t={start:0,end:0,dir:void 0};let{anchorNode:n,anchorOffset:r,focusNode:o,focusOffset:a}=e;if(n&&o)return n===l&&o===l?(t.start=0<r&&l.textContent?l.textContent.length:0,t.end=0<a&&l.textContent?l.textContent.length:0,t.dir=a>=r?"->":"<-"):(n.nodeType===Node.ELEMENT_NODE&&(e=f.createTextNode(""),n.insertBefore(e,n.childNodes[r]),n=e,r=0),o.nodeType===Node.ELEMENT_NODE&&(e=f.createTextNode(""),o.insertBefore(e,o.childNodes[a]),o=e,a=0),w(l,e=>{if(e===n&&e===o)return t.start+=r,t.end+=a,t.dir=r<=a?"->":"<-","stop";if(e===n){if(t.start+=r,t.dir)return"stop";t.dir="->"}else if(e===o){if(t.end+=a,t.dir)return"stop";t.dir="<-"}e.nodeType===Node.TEXT_NODE&&("->"!=t.dir&&(t.start+=e.nodeValue.length),"<-"!=t.dir)&&(t.end+=e.nodeValue.length)}),l.normalize()),t;throw"error1"}function T(n){var e=H();let r,o=0,a,i=0,d=(n.dir||(n.dir="->"),n.start<0&&(n.start=0),n.end<0&&(n.end=0),"<-"==n.dir&&({start:t,end:s}=n,n.start=s,n.end=t),0);w(l,e=>{var t;if(e.nodeType===Node.TEXT_NODE)return t=(e.nodeValue||"").length,d+t>n.start&&(r||(r=e,o=n.start-d),d+t>n.end)?(a=e,i=n.end-d,"stop"):void(d+=t)}),r||(r=l,o=l.childNodes.length),a||(a=l,i=l.childNodes.length),"<-"==n.dir&&([r,o,a,i]=[a,i,r,o]);var t,s=C(r),s=(s&&(t=f.createTextNode(""),s.parentNode?.insertBefore(t,s),r=t,o=0),C(a));s&&(t=f.createTextNode(""),s.parentNode?.insertBefore(t,s),a=t,i=0),e.setBaseAndExtent(r,o,a,i),l.normalize()}function C(e){for(;e&&e!==l;){if(e.nodeType===Node.ELEMENT_NODE){var t=e;if("false"==t.getAttribute("contenteditable"))return t}e=e.parentNode}}function E(){var e=H().getRangeAt(0),t=f.createRange();return t.selectNodeContents(l),t.setEnd(e.startContainer,e.startOffset),t.toString()}function m(){var e=H().getRangeAt(0),t=f.createRange();return t.selectNodeContents(l),t.setStart(e.endContainer,e.endOffset),t.toString()}function b(e){g&&"Enter"===e.key&&(B(e),e.stopPropagation(),""==m()?(L("\n "),(e=v()).start=--e.end,T(e)):L("\n"))}function x(){var e,t,n;a&&(e=l.innerHTML,t=v(),(n=u[p])&&n.html===e&&n.pos.start===t.start&&n.pos.end===t.end||(p++,u[p]={html:e,pos:t},u.splice(p+1),300<p&&(p=300,u.splice(0,1))))}function w(e,t){var n=[];e.firstChild&&n.push(e.firstChild);let r=n.pop();for(;r&&"stop"!==t(r);)r.nextSibling&&n.push(r.nextSibling),r.firstChild&&n.push(r.firstChild),r=n.pop()}function k(e){return e.metaKey||e.ctrlKey}function O(e){return k(e)&&!e.shiftKey&&"Z"===D(e)}function M(e){return k(e)&&e.shiftKey&&"Z"===D(e)}function D(e){e=e.key||e.keyCode||e.which;if(e)return("string"==typeof e?e:String.fromCharCode(e)).toUpperCase()}function L(e){e=e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;"),f.execCommand("insertHTML",!1,e)}function S(t,n){let r=0;return(...e)=>{clearTimeout(r),r=o.setTimeout(()=>t(...e),n)}}function A(e){let t=e.length-1;for(;0<=t&&"\n"!==e[t];)t--;let n=++t;for(;n<e.length&&/[ \t]/.test(e[n]);)n++;return[e.substring(t,n)||"",t,n]}function _(){return l.textContent||""}function B(e){e.preventDefault()}function H(){return(l.parentNode?.nodeType==Node.DOCUMENT_FRAGMENT_NODE?l.parentNode:o).getSelection()}return e("keydown",e=>{if(!e.defaultPrevented){if(h=_(),c.preserveIdent){var t=e;if("Enter"===t.key){var n=E(),r=m(),[o]=A(n);let e=o;c.indentOn.test(n)&&(e+=c.tab),0<e.length?(B(t),t.stopPropagation(),L("\n"+e)):b(t),e!==o&&c.moveToNewLine.test(r)&&(n=v(),L("\n"+o),T(n))}}else b(e);if(c.catchTab){t=e;"Tab"===t.key&&(B(t),t.shiftKey?([t,r]=A(E()),0<t.length&&(o=v(),t=Math.min(c.tab.length,t.length),T({start:r,end:r+t}),f.execCommand("delete"),o.start-=t,o.end-=t,T(o))):L(c.tab))}if(c.addClosing){var a,n=e,i=`([{'"`;i.includes(n.key)&&(B(n),a=v(),d=a.start==a.end?"":H().toString(),L(n.key+d+`)]}'"`[i.indexOf(n.key)]),a.start++,a.end++,T(a))}var d,s;c.history&&(O(d=e)&&(B(d),p--,(s=u[p])&&(l.innerHTML=s.html,T(s.pos)),p<0)&&(p=0),M(d)&&(B(d),p++,(s=u[p])&&(l.innerHTML=s.html,T(s.pos)),p>=u.length)&&p--,N(e))&&!y&&(x(),y=!0),g&&(!k(i=e)||"C"!==D(i))&&T(v())}}),e("keyup",e=>{e.defaultPrevented||e.isComposing||(h!==_()&&t(),s(e),i(_()))}),e("focus",e=>{a=!0}),e("blur",e=>{a=!1}),e("paste",e=>{var t;x(),(e=e).defaultPrevented||(B(e),e=(e.originalEvent??e).clipboardData.getData("text/plain").replace(/\r\n?/g,"\n"),t=v(),L(e),d(l),T({start:Math.min(t.start,t.end)+e.length,end:Math.min(t.start,t.end)+e.length,dir:"<-"})),x(),i(_())}),e("cut",e=>{var t,n;x(),e=e,t=v(),n=H(),(e.originalEvent??e).clipboardData.setData("text/plain",n.toString()),f.execCommand("delete"),d(l),T({start:Math.min(t.start,t.end),end:Math.min(t.start,t.end),dir:"<-"}),B(e),x(),i(_())}),{updateOptions(e){Object.assign(c,e)},updateCode(e){l.textContent=e,d(l),i(e)},onUpdate(e){i=e},toString:_,save:v,restore:T,recordHistory:x,destroy(){for(var[e,t]of r)l.removeEventListener(e,t)}}} \ No newline at end of file
diff --git a/interface/js/lib/linenumbers.min.js b/interface/js/lib/linenumbers.min.js
deleted file mode 100644
index 0dd83d0d0..000000000
--- a/interface/js/lib/linenumbers.min.js
+++ /dev/null
@@ -1,5 +0,0 @@
-/*!
- * CodeJar 3.2.2 helper: lineNumbers (https://github.com/antonmedv/codejar)
- * Copyright (c) 2020, Anton Medvedev, MIT
- */
-function withLineNumbers(e,t={}){const o=Object.assign({class:"codejar-linenumbers",wrapClass:"codejar-wrap",width:"35px",backgroundColor:"rgba(128, 128, 128, 0.15)",color:""},t);let l;return function(t){e(t),l||(l=init(t,o),t.addEventListener("scroll",()=>l.style.top=`-${t.scrollTop}px`));const n=(t.textContent||"").replace(/\n+$/,"\n").split("\n").length+1;let s="";for(let e=1;e<n;e++)s+=`${e}\n`;l.innerText=s}}function init(e,t){const o=getComputedStyle(e),l=document.createElement("div");l.className=t.wrapClass,l.style.position="relative";const n=document.createElement("div");n.className=t.class,l.appendChild(n),n.style.position="absolute",n.style.top="0px",n.style.left="0px",n.style.bottom="0px",n.style.width=t.width,n.style.overflow="hidden",n.style.backgroundColor=t.backgroundColor,n.style.color=t.color||o.color,n.style.setProperty("mix-blend-mode","difference"),n.style.fontFamily=o.fontFamily,n.style.fontSize=o.fontSize,n.style.lineHeight=o.lineHeight,n.style.paddingTop=o.paddingTop,n.style.paddingLeft=o.paddingLeft,n.style.borderTopLeftRadius=o.borderTopLeftRadius,n.style.borderBottomLeftRadius=o.borderBottomLeftRadius;const s=document.createElement("div");return s.style.position="relative",s.style.top="0px",n.appendChild(s),e.style.paddingLeft=`calc(${t.width} + ${n.style.paddingLeft})`,e.style.whiteSpace="pre",e.parentNode.insertBefore(l,e),l.appendChild(e),s} \ No newline at end of file
diff --git a/interface/js/main.js b/interface/js/main.js
index d0e904f37..4182bb2bc 100644
--- a/interface/js/main.js
+++ b/interface/js/main.js
@@ -14,7 +14,7 @@ requirejs.config({
fontawesome: "fontawesome.min",
fontawesome_solid: "solid.min",
footable: "footable.min",
- linenumbers: "linenumbers.min",
+ linenumbers: "codejar-linenumbers.min",
nprogress: "nprogress.min",
prism: "prism",
stickytabs: "jquery.stickytabs.min"
diff --git a/src/libserver/hyperscan_tools.cxx b/src/libserver/hyperscan_tools.cxx
index 4bcc68e4a..3fce3ce26 100644
--- a/src/libserver/hyperscan_tools.cxx
+++ b/src/libserver/hyperscan_tools.cxx
@@ -94,6 +94,7 @@ private:
ankerl::svector<std::string, 4> cache_dirs;
ankerl::svector<std::string, 8> cache_extensions;
ankerl::unordered_dense::set<std::string> known_cached_files;
+ bool loaded = false;
private:
hs_known_files_cache() = default;
@@ -203,7 +204,7 @@ public:
{
auto env_cleanup_disable = std::getenv("RSPAMD_NO_CLEANUP");
/* We clean dir merely if we are running from the main process */
- if (rspamd_current_worker == nullptr && env_cleanup_disable == nullptr) {
+ if (rspamd_current_worker == nullptr && env_cleanup_disable == nullptr && loaded) {
const auto *log_func = RSPAMD_LOG_FUNC;
auto cleanup_dir = [&](std::string_view dir) -> void {
for (const auto &ext: cache_extensions) {
@@ -259,6 +260,14 @@ public:
else if (rspamd_current_worker == nullptr && env_cleanup_disable != nullptr) {
msg_debug_hyperscan("disable hyperscan cleanup: env variable RSPAMD_NO_CLEANUP is set");
}
+ else if (!loaded) {
+ msg_debug_hyperscan("disable hyperscan cleanup: not loaded");
+ }
+ }
+
+ auto notice_loaded() -> void
+ {
+ loaded = true;
}
};
@@ -601,4 +610,9 @@ void rspamd_hyperscan_cleanup_maybe(void)
rspamd::util::hs_known_files_cache::get().cleanup_maybe();
}
+void rspamd_hyperscan_notice_loaded(void)
+{
+ rspamd::util::hs_known_files_cache::get().notice_loaded();
+}
+
#endif// WITH_HYPERSCAN \ No newline at end of file
diff --git a/src/libserver/hyperscan_tools.h b/src/libserver/hyperscan_tools.h
index c8dd490ab..624b7b069 100644
--- a/src/libserver/hyperscan_tools.h
+++ b/src/libserver/hyperscan_tools.h
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2022 Vsevolod Stakhov
+/*
+ * Copyright 2023 Vsevolod Stakhov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -61,6 +61,11 @@ void rspamd_hyperscan_free(rspamd_hyperscan_t *db, bool invalid);
void rspamd_hyperscan_notice_known(const char *fname);
/**
+ * Notice that hyperscan files are all loaded (e.g. in the main process), so we can cleanup old files on termination
+ */
+void rspamd_hyperscan_notice_loaded(void);
+
+/**
* Cleans up old files. This method should be called on config free (in the main process)
*/
void rspamd_hyperscan_cleanup_maybe(void);
diff --git a/src/libserver/rspamd_control.c b/src/libserver/rspamd_control.c
index 9ed78a316..986a4a2ea 100644
--- a/src/libserver/rspamd_control.c
+++ b/src/libserver/rspamd_control.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * Copyright 2023 Vsevolod Stakhov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -838,7 +838,7 @@ rspamd_srv_handler(EV_P_ ev_io *w, int revents)
{
struct rspamd_worker *worker;
static struct rspamd_srv_command cmd;
- struct rspamd_main *srv;
+ struct rspamd_main *rspamd_main;
struct rspamd_srv_reply_data *rdata;
struct msghdr msg;
struct cmsghdr *cmsg;
@@ -851,7 +851,7 @@ rspamd_srv_handler(EV_P_ ev_io *w, int revents)
if (revents == EV_READ) {
worker = (struct rspamd_worker *) w->data;
- srv = worker->srv;
+ rspamd_main = worker->srv;
iov.iov_base = &cmd;
iov.iov_len = sizeof(cmd);
memset(&msg, 0, sizeof(msg));
@@ -864,8 +864,8 @@ rspamd_srv_handler(EV_P_ ev_io *w, int revents)
if (r == -1) {
if (errno != EAGAIN) {
- msg_err("cannot read from worker's srv pipe: %s",
- strerror(errno));
+ msg_err_main("cannot read from worker's srv pipe: %s",
+ strerror(errno));
}
else {
return;
@@ -876,18 +876,18 @@ rspamd_srv_handler(EV_P_ ev_io *w, int revents)
* Usually this means that a worker is dead, so do not try to read
* anything
*/
- msg_err("cannot read from worker's srv pipe connection closed; command = %s",
- rspamd_srv_command_to_string(cmd.type));
+ msg_err_main("cannot read from worker's srv pipe connection closed; command = %s",
+ rspamd_srv_command_to_string(cmd.type));
ev_io_stop(EV_A_ w);
}
else if (r != sizeof(cmd)) {
- msg_err("cannot read from worker's srv pipe incomplete command: %d != %d; command = %s",
- (gint) r, (gint) sizeof(cmd), rspamd_srv_command_to_string(cmd.type));
+ msg_err_main("cannot read from worker's srv pipe incomplete command: %d != %d; command = %s",
+ (gint) r, (gint) sizeof(cmd), rspamd_srv_command_to_string(cmd.type));
}
else {
rdata = g_malloc0(sizeof(*rdata));
rdata->worker = worker;
- rdata->srv = srv;
+ rdata->srv = rspamd_main;
rdata->rep.id = cmd.id;
rdata->rep.type = cmd.type;
rdata->fd = -1;
@@ -899,19 +899,19 @@ rspamd_srv_handler(EV_P_ ev_io *w, int revents)
switch (cmd.type) {
case RSPAMD_SRV_SOCKETPAIR:
- spair = g_hash_table_lookup(srv->spairs, cmd.cmd.spair.pair_id);
+ spair = g_hash_table_lookup(rspamd_main->spairs, cmd.cmd.spair.pair_id);
if (spair == NULL) {
spair = g_malloc(sizeof(gint) * 2);
if (rspamd_socketpair(spair, cmd.cmd.spair.af) == -1) {
rdata->rep.reply.spair.code = errno;
- msg_err("cannot create socket pair: %s", strerror(errno));
+ msg_err_main("cannot create socket pair: %s", strerror(errno));
}
else {
nid = g_malloc(sizeof(cmd.cmd.spair.pair_id));
memcpy(nid, cmd.cmd.spair.pair_id,
sizeof(cmd.cmd.spair.pair_id));
- g_hash_table_insert(srv->spairs, nid, spair);
+ g_hash_table_insert(rspamd_main->spairs, nid, spair);
rdata->rep.reply.spair.code = 0;
rdata->fd = cmd.cmd.spair.pair_num ? spair[1] : spair[0];
}
@@ -923,14 +923,19 @@ rspamd_srv_handler(EV_P_ ev_io *w, int revents)
break;
case RSPAMD_SRV_HYPERSCAN_LOADED:
/* Load RE cache to provide it for new forks */
- if (rspamd_re_cache_is_hs_loaded(srv->cfg->re_cache) != RSPAMD_HYPERSCAN_LOADED_FULL ||
+ if (rspamd_re_cache_is_hs_loaded(rspamd_main->cfg->re_cache) != RSPAMD_HYPERSCAN_LOADED_FULL ||
cmd.cmd.hs_loaded.forced) {
rspamd_re_cache_load_hyperscan(
- srv->cfg->re_cache,
+ rspamd_main->cfg->re_cache,
cmd.cmd.hs_loaded.cache_dir,
false);
}
+ /* After getting this notice, we can clean up old hyperscan files */
+ rspamd_hyperscan_notice_loaded();
+ msg_info_main("received hyperscan cache loaded from %s",
+ cmd.cmd.hs_loaded.cache_dir);
+
/* Broadcast command to all workers */
memset(&wcmd, 0, sizeof(wcmd));
wcmd.type = RSPAMD_CONTROL_HYPERSCAN_LOADED;
@@ -938,7 +943,7 @@ rspamd_srv_handler(EV_P_ ev_io *w, int revents)
cmd.cmd.hs_loaded.cache_dir,
sizeof(wcmd.cmd.hs_loaded.cache_dir));
wcmd.cmd.hs_loaded.forced = cmd.cmd.hs_loaded.forced;
- rspamd_control_broadcast_cmd(srv, &wcmd, rfd,
+ rspamd_control_broadcast_cmd(rspamd_main, &wcmd, rfd,
rspamd_control_ignore_io_handler, NULL, worker->pid);
break;
case RSPAMD_SRV_MONITORED_CHANGE:
@@ -950,26 +955,26 @@ rspamd_srv_handler(EV_P_ ev_io *w, int revents)
sizeof(wcmd.cmd.monitored_change.tag));
wcmd.cmd.monitored_change.alive = cmd.cmd.monitored_change.alive;
wcmd.cmd.monitored_change.sender = cmd.cmd.monitored_change.sender;
- rspamd_control_broadcast_cmd(srv, &wcmd, rfd,
+ rspamd_control_broadcast_cmd(rspamd_main, &wcmd, rfd,
rspamd_control_ignore_io_handler, NULL, 0);
break;
case RSPAMD_SRV_LOG_PIPE:
memset(&wcmd, 0, sizeof(wcmd));
wcmd.type = RSPAMD_CONTROL_LOG_PIPE;
wcmd.cmd.log_pipe.type = cmd.cmd.log_pipe.type;
- rspamd_control_broadcast_cmd(srv, &wcmd, rfd,
+ rspamd_control_broadcast_cmd(rspamd_main, &wcmd, rfd,
rspamd_control_log_pipe_io_handler, NULL, 0);
break;
case RSPAMD_SRV_ON_FORK:
rdata->rep.reply.on_fork.status = 0;
- rspamd_control_handle_on_fork(&cmd, srv);
+ rspamd_control_handle_on_fork(&cmd, rspamd_main);
break;
case RSPAMD_SRV_HEARTBEAT:
worker->hb.last_event = ev_time();
rdata->rep.reply.heartbeat.status = 0;
break;
case RSPAMD_SRV_HEALTH:
- rspamd_fill_health_reply(srv, &rdata->rep);
+ rspamd_fill_health_reply(rspamd_main, &rdata->rep);
break;
case RSPAMD_SRV_NOTICE_HYPERSCAN_CACHE:
#ifdef WITH_HYPERSCAN
@@ -984,11 +989,11 @@ rspamd_srv_handler(EV_P_ ev_io *w, int revents)
/* Ensure that memcpy is safe */
G_STATIC_ASSERT(sizeof(wcmd.cmd.fuzzy_blocked) == sizeof(cmd.cmd.fuzzy_blocked));
memcpy(&wcmd.cmd.fuzzy_blocked, &cmd.cmd.fuzzy_blocked, sizeof(wcmd.cmd.fuzzy_blocked));
- rspamd_control_broadcast_cmd(srv, &wcmd, rfd,
+ rspamd_control_broadcast_cmd(rspamd_main, &wcmd, rfd,
rspamd_control_ignore_io_handler, NULL, worker->pid);
break;
default:
- msg_err("unknown command type: %d", cmd.type);
+ msg_err_main("unknown command type: %d", cmd.type);
break;
}
@@ -1008,7 +1013,7 @@ rspamd_srv_handler(EV_P_ ev_io *w, int revents)
rdata = (struct rspamd_srv_reply_data *) w->data;
worker = rdata->worker;
worker->tmp_data = NULL; /* Avoid race */
- srv = rdata->srv;
+ rspamd_main = rdata->srv;
memset(&msg, 0, sizeof(msg));
@@ -1032,13 +1037,13 @@ rspamd_srv_handler(EV_P_ ev_io *w, int revents)
r = sendmsg(w->fd, &msg, 0);
if (r == -1) {
- msg_err("cannot write to worker's srv pipe when writing reply: %s; command = %s",
- strerror(errno), rspamd_srv_command_to_string(rdata->rep.type));
+ msg_err_main("cannot write to worker's srv pipe when writing reply: %s; command = %s",
+ strerror(errno), rspamd_srv_command_to_string(rdata->rep.type));
}
else if (r != sizeof(rdata->rep)) {
- msg_err("cannot write to worker's srv pipe: %d != %d; command = %s",
- (int) r, (int) sizeof(rdata->rep),
- rspamd_srv_command_to_string(rdata->rep.type));
+ msg_err_main("cannot write to worker's srv pipe: %d != %d; command = %s",
+ (int) r, (int) sizeof(rdata->rep),
+ rspamd_srv_command_to_string(rdata->rep.type));
}
g_free(rdata);
diff --git a/test/functional/lib/rspamd.robot b/test/functional/lib/rspamd.robot
index 27dad96ee..696b5f97d 100644
--- a/test/functional/lib/rspamd.robot
+++ b/test/functional/lib/rspamd.robot
@@ -163,16 +163,20 @@ Export Rspamd Variables To Environment
Export Scoped Variables
[Arguments] ${scope} &{vars}
- FOR ${k} ${v} IN &{vars}
- IF '${scope}' == 'Test'
+ IF '${scope}' == 'Test'
+ FOR ${k} ${v} IN &{vars}
Set Test Variable ${${k}} ${v}
- ELSE IF '${scope}' == 'Suite'
+ END
+ ELSE IF '${scope}' == 'Suite'
+ FOR ${k} ${v} IN &{vars}
Set Suite Variable ${${k}} ${v}
- ELSE IF '${scope}' == 'Global'
+ END
+ ELSE IF '${scope}' == 'Global'
+ FOR ${k} ${v} IN &{vars}
Set Global Variable ${${k}} ${v}
- ELSE
- Fail message="Don't know what to do with scope: ${scope}"
END
+ ELSE
+ Fail message="Don't know what to do with scope: ${scope}"
END
Log does not contain segfault record