From 608920e8a820b31c3978b763b55ffcadd946c236 Mon Sep 17 00:00:00 2001 From: vados-dev Date: Mon, 2 Mar 2026 22:40:09 +0300 Subject: [PATCH] Backup for MikroMaster sucessfully creatd at Mar 02 22:40:09. --- .../20260302/20260302224003-Binary.backup | Bin 0 -> 289700 bytes .../20260302/20260302224003-Config.rsc | 3971 +++++++++++++++++ .../20260302/20260302224003-Diff-Config.rsc | 4 + 3 files changed, 3975 insertions(+) create mode 100644 MikroMaster/20260302/20260302224003-Binary.backup create mode 100644 MikroMaster/20260302/20260302224003-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302224003-Diff-Config.rsc diff --git a/MikroMaster/20260302/20260302224003-Binary.backup b/MikroMaster/20260302/20260302224003-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..ff5ddc1b0a35ef29dcc28367f5b89f49680fce20 GIT binary patch literal 289700 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 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n :global InitSetup;\r\ + \n\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n\r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$InitSetup != true && ((\$ScriptVal->\"name\") != \"AM-Globa\ + lConfig\" || (\$ScriptVal->\"name\") != \"AM-GlobalFunc\")) do={\r\ + \n :if (\$SourceNew = (\$ScriptVal->\"source\") || \$SourceCRLF = (\ + \$ScriptVal->\"source\")) do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") \ + . \"' source did not change. End of lines set to CRLF.\");\r\ + \n if (\$ScriptUpdatesCRLF = false) do={\r\ + \n :put [ :tolf \$SourceNew ];\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\"\ + ) . \"' source update end of lines to LF.\");\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n :global InitSetup (a);\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;};\r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:put \"Add or/and fix Global scheduler...\";\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:put \"Add or/and fix Update Script scheduler\";\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/history/20260302/20260302224003-Diff-Config.rsc b/MikroMaster/history/20260302/20260302224003-Diff-Config.rsc new file mode 100644 index 0000000..551e3b2 --- /dev/null +++ b/MikroMaster/history/20260302/20260302224003-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 22:40:04 by RouterOS 7.21.2 +--- +> # 2026-03-02 22:20:04 by RouterOS 7.21.2 -- 2.52.0