diff --git a/data/web/admin.php b/data/web/admin.php index e53d18fd7..a3b908b74 100644 --- a/data/web/admin.php +++ b/data/web/admin.php @@ -10,9 +10,6 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/header.inc.php'; $_SESSION['return_to'] = $_SERVER['REQUEST_URI']; $tfa_data = get_tfa(); $fido2_data = fido2(array("action" => "get_friendly_names")); -if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CACHE')) { - $_SESSION['gal'] = json_decode($license_cache, true); -} $js_minifier->add('/web/js/site/admin.js'); $js_minifier->add('/web/js/presets/rspamd.js'); @@ -89,7 +86,6 @@ $template_data = [ 'tfa_id' => @$_SESSION['tfa_id'], 'fido2_cid' => @$_SESSION['fido2_cid'], 'fido2_data' => $fido2_data, - 'gal' => @$_SESSION['gal'], 'api' => [ 'ro' => admin_api('ro', 'get'), 'rw' => admin_api('rw', 'get'), diff --git a/data/web/debug.php b/data/web/debug.php index 5618ec00b..45c4456ce 100644 --- a/data/web/debug.php +++ b/data/web/debug.php @@ -11,6 +11,11 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI']; $solr_status = (preg_match("/^([yY][eE][sS]|[yY])+$/", $_ENV["SKIP_SOLR"])) ? false : solr_status(); $clamd_status = (preg_match("/^([yY][eE][sS]|[yY])+$/", $_ENV["SKIP_CLAMD"])) ? false : true; + +if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CACHE')) { + $_SESSION['gal'] = json_decode($license_cache, true); +} + $js_minifier->add('/web/js/site/debug.js'); // vmail df @@ -54,6 +59,7 @@ $template_data = [ 'vmail_df' => $vmail_df, 'hostname' => $hostname, 'timezone' => $timezone, + 'gal' => @$_SESSION['gal'], 'license_guid' => license('guid'), 'solr_status' => $solr_status, 'solr_uptime' => round($solr_status['status']['dovecot-fts']['uptime'] / 1000 / 60 / 60), diff --git a/data/web/inc/prerequisites.inc.php b/data/web/inc/prerequisites.inc.php index 754d98d55..b3b1cc13d 100644 --- a/data/web/inc/prerequisites.inc.php +++ b/data/web/inc/prerequisites.inc.php @@ -234,7 +234,7 @@ if (!isset($_SESSION['mailcow_locale']) && !isset($_COOKIE['mailcow_locale'])) { // Try suggest match // e.g. suggest en-gb when only en-us is provided - if (!isset($_COOKIE['mailcow_locale'])) { + if (!isset($_SESSION['mailcow_locale'])) { foreach ($lang2pref as $lang => $q) { if (array_key_exists(substr($lang, 0, 2), $AVAILABLE_BASE_LANGUAGES)) { $_SESSION['mailcow_locale'] = $AVAILABLE_BASE_LANGUAGES[substr($lang, 0, 2)]; diff --git a/data/web/js/build/005-datatables.js b/data/web/js/build/004-datatables.js similarity index 100% rename from data/web/js/build/005-datatables.js rename to data/web/js/build/004-datatables.js diff --git a/data/web/js/build/004-moment.min.js b/data/web/js/build/004-moment.min.js deleted file mode 100644 index 9fb34ee07..000000000 --- a/data/web/js/build/004-moment.min.js +++ /dev/null @@ -1,7 +0,0 @@ -//! moment.js -//! version : 2.8.4 -//! authors : Tim Wood, Iskren Chernev, Moment.js contributors -//! license : MIT -//! momentjs.com -(function(a){function b(a,b,c){switch(arguments.length){case 2:return null!=a?a:b;case 3:return null!=a?a:null!=b?b:c;default:throw new Error("Implement me")}}function c(a,b){return zb.call(a,b)}function d(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1}}function e(a){tb.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+a)}function f(a,b){var c=!0;return m(function(){return c&&(e(a),c=!1),b.apply(this,arguments)},b)}function g(a,b){qc[a]||(e(b),qc[a]=!0)}function h(a,b){return function(c){return p(a.call(this,c),b)}}function i(a,b){return function(c){return this.localeData().ordinal(a.call(this,c),b)}}function j(){}function k(a,b){b!==!1&&F(a),n(this,a),this._d=new Date(+a._d)}function l(a){var b=y(a),c=b.year||0,d=b.quarter||0,e=b.month||0,f=b.week||0,g=b.day||0,h=b.hour||0,i=b.minute||0,j=b.second||0,k=b.millisecond||0;this._milliseconds=+k+1e3*j+6e4*i+36e5*h,this._days=+g+7*f,this._months=+e+3*d+12*c,this._data={},this._locale=tb.localeData(),this._bubble()}function m(a,b){for(var d in b)c(b,d)&&(a[d]=b[d]);return c(b,"toString")&&(a.toString=b.toString),c(b,"valueOf")&&(a.valueOf=b.valueOf),a}function n(a,b){var c,d,e;if("undefined"!=typeof b._isAMomentObject&&(a._isAMomentObject=b._isAMomentObject),"undefined"!=typeof b._i&&(a._i=b._i),"undefined"!=typeof b._f&&(a._f=b._f),"undefined"!=typeof b._l&&(a._l=b._l),"undefined"!=typeof b._strict&&(a._strict=b._strict),"undefined"!=typeof b._tzm&&(a._tzm=b._tzm),"undefined"!=typeof b._isUTC&&(a._isUTC=b._isUTC),"undefined"!=typeof b._offset&&(a._offset=b._offset),"undefined"!=typeof b._pf&&(a._pf=b._pf),"undefined"!=typeof b._locale&&(a._locale=b._locale),Ib.length>0)for(c in Ib)d=Ib[c],e=b[d],"undefined"!=typeof e&&(a[d]=e);return a}function o(a){return 0>a?Math.ceil(a):Math.floor(a)}function p(a,b,c){for(var d=""+Math.abs(a),e=a>=0;d.lengthd;d++)(c&&a[d]!==b[d]||!c&&A(a[d])!==A(b[d]))&&g++;return g+f}function x(a){if(a){var b=a.toLowerCase().replace(/(.)s$/,"$1");a=jc[a]||kc[b]||b}return a}function y(a){var b,d,e={};for(d in a)c(a,d)&&(b=x(d),b&&(e[b]=a[d]));return e}function z(b){var c,d;if(0===b.indexOf("week"))c=7,d="day";else{if(0!==b.indexOf("month"))return;c=12,d="month"}tb[b]=function(e,f){var g,h,i=tb._locale[b],j=[];if("number"==typeof e&&(f=e,e=a),h=function(a){var b=tb().utc().set(d,a);return i.call(tb._locale,b,e||"")},null!=f)return h(f);for(g=0;c>g;g++)j.push(h(g));return j}}function A(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=b>=0?Math.floor(b):Math.ceil(b)),c}function B(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function C(a,b,c){return hb(tb([a,11,31+b-c]),b,c).week}function D(a){return E(a)?366:365}function E(a){return a%4===0&&a%100!==0||a%400===0}function F(a){var b;a._a&&-2===a._pf.overflow&&(b=a._a[Bb]<0||a._a[Bb]>11?Bb:a._a[Cb]<1||a._a[Cb]>B(a._a[Ab],a._a[Bb])?Cb:a._a[Db]<0||a._a[Db]>24||24===a._a[Db]&&(0!==a._a[Eb]||0!==a._a[Fb]||0!==a._a[Gb])?Db:a._a[Eb]<0||a._a[Eb]>59?Eb:a._a[Fb]<0||a._a[Fb]>59?Fb:a._a[Gb]<0||a._a[Gb]>999?Gb:-1,a._pf._overflowDayOfYear&&(Ab>b||b>Cb)&&(b=Cb),a._pf.overflow=b)}function G(b){return null==b._isValid&&(b._isValid=!isNaN(b._d.getTime())&&b._pf.overflow<0&&!b._pf.empty&&!b._pf.invalidMonth&&!b._pf.nullInput&&!b._pf.invalidFormat&&!b._pf.userInvalidated,b._strict&&(b._isValid=b._isValid&&0===b._pf.charsLeftOver&&0===b._pf.unusedTokens.length&&b._pf.bigHour===a)),b._isValid}function H(a){return a?a.toLowerCase().replace("_","-"):a}function I(a){for(var b,c,d,e,f=0;f0;){if(d=J(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&w(e,c,!0)>=b-1)break;b--}f++}return null}function J(a){var b=null;if(!Hb[a]&&Jb)try{b=tb.locale(),require("./locale/"+a),tb.locale(b)}catch(c){}return Hb[a]}function K(a,b){var c,d;return b._isUTC?(c=b.clone(),d=(tb.isMoment(a)||v(a)?+a:+tb(a))-+c,c._d.setTime(+c._d+d),tb.updateOffset(c,!1),c):tb(a).local()}function L(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function M(a){var b,c,d=a.match(Nb);for(b=0,c=d.length;c>b;b++)d[b]=pc[d[b]]?pc[d[b]]:L(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function N(a,b){return a.isValid()?(b=O(b,a.localeData()),lc[b]||(lc[b]=M(b)),lc[b](a)):a.localeData().invalidDate()}function O(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(Ob.lastIndex=0;d>=0&&Ob.test(a);)a=a.replace(Ob,c),Ob.lastIndex=0,d-=1;return a}function P(a,b){var c,d=b._strict;switch(a){case"Q":return Zb;case"DDDD":return _b;case"YYYY":case"GGGG":case"gggg":return d?ac:Rb;case"Y":case"G":case"g":return cc;case"YYYYYY":case"YYYYY":case"GGGGG":case"ggggg":return d?bc:Sb;case"S":if(d)return Zb;case"SS":if(d)return $b;case"SSS":if(d)return _b;case"DDD":return Qb;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return Ub;case"a":case"A":return b._locale._meridiemParse;case"x":return Xb;case"X":return Yb;case"Z":case"ZZ":return Vb;case"T":return Wb;case"SSSS":return Tb;case"MM":case"DD":case"YY":case"GG":case"gg":case"HH":case"hh":case"mm":case"ss":case"ww":case"WW":return d?$b:Pb;case"M":case"D":case"d":case"H":case"h":case"m":case"s":case"w":case"W":case"e":case"E":return Pb;case"Do":return d?b._locale._ordinalParse:b._locale._ordinalParseLenient;default:return c=new RegExp(Y(X(a.replace("\\","")),"i"))}}function Q(a){a=a||"";var b=a.match(Vb)||[],c=b[b.length-1]||[],d=(c+"").match(hc)||["-",0,0],e=+(60*d[1])+A(d[2]);return"+"===d[0]?-e:e}function R(a,b,c){var d,e=c._a;switch(a){case"Q":null!=b&&(e[Bb]=3*(A(b)-1));break;case"M":case"MM":null!=b&&(e[Bb]=A(b)-1);break;case"MMM":case"MMMM":d=c._locale.monthsParse(b,a,c._strict),null!=d?e[Bb]=d:c._pf.invalidMonth=b;break;case"D":case"DD":null!=b&&(e[Cb]=A(b));break;case"Do":null!=b&&(e[Cb]=A(parseInt(b.match(/\d{1,2}/)[0],10)));break;case"DDD":case"DDDD":null!=b&&(c._dayOfYear=A(b));break;case"YY":e[Ab]=tb.parseTwoDigitYear(b);break;case"YYYY":case"YYYYY":case"YYYYYY":e[Ab]=A(b);break;case"a":case"A":c._isPm=c._locale.isPM(b);break;case"h":case"hh":c._pf.bigHour=!0;case"H":case"HH":e[Db]=A(b);break;case"m":case"mm":e[Eb]=A(b);break;case"s":case"ss":e[Fb]=A(b);break;case"S":case"SS":case"SSS":case"SSSS":e[Gb]=A(1e3*("0."+b));break;case"x":c._d=new Date(A(b));break;case"X":c._d=new Date(1e3*parseFloat(b));break;case"Z":case"ZZ":c._useUTC=!0,c._tzm=Q(b);break;case"dd":case"ddd":case"dddd":d=c._locale.weekdaysParse(b),null!=d?(c._w=c._w||{},c._w.d=d):c._pf.invalidWeekday=b;break;case"w":case"ww":case"W":case"WW":case"d":case"e":case"E":a=a.substr(0,1);case"gggg":case"GGGG":case"GGGGG":a=a.substr(0,2),b&&(c._w=c._w||{},c._w[a]=A(b));break;case"gg":case"GG":c._w=c._w||{},c._w[a]=tb.parseTwoDigitYear(b)}}function S(a){var c,d,e,f,g,h,i;c=a._w,null!=c.GG||null!=c.W||null!=c.E?(g=1,h=4,d=b(c.GG,a._a[Ab],hb(tb(),1,4).year),e=b(c.W,1),f=b(c.E,1)):(g=a._locale._week.dow,h=a._locale._week.doy,d=b(c.gg,a._a[Ab],hb(tb(),g,h).year),e=b(c.w,1),null!=c.d?(f=c.d,g>f&&++e):f=null!=c.e?c.e+g:g),i=ib(d,e,f,h,g),a._a[Ab]=i.year,a._dayOfYear=i.dayOfYear}function T(a){var c,d,e,f,g=[];if(!a._d){for(e=V(a),a._w&&null==a._a[Cb]&&null==a._a[Bb]&&S(a),a._dayOfYear&&(f=b(a._a[Ab],e[Ab]),a._dayOfYear>D(f)&&(a._pf._overflowDayOfYear=!0),d=db(f,0,a._dayOfYear),a._a[Bb]=d.getUTCMonth(),a._a[Cb]=d.getUTCDate()),c=0;3>c&&null==a._a[c];++c)a._a[c]=g[c]=e[c];for(;7>c;c++)a._a[c]=g[c]=null==a._a[c]?2===c?1:0:a._a[c];24===a._a[Db]&&0===a._a[Eb]&&0===a._a[Fb]&&0===a._a[Gb]&&(a._nextDay=!0,a._a[Db]=0),a._d=(a._useUTC?db:cb).apply(null,g),null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()+a._tzm),a._nextDay&&(a._a[Db]=24)}}function U(a){var b;a._d||(b=y(a._i),a._a=[b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],T(a))}function V(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function W(b){if(b._f===tb.ISO_8601)return void $(b);b._a=[],b._pf.empty=!0;var c,d,e,f,g,h=""+b._i,i=h.length,j=0;for(e=O(b._f,b._locale).match(Nb)||[],c=0;c0&&b._pf.unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),j+=d.length),pc[f]?(d?b._pf.empty=!1:b._pf.unusedTokens.push(f),R(f,d,b)):b._strict&&!d&&b._pf.unusedTokens.push(f);b._pf.charsLeftOver=i-j,h.length>0&&b._pf.unusedInput.push(h),b._pf.bigHour===!0&&b._a[Db]<=12&&(b._pf.bigHour=a),b._isPm&&b._a[Db]<12&&(b._a[Db]+=12),b._isPm===!1&&12===b._a[Db]&&(b._a[Db]=0),T(b),F(b)}function X(a){return a.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e})}function Y(a){return a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function Z(a){var b,c,e,f,g;if(0===a._f.length)return a._pf.invalidFormat=!0,void(a._d=new Date(0/0));for(f=0;fg)&&(e=g,c=b));m(a,c||b)}function $(a){var b,c,d=a._i,e=dc.exec(d);if(e){for(a._pf.iso=!0,b=0,c=fc.length;c>b;b++)if(fc[b][1].exec(d)){a._f=fc[b][0]+(e[6]||" ");break}for(b=0,c=gc.length;c>b;b++)if(gc[b][1].exec(d)){a._f+=gc[b][0];break}d.match(Vb)&&(a._f+="Z"),W(a)}else a._isValid=!1}function _(a){$(a),a._isValid===!1&&(delete a._isValid,tb.createFromInputFallback(a))}function ab(a,b){var c,d=[];for(c=0;ca&&h.setFullYear(a),h}function db(a){var b=new Date(Date.UTC.apply(null,arguments));return 1970>a&&b.setUTCFullYear(a),b}function eb(a,b){if("string"==typeof a)if(isNaN(a)){if(a=b.weekdaysParse(a),"number"!=typeof a)return null}else a=parseInt(a,10);return a}function fb(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function gb(a,b,c){var d=tb.duration(a).abs(),e=yb(d.as("s")),f=yb(d.as("m")),g=yb(d.as("h")),h=yb(d.as("d")),i=yb(d.as("M")),j=yb(d.as("y")),k=e0,k[4]=c,fb.apply({},k)}function hb(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=tb(a).add(f,"d"),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function ib(a,b,c,d,e){var f,g,h=db(a,0,1).getUTCDay();return h=0===h?7:h,c=null!=c?c:e,f=e-h+(h>d?7:0)-(e>h?7:0),g=7*(b-1)+(c-e)+f+1,{year:g>0?a:a-1,dayOfYear:g>0?g:D(a-1)+g}}function jb(b){var c,d=b._i,e=b._f;return b._locale=b._locale||tb.localeData(b._l),null===d||e===a&&""===d?tb.invalid({nullInput:!0}):("string"==typeof d&&(b._i=d=b._locale.preparse(d)),tb.isMoment(d)?new k(d,!0):(e?u(e)?Z(b):W(b):bb(b),c=new k(b),c._nextDay&&(c.add(1,"d"),c._nextDay=a),c))}function kb(a,b){var c,d;if(1===b.length&&u(b[0])&&(b=b[0]),!b.length)return tb();for(c=b[0],d=1;d=0?"+":"-";return b+p(Math.abs(a),6)},gg:function(){return p(this.weekYear()%100,2)},gggg:function(){return p(this.weekYear(),4)},ggggg:function(){return p(this.weekYear(),5)},GG:function(){return p(this.isoWeekYear()%100,2)},GGGG:function(){return p(this.isoWeekYear(),4)},GGGGG:function(){return p(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.localeData().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.localeData().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return A(this.milliseconds()/100)},SS:function(){return p(A(this.milliseconds()/10),2)},SSS:function(){return p(this.milliseconds(),3)},SSSS:function(){return p(this.milliseconds(),3)},Z:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+p(A(a/60),2)+":"+p(A(a)%60,2)},ZZ:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+p(A(a/60),2)+p(A(a)%60,2)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},x:function(){return this.valueOf()},X:function(){return this.unix()},Q:function(){return this.quarter()}},qc={},rc=["months","monthsShort","weekdays","weekdaysShort","weekdaysMin"];nc.length;)vb=nc.pop(),pc[vb+"o"]=i(pc[vb],vb);for(;oc.length;)vb=oc.pop(),pc[vb+vb]=h(pc[vb],2);pc.DDDD=h(pc.DDD,3),m(j.prototype,{set:function(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b;this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(a){return this._months[a.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(a){return this._monthsShort[a.month()]},monthsParse:function(a,b,c){var d,e,f;for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),d=0;12>d;d++){if(e=tb.utc([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(a){return this._weekdays[a.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(a){return this._weekdaysShort[a.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(a){return this._weekdaysMin[a.day()]},weekdaysParse:function(a){var b,c,d;for(this._weekdaysParse||(this._weekdaysParse=[]),b=0;7>b;b++)if(this._weekdaysParse[b]||(c=tb([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b},_longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY LT",LLLL:"dddd, MMMM D, YYYY LT"},longDateFormat:function(a){var b=this._longDateFormat[a];return!b&&this._longDateFormat[a.toUpperCase()]&&(b=this._longDateFormat[a.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a]=b),b},isPM:function(a){return"p"===(a+"").toLowerCase().charAt(0)},_meridiemParse:/[ap]\.?m?\.?/i,meridiem:function(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},calendar:function(a,b,c){var d=this._calendar[a];return"function"==typeof d?d.apply(b,[c]):d},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)},pastFuture:function(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)},ordinal:function(a){return this._ordinal.replace("%d",a)},_ordinal:"%d",_ordinalParse:/\d{1,2}/,preparse:function(a){return a},postformat:function(a){return a},week:function(a){return hb(a,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6},_invalidDate:"Invalid date",invalidDate:function(){return this._invalidDate}}),tb=function(b,c,e,f){var g;return"boolean"==typeof e&&(f=e,e=a),g={},g._isAMomentObject=!0,g._i=b,g._f=c,g._l=e,g._strict=f,g._isUTC=!1,g._pf=d(),jb(g)},tb.suppressDeprecationWarnings=!1,tb.createFromInputFallback=f("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}),tb.min=function(){var a=[].slice.call(arguments,0);return kb("isBefore",a)},tb.max=function(){var a=[].slice.call(arguments,0);return kb("isAfter",a)},tb.utc=function(b,c,e,f){var g;return"boolean"==typeof e&&(f=e,e=a),g={},g._isAMomentObject=!0,g._useUTC=!0,g._isUTC=!0,g._l=e,g._i=b,g._f=c,g._strict=f,g._pf=d(),jb(g).utc()},tb.unix=function(a){return tb(1e3*a)},tb.duration=function(a,b){var d,e,f,g,h=a,i=null;return tb.isDuration(a)?h={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(h={},b?h[b]=a:h.milliseconds=a):(i=Lb.exec(a))?(d="-"===i[1]?-1:1,h={y:0,d:A(i[Cb])*d,h:A(i[Db])*d,m:A(i[Eb])*d,s:A(i[Fb])*d,ms:A(i[Gb])*d}):(i=Mb.exec(a))?(d="-"===i[1]?-1:1,f=function(a){var b=a&&parseFloat(a.replace(",","."));return(isNaN(b)?0:b)*d},h={y:f(i[2]),M:f(i[3]),d:f(i[4]),h:f(i[5]),m:f(i[6]),s:f(i[7]),w:f(i[8])}):"object"==typeof h&&("from"in h||"to"in h)&&(g=r(tb(h.from),tb(h.to)),h={},h.ms=g.milliseconds,h.M=g.months),e=new l(h),tb.isDuration(a)&&c(a,"_locale")&&(e._locale=a._locale),e},tb.version=wb,tb.defaultFormat=ec,tb.ISO_8601=function(){},tb.momentProperties=Ib,tb.updateOffset=function(){},tb.relativeTimeThreshold=function(b,c){return mc[b]===a?!1:c===a?mc[b]:(mc[b]=c,!0)},tb.lang=f("moment.lang is deprecated. Use moment.locale instead.",function(a,b){return tb.locale(a,b)}),tb.locale=function(a,b){var c;return a&&(c="undefined"!=typeof b?tb.defineLocale(a,b):tb.localeData(a),c&&(tb.duration._locale=tb._locale=c)),tb._locale._abbr},tb.defineLocale=function(a,b){return null!==b?(b.abbr=a,Hb[a]||(Hb[a]=new j),Hb[a].set(b),tb.locale(a),Hb[a]):(delete Hb[a],null)},tb.langData=f("moment.langData is deprecated. Use moment.localeData instead.",function(a){return tb.localeData(a)}),tb.localeData=function(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return tb._locale;if(!u(a)){if(b=J(a))return b;a=[a]}return I(a)},tb.isMoment=function(a){return a instanceof k||null!=a&&c(a,"_isAMomentObject")},tb.isDuration=function(a){return a instanceof l};for(vb=rc.length-1;vb>=0;--vb)z(rc[vb]);tb.normalizeUnits=function(a){return x(a)},tb.invalid=function(a){var b=tb.utc(0/0);return null!=a?m(b._pf,a):b._pf.userInvalidated=!0,b},tb.parseZone=function(){return tb.apply(null,arguments).parseZone()},tb.parseTwoDigitYear=function(a){return A(a)+(A(a)>68?1900:2e3)},m(tb.fn=k.prototype,{clone:function(){return tb(this)},valueOf:function(){return+this._d+6e4*(this._offset||0)},unix:function(){return Math.floor(+this/1e3)},toString:function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._offset?new Date(+this):this._d},toISOString:function(){var a=tb(this).utc();return 00:!1},parsingFlags:function(){return m({},this._pf)},invalidAt:function(){return this._pf.overflow},utc:function(a){return this.zone(0,a)},local:function(a){return this._isUTC&&(this.zone(0,a),this._isUTC=!1,a&&this.add(this._dateTzOffset(),"m")),this},format:function(a){var b=N(this,a||tb.defaultFormat);return this.localeData().postformat(b)},add:s(1,"add"),subtract:s(-1,"subtract"),diff:function(a,b,c){var d,e,f,g=K(a,this),h=6e4*(this.zone()-g.zone());return b=x(b),"year"===b||"month"===b?(d=432e5*(this.daysInMonth()+g.daysInMonth()),e=12*(this.year()-g.year())+(this.month()-g.month()),f=this-tb(this).startOf("month")-(g-tb(g).startOf("month")),f-=6e4*(this.zone()-tb(this).startOf("month").zone()-(g.zone()-tb(g).startOf("month").zone())),e+=f/d,"year"===b&&(e/=12)):(d=this-g,e="second"===b?d/1e3:"minute"===b?d/6e4:"hour"===b?d/36e5:"day"===b?(d-h)/864e5:"week"===b?(d-h)/6048e5:d),c?e:o(e)},from:function(a,b){return tb.duration({to:this,from:a}).locale(this.locale()).humanize(!b)},fromNow:function(a){return this.from(tb(),a)},calendar:function(a){var b=a||tb(),c=K(b,this).startOf("day"),d=this.diff(c,"days",!0),e=-6>d?"sameElse":-1>d?"lastWeek":0>d?"lastDay":1>d?"sameDay":2>d?"nextDay":7>d?"nextWeek":"sameElse";return this.format(this.localeData().calendar(e,this,tb(b)))},isLeapYear:function(){return E(this.year())},isDST:function(){return this.zone()+a):(c=tb.isMoment(a)?+a:+tb(a),c<+this.clone().startOf(b))},isBefore:function(a,b){var c;return b=x("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=tb.isMoment(a)?a:tb(a),+a>+this):(c=tb.isMoment(a)?+a:+tb(a),+this.clone().endOf(b)a?this:a}),max:f("moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(a){return a=tb.apply(null,arguments),a>this?this:a}),zone:function(a,b){var c,d=this._offset||0;return null==a?this._isUTC?d:this._dateTzOffset():("string"==typeof a&&(a=Q(a)),Math.abs(a)<16&&(a=60*a),!this._isUTC&&b&&(c=this._dateTzOffset()),this._offset=a,this._isUTC=!0,null!=c&&this.subtract(c,"m"),d!==a&&(!b||this._changeInProgress?t(this,tb.duration(d-a,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,tb.updateOffset(this,!0),this._changeInProgress=null)),this)},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},parseZone:function(){return this._tzm?this.zone(this._tzm):"string"==typeof this._i&&this.zone(this._i),this},hasAlignedHourOffset:function(a){return a=a?tb(a).zone():0,(this.zone()-a)%60===0},daysInMonth:function(){return B(this.year(),this.month())},dayOfYear:function(a){var b=yb((tb(this).startOf("day")-tb(this).startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")},quarter:function(a){return null==a?Math.ceil((this.month()+1)/3):this.month(3*(a-1)+this.month()%3)},weekYear:function(a){var b=hb(this,this.localeData()._week.dow,this.localeData()._week.doy).year;return null==a?b:this.add(a-b,"y")},isoWeekYear:function(a){var b=hb(this,1,4).year;return null==a?b:this.add(a-b,"y")},week:function(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")},isoWeek:function(a){var b=hb(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")},weekday:function(a){var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")},isoWeekday:function(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)},isoWeeksInYear:function(){return C(this.year(),1,4)},weeksInYear:function(){var a=this.localeData()._week;return C(this.year(),a.dow,a.doy)},get:function(a){return a=x(a),this[a]()},set:function(a,b){return a=x(a),"function"==typeof this[a]&&this[a](b),this},locale:function(b){var c;return b===a?this._locale._abbr:(c=tb.localeData(b),null!=c&&(this._locale=c),this)},lang:f("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(b){return b===a?this.localeData():this.locale(b)}),localeData:function(){return this._locale},_dateTzOffset:function(){return 15*Math.round(this._d.getTimezoneOffset()/15)}}),tb.fn.millisecond=tb.fn.milliseconds=ob("Milliseconds",!1),tb.fn.second=tb.fn.seconds=ob("Seconds",!1),tb.fn.minute=tb.fn.minutes=ob("Minutes",!1),tb.fn.hour=tb.fn.hours=ob("Hours",!0),tb.fn.date=ob("Date",!0),tb.fn.dates=f("dates accessor is deprecated. Use date instead.",ob("Date",!0)),tb.fn.year=ob("FullYear",!0),tb.fn.years=f("years accessor is deprecated. Use year instead.",ob("FullYear",!0)),tb.fn.days=tb.fn.day,tb.fn.months=tb.fn.month,tb.fn.weeks=tb.fn.week,tb.fn.isoWeeks=tb.fn.isoWeek,tb.fn.quarters=tb.fn.quarter,tb.fn.toJSON=tb.fn.toISOString,m(tb.duration.fn=l.prototype,{_bubble:function(){var a,b,c,d=this._milliseconds,e=this._days,f=this._months,g=this._data,h=0;g.milliseconds=d%1e3,a=o(d/1e3),g.seconds=a%60,b=o(a/60),g.minutes=b%60,c=o(b/60),g.hours=c%24,e+=o(c/24),h=o(pb(e)),e-=o(qb(h)),f+=o(e/30),e%=30,h+=o(f/12),f%=12,g.days=e,g.months=f,g.years=h},abs:function(){return this._milliseconds=Math.abs(this._milliseconds),this._days=Math.abs(this._days),this._months=Math.abs(this._months),this._data.milliseconds=Math.abs(this._data.milliseconds),this._data.seconds=Math.abs(this._data.seconds),this._data.minutes=Math.abs(this._data.minutes),this._data.hours=Math.abs(this._data.hours),this._data.months=Math.abs(this._data.months),this._data.years=Math.abs(this._data.years),this},weeks:function(){return o(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*A(this._months/12)},humanize:function(a){var b=gb(this,!a,this.localeData());return a&&(b=this.localeData().pastFuture(+this,b)),this.localeData().postformat(b)},add:function(a,b){var c=tb.duration(a,b);return this._milliseconds+=c._milliseconds,this._days+=c._days,this._months+=c._months,this._bubble(),this},subtract:function(a,b){var c=tb.duration(a,b);return this._milliseconds-=c._milliseconds,this._days-=c._days,this._months-=c._months,this._bubble(),this},get:function(a){return a=x(a),this[a.toLowerCase()+"s"]()},as:function(a){var b,c;if(a=x(a),"month"===a||"year"===a)return b=this._days+this._milliseconds/864e5,c=this._months+12*pb(b),"month"===a?c:c/12;switch(b=this._days+Math.round(qb(this._months/12)),a){case"week":return b/7+this._milliseconds/6048e5;case"day":return b+this._milliseconds/864e5;case"hour":return 24*b+this._milliseconds/36e5;case"minute":return 24*b*60+this._milliseconds/6e4;case"second":return 24*b*60*60+this._milliseconds/1e3; -case"millisecond":return Math.floor(24*b*60*60*1e3)+this._milliseconds;default:throw new Error("Unknown unit "+a)}},lang:tb.fn.lang,locale:tb.fn.locale,toIsoString:f("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",function(){return this.toISOString()}),toISOString:function(){var a=Math.abs(this.years()),b=Math.abs(this.months()),c=Math.abs(this.days()),d=Math.abs(this.hours()),e=Math.abs(this.minutes()),f=Math.abs(this.seconds()+this.milliseconds()/1e3);return this.asSeconds()?(this.asSeconds()<0?"-":"")+"P"+(a?a+"Y":"")+(b?b+"M":"")+(c?c+"D":"")+(d||e||f?"T":"")+(d?d+"H":"")+(e?e+"M":"")+(f?f+"S":""):"P0D"},localeData:function(){return this._locale}}),tb.duration.fn.toString=tb.duration.fn.toISOString;for(vb in ic)c(ic,vb)&&rb(vb.toLowerCase());tb.duration.fn.asMilliseconds=function(){return this.as("ms")},tb.duration.fn.asSeconds=function(){return this.as("s")},tb.duration.fn.asMinutes=function(){return this.as("m")},tb.duration.fn.asHours=function(){return this.as("h")},tb.duration.fn.asDays=function(){return this.as("d")},tb.duration.fn.asWeeks=function(){return this.as("weeks")},tb.duration.fn.asMonths=function(){return this.as("M")},tb.duration.fn.asYears=function(){return this.as("y")},tb.locale("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===A(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),Jb?module.exports=tb:"function"==typeof define&&define.amd?(define("moment",function(a,b,c){return c.config&&c.config()&&c.config().noGlobal===!0&&(xb.moment=ub),tb}),sb(!0)):sb()}).call(this); \ No newline at end of file diff --git a/data/web/js/build/007-notifications.min.js b/data/web/js/build/005-notifications.min.js similarity index 100% rename from data/web/js/build/007-notifications.min.js rename to data/web/js/build/005-notifications.min.js diff --git a/data/web/js/build/006-datetime-moment.js b/data/web/js/build/006-datetime-moment.js deleted file mode 100644 index 52b537c07..000000000 --- a/data/web/js/build/006-datetime-moment.js +++ /dev/null @@ -1,70 +0,0 @@ -/** - * This plug-in for DataTables represents the ultimate option in extensibility - * for sorting date / time strings correctly. It uses - * [Moment.js](http://momentjs.com) to create automatic type detection and - * sorting plug-ins for DataTables based on a given format. This way, DataTables - * will automatically detect your temporal information and sort it correctly. - * - * For usage instructions, please see the DataTables blog - * post that [introduces it](//datatables.net/blog/2014-12-18). - * - * @name Ultimate Date / Time sorting - * @summary Sort date and time in any format using Moment.js - * @author [Allan Jardine](//datatables.net) - * @depends DataTables 1.10+, Moment.js 1.7+ - * - * @example - * $.fn.dataTable.moment( 'HH:mm MMM D, YY' ); - * $.fn.dataTable.moment( 'dddd, MMMM Do, YYYY' ); - * - * $('#example').DataTable(); - */ - -(function (factory) { - if (typeof define === "function" && define.amd) { - define(["jquery", "moment", "datatables.net"], factory); - } else { - factory(jQuery, moment); - } -}(function ($, moment) { - -function strip (d) { - if ( typeof d === 'string' ) { - // Strip HTML tags and newline characters if possible - d = d.replace(/(<.*?>)|(\r?\n|\r)/g, ''); - - // Strip out surrounding white space - d = d.trim(); - } - - return d; -} - -$.fn.dataTable.moment = function ( format, locale, reverseEmpties ) { - var types = $.fn.dataTable.ext.type; - - // Add type detection - types.detect.unshift( function ( d ) { - d = strip(d); - - // Null and empty values are acceptable - if ( d === '' || d === null ) { - return 'moment-'+format; - } - - return moment( d, format, locale, true ).isValid() ? - 'moment-'+format : - null; - } ); - - // Add sorting method - use an integer for the sorting - types.order[ 'moment-'+format+'-pre' ] = function ( d ) { - d = strip(d); - - return !moment(d, format, locale, true).isValid() ? - (reverseEmpties ? -Infinity : Infinity) : - parseInt( moment( d, format, locale, true ).format( 'x' ), 10 ); - }; -}; - -})); diff --git a/data/web/js/build/008-formcache.min.js b/data/web/js/build/006-formcache.min.js similarity index 100% rename from data/web/js/build/008-formcache.min.js rename to data/web/js/build/006-formcache.min.js diff --git a/data/web/js/build/009-chart.js b/data/web/js/build/007-chart.js similarity index 100% rename from data/web/js/build/009-chart.js rename to data/web/js/build/007-chart.js diff --git a/data/web/js/build/010-chartjs-plugin-datalabels.js b/data/web/js/build/008-chartjs-plugin-datalabels.js similarity index 100% rename from data/web/js/build/010-chartjs-plugin-datalabels.js rename to data/web/js/build/008-chartjs-plugin-datalabels.js diff --git a/data/web/js/build/011-numberedtextarea.min.js b/data/web/js/build/009-numberedtextarea.min.js similarity index 100% rename from data/web/js/build/011-numberedtextarea.min.js rename to data/web/js/build/009-numberedtextarea.min.js diff --git a/data/web/js/build/012-sha1.min.js b/data/web/js/build/010-sha1.min.js similarity index 100% rename from data/web/js/build/012-sha1.min.js rename to data/web/js/build/010-sha1.min.js diff --git a/data/web/js/build/013-api.js b/data/web/js/build/011-api.js similarity index 100% rename from data/web/js/build/013-api.js rename to data/web/js/build/011-api.js diff --git a/data/web/js/build/014-markdown-it.min.js b/data/web/js/build/012-markdown-it.min.js similarity index 100% rename from data/web/js/build/014-markdown-it.min.js rename to data/web/js/build/012-markdown-it.min.js diff --git a/data/web/js/build/015-mailcow.js b/data/web/js/build/013-mailcow.js similarity index 96% rename from data/web/js/build/015-mailcow.js rename to data/web/js/build/013-mailcow.js index 1532ee54d..c734c8249 100644 --- a/data/web/js/build/015-mailcow.js +++ b/data/web/js/build/013-mailcow.js @@ -1,354 +1,353 @@ -$(document).ready(function() { - // mailcow alert box generator - window.mailcow_alert_box = function(message, type) { - msg = $('').text(message).text(); - if (type == 'danger' || type == 'info') { - auto_hide = 0; - $('#' + localStorage.getItem("add_modal")).modal('show'); - localStorage.removeItem("add_modal"); - } else { - auto_hide = 5000; - } - $.notify({message: msg},{z_index: 20000, delay: auto_hide, type: type,placement: {from: "bottom",align: "right"},animate: {enter: 'animated fadeInUp',exit: 'animated fadeOutDown'}}); - } - - $(".generate_password").click(function( event ) { - event.preventDefault(); - $('[data-hibp]').trigger('input'); - if (typeof($(this).closest("form").data('pwgen-length')) == "number") { - var random_passwd = GPW.pronounceable($(this).closest("form").data('pwgen-length')) - } - else { - var random_passwd = GPW.pronounceable(8) - } - $(this).closest("form").find('[data-pwgen-field]').attr('type', 'text'); - $(this).closest("form").find('[data-pwgen-field]').val(random_passwd); - }); - function str_rot13(str) { - return (str + '').replace(/[a-z]/gi, function(s){ - return String.fromCharCode(s.charCodeAt(0) + (s.toLowerCase() < 'n' ? 13 : -13)) - }) - } - $(".rot-enc").html(function(){ - return str_rot13($(this).html()) - }); - // https://stackoverflow.com/questions/4399005/implementing-jquerys-shake-effect-with-animate - function shake(div,interval,distance,times) { - if(typeof interval === 'undefined') { - interval = 100; - } - if(typeof distance === 'undefined') { - distance = 10; - } - if(typeof times === 'undefined') { - times = 4; - } - $(div).css('position','relative'); - for(var iter=0;iter<(times+1);iter++){ - $(div).animate({ left: ((iter%2==0 ? distance : distance*-1))}, interval); - } - $(div).animate({ left: 0},interval); - } - - // form cache - $('[data-cached-form="true"]').formcache({key: $(this).data('id')}); - - // tooltips - $(function () { - $('[data-bs-toggle="tooltip"]').tooltip() - }); - - // remember last navigation pill - (function () { - 'use strict'; - // remember desktop tabs - $('button[data-bs-toggle="tab"]').on('click', function (e) { - if ($(this).data('dont-remember') == 1) { - return true; - } - var id = $(this).parents('[role="tablist"]').attr('id'); - var key = 'lastTag'; - if (id) { - key += ':' + id; - } - - var tab_id = $(e.target).attr('data-bs-target').substring(1); - localStorage.setItem(key, tab_id); - }); - // remember mobile tabs - $('button[data-bs-target^="#collapse-tab-"]').on('click', function (e) { - // only remember tab if its being opened - if ($(this).hasClass('collapsed')) return false; - var tab_id = $(this).closest('div[role="tabpanel"]').attr('id'); - - if ($(this).data('dont-remember') == 1) { - return true; - } - var id = $(this).parents('[role="tablist"]').attr('id');; - var key = 'lastTag'; - if (id) { - key += ':' + id; - } - - localStorage.setItem(key, tab_id); - }); - // open last tab - $('[role="tablist"]').each(function (idx, elem) { - var id = $(elem).attr('id'); - var key = 'lastTag'; - if (id) { - key += ':' + id; - } - var lastTab = localStorage.getItem(key); - if (lastTab) { - $('[data-bs-target="#' + lastTab + '"]').click(); - var tab = $('[id^="' + lastTab + '"]'); - $(tab).find('.card-body.collapse').collapse('show'); - } - }); - })(); - - // IE fix to hide scrollbars when table body is empty - $('tbody').filter(function (index) { - return $(this).children().length < 1; - }).remove(); - - // selectpicker - $('select').selectpicker({ - 'styleBase': 'btn btn-xs-lg', - 'noneSelectedText': lang_footer.nothing_selected - }); - - // haveibeenpwned and passwd policy - $.ajax({ - url: '/api/v1/get/passwordpolicy/html', - type: 'GET', - success: function(res) { - $(".hibp-out").after(res); - } - }); - $('[data-hibp]').after('

' + lang_footer.hibp_check + '

'); - $('[data-hibp]').on('input', function() { - out_field = $(this).next('.haveibeenpwned').next('.hibp-out').text('').attr('class', 'hibp-out'); - }); - $('.haveibeenpwned:not(.task-running)').on('click', function() { - var hibp_field = $(this) - $(hibp_field).addClass('task-running'); - var hibp_result = $(hibp_field).next('.hibp-out') - var password_field = $(this).prev('[data-hibp]') - if ($(password_field).val() == '') { - shake(password_field); - } - else { - $(hibp_result).attr('class', 'hibp-out badge fs-5 bg-info'); - $(hibp_result).text(lang_footer.loading); - var password_digest = $.sha1($(password_field).val()) - var digest_five = password_digest.substring(0, 5).toUpperCase(); - var queryURL = "https://api.pwnedpasswords.com/range/" + digest_five; - var compl_digest = password_digest.substring(5, 41).toUpperCase(); - $.ajax({ - url: queryURL, - type: 'GET', - success: function(res) { - if (res.search(compl_digest) > -1){ - $(hibp_result).removeClass('badge fs-5 bg-info').addClass('badge fs-5 bg-danger'); - $(hibp_result).text(lang_footer.hibp_nok) - } else { - $(hibp_result).removeClass('badge fs-5 bg-info').addClass('badge fs-5 bg-success'); - $(hibp_result).text(lang_footer.hibp_ok) - } - $(hibp_field).removeClass('task-running'); - }, - error: function(xhr, status, error) { - $(hibp_result).removeClass('badge fs-5 bg-info').addClass('badge fs-5 bg-warning'); - $(hibp_result).text('API error: ' + xhr.responseText) - $(hibp_field).removeClass('task-running'); - } - }); - } - }); - - // Disable disallowed inputs - $('[data-acl="0"]').each(function(event){ - if ($(this).is("a")) { - $(this).removeAttr("data-bs-toggle"); - $(this).removeAttr("data-bs-target"); - $(this).removeAttr("data-action"); - $(this).click(function(event) { - event.preventDefault(); - }); - } - if ($(this).is("select")) { - $(this).selectpicker('destroy'); - $(this).replaceWith(function() { - return ''; - }); - } - if ($(this).hasClass('btn-group')) { - $(this).find('a').each(function(){ - $(this).removeClass('dropdown-toggle') - .removeAttr('data-bs-toggle') - .removeAttr('data-bs-target') - .removeAttr('data-action') - .removeAttr('id') - .attr("disabled", true); - $(this).click(function(event) { - event.preventDefault(); - return; - }); - }); - $(this).find('button').each(function() { - $(this).attr("disabled", true); - }); - } else if ($(this).hasClass('input-group')) { - $(this).find('input').each(function() { - $(this).removeClass('dropdown-toggle') - .removeAttr('data-bs-toggle') - .attr("disabled", true); - $(this).click(function(event) { - event.preventDefault(); - }); - }); - $(this).find('button').each(function() { - $(this).attr("disabled", true); - }); - } else if ($(this).hasClass('form-group')) { - $(this).find('input').each(function() { - $(this).attr("disabled", true); - }); - } else if ($(this).hasClass('btn')) { - $(this).attr("disabled", true); - } else if ($(this).attr('data-provide') == 'slider') { - $(this).attr('disabled', true); - } else if ($(this).is(':checkbox')) { - $(this).attr("disabled", true); - } - $(this).data("toggle", "tooltip"); - $(this).attr("title", lang_acl.prohibited); - $(this).tooltip(); - }); - - // disable submit after submitting form (not API driven buttons) - $('form').submit(function() { - if ($('form button[type="submit"]').data('submitted') == '1') { - return false; - } else { - $(this).find('button[type="submit"]').first().text(lang_footer.loading); - $('form button[type="submit"]').attr('data-submitted', '1'); - function disableF5(e) { if ((e.which || e.keyCode) == 116 || (e.which || e.keyCode) == 82) e.preventDefault(); }; - $(document).on("keydown", disableF5); - } - }); - // Textarea line numbers - $(".textarea-code").numberedtextarea({allowTabChar: true}); - // trigger container restart - $('#RestartContainer').on('show.bs.modal', function(e) { - var container = $(e.relatedTarget).data('container'); - $('#containerName').text(container); - $('#triggerRestartContainer').click(function(){ - $(this).prop("disabled",true); - $(this).html('
Loading...
'); - $('#statusTriggerRestartContainer').html(lang_footer.restarting_container); - $.ajax({ - method: 'get', - url: '/inc/ajax/container_ctrl.php', - timeout: docker_timeout, - data: { - 'service': container, - 'action': 'restart' - } - }) - .always( function (data, status) { - $('#statusTriggerRestartContainer').append(data); - var htmlResponse = $.parseHTML(data) - if ($(htmlResponse).find('span').hasClass('text-success')) { - $('#triggerRestartContainer').html(' '); - setTimeout(function(){ - $('#RestartContainer').modal('toggle'); - window.location = window.location.href.split("#")[0]; - }, 1200); - } else { - $('#triggerRestartContainer').html(' '); - } - }) - }); - }) - - // Jquery Datatables, enable responsive plugin and date sort plugin - $.extend($.fn.dataTable.defaults, { - responsive: true - }); - $.fn.dataTable.moment('dd:mm:YYYY'); - - // tag boxes - $('.tag-box .tag-add').click(function(){ - addTag(this); - }); - $(".tag-box .tag-input").keydown(function (e) { - if (e.which == 13){ - e.preventDefault(); - addTag(this); - } - }); - - // Dark Mode Loader - $('#dark-mode-toggle').click(toggleDarkMode); - if ($('#dark-mode-theme').length) { - $('#dark-mode-toggle').prop('checked', true); - if ($('#rspamd_logo').length) $('#rspamd_logo').attr('src', '/img/rspamd_logo_light.png'); - if ($('#rspamd_logo_sm').length) $('#rspamd_logo_sm').attr('src', '/img/rspamd_logo_light.png'); - } - function toggleDarkMode(){ - if($('#dark-mode-theme').length){ - $('#dark-mode-theme').remove(); - $('#dark-mode-toggle').prop('checked', false); - if ($('#rspamd_logo').length) $('#rspamd_logo').attr('src', '/img/rspamd_logo_dark.png'); - if ($('#rspamd_logo_sm').length) $('#rspamd_logo_sm').attr('src', '/img/rspamd_logo_dark.png'); - localStorage.setItem('theme', 'light'); - }else{ - $('head').append(''); - $('#dark-mode-toggle').prop('checked', true); - if ($('#rspamd_logo').length) $('#rspamd_logo').attr('src', '/img/rspamd_logo_light.png'); - if ($('#rspamd_logo_sm').length) $('#rspamd_logo_sm').attr('src', '/img/rspamd_logo_light.png'); - localStorage.setItem('theme', 'dark'); - } - } -}); - - -// https://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery -function escapeHtml(n){var entityMap={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="}; return String(n).replace(/[&<>"'`=\/]/g,function(n){return entityMap[n]})} -function unescapeHtml(t){var n={"&":"&","<":"<",">":">",""":'"',"'":"'","/":"/","`":"`","=":"="};return String(t).replace(/&|<|>|"|'|/|`|=/g,function(t){return n[t]})} - -function addTag(tagAddElem, tag = null){ - var tagboxElem = $(tagAddElem).parent(); - var tagInputElem = $(tagboxElem).find(".tag-input")[0]; - var tagValuesElem = $(tagboxElem).find(".tag-values")[0]; - - if (!tag) - tag = $(tagInputElem).val(); - if (!tag) return; - var value_tags = []; - try { - value_tags = JSON.parse($(tagValuesElem).val()); - } catch {} - if (!Array.isArray(value_tags)) value_tags = []; - if (value_tags.includes(tag)) return; - - $(' ' + escapeHtml(tag) + '').insertBefore('.tag-input').click(function(){ - var del_tag = unescapeHtml($(this).text()); - var del_tags = []; - try { - del_tags = JSON.parse($(tagValuesElem).val()); - } catch {} - if (Array.isArray(del_tags)){ - del_tags.splice(del_tags.indexOf(del_tag), 1); - $(tagValuesElem).val(JSON.stringify(del_tags)); - } - $(this).remove(); - }); - - value_tags.push(tag); - $(tagValuesElem).val(JSON.stringify(value_tags)); - $(tagInputElem).val(''); -} \ No newline at end of file +$(document).ready(function() { + // mailcow alert box generator + window.mailcow_alert_box = function(message, type) { + msg = $('').text(message).text(); + if (type == 'danger' || type == 'info') { + auto_hide = 0; + $('#' + localStorage.getItem("add_modal")).modal('show'); + localStorage.removeItem("add_modal"); + } else { + auto_hide = 5000; + } + $.notify({message: msg},{z_index: 20000, delay: auto_hide, type: type,placement: {from: "bottom",align: "right"},animate: {enter: 'animated fadeInUp',exit: 'animated fadeOutDown'}}); + } + + $(".generate_password").click(function( event ) { + event.preventDefault(); + $('[data-hibp]').trigger('input'); + if (typeof($(this).closest("form").data('pwgen-length')) == "number") { + var random_passwd = GPW.pronounceable($(this).closest("form").data('pwgen-length')) + } + else { + var random_passwd = GPW.pronounceable(8) + } + $(this).closest("form").find('[data-pwgen-field]').attr('type', 'text'); + $(this).closest("form").find('[data-pwgen-field]').val(random_passwd); + }); + function str_rot13(str) { + return (str + '').replace(/[a-z]/gi, function(s){ + return String.fromCharCode(s.charCodeAt(0) + (s.toLowerCase() < 'n' ? 13 : -13)) + }) + } + $(".rot-enc").html(function(){ + return str_rot13($(this).html()) + }); + // https://stackoverflow.com/questions/4399005/implementing-jquerys-shake-effect-with-animate + function shake(div,interval,distance,times) { + if(typeof interval === 'undefined') { + interval = 100; + } + if(typeof distance === 'undefined') { + distance = 10; + } + if(typeof times === 'undefined') { + times = 4; + } + $(div).css('position','relative'); + for(var iter=0;iter<(times+1);iter++){ + $(div).animate({ left: ((iter%2==0 ? distance : distance*-1))}, interval); + } + $(div).animate({ left: 0},interval); + } + + // form cache + $('[data-cached-form="true"]').formcache({key: $(this).data('id')}); + + // tooltips + $(function () { + $('[data-bs-toggle="tooltip"]').tooltip() + }); + + // remember last navigation pill + (function () { + 'use strict'; + // remember desktop tabs + $('button[data-bs-toggle="tab"]').on('click', function (e) { + if ($(this).data('dont-remember') == 1) { + return true; + } + var id = $(this).parents('[role="tablist"]').attr('id'); + var key = 'lastTag'; + if (id) { + key += ':' + id; + } + + var tab_id = $(e.target).attr('data-bs-target').substring(1); + localStorage.setItem(key, tab_id); + }); + // remember mobile tabs + $('button[data-bs-target^="#collapse-tab-"]').on('click', function (e) { + // only remember tab if its being opened + if ($(this).hasClass('collapsed')) return false; + var tab_id = $(this).closest('div[role="tabpanel"]').attr('id'); + + if ($(this).data('dont-remember') == 1) { + return true; + } + var id = $(this).parents('[role="tablist"]').attr('id');; + var key = 'lastTag'; + if (id) { + key += ':' + id; + } + + localStorage.setItem(key, tab_id); + }); + // open last tab + $('[role="tablist"]').each(function (idx, elem) { + var id = $(elem).attr('id'); + var key = 'lastTag'; + if (id) { + key += ':' + id; + } + var lastTab = localStorage.getItem(key); + if (lastTab) { + $('[data-bs-target="#' + lastTab + '"]').click(); + var tab = $('[id^="' + lastTab + '"]'); + $(tab).find('.card-body.collapse').collapse('show'); + } + }); + })(); + + // IE fix to hide scrollbars when table body is empty + $('tbody').filter(function (index) { + return $(this).children().length < 1; + }).remove(); + + // selectpicker + $('select').selectpicker({ + 'styleBase': 'btn btn-xs-lg', + 'noneSelectedText': lang_footer.nothing_selected + }); + + // haveibeenpwned and passwd policy + $.ajax({ + url: '/api/v1/get/passwordpolicy/html', + type: 'GET', + success: function(res) { + $(".hibp-out").after(res); + } + }); + $('[data-hibp]').after('

' + lang_footer.hibp_check + '

'); + $('[data-hibp]').on('input', function() { + out_field = $(this).next('.haveibeenpwned').next('.hibp-out').text('').attr('class', 'hibp-out'); + }); + $('.haveibeenpwned:not(.task-running)').on('click', function() { + var hibp_field = $(this) + $(hibp_field).addClass('task-running'); + var hibp_result = $(hibp_field).next('.hibp-out') + var password_field = $(this).prev('[data-hibp]') + if ($(password_field).val() == '') { + shake(password_field); + } + else { + $(hibp_result).attr('class', 'hibp-out badge fs-5 bg-info'); + $(hibp_result).text(lang_footer.loading); + var password_digest = $.sha1($(password_field).val()) + var digest_five = password_digest.substring(0, 5).toUpperCase(); + var queryURL = "https://api.pwnedpasswords.com/range/" + digest_five; + var compl_digest = password_digest.substring(5, 41).toUpperCase(); + $.ajax({ + url: queryURL, + type: 'GET', + success: function(res) { + if (res.search(compl_digest) > -1){ + $(hibp_result).removeClass('badge fs-5 bg-info').addClass('badge fs-5 bg-danger'); + $(hibp_result).text(lang_footer.hibp_nok) + } else { + $(hibp_result).removeClass('badge fs-5 bg-info').addClass('badge fs-5 bg-success'); + $(hibp_result).text(lang_footer.hibp_ok) + } + $(hibp_field).removeClass('task-running'); + }, + error: function(xhr, status, error) { + $(hibp_result).removeClass('badge fs-5 bg-info').addClass('badge fs-5 bg-warning'); + $(hibp_result).text('API error: ' + xhr.responseText) + $(hibp_field).removeClass('task-running'); + } + }); + } + }); + + // Disable disallowed inputs + $('[data-acl="0"]').each(function(event){ + if ($(this).is("a")) { + $(this).removeAttr("data-bs-toggle"); + $(this).removeAttr("data-bs-target"); + $(this).removeAttr("data-action"); + $(this).click(function(event) { + event.preventDefault(); + }); + } + if ($(this).is("select")) { + $(this).selectpicker('destroy'); + $(this).replaceWith(function() { + return ''; + }); + } + if ($(this).hasClass('btn-group')) { + $(this).find('a').each(function(){ + $(this).removeClass('dropdown-toggle') + .removeAttr('data-bs-toggle') + .removeAttr('data-bs-target') + .removeAttr('data-action') + .removeAttr('id') + .attr("disabled", true); + $(this).click(function(event) { + event.preventDefault(); + return; + }); + }); + $(this).find('button').each(function() { + $(this).attr("disabled", true); + }); + } else if ($(this).hasClass('input-group')) { + $(this).find('input').each(function() { + $(this).removeClass('dropdown-toggle') + .removeAttr('data-bs-toggle') + .attr("disabled", true); + $(this).click(function(event) { + event.preventDefault(); + }); + }); + $(this).find('button').each(function() { + $(this).attr("disabled", true); + }); + } else if ($(this).hasClass('form-group')) { + $(this).find('input').each(function() { + $(this).attr("disabled", true); + }); + } else if ($(this).hasClass('btn')) { + $(this).attr("disabled", true); + } else if ($(this).attr('data-provide') == 'slider') { + $(this).attr('disabled', true); + } else if ($(this).is(':checkbox')) { + $(this).attr("disabled", true); + } + $(this).data("toggle", "tooltip"); + $(this).attr("title", lang_acl.prohibited); + $(this).tooltip(); + }); + + // disable submit after submitting form (not API driven buttons) + $('form').submit(function() { + if ($('form button[type="submit"]').data('submitted') == '1') { + return false; + } else { + $(this).find('button[type="submit"]').first().text(lang_footer.loading); + $('form button[type="submit"]').attr('data-submitted', '1'); + function disableF5(e) { if ((e.which || e.keyCode) == 116 || (e.which || e.keyCode) == 82) e.preventDefault(); }; + $(document).on("keydown", disableF5); + } + }); + // Textarea line numbers + $(".textarea-code").numberedtextarea({allowTabChar: true}); + // trigger container restart + $('#RestartContainer').on('show.bs.modal', function(e) { + var container = $(e.relatedTarget).data('container'); + $('#containerName').text(container); + $('#triggerRestartContainer').click(function(){ + $(this).prop("disabled",true); + $(this).html('
Loading...
'); + $('#statusTriggerRestartContainer').html(lang_footer.restarting_container); + $.ajax({ + method: 'get', + url: '/inc/ajax/container_ctrl.php', + timeout: docker_timeout, + data: { + 'service': container, + 'action': 'restart' + } + }) + .always( function (data, status) { + $('#statusTriggerRestartContainer').append(data); + var htmlResponse = $.parseHTML(data) + if ($(htmlResponse).find('span').hasClass('text-success')) { + $('#triggerRestartContainer').html(' '); + setTimeout(function(){ + $('#RestartContainer').modal('toggle'); + window.location = window.location.href.split("#")[0]; + }, 1200); + } else { + $('#triggerRestartContainer').html(' '); + } + }) + }); + }) + + // Jquery Datatables, enable responsive plugin + $.extend($.fn.dataTable.defaults, { + responsive: true + }); + + // tag boxes + $('.tag-box .tag-add').click(function(){ + addTag(this); + }); + $(".tag-box .tag-input").keydown(function (e) { + if (e.which == 13){ + e.preventDefault(); + addTag(this); + } + }); + + // Dark Mode Loader + $('#dark-mode-toggle').click(toggleDarkMode); + if ($('#dark-mode-theme').length) { + $('#dark-mode-toggle').prop('checked', true); + if ($('#rspamd_logo').length) $('#rspamd_logo').attr('src', '/img/rspamd_logo_light.png'); + if ($('#rspamd_logo_sm').length) $('#rspamd_logo_sm').attr('src', '/img/rspamd_logo_light.png'); + } + function toggleDarkMode(){ + if($('#dark-mode-theme').length){ + $('#dark-mode-theme').remove(); + $('#dark-mode-toggle').prop('checked', false); + if ($('#rspamd_logo').length) $('#rspamd_logo').attr('src', '/img/rspamd_logo_dark.png'); + if ($('#rspamd_logo_sm').length) $('#rspamd_logo_sm').attr('src', '/img/rspamd_logo_dark.png'); + localStorage.setItem('theme', 'light'); + }else{ + $('head').append(''); + $('#dark-mode-toggle').prop('checked', true); + if ($('#rspamd_logo').length) $('#rspamd_logo').attr('src', '/img/rspamd_logo_light.png'); + if ($('#rspamd_logo_sm').length) $('#rspamd_logo_sm').attr('src', '/img/rspamd_logo_light.png'); + localStorage.setItem('theme', 'dark'); + } + } +}); + + +// https://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery +function escapeHtml(n){var entityMap={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="}; return String(n).replace(/[&<>"'`=\/]/g,function(n){return entityMap[n]})} +function unescapeHtml(t){var n={"&":"&","<":"<",">":">",""":'"',"'":"'","/":"/","`":"`","=":"="};return String(t).replace(/&|<|>|"|'|/|`|=/g,function(t){return n[t]})} + +function addTag(tagAddElem, tag = null){ + var tagboxElem = $(tagAddElem).parent(); + var tagInputElem = $(tagboxElem).find(".tag-input")[0]; + var tagValuesElem = $(tagboxElem).find(".tag-values")[0]; + + if (!tag) + tag = $(tagInputElem).val(); + if (!tag) return; + var value_tags = []; + try { + value_tags = JSON.parse($(tagValuesElem).val()); + } catch {} + if (!Array.isArray(value_tags)) value_tags = []; + if (value_tags.includes(tag)) return; + + $(' ' + escapeHtml(tag) + '').insertBefore('.tag-input').click(function(){ + var del_tag = unescapeHtml($(this).text()); + var del_tags = []; + try { + del_tags = JSON.parse($(tagValuesElem).val()); + } catch {} + if (Array.isArray(del_tags)){ + del_tags.splice(del_tags.indexOf(del_tag), 1); + $(tagValuesElem).val(JSON.stringify(del_tags)); + } + $(this).remove(); + }); + + value_tags.push(tag); + $(tagValuesElem).val(JSON.stringify(value_tags)); + $(tagInputElem).val(''); +} diff --git a/data/web/js/site/debug.js b/data/web/js/site/debug.js index 8c4090224..1996600af 100644 --- a/data/web/js/site/debug.js +++ b/data/web/js/site/debug.js @@ -1,1533 +1,1541 @@ -$(document).ready(function() { - // Parse seconds ago to date - // Get "now" timestamp - var ts_now = Math.round((new Date()).getTime() / 1000); - $('.parse_s_ago').each(function(i, parse_s_ago) { - var started_s_ago = parseInt($(this).text(), 10); - if (typeof started_s_ago != 'NaN') { - var started_date = new Date((ts_now - started_s_ago) * 1000); - if (started_date instanceof Date && !isNaN(started_date)) { - var started_local_date = started_date.toLocaleDateString(undefined, { - year: "numeric", - month: "2-digit", - day: "2-digit", - hour: "2-digit", - minute: "2-digit", - second: "2-digit" - }); - $(this).text(started_local_date); - } else { - $(this).text('-'); - } - } - }); - // Parse general dates - $('.parse_date').each(function(i, parse_date) { - var started_date = new Date(Date.parse($(this).text())); - if (typeof started_date != 'NaN') { - var started_local_date = started_date.toLocaleDateString(undefined, { - year: "numeric", - month: "2-digit", - day: "2-digit", - hour: "2-digit", - minute: "2-digit", - second: "2-digit" - }); - $(this).text(started_local_date); - } - }); - - // set update loop container list - containersToUpdate = {} - // set default ChartJs Font Color - Chart.defaults.color = '#999'; - // create host cpu and mem charts - createHostCpuAndMemChart(); - // check for new version - if (mailcow_info.branch === "master"){ - check_update(mailcow_info.version_tag, mailcow_info.project_url); - } - $("#maiclow_version").click(function(){ - if (mailcow_cc_role !== "admin" && mailcow_cc_role !== "domainadmin" || - mailcow_info.branch !== "master") - return; - - showVersionModal("Version " + mailcow_info.version_tag, mailcow_info.version_tag); - }) - // get public ips - get_public_ips(); - update_container_stats(); -}); -jQuery(function($){ - if (localStorage.getItem("current_page") === null) { - var current_page = {}; - } else { - var current_page = JSON.parse(localStorage.getItem('current_page')); - } - // http://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery - var entityMap={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="}; - function escapeHtml(n){return String(n).replace(/[&<>"'`=\/]/g,function(n){return entityMap[n]})} - function humanFileSize(i){if(Math.abs(i)<1024)return i+" B";var B=["KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"],e=-1;do{i/=1024,++e}while(Math.abs(i)>=1024&&e 0 && item.symbols[a].score > 0) { - return item.symbols[b].score - item.symbols[a].score - } - return item.symbols[b].score - item.symbols[a].score - }).map(function(key) { - var sym = item.symbols[key]; - if (sym.score < 0) { - sym.score_formatted = '(' + sym.score + ')' - } - else if (sym.score === 0) { - sym.score_formatted = '(' + sym.score + ')' - } - else { - sym.score_formatted = '(' + sym.score + ')' - } - var str = '' + key + ' ' + sym.score_formatted; - if (sym.options) { - str += ' [' + escapeHtml(sym.options.join(", ")) + "]"; - } - return str - }).join('
\n'); - item.subject = escapeHtml(item.subject); - var scan_time = item.time_real.toFixed(3); - if (item.time_virtual) { - scan_time += ' / ' + item.time_virtual.toFixed(3); - } - item.scan_time = { - "options": { - "sortValue": item.time_real - }, - "value": scan_time - }; - if (item.action === 'clean' || item.action === 'no action') { - item.action = "
" + item.action + "
"; - } else if (item.action === 'rewrite subject' || item.action === 'add header' || item.action === 'probable spam') { - item.action = "
" + item.action + "
"; - } else if (item.action === 'spam' || item.action === 'reject') { - item.action = "
" + item.action + "
"; - } else { - item.action = "
" + item.action + "
"; - } - var score_content; - if (item.score < item.required_score) { - score_content = "[ " + item.score.toFixed(2) + " / " + item.required_score + " ]"; - } else { - score_content = "[ " + item.score.toFixed(2) + " / " + item.required_score + " ]"; - } - item.score = { - "options": { - "sortValue": item.score - }, - "value": score_content - }; - if (item.user == null) { - item.user = "none"; - } - }); - } else if (table == 'autodiscover_log') { - $.each(data, function (i, item) { - if (item.ua == null) { - item.ua = 'unknown'; - } else { - item.ua = escapeHtml(item.ua); - } - item.ua = '' + item.ua + ''; - if (item.service == "activesync") { - item.service = 'ActiveSync'; - } - else if (item.service == "imap") { - item.service = 'IMAP, SMTP, Cal-/CardDAV'; - } - else { - item.service = '' + escapeHtml(item.service) + ''; - } - }); - } else if (table == 'watchdog') { - $.each(data, function (i, item) { - if (item.message == null) { - item.message = 'Health level: ' + item.lvl + '% (' + item.hpnow + '/' + item.hptotal + ')'; - if (item.hpdiff < 0) { - item.trend = ' ' + item.hpdiff + ''; - } - else if (item.hpdiff == 0) { - item.trend = ' ' + item.hpdiff + ''; - } - else { - item.trend = ' ' + item.hpdiff + ''; - } - } - else { - item.trend = ''; - item.service = ''; - } - }); - } else if (table == 'mailcow_ui') { - $.each(data, function (i, item) { - if (item === null) { return true; } - item.user = escapeHtml(item.user); - item.call = escapeHtml(item.call); - item.task = '' + item.task + ''; - item.type = '' + item.type + ''; - }); - } else if (table == 'sasl_log_table') { - $.each(data, function (i, item) { - if (item === null) { return true; } - item.username = escapeHtml(item.username); - item.service = '
' + item.service.toUpperCase() + '
'; - }); - } else if (table == 'general_syslog') { - $.each(data, function (i, item) { - if (item === null) { return true; } - if (item.message.match("^base64,")) { - try { - item.message = atob(item.message.slice(7)).replace(/\\n/g, "
"); - } catch(e) { - item.message = item.message.slice(7); - } - } else { - item.message = escapeHtml(item.message); - } - item.call = escapeHtml(item.call); - var danger_class = ["emerg", "alert", "crit", "err"]; - var warning_class = ["warning", "warn"]; - var info_class = ["notice", "info", "debug"]; - if (jQuery.inArray(item.priority, danger_class) !== -1) { - item.priority = '' + item.priority + ''; - } else if (jQuery.inArray(item.priority, warning_class) !== -1) { - item.priority = '' + item.priority + ''; - } else if (jQuery.inArray(item.priority, info_class) !== -1) { - item.priority = '' + item.priority + ''; - } - }); - } else if (table == 'apilog') { - $.each(data, function (i, item) { - if (item === null) { return true; } - if (item.method == 'GET') { - item.method = '' + item.method + ''; - } else if (item.method == 'POST') { - item.method = '' + item.method + ''; - } - item.data = escapeHtml(item.data); - }); - } else if (table == 'rllog') { - $.each(data, function (i, item) { - if (item.user == null) { - item.user = "none"; - } - if (item.rl_hash == null) { - item.rl_hash = "err"; - } - item.indicator = ' '; - if (item.rl_hash != 'err') { - item.action = ' ' + lang.reset_limit + ''; - } - }); - } - return data - }; - $('.add_log_lines').on('click', function (e) { - e.preventDefault(); - var log_table= $(this).data("table") - var new_nrows = $(this).data("nrows") - var post_process = $(this).data("post-process") - var log_url = $(this).data("log-url") - if (log_table === undefined || new_nrows === undefined || post_process === undefined || log_url === undefined) { - console.log("no data-table or data-nrows or log_url or data-post-process attr found"); - return; - } - - if (table = $('#' + log_table).DataTable()) { - var heading = $('#' + log_table).closest('.card').find('.card-header'); - var load_rows = (table.page.len() + 1) + '-' + (table.page.len() + new_nrows) - - $.get('/api/v1/get/logs/' + log_url + '/' + load_rows).then(function(data){ - if (data.length === undefined) { mailcow_alert_box(lang.no_new_rows, "info"); return; } - var rows = process_table_data(data, post_process); - var rows_now = (table.page.len() + data.length); - $(heading).children('.table-lines').text(rows_now) - mailcow_alert_box(data.length + lang.additional_rows, "success"); - table.rows.add(rows).draw(); - }); - } - }) - - // detect element visibility changes - function onVisible(element, callback) { - $(document).ready(function() { - element_object = document.querySelector(element); - if (element_object === null) return; - - new IntersectionObserver((entries, observer) => { - entries.forEach(entry => { - if(entry.intersectionRatio > 0) { - callback(element_object); - } - }); - }).observe(element_object); - }); - } - // Draw Table if tab is active - onVisible("[id^=postfix_log]", () => draw_postfix_logs()); - onVisible("[id^=dovecot_log]", () => draw_dovecot_logs()); - onVisible("[id^=sogo_log]", () => draw_sogo_logs()); - onVisible("[id^=watchdog_log]", () => draw_watchdog_logs()); - onVisible("[id^=autodiscover_log]", () => draw_autodiscover_logs()); - onVisible("[id^=acme_log]", () => draw_acme_logs()); - onVisible("[id^=api_log]", () => draw_api_logs()); - onVisible("[id^=rl_log]", () => draw_rl_logs()); - onVisible("[id^=ui_logs]", () => draw_ui_logs()); - onVisible("[id^=sasl_logs]", () => draw_sasl_logs()); - onVisible("[id^=netfilter_log]", () => draw_netfilter_logs()); - onVisible("[id^=rspamd_history]", () => draw_rspamd_history()); - onVisible("[id^=rspamd_donut]", () => rspamd_pie_graph()); - - - - // start polling host stats if tab is active - onVisible("[id^=tab-containers]", () => update_stats()); - // start polling container stats if collapse is active - var containerElements = document.querySelectorAll(".container-details-collapse"); - for (let i = 0; i < containerElements.length; i++){ - new IntersectionObserver((entries, observer) => { - entries.forEach(entry => { - if(entry.intersectionRatio > 0) { - - if (!containerElements[i].classList.contains("show")){ - var container = containerElements[i].id.replace("Collapse", ""); - var container_id = containerElements[i].getAttribute("data-id"); - - // check if chart exists or needs to be created - if (!Chart.getChart(container + "_DiskIOChart")) - createReadWriteChart(container + "_DiskIOChart", "Read", "Write"); - if (!Chart.getChart(container + "_NetIOChart")) - createReadWriteChart(container + "_NetIOChart", "Recv", "Sent"); - - // add container to polling list - containersToUpdate[container] = { - id: container_id, - state: "idle" - } - - // stop polling if collapse is closed - containerElements[i].addEventListener('hidden.bs.collapse', function () { - var diskIOCtx = Chart.getChart(container + "_DiskIOChart"); - var netIOCtx = Chart.getChart(container + "_NetIOChart"); - - diskIOCtx.data.datasets[0].data = []; - diskIOCtx.data.datasets[1].data = []; - diskIOCtx.data.labels = []; - netIOCtx.data.datasets[0].data = []; - netIOCtx.data.datasets[1].data = []; - netIOCtx.data.labels = []; - - diskIOCtx.update(); - netIOCtx.update(); - - delete containersToUpdate[container]; - }); - } - - } - }); - }).observe(containerElements[i]); - } -}); - - -// update system stats - every 5 seconds if system & container tab is active -function update_stats(timeout=5){ - if (!$('#tab-containers').hasClass('active')) { - // tab not active - dont fetch stats - run again in n seconds - return; - } - - window.fetch("/api/v1/get/status/host", {method:'GET',cache:'no-cache'}).then(function(response) { - return response.json(); - }).then(function(data) { - console.log(data); - - if (data){ - // display table data - $("#host_date").text(data.system_time); - $("#host_uptime").text(formatUptime(data.uptime)); - $("#host_cpu_cores").text(data.cpu.cores); - $("#host_cpu_usage").text(parseInt(data.cpu.usage).toString() + "%"); - $("#host_memory_total").text((data.memory.total / (1024 ** 3)).toFixed(2).toString() + "GB"); - $("#host_memory_usage").text(parseInt(data.memory.usage).toString() + "%"); - - // update cpu and mem chart - var cpu_chart = Chart.getChart("host_cpu_chart"); - var mem_chart = Chart.getChart("host_mem_chart"); - - cpu_chart.data.labels.push(data.system_time.split(" ")[1]); - if (cpu_chart.data.labels.length > 30) cpu_chart.data.labels.shift(); - mem_chart.data.labels.push(data.system_time.split(" ")[1]); - if (mem_chart.data.labels.length > 30) mem_chart.data.labels.shift(); - - cpu_chart.data.datasets[0].data.push(data.cpu.usage); - if (cpu_chart.data.datasets[0].data.length > 30) cpu_chart.data.datasets[0].data.shift(); - mem_chart.data.datasets[0].data.push(data.memory.usage); - if (mem_chart.data.datasets[0].data.length > 30) mem_chart.data.datasets[0].data.shift(); - - cpu_chart.update(); - mem_chart.update(); - } - - // run again in n seconds - setTimeout(update_stats, timeout * 1000); - }); -} -// update specific container stats - every n (default 5s) seconds -function update_container_stats(timeout=5){ - - if ($('#tab-containers').hasClass('active')) { - for (let container in containersToUpdate){ - container_id = containersToUpdate[container].id; - // check if container update stats is already running - if (containersToUpdate[container].state == "running") - continue; - containersToUpdate[container].state = "running"; - - - window.fetch("/api/v1/get/status/container/" + container_id, {method:'GET',cache:'no-cache'}).then(function(response) { - return response.json(); - }).then(function(data) { - var diskIOCtx = Chart.getChart(container + "_DiskIOChart"); - var netIOCtx = Chart.getChart(container + "_NetIOChart"); - - console.log(container); - console.log(data); - prev_stats = null; - if (data.length >= 2){ - prev_stats = data[data.length -2]; - - // hide spinners if we collected enough data - $('#' + container + "_DiskIOChart").removeClass('d-none'); - $('#' + container + "_DiskIOChart").prev().addClass('d-none'); - $('#' + container + "_NetIOChart").removeClass('d-none'); - $('#' + container + "_NetIOChart").prev().addClass('d-none'); - } - - data = data[data.length -1]; - - if (prev_stats != null){ - // calc time diff - var time_diff = (new Date(data.read) - new Date(prev_stats.read)) / 1000; - - // calc disk io b/s - if ('io_service_bytes_recursive' in prev_stats.blkio_stats && prev_stats.blkio_stats.io_service_bytes_recursive !== null){ - var prev_read_bytes = 0; - var prev_write_bytes = 0; - for (var i = 0; i < prev_stats.blkio_stats.io_service_bytes_recursive.length; i++){ - if (prev_stats.blkio_stats.io_service_bytes_recursive[i].op == "read") - prev_read_bytes = prev_stats.blkio_stats.io_service_bytes_recursive[i].value; - else if (prev_stats.blkio_stats.io_service_bytes_recursive[i].op == "write") - prev_write_bytes = prev_stats.blkio_stats.io_service_bytes_recursive[i].value; - } - var read_bytes = 0; - var write_bytes = 0; - for (var i = 0; i < data.blkio_stats.io_service_bytes_recursive.length; i++){ - if (data.blkio_stats.io_service_bytes_recursive[i].op == "read") - read_bytes = data.blkio_stats.io_service_bytes_recursive[i].value; - else if (data.blkio_stats.io_service_bytes_recursive[i].op == "write") - write_bytes = data.blkio_stats.io_service_bytes_recursive[i].value; - } - var diff_bytes_read = (read_bytes - prev_read_bytes) / time_diff; - var diff_bytes_write = (write_bytes - prev_write_bytes) / time_diff; - } - - // calc net io b/s - if ('networks' in prev_stats){ - var prev_recv_bytes = 0; - var prev_sent_bytes = 0; - for (var key in prev_stats.networks){ - prev_recv_bytes += prev_stats.networks[key].rx_bytes; - prev_sent_bytes += prev_stats.networks[key].tx_bytes; - } - var recv_bytes = 0; - var sent_bytes = 0; - for (var key in data.networks){ - recv_bytes += data.networks[key].rx_bytes; - sent_bytes += data.networks[key].tx_bytes; - } - var diff_bytes_recv = (recv_bytes - prev_recv_bytes) / time_diff; - var diff_bytes_sent = (sent_bytes - prev_sent_bytes) / time_diff; - } - - addReadWriteChart(diskIOCtx, diff_bytes_read, diff_bytes_write, ""); - addReadWriteChart(netIOCtx, diff_bytes_recv, diff_bytes_sent, ""); - } - - // run again in n seconds - containersToUpdate[container].state = "idle"; - }).catch(err => { - console.log(err); - }); - } - } - - // run again in n seconds - setTimeout(update_container_stats, timeout * 1000); -} -// get public ips -function get_public_ips(){ - window.fetch("/api/v1/get/status/host/ip", {method:'GET',cache:'no-cache'}).then(function(response) { - return response.json(); - }).then(function(data) { - console.log(data); - - // display host ips - if (data.ipv4) - $("#host_ipv4").text(data.ipv4); - if (data.ipv6) - $("#host_ipv6").text(data.ipv6); - }); -} -// format hosts uptime seconds to readable string -function formatUptime(seconds){ - seconds = Number(seconds); - var d = Math.floor(seconds / (3600*24)); - var h = Math.floor(seconds % (3600*24) / 3600); - var m = Math.floor(seconds % 3600 / 60); - var s = Math.floor(seconds % 60); - - var dFormat = d > 0 ? d + "D " : ""; - var hFormat = h > 0 ? h + "H " : ""; - var mFormat = m > 0 ? m + "M " : ""; - var sFormat = s > 0 ? s + "S" : ""; - return dFormat + hFormat + mFormat + sFormat; -} -// format bytes to readable string -function formatBytes(bytes){ - // b - if (bytes < 1000) return bytes.toFixed(2).toString()+' B/s'; - // b to kb - bytes = bytes / 1024; - if (bytes < 1000) return bytes.toFixed(2).toString()+' KB/s'; - // kb to mb - bytes = bytes / 1024; - if (bytes < 1000) return bytes.toFixed(2).toString()+' MB/s'; - // final mb to gb - return (bytes / 1024).toFixed(2).toString()+' GB/s'; -} -// create read write line chart -function createReadWriteChart(chart_id, read_lable, write_lable){ - var ctx = document.getElementById(chart_id); - - var dataNet = { - labels: [], - datasets: [{ - label: read_lable, - backgroundColor: "rgba(41, 187, 239, 0.3)", - borderColor: "rgba(41, 187, 239, 0.6)", - pointRadius: 1, - pointHitRadius: 6, - borderWidth: 2, - fill: true, - tension: 0.2, - data: [] - }, { - label: write_lable, - backgroundColor: "rgba(239, 60, 41, 0.3)", - borderColor: "rgba(239, 60, 41, 0.6)", - pointRadius: 1, - pointHitRadius: 6, - borderWidth: 2, - fill: true, - tension: 0.2, - data: [] - }] - }; - var optionsNet = { - interaction: { - mode: 'index' - }, - scales: { - yAxis: { - min: 0, - grid: { - display: false - }, - ticks: { - callback: function(i, index, ticks) { - return formatBytes(i); - } - } - }, - xAxis: { - grid: { - display: false - } - } - } - }; - - return new Chart(ctx, { - type: 'line', - data: dataNet, - options: optionsNet - }); -} -// add to read write line chart -function addReadWriteChart(chart_context, read_point, write_point, time, limit = 30){ - // push time label for x-axis - chart_context.data.labels.push(time); - if (chart_context.data.labels.length > limit) chart_context.data.labels.shift(); - - // push datapoints - chart_context.data.datasets[0].data.push(read_point); - chart_context.data.datasets[1].data.push(write_point); - // shift data if more than 20 entires exists - if (chart_context.data.datasets[0].data.length > limit) chart_context.data.datasets[0].data.shift(); - if (chart_context.data.datasets[1].data.length > limit) chart_context.data.datasets[1].data.shift(); - - chart_context.update(); -} -// create host cpu and mem chart -function createHostCpuAndMemChart(){ - var cpu_ctx = document.getElementById("host_cpu_chart"); - var mem_ctx = document.getElementById("host_mem_chart"); - - var dataCpu = { - labels: [], - datasets: [{ - label: "CPU %", - backgroundColor: "rgba(41, 187, 239, 0.3)", - borderColor: "rgba(41, 187, 239, 0.6)", - pointRadius: 1, - pointHitRadius: 6, - borderWidth: 2, - fill: true, - tension: 0.2, - data: [] - }] - }; - var optionsCpu = { - interaction: { - mode: 'index' - }, - scales: { - yAxis: { - min: 0, - grid: { - display: false - }, - ticks: { - callback: function(i, index, ticks) { - return i.toFixed(0).toString() + "%"; - } - } - }, - xAxis: { - grid: { - display: false - } - } - } - }; - - var dataMem = { - labels: [], - datasets: [{ - label: "MEM %", - backgroundColor: "rgba(41, 187, 239, 0.3)", - borderColor: "rgba(41, 187, 239, 0.6)", - pointRadius: 1, - pointHitRadius: 6, - borderWidth: 2, - fill: true, - tension: 0.2, - data: [] - }] - }; - var optionsMem = { - interaction: { - mode: 'index' - }, - scales: { - yAxis: { - min: 0, - grid: { - display: false - }, - ticks: { - callback: function(i, index, ticks) { - return i.toFixed(0).toString() + "%"; - } - } - }, - xAxis: { - grid: { - display: false - } - } - } - }; - - - var net_io_chart = new Chart(cpu_ctx, { - type: 'line', - data: dataCpu, - options: optionsCpu - }); - var disk_io_chart = new Chart(mem_ctx, { - type: 'line', - data: dataMem, - options: optionsMem - }); -} -// check for mailcow updates -function check_update(current_version, github_repo_url){ - if (!current_version || !github_repo_url) return false; - - var github_account = github_repo_url.split("/")[3]; - var github_repo_name = github_repo_url.split("/")[4]; - - // get details about latest release - window.fetch("https://api.github.com/repos/"+github_account+"/"+github_repo_name+"/releases/latest", {method:'GET',cache:'no-cache'}).then(function(response) { - return response.json(); - }).then(function(latest_data) { - // get details about current release - window.fetch("https://api.github.com/repos/"+github_account+"/"+github_repo_name+"/releases/tags/"+current_version, {method:'GET',cache:'no-cache'}).then(function(response) { - return response.json(); - }).then(function(current_data) { - // compare releases - var date_current = new Date(current_data.created_at); - var date_latest = new Date(latest_data.created_at); - if (date_latest.getTime() <= date_current.getTime()){ - // no update available - $("#mailcow_update").removeClass("text-warning text-danger").addClass("text-success"); - $("#mailcow_update").html("" + lang_debug.no_update_available + ""); - } else { - // update available - $("#mailcow_update").removeClass("text-danger text-success").addClass("text-warning"); - $("#mailcow_update").html(lang_debug.update_available + ` `+latest_data.tag_name+``); - $("#mailcow_update_changelog").click(function(){ - if (mailcow_cc_role !== "admin" && mailcow_cc_role !== "domainadmin") - return; - - showVersionModal("New Release " + latest_data.tag_name, latest_data.tag_name); - }) - } - }).catch(err => { - // err - console.log(err); - $("#mailcow_update").removeClass("text-success text-warning").addClass("text-danger"); - $("#mailcow_update").html(""+ lang_debug.update_failed +""); - }); - }).catch(err => { - // err - console.log(err); - $("#mailcow_update").removeClass("text-success text-warning").addClass("text-danger"); - $("#mailcow_update").html(""+ lang_debug.update_failed +""); - }); -} -// show version changelog modal -function showVersionModal(title, version){ - $.ajax({ - type: 'GET', - url: 'https://api.github.com/repos/' + mailcow_info.project_owner + '/' + mailcow_info.project_repo + '/releases/tags/' + version, - dataType: 'json', - success: function (data) { - var md = window.markdownit(); - var result = md.render(data.body); - result = parseGithubMarkdownLinks(result); - - $('#showVersionModal').find(".modal-title").html(title); - $('#showVersionModal').find(".modal-body").html(` -

` + data.name + `

- ` + result + ` - Github Link: - ` + version + ` - - `); - - new bootstrap.Modal(document.getElementById("showVersionModal"), { - backdrop: 'static', - keyboard: false - }).show(); - } - }); -} -function parseGithubMarkdownLinks(inputText) { - var replacedText, replacePattern1; - - replacePattern1 = /(\b(https?):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim; - replacedText = inputText.replace(replacePattern1, (matched, index, original, input_string) => { - if (matched.includes('github.com')){ - // return short link if it's github link - last_uri_path = matched.split('/'); - last_uri_path = last_uri_path[last_uri_path.length - 1]; - - // adjust Full Changelog link to match last git version and new git version, if link is a compare link - if (matched.includes('/compare/') && mailcow_info.last_version_tag !== ''){ - matched = matched.replace(last_uri_path, mailcow_info.last_version_tag + '...' + mailcow_info.version_tag); - last_uri_path = mailcow_info.last_version_tag + '...' + mailcow_info.version_tag; - } - - return '' + last_uri_path + '
'; - }; - - // if it's not a github link, return complete link - return '' + matched + ''; - }); - - return replacedText; -} \ No newline at end of file +const LOCALE = undefined; +const DATETIME_FORMAT = { + year: "numeric", + month: "2-digit", + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + second: "2-digit" +}; + +$(document).ready(function() { + // Parse seconds ago to date + // Get "now" timestamp + var ts_now = Math.round((new Date()).getTime() / 1000); + $('.parse_s_ago').each(function(i, parse_s_ago) { + var started_s_ago = parseInt($(this).text(), 10); + if (typeof started_s_ago != 'NaN') { + var started_date = new Date((ts_now - started_s_ago) * 1000); + if (started_date instanceof Date && !isNaN(started_date)) { + var started_local_date = started_date.toLocaleDateString(LOCALE, DATETIME_FORMAT); + $(this).text(started_local_date); + } else { + $(this).text('-'); + } + } + }); + // Parse general dates + $('.parse_date').each(function(i, parse_date) { + var started_date = new Date(Date.parse($(this).text())); + if (typeof started_date != 'NaN') { + var started_local_date = started_date.toLocaleDateString(LOCALE, DATETIME_FORMAT); + $(this).text(started_local_date); + } + }); + + // set update loop container list + containersToUpdate = {} + // set default ChartJs Font Color + Chart.defaults.color = '#999'; + // create host cpu and mem charts + createHostCpuAndMemChart(); + // check for new version + if (mailcow_info.branch === "master"){ + check_update(mailcow_info.version_tag, mailcow_info.project_url); + } + $("#maiclow_version").click(function(){ + if (mailcow_cc_role !== "admin" && mailcow_cc_role !== "domainadmin" || + mailcow_info.branch !== "master") + return; + + showVersionModal("Version " + mailcow_info.version_tag, mailcow_info.version_tag); + }) + // get public ips + get_public_ips(); + update_container_stats(); +}); +jQuery(function($){ + if (localStorage.getItem("current_page") === null) { + var current_page = {}; + } else { + var current_page = JSON.parse(localStorage.getItem('current_page')); + } + // http://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery + var entityMap={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="}; + function escapeHtml(n){return String(n).replace(/[&<>"'`=\/]/g,function(n){return entityMap[n]})} + function humanFileSize(i){if(Math.abs(i)<1024)return i+" B";var B=["KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"],e=-1;do{i/=1024,++e}while(Math.abs(i)>=1024&&e 0 && item.symbols[a].score > 0) { + return item.symbols[b].score - item.symbols[a].score + } + return item.symbols[b].score - item.symbols[a].score + }).map(function(key) { + var sym = item.symbols[key]; + if (sym.score < 0) { + sym.score_formatted = '(' + sym.score + ')' + } + else if (sym.score === 0) { + sym.score_formatted = '(' + sym.score + ')' + } + else { + sym.score_formatted = '(' + sym.score + ')' + } + var str = '' + key + ' ' + sym.score_formatted; + if (sym.options) { + str += ' [' + escapeHtml(sym.options.join(", ")) + "]"; + } + return str + }).join('
\n'); + item.subject = escapeHtml(item.subject); + var scan_time = item.time_real.toFixed(3); + if (item.time_virtual) { + scan_time += ' / ' + item.time_virtual.toFixed(3); + } + item.scan_time = { + "sortBy": item.time_real, + "value": scan_time + }; + if (item.action === 'clean' || item.action === 'no action') { + item.action = "
" + item.action + "
"; + } else if (item.action === 'rewrite subject' || item.action === 'add header' || item.action === 'probable spam') { + item.action = "
" + item.action + "
"; + } else if (item.action === 'spam' || item.action === 'reject') { + item.action = "
" + item.action + "
"; + } else { + item.action = "
" + item.action + "
"; + } + var score_content; + if (item.score < item.required_score) { + score_content = "[ " + item.score.toFixed(2) + " / " + item.required_score + " ]"; + } else { + score_content = "[ " + item.score.toFixed(2) + " / " + item.required_score + " ]"; + } + item.score = { + "sortBy": item.score, + "value": score_content + }; + if (item.user == null) { + item.user = "none"; + } + }); + } else if (table == 'autodiscover_log') { + $.each(data, function (i, item) { + if (item.ua == null) { + item.ua = 'unknown'; + } else { + item.ua = escapeHtml(item.ua); + } + item.ua = '' + item.ua + ''; + if (item.service == "activesync") { + item.service = 'ActiveSync'; + } + else if (item.service == "imap") { + item.service = 'IMAP, SMTP, Cal-/CardDAV'; + } + else { + item.service = '' + escapeHtml(item.service) + ''; + } + }); + } else if (table == 'watchdog') { + $.each(data, function (i, item) { + if (item.message == null) { + item.message = 'Health level: ' + item.lvl + '% (' + item.hpnow + '/' + item.hptotal + ')'; + if (item.hpdiff < 0) { + item.trend = ' ' + item.hpdiff + ''; + } + else if (item.hpdiff == 0) { + item.trend = ' ' + item.hpdiff + ''; + } + else { + item.trend = ' ' + item.hpdiff + ''; + } + } + else { + item.trend = ''; + item.service = ''; + } + }); + } else if (table == 'mailcow_ui') { + $.each(data, function (i, item) { + if (item === null) { return true; } + item.user = escapeHtml(item.user); + item.call = escapeHtml(item.call); + item.task = '' + item.task + ''; + item.type = '' + item.type + ''; + }); + } else if (table == 'sasl_log_table') { + $.each(data, function (i, item) { + if (item === null) { return true; } + item.username = escapeHtml(item.username); + item.service = '
' + item.service.toUpperCase() + '
'; + }); + } else if (table == 'general_syslog') { + $.each(data, function (i, item) { + if (item === null) { return true; } + if (item.message.match("^base64,")) { + try { + item.message = atob(item.message.slice(7)).replace(/\\n/g, "
"); + } catch(e) { + item.message = item.message.slice(7); + } + } else { + item.message = escapeHtml(item.message); + } + item.call = escapeHtml(item.call); + var danger_class = ["emerg", "alert", "crit", "err"]; + var warning_class = ["warning", "warn"]; + var info_class = ["notice", "info", "debug"]; + if (jQuery.inArray(item.priority, danger_class) !== -1) { + item.priority = '' + item.priority + ''; + } else if (jQuery.inArray(item.priority, warning_class) !== -1) { + item.priority = '' + item.priority + ''; + } else if (jQuery.inArray(item.priority, info_class) !== -1) { + item.priority = '' + item.priority + ''; + } + }); + } else if (table == 'apilog') { + $.each(data, function (i, item) { + if (item === null) { return true; } + if (item.method == 'GET') { + item.method = '' + item.method + ''; + } else if (item.method == 'POST') { + item.method = '' + item.method + ''; + } + item.data = escapeHtml(item.data); + }); + } else if (table == 'rllog') { + $.each(data, function (i, item) { + if (item.user == null) { + item.user = "none"; + } + if (item.rl_hash == null) { + item.rl_hash = "err"; + } + item.indicator = ' '; + if (item.rl_hash != 'err') { + item.action = ' ' + lang.reset_limit + ''; + } + }); + } + return data + }; + $('.add_log_lines').on('click', function (e) { + e.preventDefault(); + var log_table= $(this).data("table") + var new_nrows = $(this).data("nrows") + var post_process = $(this).data("post-process") + var log_url = $(this).data("log-url") + if (log_table === undefined || new_nrows === undefined || post_process === undefined || log_url === undefined) { + console.log("no data-table or data-nrows or log_url or data-post-process attr found"); + return; + } + + if (table = $('#' + log_table).DataTable()) { + var heading = $('#' + log_table).closest('.card').find('.card-header'); + var load_rows = (table.page.len() + 1) + '-' + (table.page.len() + new_nrows) + + $.get('/api/v1/get/logs/' + log_url + '/' + load_rows).then(function(data){ + if (data.length === undefined) { mailcow_alert_box(lang.no_new_rows, "info"); return; } + var rows = process_table_data(data, post_process); + var rows_now = (table.page.len() + data.length); + $(heading).children('.table-lines').text(rows_now) + mailcow_alert_box(data.length + lang.additional_rows, "success"); + table.rows.add(rows).draw(); + }); + } + }) + + // detect element visibility changes + function onVisible(element, callback) { + $(document).ready(function() { + element_object = document.querySelector(element); + if (element_object === null) return; + + new IntersectionObserver((entries, observer) => { + entries.forEach(entry => { + if(entry.intersectionRatio > 0) { + callback(element_object); + } + }); + }).observe(element_object); + }); + } + // Draw Table if tab is active + onVisible("[id^=postfix_log]", () => draw_postfix_logs()); + onVisible("[id^=dovecot_log]", () => draw_dovecot_logs()); + onVisible("[id^=sogo_log]", () => draw_sogo_logs()); + onVisible("[id^=watchdog_log]", () => draw_watchdog_logs()); + onVisible("[id^=autodiscover_log]", () => draw_autodiscover_logs()); + onVisible("[id^=acme_log]", () => draw_acme_logs()); + onVisible("[id^=api_log]", () => draw_api_logs()); + onVisible("[id^=rl_log]", () => draw_rl_logs()); + onVisible("[id^=ui_logs]", () => draw_ui_logs()); + onVisible("[id^=sasl_logs]", () => draw_sasl_logs()); + onVisible("[id^=netfilter_log]", () => draw_netfilter_logs()); + onVisible("[id^=rspamd_history]", () => draw_rspamd_history()); + onVisible("[id^=rspamd_donut]", () => rspamd_pie_graph()); + + + + // start polling host stats if tab is active + onVisible("[id^=tab-containers]", () => update_stats()); + // start polling container stats if collapse is active + var containerElements = document.querySelectorAll(".container-details-collapse"); + for (let i = 0; i < containerElements.length; i++){ + new IntersectionObserver((entries, observer) => { + entries.forEach(entry => { + if(entry.intersectionRatio > 0) { + + if (!containerElements[i].classList.contains("show")){ + var container = containerElements[i].id.replace("Collapse", ""); + var container_id = containerElements[i].getAttribute("data-id"); + + // check if chart exists or needs to be created + if (!Chart.getChart(container + "_DiskIOChart")) + createReadWriteChart(container + "_DiskIOChart", "Read", "Write"); + if (!Chart.getChart(container + "_NetIOChart")) + createReadWriteChart(container + "_NetIOChart", "Recv", "Sent"); + + // add container to polling list + containersToUpdate[container] = { + id: container_id, + state: "idle" + } + + // stop polling if collapse is closed + containerElements[i].addEventListener('hidden.bs.collapse', function () { + var diskIOCtx = Chart.getChart(container + "_DiskIOChart"); + var netIOCtx = Chart.getChart(container + "_NetIOChart"); + + diskIOCtx.data.datasets[0].data = []; + diskIOCtx.data.datasets[1].data = []; + diskIOCtx.data.labels = []; + netIOCtx.data.datasets[0].data = []; + netIOCtx.data.datasets[1].data = []; + netIOCtx.data.labels = []; + + diskIOCtx.update(); + netIOCtx.update(); + + delete containersToUpdate[container]; + }); + } + + } + }); + }).observe(containerElements[i]); + } +}); + + +// update system stats - every 5 seconds if system & container tab is active +function update_stats(timeout=5){ + if (!$('#tab-containers').hasClass('active')) { + // tab not active - dont fetch stats - run again in n seconds + return; + } + + window.fetch("/api/v1/get/status/host", {method:'GET',cache:'no-cache'}).then(function(response) { + return response.json(); + }).then(function(data) { + console.log(data); + + if (data){ + // display table data + $("#host_date").text(data.system_time); + $("#host_uptime").text(formatUptime(data.uptime)); + $("#host_cpu_cores").text(data.cpu.cores); + $("#host_cpu_usage").text(parseInt(data.cpu.usage).toString() + "%"); + $("#host_memory_total").text((data.memory.total / (1024 ** 3)).toFixed(2).toString() + "GB"); + $("#host_memory_usage").text(parseInt(data.memory.usage).toString() + "%"); + + // update cpu and mem chart + var cpu_chart = Chart.getChart("host_cpu_chart"); + var mem_chart = Chart.getChart("host_mem_chart"); + + cpu_chart.data.labels.push(data.system_time.split(" ")[1]); + if (cpu_chart.data.labels.length > 30) cpu_chart.data.labels.shift(); + mem_chart.data.labels.push(data.system_time.split(" ")[1]); + if (mem_chart.data.labels.length > 30) mem_chart.data.labels.shift(); + + cpu_chart.data.datasets[0].data.push(data.cpu.usage); + if (cpu_chart.data.datasets[0].data.length > 30) cpu_chart.data.datasets[0].data.shift(); + mem_chart.data.datasets[0].data.push(data.memory.usage); + if (mem_chart.data.datasets[0].data.length > 30) mem_chart.data.datasets[0].data.shift(); + + cpu_chart.update(); + mem_chart.update(); + } + + // run again in n seconds + setTimeout(update_stats, timeout * 1000); + }); +} +// update specific container stats - every n (default 5s) seconds +function update_container_stats(timeout=5){ + + if ($('#tab-containers').hasClass('active')) { + for (let container in containersToUpdate){ + container_id = containersToUpdate[container].id; + // check if container update stats is already running + if (containersToUpdate[container].state == "running") + continue; + containersToUpdate[container].state = "running"; + + + window.fetch("/api/v1/get/status/container/" + container_id, {method:'GET',cache:'no-cache'}).then(function(response) { + return response.json(); + }).then(function(data) { + var diskIOCtx = Chart.getChart(container + "_DiskIOChart"); + var netIOCtx = Chart.getChart(container + "_NetIOChart"); + + console.log(container); + console.log(data); + prev_stats = null; + if (data.length >= 2){ + prev_stats = data[data.length -2]; + + // hide spinners if we collected enough data + $('#' + container + "_DiskIOChart").removeClass('d-none'); + $('#' + container + "_DiskIOChart").prev().addClass('d-none'); + $('#' + container + "_NetIOChart").removeClass('d-none'); + $('#' + container + "_NetIOChart").prev().addClass('d-none'); + } + + data = data[data.length -1]; + + if (prev_stats != null){ + // calc time diff + var time_diff = (new Date(data.read) - new Date(prev_stats.read)) / 1000; + + // calc disk io b/s + if ('io_service_bytes_recursive' in prev_stats.blkio_stats && prev_stats.blkio_stats.io_service_bytes_recursive !== null){ + var prev_read_bytes = 0; + var prev_write_bytes = 0; + for (var i = 0; i < prev_stats.blkio_stats.io_service_bytes_recursive.length; i++){ + if (prev_stats.blkio_stats.io_service_bytes_recursive[i].op == "read") + prev_read_bytes = prev_stats.blkio_stats.io_service_bytes_recursive[i].value; + else if (prev_stats.blkio_stats.io_service_bytes_recursive[i].op == "write") + prev_write_bytes = prev_stats.blkio_stats.io_service_bytes_recursive[i].value; + } + var read_bytes = 0; + var write_bytes = 0; + for (var i = 0; i < data.blkio_stats.io_service_bytes_recursive.length; i++){ + if (data.blkio_stats.io_service_bytes_recursive[i].op == "read") + read_bytes = data.blkio_stats.io_service_bytes_recursive[i].value; + else if (data.blkio_stats.io_service_bytes_recursive[i].op == "write") + write_bytes = data.blkio_stats.io_service_bytes_recursive[i].value; + } + var diff_bytes_read = (read_bytes - prev_read_bytes) / time_diff; + var diff_bytes_write = (write_bytes - prev_write_bytes) / time_diff; + } + + // calc net io b/s + if ('networks' in prev_stats){ + var prev_recv_bytes = 0; + var prev_sent_bytes = 0; + for (var key in prev_stats.networks){ + prev_recv_bytes += prev_stats.networks[key].rx_bytes; + prev_sent_bytes += prev_stats.networks[key].tx_bytes; + } + var recv_bytes = 0; + var sent_bytes = 0; + for (var key in data.networks){ + recv_bytes += data.networks[key].rx_bytes; + sent_bytes += data.networks[key].tx_bytes; + } + var diff_bytes_recv = (recv_bytes - prev_recv_bytes) / time_diff; + var diff_bytes_sent = (sent_bytes - prev_sent_bytes) / time_diff; + } + + addReadWriteChart(diskIOCtx, diff_bytes_read, diff_bytes_write, ""); + addReadWriteChart(netIOCtx, diff_bytes_recv, diff_bytes_sent, ""); + } + + // run again in n seconds + containersToUpdate[container].state = "idle"; + }).catch(err => { + console.log(err); + }); + } + } + + // run again in n seconds + setTimeout(update_container_stats, timeout * 1000); +} +// get public ips +function get_public_ips(){ + window.fetch("/api/v1/get/status/host/ip", {method:'GET',cache:'no-cache'}).then(function(response) { + return response.json(); + }).then(function(data) { + console.log(data); + + // display host ips + if (data.ipv4) + $("#host_ipv4").text(data.ipv4); + if (data.ipv6) + $("#host_ipv6").text(data.ipv6); + }); +} +// format hosts uptime seconds to readable string +function formatUptime(seconds){ + seconds = Number(seconds); + var d = Math.floor(seconds / (3600*24)); + var h = Math.floor(seconds % (3600*24) / 3600); + var m = Math.floor(seconds % 3600 / 60); + var s = Math.floor(seconds % 60); + + var dFormat = d > 0 ? d + "D " : ""; + var hFormat = h > 0 ? h + "H " : ""; + var mFormat = m > 0 ? m + "M " : ""; + var sFormat = s > 0 ? s + "S" : ""; + return dFormat + hFormat + mFormat + sFormat; +} +// format bytes to readable string +function formatBytes(bytes){ + // b + if (bytes < 1000) return bytes.toFixed(2).toString()+' B/s'; + // b to kb + bytes = bytes / 1024; + if (bytes < 1000) return bytes.toFixed(2).toString()+' KB/s'; + // kb to mb + bytes = bytes / 1024; + if (bytes < 1000) return bytes.toFixed(2).toString()+' MB/s'; + // final mb to gb + return (bytes / 1024).toFixed(2).toString()+' GB/s'; +} +// create read write line chart +function createReadWriteChart(chart_id, read_lable, write_lable){ + var ctx = document.getElementById(chart_id); + + var dataNet = { + labels: [], + datasets: [{ + label: read_lable, + backgroundColor: "rgba(41, 187, 239, 0.3)", + borderColor: "rgba(41, 187, 239, 0.6)", + pointRadius: 1, + pointHitRadius: 6, + borderWidth: 2, + fill: true, + tension: 0.2, + data: [] + }, { + label: write_lable, + backgroundColor: "rgba(239, 60, 41, 0.3)", + borderColor: "rgba(239, 60, 41, 0.6)", + pointRadius: 1, + pointHitRadius: 6, + borderWidth: 2, + fill: true, + tension: 0.2, + data: [] + }] + }; + var optionsNet = { + interaction: { + mode: 'index' + }, + scales: { + yAxis: { + min: 0, + grid: { + display: false + }, + ticks: { + callback: function(i, index, ticks) { + return formatBytes(i); + } + } + }, + xAxis: { + grid: { + display: false + } + } + } + }; + + return new Chart(ctx, { + type: 'line', + data: dataNet, + options: optionsNet + }); +} +// add to read write line chart +function addReadWriteChart(chart_context, read_point, write_point, time, limit = 30){ + // push time label for x-axis + chart_context.data.labels.push(time); + if (chart_context.data.labels.length > limit) chart_context.data.labels.shift(); + + // push datapoints + chart_context.data.datasets[0].data.push(read_point); + chart_context.data.datasets[1].data.push(write_point); + // shift data if more than 20 entires exists + if (chart_context.data.datasets[0].data.length > limit) chart_context.data.datasets[0].data.shift(); + if (chart_context.data.datasets[1].data.length > limit) chart_context.data.datasets[1].data.shift(); + + chart_context.update(); +} +// create host cpu and mem chart +function createHostCpuAndMemChart(){ + var cpu_ctx = document.getElementById("host_cpu_chart"); + var mem_ctx = document.getElementById("host_mem_chart"); + + var dataCpu = { + labels: [], + datasets: [{ + label: "CPU %", + backgroundColor: "rgba(41, 187, 239, 0.3)", + borderColor: "rgba(41, 187, 239, 0.6)", + pointRadius: 1, + pointHitRadius: 6, + borderWidth: 2, + fill: true, + tension: 0.2, + data: [] + }] + }; + var optionsCpu = { + interaction: { + mode: 'index' + }, + scales: { + yAxis: { + min: 0, + grid: { + display: false + }, + ticks: { + callback: function(i, index, ticks) { + return i.toFixed(0).toString() + "%"; + } + } + }, + xAxis: { + grid: { + display: false + } + } + } + }; + + var dataMem = { + labels: [], + datasets: [{ + label: "MEM %", + backgroundColor: "rgba(41, 187, 239, 0.3)", + borderColor: "rgba(41, 187, 239, 0.6)", + pointRadius: 1, + pointHitRadius: 6, + borderWidth: 2, + fill: true, + tension: 0.2, + data: [] + }] + }; + var optionsMem = { + interaction: { + mode: 'index' + }, + scales: { + yAxis: { + min: 0, + grid: { + display: false + }, + ticks: { + callback: function(i, index, ticks) { + return i.toFixed(0).toString() + "%"; + } + } + }, + xAxis: { + grid: { + display: false + } + } + } + }; + + + var net_io_chart = new Chart(cpu_ctx, { + type: 'line', + data: dataCpu, + options: optionsCpu + }); + var disk_io_chart = new Chart(mem_ctx, { + type: 'line', + data: dataMem, + options: optionsMem + }); +} +// check for mailcow updates +function check_update(current_version, github_repo_url){ + if (!current_version || !github_repo_url) return false; + + var github_account = github_repo_url.split("/")[3]; + var github_repo_name = github_repo_url.split("/")[4]; + + // get details about latest release + window.fetch("https://api.github.com/repos/"+github_account+"/"+github_repo_name+"/releases/latest", {method:'GET',cache:'no-cache'}).then(function(response) { + return response.json(); + }).then(function(latest_data) { + // get details about current release + window.fetch("https://api.github.com/repos/"+github_account+"/"+github_repo_name+"/releases/tags/"+current_version, {method:'GET',cache:'no-cache'}).then(function(response) { + return response.json(); + }).then(function(current_data) { + // compare releases + var date_current = new Date(current_data.created_at); + var date_latest = new Date(latest_data.created_at); + if (date_latest.getTime() <= date_current.getTime()){ + // no update available + $("#mailcow_update").removeClass("text-warning text-danger").addClass("text-success"); + $("#mailcow_update").html("" + lang_debug.no_update_available + ""); + } else { + // update available + $("#mailcow_update").removeClass("text-danger text-success").addClass("text-warning"); + $("#mailcow_update").html(lang_debug.update_available + ` `+latest_data.tag_name+``); + $("#mailcow_update_changelog").click(function(){ + if (mailcow_cc_role !== "admin" && mailcow_cc_role !== "domainadmin") + return; + + showVersionModal("New Release " + latest_data.tag_name, latest_data.tag_name); + }) + } + }).catch(err => { + // err + console.log(err); + $("#mailcow_update").removeClass("text-success text-warning").addClass("text-danger"); + $("#mailcow_update").html(""+ lang_debug.update_failed +""); + }); + }).catch(err => { + // err + console.log(err); + $("#mailcow_update").removeClass("text-success text-warning").addClass("text-danger"); + $("#mailcow_update").html(""+ lang_debug.update_failed +""); + }); +} +// show version changelog modal +function showVersionModal(title, version){ + $.ajax({ + type: 'GET', + url: 'https://api.github.com/repos/' + mailcow_info.project_owner + '/' + mailcow_info.project_repo + '/releases/tags/' + version, + dataType: 'json', + success: function (data) { + var md = window.markdownit(); + var result = md.render(data.body); + result = parseGithubMarkdownLinks(result); + + $('#showVersionModal').find(".modal-title").html(title); + $('#showVersionModal').find(".modal-body").html(` +

` + data.name + `

+ ` + result + ` + Github Link: + ` + version + ` + + `); + + new bootstrap.Modal(document.getElementById("showVersionModal"), { + backdrop: 'static', + keyboard: false + }).show(); + } + }); +} +function parseGithubMarkdownLinks(inputText) { + var replacedText, replacePattern1; + + replacePattern1 = /(\b(https?):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim; + replacedText = inputText.replace(replacePattern1, (matched, index, original, input_string) => { + if (matched.includes('github.com')){ + // return short link if it's github link + last_uri_path = matched.split('/'); + last_uri_path = last_uri_path[last_uri_path.length - 1]; + + // adjust Full Changelog link to match last git version and new git version, if link is a compare link + if (matched.includes('/compare/') && mailcow_info.last_version_tag !== ''){ + matched = matched.replace(last_uri_path, mailcow_info.last_version_tag + '...' + mailcow_info.version_tag); + last_uri_path = mailcow_info.last_version_tag + '...' + mailcow_info.version_tag; + } + + return '' + last_uri_path + '
'; + }; + + // if it's not a github link, return complete link + return '' + matched + ''; + }); + + return replacedText; +} + +function convertTimestampToLocalFormat(timestamp) { + var date = new Date(timestamp ? timestamp * 1000 : 0); + return date.toLocaleDateString(LOCALE, DATETIME_FORMAT); +} diff --git a/data/web/js/site/quarantine.js b/data/web/js/site/quarantine.js index d838b0fb7..34531b0d3 100644 --- a/data/web/js/site/quarantine.js +++ b/data/web/js/site/quarantine.js @@ -97,7 +97,7 @@ jQuery(function($){ }, { title: lang.subj, - data: 'sender', + data: 'subject', defaultContent: '' }, { diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json index b6229491a..7b4b1f46f 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -488,6 +488,7 @@ "chart_this_server": "Chart (dieser Server)", "containers_info": "Container-Information", "container_running": "Läuft", + "container_disabled": "Container gestoppt oder deaktiviert", "container_stopped": "Angehalten", "cores": "Kerne", "current_time": "Systemzeit", diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index ce6e2cf8e..00b14f07a 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -491,6 +491,7 @@ "chart_this_server": "Chart (this server)", "containers_info": "Container information", "container_running": "Running", + "container_disabled": "Container stopped or disabled", "container_stopped": "Stopped", "cores": "Cores", "current_time": "System Time", diff --git a/data/web/templates/base.twig b/data/web/templates/base.twig index 743a2b2da..06c47bd2c 100644 --- a/data/web/templates/base.twig +++ b/data/web/templates/base.twig @@ -80,7 +80,9 @@ {% if mailcow_cc_role == 'admin' %}
  • {{ lang.queue.queue_manager }}
  • {% endif %} + {% if mailcow_cc_role == 'admin' %}
  • {{ lang.header.restart_sogo }}
  • + {% endif %} {% endif %} diff --git a/data/web/templates/debug.twig b/data/web/templates/debug.twig index eb48d54e8..6c96de880 100644 --- a/data/web/templates/debug.twig +++ b/data/web/templates/debug.twig @@ -160,8 +160,14 @@
    solr-mailcow + {% if containers["solr-mailcow"].State.Running == 1 %} ({{ containers["solr-mailcow"].Config.Image }}) + {% endif %} + {% if containers["solr-mailcow"].State.Running == 1 %} ({{ lang.debug.started_on }} {{ containers["solr-mailcow"].State.StartedAtHR }}) + {% elseif containers["solr-mailcow"].State.Running != 1 %} + {{ lang.debug.container_disabled }} + {% endif %} {% if containers["solr-mailcow"].State.Running == 1 %} {{ lang.debug.container_running }} @@ -169,19 +175,22 @@ . . - {% elseif containers["solr-mailcow"].State %} + {% elseif containers["solr-mailcow"].State.Running != 1 %} {{ lang.debug.container_stopped }} {% endif %}
    + {% if containers["solr-mailcow"].State.Running == 1 %}
    + {% endif %}
    + {% if containers["solr-mailcow"].State.Running == 1 %}
    @@ -238,6 +247,7 @@
    + {% endif %} diff --git a/data/web/templates/edit/mailbox.twig b/data/web/templates/edit/mailbox.twig index ce01a659e..289638d6f 100644 --- a/data/web/templates/edit/mailbox.twig +++ b/data/web/templates/edit/mailbox.twig @@ -274,7 +274,7 @@

    {{ lang.user.pushover_info|format(mailbox)|raw }}

    -

    {{ lang.edit.pushover_vars|raw }}: {SUBJECT}, {SENDER}, {SENDER_ADDRESS}, {SENDER_NAME}, {TO_NAME}, {TO_ADDRESS}, {MSG_ID}

    +

    {{ lang.edit.pushover_vars|raw }}: {SUBJECT}, {SENDER}, {SENDER_ADDRESS}, {SENDER_NAME}, {TO_NAME}, {TO_ADDRESS}, {MSG_ID}

    diff --git a/helper-scripts/update_compose.sh b/helper-scripts/update_compose.sh index 01be926fe..ae2d6ab14 100755 --- a/helper-scripts/update_compose.sh +++ b/helper-scripts/update_compose.sh @@ -42,8 +42,6 @@ echo -e "\e[32mTrying to determine GLIBC version...\e[0m" elif [[ $(curl -sL -w "%{http_code}" https://github.com/docker/compose/releases/latest -o /dev/null) == "200" ]]; then LATEST_COMPOSE=$(curl -Ls -w %{url_effective} -o /dev/null https://github.com/docker/compose/releases/latest) # redirect to latest release LATEST_COMPOSE=${LATEST_COMPOSE##*/} #get the latest version from the redirect, inlcuding the "v" prefix - if [ $DC_DL_SUFFIX]; then - LATEST_COMPOSE=1.27.4 # force 1.27.4 for legacy systems, tag is not prefixed by "v" COMPOSE_VERSION=$(docker-compose version --short) if [[ "$LATEST_COMPOSE" != "$COMPOSE_VERSION" ]]; then COMPOSE_PATH=$(command -v docker-compose) @@ -71,4 +69,4 @@ elif [ "${DOCKER_COMPOSE_VERSION}" == "native" ]; then else echo -e "\e[31mCan not read DOCKER_COMPOSE_VERSION variable from mailcow.conf! Is your mailcow up to date? Exiting...\e[0m" exit 1 -fi +fi \ No newline at end of file