From 8a0bb3d0962b1204bea523323a30fef73a7ecc69 Mon Sep 17 00:00:00 2001 From: apor Date: Tue, 14 May 2024 10:08:59 +0300 Subject: [PATCH 01/58] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BE=D0=BF=D0=BE=D0=B2=D0=B5=D1=89=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=BE=20=D0=BF=D1=80=D0=B8=D1=81=D0=BE=D0=B5=D0=B4?= =?UTF-8?q?=D0=B8=D0=BD=D0=B5=D0=BD=D0=B8=D0=B8=20=D1=81=D0=BE=D1=82=D1=80?= =?UTF-8?q?=D1=83=D0=B4=D0=BD=D0=B8=D0=BA=D0=B0=20=D0=BA=20=D0=BA=D0=BE?= =?UTF-8?q?=D0=BD=D1=84=D0=B5=D1=80=D0=B5=D0=BD=D1=86=D0=B8=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../js/pbx/OutOffWorkTime/out-of-work-time-modify.js | 12 ++++++------ .../js/src/OutOffWorkTime/out-of-work-time-modify.js | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/sites/admin-cabinet/assets/js/pbx/OutOffWorkTime/out-of-work-time-modify.js b/sites/admin-cabinet/assets/js/pbx/OutOffWorkTime/out-of-work-time-modify.js index 79a801bba..26f3cd2fb 100644 --- a/sites/admin-cabinet/assets/js/pbx/OutOffWorkTime/out-of-work-time-modify.js +++ b/sites/admin-cabinet/assets/js/pbx/OutOffWorkTime/out-of-work-time-modify.js @@ -372,7 +372,7 @@ var outOfWorkTimeRecord = { } // Check all fields - if ($('#calType').parent().dropdown('get value') !== 'caldav' && result.data.time_from === '' && result.data.time_to === '' && result.data.weekday_from === '-1' && result.data.weekday_to === '-1' && result.data.date_from === '' && result.data.date_to === '') { + if ($('#calType').parent().dropdown('get value') === 'none' && result.data.time_from === '' && result.data.time_to === '' && result.data.weekday_from === '-1' && result.data.weekday_to === '-1' && result.data.date_from === '' && result.data.date_to === '') { $('.form .error.message').html(globalTranslate.tf_ValidateNoRulesSelected).show(); Form.$submitButton.transition('shake').removeClass('loading disabled'); return false; @@ -396,12 +396,12 @@ var outOfWorkTimeRecord = { var serverOffset = parseInt(outOfWorkTimeRecord.$formObj.form('get value', 'serverOffset')); var offsetDiff = serverOffset + currentOffset; - if ($('#calType').parent().dropdown('get value') === 'caldav') { - Form.validateRules.timefrom.rules = []; - Form.validateRules.timeto.rules = []; - } else { + if ($('#calType').parent().dropdown('get value') === 'none') { Form.validateRules.timefrom.rules = outOfWorkTimeRecord.additionalTimeIntervalRules; Form.validateRules.timeto.rules = outOfWorkTimeRecord.additionalTimeIntervalRules; + } else { + Form.validateRules.timefrom.rules = []; + Form.validateRules.timeto.rules = []; } if (dateFrom) { @@ -483,4 +483,4 @@ $.fn.form.settings.rules.customNotEmptyIfCalType = function (value) { $(document).ready(function () { outOfWorkTimeRecord.initialize(); }); -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9PdXRPZmZXb3JrVGltZS9vdXQtb2Ytd29yay10aW1lLW1vZGlmeS5qcyJdLCJuYW1lcyI6WyJvdXRPZldvcmtUaW1lUmVjb3JkIiwiJGZvcm1PYmoiLCIkIiwiJGRlZmF1bHREcm9wZG93biIsIiRyYW5nZURheXNTdGFydCIsIiRyYW5nZURheXNFbmQiLCIkcmFuZ2VUaW1lU3RhcnQiLCIkcmFuZ2VUaW1lRW5kIiwiJGRhdGVfZnJvbSIsIiRkYXRlX3RvIiwiJHRpbWVfdG8iLCIkZm9yd2FyZGluZ1NlbGVjdERyb3Bkb3duIiwiYWRkaXRpb25hbFRpbWVJbnRlcnZhbFJ1bGVzIiwidHlwZSIsInZhbHVlIiwicHJvbXB0IiwiZ2xvYmFsVHJhbnNsYXRlIiwidGZfVmFsaWRhdGVDaGVja1RpbWVJbnRlcnZhbCIsInZhbGlkYXRlUnVsZXMiLCJhdWRpb19tZXNzYWdlX2lkIiwiaWRlbnRpZmllciIsInJ1bGVzIiwidGZfVmFsaWRhdGVBdWRpb01lc3NhZ2VFbXB0eSIsImNhbFVybCIsInRmX1ZhbGlkYXRlQ2FsVXJpIiwiZXh0ZW5zaW9uIiwidGZfVmFsaWRhdGVFeHRlbnNpb25FbXB0eSIsInRpbWVmcm9tIiwib3B0aW9uYWwiLCJ0aW1ldG8iLCJpbml0aWFsaXplIiwidGFiIiwiZHJvcGRvd24iLCJjYWxlbmRhciIsImZpcnN0RGF5T2ZXZWVrIiwiU2VtYW50aWNMb2NhbGl6YXRpb24iLCJjYWxlbmRhckZpcnN0RGF5T2ZXZWVrIiwidGV4dCIsImNhbGVuZGFyVGV4dCIsImVuZENhbGVuZGFyIiwiaW5saW5lIiwibW9udGhGaXJzdCIsInJlZ0V4cCIsInN0YXJ0Q2FsZW5kYXIiLCJvbkNoYW5nZSIsIm5ld0RhdGVUbyIsIm9sZERhdGVUbyIsImF0dHIiLCJEYXRlIiwidHJpZ2dlciIsIkZvcm0iLCJkYXRhQ2hhbmdlZCIsImRpc2FibGVNaW51dGUiLCJhbXBtIiwibmV3VGltZVRvIiwib2xkVGltZVRvIiwidG9nZ2xlRGlzYWJsZWRGaWVsZENsYXNzIiwiZnJvbSIsImZvcm0iLCJ0byIsIm9uIiwiZSIsImRhdGVfZnJvbSIsImRhdGVfdG8iLCJwcmV2ZW50RGVmYXVsdCIsIndlZWtkYXlfZnJvbSIsIndlZWtkYXlfdG8iLCJTb3VuZEZpbGVzU2VsZWN0b3IiLCJnZXREcm9wZG93blNldHRpbmdzV2l0aEVtcHR5IiwiY2hhbmdlRGF0ZUZvcm1hdCIsImluaXRpYWxpemVGb3JtIiwiRXh0ZW5zaW9ucyIsImdldERyb3Bkb3duU2V0dGluZ3NXaXRob3V0RW1wdHkiLCJjaGVja2JveCIsIm5ld1N0YXRlIiwicGFyZW50IiwiZGlkIiwiZmlsdGVyIiwiY2hhbmdlUmVzdHJpY3Rpb24iLCJzaG93IiwiaGlkZSIsImRhdGVGcm9tIiwiZGF0ZVRvIiwiY3VycmVudE9mZnNldCIsImdldFRpbWV6b25lT2Zmc2V0Iiwic2VydmVyT2Zmc2V0IiwicGFyc2VJbnQiLCJvZmZzZXREaWZmIiwidW5kZWZpbmVkIiwibGVuZ3RoIiwiZGF0ZUZyb21JbkJyb3dzZXJUWiIsImRhdGVUb0luQnJvd3NlclRaIiwiY3VzdG9tVmFsaWRhdGVGb3JtIiwicmVzdWx0IiwiZGF0YSIsImh0bWwiLCJ0Zl9WYWxpZGF0ZUNoZWNrRGF0ZUludGVydmFsIiwiJHN1Ym1pdEJ1dHRvbiIsInRyYW5zaXRpb24iLCJyZW1vdmVDbGFzcyIsInRmX1ZhbGlkYXRlQ2hlY2tXZWVrRGF5SW50ZXJ2YWwiLCJ0aW1lX2Zyb20iLCJ0aW1lX3RvIiwidGZfVmFsaWRhdGVOb1J1bGVzU2VsZWN0ZWQiLCJjYkJlZm9yZVNlbmRGb3JtIiwic2V0dGluZ3MiLCJzZXRIb3VycyIsIk1hdGgiLCJmbG9vciIsImdldFRpbWUiLCJjYkFmdGVyU2VuZEZvcm0iLCJyZXNwb25zZSIsInVybCIsImdsb2JhbFJvb3RVcmwiLCJmbiIsImN1c3RvbU5vdEVtcHR5SWZBY3Rpb25SdWxlIiwiYWN0aW9uIiwidmFsIiwiY3VzdG9tTm90RW1wdHlJZkNhbFR5cGUiLCJVUkwiLCJfIiwiZG9jdW1lbnQiLCJyZWFkeSJd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QUFPLElBQVA7QUFDSCxDQVZEO0FBYUE7QUFDQTtBQUNBOzs7QUFDQXRILENBQUMsQ0FBQ3VILFFBQUQsQ0FBRCxDQUFZQyxLQUFaLENBQWtCLFlBQU07QUFDcEIxSCxFQUFBQSxtQkFBbUIsQ0FBQzhCLFVBQXBCO0FBQ0gsQ0FGRCIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBNaWtvUEJYIC0gZnJlZSBwaG9uZSBzeXN0ZW0gZm9yIHNtYWxsIGJ1c2luZXNzXG4gKiBDb3B5cmlnaHQgwqkgMjAxNy0yMDIzIEFsZXhleSBQb3J0bm92IGFuZCBOaWtvbGF5IEJla2V0b3ZcbiAqXG4gKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIHByb2dyYW0uXG4gKiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICovXG5cbi8qIGdsb2JhbCBnbG9iYWxSb290VXJsLGdsb2JhbFRyYW5zbGF0ZSwgRXh0ZW5zaW9ucywgRm9ybSwgU2VtYW50aWNMb2NhbGl6YXRpb24sIFNvdW5kRmlsZXNTZWxlY3RvciAqL1xuXG5cbi8qKlxuICogT2JqZWN0IGZvciBtYW5hZ2luZyBPdXQtb2YtV29yayBUaW1lIHNldHRpbmdzXG4gKlxuICogQG1vZHVsZSBvdXRPZldvcmtUaW1lUmVjb3JkXG4gKi9cbmNvbnN0IG91dE9mV29ya1RpbWVSZWNvcmQgPSB7XG4gICAgLyoqXG4gICAgICogalF1ZXJ5IG9iamVjdCBmb3IgdGhlIGZvcm0uXG4gICAgICogQHR5cGUge2pRdWVyeX1cbiAgICAgKi9cbiAgICAkZm9ybU9iajogJCgnI3NhdmUtb3V0b2Zmd29yay1mb3JtJyksXG5cbiAgICAkZGVmYXVsdERyb3Bkb3duOiAkKCcjc2F2ZS1vdXRvZmZ3b3JrLWZvcm0gLmRyb3Bkb3duLWRlZmF1bHQnKSxcbiAgICAkcmFuZ2VEYXlzU3RhcnQ6ICQoJyNyYW5nZS1kYXlzLXN0YXJ0JyksXG4gICAgJHJhbmdlRGF5c0VuZDogJCgnI3JhbmdlLWRheXMtZW5kJyksXG4gICAgJHJhbmdlVGltZVN0YXJ0OiAkKCcjcmFuZ2UtdGltZS1zdGFydCcpLFxuICAgICRyYW5nZVRpbWVFbmQ6ICQoJyNyYW5nZS10aW1lLWVuZCcpLFxuICAgICRkYXRlX2Zyb206ICQoJyNkYXRlX2Zyb20nKSxcbiAgICAkZGF0ZV90bzogJCgnI2RhdGVfdG8nKSxcbiAgICAkdGltZV90bzogJCgnI3RpbWVfdG8nKSxcbiAgICAkZm9yd2FyZGluZ1NlbGVjdERyb3Bkb3duOiAkKCcjc2F2ZS1vdXRvZmZ3b3JrLWZvcm0gLmZvcndhcmRpbmctc2VsZWN0JyksXG5cblxuICAgIC8qKlxuICAgICAqIEFkZGl0aW9uYWwgY29uZGl0aW9uIGZvciB0aGUgdGltZSBpbnRlcnZhbFxuICAgICAqIEB0eXBlIHthcnJheX1cbiAgICAgKi9cbiAgICBhZGRpdGlvbmFsVGltZUludGVydmFsUnVsZXM6IFt7XG4gICAgICAgIHR5cGU6ICdyZWdFeHAnLFxuICAgICAgICB2YWx1ZTogL14oMlswLTNdfDE/WzAtOV0pOihbMC01XT9bMC05XSkkLyxcbiAgICAgICAgcHJvbXB0OiBnbG9iYWxUcmFuc2xhdGUudGZfVmFsaWRhdGVDaGVja1RpbWVJbnRlcnZhbCxcbiAgICB9XSxcblxuICAgIC8qKlxuICAgICAqIFZhbGlkYXRpb24gcnVsZXMgZm9yIHRoZSBmb3JtIGZpZWxkcyBiZWZvcmUgc3VibWlzc2lvbi5cbiAgICAgKlxuICAgICAqIEB0eXBlIHtvYmplY3R9XG4gICAgICovXG4gICAgdmFsaWRhdGVSdWxlczoge1xuICAgICAgICBhdWRpb19tZXNzYWdlX2lkOiB7XG4gICAgICAgICAgICBpZGVudGlmaWVyOiAnYXVkaW9fbWVzc2FnZV9pZCcsXG4gICAgICAgICAgICBydWxlczogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2N1c3RvbU5vdEVtcHR5SWZBY3Rpb25SdWxlW3BsYXltZXNzYWdlXScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLnRmX1ZhbGlkYXRlQXVkaW9NZXNzYWdlRW1wdHksXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICAgIGNhbFVybDoge1xuICAgICAgICAgICAgaWRlbnRpZmllcjogJ2NhbFVybCcsXG4gICAgICAgICAgICBydWxlczogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZSAgIDogJ2N1c3RvbU5vdEVtcHR5SWZDYWxUeXBlJyxcbiAgICAgICAgICAgICAgICAgICAgcHJvbXB0IDogZ2xvYmFsVHJhbnNsYXRlLnRmX1ZhbGlkYXRlQ2FsVXJpXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgXVxuICAgICAgICB9LFxuICAgICAgICBleHRlbnNpb246IHtcbiAgICAgICAgICAgIGlkZW50aWZpZXI6ICdleHRlbnNpb24nLFxuICAgICAgICAgICAgcnVsZXM6IFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdjdXN0b21Ob3RFbXB0eUlmQWN0aW9uUnVsZVtleHRlbnNpb25dJyxcbiAgICAgICAgICAgICAgICAgICAgcHJvbXB0OiBnbG9iYWxUcmFuc2xhdGUudGZfVmFsaWRhdGVFeHRlbnNpb25FbXB0eSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgICAgdGltZWZyb206IHtcbiAgICAgICAgICAgIG9wdGlvbmFsOiB0cnVlLFxuICAgICAgICAgICAgaWRlbnRpZmllcjogJ3RpbWVfZnJvbScsXG4gICAgICAgICAgICBydWxlczogW3tcbiAgICAgICAgICAgICAgICB0eXBlOiAncmVnRXhwJyxcbiAgICAgICAgICAgICAgICB2YWx1ZTogL14oMlswLTNdfDE/WzAtOV0pOihbMC01XT9bMC05XSkkLyxcbiAgICAgICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS50Zl9WYWxpZGF0ZUNoZWNrVGltZUludGVydmFsLFxuICAgICAgICAgICAgfV0sXG4gICAgICAgIH0sXG4gICAgICAgIHRpbWV0bzoge1xuICAgICAgICAgICAgaWRlbnRpZmllcjogJ3RpbWVfdG8nLFxuICAgICAgICAgICAgb3B0aW9uYWw6IHRydWUsXG4gICAgICAgICAgICBydWxlczogW3tcbiAgICAgICAgICAgICAgICB0eXBlOiAncmVnRXhwJyxcbiAgICAgICAgICAgICAgICB2YWx1ZTogL14oMlswLTNdfDE/WzAtOV0pOihbMC01XT9bMC05XSkkLyxcbiAgICAgICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS50Zl9WYWxpZGF0ZUNoZWNrVGltZUludGVydmFsLFxuICAgICAgICAgICAgfV0sXG4gICAgICAgIH0sXG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemVzIHRoZSBvdXQgb2Ygd29yayB0aW1lIHJlY29yZCBmb3JtLlxuICAgICAqL1xuICAgIGluaXRpYWxpemUoKSB7XG4gICAgICAgIC8vIEluaXRpYWxpemUgdGFiIGJlaGF2aW9yIGZvciB0aGUgb3V0LXRpbWUtbW9kaWZ5LW1lbnVcbiAgICAgICAgJCgnI291dC10aW1lLW1vZGlmeS1tZW51IC5pdGVtJykudGFiKCk7XG5cbiAgICAgICAgLy8gSW5pdGlhbGl6ZSB0aGUgZGVmYXVsdCBkcm9wZG93blxuICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLiRkZWZhdWx0RHJvcGRvd24uZHJvcGRvd24oKTtcblxuICAgICAgICAvLyBJbml0aWFsaXplIHRoZSBjYWxlbmRhciBmb3IgcmFuZ2UgZGF5cyBzdGFydFxuICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLiRyYW5nZURheXNTdGFydC5jYWxlbmRhcih7XG4gICAgICAgICAgICAvLyBDYWxlbmRhciBjb25maWd1cmF0aW9uIG9wdGlvbnNcbiAgICAgICAgICAgIGZpcnN0RGF5T2ZXZWVrOiBTZW1hbnRpY0xvY2FsaXphdGlvbi5jYWxlbmRhckZpcnN0RGF5T2ZXZWVrLFxuICAgICAgICAgICAgdGV4dDogU2VtYW50aWNMb2NhbGl6YXRpb24uY2FsZW5kYXJUZXh0LFxuICAgICAgICAgICAgZW5kQ2FsZW5kYXI6IG91dE9mV29ya1RpbWVSZWNvcmQuJHJhbmdlRGF5c0VuZCxcbiAgICAgICAgICAgIHR5cGU6ICdkYXRlJyxcbiAgICAgICAgICAgIGlubGluZTogZmFsc2UsXG4gICAgICAgICAgICBtb250aEZpcnN0OiBmYWxzZSxcbiAgICAgICAgICAgIHJlZ0V4cDogU2VtYW50aWNMb2NhbGl6YXRpb24ucmVnRXhwLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBJbml0aWFsaXplIHRoZSBjYWxlbmRhciBmb3IgcmFuZ2UgZGF5cyBlbmRcbiAgICAgICAgb3V0T2ZXb3JrVGltZVJlY29yZC4kcmFuZ2VEYXlzRW5kLmNhbGVuZGFyKHtcbiAgICAgICAgICAgIC8vIENhbGVuZGFyIGNvbmZpZ3VyYXRpb24gb3B0aW9uc1xuICAgICAgICAgICAgZmlyc3REYXlPZldlZWs6IFNlbWFudGljTG9jYWxpemF0aW9uLmNhbGVuZGFyRmlyc3REYXlPZldlZWssXG4gICAgICAgICAgICB0ZXh0OiBTZW1hbnRpY0xvY2FsaXphdGlvbi5jYWxlbmRhclRleHQsXG4gICAgICAgICAgICBzdGFydENhbGVuZGFyOiBvdXRPZldvcmtUaW1lUmVjb3JkLiRyYW5nZURheXNTdGFydCxcbiAgICAgICAgICAgIHR5cGU6ICdkYXRlJyxcbiAgICAgICAgICAgIGlubGluZTogZmFsc2UsXG4gICAgICAgICAgICBtb250aEZpcnN0OiBmYWxzZSxcbiAgICAgICAgICAgIHJlZ0V4cDogU2VtYW50aWNMb2NhbGl6YXRpb24ucmVnRXhwLFxuICAgICAgICAgICAgb25DaGFuZ2U6IChuZXdEYXRlVG8pID0+IHtcbiAgICAgICAgICAgICAgICAvLyBIYW5kbGUgdGhlIGNoYW5nZSBldmVudCBmb3IgcmFuZ2UgdGltZSBlbmRcbiAgICAgICAgICAgICAgICBsZXQgb2xkRGF0ZVRvID0gb3V0T2ZXb3JrVGltZVJlY29yZC4kZGF0ZV90by5hdHRyKCd2YWx1ZScpO1xuICAgICAgICAgICAgICAgIGlmIChuZXdEYXRlVG8gIT09IG51bGwgJiYgb2xkRGF0ZVRvICE9PSAnJykge1xuICAgICAgICAgICAgICAgICAgICBvbGREYXRlVG8gPSBuZXcgRGF0ZShvbGREYXRlVG8gKiAxMDAwKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKChuZXdEYXRlVG8gLSBvbGREYXRlVG8pICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLiRkYXRlX2Zyb20udHJpZ2dlcignY2hhbmdlJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBGb3JtLmRhdGFDaGFuZ2VkKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBJbml0aWFsaXplIHRoZSBjYWxlbmRhciBmb3IgcmFuZ2UgdGltZSBzdGFydFxuICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLiRyYW5nZVRpbWVTdGFydC5jYWxlbmRhcih7XG4gICAgICAgICAgICAvLyBDYWxlbmRhciBjb25maWd1cmF0aW9uIG9wdGlvbnNcbiAgICAgICAgICAgIGZpcnN0RGF5T2ZXZWVrOiBTZW1hbnRpY0xvY2FsaXphdGlvbi5jYWxlbmRhckZpcnN0RGF5T2ZXZWVrLFxuICAgICAgICAgICAgdGV4dDogU2VtYW50aWNMb2NhbGl6YXRpb24uY2FsZW5kYXJUZXh0LFxuICAgICAgICAgICAgZW5kQ2FsZW5kYXI6IG91dE9mV29ya1RpbWVSZWNvcmQuJHJhbmdlVGltZUVuZCxcbiAgICAgICAgICAgIHR5cGU6ICd0aW1lJyxcbiAgICAgICAgICAgIGlubGluZTogZmFsc2UsXG4gICAgICAgICAgICBkaXNhYmxlTWludXRlOiB0cnVlLFxuICAgICAgICAgICAgYW1wbTogZmFsc2UsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIGNhbGVuZGFyIGZvciByYW5nZSB0aW1lIGVuZFxuICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLiRyYW5nZVRpbWVFbmQuY2FsZW5kYXIoe1xuICAgICAgICAgICAgLy8gQ2FsZW5kYXIgY29uZmlndXJhdGlvbiBvcHRpb25zXG4gICAgICAgICAgICBmaXJzdERheU9mV2VlazogU2VtYW50aWNMb2NhbGl6YXRpb24uY2FsZW5kYXJGaXJzdERheU9mV2VlayxcbiAgICAgICAgICAgIHRleHQ6IFNlbWFudGljTG9jYWxpemF0aW9uLmNhbGVuZGFyVGV4dCxcbiAgICAgICAgICAgIHR5cGU6ICd0aW1lJyxcbiAgICAgICAgICAgIGlubGluZTogZmFsc2UsXG4gICAgICAgICAgICBkaXNhYmxlTWludXRlOiB0cnVlLFxuICAgICAgICAgICAgYW1wbTogZmFsc2UsXG4gICAgICAgICAgICBvbkNoYW5nZTogKG5ld1RpbWVUbykgPT4ge1xuICAgICAgICAgICAgICAgIC8vIEhhbmRsZSB0aGUgY2hhbmdlIGV2ZW50IGZvciByYW5nZSB0aW1lIGVuZFxuICAgICAgICAgICAgICAgIGxldCBvbGRUaW1lVG8gPSBvdXRPZldvcmtUaW1lUmVjb3JkLiR0aW1lX3RvLmF0dHIoJ3ZhbHVlJyk7XG4gICAgICAgICAgICAgICAgaWYgKG5ld1RpbWVUbyAhPT0gbnVsbCAmJiBvbGRUaW1lVG8gIT09ICcnKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFRpbWVUbyA9IG5ldyBEYXRlKG9sZFRpbWVUbyAqIDEwMDApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoKG5ld1RpbWVUbyAtIG9sZFRpbWVUbykgIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dE9mV29ya1RpbWVSZWNvcmQuJHRpbWVfdG8udHJpZ2dlcignY2hhbmdlJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBGb3JtLmRhdGFDaGFuZ2VkKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBJbml0aWFsaXplIHRoZSBhY3Rpb24gZHJvcGRvd25cbiAgICAgICAgJCgnI2FjdGlvbicpXG4gICAgICAgICAgICAuZHJvcGRvd24oe1xuICAgICAgICAgICAgICAgIG9uQ2hhbmdlKCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBIYW5kbGUgdGhlIGNoYW5nZSBldmVudCBmb3IgdGhlIGFjdGlvbiBkcm9wZG93blxuICAgICAgICAgICAgICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLnRvZ2dsZURpc2FibGVkRmllbGRDbGFzcygpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgLy8gSW5pdGlhbGl6ZSB0aGUgY2FsVHlwZSBkcm9wZG93blxuICAgICAgICAkKCcjY2FsVHlwZScpXG4gICAgICAgICAgICAuZHJvcGRvd24oe1xuICAgICAgICAgICAgICAgIG9uQ2hhbmdlKCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBIYW5kbGUgdGhlIGNoYW5nZSBldmVudCBmb3IgdGhlIGFjdGlvbiBkcm9wZG93blxuICAgICAgICAgICAgICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLnRvZ2dsZURpc2FibGVkRmllbGRDbGFzcygpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAvLyBJbml0aWFsaXplIHRoZSB3ZWVrZGF5X2Zyb20gZHJvcGRvd25cbiAgICAgICAgJCgnI3dlZWtkYXlfZnJvbScpXG4gICAgICAgICAgICAuZHJvcGRvd24oe1xuICAgICAgICAgICAgICAgIG9uQ2hhbmdlKCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBIYW5kbGUgdGhlIGNoYW5nZSBldmVudCBmb3IgdGhlIHdlZWtkYXlfZnJvbSBkcm9wZG93blxuICAgICAgICAgICAgICAgICAgICBjb25zdCBmcm9tID0gb3V0T2ZXb3JrVGltZVJlY29yZC4kZm9ybU9iai5mb3JtKCdnZXQgdmFsdWUnLCAnd2Vla2RheV9mcm9tJyk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRvID0gb3V0T2ZXb3JrVGltZVJlY29yZC4kZm9ybU9iai5mb3JtKCdnZXQgdmFsdWUnLCAnd2Vla2RheV90bycpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZnJvbSA8IHRvIHx8IHRvID09PSAtMSB8fCBmcm9tID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0T2ZXb3JrVGltZVJlY29yZC4kZm9ybU9iai5mb3JtKCdzZXQgdmFsdWUnLCAnd2Vla2RheV90bycsIGZyb20pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIHdlZWtkYXlfdG8gZHJvcGRvd25cbiAgICAgICAgJCgnI3dlZWtkYXlfdG8nKVxuICAgICAgICAgICAgLmRyb3Bkb3duKHtcbiAgICAgICAgICAgICAgICBvbkNoYW5nZSgpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSGFuZGxlIHRoZSBjaGFuZ2UgZXZlbnQgZm9yIHRoZSB3ZWVrZGF5X3RvIGRyb3Bkb3duXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGZyb20gPSBvdXRPZldvcmtUaW1lUmVjb3JkLiRmb3JtT2JqLmZvcm0oJ2dldCB2YWx1ZScsICd3ZWVrZGF5X2Zyb20nKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdG8gPSBvdXRPZldvcmtUaW1lUmVjb3JkLiRmb3JtT2JqLmZvcm0oJ2dldCB2YWx1ZScsICd3ZWVrZGF5X3RvJyk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0byA8IGZyb20gfHwgZnJvbSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dE9mV29ya1RpbWVSZWNvcmQuJGZvcm1PYmouZm9ybSgnc2V0IHZhbHVlJywgJ3dlZWtkYXlfZnJvbScsIHRvKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAvLyBCaW5kIGNsaWNrIGV2ZW50IHRvIGVyYXNlLWRhdGVzIGJ1dHRvblxuICAgICAgICAkKCcjZXJhc2UtZGF0ZXMnKS5vbignY2xpY2snLCAoZSkgPT4ge1xuICAgICAgICAgICAgLy8gSGFuZGxlIHRoZSBjbGljayBldmVudCBmb3IgZXJhc2UtZGF0ZXMgYnV0dG9uXG4gICAgICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLiRyYW5nZURheXNTdGFydC5jYWxlbmRhcignY2xlYXInKTtcbiAgICAgICAgICAgIG91dE9mV29ya1RpbWVSZWNvcmQuJHJhbmdlRGF5c0VuZC5jYWxlbmRhcignY2xlYXInKTtcbiAgICAgICAgICAgIG91dE9mV29ya1RpbWVSZWNvcmQuJGZvcm1PYmpcbiAgICAgICAgICAgICAgICAuZm9ybSgnc2V0IHZhbHVlcycsIHtcbiAgICAgICAgICAgICAgICAgICAgZGF0ZV9mcm9tOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgZGF0ZV90bzogJycsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEJpbmQgY2xpY2sgZXZlbnQgdG8gZXJhc2Utd2Vla2RheXMgYnV0dG9uXG4gICAgICAgICQoJyNlcmFzZS13ZWVrZGF5cycpLm9uKCdjbGljaycsIChlKSA9PiB7XG4gICAgICAgICAgICAvLyBIYW5kbGUgdGhlIGNsaWNrIGV2ZW50IGZvciBlcmFzZS13ZWVrZGF5cyBidXR0b25cbiAgICAgICAgICAgIG91dE9mV29ya1RpbWVSZWNvcmQuJGZvcm1PYmpcbiAgICAgICAgICAgICAgICAuZm9ybSgnc2V0IHZhbHVlcycsIHtcbiAgICAgICAgICAgICAgICAgICAgd2Vla2RheV9mcm9tOiAtMSxcbiAgICAgICAgICAgICAgICAgICAgd2Vla2RheV90bzogLTEsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLiRyYW5nZURheXNTdGFydC50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gQmluZCBjbGljayBldmVudCB0byBlcmFzZS10aW1lcGVyaW9kIGJ1dHRvblxuICAgICAgICAkKCcjZXJhc2UtdGltZXBlcmlvZCcpLm9uKCdjbGljaycsIChlKSA9PiB7XG4gICAgICAgICAgICAvLyBIYW5kbGUgdGhlIGNsaWNrIGV2ZW50IGZvciBlcmFzZS10aW1lcGVyaW9kIGJ1dHRvblxuICAgICAgICAgICAgb3V0T2ZXb3JrVGltZVJlY29yZC4kcmFuZ2VUaW1lU3RhcnQuY2FsZW5kYXIoJ2NsZWFyJyk7XG4gICAgICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLiRyYW5nZVRpbWVFbmQuY2FsZW5kYXIoJ2NsZWFyJyk7XG4gICAgICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLiR0aW1lX3RvLnRyaWdnZXIoJ2NoYW5nZScpO1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyBJbml0aWFsaXplIGF1ZGlvLW1lc3NhZ2Utc2VsZWN0IGRyb3Bkb3duXG4gICAgICAgICQoJyNzYXZlLW91dG9mZndvcmstZm9ybSAuYXVkaW8tbWVzc2FnZS1zZWxlY3QnKS5kcm9wZG93bihTb3VuZEZpbGVzU2VsZWN0b3IuZ2V0RHJvcGRvd25TZXR0aW5nc1dpdGhFbXB0eSgpKTtcblxuICAgICAgICAvLyBDaGFuZ2UgdGhlIGRhdGUgZm9ybWF0IGZyb20gbGludXh0aW1lIHRvIGxvY2FsIHJlcHJlc2VudGF0aW9uXG4gICAgICAgIG91dE9mV29ya1RpbWVSZWNvcmQuY2hhbmdlRGF0ZUZvcm1hdCgpO1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIGZvcm1cbiAgICAgICAgb3V0T2ZXb3JrVGltZVJlY29yZC5pbml0aWFsaXplRm9ybSgpO1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIGZvcndhcmRpbmdTZWxlY3REcm9wZG93blxuICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLiRmb3J3YXJkaW5nU2VsZWN0RHJvcGRvd24uZHJvcGRvd24oRXh0ZW5zaW9ucy5nZXREcm9wZG93blNldHRpbmdzV2l0aG91dEVtcHR5KCkpO1xuXG4gICAgICAgIC8vIFRvZ2dsZSBkaXNhYmxlZCBmaWVsZCBjbGFzcyBiYXNlZCBvbiBhY3Rpb24gdmFsdWVcbiAgICAgICAgb3V0T2ZXb3JrVGltZVJlY29yZC50b2dnbGVEaXNhYmxlZEZpZWxkQ2xhc3MoKTtcblxuICAgICAgICAvLyBCaW5kIGNoZWNrYm94IGNoYW5nZSBldmVudCBmb3IgaW5ib3VuZCBydWxlcyB0YWJsZVxuICAgICAgICAkKCcjaW5ib3VuZC1ydWxlcy10YWJsZSAudWkuY2hlY2tib3gnKS5jaGVja2JveCh7XG4gICAgICAgICAgICBvbkNoYW5nZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGxldCBuZXdTdGF0ZSA9ICd1bmNoZWNrZWQnO1xuICAgICAgICAgICAgICAgIC8vIEhhbmRsZSB0aGUgY2hhbmdlIGV2ZW50IGZvciBpbmJvdW5kIHJ1bGVzIHRhYmxlIGNoZWNrYm94XG4gICAgICAgICAgICAgICAgaWYgKCQodGhpcykucGFyZW50KCkuY2hlY2tib3goJ2lzIGNoZWNrZWQnKSkge1xuICAgICAgICAgICAgICAgICAgICBuZXdTdGF0ZSA9ICdjaGVja2VkJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IGRpZCA9ICQodGhpcykucGFyZW50KCkuYXR0cignZGF0YS1kaWQnKTtcbiAgICAgICAgICAgICAgICBsZXQgZmlsdGVyID0gJyNpbmJvdW5kLXJ1bGVzLXRhYmxlIC51aS5jaGVja2JveFtkYXRhLWNvbnRleHQtaWQ9JyArICQodGhpcykucGFyZW50KCkuYXR0cignZGF0YS1jb250ZXh0LWlkJykgKyAnXSc7XG4gICAgICAgICAgICAgICAgaWYoZGlkICE9PSAnJyAmJiBuZXdTdGF0ZSA9PT0gJ2NoZWNrZWQnKXtcbiAgICAgICAgICAgICAgICAgICAgZmlsdGVyID0gZmlsdGVyICsgJy51aS5jaGVja2JveFtkYXRhLWRpZD0nK2RpZCsnXSc7XG4gICAgICAgICAgICAgICAgfWVsc2UgaWYoZGlkID09PSAnJyAmJiBuZXdTdGF0ZSA9PT0gJ3VuY2hlY2tlZCcpe1xuICAgICAgICAgICAgICAgICAgICBmaWx0ZXIgPSBmaWx0ZXIgKyAnLnVpLmNoZWNrYm94W2RhdGEtZGlkPVwiXCJdJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgJChmaWx0ZXIpLmNoZWNrYm94KCdzZXQgJytuZXdTdGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEJpbmQgY2hlY2tib3ggY2hhbmdlIGV2ZW50IGZvciBhbGxvd1Jlc3RyaWN0aW9uIGNoZWNrYm94XG4gICAgICAgICQoJyNhbGxvd1Jlc3RyaWN0aW9uJykucGFyZW50KCkuY2hlY2tib3goe1xuICAgICAgICAgICAgb25DaGFuZ2U6IG91dE9mV29ya1RpbWVSZWNvcmQuY2hhbmdlUmVzdHJpY3Rpb25cbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gQ2FsbCBjaGFuZ2VSZXN0cmljdGlvbiBtZXRob2RcbiAgICAgICAgb3V0T2ZXb3JrVGltZVJlY29yZC5jaGFuZ2VSZXN0cmljdGlvbigpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBDaGFuZ2VzIHRoZSB2aXNpYmlsaXR5IG9mIHRoZSAncnVsZXMnIHRhYiBiYXNlZCBvbiB0aGUgY2hlY2tlZCBzdGF0dXMgb2YgdGhlICdhbGxvd1Jlc3RyaWN0aW9uJyBjaGVja2JveC5cbiAgICAgKi9cbiAgICBjaGFuZ2VSZXN0cmljdGlvbigpIHtcbiAgICAgICAgaWYgKCQoJyNhbGxvd1Jlc3RyaWN0aW9uJykucGFyZW50KCkuY2hlY2tib3goJ2lzIGNoZWNrZWQnKSkge1xuICAgICAgICAgICAgJChcImFbZGF0YS10YWI9J3J1bGVzJ11cIikuc2hvdygpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgJChcImFbZGF0YS10YWI9J3J1bGVzJ11cIikuaGlkZSgpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIHRoZSBkYXRlIGZvcm1hdCBmcm9tIGxpbnV4dGltZSB0byB0aGUgbG9jYWwgcmVwcmVzZW50YXRpb24uXG4gICAgICovXG4gICAgY2hhbmdlRGF0ZUZvcm1hdCgpIHtcbiAgICAgICAgY29uc3QgZGF0ZUZyb20gPSBvdXRPZldvcmtUaW1lUmVjb3JkLiRkYXRlX2Zyb20uYXR0cigndmFsdWUnKTtcbiAgICAgICAgY29uc3QgZGF0ZVRvID0gb3V0T2ZXb3JrVGltZVJlY29yZC4kZGF0ZV90by5hdHRyKCd2YWx1ZScpO1xuICAgICAgICBjb25zdCBjdXJyZW50T2Zmc2V0ID0gbmV3IERhdGUoKS5nZXRUaW1lem9uZU9mZnNldCgpO1xuICAgICAgICBjb25zdCBzZXJ2ZXJPZmZzZXQgPSBwYXJzZUludChvdXRPZldvcmtUaW1lUmVjb3JkLiRmb3JtT2JqLmZvcm0oJ2dldCB2YWx1ZScsICdzZXJ2ZXJPZmZzZXQnKSk7XG4gICAgICAgIGNvbnN0IG9mZnNldERpZmYgPSBzZXJ2ZXJPZmZzZXQgKyBjdXJyZW50T2Zmc2V0O1xuICAgICAgICBpZiAoZGF0ZUZyb20gIT09IHVuZGVmaW5lZCAmJiBkYXRlRnJvbS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBjb25zdCBkYXRlRnJvbUluQnJvd3NlclRaID0gZGF0ZUZyb20gKiAxMDAwICsgb2Zmc2V0RGlmZiAqIDYwICogMTAwMDtcbiAgICAgICAgICAgIG91dE9mV29ya1RpbWVSZWNvcmQuJHJhbmdlRGF5c1N0YXJ0LmNhbGVuZGFyKCdzZXQgZGF0ZScsIG5ldyBEYXRlKGRhdGVGcm9tSW5Ccm93c2VyVFopKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZGF0ZVRvICE9PSB1bmRlZmluZWQgJiYgZGF0ZVRvLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGNvbnN0IGRhdGVUb0luQnJvd3NlclRaID0gZGF0ZVRvICogMTAwMCArIG9mZnNldERpZmYgKiA2MCAqIDEwMDA7XG4gICAgICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLiRyYW5nZURheXNFbmQuY2FsZW5kYXIoJ3NldCBkYXRlJywgbmV3IERhdGUoZGF0ZVRvSW5Ccm93c2VyVFopKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBUb2dnbGVzIHRoZSB2aXNpYmlsaXR5IG9mIGNlcnRhaW4gZmllbGQgZ3JvdXBzIGJhc2VkIG9uIHRoZSBzZWxlY3RlZCBhY3Rpb24gdmFsdWUuXG4gICAgICovXG4gICAgdG9nZ2xlRGlzYWJsZWRGaWVsZENsYXNzKCkge1xuICAgICAgICBpZihvdXRPZldvcmtUaW1lUmVjb3JkLiRmb3JtT2JqLmZvcm0oJ2dldCB2YWx1ZScsICdhY3Rpb24nKSA9PT0gJ2V4dGVuc2lvbicpIHtcbiAgICAgICAgICAgICQoJyNleHRlbnNpb24tZ3JvdXAnKS5zaG93KCk7XG4gICAgICAgICAgICAkKCcjYXVkaW8tZmlsZS1ncm91cCcpLmhpZGUoKTtcbiAgICAgICAgICAgICQoJyNhdWRpb19tZXNzYWdlX2lkJykuZHJvcGRvd24oJ2NsZWFyJyk7XG4gICAgICAgIH1lbHNle1xuICAgICAgICAgICAgJCgnI2V4dGVuc2lvbi1ncm91cCcpLmhpZGUoKTtcbiAgICAgICAgICAgICQoJyNhdWRpby1maWxlLWdyb3VwJykuc2hvdygpO1xuICAgICAgICAgICAgb3V0T2ZXb3JrVGltZVJlY29yZC4kZm9ybU9iai5mb3JtKCdzZXQgdmFsdWUnLCAnZXh0ZW5zaW9uJywgLTEpO1xuICAgICAgICB9XG4gICAgICAgIGlmKG91dE9mV29ya1RpbWVSZWNvcmQuJGZvcm1PYmouZm9ybSgnZ2V0IHZhbHVlJywgJ2NhbFR5cGUnKSA9PT0gJ25vbmUnKXtcbiAgICAgICAgICAgICQoJyNjYWxsLXR5cGUtbWFpbi10YWInKS5zaG93KCk7XG4gICAgICAgICAgICAkKCcjY2FsbC10eXBlLWNhbGVuZGFyLXRhYicpLmhpZGUoKTtcbiAgICAgICAgfWVsc2V7XG4gICAgICAgICAgICAkKCcjY2FsbC10eXBlLW1haW4tdGFiJykuaGlkZSgpO1xuICAgICAgICAgICAgJCgnI2NhbGwtdHlwZS1jYWxlbmRhci10YWInKS5zaG93KCk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQ3VzdG9tIGZvcm0gdmFsaWRhdGlvbiBmb3IgdmFsaWRhdGluZyBzcGVjaWZpYyBmaWVsZHMgaW4gYSBmb3JtLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHJlc3VsdCAtIFRoZSByZXN1bHQgb2JqZWN0IGNvbnRhaW5pbmcgZm9ybSBkYXRhLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufE9iamVjdH0gUmV0dXJucyBmYWxzZSBpZiB2YWxpZGF0aW9uIGZhaWxzLCBvciB0aGUgcmVzdWx0IG9iamVjdCBpZiB2YWxpZGF0aW9uIHBhc3Nlcy5cbiAgICAgKi9cbiAgICBjdXN0b21WYWxpZGF0ZUZvcm0ocmVzdWx0KSB7XG4gICAgICAgIC8vIENoZWNrIGRhdGUgZmllbGRzXG4gICAgICAgIGlmICgocmVzdWx0LmRhdGEuZGF0ZV9mcm9tICE9PSAnJyAmJiByZXN1bHQuZGF0YS5kYXRlX3RvID09PSAnJylcbiAgICAgICAgICAgIHx8IChyZXN1bHQuZGF0YS5kYXRlX3RvICE9PSAnJyAmJiByZXN1bHQuZGF0YS5kYXRlX2Zyb20gPT09ICcnKSkge1xuICAgICAgICAgICAgJCgnLmZvcm0gLmVycm9yLm1lc3NhZ2UnKS5odG1sKGdsb2JhbFRyYW5zbGF0ZS50Zl9WYWxpZGF0ZUNoZWNrRGF0ZUludGVydmFsKS5zaG93KCk7XG4gICAgICAgICAgICBGb3JtLiRzdWJtaXRCdXR0b24udHJhbnNpdGlvbignc2hha2UnKS5yZW1vdmVDbGFzcygnbG9hZGluZyBkaXNhYmxlZCcpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2sgd2Vla2RheSBmaWVsZHNcbiAgICAgICAgaWYgKChyZXN1bHQuZGF0YS53ZWVrZGF5X2Zyb20gPiAwICYmIHJlc3VsdC5kYXRhLndlZWtkYXlfdG8gPT09ICctMScpXG4gICAgICAgICAgICB8fCAocmVzdWx0LmRhdGEud2Vla2RheV90byA+IDAgJiYgcmVzdWx0LmRhdGEud2Vla2RheV9mcm9tID09PSAnLTEnKSkge1xuICAgICAgICAgICAgJCgnLmZvcm0gLmVycm9yLm1lc3NhZ2UnKS5odG1sKGdsb2JhbFRyYW5zbGF0ZS50Zl9WYWxpZGF0ZUNoZWNrV2Vla0RheUludGVydmFsKS5zaG93KCk7XG4gICAgICAgICAgICBGb3JtLiRzdWJtaXRCdXR0b24udHJhbnNpdGlvbignc2hha2UnKS5yZW1vdmVDbGFzcygnbG9hZGluZyBkaXNhYmxlZCcpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2sgdGltZSBmaWVsZHNcbiAgICAgICAgaWYgKChyZXN1bHQuZGF0YS50aW1lX2Zyb20ubGVuZ3RoID4gMCAmJiByZXN1bHQuZGF0YS50aW1lX3RvLmxlbmd0aCA9PT0gMClcbiAgICAgICAgICAgIHx8IChyZXN1bHQuZGF0YS50aW1lX3RvLmxlbmd0aCA+IDAgJiYgcmVzdWx0LmRhdGEudGltZV9mcm9tLmxlbmd0aCA9PT0gMCkpIHtcbiAgICAgICAgICAgICQoJy5mb3JtIC5lcnJvci5tZXNzYWdlJykuaHRtbChnbG9iYWxUcmFuc2xhdGUudGZfVmFsaWRhdGVDaGVja1RpbWVJbnRlcnZhbCkuc2hvdygpO1xuICAgICAgICAgICAgRm9ybS4kc3VibWl0QnV0dG9uLnRyYW5zaXRpb24oJ3NoYWtlJykucmVtb3ZlQ2xhc3MoJ2xvYWRpbmcgZGlzYWJsZWQnKTtcblxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2sgdGltZSBmaWVsZCBmb3JtYXRcbiAgICAgICAgaWYgKChyZXN1bHQuZGF0YS50aW1lX2Zyb20ubGVuZ3RoID4gMCAmJiByZXN1bHQuZGF0YS50aW1lX3RvLmxlbmd0aCA9PT0gMClcbiAgICAgICAgICAgIHx8IChyZXN1bHQuZGF0YS50aW1lX3RvLmxlbmd0aCA+IDAgJiYgcmVzdWx0LmRhdGEudGltZV9mcm9tLmxlbmd0aCA9PT0gMCkpIHtcbiAgICAgICAgICAgICQoJy5mb3JtIC5lcnJvci5tZXNzYWdlJykuaHRtbChnbG9iYWxUcmFuc2xhdGUudGZfVmFsaWRhdGVDaGVja1RpbWVJbnRlcnZhbCkuc2hvdygpO1xuICAgICAgICAgICAgRm9ybS4kc3VibWl0QnV0dG9uLnRyYW5zaXRpb24oJ3NoYWtlJykucmVtb3ZlQ2xhc3MoJ2xvYWRpbmcgZGlzYWJsZWQnKTtcblxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2sgYWxsIGZpZWxkc1xuICAgICAgICBpZiAoJCgnI2NhbFR5cGUnKS5wYXJlbnQoKS5kcm9wZG93bignZ2V0IHZhbHVlJykgIT09ICdjYWxkYXYnXG4gICAgICAgICAgICAmJiByZXN1bHQuZGF0YS50aW1lX2Zyb20gPT09ICcnXG4gICAgICAgICAgICAmJiByZXN1bHQuZGF0YS50aW1lX3RvID09PSAnJ1xuICAgICAgICAgICAgJiYgcmVzdWx0LmRhdGEud2Vla2RheV9mcm9tID09PSAnLTEnXG4gICAgICAgICAgICAmJiByZXN1bHQuZGF0YS53ZWVrZGF5X3RvID09PSAnLTEnXG4gICAgICAgICAgICAmJiByZXN1bHQuZGF0YS5kYXRlX2Zyb20gPT09ICcnXG4gICAgICAgICAgICAmJiByZXN1bHQuZGF0YS5kYXRlX3RvID09PSAnJykge1xuICAgICAgICAgICAgJCgnLmZvcm0gLmVycm9yLm1lc3NhZ2UnKS5odG1sKGdsb2JhbFRyYW5zbGF0ZS50Zl9WYWxpZGF0ZU5vUnVsZXNTZWxlY3RlZCkuc2hvdygpO1xuICAgICAgICAgICAgRm9ybS4kc3VibWl0QnV0dG9uLnRyYW5zaXRpb24oJ3NoYWtlJykucmVtb3ZlQ2xhc3MoJ2xvYWRpbmcgZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBDYWxsYmFjayBmdW5jdGlvbiB0byBiZSBjYWxsZWQgYmVmb3JlIHRoZSBmb3JtIGlzIHNlbnRcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc2V0dGluZ3MgLSBUaGUgY3VycmVudCBzZXR0aW5ncyBvZiB0aGUgZm9ybVxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IC0gVGhlIHVwZGF0ZWQgc2V0dGluZ3Mgb2YgdGhlIGZvcm1cbiAgICAgKi9cbiAgICBjYkJlZm9yZVNlbmRGb3JtKHNldHRpbmdzKSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHNldHRpbmdzO1xuICAgICAgICAkKCcuZm9ybSAuZXJyb3IubWVzc2FnZScpLmh0bWwoJycpLmhpZGUoKTtcbiAgICAgICAgcmVzdWx0LmRhdGEgPSBvdXRPZldvcmtUaW1lUmVjb3JkLiRmb3JtT2JqLmZvcm0oJ2dldCB2YWx1ZXMnKTtcbiAgICAgICAgY29uc3QgZGF0ZUZyb20gPSBvdXRPZldvcmtUaW1lUmVjb3JkLiRyYW5nZURheXNTdGFydC5jYWxlbmRhcignZ2V0IGRhdGUnKTtcbiAgICAgICAgY29uc3QgZGF0ZVRvID0gb3V0T2ZXb3JrVGltZVJlY29yZC4kcmFuZ2VEYXlzRW5kLmNhbGVuZGFyKCdnZXQgZGF0ZScpO1xuICAgICAgICBjb25zdCBjdXJyZW50T2Zmc2V0ID0gbmV3IERhdGUoKS5nZXRUaW1lem9uZU9mZnNldCgpO1xuICAgICAgICBjb25zdCBzZXJ2ZXJPZmZzZXQgPSBwYXJzZUludChvdXRPZldvcmtUaW1lUmVjb3JkLiRmb3JtT2JqLmZvcm0oJ2dldCB2YWx1ZScsICdzZXJ2ZXJPZmZzZXQnKSk7XG4gICAgICAgIGNvbnN0IG9mZnNldERpZmYgPSBzZXJ2ZXJPZmZzZXQgKyBjdXJyZW50T2Zmc2V0O1xuXG4gICAgICAgIGlmKCQoJyNjYWxUeXBlJykucGFyZW50KCkuZHJvcGRvd24oJ2dldCB2YWx1ZScpID09PSAnY2FsZGF2Jyl7XG4gICAgICAgICAgICBGb3JtLnZhbGlkYXRlUnVsZXMudGltZWZyb20ucnVsZXMgPSBbXTtcbiAgICAgICAgICAgIEZvcm0udmFsaWRhdGVSdWxlcy50aW1ldG8ucnVsZXMgPSBbXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIEZvcm0udmFsaWRhdGVSdWxlcy50aW1lZnJvbS5ydWxlcyA9IG91dE9mV29ya1RpbWVSZWNvcmQuYWRkaXRpb25hbFRpbWVJbnRlcnZhbFJ1bGVzO1xuICAgICAgICAgICAgRm9ybS52YWxpZGF0ZVJ1bGVzLnRpbWV0by5ydWxlcyA9IG91dE9mV29ya1RpbWVSZWNvcmQuYWRkaXRpb25hbFRpbWVJbnRlcnZhbFJ1bGVzO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRhdGVGcm9tKSB7XG4gICAgICAgICAgICBkYXRlRnJvbS5zZXRIb3VycygwLCAwLCAwLCAwKTtcbiAgICAgICAgICAgIHJlc3VsdC5kYXRhLmRhdGVfZnJvbSA9IE1hdGguZmxvb3IoZGF0ZUZyb20uZ2V0VGltZSgpLzEwMDApIC0gb2Zmc2V0RGlmZiAqIDYwO1xuICAgICAgICB9XG4gICAgICAgIGlmIChkYXRlVG8pIHtcbiAgICAgICAgICAgIGRhdGVUby5zZXRIb3VycygyMywgNTksIDU5LCAwKTtcbiAgICAgICAgICAgIHJlc3VsdC5kYXRhLmRhdGVfdG8gPSBNYXRoLmZsb29yKGRhdGVUby5nZXRUaW1lKCkvMTAwMCkgLSBvZmZzZXREaWZmICogNjA7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG91dE9mV29ya1RpbWVSZWNvcmQuY3VzdG9tVmFsaWRhdGVGb3JtKHJlc3VsdCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIENhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCBhZnRlciB0aGUgZm9ybSBoYXMgYmVlbiBzZW50LlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSByZXNwb25zZSAtIFRoZSByZXNwb25zZSBmcm9tIHRoZSBzZXJ2ZXIgYWZ0ZXIgdGhlIGZvcm0gaXMgc2VudFxuICAgICAqL1xuICAgIGNiQWZ0ZXJTZW5kRm9ybShyZXNwb25zZSkge1xuXG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemUgdGhlIGZvcm0gd2l0aCBjdXN0b20gc2V0dGluZ3NcbiAgICAgKi9cbiAgICBpbml0aWFsaXplRm9ybSgpIHtcbiAgICAgICAgRm9ybS4kZm9ybU9iaiA9IG91dE9mV29ya1RpbWVSZWNvcmQuJGZvcm1PYmo7XG4gICAgICAgIEZvcm0udXJsID0gYCR7Z2xvYmFsUm9vdFVybH1vdXQtb2ZmLXdvcmstdGltZS9zYXZlYDsgLy8gRm9ybSBzdWJtaXNzaW9uIFVSTFxuICAgICAgICBGb3JtLnZhbGlkYXRlUnVsZXMgPSBvdXRPZldvcmtUaW1lUmVjb3JkLnZhbGlkYXRlUnVsZXM7IC8vIEZvcm0gdmFsaWRhdGlvbiBydWxlc1xuICAgICAgICBGb3JtLmNiQmVmb3JlU2VuZEZvcm0gPSBvdXRPZldvcmtUaW1lUmVjb3JkLmNiQmVmb3JlU2VuZEZvcm07IC8vIENhbGxiYWNrIGJlZm9yZSBmb3JtIGlzIHNlbnRcbiAgICAgICAgRm9ybS5jYkFmdGVyU2VuZEZvcm0gPSBvdXRPZldvcmtUaW1lUmVjb3JkLmNiQWZ0ZXJTZW5kRm9ybTsgLy8gQ2FsbGJhY2sgYWZ0ZXIgZm9ybSBpcyBzZW50XG4gICAgICAgIEZvcm0uaW5pdGlhbGl6ZSgpO1xuICAgIH0sXG59O1xuXG4vKipcbiAqIEN1c3RvbSBmb3JtIHZhbGlkYXRpb24gcnVsZSB0aGF0IGNoZWNrcyBpZiBhIHZhbHVlIGlzIG5vdCBlbXB0eSBiYXNlZCBvbiBhIHNwZWNpZmljIGFjdGlvbi5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgLSBUaGUgdmFsdWUgdG8gYmUgdmFsaWRhdGVkLlxuICogQHBhcmFtIHtzdHJpbmd9IGFjdGlvbiAtIFRoZSBhY3Rpb24gdG8gY29tcGFyZSBhZ2FpbnN0LlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgdHJ1ZSBpZiB0aGUgdmFsdWUgaXMgbm90IGVtcHR5IG9yIHRoZSBhY3Rpb24gZG9lcyBub3QgbWF0Y2gsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuJC5mbi5mb3JtLnNldHRpbmdzLnJ1bGVzLmN1c3RvbU5vdEVtcHR5SWZBY3Rpb25SdWxlID0gKHZhbHVlLCBhY3Rpb24pID0+IHtcbiAgICBpZiAodmFsdWUubGVuZ3RoID09PSAwICYmICQoJyNhY3Rpb24nKS52YWwoKSA9PT0gYWN0aW9uKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59O1xuXG4vKipcbiAqIEN1c3RvbSBmb3JtIHZhbGlkYXRpb24gcnVsZSB0aGF0IGNoZWNrcyBpZiBhIHZhbHVlIGlzIG5vdCBlbXB0eSBiYXNlZCBvbiBhIHNwZWNpZmljIGFjdGlvbi5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgLSBUaGUgdmFsdWUgdG8gYmUgdmFsaWRhdGVkLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgdHJ1ZSBpZiB0aGUgdmFsdWUgaXMgbm90IGVtcHR5IG9yIHRoZSBhY3Rpb24gZG9lcyBub3QgbWF0Y2gsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuJC5mbi5mb3JtLnNldHRpbmdzLnJ1bGVzLmN1c3RvbU5vdEVtcHR5SWZDYWxUeXBlID0gKHZhbHVlKSA9PiB7XG4gICAgaWYgKCQoJyNjYWxUeXBlJykudmFsKCkgPT09ICdub25lJykge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgbGV0IHVybCA9IG5ldyBVUkwodmFsdWUpO1xuICAgIH0gY2F0Y2ggKF8pIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn07XG5cblxuLyoqXG4gKiAgSW5pdGlhbGl6ZSBvdXQgb2Ygd29yayBmb3JtIG9uIGRvY3VtZW50IHJlYWR5XG4gKi9cbiQoZG9jdW1lbnQpLnJlYWR5KCgpID0+IHtcbiAgICBvdXRPZldvcmtUaW1lUmVjb3JkLmluaXRpYWxpemUoKTtcbn0pO1xuIl19 \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9PdXRPZmZXb3JrVGltZS9vdXQtb2Ytd29yay10aW1lLW1vZGlmeS5qcyJdLCJuYW1lcyI6WyJvdXRPZldvcmtUaW1lUmVjb3JkIiwiJGZvcm1PYmoiLCIkIiwiJGRlZmF1bHREcm9wZG93biIsIiRyYW5nZURheXNTdGFydCIsIiRyYW5nZURheXNFbmQiLCIkcmFuZ2VUaW1lU3RhcnQiLCIkcmFuZ2VUaW1lRW5kIiwiJGRhdGVfZnJvbSIsIiRkYXRlX3RvIiwiJHRpbWVfdG8iLCIkZm9yd2FyZGluZ1NlbGVjdERyb3Bkb3duIiwiYWRkaXRpb25hbFRpbWVJbnRlcnZhbFJ1bGVzIiwidHlwZSIsInZhbHVlIiwicHJvbXB0IiwiZ2xvYmFsVHJhbnNsYXRlIiwidGZfVmFsaWRhdGVDaGVja1RpbWVJbnRlcnZhbCIsInZhbGlkYXRlUnVsZXMiLCJhdWRpb19tZXNzYWdlX2lkIiwiaWRlbnRpZmllciIsInJ1bGVzIiwidGZfVmFsaWRhdGVBdWRpb01lc3NhZ2VFbXB0eSIsImNhbFVybCIsInRmX1ZhbGlkYXRlQ2FsVXJpIiwiZXh0ZW5zaW9uIiwidGZfVmFsaWRhdGVFeHRlbnNpb25FbXB0eSIsInRpbWVmcm9tIiwib3B0aW9uYWwiLCJ0aW1ldG8iLCJpbml0aWFsaXplIiwidGFiIiwiZHJvcGRvd24iLCJjYWxlbmRhciIsImZpcnN0RGF5T2ZXZWVrIiwiU2VtYW50aWNMb2NhbGl6YXRpb24iLCJjYWxlbmRhckZpcnN0RGF5T2ZXZWVrIiwidGV4dCIsImNhbGVuZGFyVGV4dCIsImVuZENhbGVuZGFyIiwiaW5saW5lIiwibW9udGhGaXJzdCIsInJlZ0V4cCIsInN0YXJ0Q2FsZW5kYXIiLCJvbkNoYW5nZSIsIm5ld0RhdGVUbyIsIm9sZERhdGVUbyIsImF0dHIiLCJEYXRlIiwidHJpZ2dlciIsIkZvcm0iLCJkYXRhQ2hhbmdlZCIsImRpc2FibGVNaW51dGUiLCJhbXBtIiwibmV3VGltZVRvIiwib2xkVGltZVRvIiwidG9nZ2xlRGlzYWJsZWRGaWVsZENsYXNzIiwiZnJvbSIsImZvcm0iLCJ0byIsIm9uIiwiZSIsImRhdGVfZnJvbSIsImRhdGVfdG8iLCJwcmV2ZW50RGVmYXVsdCIsIndlZWtkYXlfZnJvbSIsIndlZWtkYXlfdG8iLCJTb3VuZEZpbGVzU2VsZWN0b3IiLCJnZXREcm9wZG93blNldHRpbmdzV2l0aEVtcHR5IiwiY2hhbmdlRGF0ZUZvcm1hdCIsImluaXRpYWxpemVGb3JtIiwiRXh0ZW5zaW9ucyIsImdldERyb3Bkb3duU2V0dGluZ3NXaXRob3V0RW1wdHkiLCJjaGVja2JveCIsIm5ld1N0YXRlIiwicGFyZW50IiwiZGlkIiwiZmlsdGVyIiwiY2hhbmdlUmVzdHJpY3Rpb24iLCJzaG93IiwiaGlkZSIsImRhdGVGcm9tIiwiZGF0ZVRvIiwiY3VycmVudE9mZnNldCIsImdldFRpbWV6b25lT2Zmc2V0Iiwic2VydmVyT2Zmc2V0IiwicGFyc2VJbnQiLCJvZmZzZXREaWZmIiwidW5kZWZpbmVkIiwibGVuZ3RoIiwiZGF0ZUZyb21JbkJyb3dzZXJUWiIsImRhdGVUb0luQnJvd3NlclRaIiwiY3VzdG9tVmFsaWRhdGVGb3JtIiwicmVzdWx0IiwiZGF0YSIsImh0bWwiLCJ0Zl9WYWxpZGF0ZUNoZWNrRGF0ZUludGVydmFsIiwiJHN1Ym1pdEJ1dHRvbiIsInRyYW5zaXRpb24iLCJyZW1vdmVDbGFzcyIsInRmX1ZhbGlkYXRlQ2hlY2tXZWVrRGF5SW50ZXJ2YWwiLCJ0aW1lX2Zyb20iLCJ0aW1lX3RvIiwidGZfVmFsaWRhdGVOb1J1bGVzU2VsZWN0ZWQiLCJjYkJlZm9yZVNlbmRGb3JtIiwic2V0dGluZ3MiLCJzZXRIb3VycyIsIk1hdGgiLCJmbG9vciIsImdldFRpbWUiLCJjYkFmdGVyU2VuZEZvcm0iLCJyZXNwb25zZSIsInVybCIsImdsb2JhbFJvb3RVcmwiLCJmbiIsImN1c3RvbU5vdEVtcHR5SWZBY3Rpb25SdWxlIiwiYWN0aW9uIiwidmFsIiwiY3VzdG9tTm90RW1wdHlJZkNhbFR5cGUiLCJVUkwiLCJfIiwiZG9jdW1lbnQiLCJyZWFkeSJd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QUFPLElBQVA7QUFDSCxDQVZEO0FBYUE7QUFDQTtBQUNBOzs7QUFDQXRILENBQUMsQ0FBQ3VILFFBQUQsQ0FBRCxDQUFZQyxLQUFaLENBQWtCLFlBQU07QUFDcEIxSCxFQUFBQSxtQkFBbUIsQ0FBQzhCLFVBQXBCO0FBQ0gsQ0FGRCIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBNaWtvUEJYIC0gZnJlZSBwaG9uZSBzeXN0ZW0gZm9yIHNtYWxsIGJ1c2luZXNzXG4gKiBDb3B5cmlnaHQgwqkgMjAxNy0yMDIzIEFsZXhleSBQb3J0bm92IGFuZCBOaWtvbGF5IEJla2V0b3ZcbiAqXG4gKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIHByb2dyYW0uXG4gKiBJZiBub3QsIHNlZSA8aHR0cHM6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICovXG5cbi8qIGdsb2JhbCBnbG9iYWxSb290VXJsLGdsb2JhbFRyYW5zbGF0ZSwgRXh0ZW5zaW9ucywgRm9ybSwgU2VtYW50aWNMb2NhbGl6YXRpb24sIFNvdW5kRmlsZXNTZWxlY3RvciAqL1xuXG5cbi8qKlxuICogT2JqZWN0IGZvciBtYW5hZ2luZyBPdXQtb2YtV29yayBUaW1lIHNldHRpbmdzXG4gKlxuICogQG1vZHVsZSBvdXRPZldvcmtUaW1lUmVjb3JkXG4gKi9cbmNvbnN0IG91dE9mV29ya1RpbWVSZWNvcmQgPSB7XG4gICAgLyoqXG4gICAgICogalF1ZXJ5IG9iamVjdCBmb3IgdGhlIGZvcm0uXG4gICAgICogQHR5cGUge2pRdWVyeX1cbiAgICAgKi9cbiAgICAkZm9ybU9iajogJCgnI3NhdmUtb3V0b2Zmd29yay1mb3JtJyksXG5cbiAgICAkZGVmYXVsdERyb3Bkb3duOiAkKCcjc2F2ZS1vdXRvZmZ3b3JrLWZvcm0gLmRyb3Bkb3duLWRlZmF1bHQnKSxcbiAgICAkcmFuZ2VEYXlzU3RhcnQ6ICQoJyNyYW5nZS1kYXlzLXN0YXJ0JyksXG4gICAgJHJhbmdlRGF5c0VuZDogJCgnI3JhbmdlLWRheXMtZW5kJyksXG4gICAgJHJhbmdlVGltZVN0YXJ0OiAkKCcjcmFuZ2UtdGltZS1zdGFydCcpLFxuICAgICRyYW5nZVRpbWVFbmQ6ICQoJyNyYW5nZS10aW1lLWVuZCcpLFxuICAgICRkYXRlX2Zyb206ICQoJyNkYXRlX2Zyb20nKSxcbiAgICAkZGF0ZV90bzogJCgnI2RhdGVfdG8nKSxcbiAgICAkdGltZV90bzogJCgnI3RpbWVfdG8nKSxcbiAgICAkZm9yd2FyZGluZ1NlbGVjdERyb3Bkb3duOiAkKCcjc2F2ZS1vdXRvZmZ3b3JrLWZvcm0gLmZvcndhcmRpbmctc2VsZWN0JyksXG5cblxuICAgIC8qKlxuICAgICAqIEFkZGl0aW9uYWwgY29uZGl0aW9uIGZvciB0aGUgdGltZSBpbnRlcnZhbFxuICAgICAqIEB0eXBlIHthcnJheX1cbiAgICAgKi9cbiAgICBhZGRpdGlvbmFsVGltZUludGVydmFsUnVsZXM6IFt7XG4gICAgICAgIHR5cGU6ICdyZWdFeHAnLFxuICAgICAgICB2YWx1ZTogL14oMlswLTNdfDE/WzAtOV0pOihbMC01XT9bMC05XSkkLyxcbiAgICAgICAgcHJvbXB0OiBnbG9iYWxUcmFuc2xhdGUudGZfVmFsaWRhdGVDaGVja1RpbWVJbnRlcnZhbCxcbiAgICB9XSxcblxuICAgIC8qKlxuICAgICAqIFZhbGlkYXRpb24gcnVsZXMgZm9yIHRoZSBmb3JtIGZpZWxkcyBiZWZvcmUgc3VibWlzc2lvbi5cbiAgICAgKlxuICAgICAqIEB0eXBlIHtvYmplY3R9XG4gICAgICovXG4gICAgdmFsaWRhdGVSdWxlczoge1xuICAgICAgICBhdWRpb19tZXNzYWdlX2lkOiB7XG4gICAgICAgICAgICBpZGVudGlmaWVyOiAnYXVkaW9fbWVzc2FnZV9pZCcsXG4gICAgICAgICAgICBydWxlczogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2N1c3RvbU5vdEVtcHR5SWZBY3Rpb25SdWxlW3BsYXltZXNzYWdlXScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLnRmX1ZhbGlkYXRlQXVkaW9NZXNzYWdlRW1wdHksXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICAgIGNhbFVybDoge1xuICAgICAgICAgICAgaWRlbnRpZmllcjogJ2NhbFVybCcsXG4gICAgICAgICAgICBydWxlczogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZSAgIDogJ2N1c3RvbU5vdEVtcHR5SWZDYWxUeXBlJyxcbiAgICAgICAgICAgICAgICAgICAgcHJvbXB0IDogZ2xvYmFsVHJhbnNsYXRlLnRmX1ZhbGlkYXRlQ2FsVXJpXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgXVxuICAgICAgICB9LFxuICAgICAgICBleHRlbnNpb246IHtcbiAgICAgICAgICAgIGlkZW50aWZpZXI6ICdleHRlbnNpb24nLFxuICAgICAgICAgICAgcnVsZXM6IFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdjdXN0b21Ob3RFbXB0eUlmQWN0aW9uUnVsZVtleHRlbnNpb25dJyxcbiAgICAgICAgICAgICAgICAgICAgcHJvbXB0OiBnbG9iYWxUcmFuc2xhdGUudGZfVmFsaWRhdGVFeHRlbnNpb25FbXB0eSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgICAgdGltZWZyb206IHtcbiAgICAgICAgICAgIG9wdGlvbmFsOiB0cnVlLFxuICAgICAgICAgICAgaWRlbnRpZmllcjogJ3RpbWVfZnJvbScsXG4gICAgICAgICAgICBydWxlczogW3tcbiAgICAgICAgICAgICAgICB0eXBlOiAncmVnRXhwJyxcbiAgICAgICAgICAgICAgICB2YWx1ZTogL14oMlswLTNdfDE/WzAtOV0pOihbMC01XT9bMC05XSkkLyxcbiAgICAgICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS50Zl9WYWxpZGF0ZUNoZWNrVGltZUludGVydmFsLFxuICAgICAgICAgICAgfV0sXG4gICAgICAgIH0sXG4gICAgICAgIHRpbWV0bzoge1xuICAgICAgICAgICAgaWRlbnRpZmllcjogJ3RpbWVfdG8nLFxuICAgICAgICAgICAgb3B0aW9uYWw6IHRydWUsXG4gICAgICAgICAgICBydWxlczogW3tcbiAgICAgICAgICAgICAgICB0eXBlOiAncmVnRXhwJyxcbiAgICAgICAgICAgICAgICB2YWx1ZTogL14oMlswLTNdfDE/WzAtOV0pOihbMC01XT9bMC05XSkkLyxcbiAgICAgICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS50Zl9WYWxpZGF0ZUNoZWNrVGltZUludGVydmFsLFxuICAgICAgICAgICAgfV0sXG4gICAgICAgIH0sXG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemVzIHRoZSBvdXQgb2Ygd29yayB0aW1lIHJlY29yZCBmb3JtLlxuICAgICAqL1xuICAgIGluaXRpYWxpemUoKSB7XG4gICAgICAgIC8vIEluaXRpYWxpemUgdGFiIGJlaGF2aW9yIGZvciB0aGUgb3V0LXRpbWUtbW9kaWZ5LW1lbnVcbiAgICAgICAgJCgnI291dC10aW1lLW1vZGlmeS1tZW51IC5pdGVtJykudGFiKCk7XG5cbiAgICAgICAgLy8gSW5pdGlhbGl6ZSB0aGUgZGVmYXVsdCBkcm9wZG93blxuICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLiRkZWZhdWx0RHJvcGRvd24uZHJvcGRvd24oKTtcblxuICAgICAgICAvLyBJbml0aWFsaXplIHRoZSBjYWxlbmRhciBmb3IgcmFuZ2UgZGF5cyBzdGFydFxuICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLiRyYW5nZURheXNTdGFydC5jYWxlbmRhcih7XG4gICAgICAgICAgICAvLyBDYWxlbmRhciBjb25maWd1cmF0aW9uIG9wdGlvbnNcbiAgICAgICAgICAgIGZpcnN0RGF5T2ZXZWVrOiBTZW1hbnRpY0xvY2FsaXphdGlvbi5jYWxlbmRhckZpcnN0RGF5T2ZXZWVrLFxuICAgICAgICAgICAgdGV4dDogU2VtYW50aWNMb2NhbGl6YXRpb24uY2FsZW5kYXJUZXh0LFxuICAgICAgICAgICAgZW5kQ2FsZW5kYXI6IG91dE9mV29ya1RpbWVSZWNvcmQuJHJhbmdlRGF5c0VuZCxcbiAgICAgICAgICAgIHR5cGU6ICdkYXRlJyxcbiAgICAgICAgICAgIGlubGluZTogZmFsc2UsXG4gICAgICAgICAgICBtb250aEZpcnN0OiBmYWxzZSxcbiAgICAgICAgICAgIHJlZ0V4cDogU2VtYW50aWNMb2NhbGl6YXRpb24ucmVnRXhwLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBJbml0aWFsaXplIHRoZSBjYWxlbmRhciBmb3IgcmFuZ2UgZGF5cyBlbmRcbiAgICAgICAgb3V0T2ZXb3JrVGltZVJlY29yZC4kcmFuZ2VEYXlzRW5kLmNhbGVuZGFyKHtcbiAgICAgICAgICAgIC8vIENhbGVuZGFyIGNvbmZpZ3VyYXRpb24gb3B0aW9uc1xuICAgICAgICAgICAgZmlyc3REYXlPZldlZWs6IFNlbWFudGljTG9jYWxpemF0aW9uLmNhbGVuZGFyRmlyc3REYXlPZldlZWssXG4gICAgICAgICAgICB0ZXh0OiBTZW1hbnRpY0xvY2FsaXphdGlvbi5jYWxlbmRhclRleHQsXG4gICAgICAgICAgICBzdGFydENhbGVuZGFyOiBvdXRPZldvcmtUaW1lUmVjb3JkLiRyYW5nZURheXNTdGFydCxcbiAgICAgICAgICAgIHR5cGU6ICdkYXRlJyxcbiAgICAgICAgICAgIGlubGluZTogZmFsc2UsXG4gICAgICAgICAgICBtb250aEZpcnN0OiBmYWxzZSxcbiAgICAgICAgICAgIHJlZ0V4cDogU2VtYW50aWNMb2NhbGl6YXRpb24ucmVnRXhwLFxuICAgICAgICAgICAgb25DaGFuZ2U6IChuZXdEYXRlVG8pID0+IHtcbiAgICAgICAgICAgICAgICAvLyBIYW5kbGUgdGhlIGNoYW5nZSBldmVudCBmb3IgcmFuZ2UgdGltZSBlbmRcbiAgICAgICAgICAgICAgICBsZXQgb2xkRGF0ZVRvID0gb3V0T2ZXb3JrVGltZVJlY29yZC4kZGF0ZV90by5hdHRyKCd2YWx1ZScpO1xuICAgICAgICAgICAgICAgIGlmIChuZXdEYXRlVG8gIT09IG51bGwgJiYgb2xkRGF0ZVRvICE9PSAnJykge1xuICAgICAgICAgICAgICAgICAgICBvbGREYXRlVG8gPSBuZXcgRGF0ZShvbGREYXRlVG8gKiAxMDAwKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKChuZXdEYXRlVG8gLSBvbGREYXRlVG8pICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLiRkYXRlX2Zyb20udHJpZ2dlcignY2hhbmdlJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBGb3JtLmRhdGFDaGFuZ2VkKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBJbml0aWFsaXplIHRoZSBjYWxlbmRhciBmb3IgcmFuZ2UgdGltZSBzdGFydFxuICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLiRyYW5nZVRpbWVTdGFydC5jYWxlbmRhcih7XG4gICAgICAgICAgICAvLyBDYWxlbmRhciBjb25maWd1cmF0aW9uIG9wdGlvbnNcbiAgICAgICAgICAgIGZpcnN0RGF5T2ZXZWVrOiBTZW1hbnRpY0xvY2FsaXphdGlvbi5jYWxlbmRhckZpcnN0RGF5T2ZXZWVrLFxuICAgICAgICAgICAgdGV4dDogU2VtYW50aWNMb2NhbGl6YXRpb24uY2FsZW5kYXJUZXh0LFxuICAgICAgICAgICAgZW5kQ2FsZW5kYXI6IG91dE9mV29ya1RpbWVSZWNvcmQuJHJhbmdlVGltZUVuZCxcbiAgICAgICAgICAgIHR5cGU6ICd0aW1lJyxcbiAgICAgICAgICAgIGlubGluZTogZmFsc2UsXG4gICAgICAgICAgICBkaXNhYmxlTWludXRlOiB0cnVlLFxuICAgICAgICAgICAgYW1wbTogZmFsc2UsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIGNhbGVuZGFyIGZvciByYW5nZSB0aW1lIGVuZFxuICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLiRyYW5nZVRpbWVFbmQuY2FsZW5kYXIoe1xuICAgICAgICAgICAgLy8gQ2FsZW5kYXIgY29uZmlndXJhdGlvbiBvcHRpb25zXG4gICAgICAgICAgICBmaXJzdERheU9mV2VlazogU2VtYW50aWNMb2NhbGl6YXRpb24uY2FsZW5kYXJGaXJzdERheU9mV2VlayxcbiAgICAgICAgICAgIHRleHQ6IFNlbWFudGljTG9jYWxpemF0aW9uLmNhbGVuZGFyVGV4dCxcbiAgICAgICAgICAgIHR5cGU6ICd0aW1lJyxcbiAgICAgICAgICAgIGlubGluZTogZmFsc2UsXG4gICAgICAgICAgICBkaXNhYmxlTWludXRlOiB0cnVlLFxuICAgICAgICAgICAgYW1wbTogZmFsc2UsXG4gICAgICAgICAgICBvbkNoYW5nZTogKG5ld1RpbWVUbykgPT4ge1xuICAgICAgICAgICAgICAgIC8vIEhhbmRsZSB0aGUgY2hhbmdlIGV2ZW50IGZvciByYW5nZSB0aW1lIGVuZFxuICAgICAgICAgICAgICAgIGxldCBvbGRUaW1lVG8gPSBvdXRPZldvcmtUaW1lUmVjb3JkLiR0aW1lX3RvLmF0dHIoJ3ZhbHVlJyk7XG4gICAgICAgICAgICAgICAgaWYgKG5ld1RpbWVUbyAhPT0gbnVsbCAmJiBvbGRUaW1lVG8gIT09ICcnKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFRpbWVUbyA9IG5ldyBEYXRlKG9sZFRpbWVUbyAqIDEwMDApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoKG5ld1RpbWVUbyAtIG9sZFRpbWVUbykgIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dE9mV29ya1RpbWVSZWNvcmQuJHRpbWVfdG8udHJpZ2dlcignY2hhbmdlJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBGb3JtLmRhdGFDaGFuZ2VkKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBJbml0aWFsaXplIHRoZSBhY3Rpb24gZHJvcGRvd25cbiAgICAgICAgJCgnI2FjdGlvbicpXG4gICAgICAgICAgICAuZHJvcGRvd24oe1xuICAgICAgICAgICAgICAgIG9uQ2hhbmdlKCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBIYW5kbGUgdGhlIGNoYW5nZSBldmVudCBmb3IgdGhlIGFjdGlvbiBkcm9wZG93blxuICAgICAgICAgICAgICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLnRvZ2dsZURpc2FibGVkRmllbGRDbGFzcygpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgLy8gSW5pdGlhbGl6ZSB0aGUgY2FsVHlwZSBkcm9wZG93blxuICAgICAgICAkKCcjY2FsVHlwZScpXG4gICAgICAgICAgICAuZHJvcGRvd24oe1xuICAgICAgICAgICAgICAgIG9uQ2hhbmdlKCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBIYW5kbGUgdGhlIGNoYW5nZSBldmVudCBmb3IgdGhlIGFjdGlvbiBkcm9wZG93blxuICAgICAgICAgICAgICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLnRvZ2dsZURpc2FibGVkRmllbGRDbGFzcygpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAvLyBJbml0aWFsaXplIHRoZSB3ZWVrZGF5X2Zyb20gZHJvcGRvd25cbiAgICAgICAgJCgnI3dlZWtkYXlfZnJvbScpXG4gICAgICAgICAgICAuZHJvcGRvd24oe1xuICAgICAgICAgICAgICAgIG9uQ2hhbmdlKCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBIYW5kbGUgdGhlIGNoYW5nZSBldmVudCBmb3IgdGhlIHdlZWtkYXlfZnJvbSBkcm9wZG93blxuICAgICAgICAgICAgICAgICAgICBjb25zdCBmcm9tID0gb3V0T2ZXb3JrVGltZVJlY29yZC4kZm9ybU9iai5mb3JtKCdnZXQgdmFsdWUnLCAnd2Vla2RheV9mcm9tJyk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRvID0gb3V0T2ZXb3JrVGltZVJlY29yZC4kZm9ybU9iai5mb3JtKCdnZXQgdmFsdWUnLCAnd2Vla2RheV90bycpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZnJvbSA8IHRvIHx8IHRvID09PSAtMSB8fCBmcm9tID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0T2ZXb3JrVGltZVJlY29yZC4kZm9ybU9iai5mb3JtKCdzZXQgdmFsdWUnLCAnd2Vla2RheV90bycsIGZyb20pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIHdlZWtkYXlfdG8gZHJvcGRvd25cbiAgICAgICAgJCgnI3dlZWtkYXlfdG8nKVxuICAgICAgICAgICAgLmRyb3Bkb3duKHtcbiAgICAgICAgICAgICAgICBvbkNoYW5nZSgpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSGFuZGxlIHRoZSBjaGFuZ2UgZXZlbnQgZm9yIHRoZSB3ZWVrZGF5X3RvIGRyb3Bkb3duXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGZyb20gPSBvdXRPZldvcmtUaW1lUmVjb3JkLiRmb3JtT2JqLmZvcm0oJ2dldCB2YWx1ZScsICd3ZWVrZGF5X2Zyb20nKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdG8gPSBvdXRPZldvcmtUaW1lUmVjb3JkLiRmb3JtT2JqLmZvcm0oJ2dldCB2YWx1ZScsICd3ZWVrZGF5X3RvJyk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0byA8IGZyb20gfHwgZnJvbSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dE9mV29ya1RpbWVSZWNvcmQuJGZvcm1PYmouZm9ybSgnc2V0IHZhbHVlJywgJ3dlZWtkYXlfZnJvbScsIHRvKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAvLyBCaW5kIGNsaWNrIGV2ZW50IHRvIGVyYXNlLWRhdGVzIGJ1dHRvblxuICAgICAgICAkKCcjZXJhc2UtZGF0ZXMnKS5vbignY2xpY2snLCAoZSkgPT4ge1xuICAgICAgICAgICAgLy8gSGFuZGxlIHRoZSBjbGljayBldmVudCBmb3IgZXJhc2UtZGF0ZXMgYnV0dG9uXG4gICAgICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLiRyYW5nZURheXNTdGFydC5jYWxlbmRhcignY2xlYXInKTtcbiAgICAgICAgICAgIG91dE9mV29ya1RpbWVSZWNvcmQuJHJhbmdlRGF5c0VuZC5jYWxlbmRhcignY2xlYXInKTtcbiAgICAgICAgICAgIG91dE9mV29ya1RpbWVSZWNvcmQuJGZvcm1PYmpcbiAgICAgICAgICAgICAgICAuZm9ybSgnc2V0IHZhbHVlcycsIHtcbiAgICAgICAgICAgICAgICAgICAgZGF0ZV9mcm9tOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgZGF0ZV90bzogJycsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEJpbmQgY2xpY2sgZXZlbnQgdG8gZXJhc2Utd2Vla2RheXMgYnV0dG9uXG4gICAgICAgICQoJyNlcmFzZS13ZWVrZGF5cycpLm9uKCdjbGljaycsIChlKSA9PiB7XG4gICAgICAgICAgICAvLyBIYW5kbGUgdGhlIGNsaWNrIGV2ZW50IGZvciBlcmFzZS13ZWVrZGF5cyBidXR0b25cbiAgICAgICAgICAgIG91dE9mV29ya1RpbWVSZWNvcmQuJGZvcm1PYmpcbiAgICAgICAgICAgICAgICAuZm9ybSgnc2V0IHZhbHVlcycsIHtcbiAgICAgICAgICAgICAgICAgICAgd2Vla2RheV9mcm9tOiAtMSxcbiAgICAgICAgICAgICAgICAgICAgd2Vla2RheV90bzogLTEsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLiRyYW5nZURheXNTdGFydC50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gQmluZCBjbGljayBldmVudCB0byBlcmFzZS10aW1lcGVyaW9kIGJ1dHRvblxuICAgICAgICAkKCcjZXJhc2UtdGltZXBlcmlvZCcpLm9uKCdjbGljaycsIChlKSA9PiB7XG4gICAgICAgICAgICAvLyBIYW5kbGUgdGhlIGNsaWNrIGV2ZW50IGZvciBlcmFzZS10aW1lcGVyaW9kIGJ1dHRvblxuICAgICAgICAgICAgb3V0T2ZXb3JrVGltZVJlY29yZC4kcmFuZ2VUaW1lU3RhcnQuY2FsZW5kYXIoJ2NsZWFyJyk7XG4gICAgICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLiRyYW5nZVRpbWVFbmQuY2FsZW5kYXIoJ2NsZWFyJyk7XG4gICAgICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLiR0aW1lX3RvLnRyaWdnZXIoJ2NoYW5nZScpO1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyBJbml0aWFsaXplIGF1ZGlvLW1lc3NhZ2Utc2VsZWN0IGRyb3Bkb3duXG4gICAgICAgICQoJyNzYXZlLW91dG9mZndvcmstZm9ybSAuYXVkaW8tbWVzc2FnZS1zZWxlY3QnKS5kcm9wZG93bihTb3VuZEZpbGVzU2VsZWN0b3IuZ2V0RHJvcGRvd25TZXR0aW5nc1dpdGhFbXB0eSgpKTtcblxuICAgICAgICAvLyBDaGFuZ2UgdGhlIGRhdGUgZm9ybWF0IGZyb20gbGludXh0aW1lIHRvIGxvY2FsIHJlcHJlc2VudGF0aW9uXG4gICAgICAgIG91dE9mV29ya1RpbWVSZWNvcmQuY2hhbmdlRGF0ZUZvcm1hdCgpO1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIGZvcm1cbiAgICAgICAgb3V0T2ZXb3JrVGltZVJlY29yZC5pbml0aWFsaXplRm9ybSgpO1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIGZvcndhcmRpbmdTZWxlY3REcm9wZG93blxuICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLiRmb3J3YXJkaW5nU2VsZWN0RHJvcGRvd24uZHJvcGRvd24oRXh0ZW5zaW9ucy5nZXREcm9wZG93blNldHRpbmdzV2l0aG91dEVtcHR5KCkpO1xuXG4gICAgICAgIC8vIFRvZ2dsZSBkaXNhYmxlZCBmaWVsZCBjbGFzcyBiYXNlZCBvbiBhY3Rpb24gdmFsdWVcbiAgICAgICAgb3V0T2ZXb3JrVGltZVJlY29yZC50b2dnbGVEaXNhYmxlZEZpZWxkQ2xhc3MoKTtcblxuICAgICAgICAvLyBCaW5kIGNoZWNrYm94IGNoYW5nZSBldmVudCBmb3IgaW5ib3VuZCBydWxlcyB0YWJsZVxuICAgICAgICAkKCcjaW5ib3VuZC1ydWxlcy10YWJsZSAudWkuY2hlY2tib3gnKS5jaGVja2JveCh7XG4gICAgICAgICAgICBvbkNoYW5nZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGxldCBuZXdTdGF0ZSA9ICd1bmNoZWNrZWQnO1xuICAgICAgICAgICAgICAgIC8vIEhhbmRsZSB0aGUgY2hhbmdlIGV2ZW50IGZvciBpbmJvdW5kIHJ1bGVzIHRhYmxlIGNoZWNrYm94XG4gICAgICAgICAgICAgICAgaWYgKCQodGhpcykucGFyZW50KCkuY2hlY2tib3goJ2lzIGNoZWNrZWQnKSkge1xuICAgICAgICAgICAgICAgICAgICBuZXdTdGF0ZSA9ICdjaGVja2VkJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IGRpZCA9ICQodGhpcykucGFyZW50KCkuYXR0cignZGF0YS1kaWQnKTtcbiAgICAgICAgICAgICAgICBsZXQgZmlsdGVyID0gJyNpbmJvdW5kLXJ1bGVzLXRhYmxlIC51aS5jaGVja2JveFtkYXRhLWNvbnRleHQtaWQ9JyArICQodGhpcykucGFyZW50KCkuYXR0cignZGF0YS1jb250ZXh0LWlkJykgKyAnXSc7XG4gICAgICAgICAgICAgICAgaWYoZGlkICE9PSAnJyAmJiBuZXdTdGF0ZSA9PT0gJ2NoZWNrZWQnKXtcbiAgICAgICAgICAgICAgICAgICAgZmlsdGVyID0gZmlsdGVyICsgJy51aS5jaGVja2JveFtkYXRhLWRpZD0nK2RpZCsnXSc7XG4gICAgICAgICAgICAgICAgfWVsc2UgaWYoZGlkID09PSAnJyAmJiBuZXdTdGF0ZSA9PT0gJ3VuY2hlY2tlZCcpe1xuICAgICAgICAgICAgICAgICAgICBmaWx0ZXIgPSBmaWx0ZXIgKyAnLnVpLmNoZWNrYm94W2RhdGEtZGlkPVwiXCJdJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgJChmaWx0ZXIpLmNoZWNrYm94KCdzZXQgJytuZXdTdGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEJpbmQgY2hlY2tib3ggY2hhbmdlIGV2ZW50IGZvciBhbGxvd1Jlc3RyaWN0aW9uIGNoZWNrYm94XG4gICAgICAgICQoJyNhbGxvd1Jlc3RyaWN0aW9uJykucGFyZW50KCkuY2hlY2tib3goe1xuICAgICAgICAgICAgb25DaGFuZ2U6IG91dE9mV29ya1RpbWVSZWNvcmQuY2hhbmdlUmVzdHJpY3Rpb25cbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gQ2FsbCBjaGFuZ2VSZXN0cmljdGlvbiBtZXRob2RcbiAgICAgICAgb3V0T2ZXb3JrVGltZVJlY29yZC5jaGFuZ2VSZXN0cmljdGlvbigpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBDaGFuZ2VzIHRoZSB2aXNpYmlsaXR5IG9mIHRoZSAncnVsZXMnIHRhYiBiYXNlZCBvbiB0aGUgY2hlY2tlZCBzdGF0dXMgb2YgdGhlICdhbGxvd1Jlc3RyaWN0aW9uJyBjaGVja2JveC5cbiAgICAgKi9cbiAgICBjaGFuZ2VSZXN0cmljdGlvbigpIHtcbiAgICAgICAgaWYgKCQoJyNhbGxvd1Jlc3RyaWN0aW9uJykucGFyZW50KCkuY2hlY2tib3goJ2lzIGNoZWNrZWQnKSkge1xuICAgICAgICAgICAgJChcImFbZGF0YS10YWI9J3J1bGVzJ11cIikuc2hvdygpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgJChcImFbZGF0YS10YWI9J3J1bGVzJ11cIikuaGlkZSgpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIHRoZSBkYXRlIGZvcm1hdCBmcm9tIGxpbnV4dGltZSB0byB0aGUgbG9jYWwgcmVwcmVzZW50YXRpb24uXG4gICAgICovXG4gICAgY2hhbmdlRGF0ZUZvcm1hdCgpIHtcbiAgICAgICAgY29uc3QgZGF0ZUZyb20gPSBvdXRPZldvcmtUaW1lUmVjb3JkLiRkYXRlX2Zyb20uYXR0cigndmFsdWUnKTtcbiAgICAgICAgY29uc3QgZGF0ZVRvID0gb3V0T2ZXb3JrVGltZVJlY29yZC4kZGF0ZV90by5hdHRyKCd2YWx1ZScpO1xuICAgICAgICBjb25zdCBjdXJyZW50T2Zmc2V0ID0gbmV3IERhdGUoKS5nZXRUaW1lem9uZU9mZnNldCgpO1xuICAgICAgICBjb25zdCBzZXJ2ZXJPZmZzZXQgPSBwYXJzZUludChvdXRPZldvcmtUaW1lUmVjb3JkLiRmb3JtT2JqLmZvcm0oJ2dldCB2YWx1ZScsICdzZXJ2ZXJPZmZzZXQnKSk7XG4gICAgICAgIGNvbnN0IG9mZnNldERpZmYgPSBzZXJ2ZXJPZmZzZXQgKyBjdXJyZW50T2Zmc2V0O1xuICAgICAgICBpZiAoZGF0ZUZyb20gIT09IHVuZGVmaW5lZCAmJiBkYXRlRnJvbS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBjb25zdCBkYXRlRnJvbUluQnJvd3NlclRaID0gZGF0ZUZyb20gKiAxMDAwICsgb2Zmc2V0RGlmZiAqIDYwICogMTAwMDtcbiAgICAgICAgICAgIG91dE9mV29ya1RpbWVSZWNvcmQuJHJhbmdlRGF5c1N0YXJ0LmNhbGVuZGFyKCdzZXQgZGF0ZScsIG5ldyBEYXRlKGRhdGVGcm9tSW5Ccm93c2VyVFopKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZGF0ZVRvICE9PSB1bmRlZmluZWQgJiYgZGF0ZVRvLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGNvbnN0IGRhdGVUb0luQnJvd3NlclRaID0gZGF0ZVRvICogMTAwMCArIG9mZnNldERpZmYgKiA2MCAqIDEwMDA7XG4gICAgICAgICAgICBvdXRPZldvcmtUaW1lUmVjb3JkLiRyYW5nZURheXNFbmQuY2FsZW5kYXIoJ3NldCBkYXRlJywgbmV3IERhdGUoZGF0ZVRvSW5Ccm93c2VyVFopKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBUb2dnbGVzIHRoZSB2aXNpYmlsaXR5IG9mIGNlcnRhaW4gZmllbGQgZ3JvdXBzIGJhc2VkIG9uIHRoZSBzZWxlY3RlZCBhY3Rpb24gdmFsdWUuXG4gICAgICovXG4gICAgdG9nZ2xlRGlzYWJsZWRGaWVsZENsYXNzKCkge1xuICAgICAgICBpZihvdXRPZldvcmtUaW1lUmVjb3JkLiRmb3JtT2JqLmZvcm0oJ2dldCB2YWx1ZScsICdhY3Rpb24nKSA9PT0gJ2V4dGVuc2lvbicpIHtcbiAgICAgICAgICAgICQoJyNleHRlbnNpb24tZ3JvdXAnKS5zaG93KCk7XG4gICAgICAgICAgICAkKCcjYXVkaW8tZmlsZS1ncm91cCcpLmhpZGUoKTtcbiAgICAgICAgICAgICQoJyNhdWRpb19tZXNzYWdlX2lkJykuZHJvcGRvd24oJ2NsZWFyJyk7XG4gICAgICAgIH1lbHNle1xuICAgICAgICAgICAgJCgnI2V4dGVuc2lvbi1ncm91cCcpLmhpZGUoKTtcbiAgICAgICAgICAgICQoJyNhdWRpby1maWxlLWdyb3VwJykuc2hvdygpO1xuICAgICAgICAgICAgb3V0T2ZXb3JrVGltZVJlY29yZC4kZm9ybU9iai5mb3JtKCdzZXQgdmFsdWUnLCAnZXh0ZW5zaW9uJywgLTEpO1xuICAgICAgICB9XG4gICAgICAgIGlmKG91dE9mV29ya1RpbWVSZWNvcmQuJGZvcm1PYmouZm9ybSgnZ2V0IHZhbHVlJywgJ2NhbFR5cGUnKSA9PT0gJ25vbmUnKXtcbiAgICAgICAgICAgICQoJyNjYWxsLXR5cGUtbWFpbi10YWInKS5zaG93KCk7XG4gICAgICAgICAgICAkKCcjY2FsbC10eXBlLWNhbGVuZGFyLXRhYicpLmhpZGUoKTtcbiAgICAgICAgfWVsc2V7XG4gICAgICAgICAgICAkKCcjY2FsbC10eXBlLW1haW4tdGFiJykuaGlkZSgpO1xuICAgICAgICAgICAgJCgnI2NhbGwtdHlwZS1jYWxlbmRhci10YWInKS5zaG93KCk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQ3VzdG9tIGZvcm0gdmFsaWRhdGlvbiBmb3IgdmFsaWRhdGluZyBzcGVjaWZpYyBmaWVsZHMgaW4gYSBmb3JtLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHJlc3VsdCAtIFRoZSByZXN1bHQgb2JqZWN0IGNvbnRhaW5pbmcgZm9ybSBkYXRhLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufE9iamVjdH0gUmV0dXJucyBmYWxzZSBpZiB2YWxpZGF0aW9uIGZhaWxzLCBvciB0aGUgcmVzdWx0IG9iamVjdCBpZiB2YWxpZGF0aW9uIHBhc3Nlcy5cbiAgICAgKi9cbiAgICBjdXN0b21WYWxpZGF0ZUZvcm0ocmVzdWx0KSB7XG4gICAgICAgIC8vIENoZWNrIGRhdGUgZmllbGRzXG4gICAgICAgIGlmICgocmVzdWx0LmRhdGEuZGF0ZV9mcm9tICE9PSAnJyAmJiByZXN1bHQuZGF0YS5kYXRlX3RvID09PSAnJylcbiAgICAgICAgICAgIHx8IChyZXN1bHQuZGF0YS5kYXRlX3RvICE9PSAnJyAmJiByZXN1bHQuZGF0YS5kYXRlX2Zyb20gPT09ICcnKSkge1xuICAgICAgICAgICAgJCgnLmZvcm0gLmVycm9yLm1lc3NhZ2UnKS5odG1sKGdsb2JhbFRyYW5zbGF0ZS50Zl9WYWxpZGF0ZUNoZWNrRGF0ZUludGVydmFsKS5zaG93KCk7XG4gICAgICAgICAgICBGb3JtLiRzdWJtaXRCdXR0b24udHJhbnNpdGlvbignc2hha2UnKS5yZW1vdmVDbGFzcygnbG9hZGluZyBkaXNhYmxlZCcpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2sgd2Vla2RheSBmaWVsZHNcbiAgICAgICAgaWYgKChyZXN1bHQuZGF0YS53ZWVrZGF5X2Zyb20gPiAwICYmIHJlc3VsdC5kYXRhLndlZWtkYXlfdG8gPT09ICctMScpXG4gICAgICAgICAgICB8fCAocmVzdWx0LmRhdGEud2Vla2RheV90byA+IDAgJiYgcmVzdWx0LmRhdGEud2Vla2RheV9mcm9tID09PSAnLTEnKSkge1xuICAgICAgICAgICAgJCgnLmZvcm0gLmVycm9yLm1lc3NhZ2UnKS5odG1sKGdsb2JhbFRyYW5zbGF0ZS50Zl9WYWxpZGF0ZUNoZWNrV2Vla0RheUludGVydmFsKS5zaG93KCk7XG4gICAgICAgICAgICBGb3JtLiRzdWJtaXRCdXR0b24udHJhbnNpdGlvbignc2hha2UnKS5yZW1vdmVDbGFzcygnbG9hZGluZyBkaXNhYmxlZCcpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2sgdGltZSBmaWVsZHNcbiAgICAgICAgaWYgKChyZXN1bHQuZGF0YS50aW1lX2Zyb20ubGVuZ3RoID4gMCAmJiByZXN1bHQuZGF0YS50aW1lX3RvLmxlbmd0aCA9PT0gMClcbiAgICAgICAgICAgIHx8IChyZXN1bHQuZGF0YS50aW1lX3RvLmxlbmd0aCA+IDAgJiYgcmVzdWx0LmRhdGEudGltZV9mcm9tLmxlbmd0aCA9PT0gMCkpIHtcbiAgICAgICAgICAgICQoJy5mb3JtIC5lcnJvci5tZXNzYWdlJykuaHRtbChnbG9iYWxUcmFuc2xhdGUudGZfVmFsaWRhdGVDaGVja1RpbWVJbnRlcnZhbCkuc2hvdygpO1xuICAgICAgICAgICAgRm9ybS4kc3VibWl0QnV0dG9uLnRyYW5zaXRpb24oJ3NoYWtlJykucmVtb3ZlQ2xhc3MoJ2xvYWRpbmcgZGlzYWJsZWQnKTtcblxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2sgdGltZSBmaWVsZCBmb3JtYXRcbiAgICAgICAgaWYgKChyZXN1bHQuZGF0YS50aW1lX2Zyb20ubGVuZ3RoID4gMCAmJiByZXN1bHQuZGF0YS50aW1lX3RvLmxlbmd0aCA9PT0gMClcbiAgICAgICAgICAgIHx8IChyZXN1bHQuZGF0YS50aW1lX3RvLmxlbmd0aCA+IDAgJiYgcmVzdWx0LmRhdGEudGltZV9mcm9tLmxlbmd0aCA9PT0gMCkpIHtcbiAgICAgICAgICAgICQoJy5mb3JtIC5lcnJvci5tZXNzYWdlJykuaHRtbChnbG9iYWxUcmFuc2xhdGUudGZfVmFsaWRhdGVDaGVja1RpbWVJbnRlcnZhbCkuc2hvdygpO1xuICAgICAgICAgICAgRm9ybS4kc3VibWl0QnV0dG9uLnRyYW5zaXRpb24oJ3NoYWtlJykucmVtb3ZlQ2xhc3MoJ2xvYWRpbmcgZGlzYWJsZWQnKTtcblxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2sgYWxsIGZpZWxkc1xuICAgICAgICBpZiAoJCgnI2NhbFR5cGUnKS5wYXJlbnQoKS5kcm9wZG93bignZ2V0IHZhbHVlJykgPT09ICdub25lJ1xuICAgICAgICAgICAgJiYgcmVzdWx0LmRhdGEudGltZV9mcm9tID09PSAnJ1xuICAgICAgICAgICAgJiYgcmVzdWx0LmRhdGEudGltZV90byA9PT0gJydcbiAgICAgICAgICAgICYmIHJlc3VsdC5kYXRhLndlZWtkYXlfZnJvbSA9PT0gJy0xJ1xuICAgICAgICAgICAgJiYgcmVzdWx0LmRhdGEud2Vla2RheV90byA9PT0gJy0xJ1xuICAgICAgICAgICAgJiYgcmVzdWx0LmRhdGEuZGF0ZV9mcm9tID09PSAnJ1xuICAgICAgICAgICAgJiYgcmVzdWx0LmRhdGEuZGF0ZV90byA9PT0gJycpIHtcbiAgICAgICAgICAgICQoJy5mb3JtIC5lcnJvci5tZXNzYWdlJykuaHRtbChnbG9iYWxUcmFuc2xhdGUudGZfVmFsaWRhdGVOb1J1bGVzU2VsZWN0ZWQpLnNob3coKTtcbiAgICAgICAgICAgIEZvcm0uJHN1Ym1pdEJ1dHRvbi50cmFuc2l0aW9uKCdzaGFrZScpLnJlbW92ZUNsYXNzKCdsb2FkaW5nIGRpc2FibGVkJyk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQ2FsbGJhY2sgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIGJlZm9yZSB0aGUgZm9ybSBpcyBzZW50XG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNldHRpbmdzIC0gVGhlIGN1cnJlbnQgc2V0dGluZ3Mgb2YgdGhlIGZvcm1cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSAtIFRoZSB1cGRhdGVkIHNldHRpbmdzIG9mIHRoZSBmb3JtXG4gICAgICovXG4gICAgY2JCZWZvcmVTZW5kRm9ybShzZXR0aW5ncykge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBzZXR0aW5ncztcbiAgICAgICAgJCgnLmZvcm0gLmVycm9yLm1lc3NhZ2UnKS5odG1sKCcnKS5oaWRlKCk7XG4gICAgICAgIHJlc3VsdC5kYXRhID0gb3V0T2ZXb3JrVGltZVJlY29yZC4kZm9ybU9iai5mb3JtKCdnZXQgdmFsdWVzJyk7XG4gICAgICAgIGNvbnN0IGRhdGVGcm9tID0gb3V0T2ZXb3JrVGltZVJlY29yZC4kcmFuZ2VEYXlzU3RhcnQuY2FsZW5kYXIoJ2dldCBkYXRlJyk7XG4gICAgICAgIGNvbnN0IGRhdGVUbyA9IG91dE9mV29ya1RpbWVSZWNvcmQuJHJhbmdlRGF5c0VuZC5jYWxlbmRhcignZ2V0IGRhdGUnKTtcbiAgICAgICAgY29uc3QgY3VycmVudE9mZnNldCA9IG5ldyBEYXRlKCkuZ2V0VGltZXpvbmVPZmZzZXQoKTtcbiAgICAgICAgY29uc3Qgc2VydmVyT2Zmc2V0ID0gcGFyc2VJbnQob3V0T2ZXb3JrVGltZVJlY29yZC4kZm9ybU9iai5mb3JtKCdnZXQgdmFsdWUnLCAnc2VydmVyT2Zmc2V0JykpO1xuICAgICAgICBjb25zdCBvZmZzZXREaWZmID0gc2VydmVyT2Zmc2V0ICsgY3VycmVudE9mZnNldDtcblxuICAgICAgICBpZigkKCcjY2FsVHlwZScpLnBhcmVudCgpLmRyb3Bkb3duKCdnZXQgdmFsdWUnKSA9PT0gJ25vbmUnKXtcbiAgICAgICAgICAgIEZvcm0udmFsaWRhdGVSdWxlcy50aW1lZnJvbS5ydWxlcyA9IG91dE9mV29ya1RpbWVSZWNvcmQuYWRkaXRpb25hbFRpbWVJbnRlcnZhbFJ1bGVzO1xuICAgICAgICAgICAgRm9ybS52YWxpZGF0ZVJ1bGVzLnRpbWV0by5ydWxlcyA9IG91dE9mV29ya1RpbWVSZWNvcmQuYWRkaXRpb25hbFRpbWVJbnRlcnZhbFJ1bGVzO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgRm9ybS52YWxpZGF0ZVJ1bGVzLnRpbWVmcm9tLnJ1bGVzID0gW107XG4gICAgICAgICAgICBGb3JtLnZhbGlkYXRlUnVsZXMudGltZXRvLnJ1bGVzID0gW107XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZGF0ZUZyb20pIHtcbiAgICAgICAgICAgIGRhdGVGcm9tLnNldEhvdXJzKDAsIDAsIDAsIDApO1xuICAgICAgICAgICAgcmVzdWx0LmRhdGEuZGF0ZV9mcm9tID0gTWF0aC5mbG9vcihkYXRlRnJvbS5nZXRUaW1lKCkvMTAwMCkgLSBvZmZzZXREaWZmICogNjA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGRhdGVUbykge1xuICAgICAgICAgICAgZGF0ZVRvLnNldEhvdXJzKDIzLCA1OSwgNTksIDApO1xuICAgICAgICAgICAgcmVzdWx0LmRhdGEuZGF0ZV90byA9IE1hdGguZmxvb3IoZGF0ZVRvLmdldFRpbWUoKS8xMDAwKSAtIG9mZnNldERpZmYgKiA2MDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb3V0T2ZXb3JrVGltZVJlY29yZC5jdXN0b21WYWxpZGF0ZUZvcm0ocmVzdWx0KTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQ2FsbGJhY2sgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIGFmdGVyIHRoZSBmb3JtIGhhcyBiZWVuIHNlbnQuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHJlc3BvbnNlIC0gVGhlIHJlc3BvbnNlIGZyb20gdGhlIHNlcnZlciBhZnRlciB0aGUgZm9ybSBpcyBzZW50XG4gICAgICovXG4gICAgY2JBZnRlclNlbmRGb3JtKHJlc3BvbnNlKSB7XG5cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZSB0aGUgZm9ybSB3aXRoIGN1c3RvbSBzZXR0aW5nc1xuICAgICAqL1xuICAgIGluaXRpYWxpemVGb3JtKCkge1xuICAgICAgICBGb3JtLiRmb3JtT2JqID0gb3V0T2ZXb3JrVGltZVJlY29yZC4kZm9ybU9iajtcbiAgICAgICAgRm9ybS51cmwgPSBgJHtnbG9iYWxSb290VXJsfW91dC1vZmYtd29yay10aW1lL3NhdmVgOyAvLyBGb3JtIHN1Ym1pc3Npb24gVVJMXG4gICAgICAgIEZvcm0udmFsaWRhdGVSdWxlcyA9IG91dE9mV29ya1RpbWVSZWNvcmQudmFsaWRhdGVSdWxlczsgLy8gRm9ybSB2YWxpZGF0aW9uIHJ1bGVzXG4gICAgICAgIEZvcm0uY2JCZWZvcmVTZW5kRm9ybSA9IG91dE9mV29ya1RpbWVSZWNvcmQuY2JCZWZvcmVTZW5kRm9ybTsgLy8gQ2FsbGJhY2sgYmVmb3JlIGZvcm0gaXMgc2VudFxuICAgICAgICBGb3JtLmNiQWZ0ZXJTZW5kRm9ybSA9IG91dE9mV29ya1RpbWVSZWNvcmQuY2JBZnRlclNlbmRGb3JtOyAvLyBDYWxsYmFjayBhZnRlciBmb3JtIGlzIHNlbnRcbiAgICAgICAgRm9ybS5pbml0aWFsaXplKCk7XG4gICAgfSxcbn07XG5cbi8qKlxuICogQ3VzdG9tIGZvcm0gdmFsaWRhdGlvbiBydWxlIHRoYXQgY2hlY2tzIGlmIGEgdmFsdWUgaXMgbm90IGVtcHR5IGJhc2VkIG9uIGEgc3BlY2lmaWMgYWN0aW9uLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSAtIFRoZSB2YWx1ZSB0byBiZSB2YWxpZGF0ZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gYWN0aW9uIC0gVGhlIGFjdGlvbiB0byBjb21wYXJlIGFnYWluc3QuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyB0cnVlIGlmIHRoZSB2YWx1ZSBpcyBub3QgZW1wdHkgb3IgdGhlIGFjdGlvbiBkb2VzIG5vdCBtYXRjaCwgZmFsc2Ugb3RoZXJ3aXNlLlxuICovXG4kLmZuLmZvcm0uc2V0dGluZ3MucnVsZXMuY3VzdG9tTm90RW1wdHlJZkFjdGlvblJ1bGUgPSAodmFsdWUsIGFjdGlvbikgPT4ge1xuICAgIGlmICh2YWx1ZS5sZW5ndGggPT09IDAgJiYgJCgnI2FjdGlvbicpLnZhbCgpID09PSBhY3Rpb24pIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn07XG5cbi8qKlxuICogQ3VzdG9tIGZvcm0gdmFsaWRhdGlvbiBydWxlIHRoYXQgY2hlY2tzIGlmIGEgdmFsdWUgaXMgbm90IGVtcHR5IGJhc2VkIG9uIGEgc3BlY2lmaWMgYWN0aW9uLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSAtIFRoZSB2YWx1ZSB0byBiZSB2YWxpZGF0ZWQuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyB0cnVlIGlmIHRoZSB2YWx1ZSBpcyBub3QgZW1wdHkgb3IgdGhlIGFjdGlvbiBkb2VzIG5vdCBtYXRjaCwgZmFsc2Ugb3RoZXJ3aXNlLlxuICovXG4kLmZuLmZvcm0uc2V0dGluZ3MucnVsZXMuY3VzdG9tTm90RW1wdHlJZkNhbFR5cGUgPSAodmFsdWUpID0+IHtcbiAgICBpZiAoJCgnI2NhbFR5cGUnKS52YWwoKSA9PT0gJ25vbmUnKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICBsZXQgdXJsID0gbmV3IFVSTCh2YWx1ZSk7XG4gICAgfSBjYXRjaCAoXykge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufTtcblxuXG4vKipcbiAqICBJbml0aWFsaXplIG91dCBvZiB3b3JrIGZvcm0gb24gZG9jdW1lbnQgcmVhZHlcbiAqL1xuJChkb2N1bWVudCkucmVhZHkoKCkgPT4ge1xuICAgIG91dE9mV29ya1RpbWVSZWNvcmQuaW5pdGlhbGl6ZSgpO1xufSk7XG4iXX0= \ No newline at end of file diff --git a/sites/admin-cabinet/assets/js/src/OutOffWorkTime/out-of-work-time-modify.js b/sites/admin-cabinet/assets/js/src/OutOffWorkTime/out-of-work-time-modify.js index 97d316add..9cbc4f427 100644 --- a/sites/admin-cabinet/assets/js/src/OutOffWorkTime/out-of-work-time-modify.js +++ b/sites/admin-cabinet/assets/js/src/OutOffWorkTime/out-of-work-time-modify.js @@ -398,7 +398,7 @@ const outOfWorkTimeRecord = { } // Check all fields - if ($('#calType').parent().dropdown('get value') !== 'caldav' + if ($('#calType').parent().dropdown('get value') === 'none' && result.data.time_from === '' && result.data.time_to === '' && result.data.weekday_from === '-1' @@ -427,12 +427,12 @@ const outOfWorkTimeRecord = { const serverOffset = parseInt(outOfWorkTimeRecord.$formObj.form('get value', 'serverOffset')); const offsetDiff = serverOffset + currentOffset; - if($('#calType').parent().dropdown('get value') === 'caldav'){ - Form.validateRules.timefrom.rules = []; - Form.validateRules.timeto.rules = []; - } else { + if($('#calType').parent().dropdown('get value') === 'none'){ Form.validateRules.timefrom.rules = outOfWorkTimeRecord.additionalTimeIntervalRules; Form.validateRules.timeto.rules = outOfWorkTimeRecord.additionalTimeIntervalRules; + } else { + Form.validateRules.timefrom.rules = []; + Form.validateRules.timeto.rules = []; } if (dateFrom) { From a6fa46fa5a801fb31f424f95eceddd4d0abaefd6 Mon Sep 17 00:00:00 2001 From: boffart Date: Thu, 16 May 2024 14:40:24 +0300 Subject: [PATCH 02/58] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=B2=20=D0=BE=D0=BF=D0=B8=D1=81=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B8=20=D0=BD=D0=BE=D0=BC=D0=B5=D1=80=20=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D1=81=D0=B8=D0=B8=20asterisk?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 688d983a0..48c035147 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ Or follow our wiki for [additional instructions](https://wiki.mikopbx.com/en:set * Easy to install and easy to setup. * Multilingual interface with community-supported translation service. * Wiki documentation with context helpers on the web interface. -* Latest PJSIP stack and Asterisk LTS 16 release installed. +* Latest PJSIP stack and Asterisk LTS 20 release installed. * Fail2Ban and iptables already included. * Modular architecture. * Plugins marketplace. From 9aaf7bce90789ac3e4c30791f32aa0317ff700c4 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Thu, 16 May 2024 14:52:02 +0300 Subject: [PATCH 03/58] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=B2=20=D0=BE=D0=BF=D0=B8=D1=81=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B8=20=D0=B3=D0=BE=D0=B4=20Copyright?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 48c035147..a0e3d842a 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,7 @@ Become a sponsor and get your logo on our README on Github with a link to your s ## License MikoPBX© - free phone system for small business -Copyright © 2017-2021 Alexey Portnov and Nikolay Beketov +Copyright © 2017-2024 Alexey Portnov and Nikolay Beketov This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by From f34acd051d00feaead07c2693384d8ab06da75a5 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Thu, 16 May 2024 14:56:17 +0300 Subject: [PATCH 04/58] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BD=D0=BE=D0=BC=D0=B5=D1=80=20=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D1=81=D0=B8=D0=B8=20=D1=8F=D0=B4=D1=80=D0=B0=20Linux=20?= =?UTF-8?q?=D0=B2=20=D0=BE=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a0e3d842a..ff0a47663 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ The system has an easy and convenient web interface, call recording, conference ## Getting Started 1. Download [latest released](https://github.com/mikopbx/Core/releases/latest) ISO file in assets section 2. Create a new virtual machine (e.g. VMware Player) -3. Select **Other Linux 4.x kernel 64-bit** on the virtual machine settings +3. Select **Other Linux 6.6.1 kernel 64-bit** on the virtual machine settings 4. Boot from ISO firmware and install MikoPBX on storage according to internal instructions. 5. Continue set up your PBX system over a web interface with default credentials. Username: *admin* password: *admin* From 192a61f6ad5b98aab1cc1a8fa61001798124362b Mon Sep 17 00:00:00 2001 From: Weblate Date: Sun, 19 May 2024 03:30:40 +0300 Subject: [PATCH 05/58] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (1241 of 1241 strings) Co-authored-by: Everton Massen Goncalves Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/pt_BR/ Translation: MIKOPBX/Core --- src/Common/Messages/pt_BR.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Common/Messages/pt_BR.php b/src/Common/Messages/pt_BR.php index e943aa656..79609afb0 100644 --- a/src/Common/Messages/pt_BR.php +++ b/src/Common/Messages/pt_BR.php @@ -384,9 +384,9 @@ 'ex_Online' => 'Conectado', 'ex_UpdateStatus' => 'Atualização de status', 'ex_ValidateNumberIsDouble' => 'O número do ramal já está em uso', - 'ex_ValidateMobileNumberIsDouble' => 'O número do celular já está sendo usado por outro funcionário', + 'ex_ValidateMobileNumberIsDouble' => 'O número do celular já está sendo usado por outro ramal', 'ex_ValidateForwardingToBeDifferent' => 'Você não pode configurar o encaminhamento de chamadas para seu próprio número', - 'ex_ValidateNumberIsEmpty' => 'O número do ramal do funcionário não foi preenchido', + 'ex_ValidateNumberIsEmpty' => 'O número do ramal não foi preenchido', 'ex_ValidateRingingBeforeForwardOutOfRange' => 'O tempo de transferência está especificado incorretamente nas configurações de roteamento. Escolha um valor entre {ruleValue}.', 'ex_ValidateForwardingToBeFilled' => 'O número de encaminhamento de tempo limite não foi preenchido nas configurações de roteamento', 'ex_Status' => 'Status', @@ -394,10 +394,10 @@ 'ex_Mobile' => 'Móvel', 'ex_Extension' => 'Número do ramal', 'ex_Name' => 'Nome', - 'ex_AddNewExtension' => 'Adicionar funcionário', + 'ex_AddNewExtension' => 'Adicionar ramal', 'ex_ValidateExtensionNumber' => 'O número do ramal deve consistir apenas em números', 'ex_ValidateSecretEmpty' => 'A senha SIP não pode estar vazia', - 'ex_ValidateUsernameEmpty' => 'Insira o nome do funcionário', + 'ex_ValidateUsernameEmpty' => 'Insira o nome do ramal', 'ex_ValidateEmailEmpty' => 'Provavelmente o endereço de e-mail foi inserido incorretamente', 'ex_ValidateMobileIsNotCorrect' => 'Verifique se a inserção do número do celular está correta', 'ex_IfMainExtensionIsUnavailableRedirectCallTo' => 'Se o número principal não estiver disponível, transferimos a chamada para', @@ -408,7 +408,7 @@ 'ex_NatMode' => 'Modo NAT', 'ex_NetworkFilter' => 'Filtro de rede', 'ex_DTMFMode' => 'Modo DTMF', - 'ex_BusyLevelInfo' => 'Ao atingir o número especificado de conversas, o telefone do funcionário será considerado ocupado.', + 'ex_BusyLevelInfo' => 'Ao atingir o número especificado de conversas, o telefone do ramal será considerado ocupado.', 'ex_BusyLevel' => 'Número máximo de chamadas paralelas', 'ex_SipSettings' => 'Configurações SIP', 'ex_MobileDialstring' => 'Substituindo uma string de discagem', @@ -477,7 +477,7 @@ 'cq_SecRingToEachMembers' => 'Tempo de tentativas de ligar para as operadores', 'cq_QueueMemberSettings' => 'Configurações de fila para operadores', 'cq_AddQueueMembers' => 'Nenhum operador selecionado', - 'cq_SelectAgentForAddToQueue' => 'Selecione um funcionário para adicionar à fila atual', + 'cq_SelectAgentForAddToQueue' => 'Selecione um ramal para adicionar à fila atual', 'cq_QueueMembers' => 'Operadores de fila', 'cd_Description' => 'Um comentário', 'cq_QueueStrategy' => 'Estratégia de chamada para operadores', @@ -1132,7 +1132,7 @@ 'gs_Store3YearsOfRecords' => '3 anos', 'gs_PBXRecordSavePeriodLabel' => 'O período de armazenamento dos registros de conversas', 'gs_StoreAllPossibleRecords' => '∞', - 'ex_UserPhotography' => 'foto do funcionário', + 'ex_UserPhotography' => 'foto do ramal', 'topMenu_SidebarButton' => 'Cardápio', 'ext_InstalledModules' => 'Módulos instalados', 'ext_Marketplace' => 'Mercado', From 7193af6d14780ccccb991bc3558d45343b0a059f Mon Sep 17 00:00:00 2001 From: boffart <> Date: Wed, 22 May 2024 19:27:04 +0300 Subject: [PATCH 06/58] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BA=D0=BE=D0=BC=D0=B0=D0=BD=D0=B4=D1=83=20?= =?UTF-8?q?=D1=83=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=84=D0=B0?= =?UTF-8?q?=D0=B9=D0=BB=D0=BE=D0=B2.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/System/Storage.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Core/System/Storage.php b/src/Core/System/Storage.php index 56512ea29..71730d51d 100644 --- a/src/Core/System/Storage.php +++ b/src/Core/System/Storage.php @@ -978,6 +978,7 @@ private function clearTmpFiles(): void $timeout = Util::which('timeout'); $find = Util::which('find'); $mv = Util::which('mv'); + $rm = Util::which('rm'); $nice = Util::which('nice'); $tmpDir = $this->config->path('core.tempDir'); if (!file_exists($tmpDir)) { @@ -995,7 +996,7 @@ private function clearTmpFiles(): void shell_exec("$mv '$resDirForRm/swapfile' '$tmpDir/swapfile'"); } // Let's start deleting temporary files - Processes::mwExecBg("$nice -n 19 $mv -rf $resDirForRm"); + Processes::mwExecBg("$nice -n 19 $rm -rf $resDirForRm"); } Util::mwMkdir($tmpDir, true); } From 54e6339d50cf76a19461154d3c66dfdc183a4a04 Mon Sep 17 00:00:00 2001 From: Weblate Date: Thu, 30 May 2024 11:49:52 +0300 Subject: [PATCH 07/58] Translated using Weblate (Thai) Currently translated at 100.0% (1241 of 1241 strings) Co-authored-by: SUMONCHAI WONGPITAK Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/th/ Translation: MIKOPBX/Core --- src/Common/Messages/th.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Common/Messages/th.php b/src/Common/Messages/th.php index 04f44102e..71154ba25 100644 --- a/src/Common/Messages/th.php +++ b/src/Common/Messages/th.php @@ -112,7 +112,7 @@ 'BreadcrumbCallQueues' => 'คิวโทร', 'SubHeaderCallQueues' => 'สายจะถูกพักสายแล้วกระจายไปยังผู้เข้าร่วมตามกลยุทธ์', 'BreadcrumbCallQueuesmodify' => 'การตั้งค่าคิว', - 'BreadcrumbOutOffWorkTime' => 'เวลาไม่ทำงาน', + 'BreadcrumbOutOffWorkTime' => 'นอกเวลาทำการ', 'SubHeaderOutOffWorkTime' => 'กฎการดำเนินงานของสถานีนอกเวลาทำการ วันหยุด และวันหยุดสุดสัปดาห์', 'BreadcrumbOutOffWorkTimemodify' => 'การตั้งกฎเกณฑ์', 'BreadcrumbFirewall' => 'การตั้งค่าไฟร์วอลล์', @@ -161,7 +161,7 @@ 'mm_Providers' => 'ผู้ให้บริการโทรศัพท์', 'mm_IncomingRoutes' => 'เส้นทางที่เข้ามา', 'mm_OutboundRoutes' => 'เส้นทางขาออก', - 'mm_OutOffWorkTime' => 'เวลาไม่ทำงาน', + 'mm_OutOffWorkTime' => 'นอกเวลาทำการ', 'mm_System' => 'ระบบ', 'mm_NetworkSettings' => 'เครือข่ายและไฟร์วอลล์', 'mm_GeneralSettings' => 'การตั้งค่าทั่วไป', @@ -247,7 +247,7 @@ 'gs_PBXRecordSavePeriodLabel' => 'ระยะเวลาการจัดเก็บสำหรับการบันทึกการโทร', 'gs_StoreAllPossibleRecords' => '∞', 'gs_DisableAllModules' => 'ปิดการใช้งานตลาด', - 'pr_AddSIPProvider' => 'เชื่อมต่อเอสไอพี', + 'pr_AddSIPProvider' => 'เชื่อมต่อ SIP', 'pr_AddIAXProvider' => 'เชื่อมต่อ IAX', 'pr_QualifyInstructionsIAX' => 'เมื่อเปิดใช้งานตัวเลือกนี้ เครื่องหมายดอกจันจะส่งแพ็กเก็ตตัวเลือก SIP นี่เป็นสิ่งจำเป็นเพื่อรองรับ NAT tunneling บนเราเตอร์ของคุณ', 'pr_CustomFieldsDescriptions' => 'ในกรณีส่วนใหญ่ ช่องแทนที่ควรเว้นว่างไว้ @@ -406,12 +406,12 @@ 'ex_UserPhotography' => 'รูปถ่ายพนักงาน', 'ex_MobileSettings' => 'การตั้งค่าเพิ่มเติมสำหรับมือถือ', 'ex_MobileDialstring' => 'การแทนที่สตริงการเรียกเลขหมาย', - 'ex_SipSettings' => 'การตั้งค่าจิบ', + 'ex_SipSettings' => 'การตั้งค่าSIP', 'ex_BusyLevel' => 'จำนวนการสนทนาคู่ขนานสูงสุด', 'ex_BusyLevelInfo' => 'เมื่อถึงจำนวนการโทรที่กำหนด โทรศัพท์ของพนักงานจะถือว่าไม่ว่าง', 'ex_DTMFMode' => 'โหมด DTMF', 'ex_NetworkFilter' => 'ตัวกรองเครือข่าย', - 'ex_NatMode' => 'โหมดแนท', + 'ex_NatMode' => 'โหมด NAT', 'gs_CallRecordTab' => 'การบันทึกการสนทนา', 'ex_ManualAdditionalAttributes' => 'ตัวเลือกพิเศษ', 'ex_RingMainExtension' => 'ในระหว่าง', @@ -588,9 +588,9 @@ 'nw_NetworkAddressTranslations' => 'โทโพโลยีเครือข่าย', 'gs_MainTab' => 'ขั้นพื้นฐาน', 'gs_FeaturesTab' => 'การโอนสาย', - 'gs_SIPTab' => 'จิบ', + 'gs_SIPTab' => 'SIP', 'gs_AMITab' => 'อามิ&อาจัม', - 'gs_SSHTab' => 'สสส', + 'gs_SSHTab' => 'SSH', 'gs_WebTab' => 'เว็บอินเตอร์เฟส', 'gs_PBXName' => 'ชื่อระบบ PBX', 'gs_PBXDescription' => 'คำอธิบายเพิ่มเติม', From 44196a65ad96b6dc64d3c6392afb459b37f93dda Mon Sep 17 00:00:00 2001 From: Weblate Date: Fri, 31 May 2024 11:26:13 +0300 Subject: [PATCH 08/58] Translated using Weblate (Thai) Currently translated at 100.0% (1241 of 1241 strings) Co-authored-by: SUMONCHAI WONGPITAK Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/th/ Translation: MIKOPBX/Core --- src/Common/Messages/th.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Common/Messages/th.php b/src/Common/Messages/th.php index 71154ba25..ca57714d6 100644 --- a/src/Common/Messages/th.php +++ b/src/Common/Messages/th.php @@ -106,7 +106,7 @@ 'BreadcrumbIncomingRoutes' => 'เส้นทางขาเข้า', 'SubHeaderIncomingRoutes' => 'กฎและเทมเพลตสำหรับการกระจายสายเรียกเข้า', 'BreadcrumbIncomingRoutesmodify' => 'การตั้งกฎเกณฑ์', - 'BreadcrumbExtensions' => 'พนักงาน', + 'BreadcrumbExtensions' => 'เบอร์ภายใน', 'SubHeaderExtensions' => 'การตั้งค่าหมายเลขโทรศัพท์หลักและกฎการส่งต่อส่วนบุคคล', 'BreadcrumbExtensionsmodify' => 'การเปลี่ยนการตั้งค่า', 'BreadcrumbCallQueues' => 'คิวโทร', @@ -154,7 +154,7 @@ 'BreadcrumbPbxExtensionModules' => 'การจัดการโมดูลและส่วนขยายสำหรับ MikoPBX', 'SubHeaderPbxExtensionModules' => 'อัปโหลดโมดูลของคุณเองหรือดาวน์โหลดจากตลาดของเรา', 'mm_Setup' => 'โทรศัพท์', - 'mm_Extensions' => 'พนักงาน', + 'mm_Extensions' => 'เบอร์ภายใน', 'mm_CallQueues' => 'คิวโทร', 'mm_DialplanApplications' => 'แอปพลิเคชัน Dialplan', 'mm_Routing' => 'การกำหนดเส้นทาง', @@ -229,7 +229,7 @@ 'pr_WithoutRegistration' => 'การลงทะเบียนถูกปิดใช้งาน', 'pr_TableColumnProviderLogin' => 'เข้าสู่ระบบ', 'pr_TableColumnProviderHostName' => 'เจ้าภาพ', - 'pr_TableColumnProviderType' => 'พิมพ์', + 'pr_TableColumnProviderType' => 'รูปแบบ', 'pr_TableColumnProviderName' => 'ผู้ให้บริการ', 'pr_TableColumnProviderStatus' => 'สถานะ', 'pr_ValidateRTPOutOfRange' => 'ช่วงของพอร์ต RTP ไม่ถูกต้อง ค่าต้องอยู่ระหว่าง {ruleValue}', @@ -334,7 +334,7 @@ 'cd_Extensions' => 'หมายเลขโทรศัพท์สำหรับคิวนี้', 'cq_QueueStrategy' => 'กลยุทธ์การโทรสำหรับผู้ประกอบการ', 'cq_QueueMembers' => 'ตัวดำเนินการคิว', - 'cq_SelectAgentForAddToQueue' => 'เลือกพนักงานที่จะเพิ่มลงในคิวปัจจุบัน', + 'cq_SelectAgentForAddToQueue' => 'เลือกเจ้าหน้าที่ ที่จะเพิ่มลงในคิวปัจจุบัน', 'cq_AddQueueMembers' => 'ไม่ได้เลือกโอเปอเรเตอร์', 'cq_QueueMemberSettings' => 'การตั้งค่าคิวสำหรับผู้ประกอบการ', 'cq_SecRingToEachMembers' => 'เวลาพยายามโทรสำหรับผู้ปฏิบัติงาน', @@ -427,7 +427,7 @@ 'ex_PasswordNoLowSimvol' => 'รหัสผ่านจะต้องมีตัวอักษร', 'ex_PasswordNoNumbers' => 'รหัสผ่านจะต้องมีตัวเลข', 'ex_ValidateExtensionNumber' => 'หมายเลขต่อต้องประกอบด้วยตัวเลขเท่านั้น', - 'ex_AddNewExtension' => 'เพิ่มพนักงาน', + 'ex_AddNewExtension' => 'เพิ่มเบอร์ภายใน', 'ex_Name' => 'พนักงาน', 'ex_Transport' => 'โปรโตคอลการขนส่ง', 'ex_Extension' => 'หมายเลขต่อขยาย', @@ -465,7 +465,7 @@ 'ex_dropdownCategory_MENUITEMS' => 'รายการเมนู', 'ex_dropdownCategory_SYSTEM' => 'หมายเลขบริการ', 'ex_dropdownCategory_PARKING' => 'ช่องจอดรถ', - 'ex_ImpossibleToDeleteExtension' => 'ไม่สามารถลบพนักงานได้เพราะว่า มีลิงค์ต่อไปนี้', + 'ex_ImpossibleToDeleteExtension' => 'ไม่สามารถลบเบอร์ภายในได้เพราะว่า มีลิงค์ต่อไปนี้', 'ex_ImpossibleToGetSecret' => 'ไม่สามารถรับรหัสผ่านผู้ใช้', 'am_TableColumnName' => 'ชื่อ', 'am_TableColumnRead' => 'สิทธิ์การอ่าน', @@ -802,7 +802,7 @@ 'repConferenceRooms' => 'การประชุม - %represent%', 'repCustomFiles' => 'ไฟล์ระบบ - %represent%', 'repDialplanApplications' => 'แอปพลิเคชัน Dialplan - %represent%', - 'repExtensionForwardingRights' => 'การตั้งค่าการกำหนดเส้นทางพนักงาน - %represent%', + 'repExtensionForwardingRights' => 'การตั้งค่าการกำหนดเส้นทางเบอร์ภายใน- %represent%', 'repExtensions' => 'หมายเลขต่อ - %represent%', 'repExternalPhones' => 'หมายเลขภายนอก - %represent%', 'repFail2BanRules' => 'กฎ Fail2Ban - %represent%', @@ -1028,7 +1028,7 @@ 'mo_ModuleShort4Dropdown' => 'โมดูล', 'mo_SystemExten_hangup' => 'วางสาย', 'mo_SystemExten_busy' => 'เล่นโทนไม่ว่าง', - 'mo_SystemExten_did2user' => 'ส่งตรงถึงพนักงาน (จับคู่โดย DID)', + 'mo_SystemExten_did2user' => 'ส่งตรงถึงเบอร์ภายใน(จับคู่โดย DID)', 'mo_SystemExten_voicemail' => 'ข้อความเสียง', 'GoToWikiDocumentation' => 'ไปที่เอกสารออนไลน์', 'mo_ModuleSettingsError' => 'ข้อผิดพลาดในการตั้งค่าโมดูล - %modulename%', @@ -1202,8 +1202,8 @@ 'tf_calUrl' => 'URL ปฏิทิน', 'tf_calUser' => 'ชื่อผู้ใช้', 'tf_calSecret' => 'รหัสผ่าน', - 'tf_calType' => 'พิมพ์', - 'tf_CAL_TYPE_NONE' => 'สามัญ', + 'tf_calType' => 'รูปแบบ', + 'tf_CAL_TYPE_NONE' => 'ปกติ', 'tf_CAL_TYPE_CALDAV' => 'คาลดีเอวี', 'tf_CAL_TYPE_ICAL' => 'ไอแคล', 'ext_UpdateModuleTitle' => 'อัพเดตโมดูล', From f7b96d61254ccc63e2b71dcb3188f6397851ba23 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Wed, 5 Jun 2024 20:09:34 +0300 Subject: [PATCH 09/58] =?UTF-8?q?#728=20=D0=9D=D0=B5=20=D0=BA=D0=BE=D1=80?= =?UTF-8?q?=D1=80=D0=B5=D0=BA=D1=82=D0=BD=D0=BE=20=D0=B2=D1=8B=D1=87=D0=B8?= =?UTF-8?q?=D1=81=D0=BB=D1=8F=D0=B5=D1=82=D1=81=D1=8F=20=D1=85=D1=8D=D1=88?= =?UTF-8?q?=20=D0=BA=D1=80=D0=B8=D1=82=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=B8?= =?UTF-8?q?=D1=85=20=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE=D0=B5=D0=BA=20SIP?= =?UTF-8?q?,=20=D0=BA=D0=BE=D1=82=D0=BE=D1=80=D1=8B=D0=B5=20=D1=82=D1=80?= =?UTF-8?q?=D0=B5=D0=B1=D1=83=D1=8E=D1=82=20restart=20asterisk?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/Asterisk/Configs/SIPConf.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Core/Asterisk/Configs/SIPConf.php b/src/Core/Asterisk/Configs/SIPConf.php index 4419d383a..741eb106d 100644 --- a/src/Core/Asterisk/Configs/SIPConf.php +++ b/src/Core/Asterisk/Configs/SIPConf.php @@ -130,11 +130,15 @@ public function needAsteriskRestart(): bool if ($di === null) { return false; } - $mikoPBXConfig = new MikoPBXConfig(); [$topology, $extIpAddress, $externalHostName, $subnets] = $this->getTopologyData(); - $generalSettings = $mikoPBXConfig->getGeneralSettings(); - $now_hash = md5($topology . $externalHostName . $extIpAddress . $generalSettings[PbxSettingsConstants::SIP_PORT]. $generalSettings[PbxSettingsConstants::TLS_PORT] . implode('',$subnets)); + $externalSipPort = $this->generalSettings[PbxSettingsConstants::EXTERNAL_SIP_PORT]; + $externalTlsPort = $this->generalSettings[PbxSettingsConstants::EXTERNAL_TLS_PORT]; + $sipPort = $this->generalSettings[PbxSettingsConstants::SIP_PORT]; + $tlsPort = $this->generalSettings[PbxSettingsConstants::TLS_PORT]; + + $now_hash = md5($topology . $externalHostName . $extIpAddress . $sipPort.$externalSipPort. $tlsPort .$externalTlsPort. implode('',$subnets)); + $old_hash = ''; $varEtcDir = $di->getShared('config')->path('core.varEtcDir'); if (file_exists($varEtcDir . self::TOPOLOGY_HASH_FILE)) { From fa1f26dc5b4e238be78a632283211bc1527e924d Mon Sep 17 00:00:00 2001 From: Weblate Date: Sat, 8 Jun 2024 06:16:46 +0300 Subject: [PATCH 10/58] Translated using Weblate (Thai) Currently translated at 100.0% (1241 of 1241 strings) Co-authored-by: SUMONCHAI WONGPITAK Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/th/ Translation: MIKOPBX/Core --- src/Common/Messages/th.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Common/Messages/th.php b/src/Common/Messages/th.php index ca57714d6..8ea52b0e4 100644 --- a/src/Common/Messages/th.php +++ b/src/Common/Messages/th.php @@ -341,11 +341,11 @@ 'cq_WrapupTime' => 'เวลาพักของผู้ให้บริการหลังจากรับสายก่อนเริ่มรับสายใหม่', 'cq_ReciveCallWhileOnCall' => 'รับสายใหม่ระหว่างการโทร', 'cq_QueueCallerSettings' => 'การตั้งค่าคิวผู้โทร', - 'cq_CallerHearOnQueued' => 'สิ่งที่สมาชิกได้ยินขณะรอ', + 'cq_CallerHearOnQueued' => 'สิ่งที่ผู้โทรได้ยินขณะรอ', 'cq_ringing' => 'เสียงเรียกเข้า', 'cq_AnnoncePosition' => 'แจ้งตำแหน่งปัจจุบันในคิว', 'cq_AnnonceHoldTime' => 'แจ้งเกี่ยวกับเวลารอโดยประมาณ', - 'cq_PereodicAnonceSoundFile' => 'วลีส่งเสริมการขายหรือการแจ้งเตือนเพิ่มเติม', + 'cq_PereodicAnonceSoundFile' => 'ข้อความเสียง ส่งเสริมการขาย หรือการแจ้งเตือนเพิ่มเติม', 'cq_PereodicAnonceMohSoundFile' => 'เพลงพื้นหลัง (MOH)', 'gs_SSHDisablePasswordLogins' => 'ปิดการใช้งานการตรวจสอบรหัสผ่าน', 'cq_PereodicAnonceFrequency' => 'เวลาเป็นวินาทีเพื่อทำซ้ำการแจ้งเตือนทั้งหมดเป็นระยะ', @@ -354,7 +354,7 @@ 'cq_ScenaryTwo' => 'สถานการณ์ #2', 'cq_ScenaryThree' => 'สถานการณ์ #3', 'cq_ScenaryFour' => 'สถานการณ์ #4', - 'cq_IfQueueNotAnsweredFor' => 'หากสมาชิกรอคิวนานเกิน ', + 'cq_IfQueueNotAnsweredFor' => 'หากสายโทรเข้ารอคิวนานเกิน ', 'cq_SecondsCallWillBeRoutedTo' => ' วินาที โอนสายไปที่ ', 'cq_RedirectToExtensionIfEmtyQueue' => 'หากไม่มีโอเปอเรเตอร์อยู่ในคิว ให้โอนสายไปที่ ', 'cq_IfQueueNotAnsweredNumberCalls' => 'หากไม่มีโอเปอเรเตอร์รับสายภายใน ', From bb9939127bfae6d766f60a621dbeb14ca0377555 Mon Sep 17 00:00:00 2001 From: Weblate Date: Tue, 11 Jun 2024 06:27:23 +0300 Subject: [PATCH 11/58] Translated using Weblate (Thai) Currently translated at 100.0% (1241 of 1241 strings) Co-authored-by: SUMONCHAI WONGPITAK Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/th/ Translation: MIKOPBX/Core --- src/Common/Messages/th.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Common/Messages/th.php b/src/Common/Messages/th.php index 8ea52b0e4..7afd76e93 100644 --- a/src/Common/Messages/th.php +++ b/src/Common/Messages/th.php @@ -605,7 +605,7 @@ 'gs_PBXFeatureAttendedTransfer' => 'การผสมผสานการแปลเชิงปรึกษา', 'gs_PBXFeatureBlindTransfer' => 'การรวมกันเพื่อการโอนแบบไม่มีเงื่อนไข', 'gs_PBXFeatureDigitTimeout' => 'การหมดเวลาระหว่างหลักสูงสุดเมื่อป้อนหมายเลขส่วนขยาย (เป็นมิลลิวินาที)', - 'gs_PBXFeaturePickupExten' => 'ชุดค่าผสมสำหรับดักสายเรียกเข้า', + 'gs_PBXFeaturePickupExten' => 'Code ดึงสายโทรเข้า จากเครื่องอื่น', 'gs_PBXSplitAudioThread' => 'บันทึกการบันทึกในโหมดสเตอริโอ', 'gs_PBXAllowGuestCalls' => 'อนุญาตสายเรียกเข้าจากเซิร์ฟเวอร์ใด ๆ', 'gs_SIPPort' => 'พอร์ต SIP สำหรับลงทะเบียนโทรศัพท์ที่สถานีนี้', From e1633d78c0e64ba3fb3801ed63f36b2b30dcc076 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Tue, 11 Jun 2024 14:13:36 +0300 Subject: [PATCH 12/58] =?UTF-8?q?#699=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=B1=D0=BE=D0=BB=D0=B5=D0=B5=20=D0=B4=D0=B5?= =?UTF-8?q?=D1=82=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B=D0=B9=20=D0=BB=D0=BE=D0=B3?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/Asterisk/AsteriskManager.php | 28 +++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/Core/Asterisk/AsteriskManager.php b/src/Core/Asterisk/AsteriskManager.php index e257d34d8..6557a2ddb 100644 --- a/src/Core/Asterisk/AsteriskManager.php +++ b/src/Core/Asterisk/AsteriskManager.php @@ -19,6 +19,7 @@ namespace MikoPBX\Core\Asterisk; +use MikoPBX\Core\System\Processes; use MikoPBX\Core\System\SystemMessages; use MikoPBX\Core\System\Util; use Throwable; @@ -612,30 +613,41 @@ public function connect($server = null, $username = null, $secret = null, $event } // connect the socket - $errno = $errstr = null; + $errno = $errStr = null; $timeout = 2; - $this->socket = @fsockopen($this->server, $this->port, $errno, $errstr, $timeout); - if ($this->socket == false) { - SystemMessages::sysLogMsg('asmanager', "Unable to connect to manager {$this->server}:{$this->port} ($errno): $errstr", LOG_ERR); + $netStatPath = Util::which('netstat'); + $busyBoxPath = Util::which('busybox'); + $chkCommand = "$netStatPath -ntap | $busyBoxPath grep '$server ' | $busyBoxPath grep ESTABLISHED | $busyBoxPath grep asterisk"; + if(Processes::mwExec($chkCommand) === 1){ + SystemMessages::sysLogMsg('AMI', "Exceptions, Unable to connect to $server: the asterisk process is not running", LOG_ERR); + return false; + } + try { + $this->socket = fsockopen($this->server, $this->port, $errno, $errStr, $timeout); + }catch (Throwable $e){ + SystemMessages::sysLogMsg('AMI', "Exceptions, Unable to connect to manager $server ($errno): $errStr", LOG_ERR); + return false; + } + if ($this->socket === false) { + SystemMessages::sysLogMsg('AMI', "Unable to connect to manager $server ($errno): $errStr", LOG_ERR); return false; } - // PT1C; stream_set_timeout($this->socket, 1, 0); // read the header $str = $this->getStringDataFromSocket(); if ($str === '') { // a problem. - Util::sysLogMsg('asmanager', "Asterisk Manager header not received.", LOG_ERR); + SystemMessages::sysLogMsg('AMI', "Asterisk Manager header not received.", LOG_ERR); return false; } // login $res = $this->sendRequest('login', ['Username' => $username, 'Secret' => $secret, 'Events' => $events]); - if ($res['Response'] != 'Success') { + if ($res['Response'] !== 'Success') { $this->_loggedIn = false; - Util::sysLogMsg('asmanager', "Failed to login.", LOG_ERR); + SystemMessages::sysLogMsg('AMI', "Failed to login.", LOG_ERR); $this->disconnect(); return false; } From 7bd850d9c3a4a1c90394a17e4905a304e9b3c15a Mon Sep 17 00:00:00 2001 From: boffart <> Date: Fri, 14 Jun 2024 15:15:19 +0300 Subject: [PATCH 13/58] =?UTF-8?q?#739=20=D0=9F=D0=BE=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D0=BB=20=D1=83=D1=81=D1=82=D0=B0=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=BA=D1=83=20set=5Fvar=3DcontextID?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/OutOffWorkTimeController.php | 2 +- src/Core/Asterisk/Configs/ExtensionsOutWorkTimeConf.php | 2 +- src/Core/Asterisk/Configs/SIPConf.php | 9 +++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/AdminCabinet/Controllers/OutOffWorkTimeController.php b/src/AdminCabinet/Controllers/OutOffWorkTimeController.php index 29a70c168..e4b72a968 100644 --- a/src/AdminCabinet/Controllers/OutOffWorkTimeController.php +++ b/src/AdminCabinet/Controllers/OutOffWorkTimeController.php @@ -196,7 +196,7 @@ public function modifyAction(string $id = ''): void if($providerData['registration_type'] === Sip::REG_TYPE_INBOUND || empty($providerData['host'])){ $providersId[$providerData['uniqid']] = $providerData['uniqid']; }else{ - $providersId[$providerData['uniqid']] = SIPConf::getContextId($providerData['host'] . $providerData['port']); + $providersId[$providerData['uniqid']] = SIPConf::getContextId($providerData['host'] , $providerData['port']); } } unset($data); diff --git a/src/Core/Asterisk/Configs/ExtensionsOutWorkTimeConf.php b/src/Core/Asterisk/Configs/ExtensionsOutWorkTimeConf.php index ad242a601..85c73d18b 100644 --- a/src/Core/Asterisk/Configs/ExtensionsOutWorkTimeConf.php +++ b/src/Core/Asterisk/Configs/ExtensionsOutWorkTimeConf.php @@ -202,7 +202,7 @@ private function getRoutesData(): array }elseif ($provByType->registration_type === Sip::REG_TYPE_INBOUND){ $context_id = "{$provider->uniqid}-incoming"; } else { - $context_id = SIPConf::getContextId($provByType->host . $provByType->port); + $context_id = SIPConf::getContextId($provByType->host , $provByType->port); } } else { $context_id = 'none-incoming'; diff --git a/src/Core/Asterisk/Configs/SIPConf.php b/src/Core/Asterisk/Configs/SIPConf.php index 741eb106d..68c637f6e 100644 --- a/src/Core/Asterisk/Configs/SIPConf.php +++ b/src/Core/Asterisk/Configs/SIPConf.php @@ -392,7 +392,7 @@ private function getProviders(): array $arr_data['transport'] = trim($arr_data['transport']); // Retrieve used codecs. $arr_data['codecs'] = $this->getCodecs(); - $context_id = self::getContextId($sip_peer->host.$sip_peer->port); + $context_id = self::getContextId($sip_peer->host, $sip_peer->port); if ( ! isset($this->contexts_data[$context_id])) { $this->contexts_data[$context_id] = []; } @@ -1088,7 +1088,7 @@ private function generateProviderEndpoint(array $provider, array $manual_attribu // Add configuration section header $conf .= "[{$provider['uniqid']}]".PHP_EOL; - $conf .= 'set_var=contextID='.$context.PHP_EOL; + $conf .= 'set_var=contextID='.$provider['context_id'].PHP_EOL; // Generate and add configuration options $conf .= Util::overrideConfigurationArray($options, $manual_attributes, 'endpoint'); @@ -1102,11 +1102,12 @@ private function generateProviderEndpoint(array $provider, array $manual_attribu * This method generates the context ID for a given name by removing non-alphanumeric characters and appending "-incoming". * * @param string $name The name to generate the context ID from. + * @param string $port The port to generate the context ID from. * @return string The generated context ID. */ - public static function getContextId(string $name = ''):string + public static function getContextId(string $name, string $port):string { - return preg_replace("/[^a-z\d]/iu", '', $name).'-incoming'; + return preg_replace("/[^a-z\d]/iu", '', $name.$port).'-incoming'; } /** From 875b3a2c5dee742f4988b77718a0bb6b189c173e Mon Sep 17 00:00:00 2001 From: boffart <> Date: Fri, 14 Jun 2024 15:15:44 +0300 Subject: [PATCH 14/58] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BF=D1=80=D0=BE=D0=BF=D1=83=D1=80=D0=BA=D1=83?= =?UTF-8?q?=20=D0=B7=D0=B0=D0=BF=D1=83=D1=89=D0=B5=D0=BD=20=D0=BB=D0=B8=20?= =?UTF-8?q?AMI.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/Asterisk/AsteriskManager.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Core/Asterisk/AsteriskManager.php b/src/Core/Asterisk/AsteriskManager.php index 6557a2ddb..a0a809f51 100644 --- a/src/Core/Asterisk/AsteriskManager.php +++ b/src/Core/Asterisk/AsteriskManager.php @@ -618,7 +618,9 @@ public function connect($server = null, $username = null, $secret = null, $event $netStatPath = Util::which('netstat'); $busyBoxPath = Util::which('busybox'); - $chkCommand = "$netStatPath -ntap | $busyBoxPath grep '$server ' | $busyBoxPath grep ESTABLISHED | $busyBoxPath grep asterisk"; + + $address = str_replace('127.0.0.1:', '0.0.0.0:', $server); + $chkCommand = "$netStatPath -ntap | $busyBoxPath grep '$address ' | $busyBoxPath grep LISTEN | $busyBoxPath grep asterisk"; if(Processes::mwExec($chkCommand) === 1){ SystemMessages::sysLogMsg('AMI', "Exceptions, Unable to connect to $server: the asterisk process is not running", LOG_ERR); return false; From f1c9cd99795c2edd0762fd5f24d6e1c1a7bf3235 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Mon, 17 Jun 2024 12:13:56 +0300 Subject: [PATCH 15/58] =?UTF-8?q?#739=20=D0=BF=D1=80=D0=B5=D0=B4=D1=83?= =?UTF-8?q?=D1=81=D0=BC=D0=BE=D1=82=D1=80=D0=B5=D0=BB=20=D1=81=D0=B8=D1=82?= =?UTF-8?q?=D1=83=D0=B0=D1=86=D0=B8=D1=8E,=20=D0=BA=D0=BE=D0=B3=D0=B4?= =?UTF-8?q?=D0=B0=20=D0=B4=D0=BE=D0=BC=D0=B5=D0=BD=20=D1=80=D0=B0=D0=B7?= =?UTF-8?q?=D0=BD=D1=8B=D0=B9=20=D1=80=D0=B5=D0=B7=D0=BE=D0=BB=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=81=D1=8F=20=D0=B2=20=D0=BE=D0=B4=D0=B8=D0=BD=20=D0=B8?= =?UTF-8?q?=20=D1=82=D0=BE=D1=82=20=D0=B6=D0=B5=20IP.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Configs/ExtensionsOutWorkTimeConf.php | 17 +++++++++++++++++ src/Core/Asterisk/Configs/SIPConf.php | 9 +++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/Core/Asterisk/Configs/ExtensionsOutWorkTimeConf.php b/src/Core/Asterisk/Configs/ExtensionsOutWorkTimeConf.php index 85c73d18b..a6e83265b 100644 --- a/src/Core/Asterisk/Configs/ExtensionsOutWorkTimeConf.php +++ b/src/Core/Asterisk/Configs/ExtensionsOutWorkTimeConf.php @@ -89,6 +89,22 @@ public function extensionGenContexts(): string return $this->conf; } + + /** + * + * @return string Set global vars. + */ + public function extensionGlobals(): string + { + $configs = ''; + $dbData = Sip::find("type = 'friend' AND ( disabled <> '1')"); + foreach ($dbData as $sipPeer) { + $context_id = SIPConf::getContextId($sipPeer->host, $sipPeer->port); + $configs .= "CONTEXT_ID_$sipPeer->uniqid=$context_id".PHP_EOL; + } + return $configs; + } + /** * Generates the customized incoming context for a specific route before dialing system. * @@ -101,6 +117,7 @@ public function generateIncomingRoutBeforeDialSystem(string $rout_number): strin // Check the schedule for incoming external calls. return 'same => n,NoOp(contextID: ${contextID})' . PHP_EOL . "\t" . 'same => n,ExecIf($["${CONTEXT}" == "public-direct-dial"]?Set(contextID=none-incoming))' . PHP_EOL . "\t" . + 'same => n,ExecIf($["${contextID}x" == "x"]?Set(contextID=${CONTEXT_ID_${providerID}}))' . PHP_EOL . "\t" . 'same => n,ExecIf($["${contextID}x" == "x"]?Set(contextID=${CONTEXT}))' . PHP_EOL . "\t" . 'same => n,GosubIf($["${IGNORE_TIME}" != "1"]?' . self::OUT_WORK_TIME_CONTEXT . ',${EXTEN},1)' . PHP_EOL . "\t"; } diff --git a/src/Core/Asterisk/Configs/SIPConf.php b/src/Core/Asterisk/Configs/SIPConf.php index 68c637f6e..c57474b68 100644 --- a/src/Core/Asterisk/Configs/SIPConf.php +++ b/src/Core/Asterisk/Configs/SIPConf.php @@ -1088,7 +1088,7 @@ private function generateProviderEndpoint(array $provider, array $manual_attribu // Add configuration section header $conf .= "[{$provider['uniqid']}]".PHP_EOL; - $conf .= 'set_var=contextID='.$provider['context_id'].PHP_EOL; + $conf .= 'set_var=providerID='.$provider['uniqid'].PHP_EOL; // Generate and add configuration options $conf .= Util::overrideConfigurationArray($options, $manual_attributes, 'endpoint'); @@ -1107,7 +1107,12 @@ private function generateProviderEndpoint(array $provider, array $manual_attribu */ public static function getContextId(string $name, string $port):string { - return preg_replace("/[^a-z\d]/iu", '', $name.$port).'-incoming'; + if (filter_var($name, FILTER_VALIDATE_IP)) { + $nameNew = $name; + }else{ + $nameNew = gethostbyname($name); + } + return preg_replace("/[^a-z\d]/iu", '', $nameNew.$port).'-incoming'; } /** From 84e98d94af6cac7d08fcf14492fda9dc3273f3c7 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Mon, 17 Jun 2024 14:39:33 +0300 Subject: [PATCH 16/58] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BE=D1=82=D0=BC=D0=BE=D0=BD=D1=82=D0=B8=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=B4=D0=B8=D1=81=D0=BA?= =?UTF-8?q?=D0=BE=D0=B2=20=D0=BF=D1=80=D0=B8=20=D0=BF=D0=BE=D0=BF=D1=8B?= =?UTF-8?q?=D1=82=D0=BA=D0=B5=20=D0=B2=D0=BE=D1=81=D1=81=D1=82=D0=B0=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B8=D0=B7=20?= =?UTF-8?q?=D0=B1=D0=B5=D0=BA=D0=B0=D0=BF=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/System/SystemConfiguration.php | 37 +++++++++++++------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/Core/System/SystemConfiguration.php b/src/Core/System/SystemConfiguration.php index d83117ade..40f4cb443 100644 --- a/src/Core/System/SystemConfiguration.php +++ b/src/Core/System/SystemConfiguration.php @@ -54,37 +54,38 @@ public function tryRestoreConf():void $backupDir = str_replace(['/storage/usbdisk1','/mountpoint'], ['',''], $confBackupDir); $confFile = $this->configDBPath; foreach ($storages as $dev => $fs){ - SystemMessages::echoToTeletype(" - mount $dev ..."."\n", true); + SystemMessages::echoToTeletype(" - mount $dev ...".PHP_EOL, true); Util::mwMkdir($tmpMountDir."/$dev"); $res = Storage::mountDisk($dev, $fs, $tmpMountDir."/$dev"); if(!$res){ - SystemMessages::echoToTeletype(" - fail mount $dev ..."."\n", true); + SystemMessages::echoToTeletype(" - fail mount $dev ...".PHP_EOL, true); } } $tail = Util::which('tail'); $sort = Util::which('sort'); $find = Util::which('find'); - $mount = Util::which('umount'); - $rm = Util::which('rm'); $cut = Util::which('cut'); - $gzip = Util::which('gzip'); - $sqlite3 = Util::which('sqlite3'); $lastBackUp = trim(shell_exec("$find $tmpMountDir/dev/*$backupDir -type f -printf '%T@ %p\\n' | $sort -n | $tail -1 | $cut -f2- -d' '")); - if(empty($lastBackUp)){ - return; - } - SystemMessages::echoToTeletype(" - Restore $lastBackUp ..."."\n", true); - shell_exec("$rm -rf {$confFile}*"); - shell_exec("$gzip -c -d $lastBackUp | sqlite3 $confFile"); - Processes::mwExec("$sqlite3 $confFile 'select * from m_Storage'", $out, $ret); - if($ret !== 0){ - SystemMessages::echoToTeletype(" - restore $lastBackUp failed..."."\n", true); - copy(self::DEFAULT_CONFIG_DB, $confFile); - }elseif(!$this->isDefaultConf()){ - System::reboot(); + if(!empty($lastBackUp)){ + $rm = Util::which('rm'); + $gzip = Util::which('gzip'); + $sqlite3= Util::which('sqlite3'); + + SystemMessages::echoToTeletype(" - Restore $lastBackUp ...".PHP_EOL, true); + shell_exec("$rm -rf {$confFile}*"); + shell_exec("$gzip -c -d $lastBackUp | sqlite3 $confFile"); + Processes::mwExec("$sqlite3 $confFile 'select * from m_Storage'", $out, $ret); + if($ret !== 0){ + SystemMessages::echoToTeletype(" - restore $lastBackUp failed...".PHP_EOL, true); + copy(self::DEFAULT_CONFIG_DB, $confFile); + }elseif(!$this->isDefaultConf()){ + System::reboot(); + } } + $mount = Util::which('umount'); foreach ($storages as $dev => $fs){ + SystemMessages::echoToTeletype(" - umount $dev ...".PHP_EOL, true); shell_exec("$mount $dev"); } } From 9f107aa5e721a45238471cf26811d404053943aa Mon Sep 17 00:00:00 2001 From: boffart <> Date: Mon, 17 Jun 2024 14:42:18 +0300 Subject: [PATCH 17/58] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B0=20?= =?UTF-8?q?=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4=D0=B0=20=D0=B8=D0=BD=D1=84=D0=BE?= =?UTF-8?q?=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D0=BE=D0=BD=D0=BD=D0=BE=D0=B3?= =?UTF-8?q?=D0=BE=20=D1=81=D0=BE=D0=BE=D0=B1=D1=89=D0=B5=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/System/SystemConfiguration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/System/SystemConfiguration.php b/src/Core/System/SystemConfiguration.php index 40f4cb443..10f38b287 100644 --- a/src/Core/System/SystemConfiguration.php +++ b/src/Core/System/SystemConfiguration.php @@ -54,7 +54,7 @@ public function tryRestoreConf():void $backupDir = str_replace(['/storage/usbdisk1','/mountpoint'], ['',''], $confBackupDir); $confFile = $this->configDBPath; foreach ($storages as $dev => $fs){ - SystemMessages::echoToTeletype(" - mount $dev ...".PHP_EOL, true); + SystemMessages::echoToTeletype(PHP_EOL." - mount $dev ...".PHP_EOL, true); Util::mwMkdir($tmpMountDir."/$dev"); $res = Storage::mountDisk($dev, $fs, $tmpMountDir."/$dev"); if(!$res){ From 3290bad7e100fdce57decddbfa25ba2d1df9e27b Mon Sep 17 00:00:00 2001 From: boffart <> Date: Mon, 17 Jun 2024 15:23:34 +0300 Subject: [PATCH 18/58] =?UTF-8?q?=D0=9D=D0=B5=D0=B7=D0=BD=D0=B0=D1=87?= =?UTF-8?q?=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B=D0=B5=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=BF=D0=B2=D0=BA=D0=B8=20=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4?= =?UTF-8?q?=D0=B0=20=D0=BF=D1=80=D0=BE=D1=86=D0=B5=D1=81=D1=81=D0=B0=20?= =?UTF-8?q?=D1=83=D1=81=D1=82=D0=B0=D0=BD=D0=BE=D0=B2=D0=BA=D0=B8=20=D0=90?= =?UTF-8?q?=D0=A2=D0=A1.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/System/PBXInstaller.php | 28 +++++++++++++--------------- src/Core/System/Storage.php | 7 +++---- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/Core/System/PBXInstaller.php b/src/Core/System/PBXInstaller.php index e0c189617..163ae1ad6 100644 --- a/src/Core/System/PBXInstaller.php +++ b/src/Core/System/PBXInstaller.php @@ -208,9 +208,6 @@ private function proceedInstallation() $this->unpackImage(); $this->mountStorage(); $this->copyConfiguration(); - $umount = Util::which('umount'); - Processes::mwExec("$umount /mnttmp"); - echo "done\n"; // Reboot file_put_contents('/tmp/ejectcd', ''); @@ -266,17 +263,17 @@ private function mountStorage() /** * Copy the configuration to the target disk. */ - private function copyConfiguration() + private function copyConfiguration():void { // Back up the table with disk information. - echo Util::translate("Copying configuration..."); + echo Util::translate("Copying configuration...").PHP_EOL; Util::mwMkdir('/mnttmp'); - $confPartitionName = Storage::getDevPartName("/dev/{$this->target_disk}", '3'); + $confPartitionName = Storage::getDevPartName("/dev/$this->target_disk", '3'); // Mount the disk with settings. $mount = Util::which('mount'); - Processes::mwExec("{$mount} -w -o noatime {$confPartitionName} /mnttmp"); + Processes::mwExec("$mount -w -o noatime $confPartitionName /mnttmp"); $filename = $this->config->path('database.dbfile'); $result_db_file = '/mnttmp/conf/mikopbx.db'; @@ -285,7 +282,6 @@ private function copyConfiguration() $cp = Util::which('cp'); $sqlite3 = Util::which('sqlite3'); $dmpDbFile = tempnam('/tmp', 'storage'); - // Save dump of settings. $tables = ['m_Storage', 'm_LanInterfaces']; file_put_contents($dmpDbFile, ''); @@ -295,18 +291,20 @@ private function copyConfiguration() } // If another language is selected - use another settings file. $lang = PbxSettings::getValueByKey(PbxSettingsConstants::SSH_LANGUAGE); - $filename_lang = "/offload/conf/mikopbx-{$lang}.db"; + $filename_lang = "/offload/conf/mikopbx-$lang.db"; if ($lang !== 'en' && file_exists($filename_lang)) { $filename = $filename_lang; } - // Replace the settings file. - Processes::mwExec("{$cp} {$filename} {$result_db_file}"); - system("{$sqlite3} {$result_db_file} 'DROP TABLE IF EXISTS m_Storage'"); - system("{$sqlite3} {$result_db_file} 'DROP TABLE IF EXISTS m_LanInterfaces'"); - + Processes::mwExec("$cp $filename $result_db_file"); + foreach ($tables as $table) { + system("$sqlite3 $result_db_file 'DROP TABLE IF EXISTS $table'"); + } // Restore settings from backup file. - system("{$sqlite3} {$result_db_file} < {$dmpDbFile}"); + system("$sqlite3 $result_db_file < $dmpDbFile"); unlink($dmpDbFile); + + $umount = Util::which('umount'); + Processes::mwExec("$umount /mnttmp"); } } \ No newline at end of file diff --git a/src/Core/System/Storage.php b/src/Core/System/Storage.php index 71730d51d..571964d78 100644 --- a/src/Core/System/Storage.php +++ b/src/Core/System/Storage.php @@ -572,7 +572,7 @@ public static function selectAndConfigureStorageDisk(bool $automatic=false, bool passthru("exec /dev/console 2>/dev/console; /sbin/initial_storage_part_four update {$dev_disk}"); } $partitionName = self::getDevPartName($target_disk_storage, $part); - $uuid = $storage->getUuid($partitionName); + $uuid = self::getUuid($partitionName); // Create an array of disk data $data = [ 'device' => $dev_disk, @@ -580,7 +580,7 @@ public static function selectAndConfigureStorageDisk(bool $automatic=false, bool 'filesystemtype' => 'ext4', 'name' => 'Storage №1' ]; - + echo PHP_EOL ."Disk part: $dev_disk, uid: $uuid"; // Save the disk settings $storage->saveDiskSettings($data); if (file_exists('/offload/livecd')) { @@ -1879,8 +1879,7 @@ public static function mountDisk(string $dev, string $format, string $dir): bool Processes::mwExec("{$mountNtfs3gPath} /dev/{$dev} {$dir}", $out); } else { // Mount disk using specified file system format and UUID - $storage = new self(); - $uid_part = 'UUID=' . $storage->getUuid("/dev/{$dev}") . ''; + $uid_part = 'UUID=' . self::getUuid("/dev/{$dev}"); $mountPath = Util::which('mount'); Processes::mwExec("{$mountPath} -t {$format} {$uid_part} {$dir}", $out); } From e9f7427551d9ae8bd75745a259025954736cac99 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Mon, 17 Jun 2024 23:56:12 +0300 Subject: [PATCH 19/58] =?UTF-8?q?#745=20=D0=A0=D0=B0=D1=81=D1=88=D0=B8?= =?UTF-8?q?=D1=80=D0=B8=D0=BB=20=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4=20=D0=B8?= =?UTF-8?q?=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D0=B8=20=D0=B2?= =?UTF-8?q?=20=D0=BA=D0=BE=D0=BD=D1=81=D0=BE=D0=BB=D1=8C=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BE=D1=82=D0=BB=D0=B0=D0=B4=D0=BA=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/System/PBXInstaller.php | 26 ++++++++++++++++---------- src/Core/System/Storage.php | 6 ++++-- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/Core/System/PBXInstaller.php b/src/Core/System/PBXInstaller.php index 163ae1ad6..8ba1c9db2 100644 --- a/src/Core/System/PBXInstaller.php +++ b/src/Core/System/PBXInstaller.php @@ -270,11 +270,13 @@ private function copyConfiguration():void Util::mwMkdir('/mnttmp'); $confPartitionName = Storage::getDevPartName("/dev/$this->target_disk", '3'); - // Mount the disk with settings. $mount = Util::which('mount'); - Processes::mwExec("$mount -w -o noatime $confPartitionName /mnttmp"); - + $umount = Util::which('umount'); + $resUMount = Processes::mwExec("$umount $confPartitionName"); + echo "Umount $confPartitionName: $resUMount ...".PHP_EOL; + $resMount = Processes::mwExec("$mount -w -o noatime $confPartitionName /mnttmp"); + echo "Mount $confPartitionName to /mnttmp: $resMount ...".PHP_EOL; $filename = $this->config->path('database.dbfile'); $result_db_file = '/mnttmp/conf/mikopbx.db'; @@ -286,8 +288,10 @@ private function copyConfiguration():void $tables = ['m_Storage', 'm_LanInterfaces']; file_put_contents($dmpDbFile, ''); foreach ($tables as $table) { - shell_exec("sqlite3 /cf/conf/mikopbx.db '.schema $table' >> $dmpDbFile"); - shell_exec("sqlite3 /cf/conf/mikopbx.db '.dump $table' >> $dmpDbFile"); + echo "DUMP $table from /cf/conf/mikopbx.db ...".PHP_EOL; + $res = shell_exec("sqlite3 /cf/conf/mikopbx.db '.schema $table' >> $dmpDbFile"); + $res .= shell_exec("sqlite3 /cf/conf/mikopbx.db '.dump $table' >> $dmpDbFile"); + echo "$res ...".PHP_EOL; } // If another language is selected - use another settings file. $lang = PbxSettings::getValueByKey(PbxSettingsConstants::SSH_LANGUAGE); @@ -296,15 +300,17 @@ private function copyConfiguration():void $filename = $filename_lang; } // Replace the settings file. - Processes::mwExec("$cp $filename $result_db_file"); + $resCopy = Processes::mwExec("$cp $filename $result_db_file"); + echo "Copy $filename to $result_db_file: $resCopy ...".PHP_EOL; foreach ($tables as $table) { - system("$sqlite3 $result_db_file 'DROP TABLE IF EXISTS $table'"); + echo "DROP $table IF EXISTS in $result_db_file ...".PHP_EOL; + $res = shell_exec("$sqlite3 $result_db_file 'DROP TABLE IF EXISTS $table'"); + echo "$res ...".PHP_EOL; } // Restore settings from backup file. - system("$sqlite3 $result_db_file < $dmpDbFile"); + $resSaveSettings = Processes::mwExec("$sqlite3 $result_db_file < $dmpDbFile"); + echo "Save settings to $result_db_file. Result: $resSaveSettings ...".PHP_EOL; unlink($dmpDbFile); - - $umount = Util::which('umount'); Processes::mwExec("$umount /mnttmp"); } } \ No newline at end of file diff --git a/src/Core/System/Storage.php b/src/Core/System/Storage.php index 571964d78..fd39992d9 100644 --- a/src/Core/System/Storage.php +++ b/src/Core/System/Storage.php @@ -580,7 +580,7 @@ public static function selectAndConfigureStorageDisk(bool $automatic=false, bool 'filesystemtype' => 'ext4', 'name' => 'Storage №1' ]; - echo PHP_EOL ."Disk part: $dev_disk, uid: $uuid"; + echo PHP_EOL ."Disk part: $dev_disk, uid: $uuid".PHP_EOL; // Save the disk settings $storage->saveDiskSettings($data); if (file_exists('/offload/livecd')) { @@ -729,7 +729,9 @@ public function saveDiskSettings(array $data, string $id = '1'): void foreach ($data as $key => $value) { $storage_settings->writeAttribute($key, $value); } - $storage_settings->save(); + if(!$storage_settings->save()){ + echo PHP_EOL ."Fail save new storage ID in database...".PHP_EOL; + } } /** From 04c1d8bc3d26937636d0aadd902b4de1d3885c67 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Tue, 18 Jun 2024 09:27:45 +0300 Subject: [PATCH 20/58] =?UTF-8?q?#745=20=D0=A0=D0=B0=D1=81=D1=88=D0=B8?= =?UTF-8?q?=D1=80=D0=B8=D0=BB=20=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4=20=D0=B8?= =?UTF-8?q?=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D0=B8=20=D0=B2?= =?UTF-8?q?=20=D0=BA=D0=BE=D0=BD=D1=81=D0=BE=D0=BB=D1=8C=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BE=D1=82=D0=BB=D0=B0=D0=B4=D0=BA=D0=B8=20(2).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/System/PBXInstaller.php | 5 +++-- src/Core/System/Storage.php | 6 ++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Core/System/PBXInstaller.php b/src/Core/System/PBXInstaller.php index 8ba1c9db2..62a21582e 100644 --- a/src/Core/System/PBXInstaller.php +++ b/src/Core/System/PBXInstaller.php @@ -269,9 +269,10 @@ private function copyConfiguration():void echo Util::translate("Copying configuration...").PHP_EOL; Util::mwMkdir('/mnttmp'); - $confPartitionName = Storage::getDevPartName("/dev/$this->target_disk", '3'); + echo "Target disk: $this->target_disk ...".PHP_EOL; + $confPartitionName = Storage::getDevPartName($this->target_disk, '3'); // Mount the disk with settings. - $mount = Util::which('mount'); + $mount = Util::which('mount'); $umount = Util::which('umount'); $resUMount = Processes::mwExec("$umount $confPartitionName"); echo "Umount $confPartitionName: $resUMount ...".PHP_EOL; diff --git a/src/Core/System/Storage.php b/src/Core/System/Storage.php index fd39992d9..1033704c0 100644 --- a/src/Core/System/Storage.php +++ b/src/Core/System/Storage.php @@ -654,12 +654,10 @@ public static function getDevPartName(string $dev, string $part): string $grepPath = Util::which('grep'); $sortPath = Util::which('sort'); - $command = "{$lsBlkPath} -r | {$grepPath} ' part' | {$sortPath} -u | {$cutPath} -d ' ' -f 1 | {$grepPath} \"" . basename( - $dev - ) . "\" | {$grepPath} \"{$part}\$\""; + $command = "$lsBlkPath -r -p | $grepPath ' part' | $sortPath -u | $cutPath -d ' ' -f 1 | $grepPath '" . basename($dev) . "' | $grepPath \"$part\$\""; Processes::mwExec($command, $out); $devName = trim(implode('', $out)); - return '/dev/'.trim($devName); + return trim($devName); } /** From 5fa6bac638dd235a6c85fc5aff59e9229b8db95b Mon Sep 17 00:00:00 2001 From: boffart <> Date: Tue, 18 Jun 2024 12:29:16 +0300 Subject: [PATCH 21/58] =?UTF-8?q?#745=20=D0=A0=D0=B0=D1=81=D1=88=D0=B8?= =?UTF-8?q?=D1=80=D0=B8=D0=BB=20=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4=20=D0=B8?= =?UTF-8?q?=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D0=B8=20=D0=B2?= =?UTF-8?q?=20=D0=BA=D0=BE=D0=BD=D1=81=D0=BE=D0=BB=D1=8C=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BE=D1=82=D0=BB=D0=B0=D0=B4=D0=BA=D0=B8=20(3).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/System/PBXInstaller.php | 9 ++++++++- src/Core/System/Storage.php | 33 ++++++++++++++++++++------------ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/Core/System/PBXInstaller.php b/src/Core/System/PBXInstaller.php index 62a21582e..a0d153167 100644 --- a/src/Core/System/PBXInstaller.php +++ b/src/Core/System/PBXInstaller.php @@ -270,7 +270,14 @@ private function copyConfiguration():void Util::mwMkdir('/mnttmp'); echo "Target disk: $this->target_disk ...".PHP_EOL; - $confPartitionName = Storage::getDevPartName($this->target_disk, '3'); + // Touch the disk to update disk tables + $partProbePath = Util::which('partprobe'); + shell_exec($partProbePath." '/dev/$this->target_disk'"); + $confPartitionName = Storage::getDevPartName($this->target_disk, '3', true); + if(empty($confPartitionName)){ + echo "Target partition not found: $this->target_disk (part 3) ...".PHP_EOL; + return; + } // Mount the disk with settings. $mount = Util::which('mount'); $umount = Util::which('umount'); diff --git a/src/Core/System/Storage.php b/src/Core/System/Storage.php index 1033704c0..f7459e332 100644 --- a/src/Core/System/Storage.php +++ b/src/Core/System/Storage.php @@ -383,21 +383,21 @@ public function formatEntireDisk(string $device, bool $bg = false): bool // First, remove existing partitions and then create a new msdos partition table and ext4 partition // This command deletes all existing partitions and creates a new primary partition using the full disk - $command = "{$parted} --script --align optimal '{$device}' 'mklabel msdos'"; + $command = "$parted --script --align optimal '$device' 'mklabel msdos'"; Processes::mwExec($command); // Apply the command to clear the partition table // Now create a new partition that spans the entire disk - $createPartCommand = "{$parted} --script --align optimal '{$device}' 'mkpart primary ext4 0% 100%'"; + $createPartCommand = "$parted --script --align optimal '$device' 'mkpart primary ext4 0% 100%'"; $retVal = Processes::mwExec($createPartCommand); // Log the result of the create partition command - SystemMessages::sysLogMsg(__CLASS__, "{$createPartCommand} returned {$retVal}", LOG_INFO); + SystemMessages::sysLogMsg(__CLASS__, "$createPartCommand returned $retVal", LOG_INFO); sleep(2); // Wait for the system to recognize changes to the partition table // Touch the disk to update disk tables - $partprobe = Util::which('partprobe'); - Processes::mwExec("{$partprobe} '{$device}'"); + $partProbePath = Util::which('partprobe'); + Processes::mwExec("$partProbePath '$device'"); // Get the newly created partition name, assuming it's always the first partition after a fresh format $partition = self::getDevPartName($device, '1'); @@ -645,19 +645,28 @@ public static function selectAndConfigureStorageDisk(bool $automatic=false, bool * * @param string $dev The device name * @param string $part The partition number + * @param bool $verbose print verbose messages * @return string The partition name */ - public static function getDevPartName(string $dev, string $part): string + public static function getDevPartName(string $dev, string $part, bool $verbose = false): string { $lsBlkPath = Util::which('lsblk'); - $cutPath = Util::which('cut'); - $grepPath = Util::which('grep'); - $sortPath = Util::which('sort'); + $cutPath = Util::which('cut'); + $grepPath = Util::which('grep'); + $sortPath = Util::which('sort'); + // Touch the disk to update disk tables $command = "$lsBlkPath -r -p | $grepPath ' part' | $sortPath -u | $cutPath -d ' ' -f 1 | $grepPath '" . basename($dev) . "' | $grepPath \"$part\$\""; - Processes::mwExec($command, $out); - $devName = trim(implode('', $out)); - return trim($devName); + $devName = trim(shell_exec($command)); + if(empty($devName) && $verbose ){ + $verboseMsg = trim(shell_exec("$lsBlkPath -r -p")); + echo "--- filtered command ---".PHP_EOL; + echo $command.PHP_EOL; + echo "--- result 'lsblk -r -p' ---".PHP_EOL; + echo $verboseMsg.PHP_EOL; + echo "--- --- ---".PHP_EOL; + } + return $devName; } /** From bf8c33877f7f41d9ea840cd9df0a26ca8e253aeb Mon Sep 17 00:00:00 2001 From: boffart <> Date: Tue, 18 Jun 2024 13:15:42 +0300 Subject: [PATCH 22/58] =?UTF-8?q?#745=20=D0=A0=D0=B0=D1=81=D1=88=D0=B8?= =?UTF-8?q?=D1=80=D0=B8=D0=BB=20=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4=20=D0=B8?= =?UTF-8?q?=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D0=B8=20=D0=B2?= =?UTF-8?q?=20=D0=BA=D0=BE=D0=BD=D1=81=D0=BE=D0=BB=D1=8C=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BE=D1=82=D0=BB=D0=B0=D0=B4=D0=BA=D0=B8=20(4).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/System/PBXInstaller.php | 3 --- src/Core/System/Storage.php | 16 +++++++++++----- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/Core/System/PBXInstaller.php b/src/Core/System/PBXInstaller.php index a0d153167..a2a083b4b 100644 --- a/src/Core/System/PBXInstaller.php +++ b/src/Core/System/PBXInstaller.php @@ -270,9 +270,6 @@ private function copyConfiguration():void Util::mwMkdir('/mnttmp'); echo "Target disk: $this->target_disk ...".PHP_EOL; - // Touch the disk to update disk tables - $partProbePath = Util::which('partprobe'); - shell_exec($partProbePath." '/dev/$this->target_disk'"); $confPartitionName = Storage::getDevPartName($this->target_disk, '3', true); if(empty($confPartitionName)){ echo "Target partition not found: $this->target_disk (part 3) ...".PHP_EOL; diff --git a/src/Core/System/Storage.php b/src/Core/System/Storage.php index f7459e332..572612213 100644 --- a/src/Core/System/Storage.php +++ b/src/Core/System/Storage.php @@ -395,10 +395,6 @@ public function formatEntireDisk(string $device, bool $bg = false): bool sleep(2); // Wait for the system to recognize changes to the partition table - // Touch the disk to update disk tables - $partProbePath = Util::which('partprobe'); - Processes::mwExec("$partProbePath '$device'"); - // Get the newly created partition name, assuming it's always the first partition after a fresh format $partition = self::getDevPartName($device, '1'); @@ -655,8 +651,18 @@ public static function getDevPartName(string $dev, string $part, bool $verbose = $grepPath = Util::which('grep'); $sortPath = Util::which('sort'); + $basenameDisk = basename($dev); + $pathToDisk = trim(shell_exec("$lsBlkPath -n -p -a -r -o NAME,TYPE | $grepPath disk | $grepPath '$basenameDisk' | $cutPath -d ' ' -f 1")); + if($verbose) { + echo "Get dev full path...".PHP_EOL; + echo "Source dev: $dev, result full path: $pathToDisk".PHP_EOL; + } + // Touch the disk to update disk tables + $partProbePath = Util::which('partprobe'); + shell_exec($partProbePath." '$pathToDisk'"); + // Touch the disk to update disk tables - $command = "$lsBlkPath -r -p | $grepPath ' part' | $sortPath -u | $cutPath -d ' ' -f 1 | $grepPath '" . basename($dev) . "' | $grepPath \"$part\$\""; + $command = "$lsBlkPath -r -p | $grepPath ' part' | $sortPath -u | $cutPath -d ' ' -f 1 | $grepPath '" . $pathToDisk . "' | $grepPath \"$part\$\""; $devName = trim(shell_exec($command)); if(empty($devName) && $verbose ){ $verboseMsg = trim(shell_exec("$lsBlkPath -r -p")); From faaae0c0e46aaedc83b98f0b7556684fc9dc8290 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Wed, 19 Jun 2024 14:52:30 +0300 Subject: [PATCH 23/58] =?UTF-8?q?#698=20=D0=9F=D0=BE=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D0=BB=20=D1=84=D0=BE=D1=80=D0=BC=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20dialplan?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/Asterisk/AsteriskManager.php | 3 +- .../Configs/ExtensionsOutWorkTimeConf.php | 116 +++++++++--------- 2 files changed, 57 insertions(+), 62 deletions(-) diff --git a/src/Core/Asterisk/AsteriskManager.php b/src/Core/Asterisk/AsteriskManager.php index a0a809f51..efac60a40 100644 --- a/src/Core/Asterisk/AsteriskManager.php +++ b/src/Core/Asterisk/AsteriskManager.php @@ -619,8 +619,7 @@ public function connect($server = null, $username = null, $secret = null, $event $netStatPath = Util::which('netstat'); $busyBoxPath = Util::which('busybox'); - $address = str_replace('127.0.0.1:', '0.0.0.0:', $server); - $chkCommand = "$netStatPath -ntap | $busyBoxPath grep '$address ' | $busyBoxPath grep LISTEN | $busyBoxPath grep asterisk"; + $chkCommand = "$netStatPath -ntap | $busyBoxPath grep '0.0.0.0:$this->port ' | $busyBoxPath grep LISTEN | $busyBoxPath grep asterisk"; if(Processes::mwExec($chkCommand) === 1){ SystemMessages::sysLogMsg('AMI', "Exceptions, Unable to connect to $server: the asterisk process is not running", LOG_ERR); return false; diff --git a/src/Core/Asterisk/Configs/ExtensionsOutWorkTimeConf.php b/src/Core/Asterisk/Configs/ExtensionsOutWorkTimeConf.php index a6e83265b..ebd7910a1 100644 --- a/src/Core/Asterisk/Configs/ExtensionsOutWorkTimeConf.php +++ b/src/Core/Asterisk/Configs/ExtensionsOutWorkTimeConf.php @@ -28,6 +28,7 @@ use MikoPBX\Common\Models\SoundFiles; use MikoPBX\Core\System\Processes; use MikoPBX\Core\System\Util; +use DateTime; /** * Class ExtensionsOutWorkTimeConf @@ -152,13 +153,8 @@ private function generateOutWorkTimes(): void foreach ($data as $ruleData) { $contextId = 'check-out-work-time-'.$ruleData['id']; $this->conf .= 'same => n,Gosub('.$contextId.',${EXTEN},1)'.PHP_EOL."\t"; - [, $years] = $this->getOutWorkIntervals($ruleData['date_from'], $ruleData['date_to']); $additionalContexts.= '['.$contextId.']'.PHP_EOL; $additionalContexts.= 'exten => _[0-9*#+a-zA-Z]!,1,NoOp()'.PHP_EOL."\t"; - if(!empty($years)){ - $additionalContexts.= 'same => n,Set(TMP_YEARS='.implode('-',$years).'-)'.PHP_EOL."\t"; - $additionalContexts.= 'same => n,ExecIf($["STRREPLACE(TMP_YEARS,currentYear)" == "${TMP_YEARS}"]?return)'.PHP_EOL."\t"; - } // Restrictions for the route are not allowed for this rule. if ($ruleData['allowRestriction'] === '1') { $additionalContexts.= 'same => n,ExecIf($["${DIALPLAN_EXISTS('.$contextId.'-${contextID},${EXTEN},1)}" == "0"]?return)'.PHP_EOL."\t"; @@ -232,75 +228,75 @@ private function getRoutesData(): array } /** - * Get the out-of-work intervals based on the provided date range. + * Generate the out-of-work rule based on the provided data. * - * @param int $date_from The starting date. - * @param int $date_to The ending date. + * @param array $srcOutData The data for the out-of-work rule. + * @param string &$conf_out_set_var The output string for the SET variables. + * @param string &$conf The output string for the configuration. * - * @return array An array of intervals. + * @return void */ - private function getOutWorkIntervals($date_from, $date_to): array + private function generateOutWorkRule(array $srcOutData, string &$conf_out_set_var, string &$conf): void { - $years = []; - $year_from = 1 * date('Y', (int)$date_from); - $year_to = 1 * date('Y', (int)$date_to); - - $intervals = []; - $Year = $year_from; - if ($year_to === $year_from) { - if(!empty($date_from)){ - $years[] = $Year; + $intervals = $this->splitIntoMonthlyIntervals($srcOutData['date_from'], $srcOutData['date_to']); + if(empty($intervals)){ + $timesArray = $this->getTimesInterval($srcOutData); + $weekdays = $this->getWeekDayInterval($srcOutData); + [$mDays, $months] = $this->initDaysMonthsInterval($srcOutData); + $appdata = $this->initRuleAppData($srcOutData, $conf_out_set_var); + foreach ($timesArray as $times) { + $conf .= "same => n,GotoIfTime($times,$weekdays,$mDays,$months?{$appdata})\n\t"; } - $intervals[] = [ - 'date_from' => $date_from, - 'date_to' => $date_to - ]; - return [$intervals, $years]; - } - while ($Year <= $year_to) { + }else{ + foreach ($intervals as $interval){ + [$srcOutData['date_from'],$srcOutData['date_to']] = $interval; - $years[] = $Year; - if ($Year === $year_from) { - $intervals[] = [ - 'date_from' => $date_from, - 'date_to' => (string)strtotime('31-12-' . $Year) - ]; - } elseif ($Year === $year_to) { - $intervals[] = [ - 'date_from' => (string)strtotime('01-01-' . $Year), - 'date_to' => $date_to - ]; - } else { - $intervals[] = [ - 'date_from' => (string)strtotime('01-01-' . $Year), - 'date_to' => (string)strtotime('31-12-' . $Year) - ]; + $timesArray = $this->getTimesInterval($srcOutData); + $weekdays = $this->getWeekDayInterval($srcOutData); + + [$mDays, $months] = $this->initDaysMonthsInterval($srcOutData); + $appdata = $this->initRuleAppData($srcOutData, $conf_out_set_var); + + $year = 1 * date('Y', $srcOutData['date_from']); + foreach ($timesArray as $times) { + $timeAppData = "GotoIfTime($times,$weekdays,$mDays,$months?{$appdata})"; + $conf .= 'same => n,ExecIf($["${currentYear}" == "'.$year.'"]?'.$timeAppData.')'."\n\t"; + } } - $Year++; } - return [$intervals, $years]; } /** - * Generate the out-of-work rule based on the provided data. - * - * @param array $out_data The data for the out-of-work rule. - * @param string &$conf_out_set_var The output string for the SET variables. - * @param string &$conf The output string for the configuration. - * - * @return void + * Get intervals from timestamp + * @param $date_from + * @param $date_to + * @return array */ - private function generateOutWorkRule(array $out_data, string &$conf_out_set_var, string &$conf): void + private function splitIntoMonthlyIntervals($date_from, $date_to):array { - $timesArray = $this->getTimesInterval($out_data); - $weekdays = $this->getWeekDayInterval($out_data); - - [$mDays, $months] = $this->initDaysMonthsInterval($out_data); - $appdata = $this->initRuleAppData($out_data, $conf_out_set_var); - - foreach ($timesArray as $times) { - $conf .= "same => n,GotoIfTime($times,$weekdays,$mDays,$months?{$appdata})\n\t"; + if(empty($date_from) || empty($date_to)){ + return []; + } + $intervals = []; + $start = new DateTime(); + $start->setTimestamp($date_from); + $end = new DateTime(); + $end->setTimestamp($date_to); + while ($start < $end) { + $interval_start = clone $start; + $interval_end = clone $start; + $interval_end->modify('last day of this month 23:59:59'); + if ($interval_end > $end) { + $interval_end = $end; + } + $intervals[] = [ + $interval_start->getTimestamp(), + $interval_end->getTimestamp() + ]; + $start->modify('first day of next month 00:00:00'); } + + return $intervals; } /** From 0205901f4c4dbd3b6418e4e7035ece3578a0facf Mon Sep 17 00:00:00 2001 From: boffart <> Date: Thu, 20 Jun 2024 22:23:29 +0300 Subject: [PATCH 24/58] =?UTF-8?q?=D0=A3=D0=B2=D0=B5=D0=BB=D0=B8=D1=81?= =?UTF-8?q?=D0=B8=D0=BB=20=D1=82=D0=B0=D0=B9=D0=BC=D0=B0=D1=83=D1=82=20?= =?UTF-8?q?=D0=BE=D0=B6=D0=B8=D0=B4=D0=B0=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Common/Providers/CDRDatabaseProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Common/Providers/CDRDatabaseProvider.php b/src/Common/Providers/CDRDatabaseProvider.php index 15a1b0a4e..2c13cf61c 100644 --- a/src/Common/Providers/CDRDatabaseProvider.php +++ b/src/Common/Providers/CDRDatabaseProvider.php @@ -77,7 +77,7 @@ public static function getCdr(array $filter = []): array $client = new BeanstalkClient(WorkerCdr::SELECT_CDR_TUBE); $filename = ''; try { - list($result, $message) = $client->sendRequest(json_encode($filter), 2); + list($result, $message) = $client->sendRequest(json_encode($filter), 15); if ($result!==false){ $filename = json_decode($message, true, 512, JSON_THROW_ON_ERROR); } From 6f8a0b33405f2fc0bb102f51fb88d635dad0bcff Mon Sep 17 00:00:00 2001 From: boffart <> Date: Fri, 21 Jun 2024 13:38:35 +0300 Subject: [PATCH 25/58] =?UTF-8?q?#756=20=D0=92=D1=8B=D0=BD=D0=B5=D1=81=20?= =?UTF-8?q?=D0=BB=D0=BE=D0=B3=20crond=20=D0=B2=20=D0=BE=D1=82=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D1=8C=D0=BD=D1=8B=D0=B9=20=D1=84=D0=B0=D0=B9=D0=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/System/Configs/CronConf.php | 26 +++++++++++++++++++------- src/Core/System/Configs/RedisConf.php | 7 +++++++ src/Core/System/Configs/SyslogConf.php | 4 ++++ 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/Core/System/Configs/CronConf.php b/src/Core/System/Configs/CronConf.php index d2740b26b..18afd4690 100644 --- a/src/Core/System/Configs/CronConf.php +++ b/src/Core/System/Configs/CronConf.php @@ -29,8 +29,6 @@ use MikoPBX\Modules\Config\SystemConfigInterface; use Phalcon\Di\Injectable; -use function MikoPBX\Common\Config\appPath; - /** * Class CronConf * @@ -63,14 +61,13 @@ public function reStart(): int $this->generateConfig($booting); if (Util::isSystemctl()) { $systemctl = Util::which('systemctl'); - Processes::mwExec("{$systemctl} restart ".self::PROC_NAME); + Processes::mwExec("$systemctl restart ".self::PROC_NAME); } else { // T2SDE or Docker - $crond = Util::which(self::PROC_NAME); + $cronPath = Util::which(self::PROC_NAME); Processes::killByName(self::PROC_NAME); - Processes::mwExec("$crond -L /dev/null -l 8"); + Processes::mwExec("$cronPath -S -l 0"); } - return 0; } @@ -86,7 +83,7 @@ private function generateConfig(bool $boot = true): void $workerSafeScriptsPath = Util::getFilePathByClassName(WorkerSafeScriptsCore::class); $phpPath = Util::which('php'); - $WorkerSafeScripts = "$phpPath -f {$workerSafeScriptsPath} start > /dev/null 2> /dev/null"; + $WorkerSafeScripts = "$phpPath -f $workerSafeScriptsPath start > /dev/null 2> /dev/null"; $restart_night = $this->mikoPBXConfig->getGeneralSettings(PbxSettingsConstants::RESTART_EVERY_NIGHT); $asterisk = Util::which('asterisk'); @@ -130,4 +127,19 @@ private function generateConfig(bool $boot = true): void // Write the generated config to the cron file Util::fileWriteContent($cron_filename, $conf); } + + /** + * Generate additional syslog rules. + * @return void + */ + public static function generateSyslogConf():void + { + Util::mwMkdir('/etc/rsyslog.d'); + $log_fileRedis = SyslogConf::getSyslogFile(self::PROC_NAME); + $pathScriptRedis = SyslogConf::createRotateScript(self::PROC_NAME); + $confSyslogD = '$outchannel log_'.self::PROC_NAME.','.$log_fileRedis.',10485760,'.$pathScriptRedis.PHP_EOL. + 'if $programname == "'.self::PROC_NAME.'" then :omfile:$log_'.self::PROC_NAME.PHP_EOL. + 'if $programname == "'.self::PROC_NAME.'" then stop'.PHP_EOL; + file_put_contents('/etc/rsyslog.d/'.self::PROC_NAME.'.conf', $confSyslogD); + } } \ No newline at end of file diff --git a/src/Core/System/Configs/RedisConf.php b/src/Core/System/Configs/RedisConf.php index 2b64aeae9..dc061c04a 100644 --- a/src/Core/System/Configs/RedisConf.php +++ b/src/Core/System/Configs/RedisConf.php @@ -87,7 +87,14 @@ private function configure(): void $conf .= "syslog-enabled yes" . PHP_EOL; $conf .= "syslog-ident redis" . PHP_EOL; file_put_contents(self::CONF_FILE, $conf); + } + /** + * Generate additional syslog rules. + * @return void + */ + public static function generateSyslogConf():void + { Util::mwMkdir('/etc/rsyslog.d'); $log_fileRedis = SyslogConf::getSyslogFile('redis'); $pathScriptRedis = SyslogConf::createRotateScript('redis'); diff --git a/src/Core/System/Configs/SyslogConf.php b/src/Core/System/Configs/SyslogConf.php index fcf103b3d..d050e33c1 100644 --- a/src/Core/System/Configs/SyslogConf.php +++ b/src/Core/System/Configs/SyslogConf.php @@ -56,6 +56,10 @@ public function reStart(): void } Processes::killByName('syslogd'); } + + RedisConf::generateSyslogConf(); + CronConf::generateSyslogConf(); + Processes::safeStartDaemon(self::PROC_NAME, '-n'); } From fc46da0f25ef48e0c7a18deb5a7439dc13d156c7 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Fri, 21 Jun 2024 15:11:46 +0300 Subject: [PATCH 26/58] =?UTF-8?q?#725=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D1=8C=20=D0=BA=D0=B0=D1=81=D1=82=D0=BE=D0=BC=D0=B8?= =?UTF-8?q?=D0=B7=D0=B0=D1=86=D0=B8=D0=B8=20=D0=BA=D0=BE=D0=BD=D1=84=D0=B5?= =?UTF-8?q?=D1=80=D0=B5=D0=BD=D1=86=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/Asterisk/Configs/ConferenceConf.php | 4 ++-- src/Core/System/PBX.php | 12 ++++++++++++ .../Actions/ReloadConferenceAction.php | 19 +++++++++++++++++++ .../WorkerModelsEvents/ProcessCustomFiles.php | 8 ++++++++ src/Core/Workers/WorkerModelsEvents.php | 2 ++ 5 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 src/Core/Workers/Libs/WorkerModelsEvents/Actions/ReloadConferenceAction.php diff --git a/src/Core/Asterisk/Configs/ConferenceConf.php b/src/Core/Asterisk/Configs/ConferenceConf.php index 285803136..cb768c0cf 100644 --- a/src/Core/Asterisk/Configs/ConferenceConf.php +++ b/src/Core/Asterisk/Configs/ConferenceConf.php @@ -20,6 +20,7 @@ namespace MikoPBX\Core\Asterisk\Configs; use MikoPBX\Common\Models\ConferenceRooms; +use MikoPBX\Core\System\Util; /** * Generates the configuration content for confbridge.conf. @@ -39,9 +40,8 @@ class ConferenceConf extends AsteriskConfigClass protected function generateConfigProtected(): void { $conf = ""; - // Write the configuration content to the file - file_put_contents($this->config->path('asterisk.astetcdir') . '/confbridge.conf', $conf); + Util::fileWriteContent($this->config->path('asterisk.astetcdir') . '/confbridge.conf', $conf); } /** diff --git a/src/Core/System/PBX.php b/src/Core/System/PBX.php index 263e8a30e..8f12b3472 100644 --- a/src/Core/System/PBX.php +++ b/src/Core/System/PBX.php @@ -30,6 +30,7 @@ AsteriskConf, AsteriskConfigClass, AsteriskConfigInterface, + ConferenceConf, ExtensionsConf, FeaturesConf, HttpConf, @@ -206,6 +207,17 @@ public static function musicOnHoldReload(): void Processes::mwExec("{$asteriskPath} -rx 'moh reload'"); } + /** + * Reloads the Asterisk music on hold module. + */ + public static function confBridgeReload(): void + { + $o = new ConferenceConf(); + $o->generateConfig(); + $asteriskPath = Util::which('asterisk'); + Processes::mwExec("$asteriskPath -rx 'module reload app_confbridge'"); + } + /** * Reloads the Asterisk voicemail module. diff --git a/src/Core/Workers/Libs/WorkerModelsEvents/Actions/ReloadConferenceAction.php b/src/Core/Workers/Libs/WorkerModelsEvents/Actions/ReloadConferenceAction.php new file mode 100644 index 000000000..c71a43576 --- /dev/null +++ b/src/Core/Workers/Libs/WorkerModelsEvents/Actions/ReloadConferenceAction.php @@ -0,0 +1,19 @@ + '/etc/asterisk/confbridge.conf', + 'actions' => [ + ReloadConferenceAction::class + ], + ]; + $tables[] = [ 'filePath' => '/etc/asterisk/modules.conf', 'actions' => [ diff --git a/src/Core/Workers/WorkerModelsEvents.php b/src/Core/Workers/WorkerModelsEvents.php index 94c4d3f00..bbb74a1fe 100644 --- a/src/Core/Workers/WorkerModelsEvents.php +++ b/src/Core/Workers/WorkerModelsEvents.php @@ -30,6 +30,7 @@ use MikoPBX\Core\System\{BeanstalkClient, SystemMessages}; use MikoPBX\Core\Workers\Libs\WorkerModelsEvents\Actions\ReloadCloudDescriptionAction; use MikoPBX\Core\Workers\Libs\WorkerModelsEvents\Actions\ReloadCloudParametersAction; +use MikoPBX\Core\Workers\Libs\WorkerModelsEvents\Actions\ReloadConferenceAction; use MikoPBX\Core\Workers\Libs\WorkerModelsEvents\Actions\ReloadCrondAction; use MikoPBX\Core\Workers\Libs\WorkerModelsEvents\Actions\ReloadDialplanAction; use MikoPBX\Core\Workers\Libs\WorkerModelsEvents\Actions\ReloadFail2BanConfAction; @@ -200,6 +201,7 @@ private function getReloadActionsWithPriority(): array ReloadDialplanAction::class, ReloadParkingAction::class, ReloadQueuesAction::class, + ReloadConferenceAction::class, ReloadManagerAction::class, ReloadVoicemailAction::class, ReloadMOHAction::class, From a4d80bfec3df87dab7777f4d092b5035b208b425 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Tue, 25 Jun 2024 09:56:04 +0300 Subject: [PATCH 27/58] =?UTF-8?q?#761=20=D0=98=D1=81=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D0=BB=20=D0=BE=D1=88=D0=B8=D0=BA=D0=B8=20=D1=84?= =?UTF-8?q?=D0=BE=D1=80=D0=BC=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=BA=D0=BE=D0=BD=D1=84=D0=B8=D0=B3=D1=83=D1=80=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D0=BE=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE=20=D1=84=D0=B0?= =?UTF-8?q?=D0=B9=D0=BB=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/System/Configs/Fail2BanConf.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Core/System/Configs/Fail2BanConf.php b/src/Core/System/Configs/Fail2BanConf.php index bab46fa3a..96d6be925 100644 --- a/src/Core/System/Configs/Fail2BanConf.php +++ b/src/Core/System/Configs/Fail2BanConf.php @@ -24,8 +24,8 @@ use MikoPBX\Common\Models\PbxSettings; use MikoPBX\Common\Models\PbxSettingsConstants; use MikoPBX\Common\Providers\PBXConfModulesProvider; +use MikoPBX\Core\System\Directories; use MikoPBX\Core\System\Processes; -use MikoPBX\Core\System\System; use MikoPBX\Core\System\Util; use MikoPBX\Core\System\Verify; use MikoPBX\Modules\Config\SystemConfigInterface; @@ -138,14 +138,14 @@ public static function reloadFail2ban(): void */ private function generateConf():void { - $log_dir = System::getLogDir() . '/fail2ban'; + $log_dir = Directories::getDir(Directories::CORE_LOGS_DIR) . '/fail2ban'; $lofFileName = "$log_dir/fail2ban.log"; Util::mwMkdir($log_dir); $conf = '['.'Definition'.']'.PHP_EOL. 'allowipv6 = auto'.PHP_EOL. 'loglevel = INFO'.PHP_EOL. - 'logtarget = FILE'.PHP_EOL. - "syslogsocket = $lofFileName".PHP_EOL. + "logtarget = $lofFileName".PHP_EOL. + 'syslogsocket = auto'.PHP_EOL. 'socket = /var/run/fail2ban/fail2ban.sock'.PHP_EOL. 'pidfile = /var/run/fail2ban/fail2ban.pid'.PHP_EOL. 'dbfile = /var/lib/fail2ban/fail2ban.sqlite3'.PHP_EOL. @@ -168,7 +168,7 @@ public static function logRotate(): void return; } $max_size = 10; - $log_dir = System::getLogDir() . '/fail2ban/'; + $log_dir = Directories::getDir(Directories::CORE_LOGS_DIR) . '/fail2ban/'; $text_config = $log_dir."fail2ban.log { nocreate nocopytruncate @@ -331,7 +331,7 @@ public function writeConfig(): void "logpath = $syslog_file\n" . "action = $action\n\n"; } - $log_dir = System::getLogDir() . '/asterisk/'; + $log_dir = Directories::getDir(Directories::CORE_LOGS_DIR) . '/asterisk/'; $jails = [ 'asterisk_security_log' => ['security_log', '', $asteriskPorts], 'asterisk_error' => ['error', '_ERROR', $asteriskPorts], @@ -343,7 +343,7 @@ public function writeConfig(): void $commonParams. "filter = asterisk-main" . PHP_EOL. 'action = miko-iptables-multiport-all[name=ASTERISK'.$actionNamePrefix.', port="'.implode(',', $ports).'"]'. PHP_EOL. - "logpath = {$log_dir}$logPrefix". PHP_EOL. PHP_EOL; + "logpath = $log_dir$logPrefix". PHP_EOL. PHP_EOL; } // Write the Fail2Ban configuration to the jail.local file Util::fileWriteContent('/etc/fail2ban/jail.local', $config); From 1d766b7b016fc39d0ea93449475ef2b0b1fc2293 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Wed, 26 Jun 2024 09:24:53 +0300 Subject: [PATCH 28/58] =?UTF-8?q?#736=20=D0=BF=D0=BE=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D0=BB=20=D1=82=D0=B8=D0=BF=20=D1=81=D0=BE=D0=B7?= =?UTF-8?q?=D0=B4=D0=B0=D0=B2=D0=B0=D0=B5=D0=BC=D0=BE=D0=B3=D0=BE=20=D1=80?= =?UTF-8?q?=D0=B0=D0=B7=D0=B4=D0=B5=D0=BB=D0=B0=20storage=20=D0=BD=D0=B0?= =?UTF-8?q?=20GPT.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/System/Storage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/System/Storage.php b/src/Core/System/Storage.php index 572612213..1fe90b50a 100644 --- a/src/Core/System/Storage.php +++ b/src/Core/System/Storage.php @@ -383,7 +383,7 @@ public function formatEntireDisk(string $device, bool $bg = false): bool // First, remove existing partitions and then create a new msdos partition table and ext4 partition // This command deletes all existing partitions and creates a new primary partition using the full disk - $command = "$parted --script --align optimal '$device' 'mklabel msdos'"; + $command = "$parted --script --align optimal '$device' 'mklabel gpt'"; Processes::mwExec($command); // Apply the command to clear the partition table // Now create a new partition that spans the entire disk From 553a25f035b9a3335f2414e38b45e8302b5aeaae Mon Sep 17 00:00:00 2001 From: boffart <> Date: Wed, 26 Jun 2024 10:02:34 +0300 Subject: [PATCH 29/58] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BE=D1=84=D0=BE=D1=80=D0=BC=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=BA=D0=BE=D0=B4=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/System/Storage.php | 188 ++++++++++++++++++------------------ 1 file changed, 93 insertions(+), 95 deletions(-) diff --git a/src/Core/System/Storage.php b/src/Core/System/Storage.php index 1fe90b50a..61c3b663e 100644 --- a/src/Core/System/Storage.php +++ b/src/Core/System/Storage.php @@ -111,7 +111,7 @@ public static function isStorageDiskMounted(string $filter = '', string &$mount_ } if ('' === $filter) { $varEtcDir = Directories::getDir(Directories::CORE_VAR_ETC_DIR); - $filename = "{$varEtcDir}/storage_device"; + $filename = "$varEtcDir/storage_device"; // If the storage_device file exists, read its contents as the filter, otherwise use 'usbdisk1' as the filter if (file_exists($filename)) { @@ -127,7 +127,7 @@ public static function isStorageDiskMounted(string $filter = '', string &$mount_ $filter = escapeshellarg($filter); // Execute the command to filter the mount points based on the filter - $out = shell_exec("$mount | $grep $filter | {$awk} '{print $3}'"); + $out = shell_exec("$mount | $grep $filter | $awk '{print $3}'"); $mount_dir = trim($out); return ($mount_dir !== ''); } @@ -194,7 +194,7 @@ public static function mountSftpDisk(string $host, string $port, string $user, s $sshfsPath = Util::which('sshfs'); // Build the command to mount the SFTP disk - $command = "{$timeoutPath} 3 {$sshfsPath} -p {$port} -o nonempty -o password_stdin -o 'StrictHostKeyChecking=no' " . "{$user}@{$host}:{$remote_dir} {$local_dir} << EOF\n" . "{$pass}\n" . "EOF\n"; + $command = "$timeoutPath 3 $sshfsPath -p $port -o nonempty -o password_stdin -o 'StrictHostKeyChecking=no' " . "$user@$host:$remote_dir $local_dir << EOF\n" . "$pass\n" . "EOF\n"; // Execute the command to mount the SFTP disk Processes::mwExec($command, $out); @@ -231,7 +231,7 @@ public static function mountFtp(string $host, string $port, string $user, string if (!empty($user)) { $auth_line .= 'user="' . $user; if (!empty($pass)) { - $auth_line .= ":{$pass}"; + $auth_line .= ":$pass"; } $auth_line .= '",'; } @@ -239,17 +239,17 @@ public static function mountFtp(string $host, string $port, string $user, string // Build the connect line for the FTP connection $connect_line = 'ftp://' . $host; if (!empty($port)) { - $connect_line .= ":{$port}"; + $connect_line .= ":$port"; } if (!empty($remote_dir)) { - $connect_line .= "$remote_dir"; + $connect_line .= $remote_dir; } $timeoutPath = Util::which('timeout'); $curlftpfsPath = Util::which('curlftpfs'); // Build the command to mount the FTP disk - $command = "{$timeoutPath} 3 {$curlftpfsPath} -o allow_other -o {$auth_line}fsname={$host} {$connect_line} {$local_dir}"; + $command = "$timeoutPath 3 $curlftpfsPath -o allow_other -o {$auth_line}fsname=$host $connect_line $local_dir"; // Execute the command to mount the FTP disk Processes::mwExec($command, $out); @@ -295,13 +295,13 @@ public static function mountWebDav(string $host, string $user, string $pass, str // Write WebDAV credentials to secrets file - file_put_contents('/etc/davfs2/secrets', "{$host}{$dstDir} $user $pass"); + file_put_contents('/etc/davfs2/secrets', "$host$dstDir $user $pass"); file_put_contents('/etc/davfs2/davfs2.conf', $conf); $timeoutPath = Util::which('timeout'); $mount = Util::which('mount.davfs'); // Build the command to mount the WebDAV disk - $command = "$timeoutPath 3 yes | $mount {$host}{$dstDir} {$local_dir}"; + $command = "$timeoutPath 3 yes | $mount $host$dstDir $local_dir"; // Execute the command to mount the WebDAV disk Processes::mwExec($command, $out); @@ -319,10 +319,10 @@ public static function mountWebDav(string $host, string $user, string $pass, str * @param string $dev The device path of the disk. * @return bool Returns true if the file system creation process is initiated, false otherwise. */ - public static function mkfs_disk(string $dev) + public static function mkfs_disk(string $dev):bool { if (!file_exists($dev)) { - $dev = "/dev/{$dev}"; + $dev = "/dev/$dev"; } if (!file_exists($dev)) { return false; @@ -332,7 +332,7 @@ public static function mkfs_disk(string $dev) // If the disk is not mounted or successfully unmounted, proceed with the file system creation if (empty($dir) || self::umountDisk($dir)) { - $st = new Storage(); + $st = new self(); // Initiate the file system creation process $st->formatEntireDisk($dev, true); sleep(1); @@ -358,13 +358,13 @@ public static function umountDisk(string $dir): bool // If the disk is mounted, terminate processes using the disk and unmount it if (self::isStorageDiskMounted($dir)) { Processes::mwExec("/sbin/shell_functions.sh 'killprocesses' '$dir' -TERM 0"); - Processes::mwExec("{$umount} {$dir}"); + Processes::mwExec("$umount $dir"); } $result = !self::isStorageDiskMounted($dir); // If the disk is successfully unmounted and the directory exists, remove the directory if ($result && file_exists($dir)) { - Processes::mwExec("{$rm} -rf '{$dir}'"); + Processes::mwExec("$rm -rf '$dir'"); } return $result; @@ -393,8 +393,6 @@ public function formatEntireDisk(string $device, bool $bg = false): bool // Log the result of the create partition command SystemMessages::sysLogMsg(__CLASS__, "$createPartCommand returned $retVal", LOG_INFO); - sleep(2); // Wait for the system to recognize changes to the partition table - // Get the newly created partition name, assuming it's always the first partition after a fresh format $partition = self::getDevPartName($device, '1'); @@ -411,11 +409,11 @@ public function formatEntireDisk(string $device, bool $bg = false): bool public function formatPartition(string $partition, bool $bg = false): bool { $mkfs = Util::which("mkfs.ext4"); - $cmd = "{$mkfs} {$partition}"; + $cmd = "$mkfs $partition"; if ($bg === false) { // Execute the mkfs command and check the return value - $retVal = Processes::mwExec("{$cmd} 2>&1"); - SystemMessages::sysLogMsg(__CLASS__, "{$cmd} returned {$retVal}"); + $retVal = Processes::mwExec("$cmd 2>&1"); + SystemMessages::sysLogMsg(__CLASS__, "$cmd returned $retVal"); $result = ($retVal === 0); } else { usleep(200000); @@ -436,14 +434,14 @@ public function formatPartition(string $partition, bool $bg = false): bool public static function statusMkfs(string $dev): string { if (!file_exists($dev)) { - $dev = "/dev/{$dev}"; + $dev = "/dev/$dev"; } $out = []; $psPath = Util::which('ps'); $grepPath = Util::which('grep'); // Execute the command to check the status of mkfs process - Processes::mwExec("{$psPath} -A -f | {$grepPath} {$dev} | {$grepPath} mkfs | {$grepPath} -v grep", $out); + Processes::mwExec("$psPath -A -f | $grepPath $dev | $grepPath mkfs | $grepPath -v grep", $out); $mount_dir = trim(implode('', $out)); return empty($mount_dir) ? 'ended' : 'inprogress'; @@ -562,10 +560,10 @@ public static function selectAndConfigureStorageDisk(bool $automatic=false, bool $storage->formatEntireDisk($dev_disk); } elseif($part === '4' && $forceFormatStorage) { echo PHP_EOL . Util::translate('Formatting storage partition 4 on disk').': '.$dev_disk.'...'.PHP_EOL; - passthru("exec /dev/console 2>/dev/console; /sbin/initial_storage_part_four create {$dev_disk}"); + passthru("exec /dev/console 2>/dev/console; /sbin/initial_storage_part_four create $dev_disk"); } elseif($part === '4') { echo PHP_EOL . Util::translate('Update storage partition 4 on disk').': '.$dev_disk.'...'.PHP_EOL; - passthru("exec /dev/console 2>/dev/console; /sbin/initial_storage_part_four update {$dev_disk}"); + passthru("exec /dev/console 2>/dev/console; /sbin/initial_storage_part_four update $dev_disk"); } $partitionName = self::getDevPartName($target_disk_storage, $part); $uuid = self::getUuid($partitionName); @@ -693,8 +691,8 @@ public static function isStorageDisk(string $device): bool Util::mwMkdir($tmp_dir); $out = []; + $uid_part = 'UUID=' . self::getUuid($device); $storage = new self(); - $uid_part = 'UUID=' . $storage->getUuid($device) . ''; $format = $storage->getFsType($device); // If the file system type is not available, return false if ($format === '') { @@ -704,8 +702,8 @@ public static function isStorageDisk(string $device): bool $umount = Util::which('umount'); $rm = Util::which('rm'); - Processes::mwExec("{$mount} -t {$format} {$uid_part} {$tmp_dir}", $out); - if (is_dir("{$tmp_dir}/mikopbx") && trim(implode('', $out)) === '') { + Processes::mwExec("$mount -t $format $uid_part $tmp_dir", $out); + if (is_dir("$tmp_dir/mikopbx") && trim(implode('', $out)) === '') { // $out - empty string, no errors // mikopbx directory exists $result = true; @@ -713,12 +711,12 @@ public static function isStorageDisk(string $device): bool // Check if the storage disk is mounted, and unmount if necessary if (self::isStorageDiskMounted($device)) { - Processes::mwExec("{$umount} {$device}"); + Processes::mwExec("$umount $device"); } // Check if the storage disk is unmounted, and remove the temporary directory if (!self::isStorageDiskMounted($device)) { - Processes::mwExec("{$rm} -rf '{$tmp_dir}'"); + Processes::mwExec("$rm -rf '$tmp_dir'"); } return $result; @@ -775,8 +773,8 @@ public function getDiskSettings(string $id = ''): array */ public function configure(): void { - $varEtcDir = $this->config->path('core.varEtcDir'); - $storage_dev_file = "{$varEtcDir}/storage_device"; + $varEtcDir = $this->config->path(Directories::CORE_VAR_ETC_DIR); + $storage_dev_file = "$varEtcDir/storage_device"; if (!Util::isT2SdeLinux()) { // Configure for non-T2Sde Linux file_put_contents($storage_dev_file, "/storage/usbdisk1"); @@ -822,11 +820,11 @@ public function configure(): void // Check if the file system type matches the expected type if ($formatFs !== $disk['filesystemtype'] && !($formatFs === 'ext4' && $disk['filesystemtype'] === 'ext2')) { - SystemMessages::sysLogMsg(__METHOD__, "The file system type has changed {$disk['filesystemtype']} -> {$formatFs}. The disk will not be connected."); + SystemMessages::sysLogMsg(__METHOD__, "The file system type has changed {$disk['filesystemtype']} -> $formatFs. The disk will not be connected."); continue; } - $str_uid = 'UUID=' . $this->getUuid($dev); - $conf .= "{$str_uid} /storage/usbdisk{$disk['id']} {$formatFs} async,rw 0 0\n"; + $str_uid = 'UUID=' . self::getUuid($dev); + $conf .= "$str_uid /storage/usbdisk{$disk['id']} $formatFs async,rw 0 0\n"; $mount_point = "/storage/usbdisk{$disk['id']}"; Util::mwMkdir($mount_point); SystemMessages::sysLogMsg(__METHOD__, "Create mount point: $conf"); @@ -862,7 +860,7 @@ private function updateConfigWithNewMountPoint(string $mount_point): void try { $data = json_decode($jsonString, true, 512, JSON_THROW_ON_ERROR); } catch (JsonException $exception) { - throw new Error("{$staticSettingsFileOrig} has broken format"); + throw new Error("$staticSettingsFileOrig has broken format"); } foreach ($data as $rootKey => $rootEntry) { foreach ($rootEntry as $nestedKey => $entry) { @@ -908,7 +906,7 @@ private function createWorkDirs(): void { $path = ''; $mountPath = Util::which('mount'); - Processes::mwExec("{$mountPath} -o remount,rw /offload 2> /dev/null"); + Processes::mwExec("$mountPath -o remount,rw /offload 2> /dev/null"); $isLiveCd = file_exists('/offload/livecd'); @@ -951,7 +949,7 @@ private function createWorkDirs(): void $this->clearCacheFiles(); $this->clearTmpFiles(); $this->applyFolderRights(); - Processes::mwExec("{$mountPath} -o remount,ro /offload 2> /dev/null"); + Processes::mwExec("$mountPath -o remount,ro /offload 2> /dev/null"); } /** @@ -962,25 +960,25 @@ private function createWorkDirs(): void public function clearCacheFiles(): void { $cacheDirs = []; - $cacheDirs[] = $this->config->path('www.uploadDir'); - $cacheDirs[] = $this->config->path('www.downloadCacheDir'); - $cacheDirs[] = $this->config->path('adminApplication.assetsCacheDir') . '/js'; - $cacheDirs[] = $this->config->path('adminApplication.assetsCacheDir') . '/css'; - $cacheDirs[] = $this->config->path('adminApplication.assetsCacheDir') . '/img'; - $cacheDirs[] = $this->config->path('adminApplication.viewCacheDir'); - $cacheDirs[] = $this->config->path('adminApplication.voltCacheDir'); + $cacheDirs[] = $this->config->path(Directories::WWW_UPLOAD_DIR); + $cacheDirs[] = $this->config->path(Directories::WWW_DOWNLOAD_CACHE_DIR); + $cacheDirs[] = $this->config->path(Directories::APP_ASSETS_CACHE_DIR) . '/js'; + $cacheDirs[] = $this->config->path(Directories::APP_ASSETS_CACHE_DIR) . '/css'; + $cacheDirs[] = $this->config->path(Directories::APP_ASSETS_CACHE_DIR) . '/img'; + $cacheDirs[] = $this->config->path(Directories::APP_VIEW_CACHE_DIR); + $cacheDirs[] = $this->config->path(Directories::APP_VOLT_CACHE_DIR); $rmPath = Util::which('rm'); // Clear cache files for each directory foreach ($cacheDirs as $cacheDir) { if (!empty($cacheDir)) { - Processes::mwExec("{$rmPath} -rf {$cacheDir}/*"); + Processes::mwExec("$rmPath -rf $cacheDir/*"); } } // Delete boot cache folders if storage disk is mounted if (is_dir('/mountpoint') && self::isStorageDiskMounted()) { - Processes::mwExec("{$rmPath} -rf /mountpoint"); + Processes::mwExec("$rmPath -rf /mountpoint"); } } @@ -995,7 +993,7 @@ private function clearTmpFiles(): void $mv = Util::which('mv'); $rm = Util::which('rm'); $nice = Util::which('nice'); - $tmpDir = $this->config->path('core.tempDir'); + $tmpDir = $this->config->path(Directories::CORE_TEMP_DIR); if (!file_exists($tmpDir)) { return; } @@ -1038,7 +1036,7 @@ private function getStorageDev(array $disk, string $cf_disk): string } } // Determine the disk by its name. - if ($disk['device'] !== "/dev/{$cf_disk}") { + if ($disk['device'] !== "/dev/$cf_disk") { // If it's a regular disk, use partition 1. $part = "1"; } else { @@ -1074,7 +1072,7 @@ private function hddExists(string $disk): bool // Loop for up to 10 seconds or until a non-empty UUID is found. while (true) { // Retrieve the UUID for the disk. - $uid = $this->getUuid($disk); + $uid = self::getUuid($disk); SystemMessages::sysLogMsg(__METHOD__, "Disk with name $disk has GUID: $uid", LOG_DEBUG); // If the UUID is not empty, the disk exists. @@ -1103,7 +1101,7 @@ private function hddExists(string $disk): bool */ public function saveFstab(string $conf = ''): void { - $varEtcDir = $this->config->path('core.varEtcDir'); + $varEtcDir = $this->config->path(Directories::CORE_VAR_ETC_DIR); // Create the mount point directory for additional disks Util::mwMkdir('/storage'); @@ -1125,9 +1123,9 @@ public function saveFstab(string $conf = ''): void $part2 = self::getDevPartName($cf_disk, '2'); $part3 = self::getDevPartName($cf_disk, '3'); - $uid_part2 = 'UUID=' . $this->getUuid("$part2"); + $uid_part2 = 'UUID=' . self::getUuid($part2); $format_p2 = $this->getFsType($part2); - $uid_part3 = 'UUID=' . $this->getUuid("$part3"); + $uid_part3 = 'UUID=' . self::getUuid($part3); $format_p3 = $this->getFsType($part3); $fstab .= "$uid_part2 /offload $format_p2 ro 0 0\n"; @@ -1203,7 +1201,7 @@ private function getLsBlkDiskInfo(): array // Execute lsblk command to get disk information in JSON format Processes::mwExec( - "{$lsBlkPath} -J -b -o VENDOR,MODEL,SERIAL,LABEL,TYPE,FSTYPE,MOUNTPOINT,SUBSYSTEMS,NAME,UUID", + "$lsBlkPath -J -b -o VENDOR,MODEL,SERIAL,LABEL,TYPE,FSTYPE,MOUNTPOINT,SUBSYSTEMS,NAME,UUID", $out ); try { @@ -1224,7 +1222,7 @@ public function createWorkDirsAfterDBUpgrade(): void { // Remount /offload directory as read-write $mountPath = Util::which('mount'); - Processes::mwExec("{$mountPath} -o remount,rw /offload 2> /dev/null"); + Processes::mwExec("$mountPath -o remount,rw /offload 2> /dev/null"); // Create symlinks for module caches $this->createModulesCacheSymlinks(); @@ -1233,7 +1231,7 @@ public function createWorkDirsAfterDBUpgrade(): void $this->applyFolderRights(); // Remount /offload directory as read-only - Processes::mwExec("{$mountPath} -o remount,ro /offload 2> /dev/null"); + Processes::mwExec("$mountPath -o remount,ro /offload 2> /dev/null"); } /** @@ -1265,15 +1263,15 @@ public function createAssetsSymlinks(): void { // Create symlink for JS cache directory $jsCacheDir = appPath('sites/admin-cabinet/assets/js/cache'); - Util::createUpdateSymlink($this->config->path('adminApplication.assetsCacheDir') . '/js', $jsCacheDir); + Util::createUpdateSymlink($this->config->path(Directories::APP_ASSETS_CACHE_DIR) . '/js', $jsCacheDir); // Create symlink for CSS cache directory $cssCacheDir = appPath('sites/admin-cabinet/assets/css/cache'); - Util::createUpdateSymlink($this->config->path('adminApplication.assetsCacheDir') . '/css', $cssCacheDir); + Util::createUpdateSymlink($this->config->path(Directories::APP_ASSETS_CACHE_DIR) . '/css', $cssCacheDir); // Create symlink for image cache directory $imgCacheDir = appPath('sites/admin-cabinet/assets/img/cache'); - Util::createUpdateSymlink($this->config->path('adminApplication.assetsCacheDir') . '/img', $imgCacheDir); + Util::createUpdateSymlink($this->config->path(Directories::APP_ASSETS_CACHE_DIR) . '/img', $imgCacheDir); } @@ -1285,7 +1283,7 @@ public function createAssetsSymlinks(): void public function createViewSymlinks(): void { $viewCacheDir = appPath('src/AdminCabinet/Views/Modules'); - Util::createUpdateSymlink($this->config->path('adminApplication.viewCacheDir'), $viewCacheDir); + Util::createUpdateSymlink($this->config->path(Directories::APP_VIEW_CACHE_DIR), $viewCacheDir); } /** @@ -1296,16 +1294,16 @@ public function createViewSymlinks(): void */ public function createAGIBINSymlinks(bool $isLiveCd): void { - $agiBinDir = $this->config->path('asterisk.astagidir'); + $agiBinDir = $this->config->path(Directories::AST_AGI_BIN_DIR); if ($isLiveCd && strpos($agiBinDir, '/offload/') !== 0) { Util::mwMkdir($agiBinDir); } $roAgiBinFolder = appPath('src/Core/Asterisk/agi-bin'); - $files = glob("{$roAgiBinFolder}/*.{php}", GLOB_BRACE); + $files = glob("$roAgiBinFolder/*.{php}", GLOB_BRACE); foreach ($files as $file) { $fileInfo = pathinfo($file); - $newFilename = "{$agiBinDir}/{$fileInfo['filename']}.{$fileInfo['extension']}"; + $newFilename = "$agiBinDir/{$fileInfo['filename']}.{$fileInfo['extension']}"; Util::createUpdateSymlink($file, $newFilename); } } @@ -1336,8 +1334,8 @@ private function applyFolderRights(): void } // Add additional directories with WWW rights - $www_dirs[] = $this->config->path('core.tempDir'); - $www_dirs[] = $this->config->path('core.logsDir'); + $www_dirs[] = $this->config->path(Directories::CORE_TEMP_DIR); + $www_dirs[] = $this->config->path(Directories::CORE_LOGS_DIR); // Create empty log files with WWW rights $logFiles = [ @@ -1365,7 +1363,7 @@ private function applyFolderRights(): void Util::addExecutableRights(implode(' ', $exec_dirs)); $mountPath = Util::which('mount'); - Processes::mwExec("{$mountPath} -o remount,ro /offload 2> /dev/null"); + Processes::mwExec("$mountPath -o remount,ro /offload 2> /dev/null"); } /** @@ -1373,18 +1371,18 @@ private function applyFolderRights(): void */ public function mountSwap(): void { - $tempDir = $this->config->path('core.tempDir'); - $swapFile = "{$tempDir}/swapfile"; + $tempDir = $this->config->path(Directories::CORE_TEMP_DIR); + $swapFile = "$tempDir/swapfile"; $swapOffCmd = Util::which('swapoff'); - Processes::mwExec("{$swapOffCmd} {$swapFile}"); + Processes::mwExec("$swapOffCmd $swapFile"); $this->makeSwapFile($swapFile); if (!file_exists($swapFile)) { return; } $swapOnCmd = Util::which('swapon'); - $result = Processes::mwExec("{$swapOnCmd} {$swapFile}"); + $result = Processes::mwExec("$swapOnCmd $swapFile"); SystemMessages::sysLogMsg('Swap', 'connect swap result: ' . $result, LOG_INFO); } @@ -1398,7 +1396,7 @@ private function makeSwapFile(string $swapFile): void $swapLabel = Util::which('swaplabel'); // Check if swap file already exists - if (Processes::mwExec("{$swapLabel} {$swapFile}") === 0) { + if (Processes::mwExec("$swapLabel $swapFile") === 0) { return; } if (file_exists($swapFile)) { @@ -1421,12 +1419,12 @@ private function makeSwapFile(string $swapFile): void SystemMessages::sysLogMsg('Swap', 'make swap ' . $swapFile, LOG_INFO); // Create swap file using dd command - Processes::mwExec("{$ddCmd} if=/dev/zero of={$swapFile} bs={$bs} count={$countBlock}"); + Processes::mwExec("$ddCmd if=/dev/zero of=$swapFile bs=$bs count=$countBlock"); $mkSwapCmd = Util::which('mkswap'); // Set up swap space on the file - Processes::mwExec("{$mkSwapCmd} {$swapFile}"); + Processes::mwExec("$mkSwapCmd $swapFile"); } /** @@ -1472,7 +1470,7 @@ public function getAllHdd(bool $mounted_only = false): array // Execute the command to get disk information for /storage directory Processes::mwExec( - "{$dfPath} -k /storage | {$awkPath} '{ print \$1 \"|\" $3 \"|\" \$4} ' | {$grepPath} -v 'Available'", + "$dfPath -k /storage | $awkPath '{ print \$1 \"|\" $3 \"|\" \$4} ' | $grepPath -v 'Available'", $out ); $disk_data = explode('|', implode(" ", $out)); @@ -1497,10 +1495,10 @@ public function getAllHdd(bool $mounted_only = false): array // Get CD-ROM and HDD devices $cd_disks = $this->cdromGetDevices(); - $disks = $this->diskGetDevices(); + $disks = $this->diskGetDevices(); $cf_disk = ''; - $varEtcDir = $this->config->path('core.varEtcDir'); + $varEtcDir = $this->config->path(Directories::CORE_VAR_ETC_DIR); if (file_exists($varEtcDir . '/cfdevice')) { $cf_disk = trim(file_get_contents($varEtcDir . '/cfdevice')); @@ -1534,7 +1532,7 @@ public function getAllHdd(bool $mounted_only = false): array if ($mb_size > 100) { $temp_size = sprintf("%.0f MB", $mb_size); $temp_vendor = $this->getVendorDisk($diskInfo); - $free_space = $this->getFreeSpace($disk); + $free_space = self::getFreeSpace($disk); $arr_disk_info = $this->determineFormatFs($diskInfo); @@ -1634,7 +1632,7 @@ public static function diskIsMounted(string $disk, string $filter = '/dev/') $mountPath = Util::which('mount'); // Execute mount command and grep the output for the disk name - Processes::mwExec("{$mountPath} | {$grepPath} '{$filter}{$disk}'", $out); + Processes::mwExec("$mountPath | $grepPath '$filter$disk'", $out); if (count($out) > 0) { $res_out = end($out); } else { @@ -1665,7 +1663,7 @@ private function getVendorDisk(array $diskInfo): string } // If no vendor-related data is found, use the disk name - if (count($temp_vendor) === 0) { + if (empty($temp_vendor)) { $temp_vendor[] = $diskInfo['name'] ?? 'ERROR: NoName'; } return implode(', ', $temp_vendor); @@ -1716,19 +1714,19 @@ public function determineFormatFs(array $deviceInfo): array // Iterate through each device partition foreach ($devices as $dev) { - if (empty($dev) || (count($devices) > 1 && $device === $dev) || is_dir("/sys/block/{$dev}")) { + if (empty($dev) || (count($devices) > 1 && $device === $dev) || is_dir("/sys/block/$dev")) { continue; } $mb_size = 0; $path_size_info = ''; - $tmp_path = "/sys/block/{$device}/{$dev}/size"; + $tmp_path = "/sys/block/$device/$dev/size"; if (file_exists($tmp_path)) { $path_size_info = $tmp_path; } // If the size path is not found, try an alternate path if (empty($path_size_info)) { - $tmp_path = "/sys/block/" . substr($dev, 0, 3) . "/{$dev}/size"; + $tmp_path = "/sys/block/" . substr($dev, 0, 3) . "/$dev/size"; if (file_exists($tmp_path)) { $path_size_info = $tmp_path; } @@ -1749,16 +1747,16 @@ public function determineFormatFs(array $deviceInfo): array $mount_dir = ''; // Check if the device is currently mounted - if (self::isStorageDiskMounted("/dev/{$dev} ", $mount_dir)) { + if (self::isStorageDiskMounted("/dev/$dev ", $mount_dir)) { $grepPath = Util::which('grep'); $awkPath = Util::which('awk'); $mountPath = Util::which('mount'); // Get the file system type and free space of the mounted device - Processes::mwExec("{$mountPath} | {$grepPath} '/dev/{$dev}' | {$awkPath} '{print $5}'", $out); + Processes::mwExec("$mountPath | $grepPath '/dev/$dev' | $awkPath '{print $5}'", $out); $fs = trim(implode("", $out)); $fs = ($fs === 'fuseblk') ? 'ntfs' : $fs; - $free_space = $this->getFreeSpace("/dev/{$dev} "); + $free_space = self::getFreeSpace("/dev/$dev "); $used_space = $mb_size - $free_space; } else { $format = $this->getFsType($device); @@ -1781,7 +1779,7 @@ public function determineFormatFs(array $deviceInfo): array 'size' => round($mb_size, 2), "used_space" => round($used_space, 2), "free_space" => round($mb_size - $used_space, 2), - "uuid" => $this->getUuid("/dev/{$dev} "), + "uuid" => self::getUuid("/dev/$dev "), "fs" => $fs, ]; @@ -1806,7 +1804,7 @@ private function getDiskParted(string $diskName): array $lsBlkPath = Util::which('lsblk'); // Execute lsblk command to get disk partition information in JSON format - Processes::mwExec("{$lsBlkPath} -J -b -o NAME,TYPE {$diskName}", $out); + Processes::mwExec("$lsBlkPath -J -b -o NAME,TYPE $diskName", $out); try { $data = json_decode(implode(PHP_EOL, $out), true, 512, JSON_THROW_ON_ERROR); @@ -1847,7 +1845,7 @@ public function getFsType(string $device): string // Execute the command to retrieve the file system type of the device Processes::mwExec( - "$blkid -ofull /dev/{$device} | $sed -r 's/[[:alnum:]]+=/\\n&/g' | $grep \"^TYPE=\" | $awk -F \"\\\"\" '{print $2}'", + "$blkid -ofull /dev/$device | $sed -r 's/[[:alnum:]]+=/\\n&/g' | $grep \"^TYPE=\" | $awk -F \"\\\"\" '{print $2}'", $out ); $format = implode('', $out); @@ -1871,7 +1869,7 @@ public function getFsType(string $device): string public static function mountDisk(string $dev, string $format, string $dir): bool { // Check if the disk is already mounted - if (self::isStorageDiskMounted("/dev/{$dev} ")) { + if (self::isStorageDiskMounted("/dev/$dev ")) { return true; } @@ -1891,16 +1889,16 @@ public static function mountDisk(string $dev, string $format, string $dir): bool if ('ntfs' === $format) { // Mount NTFS disk using 'mount.ntfs-3g' command $mountNtfs3gPath = Util::which('mount.ntfs-3g'); - Processes::mwExec("{$mountNtfs3gPath} /dev/{$dev} {$dir}", $out); + Processes::mwExec("$mountNtfs3gPath /dev/$dev $dir", $out); } else { // Mount disk using specified file system format and UUID - $uid_part = 'UUID=' . self::getUuid("/dev/{$dev}"); + $uid_part = 'UUID=' . self::getUuid("/dev/$dev"); $mountPath = Util::which('mount'); - Processes::mwExec("{$mountPath} -t {$format} {$uid_part} {$dir}", $out); + Processes::mwExec("$mountPath -t $format $uid_part $dir", $out); } // Check if the disk is now mounted - return self::isStorageDiskMounted("/dev/{$dev} "); + return self::isStorageDiskMounted("/dev/$dev "); } /** @@ -1921,7 +1919,7 @@ public static function getUuid(string $device): string // Build the command to retrieve the UUID of the device $cmd = "$lsblk -r -o NAME,UUID | $grep " . basename($device) . " | $cut -d ' ' -f 2"; $res = Processes::mwExec($cmd, $output); - if ($res === 0 && count($output) > 0) { + if ($res === 0 && !empty($output)) { $result = $output[0]; } else { $result = ''; @@ -1946,9 +1944,9 @@ public function getRecoverDiskName(): string } foreach ($diskInfo['children'] as $child) { $mountpoint = $child['mountpoint'] ?? ''; - $diskPath = "/dev/{$disk}"; + $diskPath = "/dev/$disk"; if ($mountpoint === '/conf.recover' && file_exists($diskPath)) { - return "/dev/{$disk}"; + return "/dev/$disk"; } } } @@ -1978,7 +1976,7 @@ public static function connectStorageInCloud(): string } // In some Clouds the virtual machine starts immediately before the storage disk was attached - if (!Storage::selectAndConfigureStorageDisk(true)){ + if (!self::selectAndConfigureStorageDisk(true)){ return SystemMessages::RESULT_FAILED; } From 017abc6cb2828bf25706e60231a72ede94e783f8 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Wed, 26 Jun 2024 12:27:43 +0300 Subject: [PATCH 30/58] =?UTF-8?q?#736=20=D0=92=D0=B5=D1=80=D0=BD=D1=83?= =?UTF-8?q?=D0=BB=20=D0=BE=D0=B1=D1=80=D0=B0=D1=82=D0=BD=D0=BE.=20mbr=20?= =?UTF-8?q?=D1=80=D0=B0=D0=B7=D0=BC=D0=B5=D1=82=D0=BA=D1=83.=20=D0=A2?= =?UTF-8?q?=D0=B8=D0=BF=20=D1=80=D0=B0=D0=B7=D0=BC=D0=B5=D1=82=D0=BA=D0=B8?= =?UTF-8?q?=20=D0=B4=D0=BE=D0=BB=D0=B6=D0=B5=D0=BD=20=D0=B1=D1=8B=D1=82?= =?UTF-8?q?=D1=8C=20=D0=BE=D0=B4=D0=B8=D0=BD=20=D0=BD=D0=B0=20=D0=B2=D1=81?= =?UTF-8?q?=D0=B5=D1=85=20=D0=B4=D0=B8=D1=81=D0=BA=D0=B0=D1=85,=20=D0=B8?= =?UTF-8?q?=D0=BB=D0=B8=20=D0=BF=D0=BE=D1=8F=D0=B2=D0=BB=D1=8F=D1=8E=D1=82?= =?UTF-8?q?=D1=81=D1=8F=20=D0=BF=D1=80=D0=BE=D0=B1=D0=BB=D0=B5=D0=BC=D1=8B?= =?UTF-8?q?=20=D1=81=20=D0=B7=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=BA=D0=BE?= =?UTF-8?q?=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/System/Storage.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Core/System/Storage.php b/src/Core/System/Storage.php index 61c3b663e..1d61439da 100644 --- a/src/Core/System/Storage.php +++ b/src/Core/System/Storage.php @@ -383,7 +383,7 @@ public function formatEntireDisk(string $device, bool $bg = false): bool // First, remove existing partitions and then create a new msdos partition table and ext4 partition // This command deletes all existing partitions and creates a new primary partition using the full disk - $command = "$parted --script --align optimal '$device' 'mklabel gpt'"; + $command = "$parted --script --align optimal '$device' 'mklabel msdos'"; Processes::mwExec($command); // Apply the command to clear the partition table // Now create a new partition that spans the entire disk @@ -519,7 +519,7 @@ public static function selectAndConfigureStorageDisk(bool $automatic=false, bool // Check if the disk selection should be automatic if ($automatic) { $target_disk_storage = $selected_disk['id']; - SystemMessages::echoToTeletype(PHP_EOL.' |- '."Automatically selected storage disk is $target_disk_storage"); + SystemMessages::echoToTeletype(PHP_EOL.' - '."Automatically selected storage disk is $target_disk_storage"); } else { echo PHP_EOL." " . Util::translate('Select the drive to store the data.'); echo PHP_EOL." " . Util::translate('Selected disk:') . "\033[33;1m [{$selected_disk['id']}] \033[0m ".PHP_EOL.PHP_EOL; From b1c3347a718ff7ee6810982f268ba24b49fb313d Mon Sep 17 00:00:00 2001 From: boffart <> Date: Thu, 27 Jun 2024 14:58:23 +0300 Subject: [PATCH 31/58] =?UTF-8?q?=D0=9E=D0=BF=D1=82=D0=B8=D0=BC=D0=B8?= =?UTF-8?q?=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20=D0=B8=20=D1=80=D0=B5=D1=84?= =?UTF-8?q?=D0=B0=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=BD=D0=B3.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Lib/CdrDB/GetActiveChannelsAction.php | 76 ++++++++----------- 1 file changed, 33 insertions(+), 43 deletions(-) diff --git a/src/PBXCoreREST/Lib/CdrDB/GetActiveChannelsAction.php b/src/PBXCoreREST/Lib/CdrDB/GetActiveChannelsAction.php index 7878681c5..dea8ec183 100644 --- a/src/PBXCoreREST/Lib/CdrDB/GetActiveChannelsAction.php +++ b/src/PBXCoreREST/Lib/CdrDB/GetActiveChannelsAction.php @@ -19,17 +19,18 @@ namespace MikoPBX\PBXCoreREST\Lib\CdrDB; -use MikoPBX\Core\System\BeanstalkClient; +use MikoPBX\Common\Providers\CDRDatabaseProvider; use MikoPBX\Core\System\Util; -use MikoPBX\Core\Workers\WorkerCdr; use MikoPBX\PBXCoreREST\Lib\PBXApiResult; +use Phalcon\Exception; +use Phalcon\Di\Injectable; /** * Get active channels. These are the unfinished calls (endtime IS NULL). * * @package MikoPBX\PBXCoreREST\Lib\CdrDB */ -class GetActiveChannelsAction extends \Phalcon\Di\Injectable +class GetActiveChannelsAction extends Injectable { /** * Get active channels. These are the unfinished calls (endtime IS NULL). @@ -40,52 +41,41 @@ public static function main(): PBXApiResult { $res = new PBXApiResult(); $res->processor = __METHOD__; + $res->success = true; try { - $res->success = true; + $activeChannels = Util::getAstManager('off')->GetChannels(); + }catch (Exception $e){ + $res->success = false; + $res->messages[] = $e->getMessage(); + return $res; + } - $filter = [ - 'endtime=""', - 'order' => 'id', - 'columns' => 'start,answer,src_chan,dst_chan,src_num,dst_num,did,linkedid', - 'miko_tmp_db' => true, - 'miko_result_in_file' => true, - ]; - $client = new BeanstalkClient(WorkerCdr::SELECT_CDR_TUBE); - list($result, $message) = $client->sendRequest(json_encode($filter), 2); - if ($result === false) { - $res->data = []; - } else { - $am = Util::getAstManager('off'); - $active_chans = $am->GetChannels(true); - $result_data = []; + $filter = [ + 'endtime=""', + 'order' => 'id', + 'columns' => 'start,answer,src_chan,dst_chan,src_num,dst_num,did,linkedid', + 'miko_tmp_db' => true, + ]; + $cdrData = CDRDatabaseProvider::getCdr($filter); - $result = json_decode($message); - if (file_exists($result)) { - $data = json_decode(file_get_contents($result), true); - unlink($result); - foreach ($data as $row) { - if (!isset($active_chans[$row['linkedid']])) { - // The call no longer exists. - continue; - } - if (empty($row['dst_chan']) && empty($row['src_chan'])) { - // This is an erroneous situation. Ignore such a call. - continue; - } - $channels = $active_chans[$row['linkedid']]; - if ((empty($row['src_chan']) || in_array($row['src_chan'], $channels)) - && (empty($row['dst_chan']) || in_array($row['dst_chan'], $channels))) { - $result_data[] = $row; - } - } - } - $res->data = $result_data; + $result_data = []; + foreach ($cdrData as $row) { + if (!isset($activeChannels[$row['linkedid']])) { + // The call no longer exists. + continue; + } + if (empty($row['dst_chan']) && empty($row['src_chan'])) { + // This is an erroneous situation. Ignore such a call. + continue; + } + $channels = $activeChannels[$row['linkedid']]; + if ((empty($row['src_chan']) || in_array($row['src_chan'], $channels, true)) + && (empty($row['dst_chan']) || in_array($row['dst_chan'], $channels, true))) { + $result_data[] = $row; } - } catch (\Throwable $e) { - $res->success = false; - $res->messages[] = $e->getMessage(); } + $res->data = $result_data; return $res; } } \ No newline at end of file From 5bd26803dc5a37b1263e76e32f4056166e3c54d2 Mon Sep 17 00:00:00 2001 From: Weblate Date: Fri, 5 Jul 2024 00:21:13 +0300 Subject: [PATCH 32/58] Translated using Weblate (Portuguese) Currently translated at 100.0% (1241 of 1241 strings) Co-authored-by: David Coimbra de Oliveira Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/pt/ Translation: MIKOPBX/Core --- src/Common/Messages/pt.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Common/Messages/pt.php b/src/Common/Messages/pt.php index ecfcebd86..20c7269d5 100644 --- a/src/Common/Messages/pt.php +++ b/src/Common/Messages/pt.php @@ -830,7 +830,7 @@ 'ex_Number' => 'Número do ramal', 'ex_Language' => 'Interface e linguagem de alerta', 'ex_ThisEmailAlreadyRegisteredForOtherUser' => 'O endereço digitado já está registrado para', - 'ex_EmailAddress' => 'Endereço de email', + 'ex_EmailAddress' => 'Endereço de e-mail', 'ex_Username' => 'Nome completo do usuário', 'ex_RoutingSettings' => 'Configurações de roteamento', 'ex_GeneralSettings' => 'Parâmetros-chave', @@ -876,13 +876,13 @@ 'November' => 'Novembro', 'October' => 'Outubro', 'September' => 'Setembro', - 'August' => 'Agosto', + 'August' => 'agosto', 'July' => 'Julho', 'June' => 'Junho', 'May' => 'Maio', 'April' => 'Abril', 'March' => 'Março', - 'February' => 'Fevereiro', + 'February' => 'fevereiro', 'gs_WebAdminLanguage' => 'Linguagem da interface da Web', 'lang_HelpWithTranslateIt' => 'Ajuda com a tradução do MikoPBX', 'topMenu_Support' => 'Suporte', @@ -1109,7 +1109,7 @@ 'mo_SystemExten_hangup' => 'Terminar chamada', 'mo_SystemExten_busy' => 'Reproduzir sinal de ocupado', 'mo_SystemExten_did2user' => 'Direto ao funcionário (correspondência por DID)', - 'pr_FromUser_v2' => 'do utilizador', + 'pr_FromUser_v2' => 'Usuário', 'pr_FromDomain_v2' => 'domínio', 'mo_SystemExten_voicemail' => 'Correio de voz', 'f2b_Jail_asterisk_v2' => 'Erros de autorização SIP', From 332526e8791b97677a0e28da13472e50fb712257 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Wed, 10 Jul 2024 17:08:50 +0300 Subject: [PATCH 33/58] =?UTF-8?q?#767=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4=20=D0=B8=D0=BD?= =?UTF-8?q?=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D0=B8=20=D0=BE=D0=B1?= =?UTF-8?q?=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8=20=D0=B2=20=D1=81=D0=BB?= =?UTF-8?q?=D1=83=D1=87=D0=B0=D0=B5=20=D0=BF=D1=80=D0=BE=D0=B1=D0=BB=D0=B5?= =?UTF-8?q?=D0=BC=20=D1=81=20=D1=81=D0=BE=D1=85=D1=80=D0=B0=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=D0=BC=20=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=B5=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../general-settings-modify.js | 48 ++++++++++++++++++- .../general-settings-modify.js | 35 ++++++++++++++ src/Common/Messages/ru.php | 2 + 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/sites/admin-cabinet/assets/js/pbx/GeneralSettings/general-settings-modify.js b/sites/admin-cabinet/assets/js/pbx/GeneralSettings/general-settings-modify.js index ee35cce5d..fbb8aa32d 100644 --- a/sites/admin-cabinet/assets/js/pbx/GeneralSettings/general-settings-modify.js +++ b/sites/admin-cabinet/assets/js/pbx/GeneralSettings/general-settings-modify.js @@ -356,8 +356,11 @@ var generalSettingsModify = { * @param {Object} response - The response from the server after the form is sent */ cbAfterSendForm: function cbAfterSendForm(response) { + $("#error-messages").remove(); + if (!response.success) { Form.$submitButton.removeClass('disabled'); + generalSettingsModify.generateErrorMessageHtml(response); } else { $('.password-validate').remove(); } @@ -365,6 +368,49 @@ var generalSettingsModify = { generalSettingsModify.checkDeleteAllConditions(); }, + /** + * The function collects an information message about a data saving error + * @param response + * @returns {string} + */ + generateErrorMessageHtml: function generateErrorMessageHtml(response) { + if (response.messages && response.messages.error) { + var $div = $('
', { + "class": 'ui negative message', + id: 'error-messages' + }); + var $header = $('
', { + "class": 'header' + }).text(globalTranslate.gs_ErrorSaveSettings); + $div.append($header); + var $ul = $('
    ', { + "class": 'list' + }); + var messagesSet = new Set(); + response.messages.error.forEach(function (errorArray) { + errorArray.forEach(function (error) { + var textContent = ''; + + if (globalTranslate[error.message] === undefined) { + textContent = error.message; + } else { + textContent = globalTranslate[error.message]; + } + + if (messagesSet.has(textContent)) { + return; + } + + messagesSet.add(error.message); + $ul.append($('
  • ').text(textContent)); + }); + }); + $div.append($ul); + $('#submitbutton').before($div); + return $div; + } + }, + /** * Initialize the validation rules of the form */ @@ -406,4 +452,4 @@ var generalSettingsModify = { $(document).ready(function () { generalSettingsModify.initialize(); }); -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9HZW5lcmFsU2V0dGluZ3MvZ2VuZXJhbC1zZXR0aW5ncy1tb2RpZnkuanMiXSwibmFtZXMiOlsiZ2VuZXJhbFNldHRpbmdzTW9kaWZ5IiwiJGZvcm1PYmoiLCIkIiwiJHdlYkFkbWluUGFzc3dvcmQiLCIkc3NoUGFzc3dvcmQiLCIkZGlzYWJsZVNTSFBhc3N3b3JkIiwicGFyZW50IiwiJHNzaFBhc3N3b3JkU2VnbWVudCIsImhpZGRlblBhc3N3b3JkIiwiJHJlY29yZHNTYXZlUGVyaW9kU2xpZGVyIiwic2F2ZVJlY29yZHNQZXJpb2QiLCJ2YWxpZGF0ZVJ1bGVzIiwicGJ4bmFtZSIsImlkZW50aWZpZXIiLCJydWxlcyIsInR5cGUiLCJwcm9tcHQiLCJnbG9iYWxUcmFuc2xhdGUiLCJnc19WYWxpZGF0ZUVtcHR5UEJYTmFtZSIsIldlYkFkbWluUGFzc3dvcmQiLCJXZWJBZG1pblBhc3N3b3JkUmVwZWF0IiwiZ3NfVmFsaWRhdGVXZWJQYXNzd29yZHNGaWVsZERpZmZlcmVudCIsIlNTSFBhc3N3b3JkIiwiU1NIUGFzc3dvcmRSZXBlYXQiLCJnc19WYWxpZGF0ZVNTSFBhc3N3b3Jkc0ZpZWxkRGlmZmVyZW50IiwiV0VCUG9ydCIsImdzX1ZhbGlkYXRlV0VCUG9ydE91dE9mUmFuZ2UiLCJnc19WYWxpZGF0ZVdFQkhUVFBTUG9ydE5vdEVxdWFsVG9XRUJQb3J0IiwiZ3NfVmFsaWRhdGVXRUJQb3J0Tm90RXF1YWxUb0FqYW1Qb3J0IiwiZ3NfVmFsaWRhdGVXRUJQb3J0Tm90RXF1YWxUb0FqYW1UTFNQb3J0IiwiV0VCSFRUUFNQb3J0IiwiZ3NfVmFsaWRhdGVXRUJIVFRQU1BvcnRPdXRPZlJhbmdlIiwiZ3NfVmFsaWRhdGVXRUJIVFRQU1BvcnROb3RFcXVhbFRvQWphbVBvcnQiLCJnc19WYWxpZGF0ZVdFQkhUVFBTUG9ydE5vdEVxdWFsVG9BamFtVExTUG9ydCIsIkFKQU1Qb3J0IiwiZ3NfVmFsaWRhdGVBSkFNUG9ydE91dE9mUmFuZ2UiLCJ3ZWJBZG1pblBhc3N3b3JkUnVsZXMiLCJnc19WYWxpZGF0ZUVtcHR5V2ViUGFzc3dvcmQiLCJnc19WYWxpZGF0ZVdlYWtXZWJQYXNzd29yZCIsInZhbHVlIiwiZ3NfUGFzc3dvcmRzIiwiZ3NfUGFzc3dvcmROb0xvd1NpbXZvbCIsImdzX1Bhc3N3b3JkTm9OdW1iZXJzIiwiZ3NfUGFzc3dvcmROb1VwcGVyU2ltdm9sIiwiYWRkaXRpb25hbFNzaFZhbGlkUnVsZXNQYXNzIiwiZ3NfVmFsaWRhdGVFbXB0eVNTSFBhc3N3b3JkIiwiZ3NfVmFsaWRhdGVXZWFrU1NIUGFzc3dvcmQiLCJnc19TU0hQYXNzd29yZCIsImFkZGl0aW9uYWxTc2hWYWxpZFJ1bGVzTm9QYXNzIiwiaW5pdGlhbGl6ZSIsIm9uIiwidmFsIiwiaW5pdFJ1bGVzIiwiUGFzc3dvcmRTY29yZSIsImNoZWNrUGFzc1N0cmVuZ3RoIiwicGFzcyIsImJhciIsInNlY3Rpb24iLCJmaW5kIiwidGFiIiwiaGlzdG9yeSIsImhpc3RvcnlUeXBlIiwiZHJvcGRvd24iLCJjaGVja2JveCIsInRhYmxlRG5EIiwib25Ecm9wIiwiRm9ybSIsImRhdGFDaGFuZ2VkIiwib25EcmFnQ2xhc3MiLCJkcmFnSGFuZGxlIiwiU291bmRGaWxlc1NlbGVjdG9yIiwiZ2V0RHJvcGRvd25TZXR0aW5nc1dpdGhFbXB0eSIsInNsaWRlciIsIm1pbiIsIm1heCIsInN0ZXAiLCJzbW9vdGgiLCJpbnRlcnByZXRMYWJlbCIsImxhYmVscyIsImdzX1N0b3JlMU1vbnRoT2ZSZWNvcmRzIiwiZ3NfU3RvcmUzTW9udGhzT2ZSZWNvcmRzIiwiZ3NfU3RvcmU2TW9udGhzT2ZSZWNvcmRzIiwiZ3NfU3RvcmUxWWVhck9mUmVjb3JkcyIsImdzX1N0b3JlM1llYXJzT2ZSZWNvcmRzIiwiZ3NfU3RvcmVBbGxQb3NzaWJsZVJlY29yZHMiLCJvbkNoYW5nZSIsImNiQWZ0ZXJTZWxlY3RTYXZlUGVyaW9kU2xpZGVyIiwiaW5pdGlhbGl6ZUZvcm0iLCJzaG93SGlkZVNTSFBhc3N3b3JkIiwicmVjb3JkU2F2ZVBlcmlvZCIsImZvcm0iLCJpbmRleE9mIiwid2luZG93IiwiZXZlbnQiLCJuYW1lVGFiIiwiaGlkZSIsInNob3ciLCJjaGVja0RlbGV0ZUFsbENvbmRpdGlvbnMiLCJkZWxldGVBbGxJbnB1dCIsImdzX0VudGVyRGVsZXRlQWxsUGhyYXNlIiwiUGJ4QXBpIiwiU3lzdGVtUmVzdG9yZURlZmF1bHRTZXR0aW5ncyIsImNiQWZ0ZXJSZXN0b3JlRGVmYXVsdFNldHRpbmdzIiwicmVzcG9uc2UiLCJVc2VyTWVzc2FnZSIsInNob3dJbmZvcm1hdGlvbiIsImdzX0FsbFNldHRpbmdzRGVsZXRlZCIsInNob3dNdWx0aVN0cmluZyIsInNhdmVQZXJpb2QiLCJjYkJlZm9yZVNlbmRGb3JtIiwic2V0dGluZ3MiLCJyZXN1bHQiLCJkYXRhIiwiYXJyQ29kZWNzIiwiZWFjaCIsImluZGV4Iiwib2JqIiwiYXR0ciIsInB1c2giLCJjb2RlY0lkIiwiZGlzYWJsZWQiLCJwcmlvcml0eSIsImNvZGVjcyIsIkpTT04iLCJzdHJpbmdpZnkiLCJjYkFmdGVyU2VuZEZvcm0iLCJzdWNjZXNzIiwiJHN1Ym1pdEJ1dHRvbiIsInJlbW92ZUNsYXNzIiwicmVtb3ZlIiwidXJsIiwiZ2xvYmFsUm9vdFVybCIsImRvY3VtZW50IiwicmVhZHkiXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFNQSxxQkFBcUIsR0FBRztBQUMxQjtBQUNKO0FBQ0E7QUFDQTtBQUNJQyxFQUFBQSxRQUFRLEVBQUVDLENBQUMsQ0FBQyx3QkFBRCxDQUxlOztBQU8xQjtBQUNKO0FBQ0E7QUFDQTtBQUNJQyxFQUFBQSxpQkFBaUIsRUFBRUQsQ0FBQyxDQUFDLG1CQUFELENBWE07O0FBYTFCO0FBQ0o7QUFDQTtBQUNBO0FBQ0lFLEVBQUFBLFlBQVksRUFBRUYsQ0FBQyxD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RkQsTUFFTztBQUNIb0QsTUFBQUEsSUFBSSxDQUFDdkQsYUFBTCxDQUFtQlEsZ0JBQW5CLENBQW9DTCxLQUFwQyxHQUE0Q2QscUJBQXFCLENBQUNvQyxxQkFBbEU7QUFDSDtBQUNKLEdBdmF5Qjs7QUF5YTFCO0FBQ0o7QUFDQTtBQUNJbUQsRUFBQUEsY0E1YTBCLDRCQTRhVDtBQUNickIsSUFBQUEsSUFBSSxDQUFDakUsUUFBTCxHQUFnQkQscUJBQXFCLENBQUNDLFFBQXRDO0FBQ0FpRSxJQUFBQSxJQUFJLENBQUNnRSxHQUFMLGFBQWNDLGFBQWQsMkJBRmEsQ0FFdUM7O0FBQ3BEakUsSUFBQUEsSUFBSSxDQUFDdkQsYUFBTCxHQUFxQlgscUJBQXFCLENBQUNXLGFBQTNDLENBSGEsQ0FHNkM7O0FBQzFEdUQsSUFBQUEsSUFBSSxDQUFDMkMsZ0JBQUwsR0FBd0I3RyxxQkFBcUIsQ0FBQzZHLGdCQUE5QyxDQUphLENBSW1EOztBQUNoRTNDLElBQUFBLElBQUksQ0FBQzJELGVBQUwsR0FBdUI3SCxxQkFBcUIsQ0FBQzZILGVBQTdDLENBTGEsQ0FLaUQ7O0FBQzlEM0QsSUFBQUEsSUFBSSxDQUFDakIsVUFBTDtBQUNIO0FBbmJ5QixDQUE5QixDLENBc2JBOztBQUNBL0MsQ0FBQyxDQUFDa0ksUUFBRCxDQUFELENBQVlDLEtBQVosQ0FBa0IsWUFBTTtBQUNwQnJJLEVBQUFBLHFCQUFxQixDQUFDaUQsVUFBdEI7QUFDSCxDQUZEIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIE1pa29QQlggLSBmcmVlIHBob25lIHN5c3RlbSBmb3Igc21hbGwgYnVzaW5lc3NcbiAqIENvcHlyaWdodCDCqSAyMDE3LTIwMjMgQWxleGV5IFBvcnRub3YgYW5kIE5pa29sYXkgQmVrZXRvdlxuICpcbiAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbS5cbiAqIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKi9cblxuXG4vKiBnbG9iYWwgZ2xvYmFsUm9vdFVybCxnbG9iYWxUcmFuc2xhdGUsIEZvcm0sIFBhc3N3b3JkU2NvcmUsIFBieEFwaSwgVXNlck1lc3NhZ2UsIFNvdW5kRmlsZXNTZWxlY3RvciwgJCAqL1xuXG4vKipcbiAqIEEgbW9kdWxlIHRvIGhhbmRsZSBtb2RpZmljYXRpb24gb2YgZ2VuZXJhbCBzZXR0aW5ncy5cbiAqL1xuY29uc3QgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5ID0ge1xuICAgIC8qKlxuICAgICAqIGpRdWVyeSBvYmplY3QgZm9yIHRoZSBmb3JtLlxuICAgICAqIEB0eXBlIHtqUXVlcnl9XG4gICAgICovXG4gICAgJGZvcm1PYmo6ICQoJyNnZW5lcmFsLXNldHRpbmdzLWZvcm0nKSxcblxuICAgIC8qKlxuICAgICAqIGpRdWVyeSBvYmplY3QgZm9yIHRoZSB3ZWIgYWRtaW4gcGFzc3dvcmQgaW5wdXQgZmllbGQuXG4gICAgICogQHR5cGUge2pRdWVyeX1cbiAgICAgKi9cbiAgICAkd2ViQWRtaW5QYXNzd29yZDogJCgnI1dlYkFkbWluUGFzc3dvcmQnKSxcblxuICAgIC8qKlxuICAgICAqIGpRdWVyeSBvYmplY3QgZm9yIHRoZSBzc2ggcGFzc3dvcmQgaW5wdXQgZmllbGQuXG4gICAgICogQHR5cGUge2pRdWVyeX1cbiAgICAgKi9cbiAgICAkc3NoUGFzc3dvcmQ6ICQoJyNTU0hQYXNzd29yZCcpLFxuXG4gICAgLyoqXG4gICAgICogalF1ZXJ5IG9iamVjdCBmb3IgdGhlIHdlYiBzc2ggcGFzc3dvcmQgaW5wdXQgZmllbGQuXG4gICAgICogQHR5cGUge2pRdWVyeX1cbiAgICAgKi9cbiAgICAkZGlzYWJsZVNTSFBhc3N3b3JkOiAkKCcjU1NIRGlzYWJsZVBhc3N3b3JkTG9naW5zJykucGFyZW50KCcuY2hlY2tib3gnKSxcblxuICAgIC8qKlxuICAgICAqIGpRdWVyeSBvYmplY3QgZm9yIHRoZSBTU0ggcGFzc3dvcmQgZmllbGRzXG4gICAgICogQHR5cGUge2pRdWVyeX1cbiAgICAgKi9cbiAgICAkc3NoUGFzc3dvcmRTZWdtZW50OiAkKCcjb25seS1pZi1wYXNzd29yZC1lbmFibGVkJyksXG5cbiAgICAvKipcbiAgICAgKiBJZiBwYXNzd29yZCBzZXQsIGl0IHdpbGwgYmUgaGlkZWQgZnJvbSB3ZWIgdWkuXG4gICAgICovXG4gICAgaGlkZGVuUGFzc3dvcmQ6ICd4eHh4eHh4JyxcblxuICAgIC8qKlxuICAgICAqIGpRdWVyeSBvYmplY3QgZm9yIHRoZSByZWNvcmRzIHJldGVudGlvbiBwZXJpb2Qgc2xpZGVyLlxuICAgICAqIEB0eXBlIHtqUXVlcnl9XG4gICAgICovXG4gICAgJHJlY29yZHNTYXZlUGVyaW9kU2xpZGVyOiAkKCcjUEJYUmVjb3JkU2F2ZVBlcmlvZFNsaWRlcicpLFxuXG4gICAgLyoqXG4gICAgICogUG9zc2libGUgcGVyaW9kIHZhbHVlcyBmb3IgdGhlIHJlY29yZHMgcmV0ZW50aW9uLlxuICAgICAqL1xuICAgIHNhdmVSZWNvcmRzUGVyaW9kOiBbJzMwJywgJzkwJywgJzE4MCcsICczNjAnLCAnMTA4MCcsICcnXSxcblxuICAgIC8qKlxuICAgICAqIFZhbGlkYXRpb24gcnVsZXMgZm9yIHRoZSBmb3JtIGZpZWxkcyBiZWZvcmUgc3VibWlzc2lvbi5cbiAgICAgKlxuICAgICAqIEB0eXBlIHtvYmplY3R9XG4gICAgICovXG4gICAgdmFsaWRhdGVSdWxlczogeyAvLyBnZW5lcmFsU2V0dGluZ3NNb2RpZnkudmFsaWRhdGVSdWxlcy5TU0hQYXNzd29yZC5ydWxlc1xuICAgICAgICBwYnhuYW1lOiB7XG4gICAgICAgICAgICBpZGVudGlmaWVyOiAnUEJYTmFtZScsXG4gICAgICAgICAgICBydWxlczogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2VtcHR5JyxcbiAgICAgICAgICAgICAgICAgICAgcHJvbXB0OiBnbG9iYWxUcmFuc2xhdGUuZ3NfVmFsaWRhdGVFbXB0eVBCWE5hbWUsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICAgIFdlYkFkbWluUGFzc3dvcmQ6IHtcbiAgICAgICAgICAgIGlkZW50aWZpZXI6ICdXZWJBZG1pblBhc3N3b3JkJyxcbiAgICAgICAgICAgIHJ1bGVzOiBbXSxcbiAgICAgICAgfSxcbiAgICAgICAgV2ViQWRtaW5QYXNzd29yZFJlcGVhdDoge1xuICAgICAgICAgICAgaWRlbnRpZmllcjogJ1dlYkFkbWluUGFzc3dvcmRSZXBlYXQnLFxuICAgICAgICAgICAgcnVsZXM6IFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdtYXRjaFtXZWJBZG1pblBhc3N3b3JkXScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV2ViUGFzc3dvcmRzRmllbGREaWZmZXJlbnQsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICAgIFNTSFBhc3N3b3JkOiB7XG4gICAgICAgICAgICBpZGVudGlmaWVyOiAnU1NIUGFzc3dvcmQnLFxuICAgICAgICAgICAgcnVsZXM6IFtdLFxuICAgICAgICB9LFxuICAgICAgICBTU0hQYXNzd29yZFJlcGVhdDoge1xuICAgICAgICAgICAgaWRlbnRpZmllcjogJ1NTSFBhc3N3b3JkUmVwZWF0JyxcbiAgICAgICAgICAgIHJ1bGVzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnbWF0Y2hbU1NIUGFzc3dvcmRdJyxcbiAgICAgICAgICAgICAgICAgICAgcHJvbXB0OiBnbG9iYWxUcmFuc2xhdGUuZ3NfVmFsaWRhdGVTU0hQYXNzd29yZHNGaWVsZERpZmZlcmVudCxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgICAgV0VCUG9ydDoge1xuICAgICAgICAgICAgaWRlbnRpZmllcjogJ1dFQlBvcnQnLFxuICAgICAgICAgICAgcnVsZXM6IFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdpbnRlZ2VyWzEuLjY1NTM1XScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV0VCUG9ydE91dE9mUmFuZ2UsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdkaWZmZXJlbnRbV0VCSFRUUFNQb3J0XScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV0VCSFRUUFNQb3J0Tm90RXF1YWxUb1dFQlBvcnQsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdkaWZmZXJlbnRbQUpBTVBvcnRUTFNdJyxcbiAgICAgICAgICAgICAgICAgICAgcHJvbXB0OiBnbG9iYWxUcmFuc2xhdGUuZ3NfVmFsaWRhdGVXRUJQb3J0Tm90RXF1YWxUb0FqYW1Qb3J0LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnZGlmZmVyZW50W0FKQU1Qb3J0XScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV0VCUG9ydE5vdEVxdWFsVG9BamFtVExTUG9ydCxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgICAgV0VCSFRUUFNQb3J0OiB7XG4gICAgICAgICAgICBpZGVudGlmaWVyOiAnV0VCSFRUUFNQb3J0JyxcbiAgICAgICAgICAgIHJ1bGVzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnaW50ZWdlclsxLi42NTUzNV0nLFxuICAgICAgICAgICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS5nc19WYWxpZGF0ZVdFQkhUVFBTUG9ydE91dE9mUmFuZ2UsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdkaWZmZXJlbnRbV0VCUG9ydF0nLFxuICAgICAgICAgICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS5nc19WYWxpZGF0ZVdFQkhUVFBTUG9ydE5vdEVxdWFsVG9XRUJQb3J0LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnZGlmZmVyZW50W0FKQU1Qb3J0VExTXScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV0VCSFRUUFNQb3J0Tm90RXF1YWxUb0FqYW1Qb3J0LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnZGlmZmVyZW50W0FKQU1Qb3J0XScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV0VCSFRUUFNQb3J0Tm90RXF1YWxUb0FqYW1UTFNQb3J0LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgICBBSkFNUG9ydDoge1xuICAgICAgICAgICAgaWRlbnRpZmllcjogJ0FKQU1Qb3J0JyxcbiAgICAgICAgICAgIHJ1bGVzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnaW50ZWdlclsxLi42NTUzNV0nLFxuICAgICAgICAgICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS5nc19WYWxpZGF0ZUFKQU1Qb3J0T3V0T2ZSYW5nZSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2RpZmZlcmVudFtBSkFNUG9ydFRMU10nLFxuICAgICAgICAgICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS5nc19WYWxpZGF0ZUFKQU1Qb3J0T3V0T2ZSYW5nZSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICB9LFxuXG4gICAgLy8gUnVsZXMgZm9yIHRoZSB3ZWIgYWRtaW4gcGFzc3dvcmQgZmllbGQgd2hlbiBpdCBub3QgZXF1YWwgdG8gaGlkZGVuUGFzc3dvcmRcbiAgICB3ZWJBZG1pblBhc3N3b3JkUnVsZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ2VtcHR5JyxcbiAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlRW1wdHlXZWJQYXNzd29yZCxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ21pbkxlbmd0aFs1XScsXG4gICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS5nc19WYWxpZGF0ZVdlYWtXZWJQYXNzd29yZCxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ25vdFJlZ0V4cCcsXG4gICAgICAgICAgICB2YWx1ZTogL1thLXpdLyxcbiAgICAgICAgICAgIHByb21wdDogJzxiPicgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmRzICsgJzwvYj46ICcgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmROb0xvd1NpbXZvbFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiAnbm90UmVnRXhwJyxcbiAgICAgICAgICAgIHZhbHVlOiAvXFxkLyxcbiAgICAgICAgICAgIHByb21wdDogJzxiPicgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmRzICsgJzwvYj46ICcgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmROb051bWJlcnNcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ25vdFJlZ0V4cCcsXG4gICAgICAgICAgICB2YWx1ZTogL1tBLVpdLyxcbiAgICAgICAgICAgIHByb21wdDogJzxiPicgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmRzICsgJzwvYj46ICcgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmROb1VwcGVyU2ltdm9sXG4gICAgICAgIH1cbiAgICBdLFxuICAgIC8vIFJ1bGVzIGZvciB0aGUgU1NIIHBhc3N3b3JkIGZpZWxkIHdoZW4gU1NIIGxvZ2luIHRocm91Z2ggdGhlIHBhc3N3b3JkIGVuYWJsZWQsIGFuZCBpdCBub3QgZXF1YWwgdG8gaGlkZGVuUGFzc3dvcmRcbiAgICBhZGRpdGlvbmFsU3NoVmFsaWRSdWxlc1Bhc3M6IFtcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ2VtcHR5JyxcbiAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlRW1wdHlTU0hQYXNzd29yZCxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ21pbkxlbmd0aFs1XScsXG4gICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS5nc19WYWxpZGF0ZVdlYWtTU0hQYXNzd29yZCxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ25vdFJlZ0V4cCcsXG4gICAgICAgICAgICB2YWx1ZTogL1thLXpdLyxcbiAgICAgICAgICAgIHByb21wdDogJzxiPicgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfU1NIUGFzc3dvcmQgKyAnPC9iPjogJyArIGdsb2JhbFRyYW5zbGF0ZS5nc19QYXNzd29yZE5vTG93U2ltdm9sXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICAgIHR5cGU6ICdub3RSZWdFeHAnLFxuICAgICAgICAgICAgdmFsdWU6IC9cXGQvLFxuICAgICAgICAgICAgcHJvbXB0OiAnPGI+JyArIGdsb2JhbFRyYW5zbGF0ZS5nc19TU0hQYXNzd29yZCArICc8L2I+OiAnICsgZ2xvYmFsVHJhbnNsYXRlLmdzX1Bhc3N3b3JkTm9OdW1iZXJzXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICAgIHR5cGU6ICdub3RSZWdFeHAnLFxuICAgICAgICAgICAgdmFsdWU6IC9bQS1aXS8sXG4gICAgICAgICAgICBwcm9tcHQ6ICc8Yj4nICsgZ2xvYmFsVHJhbnNsYXRlLmdzX1NTSFBhc3N3b3JkICsgJzwvYj46ICcgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmROb1VwcGVyU2ltdm9sXG4gICAgICAgIH1cbiAgICBdLFxuXG4gICAgLy8gUnVsZXMgZm9yIHRoZSBTU0ggcGFzc3dvcmQgZmllbGQgd2hlbiBTU0ggbG9naW4gdGhyb3VnaCB0aGUgcGFzc3dvcmQgZGlzYWJsZWRcbiAgICBhZGRpdGlvbmFsU3NoVmFsaWRSdWxlc05vUGFzczogW1xuICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiAnZW1wdHknLFxuICAgICAgICAgICAgcHJvbXB0OiBnbG9iYWxUcmFuc2xhdGUuZ3NfVmFsaWRhdGVFbXB0eVNTSFBhc3N3b3JkLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiAnbWluTGVuZ3RoWzVdJyxcbiAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV2Vha1NTSFBhc3N3b3JkLFxuICAgICAgICB9XG4gICAgXSxcblxuICAgIC8qKlxuICAgICAqICBJbml0aWFsaXplIG1vZHVsZSB3aXRoIGV2ZW50IGJpbmRpbmdzIGFuZCBjb21wb25lbnQgaW5pdGlhbGl6YXRpb25zLlxuICAgICAqL1xuICAgIGluaXRpYWxpemUoKSB7XG5cbiAgICAgICAgLy8gV2hlbiBXZWJBZG1pblBhc3N3b3JkIGlucHV0IGlzIGNoYW5nZWQsIHJlY2FsY3VsYXRlIHRoZSBwYXNzd29yZCBzdHJlbmd0aFxuICAgICAgICBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJHdlYkFkbWluUGFzc3dvcmQub24oJ2tleXVwJywgKCkgPT4ge1xuICAgICAgICAgICAgaWYgKGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kd2ViQWRtaW5QYXNzd29yZC52YWwoKSAhPT0gZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmhpZGRlblBhc3N3b3JkKSB7XG4gICAgICAgICAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmluaXRSdWxlcygpO1xuICAgICAgICAgICAgICAgIFBhc3N3b3JkU2NvcmUuY2hlY2tQYXNzU3RyZW5ndGgoe1xuICAgICAgICAgICAgICAgICAgICBwYXNzOiBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJHdlYkFkbWluUGFzc3dvcmQudmFsKCksXG4gICAgICAgICAgICAgICAgICAgIGJhcjogJCgnLnBhc3N3b3JkLXNjb3JlJyksXG4gICAgICAgICAgICAgICAgICAgIHNlY3Rpb246ICQoJy5wYXNzd29yZC1zY29yZS1zZWN0aW9uJyksXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFdoZW4gU1NIUGFzc3dvcmQgaW5wdXQgaXMgY2hhbmdlZCwgcmVjYWxjdWxhdGUgdGhlIHBhc3N3b3JkIHN0cmVuZ3RoXG4gICAgICAgIGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kc3NoUGFzc3dvcmQub24oJ2tleXVwJywgKCkgPT4ge1xuICAgICAgICAgICAgaWYgKGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kc3NoUGFzc3dvcmQudmFsKCkgIT09IGdlbmVyYWxTZXR0aW5nc01vZGlmeS5oaWRkZW5QYXNzd29yZCkge1xuICAgICAgICAgICAgICAgIGdlbmVyYWxTZXR0aW5nc01vZGlmeS5pbml0UnVsZXMoKTtcbiAgICAgICAgICAgICAgICBQYXNzd29yZFNjb3JlLmNoZWNrUGFzc1N0cmVuZ3RoKHtcbiAgICAgICAgICAgICAgICAgICAgcGFzczogZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LiRzc2hQYXNzd29yZC52YWwoKSxcbiAgICAgICAgICAgICAgICAgICAgYmFyOiAkKCcuc3NoLXBhc3N3b3JkLXNjb3JlJyksXG4gICAgICAgICAgICAgICAgICAgIHNlY3Rpb246ICQoJy5zc2gtcGFzc3dvcmQtc2NvcmUtc2VjdGlvbicpLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBFbmFibGUgdGFiIG5hdmlnYXRpb24gd2l0aCBoaXN0b3J5IHN1cHBvcnRcbiAgICAgICAgJCgnI2dlbmVyYWwtc2V0dGluZ3MtbWVudScpLmZpbmQoJy5pdGVtJykudGFiKHtcbiAgICAgICAgICAgIGhpc3Rvcnk6IHRydWUsXG4gICAgICAgICAgICBoaXN0b3J5VHlwZTogJ2hhc2gnLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBFbmFibGUgZHJvcGRvd25zIG9uIHRoZSBmb3JtXG4gICAgICAgICQoJyNnZW5lcmFsLXNldHRpbmdzLWZvcm0gLmRyb3Bkb3duJykuZHJvcGRvd24oKTtcblxuICAgICAgICAvLyBFbmFibGUgY2hlY2tib3hlcyBvbiB0aGUgZm9ybVxuICAgICAgICAkKCcjZ2VuZXJhbC1zZXR0aW5ncy1mb3JtIC5jaGVja2JveCcpLmNoZWNrYm94KCk7XG5cbiAgICAgICAgLy8gRW5hYmxlIHRhYmxlIGRyYWctbi1kcm9wIGZ1bmN0aW9uYWxpdHlcbiAgICAgICAgJCgnI2F1ZGlvLWNvZGVjcy10YWJsZSwgI3ZpZGVvLWNvZGVjcy10YWJsZScpLnRhYmxlRG5EKHtcbiAgICAgICAgICAgIG9uRHJvcCgpIHtcbiAgICAgICAgICAgICAgICAvLyBUcmlnZ2VyIGNoYW5nZSBldmVudCB0byBhY2tub3dsZWRnZSB0aGUgbW9kaWZpY2F0aW9uXG4gICAgICAgICAgICAgICAgRm9ybS5kYXRhQ2hhbmdlZCgpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9uRHJhZ0NsYXNzOiAnaG92ZXJpbmdSb3cnLFxuICAgICAgICAgICAgZHJhZ0hhbmRsZTogJy5kcmFnSGFuZGxlJyxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gRW5hYmxlIGRyb3Bkb3duIHdpdGggc291bmQgZmlsZSBzZWxlY3Rpb25cbiAgICAgICAgJCgnI2dlbmVyYWwtc2V0dGluZ3MtZm9ybSAuYXVkaW8tbWVzc2FnZS1zZWxlY3QnKS5kcm9wZG93bihTb3VuZEZpbGVzU2VsZWN0b3IuZ2V0RHJvcGRvd25TZXR0aW5nc1dpdGhFbXB0eSgpKTtcblxuICAgICAgICAvLyBJbml0aWFsaXplIHJlY29yZHMgc2F2ZSBwZXJpb2Qgc2xpZGVyXG4gICAgICAgIGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kcmVjb3Jkc1NhdmVQZXJpb2RTbGlkZXJcbiAgICAgICAgICAgIC5zbGlkZXIoe1xuICAgICAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgICAgICBtYXg6IDUsXG4gICAgICAgICAgICAgICAgc3RlcDogMSxcbiAgICAgICAgICAgICAgICBzbW9vdGg6IHRydWUsXG4gICAgICAgICAgICAgICAgaW50ZXJwcmV0TGFiZWw6IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgbGFiZWxzID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAgZ2xvYmFsVHJhbnNsYXRlLmdzX1N0b3JlMU1vbnRoT2ZSZWNvcmRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgZ2xvYmFsVHJhbnNsYXRlLmdzX1N0b3JlM01vbnRoc09mUmVjb3JkcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdsb2JhbFRyYW5zbGF0ZS5nc19TdG9yZTZNb250aHNPZlJlY29yZHMsXG4gICAgICAgICAgICAgICAgICAgICAgICBnbG9iYWxUcmFuc2xhdGUuZ3NfU3RvcmUxWWVhck9mUmVjb3JkcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdsb2JhbFRyYW5zbGF0ZS5nc19TdG9yZTNZZWFyc09mUmVjb3JkcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdsb2JhbFRyYW5zbGF0ZS5nc19TdG9yZUFsbFBvc3NpYmxlUmVjb3JkcyxcbiAgICAgICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGxhYmVsc1t2YWx1ZV07XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBvbkNoYW5nZTogZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmNiQWZ0ZXJTZWxlY3RTYXZlUGVyaW9kU2xpZGVyLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgO1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIGZvcm1cbiAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmluaXRpYWxpemVGb3JtKCk7XG5cbiAgICAgICAgLy8gSW5pdGlhbGl6ZSBhZGRpdGlvbmFsIHZhbGlkYXRpb24gcnVsZXNcbiAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmluaXRSdWxlcygpO1xuXG4gICAgICAgIC8vIFNob3csIGhpZGUgc3NoIHBhc3N3b3JkIHNlZ21lbnRcbiAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LiRkaXNhYmxlU1NIUGFzc3dvcmQuY2hlY2tib3goe1xuICAgICAgICAgICAgJ29uQ2hhbmdlJzogZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LnNob3dIaWRlU1NIUGFzc3dvcmRcbiAgICAgICAgfSk7XG4gICAgICAgIGdlbmVyYWxTZXR0aW5nc01vZGlmeS5zaG93SGlkZVNTSFBhc3N3b3JkKCk7XG5cbiAgICAgICAgLy8gU2V0IHRoZSBpbml0aWFsIHZhbHVlIGZvciB0aGUgcmVjb3JkcyBzYXZlIHBlcmlvZCBzbGlkZXJcbiAgICAgICAgY29uc3QgcmVjb3JkU2F2ZVBlcmlvZCA9IGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kZm9ybU9iai5mb3JtKCdnZXQgdmFsdWUnLCAnUEJYUmVjb3JkU2F2ZVBlcmlvZCcpO1xuICAgICAgICBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJHJlY29yZHNTYXZlUGVyaW9kU2xpZGVyXG4gICAgICAgICAgICAuc2xpZGVyKCdzZXQgdmFsdWUnLCBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuc2F2ZVJlY29yZHNQZXJpb2QuaW5kZXhPZihyZWNvcmRTYXZlUGVyaW9kKSwgZmFsc2UpO1xuXG4gICAgICAgIC8vIEFkZCBldmVudCBsaXN0ZW5lciB0byBoYW5kbGUgdGFiIGFjdGl2YXRpb25cbiAgICAgICAgJCh3aW5kb3cpLm9uKCdHUy1BY3RpdmF0ZVRhYicsIChldmVudCwgbmFtZVRhYikgPT4ge1xuICAgICAgICAgICAgJCgnI2dlbmVyYWwtc2V0dGluZ3MtbWVudScpLmZpbmQoJy5pdGVtJykudGFiKCdjaGFuZ2UgdGFiJywgbmFtZVRhYik7XG4gICAgICAgIH0pO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBTaG93LCBoaWRlIHNzaCBwYXNzd29yZCBzZWdtZW50IGFjY29yZGluZyB0byB0aGUgdmFsdWUgb2YgdXNlIFNTSCBwYXNzd29yZCBjaGVja2JveC5cbiAgICAgKi9cbiAgICBzaG93SGlkZVNTSFBhc3N3b3JkKCl7XG4gICAgICAgIGlmIChnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJGRpc2FibGVTU0hQYXNzd29yZC5jaGVja2JveCgnaXMgY2hlY2tlZCcpKSB7XG4gICAgICAgICAgICBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJHNzaFBhc3N3b3JkU2VnbWVudC5oaWRlKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJHNzaFBhc3N3b3JkU2VnbWVudC5zaG93KCk7XG4gICAgICAgIH1cbiAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmluaXRSdWxlcygpO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGNvbmRpdGlvbnMgZm9yIGRlbGV0aW5nIGFsbCByZWNvcmRzLlxuICAgICAqIENvbXBhcmVzIHRoZSB2YWx1ZSBvZiB0aGUgJ2RlbGV0ZUFsbElucHV0JyBmaWVsZCB3aXRoIGEgcGhyYXNlLlxuICAgICAqIElmIHRoZXkgbWF0Y2gsIGl0IHRyaWdnZXJzIGEgc3lzdGVtIHJlc3RvcmUgdG8gZGVmYXVsdCBzZXR0aW5ncy5cbiAgICAgKi9cbiAgICBjaGVja0RlbGV0ZUFsbENvbmRpdGlvbnMoKSB7XG5cbiAgICAgICAgLy8gR2V0IHRoZSB2YWx1ZSBvZiAnZGVsZXRlQWxsSW5wdXQnIGZpZWxkLlxuICAgICAgICBjb25zdCBkZWxldGVBbGxJbnB1dCA9IGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kZm9ybU9iai5mb3JtKCdnZXQgdmFsdWUnLCAnZGVsZXRlQWxsSW5wdXQnKTtcblxuICAgICAgICAvLyBJZiB0aGUgZW50ZXJlZCBwaHJhc2UgbWF0Y2hlcyB0aGUgcGhyYXNlIGluICdnbG9iYWxUcmFuc2xhdGUuZ3NfRW50ZXJEZWxldGVBbGxQaHJhc2UnLFxuICAgICAgICAvLyBjYWxsICdQYnhBcGkuU3lzdGVtUmVzdG9yZURlZmF1bHRTZXR0aW5ncycgdG8gcmVzdG9yZSBkZWZhdWx0IHNldHRpbmdzLlxuICAgICAgICBpZiAoZGVsZXRlQWxsSW5wdXQgPT09IGdsb2JhbFRyYW5zbGF0ZS5nc19FbnRlckRlbGV0ZUFsbFBocmFzZSkge1xuICAgICAgICAgICAgUGJ4QXBpLlN5c3RlbVJlc3RvcmVEZWZhdWx0U2V0dGluZ3MoZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmNiQWZ0ZXJSZXN0b3JlRGVmYXVsdFNldHRpbmdzKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGUgcmVzcG9uc2UgYWZ0ZXIgcmVzdG9yaW5nIGRlZmF1bHQgc2V0dGluZ3MuXG4gICAgICogQHBhcmFtIHtib29sZWFufHN0cmluZ30gcmVzcG9uc2UgLSBSZXNwb25zZSBmcm9tIHRoZSBzZXJ2ZXIgYWZ0ZXIgcmVzdG9yaW5nIGRlZmF1bHQgc2V0dGluZ3MuXG4gICAgICovXG4gICAgY2JBZnRlclJlc3RvcmVEZWZhdWx0U2V0dGluZ3MocmVzcG9uc2UpIHtcblxuICAgICAgICAvLyBDaGVjayBpZiB0aGUgcmVzcG9uc2UgaXMgdHJ1ZSwgZGlzcGxheSBhIHN1Y2Nlc3MgbWVzc2FnZVxuICAgICAgICAvLyBvdGhlcndpc2UsIGRpc3BsYXkgdGhlIHJlc3BvbnNlIG1lc3NhZ2UuXG4gICAgICAgIGlmIChyZXNwb25zZSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgVXNlck1lc3NhZ2Uuc2hvd0luZm9ybWF0aW9uKGdsb2JhbFRyYW5zbGF0ZS5nc19BbGxTZXR0aW5nc0RlbGV0ZWQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgVXNlck1lc3NhZ2Uuc2hvd011bHRpU3RyaW5nKHJlc3BvbnNlKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGUgZXZlbnQgYWZ0ZXIgdGhlIHNlbGVjdCBzYXZlIHBlcmlvZCBzbGlkZXIgaXMgY2hhbmdlZC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgLSBUaGUgc2VsZWN0ZWQgdmFsdWUgZnJvbSB0aGUgc2xpZGVyLlxuICAgICAqL1xuICAgIGNiQWZ0ZXJTZWxlY3RTYXZlUGVyaW9kU2xpZGVyKHZhbHVlKSB7XG5cbiAgICAgICAgLy8gR2V0IHRoZSBzYXZlIHBlcmlvZCBjb3JyZXNwb25kaW5nIHRvIHRoZSBzbGlkZXIgdmFsdWUuXG4gICAgICAgIGNvbnN0IHNhdmVQZXJpb2QgPSBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuc2F2ZVJlY29yZHNQZXJpb2RbdmFsdWVdO1xuXG4gICAgICAgIC8vIFNldCB0aGUgZm9ybSB2YWx1ZSBmb3IgJ1BCWFJlY29yZFNhdmVQZXJpb2QnIHRvIHRoZSBzZWxlY3RlZCBzYXZlIHBlcmlvZC5cbiAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LiRmb3JtT2JqLmZvcm0oJ3NldCB2YWx1ZScsICdQQlhSZWNvcmRTYXZlUGVyaW9kJywgc2F2ZVBlcmlvZCk7XG5cbiAgICAgICAgLy8gVHJpZ2dlciBjaGFuZ2UgZXZlbnQgdG8gYWNrbm93bGVkZ2UgdGhlIG1vZGlmaWNhdGlvblxuICAgICAgICBGb3JtLmRhdGFDaGFuZ2VkKCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIENhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCBiZWZvcmUgdGhlIGZvcm0gaXMgc2VudFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzZXR0aW5ncyAtIFRoZSBjdXJyZW50IHNldHRpbmdzIG9mIHRoZSBmb3JtXG4gICAgICogQHJldHVybnMge09iamVjdH0gLSBUaGUgdXBkYXRlZCBzZXR0aW5ncyBvZiB0aGUgZm9ybVxuICAgICAqL1xuICAgIGNiQmVmb3JlU2VuZEZvcm0oc2V0dGluZ3MpIHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gc2V0dGluZ3M7XG4gICAgICAgIHJlc3VsdC5kYXRhID0gZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LiRmb3JtT2JqLmZvcm0oJ2dldCB2YWx1ZXMnKTtcbiAgICAgICAgY29uc3QgYXJyQ29kZWNzID0gW107XG4gICAgICAgICQoJyNhdWRpby1jb2RlY3MtdGFibGUgLmNvZGVjLXJvdywgI3ZpZGVvLWNvZGVjcy10YWJsZSAuY29kZWMtcm93JykuZWFjaCgoaW5kZXgsIG9iaikgPT4ge1xuICAgICAgICAgICAgaWYgKCQob2JqKS5hdHRyKCdpZCcpKSB7XG4gICAgICAgICAgICAgICAgYXJyQ29kZWNzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBjb2RlY0lkOiAkKG9iaikuYXR0cignaWQnKSxcbiAgICAgICAgICAgICAgICAgICAgZGlzYWJsZWQ6ICQob2JqKS5maW5kKCcuY2hlY2tib3gnKS5jaGVja2JveCgnaXMgdW5jaGVja2VkJyksXG4gICAgICAgICAgICAgICAgICAgIHByaW9yaXR5OiBpbmRleCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJlc3VsdC5kYXRhLmNvZGVjcyA9IEpTT04uc3RyaW5naWZ5KGFyckNvZGVjcyk7XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQ2FsbGJhY2sgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIGFmdGVyIHRoZSBmb3JtIGhhcyBiZWVuIHNlbnQuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHJlc3BvbnNlIC0gVGhlIHJlc3BvbnNlIGZyb20gdGhlIHNlcnZlciBhZnRlciB0aGUgZm9ybSBpcyBzZW50XG4gICAgICovXG4gICAgY2JBZnRlclNlbmRGb3JtKHJlc3BvbnNlKSB7XG4gICAgICAgIGlmICghcmVzcG9uc2Uuc3VjY2Vzcykge1xuICAgICAgICAgICAgRm9ybS4kc3VibWl0QnV0dG9uLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgJCgnLnBhc3N3b3JkLXZhbGlkYXRlJykucmVtb3ZlKCk7XG4gICAgICAgIH1cbiAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmNoZWNrRGVsZXRlQWxsQ29uZGl0aW9ucygpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplIHRoZSB2YWxpZGF0aW9uIHJ1bGVzIG9mIHRoZSBmb3JtXG4gICAgICovXG4gICAgaW5pdFJ1bGVzKCkge1xuICAgICAgICAvLyBTU0hQYXNzd29yZFxuICAgICAgICBpZiAoZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LiRkaXNhYmxlU1NIUGFzc3dvcmQuY2hlY2tib3goJ2lzIGNoZWNrZWQnKSkge1xuICAgICAgICAgICAgRm9ybS52YWxpZGF0ZVJ1bGVzLlNTSFBhc3N3b3JkLnJ1bGVzID0gZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmFkZGl0aW9uYWxTc2hWYWxpZFJ1bGVzTm9QYXNzO1xuICAgICAgICB9IGVsc2UgaWYgKGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kc3NoUGFzc3dvcmQudmFsKCkgPT09IGdlbmVyYWxTZXR0aW5nc01vZGlmeS5oaWRkZW5QYXNzd29yZCkge1xuICAgICAgICAgICAgRm9ybS52YWxpZGF0ZVJ1bGVzLlNTSFBhc3N3b3JkLnJ1bGVzID0gW107XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBGb3JtLnZhbGlkYXRlUnVsZXMuU1NIUGFzc3dvcmQucnVsZXMgPSBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuYWRkaXRpb25hbFNzaFZhbGlkUnVsZXNQYXNzO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gV2ViQWRtaW5QYXNzd29yZFxuICAgICAgICBpZiAoZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LiR3ZWJBZG1pblBhc3N3b3JkLnZhbCgpID09PSBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuaGlkZGVuUGFzc3dvcmQpIHtcbiAgICAgICAgICAgIEZvcm0udmFsaWRhdGVSdWxlcy5XZWJBZG1pblBhc3N3b3JkLnJ1bGVzID0gW107XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBGb3JtLnZhbGlkYXRlUnVsZXMuV2ViQWRtaW5QYXNzd29yZC5ydWxlcyA9IGdlbmVyYWxTZXR0aW5nc01vZGlmeS53ZWJBZG1pblBhc3N3b3JkUnVsZXM7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZSB0aGUgZm9ybSB3aXRoIGN1c3RvbSBzZXR0aW5nc1xuICAgICAqL1xuICAgIGluaXRpYWxpemVGb3JtKCkge1xuICAgICAgICBGb3JtLiRmb3JtT2JqID0gZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LiRmb3JtT2JqO1xuICAgICAgICBGb3JtLnVybCA9IGAke2dsb2JhbFJvb3RVcmx9Z2VuZXJhbC1zZXR0aW5ncy9zYXZlYDsgLy8gRm9ybSBzdWJtaXNzaW9uIFVSTFxuICAgICAgICBGb3JtLnZhbGlkYXRlUnVsZXMgPSBnZW5lcmFsU2V0dGluZ3NNb2RpZnkudmFsaWRhdGVSdWxlczsgLy8gRm9ybSB2YWxpZGF0aW9uIHJ1bGVzXG4gICAgICAgIEZvcm0uY2JCZWZvcmVTZW5kRm9ybSA9IGdlbmVyYWxTZXR0aW5nc01vZGlmeS5jYkJlZm9yZVNlbmRGb3JtOyAvLyBDYWxsYmFjayBiZWZvcmUgZm9ybSBpcyBzZW50XG4gICAgICAgIEZvcm0uY2JBZnRlclNlbmRGb3JtID0gZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmNiQWZ0ZXJTZW5kRm9ybTsgLy8gQ2FsbGJhY2sgYWZ0ZXIgZm9ybSBpcyBzZW50XG4gICAgICAgIEZvcm0uaW5pdGlhbGl6ZSgpO1xuICAgIH1cbn07XG5cbi8vIFdoZW4gdGhlIGRvY3VtZW50IGlzIHJlYWR5LCBpbml0aWFsaXplIHRoZSBnZW5lcmFsU2V0dGluZ3MgbWFuYWdlbWVudCBpbnRlcmZhY2UuXG4kKGRvY3VtZW50KS5yZWFkeSgoKSA9PiB7XG4gICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmluaXRpYWxpemUoKTtcbn0pOyJdfQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9HZW5lcmFsU2V0dGluZ3MvZ2VuZXJhbC1zZXR0aW5ncy1tb2RpZnkuanMiXSwibmFtZXMiOlsiZ2VuZXJhbFNldHRpbmdzTW9kaWZ5IiwiJGZvcm1PYmoiLCIkIiwiJHdlYkFkbWluUGFzc3dvcmQiLCIkc3NoUGFzc3dvcmQiLCIkZGlzYWJsZVNTSFBhc3N3b3JkIiwicGFyZW50IiwiJHNzaFBhc3N3b3JkU2VnbWVudCIsImhpZGRlblBhc3N3b3JkIiwiJHJlY29yZHNTYXZlUGVyaW9kU2xpZGVyIiwic2F2ZVJlY29yZHNQZXJpb2QiLCJ2YWxpZGF0ZVJ1bGVzIiwicGJ4bmFtZSIsImlkZW50aWZpZXIiLCJydWxlcyIsInR5cGUiLCJwcm9tcHQiLCJnbG9iYWxUcmFuc2xhdGUiLCJnc19WYWxpZGF0ZUVtcHR5UEJYTmFtZSIsIldlYkFkbWluUGFzc3dvcmQiLCJXZWJBZG1pblBhc3N3b3JkUmVwZWF0IiwiZ3NfVmFsaWRhdGVXZWJQYXNzd29yZHNGaWVsZERpZmZlcmVudCIsIlNTSFBhc3N3b3JkIiwiU1NIUGFzc3dvcmRSZXBlYXQiLCJnc19WYWxpZGF0ZVNTSFBhc3N3b3Jkc0ZpZWxkRGlmZmVyZW50IiwiV0VCUG9ydCIsImdzX1ZhbGlkYXRlV0VCUG9ydE91dE9mUmFuZ2UiLCJnc19WYWxpZGF0ZVdFQkhUVFBTUG9ydE5vdEVxdWFsVG9XRUJQb3J0IiwiZ3NfVmFsaWRhdGVXRUJQb3J0Tm90RXF1YWxUb0FqYW1Qb3J0IiwiZ3NfVmFsaWRhdGVXRUJQb3J0Tm90RXF1YWxUb0FqYW1UTFNQb3J0IiwiV0VCSFRUUFNQb3J0IiwiZ3NfVmFsaWRhdGVXRUJIVFRQU1BvcnRPdXRPZlJhbmdlIiwiZ3NfVmFsaWRhdGVXRUJIVFRQU1BvcnROb3RFcXVhbFRvQWphbVBvcnQiLCJnc19WYWxpZGF0ZVdFQkhUVFBTUG9ydE5vdEVxdWFsVG9BamFtVExTUG9ydCIsIkFKQU1Qb3J0IiwiZ3NfVmFsaWRhdGVBSkFNUG9ydE91dE9mUmFuZ2UiLCJ3ZWJBZG1pblBhc3N3b3JkUnVsZXMiLCJnc19WYWxpZGF0ZUVtcHR5V2ViUGFzc3dvcmQiLCJnc19WYWxpZGF0ZVdlYWtXZWJQYXNzd29yZCIsInZhbHVlIiwiZ3NfUGFzc3dvcmRzIiwiZ3NfUGFzc3dvcmROb0xvd1NpbXZvbCIsImdzX1Bhc3N3b3JkTm9OdW1iZXJzIiwiZ3NfUGFzc3dvcmROb1VwcGVyU2ltdm9sIiwiYWRkaXRpb25hbFNzaFZhbGlkUnVsZXNQYXNzIiwiZ3NfVmFsaWRhdGVFbXB0eVNTSFBhc3N3b3JkIiwiZ3NfVmFsaWRhdGVXZWFrU1NIUGFzc3dvcmQiLCJnc19TU0hQYXNzd29yZCIsImFkZGl0aW9uYWxTc2hWYWxpZFJ1bGVzTm9QYXNzIiwiaW5pdGlhbGl6ZSIsIm9uIiwidmFsIiwiaW5pdFJ1bGVzIiwiUGFzc3dvcmRTY29yZSIsImNoZWNrUGFzc1N0cmVuZ3RoIiwicGFzcyIsImJhciIsInNlY3Rpb24iLCJmaW5kIiwidGFiIiwiaGlzdG9yeSIsImhpc3RvcnlUeXBlIiwiZHJvcGRvd24iLCJjaGVja2JveCIsInRhYmxlRG5EIiwib25Ecm9wIiwiRm9ybSIsImRhdGFDaGFuZ2VkIiwib25EcmFnQ2xhc3MiLCJkcmFnSGFuZGxlIiwiU291bmRGaWxlc1NlbGVjdG9yIiwiZ2V0RHJvcGRvd25TZXR0aW5nc1dpdGhFbXB0eSIsInNsaWRlciIsIm1pbiIsIm1heCIsInN0ZXAiLCJzbW9vdGgiLCJpbnRlcnByZXRMYWJlbCIsImxhYmVscyIsImdzX1N0b3JlMU1vbnRoT2ZSZWNvcmRzIiwiZ3NfU3RvcmUzTW9udGhzT2ZSZWNvcmRzIiwiZ3NfU3RvcmU2TW9udGhzT2ZSZWNvcmRzIiwiZ3NfU3RvcmUxWWVhck9mUmVjb3JkcyIsImdzX1N0b3JlM1llYXJzT2ZSZWNvcmRzIiwiZ3NfU3RvcmVBbGxQb3NzaWJsZVJlY29yZHMiLCJvbkNoYW5nZSIsImNiQWZ0ZXJTZWxlY3RTYXZlUGVyaW9kU2xpZGVyIiwiaW5pdGlhbGl6ZUZvcm0iLCJzaG93SGlkZVNTSFBhc3N3b3JkIiwicmVjb3JkU2F2ZVBlcmlvZCIsImZvcm0iLCJpbmRleE9mIiwid2luZG93IiwiZXZlbnQiLCJuYW1lVGFiIiwiaGlkZSIsInNob3ciLCJjaGVja0RlbGV0ZUFsbENvbmRpdGlvbnMiLCJkZWxldGVBbGxJbnB1dCIsImdzX0VudGVyRGVsZXRlQWxsUGhyYXNlIiwiUGJ4QXBpIiwiU3lzdGVtUmVzdG9yZURlZmF1bHRTZXR0aW5ncyIsImNiQWZ0ZXJSZXN0b3JlRGVmYXVsdFNldHRpbmdzIiwicmVzcG9uc2UiLCJVc2VyTWVzc2FnZSIsInNob3dJbmZvcm1hdGlvbiIsImdzX0FsbFNldHRpbmdzRGVsZXRlZCIsInNob3dNdWx0aVN0cmluZyIsInNhdmVQZXJpb2QiLCJjYkJlZm9yZVNlbmRGb3JtIiwic2V0dGluZ3MiLCJyZXN1bHQiLCJkYXRhIiwiYXJyQ29kZWNzIiwiZWFjaCIsImluZGV4Iiwib2JqIiwiYXR0ciIsInB1c2giLCJjb2RlY0lkIiwiZGlzYWJsZWQiLCJwcmlvcml0eSIsImNvZGVjcyIsIkpTT04iLCJzdHJpbmdpZnkiLCJjYkFmdGVyU2VuZEZvcm0iLCJyZW1vdmUiLCJzdWNjZXNzIiwiJHN1Ym1pdEJ1dHRvbiIsInJlbW92ZUNsYXNzIiwiZ2VuZXJhdGVFcnJvck1lc3NhZ2VIdG1sIiwibWVzc2FnZXMiLCJlcnJvciIsIiRkaXYiLCJpZCIsIiRoZWFkZXIiLCJ0ZXh0IiwiZ3NfRXJyb3JTYXZlU2V0dGluZ3MiLCJhcHBlbmQiLCIkdWwiLCJtZXNzYWdlc1NldCIsIlNldCIsImZvckVhY2giLCJlcnJvckFycmF5IiwidGV4dENvbnRlbnQiLCJtZXNzYWdlIiwidW5kZWZpbmVkIiwiaGFzIiwiYWRkIiwiYmVmb3JlIiwidXJsIiwiZ2xvYmFsUm9vdFVybCIsImRvY3VtZW50IiwicmVhZHkiXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFHQTs7QUFFQTtBQUNB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dkQsYUFBTCxHQUFxQlgscUJBQXFCLENBQUNXLGFBQTNDLENBSGEsQ0FHNkM7O0FBQzFEdUQsSUFBQUEsSUFBSSxDQUFDMkMsZ0JBQUwsR0FBd0I3RyxxQkFBcUIsQ0FBQzZHLGdCQUE5QyxDQUphLENBSW1EOztBQUNoRTNDLElBQUFBLElBQUksQ0FBQzJELGVBQUwsR0FBdUI3SCxxQkFBcUIsQ0FBQzZILGVBQTdDLENBTGEsQ0FLaUQ7O0FBQzlEM0QsSUFBQUEsSUFBSSxDQUFDakIsVUFBTDtBQUNIO0FBdGR5QixDQUE5QixDLENBeWRBOztBQUNBL0MsQ0FBQyxDQUFDc0osUUFBRCxDQUFELENBQVlDLEtBQVosQ0FBa0IsWUFBTTtBQUNwQnpKLEVBQUFBLHFCQUFxQixDQUFDaUQsVUFBdEI7QUFDSCxDQUZEIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIE1pa29QQlggLSBmcmVlIHBob25lIHN5c3RlbSBmb3Igc21hbGwgYnVzaW5lc3NcbiAqIENvcHlyaWdodCDCqSAyMDE3LTIwMjMgQWxleGV5IFBvcnRub3YgYW5kIE5pa29sYXkgQmVrZXRvdlxuICpcbiAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbS5cbiAqIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKi9cblxuXG4vKiBnbG9iYWwgZ2xvYmFsUm9vdFVybCxnbG9iYWxUcmFuc2xhdGUsIEZvcm0sIFBhc3N3b3JkU2NvcmUsIFBieEFwaSwgVXNlck1lc3NhZ2UsIFNvdW5kRmlsZXNTZWxlY3RvciwgJCAqL1xuXG4vKipcbiAqIEEgbW9kdWxlIHRvIGhhbmRsZSBtb2RpZmljYXRpb24gb2YgZ2VuZXJhbCBzZXR0aW5ncy5cbiAqL1xuY29uc3QgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5ID0ge1xuICAgIC8qKlxuICAgICAqIGpRdWVyeSBvYmplY3QgZm9yIHRoZSBmb3JtLlxuICAgICAqIEB0eXBlIHtqUXVlcnl9XG4gICAgICovXG4gICAgJGZvcm1PYmo6ICQoJyNnZW5lcmFsLXNldHRpbmdzLWZvcm0nKSxcblxuICAgIC8qKlxuICAgICAqIGpRdWVyeSBvYmplY3QgZm9yIHRoZSB3ZWIgYWRtaW4gcGFzc3dvcmQgaW5wdXQgZmllbGQuXG4gICAgICogQHR5cGUge2pRdWVyeX1cbiAgICAgKi9cbiAgICAkd2ViQWRtaW5QYXNzd29yZDogJCgnI1dlYkFkbWluUGFzc3dvcmQnKSxcblxuICAgIC8qKlxuICAgICAqIGpRdWVyeSBvYmplY3QgZm9yIHRoZSBzc2ggcGFzc3dvcmQgaW5wdXQgZmllbGQuXG4gICAgICogQHR5cGUge2pRdWVyeX1cbiAgICAgKi9cbiAgICAkc3NoUGFzc3dvcmQ6ICQoJyNTU0hQYXNzd29yZCcpLFxuXG4gICAgLyoqXG4gICAgICogalF1ZXJ5IG9iamVjdCBmb3IgdGhlIHdlYiBzc2ggcGFzc3dvcmQgaW5wdXQgZmllbGQuXG4gICAgICogQHR5cGUge2pRdWVyeX1cbiAgICAgKi9cbiAgICAkZGlzYWJsZVNTSFBhc3N3b3JkOiAkKCcjU1NIRGlzYWJsZVBhc3N3b3JkTG9naW5zJykucGFyZW50KCcuY2hlY2tib3gnKSxcblxuICAgIC8qKlxuICAgICAqIGpRdWVyeSBvYmplY3QgZm9yIHRoZSBTU0ggcGFzc3dvcmQgZmllbGRzXG4gICAgICogQHR5cGUge2pRdWVyeX1cbiAgICAgKi9cbiAgICAkc3NoUGFzc3dvcmRTZWdtZW50OiAkKCcjb25seS1pZi1wYXNzd29yZC1lbmFibGVkJyksXG5cbiAgICAvKipcbiAgICAgKiBJZiBwYXNzd29yZCBzZXQsIGl0IHdpbGwgYmUgaGlkZWQgZnJvbSB3ZWIgdWkuXG4gICAgICovXG4gICAgaGlkZGVuUGFzc3dvcmQ6ICd4eHh4eHh4JyxcblxuICAgIC8qKlxuICAgICAqIGpRdWVyeSBvYmplY3QgZm9yIHRoZSByZWNvcmRzIHJldGVudGlvbiBwZXJpb2Qgc2xpZGVyLlxuICAgICAqIEB0eXBlIHtqUXVlcnl9XG4gICAgICovXG4gICAgJHJlY29yZHNTYXZlUGVyaW9kU2xpZGVyOiAkKCcjUEJYUmVjb3JkU2F2ZVBlcmlvZFNsaWRlcicpLFxuXG4gICAgLyoqXG4gICAgICogUG9zc2libGUgcGVyaW9kIHZhbHVlcyBmb3IgdGhlIHJlY29yZHMgcmV0ZW50aW9uLlxuICAgICAqL1xuICAgIHNhdmVSZWNvcmRzUGVyaW9kOiBbJzMwJywgJzkwJywgJzE4MCcsICczNjAnLCAnMTA4MCcsICcnXSxcblxuICAgIC8qKlxuICAgICAqIFZhbGlkYXRpb24gcnVsZXMgZm9yIHRoZSBmb3JtIGZpZWxkcyBiZWZvcmUgc3VibWlzc2lvbi5cbiAgICAgKlxuICAgICAqIEB0eXBlIHtvYmplY3R9XG4gICAgICovXG4gICAgdmFsaWRhdGVSdWxlczogeyAvLyBnZW5lcmFsU2V0dGluZ3NNb2RpZnkudmFsaWRhdGVSdWxlcy5TU0hQYXNzd29yZC5ydWxlc1xuICAgICAgICBwYnhuYW1lOiB7XG4gICAgICAgICAgICBpZGVudGlmaWVyOiAnUEJYTmFtZScsXG4gICAgICAgICAgICBydWxlczogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2VtcHR5JyxcbiAgICAgICAgICAgICAgICAgICAgcHJvbXB0OiBnbG9iYWxUcmFuc2xhdGUuZ3NfVmFsaWRhdGVFbXB0eVBCWE5hbWUsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICAgIFdlYkFkbWluUGFzc3dvcmQ6IHtcbiAgICAgICAgICAgIGlkZW50aWZpZXI6ICdXZWJBZG1pblBhc3N3b3JkJyxcbiAgICAgICAgICAgIHJ1bGVzOiBbXSxcbiAgICAgICAgfSxcbiAgICAgICAgV2ViQWRtaW5QYXNzd29yZFJlcGVhdDoge1xuICAgICAgICAgICAgaWRlbnRpZmllcjogJ1dlYkFkbWluUGFzc3dvcmRSZXBlYXQnLFxuICAgICAgICAgICAgcnVsZXM6IFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdtYXRjaFtXZWJBZG1pblBhc3N3b3JkXScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV2ViUGFzc3dvcmRzRmllbGREaWZmZXJlbnQsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICAgIFNTSFBhc3N3b3JkOiB7XG4gICAgICAgICAgICBpZGVudGlmaWVyOiAnU1NIUGFzc3dvcmQnLFxuICAgICAgICAgICAgcnVsZXM6IFtdLFxuICAgICAgICB9LFxuICAgICAgICBTU0hQYXNzd29yZFJlcGVhdDoge1xuICAgICAgICAgICAgaWRlbnRpZmllcjogJ1NTSFBhc3N3b3JkUmVwZWF0JyxcbiAgICAgICAgICAgIHJ1bGVzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnbWF0Y2hbU1NIUGFzc3dvcmRdJyxcbiAgICAgICAgICAgICAgICAgICAgcHJvbXB0OiBnbG9iYWxUcmFuc2xhdGUuZ3NfVmFsaWRhdGVTU0hQYXNzd29yZHNGaWVsZERpZmZlcmVudCxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgICAgV0VCUG9ydDoge1xuICAgICAgICAgICAgaWRlbnRpZmllcjogJ1dFQlBvcnQnLFxuICAgICAgICAgICAgcnVsZXM6IFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdpbnRlZ2VyWzEuLjY1NTM1XScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV0VCUG9ydE91dE9mUmFuZ2UsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdkaWZmZXJlbnRbV0VCSFRUUFNQb3J0XScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV0VCSFRUUFNQb3J0Tm90RXF1YWxUb1dFQlBvcnQsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdkaWZmZXJlbnRbQUpBTVBvcnRUTFNdJyxcbiAgICAgICAgICAgICAgICAgICAgcHJvbXB0OiBnbG9iYWxUcmFuc2xhdGUuZ3NfVmFsaWRhdGVXRUJQb3J0Tm90RXF1YWxUb0FqYW1Qb3J0LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnZGlmZmVyZW50W0FKQU1Qb3J0XScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV0VCUG9ydE5vdEVxdWFsVG9BamFtVExTUG9ydCxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgICAgV0VCSFRUUFNQb3J0OiB7XG4gICAgICAgICAgICBpZGVudGlmaWVyOiAnV0VCSFRUUFNQb3J0JyxcbiAgICAgICAgICAgIHJ1bGVzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnaW50ZWdlclsxLi42NTUzNV0nLFxuICAgICAgICAgICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS5nc19WYWxpZGF0ZVdFQkhUVFBTUG9ydE91dE9mUmFuZ2UsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdkaWZmZXJlbnRbV0VCUG9ydF0nLFxuICAgICAgICAgICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS5nc19WYWxpZGF0ZVdFQkhUVFBTUG9ydE5vdEVxdWFsVG9XRUJQb3J0LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnZGlmZmVyZW50W0FKQU1Qb3J0VExTXScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV0VCSFRUUFNQb3J0Tm90RXF1YWxUb0FqYW1Qb3J0LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnZGlmZmVyZW50W0FKQU1Qb3J0XScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV0VCSFRUUFNQb3J0Tm90RXF1YWxUb0FqYW1UTFNQb3J0LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgICBBSkFNUG9ydDoge1xuICAgICAgICAgICAgaWRlbnRpZmllcjogJ0FKQU1Qb3J0JyxcbiAgICAgICAgICAgIHJ1bGVzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnaW50ZWdlclsxLi42NTUzNV0nLFxuICAgICAgICAgICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS5nc19WYWxpZGF0ZUFKQU1Qb3J0T3V0T2ZSYW5nZSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2RpZmZlcmVudFtBSkFNUG9ydFRMU10nLFxuICAgICAgICAgICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS5nc19WYWxpZGF0ZUFKQU1Qb3J0T3V0T2ZSYW5nZSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICB9LFxuXG4gICAgLy8gUnVsZXMgZm9yIHRoZSB3ZWIgYWRtaW4gcGFzc3dvcmQgZmllbGQgd2hlbiBpdCBub3QgZXF1YWwgdG8gaGlkZGVuUGFzc3dvcmRcbiAgICB3ZWJBZG1pblBhc3N3b3JkUnVsZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ2VtcHR5JyxcbiAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlRW1wdHlXZWJQYXNzd29yZCxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ21pbkxlbmd0aFs1XScsXG4gICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS5nc19WYWxpZGF0ZVdlYWtXZWJQYXNzd29yZCxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ25vdFJlZ0V4cCcsXG4gICAgICAgICAgICB2YWx1ZTogL1thLXpdLyxcbiAgICAgICAgICAgIHByb21wdDogJzxiPicgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmRzICsgJzwvYj46ICcgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmROb0xvd1NpbXZvbFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiAnbm90UmVnRXhwJyxcbiAgICAgICAgICAgIHZhbHVlOiAvXFxkLyxcbiAgICAgICAgICAgIHByb21wdDogJzxiPicgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmRzICsgJzwvYj46ICcgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmROb051bWJlcnNcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ25vdFJlZ0V4cCcsXG4gICAgICAgICAgICB2YWx1ZTogL1tBLVpdLyxcbiAgICAgICAgICAgIHByb21wdDogJzxiPicgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmRzICsgJzwvYj46ICcgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmROb1VwcGVyU2ltdm9sXG4gICAgICAgIH1cbiAgICBdLFxuICAgIC8vIFJ1bGVzIGZvciB0aGUgU1NIIHBhc3N3b3JkIGZpZWxkIHdoZW4gU1NIIGxvZ2luIHRocm91Z2ggdGhlIHBhc3N3b3JkIGVuYWJsZWQsIGFuZCBpdCBub3QgZXF1YWwgdG8gaGlkZGVuUGFzc3dvcmRcbiAgICBhZGRpdGlvbmFsU3NoVmFsaWRSdWxlc1Bhc3M6IFtcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ2VtcHR5JyxcbiAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlRW1wdHlTU0hQYXNzd29yZCxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ21pbkxlbmd0aFs1XScsXG4gICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS5nc19WYWxpZGF0ZVdlYWtTU0hQYXNzd29yZCxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ25vdFJlZ0V4cCcsXG4gICAgICAgICAgICB2YWx1ZTogL1thLXpdLyxcbiAgICAgICAgICAgIHByb21wdDogJzxiPicgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfU1NIUGFzc3dvcmQgKyAnPC9iPjogJyArIGdsb2JhbFRyYW5zbGF0ZS5nc19QYXNzd29yZE5vTG93U2ltdm9sXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICAgIHR5cGU6ICdub3RSZWdFeHAnLFxuICAgICAgICAgICAgdmFsdWU6IC9cXGQvLFxuICAgICAgICAgICAgcHJvbXB0OiAnPGI+JyArIGdsb2JhbFRyYW5zbGF0ZS5nc19TU0hQYXNzd29yZCArICc8L2I+OiAnICsgZ2xvYmFsVHJhbnNsYXRlLmdzX1Bhc3N3b3JkTm9OdW1iZXJzXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICAgIHR5cGU6ICdub3RSZWdFeHAnLFxuICAgICAgICAgICAgdmFsdWU6IC9bQS1aXS8sXG4gICAgICAgICAgICBwcm9tcHQ6ICc8Yj4nICsgZ2xvYmFsVHJhbnNsYXRlLmdzX1NTSFBhc3N3b3JkICsgJzwvYj46ICcgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmROb1VwcGVyU2ltdm9sXG4gICAgICAgIH1cbiAgICBdLFxuXG4gICAgLy8gUnVsZXMgZm9yIHRoZSBTU0ggcGFzc3dvcmQgZmllbGQgd2hlbiBTU0ggbG9naW4gdGhyb3VnaCB0aGUgcGFzc3dvcmQgZGlzYWJsZWRcbiAgICBhZGRpdGlvbmFsU3NoVmFsaWRSdWxlc05vUGFzczogW1xuICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiAnZW1wdHknLFxuICAgICAgICAgICAgcHJvbXB0OiBnbG9iYWxUcmFuc2xhdGUuZ3NfVmFsaWRhdGVFbXB0eVNTSFBhc3N3b3JkLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiAnbWluTGVuZ3RoWzVdJyxcbiAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV2Vha1NTSFBhc3N3b3JkLFxuICAgICAgICB9XG4gICAgXSxcblxuICAgIC8qKlxuICAgICAqICBJbml0aWFsaXplIG1vZHVsZSB3aXRoIGV2ZW50IGJpbmRpbmdzIGFuZCBjb21wb25lbnQgaW5pdGlhbGl6YXRpb25zLlxuICAgICAqL1xuICAgIGluaXRpYWxpemUoKSB7XG5cbiAgICAgICAgLy8gV2hlbiBXZWJBZG1pblBhc3N3b3JkIGlucHV0IGlzIGNoYW5nZWQsIHJlY2FsY3VsYXRlIHRoZSBwYXNzd29yZCBzdHJlbmd0aFxuICAgICAgICBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJHdlYkFkbWluUGFzc3dvcmQub24oJ2tleXVwJywgKCkgPT4ge1xuICAgICAgICAgICAgaWYgKGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kd2ViQWRtaW5QYXNzd29yZC52YWwoKSAhPT0gZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmhpZGRlblBhc3N3b3JkKSB7XG4gICAgICAgICAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmluaXRSdWxlcygpO1xuICAgICAgICAgICAgICAgIFBhc3N3b3JkU2NvcmUuY2hlY2tQYXNzU3RyZW5ndGgoe1xuICAgICAgICAgICAgICAgICAgICBwYXNzOiBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJHdlYkFkbWluUGFzc3dvcmQudmFsKCksXG4gICAgICAgICAgICAgICAgICAgIGJhcjogJCgnLnBhc3N3b3JkLXNjb3JlJyksXG4gICAgICAgICAgICAgICAgICAgIHNlY3Rpb246ICQoJy5wYXNzd29yZC1zY29yZS1zZWN0aW9uJyksXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFdoZW4gU1NIUGFzc3dvcmQgaW5wdXQgaXMgY2hhbmdlZCwgcmVjYWxjdWxhdGUgdGhlIHBhc3N3b3JkIHN0cmVuZ3RoXG4gICAgICAgIGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kc3NoUGFzc3dvcmQub24oJ2tleXVwJywgKCkgPT4ge1xuICAgICAgICAgICAgaWYgKGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kc3NoUGFzc3dvcmQudmFsKCkgIT09IGdlbmVyYWxTZXR0aW5nc01vZGlmeS5oaWRkZW5QYXNzd29yZCkge1xuICAgICAgICAgICAgICAgIGdlbmVyYWxTZXR0aW5nc01vZGlmeS5pbml0UnVsZXMoKTtcbiAgICAgICAgICAgICAgICBQYXNzd29yZFNjb3JlLmNoZWNrUGFzc1N0cmVuZ3RoKHtcbiAgICAgICAgICAgICAgICAgICAgcGFzczogZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LiRzc2hQYXNzd29yZC52YWwoKSxcbiAgICAgICAgICAgICAgICAgICAgYmFyOiAkKCcuc3NoLXBhc3N3b3JkLXNjb3JlJyksXG4gICAgICAgICAgICAgICAgICAgIHNlY3Rpb246ICQoJy5zc2gtcGFzc3dvcmQtc2NvcmUtc2VjdGlvbicpLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBFbmFibGUgdGFiIG5hdmlnYXRpb24gd2l0aCBoaXN0b3J5IHN1cHBvcnRcbiAgICAgICAgJCgnI2dlbmVyYWwtc2V0dGluZ3MtbWVudScpLmZpbmQoJy5pdGVtJykudGFiKHtcbiAgICAgICAgICAgIGhpc3Rvcnk6IHRydWUsXG4gICAgICAgICAgICBoaXN0b3J5VHlwZTogJ2hhc2gnLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBFbmFibGUgZHJvcGRvd25zIG9uIHRoZSBmb3JtXG4gICAgICAgICQoJyNnZW5lcmFsLXNldHRpbmdzLWZvcm0gLmRyb3Bkb3duJykuZHJvcGRvd24oKTtcblxuICAgICAgICAvLyBFbmFibGUgY2hlY2tib3hlcyBvbiB0aGUgZm9ybVxuICAgICAgICAkKCcjZ2VuZXJhbC1zZXR0aW5ncy1mb3JtIC5jaGVja2JveCcpLmNoZWNrYm94KCk7XG5cbiAgICAgICAgLy8gRW5hYmxlIHRhYmxlIGRyYWctbi1kcm9wIGZ1bmN0aW9uYWxpdHlcbiAgICAgICAgJCgnI2F1ZGlvLWNvZGVjcy10YWJsZSwgI3ZpZGVvLWNvZGVjcy10YWJsZScpLnRhYmxlRG5EKHtcbiAgICAgICAgICAgIG9uRHJvcCgpIHtcbiAgICAgICAgICAgICAgICAvLyBUcmlnZ2VyIGNoYW5nZSBldmVudCB0byBhY2tub3dsZWRnZSB0aGUgbW9kaWZpY2F0aW9uXG4gICAgICAgICAgICAgICAgRm9ybS5kYXRhQ2hhbmdlZCgpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9uRHJhZ0NsYXNzOiAnaG92ZXJpbmdSb3cnLFxuICAgICAgICAgICAgZHJhZ0hhbmRsZTogJy5kcmFnSGFuZGxlJyxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gRW5hYmxlIGRyb3Bkb3duIHdpdGggc291bmQgZmlsZSBzZWxlY3Rpb25cbiAgICAgICAgJCgnI2dlbmVyYWwtc2V0dGluZ3MtZm9ybSAuYXVkaW8tbWVzc2FnZS1zZWxlY3QnKS5kcm9wZG93bihTb3VuZEZpbGVzU2VsZWN0b3IuZ2V0RHJvcGRvd25TZXR0aW5nc1dpdGhFbXB0eSgpKTtcblxuICAgICAgICAvLyBJbml0aWFsaXplIHJlY29yZHMgc2F2ZSBwZXJpb2Qgc2xpZGVyXG4gICAgICAgIGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kcmVjb3Jkc1NhdmVQZXJpb2RTbGlkZXJcbiAgICAgICAgICAgIC5zbGlkZXIoe1xuICAgICAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgICAgICBtYXg6IDUsXG4gICAgICAgICAgICAgICAgc3RlcDogMSxcbiAgICAgICAgICAgICAgICBzbW9vdGg6IHRydWUsXG4gICAgICAgICAgICAgICAgaW50ZXJwcmV0TGFiZWw6IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgbGFiZWxzID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAgZ2xvYmFsVHJhbnNsYXRlLmdzX1N0b3JlMU1vbnRoT2ZSZWNvcmRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgZ2xvYmFsVHJhbnNsYXRlLmdzX1N0b3JlM01vbnRoc09mUmVjb3JkcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdsb2JhbFRyYW5zbGF0ZS5nc19TdG9yZTZNb250aHNPZlJlY29yZHMsXG4gICAgICAgICAgICAgICAgICAgICAgICBnbG9iYWxUcmFuc2xhdGUuZ3NfU3RvcmUxWWVhck9mUmVjb3JkcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdsb2JhbFRyYW5zbGF0ZS5nc19TdG9yZTNZZWFyc09mUmVjb3JkcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdsb2JhbFRyYW5zbGF0ZS5nc19TdG9yZUFsbFBvc3NpYmxlUmVjb3JkcyxcbiAgICAgICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGxhYmVsc1t2YWx1ZV07XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBvbkNoYW5nZTogZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmNiQWZ0ZXJTZWxlY3RTYXZlUGVyaW9kU2xpZGVyLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgO1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIGZvcm1cbiAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmluaXRpYWxpemVGb3JtKCk7XG5cbiAgICAgICAgLy8gSW5pdGlhbGl6ZSBhZGRpdGlvbmFsIHZhbGlkYXRpb24gcnVsZXNcbiAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmluaXRSdWxlcygpO1xuXG4gICAgICAgIC8vIFNob3csIGhpZGUgc3NoIHBhc3N3b3JkIHNlZ21lbnRcbiAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LiRkaXNhYmxlU1NIUGFzc3dvcmQuY2hlY2tib3goe1xuICAgICAgICAgICAgJ29uQ2hhbmdlJzogZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LnNob3dIaWRlU1NIUGFzc3dvcmRcbiAgICAgICAgfSk7XG4gICAgICAgIGdlbmVyYWxTZXR0aW5nc01vZGlmeS5zaG93SGlkZVNTSFBhc3N3b3JkKCk7XG5cbiAgICAgICAgLy8gU2V0IHRoZSBpbml0aWFsIHZhbHVlIGZvciB0aGUgcmVjb3JkcyBzYXZlIHBlcmlvZCBzbGlkZXJcbiAgICAgICAgY29uc3QgcmVjb3JkU2F2ZVBlcmlvZCA9IGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kZm9ybU9iai5mb3JtKCdnZXQgdmFsdWUnLCAnUEJYUmVjb3JkU2F2ZVBlcmlvZCcpO1xuICAgICAgICBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJHJlY29yZHNTYXZlUGVyaW9kU2xpZGVyXG4gICAgICAgICAgICAuc2xpZGVyKCdzZXQgdmFsdWUnLCBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuc2F2ZVJlY29yZHNQZXJpb2QuaW5kZXhPZihyZWNvcmRTYXZlUGVyaW9kKSwgZmFsc2UpO1xuXG4gICAgICAgIC8vIEFkZCBldmVudCBsaXN0ZW5lciB0byBoYW5kbGUgdGFiIGFjdGl2YXRpb25cbiAgICAgICAgJCh3aW5kb3cpLm9uKCdHUy1BY3RpdmF0ZVRhYicsIChldmVudCwgbmFtZVRhYikgPT4ge1xuICAgICAgICAgICAgJCgnI2dlbmVyYWwtc2V0dGluZ3MtbWVudScpLmZpbmQoJy5pdGVtJykudGFiKCdjaGFuZ2UgdGFiJywgbmFtZVRhYik7XG4gICAgICAgIH0pO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBTaG93LCBoaWRlIHNzaCBwYXNzd29yZCBzZWdtZW50IGFjY29yZGluZyB0byB0aGUgdmFsdWUgb2YgdXNlIFNTSCBwYXNzd29yZCBjaGVja2JveC5cbiAgICAgKi9cbiAgICBzaG93SGlkZVNTSFBhc3N3b3JkKCl7XG4gICAgICAgIGlmIChnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJGRpc2FibGVTU0hQYXNzd29yZC5jaGVja2JveCgnaXMgY2hlY2tlZCcpKSB7XG4gICAgICAgICAgICBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJHNzaFBhc3N3b3JkU2VnbWVudC5oaWRlKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJHNzaFBhc3N3b3JkU2VnbWVudC5zaG93KCk7XG4gICAgICAgIH1cbiAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmluaXRSdWxlcygpO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGNvbmRpdGlvbnMgZm9yIGRlbGV0aW5nIGFsbCByZWNvcmRzLlxuICAgICAqIENvbXBhcmVzIHRoZSB2YWx1ZSBvZiB0aGUgJ2RlbGV0ZUFsbElucHV0JyBmaWVsZCB3aXRoIGEgcGhyYXNlLlxuICAgICAqIElmIHRoZXkgbWF0Y2gsIGl0IHRyaWdnZXJzIGEgc3lzdGVtIHJlc3RvcmUgdG8gZGVmYXVsdCBzZXR0aW5ncy5cbiAgICAgKi9cbiAgICBjaGVja0RlbGV0ZUFsbENvbmRpdGlvbnMoKSB7XG5cbiAgICAgICAgLy8gR2V0IHRoZSB2YWx1ZSBvZiAnZGVsZXRlQWxsSW5wdXQnIGZpZWxkLlxuICAgICAgICBjb25zdCBkZWxldGVBbGxJbnB1dCA9IGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kZm9ybU9iai5mb3JtKCdnZXQgdmFsdWUnLCAnZGVsZXRlQWxsSW5wdXQnKTtcblxuICAgICAgICAvLyBJZiB0aGUgZW50ZXJlZCBwaHJhc2UgbWF0Y2hlcyB0aGUgcGhyYXNlIGluICdnbG9iYWxUcmFuc2xhdGUuZ3NfRW50ZXJEZWxldGVBbGxQaHJhc2UnLFxuICAgICAgICAvLyBjYWxsICdQYnhBcGkuU3lzdGVtUmVzdG9yZURlZmF1bHRTZXR0aW5ncycgdG8gcmVzdG9yZSBkZWZhdWx0IHNldHRpbmdzLlxuICAgICAgICBpZiAoZGVsZXRlQWxsSW5wdXQgPT09IGdsb2JhbFRyYW5zbGF0ZS5nc19FbnRlckRlbGV0ZUFsbFBocmFzZSkge1xuICAgICAgICAgICAgUGJ4QXBpLlN5c3RlbVJlc3RvcmVEZWZhdWx0U2V0dGluZ3MoZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmNiQWZ0ZXJSZXN0b3JlRGVmYXVsdFNldHRpbmdzKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGUgcmVzcG9uc2UgYWZ0ZXIgcmVzdG9yaW5nIGRlZmF1bHQgc2V0dGluZ3MuXG4gICAgICogQHBhcmFtIHtib29sZWFufHN0cmluZ30gcmVzcG9uc2UgLSBSZXNwb25zZSBmcm9tIHRoZSBzZXJ2ZXIgYWZ0ZXIgcmVzdG9yaW5nIGRlZmF1bHQgc2V0dGluZ3MuXG4gICAgICovXG4gICAgY2JBZnRlclJlc3RvcmVEZWZhdWx0U2V0dGluZ3MocmVzcG9uc2UpIHtcblxuICAgICAgICAvLyBDaGVjayBpZiB0aGUgcmVzcG9uc2UgaXMgdHJ1ZSwgZGlzcGxheSBhIHN1Y2Nlc3MgbWVzc2FnZVxuICAgICAgICAvLyBvdGhlcndpc2UsIGRpc3BsYXkgdGhlIHJlc3BvbnNlIG1lc3NhZ2UuXG4gICAgICAgIGlmIChyZXNwb25zZSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgVXNlck1lc3NhZ2Uuc2hvd0luZm9ybWF0aW9uKGdsb2JhbFRyYW5zbGF0ZS5nc19BbGxTZXR0aW5nc0RlbGV0ZWQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgVXNlck1lc3NhZ2Uuc2hvd011bHRpU3RyaW5nKHJlc3BvbnNlKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGUgZXZlbnQgYWZ0ZXIgdGhlIHNlbGVjdCBzYXZlIHBlcmlvZCBzbGlkZXIgaXMgY2hhbmdlZC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgLSBUaGUgc2VsZWN0ZWQgdmFsdWUgZnJvbSB0aGUgc2xpZGVyLlxuICAgICAqL1xuICAgIGNiQWZ0ZXJTZWxlY3RTYXZlUGVyaW9kU2xpZGVyKHZhbHVlKSB7XG5cbiAgICAgICAgLy8gR2V0IHRoZSBzYXZlIHBlcmlvZCBjb3JyZXNwb25kaW5nIHRvIHRoZSBzbGlkZXIgdmFsdWUuXG4gICAgICAgIGNvbnN0IHNhdmVQZXJpb2QgPSBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuc2F2ZVJlY29yZHNQZXJpb2RbdmFsdWVdO1xuXG4gICAgICAgIC8vIFNldCB0aGUgZm9ybSB2YWx1ZSBmb3IgJ1BCWFJlY29yZFNhdmVQZXJpb2QnIHRvIHRoZSBzZWxlY3RlZCBzYXZlIHBlcmlvZC5cbiAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LiRmb3JtT2JqLmZvcm0oJ3NldCB2YWx1ZScsICdQQlhSZWNvcmRTYXZlUGVyaW9kJywgc2F2ZVBlcmlvZCk7XG5cbiAgICAgICAgLy8gVHJpZ2dlciBjaGFuZ2UgZXZlbnQgdG8gYWNrbm93bGVkZ2UgdGhlIG1vZGlmaWNhdGlvblxuICAgICAgICBGb3JtLmRhdGFDaGFuZ2VkKCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIENhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCBiZWZvcmUgdGhlIGZvcm0gaXMgc2VudFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzZXR0aW5ncyAtIFRoZSBjdXJyZW50IHNldHRpbmdzIG9mIHRoZSBmb3JtXG4gICAgICogQHJldHVybnMge09iamVjdH0gLSBUaGUgdXBkYXRlZCBzZXR0aW5ncyBvZiB0aGUgZm9ybVxuICAgICAqL1xuICAgIGNiQmVmb3JlU2VuZEZvcm0oc2V0dGluZ3MpIHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gc2V0dGluZ3M7XG4gICAgICAgIHJlc3VsdC5kYXRhID0gZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LiRmb3JtT2JqLmZvcm0oJ2dldCB2YWx1ZXMnKTtcbiAgICAgICAgY29uc3QgYXJyQ29kZWNzID0gW107XG4gICAgICAgICQoJyNhdWRpby1jb2RlY3MtdGFibGUgLmNvZGVjLXJvdywgI3ZpZGVvLWNvZGVjcy10YWJsZSAuY29kZWMtcm93JykuZWFjaCgoaW5kZXgsIG9iaikgPT4ge1xuICAgICAgICAgICAgaWYgKCQob2JqKS5hdHRyKCdpZCcpKSB7XG4gICAgICAgICAgICAgICAgYXJyQ29kZWNzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBjb2RlY0lkOiAkKG9iaikuYXR0cignaWQnKSxcbiAgICAgICAgICAgICAgICAgICAgZGlzYWJsZWQ6ICQob2JqKS5maW5kKCcuY2hlY2tib3gnKS5jaGVja2JveCgnaXMgdW5jaGVja2VkJyksXG4gICAgICAgICAgICAgICAgICAgIHByaW9yaXR5OiBpbmRleCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJlc3VsdC5kYXRhLmNvZGVjcyA9IEpTT04uc3RyaW5naWZ5KGFyckNvZGVjcyk7XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQ2FsbGJhY2sgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIGFmdGVyIHRoZSBmb3JtIGhhcyBiZWVuIHNlbnQuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHJlc3BvbnNlIC0gVGhlIHJlc3BvbnNlIGZyb20gdGhlIHNlcnZlciBhZnRlciB0aGUgZm9ybSBpcyBzZW50XG4gICAgICovXG4gICAgY2JBZnRlclNlbmRGb3JtKHJlc3BvbnNlKSB7XG4gICAgICAgICQoXCIjZXJyb3ItbWVzc2FnZXNcIikucmVtb3ZlKCk7XG4gICAgICAgIGlmICghcmVzcG9uc2Uuc3VjY2Vzcykge1xuICAgICAgICAgICAgRm9ybS4kc3VibWl0QnV0dG9uLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmdlbmVyYXRlRXJyb3JNZXNzYWdlSHRtbChyZXNwb25zZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAkKCcucGFzc3dvcmQtdmFsaWRhdGUnKS5yZW1vdmUoKTtcbiAgICAgICAgfVxuICAgICAgICBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuY2hlY2tEZWxldGVBbGxDb25kaXRpb25zKCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFRoZSBmdW5jdGlvbiBjb2xsZWN0cyBhbiBpbmZvcm1hdGlvbiBtZXNzYWdlIGFib3V0IGEgZGF0YSBzYXZpbmcgZXJyb3JcbiAgICAgKiBAcGFyYW0gcmVzcG9uc2VcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuICAgIGdlbmVyYXRlRXJyb3JNZXNzYWdlSHRtbChyZXNwb25zZSkge1xuICAgICAgICBpZiAocmVzcG9uc2UubWVzc2FnZXMgJiYgcmVzcG9uc2UubWVzc2FnZXMuZXJyb3IpIHtcbiAgICAgICAgICAgIGNvbnN0ICRkaXYgPSAkKCc8ZGl2PicsIHsgY2xhc3M6ICd1aSBuZWdhdGl2ZSBtZXNzYWdlJywgaWQ6ICdlcnJvci1tZXNzYWdlcycgfSk7XG4gICAgICAgICAgICBjb25zdCAkaGVhZGVyID0gJCgnPGRpdj4nLCB7IGNsYXNzOiAnaGVhZGVyJyB9KS50ZXh0KGdsb2JhbFRyYW5zbGF0ZS5nc19FcnJvclNhdmVTZXR0aW5ncyk7XG4gICAgICAgICAgICAkZGl2LmFwcGVuZCgkaGVhZGVyKTtcbiAgICAgICAgICAgIGNvbnN0ICR1bCA9ICQoJzx1bD4nLCB7IGNsYXNzOiAnbGlzdCcgfSk7XG4gICAgICAgICAgICBjb25zdCBtZXNzYWdlc1NldCA9IG5ldyBTZXQoKTtcbiAgICAgICAgICAgIHJlc3BvbnNlLm1lc3NhZ2VzLmVycm9yLmZvckVhY2goZXJyb3JBcnJheSA9PiB7XG4gICAgICAgICAgICAgICAgZXJyb3JBcnJheS5mb3JFYWNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHRleHRDb250ZW50ID0nJztcbiAgICAgICAgICAgICAgICAgICAgaWYoZ2xvYmFsVHJhbnNsYXRlW2Vycm9yLm1lc3NhZ2VdID09PSB1bmRlZmluZWQpe1xuICAgICAgICAgICAgICAgICAgICAgICAgdGV4dENvbnRlbnQgPSBlcnJvci5tZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICB9ZWxzZXtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHRDb250ZW50ID0gZ2xvYmFsVHJhbnNsYXRlW2Vycm9yLm1lc3NhZ2VdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlc1NldC5oYXModGV4dENvbnRlbnQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZXNTZXQuYWRkKGVycm9yLm1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgICAgICAkdWwuYXBwZW5kKCQoJzxsaT4nKS50ZXh0KHRleHRDb250ZW50KSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICRkaXYuYXBwZW5kKCR1bCk7XG4gICAgICAgICAgICAkKCcjc3VibWl0YnV0dG9uJykuYmVmb3JlKCRkaXYpO1xuICAgICAgICAgICAgcmV0dXJuICRkaXY7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZSB0aGUgdmFsaWRhdGlvbiBydWxlcyBvZiB0aGUgZm9ybVxuICAgICAqL1xuICAgIGluaXRSdWxlcygpIHtcbiAgICAgICAgLy8gU1NIUGFzc3dvcmRcbiAgICAgICAgaWYgKGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kZGlzYWJsZVNTSFBhc3N3b3JkLmNoZWNrYm94KCdpcyBjaGVja2VkJykpIHtcbiAgICAgICAgICAgIEZvcm0udmFsaWRhdGVSdWxlcy5TU0hQYXNzd29yZC5ydWxlcyA9IGdlbmVyYWxTZXR0aW5nc01vZGlmeS5hZGRpdGlvbmFsU3NoVmFsaWRSdWxlc05vUGFzcztcbiAgICAgICAgfSBlbHNlIGlmIChnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJHNzaFBhc3N3b3JkLnZhbCgpID09PSBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuaGlkZGVuUGFzc3dvcmQpIHtcbiAgICAgICAgICAgIEZvcm0udmFsaWRhdGVSdWxlcy5TU0hQYXNzd29yZC5ydWxlcyA9IFtdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgRm9ybS52YWxpZGF0ZVJ1bGVzLlNTSFBhc3N3b3JkLnJ1bGVzID0gZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmFkZGl0aW9uYWxTc2hWYWxpZFJ1bGVzUGFzcztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFdlYkFkbWluUGFzc3dvcmRcbiAgICAgICAgaWYgKGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kd2ViQWRtaW5QYXNzd29yZC52YWwoKSA9PT0gZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmhpZGRlblBhc3N3b3JkKSB7XG4gICAgICAgICAgICBGb3JtLnZhbGlkYXRlUnVsZXMuV2ViQWRtaW5QYXNzd29yZC5ydWxlcyA9IFtdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgRm9ybS52YWxpZGF0ZVJ1bGVzLldlYkFkbWluUGFzc3dvcmQucnVsZXMgPSBnZW5lcmFsU2V0dGluZ3NNb2RpZnkud2ViQWRtaW5QYXNzd29yZFJ1bGVzO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemUgdGhlIGZvcm0gd2l0aCBjdXN0b20gc2V0dGluZ3NcbiAgICAgKi9cbiAgICBpbml0aWFsaXplRm9ybSgpIHtcbiAgICAgICAgRm9ybS4kZm9ybU9iaiA9IGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kZm9ybU9iajtcbiAgICAgICAgRm9ybS51cmwgPSBgJHtnbG9iYWxSb290VXJsfWdlbmVyYWwtc2V0dGluZ3Mvc2F2ZWA7IC8vIEZvcm0gc3VibWlzc2lvbiBVUkxcbiAgICAgICAgRm9ybS52YWxpZGF0ZVJ1bGVzID0gZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LnZhbGlkYXRlUnVsZXM7IC8vIEZvcm0gdmFsaWRhdGlvbiBydWxlc1xuICAgICAgICBGb3JtLmNiQmVmb3JlU2VuZEZvcm0gPSBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuY2JCZWZvcmVTZW5kRm9ybTsgLy8gQ2FsbGJhY2sgYmVmb3JlIGZvcm0gaXMgc2VudFxuICAgICAgICBGb3JtLmNiQWZ0ZXJTZW5kRm9ybSA9IGdlbmVyYWxTZXR0aW5nc01vZGlmeS5jYkFmdGVyU2VuZEZvcm07IC8vIENhbGxiYWNrIGFmdGVyIGZvcm0gaXMgc2VudFxuICAgICAgICBGb3JtLmluaXRpYWxpemUoKTtcbiAgICB9XG59O1xuXG4vLyBXaGVuIHRoZSBkb2N1bWVudCBpcyByZWFkeSwgaW5pdGlhbGl6ZSB0aGUgZ2VuZXJhbFNldHRpbmdzIG1hbmFnZW1lbnQgaW50ZXJmYWNlLlxuJChkb2N1bWVudCkucmVhZHkoKCkgPT4ge1xuICAgIGdlbmVyYWxTZXR0aW5nc01vZGlmeS5pbml0aWFsaXplKCk7XG59KTsiXX0= \ No newline at end of file diff --git a/sites/admin-cabinet/assets/js/src/GeneralSettings/general-settings-modify.js b/sites/admin-cabinet/assets/js/src/GeneralSettings/general-settings-modify.js index 9344f8f7b..aabe559bb 100644 --- a/sites/admin-cabinet/assets/js/src/GeneralSettings/general-settings-modify.js +++ b/sites/admin-cabinet/assets/js/src/GeneralSettings/general-settings-modify.js @@ -418,14 +418,49 @@ const generalSettingsModify = { * @param {Object} response - The response from the server after the form is sent */ cbAfterSendForm(response) { + $("#error-messages").remove(); if (!response.success) { Form.$submitButton.removeClass('disabled'); + generalSettingsModify.generateErrorMessageHtml(response); } else { $('.password-validate').remove(); } generalSettingsModify.checkDeleteAllConditions(); }, + /** + * The function collects an information message about a data saving error + * @param response + * @returns {string} + */ + generateErrorMessageHtml(response) { + if (response.messages && response.messages.error) { + const $div = $('
    ', { class: 'ui negative message', id: 'error-messages' }); + const $header = $('
    ', { class: 'header' }).text(globalTranslate.gs_ErrorSaveSettings); + $div.append($header); + const $ul = $('
      ', { class: 'list' }); + const messagesSet = new Set(); + response.messages.error.forEach(errorArray => { + errorArray.forEach(error => { + let textContent =''; + if(globalTranslate[error.message] === undefined){ + textContent = error.message; + }else{ + textContent = globalTranslate[error.message]; + } + if (messagesSet.has(textContent)) { + return; + } + messagesSet.add(error.message); + $ul.append($('
    • ').text(textContent)); + }); + }); + $div.append($ul); + $('#submitbutton').before($div); + return $div; + } + }, + /** * Initialize the validation rules of the form */ diff --git a/src/Common/Messages/ru.php b/src/Common/Messages/ru.php index f2960dd24..fc0bc506f 100644 --- a/src/Common/Messages/ru.php +++ b/src/Common/Messages/ru.php @@ -246,6 +246,8 @@ 'gs_PBXRecordSavePeriodLabel' => 'Период хранения записей разговоров', 'gs_StoreAllPossibleRecords' => '∞', 'gs_DisableAllModules' => 'Отключить маркетплейс', + 'gs_ErrorSaveSettings' => 'Ошибка сохранения настроек', + 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Указанный внутренний номер уже используется', 'pr_AddSIPProvider' => 'Подключить SIP', 'pr_AddIAXProvider' => 'Подключить IAX', 'pr_QualifyInstructionsIAX' => 'При включение этой опции Asterisk будет отправлять SIP Options пакеты. Это необходимо для поддержки NAT туннелирования на вашем маршрутизаторе.', From 7cd0c17767124ed1232a9b7915f087e9d939822b Mon Sep 17 00:00:00 2001 From: boffart <> Date: Thu, 11 Jul 2024 09:22:32 +0300 Subject: [PATCH 34/58] =?UTF-8?q?#767=20=D0=9F=D0=BE=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D0=BB=20=D0=BE=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../assets/js/pbx/GeneralSettings/general-settings-modify.js | 4 +--- .../assets/js/src/GeneralSettings/general-settings-modify.js | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/sites/admin-cabinet/assets/js/pbx/GeneralSettings/general-settings-modify.js b/sites/admin-cabinet/assets/js/pbx/GeneralSettings/general-settings-modify.js index fbb8aa32d..89800a675 100644 --- a/sites/admin-cabinet/assets/js/pbx/GeneralSettings/general-settings-modify.js +++ b/sites/admin-cabinet/assets/js/pbx/GeneralSettings/general-settings-modify.js @@ -371,7 +371,6 @@ var generalSettingsModify = { /** * The function collects an information message about a data saving error * @param response - * @returns {string} */ generateErrorMessageHtml: function generateErrorMessageHtml(response) { if (response.messages && response.messages.error) { @@ -407,7 +406,6 @@ var generalSettingsModify = { }); $div.append($ul); $('#submitbutton').before($div); - return $div; } }, @@ -452,4 +450,4 @@ var generalSettingsModify = { $(document).ready(function () { generalSettingsModify.initialize(); }); -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9HZW5lcmFsU2V0dGluZ3MvZ2VuZXJhbC1zZXR0aW5ncy1tb2RpZnkuanMiXSwibmFtZXMiOlsiZ2VuZXJhbFNldHRpbmdzTW9kaWZ5IiwiJGZvcm1PYmoiLCIkIiwiJHdlYkFkbWluUGFzc3dvcmQiLCIkc3NoUGFzc3dvcmQiLCIkZGlzYWJsZVNTSFBhc3N3b3JkIiwicGFyZW50IiwiJHNzaFBhc3N3b3JkU2VnbWVudCIsImhpZGRlblBhc3N3b3JkIiwiJHJlY29yZHNTYXZlUGVyaW9kU2xpZGVyIiwic2F2ZVJlY29yZHNQZXJpb2QiLCJ2YWxpZGF0ZVJ1bGVzIiwicGJ4bmFtZSIsImlkZW50aWZpZXIiLCJydWxlcyIsInR5cGUiLCJwcm9tcHQiLCJnbG9iYWxUcmFuc2xhdGUiLCJnc19WYWxpZGF0ZUVtcHR5UEJYTmFtZSIsIldlYkFkbWluUGFzc3dvcmQiLCJXZWJBZG1pblBhc3N3b3JkUmVwZWF0IiwiZ3NfVmFsaWRhdGVXZWJQYXNzd29yZHNGaWVsZERpZmZlcmVudCIsIlNTSFBhc3N3b3JkIiwiU1NIUGFzc3dvcmRSZXBlYXQiLCJnc19WYWxpZGF0ZVNTSFBhc3N3b3Jkc0ZpZWxkRGlmZmVyZW50IiwiV0VCUG9ydCIsImdzX1ZhbGlkYXRlV0VCUG9ydE91dE9mUmFuZ2UiLCJnc19WYWxpZGF0ZVdFQkhUVFBTUG9ydE5vdEVxdWFsVG9XRUJQb3J0IiwiZ3NfVmFsaWRhdGVXRUJQb3J0Tm90RXF1YWxUb0FqYW1Qb3J0IiwiZ3NfVmFsaWRhdGVXRUJQb3J0Tm90RXF1YWxUb0FqYW1UTFNQb3J0IiwiV0VCSFRUUFNQb3J0IiwiZ3NfVmFsaWRhdGVXRUJIVFRQU1BvcnRPdXRPZlJhbmdlIiwiZ3NfVmFsaWRhdGVXRUJIVFRQU1BvcnROb3RFcXVhbFRvQWphbVBvcnQiLCJnc19WYWxpZGF0ZVdFQkhUVFBTUG9ydE5vdEVxdWFsVG9BamFtVExTUG9ydCIsIkFKQU1Qb3J0IiwiZ3NfVmFsaWRhdGVBSkFNUG9ydE91dE9mUmFuZ2UiLCJ3ZWJBZG1pblBhc3N3b3JkUnVsZXMiLCJnc19WYWxpZGF0ZUVtcHR5V2ViUGFzc3dvcmQiLCJnc19WYWxpZGF0ZVdlYWtXZWJQYXNzd29yZCIsInZhbHVlIiwiZ3NfUGFzc3dvcmRzIiwiZ3NfUGFzc3dvcmROb0xvd1NpbXZvbCIsImdzX1Bhc3N3b3JkTm9OdW1iZXJzIiwiZ3NfUGFzc3dvcmROb1VwcGVyU2ltdm9sIiwiYWRkaXRpb25hbFNzaFZhbGlkUnVsZXNQYXNzIiwiZ3NfVmFsaWRhdGVFbXB0eVNTSFBhc3N3b3JkIiwiZ3NfVmFsaWRhdGVXZWFrU1NIUGFzc3dvcmQiLCJnc19TU0hQYXNzd29yZCIsImFkZGl0aW9uYWxTc2hWYWxpZFJ1bGVzTm9QYXNzIiwiaW5pdGlhbGl6ZSIsIm9uIiwidmFsIiwiaW5pdFJ1bGVzIiwiUGFzc3dvcmRTY29yZSIsImNoZWNrUGFzc1N0cmVuZ3RoIiwicGFzcyIsImJhciIsInNlY3Rpb24iLCJmaW5kIiwidGFiIiwiaGlzdG9yeSIsImhpc3RvcnlUeXBlIiwiZHJvcGRvd24iLCJjaGVja2JveCIsInRhYmxlRG5EIiwib25Ecm9wIiwiRm9ybSIsImRhdGFDaGFuZ2VkIiwib25EcmFnQ2xhc3MiLCJkcmFnSGFuZGxlIiwiU291bmRGaWxlc1NlbGVjdG9yIiwiZ2V0RHJvcGRvd25TZXR0aW5nc1dpdGhFbXB0eSIsInNsaWRlciIsIm1pbiIsIm1heCIsInN0ZXAiLCJzbW9vdGgiLCJpbnRlcnByZXRMYWJlbCIsImxhYmVscyIsImdzX1N0b3JlMU1vbnRoT2ZSZWNvcmRzIiwiZ3NfU3RvcmUzTW9udGhzT2ZSZWNvcmRzIiwiZ3NfU3RvcmU2TW9udGhzT2ZSZWNvcmRzIiwiZ3NfU3RvcmUxWWVhck9mUmVjb3JkcyIsImdzX1N0b3JlM1llYXJzT2ZSZWNvcmRzIiwiZ3NfU3RvcmVBbGxQb3NzaWJsZVJlY29yZHMiLCJvbkNoYW5nZSIsImNiQWZ0ZXJTZWxlY3RTYXZlUGVyaW9kU2xpZGVyIiwiaW5pdGlhbGl6ZUZvcm0iLCJzaG93SGlkZVNTSFBhc3N3b3JkIiwicmVjb3JkU2F2ZVBlcmlvZCIsImZvcm0iLCJpbmRleE9mIiwid2luZG93IiwiZXZlbnQiLCJuYW1lVGFiIiwiaGlkZSIsInNob3ciLCJjaGVja0RlbGV0ZUFsbENvbmRpdGlvbnMiLCJkZWxldGVBbGxJbnB1dCIsImdzX0VudGVyRGVsZXRlQWxsUGhyYXNlIiwiUGJ4QXBpIiwiU3lzdGVtUmVzdG9yZURlZmF1bHRTZXR0aW5ncyIsImNiQWZ0ZXJSZXN0b3JlRGVmYXVsdFNldHRpbmdzIiwicmVzcG9uc2UiLCJVc2VyTWVzc2FnZSIsInNob3dJbmZvcm1hdGlvbiIsImdzX0FsbFNldHRpbmdzRGVsZXRlZCIsInNob3dNdWx0aVN0cmluZyIsInNhdmVQZXJpb2QiLCJjYkJlZm9yZVNlbmRGb3JtIiwic2V0dGluZ3MiLCJyZXN1bHQiLCJkYXRhIiwiYXJyQ29kZWNzIiwiZWFjaCIsImluZGV4Iiwib2JqIiwiYXR0ciIsInB1c2giLCJjb2RlY0lkIiwiZGlzYWJsZWQiLCJwcmlvcml0eSIsImNvZGVjcyIsIkpTT04iLCJzdHJpbmdpZnkiLCJjYkFmdGVyU2VuZEZvcm0iLCJyZW1vdmUiLCJzdWNjZXNzIiwiJHN1Ym1pdEJ1dHRvbiIsInJlbW92ZUNsYXNzIiwiZ2VuZXJhdGVFcnJvck1lc3NhZ2VIdG1sIiwibWVzc2FnZXMiLCJlcnJvciIsIiRkaXYiLCJpZCIsIiRoZWFkZXIiLCJ0ZXh0IiwiZ3NfRXJyb3JTYXZlU2V0dGluZ3MiLCJhcHBlbmQiLCIkdWwiLCJtZXNzYWdlc1NldCIsIlNldCIsImZvckVhY2giLCJlcnJvckFycmF5IiwidGV4dENvbnRlbnQiLCJtZXNzYWdlIiwidW5kZWZpbmVkIiwiaGFzIiwiYWRkIiwiYmVmb3JlIiwidXJsIiwiZ2xvYmFsUm9vdFVybCIsImRvY3VtZW50IiwicmVhZHkiXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFHQTs7QUFFQTtBQUNB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dkQsYUFBTCxHQUFxQlgscUJBQXFCLENBQUNXLGFBQTNDLENBSGEsQ0FHNkM7O0FBQzFEdUQsSUFBQUEsSUFBSSxDQUFDMkMsZ0JBQUwsR0FBd0I3RyxxQkFBcUIsQ0FBQzZHLGdCQUE5QyxDQUphLENBSW1EOztBQUNoRTNDLElBQUFBLElBQUksQ0FBQzJELGVBQUwsR0FBdUI3SCxxQkFBcUIsQ0FBQzZILGVBQTdDLENBTGEsQ0FLaUQ7O0FBQzlEM0QsSUFBQUEsSUFBSSxDQUFDakIsVUFBTDtBQUNIO0FBdGR5QixDQUE5QixDLENBeWRBOztBQUNBL0MsQ0FBQyxDQUFDc0osUUFBRCxDQUFELENBQVlDLEtBQVosQ0FBa0IsWUFBTTtBQUNwQnpKLEVBQUFBLHFCQUFxQixDQUFDaUQsVUFBdEI7QUFDSCxDQUZEIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIE1pa29QQlggLSBmcmVlIHBob25lIHN5c3RlbSBmb3Igc21hbGwgYnVzaW5lc3NcbiAqIENvcHlyaWdodCDCqSAyMDE3LTIwMjMgQWxleGV5IFBvcnRub3YgYW5kIE5pa29sYXkgQmVrZXRvdlxuICpcbiAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbS5cbiAqIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKi9cblxuXG4vKiBnbG9iYWwgZ2xvYmFsUm9vdFVybCxnbG9iYWxUcmFuc2xhdGUsIEZvcm0sIFBhc3N3b3JkU2NvcmUsIFBieEFwaSwgVXNlck1lc3NhZ2UsIFNvdW5kRmlsZXNTZWxlY3RvciwgJCAqL1xuXG4vKipcbiAqIEEgbW9kdWxlIHRvIGhhbmRsZSBtb2RpZmljYXRpb24gb2YgZ2VuZXJhbCBzZXR0aW5ncy5cbiAqL1xuY29uc3QgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5ID0ge1xuICAgIC8qKlxuICAgICAqIGpRdWVyeSBvYmplY3QgZm9yIHRoZSBmb3JtLlxuICAgICAqIEB0eXBlIHtqUXVlcnl9XG4gICAgICovXG4gICAgJGZvcm1PYmo6ICQoJyNnZW5lcmFsLXNldHRpbmdzLWZvcm0nKSxcblxuICAgIC8qKlxuICAgICAqIGpRdWVyeSBvYmplY3QgZm9yIHRoZSB3ZWIgYWRtaW4gcGFzc3dvcmQgaW5wdXQgZmllbGQuXG4gICAgICogQHR5cGUge2pRdWVyeX1cbiAgICAgKi9cbiAgICAkd2ViQWRtaW5QYXNzd29yZDogJCgnI1dlYkFkbWluUGFzc3dvcmQnKSxcblxuICAgIC8qKlxuICAgICAqIGpRdWVyeSBvYmplY3QgZm9yIHRoZSBzc2ggcGFzc3dvcmQgaW5wdXQgZmllbGQuXG4gICAgICogQHR5cGUge2pRdWVyeX1cbiAgICAgKi9cbiAgICAkc3NoUGFzc3dvcmQ6ICQoJyNTU0hQYXNzd29yZCcpLFxuXG4gICAgLyoqXG4gICAgICogalF1ZXJ5IG9iamVjdCBmb3IgdGhlIHdlYiBzc2ggcGFzc3dvcmQgaW5wdXQgZmllbGQuXG4gICAgICogQHR5cGUge2pRdWVyeX1cbiAgICAgKi9cbiAgICAkZGlzYWJsZVNTSFBhc3N3b3JkOiAkKCcjU1NIRGlzYWJsZVBhc3N3b3JkTG9naW5zJykucGFyZW50KCcuY2hlY2tib3gnKSxcblxuICAgIC8qKlxuICAgICAqIGpRdWVyeSBvYmplY3QgZm9yIHRoZSBTU0ggcGFzc3dvcmQgZmllbGRzXG4gICAgICogQHR5cGUge2pRdWVyeX1cbiAgICAgKi9cbiAgICAkc3NoUGFzc3dvcmRTZWdtZW50OiAkKCcjb25seS1pZi1wYXNzd29yZC1lbmFibGVkJyksXG5cbiAgICAvKipcbiAgICAgKiBJZiBwYXNzd29yZCBzZXQsIGl0IHdpbGwgYmUgaGlkZWQgZnJvbSB3ZWIgdWkuXG4gICAgICovXG4gICAgaGlkZGVuUGFzc3dvcmQ6ICd4eHh4eHh4JyxcblxuICAgIC8qKlxuICAgICAqIGpRdWVyeSBvYmplY3QgZm9yIHRoZSByZWNvcmRzIHJldGVudGlvbiBwZXJpb2Qgc2xpZGVyLlxuICAgICAqIEB0eXBlIHtqUXVlcnl9XG4gICAgICovXG4gICAgJHJlY29yZHNTYXZlUGVyaW9kU2xpZGVyOiAkKCcjUEJYUmVjb3JkU2F2ZVBlcmlvZFNsaWRlcicpLFxuXG4gICAgLyoqXG4gICAgICogUG9zc2libGUgcGVyaW9kIHZhbHVlcyBmb3IgdGhlIHJlY29yZHMgcmV0ZW50aW9uLlxuICAgICAqL1xuICAgIHNhdmVSZWNvcmRzUGVyaW9kOiBbJzMwJywgJzkwJywgJzE4MCcsICczNjAnLCAnMTA4MCcsICcnXSxcblxuICAgIC8qKlxuICAgICAqIFZhbGlkYXRpb24gcnVsZXMgZm9yIHRoZSBmb3JtIGZpZWxkcyBiZWZvcmUgc3VibWlzc2lvbi5cbiAgICAgKlxuICAgICAqIEB0eXBlIHtvYmplY3R9XG4gICAgICovXG4gICAgdmFsaWRhdGVSdWxlczogeyAvLyBnZW5lcmFsU2V0dGluZ3NNb2RpZnkudmFsaWRhdGVSdWxlcy5TU0hQYXNzd29yZC5ydWxlc1xuICAgICAgICBwYnhuYW1lOiB7XG4gICAgICAgICAgICBpZGVudGlmaWVyOiAnUEJYTmFtZScsXG4gICAgICAgICAgICBydWxlczogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2VtcHR5JyxcbiAgICAgICAgICAgICAgICAgICAgcHJvbXB0OiBnbG9iYWxUcmFuc2xhdGUuZ3NfVmFsaWRhdGVFbXB0eVBCWE5hbWUsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICAgIFdlYkFkbWluUGFzc3dvcmQ6IHtcbiAgICAgICAgICAgIGlkZW50aWZpZXI6ICdXZWJBZG1pblBhc3N3b3JkJyxcbiAgICAgICAgICAgIHJ1bGVzOiBbXSxcbiAgICAgICAgfSxcbiAgICAgICAgV2ViQWRtaW5QYXNzd29yZFJlcGVhdDoge1xuICAgICAgICAgICAgaWRlbnRpZmllcjogJ1dlYkFkbWluUGFzc3dvcmRSZXBlYXQnLFxuICAgICAgICAgICAgcnVsZXM6IFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdtYXRjaFtXZWJBZG1pblBhc3N3b3JkXScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV2ViUGFzc3dvcmRzRmllbGREaWZmZXJlbnQsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICAgIFNTSFBhc3N3b3JkOiB7XG4gICAgICAgICAgICBpZGVudGlmaWVyOiAnU1NIUGFzc3dvcmQnLFxuICAgICAgICAgICAgcnVsZXM6IFtdLFxuICAgICAgICB9LFxuICAgICAgICBTU0hQYXNzd29yZFJlcGVhdDoge1xuICAgICAgICAgICAgaWRlbnRpZmllcjogJ1NTSFBhc3N3b3JkUmVwZWF0JyxcbiAgICAgICAgICAgIHJ1bGVzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnbWF0Y2hbU1NIUGFzc3dvcmRdJyxcbiAgICAgICAgICAgICAgICAgICAgcHJvbXB0OiBnbG9iYWxUcmFuc2xhdGUuZ3NfVmFsaWRhdGVTU0hQYXNzd29yZHNGaWVsZERpZmZlcmVudCxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgICAgV0VCUG9ydDoge1xuICAgICAgICAgICAgaWRlbnRpZmllcjogJ1dFQlBvcnQnLFxuICAgICAgICAgICAgcnVsZXM6IFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdpbnRlZ2VyWzEuLjY1NTM1XScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV0VCUG9ydE91dE9mUmFuZ2UsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdkaWZmZXJlbnRbV0VCSFRUUFNQb3J0XScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV0VCSFRUUFNQb3J0Tm90RXF1YWxUb1dFQlBvcnQsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdkaWZmZXJlbnRbQUpBTVBvcnRUTFNdJyxcbiAgICAgICAgICAgICAgICAgICAgcHJvbXB0OiBnbG9iYWxUcmFuc2xhdGUuZ3NfVmFsaWRhdGVXRUJQb3J0Tm90RXF1YWxUb0FqYW1Qb3J0LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnZGlmZmVyZW50W0FKQU1Qb3J0XScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV0VCUG9ydE5vdEVxdWFsVG9BamFtVExTUG9ydCxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgICAgV0VCSFRUUFNQb3J0OiB7XG4gICAgICAgICAgICBpZGVudGlmaWVyOiAnV0VCSFRUUFNQb3J0JyxcbiAgICAgICAgICAgIHJ1bGVzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnaW50ZWdlclsxLi42NTUzNV0nLFxuICAgICAgICAgICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS5nc19WYWxpZGF0ZVdFQkhUVFBTUG9ydE91dE9mUmFuZ2UsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdkaWZmZXJlbnRbV0VCUG9ydF0nLFxuICAgICAgICAgICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS5nc19WYWxpZGF0ZVdFQkhUVFBTUG9ydE5vdEVxdWFsVG9XRUJQb3J0LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnZGlmZmVyZW50W0FKQU1Qb3J0VExTXScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV0VCSFRUUFNQb3J0Tm90RXF1YWxUb0FqYW1Qb3J0LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnZGlmZmVyZW50W0FKQU1Qb3J0XScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV0VCSFRUUFNQb3J0Tm90RXF1YWxUb0FqYW1UTFNQb3J0LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgICBBSkFNUG9ydDoge1xuICAgICAgICAgICAgaWRlbnRpZmllcjogJ0FKQU1Qb3J0JyxcbiAgICAgICAgICAgIHJ1bGVzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnaW50ZWdlclsxLi42NTUzNV0nLFxuICAgICAgICAgICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS5nc19WYWxpZGF0ZUFKQU1Qb3J0T3V0T2ZSYW5nZSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2RpZmZlcmVudFtBSkFNUG9ydFRMU10nLFxuICAgICAgICAgICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS5nc19WYWxpZGF0ZUFKQU1Qb3J0T3V0T2ZSYW5nZSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICB9LFxuXG4gICAgLy8gUnVsZXMgZm9yIHRoZSB3ZWIgYWRtaW4gcGFzc3dvcmQgZmllbGQgd2hlbiBpdCBub3QgZXF1YWwgdG8gaGlkZGVuUGFzc3dvcmRcbiAgICB3ZWJBZG1pblBhc3N3b3JkUnVsZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ2VtcHR5JyxcbiAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlRW1wdHlXZWJQYXNzd29yZCxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ21pbkxlbmd0aFs1XScsXG4gICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS5nc19WYWxpZGF0ZVdlYWtXZWJQYXNzd29yZCxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ25vdFJlZ0V4cCcsXG4gICAgICAgICAgICB2YWx1ZTogL1thLXpdLyxcbiAgICAgICAgICAgIHByb21wdDogJzxiPicgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmRzICsgJzwvYj46ICcgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmROb0xvd1NpbXZvbFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiAnbm90UmVnRXhwJyxcbiAgICAgICAgICAgIHZhbHVlOiAvXFxkLyxcbiAgICAgICAgICAgIHByb21wdDogJzxiPicgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmRzICsgJzwvYj46ICcgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmROb051bWJlcnNcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ25vdFJlZ0V4cCcsXG4gICAgICAgICAgICB2YWx1ZTogL1tBLVpdLyxcbiAgICAgICAgICAgIHByb21wdDogJzxiPicgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmRzICsgJzwvYj46ICcgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmROb1VwcGVyU2ltdm9sXG4gICAgICAgIH1cbiAgICBdLFxuICAgIC8vIFJ1bGVzIGZvciB0aGUgU1NIIHBhc3N3b3JkIGZpZWxkIHdoZW4gU1NIIGxvZ2luIHRocm91Z2ggdGhlIHBhc3N3b3JkIGVuYWJsZWQsIGFuZCBpdCBub3QgZXF1YWwgdG8gaGlkZGVuUGFzc3dvcmRcbiAgICBhZGRpdGlvbmFsU3NoVmFsaWRSdWxlc1Bhc3M6IFtcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ2VtcHR5JyxcbiAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlRW1wdHlTU0hQYXNzd29yZCxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ21pbkxlbmd0aFs1XScsXG4gICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS5nc19WYWxpZGF0ZVdlYWtTU0hQYXNzd29yZCxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ25vdFJlZ0V4cCcsXG4gICAgICAgICAgICB2YWx1ZTogL1thLXpdLyxcbiAgICAgICAgICAgIHByb21wdDogJzxiPicgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfU1NIUGFzc3dvcmQgKyAnPC9iPjogJyArIGdsb2JhbFRyYW5zbGF0ZS5nc19QYXNzd29yZE5vTG93U2ltdm9sXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICAgIHR5cGU6ICdub3RSZWdFeHAnLFxuICAgICAgICAgICAgdmFsdWU6IC9cXGQvLFxuICAgICAgICAgICAgcHJvbXB0OiAnPGI+JyArIGdsb2JhbFRyYW5zbGF0ZS5nc19TU0hQYXNzd29yZCArICc8L2I+OiAnICsgZ2xvYmFsVHJhbnNsYXRlLmdzX1Bhc3N3b3JkTm9OdW1iZXJzXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICAgIHR5cGU6ICdub3RSZWdFeHAnLFxuICAgICAgICAgICAgdmFsdWU6IC9bQS1aXS8sXG4gICAgICAgICAgICBwcm9tcHQ6ICc8Yj4nICsgZ2xvYmFsVHJhbnNsYXRlLmdzX1NTSFBhc3N3b3JkICsgJzwvYj46ICcgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmROb1VwcGVyU2ltdm9sXG4gICAgICAgIH1cbiAgICBdLFxuXG4gICAgLy8gUnVsZXMgZm9yIHRoZSBTU0ggcGFzc3dvcmQgZmllbGQgd2hlbiBTU0ggbG9naW4gdGhyb3VnaCB0aGUgcGFzc3dvcmQgZGlzYWJsZWRcbiAgICBhZGRpdGlvbmFsU3NoVmFsaWRSdWxlc05vUGFzczogW1xuICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiAnZW1wdHknLFxuICAgICAgICAgICAgcHJvbXB0OiBnbG9iYWxUcmFuc2xhdGUuZ3NfVmFsaWRhdGVFbXB0eVNTSFBhc3N3b3JkLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiAnbWluTGVuZ3RoWzVdJyxcbiAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV2Vha1NTSFBhc3N3b3JkLFxuICAgICAgICB9XG4gICAgXSxcblxuICAgIC8qKlxuICAgICAqICBJbml0aWFsaXplIG1vZHVsZSB3aXRoIGV2ZW50IGJpbmRpbmdzIGFuZCBjb21wb25lbnQgaW5pdGlhbGl6YXRpb25zLlxuICAgICAqL1xuICAgIGluaXRpYWxpemUoKSB7XG5cbiAgICAgICAgLy8gV2hlbiBXZWJBZG1pblBhc3N3b3JkIGlucHV0IGlzIGNoYW5nZWQsIHJlY2FsY3VsYXRlIHRoZSBwYXNzd29yZCBzdHJlbmd0aFxuICAgICAgICBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJHdlYkFkbWluUGFzc3dvcmQub24oJ2tleXVwJywgKCkgPT4ge1xuICAgICAgICAgICAgaWYgKGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kd2ViQWRtaW5QYXNzd29yZC52YWwoKSAhPT0gZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmhpZGRlblBhc3N3b3JkKSB7XG4gICAgICAgICAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmluaXRSdWxlcygpO1xuICAgICAgICAgICAgICAgIFBhc3N3b3JkU2NvcmUuY2hlY2tQYXNzU3RyZW5ndGgoe1xuICAgICAgICAgICAgICAgICAgICBwYXNzOiBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJHdlYkFkbWluUGFzc3dvcmQudmFsKCksXG4gICAgICAgICAgICAgICAgICAgIGJhcjogJCgnLnBhc3N3b3JkLXNjb3JlJyksXG4gICAgICAgICAgICAgICAgICAgIHNlY3Rpb246ICQoJy5wYXNzd29yZC1zY29yZS1zZWN0aW9uJyksXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFdoZW4gU1NIUGFzc3dvcmQgaW5wdXQgaXMgY2hhbmdlZCwgcmVjYWxjdWxhdGUgdGhlIHBhc3N3b3JkIHN0cmVuZ3RoXG4gICAgICAgIGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kc3NoUGFzc3dvcmQub24oJ2tleXVwJywgKCkgPT4ge1xuICAgICAgICAgICAgaWYgKGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kc3NoUGFzc3dvcmQudmFsKCkgIT09IGdlbmVyYWxTZXR0aW5nc01vZGlmeS5oaWRkZW5QYXNzd29yZCkge1xuICAgICAgICAgICAgICAgIGdlbmVyYWxTZXR0aW5nc01vZGlmeS5pbml0UnVsZXMoKTtcbiAgICAgICAgICAgICAgICBQYXNzd29yZFNjb3JlLmNoZWNrUGFzc1N0cmVuZ3RoKHtcbiAgICAgICAgICAgICAgICAgICAgcGFzczogZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LiRzc2hQYXNzd29yZC52YWwoKSxcbiAgICAgICAgICAgICAgICAgICAgYmFyOiAkKCcuc3NoLXBhc3N3b3JkLXNjb3JlJyksXG4gICAgICAgICAgICAgICAgICAgIHNlY3Rpb246ICQoJy5zc2gtcGFzc3dvcmQtc2NvcmUtc2VjdGlvbicpLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBFbmFibGUgdGFiIG5hdmlnYXRpb24gd2l0aCBoaXN0b3J5IHN1cHBvcnRcbiAgICAgICAgJCgnI2dlbmVyYWwtc2V0dGluZ3MtbWVudScpLmZpbmQoJy5pdGVtJykudGFiKHtcbiAgICAgICAgICAgIGhpc3Rvcnk6IHRydWUsXG4gICAgICAgICAgICBoaXN0b3J5VHlwZTogJ2hhc2gnLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBFbmFibGUgZHJvcGRvd25zIG9uIHRoZSBmb3JtXG4gICAgICAgICQoJyNnZW5lcmFsLXNldHRpbmdzLWZvcm0gLmRyb3Bkb3duJykuZHJvcGRvd24oKTtcblxuICAgICAgICAvLyBFbmFibGUgY2hlY2tib3hlcyBvbiB0aGUgZm9ybVxuICAgICAgICAkKCcjZ2VuZXJhbC1zZXR0aW5ncy1mb3JtIC5jaGVja2JveCcpLmNoZWNrYm94KCk7XG5cbiAgICAgICAgLy8gRW5hYmxlIHRhYmxlIGRyYWctbi1kcm9wIGZ1bmN0aW9uYWxpdHlcbiAgICAgICAgJCgnI2F1ZGlvLWNvZGVjcy10YWJsZSwgI3ZpZGVvLWNvZGVjcy10YWJsZScpLnRhYmxlRG5EKHtcbiAgICAgICAgICAgIG9uRHJvcCgpIHtcbiAgICAgICAgICAgICAgICAvLyBUcmlnZ2VyIGNoYW5nZSBldmVudCB0byBhY2tub3dsZWRnZSB0aGUgbW9kaWZpY2F0aW9uXG4gICAgICAgICAgICAgICAgRm9ybS5kYXRhQ2hhbmdlZCgpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9uRHJhZ0NsYXNzOiAnaG92ZXJpbmdSb3cnLFxuICAgICAgICAgICAgZHJhZ0hhbmRsZTogJy5kcmFnSGFuZGxlJyxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gRW5hYmxlIGRyb3Bkb3duIHdpdGggc291bmQgZmlsZSBzZWxlY3Rpb25cbiAgICAgICAgJCgnI2dlbmVyYWwtc2V0dGluZ3MtZm9ybSAuYXVkaW8tbWVzc2FnZS1zZWxlY3QnKS5kcm9wZG93bihTb3VuZEZpbGVzU2VsZWN0b3IuZ2V0RHJvcGRvd25TZXR0aW5nc1dpdGhFbXB0eSgpKTtcblxuICAgICAgICAvLyBJbml0aWFsaXplIHJlY29yZHMgc2F2ZSBwZXJpb2Qgc2xpZGVyXG4gICAgICAgIGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kcmVjb3Jkc1NhdmVQZXJpb2RTbGlkZXJcbiAgICAgICAgICAgIC5zbGlkZXIoe1xuICAgICAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgICAgICBtYXg6IDUsXG4gICAgICAgICAgICAgICAgc3RlcDogMSxcbiAgICAgICAgICAgICAgICBzbW9vdGg6IHRydWUsXG4gICAgICAgICAgICAgICAgaW50ZXJwcmV0TGFiZWw6IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgbGFiZWxzID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAgZ2xvYmFsVHJhbnNsYXRlLmdzX1N0b3JlMU1vbnRoT2ZSZWNvcmRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgZ2xvYmFsVHJhbnNsYXRlLmdzX1N0b3JlM01vbnRoc09mUmVjb3JkcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdsb2JhbFRyYW5zbGF0ZS5nc19TdG9yZTZNb250aHNPZlJlY29yZHMsXG4gICAgICAgICAgICAgICAgICAgICAgICBnbG9iYWxUcmFuc2xhdGUuZ3NfU3RvcmUxWWVhck9mUmVjb3JkcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdsb2JhbFRyYW5zbGF0ZS5nc19TdG9yZTNZZWFyc09mUmVjb3JkcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdsb2JhbFRyYW5zbGF0ZS5nc19TdG9yZUFsbFBvc3NpYmxlUmVjb3JkcyxcbiAgICAgICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGxhYmVsc1t2YWx1ZV07XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBvbkNoYW5nZTogZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmNiQWZ0ZXJTZWxlY3RTYXZlUGVyaW9kU2xpZGVyLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgO1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIGZvcm1cbiAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmluaXRpYWxpemVGb3JtKCk7XG5cbiAgICAgICAgLy8gSW5pdGlhbGl6ZSBhZGRpdGlvbmFsIHZhbGlkYXRpb24gcnVsZXNcbiAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmluaXRSdWxlcygpO1xuXG4gICAgICAgIC8vIFNob3csIGhpZGUgc3NoIHBhc3N3b3JkIHNlZ21lbnRcbiAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LiRkaXNhYmxlU1NIUGFzc3dvcmQuY2hlY2tib3goe1xuICAgICAgICAgICAgJ29uQ2hhbmdlJzogZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LnNob3dIaWRlU1NIUGFzc3dvcmRcbiAgICAgICAgfSk7XG4gICAgICAgIGdlbmVyYWxTZXR0aW5nc01vZGlmeS5zaG93SGlkZVNTSFBhc3N3b3JkKCk7XG5cbiAgICAgICAgLy8gU2V0IHRoZSBpbml0aWFsIHZhbHVlIGZvciB0aGUgcmVjb3JkcyBzYXZlIHBlcmlvZCBzbGlkZXJcbiAgICAgICAgY29uc3QgcmVjb3JkU2F2ZVBlcmlvZCA9IGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kZm9ybU9iai5mb3JtKCdnZXQgdmFsdWUnLCAnUEJYUmVjb3JkU2F2ZVBlcmlvZCcpO1xuICAgICAgICBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJHJlY29yZHNTYXZlUGVyaW9kU2xpZGVyXG4gICAgICAgICAgICAuc2xpZGVyKCdzZXQgdmFsdWUnLCBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuc2F2ZVJlY29yZHNQZXJpb2QuaW5kZXhPZihyZWNvcmRTYXZlUGVyaW9kKSwgZmFsc2UpO1xuXG4gICAgICAgIC8vIEFkZCBldmVudCBsaXN0ZW5lciB0byBoYW5kbGUgdGFiIGFjdGl2YXRpb25cbiAgICAgICAgJCh3aW5kb3cpLm9uKCdHUy1BY3RpdmF0ZVRhYicsIChldmVudCwgbmFtZVRhYikgPT4ge1xuICAgICAgICAgICAgJCgnI2dlbmVyYWwtc2V0dGluZ3MtbWVudScpLmZpbmQoJy5pdGVtJykudGFiKCdjaGFuZ2UgdGFiJywgbmFtZVRhYik7XG4gICAgICAgIH0pO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBTaG93LCBoaWRlIHNzaCBwYXNzd29yZCBzZWdtZW50IGFjY29yZGluZyB0byB0aGUgdmFsdWUgb2YgdXNlIFNTSCBwYXNzd29yZCBjaGVja2JveC5cbiAgICAgKi9cbiAgICBzaG93SGlkZVNTSFBhc3N3b3JkKCl7XG4gICAgICAgIGlmIChnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJGRpc2FibGVTU0hQYXNzd29yZC5jaGVja2JveCgnaXMgY2hlY2tlZCcpKSB7XG4gICAgICAgICAgICBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJHNzaFBhc3N3b3JkU2VnbWVudC5oaWRlKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJHNzaFBhc3N3b3JkU2VnbWVudC5zaG93KCk7XG4gICAgICAgIH1cbiAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmluaXRSdWxlcygpO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGNvbmRpdGlvbnMgZm9yIGRlbGV0aW5nIGFsbCByZWNvcmRzLlxuICAgICAqIENvbXBhcmVzIHRoZSB2YWx1ZSBvZiB0aGUgJ2RlbGV0ZUFsbElucHV0JyBmaWVsZCB3aXRoIGEgcGhyYXNlLlxuICAgICAqIElmIHRoZXkgbWF0Y2gsIGl0IHRyaWdnZXJzIGEgc3lzdGVtIHJlc3RvcmUgdG8gZGVmYXVsdCBzZXR0aW5ncy5cbiAgICAgKi9cbiAgICBjaGVja0RlbGV0ZUFsbENvbmRpdGlvbnMoKSB7XG5cbiAgICAgICAgLy8gR2V0IHRoZSB2YWx1ZSBvZiAnZGVsZXRlQWxsSW5wdXQnIGZpZWxkLlxuICAgICAgICBjb25zdCBkZWxldGVBbGxJbnB1dCA9IGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kZm9ybU9iai5mb3JtKCdnZXQgdmFsdWUnLCAnZGVsZXRlQWxsSW5wdXQnKTtcblxuICAgICAgICAvLyBJZiB0aGUgZW50ZXJlZCBwaHJhc2UgbWF0Y2hlcyB0aGUgcGhyYXNlIGluICdnbG9iYWxUcmFuc2xhdGUuZ3NfRW50ZXJEZWxldGVBbGxQaHJhc2UnLFxuICAgICAgICAvLyBjYWxsICdQYnhBcGkuU3lzdGVtUmVzdG9yZURlZmF1bHRTZXR0aW5ncycgdG8gcmVzdG9yZSBkZWZhdWx0IHNldHRpbmdzLlxuICAgICAgICBpZiAoZGVsZXRlQWxsSW5wdXQgPT09IGdsb2JhbFRyYW5zbGF0ZS5nc19FbnRlckRlbGV0ZUFsbFBocmFzZSkge1xuICAgICAgICAgICAgUGJ4QXBpLlN5c3RlbVJlc3RvcmVEZWZhdWx0U2V0dGluZ3MoZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmNiQWZ0ZXJSZXN0b3JlRGVmYXVsdFNldHRpbmdzKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGUgcmVzcG9uc2UgYWZ0ZXIgcmVzdG9yaW5nIGRlZmF1bHQgc2V0dGluZ3MuXG4gICAgICogQHBhcmFtIHtib29sZWFufHN0cmluZ30gcmVzcG9uc2UgLSBSZXNwb25zZSBmcm9tIHRoZSBzZXJ2ZXIgYWZ0ZXIgcmVzdG9yaW5nIGRlZmF1bHQgc2V0dGluZ3MuXG4gICAgICovXG4gICAgY2JBZnRlclJlc3RvcmVEZWZhdWx0U2V0dGluZ3MocmVzcG9uc2UpIHtcblxuICAgICAgICAvLyBDaGVjayBpZiB0aGUgcmVzcG9uc2UgaXMgdHJ1ZSwgZGlzcGxheSBhIHN1Y2Nlc3MgbWVzc2FnZVxuICAgICAgICAvLyBvdGhlcndpc2UsIGRpc3BsYXkgdGhlIHJlc3BvbnNlIG1lc3NhZ2UuXG4gICAgICAgIGlmIChyZXNwb25zZSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgVXNlck1lc3NhZ2Uuc2hvd0luZm9ybWF0aW9uKGdsb2JhbFRyYW5zbGF0ZS5nc19BbGxTZXR0aW5nc0RlbGV0ZWQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgVXNlck1lc3NhZ2Uuc2hvd011bHRpU3RyaW5nKHJlc3BvbnNlKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGUgZXZlbnQgYWZ0ZXIgdGhlIHNlbGVjdCBzYXZlIHBlcmlvZCBzbGlkZXIgaXMgY2hhbmdlZC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgLSBUaGUgc2VsZWN0ZWQgdmFsdWUgZnJvbSB0aGUgc2xpZGVyLlxuICAgICAqL1xuICAgIGNiQWZ0ZXJTZWxlY3RTYXZlUGVyaW9kU2xpZGVyKHZhbHVlKSB7XG5cbiAgICAgICAgLy8gR2V0IHRoZSBzYXZlIHBlcmlvZCBjb3JyZXNwb25kaW5nIHRvIHRoZSBzbGlkZXIgdmFsdWUuXG4gICAgICAgIGNvbnN0IHNhdmVQZXJpb2QgPSBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuc2F2ZVJlY29yZHNQZXJpb2RbdmFsdWVdO1xuXG4gICAgICAgIC8vIFNldCB0aGUgZm9ybSB2YWx1ZSBmb3IgJ1BCWFJlY29yZFNhdmVQZXJpb2QnIHRvIHRoZSBzZWxlY3RlZCBzYXZlIHBlcmlvZC5cbiAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LiRmb3JtT2JqLmZvcm0oJ3NldCB2YWx1ZScsICdQQlhSZWNvcmRTYXZlUGVyaW9kJywgc2F2ZVBlcmlvZCk7XG5cbiAgICAgICAgLy8gVHJpZ2dlciBjaGFuZ2UgZXZlbnQgdG8gYWNrbm93bGVkZ2UgdGhlIG1vZGlmaWNhdGlvblxuICAgICAgICBGb3JtLmRhdGFDaGFuZ2VkKCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIENhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCBiZWZvcmUgdGhlIGZvcm0gaXMgc2VudFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzZXR0aW5ncyAtIFRoZSBjdXJyZW50IHNldHRpbmdzIG9mIHRoZSBmb3JtXG4gICAgICogQHJldHVybnMge09iamVjdH0gLSBUaGUgdXBkYXRlZCBzZXR0aW5ncyBvZiB0aGUgZm9ybVxuICAgICAqL1xuICAgIGNiQmVmb3JlU2VuZEZvcm0oc2V0dGluZ3MpIHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gc2V0dGluZ3M7XG4gICAgICAgIHJlc3VsdC5kYXRhID0gZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LiRmb3JtT2JqLmZvcm0oJ2dldCB2YWx1ZXMnKTtcbiAgICAgICAgY29uc3QgYXJyQ29kZWNzID0gW107XG4gICAgICAgICQoJyNhdWRpby1jb2RlY3MtdGFibGUgLmNvZGVjLXJvdywgI3ZpZGVvLWNvZGVjcy10YWJsZSAuY29kZWMtcm93JykuZWFjaCgoaW5kZXgsIG9iaikgPT4ge1xuICAgICAgICAgICAgaWYgKCQob2JqKS5hdHRyKCdpZCcpKSB7XG4gICAgICAgICAgICAgICAgYXJyQ29kZWNzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBjb2RlY0lkOiAkKG9iaikuYXR0cignaWQnKSxcbiAgICAgICAgICAgICAgICAgICAgZGlzYWJsZWQ6ICQob2JqKS5maW5kKCcuY2hlY2tib3gnKS5jaGVja2JveCgnaXMgdW5jaGVja2VkJyksXG4gICAgICAgICAgICAgICAgICAgIHByaW9yaXR5OiBpbmRleCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJlc3VsdC5kYXRhLmNvZGVjcyA9IEpTT04uc3RyaW5naWZ5KGFyckNvZGVjcyk7XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQ2FsbGJhY2sgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIGFmdGVyIHRoZSBmb3JtIGhhcyBiZWVuIHNlbnQuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHJlc3BvbnNlIC0gVGhlIHJlc3BvbnNlIGZyb20gdGhlIHNlcnZlciBhZnRlciB0aGUgZm9ybSBpcyBzZW50XG4gICAgICovXG4gICAgY2JBZnRlclNlbmRGb3JtKHJlc3BvbnNlKSB7XG4gICAgICAgICQoXCIjZXJyb3ItbWVzc2FnZXNcIikucmVtb3ZlKCk7XG4gICAgICAgIGlmICghcmVzcG9uc2Uuc3VjY2Vzcykge1xuICAgICAgICAgICAgRm9ybS4kc3VibWl0QnV0dG9uLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmdlbmVyYXRlRXJyb3JNZXNzYWdlSHRtbChyZXNwb25zZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAkKCcucGFzc3dvcmQtdmFsaWRhdGUnKS5yZW1vdmUoKTtcbiAgICAgICAgfVxuICAgICAgICBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuY2hlY2tEZWxldGVBbGxDb25kaXRpb25zKCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFRoZSBmdW5jdGlvbiBjb2xsZWN0cyBhbiBpbmZvcm1hdGlvbiBtZXNzYWdlIGFib3V0IGEgZGF0YSBzYXZpbmcgZXJyb3JcbiAgICAgKiBAcGFyYW0gcmVzcG9uc2VcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuICAgIGdlbmVyYXRlRXJyb3JNZXNzYWdlSHRtbChyZXNwb25zZSkge1xuICAgICAgICBpZiAocmVzcG9uc2UubWVzc2FnZXMgJiYgcmVzcG9uc2UubWVzc2FnZXMuZXJyb3IpIHtcbiAgICAgICAgICAgIGNvbnN0ICRkaXYgPSAkKCc8ZGl2PicsIHsgY2xhc3M6ICd1aSBuZWdhdGl2ZSBtZXNzYWdlJywgaWQ6ICdlcnJvci1tZXNzYWdlcycgfSk7XG4gICAgICAgICAgICBjb25zdCAkaGVhZGVyID0gJCgnPGRpdj4nLCB7IGNsYXNzOiAnaGVhZGVyJyB9KS50ZXh0KGdsb2JhbFRyYW5zbGF0ZS5nc19FcnJvclNhdmVTZXR0aW5ncyk7XG4gICAgICAgICAgICAkZGl2LmFwcGVuZCgkaGVhZGVyKTtcbiAgICAgICAgICAgIGNvbnN0ICR1bCA9ICQoJzx1bD4nLCB7IGNsYXNzOiAnbGlzdCcgfSk7XG4gICAgICAgICAgICBjb25zdCBtZXNzYWdlc1NldCA9IG5ldyBTZXQoKTtcbiAgICAgICAgICAgIHJlc3BvbnNlLm1lc3NhZ2VzLmVycm9yLmZvckVhY2goZXJyb3JBcnJheSA9PiB7XG4gICAgICAgICAgICAgICAgZXJyb3JBcnJheS5mb3JFYWNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHRleHRDb250ZW50ID0nJztcbiAgICAgICAgICAgICAgICAgICAgaWYoZ2xvYmFsVHJhbnNsYXRlW2Vycm9yLm1lc3NhZ2VdID09PSB1bmRlZmluZWQpe1xuICAgICAgICAgICAgICAgICAgICAgICAgdGV4dENvbnRlbnQgPSBlcnJvci5tZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICB9ZWxzZXtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHRDb250ZW50ID0gZ2xvYmFsVHJhbnNsYXRlW2Vycm9yLm1lc3NhZ2VdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlc1NldC5oYXModGV4dENvbnRlbnQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZXNTZXQuYWRkKGVycm9yLm1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgICAgICAkdWwuYXBwZW5kKCQoJzxsaT4nKS50ZXh0KHRleHRDb250ZW50KSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICRkaXYuYXBwZW5kKCR1bCk7XG4gICAgICAgICAgICAkKCcjc3VibWl0YnV0dG9uJykuYmVmb3JlKCRkaXYpO1xuICAgICAgICAgICAgcmV0dXJuICRkaXY7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZSB0aGUgdmFsaWRhdGlvbiBydWxlcyBvZiB0aGUgZm9ybVxuICAgICAqL1xuICAgIGluaXRSdWxlcygpIHtcbiAgICAgICAgLy8gU1NIUGFzc3dvcmRcbiAgICAgICAgaWYgKGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kZGlzYWJsZVNTSFBhc3N3b3JkLmNoZWNrYm94KCdpcyBjaGVja2VkJykpIHtcbiAgICAgICAgICAgIEZvcm0udmFsaWRhdGVSdWxlcy5TU0hQYXNzd29yZC5ydWxlcyA9IGdlbmVyYWxTZXR0aW5nc01vZGlmeS5hZGRpdGlvbmFsU3NoVmFsaWRSdWxlc05vUGFzcztcbiAgICAgICAgfSBlbHNlIGlmIChnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJHNzaFBhc3N3b3JkLnZhbCgpID09PSBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuaGlkZGVuUGFzc3dvcmQpIHtcbiAgICAgICAgICAgIEZvcm0udmFsaWRhdGVSdWxlcy5TU0hQYXNzd29yZC5ydWxlcyA9IFtdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgRm9ybS52YWxpZGF0ZVJ1bGVzLlNTSFBhc3N3b3JkLnJ1bGVzID0gZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmFkZGl0aW9uYWxTc2hWYWxpZFJ1bGVzUGFzcztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFdlYkFkbWluUGFzc3dvcmRcbiAgICAgICAgaWYgKGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kd2ViQWRtaW5QYXNzd29yZC52YWwoKSA9PT0gZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmhpZGRlblBhc3N3b3JkKSB7XG4gICAgICAgICAgICBGb3JtLnZhbGlkYXRlUnVsZXMuV2ViQWRtaW5QYXNzd29yZC5ydWxlcyA9IFtdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgRm9ybS52YWxpZGF0ZVJ1bGVzLldlYkFkbWluUGFzc3dvcmQucnVsZXMgPSBnZW5lcmFsU2V0dGluZ3NNb2RpZnkud2ViQWRtaW5QYXNzd29yZFJ1bGVzO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemUgdGhlIGZvcm0gd2l0aCBjdXN0b20gc2V0dGluZ3NcbiAgICAgKi9cbiAgICBpbml0aWFsaXplRm9ybSgpIHtcbiAgICAgICAgRm9ybS4kZm9ybU9iaiA9IGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kZm9ybU9iajtcbiAgICAgICAgRm9ybS51cmwgPSBgJHtnbG9iYWxSb290VXJsfWdlbmVyYWwtc2V0dGluZ3Mvc2F2ZWA7IC8vIEZvcm0gc3VibWlzc2lvbiBVUkxcbiAgICAgICAgRm9ybS52YWxpZGF0ZVJ1bGVzID0gZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LnZhbGlkYXRlUnVsZXM7IC8vIEZvcm0gdmFsaWRhdGlvbiBydWxlc1xuICAgICAgICBGb3JtLmNiQmVmb3JlU2VuZEZvcm0gPSBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuY2JCZWZvcmVTZW5kRm9ybTsgLy8gQ2FsbGJhY2sgYmVmb3JlIGZvcm0gaXMgc2VudFxuICAgICAgICBGb3JtLmNiQWZ0ZXJTZW5kRm9ybSA9IGdlbmVyYWxTZXR0aW5nc01vZGlmeS5jYkFmdGVyU2VuZEZvcm07IC8vIENhbGxiYWNrIGFmdGVyIGZvcm0gaXMgc2VudFxuICAgICAgICBGb3JtLmluaXRpYWxpemUoKTtcbiAgICB9XG59O1xuXG4vLyBXaGVuIHRoZSBkb2N1bWVudCBpcyByZWFkeSwgaW5pdGlhbGl6ZSB0aGUgZ2VuZXJhbFNldHRpbmdzIG1hbmFnZW1lbnQgaW50ZXJmYWNlLlxuJChkb2N1bWVudCkucmVhZHkoKCkgPT4ge1xuICAgIGdlbmVyYWxTZXR0aW5nc01vZGlmeS5pbml0aWFsaXplKCk7XG59KTsiXX0= \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9HZW5lcmFsU2V0dGluZ3MvZ2VuZXJhbC1zZXR0aW5ncy1tb2RpZnkuanMiXSwibmFtZXMiOlsiZ2VuZXJhbFNldHRpbmdzTW9kaWZ5IiwiJGZvcm1PYmoiLCIkIiwiJHdlYkFkbWluUGFzc3dvcmQiLCIkc3NoUGFzc3dvcmQiLCIkZGlzYWJsZVNTSFBhc3N3b3JkIiwicGFyZW50IiwiJHNzaFBhc3N3b3JkU2VnbWVudCIsImhpZGRlblBhc3N3b3JkIiwiJHJlY29yZHNTYXZlUGVyaW9kU2xpZGVyIiwic2F2ZVJlY29yZHNQZXJpb2QiLCJ2YWxpZGF0ZVJ1bGVzIiwicGJ4bmFtZSIsImlkZW50aWZpZXIiLCJydWxlcyIsInR5cGUiLCJwcm9tcHQiLCJnbG9iYWxUcmFuc2xhdGUiLCJnc19WYWxpZGF0ZUVtcHR5UEJYTmFtZSIsIldlYkFkbWluUGFzc3dvcmQiLCJXZWJBZG1pblBhc3N3b3JkUmVwZWF0IiwiZ3NfVmFsaWRhdGVXZWJQYXNzd29yZHNGaWVsZERpZmZlcmVudCIsIlNTSFBhc3N3b3JkIiwiU1NIUGFzc3dvcmRSZXBlYXQiLCJnc19WYWxpZGF0ZVNTSFBhc3N3b3Jkc0ZpZWxkRGlmZmVyZW50IiwiV0VCUG9ydCIsImdzX1ZhbGlkYXRlV0VCUG9ydE91dE9mUmFuZ2UiLCJnc19WYWxpZGF0ZVdFQkhUVFBTUG9ydE5vdEVxdWFsVG9XRUJQb3J0IiwiZ3NfVmFsaWRhdGVXRUJQb3J0Tm90RXF1YWxUb0FqYW1Qb3J0IiwiZ3NfVmFsaWRhdGVXRUJQb3J0Tm90RXF1YWxUb0FqYW1UTFNQb3J0IiwiV0VCSFRUUFNQb3J0IiwiZ3NfVmFsaWRhdGVXRUJIVFRQU1BvcnRPdXRPZlJhbmdlIiwiZ3NfVmFsaWRhdGVXRUJIVFRQU1BvcnROb3RFcXVhbFRvQWphbVBvcnQiLCJnc19WYWxpZGF0ZVdFQkhUVFBTUG9ydE5vdEVxdWFsVG9BamFtVExTUG9ydCIsIkFKQU1Qb3J0IiwiZ3NfVmFsaWRhdGVBSkFNUG9ydE91dE9mUmFuZ2UiLCJ3ZWJBZG1pblBhc3N3b3JkUnVsZXMiLCJnc19WYWxpZGF0ZUVtcHR5V2ViUGFzc3dvcmQiLCJnc19WYWxpZGF0ZVdlYWtXZWJQYXNzd29yZCIsInZhbHVlIiwiZ3NfUGFzc3dvcmRzIiwiZ3NfUGFzc3dvcmROb0xvd1NpbXZvbCIsImdzX1Bhc3N3b3JkTm9OdW1iZXJzIiwiZ3NfUGFzc3dvcmROb1VwcGVyU2ltdm9sIiwiYWRkaXRpb25hbFNzaFZhbGlkUnVsZXNQYXNzIiwiZ3NfVmFsaWRhdGVFbXB0eVNTSFBhc3N3b3JkIiwiZ3NfVmFsaWRhdGVXZWFrU1NIUGFzc3dvcmQiLCJnc19TU0hQYXNzd29yZCIsImFkZGl0aW9uYWxTc2hWYWxpZFJ1bGVzTm9QYXNzIiwiaW5pdGlhbGl6ZSIsIm9uIiwidmFsIiwiaW5pdFJ1bGVzIiwiUGFzc3dvcmRTY29yZSIsImNoZWNrUGFzc1N0cmVuZ3RoIiwicGFzcyIsImJhciIsInNlY3Rpb24iLCJmaW5kIiwidGFiIiwiaGlzdG9yeSIsImhpc3RvcnlUeXBlIiwiZHJvcGRvd24iLCJjaGVja2JveCIsInRhYmxlRG5EIiwib25Ecm9wIiwiRm9ybSIsImRhdGFDaGFuZ2VkIiwib25EcmFnQ2xhc3MiLCJkcmFnSGFuZGxlIiwiU291bmRGaWxlc1NlbGVjdG9yIiwiZ2V0RHJvcGRvd25TZXR0aW5nc1dpdGhFbXB0eSIsInNsaWRlciIsIm1pbiIsIm1heCIsInN0ZXAiLCJzbW9vdGgiLCJpbnRlcnByZXRMYWJlbCIsImxhYmVscyIsImdzX1N0b3JlMU1vbnRoT2ZSZWNvcmRzIiwiZ3NfU3RvcmUzTW9udGhzT2ZSZWNvcmRzIiwiZ3NfU3RvcmU2TW9udGhzT2ZSZWNvcmRzIiwiZ3NfU3RvcmUxWWVhck9mUmVjb3JkcyIsImdzX1N0b3JlM1llYXJzT2ZSZWNvcmRzIiwiZ3NfU3RvcmVBbGxQb3NzaWJsZVJlY29yZHMiLCJvbkNoYW5nZSIsImNiQWZ0ZXJTZWxlY3RTYXZlUGVyaW9kU2xpZGVyIiwiaW5pdGlhbGl6ZUZvcm0iLCJzaG93SGlkZVNTSFBhc3N3b3JkIiwicmVjb3JkU2F2ZVBlcmlvZCIsImZvcm0iLCJpbmRleE9mIiwid2luZG93IiwiZXZlbnQiLCJuYW1lVGFiIiwiaGlkZSIsInNob3ciLCJjaGVja0RlbGV0ZUFsbENvbmRpdGlvbnMiLCJkZWxldGVBbGxJbnB1dCIsImdzX0VudGVyRGVsZXRlQWxsUGhyYXNlIiwiUGJ4QXBpIiwiU3lzdGVtUmVzdG9yZURlZmF1bHRTZXR0aW5ncyIsImNiQWZ0ZXJSZXN0b3JlRGVmYXVsdFNldHRpbmdzIiwicmVzcG9uc2UiLCJVc2VyTWVzc2FnZSIsInNob3dJbmZvcm1hdGlvbiIsImdzX0FsbFNldHRpbmdzRGVsZXRlZCIsInNob3dNdWx0aVN0cmluZyIsInNhdmVQZXJpb2QiLCJjYkJlZm9yZVNlbmRGb3JtIiwic2V0dGluZ3MiLCJyZXN1bHQiLCJkYXRhIiwiYXJyQ29kZWNzIiwiZWFjaCIsImluZGV4Iiwib2JqIiwiYXR0ciIsInB1c2giLCJjb2RlY0lkIiwiZGlzYWJsZWQiLCJwcmlvcml0eSIsImNvZGVjcyIsIkpTT04iLCJzdHJpbmdpZnkiLCJjYkFmdGVyU2VuZEZvcm0iLCJyZW1vdmUiLCJzdWNjZXNzIiwiJHN1Ym1pdEJ1dHRvbiIsInJlbW92ZUNsYXNzIiwiZ2VuZXJhdGVFcnJvck1lc3NhZ2VIdG1sIiwibWVzc2FnZXMiLCJlcnJvciIsIiRkaXYiLCJpZCIsIiRoZWFkZXIiLCJ0ZXh0IiwiZ3NfRXJyb3JTYXZlU2V0dGluZ3MiLCJhcHBlbmQiLCIkdWwiLCJtZXNzYWdlc1NldCIsIlNldCIsImZvckVhY2giLCJlcnJvckFycmF5IiwidGV4dENvbnRlbnQiLCJtZXNzYWdlIiwidW5kZWZpbmVkIiwiaGFzIiwiYWRkIiwiYmVmb3JlIiwidXJsIiwiZ2xvYmFsUm9vdFVybCIsImRvY3VtZW50IiwicmVhZHkiXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFHQTs7QUFFQTtBQUNB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LENBQUNXLGFBQTNDLENBSGEsQ0FHNkM7O0FBQzFEdUQsSUFBQUEsSUFBSSxDQUFDMkMsZ0JBQUwsR0FBd0I3RyxxQkFBcUIsQ0FBQzZHLGdCQUE5QyxDQUphLENBSW1EOztBQUNoRTNDLElBQUFBLElBQUksQ0FBQzJELGVBQUwsR0FBdUI3SCxxQkFBcUIsQ0FBQzZILGVBQTdDLENBTGEsQ0FLaUQ7O0FBQzlEM0QsSUFBQUEsSUFBSSxDQUFDakIsVUFBTDtBQUNIO0FBcGR5QixDQUE5QixDLENBdWRBOztBQUNBL0MsQ0FBQyxDQUFDc0osUUFBRCxDQUFELENBQVlDLEtBQVosQ0FBa0IsWUFBTTtBQUNwQnpKLEVBQUFBLHFCQUFxQixDQUFDaUQsVUFBdEI7QUFDSCxDQUZEIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIE1pa29QQlggLSBmcmVlIHBob25lIHN5c3RlbSBmb3Igc21hbGwgYnVzaW5lc3NcbiAqIENvcHlyaWdodCDCqSAyMDE3LTIwMjMgQWxleGV5IFBvcnRub3YgYW5kIE5pa29sYXkgQmVrZXRvdlxuICpcbiAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbS5cbiAqIElmIG5vdCwgc2VlIDxodHRwczovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKi9cblxuXG4vKiBnbG9iYWwgZ2xvYmFsUm9vdFVybCxnbG9iYWxUcmFuc2xhdGUsIEZvcm0sIFBhc3N3b3JkU2NvcmUsIFBieEFwaSwgVXNlck1lc3NhZ2UsIFNvdW5kRmlsZXNTZWxlY3RvciwgJCAqL1xuXG4vKipcbiAqIEEgbW9kdWxlIHRvIGhhbmRsZSBtb2RpZmljYXRpb24gb2YgZ2VuZXJhbCBzZXR0aW5ncy5cbiAqL1xuY29uc3QgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5ID0ge1xuICAgIC8qKlxuICAgICAqIGpRdWVyeSBvYmplY3QgZm9yIHRoZSBmb3JtLlxuICAgICAqIEB0eXBlIHtqUXVlcnl9XG4gICAgICovXG4gICAgJGZvcm1PYmo6ICQoJyNnZW5lcmFsLXNldHRpbmdzLWZvcm0nKSxcblxuICAgIC8qKlxuICAgICAqIGpRdWVyeSBvYmplY3QgZm9yIHRoZSB3ZWIgYWRtaW4gcGFzc3dvcmQgaW5wdXQgZmllbGQuXG4gICAgICogQHR5cGUge2pRdWVyeX1cbiAgICAgKi9cbiAgICAkd2ViQWRtaW5QYXNzd29yZDogJCgnI1dlYkFkbWluUGFzc3dvcmQnKSxcblxuICAgIC8qKlxuICAgICAqIGpRdWVyeSBvYmplY3QgZm9yIHRoZSBzc2ggcGFzc3dvcmQgaW5wdXQgZmllbGQuXG4gICAgICogQHR5cGUge2pRdWVyeX1cbiAgICAgKi9cbiAgICAkc3NoUGFzc3dvcmQ6ICQoJyNTU0hQYXNzd29yZCcpLFxuXG4gICAgLyoqXG4gICAgICogalF1ZXJ5IG9iamVjdCBmb3IgdGhlIHdlYiBzc2ggcGFzc3dvcmQgaW5wdXQgZmllbGQuXG4gICAgICogQHR5cGUge2pRdWVyeX1cbiAgICAgKi9cbiAgICAkZGlzYWJsZVNTSFBhc3N3b3JkOiAkKCcjU1NIRGlzYWJsZVBhc3N3b3JkTG9naW5zJykucGFyZW50KCcuY2hlY2tib3gnKSxcblxuICAgIC8qKlxuICAgICAqIGpRdWVyeSBvYmplY3QgZm9yIHRoZSBTU0ggcGFzc3dvcmQgZmllbGRzXG4gICAgICogQHR5cGUge2pRdWVyeX1cbiAgICAgKi9cbiAgICAkc3NoUGFzc3dvcmRTZWdtZW50OiAkKCcjb25seS1pZi1wYXNzd29yZC1lbmFibGVkJyksXG5cbiAgICAvKipcbiAgICAgKiBJZiBwYXNzd29yZCBzZXQsIGl0IHdpbGwgYmUgaGlkZWQgZnJvbSB3ZWIgdWkuXG4gICAgICovXG4gICAgaGlkZGVuUGFzc3dvcmQ6ICd4eHh4eHh4JyxcblxuICAgIC8qKlxuICAgICAqIGpRdWVyeSBvYmplY3QgZm9yIHRoZSByZWNvcmRzIHJldGVudGlvbiBwZXJpb2Qgc2xpZGVyLlxuICAgICAqIEB0eXBlIHtqUXVlcnl9XG4gICAgICovXG4gICAgJHJlY29yZHNTYXZlUGVyaW9kU2xpZGVyOiAkKCcjUEJYUmVjb3JkU2F2ZVBlcmlvZFNsaWRlcicpLFxuXG4gICAgLyoqXG4gICAgICogUG9zc2libGUgcGVyaW9kIHZhbHVlcyBmb3IgdGhlIHJlY29yZHMgcmV0ZW50aW9uLlxuICAgICAqL1xuICAgIHNhdmVSZWNvcmRzUGVyaW9kOiBbJzMwJywgJzkwJywgJzE4MCcsICczNjAnLCAnMTA4MCcsICcnXSxcblxuICAgIC8qKlxuICAgICAqIFZhbGlkYXRpb24gcnVsZXMgZm9yIHRoZSBmb3JtIGZpZWxkcyBiZWZvcmUgc3VibWlzc2lvbi5cbiAgICAgKlxuICAgICAqIEB0eXBlIHtvYmplY3R9XG4gICAgICovXG4gICAgdmFsaWRhdGVSdWxlczogeyAvLyBnZW5lcmFsU2V0dGluZ3NNb2RpZnkudmFsaWRhdGVSdWxlcy5TU0hQYXNzd29yZC5ydWxlc1xuICAgICAgICBwYnhuYW1lOiB7XG4gICAgICAgICAgICBpZGVudGlmaWVyOiAnUEJYTmFtZScsXG4gICAgICAgICAgICBydWxlczogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2VtcHR5JyxcbiAgICAgICAgICAgICAgICAgICAgcHJvbXB0OiBnbG9iYWxUcmFuc2xhdGUuZ3NfVmFsaWRhdGVFbXB0eVBCWE5hbWUsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICAgIFdlYkFkbWluUGFzc3dvcmQ6IHtcbiAgICAgICAgICAgIGlkZW50aWZpZXI6ICdXZWJBZG1pblBhc3N3b3JkJyxcbiAgICAgICAgICAgIHJ1bGVzOiBbXSxcbiAgICAgICAgfSxcbiAgICAgICAgV2ViQWRtaW5QYXNzd29yZFJlcGVhdDoge1xuICAgICAgICAgICAgaWRlbnRpZmllcjogJ1dlYkFkbWluUGFzc3dvcmRSZXBlYXQnLFxuICAgICAgICAgICAgcnVsZXM6IFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdtYXRjaFtXZWJBZG1pblBhc3N3b3JkXScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV2ViUGFzc3dvcmRzRmllbGREaWZmZXJlbnQsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICAgIFNTSFBhc3N3b3JkOiB7XG4gICAgICAgICAgICBpZGVudGlmaWVyOiAnU1NIUGFzc3dvcmQnLFxuICAgICAgICAgICAgcnVsZXM6IFtdLFxuICAgICAgICB9LFxuICAgICAgICBTU0hQYXNzd29yZFJlcGVhdDoge1xuICAgICAgICAgICAgaWRlbnRpZmllcjogJ1NTSFBhc3N3b3JkUmVwZWF0JyxcbiAgICAgICAgICAgIHJ1bGVzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnbWF0Y2hbU1NIUGFzc3dvcmRdJyxcbiAgICAgICAgICAgICAgICAgICAgcHJvbXB0OiBnbG9iYWxUcmFuc2xhdGUuZ3NfVmFsaWRhdGVTU0hQYXNzd29yZHNGaWVsZERpZmZlcmVudCxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgICAgV0VCUG9ydDoge1xuICAgICAgICAgICAgaWRlbnRpZmllcjogJ1dFQlBvcnQnLFxuICAgICAgICAgICAgcnVsZXM6IFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdpbnRlZ2VyWzEuLjY1NTM1XScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV0VCUG9ydE91dE9mUmFuZ2UsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdkaWZmZXJlbnRbV0VCSFRUUFNQb3J0XScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV0VCSFRUUFNQb3J0Tm90RXF1YWxUb1dFQlBvcnQsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdkaWZmZXJlbnRbQUpBTVBvcnRUTFNdJyxcbiAgICAgICAgICAgICAgICAgICAgcHJvbXB0OiBnbG9iYWxUcmFuc2xhdGUuZ3NfVmFsaWRhdGVXRUJQb3J0Tm90RXF1YWxUb0FqYW1Qb3J0LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnZGlmZmVyZW50W0FKQU1Qb3J0XScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV0VCUG9ydE5vdEVxdWFsVG9BamFtVExTUG9ydCxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgICAgV0VCSFRUUFNQb3J0OiB7XG4gICAgICAgICAgICBpZGVudGlmaWVyOiAnV0VCSFRUUFNQb3J0JyxcbiAgICAgICAgICAgIHJ1bGVzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnaW50ZWdlclsxLi42NTUzNV0nLFxuICAgICAgICAgICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS5nc19WYWxpZGF0ZVdFQkhUVFBTUG9ydE91dE9mUmFuZ2UsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdkaWZmZXJlbnRbV0VCUG9ydF0nLFxuICAgICAgICAgICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS5nc19WYWxpZGF0ZVdFQkhUVFBTUG9ydE5vdEVxdWFsVG9XRUJQb3J0LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnZGlmZmVyZW50W0FKQU1Qb3J0VExTXScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV0VCSFRUUFNQb3J0Tm90RXF1YWxUb0FqYW1Qb3J0LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnZGlmZmVyZW50W0FKQU1Qb3J0XScsXG4gICAgICAgICAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV0VCSFRUUFNQb3J0Tm90RXF1YWxUb0FqYW1UTFNQb3J0LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgICBBSkFNUG9ydDoge1xuICAgICAgICAgICAgaWRlbnRpZmllcjogJ0FKQU1Qb3J0JyxcbiAgICAgICAgICAgIHJ1bGVzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnaW50ZWdlclsxLi42NTUzNV0nLFxuICAgICAgICAgICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS5nc19WYWxpZGF0ZUFKQU1Qb3J0T3V0T2ZSYW5nZSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2RpZmZlcmVudFtBSkFNUG9ydFRMU10nLFxuICAgICAgICAgICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS5nc19WYWxpZGF0ZUFKQU1Qb3J0T3V0T2ZSYW5nZSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICB9LFxuXG4gICAgLy8gUnVsZXMgZm9yIHRoZSB3ZWIgYWRtaW4gcGFzc3dvcmQgZmllbGQgd2hlbiBpdCBub3QgZXF1YWwgdG8gaGlkZGVuUGFzc3dvcmRcbiAgICB3ZWJBZG1pblBhc3N3b3JkUnVsZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ2VtcHR5JyxcbiAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlRW1wdHlXZWJQYXNzd29yZCxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ21pbkxlbmd0aFs1XScsXG4gICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS5nc19WYWxpZGF0ZVdlYWtXZWJQYXNzd29yZCxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ25vdFJlZ0V4cCcsXG4gICAgICAgICAgICB2YWx1ZTogL1thLXpdLyxcbiAgICAgICAgICAgIHByb21wdDogJzxiPicgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmRzICsgJzwvYj46ICcgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmROb0xvd1NpbXZvbFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiAnbm90UmVnRXhwJyxcbiAgICAgICAgICAgIHZhbHVlOiAvXFxkLyxcbiAgICAgICAgICAgIHByb21wdDogJzxiPicgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmRzICsgJzwvYj46ICcgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmROb051bWJlcnNcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ25vdFJlZ0V4cCcsXG4gICAgICAgICAgICB2YWx1ZTogL1tBLVpdLyxcbiAgICAgICAgICAgIHByb21wdDogJzxiPicgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmRzICsgJzwvYj46ICcgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmROb1VwcGVyU2ltdm9sXG4gICAgICAgIH1cbiAgICBdLFxuICAgIC8vIFJ1bGVzIGZvciB0aGUgU1NIIHBhc3N3b3JkIGZpZWxkIHdoZW4gU1NIIGxvZ2luIHRocm91Z2ggdGhlIHBhc3N3b3JkIGVuYWJsZWQsIGFuZCBpdCBub3QgZXF1YWwgdG8gaGlkZGVuUGFzc3dvcmRcbiAgICBhZGRpdGlvbmFsU3NoVmFsaWRSdWxlc1Bhc3M6IFtcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ2VtcHR5JyxcbiAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlRW1wdHlTU0hQYXNzd29yZCxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ21pbkxlbmd0aFs1XScsXG4gICAgICAgICAgICBwcm9tcHQ6IGdsb2JhbFRyYW5zbGF0ZS5nc19WYWxpZGF0ZVdlYWtTU0hQYXNzd29yZCxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ25vdFJlZ0V4cCcsXG4gICAgICAgICAgICB2YWx1ZTogL1thLXpdLyxcbiAgICAgICAgICAgIHByb21wdDogJzxiPicgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfU1NIUGFzc3dvcmQgKyAnPC9iPjogJyArIGdsb2JhbFRyYW5zbGF0ZS5nc19QYXNzd29yZE5vTG93U2ltdm9sXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICAgIHR5cGU6ICdub3RSZWdFeHAnLFxuICAgICAgICAgICAgdmFsdWU6IC9cXGQvLFxuICAgICAgICAgICAgcHJvbXB0OiAnPGI+JyArIGdsb2JhbFRyYW5zbGF0ZS5nc19TU0hQYXNzd29yZCArICc8L2I+OiAnICsgZ2xvYmFsVHJhbnNsYXRlLmdzX1Bhc3N3b3JkTm9OdW1iZXJzXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICAgIHR5cGU6ICdub3RSZWdFeHAnLFxuICAgICAgICAgICAgdmFsdWU6IC9bQS1aXS8sXG4gICAgICAgICAgICBwcm9tcHQ6ICc8Yj4nICsgZ2xvYmFsVHJhbnNsYXRlLmdzX1NTSFBhc3N3b3JkICsgJzwvYj46ICcgKyBnbG9iYWxUcmFuc2xhdGUuZ3NfUGFzc3dvcmROb1VwcGVyU2ltdm9sXG4gICAgICAgIH1cbiAgICBdLFxuXG4gICAgLy8gUnVsZXMgZm9yIHRoZSBTU0ggcGFzc3dvcmQgZmllbGQgd2hlbiBTU0ggbG9naW4gdGhyb3VnaCB0aGUgcGFzc3dvcmQgZGlzYWJsZWRcbiAgICBhZGRpdGlvbmFsU3NoVmFsaWRSdWxlc05vUGFzczogW1xuICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiAnZW1wdHknLFxuICAgICAgICAgICAgcHJvbXB0OiBnbG9iYWxUcmFuc2xhdGUuZ3NfVmFsaWRhdGVFbXB0eVNTSFBhc3N3b3JkLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiAnbWluTGVuZ3RoWzVdJyxcbiAgICAgICAgICAgIHByb21wdDogZ2xvYmFsVHJhbnNsYXRlLmdzX1ZhbGlkYXRlV2Vha1NTSFBhc3N3b3JkLFxuICAgICAgICB9XG4gICAgXSxcblxuICAgIC8qKlxuICAgICAqICBJbml0aWFsaXplIG1vZHVsZSB3aXRoIGV2ZW50IGJpbmRpbmdzIGFuZCBjb21wb25lbnQgaW5pdGlhbGl6YXRpb25zLlxuICAgICAqL1xuICAgIGluaXRpYWxpemUoKSB7XG5cbiAgICAgICAgLy8gV2hlbiBXZWJBZG1pblBhc3N3b3JkIGlucHV0IGlzIGNoYW5nZWQsIHJlY2FsY3VsYXRlIHRoZSBwYXNzd29yZCBzdHJlbmd0aFxuICAgICAgICBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJHdlYkFkbWluUGFzc3dvcmQub24oJ2tleXVwJywgKCkgPT4ge1xuICAgICAgICAgICAgaWYgKGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kd2ViQWRtaW5QYXNzd29yZC52YWwoKSAhPT0gZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmhpZGRlblBhc3N3b3JkKSB7XG4gICAgICAgICAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmluaXRSdWxlcygpO1xuICAgICAgICAgICAgICAgIFBhc3N3b3JkU2NvcmUuY2hlY2tQYXNzU3RyZW5ndGgoe1xuICAgICAgICAgICAgICAgICAgICBwYXNzOiBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJHdlYkFkbWluUGFzc3dvcmQudmFsKCksXG4gICAgICAgICAgICAgICAgICAgIGJhcjogJCgnLnBhc3N3b3JkLXNjb3JlJyksXG4gICAgICAgICAgICAgICAgICAgIHNlY3Rpb246ICQoJy5wYXNzd29yZC1zY29yZS1zZWN0aW9uJyksXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFdoZW4gU1NIUGFzc3dvcmQgaW5wdXQgaXMgY2hhbmdlZCwgcmVjYWxjdWxhdGUgdGhlIHBhc3N3b3JkIHN0cmVuZ3RoXG4gICAgICAgIGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kc3NoUGFzc3dvcmQub24oJ2tleXVwJywgKCkgPT4ge1xuICAgICAgICAgICAgaWYgKGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kc3NoUGFzc3dvcmQudmFsKCkgIT09IGdlbmVyYWxTZXR0aW5nc01vZGlmeS5oaWRkZW5QYXNzd29yZCkge1xuICAgICAgICAgICAgICAgIGdlbmVyYWxTZXR0aW5nc01vZGlmeS5pbml0UnVsZXMoKTtcbiAgICAgICAgICAgICAgICBQYXNzd29yZFNjb3JlLmNoZWNrUGFzc1N0cmVuZ3RoKHtcbiAgICAgICAgICAgICAgICAgICAgcGFzczogZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LiRzc2hQYXNzd29yZC52YWwoKSxcbiAgICAgICAgICAgICAgICAgICAgYmFyOiAkKCcuc3NoLXBhc3N3b3JkLXNjb3JlJyksXG4gICAgICAgICAgICAgICAgICAgIHNlY3Rpb246ICQoJy5zc2gtcGFzc3dvcmQtc2NvcmUtc2VjdGlvbicpLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBFbmFibGUgdGFiIG5hdmlnYXRpb24gd2l0aCBoaXN0b3J5IHN1cHBvcnRcbiAgICAgICAgJCgnI2dlbmVyYWwtc2V0dGluZ3MtbWVudScpLmZpbmQoJy5pdGVtJykudGFiKHtcbiAgICAgICAgICAgIGhpc3Rvcnk6IHRydWUsXG4gICAgICAgICAgICBoaXN0b3J5VHlwZTogJ2hhc2gnLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBFbmFibGUgZHJvcGRvd25zIG9uIHRoZSBmb3JtXG4gICAgICAgICQoJyNnZW5lcmFsLXNldHRpbmdzLWZvcm0gLmRyb3Bkb3duJykuZHJvcGRvd24oKTtcblxuICAgICAgICAvLyBFbmFibGUgY2hlY2tib3hlcyBvbiB0aGUgZm9ybVxuICAgICAgICAkKCcjZ2VuZXJhbC1zZXR0aW5ncy1mb3JtIC5jaGVja2JveCcpLmNoZWNrYm94KCk7XG5cbiAgICAgICAgLy8gRW5hYmxlIHRhYmxlIGRyYWctbi1kcm9wIGZ1bmN0aW9uYWxpdHlcbiAgICAgICAgJCgnI2F1ZGlvLWNvZGVjcy10YWJsZSwgI3ZpZGVvLWNvZGVjcy10YWJsZScpLnRhYmxlRG5EKHtcbiAgICAgICAgICAgIG9uRHJvcCgpIHtcbiAgICAgICAgICAgICAgICAvLyBUcmlnZ2VyIGNoYW5nZSBldmVudCB0byBhY2tub3dsZWRnZSB0aGUgbW9kaWZpY2F0aW9uXG4gICAgICAgICAgICAgICAgRm9ybS5kYXRhQ2hhbmdlZCgpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9uRHJhZ0NsYXNzOiAnaG92ZXJpbmdSb3cnLFxuICAgICAgICAgICAgZHJhZ0hhbmRsZTogJy5kcmFnSGFuZGxlJyxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gRW5hYmxlIGRyb3Bkb3duIHdpdGggc291bmQgZmlsZSBzZWxlY3Rpb25cbiAgICAgICAgJCgnI2dlbmVyYWwtc2V0dGluZ3MtZm9ybSAuYXVkaW8tbWVzc2FnZS1zZWxlY3QnKS5kcm9wZG93bihTb3VuZEZpbGVzU2VsZWN0b3IuZ2V0RHJvcGRvd25TZXR0aW5nc1dpdGhFbXB0eSgpKTtcblxuICAgICAgICAvLyBJbml0aWFsaXplIHJlY29yZHMgc2F2ZSBwZXJpb2Qgc2xpZGVyXG4gICAgICAgIGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kcmVjb3Jkc1NhdmVQZXJpb2RTbGlkZXJcbiAgICAgICAgICAgIC5zbGlkZXIoe1xuICAgICAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgICAgICBtYXg6IDUsXG4gICAgICAgICAgICAgICAgc3RlcDogMSxcbiAgICAgICAgICAgICAgICBzbW9vdGg6IHRydWUsXG4gICAgICAgICAgICAgICAgaW50ZXJwcmV0TGFiZWw6IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgbGFiZWxzID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAgZ2xvYmFsVHJhbnNsYXRlLmdzX1N0b3JlMU1vbnRoT2ZSZWNvcmRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgZ2xvYmFsVHJhbnNsYXRlLmdzX1N0b3JlM01vbnRoc09mUmVjb3JkcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdsb2JhbFRyYW5zbGF0ZS5nc19TdG9yZTZNb250aHNPZlJlY29yZHMsXG4gICAgICAgICAgICAgICAgICAgICAgICBnbG9iYWxUcmFuc2xhdGUuZ3NfU3RvcmUxWWVhck9mUmVjb3JkcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdsb2JhbFRyYW5zbGF0ZS5nc19TdG9yZTNZZWFyc09mUmVjb3JkcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdsb2JhbFRyYW5zbGF0ZS5nc19TdG9yZUFsbFBvc3NpYmxlUmVjb3JkcyxcbiAgICAgICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGxhYmVsc1t2YWx1ZV07XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBvbkNoYW5nZTogZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmNiQWZ0ZXJTZWxlY3RTYXZlUGVyaW9kU2xpZGVyLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgO1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIGZvcm1cbiAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmluaXRpYWxpemVGb3JtKCk7XG5cbiAgICAgICAgLy8gSW5pdGlhbGl6ZSBhZGRpdGlvbmFsIHZhbGlkYXRpb24gcnVsZXNcbiAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmluaXRSdWxlcygpO1xuXG4gICAgICAgIC8vIFNob3csIGhpZGUgc3NoIHBhc3N3b3JkIHNlZ21lbnRcbiAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LiRkaXNhYmxlU1NIUGFzc3dvcmQuY2hlY2tib3goe1xuICAgICAgICAgICAgJ29uQ2hhbmdlJzogZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LnNob3dIaWRlU1NIUGFzc3dvcmRcbiAgICAgICAgfSk7XG4gICAgICAgIGdlbmVyYWxTZXR0aW5nc01vZGlmeS5zaG93SGlkZVNTSFBhc3N3b3JkKCk7XG5cbiAgICAgICAgLy8gU2V0IHRoZSBpbml0aWFsIHZhbHVlIGZvciB0aGUgcmVjb3JkcyBzYXZlIHBlcmlvZCBzbGlkZXJcbiAgICAgICAgY29uc3QgcmVjb3JkU2F2ZVBlcmlvZCA9IGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kZm9ybU9iai5mb3JtKCdnZXQgdmFsdWUnLCAnUEJYUmVjb3JkU2F2ZVBlcmlvZCcpO1xuICAgICAgICBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJHJlY29yZHNTYXZlUGVyaW9kU2xpZGVyXG4gICAgICAgICAgICAuc2xpZGVyKCdzZXQgdmFsdWUnLCBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuc2F2ZVJlY29yZHNQZXJpb2QuaW5kZXhPZihyZWNvcmRTYXZlUGVyaW9kKSwgZmFsc2UpO1xuXG4gICAgICAgIC8vIEFkZCBldmVudCBsaXN0ZW5lciB0byBoYW5kbGUgdGFiIGFjdGl2YXRpb25cbiAgICAgICAgJCh3aW5kb3cpLm9uKCdHUy1BY3RpdmF0ZVRhYicsIChldmVudCwgbmFtZVRhYikgPT4ge1xuICAgICAgICAgICAgJCgnI2dlbmVyYWwtc2V0dGluZ3MtbWVudScpLmZpbmQoJy5pdGVtJykudGFiKCdjaGFuZ2UgdGFiJywgbmFtZVRhYik7XG4gICAgICAgIH0pO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBTaG93LCBoaWRlIHNzaCBwYXNzd29yZCBzZWdtZW50IGFjY29yZGluZyB0byB0aGUgdmFsdWUgb2YgdXNlIFNTSCBwYXNzd29yZCBjaGVja2JveC5cbiAgICAgKi9cbiAgICBzaG93SGlkZVNTSFBhc3N3b3JkKCl7XG4gICAgICAgIGlmIChnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJGRpc2FibGVTU0hQYXNzd29yZC5jaGVja2JveCgnaXMgY2hlY2tlZCcpKSB7XG4gICAgICAgICAgICBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJHNzaFBhc3N3b3JkU2VnbWVudC5oaWRlKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuJHNzaFBhc3N3b3JkU2VnbWVudC5zaG93KCk7XG4gICAgICAgIH1cbiAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmluaXRSdWxlcygpO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGNvbmRpdGlvbnMgZm9yIGRlbGV0aW5nIGFsbCByZWNvcmRzLlxuICAgICAqIENvbXBhcmVzIHRoZSB2YWx1ZSBvZiB0aGUgJ2RlbGV0ZUFsbElucHV0JyBmaWVsZCB3aXRoIGEgcGhyYXNlLlxuICAgICAqIElmIHRoZXkgbWF0Y2gsIGl0IHRyaWdnZXJzIGEgc3lzdGVtIHJlc3RvcmUgdG8gZGVmYXVsdCBzZXR0aW5ncy5cbiAgICAgKi9cbiAgICBjaGVja0RlbGV0ZUFsbENvbmRpdGlvbnMoKSB7XG5cbiAgICAgICAgLy8gR2V0IHRoZSB2YWx1ZSBvZiAnZGVsZXRlQWxsSW5wdXQnIGZpZWxkLlxuICAgICAgICBjb25zdCBkZWxldGVBbGxJbnB1dCA9IGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kZm9ybU9iai5mb3JtKCdnZXQgdmFsdWUnLCAnZGVsZXRlQWxsSW5wdXQnKTtcblxuICAgICAgICAvLyBJZiB0aGUgZW50ZXJlZCBwaHJhc2UgbWF0Y2hlcyB0aGUgcGhyYXNlIGluICdnbG9iYWxUcmFuc2xhdGUuZ3NfRW50ZXJEZWxldGVBbGxQaHJhc2UnLFxuICAgICAgICAvLyBjYWxsICdQYnhBcGkuU3lzdGVtUmVzdG9yZURlZmF1bHRTZXR0aW5ncycgdG8gcmVzdG9yZSBkZWZhdWx0IHNldHRpbmdzLlxuICAgICAgICBpZiAoZGVsZXRlQWxsSW5wdXQgPT09IGdsb2JhbFRyYW5zbGF0ZS5nc19FbnRlckRlbGV0ZUFsbFBocmFzZSkge1xuICAgICAgICAgICAgUGJ4QXBpLlN5c3RlbVJlc3RvcmVEZWZhdWx0U2V0dGluZ3MoZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmNiQWZ0ZXJSZXN0b3JlRGVmYXVsdFNldHRpbmdzKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGUgcmVzcG9uc2UgYWZ0ZXIgcmVzdG9yaW5nIGRlZmF1bHQgc2V0dGluZ3MuXG4gICAgICogQHBhcmFtIHtib29sZWFufHN0cmluZ30gcmVzcG9uc2UgLSBSZXNwb25zZSBmcm9tIHRoZSBzZXJ2ZXIgYWZ0ZXIgcmVzdG9yaW5nIGRlZmF1bHQgc2V0dGluZ3MuXG4gICAgICovXG4gICAgY2JBZnRlclJlc3RvcmVEZWZhdWx0U2V0dGluZ3MocmVzcG9uc2UpIHtcblxuICAgICAgICAvLyBDaGVjayBpZiB0aGUgcmVzcG9uc2UgaXMgdHJ1ZSwgZGlzcGxheSBhIHN1Y2Nlc3MgbWVzc2FnZVxuICAgICAgICAvLyBvdGhlcndpc2UsIGRpc3BsYXkgdGhlIHJlc3BvbnNlIG1lc3NhZ2UuXG4gICAgICAgIGlmIChyZXNwb25zZSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgVXNlck1lc3NhZ2Uuc2hvd0luZm9ybWF0aW9uKGdsb2JhbFRyYW5zbGF0ZS5nc19BbGxTZXR0aW5nc0RlbGV0ZWQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgVXNlck1lc3NhZ2Uuc2hvd011bHRpU3RyaW5nKHJlc3BvbnNlKTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGUgZXZlbnQgYWZ0ZXIgdGhlIHNlbGVjdCBzYXZlIHBlcmlvZCBzbGlkZXIgaXMgY2hhbmdlZC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgLSBUaGUgc2VsZWN0ZWQgdmFsdWUgZnJvbSB0aGUgc2xpZGVyLlxuICAgICAqL1xuICAgIGNiQWZ0ZXJTZWxlY3RTYXZlUGVyaW9kU2xpZGVyKHZhbHVlKSB7XG5cbiAgICAgICAgLy8gR2V0IHRoZSBzYXZlIHBlcmlvZCBjb3JyZXNwb25kaW5nIHRvIHRoZSBzbGlkZXIgdmFsdWUuXG4gICAgICAgIGNvbnN0IHNhdmVQZXJpb2QgPSBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuc2F2ZVJlY29yZHNQZXJpb2RbdmFsdWVdO1xuXG4gICAgICAgIC8vIFNldCB0aGUgZm9ybSB2YWx1ZSBmb3IgJ1BCWFJlY29yZFNhdmVQZXJpb2QnIHRvIHRoZSBzZWxlY3RlZCBzYXZlIHBlcmlvZC5cbiAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LiRmb3JtT2JqLmZvcm0oJ3NldCB2YWx1ZScsICdQQlhSZWNvcmRTYXZlUGVyaW9kJywgc2F2ZVBlcmlvZCk7XG5cbiAgICAgICAgLy8gVHJpZ2dlciBjaGFuZ2UgZXZlbnQgdG8gYWNrbm93bGVkZ2UgdGhlIG1vZGlmaWNhdGlvblxuICAgICAgICBGb3JtLmRhdGFDaGFuZ2VkKCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIENhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCBiZWZvcmUgdGhlIGZvcm0gaXMgc2VudFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzZXR0aW5ncyAtIFRoZSBjdXJyZW50IHNldHRpbmdzIG9mIHRoZSBmb3JtXG4gICAgICogQHJldHVybnMge09iamVjdH0gLSBUaGUgdXBkYXRlZCBzZXR0aW5ncyBvZiB0aGUgZm9ybVxuICAgICAqL1xuICAgIGNiQmVmb3JlU2VuZEZvcm0oc2V0dGluZ3MpIHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gc2V0dGluZ3M7XG4gICAgICAgIHJlc3VsdC5kYXRhID0gZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LiRmb3JtT2JqLmZvcm0oJ2dldCB2YWx1ZXMnKTtcbiAgICAgICAgY29uc3QgYXJyQ29kZWNzID0gW107XG4gICAgICAgICQoJyNhdWRpby1jb2RlY3MtdGFibGUgLmNvZGVjLXJvdywgI3ZpZGVvLWNvZGVjcy10YWJsZSAuY29kZWMtcm93JykuZWFjaCgoaW5kZXgsIG9iaikgPT4ge1xuICAgICAgICAgICAgaWYgKCQob2JqKS5hdHRyKCdpZCcpKSB7XG4gICAgICAgICAgICAgICAgYXJyQ29kZWNzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBjb2RlY0lkOiAkKG9iaikuYXR0cignaWQnKSxcbiAgICAgICAgICAgICAgICAgICAgZGlzYWJsZWQ6ICQob2JqKS5maW5kKCcuY2hlY2tib3gnKS5jaGVja2JveCgnaXMgdW5jaGVja2VkJyksXG4gICAgICAgICAgICAgICAgICAgIHByaW9yaXR5OiBpbmRleCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJlc3VsdC5kYXRhLmNvZGVjcyA9IEpTT04uc3RyaW5naWZ5KGFyckNvZGVjcyk7XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQ2FsbGJhY2sgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIGFmdGVyIHRoZSBmb3JtIGhhcyBiZWVuIHNlbnQuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHJlc3BvbnNlIC0gVGhlIHJlc3BvbnNlIGZyb20gdGhlIHNlcnZlciBhZnRlciB0aGUgZm9ybSBpcyBzZW50XG4gICAgICovXG4gICAgY2JBZnRlclNlbmRGb3JtKHJlc3BvbnNlKSB7XG4gICAgICAgICQoXCIjZXJyb3ItbWVzc2FnZXNcIikucmVtb3ZlKCk7XG4gICAgICAgIGlmICghcmVzcG9uc2Uuc3VjY2Vzcykge1xuICAgICAgICAgICAgRm9ybS4kc3VibWl0QnV0dG9uLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmdlbmVyYXRlRXJyb3JNZXNzYWdlSHRtbChyZXNwb25zZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAkKCcucGFzc3dvcmQtdmFsaWRhdGUnKS5yZW1vdmUoKTtcbiAgICAgICAgfVxuICAgICAgICBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuY2hlY2tEZWxldGVBbGxDb25kaXRpb25zKCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFRoZSBmdW5jdGlvbiBjb2xsZWN0cyBhbiBpbmZvcm1hdGlvbiBtZXNzYWdlIGFib3V0IGEgZGF0YSBzYXZpbmcgZXJyb3JcbiAgICAgKiBAcGFyYW0gcmVzcG9uc2VcbiAgICAgKi9cbiAgICBnZW5lcmF0ZUVycm9yTWVzc2FnZUh0bWwocmVzcG9uc2UpIHtcbiAgICAgICAgaWYgKHJlc3BvbnNlLm1lc3NhZ2VzICYmIHJlc3BvbnNlLm1lc3NhZ2VzLmVycm9yKSB7XG4gICAgICAgICAgICBjb25zdCAkZGl2ID0gJCgnPGRpdj4nLCB7IGNsYXNzOiAndWkgbmVnYXRpdmUgbWVzc2FnZScsIGlkOiAnZXJyb3ItbWVzc2FnZXMnIH0pO1xuICAgICAgICAgICAgY29uc3QgJGhlYWRlciA9ICQoJzxkaXY+JywgeyBjbGFzczogJ2hlYWRlcicgfSkudGV4dChnbG9iYWxUcmFuc2xhdGUuZ3NfRXJyb3JTYXZlU2V0dGluZ3MpO1xuICAgICAgICAgICAgJGRpdi5hcHBlbmQoJGhlYWRlcik7XG4gICAgICAgICAgICBjb25zdCAkdWwgPSAkKCc8dWw+JywgeyBjbGFzczogJ2xpc3QnIH0pO1xuICAgICAgICAgICAgY29uc3QgbWVzc2FnZXNTZXQgPSBuZXcgU2V0KCk7XG4gICAgICAgICAgICByZXNwb25zZS5tZXNzYWdlcy5lcnJvci5mb3JFYWNoKGVycm9yQXJyYXkgPT4ge1xuICAgICAgICAgICAgICAgIGVycm9yQXJyYXkuZm9yRWFjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGxldCB0ZXh0Q29udGVudCA9Jyc7XG4gICAgICAgICAgICAgICAgICAgIGlmKGdsb2JhbFRyYW5zbGF0ZVtlcnJvci5tZXNzYWdlXSA9PT0gdW5kZWZpbmVkKXtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHRDb250ZW50ID0gZXJyb3IubWVzc2FnZTtcbiAgICAgICAgICAgICAgICAgICAgfWVsc2V7XG4gICAgICAgICAgICAgICAgICAgICAgICB0ZXh0Q29udGVudCA9IGdsb2JhbFRyYW5zbGF0ZVtlcnJvci5tZXNzYWdlXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAobWVzc2FnZXNTZXQuaGFzKHRleHRDb250ZW50KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2VzU2V0LmFkZChlcnJvci5tZXNzYWdlKTtcbiAgICAgICAgICAgICAgICAgICAgJHVsLmFwcGVuZCgkKCc8bGk+JykudGV4dCh0ZXh0Q29udGVudCkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAkZGl2LmFwcGVuZCgkdWwpO1xuICAgICAgICAgICAgJCgnI3N1Ym1pdGJ1dHRvbicpLmJlZm9yZSgkZGl2KTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplIHRoZSB2YWxpZGF0aW9uIHJ1bGVzIG9mIHRoZSBmb3JtXG4gICAgICovXG4gICAgaW5pdFJ1bGVzKCkge1xuICAgICAgICAvLyBTU0hQYXNzd29yZFxuICAgICAgICBpZiAoZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LiRkaXNhYmxlU1NIUGFzc3dvcmQuY2hlY2tib3goJ2lzIGNoZWNrZWQnKSkge1xuICAgICAgICAgICAgRm9ybS52YWxpZGF0ZVJ1bGVzLlNTSFBhc3N3b3JkLnJ1bGVzID0gZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmFkZGl0aW9uYWxTc2hWYWxpZFJ1bGVzTm9QYXNzO1xuICAgICAgICB9IGVsc2UgaWYgKGdlbmVyYWxTZXR0aW5nc01vZGlmeS4kc3NoUGFzc3dvcmQudmFsKCkgPT09IGdlbmVyYWxTZXR0aW5nc01vZGlmeS5oaWRkZW5QYXNzd29yZCkge1xuICAgICAgICAgICAgRm9ybS52YWxpZGF0ZVJ1bGVzLlNTSFBhc3N3b3JkLnJ1bGVzID0gW107XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBGb3JtLnZhbGlkYXRlUnVsZXMuU1NIUGFzc3dvcmQucnVsZXMgPSBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuYWRkaXRpb25hbFNzaFZhbGlkUnVsZXNQYXNzO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gV2ViQWRtaW5QYXNzd29yZFxuICAgICAgICBpZiAoZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LiR3ZWJBZG1pblBhc3N3b3JkLnZhbCgpID09PSBnZW5lcmFsU2V0dGluZ3NNb2RpZnkuaGlkZGVuUGFzc3dvcmQpIHtcbiAgICAgICAgICAgIEZvcm0udmFsaWRhdGVSdWxlcy5XZWJBZG1pblBhc3N3b3JkLnJ1bGVzID0gW107XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBGb3JtLnZhbGlkYXRlUnVsZXMuV2ViQWRtaW5QYXNzd29yZC5ydWxlcyA9IGdlbmVyYWxTZXR0aW5nc01vZGlmeS53ZWJBZG1pblBhc3N3b3JkUnVsZXM7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZSB0aGUgZm9ybSB3aXRoIGN1c3RvbSBzZXR0aW5nc1xuICAgICAqL1xuICAgIGluaXRpYWxpemVGb3JtKCkge1xuICAgICAgICBGb3JtLiRmb3JtT2JqID0gZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LiRmb3JtT2JqO1xuICAgICAgICBGb3JtLnVybCA9IGAke2dsb2JhbFJvb3RVcmx9Z2VuZXJhbC1zZXR0aW5ncy9zYXZlYDsgLy8gRm9ybSBzdWJtaXNzaW9uIFVSTFxuICAgICAgICBGb3JtLnZhbGlkYXRlUnVsZXMgPSBnZW5lcmFsU2V0dGluZ3NNb2RpZnkudmFsaWRhdGVSdWxlczsgLy8gRm9ybSB2YWxpZGF0aW9uIHJ1bGVzXG4gICAgICAgIEZvcm0uY2JCZWZvcmVTZW5kRm9ybSA9IGdlbmVyYWxTZXR0aW5nc01vZGlmeS5jYkJlZm9yZVNlbmRGb3JtOyAvLyBDYWxsYmFjayBiZWZvcmUgZm9ybSBpcyBzZW50XG4gICAgICAgIEZvcm0uY2JBZnRlclNlbmRGb3JtID0gZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmNiQWZ0ZXJTZW5kRm9ybTsgLy8gQ2FsbGJhY2sgYWZ0ZXIgZm9ybSBpcyBzZW50XG4gICAgICAgIEZvcm0uaW5pdGlhbGl6ZSgpO1xuICAgIH1cbn07XG5cbi8vIFdoZW4gdGhlIGRvY3VtZW50IGlzIHJlYWR5LCBpbml0aWFsaXplIHRoZSBnZW5lcmFsU2V0dGluZ3MgbWFuYWdlbWVudCBpbnRlcmZhY2UuXG4kKGRvY3VtZW50KS5yZWFkeSgoKSA9PiB7XG4gICAgZ2VuZXJhbFNldHRpbmdzTW9kaWZ5LmluaXRpYWxpemUoKTtcbn0pOyJdfQ== \ No newline at end of file diff --git a/sites/admin-cabinet/assets/js/src/GeneralSettings/general-settings-modify.js b/sites/admin-cabinet/assets/js/src/GeneralSettings/general-settings-modify.js index aabe559bb..220bf610f 100644 --- a/sites/admin-cabinet/assets/js/src/GeneralSettings/general-settings-modify.js +++ b/sites/admin-cabinet/assets/js/src/GeneralSettings/general-settings-modify.js @@ -431,7 +431,6 @@ const generalSettingsModify = { /** * The function collects an information message about a data saving error * @param response - * @returns {string} */ generateErrorMessageHtml(response) { if (response.messages && response.messages.error) { @@ -457,7 +456,6 @@ const generalSettingsModify = { }); $div.append($ul); $('#submitbutton').before($div); - return $div; } }, From d7480ae8250b4ad6ff2afd01dede8b166d96111d Mon Sep 17 00:00:00 2001 From: Weblate Date: Thu, 11 Jul 2024 17:22:06 +0300 Subject: [PATCH 35/58] Translated using Weblate (Thai) Currently translated at 100.0% (1243 of 1243 strings) Translated using Weblate (Romanian) Currently translated at 100.0% (1243 of 1243 strings) Translated using Weblate (Dutch) Currently translated at 100.0% (1243 of 1243 strings) Translated using Weblate (Azerbaijani) Currently translated at 100.0% (1243 of 1243 strings) Translated using Weblate (Greek) Currently translated at 100.0% (1243 of 1243 strings) Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (1243 of 1243 strings) Translated using Weblate (Georgian) Currently translated at 100.0% (1243 of 1243 strings) Translated using Weblate (Turkish) Currently translated at 100.0% (1243 of 1243 strings) Translated using Weblate (Swedish) Currently translated at 100.0% (1243 of 1243 strings) Translated using Weblate (Czech) Currently translated at 100.0% (1243 of 1243 strings) Translated using Weblate (Polish) Currently translated at 100.0% (1243 of 1243 strings) Translated using Weblate (Japanese) Currently translated at 100.0% (1243 of 1243 strings) Translated using Weblate (Italian) Currently translated at 100.0% (1243 of 1243 strings) Translated using Weblate (Danish) Currently translated at 100.0% (1243 of 1243 strings) Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (1243 of 1243 strings) Translated using Weblate (Spanish) Currently translated at 100.0% (1243 of 1243 strings) Translated using Weblate (Vietnamese) Currently translated at 100.0% (1243 of 1243 strings) Translated using Weblate (Portuguese) Currently translated at 100.0% (1243 of 1243 strings) Translated using Weblate (French) Currently translated at 100.0% (1243 of 1243 strings) Translated using Weblate (Ukrainian) Currently translated at 100.0% (1243 of 1243 strings) Translated using Weblate (English) Currently translated at 100.0% (1243 of 1243 strings) Translated using Weblate (German) Currently translated at 100.0% (1243 of 1243 strings) Co-authored-by: Anonymous Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/az/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/cs/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/da/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/de/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/el/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/en/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/es/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/fr/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/it/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/ja/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/ka/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/nl/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/pl/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/pt/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/pt_BR/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/ro/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/sv/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/th/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/tr/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/uk/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/vi/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/zh_Hans/ Translation: MIKOPBX/Core --- src/Common/Messages/az.php | 2 ++ src/Common/Messages/cs.php | 2 ++ src/Common/Messages/da.php | 2 ++ src/Common/Messages/de.php | 2 ++ src/Common/Messages/el.php | 2 ++ src/Common/Messages/en.php | 2 ++ src/Common/Messages/es.php | 2 ++ src/Common/Messages/fr.php | 2 ++ src/Common/Messages/it.php | 2 ++ src/Common/Messages/ja.php | 2 ++ src/Common/Messages/ka.php | 2 ++ src/Common/Messages/nl.php | 2 ++ src/Common/Messages/pl.php | 2 ++ src/Common/Messages/pt.php | 2 ++ src/Common/Messages/pt_BR.php | 2 ++ src/Common/Messages/ro.php | 2 ++ src/Common/Messages/sv.php | 2 ++ src/Common/Messages/th.php | 2 ++ src/Common/Messages/tr.php | 2 ++ src/Common/Messages/uk.php | 2 ++ src/Common/Messages/vi.php | 2 ++ src/Common/Messages/zh_Hans.php | 2 ++ 22 files changed, 44 insertions(+) diff --git a/src/Common/Messages/az.php b/src/Common/Messages/az.php index 02ceeba9e..33d6b8421 100644 --- a/src/Common/Messages/az.php +++ b/src/Common/Messages/az.php @@ -1279,4 +1279,6 @@ 'nw_NATInfo6OR' => 'YA', 'nw_NATInfo2' => '1:1 NAT istifadə edilmirsə, marşrutlaşdırıcının parametrlərində aşağıdakı portları ictimai IP-dən PBX-in daxili IP ünvanına yönləndirin.', 'nw_PublicSIPPort' => 'SIP port nömrəsi daxili %SIP_PORT% PBX-ə yönləndirildi', + 'gs_ErrorSaveSettings' => 'Parametrləri yadda saxlama xətası', + 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Göstərilən artırma nömrəsi artıq istifadə olunur', ]; diff --git a/src/Common/Messages/cs.php b/src/Common/Messages/cs.php index 1bc3eeb4e..e1c497780 100644 --- a/src/Common/Messages/cs.php +++ b/src/Common/Messages/cs.php @@ -1280,4 +1280,6 @@ 'nw_NATInfo6OR' => 'NEBO', 'nw_PublicSIPPort' => 'Číslo SIP portu přesměrováno na interní %SIP_PORT% PBX', 'nw_PublicTLSPort' => 'Číslo portu SIP TLS přesměrováno na interní %TLS_PORT% PBX', + 'gs_ErrorSaveSettings' => 'Při ukládání nastavení došlo k chybě', + 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Zadané číslo pobočky se již používá', ]; diff --git a/src/Common/Messages/da.php b/src/Common/Messages/da.php index bb21dd3fc..ad7a1060e 100644 --- a/src/Common/Messages/da.php +++ b/src/Common/Messages/da.php @@ -1280,4 +1280,6 @@ 'nw_NATInfo2' => 'Hvis 1:1 NAT ikke bruges, skal du omdirigere følgende porte fra den offentlige IP til den interne IP-adresse på PBX\'en i dine routerindstillinger.', 'nw_NATInfo4' => '%RTP_PORT_FROM%-%RTP_PORT_TO% UDP', 'nw_NATInfo5' => 'Hvis et eksternt værtsnavn er angivet, vil det blive brugt frem for den eksterne IP-adresse.', + 'gs_ErrorSaveSettings' => 'Fejl under lagring af indstillinger', + 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Det angivne lokalnummer er allerede i brug', ]; diff --git a/src/Common/Messages/de.php b/src/Common/Messages/de.php index c54ec14ba..efd51e7d2 100644 --- a/src/Common/Messages/de.php +++ b/src/Common/Messages/de.php @@ -1283,4 +1283,6 @@ 'nw_NATInfo1' => 'Wenn Ihr Netzwerk für die Unterstützung von 1:1-NAT konfiguriert ist (normalerweise die Standardeinstellung in Clouds), müssen Sie keine zusätzlichen Einstellungen an Ihrem Router vornehmen.', 'nw_NATInfo2' => 'Wenn 1:1 NAT nicht verwendet wird, leiten Sie in Ihren Router-Einstellungen die folgenden Ports von der öffentlichen IP auf die interne IP-Adresse der TK-Anlage um.', 'nw_PublicSIPPort' => 'SIP-Portnummer, die an die interne %SIP_PORT%-PBX weitergeleitet wird', + 'gs_ErrorSaveSettings' => 'Fehler beim Speichern der Einstellungen', + 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Die angegebene Nebenstellennummer wird bereits verwendet', ]; diff --git a/src/Common/Messages/el.php b/src/Common/Messages/el.php index c1536316c..517e22994 100644 --- a/src/Common/Messages/el.php +++ b/src/Common/Messages/el.php @@ -1280,4 +1280,6 @@ 'nw_NATInfo2' => 'Εάν δεν χρησιμοποιείται NAT 1:1, ανακατευθύνετε τις ακόλουθες θύρες από τη δημόσια IP στην εσωτερική διεύθυνση IP του PBX στις ρυθμίσεις του δρομολογητή σας.', 'nw_PublicSIPPort' => 'Ο αριθμός θύρας SIP προωθείται στο εσωτερικό PBX %SIP_PORT%', 'nw_PublicTLSPort' => 'Ο αριθμός θύρας SIP TLS προωθείται στο εσωτερικό PBX %TLS_PORT%', + 'gs_ErrorSaveSettings' => 'Σφάλμα αποθήκευσης ρυθμίσεων', + 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Ο καθορισμένος αριθμός επέκτασης χρησιμοποιείται ήδη', ]; diff --git a/src/Common/Messages/en.php b/src/Common/Messages/en.php index 328d6e08f..77a589267 100644 --- a/src/Common/Messages/en.php +++ b/src/Common/Messages/en.php @@ -1283,4 +1283,6 @@ 'nw_NATInfo6OR' => 'OR', 'nw_PublicSIPPort' => 'SIP port number forwarded to internal %SIP_PORT% PBX', 'nw_PublicTLSPort' => 'SIP TLS port number forwarded to internal %TLS_PORT% PBX', + 'gs_ErrorSaveSettings' => 'Error saving settings', + 'mo_ThisNumberNotUniqueForExtensionsModels' => 'The specified extension number is already in use', ]; diff --git a/src/Common/Messages/es.php b/src/Common/Messages/es.php index 6f929df81..7cf505b6f 100644 --- a/src/Common/Messages/es.php +++ b/src/Common/Messages/es.php @@ -1280,4 +1280,6 @@ 'nw_NATInfo3' => '%SIP_PORT% TCP/UDP y %TLS_PORT% TCP', 'nw_NATInfo5' => 'Si se especifica un nombre de host externo, se utilizará con preferencia a la dirección IP externa.', 'nw_PublicTLSPort' => 'Número de puerto SIP TLS reenviado al PBX interno %TLS_PORT%', + 'gs_ErrorSaveSettings' => 'Error al guardar la configuración', + 'mo_ThisNumberNotUniqueForExtensionsModels' => 'El número de extensión especificado ya está en uso', ]; diff --git a/src/Common/Messages/fr.php b/src/Common/Messages/fr.php index 529625e53..9091997f0 100644 --- a/src/Common/Messages/fr.php +++ b/src/Common/Messages/fr.php @@ -1280,4 +1280,6 @@ 'nw_NATInfo2' => 'Si le NAT 1:1 n\'est pas utilisé, redirigez les ports suivants de l\'adresse IP publique vers l\'adresse IP interne du PBX dans les paramètres de votre routeur.', 'nw_NATInfo3' => '%SIP_PORT% TCP/UDP et %TLS_PORT% TCP', 'nw_NATInfo4' => '%RTP_PORT_FROM%-%RTP_PORT_TO%UDP', + 'gs_ErrorSaveSettings' => 'Erreur lors de l\'enregistrement des paramètres', + 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Le numéro de poste spécifié est déjà utilisé', ]; diff --git a/src/Common/Messages/it.php b/src/Common/Messages/it.php index 2b432f2b5..e526eac53 100644 --- a/src/Common/Messages/it.php +++ b/src/Common/Messages/it.php @@ -1280,4 +1280,6 @@ 'nw_NATInfo6OR' => 'O', 'nw_PublicSIPPort' => 'Numero di porta SIP inoltrato al PBX interno %SIP_PORT%.', 'nw_PublicTLSPort' => 'Numero di porta SIP TLS inoltrato al PBX interno %TLS_PORT%.', + 'gs_ErrorSaveSettings' => 'Errore durante il salvataggio delle impostazioni', + 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Il numero di interno specificato è già in uso', ]; diff --git a/src/Common/Messages/ja.php b/src/Common/Messages/ja.php index b86b10654..b626ff3b6 100644 --- a/src/Common/Messages/ja.php +++ b/src/Common/Messages/ja.php @@ -1280,4 +1280,6 @@ 'nw_NATInfo2' => '1:1 NAT が使用されていない場合は、ルーター設定で次のポートをパブリック IP から PBX の内部 IP アドレスにリダイレクトします。', 'nw_NATInfo3' => '%SIP_PORT% TCP/UDP および %TLS_PORT% TCP', 'nw_PublicTLSPort' => '内部 %TLS_PORT% PBX に転送される SIP TLS ポート番号', + 'mo_ThisNumberNotUniqueForExtensionsModels' => '指定された内線番号はすでに使用されています', + 'gs_ErrorSaveSettings' => '設定の保存中にエラーが発生しました', ]; diff --git a/src/Common/Messages/ka.php b/src/Common/Messages/ka.php index acade8f33..dfb0673ac 100644 --- a/src/Common/Messages/ka.php +++ b/src/Common/Messages/ka.php @@ -1280,4 +1280,6 @@ 'nw_NATInfo1' => 'თუ თქვენი ქსელი კონფიგურირებულია 1:1 NAT-ის მხარდასაჭერად (ჩვეულებრივ, ნაგულისხმევია ღრუბლებში), თქვენ არ გჭირდებათ რაიმე დამატებითი პარამეტრების გაკეთება თქვენს როუტერზე.', 'nw_NATInfo5' => 'თუ მითითებულია გარე ჰოსტის სახელი, ის გამოყენებული იქნება უპირატესად გარე IP მისამართის ნაცვლად.', 'nw_PublicSIPPort' => 'SIP პორტის ნომერი გადაგზავნილია შიდა %SIP_PORT% PBX-ში', + 'gs_ErrorSaveSettings' => 'შეცდომა პარამეტრების შენახვისას', + 'mo_ThisNumberNotUniqueForExtensionsModels' => 'მითითებული გაფართოების ნომერი უკვე გამოიყენება', ]; diff --git a/src/Common/Messages/nl.php b/src/Common/Messages/nl.php index 4c0561107..8215594f5 100644 --- a/src/Common/Messages/nl.php +++ b/src/Common/Messages/nl.php @@ -1279,4 +1279,6 @@ 'nw_NATInfo6OR' => 'OF', 'nw_PublicSIPPort' => 'SIP-poortnummer doorgestuurd naar interne %SIP_PORT% PBX', 'nw_PublicTLSPort' => 'SIP TLS-poortnummer doorgestuurd naar interne %TLS_PORT% PBX', + 'gs_ErrorSaveSettings' => 'Fout bij opslaan van instellingen', + 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Het opgegeven toestelnummer is al in gebruik', ]; diff --git a/src/Common/Messages/pl.php b/src/Common/Messages/pl.php index fbf24a53a..d12375291 100644 --- a/src/Common/Messages/pl.php +++ b/src/Common/Messages/pl.php @@ -1280,4 +1280,6 @@ 'nw_NATInfo5' => 'Jeśli określono zewnętrzną nazwę hosta, będzie ona używana zamiast zewnętrznego adresu IP.', 'nw_NATInfo6OR' => 'LUB', 'nw_PublicTLSPort' => 'Numer portu SIP TLS przekazywany do wewnętrznej centrali %TLS_PORT% PBX', + 'gs_ErrorSaveSettings' => 'Błąd podczas zapisywania ustawień', + 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Podany numer wewnętrzny jest już zajęty', ]; diff --git a/src/Common/Messages/pt.php b/src/Common/Messages/pt.php index 20c7269d5..01fff494f 100644 --- a/src/Common/Messages/pt.php +++ b/src/Common/Messages/pt.php @@ -1280,4 +1280,6 @@ 'nw_NATInfo6OR' => 'OU', 'nw_PublicSIPPort' => 'Número da porta SIP encaminhado para PBX interno %SIP_PORT%', 'nw_PublicTLSPort' => 'Número da porta SIP TLS encaminhado para PBX interno %TLS_PORT%', + 'gs_ErrorSaveSettings' => 'Erro ao salvar as configurações', + 'mo_ThisNumberNotUniqueForExtensionsModels' => 'O número de ramal especificado já está em uso', ]; diff --git a/src/Common/Messages/pt_BR.php b/src/Common/Messages/pt_BR.php index 79609afb0..6062ca170 100644 --- a/src/Common/Messages/pt_BR.php +++ b/src/Common/Messages/pt_BR.php @@ -1279,4 +1279,6 @@ 'nw_NATInfo5' => 'Se um nome de host externo for especificado, ele será usado preferencialmente ao endereço IP externo.', 'nw_NATInfo6OR' => 'OU', 'nw_PublicSIPPort' => 'Número da porta SIP encaminhado para PBX interno %SIP_PORT%', + 'gs_ErrorSaveSettings' => 'Erro ao salvar as configurações', + 'mo_ThisNumberNotUniqueForExtensionsModels' => 'O número de ramal especificado já está em uso', ]; diff --git a/src/Common/Messages/ro.php b/src/Common/Messages/ro.php index cf18aa1c2..77963fed8 100644 --- a/src/Common/Messages/ro.php +++ b/src/Common/Messages/ro.php @@ -1262,4 +1262,6 @@ 'nw_NATInfo6OR' => 'SAU', 'nw_PublicSIPPort' => 'Numărul portului SIP redirecționat către PBX intern %SIP_PORT%.', 'nw_PublicTLSPort' => 'Numărul portului SIP TLS redirecționat către centrala internă %TLS_PORT%.', + 'gs_ErrorSaveSettings' => 'Eroare la salvarea setărilor', + 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Numărul de extensie specificat este deja în uz', ]; diff --git a/src/Common/Messages/sv.php b/src/Common/Messages/sv.php index 9b643d04c..764d4656a 100644 --- a/src/Common/Messages/sv.php +++ b/src/Common/Messages/sv.php @@ -1246,4 +1246,6 @@ 'nw_NATInfo6OR' => 'ELLER', 'nw_PublicSIPPort' => 'SIP-portnummer vidarebefordrat till intern %SIP_PORT% PBX', 'nw_PublicTLSPort' => 'SIP TLS-portnummer vidarebefordrat till intern %TLS_PORT% PBX', + 'gs_ErrorSaveSettings' => 'Det gick inte att spara inställningar', + 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Det angivna anknytningsnumret används redan', ]; diff --git a/src/Common/Messages/th.php b/src/Common/Messages/th.php index 7afd76e93..adee96048 100644 --- a/src/Common/Messages/th.php +++ b/src/Common/Messages/th.php @@ -1244,4 +1244,6 @@ 'nw_PublicTLSPort' => 'หมายเลขพอร์ต SIP TLS ส่งต่อไปยัง PBX ภายใน %TLS_PORT%', 'nw_NATInfo1' => 'หากเครือข่ายของคุณได้รับการกำหนดค่าให้รองรับ NAT 1:1 (โดยปกติจะเป็นค่าเริ่มต้นในระบบคลาวด์) คุณไม่จำเป็นต้องทำการตั้งค่าเพิ่มเติมใดๆ บนเราเตอร์ของคุณ', 'nw_NATInfo2' => 'หากไม่ได้ใช้ NAT 1:1 ให้เปลี่ยนเส้นทางพอร์ตต่อไปนี้จาก IP สาธารณะไปยังที่อยู่ IP ภายในของ PBX ในการตั้งค่าเราเตอร์ของคุณ', + 'gs_ErrorSaveSettings' => 'เกิดข้อผิดพลาดในการบันทึกการตั้งค่า', + 'mo_ThisNumberNotUniqueForExtensionsModels' => 'หมายเลขต่อขยายที่ระบุมีการใช้งานแล้ว', ]; diff --git a/src/Common/Messages/tr.php b/src/Common/Messages/tr.php index 266403485..c3fd6c8a1 100644 --- a/src/Common/Messages/tr.php +++ b/src/Common/Messages/tr.php @@ -1246,4 +1246,6 @@ 'nw_NATInfo4' => '%RTP_PORT_FROM%-%RTP_PORT_TO% UDP', 'nw_NATInfo5' => 'Harici bir ana bilgisayar adı belirtilirse, harici IP adresi yerine bu ad kullanılacaktır.', 'nw_PublicSIPPort' => 'Dahili %SIP_PORT% PBX\'e iletilen SIP bağlantı noktası numarası', + 'gs_ErrorSaveSettings' => 'Ayarlar kaydedilirken hata oluştu', + 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Belirtilen dahili numara zaten kullanımda', ]; diff --git a/src/Common/Messages/uk.php b/src/Common/Messages/uk.php index c3bae740a..74e774788 100644 --- a/src/Common/Messages/uk.php +++ b/src/Common/Messages/uk.php @@ -1280,4 +1280,6 @@ 'nw_NATInfo5' => 'Якщо вказано зовнішнє ім\'я хоста, воно буде використовуватись у пріоритеті замість зовнішньої IP-адреси.', 'nw_PublicSIPPort' => 'Номер порту SIP перенаправленого на внутрішній %SIP_PORT% PBX', 'nw_PublicTLSPort' => 'Номер порту SIP TLS перенаправленого на внутрішній %TLS_PORT% PBX', + 'gs_ErrorSaveSettings' => 'Помилка збереження налаштувань', + 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Вказаний внутрішній номер вже використовується', ]; diff --git a/src/Common/Messages/vi.php b/src/Common/Messages/vi.php index 4eeded666..f3de3c885 100644 --- a/src/Common/Messages/vi.php +++ b/src/Common/Messages/vi.php @@ -1246,4 +1246,6 @@ 'nw_NATInfo3' => '%SIP_PORT% TCP/UDP và %TLS_PORT% TCP', 'nw_NATInfo4' => '%RTP_PORT_FROM%-%RTP_PORT_TO% UDP', 'nw_NATInfo6OR' => 'HOẶC', + 'gs_ErrorSaveSettings' => 'Lỗi lưu cài đặt', + 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Số máy nhánh được chỉ định đã được sử dụng', ]; diff --git a/src/Common/Messages/zh_Hans.php b/src/Common/Messages/zh_Hans.php index 4e706b227..b529d5daf 100644 --- a/src/Common/Messages/zh_Hans.php +++ b/src/Common/Messages/zh_Hans.php @@ -1246,4 +1246,6 @@ 'nw_NATInfo4' => '%RTP_PORT_FROM%-%RTP_PORT_TO% UDP', 'nw_NATInfo5' => '如果指定了外部主机名,则将优先使用外部主机名而不是外部 IP 地址。', 'nw_PublicTLSPort' => '转发到内部 %TLS_PORT% PBX 的 SIP TLS 端口号', + 'gs_ErrorSaveSettings' => '保存设置时出错', + 'mo_ThisNumberNotUniqueForExtensionsModels' => '指定的分机号码已被使用', ]; From c500efff3c9cb0b9b883ac08d3b36c27fa4aa78a Mon Sep 17 00:00:00 2001 From: boffart <> Date: Fri, 12 Jul 2024 11:57:47 +0300 Subject: [PATCH 36/58] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D1=81=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=B8=20=D0=BC?= =?UTF-8?q?=D0=BE=D0=BD=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=B2=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB=D1=8C=20=D1=80?= =?UTF-8?q?=D0=B5=D0=B7=D0=B5=D1=80=D0=B2=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=BF=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/System/Storage.php | 141 ------------------------------------ 1 file changed, 141 deletions(-) diff --git a/src/Core/System/Storage.php b/src/Core/System/Storage.php index 1d61439da..206073c1b 100644 --- a/src/Core/System/Storage.php +++ b/src/Core/System/Storage.php @@ -172,147 +172,6 @@ public function copyMohFilesToStorage(): void } } - /** - * Mount an SFTP disk. - * - * @param string $host The SFTP server host. - * @param string $port The SFTP server port. - * @param string $user The SFTP server username. - * @param string $pass The SFTP server password. - * @param string $remote_dir The remote directory on the SFTP server. - * @param string $local_dir The local directory to mount the SFTP disk. - * @return bool Returns true if the SFTP disk is successfully mounted, false otherwise. - */ - public static function mountSftpDisk(string $host, string $port, string $user, string $pass, string $remote_dir, string $local_dir): bool - { - - // Create the local directory if it doesn't exist - Util::mwMkdir($local_dir); - - $out = []; - $timeoutPath = Util::which('timeout'); - $sshfsPath = Util::which('sshfs'); - - // Build the command to mount the SFTP disk - $command = "$timeoutPath 3 $sshfsPath -p $port -o nonempty -o password_stdin -o 'StrictHostKeyChecking=no' " . "$user@$host:$remote_dir $local_dir << EOF\n" . "$pass\n" . "EOF\n"; - - // Execute the command to mount the SFTP disk - Processes::mwExec($command, $out); - $response = trim(implode('', $out)); - - if ('Terminated' === $response) { - // The remote server did not respond or an incorrect password was provided. - unset($response); - } - - return self::isStorageDiskMounted("$local_dir "); - } - - /** - * Mount an FTP disk. - * - * @param string $host The FTP server host. - * @param string $port The FTP server port. - * @param string $user The FTP server username. - * @param string $pass The FTP server password. - * @param string $remote_dir The remote directory on the FTP server. - * @param string $local_dir The local directory to mount the FTP disk. - * @return bool Returns true if the FTP disk is successfully mounted, false otherwise. - */ - public static function mountFtp(string $host, string $port, string $user, string $pass, string $remote_dir, string $local_dir): bool - { - - // Create the local directory if it doesn't exist - Util::mwMkdir($local_dir); - $out = []; - - // Build the authentication line for the FTP connection - $auth_line = ''; - if (!empty($user)) { - $auth_line .= 'user="' . $user; - if (!empty($pass)) { - $auth_line .= ":$pass"; - } - $auth_line .= '",'; - } - - // Build the connect line for the FTP connection - $connect_line = 'ftp://' . $host; - if (!empty($port)) { - $connect_line .= ":$port"; - } - if (!empty($remote_dir)) { - $connect_line .= $remote_dir; - } - - $timeoutPath = Util::which('timeout'); - $curlftpfsPath = Util::which('curlftpfs'); - - // Build the command to mount the FTP disk - $command = "$timeoutPath 3 $curlftpfsPath -o allow_other -o {$auth_line}fsname=$host $connect_line $local_dir"; - - // Execute the command to mount the FTP disk - Processes::mwExec($command, $out); - $response = trim(implode('', $out)); - if ('Terminated' === $response) { - // The remote server did not respond or an incorrect password was provided. - unset($response); - } - - return self::isStorageDiskMounted("$local_dir "); - } - - /** - * Mount a WebDAV disk. - * - * @param string $host The WebDAV server host. - * @param string $user The WebDAV server username. - * @param string $pass The WebDAV server password. - * @param string $dstDir The destination directory on the WebDAV server. - * @param string $local_dir The local directory to mount the WebDAV disk. - * @return bool Returns true if the WebDAV disk is successfully mounted, false otherwise. - */ - public static function mountWebDav(string $host, string $user, string $pass, string $dstDir, string $local_dir): bool - { - $host = trim($host); - $dstDir = trim($dstDir); - - // Remove trailing slash from host if present - if (substr($host, -1) === '/') { - $host = substr($host, 0, -1); - } - - // Remove leading slash from destination directory if present - if ($dstDir[0] === '/') { - $dstDir = substr($dstDir, 1); - } - - // Create the local directory if it doesn't exist - Util::mwMkdir($local_dir); - $out = []; - $conf = 'dav_user www' . PHP_EOL . - 'dav_group www' . PHP_EOL; - - - // Write WebDAV credentials to secrets file - file_put_contents('/etc/davfs2/secrets', "$host$dstDir $user $pass"); - file_put_contents('/etc/davfs2/davfs2.conf', $conf); - $timeoutPath = Util::which('timeout'); - $mount = Util::which('mount.davfs'); - - // Build the command to mount the WebDAV disk - $command = "$timeoutPath 3 yes | $mount $host$dstDir $local_dir"; - - // Execute the command to mount the WebDAV disk - Processes::mwExec($command, $out); - $response = trim(implode('', $out)); - if ('Terminated' === $response) { - // The remote server did not respond or an incorrect password was provided. - unset($response); - } - return self::isStorageDiskMounted("$local_dir "); - } - /** * Create a file system on a disk. * From a9b4361c3b91120676d5e5941f681ca9b766bf6a Mon Sep 17 00:00:00 2001 From: boffart <> Date: Fri, 12 Jul 2024 13:27:14 +0300 Subject: [PATCH 37/58] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BF=D1=80=D0=BE=D0=B1=D0=BB=D0=B5=D0=BC=D1=8B?= =?UTF-8?q?=20=D0=BF=D0=BE=D0=BB=D1=83=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=B8=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D0=B8=20?= =?UTF-8?q?=D0=BE=20=D1=82=D0=BE=D1=87=D0=BA=D0=B5=20=D0=BC=D0=BE=D0=BD?= =?UTF-8?q?=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20=D0=B4?= =?UTF-8?q?=D0=B8=D1=81=D0=BA=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/System/Storage.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Core/System/Storage.php b/src/Core/System/Storage.php index 206073c1b..8ec32621b 100644 --- a/src/Core/System/Storage.php +++ b/src/Core/System/Storage.php @@ -123,11 +123,12 @@ public static function isStorageDiskMounted(string $filter = '', string &$mount_ $grep = Util::which('grep'); $mount = Util::which('mount'); $awk = Util::which('awk'); + $head = Util::which('head'); $filter = escapeshellarg($filter); // Execute the command to filter the mount points based on the filter - $out = shell_exec("$mount | $grep $filter | $awk '{print $3}'"); + $out = shell_exec("$mount | $grep $filter | $awk '{print $3}' | $head -n 1"); $mount_dir = trim($out); return ($mount_dir !== ''); } @@ -1489,9 +1490,10 @@ public static function diskIsMounted(string $disk, string $filter = '/dev/') $out = []; $grepPath = Util::which('grep'); $mountPath = Util::which('mount'); + $headPath = Util::which('head'); // Execute mount command and grep the output for the disk name - Processes::mwExec("$mountPath | $grepPath '$filter$disk'", $out); + Processes::mwExec("$mountPath | $grepPath '$filter${disk}' | $headPath -n 1", $out); if (count($out) > 0) { $res_out = end($out); } else { @@ -1541,9 +1543,10 @@ public static function getFreeSpace(string $hdd) $grep = Util::which('grep'); $awk = Util::which('awk'); $df = Util::which('df'); + $head = Util::which('head'); // Execute df command to get the free space for the HDD - Processes::mwExec("$df -m | $grep $hdd | $awk '{print $4}'", $out); + Processes::mwExec("$df -m | $grep $hdd | $grep -v custom_modules | $head -n 1 | $awk '{print $4}'", $out); $result = 0; // Sum up the free space values From bda9c04dfde89d475173ab2bd2111bbf7046d434 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Wed, 17 Jul 2024 08:37:47 +0300 Subject: [PATCH 38/58] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B0=20?= =?UTF-8?q?=D0=BE=D1=84=D0=BE=D1=80=D0=BC=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=BA=D0=BE=D0=B4=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Lib/System/ConvertAudioFileAction.php | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/PBXCoreREST/Lib/System/ConvertAudioFileAction.php b/src/PBXCoreREST/Lib/System/ConvertAudioFileAction.php index 826325408..0aa008b79 100644 --- a/src/PBXCoreREST/Lib/System/ConvertAudioFileAction.php +++ b/src/PBXCoreREST/Lib/System/ConvertAudioFileAction.php @@ -22,11 +22,12 @@ use MikoPBX\Core\System\Processes; use MikoPBX\Core\System\Util; use MikoPBX\PBXCoreREST\Lib\PBXApiResult; +use Phalcon\Di\Injectable; /** * * @package MikoPBX\PBXCoreREST\Lib\System */ -class ConvertAudioFileAction extends \Phalcon\Di\Injectable +class ConvertAudioFileAction extends Injectable { /** * Convert the audio file to various codecs using Asterisk. @@ -38,18 +39,17 @@ public static function main(string $filename): PBXApiResult { $res = new PBXApiResult(); $res->processor = __METHOD__; - if ( ! file_exists($filename)) { + if (!file_exists($filename)) { $res->success = false; - $res->messages[] = "File '{$filename}' not found."; - - return $res; + $res->messages[] = "File '$filename' not found."; } $out = []; $tmp_filename = '/tmp/' . time() . "_" . basename($filename); - if (false === copy($filename, $tmp_filename)) { + if ($res->success && false === copy($filename, $tmp_filename)) { $res->success = false; - $res->messages[] = "Unable to create temporary file '{$tmp_filename}'."; - + $res->messages[] = "Unable to create temporary file '$tmp_filename'."; + } + if(!$res->success){ return $res; } @@ -62,12 +62,14 @@ public static function main(string $filename): PBXApiResult $tmp_filename = escapeshellcmd($tmp_filename); $n_filename = escapeshellcmd($n_filename); $soxPath = Util::which('sox'); - Processes::mwExec("{$soxPath} -v 0.99 -G '{$tmp_filename}' -c 1 -r 8000 -b 16 '{$n_filename}'", $out); + + // Предварительная конвертация в wav. + Processes::mwExec("$soxPath -v 0.99 -G '$n_filename' -c 1 -r 8000 -b 16 '$n_filename'", $out); $result_str = implode('', $out); // Convert wav file to mp3 format $lamePath = Util::which('lame'); - Processes::mwExec("{$lamePath} -b 32 --silent '{$n_filename}' '{$n_filename_mp3}'", $out); + Processes::mwExec("$lamePath -b 32 --silent '$n_filename' '$n_filename_mp3'", $out); $result_mp3 = implode('', $out); // Convert the file to various codecs using Asterisk @@ -77,7 +79,7 @@ public static function main(string $filename): PBXApiResult foreach ($codecs as $codec){ $result = shell_exec("$asteriskPath -rx 'file convert $tmp_filename $trimmedFileName.$codec'"); if(strpos($result, 'Converted') !== 0){ - shell_exec("$rmPath -rf /root/test.{$codec}"); + shell_exec("$rmPath -rf /root/test.$codec"); } } @@ -91,9 +93,8 @@ public static function main(string $filename): PBXApiResult return $res; } - if (file_exists($filename) - && $filename !== $n_filename - && $filename !== $n_filename_mp3) { + if ($filename !== $n_filename + && $filename !== $n_filename_mp3 && file_exists($filename)) { // Remove the original file if it's different from the converted files unlink($filename); } From c5655c859942da46d23406732c0869a29dfd3238 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Mon, 22 Jul 2024 09:20:56 +0300 Subject: [PATCH 39/58] =?UTF-8?q?#770=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=B3=D1=80=D1=83=D0=BF=D0=BF=D1=83=20kvm.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/System/RootFS/etc/group | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Core/System/RootFS/etc/group b/src/Core/System/RootFS/etc/group index cc2963de0..2010fe792 100644 --- a/src/Core/System/RootFS/etc/group +++ b/src/Core/System/RootFS/etc/group @@ -11,3 +11,4 @@ dialout:x:1008: kmem:x:1009: uucp:x:1010: www:x:1011: +kvm:x:61: From 728f79c10eb097f5ffa49d3c57df2144149b7219 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Tue, 23 Jul 2024 14:38:19 +0300 Subject: [PATCH 40/58] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B0=20?= =?UTF-8?q?=D0=BE=D1=84=D0=BE=D1=80=D0=BC=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=BA=D0=BE=D0=B4=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Workers/Libs/WorkerCallEvents/ActionDialAnswer.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Core/Workers/Libs/WorkerCallEvents/ActionDialAnswer.php b/src/Core/Workers/Libs/WorkerCallEvents/ActionDialAnswer.php index 218743ce6..cd345d65e 100644 --- a/src/Core/Workers/Libs/WorkerCallEvents/ActionDialAnswer.php +++ b/src/Core/Workers/Libs/WorkerCallEvents/ActionDialAnswer.php @@ -118,16 +118,15 @@ private static function fillPickUpCdr($worker, $data): void $new_data = $m_row_data->toArray(); // Update certain fields in the new data. - $new_data['start'] = $data['answer']; - $new_data['answer'] = $data['answer']; - $new_data['endtime'] = ''; + $new_data['start'] = $data['answer']; + $new_data['answer'] = $data['answer']; + $new_data['endtime'] = ''; $new_data['dst_chan'] = $data['agi_channel']; - $new_data['dst_num'] = $data['dst_num']; + $new_data['dst_num'] = $data['dst_num']; $new_data['UNIQUEID'] = $data['id']; // Check if call recording is enabled for this source and destination numbers. if ($worker->enableMonitor($new_data['src_num'] ?? '', $new_data['dst_num'] ?? '')) { - // If it is, start recording the call. $new_data['recordingfile'] = $worker->MixMonitor($new_data['dst_chan'], 'pickup_' . $new_data['UNIQUEID'], '', '', 'fillPickUpCdr'); } From da3e0394997389f95cd5c440b663e6232b2e007e Mon Sep 17 00:00:00 2001 From: boffart <> Date: Wed, 24 Jul 2024 13:02:06 +0300 Subject: [PATCH 41/58] =?UTF-8?q?#727=20=D0=9F=D0=B5=D1=80=D0=B5=D0=BF?= =?UTF-8?q?=D0=B8=D1=81=D0=B0=D0=BB=20=D0=BF=D1=80=D0=BE=D1=86=D0=B5=D1=81?= =?UTF-8?q?=D1=81=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20/=20=D1=83=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?=20=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D0=B5?= =?UTF-8?q?=D0=BB=D1=8F=20=D0=B4=D0=BB=D1=8F=20ssh.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/System/Configs/SSHConf.php | 72 ++++++++++++++--------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/src/Core/System/Configs/SSHConf.php b/src/Core/System/Configs/SSHConf.php index 9ab671a28..49bf68e1f 100644 --- a/src/Core/System/Configs/SSHConf.php +++ b/src/Core/System/Configs/SSHConf.php @@ -60,8 +60,8 @@ public function configure(): bool file_put_contents($lofFile, ''); } $this->generateDropbearKeys(); - $sshLogin = $this->getSSHLogin(); - $sshPort = escapeshellcmd(PbxSettings::getValueByKey(PbxSettingsConstants::SSH_PORT)); + $sshLogin = $this->getCreateSshUser(); + $sshPort = escapeshellcmd(PbxSettings::getValueByKey(PbxSettingsConstants::SSH_PORT)); // Update root password and restart SSH server $this->updateShellPassword($sshLogin); @@ -118,38 +118,34 @@ private function generateDropbearKeys(): void * * @return string SSH login username. */ - private function getSSHLogin(): string + private function getCreateSshUser(): string { $sshLogin = PbxSettings::getValueByKey(PbxSettingsConstants::SSH_LOGIN); $homeDir = $this->getUserHomeDir($sshLogin); - $passwdPath = '/etc/passwd'; - $newEntry = "$sshLogin:x:0:0:MikoPBX Admin:$homeDir:/bin/bash\n"; - - if ($sshLogin !== 'root') { - // Read the current contents of the passwd file - $passwdContent = file_get_contents($passwdPath); - $lines = explode("\n", $passwdContent); - $updated = false; - - // Check each line and update the entry if it exists - foreach ($lines as &$line) { - if (strpos($line, "$sshLogin:") === 0) { - $line = $newEntry; - $updated = true; - break; - } - } - unset($line); // break the reference with the last element - - // If the entry was updated, rewrite the file - if ($updated) { - file_put_contents($passwdPath, implode("\n", $lines)); - } else { - // Append the new entry if it wasn't found - file_put_contents($passwdPath, $newEntry, FILE_APPEND); + // System users, you can't touch them + $mainUsers = ['root', 'www']; + $bbPath = Util::which('busybox'); + // We clean all non-system users + exec("$bbPath cut -f 1 -d ':' < /etc/passwd", $systemUsers); + foreach ($systemUsers as $user){ + if($sshLogin === $user || in_array($user, $mainUsers, true)){ + continue; } + // Deleting the user + shell_exec("$bbPath deluser $user"); + // Deleting the group + shell_exec("$bbPath delgroup $user"); + } + if ($sshLogin !== 'root') { + // Adding a group '$sshLogin' + shell_exec("$bbPath addgroup $sshLogin"); + // Adding user '$sshLogin' + shell_exec("$bbPath adduser -h $homeDir -g 'MikoPBX SSH Admin' -s /bin/bash -G root -D '$sshLogin'"); + // Adding a user to the group '$sshLogin' + shell_exec("$bbPath addgroup -S '$sshLogin' $sshLogin"); + // Adding a user to the group 'root' + shell_exec("$bbPath addgroup -S '$sshLogin' root"); } - return $sshLogin; } @@ -174,17 +170,21 @@ private function getUserHomeDir(string $sshLogin = 'root'): string */ private function updateShellPassword(string $sshLogin = 'root'): void { - $password = PbxSettings::getValueByKey(PbxSettingsConstants::SSH_PASSWORD); - $hashString = PbxSettings::getValueByKey(PbxSettingsConstants::SSH_PASSWORD_HASH_STRING); - $disablePassLogin = PbxSettings::getValueByKey(PbxSettingsConstants::SSH_DISABLE_SSH_PASSWORD); + $password = PbxSettings::getValueByKey(PbxSettingsConstants::SSH_PASSWORD); + $hashString = PbxSettings::getValueByKey(PbxSettingsConstants::SSH_PASSWORD_HASH_STRING); + $disablePassLogin = PbxSettings::getValueByKey(PbxSettingsConstants::SSH_DISABLE_SSH_PASSWORD); - $echo = Util::which('echo'); + $echo = Util::which('echo'); $chpasswd = Util::which('chpasswd'); - $passwd = Util::which('passwd'); - Processes::mwExec("{$passwd} -l www"); + $passwd = Util::which('passwd'); + Processes::mwExec("$passwd -l www"); if ($disablePassLogin === '1') { Processes::mwExec("$passwd -l $sshLogin"); + Processes::mwExec("$passwd -l root"); + } elseif($sshLogin === 'root') { + Processes::mwExec("$echo '$sshLogin:$password' | $chpasswd"); } else { + Processes::mwExec("$passwd -l root"); Processes::mwExec("$echo '$sshLogin:$password' | $chpasswd"); } @@ -209,7 +209,7 @@ private function generateAuthorizedKeys(string $sshLogin = 'root'): void Util::mwMkdir($sshDir); $authorizedKeys = PbxSettings::getValueByKey(PbxSettingsConstants::SSH_AUTHORIZED_KEYS); - file_put_contents("{$sshDir}/authorized_keys", $authorizedKeys); + file_put_contents("$sshDir/authorized_keys", $authorizedKeys); } /** From bf3b00ac7da00b26b9a768609d8aa75c2fef2606 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Thu, 25 Jul 2024 10:11:23 +0300 Subject: [PATCH 42/58] =?UTF-8?q?#727=20=D0=9F=D0=B5=D1=80=D0=B5=D0=BF?= =?UTF-8?q?=D0=B8=D1=81=D0=B0=D0=BB=20=D0=BF=D1=80=D0=BE=D1=86=D0=B5=D1=81?= =?UTF-8?q?=D1=81=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20/=20=D1=83=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?=20=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D0=B5?= =?UTF-8?q?=D0=BB=D1=8F=20=D0=B4=D0=BB=D1=8F=20ssh.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/System/Configs/SSHConf.php | 8 ++++++++ src/Core/System/Notifications.php | 8 ++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Core/System/Configs/SSHConf.php b/src/Core/System/Configs/SSHConf.php index 49bf68e1f..ee22044ef 100644 --- a/src/Core/System/Configs/SSHConf.php +++ b/src/Core/System/Configs/SSHConf.php @@ -145,6 +145,14 @@ private function getCreateSshUser(): string shell_exec("$bbPath addgroup -S '$sshLogin' $sshLogin"); // Adding a user to the group 'root' shell_exec("$bbPath addgroup -S '$sshLogin' root"); + + $cat = Util::which('cat'); + $cut = Util::which('cut'); + $sed = Util::which('sed'); + $chown = Util::which('chown'); + $currentGroupId = trim(shell_exec("$cat /etc/passwd | grep '^$sshLogin:' | $cut -f 3 -d ':'")); + shell_exec("$sed -i 's/$sshLogin:x:$currentGroupId:/$sshLogin:x:0:/g' /etc/passwd"); + shell_exec("$chown -R $sshLogin:$sshLogin $homeDir"); } return $sshLogin; } diff --git a/src/Core/System/Notifications.php b/src/Core/System/Notifications.php index 4f819fd95..6a13112cc 100644 --- a/src/Core/System/Notifications.php +++ b/src/Core/System/Notifications.php @@ -86,6 +86,9 @@ public static function sendAdminNotification(string $subject, array $messages, b { // Prevent sending the same message twice. $di = Di::getDefault(); + if(!$di){ + return; + } $managedCache = $di->getShared(ManagedCacheProvider::SERVICE_NAME); $cacheKey = 'sendAdminNotification:' . md5($subject . implode('', $messages)); $cacheTime = 3600 * 24; // 1 day @@ -96,7 +99,7 @@ public static function sendAdminNotification(string $subject, array $messages, b } // Check if the notification system is available (e.g., PHP Mailer is configured and working). - if (!Notifications::checkConnection(Notifications::TYPE_PHP_MAILER)) { + if (!self::checkConnection(self::TYPE_PHP_MAILER)) { return; } @@ -106,7 +109,8 @@ public static function sendAdminNotification(string $subject, array $messages, b foreach ($messages as $message) { $text .= '
      ' . Util::translate($message, false); } - $text = $text . '

      ' . SystemMessages::getInfoMessage("The MikoPBX connection information"); + $text .= '

      ' . SystemMessages::getInfoMessage("The MikoPBX connection information"); + $text = str_replace(PHP_EOL, '
      ', $text); // Get the admin email address from PbxSettings. $adminMail = PbxSettings::getValueByKey(PbxSettingsConstants::SYSTEM_NOTIFICATIONS_EMAIL); From da532b833bef05296a4f269abb73d5d15a276085 Mon Sep 17 00:00:00 2001 From: Weblate Date: Tue, 30 Jul 2024 12:42:09 +0300 Subject: [PATCH 43/58] Translated using Weblate (Hungarian) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 100.0% (1243 of 1243 strings) Added translation using Weblate (Hungarian) Co-authored-by: Anonymous Co-authored-by: Juhász Béla Co-authored-by: Weblate Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/hu/ Translation: MIKOPBX/Core --- src/Common/Messages/hu.php | 1236 ++++++++++++++++++++++++++++++++++++ 1 file changed, 1236 insertions(+) create mode 100644 src/Common/Messages/hu.php diff --git a/src/Common/Messages/hu.php b/src/Common/Messages/hu.php new file mode 100644 index 000000000..9e5bb886d --- /dev/null +++ b/src/Common/Messages/hu.php @@ -0,0 +1,1236 @@ + 'NAT mód', + 'ext_Available' => '-re frissíthető', + 'ext_InstallModule' => 'Modul telepítése', + 'ext_FreeModule' => 'Ingyenes modul', + 'gs_PBXName' => 'PBX rendszernév', + 'mo_ApplicationShort4Dropdown' => 'Alkalmazás', + 'mo_IVRMenuShort4Dropdown' => 'IVR menü', + 'mo_ModuleShort4Dropdown' => 'Modul', + 'lic_ReloadPage' => 'Frissítsd az oldalt…', + 'auth_ValidateLoginNotEmpty' => 'Adja meg a bejelentkezést', + 'auth_SubmitButton' => 'Belépés', + 'auth_WrongLoginPassword' => 'Az engedélyezés nem sikerült, még %attempts% próbálkozása van hátra', + 'BreadcrumbFirewallmodify' => 'Szabály felállítása', + 'SubHeaderFirewall' => 'Az állomáshoz való hozzáférés korlátozása forgalomtípus és alhálózatok szerint', + 'BreadcrumbGeneralSettings' => 'Rendszerbeállítások', + 'bt_ToolTipUpgradeOnline' => 'Frissítés online', + 'ms_SuccessfulSaved' => 'A beállítások elmentve', + 'ms_SuccessfulDeleted' => 'Adatok törölve', + 'Codecs' => 'Kodekek', + 'sip_registration_type' => 'Fiók Típus', + 'sip_REG_TYPE_OUTBOUND' => 'Kimenő regisztráció', + 'sip_REG_TYPE_INBOUND' => 'Bejövő regisztráció', + 'gs_CallRecordTab' => 'Beszélgetések rögzítése', + 'ex_ManualAdditionalAttributes' => 'Extra lehetőségek', + 'ex_SecondsAndThenRedirectCallTo' => 'Másodpercig próbáljuk hívni a fő számot, majd áttérünk a számra', + 'ext_ShowModuleItemAtMainMenu' => 'Modul megjelenítése az oldalmenüben', + 'ext_Marketplace' => 'Piactér', + 'ext_ModuleLicenseProblem' => 'Probléma a bővítőmodul licencével', + 'ex_PortugueseBrazil' => 'Portugália (Brazília)', + 'ex_Vietnamese' => 'Tiếng việt', + 'ex_Chinese' => '中国人', + 'May' => 'Lehet', + 'June' => 'június', + 'July' => 'július', + 'August' => 'augusztus', + 'September' => 'szeptember', + 'ShortDayTuesday' => 'W', + 'Now' => 'Most', + 'ex_dropdownCategory_CALLQUEUES' => 'Hívási sorok', + 'tf_WeekDaysFrom' => 'A hét napjai', + 'tf_TimePeriodFrom' => 'Időtartam', + 'tf_PeriodAction' => 'Bejövő hívás művelet', + 'tf_AllowRestriction' => 'Csak meghatározott bejövő útvonalakra vonatkozik', + 'tf_Description' => 'Egy komment', + 'tf_SelectActionPlayMessage' => 'Hangfájl lejátszása', + 'tf_SelectActionRedirectToExtension' => 'Hívás átadása', + 'tf_SelectAudioMessage' => 'Válassza ki a hangfájlt', + 'tf_SelectExtension' => 'Válassza ki a mellékállomás számát', + 'gs_PBXDescription' => 'További leírás', + 'gs_NeedRestartPBX' => 'A módosítás után a csillag szolgáltatás újraindul', + 'gs_PBXLanguage' => 'A rendszer hangjának nyelve', + 'gs_PBXInternalExtensionLength' => 'A belső számok maximális hossza', + 'f2b_BanedTime' => 'dátum', + 'f2b_TableBannedHeader' => 'Letiltott címek', + 'f2b_Unban' => 'Blokkolás feloldása', + 'BreadcrumbHome' => 'Az elejére', + 'BreadcrumbProvidersmodifysip' => 'SIP-szolgáltató beállítása', + 'mm_CustomFiles' => 'A rendszerfájlok testreszabása', + 'bt_Delete' => 'Töröl', + 'bt_SaveSettings' => 'Megment', + 'bt_SaveSettingsAndAddNew' => 'Mentse el és adja hozzá', + 'bt_SaveSettingsAndExit' => 'Mentés és bezárás', + 'bt_ApplyChangesToPBX' => 'Módosítások elfogadása', + 'bt_BackToList' => 'Vissza a listához', + 'pr_RedefinitionFromUser' => 'A "From" SIP-fejléc újradefiniálása', + 'pr_FromUser_v2' => 'Felhasználó', + 'pr_ValidationProviderNameIsEmpty' => 'Írja be a szolgáltató nevét', + 'pr_DisableFromUser' => 'Tiltsa le a fromuser mező használatát', + 'pr_TableColumnProviderLogin' => 'Belépés', + 'pr_TableColumnProviderHostName' => 'Házigazda', + 'gs_UseWebRTC' => 'Használja a WebRTC-t', + 'gs_Store1MonthOfRecords' => '1 hónap', + 'gs_Store3MonthsOfRecords' => '3 hónap', + 'pr_DeleteDescription_v2' => 'A szolgáltatóval együtt az összes kapcsolódó kimenő útválasztási szabály törlődik, és a bejövő forgalomirányítási szabályokban az összes hivatkozás helyére a „Nincs kapcsolat a szolgáltatóhoz, nincs jogosultság” szövegre.', + 'gs_PBXRecordCalls' => 'Beszélgetések rögzítése', + 'gs_PBXRecordCallsInner' => 'Belső beszélgetések rögzítése', + 'gs_RestartEveryNight' => 'Indítsa újra az alközpontot minden este', + 'gs_PBXCallParkingExt' => 'Hívja a Park számát', + 'gs_PBXCallParkingSlotRange' => 'Parkolóhelyek választéka', + 'gs_PBXFeatureAttendedTransfer' => 'Tanácsadó fordítási kombináció', + 'gs_PBXFeatureBlindTransfer' => 'Kombináció a feltétel nélküli átvitelhez', + 'mo_SystemExten_busy' => 'Foglalt hang lejátszása', + 'cal_ThisMonth' => 'Jelenlegi hónap', + 'cal_LastMonth' => 'Múlt hónap', + 'cal_ApplyBtn' => 'Alkalmaz', + 'cal_CancelBtn' => 'Megszünteti', + 'cal_from' => 'Val vel', + 'f2b_Jail_asterisk_ami_v2' => 'AMI vagy AJAM engedélyezési hibák', + 'f2b_Jail_asterisk_v2' => 'SIP hitelesítési hibák', + 'f2b_Jail_asterisk_security_log_v2' => 'SIP engedélyezési hibák (security_log)', + 'f2b_Jail_asterisk_error_v2' => 'SIP engedélyezési hibák (hiba)', + 'cal_to' => 'Által', + 'ir_hangup' => 'Tedd le a telefont', + 'ir_Extension' => 'szám', + 'cal_CustomPeriod' => 'Tetszőleges', + 'sntry_Title' => 'Valami elromlott!', + 'sntry_Subtitle' => 'A hibát jelezték a fejlesztőnek.', + 'sntry_Subtitle2' => 'Kérjük, írja le azokat a lépéseket, amelyek ehhez a hibához vezettek.', + 'sntry_LabelComments' => 'Mit csináltál?', + 'cq_StaticAgents' => 'Résztvevők', + 'gs_WEBHTTPSPublicKey' => 'HTTPs nyilvános kulcs', + 'gs_ValidateEmptyPBXName' => 'Az állomás neve nincs megadva', + 'gs_TwoDigthts' => '2 számjegy', + 'gs_ThreeDigthts' => '3 számjegy', + 'gs_FourDigthts' => '4 számjegy', + 'cq_AddQueueMembers' => 'Nincsenek kiválasztva operátorok', + 'gs_FiveDigthts' => '5 számjegy', + 'gs_SixDigthts' => '6 szám', + 'gs_SevenDigthts' => '7 számjegy', + 'gs_ElevenDigthts' => '11 számjegy', + 'gs_WebAdminLogin' => 'Belépés', + 'gs_WebAdminPassword' => 'Jelszó', + 'gs_WebAdminPasswordRepeat' => 'Írja be újra a jelszavát', + 'sntry_LabelClose' => 'Bezárás', + 'sntry_LabelSubmit' => 'Küld', + 'gs_SSHPasswordRepeat' => 'Írja be újra a jelszavát', + 'gs_Passwords' => 'WEB interfész jelszó', + 'gs_DefaultPasswordWarning' => 'Ne használja a szokásos rendszergazdai bejelentkezést és jelszót', + 'gs_ValidateEmptyWebPassword' => 'Az adminisztrátori jelszó nem lehet üres', + 'gs_ValidateWeakWebPassword' => 'A WEB jelszónak 4 karakternél hosszabbnak kell lennie', + 'gs_ValidateWebPasswordsFieldDifferent' => 'A webes felület jelszava helytelenül lett megadva', + 'ms_SMTPPassword' => 'SMTP jelszó', + 'ms_SMTPSenderAddress' => 'A feladó címe', + 'ms_SMTPFromUsername' => 'Küldő neve', + 'ms_SMTPUseTLS' => 'Használja a TLS-t', + 'ms_SMTPCertCheck' => 'Ellenőrizze a kiszolgáló tanúsítványát', + 'ms_MailEnableNotifications' => 'Figyelmeztetések használata', + 'ex_ThisUserIdNotExistInUsersModel' => 'Ez a felhasználó nem létezik', + 'ex_ThisNumberNotExistInSipModel' => 'Ez a szám nem rendelkezik a megfelelő SIP-beállításokkal', + 'ex_NoNetworkFilter' => 'Bármilyen címről engedélyezett a csatlakozás', + 'ex_PermitNetwork' => 'Engedélyezett hálózat', + 'ex_Username' => 'A felhasználó teljes neve', + 'ex_EmailAddress' => 'Email cím', + 'ex_ThisEmailAlreadyRegisteredForOtherUser' => 'A megadott cím már regisztrálva van', + 'ex_Language' => 'Interfész és értesítési nyelv', + 'ex_Number' => 'Mellék számát', + 'ex_RingMainExtension' => 'Alatt', + 'ex_IfMainExtensionIsBusyRedirectCallTo' => 'Ha a fő szám foglalt, átirányítjuk a hívást a számra', + 'ex_IfMainExtensionIsUnavailableRedirectCallTo' => 'Ha a fő szám nem elérhető, átirányítjuk a hívást a számra', + 'ex_ValidateMobileIsNotCorrect' => 'Ellenőrizze, hogy helyesen adta-e meg mobilszámát', + 'ex_Name' => 'Munkavállaló', + 'f2b_Jail_asterisk_public_v2' => 'SIP engedélyezési hibák (nyilvános)', + 'ex_Offline' => 'Tiltva', + 'tf_TableColumnAction' => 'Akció', + 'tf_ValidateCheckWeekDayInterval' => 'Ellenőrizze a hét napjait', + 'fw_ValidateRuleName' => 'Adjon nevet az alhálózatnak', + 'nw_DNSAddresses' => 'DNS szerver címek', + 'nw_PublicAddress' => 'Az útválasztó külső IP-címe', + 'nw_InternetInterface' => 'Hálózati interfész Internet hozzáféréssel', + 'nw_NetworkInterfaces' => 'Hálózati interfészek', + 'nw_InterfaceName' => 'Név', + 'nw_SelectInterface' => 'Válassza ki a hálózati interfészt', + 'nw_AllowNatPortForwarding' => 'Ez az állomás egy NAT router mögött található', + 'nw_NATInfo4' => '%RTP_PORT_FROM%-%RTP_PORT_TO% UDP', + 'repFail2BanRules' => 'Fail2Ban szabály – %represent%', + 'repFirewallRules' => 'Tűzfalszabály – %represent%', + 'repIax' => 'IAX-fiók – %represent%', + 'repIncomingRoutingTable' => '%represent%', + 'repIncomingRoutingTableNumber' => 'Bejövő feldolgozási szabály – N%represent%', + 'repLanInterfaces' => 'Rendszerfájl – %represent%', + 'repNetworkFilters' => 'Vonalszűrő – %represent%', + 'repOutgoingRoutingTable' => '%represent%', + 'repOutgoingRoutingTableNumber' => 'Kimenő feldolgozási szabály – N%represent%', + 'repOutWorkTimes' => 'Nyitvatartás után – %represent%', + 'repPbxSettings' => 'Állomásbeállítások - %represent%', + 'repSip' => 'SIP-fiók – %represent%', + 'repSoundFiles' => 'Hangfájl - %represent%', + 'repIvrMenu' => 'IVR menü – %represent%', + 'f2b_Jail_dropbear' => 'SSH munkamenet engedélyezési hibák', + 'f2b_Jail_mikopbx-www' => 'Engedélyezési hibák az alközpont adminisztrációs felületén', + 'f2b_WhiteList' => 'A soha nem blokkolt címek listája', + 'f2b_MaxRetry' => 'A blokkolás előtti próbálkozások száma', + 'f2b_FindTime' => 'Másodperceken belül)', + 'f2b_BanTime' => 'Letiltás (másodperc)', + 'gs_SSHecdsaKey' => 'SSH ECDSA kulcs', + 'gs_SSHRsaKey' => 'SSH RSA kulcs', + 'gs_SSHDssKey' => 'SSH DSS kulcs', + 'gs_RedirectToHttps' => 'Átirányítás HTTPS-re', + 'gs_CodecsOrder' => 'Codec prioritás', + 'gs_DangerZone' => 'Rendszerbeállítások eltávolítása', + 'gs_RestoreAllSettingsHeader' => 'Figyelem!', + 'gs_EnterDeleteAllPhrase' => 'törölj mindent', + 'gs_AllSettingsDeleted' => 'Minden beállítás törlődik', + 'gs_PBXRecordAnnouncementIn' => 'Válassza ki a hívásrögzítési figyelmeztetést a bejövő hívásokhoz', + 'da_Type' => 'Kód típusa', + 'da_ColumnExtension' => 'Szám', + 'sf_StartRecordSoundFileButton' => 'Felvétel megkezdése', + 'sf_StopRecordSoundFileButton' => 'Állj meg', + 'sf_ColumnFile' => 'Név', + 'sf_ColumnPlayer' => 'Játékos', + 'sf_AddNewSoundFile' => 'Új hangfájl hozzáadása', + 'sf_UploadError' => 'Hiba az audiofájl betöltésekor', + 'lic_ValidateCompanyNameEmpty' => 'A kötelező mező nincs kitöltve - cégnév', + 'lic_ValidateLicenseKeyEmpty' => 'A kötelező mező nincs kitöltve - Licenckulcs', + 'mo_SystemExten_hangup' => 'Hívás befejezése', + 'pass_CheckSSHPasswordEmpty' => 'A mező üres: SSH', + 'pass_CheckSSHPasswordSimple' => 'Az SSH jelszó túl egyszerű.', + 'adv_ThisCopyIsNotRegistered' => 'A program ezen példánya nem licencelt – Ingyenes aktiválás', + 'cal_Today' => 'Ma', + 'disable' => 'letiltása', + 'Error resetting password.' => "Jelszó visszaállítási hiba", + 'sd_ToolTipErase' => 'Fájl törlése', + 'ext_DeleteModuleError' => 'Hiba a modul eltávolításakor', + 'lic_LastQuestionAnswer' => 'A licencekkel kapcsolatos gyakran ismételt kérdések az címen, az címen találhatók.', + 'lic_NoInetHeader' => 'Nincs hozzáférés a licencszerverhez.', + 'lic_NoInet' => 'Talán nincs internet-hozzáférés a MikoPBX szerverről', + 'lic_NoInetLicMiko' => 'Valószínűleg korlátozott hozzáférés az erőforráshoz lic.mikopbx.com', + 'lic_NoInetNetSettings' => "Ellenőrizze a DNS és az Gateway beállításait a hálózati beállításokban", + 'lic_LicenseProblem' => 'Probléma a Marketplace regisztrációjával', + 'lic_ManageLicense' => 'A licenc kezeléséhez, a kötések visszaállításához és a problémák elemzéséhez látogasson el a webhelyre ', + 'lic_ManageLicenseKeyOnSitePreLinkText' => 'A licenc kezeléséhez állítsa vissza a gazdagép-összerendeléseket, tekintse meg a statisztikákat', + 'lic_ManageLicenseKeyOnSiteLinkText' => 'link', + 'lic_ManageLicenseKey' => 'Licenckezelés', + 'lic_GeneralError' => 'Hiba történt a licenc aktiválásakor', + 'lic_HostLookupFailed' => 'Nincs kapcsolat a licencszerverrel, DNS probléma', + 'er_Home' => 'Ugrás a tetejére', + 'rs_RestartPhoneSystem' => 'Indítsa újra a MikoPBX-et', + 'rs_ShutDownPhoneSystem' => 'Kapcsolja ki a MikoPBX-et', + 'rs_CurrentCalls' => 'Aktív hívások', + 'rs_DateCall' => 'kezdő dátum', + 'rs_Src' => 'WHO', + 'rs_Dst' => 'Kinek', + 'rs_ShutdownRebootMessage' => 'Újraindításkor vagy leállításkor minden folyamatban lévő hívás megszakad.', + 'auth_Login' => 'Belépés', + 'auth_Password' => 'Jelszó', + 'auth_ValidatePasswordNotEmpty' => 'írd be a jelszót', + 'auth_TooManyLoginAttempts' => 'Túl sok bejelentkezési kísérlet. Az Ön IP-címe %interval% másodpercig blokkolva van.', + 'auth_RememberMe' => 'Emlékezz rám', + 'auth_DefaultCloudPasswordInstructions' => 'Az alapértelmezett jelszó megegyezik a felhőben lévő virtuális gép egyedi azonosítójával', + 'log_CaptureMessage' => 'Kezdje el gyűjteni a hálózati csomagokat, és indítson hívást vagy más műveletet, amely a hibát okozza. +
      A rendszer elmenti a hálózati kártyán jelenleg áthaladó összes csomagot további elemzés céljából.', + 'log_StartCapturePCAP' => 'Rajt', + 'log_StopCapturePCAP' => 'Állj le és töltsd le', + 'log_DownloadLogs' => 'Töltse le az összes rendszernaplót', + 'dbg_NoDebugInformation' => 'Nincs információ', + 'dbg_Header' => 'Hibakeresési információk', + 'f2b_Reason' => 'Ok', + 'f2b_IpAddres' => 'IP-cím', + 'f2b_Fail2BanSwitch' => 'Használja a Fail2Ban aktív blokkoló rendszert', + 'f2b_ValidateMaxRetryRange' => 'A kísérletek számának paramétere nincs megfelelően beállítva', + 'f2b_ValidateFindTimeRange' => 'Az engedélyezési kísérletek elemzési időszaka nincs megfelelően beállítva', + 'f2b_ValidateBanTimeRange' => 'A blokkolási időszak helytelen', + 'f2b_TableBannedEmpty' => 'Nincs adat', + 'f2b_SettingsTabHeader' => 'A védelem beállítása', + 'f2b_BannedIpTabHeader' => 'Letiltott címek', + 'upd_FileName' => 'Válassza ki a frissítési fájlt', + 'upd_UpdateSystem' => 'Frissítés alkalmazása', + 'upd_VersionColumn' => 'Változat', + 'upd_DescriptionColumn' => 'Leírás', + 'upd_AvailableUpdates' => 'Online frissítések elérhetők', + 'upd_DownloadUpgradeError' => 'Hiba történt a frissítés letöltése során, próbálkozzon újra később', + 'upd_UploadError' => 'Hiba a frissítés letöltése közben', + 'upd_UpdateTitle' => 'PBX frissítés', + 'upd_Cancel' => 'Megszünteti', + 'upd_Update' => 'Frissítés', + 'upd_UploadInProgress' => 'A frissítési fájl letöltése folyamatban van…', + 'upd_UpgradeInProgress' => 'A rendszerfájlok frissítése folyamatban van…', + 'upd_UpgradeError' => 'Hiba történt a MikoPBX frissítésekor', + 'upd_UpdateDescription' => 'A frissítés letöltése után a MikoPBX automatikusan újraindul, és minden aktuális hívás megszakad. Frissítés előtt mindenképpen készítsen biztonsági másolatot a MikoPBX-ről.', + 'upd_EnterIHaveBackupPhrasePreText' => 'A rendszer frissítéséhez írja be a következő kifejezést a beviteli mezőbe:', + 'upd_EnterIHaveBackupPhrase' => 'Igen van tartalékom', + 'upd_UpdateDockerHeader' => 'Tároló frissítési szabályok', + 'upd_UpdateDockerText' => 'Állítsa le a tárolót, törölje azt, töltse le a legújabb verziót, és indítsa újra, megőrizve a tárhely-beillesztési beállításokat és a környezeti változókat. A folyamatot részletesebben a dokumentáció írja le.', + 'ext_TableColumnDescription' => 'Modul neve', + 'ext_TableColumnDeveloper' => 'Fejlesztő', + 'ext_TableColumnVersion' => 'Változat', + 'ext_UpdateModule' => 'Modul frissítése', + 'ext_UpdateModuleError' => 'Hiba a modul telepítésekor', + 'ext_AvailableModules' => 'Modulok beépíthetők', + 'ext_ModuleDisabledStatusDisabled' => 'Modul letiltva', + 'ext_ModuleDisabledStatusEnabled' => 'Modul engedélyezve', + 'ext_ModuleStatusChanging' => 'Modulállapotok módosítása…', + 'ext_ModuleChangedObjects' => 'A következő objektumok módosultak', + 'ext_DeleteTitle' => 'Bővítő modul eltávolítása', + 'ext_DeleteDescription' => 'A modul törlése előtt ellenőrzi, hogy vannak-e kereszthivatkozások a többi modul és a rendszerbeállítások között.', + 'ext_KeepModuleSettings' => 'Mentse el az aktuális modulbeállításokat', + 'ext_Cancel' => 'Megszünteti', + 'ext_Delete' => 'Töröl', + 'ext_GetLinkError' => 'Hiba történt a modulelosztó készlet webhelyről történő fogadásakor. Kérlek, próbáld újra később.', + 'ext_NoLicenseAvailable' => 'Nincs engedély a modul telepítésére vagy frissítésére.', + 'ext_Version' => 'Változat', + 'ext_ValidateCaptionEmpty' => 'A menüelem neve üres', + 'ext_SelectMenuGroup' => 'Válasszon egy oldalmenüszakaszt', + 'ext_SettingsForModule' => 'Modul beállítások:', + 'ext_Caption' => 'A menüelem neve', + 'ext_AddNewExtension' => 'Új modul betöltése', + 'ext_CreateNewExtension' => 'Készítse el saját modulját', + 'ext_UploadError' => 'Modul letöltési hiba', + 'ext_UploadInProgress' => 'Modul betöltése…', + 'ext_InstallationInProgress' => 'Modul telepítése…', + 'ext_GetReleaseInProgress' => 'Adatkérés az adattárból…', + 'ext_DownloadInProgress' => 'Modul letöltése…', + 'ext_CheckLicenseInProgress' => 'A jogosítvány ellenőrzése…', + 'ext_ModuleChangeStatusError' => 'Problémák a modulállapot megváltoztatásakor', + 'ext_InstallationError' => 'Hiba a modul telepítésekor', + 'ext_InstalledModules' => 'Telepített modulok', + 'ext_Licensing' => 'Licenckezelés', + 'ext_NoAvailableModules' => 'Nincsenek telepíthető modulok', + 'ext_NoInstalledModules' => 'Nincsenek telepítve modulok', + 'ext_GoToMarketplace' => 'Menj a piactérre', + 'ext_GoToRegistration' => 'Regisztráció a piacon', + 'ext_LicenseProblemHeader' => 'Licenc probléma', + 'ext_ModuleDependsHigherVersion' => 'A modul telepítéséhez %version% vagy a MikoPBX újabb verziója szükséges', + 'ext_UninstallDBError' => 'Hiba a modul adatbázis törlésekor', + 'ext_UnInstallFiles' => 'Hiba a modulfájlok törlésekor', + 'ext_EmptyLicenseKey' => 'A modul licencének aktiválásához szükséges licenckulcs nincs telepítve', + 'ext_ErrorOnAppliesFilesRights' => 'Hiba a modulfájlokhoz való jogok hozzárendelése során', + 'ext_ErrorOnInstallDB' => 'Hiba a moduladatbázis beállítása közben', + 'ext_ErrorOnInstallFiles' => 'Hibák a modulfájlok másolásakor', + 'ext_ErrorOnLicenseActivation' => 'Hibák a licenc aktiválásakor', + 'ext_ErrorOnDecodeModuleJson' => 'Hiba a modul konfigurációs fájljának elemzésekor %filename%', + 'ext_ErrorOnEnableFirewallSettings' => 'Hiba a modul tűzfalbeállításainak engedélyezésekor', + 'ext_ErrorOnDisableFirewallSettings' => 'Hiba a modul tűzfalbeállításainak kizárásakor', + 'ext_ErrorOnModuleBeforeEnable' => 'Hibák annak ellenőrzése során, hogy a modul engedélyezhető-e', + 'ext_ErrorOnModuleBeforeDisable' => 'Hibák az ellenőrzés során, hogy a modul kikapcsolható-e', + 'ext_ModuleExecutionProblem' => 'Súlyos hiba történt:', + 'ext_DisableReasonHeader' => 'A modul automatikusan letiltásra került', + 'ext_UpdateAllModules' => 'Frissítse az összes telepített modult', + 'ext_EmptyRepoAnswer' => 'A modul telepítéséhez nem érhető el kiadás', + 'ext_ErrDownloadTimeout' => 'Nem sikerült letölteni a modul frissítését. Időtúllépés a működéshez.', + 'ext_ErrUploadTimeout' => 'Nem sikerült feltölteni a modulfájlt. Időtúllépés a működéshez.', + 'ext_ErrInstallationTimeout' => 'Nem sikerült telepíteni a modult. Időtúllépés a működéshez.', + 'ext_ModuleLastRelease' => 'Jelenlegi kiadás', + 'ext_ModulePublisher' => 'Fejlesztő', + 'ext_ModuleDescriptionTab' => 'Modul leírása', + 'ext_ModuleChangelogTab' => 'Verziótörténet', + 'ext_UsefulLinks' => 'Hasznos Linkek', + 'ext_ExternalDescription' => 'Részletes leírás, dokumentáció', + 'ext_CommercialModule' => 'Fizetett modul', + 'ext_InstallModuleShort' => 'Telepítés', + 'ext_UpdateModuleShort' => 'Frissítés', + 'ext_InstallModuleReleaseTag' => 'Kiadás', + 'ext_InstallModuleVersion' => 'Verzió telepítése', + 'ext_ShowModuleRepoDetails' => 'Nyissa meg a modul részletes leírását', + 'ext_ModuleEulaTab' => 'Licencszerződés', + 'ext_FromDate' => 'kiadták', + 'ext_InstallModuleTitle' => 'A modul telepítése', + 'ex_English' => 'angol', + 'ex_EnglishUK' => 'angol (UK)', + 'ex_Japanese' => '日本語', + 'ex_Deutsch' => 'Deutsch', + 'ex_Spanish' => 'Espanol', + 'ex_French' => 'Le français', + 'ex_Dutch' => 'Hollandia', + 'ex_Georgian' => 'ქართველი', + 'January' => 'január', + 'February' => 'február', + 'March' => 'március', + 'April' => 'április', + 'October' => 'október', + 'November' => 'november', + 'December' => 'december', + 'Jan' => 'jan', + 'Feb' => 'Február', + 'Mar' => 'márc', + 'Apr' => 'Április', + 'Jun' => 'Június', + 'Jul' => 'Július', + 'Aug' => 'Augusztus', + 'Sep' => 'szept', + 'Oct' => 'Október', + 'Nov' => 'De én', + 'Dec' => 'December', + 'ShortDaySunday' => 'Vos', + 'ShortDayMonday' => 'Hétfő', + 'ShortDayWednesday' => 'Házasodik', + 'ShortDayThursday' => 'cs', + 'ShortDayFriday' => 'Péntek', + 'ShortDaySaturday' => 'Ült', + 'Today' => 'Ma', + 'MetaTegHeadDescription' => 'Üzleti telefon rendszer', + 'Loading' => 'Betöltés', + 'qf_Qualify' => 'NAT munkamenet támogatása', + 'qf_Frequency' => 'Küldési gyakoriság másodpercben:', + 'qf_QualifyInstructions' => 'Ha ez az opció engedélyezve van, a MikoPBX SIP OPTIONS csomagokat küld a megadott gyakorisággal. Erre azért van szükség, hogy támogassa a NAT alagútkezelést az útválasztón.', + 'AdvancedOptions' => 'További beállítások', + 'ConnectionSettings' => 'Csatlakozási beállítások', + 'BreadcrumbAdminCabinet' => 'Adminisztrációs felület', + 'BreadcrumbPBXCoreREST' => 'REST API', + 'BreadcrumbProviders' => 'Telefonszolgáltatók', + 'SubHeaderProviders' => 'Fiókok létrehozása külső bejövő és kimenő kapcsolatok szervezéséhez', + 'BreadcrumbAsteriskManagers' => 'Asterisk Manager Interface (AMI)', + 'SubHeaderAsteriskManagers' => 'Hozzáférési jogok beállítása az állomás AMI interfészéhez', + 'BreadcrumbAsteriskManagersmodify' => 'Fiók beállítása', + 'BreadcrumbProvidersmodifyiax' => 'IAX szolgáltató beállítása', + 'BreadcrumbTimeSettings' => 'rendszeridő', + 'SubHeaderTimeSettings' => 'Az óra és a naptár beállítása', + 'BreadcrumbMailSettings' => 'Levelezési beállítások', + 'SubHeaderMailSettings' => 'Levelezőszerver beállítása értesítések küldésére a felhasználóknak és a rendszergazdáknak', + 'BreadcrumbNetwork' => 'Hálózati beállítások', + 'SubHeaderNetwork' => 'Hálózati kártyák konfigurálása (DHCP, DNS, GATEWAY, VLAN)', + 'BreadcrumbModify' => 'Szabály felállítása', + 'BreadcrumbOutboundRoutes' => 'Kimenő útválasztás', + 'SubHeaderOutboundRoutes' => 'A szolgáltatókon keresztüli híváselosztás szabályai és sablonjai', + 'BreadcrumbOutboundRoutesmodify' => 'Szabály felállítása', + 'BreadcrumbIncomingRoutes' => 'Bejövő útválasztás', + 'SubHeaderIncomingRoutes' => 'A bejövő hívások elosztásának szabályai és sablonjai', + 'BreadcrumbIncomingRoutesmodify' => 'Szabály felállítása', + 'BreadcrumbExtensions' => 'Alkalmazottak', + 'SubHeaderExtensions' => 'Elsődleges telefonszámok és személyes továbbítási szabályok beállítása', + 'BreadcrumbExtensionsmodify' => 'Beállítások módosítása', + 'BreadcrumbCallQueues' => 'Hívási sorok', + 'SubHeaderCallQueues' => 'A hívások tartásba kerülnek, majd stratégia szerint szétosztják a résztvevők között', + 'BreadcrumbCallQueuesmodify' => 'Sor felállítása', + 'BreadcrumbOutOffWorkTime' => 'Nem munkaidő', + 'SubHeaderOutOffWorkTime' => 'Az állomás munkaidőn túli, ünnepnapokon és hétvégén történő üzemeltetésének szabályai', + 'BreadcrumbOutOffWorkTimemodify' => 'Szabály felállítása', + 'BreadcrumbFirewall' => 'Tűzfal beállítása', + 'SubHeaderGeneralSettings' => 'Alapvető rendszerparaméterek konfigurálása', + 'BreadcrumbIvrMenu' => 'Interaktív hangmenük – IVR', + 'BreadcrumbIvrMenumodify' => 'Az IVR menü beállítása', + 'SubHeaderIvrMenu' => 'A bejövő hívások irányításának sémájának és opcióinak konfigurálása', + 'BreadcrumbDialplanApplications' => 'Dialplan alkalmazások', + 'BreadcrumbDialplanApplicationsmodify' => 'Az alkalmazás beállítása', + 'SubHeaderDialplanApplications' => 'Programozható hangalkalmazások PHP-ben és Asterisk Dialplanban', + 'BreadcrumbConferenceRooms' => 'Konferenciák', + 'SubHeaderConferenceRooms' => 'Szobák kialakítása több résztvevős audiokonferenciákhoz', + 'BreadcrumbConferenceRoomsmodify' => 'Beállítások', + 'BreadcrumbCallDetailRecords' => 'Híváslista', + 'SubHeaderCallDetailRecords' => 'Beszélgetési napló és hívásnapló', + 'BreadcrumbCustomFilesmodify' => 'Szerkesztés', + 'BreadcrumbCustomFiles' => 'Rendszerfájlok', + 'SubHeaderCustomFiles' => 'A rendszer és az Asterisk konfigurációs fájlok testreszabása', + 'BreadcrumbSoundFiles' => 'Hangfájlok', + 'SubHeaderSoundFiles' => 'Különféle hívási helyzetekben és interaktív hangmenükben használható', + 'BreadcrumbLicensing' => 'Engedélyezés', + 'SubHeaderLicensing' => 'Új bővítmények és modulok eléréséhez regisztráljon a Piactéren', + 'BreadcrumbErrors' => 'Hiba üzenet', + 'SubHeaderErrors' => 'Ha ez a hiba reprodukálható, forduljon a fejlesztőhöz.', + 'BreadcrumbRestart' => 'Indítsa újra a rendszert', + 'BreadcrumbRestartmanage' => 'Indítsa újra a rendszert', + 'SubHeaderRestart' => 'Modulok újraindítása, teljes újraindítás vagy leállítás', + 'BreadcrumbSession' => 'Engedélyezés', + 'BreadcrumbSessionend' => 'Engedélyezés', + 'BreadcrumbSystemDiagnostic' => 'Rendszerdiagnosztika', + 'SubHeaderSystemDiagnostic' => 'Rendszernaplók gyűjtése a MikoPBX működési hibáinak részletes elemzéséhez', + 'BreadcrumbFail2Ban' => 'Hackelés elleni védelem', + 'SubHeaderFail2Ban' => 'Automatikus blokkolás jelszavak kiválasztásakor', + 'BreadcrumbUpdate' => 'Rendszerfrissítés', + 'SubHeaderUpdate' => 'Hibajavítások, teljesítményjavítások, új funkciók', + 'BreadcrumbPbxExtensionModules' => 'Modulok és bővítmények kezelése MikoPBX-hez', + 'SubHeaderPbxExtensionModules' => 'Töltsd fel saját vagy tölts le modulokat piacterünkről', + 'mm_Setup' => 'Telefonálás', + 'mm_Extensions' => 'Alkalmazottak', + 'mm_CallQueues' => 'Hívási sorok', + 'mm_DialplanApplications' => 'Dialplan alkalmazások', + 'mm_Routing' => 'útvonalválasztás', + 'mm_Providers' => 'Telefonszolgáltatók', + 'mm_IncomingRoutes' => 'Bejövő útvonalak', + 'mm_OutboundRoutes' => 'Kimenő útvonalak', + 'mm_OutOffWorkTime' => 'Nem munkaidő', + 'mm_System' => 'Rendszer', + 'mm_NetworkSettings' => 'Hálózat és tűzfal', + 'mm_GeneralSettings' => 'Általános beállítások', + 'mm_TimeSettings' => 'dátum és idő', + 'mm_Network' => 'Hálózati interfészek', + 'mm_Firewall' => 'Tűzfal', + 'mm_MailSettings' => 'Levél és értesítések', + 'mm_AsteriskManagers' => 'Hozzáférés az AMI-hez', + 'mm_IvrMenu' => 'IVR menü', + 'mm_ConferenceRooms' => 'Konferenciák', + 'mm_CallDetailRecords' => 'Híváslista', + 'mm_SoundFiles' => 'Hangfájlok', + 'mm_Restart' => 'Indítsa újra', + 'mm_PbxExtensionModules' => 'Modulok', + 'mm_Maintenance' => 'Szolgáltatás', + 'mm_Logout' => 'Kijárat', + 'mm_SystemDiagnostic' => 'Rendszernaplók', + 'mm_Fail2Ban' => 'Hackelés elleni védelem', + 'mm_Update' => 'PBX frissítés', + 'mm_ModuleManager' => 'Modulok piactere', + 'mm_SSHConsole' => 'SSH konzol', + 'mm_Integrations' => 'Integrációk', + 'bt_Edit' => 'változás', + 'bt_Clear' => 'Egyértelmű', + 'bt_Back' => 'Vissza', + 'bt_ToolTipCopyPassword' => 'A jelszó a vágólapra másolva', + 'bt_ToolTipEdit' => 'változás', + 'bt_ToolTipRestore' => 'visszaállítás', + 'bt_ToolTipDownload' => 'Letöltés', + 'bt_ToolTipCopy' => 'Másolat', + 'bt_ToolTipDelete' => 'Töröl', + 'sip_REG_TYPE_NONE' => 'Hitelesítés IP címmel, jelszó nélkül', + 'pr_ProviderName' => 'Szolgáltató neve', + 'pr_ProviderLogin' => 'Belépés', + 'pr_ProviderPassword' => 'Jelszó', + 'pr_ProviderHostOrIPAddress' => 'Gazda vagy IP-cím', + 'pr_DTMFMode' => 'DTMF mód', + 'pr_RegistrationSettings' => 'Regisztrációs beállítások', + 'pr_ValidationProviderHostIsEmpty' => 'Adja meg a szerver nevét vagy a szolgáltató IP-címét', + 'pr_ValidationProviderLoginIsEmpty' => 'Adja meg bejelentkezési adatait, hogy engedélyezze a szolgáltatóval', + 'pr_ValidationProviderLoginNotSingleSimbol' => 'A bejelentkezésnek egy karakternél hosszabbnak kell lennie', + 'pr_SIPPort' => 'SIP csatlakozási port', + 'pr_NoRegister' => 'Regisztráció letiltása', + 'pr_ManualAdditionalAtributes' => 'Extra lehetőségek', + 'pr_UpdateStatus' => 'Állapotfrissítés', + 'pr_Online' => 'A kapcsolat létrejött', + 'pr_Offline' => 'Tiltva', + 'pr_WithoutRegistration' => 'A regisztráció letiltva', + 'pr_TableColumnProviderType' => 'típus', + 'pr_TableColumnProviderName' => 'Szolgáltató', + 'pr_TableColumnProviderStatus' => 'Állapot', + 'pr_ValidateRTPOutOfRange' => 'Az RTP-portok tartománya nem megfelelő. Az értékeknek {ruleValue} között kell lenniük', + 'pr_RTPPortRange' => 'RTP port tartomány', + 'pr_RTPPortFrom' => 'VAL VEL', + 'pr_RTPPortTo' => 'Által', + 'pr_Note' => 'Megjegyzés vagy hasznos információ a szolgáltatóról', + 'gs_RTPStunServer' => 'STUN szerver címe (például: stun.test.net:10000)', + 'gs_Store6MonthsOfRecords' => '6 hónap', + 'gs_Store1YearOfRecords' => '1 év', + 'gs_Store3YearsOfRecords' => '3 év', + 'gs_PBXRecordSavePeriodLabel' => 'A hívásfelvételek tárolási ideje', + 'gs_StoreAllPossibleRecords' => '∞', + 'gs_DisableAllModules' => 'Piactér letiltása', + 'gs_ErrorSaveSettings' => 'Hiba a beállítások mentésekor', + 'mo_ThisNumberNotUniqueForExtensionsModels' => 'A megadott mellékszám már használatban van', + 'pr_AddSIPProvider' => 'Csatlakoztassa a SIP-t', + 'pr_AddIAXProvider' => 'Csatlakoztassa az IAX-et', + 'ir_CallTransferTo' => 'A hívás a következő címre lesz átirányítva', + 'pr_QualifyInstructionsIAX' => 'Ha ez az opció engedélyezve van, az Asterisk SIP Options csomagokat küld. Erre azért van szükség, hogy támogassa a NAT alagútkezelést az útválasztón.', + 'pr_CustomFieldsDescriptions' => 'A legtöbb esetben a felülbírálási mezőket üresen kell hagyni. + Csak ha a hívások nem működnek az Ön számára, és a szolgáltató speciális beállításokat igényel, akkor ezeket a mezőket a szolgáltató ajánlása szerint kell kitölteni.', + 'pr_ReceiveCallsWithoutAuth' => 'Hívások fogadása hitelesítés nélkül', + 'pr_ValidationProviderPortRange' => 'A szolgáltató portjának a következőn belül kell lennie: {ruleValue}', + 'pr_DeleteTitle' => 'Szolgáltató eltávolítása', + 'pr_DeleteDescription' => 'A szolgáltatóval együtt az összes kapcsolódó kimenő útválasztási szabály törlődik, és a bejövő forgalomirányítási szabályokban az összes hivatkozás helyére "Bármely szolgáltató" kerül.', + 'pr_Cancel' => 'Megszünteti', + 'pr_Delete' => 'Töröl', + 'pr_EnterHostOrIp' => 'További szolgáltatói címek', + 'pr_EnterHostOrIpPlaceholder' => 'Írja be az IP-címet vagy az alhálózatot, és nyomja meg az Enter billentyűt', + 'pr_NoAnyAdditionalHosts' => 'Nincsenek megadva további címek ehhez a szolgáltatóhoz', + 'or_RuleName' => 'Szabály neve', + 'or_Note' => 'A jegyzet', + 'or_PatternToMatch' => 'A szabály működni fog, ha', + 'or_NumberBeginsWithTheDigits' => 'A szám ezzel kezdődik', + 'or_TheRestOfTheNumberMustBe' => 'A szám többi része a megadott számú számjegyből áll', + 'or_ReformatNumber' => 'Szám konvertálása', + 'or_BeforeConnectingTheCallTrim' => 'Mielőtt elkezdenénk a hívást, megszakítjuk', + 'or_digitsFromTheFrontAndThenPrependTheDigits' => 'számokat a szám elejére, majd adja hozzá az elejéhez', + 'or_CallThrough' => 'Irányítsa a hívást', + 'or_Provider' => 'a szolgáltatón keresztül', + 'or_ValidationPleaseEnterRuleName' => 'Adja meg a szabály nevét', + 'or_ValidateBeginPattern' => 'Hiba a számszűrő mezőben. Lehet benne számok és jelek :)|', + 'or_ValidateRestNumbers' => 'A szám minimális hosszának 2-nél nagyobbnak kell lennie', + 'or_ValidateTrimFromBegin' => 'Helytelen érték a szám elején lévő karakterek csonkolásához', + 'ir_ValidateForwardingToBeFilled' => 'Az átirányítási szám nincs megadva', + 'or_ValidatePrepend' => 'Hiba történt a szám elejéhez való hozzáadáskor. A mező tartalmazhat számokat és jeleket: * # +. Az érték maximális hossza 20 karakter.', + 'or_AddNewRule' => 'Új szabály hozzáadása', + 'or_TableColumnName' => 'Név', + 'or_TableColumnRule' => 'Szabály', + 'or_TableColumnProvider' => 'Szolgáltató', + 'or_TableColumnNote' => 'A jegyzet', + 'or_RuleDescription' => '%numberbeginswith% az elején, majd %restnumbers% számjegy', + 'or_RuleDescriptionBeginEmpty' => 'A szám %restnumbers% számjegyekből áll', + 'or_RuleNotConfigured' => 'A szabály nincs konfigurálva', + 'or_RuleAnyNumbers' => 'Bármilyen szám', + 'or_RuleDescriptionFullMatch' => 'Csak a %numberbeginswith% számhoz', + 'or_RuleDescriptionBeginMatch' => 'Bármilyen hosszúságú, %numberbeginswith% karakterrel kezdődő számokhoz', + 'or_ValidationPleaseSelectProvider' => 'Válassza ki azt a szolgáltatót, amelyre ez a szabály vonatkozik.', + 'ir_Provider' => 'Szolgáltató', + 'ir_RuleName' => 'Szabály neve', + 'ir_Note' => 'A jegyzet', + 'ir_TableColumnNote' => 'A jegyzet', + 'ir_TableColumnName' => 'Név', + 'ir_TableColumnDetails' => 'Szabály', + 'ir_RuleDescriptionWithNumberAndWithProvider' => 'A(z) %number% számra   %provider% keresztül érkező hívást a(z)   %callerid% címre irányítjuk.', + 'ir_RuleDescriptionWithoutNumber' => 'A   %provider%-on keresztül érkező hívás a következőre lesz átirányítva:   %callerid%', + 'ir_RuleDescriptionWithoutProvider' => 'A(z) %number% számra érkező hívást a(z)   %callerid% számra irányítjuk', + 'ir_RuleDescriptionWithoutNumberAndWithoutProvider' => 'A bármely szolgáltatón keresztül érkező hívást a rendszer a következő címre irányítja:   %callerid%', + 'ir_DefaultRoute' => 'Alapértelmezett bejövő útvonal', + 'ir_ActionSelect' => 'Ha egyik szabály sem egyezik', + 'ir_busy_signal' => 'Foglalt hang lejátszása', + 'ir_extension' => 'Hívás átadása', + 'ir_playback' => 'Médiafájl lejátszása', + 'ir_ExtensionSelect' => 'Számhoz', + 'ir_RuleAssignIf' => 'A szabály híváskor működni fog', + 'ir_DidNumber' => 'Kiegészítő szám (DID)', + 'ex_DTMFMode' => 'DTMF mód', + 'ir_ValidateForwardingDefaultToBeFilled' => 'Az alapértelmezett átirányítási szám nincs megadva', + 'ir_ValidationPleaseEnterRuleName' => 'Adja meg a szabály nevét', + 'ir_ValidateTimeoutOutOfRange' => 'Az átirányítási időtúllépés helytelenül van megadva. {ruleValue} között kell lennie', + 'ir_DidNumberDescription' => 'A szolgáltató továbbadhat egy további számot, ez egy opcionális mező, de bizonyos esetekben pontosabban irányíthatja a hívásokat.', + 'ir_TimeoutToTransferDefault' => 'Az az idő másodpercben, amely után a hívás a következő prioritási szabályhoz lesz irányítva', + 'ir_AddNewRule' => 'Új szabály hozzáadása', + 'ir_AnyProvider' => 'Bármilyen szolgáltató', + 'ir_AnyProvider_v2' => 'Nincs kapcsolat szolgáltatóval, nincs jogosultság', + 'cq_Extension' => 'Sorszám', + 'cq_Name' => 'Sor neve', + 'cq_Note' => 'A jegyzet', + 'cq_Description' => 'A jegyzet', + 'cq_AddNewQueue' => 'Hozzon létre egy új sort', + 'cq_QueueMembersColumnName' => 'Operátor', + 'cq_QueueMembersColumnExtension' => 'Szám', + 'cq_ringall' => 'A hívás egyszerre érkezik a sorban lévő összes résztvevőhöz, beleértve azokat is, akik foglaltak (alapértelmezés szerint)', + 'cq_leastrecent' => 'A hívás ahhoz a sortaghoz érkezik, aki a leghosszabb ideig nem fogadott hívásokat', + 'cq_fewestcalls' => 'A hívás annak a sortagnak szól, aki a legkevesebb hívást kezelte ', + 'cq_random' => 'A hívás a sorban álló bármely ingyenes résztvevőhöz érkezik', + 'cq_rrmemory' => 'A hívás a sorban lévő bármely ingyenes résztvevőhöz érkezik, kivéve azt a résztvevőt, aki az utolsó hívást feldolgozta', + 'cq_linear' => 'A hívás minden sor résztvevőhöz sorrendben érkezik', + 'cq_QueueSetup' => 'Fő beállítások', + 'cd_Extensions' => 'A sor telefonszáma', + 'cq_QueueStrategy' => 'Hívásstratégia szolgáltatók számára', + 'cd_Description' => 'Egy komment', + 'cq_QueueMembers' => 'Soroperátorok', + 'cq_SelectAgentForAddToQueue' => 'Válasszon ki egy alkalmazottat, akit hozzá szeretne adni az aktuális sorhoz', + 'cq_QueueMemberSettings' => 'Sorbeállítások az operátorok számára', + 'cq_SecRingToEachMembers' => 'Hívási kísérleti idő az operátorok számára', + 'cq_WrapupTime' => 'A kezelő pihenőideje a hívás kezelése után, mielőtt új hívások fogadását kezdené', + 'cq_ReciveCallWhileOnCall' => 'Új hívások fogadása hívás közben', + 'cq_QueueCallerSettings' => 'Hívósor beállításai', + 'cq_CallerHearOnQueued' => 'Mit hall az előfizető várakozás közben', + 'cq_ringing' => 'Híváshangok', + 'cq_moh' => 'Zene', + 'cq_AnnoncePosition' => 'Értesítés az aktuális pozícióról a sorban', + 'cq_AnnonceHoldTime' => 'Értesítés a becsült várakozási időről', + 'cq_PereodicAnonceSoundFile' => 'Promóciós kifejezés vagy kiegészítő értesítés', + 'cq_PereodicAnonceMohSoundFile' => 'Háttérzene (MOH)', + 'gs_SSHDisablePasswordLogins' => 'Jelszavas hitelesítés letiltása', + 'cq_PereodicAnonceFrequency' => 'Az összes figyelmeztetés időszakos ismétlésének ideje másodpercben', + 'cq_CallRouting' => 'Hívásirányítás hiba esetén', + 'cq_ScenaryOne' => '1. forgatókönyv', + 'cq_ScenaryTwo' => '2. forgatókönyv', + 'cq_ScenaryThree' => '3. forgatókönyv', + 'cq_ScenaryFour' => '4. forgatókönyv', + 'cq_IfQueueNotAnsweredFor' => 'Ha egy előfizető többet vár a sorban ', + 'cq_SecondsCallWillBeRoutedTo' => ' másodpercig, átirányítja a hívást a következőre ', + 'cq_RedirectToExtensionIfEmtyQueue' => 'Ha nincs operátor a sorban, vigye át a hívást a következőre ', + 'cq_IfQueueNotAnsweredNumberCalls' => 'Ha belül egyik kezelő sem veszi fel a hívást ', + 'cq_CallsCallWillBeRoutedTo' => 'hívások, az összes új hívás átirányítása ide ', + 'cq_IfQueueNotAnsweredRepeat' => 'Ha a sor feldolgozása nem szekvenciálisan történt ', + 'cq_ThisNumberIsNotFree' => 'Ez a szám foglalt', + 'cq_ValidateNameEmpty' => 'Kérjük, adja meg a sor nevét', + 'cq_ValidateExtensionEmpty' => 'A sor mellékszáma nincs megadva', + 'cq_ValidateExtensionDouble' => 'A sorhoz megadott mellékszám már használatban van', + 'cq_ValidateExtensionNumber' => 'A mellékszám csak számokból állhat', + 'cq_ValidateNoExtensions' => 'Nincsenek kiválasztva a sor tagjai', + 'cq_CallerIDPrefix' => 'A sor rövid neve, amelyet az előfizető hívóazonosítója előtt kell megjeleníteni, például "Értékesítés"', + 'ex_NetworkFilter' => 'Hálózati szűrő', + 'cq_ImpossibleToDeleteCallQueue' => 'Lehetetlen törölni egy hívási sort, mert a következő linkek vannak', + 'dt_Info' => '_START_-_END_ bejegyzések _TOTAL_', + 'dt_InfoEmpty' => 'Nincsenek a kiválasztási kritériumoknak megfelelő rekordok', + 'dt_InfoFiltered' => '(_MAX_ rekord közül kiválasztva)', + 'dt_Previous' => 'Előző', + 'dt_Next' => 'Következő', + 'dt_Search' => 'Keresés', + 'dt_TableIsEmpty' => 'nincs megjeleníthető adat', + 'ml_EmailNotSended' => 'Az üzenetet nem küldték el', + 'ml_EmailSendedSuccess' => 'Levél elküldve', + 'ml_EmailTestSubject' => 'Tesztelje az e-maileket a telefonrendszeréből', + 'ml_EmailTestBody' => 'Üdvözöljük, ha ez a levél van a levelében, akkor a beállítások helyesek.', + 'er_Unauthorized' => 'Engedélyezési hiba', + 'er_UnauthorizedDescription' => 'Nincs hozzáférése ehhez az oldalhoz.', + 'er_PageNotFound' => 'Az oldal nem található', + 'er_PageNotFoundDescription' => 'Ez az oldal nem létezik.', + 'er_InternalServerError' => 'Belső Szerverhiba', + 'er_InternalServerErrorDescription' => 'Valami elromlott. Ilyen hibák nem létezhetnek.', + 'ex_CallRecording' => 'Beszélgetések rögzítése', + 'ex_enableRecording' => 'Lehetővé teszi', + 'ex_DenyNetwork' => 'Tiltott hálózat', + 'ex_GeneralSettings' => 'Fő beállítások', + 'ex_RoutingSettings' => 'Útválasztási beállítások', + 'ex_ThisNumberIsNotFree' => 'A szám már benne van az adatbázisban', + 'ex_ThisNumberOverlapWithParkingSlots' => 'Kereszteződés számos parkolószámmal', + 'ex_MobileNumber' => 'Mobil szám', + 'ex_Secret' => 'SIP jelszó', + 'ex_ChangeAvatar' => 'Avatar módosítása', + 'ex_UserPhotography' => 'Alkalmazotti fotó', + 'ex_MobileSettings' => 'További beállítások a mobilhoz', + 'ex_MobileDialstring' => 'Tárcsázási karakterlánc felülbírálása', + 'ex_SipSettings' => 'SIP beállítások', + 'ex_BusyLevel' => 'A párhuzamos beszélgetések maximális száma', + 'ex_BusyLevelInfo' => 'A megadott számú hívás elérésekor az alkalmazott telefonja foglaltnak minősül.', + 'ex_ValidateEmailEmpty' => 'Valószínűleg rosszul adta meg az e-mail címet', + 'ex_ValidateUsernameEmpty' => 'Adja meg az alkalmazott teljes nevét', + 'ex_ValidateUsernameSpecialCharacters' => 'A teljes név nem tartalmazhat speciális karaktereket', + 'ex_ValidateSecretEmpty' => 'A SIP jelszó nem lehet üres', + 'ex_ValidateSecretWeak' => 'A SIP jelszónak 4 karakternél hosszabbnak kell lennie', + 'ex_PasswordNoLowSimvol' => 'A jelszónak betűket kell tartalmaznia', + 'ex_PasswordNoNumbers' => 'A jelszónak számokat kell tartalmaznia', + 'ex_ValidateExtensionNumber' => 'A mellékszám csak számokból állhat', + 'ex_AddNewExtension' => 'Alkalmazott hozzáadása', + 'ex_Transport' => 'Szállítási protokoll', + 'ex_Extension' => 'Mellék számát', + 'ex_OutboundProxy' => 'Kimenő proxy (például: pbx.yandex.net:5080)', + 'ex_Mobile' => 'Mobil', + 'ex_Email' => 'Email', + 'ex_Status' => 'Állapot', + 'ex_RegeneratePassword' => 'Hozzon létre egy új jelszót', + 'ex_ValidateForwardingToBeFilled' => 'Az időtúllépési továbbítási szám nincs kitöltve az útválasztási beállításokban', + 'ex_ValidateRingingBeforeForwardOutOfRange' => 'Az útválasztási beállítások azt jelzik, hogy az átvitel előtti idő nem megfelelő. Válasszon egy értéket a {ruleValue} közül.', + 'ex_ValidateNumberIsEmpty' => 'Az alkalmazotti belső szám nincs kitöltve', + 'ex_ValidateForwardingToBeDifferent' => 'A saját számra történő továbbítást nem állíthatja be', + 'ex_ValidateMobileNumberIsDouble' => 'A mobilszámot már egy másik alkalmazott használja', + 'ex_ValidateNumberIsDouble' => 'A mellékszám már foglalt', + 'ex_UpdateStatus' => 'Állapotfrissítés', + 'ex_Online' => 'csatlakoztatva', + 'ex_SelectNumber' => 'Válassza ki a számot', + 'ex_dropdownCategory_CONFERENCE' => 'Konferenciák', + 'ex_dropdownCategory_USER' => 'Alkalmazottak', + 'ex_dropdownCategory_USERS' => 'Alkalmazottak', + 'ex_dropdownCategory_DIALPLAN_APPLICATION' => 'Dialplan alkalmazások', + 'ex_dropdownCategory_IVR_MENU' => 'Interaktív hangmenük IVR', + 'ex_dropdownCategory_QUEUE' => 'Hívási sorok', + 'ex_dropdownCategory_MODULES' => 'További modulok', + 'ex_dropdownCategory_PROVIDERS' => 'Szolgáltatók', + 'ex_dropdownCategory_IVRMENU' => 'Interaktív hangmenük IVR', + 'ex_dropdownCategory_PBXEXTENSIONMODULES' => 'További modulok', + 'ex_dropdownCategory_CONFERENCEROOMS' => 'Konferenciák', + 'ex_dropdownCategory_DIALPLANAPPLICATIONS' => 'Dialplan alkalmazások', + 'ex_dropdownCategory_NETWORKFILTERS' => 'Alhálózatok', + 'ex_dropdownCategory_OUTWORKTIMES' => 'Nem munkaidő', + 'ex_dropdownCategory_ASTERISKMANAGERUSERS' => 'AMI felhasználók', + 'ex_dropdownCategory_CUSTOMFILES' => 'Konfigurációs fájlok', + 'ex_dropdownCategory_MENUITEMS' => 'Menüpontok', + 'ex_dropdownCategory_SYSTEM' => 'Szolgáltatási számok', + 'ex_dropdownCategory_PARKING' => 'Parkolóhelyek', + 'ex_ImpossibleToDeleteExtension' => 'Lehetetlen törölni egy alkalmazottat, mert a következő linkek vannak', + 'ex_ImpossibleToGetSecret' => 'Nem sikerült megszerezni a felhasználói jelszót', + 'am_TableColumnName' => 'Név', + 'am_TableColumnRead' => 'Olvasási hozzáférés', + 'am_TableColumnWrite' => 'Írási hozzáférés', + 'am_TableColumnDescription' => 'Megjegyzések', + 'am_AddNewUser' => 'AMI felhasználó hozzáadása', + 'am_TableColumnNetworkFilter' => 'Hálózati szűrő', + 'am_Read' => 'olvasás', + 'am_Write' => 'rekord', + 'am_Username' => 'Felhasználónév', + 'am_Secret' => 'Jelszó', + 'am_NetworkFilter' => 'Hálózati szűrő', + 'am_UserRights' => 'Felhasználói jogok', + 'am_Description' => 'Egy komment', + 'am_ValidationAMINameIsEmpty' => 'A fiók neve nincs megadva', + 'am_ValidationAMISecretIsEmpty' => 'A jelszó nincs kitöltve', + 'am_ErrorThisUsernameInNotAvailable' => 'Már létezik azonos nevű bejegyzés', + 'am_NoAnyServersYet' => 'Itt még nincsenek AMI-felhasználók', + 'tf_ActionPlayMessage' => 'Fájl lejátszása %message%', + 'tf_ActionTransferToExtension' => 'Hívás átirányítása ide: %extension%', + 'tf_TableColumnDatePeriod' => 'Időszak', + 'tf_TableColumnTimePeriod' => 'Idő', + 'tf_TableColumnWeekDaysPeriod' => 'A hét napjai', + 'tf_TableColumnNotes' => 'A jegyzet', + 'tf_AddNewTimeFrame' => 'Időintervallum hozzáadása', + 'tf_DateDaysFrom' => 'Időszak', + 'tf_ValidateCheckDateInterval' => 'Ellenőrizze a dátumtartományt', + 'tf_ValidateCheckTimeInterval' => 'Ellenőrizze az időintervallumot', + 'tf_ValidateAudioMessageEmpty' => 'Válassza ki a hangfelvételt', + 'tf_ValidateExtensionEmpty' => 'Válassza ki a mellékállomás számát a továbbításhoz', + 'tf_ValidateNoRulesSelected' => 'Nincs kitöltött időszak', + 'tf_TabGeneralSettings' => 'alapbeállítások', + 'tf_TabRoutsRestriction' => 'A kiválasztott útvonalakra érvényes', + 'tf_calUrl' => 'A naptár URL-je', + 'tf_calUser' => 'Felhasználónév', + 'tf_calSecret' => 'Jelszó', + 'tf_calType' => 'típus', + 'tf_CAL_TYPE_NONE' => 'Rendes', + 'tf_CAL_TYPE_CALDAV' => 'CalDAV', + 'tf_CAL_TYPE_ICAL' => 'iCal', + 'tf_ValidateCalUri' => 'A „Naptár URL-címe” mező helytelen értéket tartalmaz.', + 'Mon' => 'hétfő', + 'Tue' => 'kedd', + 'Wed' => 'szerda', + 'Thu' => 'csütörtök', + 'Fri' => 'péntek', + 'Sat' => 'szombat', + 'Sun' => 'vasárnap', + 'fw_AddNewRule' => 'Új alhálózat hozzáadása', + 'fw_TableColumnDescription' => 'Név', + 'fw_TableColumnNetwork' => 'Alhálózat/Cím', + 'fw_Description' => 'Név', + 'fw_Permit' => 'Alhálózat', + 'fw_Rules' => 'Elérhető szolgáltatások', + 'fw_sipDescription' => 'SIP & RTP - telefon regisztráció és hangforgalom', + 'fw_webDescription' => 'WEB - hozzáférés az adminisztrációs felülethez', + 'fw_amiDescription' => 'AMI – hozzáférés az Asterisk Manager API-hoz Telneten keresztül', + 'fw_ctiDescription' => 'CTI - telefonpanel csatlakoztatása', + 'fw_ajamDescription' => 'AJAM – hozzáférés a csillagkezelő API-hoz a http/https-n keresztül', + 'fw_sshDescription' => 'SSH - root hozzáférés a rendszerhez', + 'fw_icmpDescription' => 'ICMP - kapcsolat ellenőrzése ping paranccsal', + 'fw_ValidatePermitAddress' => 'A megadott alhálózati cím helytelen. Próbálja ki a 192.168.1.0/24-hez hasonló kialakítást', + 'nw_ValidateDHCPOnVlansDontSupport' => 'A DHCP nem támogatott VLAN-alhálózatok esetén', + 'fw_NewerBlockIp' => 'Soha ne blokkoljon címeket erről a hálózatról, hagyja figyelmen kívül a telefon engedélyezési és jelszóbeviteli hibákat a webes felületen', + 'fw_ItIsLocalNetwork' => 'Ez egy VPN vagy helyi hálózat, a hálózat telefonjai közvetlenül csatlakoznak az állomáshoz NAT-útválasztás nélkül', + 'fw_AllNetworksRule' => 'Minden elérhető hálózat', + 'fw_LocalNetworksRule' => 'Alhálózat, ahol a MikoPBX található', + 'fw_DenyNetwork' => 'Tiltott alhálózat', + 'fw_PermitNetwork' => 'alhálózat', + 'fw_Subnet' => 'Alhálózati maszk', + 'fw_AdditionalRules' => 'Extra lehetőségek', + 'fw_StatusEnabled' => 'Tűzfal és hackelés elleni védelem', + 'fw_StatusDisabled' => 'A tűzfal és a feltörés elleni védelem le van tiltva', + 'fw_NeedConfigureRule' => 'Beállítást igényel', + 'mo_BeforeDeleteNetworkFilterDeleteAsteriskManagerUsersFirst' => 'Talált linket erre a szabályra az Asterisk Managers listában az %username% felhasználóhoz', + 'mo_BeforeDeleteNetworkFilterDeleteSipFirst' => 'Találtam egy linket erre a szabályra az alkalmazottak listájában a %extension% címen', + 'mo_ThisVlanIdNotUniqueForLanInterfacesModels' => 'A rendszer már rendelkezik interfésszel ugyanazzal a VLAN-nal', + 'mo_Disabled' => 'kikapcsolva', + 'mo_RightNumber' => 'számú szabály.%id%', + 'mo_NewElement' => 'Új létrehozása', + 'mo_NewElementNetworkFilters' => 'Új tűzfalszabály az alhálózathoz/címhez', + 'mo_NewElementExtensions' => 'Új alkalmazott', + 'mo_NewElementCallQueues' => 'Új hívási sor', + 'mo_NewElementIvrMenu' => 'Új IVR menü', + 'mo_NewElementConferenceRooms' => 'Új konferenciaterem', + 'mo_NewElementIax' => 'Új IAX szolgáltató', + 'mo_NewElementSip' => 'Új SIP szolgáltató', + 'mo_NewElementIncomingRoutingTable' => 'Új szabály a bejövő hívások feldolgozására', + 'mo_NewElementOutgoingRoutingTable' => 'Új szabály a kimenő hívások feldolgozására', + 'mo_NewElementOutWorkTimes' => 'Új szabály a munkaidőn túli munkavégzésre', + 'mo_NewElementDialplanApplications' => 'Új alkalmazás/tárcsázási terv', + 'mo_NewElementAsteriskManagerUsers' => 'Új fiók az AMI-felhasználó számára', + 'mo_NewElementSoundFiles' => 'Új hangfájl', + 'nw_PublicHostName' => 'Az útválasztó külső gazdagépneve', + 'nw_ValidateNameIsNotBeEmpty' => 'Az interfész neve üres', + 'nw_ValidateVlanRange' => 'A VLAN értéke hibásan van kitöltve. Válasszon a {ruleValue} közül', + 'nw_Hostname' => 'Helyi gazdagépnév', + 'nw_ValidateExtIppaddrNotRight' => 'Hiba az útválasztó külső IP-címének kitöltésekor', + 'nw_ValidateExtIppaddrOrHostIsEmpty' => 'Meg kell adnia az útválasztó külső IP-címét vagy DNS-nevét', + 'nw_ValidateVlanCross' => 'Hibák az interfészek VLAN-beállításaiban, ellenőrizze a paraméterek metszetét', + 'nw_ValidateIppaddrIsEmpty' => 'A hálózati interfész IP-címe nincs kitöltve', + 'nw_ValidateIppaddrNotRight' => 'A hálózati interfész IP-címe helytelenül van megadva', + 'nw_GatewayAddress' => 'Átjáró címe', + 'nw_IPAddress' => 'IP-cím', + 'nw_NetworkMask' => 'Alhálózati maszk (CIDR)', + 'nw_VlanID' => 'VLAN azonosító', + 'nw_NATInfo1' => 'Ha hálózata úgy van beállítva, hogy támogassa az 1:1 NAT-ot (általában ez az alapértelmezett felhőben), akkor nem kell további beállításokat megadnia az útválasztón.', + 'nw_NATInfo2' => 'Ha nem használ 1:1 NAT-ot, irányítsa át a következő portokat a nyilvános IP-ről az alközpont belső IP-címére az útválasztó beállításaiban.', + 'nw_NATInfo3' => '%SIP_PORT% TCP/UDP és %TLS_PORT% TCP', + 'nw_NATInfo5' => 'Ha külső állomásnevet ad meg, akkor a rendszer a külső IP-cím helyett azt használja.', + 'nw_NATInfo6OR' => 'VAGY', + 'nw_PublicSIPPort' => 'SIP-portszám továbbítva a belső %SIP_PORT% alközpontba', + 'nw_PublicTLSPort' => 'A SIP TLS portszám továbbításra került a belső %TLS_PORT% alközpontba', + 'nw_UseDHCP' => 'Használja a DHCP-t a hálózati beállításokhoz', + 'nw_LookUpExternalIp' => 'Ismerje meg a külső IP-címet', + 'nw_DeleteCurrentInterface' => 'Távolítsa el ezt a felületet', + 'nw_NetworkAddressTranslations' => 'Hálózati topológia', + 'nw_UpdateExternalIPAutomaticallyOnReboot' => 'Frissítse a külső IP-címet minden újraindításkor', + 'gs_MainTab' => 'Alapvető', + 'gs_FeaturesTab' => 'Hívásátvitel', + 'gs_SIPTab' => 'KORTY', + 'gs_AMITab' => 'AMI&AJAM', + 'gs_SSHTab' => 'SSH', + 'gs_WebTab' => 'Webes felület', + 'gs_PBXFeatureDigitTimeout' => 'A számjegyek közötti maximális időtúllépés mellékszám megadásakor (ezredmásodpercben)', + 'gs_PBXFeaturePickupExten' => 'Kombináció a bejövő hívások lehallgatására', + 'gs_PBXSplitAudioThread' => 'A felvételek mentése sztereó módban', + 'gs_PBXAllowGuestCalls' => 'Engedélyezze a bejövő hívásokat bármely szerverről', + 'gs_SIPPort' => 'SIP port telefonok regisztrálásához ezen az állomáson', + 'gs_TLS_PORT' => 'SIP TLS port (titkosított hívások)', + 'gs_KeepAliveHeader' => 'A regisztráció időtartamának beállításai', + 'gs_SIPDefaultExpiry' => 'Normál idő másodpercben a Keep-Alive küldéséhez', + 'gs_SIPExpiryRange' => 'Minimális és maximális idő másodpercben', + 'gs_SIPPortSettings' => 'Portbeállítások a SIP jelzéshez és az RTP tartományhoz', + 'gs_RTPPortRange' => 'RTP port tartomány', + 'gs_AMIEnabled' => 'Használja az AMI interfészt', + 'gs_AMIPort' => 'AMI port', + 'gs_AJAMEnabled' => 'Használja az AJAM interfészt', + 'gs_AJAMPort' => 'AJAM kikötője', + 'gs_AJAMPortTLS' => 'Titkosított AJAM port', + 'gs_SSHPort' => 'SSH port', + 'adv_SSHPPasswordCorrupt' => 'A webes felületen beállított SSH jelszó nem egyezik a rendszerben aktuálisval. javítás', + 'gs_SSHLogin' => 'Bejelentkezés az SSH konzolhoz', + 'gs_SSHPassword' => 'SSH jelszó', + 'gs_SSHAuthorizedKeys' => 'SSH hitelesített kulcsok', + 'gs_PasswordSimple' => 'A beállított jelszó túl egyszerű.', + 'gs_SetPassword' => 'Állítson be új jelszót', + 'gs_SetPasswordError' => 'Jelszó - %password% nem használható, az egyszerű jelszavak szótárában megtalálható.', + 'gs_SetPasswordInfo' => 'A megadott jelszó nem használható az egyszerű jelszószótárban.', + 'gs_PasswordNoNumbers' => 'A jelszónak számokat kell tartalmaznia', + 'gs_PasswordNoLowSimvol' => 'A jelszónak kisbetűket kell tartalmaznia', + 'gs_PasswordNoUpperSimvol' => 'A jelszónak nagybetűket kell tartalmaznia', + 'gs_WebPort' => 'HTTP port', + 'gs_WebHTTPSPort' => 'HTTPs port', + 'gs_WEBHTTPSPrivateKey' => 'HTTPs privát kulcs', + 'gs_ValidateEmptySSHPassword' => 'Az SSH jelszó nem lehet üres', + 'gs_ValidateWeakSSHPassword' => 'Az SSH-jelszónak 4 karakternél hosszabbnak kell lennie', + 'gs_ValidateSSHPasswordsFieldDifferent' => 'Az SSH jelszó hibásan lett megadva. Írja be újra a jelszavát.', + 'gs_ValidateWEBPortOutOfRange' => 'A HTTP port mező helytelen. Válasszon egy értéket a {ruleValue} közül.', + 'gs_ValidateWEBHTTPSPortOutOfRange' => 'A HTTPS-port mező helytelen. Válasszon egy értéket a {ruleValue} közül.', + 'gs_ValidateWEBHTTPSPortNotEqualToWEBPort' => 'A HTTP- és a HTTPS-portoknak különbözniük kell', + 'gs_ValidateWEBPortNotEqualToAjamPort' => 'A HTTP- és az AJAM-portoknak különbözniük kell', + 'gs_ValidateWEBPortNotEqualToAjamTLSPort' => 'A HTTP- és az AJAM-portoknak különbözniük kell', + 'gs_ValidateWEBHTTPSPortNotEqualToAjamPort' => 'A HTTPS és az AJAM portoknak különbözniük kell', + 'gs_ValidateWEBHTTPSPortNotEqualToAjamTLSPort' => 'A HTTPS és az AJAM portoknak különbözniük kell', + 'gs_SendAnonymousMetrics' => 'Összeomlási információk küldése a fejlesztőknek', + 'gs_WebAdminLanguage' => 'Webes felület nyelve', + 'gs_CodecsTab' => 'Audio/Videó kodekek', + 'gs_AudioCodecs' => 'Audiokodekek', + 'gs_VideoCodecs' => 'Videokodekek', + 'gs_RestoreAllSettingsMessage' => 'Az összes beállítás, híváselőzmények, hívásrögzítési fájlok és telepített bővítmények törlődnek.', + 'gs_EnterDeleteAllPhrasePreText' => 'A rendszer tisztításához írja be a következő kifejezést a beviteli mezőbe:', + 'gs_PBXRecordAnnouncementOut' => 'Válassza ki a hívásrögzítési figyelmeztetést a kimenő hívásokhoz', + 'ts_CurrentSettings' => 'Jelenlegi beállítások', + 'ts_SystemTime' => 'rendszeridő', + 'ts_TimeZone' => 'Időzóna', + 'ts_ModifySettings' => 'Új beállítások', + 'ts_ManualAdjustDateTime' => 'Állítsa be kézzel az időt', + 'ts_CurrentSystemTime' => 'Aktuális idő', + 'ts_NTPServer' => 'NTP szerverek', + 'ts_ValidateDateTime' => 'Helytelen dátum', + 'ms_SMTPSettings' => 'Üzenetküldési beállítások', + 'ms_NotificationTemplatesMissed' => 'Sablon – nem fogadott hívások', + 'ms_NotificationTemplatesVoicemail' => 'Sablon – hangposta', + 'ms_SMTPHost' => 'SMTP gazdagép', + 'ms_SMTPPort' => 'SMTP port', + 'ms_SMTPUsername' => 'SMTP bejelentkezés', + 'ms_SentTestEmailAfterSaveTo' => 'Küldjön teszt e-mailt erre a címre', + 'ms_MissedCallSubject' => 'Nem fogadott hívás – e-mail tárgya', + 'ms_MissedCallBody' => 'Nem fogadott hívás - a levél szövege', + 'ms_MissedCallFooter' => 'Nem fogadott hívás - pince', + 'ms_VoicemailSubject' => 'Hangposta - tárgysor', + 'ms_VoicemailBody' => 'Hangposta - a levél szövege', + 'ms_VoicemailFooter' => 'Hangposta - pince', + 'ms_MailSysadminEmail' => 'Rendszergazda e-mail', + 'ms_SystemEmailForMissed' => 'E-mail az elmulasztott értesítésekről', + 'ms_TestEmailSubject' => 'Levélküldés tesztelése', + 'ms_TestEmailSentSuccessfully' => 'Levél elküldve', + 'ms_TestEmailBody' => 'Ha megkapta ezt a levelet, az azt jelenti, hogy a levelezési beállításai helyesek.', + 'ms_MissedCalls' => 'Nem fogadott hívások', + 'ms_Voicemail' => 'Hangposta', + 'ms_VoicemailCommonEmail' => 'Egyetlen e-mail hangpostaüzenetek küldéséhez', + 'iv_ValidateDigitsIsNotCorrect' => 'A kód mező nincs megfelelően kitöltve', + 'iv_ValidateExtensionIsNotCorrect' => 'Az előfizetői szám nincs kiválasztva', + 'iv_ValidateExtensionIsEmpty' => 'Az IVR menü száma nincs megadva', + 'iv_ValidateAudioFileIsEmpty' => 'Nincs hangfájl kiválasztva hangos üdvözléshez', + 'iv_ValidateNameIsEmpty' => 'Az IVR menü neve nincs megadva', + 'iv_ValidateNoIVRExtensions' => 'Az IVR menü további tárcsázási műveletei nincsenek megadva', + 'iv_ValidateTimeoutExtensionIsEmpty' => 'Időtúllépési továbbítási szám nincs megadva', + 'iv_ValidateExtensionIsDouble' => 'A megadott IVR menüszám foglalt', + 'iv_ValidateRepeatNumberOutOfRange' => 'A menü ismétlések száma nem megfelelő', + 'iv_ValidateTimeoutOutOfRange' => 'A mellékszámra való várakozás időtúllépése helytelenül van megadva', + 'iv_Name' => 'Menü neve', + 'iv_Description' => 'Egy komment', + 'iv_Extensions' => 'IVR menü száma', + 'iv_PlaySound' => 'Hangos üdvözlet', + 'iv_Actions' => 'További toborzási intézkedések', + 'iv_DeleteRow' => 'Töröl', + 'iv_AddNewRow' => 'Hozzáadás', + 'iv_TimeoutExtension' => 'Alapértelmezett szám', + 'iv_TimeoutToRedirect' => 'Időtúllépés a mellékállomás számának megadására váráshoz, amely után a hangos üdvözlés megismétlődik', + 'iv_AllowEnterAnyInternalExtension' => 'Bármely belső szám további tárcsázásának engedélyezése', + 'iv_Extension' => 'IVR menü száma', + 'iv_Note' => 'Megjegyzések', + 'iv_AddNewIvrMenu' => 'Hozzon létre egy új IVR menüt', + 'iv_ThisNumberIsNotFree' => 'Ez a szám foglalt', + 'iv_NumberOfRepeat' => 'Az alapértelmezett számra váltás előtti újrapróbálkozások száma', + 'iv_ImpossibleToDeleteIVRMenu' => 'Az IVR menüt nem lehet törölni, aktív hivatkozások vannak rá', + 'da_Main' => 'Alkalmazás beállítások', + 'da_Applicationlogic' => 'Program kód', + 'da_Hint' => 'Célzás', + 'da_Description' => 'Egy komment', + 'da_Name' => 'Név', + 'da_Extensions' => 'Pályázati hívószám', + 'da_ThisNumberIsNotFree' => 'Ez a szám foglalt', + 'da_ColumnName' => 'Név', + 'da_ColumnNote' => 'Leírás', + 'da_ValidateNameIsEmpty' => 'A pályázat neve nincs kitöltve', + 'da_ValidateExtensionIsEmpty' => 'A jelentkezési szám nincs kitöltve', + 'da_ValidateExtensionDouble' => 'Az alkalmazáshoz megadott mellékszám foglalt', + 'da_AddNewDialplanApp' => 'Új hozzáadása', + 'da_TypePhp' => 'PHP-AGI szkript', + 'da_TypePlaintext' => 'Csillag tárcsázási terv', + 'da_ValidateExtensionNumber' => 'A mellékszám csak számokból állhat', + 'da_ImpossibleToDeleteDialplanApplication' => 'A Dialplans alkalmazást nem lehet törölni, linkjei vannak', + 'cr_AddNewConferenceRoom' => 'Konferencia hozzáadása', + 'cr_ColumnExtension' => 'Szám', + 'cr_ColumnName' => 'Név', + 'cr_Name' => 'Konferenciaterem neve', + 'cr_pinCode' => 'Konferencia PIN kódja', + 'cr_Extensions' => 'Szám', + 'cr_ThisNumberIsNotFree' => 'Ez a szám foglalt', + 'cr_ValidateExtensionDouble' => 'A konferenciához megadott mellékszám foglalt', + 'cr_ValidateExtensionEmpty' => 'A belső konferencia száma nincs megadva', + 'cr_ValidateNameEmpty' => 'A konferencia neve nincs megadva', + 'cr_ValidateExtensionNumber' => 'A mellékszám csak számokból állhat', + 'cr_ValidateExtensionLen' => 'A mellékszámnak két vagy több számjegyből kell állnia', + 'cr_ValidatePinNumber' => 'A PIN-kód csak számokból állhat', + 'cr_ImpossibleToDeleteConferenceRoom' => 'Ez a konferenciaterem nem törölhető', + 'cdr_ColumnDate' => 'Hívás dátuma', + 'cdr_ColumnFrom' => 'WHO', + 'cdr_ColumnTo' => 'Kinek', + 'cdr_ColumnDuration' => 'Időtartam', + 'cdr_ColumnRecordings' => 'Hívásfelvételek', + 'cdr_And' => 'És', + 'cf_ColumnPath' => 'A fájl elérési útja', + 'cf_ColumnMode' => 'Mód', + 'cf_ColumnNote' => 'A jegyzet', + 'cf_FileActionsNone' => 'Ne változz', + 'cf_FileActionsAppend' => 'Csatolás a fájl végéhez', + 'cf_FileActionsOverride' => 'Cserélje ki teljesen', + 'cf_FileActionsScript' => 'Folyamat scripttel', + 'cf_Main' => 'Megjegyzés a változásokhoz', + 'cf_Content' => 'Programkód vagy konfiguráció', + 'cf_Path' => 'A fájl elérési útja', + 'cf_Description' => 'Írja meg kommentben, hogy miért történt a változtatás', + 'cf_Mode' => 'Mód', + 'cf_OriginalFileHeader' => 'A rendszer által generált eredeti fájltartalom', + 'cf_UserEditHeader' => 'Szerkesztő a változtatásokhoz', + 'cf_ResultFileHeader' => 'A fájl tartalma változtatásokkal', + 'mo_BeforeDeleteFirst' => 'Vannak linkek az objektumhoz - %represent%', + 'ConstraintViolation' => 'A logikai integritás megsértése', + 'repAsteriskManagerUsers' => 'AMI bejegyzés – %represent%', + 'repCallQueues' => 'Hívási sor – %represent%', + 'repCallQueueMembers' => 'Hívási sor tagja – %represent%', + 'repConferenceRooms' => 'Konferencia – %represent%', + 'repCustomFiles' => 'Rendszerfájl – %represent%', + 'repDialplanApplications' => 'Dialplan alkalmazás – %represent%', + 'repExtensionForwardingRights' => 'Munkavállalói útválasztási beállítások – %represent%', + 'repExtensions' => 'Mellékállomás száma - %represent%', + 'repExternalPhones' => 'Külső szám - %represent%', + 'repIvrMenuActions' => 'Az IVR menü résztvevője – %represent%', + 'repLink' => 'link', + 'sf_ValidationFileNameIsEmpty' => 'A fájlnév nincs megadva', + 'sf_Filename' => 'Felvételi fájl neve', + 'sf_UploadNewSoundFile' => 'Új fájl feltöltése', + 'sf_RecordNewSoundFile' => 'Felvétel mikrofon segítségével', + 'sf_UploadSoundFileButton' => 'Letöltés', + 'sf_FileNotFound' => 'Hiba – a fájl nem játszható le', + 'sf_SelectAudioFile' => 'Válassza ki a hangfájlt', + 'sf_ValidationFileNotSelected' => 'Először töltse le a hangfájlt', + 'sf_CustomSounds' => 'Audio fájlok', + 'sf_MusicOnHold' => 'Zene tartásban', + 'lic_ValidateContactEmail' => 'A kötelező mező nincs kitöltve - a kapcsolattartó e-mail címe', + 'lic_ValidateContactName' => 'A kötelező mező nincs kitöltve - kapcsolattartó', + 'lic_ValidateCouponEmpty' => 'A kötelező mező nincs kitöltve - kupon', + 'lic_GetKeyForm' => 'Bejegyzés', + 'lic_ActivateCoupon' => 'Kupon aktiválás', + 'lic_LicenseKey' => 'Licenckulcs', + 'lic_CompanyName' => 'A szervezet neve', + 'lic_Email' => 'A kapcsolattartó e-mail címe', + 'lic_Contact' => 'A kapcsolattartó személy', + 'lic_Phone' => 'Kapcsolattartási telefonszám', + 'lic_Inn' => 'Egyedi cégazonosító (TIN, IIN, UNP stb.)', + 'lic_Coupon' => 'Licencmegújító kupon', + 'lic_ActivateCouponButton' => 'Kupon aktiválása', + 'lic_RegisterTheSystemButton' => 'Regisztráció', + 'lic_SaveLicenseKeyButton' => 'Kulcs mentése', + 'lic_GetTrialErrorCheckInternet' => 'A regisztráció sikertelen, ellenőrizze az internet elérhetőségét a MikoPBX-en', + 'lic_SuccessfulCouponActivation' => 'A kupon sikeresen aktiválva', + 'lic_SuccessfulActivation' => 'Sikeres rendszerregisztráció', + 'lic_WrongLicenseKeyOrEmpty' => 'A licenckulcsot helytelenül adta meg', + 'lic_FailedCheckLicense' => 'A licencszerver nem adott választ, ellenőrizze az internetbeállításokat', + 'lic_FailedCheckLicenseNotPbxResponse' => 'A MikoPBX nem válaszolt a licencinformációk iránti kérésre. A szolgáltatás nem elérhető.', + 'lic_UnknownLicenseMessage' => 'Nincs válasz az engedélyezési rendszertől', + 'lic_LicenseKeyMessage' => 'A licenckulcs az összes MIKO-termékhez tartozó licenc tárolására szolgál.
      +Ha már van kulcsa, egyszerűen beírhatja ebbe a mezőbe.
      +Ha volt kulcsa, de elfelejtette, keresse a beérkező leveleket a lic@miko.ru címen
      +A regisztrációs űrlap kitöltésével automatikusan új kulcsot kaphat.
      ', + 'lic_CouponMessage' => 'A kupon az előfizetések, próbaverziók megújítására és a bővítőmodulok licenceinek aktiválására szolgál.
      +A kupon egyszer aktiválható, ezután válik beválthatóvá.', + 'lic_CurrentLicenseInfo' => 'Részletes információk a licenckulcsban található termékekről', + 'lic_Expired' => 'A termék lejárt, kérjük, lépjen kapcsolatba a következővel: lic@mikopbx.com', + 'lic_ExpiredAfter' => 'A licenc az %expired% után jár le', + 'lic_Product' => 'Termék', + 'lic_FeatureInfo' => 'Összes %count% licenc a %name% számára, ebből foglalt %captured%', + 'lic_LicenseKeyProducts' => 'Aktivált termékek', + 'lic_LicenseKeyOwner' => 'Engedély birtokosa', + 'lic_ResetLicenseSettings' => 'Kulcskötés alaphelyzetbe állítása', + 'lic_LicenseKeyValid' => 'A program regisztrálva van', + 'lic_FailedToGetTrialKey2051' => '(2051) Ezt a példányt nem lehetett regisztrálni, mert már használta a regisztrációs számot egy másik e-mail címmel ezen a gépen.
      + Használja a korábban a lic@miko.ru címről küldött kulcsot', + 'lic_FailedToGetTrialKey2022' => '(2022) Nem sikerült regisztrálni ezt a példányt. A megadott e-mail címen már létrejött egy másik cég regisztrációs száma.
      + Használja a korábban a lic@miko.ru címről küldött kulcsot, vagy adja meg a helyes cégnevet.', + 'lic_FailedActivateCoupon2057' => '(2057) Ez a kupon le van tiltva', + 'lic_FailedActivateCoupon2040' => '(2040) Ez a kupon nem létezik, kérjük ellenőrizze a bejegyzés helyességét', + 'lic_FailedActivateCoupon2041' => '(2041) Ezt a kupont már korábban aktiválták', + 'lic_FailedActivateCoupon2037' => '(2037) Hiba a regisztrációs szám megadásakor', + 'lic_FailedCheckLicense2026' => '(2026) Hiba a licencszám megadásakor', + 'lic_FailedToCaptureFeature2008' => '(2008) Nincs szükség licencre, vagy másik MikoPBX-hez van kötve', + 'lic_InvalidLicenseKey2009' => '(2009) Licenckulcs hiba', + 'lic_FeatureExpired2011' => '(2011) A modul licence lejárt, kérjük, lépjen kapcsolatba a következővel: sale@mikopbx.com', + 'lic_IntroductionTabHeader' => 'A piacterek engedélyezéséről', + 'lic_ManagementTabHeader' => 'Regisztráció és licenckezelés', + 'lic_FirstQuestionHeader' => 'Szükséges-e regisztrálni?', + 'lic_FirstQuestionAnswer' => 'A MikoPBX alapvető funkciói teljesen ingyenesek, és nem korlátozzák a licencet. Az engedély hiánya semmilyen módon nem befolyásolja a hívásokat.
      A Piactéren bármikor regisztrálhat, illetve törölheti a regisztrációt.', + 'lic_MarketplaceHeader' => 'A piactér további lehetőségeket kínál', + 'ext_ModuleInstallDescription' => 'A modul telepítésekor a rendszer ellenőrzi a licencet. A fizetős modulokhoz lehetőség szerint próbaverziót biztosítunk. Az ingyenes modulokat feltételek nélkül telepítik. Ha a modult korábban törölték a beállítások mentése közben, akkor azok visszaállnak. A modul telepítése közben jobb, ha nem hajt végre más műveleteket a rendszeren.', + 'ext_UpdateAllModulesTitle' => 'Az összes modul frissítése', + 'ext_UpdateAllModulesDescription' => 'A rendszer az összes telepített modult a legújabb verzióra frissíti, megtartva a jelenlegi beállításokat. Javasoljuk, hogy a frissítési folyamat során ne végezzen más műveletet a rendszeren.', + 'ext_UpdateModuleTitle' => 'Modul frissítés', + 'ext_ModuleUpdateDescription' => 'A kiválasztott modul frissül a lerakat legfrissebb verziójára, és minden beállítás mentésre kerül. Fizetős modulok esetén először a licencet ellenőrizzük. A frissítés során ajánlatos tartózkodni a rendszeren végzett egyéb műveletek végrehajtásától.', + 'ext_DowngradeModuleTitle' => 'Modul verzió visszagörgetése', + 'ext_ModuleDowngradeDescription' => 'A modul visszaáll az előző verzióra. A beállítások mentésre kerülnek, de a fizetős modulok esetében először a licenc ellenőrzése történik meg. Kérjük, vegye figyelembe, hogy a visszaállítás megváltoztathatja az adatstruktúrát, és előfordulhat, hogy a modult újra kell konfigurálni. A visszaállítás során ne hajtson végre más műveleteket a rendszeren.', + 'ext_InstallUpdateAction' => 'Végrehajtás', + 'ext_SystemVersionRequired' => 'A MikoPBX minimálisan kompatibilis verziója', + 'DimmerWaitForPBXIsOnline' => 'Megszakadt a kapcsolat az alközponti maggal…', + 'DimmerWaitForPBXOnlineDescription' => 'Normális, hogy az állomás újraindul.
      Amint a kapcsolat helyreáll, az oldal automatikusan frissül!', + 'loc_NoResult' => 'Nincs találat', + 'mo_CallQueueShort4Dropdown' => 'Sor', + 'mo_ConferenceRoomsShort4Dropdown' => 'Konferencia', + 'mo_SystemExten_did2user' => 'Közvetlenül az alkalmazotthoz (a DID egyeztetése)', + 'mo_SystemExten_voicemail' => 'Hangposta', + 'GoToWikiDocumentation' => 'Nyissa meg az online dokumentációt', + 'mo_ModuleSettingsError' => 'Hibák a modul beállításaiban - %modulename%', + 'adv_MessagesHeader' => 'jegyzet', + 'adv_MessagesHeaderError' => 'Súlyos hiba', + 'adv_YouUseDefaultWebPassword' => 'Az alapértelmezett jelszót használja az adminisztrációs felületre való bejelentkezéshez - szerkesztés', + 'adv_YouUseDefaultSSHPassword' => 'Az alapértelmezett jelszót használja az SSH eléréséhez – szerkesztés', + 'adv_WebPasswordWeak' => 'Egyszerű rendszergazdai jelszó a webes felületen módosítás', + 'adv_SshPasswordWeak' => 'Egyszerű SSH-fiók jelszava módosítás', + 'adv_SipPasswordWeak' => 'Egyszerű SIP jelszó: %record%', + 'adv_AmiPasswordWeak' => 'Egyszerű jelszó az AMI-felhasználók számára %record%', + 'adv_PopupHeader' => 'A következő problémákat találtuk:', + 'pass_CheckWebAdminPasswordSimple' => 'A WEB jelszó túl egyszerű.', + 'pass_CheckWebAdminPasswordDontMatch' => 'A WEB-hez megadott jelszavak nem egyeznek', + 'pass_CheckWebAdminPasswordEmpty' => 'A mező üres: a WEB jelszava', + 'pass_CheckWebPassErrorChange' => 'Nem sikerült megváltoztatni a jelszót', + 'pass_CheckSSHPasswordDontMatch' => 'A megadott SSH jelszavak nem egyeznek', + 'adv_FirewallDisabled' => 'A tűzfal le van tiltva a rendszerben - szerkesztés', + 'adv_StorageDiskUnMounted' => 'A beállítások és adatok tárolására szolgáló lemez nincs csatlakoztatva!', + 'adv_NetworksNotConfigured' => 'Az engedélyezett alhálózatok paraméterei nincsenek konfigurálva - módosítás', + 'adv_AvailableNewVersionPBX' => 'Elérhető az alközpont új verziója – %ver%', + 'adv_StorageDiskRunningOutOfFreeSpace' => 'A tárolólemezen kifogy a szabad hely (%free% Mb)', + 'adv_ThisCopyHasLicensingTroubles' => 'PBX licencprobléma: %error% - az javítása', + 'adv_ProblemWithInternetConnection' => 'Nincs internet kapcsolat. Problémák adódhatnak a fizetős modulok működésében.', + 'cal_Yesterday' => 'Tegnap', + 'cal_LastWeek' => 'Az elmúlt 7 nap', + 'cal_Last30Days' => 'Az elmúlt 30 nap', + 'sntry_ErrorGeneric' => 'Ismeretlen hiba a küldés során. Próbáld újra!', + 'sntry_ErrorFormEntry' => 'A mezők nincsenek kitöltve, kérjük javítsa ki és próbálja meg újra elküldeni!', + 'sntry_SuccessMessage' => 'Köszönöm a segítségedet!', + 'lang_HelpWithTranslateIt' => 'Segítség a MikoPBX fordításában', + 'topMenu_Support' => 'Támogatás', + 'topMenu_SearchPlaceholder' => 'Írja be a keresett kifejezést', + 'topMenu_SidebarButton' => 'Menü', + 'MIKO_PBX' => 'MIKO alközpont', + 'PBX is running in Live or Recovery mode' => 'A rendszer helyreállítási módba indult (Live CD)', + 'LAN IP address assigned via DHCP' => 'DHCP szerveren keresztül hozzárendelt LAN IP', + 'LAN IP address' => 'A LAN IP manuális beállítása', + 'VLAN IP address assigned via' => 'VLAN IP: keresztül működik', + 'The integrity of the system is broken' => 'A rendszer integritása sérül', + 'adv_SystemBrokenComment' => 'A rendszerfájlok módosultak. Végezzen rendszer-visszaállítást/frissítést.', + 'PBX console setup' => 'MikoPBX konzol', + 'Install or recover' => 'Hajtsa végre a telepítést/visszaállítást', + 'Install on Hard Drive' => 'Hajtsa végre a telepítést', + 'Set up LAN IP address' => 'Konfigurálja a LAN IP-címét', + 'Reboot system' => 'Rendszer újraindítása', + 'Ping host' => 'Ping címek', + 'Firewall' => 'Tűzfal engedélyezése/letiltása', + 'Connect storage' => 'Csatlakoztasson egy lemezt az adattároláshoz', + 'Reset admin password' => 'Állítsa vissza a webes felület jelszavát', + 'Enter a number' => 'Adja meg a csapat számát', + 'Press ENTER to continue.' => 'Nyomja meg az ENTER-t a folytatáshoz…', + 'version' => 'változat', + 'this_is' => 'Ez ', + 'Do you want to use DHCP to configure your LAN interface?' => 'Használjak DHCP szervert a LAN interfész konfigurálásához?', + 'The LAN interface will now be configured via DHCP...' => "A LAN interfész DHCP használatával lesz konfigurálva…", + 'The LAN interface will now be configured ...' => "A LAN interfész beállítása…", + 'Enter the new LAN IP address: ' => 'Írja be az új LAN IP-címet:', + 'Subnet masks are to be entered as bit counts (as in CIDR notation).' => 'Alhálózati maszk CIDR formátumban (1-32)', + 'Enter the new LAN subnet bit count: ' => "Adja meg a maszk értékét:", + 'Enter the LAN gateway IP address: ' => "Adja meg az átjáró címét (LAN-átjáró IP-címe):", + 'Enter the LAN DNS IP address: ' => 'Adja meg a DNS-kiszolgáló címét:', + 'The system will reboot. This may take a minute.' => 'A rendszer újraindul. Ez eltart néhány percig.', + 'Do you want to proceed? (y/n): ' => 'Folytatja a folyamatot? (i/n):', + 'The system is rebooting now...' => 'Újraindítás…', + 'Enter a host name or IP address: ' => 'Adja meg a szerver címét:', + 'enable' => 'bekapcsol', + 'running' => 'beleértve', + 'stopped' => 'Tiltva', + 'Firewall is now' => 'Tűzfal most', + 'Firewall disabled' => 'Tűzfal letiltva', + 'Do you want disable firewall now? (y/n): ' => 'Letiltja? (i/n):', + 'Do you want enable firewall now? (y/n): ' => 'Bekapcsol? (i/n):', + 'Storage disk is already mounted...' => 'A tárolólemez már fel van szerelve', + 'Storage disk was mounted successfully...' => 'A tárolólemezt sikeresen csatlakoztatta', + 'Valid disks not found...' => 'Nem található egyező meghajtó', + 'Valid disks are:' => 'A megfelelő lemezek listája:', + 'Enter the device name:' => 'Írja be az eszköz nevét:', + 'Do you want reset password? (y/n): ' => 'Biztosan vissza szeretné állítani webes jelszavát a gyári beállításokra? (i/n):', + 'Password successfully reset. New login: admin. New password: admin.' => "Sikeres jelszó-visszaállítás. Felhasználónév: admin Jelszó: admin", + 'Install or recovery' => "Telepítés/helyreállítás", + 'All settings will be lost!' => 'Vissza a gyári beállításokhoz!', + 'All settings will be kept!' => 'Az aktuális beállítások mentésre kerülnek!', + 'Cancel' => 'Megszünteti', + 'Install' => 'Telepítés', + 'Reinstall to' => 'Frissítés verzióra', + 'Firmware version on this system:' => 'A rendszer jelenlegi firmware verziója:', + 'WARNING' => 'FIGYELEM', + 'The PBX will reboot after installation.' => 'A telepítés után a rendszer újraindul', + 'The PBX is about to be installed onto the' => 'A MikoPBX telepítve lesz a lemezre:', + 'everything on this device will be erased!' => 'az eszközön lévő összes adat törlődik!', + 'this cannot be undone!' => 'A művelet visszafordíthatatlan!', + 'Change language' => 'Nyelv módosítása / Az interfész nyelvének módosítása', + 'Select the drive to install the system.' => 'Válassza ki a lemezt a rendszer telepítéséhez', + 'Selected disk:' => 'Kiválasztott meghajtó:', + '(default value = ' => '(alapértelmezett = ', + 'Select the drive to store the data.' => 'Válasszon lemezt az adatok tárolására', + 'Partitioning and formatting storage disk' => 'Hozzon létre egy partíciót, és formázza meg a lemezt, hogy adatokat tároljon az eszközön', + 'Update storage partition 4 on disk' => 'A negyedik partíció frissítése az adatok lemezen való tárolására', + 'Installing PBX...' => 'MikoPBX telepítése…', + ' - Unmounting partitions...' => 'Felszerelt lemezpartíciók eltávolítása…', + ' - Unpacking img...' => 'A rendszerpartíció frissítése…', + 'Copying configuration...' => 'Kezdeti konfigurációs beállítások kitöltése…', + 'Save storage disk settings' => 'Lemezbeállítások mentése tároláshoz', + 'Formatting storage partition 4 on disk' => 'A negyedik partíció formázása adatok tárolására a lemezen', + 'Warning! Selected disk will be formatted!' => 'Figyelem! A kiválasztott lemez formázásra kerül, és minden adat megsemmisül!', + 'user' => 'felhasználó', + 'Reboot' => 'Indítsa újra a MikoPBX-et', + 'Power off' => 'Kikapcsol', + 'Choose action' => 'Válasszon egy műveletet', + 'Пропущенный вызов' => 'Nem fogadott hívása van', + 'Console' => 'Konzol (Shell)', + 'Failed to mount the disc...' => 'Nem sikerült a lemez csatlakoztatása', + 'All processes will be completed. Continue? (y/n):' => 'Minden folyamat befejeződik. Folytatni? (i/n):', + 'Configuring using DHCP' => 'Konfiguráció DHCP szerver segítségével', + 'Manual setting' => 'Kézi beállítás', + 'Storage' => 'Adattár', + 'Resize storage' => 'Növelje meg az adattároláshoz szükséges lemez méretét a teljes fel nem osztott terület felhasználásával', + 'Check storage' => 'Ellenőrizze a lemezt, hogy vannak-e hibák', + 'Storage unmounted' => 'A tárolólemez nincs csatlakoztatva', + 'sd_Filename' => 'Fájl', + 'sd_filter' => 'Szűrő', + 'sd_offset' => 'Offset', + 'sd_lines' => 'Határ', + 'sd_ShowLog' => 'Naplók megtekintése', + 'sd_CapturePcap' => 'Hálózati csomagok rögzítése', + 'sd_DownloadPcapFileError' => 'Hiba a naplóarchívum létrehozásakor', + 'sd_SystemInformation' => 'Rendszer információ', + 'sd_CollectingInfo' => 'Szolgáltatási információk gyűjtése', + 'sd_CollectingLogsInfo' => 'A naplófájlok listájának lekérése', + 'sd_PackingLogFiles' => 'Az összegyűjtött adatok csomagolása', + 'sd_ToolTipDownload' => 'Naplófájl letöltése', + 'sd_ToolTipRefresh' => 'Szerezze be a naplófájl legújabb verzióját', + 'sd_ToolTipAutoUpdate' => 'A képernyőn megjelenő tartalom automatikus frissítése', + 'msg_ErrorHeader' => 'Hiba', + 'msg_WarningHeader' => 'Figyelem', + 'msg_infoHeader' => 'Információ', + 'adv_SSHPasswordWasChangedSubject' => "Figyelem! Az SSH jelszó megváltozott!", + 'adv_SSHPasswordWasChangedBody' => "A MikoPBX eléréséhez szükséges SSH jelszó megváltozott!", + 'adv_SSHPasswordWasCompromisedSubject' => 'Figyelem! Az SSH jelszó a MikoPBX felületre való bejelentkezés nélkül megváltozott!', + 'adv_SSHPasswordMismatchStringsHash' => 'Az SSH jelszó a MikoPBX webes felületén kívül módosult', + 'adv_SSHPasswordMismatchFilesHash' => 'A MikoPBX SSH jelszó eltér a konfigurációs fájlban beállítotttól. Lehetséges, hogy manuálisan módosították a MikoPBX konzolról.', + 'adv_ThereIsSomeTroublesWithMikoPBX' => 'Figyelem! Problémákat észleltünk a MikoPBX-ben!', + 'lic_MarketplaceText' => 'A Marketplace-en történő regisztrációval további modulokhoz és bővítményekhez férhet hozzá.
      Vannak ingyenes modulok, amelyeket eltávolítottunk az alapfunkciók közül a kezdeti beállítás egyszerűsítése érdekében, valamint fizetős modulok tőlünk és más fejlesztőktől.
      Ha Ön Ha Ön fejlesztő, akkor vegye fel velünk a kapcsolatot, ha útmutatást szeretne kapni saját modulja fejlesztésével és a piactérhez való hozzáadásával kapcsolatban.', +]; From daafbb568f8442ddebfd9005b88a9ba19c75c8e4 Mon Sep 17 00:00:00 2001 From: Weblate Date: Wed, 31 Jul 2024 13:35:57 +0300 Subject: [PATCH 44/58] Translated using Weblate (Hungarian) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 100.0% (1243 of 1243 strings) Co-authored-by: Juhász Béla Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/hu/ Translation: MIKOPBX/Core --- src/Common/Messages/hu.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Common/Messages/hu.php b/src/Common/Messages/hu.php index 9e5bb886d..baea2c8b9 100644 --- a/src/Common/Messages/hu.php +++ b/src/Common/Messages/hu.php @@ -342,7 +342,7 @@ 'ex_Japanese' => '日本語', 'ex_Deutsch' => 'Deutsch', 'ex_Spanish' => 'Espanol', - 'ex_French' => 'Le français', + 'ex_French' => 'Francia', 'ex_Dutch' => 'Hollandia', 'ex_Georgian' => 'ქართველი', 'January' => 'január', From 3843ed8e08d5bbc498cdce228e0cff01e897a1bc Mon Sep 17 00:00:00 2001 From: boffart <> Date: Wed, 7 Aug 2024 17:20:33 +0300 Subject: [PATCH 45/58] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=B0=D0=B4=D1=80=D0=B5=D1=81=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=BB=D1=83=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BF=D1=83=D0=B1?= =?UTF-8?q?=D0=BB=D0=B8=D1=87=D0=BD=D0=BE=D0=B3=D0=BE=20IP=20=D0=BD=D0=B0?= =?UTF-8?q?=20amazonaws?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/System/RootFS/etc/profile | 2 +- src/Core/System/RootFS/sbin/check-out-ip | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Core/System/RootFS/etc/profile b/src/Core/System/RootFS/etc/profile index f5ee686bb..020d81e34 100644 --- a/src/Core/System/RootFS/etc/profile +++ b/src/Core/System/RootFS/etc/profile @@ -58,7 +58,7 @@ fi # Set aliases alias ls='ls --color=auto'; -alias myip="curl http://ipecho.net/plain; echo"; +alias myip="/usr/bin/curl https://checkip.amazonaws.com"; alias remount-offload="_remountOffload"; alias check-file-connection="_checkFileConnection"; alias ps='ps -A -f'; diff --git a/src/Core/System/RootFS/sbin/check-out-ip b/src/Core/System/RootFS/sbin/check-out-ip index fb27e8e07..08f607da0 100644 --- a/src/Core/System/RootFS/sbin/check-out-ip +++ b/src/Core/System/RootFS/sbin/check-out-ip @@ -24,7 +24,7 @@ if [ "$needCheckOutAddress" != '1' ]; then exit 0; fi; -outIp="$(/usr/bin/curl https://ipecho.net/plain 2> /dev/null)"; +outIp="$(/usr/bin/curl https://checkip.amazonaws.com 2> /dev/null)"; result="$?"; if [ "$result" != '0' ]; then echo 'Error getting an IP address'; From 5c22cc123b75e3abdac0a9a85187f388c9ae94de Mon Sep 17 00:00:00 2001 From: boffart <> Date: Thu, 8 Aug 2024 11:42:52 +0300 Subject: [PATCH 46/58] =?UTF-8?q?#762=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BA=D0=BE=D0=BD=D0=B2=D0=B5=D1=80=D1=82=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8E=20=D0=B3=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= =?UTF-8?q?=D0=BE=D0=B9=20=D0=BF=D0=BE=D1=87=D1=82=D1=8B=20=D0=B2=20mp3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/System/RootFS/sbin/voicemail-sender | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/Core/System/RootFS/sbin/voicemail-sender b/src/Core/System/RootFS/sbin/voicemail-sender index 59ef113f6..7392769c2 100644 --- a/src/Core/System/RootFS/sbin/voicemail-sender +++ b/src/Core/System/RootFS/sbin/voicemail-sender @@ -8,6 +8,7 @@ use MikoPBX\Core\System\SystemMessages; use MikoPBX\Core\System\Util; use MikoPBX\Core\Workers\WorkerCallEvents; use MikoPBX\Common\Models\PbxSettings; +use MikoPBX\Core\System\Processes; require_once('Globals.php'); @@ -40,14 +41,23 @@ try { $file = implode('', $parser->saveAttachments('/tmp/')); $recordingFile = VoiceMailConf::getCopyFilename($file, $linkedId, $d->getTimestamp(), true); $recordingFile = Util::trimExtensionForFile($recordingFile) . '.wav'; + + /** Convert tmp file to mp3 */ + $converter = Util::which('wav2mp3.sh'); + $baseNameTmp= Util::trimExtensionForFile($file); + $mp3File = "$baseNameTmp.mp3"; + Processes::mwExec("$converter $baseNameTmp"); + if(file_exists($mp3File)){ + $recordingFile = $mp3File; + } unlink($file); + /** create mail message */ $addresses = mailparse_rfc822_parse_addresses($parser->getHeader('to')); $rawHeaderTo = $addresses[0]['address']??''; if(!empty($rawHeaderTo)){ $toMails[] = $rawHeaderTo; } - $settings = PbxSettings::getAllPbxSettings(); $subject = str_replace([PHP_EOL, "\t"], '', $settings['MailTplVoicemailSubject']); $body = str_replace([PHP_EOL, "\t"], ['
      ', ''], $settings['MailTplVoicemailBody']); @@ -66,12 +76,15 @@ try { unset($data); } } - $message = "$body $footer"; replaceParams($subject, $params); replaceParams($message, $params); $notify = new Notifications(); $result = $notify->sendMail(implode(',', array_unique($toMails)), $subject, $message, $recordingFile); + + if(file_exists($mp3File)){ + unlink($mp3File); + } }catch (Throwable $e){ $recordingFile = ''; SystemMessages::sysLogMsg('Voicemail-Sender', $e->getMessage()); @@ -89,4 +102,4 @@ $result_send = $client->publish(json_encode($data, JSON_THROW_ON_ERROR)); $manager = Util::getAstManager(); unset($data['action']); -$manager->UserEvent('voicemail_end', $data); +$manager->UserEvent('voicemail_end', $data); \ No newline at end of file From 5ac99a2c16f44f5cb8dfb04e750842b4892929e6 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Thu, 8 Aug 2024 13:34:49 +0300 Subject: [PATCH 47/58] =?UTF-8?q?#764=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BF=D0=B0=D1=80=D0=B0=D0=BC=D0=B5=D1=82=D1=80?= =?UTF-8?q?=20NOTIFICATION=5FNAME=5FTO=20=D0=B4=D0=BB=D1=8F=20=D0=BE=D0=BF?= =?UTF-8?q?=D0=BE=D0=B2=D0=B5=D1=89=D0=B5=D0=BD=D0=B8=D0=B9=20=D0=BE=20?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D0=BF=D1=83=D1=89=D0=B5=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D1=85.=20=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0?= =?UTF-8?q?=D0=BB=20=D0=BE=D0=BF=D0=BE=D0=B2=D0=B5=D1=89=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=BE=20=D0=B3=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= =?UTF-8?q?=D0=BE=D0=B9=20=D0=BF=D0=BE=D1=87=D1=82=D0=B5,=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=B0?= =?UTF-8?q?=D1=80=D0=B0=D0=BC=D0=B5=D1=82=D1=80=D0=B0=20VM=5FCALLER=5FNAME?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Common/Models/Extensions.php | 36 ++++++++++++++++++++ src/Core/System/RootFS/sbin/voicemail-sender | 5 +++ src/Core/Workers/WorkerNotifyByEmail.php | 15 ++++++-- 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/src/Common/Models/Extensions.php b/src/Common/Models/Extensions.php index a5fb826c1..8ed11f48e 100644 --- a/src/Common/Models/Extensions.php +++ b/src/Common/Models/Extensions.php @@ -137,6 +137,42 @@ public static function getNextFreeApplicationNumber(): string return $freeExtension; } + /** + * Returns Caller ID by phone number. + * @param string $number + * @return string + */ + public static function getCidByPhoneNumber(string $number):string + { + if(empty($number)){ + return $number; + } + $number = preg_replace('/\D+/', '', $number); + $extensionLength = PbxSettings::getValueByKey(PbxSettingsConstants::PBX_INTERNAL_EXTENSION_LENGTH); + if(strlen($number) > $extensionLength){ + $query = 'number LIKE :phone:'; + $phone = '%'.substr($number, -9); + }else{ + $query = 'number = :phone:'; + $phone = $number; + } + $filter = [ + $query, + 'columns' => 'callerid', + 'bind' => [ + 'phone' => $phone + ] + ]; + $data = self::findFirst($filter); + if($data){ + $cid = $data->callerid; + }else{ + $cid = $number; + } + + return $cid; + } + /** * Get the next available internal extension number. * diff --git a/src/Core/System/RootFS/sbin/voicemail-sender b/src/Core/System/RootFS/sbin/voicemail-sender index 7392769c2..929ee496f 100644 --- a/src/Core/System/RootFS/sbin/voicemail-sender +++ b/src/Core/System/RootFS/sbin/voicemail-sender @@ -1,6 +1,7 @@ #!/usr/bin/php getGeneralSettings(); /** @var BeanstalkClient $message */ @@ -80,11 +83,16 @@ public function workerNotifyByEmail($message): void $tmpArray = []; foreach ($data as $call) { $keyHash = $call['email'] . $call['start'] . $call['from_number'] . $call['to_number']; - // Skip duplicate emails if (in_array($keyHash, $tmpArray, true)) { continue; } + if(isset($phonesCid[$call['to_number']])){ + $call['to_name'] = $phonesCid[$call['to_number']]; + }else{ + $call['to_name'] = Extensions::getCidByPhoneNumber($call['to_number']); + $phonesCid[$call['to_number']] = $call['to_name']; + } $tmpArray[] = $keyHash; if (!isset($emails[$call['email']])) { $emails[$call['email']] = [ @@ -98,7 +106,6 @@ public function workerNotifyByEmail($message): void $emails[$call['email']]['body'] .= "$email


      "; } } - foreach ($emails as $to => $email) { $subject = $email['subject']; $body = "{$email['body']}
      {$email['footer']}"; @@ -122,6 +129,7 @@ private function replaceParams(string $src, array $params): string "NOTIFICATION_MISSEDCAUSE", "NOTIFICATION_CALLERID", "NOTIFICATION_TO", + "NOTIFICATION_NAME_TO", "NOTIFICATION_DURATION", "NOTIFICATION_DATE" ], @@ -130,6 +138,7 @@ private function replaceParams(string $src, array $params): string 'NOANSWER', $params['from_number'], $params['to_number'], + $params['to_name'], $params['duration'], explode('.', $params['start'])[0] ], From 13f418c7d677c883fd286a18080220f043a23af5 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Thu, 8 Aug 2024 14:45:14 +0300 Subject: [PATCH 48/58] =?UTF-8?q?#734=20=D0=94=D0=BE=D1=80=D0=B0=D0=B1?= =?UTF-8?q?=D0=BE=D1=82=D0=B0=D0=BB=20=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=B9=D0=BA=D1=83=20indications.conf=20=D1=81=D0=B8=D0=BD?= =?UTF-8?q?=D1=85=D1=80=D0=BE=D0=BD=D0=B8=D0=B7=D0=B8=D1=80=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D0=BB=20=D1=81=20=D1=81=D0=B8=D1=81=D1=82=D0=B5=D0=BC?= =?UTF-8?q?=D0=BD=D1=8B=D0=BC=20=D1=8F=D0=B7=D1=8B=D0=BA=D0=BE=D0=BC.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/Asterisk/Configs/IndicationConf.php | 24 ++++++-- src/Core/Asterisk/Configs/SIPConf.php | 16 +----- .../Configs/Samples/indications.conf.sample | 56 ------------------- src/Core/System/PBX.php | 8 +++ 4 files changed, 28 insertions(+), 76 deletions(-) diff --git a/src/Core/Asterisk/Configs/IndicationConf.php b/src/Core/Asterisk/Configs/IndicationConf.php index b07ea4ee1..a3a111c32 100644 --- a/src/Core/Asterisk/Configs/IndicationConf.php +++ b/src/Core/Asterisk/Configs/IndicationConf.php @@ -20,6 +20,8 @@ namespace MikoPBX\Core\Asterisk\Configs; +use MikoPBX\Common\Models\PbxSettings; +use MikoPBX\Common\Models\PbxSettingsConstants; use MikoPBX\Core\System\Util; use function MikoPBX\Common\Config\appPath; @@ -32,8 +34,21 @@ */ class IndicationConf extends AsteriskConfigClass { - // The module hook applying priority - public int $priority = 1000; + public const LANG_ZONE_MAP = [ + 'ru-ru' => 'ru', + 'en-en' => 'us', + 'en-gb' => 'uk', + 'de-de' => 'de', + 'da-dk' => 'dk', + 'es-es' => 'es', + 'gr-gr' => 'gr', + 'fr-ca' => 'fr', + 'it-it' => 'it', + 'ja-jp' => 'jp', + 'nl-nl' => 'nl', + 'pl-pl' => 'pl', + 'pt-br' => 'pt', + ]; protected string $description = 'indications.conf'; @@ -44,13 +59,12 @@ class IndicationConf extends AsteriskConfigClass */ protected function generateConfigProtected(): void { - $country = 'ru'; // TODO: Add to the interface if it's an important option + $lang = PbxSettings::getValueByKey(PbxSettingsConstants::PBX_LANGUAGE); + $country = self::LANG_ZONE_MAP[$lang] ?? 'ru'; $filePath = appPath('src/Core/Asterisk/Configs/Samples/indications.conf.sample'); $data = file_get_contents($filePath); $conf = str_replace('{country}', $country, $data); - // Write the configuration content to the file Util::fileWriteContent($this->config->path('asterisk.astetcdir') . '/indications.conf', $conf); } - } \ No newline at end of file diff --git a/src/Core/Asterisk/Configs/SIPConf.php b/src/Core/Asterisk/Configs/SIPConf.php index c57474b68..ab6ccdc63 100644 --- a/src/Core/Asterisk/Configs/SIPConf.php +++ b/src/Core/Asterisk/Configs/SIPConf.php @@ -1127,21 +1127,7 @@ public static function getContextId(string $name, string $port):string */ public static function getToneZone(array &$options, string $lang): void { - $settings = [ - 'ru-ru' => 'ru', - 'en-gb' => 'uk', - 'de-de' => 'de', - 'da-dk' => 'dk', - 'es-es' => 'es', - 'gr-gr' => 'gr', - 'fr-ca' => 'fr', - 'it-it' => 'it', - 'ja-jp' => 'jp', - 'nl-nl' => 'nl', - 'pl-pl' => 'pl', - 'pt-br' => 'pt', - ]; - $toneZone = $settings[$lang] ?? ''; + $toneZone = IndicationConf::LANG_ZONE_MAP[$lang] ?? ''; if ( ! empty($toneZone)) { $options['inband_progress'] = 'yes'; $options['tone_zone'] = $toneZone; diff --git a/src/Core/Asterisk/Configs/Samples/indications.conf.sample b/src/Core/Asterisk/Configs/Samples/indications.conf.sample index c5c63615f..85d73b008 100644 --- a/src/Core/Asterisk/Configs/Samples/indications.conf.sample +++ b/src/Core/Asterisk/Configs/Samples/indications.conf.sample @@ -1,62 +1,6 @@ -; -; indications.conf -; -; Configuration file for location specific tone indications -; - -; -; NOTE: -; When adding countries to this file, please keep them in alphabetical -; order according to the 2-character country codes! -; -; The [general] category is for certain global variables. -; All other categories are interpreted as location specific indications -; - [general] country={country} - -; [example] -; description = string -; The full name of your country, in English. -; ringcadence = num[,num]* -; List of durations the physical bell rings. -; dial = tonelist -; Set of tones to be played when one picks up the hook. -; busy = tonelist -; Set of tones played when the receiving end is busy. -; congestion = tonelist -; Set of tones played when there is some congestion (on the network?) -; callwaiting = tonelist -; Set of tones played when there is a call waiting in the background. -; dialrecall = tonelist -; Not well defined; many phone systems play a recall dial tone after hook -; flash. -; record = tonelist -; Set of tones played when call recording is in progress. -; info = tonelist -; Set of tones played with special information messages (e.g., "number is -; out of service") -; name = tonelist -; Every other variable will be available as a shortcut for the "PlayList" command -; but will not be used automatically by Asterisk. -; -; -; The tonelist itself is defined by a comma-separated sequence of elements. -; Each element consist of a frequency (f) with an optional duration (in ms) -; attached to it (f/duration). The frequency component may be a mixture of two -; frequencies (f1+f2) or a frequency modulated by another frequency (f1*f2). -; The implicit modulation depth is fixed at 90%, though. -; If the list element starts with a !, that element is NOT repeated, -; therefore, only if all elements start with !, the tonelist is time-limited, -; all others will repeat indefinitely. -; -; concisely: -; element = [!]freq[+|*freq2][/duration] -; tonelist = element[,element]* -; - [at] description = Austria ringcadence = 1000,5000 diff --git a/src/Core/System/PBX.php b/src/Core/System/PBX.php index 8f12b3472..7934c96ae 100644 --- a/src/Core/System/PBX.php +++ b/src/Core/System/PBX.php @@ -35,6 +35,7 @@ FeaturesConf, HttpConf, IAXConf, + IndicationConf, ManagerConf, ModulesConf, MusicOnHoldConf, @@ -163,6 +164,9 @@ public static function coreReload(): void $asteriskConf = new AsteriskConf(); $asteriskConf->generateConfig(); + $indicationConf = new IndicationConf(); + $indicationConf->generateConfig(); + $arr_out = []; $asteriskPath = Util::which('asterisk'); Processes::mwExec("{$asteriskPath} -rx 'core reload'", $arr_out); @@ -175,6 +179,10 @@ public static function coreRestart(): void { $asteriskConf = new AsteriskConf(); $asteriskConf->generateConfig(); + + $indicationConf = new IndicationConf(); + $indicationConf->generateConfig(); + $asteriskPath = Util::which('asterisk'); Processes::mwExec("{$asteriskPath} -rx 'core restart now'"); } From edece82243d1afd93eadaebad98026ba67cf4a60 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Thu, 8 Aug 2024 14:46:31 +0300 Subject: [PATCH 49/58] #734 ... --- src/Core/Asterisk/Configs/SIPConf.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/Asterisk/Configs/SIPConf.php b/src/Core/Asterisk/Configs/SIPConf.php index ab6ccdc63..3d681edfb 100644 --- a/src/Core/Asterisk/Configs/SIPConf.php +++ b/src/Core/Asterisk/Configs/SIPConf.php @@ -1127,7 +1127,7 @@ public static function getContextId(string $name, string $port):string */ public static function getToneZone(array &$options, string $lang): void { - $toneZone = IndicationConf::LANG_ZONE_MAP[$lang] ?? ''; + $toneZone = IndicationConf::LANG_ZONE_MAP[$lang] ?? 'ru'; if ( ! empty($toneZone)) { $options['inband_progress'] = 'yes'; $options['tone_zone'] = $toneZone; From fe8e35360d1cd1b77e6a4838e7090ba24755d919 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Wed, 14 Aug 2024 14:48:30 +0300 Subject: [PATCH 50/58] =?UTF-8?q?#766=20=D0=9F=D1=80=D0=B0=D0=B2=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=BA=D0=BE=D0=BD=D0=B2=D0=B5=D1=80=D1=82=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D0=B8=20=D0=BC=D0=B5=D0=B4=D0=B8=D0=B0=20=D1=84=D0=B0?= =?UTF-8?q?=D0=B9=D0=BB=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Lib/System/ConvertAudioFileAction.php | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/PBXCoreREST/Lib/System/ConvertAudioFileAction.php b/src/PBXCoreREST/Lib/System/ConvertAudioFileAction.php index 0aa008b79..e1e052ade 100644 --- a/src/PBXCoreREST/Lib/System/ConvertAudioFileAction.php +++ b/src/PBXCoreREST/Lib/System/ConvertAudioFileAction.php @@ -39,6 +39,7 @@ public static function main(string $filename): PBXApiResult { $res = new PBXApiResult(); $res->processor = __METHOD__; + $res->success = true; if (!file_exists($filename)) { $res->success = false; $res->messages[] = "File '$filename' not found."; @@ -60,16 +61,23 @@ public static function main(string $filename): PBXApiResult // Convert file to wav format $tmp_filename = escapeshellcmd($tmp_filename); - $n_filename = escapeshellcmd($n_filename); $soxPath = Util::which('sox'); - - // Предварительная конвертация в wav. - Processes::mwExec("$soxPath -v 0.99 -G '$n_filename' -c 1 -r 8000 -b 16 '$n_filename'", $out); + $soxIPath = Util::which('soxi'); + $busyBoxPath = Util::which('busybox'); + // Pre-conversion to wav step 1. + if(Processes::mwExec("$soxIPath $tmp_filename | $busyBoxPath grep MPEG") === 0){ + Processes::mwExec("$soxPath $tmp_filename $tmp_filename.wav", $out); + unlink($tmp_filename); + $tmp_filename = "$tmp_filename.wav"; + } + $n_filename = escapeshellcmd($n_filename); + // Pre-conversion to wav step 2. + Processes::mwExec("$soxPath -v 0.99 -G '$tmp_filename' -c 1 -r 8000 -b 16 '$n_filename'", $out); $result_str = implode('', $out); // Convert wav file to mp3 format $lamePath = Util::which('lame'); - Processes::mwExec("$lamePath -b 32 --silent '$n_filename' '$n_filename_mp3'", $out); + Processes::mwExec("$lamePath -b 16 --silent '$n_filename' '$n_filename_mp3'", $out); $result_mp3 = implode('', $out); // Convert the file to various codecs using Asterisk @@ -79,7 +87,7 @@ public static function main(string $filename): PBXApiResult foreach ($codecs as $codec){ $result = shell_exec("$asteriskPath -rx 'file convert $tmp_filename $trimmedFileName.$codec'"); if(strpos($result, 'Converted') !== 0){ - shell_exec("$rmPath -rf /root/test.$codec"); + shell_exec("$rmPath -rf $trimmedFileName.$codec"); } } From 05d52f608d5fe9663cab664213a6b4eb36a5fd9b Mon Sep 17 00:00:00 2001 From: boffart <> Date: Wed, 28 Aug 2024 09:33:10 +0300 Subject: [PATCH 51/58] =?UTF-8?q?#783=20=D0=98=D1=81=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D0=BB=20=D0=BF=D0=BE=D0=BB=D1=83=D1=87=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=B8=D0=B4=D0=B5=D0=BD=D1=82=D0=B8=D1=84=D0=B8?= =?UTF-8?q?=D0=BA=D0=B0=D1=82=D0=BE=D1=80=D0=B0=20=D0=BA=D0=B0=D0=BD=D0=B0?= =?UTF-8?q?=D0=BB=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/Asterisk/Configs/lua/extensions.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Core/Asterisk/Configs/lua/extensions.lua b/src/Core/Asterisk/Configs/lua/extensions.lua index 4cd6a08b9..ca4233344 100644 --- a/src/Core/Asterisk/Configs/lua/extensions.lua +++ b/src/Core/Asterisk/Configs/lua/extensions.lua @@ -330,6 +330,11 @@ function event_dial(without_event) channel = orign_chan; end + if(channel == '')then + channel = get_variable('MASTER_CHANNEL(CHANNEL)'); + app["NoOp"]('The channel could not be determined. Use Master: ('..channel..')'); + end + local from_account = get_variable("FROM_PEER") if ( from_account=='' and string.lower(agi_channel):find("local/") == nil )then from_account = getAccountName(agi_channel); From 012182e57bc0d70891986311b0bae15bb7aa7951 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Wed, 28 Aug 2024 13:25:29 +0300 Subject: [PATCH 52/58] =?UTF-8?q?#781=20=D0=9F=D0=BE=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D0=BB=20=D1=81=D0=B1=D1=80=D0=BE=D1=81=20=5F=5FQUE?= =?UTF-8?q?UE=5FSRC=5FCHAN=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=B2=D0=B5=D1=80=D1=88=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=80=D0=B0?= =?UTF-8?q?=D0=B1=D0=BE=D1=82=D1=8B=20=D0=BE=D1=87=D0=B5=D1=80=D0=B5=D0=B4?= =?UTF-8?q?=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/Asterisk/Configs/QueueConf.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Core/Asterisk/Configs/QueueConf.php b/src/Core/Asterisk/Configs/QueueConf.php index ef28f1235..d051e8f9c 100644 --- a/src/Core/Asterisk/Configs/QueueConf.php +++ b/src/Core/Asterisk/Configs/QueueConf.php @@ -136,6 +136,7 @@ public function extensionGenInternal(): string } $ringLength = trim($queue['timeout_to_redirect_to_extension']); $queue_ext_conf .= "same => n,Queue({$queue['uniqid']},kT$options,,,$ringLength,,,queue_agent_answer) \n\t"; + $queue_ext_conf .= 'same => n,Set(__QUEUE_SRC_CHAN=${EMPTY})' . "\n\t"; // Notify about the end of the queue. $queue_ext_conf .= 'same => n,Gosub(queue_end,${EXTEN},1)' . "\n\t"; $timeoutExtension = trim($queue['timeout_extension']); From b8f91d9563b3659851ca18e645bd3e1e403a6156 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Wed, 28 Aug 2024 13:34:44 +0300 Subject: [PATCH 53/58] =?UTF-8?q?=D0=A3=D0=B1=D1=80=D0=B0=D0=BB=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=BD=D0=B2=D0=B5=D1=80=D1=82=D0=B0=D1=86=D0=B8=D1=8E=20?= =?UTF-8?q?=D1=81=D1=80=D0=B5=D0=B4=D1=81=D1=82=D0=B2=D0=B0=D0=BC=D0=B8=20?= =?UTF-8?q?asterisk=20'alaw',=20'ulaw',=20'gsm',=20'g722',=20'wav'=20?= =?UTF-8?q?=D1=8D=D1=82=D0=BE=20=D0=B7=D0=BD=D0=B0=D1=87=D0=B8=D1=82=D0=B5?= =?UTF-8?q?=D0=BB=D1=8C=D0=BD=D0=BE=20=D0=BC=D0=BE=D0=B3=D0=BB=D0=BE=20?= =?UTF-8?q?=D1=83=D1=85=D1=83=D0=B4=D1=88=D0=B0=D1=82=D1=8C=20=D0=BA=D0=B0?= =?UTF-8?q?=D1=87=D0=B5=D1=81=D1=82=D0=B2=D0=BE=20=D0=B7=D0=B0=D0=BF=D0=B8?= =?UTF-8?q?=D1=81=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/PBXCoreREST/Lib/System/ConvertAudioFileAction.php | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/PBXCoreREST/Lib/System/ConvertAudioFileAction.php b/src/PBXCoreREST/Lib/System/ConvertAudioFileAction.php index e1e052ade..1606fc490 100644 --- a/src/PBXCoreREST/Lib/System/ConvertAudioFileAction.php +++ b/src/PBXCoreREST/Lib/System/ConvertAudioFileAction.php @@ -80,17 +80,6 @@ public static function main(string $filename): PBXApiResult Processes::mwExec("$lamePath -b 16 --silent '$n_filename' '$n_filename_mp3'", $out); $result_mp3 = implode('', $out); - // Convert the file to various codecs using Asterisk - $codecs = ['alaw', 'ulaw', 'gsm', 'g722', 'wav']; - $rmPath = Util::which('rm'); - $asteriskPath = Util::which('asterisk'); - foreach ($codecs as $codec){ - $result = shell_exec("$asteriskPath -rx 'file convert $tmp_filename $trimmedFileName.$codec'"); - if(strpos($result, 'Converted') !== 0){ - shell_exec("$rmPath -rf $trimmedFileName.$codec"); - } - } - // Remove temporary file unlink($tmp_filename); if ($result_str !== '' && $result_mp3 !== '') { From 6e6a3cbd485c616cd50b73dbbe4ba6d82538df61 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Wed, 28 Aug 2024 16:21:06 +0300 Subject: [PATCH 54/58] =?UTF-8?q?#782=20=D0=9F=D0=BE=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D0=BB=20=D0=B3=D0=B5=D0=BD=D0=B5=D1=80=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D1=8E=20iax2.conf.=20=D0=9F=D0=BE=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D0=BB=20=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE=D0=B9?= =?UTF-8?q?=D0=BA=D0=B8=20=D1=81=D0=B5=D1=82=D0=B5=D0=B2=D0=BE=D0=B3=D0=BE?= =?UTF-8?q?=20=D1=8D=D0=BA=D1=80=D0=B0=D0=BD=D0=B0=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?IAX.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Common/Messages/ru.php | 1 + src/Common/Models/FirewallRules.php | 14 +++ src/Core/Asterisk/Configs/IAXConf.php | 87 +++++++++---------- .../UpdateConfigsUpToVer2024v2v10.php | 73 ++++++++++++++++ src/Core/System/Util.php | 49 ++++++----- 5 files changed, 154 insertions(+), 70 deletions(-) create mode 100644 src/Core/System/Upgrade/Releases/UpdateConfigsUpToVer2024v2v10.php diff --git a/src/Common/Messages/ru.php b/src/Common/Messages/ru.php index fc0bc506f..90b5424a1 100644 --- a/src/Common/Messages/ru.php +++ b/src/Common/Messages/ru.php @@ -543,6 +543,7 @@ 'fw_Permit' => 'Подсеть', 'fw_Rules' => 'Доступные сервисы', 'fw_sipDescription' => 'SIP & RTP - регистрация телефонов и голосовой трафик', + 'fw_iaxDescription' => 'IAX - регистрация телефонов и голосовой трафик', 'fw_webDescription' => 'WEB - доступ к административному интерфейсу', 'fw_amiDescription' => 'AMI - доступ к asterisk manager api через telnet', 'fw_ctiDescription' => 'CTI - подключение панели телефонии', diff --git a/src/Common/Models/FirewallRules.php b/src/Common/Models/FirewallRules.php index 3f1489a6b..b24574c5d 100644 --- a/src/Common/Models/FirewallRules.php +++ b/src/Common/Models/FirewallRules.php @@ -146,6 +146,19 @@ public static function getDefaultRules(): array 'action' => 'allow', 'shortName' => 'SIP & RTP', ], + 'IAX' => [ + 'rules' => [ + [ + 'portfrom' => $protectedPortSet[PbxSettingsConstants::IAX_PORT], + 'portto' => $protectedPortSet[PbxSettingsConstants::IAX_PORT], + 'protocol' => 'udp', + 'portFromKey' => PbxSettingsConstants::IAX_PORT, + 'portToKey' => PbxSettingsConstants::IAX_PORT, + ] + ], + 'action' => 'allow', + 'shortName' => 'IAX', + ], 'WEB' => [ 'rules' => [ [ @@ -255,6 +268,7 @@ public static function getProtectedPortSet(): array PbxSettingsConstants::WEB_PORT, PbxSettingsConstants::WEB_HTTPS_PORT, PbxSettingsConstants::SSH_PORT, + PbxSettingsConstants::IAX_PORT, ]; $result = []; foreach ($portSet as $portName) { diff --git a/src/Core/Asterisk/Configs/IAXConf.php b/src/Core/Asterisk/Configs/IAXConf.php index c475d2d95..52a1b3bb9 100644 --- a/src/Core/Asterisk/Configs/IAXConf.php +++ b/src/Core/Asterisk/Configs/IAXConf.php @@ -36,9 +36,7 @@ class IAXConf extends AsteriskConfigClass { // The module hook applying priority public int $priority = 600; - public const TYPE_IAX2 = 'IAX2'; - protected string $description = 'iax.conf'; /** @@ -64,9 +62,8 @@ public function extensionGenContexts(): string */ protected function generateConfigProtected(): void { - $conf = ''; - $conf .= $this->generateGeneral(); - $conf .= $this->generateProviders(); + $conf = $this->generateGeneral(); + $conf.= $this->generateProviders(); // Write the configuration content to the file Util::fileWriteContent($this->config->path('asterisk.astetcdir') . '/iax.conf', $conf); @@ -80,17 +77,15 @@ protected function generateConfigProtected(): void */ private function generateGeneral(): string { - $iax_port = (trim($this->generalSettings[PbxSettingsConstants::IAX_PORT]) !== '') ? $this->generalSettings[PbxSettingsConstants::IAX_PORT] : '4569'; - $conf = '[general]' . "\n"; - // $conf .= "context=public-direct-dial \n"; - $conf .= "bindport={$iax_port}\n"; - $conf .= "bindaddr=0.0.0.0\n"; - $conf .= "delayreject=yes\n"; - $conf .= "iaxthreadcount=100\n"; - $conf .= "iaxmaxthreadcount=200\n"; - $conf .= "jitterbuffer=no\n"; - $conf .= "forcejitterbuffer=no\n\n"; - + $iax_port = $this->generalSettings[PbxSettingsConstants::IAX_PORT]; + $conf = '[general]'.PHP_EOL; + $conf .= "bindport=$iax_port".PHP_EOL; + $conf .= "bindaddr=0.0.0.0".PHP_EOL; + $conf .= "delayreject=yes".PHP_EOL; + $conf .= "iaxthreadcount=100".PHP_EOL; + $conf .= "iaxmaxthreadcount=200".PHP_EOL; + $conf .= "jitterbuffer=no".PHP_EOL; + $conf .= "forcejitterbuffer=no".PHP_EOL.PHP_EOL; return $conf; } @@ -107,37 +102,42 @@ private function generateProviders(): string $lang = str_replace('_', '-', strtolower($this->generalSettings[PbxSettingsConstants::PBX_LANGUAGE])); $providers = $this->getProviders(); foreach ($providers as $provider) { - $prov_config .= "[{$provider['uniqid']}];\n"; - $prov_config .= "type=friend\n"; - $prov_config .= "auth=md5\n"; - $prov_config .= "context={$provider['uniqid']}-incoming \n"; - $prov_config .= "language={$lang}\n"; - $prov_config .= "qualify=2000\n"; - $prov_config .= "transfer=mediaonly\n"; - $prov_config .= "disallow=all\n"; - $prov_config .= ";username={$provider['username']}\n"; - $prov_config .= "host=dynamic\n"; - $prov_config .= "trunk=yes\n"; - - $prov_config .= "secret={$provider['secret']}\n"; + $manual_attributes = Util::parseIniSettings(base64_decode($provider['manualattributes'])); + $options = [ + 'type' => 'friend', + 'auth' => 'plaintext', + 'context' => "{$provider['uniqid']}-incoming", + 'language' => $lang, + 'qualify' => 2000, + 'transfer' => 'mediaonly', + 'disallow' => 'all', + 'username' => $provider['username'], + 'trunk' => 'yes', + 'secret' => $provider['secret'], + 'host' => 'dynamic' + ]; + $prov_config .= "[{$provider['uniqid']}];".PHP_EOL; foreach ($provider['codecs'] as $codec) { - $prov_config .= "allow={$codec}\n"; + $prov_config .= "allow=$codec".PHP_EOL; } $prov_config .= "setvar=contextID={$provider['uniqid']}-incoming".PHP_EOL; - $prov_config .= "\n"; + $prov_config .= Util::overrideConfigurationArray($options, $manual_attributes, ' '); + $prov_config .= PHP_EOL; // Formulate the registration string - if ($provider['noregister'] == 0) { + if ($provider['noregister'] === '0') { // Registration is only required if the current host has a dynamic IP - $user = $provider['username']; - $secret = (trim($provider['secret']) == '') ? '' : ":{$provider['secret']}"; - $host = $provider['host']; - $port = ''; - $reg_strings .= "register => {$user}{$secret}@{$host}{$port} \n"; + $user = $options['username']; + $secret = (trim($options['secret']) === '') ? '' : ":{$options['secret']}"; + [$host, $port] = explode( ':',$provider['host']); + if(!empty($port)){ + $port = ":$port"; + } + $reg_strings .= "register => $user$secret@$host$port ".PHP_EOL; } } - return $reg_strings . "\n" . $prov_config; + return $reg_strings .PHP_EOL . $prov_config; } /** @@ -151,26 +151,19 @@ private function getProviders(): array // Получим настройки всех аккаунтов. $arrIaxProviders = Iax::find("disabled IS NULL OR disabled = '0'"); foreach ($arrIaxProviders as $peer) { - /** @var \MikoPBX\Common\Models\Iax $peer */ + /** @var Iax $peer */ $arr_data = $peer->toArray(); - - // $network_filter = NetworkFilters::findFirst($peer->networkfilterid); - // $arr_data['permit'] = ($network_filter==null)?'':$network_filter->permit; - // $arr_data['deny'] = ($network_filter==null)?'':$network_filter->deny; - $arr_data['codecs'] = []; $filter = [ 'conditions' => 'disabled="0"', 'order' => 'type, priority', ]; - $codecs = Codecs::find($filter); + $codecs = Codecs::find($filter); foreach ($codecs as $ob_codec) { $arr_data['codecs'][] = $ob_codec->name; } $data_providers[] = $arr_data; } - return $data_providers; } - } diff --git a/src/Core/System/Upgrade/Releases/UpdateConfigsUpToVer2024v2v10.php b/src/Core/System/Upgrade/Releases/UpdateConfigsUpToVer2024v2v10.php new file mode 100644 index 000000000..8af0480f3 --- /dev/null +++ b/src/Core/System/Upgrade/Releases/UpdateConfigsUpToVer2024v2v10.php @@ -0,0 +1,73 @@ +. + */ + +namespace MikoPBX\Core\System\Upgrade\Releases; + +use MikoPBX\Common\Models\FirewallRules; +use MikoPBX\Common\Models\NetworkFilters; +use MikoPBX\Common\Models\PbxSettings; +use MikoPBX\Common\Models\PbxSettingsConstants; +use MikoPBX\Core\System\Upgrade\UpgradeSystemConfigInterface; +use Phalcon\Di\Injectable; + +class UpdateConfigsUpToVer2024v2v10 extends Injectable implements UpgradeSystemConfigInterface +{ + public const PBX_VERSION = '2024.2.10'; + + /** + * Class constructor. + */ + public function __construct() + { + } + + /** + * https://github.com/mikopbx/Core/issues/782 + */ + public function processUpdate(): void + { + $colName = PbxSettingsConstants::IAX_PORT; + $iax_port = PbxSettings::getValueByKey(PbxSettingsConstants::IAX_PORT); + $nets = NetworkFilters::find(['columns' => 'id']); + foreach ($nets as $net){ + $filter = [ + "portFromKey='$colName' AND networkfilterid='$net->id'", + 'columns' => 'id' + ]; + $rule = FirewallRules::findFirst($filter); + if($rule){ + continue; + } + $rule = new FirewallRules(); + foreach ($rule->toArray() as $key => $value){ + $rule->$key = $value; + } + $rule->networkfilterid = $net->id; + $rule->action = 'block'; + $rule->portfrom = $iax_port; + $rule->portto = $iax_port; + $rule->protocol = 'udp'; + $rule->portFromKey = $colName; + $rule->portToKey = $colName; + $rule->category = 'IAX'; + $rule->save(); + } + } + +} \ No newline at end of file diff --git a/src/Core/System/Util.php b/src/Core/System/Util.php index cd534c1db..7e29d93b1 100644 --- a/src/Core/System/Util.php +++ b/src/Core/System/Util.php @@ -53,7 +53,7 @@ class Util * * @return string The resulting configuration string. */ - public static function overrideConfigurationArray($options, $manual_attributes, $section): string + public static function overrideConfigurationArray(&$options, $manual_attributes, $section): string { $result_config = ''; if ($manual_attributes !== null && isset($manual_attributes[$section])) { @@ -70,9 +70,9 @@ public static function overrideConfigurationArray($options, $manual_attributes, } if (is_array($value)) { array_unshift($value, ' '); - $result_config .= trim(implode("\n{$key} = ", $value)) . "\n"; + $result_config .= trim(implode("\n$key = ", $value)) . "\n"; } else { - $result_config .= "{$key} = {$value}\n"; + $result_config .= "$key = $value\n"; } } @@ -744,30 +744,33 @@ public static function parseIniSettings(string $manual_attributes): array foreach ($sections as $section) { $data_rows = explode("\n", trim($section)); $section_name = trim($data_rows[0] ?? ''); - if (!empty($section_name)) { + if(empty($section_name) || strpos($section_name, '[') === false){ + // Noname section + $section_name = ' '; + }else{ unset($data_rows[0]); - $manual_data[$section_name] = []; - foreach ($data_rows as $row) { - $value = ''; + } + $manual_data[$section_name] = []; + foreach ($data_rows as $row) { + $value = ''; - // Skip rows without an equal sign - if (strpos($row, '=') === false) { - continue; - } - $key = ''; - $arr_value = explode('=', $row); - if (count($arr_value) > 1) { - $key = trim($arr_value[0]); - unset($arr_value[0]); - $value = trim(implode('=', $arr_value)); - } + // Skip rows without an equal sign + if (strpos($row, '=') === false) { + continue; + } + $key = ''; + $arr_value = explode('=', $row); + if (count($arr_value) > 1) { + $key = trim($arr_value[0]); + unset($arr_value[0]); + $value = trim(implode('=', $arr_value)); + } - // Skip rows with empty key or value not equal to '0' - if (($value !== '0' && empty($value)) || empty($key)) { - continue; - } - $manual_data[$section_name][$key] = $value; + // Skip rows with empty key or value not equal to '0' + if (($value !== '0' && empty($value)) || empty($key)) { + continue; } + $manual_data[$section_name][$key] = $value; } } From 44e696f245dd659219ee929d736dbf2cbdad0594 Mon Sep 17 00:00:00 2001 From: boffart <> Date: Wed, 28 Aug 2024 16:50:54 +0300 Subject: [PATCH 55/58] =?UTF-8?q?#779=20=D0=A2=D0=B5=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D1=8C=20=D0=B1=D1=83=D0=B4=D0=B5=D1=82=20=D0=BB=D0=B8=D1=88?= =?UTF-8?q?=D1=8C=20=D0=B4=D0=B2=D0=B5=20=D0=BF=D0=BE=D0=BF=D1=8B=D1=82?= =?UTF-8?q?=D0=BA=D0=B8=20=D0=BF=D0=BE=D0=BB=D1=83=D1=87=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=B0=D0=B4=D1=80=D0=B5=D1=81=D0=B0=20=D1=87=D0=B5?= =?UTF-8?q?=D1=80=D0=B5=D0=B7=20DHCP=20=D1=81=20=D0=B8=D0=BD=D1=82=D0=B5?= =?UTF-8?q?=D1=80=D0=B2=D0=B0=D0=BB=D0=BE=D0=BC=20=D0=B2=202=20=D1=81?= =?UTF-8?q?=D0=B5=D0=BA=D1=83=D0=BD=D0=B4=D1=8B.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/System/Network.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Core/System/Network.php b/src/Core/System/Network.php index f7a832f57..87b877198 100644 --- a/src/Core/System/Network.php +++ b/src/Core/System/Network.php @@ -783,19 +783,17 @@ public function lanConfigure(): int // Obtain IP and wait for the process to finish $workerPath = '/etc/rc/udhcpc_configure'; - $options = '-t 6 -T 5 -q -n'; + $options = '-t 2 -T 2 -q -n'; $arr_commands[] = "$udhcpc $options -i $if_name -x hostname:$hostname -s $workerPath"; // Start a new udhcpc process in the background $options = '-t 6 -T 5 -S -b -n'; $arr_commands[] = "$nohup $udhcpc $options -p {$pid_file} -i $if_name -x hostname:$hostname -s $workerPath 2>&1 &"; /* udhcpc - utility for configuring the interface - - configures /etc/resolv.conf + - configures /etc/resolv.conf Further route configuration will be performed in udhcpcConfigureRenewBound(); - and udhcpcConfigureDeconfig(). These methods will be called by the script WorkerUdhcpcConfigure.php. - // man udhcp + and udhcpcConfigureDeconfig(). These methods will be called by the PHP script udhcpc_configure. // http://pwet.fr/man/linux/administration_systeme/udhcpc/ - */ } else { // Static IP configuration From dfe479afaf9c7e025cc22a06c7b1dd17d88ffca4 Mon Sep 17 00:00:00 2001 From: Weblate Date: Thu, 29 Aug 2024 16:51:20 +0300 Subject: [PATCH 56/58] Translated using Weblate (Hungarian) Currently translated at 99.5% (1239 of 1244 strings) Translated using Weblate (Thai) Currently translated at 100.0% (1244 of 1244 strings) Translated using Weblate (Romanian) Currently translated at 100.0% (1244 of 1244 strings) Translated using Weblate (Dutch) Currently translated at 100.0% (1244 of 1244 strings) Translated using Weblate (Azerbaijani) Currently translated at 100.0% (1244 of 1244 strings) Translated using Weblate (Greek) Currently translated at 100.0% (1244 of 1244 strings) Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (1244 of 1244 strings) Translated using Weblate (Georgian) Currently translated at 100.0% (1244 of 1244 strings) Translated using Weblate (Turkish) Currently translated at 100.0% (1244 of 1244 strings) Translated using Weblate (Swedish) Currently translated at 100.0% (1244 of 1244 strings) Translated using Weblate (Czech) Currently translated at 100.0% (1244 of 1244 strings) Translated using Weblate (Polish) Currently translated at 100.0% (1244 of 1244 strings) Translated using Weblate (Japanese) Currently translated at 100.0% (1244 of 1244 strings) Translated using Weblate (Italian) Currently translated at 100.0% (1244 of 1244 strings) Translated using Weblate (Danish) Currently translated at 100.0% (1244 of 1244 strings) Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (1244 of 1244 strings) Translated using Weblate (Spanish) Currently translated at 100.0% (1244 of 1244 strings) Translated using Weblate (Vietnamese) Currently translated at 100.0% (1244 of 1244 strings) Translated using Weblate (Portuguese) Currently translated at 100.0% (1244 of 1244 strings) Translated using Weblate (French) Currently translated at 100.0% (1244 of 1244 strings) Translated using Weblate (Ukrainian) Currently translated at 100.0% (1244 of 1244 strings) Translated using Weblate (English) Currently translated at 100.0% (1244 of 1244 strings) Translated using Weblate (German) Currently translated at 100.0% (1244 of 1244 strings) Co-authored-by: Anonymous Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/az/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/cs/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/da/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/de/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/el/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/en/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/es/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/fr/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/hu/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/it/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/ja/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/ka/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/nl/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/pl/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/pt/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/pt_BR/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/ro/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/sv/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/th/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/tr/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/uk/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/vi/ Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/zh_Hans/ Translation: MIKOPBX/Core --- src/Common/Messages/az.php | 1 + src/Common/Messages/cs.php | 1 + src/Common/Messages/da.php | 1 + src/Common/Messages/de.php | 1 + src/Common/Messages/el.php | 1 + src/Common/Messages/en.php | 1 + src/Common/Messages/es.php | 1 + src/Common/Messages/fr.php | 1 + src/Common/Messages/hu.php | 1 + src/Common/Messages/it.php | 1 + src/Common/Messages/ja.php | 1 + src/Common/Messages/ka.php | 1 + src/Common/Messages/nl.php | 1 + src/Common/Messages/pl.php | 1 + src/Common/Messages/pt.php | 1 + src/Common/Messages/pt_BR.php | 1 + src/Common/Messages/ro.php | 1 + src/Common/Messages/sv.php | 1 + src/Common/Messages/th.php | 1 + src/Common/Messages/tr.php | 1 + src/Common/Messages/uk.php | 1 + src/Common/Messages/vi.php | 1 + src/Common/Messages/zh_Hans.php | 1 + 23 files changed, 23 insertions(+) diff --git a/src/Common/Messages/az.php b/src/Common/Messages/az.php index 33d6b8421..364cea563 100644 --- a/src/Common/Messages/az.php +++ b/src/Common/Messages/az.php @@ -1281,4 +1281,5 @@ 'nw_PublicSIPPort' => 'SIP port nömrəsi daxili %SIP_PORT% PBX-ə yönləndirildi', 'gs_ErrorSaveSettings' => 'Parametrləri yadda saxlama xətası', 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Göstərilən artırma nömrəsi artıq istifadə olunur', + 'fw_iaxDescription' => 'IAX - telefon qeydiyyatı və səs trafiki', ]; diff --git a/src/Common/Messages/cs.php b/src/Common/Messages/cs.php index e1c497780..3b389fe4e 100644 --- a/src/Common/Messages/cs.php +++ b/src/Common/Messages/cs.php @@ -1282,4 +1282,5 @@ 'nw_PublicTLSPort' => 'Číslo portu SIP TLS přesměrováno na interní %TLS_PORT% PBX', 'gs_ErrorSaveSettings' => 'Při ukládání nastavení došlo k chybě', 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Zadané číslo pobočky se již používá', + 'fw_iaxDescription' => 'IAX - registrace telefonu a hlasový provoz', ]; diff --git a/src/Common/Messages/da.php b/src/Common/Messages/da.php index ad7a1060e..c02097bac 100644 --- a/src/Common/Messages/da.php +++ b/src/Common/Messages/da.php @@ -1282,4 +1282,5 @@ 'nw_NATInfo5' => 'Hvis et eksternt værtsnavn er angivet, vil det blive brugt frem for den eksterne IP-adresse.', 'gs_ErrorSaveSettings' => 'Fejl under lagring af indstillinger', 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Det angivne lokalnummer er allerede i brug', + 'fw_iaxDescription' => 'IAX - telefonregistrering og taletrafik', ]; diff --git a/src/Common/Messages/de.php b/src/Common/Messages/de.php index efd51e7d2..510a62255 100644 --- a/src/Common/Messages/de.php +++ b/src/Common/Messages/de.php @@ -1285,4 +1285,5 @@ 'nw_PublicSIPPort' => 'SIP-Portnummer, die an die interne %SIP_PORT%-PBX weitergeleitet wird', 'gs_ErrorSaveSettings' => 'Fehler beim Speichern der Einstellungen', 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Die angegebene Nebenstellennummer wird bereits verwendet', + 'fw_iaxDescription' => 'IAX – Telefonregistrierung und Sprachverkehr', ]; diff --git a/src/Common/Messages/el.php b/src/Common/Messages/el.php index 517e22994..296335d7d 100644 --- a/src/Common/Messages/el.php +++ b/src/Common/Messages/el.php @@ -1282,4 +1282,5 @@ 'nw_PublicTLSPort' => 'Ο αριθμός θύρας SIP TLS προωθείται στο εσωτερικό PBX %TLS_PORT%', 'gs_ErrorSaveSettings' => 'Σφάλμα αποθήκευσης ρυθμίσεων', 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Ο καθορισμένος αριθμός επέκτασης χρησιμοποιείται ήδη', + 'fw_iaxDescription' => 'IAX - εγγραφή τηλεφώνου και φωνητική κίνηση', ]; diff --git a/src/Common/Messages/en.php b/src/Common/Messages/en.php index 77a589267..eb349cdbd 100644 --- a/src/Common/Messages/en.php +++ b/src/Common/Messages/en.php @@ -1285,4 +1285,5 @@ 'nw_PublicTLSPort' => 'SIP TLS port number forwarded to internal %TLS_PORT% PBX', 'gs_ErrorSaveSettings' => 'Error saving settings', 'mo_ThisNumberNotUniqueForExtensionsModels' => 'The specified extension number is already in use', + 'fw_iaxDescription' => 'IAX - Phone Registration and Voice Traffic', ]; diff --git a/src/Common/Messages/es.php b/src/Common/Messages/es.php index 7cf505b6f..9ed41544b 100644 --- a/src/Common/Messages/es.php +++ b/src/Common/Messages/es.php @@ -1282,4 +1282,5 @@ 'nw_PublicTLSPort' => 'Número de puerto SIP TLS reenviado al PBX interno %TLS_PORT%', 'gs_ErrorSaveSettings' => 'Error al guardar la configuración', 'mo_ThisNumberNotUniqueForExtensionsModels' => 'El número de extensión especificado ya está en uso', + 'fw_iaxDescription' => 'IAX: registro telefónico y tráfico de voz', ]; diff --git a/src/Common/Messages/fr.php b/src/Common/Messages/fr.php index 9091997f0..29ab2694b 100644 --- a/src/Common/Messages/fr.php +++ b/src/Common/Messages/fr.php @@ -1282,4 +1282,5 @@ 'nw_NATInfo4' => '%RTP_PORT_FROM%-%RTP_PORT_TO%UDP', 'gs_ErrorSaveSettings' => 'Erreur lors de l\'enregistrement des paramètres', 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Le numéro de poste spécifié est déjà utilisé', + 'fw_iaxDescription' => 'IAX - enregistrement téléphonique et trafic vocal', ]; diff --git a/src/Common/Messages/hu.php b/src/Common/Messages/hu.php index baea2c8b9..11d77cd76 100644 --- a/src/Common/Messages/hu.php +++ b/src/Common/Messages/hu.php @@ -1233,4 +1233,5 @@ 'adv_SSHPasswordMismatchFilesHash' => 'A MikoPBX SSH jelszó eltér a konfigurációs fájlban beállítotttól. Lehetséges, hogy manuálisan módosították a MikoPBX konzolról.', 'adv_ThereIsSomeTroublesWithMikoPBX' => 'Figyelem! Problémákat észleltünk a MikoPBX-ben!', 'lic_MarketplaceText' => 'A Marketplace-en történő regisztrációval további modulokhoz és bővítményekhez férhet hozzá.
      Vannak ingyenes modulok, amelyeket eltávolítottunk az alapfunkciók közül a kezdeti beállítás egyszerűsítése érdekében, valamint fizetős modulok tőlünk és más fejlesztőktől.
      Ha Ön Ha Ön fejlesztő, akkor vegye fel velünk a kapcsolatot, ha útmutatást szeretne kapni saját modulja fejlesztésével és a piactérhez való hozzáadásával kapcsolatban.', + 'fw_iaxDescription' => 'IAX - telefon regisztráció és hangforgalom', ]; diff --git a/src/Common/Messages/it.php b/src/Common/Messages/it.php index e526eac53..2c2a1c666 100644 --- a/src/Common/Messages/it.php +++ b/src/Common/Messages/it.php @@ -1282,4 +1282,5 @@ 'nw_PublicTLSPort' => 'Numero di porta SIP TLS inoltrato al PBX interno %TLS_PORT%.', 'gs_ErrorSaveSettings' => 'Errore durante il salvataggio delle impostazioni', 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Il numero di interno specificato è già in uso', + 'fw_iaxDescription' => 'IAX - registrazione telefonica e traffico vocale', ]; diff --git a/src/Common/Messages/ja.php b/src/Common/Messages/ja.php index b626ff3b6..c26a15dc1 100644 --- a/src/Common/Messages/ja.php +++ b/src/Common/Messages/ja.php @@ -1282,4 +1282,5 @@ 'nw_PublicTLSPort' => '内部 %TLS_PORT% PBX に転送される SIP TLS ポート番号', 'mo_ThisNumberNotUniqueForExtensionsModels' => '指定された内線番号はすでに使用されています', 'gs_ErrorSaveSettings' => '設定の保存中にエラーが発生しました', + 'fw_iaxDescription' => 'IAX - 電話の登録と音声トラフィック', ]; diff --git a/src/Common/Messages/ka.php b/src/Common/Messages/ka.php index dfb0673ac..5d82d2f72 100644 --- a/src/Common/Messages/ka.php +++ b/src/Common/Messages/ka.php @@ -1282,4 +1282,5 @@ 'nw_PublicSIPPort' => 'SIP პორტის ნომერი გადაგზავნილია შიდა %SIP_PORT% PBX-ში', 'gs_ErrorSaveSettings' => 'შეცდომა პარამეტრების შენახვისას', 'mo_ThisNumberNotUniqueForExtensionsModels' => 'მითითებული გაფართოების ნომერი უკვე გამოიყენება', + 'fw_iaxDescription' => 'IAX - ტელეფონის რეგისტრაცია და ხმოვანი ტრაფიკი', ]; diff --git a/src/Common/Messages/nl.php b/src/Common/Messages/nl.php index 8215594f5..8ab11f1fc 100644 --- a/src/Common/Messages/nl.php +++ b/src/Common/Messages/nl.php @@ -1281,4 +1281,5 @@ 'nw_PublicTLSPort' => 'SIP TLS-poortnummer doorgestuurd naar interne %TLS_PORT% PBX', 'gs_ErrorSaveSettings' => 'Fout bij opslaan van instellingen', 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Het opgegeven toestelnummer is al in gebruik', + 'fw_iaxDescription' => 'IAX - telefoonregistratie en spraakverkeer', ]; diff --git a/src/Common/Messages/pl.php b/src/Common/Messages/pl.php index d12375291..b45a7a029 100644 --- a/src/Common/Messages/pl.php +++ b/src/Common/Messages/pl.php @@ -1282,4 +1282,5 @@ 'nw_PublicTLSPort' => 'Numer portu SIP TLS przekazywany do wewnętrznej centrali %TLS_PORT% PBX', 'gs_ErrorSaveSettings' => 'Błąd podczas zapisywania ustawień', 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Podany numer wewnętrzny jest już zajęty', + 'fw_iaxDescription' => 'IAX - rejestracja telefonu i ruch głosowy', ]; diff --git a/src/Common/Messages/pt.php b/src/Common/Messages/pt.php index 01fff494f..0a4bfedd8 100644 --- a/src/Common/Messages/pt.php +++ b/src/Common/Messages/pt.php @@ -1282,4 +1282,5 @@ 'nw_PublicTLSPort' => 'Número da porta SIP TLS encaminhado para PBX interno %TLS_PORT%', 'gs_ErrorSaveSettings' => 'Erro ao salvar as configurações', 'mo_ThisNumberNotUniqueForExtensionsModels' => 'O número de ramal especificado já está em uso', + 'fw_iaxDescription' => 'IAX - registro telefônico e tráfego de voz', ]; diff --git a/src/Common/Messages/pt_BR.php b/src/Common/Messages/pt_BR.php index 6062ca170..750b112cf 100644 --- a/src/Common/Messages/pt_BR.php +++ b/src/Common/Messages/pt_BR.php @@ -1281,4 +1281,5 @@ 'nw_PublicSIPPort' => 'Número da porta SIP encaminhado para PBX interno %SIP_PORT%', 'gs_ErrorSaveSettings' => 'Erro ao salvar as configurações', 'mo_ThisNumberNotUniqueForExtensionsModels' => 'O número de ramal especificado já está em uso', + 'fw_iaxDescription' => 'IAX - registro telefônico e tráfego de voz', ]; diff --git a/src/Common/Messages/ro.php b/src/Common/Messages/ro.php index 77963fed8..4cdad68eb 100644 --- a/src/Common/Messages/ro.php +++ b/src/Common/Messages/ro.php @@ -1264,4 +1264,5 @@ 'nw_PublicTLSPort' => 'Numărul portului SIP TLS redirecționat către centrala internă %TLS_PORT%.', 'gs_ErrorSaveSettings' => 'Eroare la salvarea setărilor', 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Numărul de extensie specificat este deja în uz', + 'fw_iaxDescription' => 'IAX - înregistrare telefonică și trafic vocal', ]; diff --git a/src/Common/Messages/sv.php b/src/Common/Messages/sv.php index 764d4656a..0fdca01ee 100644 --- a/src/Common/Messages/sv.php +++ b/src/Common/Messages/sv.php @@ -1248,4 +1248,5 @@ 'nw_PublicTLSPort' => 'SIP TLS-portnummer vidarebefordrat till intern %TLS_PORT% PBX', 'gs_ErrorSaveSettings' => 'Det gick inte att spara inställningar', 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Det angivna anknytningsnumret används redan', + 'fw_iaxDescription' => 'IAX - telefonregistrering och rösttrafik', ]; diff --git a/src/Common/Messages/th.php b/src/Common/Messages/th.php index adee96048..d1a070e8d 100644 --- a/src/Common/Messages/th.php +++ b/src/Common/Messages/th.php @@ -1246,4 +1246,5 @@ 'nw_NATInfo2' => 'หากไม่ได้ใช้ NAT 1:1 ให้เปลี่ยนเส้นทางพอร์ตต่อไปนี้จาก IP สาธารณะไปยังที่อยู่ IP ภายในของ PBX ในการตั้งค่าเราเตอร์ของคุณ', 'gs_ErrorSaveSettings' => 'เกิดข้อผิดพลาดในการบันทึกการตั้งค่า', 'mo_ThisNumberNotUniqueForExtensionsModels' => 'หมายเลขต่อขยายที่ระบุมีการใช้งานแล้ว', + 'fw_iaxDescription' => 'IAX - การลงทะเบียนโทรศัพท์และการรับส่งข้อมูลด้วยเสียง', ]; diff --git a/src/Common/Messages/tr.php b/src/Common/Messages/tr.php index c3fd6c8a1..444548ce6 100644 --- a/src/Common/Messages/tr.php +++ b/src/Common/Messages/tr.php @@ -1248,4 +1248,5 @@ 'nw_PublicSIPPort' => 'Dahili %SIP_PORT% PBX\'e iletilen SIP bağlantı noktası numarası', 'gs_ErrorSaveSettings' => 'Ayarlar kaydedilirken hata oluştu', 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Belirtilen dahili numara zaten kullanımda', + 'fw_iaxDescription' => 'IAX - telefon kaydı ve ses trafiği', ]; diff --git a/src/Common/Messages/uk.php b/src/Common/Messages/uk.php index 74e774788..c20e25432 100644 --- a/src/Common/Messages/uk.php +++ b/src/Common/Messages/uk.php @@ -1282,4 +1282,5 @@ 'nw_PublicTLSPort' => 'Номер порту SIP TLS перенаправленого на внутрішній %TLS_PORT% PBX', 'gs_ErrorSaveSettings' => 'Помилка збереження налаштувань', 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Вказаний внутрішній номер вже використовується', + 'fw_iaxDescription' => 'IAX - реєстрація телефонів та голосовий трафік', ]; diff --git a/src/Common/Messages/vi.php b/src/Common/Messages/vi.php index f3de3c885..55f43da31 100644 --- a/src/Common/Messages/vi.php +++ b/src/Common/Messages/vi.php @@ -1248,4 +1248,5 @@ 'nw_NATInfo6OR' => 'HOẶC', 'gs_ErrorSaveSettings' => 'Lỗi lưu cài đặt', 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Số máy nhánh được chỉ định đã được sử dụng', + 'fw_iaxDescription' => 'IAX - đăng ký điện thoại và lưu lượng thoại', ]; diff --git a/src/Common/Messages/zh_Hans.php b/src/Common/Messages/zh_Hans.php index b529d5daf..55268c19b 100644 --- a/src/Common/Messages/zh_Hans.php +++ b/src/Common/Messages/zh_Hans.php @@ -1248,4 +1248,5 @@ 'nw_PublicTLSPort' => '转发到内部 %TLS_PORT% PBX 的 SIP TLS 端口号', 'gs_ErrorSaveSettings' => '保存设置时出错', 'mo_ThisNumberNotUniqueForExtensionsModels' => '指定的分机号码已被使用', + 'fw_iaxDescription' => 'IAX-电话注册和语音流量', ]; From e0e506fade6ff2c912b1ec69b33b3af042f6f341 Mon Sep 17 00:00:00 2001 From: Weblate Date: Fri, 6 Sep 2024 07:00:19 +0300 Subject: [PATCH 57/58] Added translation using Weblate (Finnish) Co-authored-by: Sakara Group --- src/Common/Messages/fi.php | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/Common/Messages/fi.php diff --git a/src/Common/Messages/fi.php b/src/Common/Messages/fi.php new file mode 100644 index 000000000..b3d9bbc7f --- /dev/null +++ b/src/Common/Messages/fi.php @@ -0,0 +1 @@ + Date: Sat, 7 Sep 2024 07:51:18 +0300 Subject: [PATCH 58/58] Translated using Weblate (Finnish) Currently translated at 100.0% (1244 of 1244 strings) Co-authored-by: Anonymous Translate-URL: https://weblate.mikopbx.com/projects/mikopbx/admin-web-interface/fi/ Translation: MIKOPBX/Core --- src/Common/Messages/fi.php | 1236 ++++++++++++++++++++++++++++++++++++ 1 file changed, 1236 insertions(+) diff --git a/src/Common/Messages/fi.php b/src/Common/Messages/fi.php index b3d9bbc7f..79c451197 100644 --- a/src/Common/Messages/fi.php +++ b/src/Common/Messages/fi.php @@ -1 +1,1237 @@ 'Palomuurin määrittäminen', + 'BreadcrumbFirewallmodify' => 'Säännön määrittäminen', + 'SubHeaderFirewall' => 'Aseman pääsyn rajoittaminen liikennetyypin ja aliverkkojen mukaan', + 'BreadcrumbGeneralSettings' => 'Järjestelmäasetukset', + 'SubHeaderIvrMenu' => 'Saapuvien puhelujen reititysmallin ja asetusten määrittäminen', + 'BreadcrumbDialplanApplications' => 'Dialplan-sovellukset', + 'BreadcrumbDialplanApplicationsmodify' => 'Sovelluksen määrittäminen', + 'SubHeaderDialplanApplications' => 'Ohjelmoitavat puhesovellukset PHP:ssä ja Asterisk Dialplanissa', + 'BreadcrumbConferenceRooms' => 'Konferenssit', + 'SubHeaderConferenceRooms' => 'Huoneiden perustaminen usean osapuolen äänikonferensseja varten', + 'BreadcrumbConferenceRoomsmodify' => 'Asetusvaihtoehdot', + 'BreadcrumbCallDetailRecords' => 'Puheluhistoria', + 'SubHeaderCallDetailRecords' => 'Keskusteluloki ja puheluloki', + 'BreadcrumbCustomFilesmodify' => 'Muokkaus', + 'BreadcrumbCustomFiles' => 'Järjestelmätiedostot', + 'SubHeaderCustomFiles' => 'Järjestelmän ja Asterisk-määritystiedostojen mukauttaminen', + 'BreadcrumbSoundFiles' => 'Äänitiedostot', + 'SubHeaderSoundFiles' => 'Käytetään erilaisissa puheluskenaarioissa ja interaktiivisissa äänivalikoissa', + 'BreadcrumbLicensing' => 'Lisensointi', + 'SubHeaderLicensing' => 'Rekisteröidy Marketplacessa saadaksesi uusia laajennuksia ja moduuleja', + 'BreadcrumbErrors' => 'Virheilmoitus', + 'SubHeaderErrors' => 'Jos tämä virhe on toistettavissa, ota yhteyttä kehittäjään.', + 'BreadcrumbRestart' => 'Käynnistä järjestelmä uudelleen', + 'BreadcrumbRestartmanage' => 'Käynnistä järjestelmä uudelleen', + 'SubHeaderRestart' => 'Moduulien uudelleenkäynnistys, täydellinen uudelleenkäynnistys tai sammutus', + 'BreadcrumbSession' => 'Valtuutus', + 'BreadcrumbSessionend' => 'Valtuutus', + 'BreadcrumbSystemDiagnostic' => 'Järjestelmän diagnostiikka', + 'SubHeaderSystemDiagnostic' => 'Järjestelmälokien kokoelma MikoPBX-toiminnan virheiden yksityiskohtaista analysointia varten', + 'BreadcrumbFail2Ban' => 'Hakkerointisuojaus', + 'SubHeaderFail2Ban' => 'Automaattinen esto, kun salasanat valitaan', + 'BreadcrumbUpdate' => 'Järjestelmän päivitys', + 'SubHeaderUpdate' => 'Virheenkorjauksia, suorituskyvyn parannuksia, uusia toimintoja', + 'BreadcrumbPbxExtensionModules' => 'Moduulien ja laajennusten hallinta MikoPBX:lle', + 'SubHeaderPbxExtensionModules' => 'Lataa omasi tai lataa moduuleja markkinapaikaltamme', + 'mm_Setup' => 'Puhelimet', + 'mm_Extensions' => 'Työntekijät', + 'mm_CallQueues' => 'Puhelujonot', + 'mm_DialplanApplications' => 'Dialplan-sovellukset', + 'mm_Routing' => 'Reititys', + 'mm_Providers' => 'Puhelinpalvelujen tarjoajat', + 'mm_IncomingRoutes' => 'Saapuvat reitit', + 'mm_OutboundRoutes' => 'Lähtevät reitit', + 'mm_OutOffWorkTime' => 'Vapaat työajat', + 'mm_System' => 'Järjestelmä', + 'mm_GeneralSettings' => 'Yleiset asetukset', + 'mm_TimeSettings' => 'Päivämäärä ja aika', + 'mm_Network' => 'Verkkoliitännät', + 'mm_Firewall' => 'Palomuuri', + 'mm_MailSettings' => 'Posti ja ilmoitukset', + 'mm_AsteriskManagers' => 'Pääsy AMI:hen', + 'mm_IvrMenu' => 'IVR-valikko', + 'mm_ConferenceRooms' => 'Konferenssit', + 'mm_CallDetailRecords' => 'Puheluhistoria', + 'mm_CustomFiles' => 'Järjestelmätiedostojen mukauttaminen', + 'mm_SoundFiles' => 'Äänitiedostot', + 'mm_Restart' => 'Käynnistä uudelleen', + 'mm_PbxExtensionModules' => 'Moduulit', + 'mm_Maintenance' => 'Palvelu', + 'mm_Logout' => 'Poistu', + 'mm_SystemDiagnostic' => 'Järjestelmälokit', + 'mm_Fail2Ban' => 'Hakkerointisuojaus', + 'mm_Update' => 'PBX-päivitys', + 'mm_ModuleManager' => 'Moduulien markkinapaikka', + 'mm_SSHConsole' => 'SSH-konsoli', + 'mm_Integrations' => 'Integraatiot', + 'bt_Edit' => 'Muuttaa', + 'bt_Clear' => 'Selkeä', + 'bt_Delete' => 'Poistaa', + 'bt_SaveSettings' => 'Tallentaa', + 'bt_SaveSettingsAndAddNew' => 'Tallenna ja lisää', + 'bt_SaveSettingsAndExit' => 'Tallenna ja sulje', + 'bt_ApplyChangesToPBX' => 'Ota muutokset käyttöön', + 'bt_BackToList' => 'Takaisin luetteloon', + 'bt_Back' => 'Takaisin', + 'bt_ToolTipCopyPassword' => 'Salasana kopioitu leikepöydälle', + 'bt_ToolTipEdit' => 'Muuttaa', + 'pr_ProviderName' => 'Palveluntarjoajan nimi', + 'pr_ProviderLogin' => 'Kirjaudu sisään', + 'pr_ProviderPassword' => 'Salasana', + 'pr_ProviderHostOrIPAddress' => 'Isäntä tai IP-osoite', + 'pr_DTMFMode' => 'DTMF-tila', + 'pr_RegistrationSettings' => 'Rekisteröintiasetukset', + 'pr_RedefinitionFromUser' => 'SIP-otsikon "From" uudelleenmäärittely', + 'pr_FromUser_v2' => 'Käyttäjä', + 'pr_ValidationProviderNameIsEmpty' => 'Anna palveluntarjoajan nimi', + 'pr_ValidationProviderHostIsEmpty' => 'Anna palvelimen nimi tai palveluntarjoajan IP-osoite', + 'pr_ValidationProviderLoginIsEmpty' => 'Anna kirjautumistunnuksesi valtuuttaaksesi palveluntarjoajan kanssa', + 'pr_ValidationProviderLoginNotSingleSimbol' => 'Kirjautumisen tulee olla pidempi kuin yksi merkki', + 'pr_DisableFromUser' => 'Poista käyttäjäkentän käyttö käytöstä', + 'pr_NoRegister' => 'Poista rekisteröinti käytöstä', + 'pr_ManualAdditionalAtributes' => 'Lisävaihtoehdot', + 'pr_UpdateStatus' => 'Tilan päivitys', + 'pr_Online' => 'Yhteys muodostettu', + 'pr_Offline' => 'Ei käytössä', + 'pr_WithoutRegistration' => 'Rekisteröinti poistettu käytöstä', + 'pr_TableColumnProviderLogin' => 'Kirjaudu sisään', + 'pr_TableColumnProviderHostName' => 'Isäntä', + 'pr_TableColumnProviderType' => 'Tyyppi', + 'pr_TableColumnProviderName' => 'Palveluntarjoaja', + 'pr_TableColumnProviderStatus' => 'Status', + 'pr_ValidateRTPOutOfRange' => 'RTP-porttien alue on väärä. Arvojen on oltava välillä {ruleValue}', + 'pr_RTPPortRange' => 'RTP-porttialue', + 'pr_RTPPortFrom' => 'KANSSA', + 'pr_RTPPortTo' => 'Tekijä:', + 'pr_Note' => 'Huomautus tai hyödyllistä tietoa palveluntarjoajasta', + 'gs_RTPStunServer' => 'STUN-palvelimen osoite (esimerkki: stun.test.net:10000)', + 'gs_UseWebRTC' => 'Käytä WebRTC:tä', + 'gs_Store1MonthOfRecords' => '1 kuukausi', + 'gs_Store3MonthsOfRecords' => '3 kuukautta', + 'gs_Store6MonthsOfRecords' => '6 kuukautta', + 'gs_Store1YearOfRecords' => '1 vuosi', + 'gs_Store3YearsOfRecords' => '3 vuotta', + 'gs_PBXRecordSavePeriodLabel' => 'Puhelutallenteiden säilytysaika', + 'gs_StoreAllPossibleRecords' => '∞', + 'gs_DisableAllModules' => 'Poista markkinapaikka käytöstä', + 'gs_ErrorSaveSettings' => 'Virhe asetusten tallentamisessa', + 'mo_ThisNumberNotUniqueForExtensionsModels' => 'Määritetty alanumero on jo käytössä', + 'pr_AddSIPProvider' => 'Yhdistä SIP', + 'pr_AddIAXProvider' => 'Yhdistä IAX', + 'pr_QualifyInstructionsIAX' => 'Kun tämä vaihtoehto on käytössä, Asterisk lähettää SIP-asetukset-paketteja. Tämä on tarpeen NAT-tunneloinnin tukemiseksi reitittimessäsi.', + 'pr_CustomFieldsDescriptions' => 'Useimmissa tapauksissa ohituskentät tulee jättää tyhjiksi. + Vain jos puhelut eivät toimi sinulle ja palveluntarjoaja vaatii erityisiä asetuksia, nämä kentät on täytettävä palveluntarjoajan suositusten mukaisesti.', + 'pr_ReceiveCallsWithoutAuth' => 'Vastaanota puheluita ilman todennusta', + 'pr_ValidationProviderPortRange' => 'Palveluntarjoajan portin on oltava alueella {ruleValue}', + 'pr_DeleteTitle' => 'Palveluntarjoajan poistaminen', + 'pr_DeleteDescription' => 'Yhdessä palveluntarjoajan kanssa kaikki siihen liittyvät lähtevän liikenteen reitityssäännöt poistetaan, ja saapuvan liikenteen reitityssäännöissä kaikki linkit korvataan sanoilla "Kaikki toimittajat".', + 'pr_DeleteDescription_v2' => 'Yhdessä palveluntarjoajan kanssa kaikki siihen liittyvät lähtevän liikenteen reitityssäännöt poistetaan, ja saapuvien reitityssäännöissä kaikki linkit korvataan tekstillä "Ei yhteyttä palveluntarjoajaan, ei valtuutusta".', + 'pr_Delete' => 'Poistaa', + 'pr_EnterHostOrIp' => 'Palveluntarjoajan lisäosoitteet', + 'pr_EnterHostOrIpPlaceholder' => 'Anna IP-osoite tai aliverkko ja paina Enter', + 'pr_NoAnyAdditionalHosts' => 'Tälle palveluntarjoajalle ei ole määritetty muita osoitteita', + 'or_RuleName' => 'Säännön nimi', + 'or_Note' => 'Huom', + 'or_PatternToMatch' => 'Sääntö toimii, jos', + 'or_NumberBeginsWithTheDigits' => 'Numero alkaa kirjaimella', + 'or_TheRestOfTheNumberMustBe' => 'Loput numerosta koostuu määritetystä määrästä numeroita', + 'or_ReformatNumber' => 'Muunna numero', + 'or_BeforeConnectingTheCallTrim' => 'Ennen kuin aloitamme puhelun, lopetimme', + 'or_digitsFromTheFrontAndThenPrependTheDigits' => 'numerot luvun alussa ja lisää sitten alkuun', + 'or_CallThrough' => 'Suora puhelu', + 'or_Provider' => 'palveluntarjoajan kautta', + 'or_ValidationPleaseEnterRuleName' => 'Anna säännön nimi', + 'or_ValidateBeginPattern' => 'Virhe numerosuodatinkentässä. Se voi sisältää numeroita ja merkkejä :)|', + 'or_ValidateRestNumbers' => 'Numeron vähimmäispituuden on oltava suurempi kuin 2', + 'or_ValidateTrimFromBegin' => 'Väärä arvo numeron alussa olevien merkkien katkaisulle', + 'or_ValidatePrepend' => 'Virhe lisättäessä luvun alkuun. Kenttä voi sisältää numeroita ja merkkejä: * # +. Arvon enimmäispituus on 20 merkkiä.', + 'or_AddNewRule' => 'Lisää uusi sääntö', + 'or_TableColumnName' => 'Nimi', + 'or_TableColumnRule' => 'Sääntö', + 'or_TableColumnProvider' => 'Palveluntarjoaja', + 'or_RuleDescriptionFullMatch' => 'Vain numerolle %numberbeginswith%', + 'or_RuleDescriptionBeginMatch' => 'Minkä tahansa pituisille numeroille, jotka alkavat %numberbeginswith%', + 'or_TableColumnNote' => 'Huom', + 'or_ValidationPleaseSelectProvider' => 'Valitse palveluntarjoaja, jota tämä sääntö koskee.', + 'ir_Provider' => 'Palveluntarjoaja', + 'ir_RuleName' => 'Säännön nimi', + 'or_RuleDescription' => '%numberbeginswith% alussa ja sitten %restnumbers% numeroa', + 'or_RuleDescriptionBeginEmpty' => 'Numero koostuu %restnumbers% numeroista', + 'or_RuleNotConfigured' => 'Sääntöä ei ole määritetty', + 'ir_Note' => 'Huom', + 'ir_TableColumnNote' => 'Huom', + 'ir_TableColumnName' => 'Nimi', + 'ir_TableColumnDetails' => 'Sääntö', + 'ir_RuleDescriptionWithNumberAndWithProvider' => 'Puhelu numeroon %number%   %provider% kautta siirretään numeroon   %callerid%', + 'ir_RuleDescriptionWithoutNumber' => 'Puhelu   %provider% kautta siirretään osoitteeseen   %callerid%', + 'ir_RuleDescriptionWithoutProvider' => 'Puhelu numeroon %number% siirretään numeroon   %callerid%', + 'ir_RuleDescriptionWithoutNumberAndWithoutProvider' => 'Minkä tahansa palveluntarjoajan kautta tuleva puhelu siirretään osoitteeseen   %callerid%', + 'ir_DefaultRoute' => 'Oletustuloreitti', + 'ir_ActionSelect' => 'Jos mikään säännöistä ei vastaa', + 'ir_busy_signal' => 'Toista varattu-ääni', + 'ir_hangup' => 'Katkaise puhelu', + 'ir_extension' => 'Siirrä puhelu', + 'ir_playback' => 'Toista mediatiedosto', + 'ir_ExtensionSelect' => 'Numeroon', + 'ir_RuleAssignIf' => 'Sääntö toimii soitettaessa', + 'ir_DidNumber' => 'Lisänumero (DID)', + 'ir_CallTransferTo' => 'Puhelu siirretään osoitteeseen', + 'ir_Extension' => 'määrä', + 'ir_ValidateForwardingToBeFilled' => 'Edelleenlähetysnumeroa ei ole määritetty', + 'ir_ValidateForwardingDefaultToBeFilled' => 'Oletussoitonsiirtonumeroa ei ole määritetty', + 'ir_ValidationPleaseEnterRuleName' => 'Anna säännön nimi', + 'ir_ValidateTimeoutOutOfRange' => 'Uudelleenohjauksen aikakatkaisu on määritetty väärin. Sen pitäisi olla välillä {ruleValue}', + 'ir_DidNumberDescription' => 'Palveluntarjoaja voi välittää lisänumeron, tämä on valinnainen kenttä, mutta joissakin tapauksissa se voi reitittää puhelut tarkemmin.', + 'ir_TimeoutToTransferDefault' => 'Aika sekunneissa, jonka jälkeen puhelu reititetään seuraavaan prioriteettisääntöön', + 'ir_AddNewRule' => 'Lisää uusi sääntö', + 'ir_AnyProvider' => 'Mikä tahansa palveluntarjoaja', + 'ir_AnyProvider_v2' => 'Ei yhteyttä palveluntarjoajaan, ei valtuutusta', + 'cq_Extension' => 'Jonon numero', + 'cq_Name' => 'Jonon nimi', + 'cq_Note' => 'Huom', + 'cq_Description' => 'Huom', + 'cq_AddNewQueue' => 'Luo uusi jono', + 'cq_StaticAgents' => 'Osallistujat', + 'cq_QueueMembersColumnName' => 'Operaattori', + 'cq_QueueMembersColumnExtension' => 'Määrä', + 'cq_ringall' => 'Puhelu saapuu samanaikaisesti kaikille jonossa oleville osallistujille, mukaan lukien varatut (oletusarvoisesti)', + 'cq_leastrecent' => 'Puhelu saapuu jonon jäsenelle, joka ei ole saanut puheluita pisimpään aikaan', + 'cq_fewestcalls' => 'Puhelu menee jonon jäsenelle, joka on käsitellyt vähiten puheluita ', + 'cq_random' => 'Puhelu saapuu kenelle tahansa jonossa olevalle vapaalle osallistujalle', + 'cq_rrmemory' => 'Puhelu saapuu kenelle tahansa jonossa olevalle vapaalle osallistujalle paitsi osallistujalle, joka käsitteli viimeisen puhelun', + 'cq_linear' => 'Kutsu saapuu jokaiselle jonoon osallistujalle järjestyksessä', + 'cd_Extensions' => 'Tämän jonon puhelinnumero', + 'cq_QueueStrategy' => 'Soittostrategia operaattoreille', + 'cd_Description' => 'Kommentti', + 'cq_QueueMembers' => 'Jonooperaattorit', + 'cq_SelectAgentForAddToQueue' => 'Valitse nykyiseen jonoon lisättävä työntekijä', + 'cq_AddQueueMembers' => 'Ei valittuja operaattoreita', + 'cq_QueueMemberSettings' => 'Operaattoreiden jonoasetukset', + 'cq_SecRingToEachMembers' => 'Soittoyritysten aika operaattoreille', + 'cq_WrapupTime' => 'Operaattorin lepoaika puhelun käsittelyn jälkeen ennen uusien puheluiden vastaanottamista', + 'cq_ReciveCallWhileOnCall' => 'Vastaanota uusia puheluita puhelun aikana', + 'cq_QueueCallerSettings' => 'Soittajajonon asetukset', + 'cq_CallerHearOnQueued' => 'Mitä tilaaja kuulee odottaessaan', + 'cq_ringing' => 'Soittoäänet', + 'cq_moh' => 'Musiikki', + 'cq_AnnoncePosition' => 'Ilmoita nykyisestä sijainnista jonossa', + 'cq_AnnonceHoldTime' => 'Ilmoita arvioidusta odotusajasta', + 'cq_PereodicAnonceSoundFile' => 'Mainoslause tai lisäilmoitus', + 'cq_PereodicAnonceMohSoundFile' => 'Taustamusiikki (MOH)', + 'gs_SSHDisablePasswordLogins' => 'Poista salasanatodennus käytöstä', + 'cq_PereodicAnonceFrequency' => 'Aika sekunteina toistaa säännöllisesti kaikki hälytykset', + 'cq_CallRouting' => 'Puhelun reititys vikojen aikana', + 'cq_ScenaryOne' => 'Skenaario #1', + 'cq_ScenaryTwo' => 'Skenaario #2', + 'cq_ScenaryThree' => 'Skenaario #3', + 'cq_ScenaryFour' => 'Skenaario #4', + 'cq_IfQueueNotAnsweredFor' => 'Jos tilaaja odottaa jonossa yli ', + 'cq_SecondsCallWillBeRoutedTo' => ' sekuntia, siirrä puhelu numeroon ', + 'cq_RedirectToExtensionIfEmtyQueue' => 'Jos jonossa ei ole operaattoreita, siirrä puhelu numeroon ', + 'cq_IfQueueNotAnsweredNumberCalls' => 'Jos kukaan operaattori ei vastaa puheluun sisällä ', + 'cq_ImpossibleToDeleteCallQueue' => 'Puhelujonon poistaminen on mahdotonta, koska siellä on seuraavat linkit', + 'dt_Info' => 'Merkinnät _START_–_END_ alkaen _TOTAL_', + 'dt_InfoEmpty' => 'Valintakriteerit täyttäviä tietueita ei ole', + 'dt_InfoFiltered' => '(valittu _MAX_ tietueesta)', + 'dt_Previous' => 'Edellinen', + 'dt_Next' => 'Seuraavaksi', + 'dt_Search' => 'Haku', + 'dt_TableIsEmpty' => 'Ei näytettävää dataa', + 'ml_EmailNotSended' => 'Viestiä ei lähetetty', + 'ml_EmailSendedSuccess' => 'Kirje lähetetty', + 'ml_EmailTestSubject' => 'Testaa sähköposti puhelinjärjestelmästäsi', + 'ml_EmailTestBody' => 'Hei, jos sinulla on tämä kirje postissasi, asetukset ovat oikein.', + 'er_Unauthorized' => 'Valtuutusvirhe', + 'er_InternalServerErrorDescription' => 'Jotain meni pieleen. Tällaisia virheitä ei pitäisi olla.', + 'ex_enableRecording' => 'Salli', + 'ex_ThisUserIdNotExistInUsersModel' => 'Tätä käyttäjää ei ole olemassa', + 'ex_ThisNumberNotExistInSipModel' => 'Tällä numerolla ei ole vastaavia SIP-asetuksia', + 'ex_NoNetworkFilter' => 'Yhteydet mistä tahansa osoitteesta ovat sallittuja', + 'ex_PermitNetwork' => 'Sallittu verkko', + 'ex_DenyNetwork' => 'Kielletty verkko', + 'ex_GeneralSettings' => 'Perusparametrit', + 'ex_RoutingSettings' => 'Reititysasetukset', + 'ex_Username' => 'Käyttäjän koko nimi', + 'ex_EmailAddress' => 'Sähköpostiosoite', + 'ex_ThisEmailAlreadyRegisteredForOtherUser' => 'Annettu osoite on jo rekisteröity', + 'ex_Language' => 'Käyttöliittymä ja ilmoituskieli', + 'ex_Number' => 'Laajennusnumero', + 'ex_ThisNumberIsNotFree' => 'Numero on jo tietokannassa', + 'ex_ThisNumberOverlapWithParkingSlots' => 'Risteys, jossa on useita pysäköintinumeroita', + 'ex_MobileNumber' => 'Matkapuhelinnumero', + 'ex_Secret' => 'SIP-salasana', + 'ex_ChangeAvatar' => 'Vaihda avataria', + 'ex_UserPhotography' => 'Työntekijän kuva', + 'ex_MobileSettings' => 'Lisäasetukset mobiililaitteille', + 'ex_MobileDialstring' => 'Valintamerkkijonon ohitus', + 'ex_SipSettings' => 'SIP-asetukset', + 'ex_BusyLevel' => 'Rinnakkaisten keskustelujen enimmäismäärä', + 'ex_BusyLevelInfo' => 'Kun määritetty määrä puheluita saavutetaan, työntekijän puhelin katsotaan varattuksi.', + 'ex_DTMFMode' => 'DTMF-tila', + 'ex_NetworkFilter' => 'Ylijännitesuodatin', + 'ex_NatMode' => 'NAT-tila', + 'gs_CallRecordTab' => 'Keskustelujen tallentaminen', + 'ex_ManualAdditionalAttributes' => 'Lisävaihtoehdot', + 'ex_RingMainExtension' => 'varten', + 'ex_SecondsAndThenRedirectCallTo' => 'Yritämme soittaa päänumeroon sekuntia, sitten siirrymme numeroon', + 'ex_IfMainExtensionIsBusyRedirectCallTo' => 'Jos päänumero on varattu, siirrämme puhelun numeroon', + 'ex_IfMainExtensionIsUnavailableRedirectCallTo' => 'Jos päänumero ei ole käytettävissä, siirrämme puhelun numeroon', + 'ex_ValidateMobileIsNotCorrect' => 'Tarkista, että matkapuhelinnumerosi on syötetty oikein', + 'ex_ValidateEmailEmpty' => 'Todennäköisesti sähköpostiosoite on syötetty väärin', + 'ex_ValidateUsernameEmpty' => 'Kirjoita työntekijän koko nimi', + 'ex_ValidateUsernameSpecialCharacters' => 'Koko nimi ei saa sisältää erikoismerkkejä', + 'ex_ValidateSecretEmpty' => 'SIP-salasana ei voi olla tyhjä', + 'ex_ValidateSecretWeak' => 'SIP-salasanan on oltava yli 4 merkkiä pitkä', + 'ex_PasswordNoLowSimvol' => 'Salasanan tulee sisältää kirjaimia', + 'ex_RegeneratePassword' => 'Luo uusi salasana', + 'ex_PasswordNoNumbers' => 'Salasanan tulee sisältää numeroita', + 'ex_ValidateExtensionNumber' => 'Alanumerossa saa olla vain numeroita', + 'ex_AddNewExtension' => 'Lisää työntekijä', + 'ex_Name' => 'Työntekijä', + 'ex_Transport' => 'Kuljetusprotokolla', + 'ex_Extension' => 'Laajennusnumero', + 'ex_OutboundProxy' => 'Lähtevä välityspalvelin (esimerkki: pbx.yandex.net:5080)', + 'ex_Mobile' => 'mobiili', + 'ex_Email' => 'Sähköposti', + 'ex_Status' => 'Status', + 'ex_ValidateForwardingToBeFilled' => 'Aikakatkaisun edelleenlähetysnumeroa ei täytetty reititysasetuksissa', + 'ex_ValidateForwardingToBeDifferent' => 'Et voi määrittää edelleenlähetystä omaan numeroosi', + 'ex_ValidateMobileNumberIsDouble' => 'Matkapuhelinnumero on jo toisen työntekijän käytössä', + 'ex_ValidateNumberIsDouble' => 'Alanumero on jo varattu', + 'ex_UpdateStatus' => 'Tilan päivitys', + 'ex_Online' => 'Yhdistetty', + 'ex_Offline' => 'Ei käytössä', + 'ex_SelectNumber' => 'Valitse numero', + 'ex_dropdownCategory_CONFERENCE' => 'Konferenssit', + 'ex_dropdownCategory_USER' => 'Työntekijät', + 'ex_dropdownCategory_USERS' => 'Työntekijät', + 'ex_dropdownCategory_DIALPLAN_APPLICATION' => 'Dialplan-sovellukset', + 'ex_dropdownCategory_IVR_MENU' => 'Interaktiiviset äänivalikot IVR', + 'ex_dropdownCategory_CALLQUEUES' => 'Puhelujonot', + 'ex_dropdownCategory_IVRMENU' => 'Interaktiiviset äänivalikot IVR', + 'ex_dropdownCategory_PBXEXTENSIONMODULES' => 'Lisämoduulit', + 'ex_dropdownCategory_CONFERENCEROOMS' => 'Konferenssit', + 'ex_dropdownCategory_DIALPLANAPPLICATIONS' => 'Dialplan-sovellukset', + 'ex_dropdownCategory_NETWORKFILTERS' => 'Aliverkot', + 'ex_dropdownCategory_QUEUE' => 'Puhelujonot', + 'ex_dropdownCategory_MODULES' => 'Lisämoduulit', + 'ex_dropdownCategory_PROVIDERS' => 'Palveluntarjoajat', + 'ex_dropdownCategory_OUTWORKTIMES' => 'Vapaat työajat', + 'ex_dropdownCategory_ASTERISKMANAGERUSERS' => 'AMI-käyttäjät', + 'ex_dropdownCategory_CUSTOMFILES' => 'Asetustiedostot', + 'ex_dropdownCategory_MENUITEMS' => 'Valikkokohteet', + 'ex_dropdownCategory_SYSTEM' => 'Palvelunumerot', + 'ex_dropdownCategory_PARKING' => 'Parkkipaikat', + 'ex_ImpossibleToDeleteExtension' => 'Työntekijän poistaminen on mahdotonta, koska siellä on seuraavat linkit', + 'ex_ImpossibleToGetSecret' => 'Käyttäjän salasanan saaminen epäonnistui', + 'am_TableColumnName' => 'Nimi', + 'am_TableColumnRead' => 'Lukuoikeus', + 'am_TableColumnWrite' => 'Kirjoitusoikeus', + 'am_TableColumnDescription' => 'Huomautuksia', + 'am_AddNewUser' => 'Lisää käyttäjä AMI', + 'am_TableColumnNetworkFilter' => 'Ylijännitesuodatin', + 'am_Read' => 'lukeminen', + 'am_Write' => 'tallentaa', + 'am_Username' => 'Käyttäjätunnus', + 'am_Secret' => 'Salasana', + 'am_NetworkFilter' => 'Ylijännitesuodatin', + 'am_UserRights' => 'Käyttäjän oikeudet', + 'am_Description' => 'Kommentti', + 'am_ValidationAMINameIsEmpty' => 'Tilin nimeä ei ole määritetty', + 'am_ValidationAMISecretIsEmpty' => 'Salasanaa ei ole täytetty', + 'am_ErrorThisUsernameInNotAvailable' => 'Samanniminen merkintä on jo olemassa', + 'am_NoAnyServersYet' => 'Täällä ei ole vielä AMI-käyttäjiä', + 'tf_TableColumnNotes' => 'Huom', + 'tf_AddNewTimeFrame' => 'Lisää aikaväli', + 'tf_DateDaysFrom' => 'Kausi', + 'tf_WeekDaysFrom' => 'Viikon päivät', + 'tf_TimePeriodFrom' => 'Aikajakso', + 'tf_PeriodAction' => 'Saapuva puhelutoiminto', + 'tf_ValidateCheckWeekDayInterval' => 'Tarkista viikonpäivien väli', + 'tf_ValidateCheckTimeInterval' => 'Tarkista aikaväli', + 'tf_ValidateAudioMessageEmpty' => 'Valitse äänitallenne', + 'tf_ValidateExtensionEmpty' => 'Valitse alanumero edelleenlähetystä varten', + 'tf_ValidateNoRulesSelected' => 'Aikaa ei täytetä', + 'tf_TabGeneralSettings' => 'Perusasetukset', + 'tf_TabRoutsRestriction' => 'Voimassa valituille reiteille', + 'tf_calUrl' => 'Kalenterin URL-osoite', + 'tf_calUser' => 'Käyttäjätunnus', + 'tf_calSecret' => 'Salasana', + 'tf_calType' => 'Tyyppi', + 'tf_CAL_TYPE_NONE' => 'Tavallinen', + 'tf_CAL_TYPE_CALDAV' => 'CalDAV', + 'tf_CAL_TYPE_ICAL' => 'iCal', + 'tf_ValidateCalUri' => 'Kalenterin URL-osoite -kentässä on virheellinen arvo.', + 'Mon' => 'maanantai', + 'Tue' => 'tiistai', + 'Wed' => 'keskiviikko', + 'Thu' => 'torstai', + 'Fri' => 'perjantai', + 'Sat' => 'lauantai', + 'Sun' => 'sunnuntai', + 'fw_AddNewRule' => 'Lisää uusi aliverkko', + 'fw_TableColumnDescription' => 'Nimi', + 'fw_TableColumnNetwork' => 'Aliverkko/osoite', + 'fw_Description' => 'Nimi', + 'fw_Permit' => 'Aliverkko', + 'fw_Rules' => 'Käytettävissä olevat palvelut', + 'fw_webDescription' => 'WEB - pääsy hallinnolliseen käyttöliittymään', + 'fw_amiDescription' => 'AMI - pääsy Asterisk Manager -sovellusliittymään Telnetin kautta', + 'fw_ctiDescription' => 'CTI - puhelinpaneelin kytkeminen', + 'fw_ajamDescription' => 'AJAM – pääsy tähtienhallintasovellusliittymään http/https:n kautta', + 'fw_sshDescription' => 'SSH - pääkäyttäjän oikeudet järjestelmään', + 'fw_icmpDescription' => 'ICMP - yhteyden tarkistus ping-komennolla', + 'fw_ValidatePermitAddress' => 'Määritetty aliverkon osoite on virheellinen. Kokeile mallia, joka on samanlainen kuin 192.168.1.0/24', + 'fw_ValidateRuleName' => 'Anna aliverkolle nimi', + 'fw_NewerBlockIp' => 'Älä koskaan estä osoitteita tästä verkosta, ohita puhelimen valtuutusvirheet ja salasanan syöttövirheet verkkoliittymässä', + 'fw_ItIsLocalNetwork' => 'Tämä on VPN tai paikallinen verkko, tämän verkon puhelimet muodostavat yhteyden suoraan asemaan ilman NAT-reititystä', + 'fw_AllNetworksRule' => 'Kaikki saatavilla olevat verkot', + 'fw_LocalNetworksRule' => 'Aliverkko, jossa MikoPBX sijaitsee', + 'fw_DenyNetwork' => 'Kielletty aliverkko', + 'fw_PermitNetwork' => 'aliverkko', + 'fw_Subnet' => 'Aliverkon maski', + 'fw_AdditionalRules' => 'Lisävaihtoehdot', + 'fw_StatusEnabled' => 'Mukana palomuuri ja hakkeroinnin esto', + 'fw_StatusDisabled' => 'Palomuuri ja hakkerointisuoja on poistettu käytöstä', + 'fw_NeedConfigureRule' => 'Vaatii asennuksen', + 'mo_BeforeDeleteNetworkFilterDeleteAsteriskManagerUsersFirst' => 'Linkki tähän sääntöön löytyi Asterisk Managers -luettelosta käyttäjälle %username%', + 'mo_BeforeDeleteNetworkFilterDeleteSipFirst' => 'Linkki tähän sääntöön löytyi työntekijäluettelosta osoitteessa %extension%', + 'mo_ThisVlanIdNotUniqueForLanInterfacesModels' => 'Järjestelmässä on jo liitäntä samaan VLAN-verkkoon', + 'mo_Disabled' => 'pois', + 'mo_RightNumber' => 'Sääntö nro.%id%', + 'mo_NewElement' => 'Uuden luominen', + 'mo_NewElementNetworkFilters' => 'Uusi palomuurisääntö aliverkolle/osoitteelle', + 'mo_NewElementSip' => 'Uusi SIP-palveluntarjoaja', + 'mo_NewElementIncomingRoutingTable' => 'Uusi sääntö saapuvien puhelujen käsittelyyn', + 'mo_NewElementOutgoingRoutingTable' => 'Uusi sääntö lähtevien puhelujen käsittelylle', + 'mo_NewElementOutWorkTimes' => 'Uusi sääntö työajan jälkeen', + 'mo_NewElementDialplanApplications' => 'Uusi sovellus/soittosuunnitelma', + 'mo_NewElementAsteriskManagerUsers' => 'Uusi tili AMI-käyttäjälle', + 'mo_NewElementSoundFiles' => 'Uusi äänitiedosto', + 'nw_PublicHostName' => 'Reitittimesi ulkoinen isäntänimi', + 'nw_ValidateDHCPOnVlansDontSupport' => 'DHCP:tä ei tueta VLAN-aliverkoissa', + 'nw_ValidateNameIsNotBeEmpty' => 'Käyttöliittymän nimi on tyhjä', + 'nw_ValidateVlanRange' => 'VLAN-arvo on täytetty väärin. Valitse {ruleValue}', + 'nw_Hostname' => 'Paikallinen isäntänimi', + 'nw_ValidateExtIppaddrNotRight' => 'Virhe täytettäessä reitittimen ulkoista IP-osoitetta', + 'nw_ValidateExtIppaddrOrHostIsEmpty' => 'Sinun on täytettävä joko reitittimen ulkoinen IP-osoite tai sen DNS-nimi', + 'nw_ValidateVlanCross' => 'Virheet rajapintojen VLAN-asetuksissa, tarkista parametrien leikkauskohta', + 'nw_ValidateIppaddrIsEmpty' => 'Verkkoliitännän IP-osoitetta ei ole täytetty', + 'nw_ValidateIppaddrNotRight' => 'Verkkoliitännän IP-osoite on määritetty väärin', + 'nw_GatewayAddress' => 'Yhdyskäytävän osoite', + 'nw_DNSAddresses' => 'DNS-palvelinosoitteet', + 'nw_PublicAddress' => 'Reitittimesi ulkoinen IP-osoite', + 'nw_InternetInterface' => 'Verkkoliitäntä Internet-yhteydellä', + 'nw_NetworkInterfaces' => 'Verkkoliitännät', + 'nw_InterfaceName' => 'Nimi', + 'nw_IPAddress' => 'IP-osoite', + 'nw_NetworkMask' => 'Aliverkon peite (CIDR)', + 'nw_VlanID' => 'VLAN ID', + 'nw_SelectInterface' => 'Valitse verkkoliitäntä', + 'nw_AllowNatPortForwarding' => 'Tämä asema sijaitsee NAT-reitittimen takana', + 'nw_NATInfo1' => 'Jos verkkosi on määritetty tukemaan 1:1 NAT:ia (yleensä oletusarvo pilvissä), sinun ei tarvitse tehdä lisäasetuksia reitittimellesi.', + 'nw_NATInfo2' => 'Jos 1:1 NAT ei ole käytössä, ohjaa seuraavat portit julkisesta IP-osoitteesta PBX:n sisäiseen IP-osoitteeseen reitittimen asetuksissa.', + 'nw_NATInfo3' => '%SIP_PORT% TCP/UDP ja %TLS_PORT% TCP', + 'nw_NATInfo4' => '%RTP_PORT_FROM%-%RTP_PORT_TO% UDP', + 'nw_NATInfo5' => 'Jos ulkoinen isäntänimi on määritetty, sitä käytetään ulkoisen IP-osoitteen sijaan.', + 'nw_NATInfo6OR' => 'TAI', + 'nw_PublicSIPPort' => 'SIP-portin numero välitetty sisäiseen %SIP_PORT% PBX:ään', + 'nw_PublicTLSPort' => 'SIP TLS -portin numero välitetty sisäiseen %TLS_PORT% PBX:ään', + 'nw_UseDHCP' => 'Käytä DHCP:tä verkkoasetusten hakemiseen', + 'nw_LookUpExternalIp' => 'Ota selvää ulkoisesta IP-osoitteesta', + 'nw_DeleteCurrentInterface' => 'Poista tämä käyttöliittymä', + 'nw_NetworkAddressTranslations' => 'Verkkotopologia', + 'nw_UpdateExternalIPAutomaticallyOnReboot' => 'Päivitä ulkoinen IP-osoite aina, kun käynnistät uudelleen', + 'gs_MainTab' => 'Perus', + 'gs_FeaturesTab' => 'Puhelujen siirrot', + 'gs_SIPTab' => 'SIEMAILLA', + 'gs_AMITab' => 'AMI&AJAM', + 'gs_SSHTab' => 'SSH', + 'gs_WebTab' => 'Web-käyttöliittymä', + 'gs_PBXName' => 'PBX-järjestelmän nimi', + 'gs_PBXDescription' => 'Lisäkuvaus', + 'gs_NeedRestartPBX' => 'Kun muutos tehdään, tähtipalvelu käynnistyy uudelleen', + 'gs_PBXLanguage' => 'Järjestelmän äänen kieli', + 'gs_PBXInternalExtensionLength' => 'Sisäisten numeroiden enimmäispituus', + 'gs_PBXRecordCalls' => 'Keskustelujen tallentaminen', + 'gs_PBXRecordCallsInner' => 'Sisäisten keskustelujen tallennus', + 'gs_RestartEveryNight' => 'Käynnistä PBX uudelleen joka ilta', + 'gs_PBXCallParkingExt' => 'Soita puiston numeroon', + 'gs_PBXCallParkingSlotRange' => 'Parkkipaikkavalikoima', + 'gs_PBXFeatureAttendedTransfer' => 'Konsultoiva käännösyhdistelmä', + 'gs_PBXFeatureBlindTransfer' => 'Yhdistelmä ehdottomaan siirtoon', + 'gs_PBXFeatureDigitTimeout' => 'Suurin välinumeroiden aikakatkaisu alanumeroa syötettäessä (millisekunteina)', + 'gs_PBXFeaturePickupExten' => 'Yhdistelmä saapuvien puhelujen sieppaamiseen', + 'gs_PBXSplitAudioThread' => 'Tallenna äänitykset stereotilassa', + 'gs_PBXAllowGuestCalls' => 'Salli saapuvat puhelut kaikilta palvelimilta', + 'gs_SIPPort' => 'SIP-portti puhelimien rekisteröintiä varten tälle asemalle', + 'gs_TLS_PORT' => 'SIP TLS -portti (salatut puhelut)', + 'gs_KeepAliveHeader' => 'Rekisteröinnin keston asetukset', + 'gs_SIPDefaultExpiry' => 'Normaali aika sekunneissa Säilytä elossa -viestin lähettämiseen', + 'gs_SIPExpiryRange' => 'Minimi- ja enimmäisaika sekunneissa', + 'gs_SIPPortSettings' => 'Porttiasetukset SIP-signalointia ja RTP-aluetta varten', + 'gs_RTPPortRange' => 'RTP-porttialue', + 'gs_AMIEnabled' => 'Käytä AMI-liitäntää', + 'gs_AMIPort' => 'AMI-portti', + 'gs_AJAMEnabled' => 'Käytä AJAM-käyttöliittymää', + 'gs_AJAMPort' => 'Port AJAM', + 'gs_AJAMPortTLS' => 'Salattu AJAM-portti', + 'gs_SSHPort' => 'SSH-portti', + 'adv_SSHPPasswordCorrupt' => 'Verkkoliittymässä asetettu SSH-salasana ei vastaa järjestelmän nykyistä salasanaa. korjaus', + 'gs_SSHLogin' => 'Kirjaudu SSH-konsoliin', + 'gs_SSHPassword' => 'SSH-salasana', + 'gs_SSHAuthorizedKeys' => 'Valtuutetut SSH-avaimet', + 'gs_SSHecdsaKey' => 'SSH ECDSA -avain', + 'gs_SSHRsaKey' => 'SSH RSA avain', + 'gs_SSHDssKey' => 'SSH DSS avain', + 'gs_PasswordSimple' => 'Määrittämäsi salasana on liian yksinkertainen.', + 'gs_SetPasswordError' => 'Salasana - %password% ei voi käyttää, se on yksinkertaisten salasanojen sanakirjassa.', + 'gs_SetPasswordInfo' => 'Määritettyä salasanaa ei voi käyttää, se on yksinkertaisessa salasanasanakirjassa.', + 'gs_PasswordNoNumbers' => 'Salasanan tulee sisältää numeroita', + 'gs_PasswordNoLowSimvol' => 'Salasanan tulee sisältää pieniä kirjaimia', + 'gs_PasswordNoUpperSimvol' => 'Salasanan tulee sisältää isoja kirjaimia', + 'gs_WebPort' => 'HTTP-portti', + 'gs_WebHTTPSPort' => 'HTTPs-portti', + 'gs_WEBHTTPSPrivateKey' => 'HTTPs yksityinen avain', + 'gs_WEBHTTPSPublicKey' => 'HTTPs julkinen avain', + 'gs_ValidateEmptyPBXName' => 'Aseman nimeä ei ole määritetty', + 'gs_TwoDigthts' => '2 numeroa', + 'gs_ThreeDigthts' => '3 numeroa', + 'gs_FourDigthts' => '4 numeroa', + 'gs_FiveDigthts' => '5 numeroa', + 'gs_SixDigthts' => '6 numeroa', + 'gs_SevenDigthts' => '7 numeroa', + 'gs_ElevenDigthts' => '11 numeroa', + 'gs_WebAdminLogin' => 'Kirjaudu sisään', + 'gs_WebAdminPassword' => 'Salasana', + 'gs_WebAdminPasswordRepeat' => 'Kirjoita salasanasi uudelleen', + 'gs_SSHPasswordRepeat' => 'Kirjoita salasanasi uudelleen', + 'gs_Passwords' => 'WEB-käyttöliittymän salasana', + 'gs_DefaultPasswordWarning' => 'Älä käytä tavallista järjestelmänvalvojan kirjautumistunnusta ja salasanaa', + 'gs_ValidateEmptyWebPassword' => 'Järjestelmänvalvojan salasana ei voi olla tyhjä', + 'gs_ValidateWeakWebPassword' => 'WEB-salasanan on oltava yli 4 merkkiä pitkä', + 'gs_ValidateWebPasswordsFieldDifferent' => 'Verkkokäyttöliittymän salasana syötettiin väärin', + 'gs_ValidateEmptySSHPassword' => 'SSH-salasana ei voi olla tyhjä', + 'gs_ValidateWeakSSHPassword' => 'SSH-salasanan on oltava yli 4 merkkiä pitkä', + 'gs_ValidateSSHPasswordsFieldDifferent' => 'SSH-salasana syötettiin väärin. Kirjoita salasanasi uudelleen.', + 'gs_ValidateWEBPortOutOfRange' => 'HTTP-porttikenttä on virheellinen. Valitse arvo väliltä {ruleValue}.', + 'gs_ValidateWEBHTTPSPortOutOfRange' => 'HTTPS-porttikenttä on virheellinen. Valitse arvo väliltä {ruleValue}.', + 'gs_ValidateWEBHTTPSPortNotEqualToWEBPort' => 'HTTP- ja HTTPS-porttien on oltava erilaiset', + 'gs_ValidateWEBPortNotEqualToAjamPort' => 'HTTP- ja AJAM-porttien on oltava erilaisia', + 'gs_ValidateWEBPortNotEqualToAjamTLSPort' => 'HTTP- ja AJAM-porttien on oltava erilaisia', + 'gs_ValidateWEBHTTPSPortNotEqualToAjamPort' => 'HTTPS- ja AJAM-porttien on oltava erilaisia', + 'gs_ValidateWEBHTTPSPortNotEqualToAjamTLSPort' => 'HTTPS- ja AJAM-porttien on oltava erilaisia', + 'gs_SendAnonymousMetrics' => 'Lähetä kaatumistiedot kehittäjille', + 'gs_WebAdminLanguage' => 'Web-käyttöliittymän kieli', + 'gs_CodecsTab' => 'Audio/video koodekit', + 'gs_AudioCodecs' => 'Äänikoodekit', + 'gs_VideoCodecs' => 'Videokoodekit', + 'gs_CodecsOrder' => 'Kodekin prioriteetti', + 'gs_DangerZone' => 'Järjestelmäasetusten poistaminen', + 'gs_RestoreAllSettingsHeader' => 'Huomio!', + 'gs_RestoreAllSettingsMessage' => 'Kaikki asetukset, puheluhistoria, puhelujen tallennustiedostot ja asennetut laajennukset poistetaan.', + 'gs_EnterDeleteAllPhrasePreText' => 'Puhdista järjestelmä kirjoittamalla syöttökenttään seuraava lause:', + 'gs_EnterDeleteAllPhrase' => 'poista kaikki', + 'gs_AllSettingsDeleted' => 'Kaikki asetukset poistetaan', + 'gs_PBXRecordAnnouncementIn' => 'Valitse puhelun tallennushälytys saapuville puheluille', + 'gs_PBXRecordAnnouncementOut' => 'Valitse lähteville puheluille puhelun tallennushälytys', + 'ts_CurrentSettings' => 'Nykyiset asetukset', + 'ts_SystemTime' => 'Järjestelmän aika', + 'ts_TimeZone' => 'Aikavyöhyke', + 'ts_ModifySettings' => 'Uudet asetukset', + 'ms_SentTestEmailAfterSaveTo' => 'Lähetä testisähköposti tähän osoitteeseen', + 'ms_MissedCallSubject' => 'Vastaamaton puhelu - sähköpostin aihe', + 'ms_MissedCallBody' => 'Vastaamaton puhelu - kirjeen teksti', + 'ms_MissedCallFooter' => 'Vastaamaton puhelu - kellari', + 'ms_VoicemailSubject' => 'Vastaaja - aiherivi', + 'ms_VoicemailBody' => 'Vastaaja - kirjeen teksti', + 'ms_VoicemailFooter' => 'Vastaaja - kellari', + 'ms_MailSysadminEmail' => 'Järjestelmänvalvojan sähköposti', + 'ms_SystemEmailForMissed' => 'Sähköposti jääneistä ilmoituksista', + 'ms_TestEmailSubject' => 'Testataan postin lähetystä', + 'ms_TestEmailSentSuccessfully' => 'Kirje lähetetty', + 'ms_TestEmailBody' => 'Jos sait tämän kirjeen, sähköpostiasetukset ovat oikein.', + 'ms_MissedCalls' => 'Vastaamattomat puhelut', + 'ms_Voicemail' => 'Vastaaja', + 'ms_VoicemailCommonEmail' => 'Yksittäinen sähköposti vastaajaviestien lähettämiseen', + 'iv_ValidateDigitsIsNotCorrect' => 'Koodikenttää ei ole täytetty oikein', + 'iv_ValidateExtensionIsNotCorrect' => 'Tilaajanumeroa ei ole valittu', + 'iv_ValidateExtensionIsEmpty' => 'IVR-valikon numeroa ei ole määritetty', + 'iv_ValidateAudioFileIsEmpty' => 'Äänitiedostoa ei ole valittu äänitervehdystä varten', + 'iv_ValidateNameIsEmpty' => 'IVR-valikon nimeä ei ole määritetty', + 'iv_ValidateNoIVRExtensions' => 'IVR-valikon lisävalinnan toimintoja ei ole määritetty', + 'iv_ValidateTimeoutExtensionIsEmpty' => 'Aikakatkaisun edelleenlähetysnumeroa ei ole määritetty', + 'iv_ValidateExtensionIsDouble' => 'Määritetty IVR-valikkonumero on varattu', + 'iv_ValidateRepeatNumberOutOfRange' => 'Valikon toistojen määrä on väärä', + 'iv_ValidateTimeoutOutOfRange' => 'Alanumeron odottamisen aikakatkaisu on syötetty väärin', + 'iv_Name' => 'Valikon nimi', + 'iv_Description' => 'Kommentti', + 'iv_Extensions' => 'IVR-valikon numero', + 'iv_PlaySound' => 'Äänitervehdys', + 'iv_Actions' => 'Toimenpiteet lisärekrytoimiseksi', + 'iv_DeleteRow' => 'Poistaa', + 'iv_AddNewRow' => 'Lisätä', + 'iv_TimeoutExtension' => 'Oletusnumero', + 'iv_Extension' => 'IVR-valikon numero', + 'iv_Note' => 'Huomautuksia', + 'iv_AddNewIvrMenu' => 'Luo uusi IVR-valikko', + 'iv_ThisNumberIsNotFree' => 'Tämä numero on varattu', + 'iv_NumberOfRepeat' => 'Uudelleenyritysten määrä ennen siirtoa oletusnumeroon', + 'iv_ImpossibleToDeleteIVRMenu' => 'IVR-valikkoa ei voi poistaa, siihen on aktiivisia linkkejä', + 'da_Main' => 'Sovellusasetukset', + 'da_Applicationlogic' => 'Ohjelmakoodi', + 'da_Hint' => 'Vihje', + 'da_Description' => 'Kommentti', + 'da_Name' => 'Nimi', + 'da_Extensions' => 'Hakemuksen puhelinnumero', + 'da_ThisNumberIsNotFree' => 'Tämä numero on varattu', + 'da_Type' => 'Koodityyppi', + 'da_ColumnExtension' => 'Määrä', + 'da_ColumnName' => 'Nimi', + 'da_ColumnNote' => 'Kuvaus', + 'da_ValidateNameIsEmpty' => 'Hakemuksen nimeä ei ole täytetty', + 'da_ValidateExtensionIsEmpty' => 'Hakemuksen numeroa ei ole täytetty', + 'da_ValidateExtensionDouble' => 'Tälle sovellukselle määritetty alanumero on varattu', + 'da_AddNewDialplanApp' => 'Lisää uusi', + 'da_TypePhp' => 'PHP-AGI-skripti', + 'da_TypePlaintext' => 'Tähtivalintasuunnitelma', + 'da_ValidateExtensionNumber' => 'Alanumerossa saa olla vain numeroita', + 'da_ImpossibleToDeleteDialplanApplication' => 'Dialplans-sovellusta ei voi poistaa, sillä siinä on linkkejä', + 'cr_AddNewConferenceRoom' => 'Lisää konferenssi', + 'cr_ColumnExtension' => 'Määrä', + 'cr_pinCode' => 'Konferenssin PIN-koodi', + 'cr_Extensions' => 'Määrä', + 'cr_ThisNumberIsNotFree' => 'Tämä numero on varattu', + 'cr_ValidateExtensionDouble' => 'Tälle konferenssille määritetty alanumero on varattu', + 'cr_ValidateExtensionEmpty' => 'Sisäistä neuvottelunumeroa ei ole määritetty', + 'cr_ValidateNameEmpty' => 'Konferenssin nimeä ei ole määritelty', + 'cr_ValidateExtensionNumber' => 'Alanumerossa saa olla vain numeroita', + 'cr_ValidateExtensionLen' => 'Alanumeron tulee koostua kahdesta tai useammasta numerosta', + 'cr_ValidatePinNumber' => 'PIN-koodi saa sisältää vain numeroita', + 'cr_ImpossibleToDeleteConferenceRoom' => 'Tätä kokoushuonetta ei voi poistaa', + 'cdr_ColumnDate' => 'Soittopäivä', + 'cdr_ColumnFrom' => 'WHO', + 'cdr_ColumnTo' => 'Kenelle', + 'cdr_ColumnDuration' => 'Kesto', + 'cdr_ColumnRecordings' => 'Puhelujen tallenteet', + 'cdr_And' => 'Ja', + 'cf_ColumnPath' => 'Tiedoston polku', + 'cf_ColumnMode' => 'tila', + 'cf_ColumnNote' => 'Huom', + 'cf_FileActionsNone' => 'Älä vaihda', + 'cf_FileActionsAppend' => 'Liitä tiedoston loppuun', + 'cf_FileActionsOverride' => 'Vaihda kokonaan', + 'cf_FileActionsScript' => 'Prosessi skriptillä', + 'cf_Main' => 'Kommentoi muutoksia', + 'cf_Content' => 'Ohjelmakoodi tai kokoonpano', + 'cf_Path' => 'Tiedoston polku', + 'cf_Description' => 'Kommentoi miksi muutokset tehtiin', + 'cf_Mode' => 'tila', + 'cf_OriginalFileHeader' => 'Järjestelmän luoma alkuperäinen tiedostosisältö', + 'cf_UserEditHeader' => 'Editor muutosten tekemiseen', + 'cf_ResultFileHeader' => 'Tiedoston sisältö muutoksineen', + 'mo_BeforeDeleteFirst' => 'Objektiin on linkkejä - %represent%', + 'ConstraintViolation' => 'Loogisen eheyden rikkominen', + 'repAsteriskManagerUsers' => 'AMI-merkintä - %represent%', + 'repCallQueues' => 'Puhelujono - %represent%', + 'repCallQueueMembers' => 'Puhelujonon jäsen - %represent%', + 'repConferenceRooms' => 'Konferenssi – %represent%', + 'repCustomFiles' => 'Järjestelmätiedosto - %represent%', + 'repDialplanApplications' => 'Dialplan-sovellus - %represent%', + 'repExtensionForwardingRights' => 'Työntekijän reititysasetukset - %represent%', + 'repExtensions' => 'Laajennuksen numero - %represent%', + 'repExternalPhones' => 'Ulkoinen numero - %represent%', + 'repFail2BanRules' => 'Fail2Ban-sääntö – %represent%', + 'repSoundFiles' => 'Äänitiedosto - %represent%', + 'repIvrMenu' => 'IVR-valikko – %represent%', + 'repIvrMenuActions' => 'IVR-menun osallistuja - %represent%', + 'repLink' => 'linkki', + 'sf_ValidationFileNameIsEmpty' => 'Tiedoston nimeä ei ole määritetty', + 'sf_Filename' => 'Tallennustiedoston nimi', + 'sf_UploadNewSoundFile' => 'Lataa uusi tiedosto', + 'sf_RecordNewSoundFile' => 'Nauhoita mikrofonilla', + 'sf_UploadSoundFileButton' => 'Lataa', + 'sf_StartRecordSoundFileButton' => 'Aloita tallennus', + 'sf_StopRecordSoundFileButton' => 'Stop', + 'sf_ColumnFile' => 'Nimi', + 'sf_ColumnPlayer' => 'Pelaaja', + 'sf_AddNewSoundFile' => 'Lisää uusi äänitiedosto', + 'sf_FileNotFound' => 'Virhe - tiedostoa ei voi toistaa', + 'sf_SelectAudioFile' => 'Valitse äänitiedosto', + 'sf_ValidationFileNotSelected' => 'Lataa ensin äänitiedosto', + 'sf_CustomSounds' => 'Äänitiedostot', + 'sf_MusicOnHold' => 'Musiikki pidossa', + 'sf_UploadError' => 'Virhe ladattaessa äänitiedostoa', + 'lic_ValidateCompanyNameEmpty' => 'Pakollinen kenttä ei täytetty - yrityksen nimi', + 'lic_ValidateContactEmail' => 'Pakollinen kenttä ei täytetty - yhteyshenkilön sähköpostiosoite', + 'lic_ValidateContactName' => 'Pakollinen kenttä ei täytetty - yhteyshenkilö', + 'lic_ValidateCouponEmpty' => 'Pakollinen kenttä ei täytetty - kuponki', + 'lic_ValidateLicenseKeyEmpty' => 'Pakollinen kenttä ei täytetty - Lisenssiavain', + 'lic_GetKeyForm' => 'Rekisteröinti', + 'lic_ActivateCoupon' => 'Kupongin aktivointi', + 'lic_LicenseKey' => 'Lisenssiavain', + 'lic_CompanyName' => 'Organisaation nimi', + 'lic_Email' => 'Yhteyshenkilön sähköpostiosoite', + 'lic_Contact' => 'Yhteyshenkilö', + 'lic_Phone' => 'Yhteydenotto puhelinnumero', + 'lic_Inn' => 'Yksilöllinen yrityksen tunniste (TIN, IIN, UNP jne.)', + 'lic_Coupon' => 'Lisenssin uusimiskuponki', + 'lic_SuccessfulCouponActivation' => 'Kuponki aktivoitu onnistuneesti', + 'lic_SuccessfulActivation' => 'Onnistunut järjestelmän rekisteröinti', + 'lic_WrongLicenseKeyOrEmpty' => 'Lisenssiavain syötettiin väärin', + 'lic_LicenseKeyMessage' => 'Lisenssiavainta käytetään kaikkien MIKO-tuotteiden lisenssien tallentamiseen.
      +Jos sinulla on jo avain, voit kirjoittaa sen tähän kenttään.
      +Jos sinulla oli avain, mutta unohdit sen, etsi saapuvat kirjeet osoitteesta lic@miko.ru
      +Voit saada uuden avaimen automaattisesti täyttämällä rekisteröintilomakkeen.
      ', + 'lic_CouponMessage' => 'Kuponkia käytetään tilausten, kokeilujen uusimiseen ja laajennusmoduulien lisenssien aktivoimiseen.
      +Kupongin voi aktivoida kerran, jonka jälkeen se lunastetaan.', + 'lic_CurrentLicenseInfo' => 'Yksityiskohtaiset tiedot lisenssiavaimen tuotteista', + 'lic_Expired' => 'Tuote on vanhentunut, ota yhteyttä lic@mikopbx.com', + 'lic_ExpiredAfter' => 'Lisenssi vanhenee %expired% jälkeen', + 'lic_Product' => 'Tuote', + 'lic_FeatureInfo' => 'Yhteensä %count% lisenssiä kohteelle %name%, joista käytössä %captured%', + 'lic_LicenseKeyProducts' => 'Aktivoidut tuotteet', + 'lic_LicenseKeyOwner' => 'Lisenssin haltija', + 'lic_ResetLicenseSettings' => 'Nollaa avaimen sidonta', + 'lic_LicenseKeyValid' => 'Ohjelma on rekisteröity', + 'lic_FailedToGetTrialKey2051' => '(2051) Tätä kopiota ei voitu rekisteröidä, koska olet jo käyttänyt rekisteröintinumeroa toisessa sähköpostissa tällä koneella.
      + Käytä avainta, joka lähetettiin sinulle aiemmin osoitteesta lic@miko.ru', + 'lic_FailedToGetTrialKey2022' => '(2022) Tämän kopion rekisteröinti epäonnistui. Toisen yrityksen rekisteröintinumero on jo luotu määritettyyn sähköpostiosoitteeseen.
      + Käytä avainta, joka lähetettiin sinulle aiemmin osoitteesta lic@miko.ru tai ilmoita oikea yrityksen nimi.', + 'lic_FailedActivateCoupon2057' => '(2057) Tämä kuponki on estetty', + 'lic_FailedActivateCoupon2040' => '(2040) Tätä kuponkia ei ole olemassa, tarkista syöttämäsi oikeellisuus', + 'lic_FailedActivateCoupon2041' => '(2041) Tämä kuponki on aktivoitu jo aiemmin', + 'lic_FailedActivateCoupon2037' => '(2037) Virhe määritettäessä rekisterinumeroa', + 'lic_FailedCheckLicense2026' => '(2026) Virhe määritettäessä lisenssinumeroa', + 'lic_FailedToCaptureFeature2008' => '(2008) Ei vaadita lisenssiä tai se on sidottu toiseen MikoPBX:ään', + 'lic_InvalidLicenseKey2009' => '(2009) Lisenssiavaimen virhe', + 'lic_FeatureExpired2011' => '(2011) Moduulilisenssi on vanhentunut, ota yhteyttä sale@mikopbx.com', + 'lic_FailedCheckLicenseNotPbxResponse' => 'MikoPBX ei vastannut lupatietopyyntöön. Palvelu ei ole saatavilla.', + 'lic_UnknownLicenseMessage' => 'Ei vastausta lupajärjestelmästä', + 'lic_IntroductionTabHeader' => 'Tietoja markkinapaikan lisensoinnista', + 'lic_ManagementTabHeader' => 'Rekisteröinti ja lisenssien hallinta', + 'lic_FirstQuestionHeader' => 'Onko rekisteröityminen tarpeellista?', + 'lic_FirstQuestionAnswer' => 'MikoPBX:n perustoiminnot ovat täysin ilmaisia, eikä niitä rajoita lisenssi. Lisenssin puute ei vaikuta puheluihin millään tavalla.
      Voit rekisteröityä Marketplaceen ja peruuttaa sen milloin tahansa.', + 'lic_MarketplaceHeader' => 'Marketplace tarjoaa lisämahdollisuuksia', + 'f2b_Reason' => 'Aiheuttaa', + 'f2b_IpAddres' => 'IP-osoite', + 'f2b_BanedTime' => 'Päivämäärä', + 'f2b_TableBannedHeader' => 'Estetyt osoitteet', + 'f2b_Unban' => 'Kumoa esto', + 'f2b_Jail_asterisk_ami_v2' => 'AMI- tai AJAM-valtuutusvirheet', + 'f2b_Jail_asterisk_v2' => 'SIP-valtuutusvirheet', + 'f2b_Jail_asterisk_security_log_v2' => 'SIP-valtuutusvirheet (security_log)', + 'f2b_Jail_asterisk_public_v2' => 'SIP-valtuutusvirheet (julkinen)', + 'f2b_Jail_dropbear' => 'SSH-istunnon valtuutusvirheet', + 'f2b_Jail_mikopbx-www' => 'Valtuutusvirheet PBX-hallintaliittymässä', + 'f2b_WhiteList' => 'Luettelo osoitteista, joita ei koskaan estetä', + 'f2b_MaxRetry' => 'Yritysten lukumäärä ennen estoa', + 'f2b_FindTime' => '(sekunnissa)', + 'f2b_BanTime' => 'Estä (sekuntia)', + 'f2b_Fail2BanSwitch' => 'Käytä Fail2Ban aktiivista estojärjestelmää', + 'f2b_ValidateMaxRetryRange' => 'Yritysten lukumäärän parametria ei ole asetettu oikein', + 'f2b_ValidateFindTimeRange' => 'Valtuutusyritysten analyysijaksoa ei ole asetettu oikein', + 'f2b_ValidateBanTimeRange' => 'Estoaika on väärä', + 'f2b_TableBannedEmpty' => 'Tietoja ei ole saatavilla', + 'f2b_SettingsTabHeader' => 'Suojauksen asettaminen', + 'f2b_BannedIpTabHeader' => 'Estetyt osoitteet', + 'upd_FileName' => 'Valitse päivitystiedosto', + 'upd_UpdateSystem' => 'Ota päivitys käyttöön', + 'upd_VersionColumn' => 'Versio', + 'upd_DescriptionColumn' => 'Kuvaus', + 'upd_AvailableUpdates' => 'Online-päivitykset saatavilla', + 'upd_DownloadUpgradeError' => 'Virhe päivityksen lataamisessa. Yritä myöhemmin uudelleen', + 'upd_UploadError' => 'Virhe päivityksen lataamisessa', + 'upd_UpdateTitle' => 'PBX-päivitys', + 'upd_Cancel' => 'Peruuttaa', + 'upd_UploadInProgress' => 'Päivitystiedostoa ladataan…', + 'upd_UpgradeInProgress' => 'Järjestelmätiedostoja päivitetään…', + 'upd_UpgradeError' => 'Virhe päivitettäessä MikoPBX:ää', + 'upd_UpdateDescription' => 'Päivityksen lataamisen jälkeen MikoPBX käynnistyy automaattisesti uudelleen ja kaikki nykyiset puhelut katkeavat. Muista varmuuskopioida MikoPBX ennen päivittämistä.', + 'upd_EnterIHaveBackupPhrasePreText' => 'Päivitä järjestelmä kirjoittamalla syöttökenttään seuraava lause:', + 'upd_EnterIHaveBackupPhrase' => 'Kyllä minulla on varmuuskopio', + 'upd_UpdateDockerHeader' => 'Säilön päivityssäännöt', + 'upd_UpdateDockerText' => 'Pysäytä säilö, poista se, lataa uusin versio ja aloita uudelleen säilyttäen tallennustilan asennusasetukset ja ympäristömuuttujat. Prosessi on kuvattu tarkemmin dokumentaatiossa.', + 'ext_TableColumnDescription' => 'Moduulin nimi', + 'ext_TableColumnVersion' => 'Versio', + 'ext_UpdateModule' => 'Päivitä moduuli', + 'ext_UpdateModuleError' => 'Virhe moduulin asennuksessa', + 'ext_DeleteModuleError' => 'Virhe poistettaessa moduulia', + 'ext_Available' => 'voidaan päivittää', + 'ext_InstallModule' => 'Asenna moduuli', + 'ext_AvailableModules' => 'Moduulit saatavilla asennettavaksi', + 'ext_ModuleDisabledStatusDisabled' => 'Moduuli poistettu käytöstä', + 'ext_ModuleDisabledStatusEnabled' => 'Moduuli käytössä', + 'ext_ModuleStatusChanging' => 'Muutetaan moduulin tiloja…', + 'ext_Delete' => 'Poistaa', + 'ext_GetLinkError' => 'Virhe vastaanotettaessa moduulin jakelusarjaa sivustolta. Yritä myöhemmin uudelleen.', + 'ext_NoLicenseAvailable' => 'Tämän moduulin asentamiseen tai päivittämiseen ei ole lisenssiä.', + 'ext_ValidateCaptionEmpty' => 'Valikkokohdan nimi on tyhjä', + 'ext_ShowModuleItemAtMainMenu' => 'Näytä moduuli sivuvalikossa', + 'ext_SelectMenuGroup' => 'Valitse sivuvalikosta kohta', + 'ext_SettingsForModule' => 'Moduulin asetukset:', + 'ext_Caption' => 'Valikkokohdan nimi', + 'ext_AddNewExtension' => 'Lataa uusi moduuli', + 'ext_CreateNewExtension' => 'Luo oma moduulisi', + 'ext_UploadError' => 'Moduulin latausvirhe', + 'ext_UploadInProgress' => 'Ladataan moduulia…', + 'ext_InstallationInProgress' => 'Moduulia asennetaan…', + 'ext_GetReleaseInProgress' => 'Pyydetään tietoja arkistosta…', + 'ext_DownloadInProgress' => 'Ladataan moduulia…', + 'ext_CheckLicenseInProgress' => 'Lisenssin tarkistus…', + 'ext_ModuleChangeStatusError' => 'Ongelmia vaihdettaessa moduulin tilaa', + 'ext_InstallationError' => 'Virhe moduulin asennuksessa', + 'ext_InstalledModules' => 'Asennetut moduulit', + 'ext_Marketplace' => 'Markkinapaikka', + 'ext_Licensing' => 'Lisenssien hallinta', + 'ext_NoAvailableModules' => 'Asennettavia moduuleja ei ole saatavana', + 'ext_ModuleDependsHigherVersion' => 'Moduulin asentamiseen tarvitset %version% tai uudemman version MikoPBX:stä', + 'ext_UninstallDBError' => 'Virhe poistettaessa moduulitietokantaa', + 'ext_UnInstallFiles' => 'Virhe poistettaessa moduulitiedostoja', + 'ext_EmptyLicenseKey' => 'Lisenssiavainta moduulin lisenssin aktivoimiseksi ei ole asennettu', + 'ext_ErrorOnAppliesFilesRights' => 'Virhe määritettäessä oikeuksia moduulitiedostoille', + 'ext_ErrorOnInstallDB' => 'Virhe määritettäessä moduulitietokantaa', + 'ext_ErrorOnInstallFiles' => 'Virheitä kopioitaessa moduulitiedostoja', + 'ext_ErrorOnLicenseActivation' => 'Virheet lisenssin aktivoinnissa', + 'ext_NoInstalledModules' => 'Ei asennettuja moduuleja', + 'ext_GoToMarketplace' => 'Mene torille', + 'ext_GoToRegistration' => 'Ilmoittautuminen torilla', + 'ext_LicenseProblemHeader' => 'Lisenssi ongelma', + 'ext_ErrorOnDecodeModuleJson' => 'Virhe jäsennettäessä moduulin määritystiedostoa %filename%', + 'ext_ErrorOnEnableFirewallSettings' => 'Virhe otettaessa käyttöön moduulin palomuuriasetuksia', + 'ext_ErrorOnDisableFirewallSettings' => 'Virhe suljettaessa pois palomuuriasetuksia moduulista', + 'ext_ErrorOnModuleBeforeEnable' => 'Virheitä tarkistettaessa, voidaanko moduuli ottaa käyttöön', + 'ext_ErrorOnModuleBeforeDisable' => 'Virheitä tarkistettaessa, voidaanko moduuli sammuttaa', + 'ext_ModuleLicenseProblem' => 'Laajennusmoduulin lisenssiongelma', + 'ext_ModuleExecutionProblem' => 'Tapahtui vakava virhe:', + 'ext_DisableReasonHeader' => 'Moduuli poistettiin käytöstä automaattisesti', + 'ext_UpdateAllModules' => 'Päivitä kaikki asennetut moduulit', + 'ext_EmptyRepoAnswer' => 'Moduulin asentamiseen ei ole saatavilla julkaisuja', + 'ext_ErrDownloadTimeout' => 'Moduulipäivityksen lataaminen epäonnistui. Toiminnan aikakatkaisu.', + 'ext_ErrUploadTimeout' => 'Moduulitiedoston lataaminen epäonnistui. Toiminnan aikakatkaisu.', + 'ext_ErrInstallationTimeout' => 'Moduulin asennus epäonnistui. Toiminnan aikakatkaisu.', + 'ext_ModuleLastRelease' => 'Nykyinen julkaisu', + 'ext_ModulePublisher' => 'Kehittäjä', + 'ext_ModuleDescriptionTab' => 'Moduulin kuvaus', + 'ext_ModuleChangelogTab' => 'Versiohistoria', + 'ext_UsefulLinks' => 'Hyödyllisiä linkkejä', + 'ext_ExternalDescription' => 'Yksityiskohtainen kuvaus, dokumentaatio', + 'ext_CommercialModule' => 'Maksullinen moduuli', + 'ext_UpdateModuleShort' => 'Päivittää', + 'ext_InstallModuleReleaseTag' => 'Vapauta', + 'ext_InstallModuleVersion' => 'Asenna versio', + 'ext_FreeModule' => 'Ilmainen moduuli', + 'ext_ShowModuleRepoDetails' => 'Avaa moduulin yksityiskohtainen kuvaus', + 'ext_ModuleEulaTab' => 'Lisenssisopimus', + 'ext_FromDate' => 'vapautettu', + 'ext_InstallModuleTitle' => 'Moduulin asennus', + 'ext_ModuleInstallDescription' => 'Moduulia asennettaessa järjestelmä tarkistaa lisenssin. Maksullisille moduuleille tarjotaan mahdollisuuksien mukaan kokeiluversio. Ilmaiset moduulit asennetaan ilman ehtoja. Jos moduuli on aiemmin poistettu asetusten tallennuksen aikana, ne palautetaan. Moduulia asennettaessa on parempi olla suorittamatta muita toimintoja järjestelmässä.', + 'ext_UpdateAllModulesTitle' => 'Päivitetään kaikki moduulit', + 'ext_UpdateAllModulesDescription' => 'Järjestelmä päivittää kaikki asennetut moduulit uusimpiin versioihin säilyttäen nykyiset asetukset. On suositeltavaa, että et suorita muita toimintoja järjestelmässä päivitysprosessin aikana.', + 'ext_UpdateModuleTitle' => 'Moduulin päivitys', + 'ext_ModuleUpdateDescription' => 'Valittu moduuli päivitetään arkistosta uusimpaan versioon ja kaikki asetukset tallennetaan. Maksullisten moduulien lisenssi tarkistetaan ensin. Päivityksen aikana on suositeltavaa pidättäytyä muista toiminnoista järjestelmässä.', + 'ext_DowngradeModuleTitle' => 'Moduuliversion palautus', + 'ext_ModuleDowngradeDescription' => 'Moduuli palautetaan edelliseen versioon. Asetukset tallennetaan, mutta maksullisten moduulien lisenssi tarkistetaan ensin. Huomaa, että palautus voi muuttaa tietorakennetta ja moduuli on ehkä määritettävä uudelleen. Vältä muiden toimintojen suorittamista järjestelmässä palautuksen aikana.', + 'ext_SystemVersionRequired' => 'Vähintään yhteensopiva MikoPBX-versio', + 'DimmerWaitForPBXIsOnline' => 'Yhteys PBX-ytimen kanssa katkesi…', + 'DimmerWaitForPBXOnlineDescription' => 'On normaalia, että asema käynnistyy uudelleen.
      Heti kun yhteys on palautettu, sivu päivittyy automaattisesti!', + 'loc_NoResult' => 'Mitään ei löytynyt', + 'mo_CallQueueShort4Dropdown' => 'Jonottaa', + 'mo_ConferenceRoomsShort4Dropdown' => 'Konferenssi', + 'mo_ApplicationShort4Dropdown' => 'Sovellus', + 'mo_IVRMenuShort4Dropdown' => 'IVR-valikko', + 'mo_ModuleShort4Dropdown' => 'Moduuli', + 'mo_SystemExten_hangup' => 'Lopeta puhelu', + 'mo_SystemExten_busy' => 'Toista varattu-ääni', + 'mo_SystemExten_did2user' => 'Suoraan työntekijälle (vastaa DID)', + 'mo_SystemExten_voicemail' => 'Vastaaja', + 'GoToWikiDocumentation' => 'Siirry online-dokumentaatioon', + 'mo_ModuleSettingsError' => 'Virheet moduulin asetuksissa - %modulename%', + 'adv_MessagesHeader' => 'Huomaa', + 'adv_MessagesHeaderError' => 'Vakava virhe', + 'adv_YouUseDefaultWebPassword' => 'Käytät oletussalasanaa kirjautuaksesi hallintaliittymään - muokkaa', + 'adv_YouUseDefaultSSHPassword' => 'Käytät oletussalasanaa käyttääksesi SSH:ta - muokkaa', + 'adv_WebPasswordWeak' => 'Yksinkertainen järjestelmänvalvojan salasana verkkoliittymässä muuta', + 'adv_SshPasswordWeak' => 'Yksinkertainen SSH-tilin salasana muutos', + 'adv_SipPasswordWeak' => 'Yksinkertainen SIP-salasana: %record%', + 'adv_AmiPasswordWeak' => 'Yksinkertainen salasana AMI-käyttäjälle %record%', + 'adv_PopupHeader' => 'Seuraavat ongelmat havaittiin:', + 'pass_CheckWebAdminPasswordSimple' => 'WEB-salasana on liian yksinkertainen.', + 'pass_CheckWebAdminPasswordDontMatch' => 'Annetut WEB-salasanat eivät täsmää', + 'pass_CheckWebAdminPasswordEmpty' => 'Kenttä on tyhjä: WEB-salasana', + 'pass_CheckWebPassErrorChange' => 'Salasanan vaihto epäonnistui', + 'pass_CheckSSHPasswordDontMatch' => 'Annetut SSH-salasanat eivät täsmää', + 'pass_CheckSSHPasswordEmpty' => 'Kenttä on tyhjä: SSH', + 'pass_CheckSSHPasswordSimple' => 'SSH-salasana on liian yksinkertainen.', + 'adv_FirewallDisabled' => 'Palomuuri on poistettu käytöstä järjestelmässä - muokkaa', + 'adv_NetworksNotConfigured' => 'Sallittujen aliverkkojen parametreja ei ole määritetty - muuta', + 'adv_AvailableNewVersionPBX' => 'Uusi versio PBX:stä saatavilla - %ver%', + 'adv_ThisCopyIsNotRegistered' => 'Tämä ohjelman kopio ei ole lisensoitu - Ilmainen aktivointi', + 'adv_StorageDiskRunningOutOfFreeSpace' => 'Tallennuslevyltä on loppumassa vapaa tila (%free% Mt)', + 'adv_ThisCopyHasLicensingTroubles' => 'PBX-lisenssiongelma: %error% - kuinka korjata ', + 'adv_ProblemWithInternetConnection' => 'Internet-yhteyttä ei ole. Maksullisten moduulien toiminnassa voi esiintyä ongelmia.', + 'cal_Yesterday' => 'Eilen', + 'cal_LastWeek' => 'Viimeiset 7 päivää', + 'cal_Last30Days' => 'Viimeiset 30 päivää', + 'cal_ThisMonth' => 'Nykyinen kuukausi', + 'cal_LastMonth' => 'Viime kuussa', + 'cal_ApplyBtn' => 'Käytä', + 'cal_CancelBtn' => 'Peruuttaa', + 'cal_from' => 'Kanssa', + 'cal_to' => 'Tekijä:', + 'cal_CustomPeriod' => 'Mielivaltainen', + 'sntry_Title' => 'Jotain meni pieleen!', + 'sntry_Subtitle' => 'Virheestä on ilmoitettu kehittäjälle.', + 'sntry_Subtitle2' => 'Kuvaile toimintasi, jotka johtivat tähän virheeseen.', + 'sntry_LabelComments' => 'Mitä sinä teit?', + 'sntry_LabelClose' => 'Lähellä', + 'sntry_LabelSubmit' => 'Lähetä', + 'sntry_ErrorGeneric' => 'Tuntematon virhe lähetettäessä. Yritä uudelleen!', + 'sntry_ErrorFormEntry' => 'Kenttiä ei ole täytetty, korjaa ne ja yritä lähettää uudelleen!', + 'sntry_SuccessMessage' => 'Kiitos avustasi!', + 'lang_HelpWithTranslateIt' => 'Apua kääntämiseen MikoPBX', + 'topMenu_Support' => 'Tukea', + 'topMenu_SearchPlaceholder' => 'Kirjoita hakutermi', + 'topMenu_SidebarButton' => 'Valikko', + 'MIKO_PBX' => 'MIKO PBX', + 'PBX is running in Live or Recovery mode' => 'Järjestelmä käynnistetty palautustilaan (Live CD)', + 'LAN IP address assigned via DHCP' => 'LAN IP määritetty DHCP-palvelimen kautta', + 'LAN IP address' => 'LAN IP asetettu manuaalisesti', + 'VLAN IP address assigned via' => 'VLAN IP: toimii kautta', + 'The integrity of the system is broken' => 'Järjestelmän eheys on vaarassa', + 'adv_SystemBrokenComment' => 'Järjestelmätiedostoja on muokattu. Suorita järjestelmän palautus/päivitys.', + 'PBX console setup' => 'MikoPBX konsoli', + 'Install or recover' => 'Suorita asennus/palautus', + 'Install on Hard Drive' => 'Suorita asennus', + 'Set up LAN IP address' => 'Määritä LAN IP-osoite', + 'Reboot system' => 'Käynnistä järjestelmä uudelleen', + 'Ping host' => 'Ping osoitteita', + 'Firewall' => 'Ota palomuuri käyttöön/poista käytöstä', + 'Connect storage' => 'Liitä levy tietojen tallentamista varten', + 'Reset admin password' => 'Palauta verkkokäyttöliittymän salasana', + 'Enter a number' => 'Syötä joukkueen numero', + 'Press ENTER to continue.' => 'Paina ENTER jatkaaksesi…', + 'version' => 'versio', + 'this_is' => 'Tämä on ', + 'Do you want to use DHCP to configure your LAN interface?' => 'Pitäisikö minun käyttää DHCP-palvelinta LAN-liitännän määrittämiseen?', + 'The LAN interface will now be configured via DHCP...' => "LAN-liitäntä konfiguroidaan DHCP:n avulla…", + 'The LAN interface will now be configured ...' => "Asetetaan LAN-liitäntää…", + 'Enter the new LAN IP address: ' => 'Anna uusi LAN-IP-osoite:', + 'Subnet masks are to be entered as bit counts (as in CIDR notation).' => 'Aliverkon peite CIDR-muodossa (1-32)', + 'Enter the new LAN subnet bit count: ' => "Anna maskin arvo:", + 'Enter the LAN gateway IP address: ' => "Anna yhdyskäytävän osoite (LAN-yhdyskäytävän IP-osoite):", + 'Enter the LAN DNS IP address: ' => 'Anna DNS-palvelimen osoite:', + 'The system will reboot. This may take a minute.' => 'Järjestelmä käynnistyy uudelleen. Tämä kestää muutaman minuutin.', + 'Do you want to proceed? (y/n): ' => 'Jatketaanko prosessia? (y/n):', + 'The system is rebooting now...' => 'Käynnistä uudelleen…', + 'Enter a host name or IP address: ' => 'Anna palvelimen osoite:', + 'disable' => 'poistaa käytöstä', + 'enable' => 'kytke päälle', + 'running' => 'mukana', + 'stopped' => 'pois käytöstä', + 'Firewall is now' => 'Palomuuri nyt', + 'Firewall disabled' => 'Palomuuri poistettu käytöstä', + 'Do you want disable firewall now? (y/n): ' => 'Poistetaanko käytöstä? (y/n):', + 'Do you want enable firewall now? (y/n): ' => 'Laitetaanko päälle? (y/n):', + 'Storage disk is already mounted...' => 'Tallennuslevy on jo asennettu', + 'Storage disk was mounted successfully...' => 'Tallennuslevy on asennettu onnistuneesti', + 'Valid disks not found...' => 'Vastaavia asemia ei löytynyt', + 'Valid disks are:' => 'Luettelo sopivista levyistä:', + 'Enter the device name:' => 'Anna laitteen nimi:', + 'Do you want reset password? (y/n): ' => 'Haluatko varmasti palauttaa verkkosalasanasi tehdasasetuksiin? (y/n):', + 'Password successfully reset. New login: admin. New password: admin.' => "Salasanan palautus onnistui. Käyttäjätunnus: admin Salasana: admin", + 'Error resetting password.' => "Salasanan palautusvirhe", + 'Install or recovery' => "Asennus/palautus", + 'All settings will be lost!' => 'Palaa tehdasasetuksiin!', + 'All settings will be kept!' => 'Nykyiset asetukset tallennetaan!', + 'Cancel' => 'Peruuttaa', + 'Install' => 'Asentaa', + 'Reinstall to' => 'Päivitä versioon', + 'Firmware version on this system:' => 'Nykyinen järjestelmän laiteohjelmistoversio:', + 'WARNING' => 'HUOMIO', + 'The PBX will reboot after installation.' => 'Järjestelmä käynnistyy uudelleen, kun asennus on valmis', + 'The PBX is about to be installed onto the' => 'MikoPBX asennetaan levylle:', + 'everything on this device will be erased!' => 'kaikki laitteen tiedot poistetaan!', + 'this cannot be undone!' => 'Operaatio on peruuttamaton!', + 'Change language' => 'Vaihda kieli / Muuta käyttöliittymän kieltä', + 'Select the drive to install the system.' => 'Valitse levy järjestelmän asentamista varten', + 'Selected disk:' => 'Valittu asema:', + '(default value = ' => '(oletus = ', + 'Select the drive to store the data.' => 'Valitse levy tietojen tallentamista varten', + 'Partitioning and formatting storage disk' => 'Luo osio ja alusta levy tietojen tallentamiseksi laitteeseen', + 'Update storage partition 4 on disk' => 'Neljännen osion päivittäminen tietojen tallentamiseksi levylle', + 'Installing PBX...' => 'Asennetaan MikoPBX:ää…', + ' - Unmounting partitions...' => 'Poistetaan asennettuja levyosioita…', + ' - Unpacking img...' => 'Päivitetään järjestelmäosiota…', + 'Copying configuration...' => 'Alkumääritysasetuksia täytetään…', + 'Save storage disk settings' => 'Tallennetaan levyasetuksia tallennusta varten', + 'Formatting storage partition 4 on disk' => 'Neljännen osion alustaminen tietojen tallentamiseksi levylle', + 'Warning! Selected disk will be formatted!' => 'Huomio! Valittu levy alustetaan ja kaikki tiedot tuhotaan!', + 'user' => 'käyttäjä', + 'Reboot' => 'Käynnistä MikoPBX uudelleen', + 'Power off' => 'Sammuta', + 'Choose action' => 'Valitse toiminto', + 'Пропущенный вызов' => 'Sinulla on vastaamaton puhelu', + 'Console' => 'Konsoli (Shell)', + 'Failed to mount the disc...' => 'Levyn asentaminen epäonnistui', + 'All processes will be completed. Continue? (y/n):' => 'Kaikki prosessit suoritetaan loppuun. Jatkaa? (y/n):', + 'Configuring using DHCP' => 'Konfigurointi DHCP-palvelimella', + 'Manual setting' => 'Manuaalinen asetus', + 'Storage' => 'Tietojen tallennus', + 'Resize storage' => 'Suurenna levyn kokoa tietojen tallennusta varten käyttämällä koko varaamatonta aluetta', + 'Check storage' => 'Tarkista levy virheiden varalta', + 'Storage unmounted' => 'Tallennuslevyä ei ole kytketty', + 'sd_Filename' => 'Tiedosto', + 'sd_filter' => 'Suodattaa', + 'sd_offset' => 'Offset', + 'sd_lines' => 'Rajoittaa', + 'sd_ShowLog' => 'Lokien katselu', + 'sd_CapturePcap' => 'Kaappaa verkkopaketteja', + 'sd_DownloadPcapFileError' => 'Virhe luotaessa lokiarkistoa', + 'sd_SystemInformation' => 'Järjestelmätiedot', + 'sd_CollectingInfo' => 'Palvelutietojen kerääminen', + 'sd_CollectingLogsInfo' => 'Lokitiedostojen luettelon hakeminen', + 'sd_PackingLogFiles' => 'Kerättyjen tietojen pakkaaminen', + 'sd_ToolTipDownload' => 'Lataa lokitiedosto', + 'sd_ToolTipRefresh' => 'Hanki uusin versio lokitiedostosta', + 'sd_ToolTipAutoUpdate' => 'Päivitä sisältö automaattisesti näytöllä', + 'sd_ToolTipErase' => 'Tyhjennä tiedosto', + 'msg_ErrorHeader' => 'Virhe', + 'msg_WarningHeader' => 'Huomio', + 'msg_infoHeader' => 'Tiedot', + 'adv_SSHPasswordWasChangedSubject' => "Huomio! SSH-salasana on vaihdettu!", + 'adv_SSHPasswordWasChangedBody' => "MikoPBX:n SSH-salasana on vaihdettu!", + 'adv_SSHPasswordWasCompromisedSubject' => 'Huomio! SSH-salasana vaihdettiin ilman kirjautumista MikoPBX-liittymään!', + 'adv_SSHPasswordMismatchStringsHash' => 'SSH-salasana vaihdettiin MikoPBX-verkkoliittymän ulkopuolella', + 'adv_SSHPasswordMismatchFilesHash' => 'MikoPBX SSH -salasana eroaa asetustiedostossa määritetystä salasanasta. Se on saatettu muuttaa manuaalisesti MikoPBX-konsolista.', + 'adv_ThereIsSomeTroublesWithMikoPBX' => 'Huomio! MikoPBX:ssäsi on havaittu ongelmia!', + 'ex_English' => 'englanti', + 'ex_EnglishUK' => 'englanti (UK)', + 'March' => 'maaliskuuta', + 'April' => 'huhtikuu', + 'May' => 'toukokuuta', + 'June' => 'kesäkuuta', + 'Jan' => 'tammikuu', + 'ShortDaySunday' => 'Vos', + 'BreadcrumbTimeSettings' => 'Järjestelmän aika', + 'SubHeaderCallQueues' => 'Puhelut asetetaan pitoon ja jaetaan sitten osallistujien kesken strategian mukaisesti', + 'BreadcrumbCallQueuesmodify' => 'Jonon asettaminen', + 'BreadcrumbOutOffWorkTime' => 'Vapaat työajat', + 'SubHeaderGeneralSettings' => 'Järjestelmän perusparametrien määrittäminen', + 'BreadcrumbIvrMenu' => 'Interaktiiviset äänivalikot - IVR', + 'BreadcrumbIvrMenumodify' => 'IVR-valikon määrittäminen', + 'mm_NetworkSettings' => 'Verkko ja palomuuri', + 'bt_ToolTipRestore' => 'Palauttaa', + 'bt_ToolTipDownload' => 'Lataa', + 'bt_ToolTipCopy' => 'Kopioida', + 'bt_ToolTipDelete' => 'Poistaa', + 'bt_ToolTipUpgradeOnline' => 'Päivitä verkossa', + 'ms_SuccessfulSaved' => 'Asetukset tallennettu', + 'ms_SuccessfulDeleted' => 'Tiedot poistettu', + 'Codecs' => 'koodekit', + 'sip_registration_type' => 'Tilin tyyppi', + 'sip_REG_TYPE_OUTBOUND' => 'Lähtevä rekisteröinti', + 'sip_REG_TYPE_INBOUND' => 'Saapuva rekisteröinti', + 'sip_REG_TYPE_NONE' => 'Todennus IP-osoitteella, ilman salasanaa', + 'pr_SIPPort' => 'SIP-liitäntäportti', + 'pr_Cancel' => 'Peruuttaa', + 'or_RuleAnyNumbers' => 'Kaikki numerot', + 'cq_QueueSetup' => 'Perusparametrit', + 'cq_CallsCallWillBeRoutedTo' => 'puhelut, siirrä kaikki uudet puhelut numeroon ', + 'cq_IfQueueNotAnsweredRepeat' => 'Jos jonoa ei käsitelty peräkkäin ', + 'cq_ThisNumberIsNotFree' => 'Tämä numero on varattu', + 'cq_ValidateNameEmpty' => 'Anna jonon nimi', + 'cq_ValidateExtensionEmpty' => 'Jonon alanumeroa ei ole määritetty', + 'cq_ValidateExtensionDouble' => 'Tälle jonolle määritetty alanumero on jo käytössä', + 'cq_ValidateExtensionNumber' => 'Alanumerossa saa olla vain numeroita', + 'cq_ValidateNoExtensions' => 'Jonon jäseniä ei ole valittu', + 'cq_CallerIDPrefix' => 'Jonon lyhyt nimi, joka näytetään ennen tilaajan soittajatunnusta, esimerkiksi "Myynti"', + 'er_UnauthorizedDescription' => 'Sinulla ei ole pääsyä tälle sivulle.', + 'er_PageNotFound' => 'Sivua ei löydy', + 'er_PageNotFoundDescription' => 'Tätä sivua ei ole olemassa.', + 'er_InternalServerError' => 'Sisäinen palvelinvirhe', + 'ex_CallRecording' => 'Keskustelujen tallentaminen', + 'ex_ValidateRingingBeforeForwardOutOfRange' => 'Reititysasetukset osoittavat, että aika ennen siirtoa on virheellinen. Valitse arvo väliltä {ruleValue}.', + 'ex_ValidateNumberIsEmpty' => 'Työntekijän sisäistä numeroa ei täytetty', + 'tf_ActionPlayMessage' => 'Toista tiedosto %message%', + 'tf_ActionTransferToExtension' => 'Siirrä puhelu numeroon %extension%', + 'tf_TableColumnDatePeriod' => 'Kausi', + 'tf_TableColumnTimePeriod' => 'Aika', + 'tf_TableColumnWeekDaysPeriod' => 'Viikon päivät', + 'tf_TableColumnAction' => 'Toiminta', + 'tf_AllowRestriction' => 'Käytä vain tiettyjä saapuvia reittejä', + 'tf_Description' => 'Kommentti', + 'tf_SelectActionPlayMessage' => 'Toista äänitiedosto', + 'tf_SelectActionRedirectToExtension' => 'Siirrä puhelu', + 'tf_SelectAudioMessage' => 'Valitse äänitiedosto', + 'tf_SelectExtension' => 'Valitse alaliittymän numero', + 'tf_ValidateCheckDateInterval' => 'Tarkista ajanjakso', + 'fw_sipDescription' => 'SIP & RTP - puhelimen rekisteröinti ja puheliikenne', + 'fw_iaxDescription' => 'IAX - puhelimen rekisteröinti ja puheliikenne', + 'mo_NewElementExtensions' => 'Uusi työntekijä', + 'mo_NewElementCallQueues' => 'Uusi soittojono', + 'mo_NewElementIvrMenu' => 'Uusi IVR-valikko', + 'mo_NewElementConferenceRooms' => 'Uusi kokoushuone', + 'mo_NewElementIax' => 'Uusi IAX-toimittaja', + 'gs_SetPassword' => 'Aseta uusi salasana', + 'gs_RedirectToHttps' => 'Ohjaa HTTPS:ään', + 'ts_ManualAdjustDateTime' => 'Säädä aika manuaalisesti', + 'ts_CurrentSystemTime' => 'Nykyinen aika', + 'ts_NTPServer' => 'NTP-palvelimet', + 'ts_ValidateDateTime' => 'Väärä päivämäärä', + 'ms_SMTPSettings' => 'Viestien lähetysasetukset', + 'ms_NotificationTemplatesMissed' => 'Malli - vastaamattomat puhelut', + 'ms_NotificationTemplatesVoicemail' => 'Malli - vastaaja', + 'ms_SMTPHost' => 'SMTP-isäntä', + 'ms_SMTPPort' => 'SMTP-portti', + 'ms_SMTPUsername' => 'SMTP-kirjautuminen', + 'ms_SMTPPassword' => 'SMTP-salasana', + 'ms_SMTPSenderAddress' => 'Lähettäjän osoite', + 'ms_SMTPFromUsername' => 'Lähettäjän nimi', + 'ms_SMTPUseTLS' => 'Käytä TLS:ää', + 'ms_SMTPCertCheck' => 'Tarkista palvelimen varmenne', + 'ms_MailEnableNotifications' => 'Käytä hälytyksiä', + 'iv_TimeoutToRedirect' => 'Alaliittymän numeron syöttämisen odottamisen aikakatkaisu, jonka jälkeen äänitervehdys toistetaan', + 'iv_AllowEnterAnyInternalExtension' => 'Salli minkä tahansa sisäisen numeron lisävalinta', + 'cr_ColumnName' => 'Nimi', + 'cr_Name' => 'Kokoushuoneen nimi', + 'repFirewallRules' => 'Palomuurisääntö - %represent%', + 'repIax' => 'IAX-tili – %represent%', + 'repIncomingRoutingTable' => '%represent%', + 'repIncomingRoutingTableNumber' => 'Saapuvien viestien käsittelysääntö - N%represent%', + 'repLanInterfaces' => 'Järjestelmätiedosto - %represent%', + 'repNetworkFilters' => 'Viivasuodatin - %represent%', + 'repOutgoingRoutingTable' => '%represent%', + 'repOutgoingRoutingTableNumber' => 'Lähtevän postin käsittelysääntö - N%represent%', + 'repOutWorkTimes' => 'Tuntien jälkeen – %represent%', + 'repPbxSettings' => 'Asemaasetukset - %represent%', + 'repSip' => 'SIP-tili - %represent%', + 'lic_ActivateCouponButton' => 'Aktivoi kuponki', + 'lic_RegisterTheSystemButton' => 'Rekisteröidy', + 'lic_SaveLicenseKeyButton' => 'Tallenna avain', + 'lic_GetTrialErrorCheckInternet' => 'Rekisteröinti epäonnistui, tarkista Internetin saatavuus MikoPBX:stä', + 'ex_Japanese' => '日本語', + 'ex_Deutsch' => 'Deutsch', + 'ex_Spanish' => 'Espanol', + 'ex_French' => 'Le français', + 'ex_PortugueseBrazil' => 'Portugali (Brasilia)', + 'ex_Vietnamese' => 'Tiếng việt', + 'ex_Chinese' => '中国人', + 'ex_Dutch' => 'Alankomaat', + 'ex_Georgian' => 'ქართველი', + 'January' => 'tammikuu', + 'February' => 'helmikuu', + 'July' => 'heinäkuu', + 'August' => 'elokuu', + 'September' => 'syyskuu', + 'October' => 'lokakuu', + 'November' => 'marraskuu', + 'December' => 'joulukuu', + 'Feb' => 'helmikuuta', + 'Mar' => 'maaliskuu', + 'Apr' => 'huhtikuu', + 'Jun' => 'kesäkuuta', + 'Jul' => 'heinäkuuta', + 'Aug' => 'elokuu', + 'Sep' => 'syyskuu', + 'Oct' => 'lokakuu', + 'Nov' => 'marraskuu', + 'Dec' => 'joulukuuta', + 'ShortDayMonday' => 'ma', + 'ShortDayTuesday' => 'W', + 'ShortDayWednesday' => 'ke', + 'ShortDayThursday' => 'to', + 'ShortDayFriday' => 'pe', + 'ShortDaySaturday' => 'la', + 'Today' => 'Tänään', + 'Now' => 'Nyt', + 'MetaTegHeadDescription' => 'Yrityspuhelinjärjestelmä', + 'Loading' => 'Ladataan', + 'qf_Qualify' => 'Tuki NAT-istuntoon', + 'qf_Frequency' => 'Lähetystaajuus sekunneissa:', + 'qf_QualifyInstructions' => 'Kun tämä vaihtoehto on käytössä, MikoPBX lähettää SIP OPTIONS -paketteja määritetyllä taajuudella. Tämä on tarpeen NAT-tunneloinnin tukemiseksi reitittimessäsi.', + 'AdvancedOptions' => 'Lisäasetukset', + 'ConnectionSettings' => 'Yhteysasetukset', + 'BreadcrumbAdminCabinet' => 'Hallinnollinen käyttöliittymä', + 'BreadcrumbPBXCoreREST' => 'REST API', + 'BreadcrumbHome' => 'Alkuun', + 'BreadcrumbProviders' => 'Puhelinpalvelujen tarjoajat', + 'SubHeaderProviders' => 'Tilien perustaminen ulkoisten saapuvien ja lähtevien yhteyksien järjestämistä varten', + 'BreadcrumbAsteriskManagers' => 'Asterisk Manager Interface (AMI)', + 'SubHeaderAsteriskManagers' => 'Aseman AMI-rajapinnan käyttöoikeuksien asettaminen', + 'BreadcrumbAsteriskManagersmodify' => 'Tilin asetukset', + 'BreadcrumbProvidersmodifysip' => 'SIP-palveluntarjoajan määrittäminen', + 'BreadcrumbProvidersmodifyiax' => 'IAX-palveluntarjoajan määrittäminen', + 'SubHeaderTimeSettings' => 'Kellon ja kalenterin asettaminen', + 'BreadcrumbMailSettings' => 'Sähköpostiasetukset', + 'lic_FailedCheckLicense' => 'Lisenssipalvelin ei vastannut, tarkista Internet-asetukset', + 'SubHeaderMailSettings' => 'Sähköpostipalvelimen määrittäminen lähettämään ilmoituksia käyttäjille ja järjestelmänvalvojille', + 'BreadcrumbNetwork' => 'Verkkoasetukset', + 'SubHeaderNetwork' => 'Verkkokorttien määrittäminen (DHCP, DNS, GATEWAY, VLAN)', + 'BreadcrumbModify' => 'Säännön määrittäminen', + 'BreadcrumbOutboundRoutes' => 'Lähtevän liikenteen reititys', + 'SubHeaderOutboundRoutes' => 'Säännöt ja mallit puheluiden jakamiseen palveluntarjoajien kautta', + 'BreadcrumbOutboundRoutesmodify' => 'Säännön määrittäminen', + 'BreadcrumbIncomingRoutes' => 'Saapuvan reitityksen', + 'SubHeaderIncomingRoutes' => 'Säännöt ja mallit saapuvien puheluiden jakamiseen', + 'BreadcrumbIncomingRoutesmodify' => 'Säännön määrittäminen', + 'BreadcrumbExtensions' => 'Työntekijät', + 'SubHeaderExtensions' => 'Ensisijaisten puhelinnumeroiden ja henkilökohtaisten edelleenlähetyssääntöjen määrittäminen', + 'BreadcrumbExtensionsmodify' => 'Asetusten muuttaminen', + 'BreadcrumbCallQueues' => 'Puhelujonot', + 'lic_NoInetHeader' => 'Ei pääsyä lisenssipalvelimeen.', + 'lic_GeneralError' => 'Virhe yritettäessä aktivoida lisenssiä', + 'lic_HostLookupFailed' => 'Ei yhteyttä lisenssipalvelimeen, DNS-ongelma', + 'er_Home' => 'Siirry alkuun', + 'rs_RestartPhoneSystem' => 'Käynnistä MikoPBX uudelleen', + 'rs_ShutDownPhoneSystem' => 'Sammuta MikoPBX', + 'auth_ValidatePasswordNotEmpty' => 'Kirjoita salasanasi', + 'auth_ValidateLoginNotEmpty' => 'Anna kirjautumistunnuksesi', + 'auth_SubmitButton' => 'Kirjaudu sisään', + 'auth_WrongLoginPassword' => 'Valtuutus epäonnistui, sinulla on %attempts% yritystä jäljellä', + 'auth_TooManyLoginAttempts' => 'Liian monta kirjautumisyritystä. IP-osoitteesi on estetty %interval% sekunniksi.', + 'log_StartCapturePCAP' => 'Aloita', + 'f2b_Jail_asterisk_error_v2' => 'SIP-valtuutusvirheet (virhe)', + 'upd_Update' => 'Päivittää', + 'ext_TableColumnDeveloper' => 'Kehittäjä', + 'ext_ModuleChangedObjects' => 'Seuraavat kohteet on muutettu', + 'ext_DeleteTitle' => 'Laajennusmoduulin poistaminen', + 'ext_DeleteDescription' => 'Ennen moduulin poistamista se tarkistaa ristiviittaukset muiden moduulien ja järjestelmäasetusten välillä.', + 'ext_KeepModuleSettings' => 'Tallenna nykyiset moduuliasetukset', + 'ext_Cancel' => 'Peruuttaa', + 'ext_Version' => 'Versio', + 'ext_InstallModuleShort' => 'Asentaa', + 'ext_InstallUpdateAction' => 'Suorittaa', + 'adv_StorageDiskUnMounted' => 'Asetusten ja tietojen tallennuslevyä ei ole kytketty!', + 'cal_Today' => 'Tänään', + 'SubHeaderOutOffWorkTime' => 'Aseman toiminnan säännöt aukioloaikojen, pyhäpäivien ja viikonloppujen jälkeen', + 'BreadcrumbOutOffWorkTimemodify' => 'Säännön määrittäminen', + 'lic_MarketplaceText' => 'Rekisteröitymällä Marketplaceen saat käyttöösi lisämoduuleja ja laajennuksia.
      On olemassa ilmaisia moduuleja, jotka olemme poistaneet perustoiminnoista alkuasennuksen yksinkertaistamiseksi, sekä maksullisia moduuleja meiltä ja muilta kehittäjiltä.
      Jos olet kehittäjä, voit ottaa yhteyttä ottaa meihin yhteyttä saadaksesi ohjeet oman moduulin kehittämiseen ja sen lisäämiseen Marketplaceen.', + 'lic_LastQuestionAnswer' => 'Lisenssiin liittyviä usein kysyttyjä kysymyksiä löytyy osoitteesta osoitteessa .', + 'lic_NoInet' => 'Ehkä MikoPBX-palvelimelta ei ole Internet-yhteyttä', + 'lic_NoInetLicMiko' => 'Mahdollisesti rajoitettu pääsy resurssiin lic.mikopbx.com', + 'lic_NoInetNetSettings' => "Tarkista DNS- ja Gateway-asetukset verkkoasetuksista", + 'lic_ReloadPage' => 'Päivitä sivu…', + 'lic_LicenseProblem' => 'Ongelma Marketplacen rekisteröinnissä', + 'lic_ManageLicense' => 'Voit hallita lisenssiäsi, nollata sidoksia ja analysoida ongelmia siirtymällä verkkosivustolle ', + 'lic_ManageLicenseKeyOnSitePreLinkText' => 'Hallitse lisenssiä nollaamalla isäntäsidokset ja tarkastelemalla tilastoja', + 'lic_ManageLicenseKeyOnSiteLinkText' => 'seuraa linkkiä', + 'lic_ManageLicenseKey' => 'Lisenssien hallinta', + 'rs_CurrentCalls' => 'Aktiiviset puhelut', + 'rs_DateCall' => 'aloituspäivämäärä', + 'rs_Src' => 'WHO', + 'rs_Dst' => 'Kenelle', + 'rs_ShutdownRebootMessage' => 'Kun käynnistetään uudelleen tai sammutetaan, kaikki käynnissä olevat puhelut keskeytyvät.', + 'auth_Login' => 'Kirjaudu sisään', + 'auth_Password' => 'Salasana', + 'auth_RememberMe' => 'Muista minut', + 'auth_DefaultCloudPasswordInstructions' => 'Oletussalasana on sama kuin pilvessä olevan virtuaalikoneen yksilöllinen tunniste', + 'log_CaptureMessage' => 'Aloita verkkopakettien kerääminen ja soita puhelu tai muu toiminta, joka aiheuttaa epäonnistumisen. +
      Järjestelmä tallentaa kaikki tällä hetkellä verkkokortin läpi kulkevat paketit lisäanalyysiä varten.', + 'log_StopCapturePCAP' => 'Pysäytä ja lataa', + 'log_DownloadLogs' => 'Lataa kaikki järjestelmälokit', + 'dbg_NoDebugInformation' => 'Ei tietoa', + 'dbg_Header' => 'Virheenkorjaustiedot', +];