diff --git a/android/app/src/main/kotlin/io/github/omeritzics/updatium/MainActivity.kt b/android/app/src/main/kotlin/io/github/omeritzics/updatium/MainActivity.kt index 193c15dba..7faf8e947 100644 --- a/android/app/src/main/kotlin/io/github/omeritzics/updatium/MainActivity.kt +++ b/android/app/src/main/kotlin/io/github/omeritzics/updatium/MainActivity.kt @@ -5,6 +5,9 @@ import android.content.ComponentName import android.content.Context import android.content.Intent import android.net.Uri +import android.content.pm.ApplicationInfo +import android.content.pm.PackageManager +import android.os.Build import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel diff --git a/assets/translations/ar.json b/assets/translations/ar.json index 8f2edb675..ca4ce9444 100644 --- a/assets/translations/ar.json +++ b/assets/translations/ar.json @@ -30,6 +30,38 @@ "gettingAppInfo": "Getting app info", "username": "اسم المستخدم", "wrongArgNum": "عدد وسائط غير صحيح", + "yaraMalwareScanner": "فحص البرامج الضارة التلقائي (قواعد نمط YARA)", + "yaraScannerDescription": "كشف أساسي للبرامج الضارة باستخدام قواعد مطابقة السلاسل نمط YARA للحماية من التهديدات المعروفة. هذا التطبيق يوفر قدرات أساسية لمطابقة الأنماط. تقع مسؤولية الاستخدام الآمن للتطبيق على المستخدم في النهاية.", + "securitySettings": "إعدادات الأمان", + "enableAutoScan": "تفعيل الفحص التلقائي", + "enableAutoScanDescription": "فحص ملفات APK التي تم تنزيلها تلقائيًا بحثًا عن برامج ضارة قبل التثبيت", + "enableAutoUpdate": "تفعيل التحديث التلقائي", + "enableAutoUpdateDescription": "تحديث قاعدة بيانات تعريفات البرامج الضارة تلقائيًا", + "updateInterval": "الفاصل الزمني للتحديث", + "updateIntervalDescription": "مدى التكرار للتحقق من تعريفات البرامج الضارة الجديدة", + "hours": "ساعات", + "threatLevelFilter": "مرشح مستوى التهديد", + "threatLevelFilterDescription": "الحد الأدنى لمستوى التهديد لتشغيل التنبيهات", + "level1": "المستوى 1", + "lowThreat": "تهديد منخفض", + "level2": "المستوى 2", + "mediumThreat": "تهديد متوسط", + "level3": "المستوى 3", + "highThreat": "تهديد عالٍ", + "quarantineSettings": "إعدادات الحجر الصحي", + "quarantineInfected": "حجر الملفات المصابة", + "quarantineInfectedDescription": "نقل البرامج الضارة المكتشفة إلى الحجر الصحي للسلامة", + "viewQuarantine": "عرض الحجر الصحي", + "viewQuarantineDescription": "إدارة الملفات المحجورة", + "databaseInformation": "معلومات قاعدة البيانات", + "lastUpdate": "آخر تحديث", + "rulesVersion": "إصدار القواعد", + "updateNow": "تحديث الآن", + "updating": "جاري التحديث...", + "rulesUpdatedSuccessfully": "تم تحديث تعريفات البرامج الضارة بنجاح", + "rulesUpdateFailed": "فشل تحديث تعريفات البرامج الضارة", + "quarantineViewComingSoon": "عرض الحجر الصحي قريبًا", + "securityScanBlocked": "تم حظر التثبيت لأن فحص الأمان فشل أو اكتشف تهديدًا", "xIsTrackOnly": "{} للتعقب فقط", "source": "المصدر", "app": "التطبيق", diff --git a/assets/translations/bs.json b/assets/translations/bs.json index 0ab042185..9c58e88ec 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -30,6 +30,37 @@ "gettingAppInfo": "Getting app info", "username": "Korisničko ime", "wrongArgNum": "Naveden je pogrešan broj argumenata", + "yaraMalwareScanner": "Auto Malware Scanning (YARA-style Rules)", + "yaraScannerDescription": "Basic malware detection using YARA-style string matching rules for protection against known threats. This implementation provides fundamental pattern matching capabilities. The responsibility for safe app usage ultimately is on the user.", + "securitySettings": "Security Settings", + "enableAutoScan": "Enable Auto-Scan", + "enableAutoScanDescription": "Automatically scan downloaded APKs for malware before installation", + "enableAutoUpdate": "Enable Auto-Update", + "enableAutoUpdateDescription": "Automatically update malware definition database", + "updateInterval": "Update Interval", + "updateIntervalDescription": "How often to check for new malware definitions", + "hours": "hours", + "threatLevelFilter": "Threat Level Filter", + "threatLevelFilterDescription": "Minimum threat level to trigger alerts", + "level1": "Level 1", + "lowThreat": "Low Threat", + "level2": "Level 2", + "mediumThreat": "Medium Threat", + "level3": "Level 3", + "highThreat": "High Threat", + "quarantineSettings": "Quarantine Settings", + "quarantineInfected": "Quarantine Infected Files", + "quarantineInfectedDescription": "Move detected malware to quarantine for safety", + "viewQuarantine": "View Quarantine", + "viewQuarantineDescription": "Manage quarantined files", + "databaseInformation": "Database Information", + "lastUpdate": "Last Update", + "rulesVersion": "Rules Version", + "updateNow": "Update Now", + "updating": "Updating...", + "rulesUpdatedSuccessfully": "Malware definitions updated successfully", + "rulesUpdateFailed": "Failed to update malware definitions", + "quarantineViewComingSoon": "Quarantine view coming soon", "xIsTrackOnly": "{} je samo za praćenje", "source": "Izvor", "app": "Aplikacija. ", diff --git a/assets/translations/ca.json b/assets/translations/ca.json index b7f54907f..62cf72bea 100644 --- a/assets/translations/ca.json +++ b/assets/translations/ca.json @@ -30,6 +30,37 @@ "gettingAppInfo": "Getting app info", "username": "Nom d'usuari", "wrongArgNum": "Nombre d'arguments proveït invàlid", + "yaraMalwareScanner": "Auto Malware Scanning (YARA-style Rules)", + "yaraScannerDescription": "Basic malware detection using YARA-style string matching rules for protection against known threats. This implementation provides fundamental pattern matching capabilities. The responsibility for safe app usage ultimately is on the user.", + "securitySettings": "Security Settings", + "enableAutoScan": "Enable Auto-Scan", + "enableAutoScanDescription": "Automatically scan downloaded APKs for malware before installation", + "enableAutoUpdate": "Enable Auto-Update", + "enableAutoUpdateDescription": "Automatically update malware definition database", + "updateInterval": "Update Interval", + "updateIntervalDescription": "How often to check for new malware definitions", + "hours": "hours", + "threatLevelFilter": "Threat Level Filter", + "threatLevelFilterDescription": "Minimum threat level to trigger alerts", + "level1": "Level 1", + "lowThreat": "Low Threat", + "level2": "Level 2", + "mediumThreat": "Medium Threat", + "level3": "Level 3", + "highThreat": "High Threat", + "quarantineSettings": "Quarantine Settings", + "quarantineInfected": "Quarantine Infected Files", + "quarantineInfectedDescription": "Move detected malware to quarantine for safety", + "viewQuarantine": "View Quarantine", + "viewQuarantineDescription": "Manage quarantined files", + "databaseInformation": "Database Information", + "lastUpdate": "Last Update", + "rulesVersion": "Rules Version", + "updateNow": "Update Now", + "updating": "Updating...", + "rulesUpdatedSuccessfully": "Malware definitions updated successfully", + "rulesUpdateFailed": "Failed to update malware definitions", + "quarantineViewComingSoon": "Quarantine view coming soon", "xIsTrackOnly": "{} és només per a seguiment", "source": "Font", "app": "Aplicació", diff --git a/assets/translations/cs.json b/assets/translations/cs.json index 842e570c7..9967a7447 100644 --- a/assets/translations/cs.json +++ b/assets/translations/cs.json @@ -30,6 +30,37 @@ "gettingAppInfo": "Getting app info", "username": "Uživatelské jméno", "wrongArgNum": "Nesprávný počet zadaných argumentů", + "yaraMalwareScanner": "Auto Malware Scanning (YARA-style Rules)", + "yaraScannerDescription": "Basic malware detection using YARA-style string matching rules for protection against known threats. This implementation provides fundamental pattern matching capabilities. The responsibility for safe app usage ultimately is on the user.", + "securitySettings": "Security Settings", + "enableAutoScan": "Enable Auto-Scan", + "enableAutoScanDescription": "Automatically scan downloaded APKs for malware before installation", + "enableAutoUpdate": "Enable Auto-Update", + "enableAutoUpdateDescription": "Automatically update malware definition database", + "updateInterval": "Update Interval", + "updateIntervalDescription": "How often to check for new malware definitions", + "hours": "hours", + "threatLevelFilter": "Threat Level Filter", + "threatLevelFilterDescription": "Minimum threat level to trigger alerts", + "level1": "Level 1", + "lowThreat": "Low Threat", + "level2": "Level 2", + "mediumThreat": "Medium Threat", + "level3": "Level 3", + "highThreat": "High Threat", + "quarantineSettings": "Quarantine Settings", + "quarantineInfected": "Quarantine Infected Files", + "quarantineInfectedDescription": "Move detected malware to quarantine for safety", + "viewQuarantine": "View Quarantine", + "viewQuarantineDescription": "Manage quarantined files", + "databaseInformation": "Database Information", + "lastUpdate": "Last Update", + "rulesVersion": "Rules Version", + "updateNow": "Update Now", + "updating": "Updating...", + "rulesUpdatedSuccessfully": "Malware definitions updated successfully", + "rulesUpdateFailed": "Failed to update malware definitions", + "quarantineViewComingSoon": "Quarantine view coming soon", "xIsTrackOnly": "{} je určeno pouze pro sledování", "source": "Zdroj", "app": "Aplikace", diff --git a/assets/translations/da.json b/assets/translations/da.json index 323669567..323168798 100644 --- a/assets/translations/da.json +++ b/assets/translations/da.json @@ -30,6 +30,37 @@ "gettingAppInfo": "Getting app info", "username": "Brugernavn", "wrongArgNum": "Forkert antal argumenter angivet", + "yaraMalwareScanner": "Auto Malware Scanning (YARA-style Rules)", + "yaraScannerDescription": "Basic malware detection using YARA-style string matching rules for protection against known threats. This implementation provides fundamental pattern matching capabilities. The responsibility for safe app usage ultimately is on the user.", + "securitySettings": "Security Settings", + "enableAutoScan": "Enable Auto-Scan", + "enableAutoScanDescription": "Automatically scan downloaded APKs for malware before installation", + "enableAutoUpdate": "Enable Auto-Update", + "enableAutoUpdateDescription": "Automatically update malware definition database", + "updateInterval": "Update Interval", + "updateIntervalDescription": "How often to check for new malware definitions", + "hours": "hours", + "threatLevelFilter": "Threat Level Filter", + "threatLevelFilterDescription": "Minimum threat level to trigger alerts", + "level1": "Level 1", + "lowThreat": "Low Threat", + "level2": "Level 2", + "mediumThreat": "Medium Threat", + "level3": "Level 3", + "highThreat": "High Threat", + "quarantineSettings": "Quarantine Settings", + "quarantineInfected": "Quarantine Infected Files", + "quarantineInfectedDescription": "Move detected malware to quarantine for safety", + "viewQuarantine": "View Quarantine", + "viewQuarantineDescription": "Manage quarantined files", + "databaseInformation": "Database Information", + "lastUpdate": "Last Update", + "rulesVersion": "Rules Version", + "updateNow": "Update Now", + "updating": "Updating...", + "rulesUpdatedSuccessfully": "Malware definitions updated successfully", + "rulesUpdateFailed": "Failed to update malware definitions", + "quarantineViewComingSoon": "Quarantine view coming soon", "xIsTrackOnly": "{} er 'Følg Kun'", "source": "Kilde", "app": "App", diff --git a/assets/translations/de.json b/assets/translations/de.json index 424d058d3..139c229bb 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -30,9 +30,40 @@ "gettingAppInfo": "Getting app info", "username": "Benutzername", "wrongArgNum": "Falsche Anzahl von Argumenten (Parametern) übermittelt", + "yaraMalwareScanner": "Automatische Malware-Erkennung (Powered by YARA)", + "yaraScannerDescription": "Branchenstandardmäßige Malware-Erkennung mit YARA-kompatiblen Regeln für umfassenden Schutz vor Viren, Trojanern und anderen Bedrohungen. Kein Scanner kann 100% Erkennung garantieren, bietet aber starken Schutz vor bekannter Malware. Die Verantwortung für die sichere App-Nutzung liegt letztlich beim Benutzer.", + "securitySettings": "Sicherheitseinstellungen", "xIsTrackOnly": "{} ist nur zur Nachverfolgung", "source": "Quelle", "app": "App", + "enableAutoScan": "Automatische Scan aktivieren", + "enableAutoScanDescription": "Heruntergeladene APKs automatisch auf Malware scannen, vor der Installation", + "enableAutoUpdate": "Automatische Updates aktivieren", + "enableAutoUpdateDescription": "Malware-Definitions-Datenbank automatisch aktualisieren", + "updateInterval": "Update-Intervall", + "updateIntervalDescription": "Wie oft nach neuen Malware-Definitionen gesucht werden soll", + "hours": "Stunden", + "threatLevelFilter": "Bedrohungsstufen-Filter", + "threatLevelFilterDescription": "Mindestbedrohungsstufe für Warnungen", + "level1": "Stufe 1", + "lowThreat": "Niedrige Bedrohung", + "level2": "Stufe 2", + "mediumThreat": "Mittlere Bedrohung", + "level3": "Stufe 3", + "highThreat": "Hohe Bedrohung", + "quarantineSettings": "Quarantäne-Einstellungen", + "quarantineInfected": "Infizierte Dateien quarantänen", + "quarantineInfectedDescription": "Erkannte Malware zur Sicherheit in Quarantäne verschieben", + "viewQuarantine": "Quarantäne anzeigen", + "viewQuarantineDescription": "Quarantänierte Dateien verwalten", + "databaseInformation": "Datenbank-Informationen", + "lastUpdate": "Letzte Aktualisierung", + "rulesVersion": "Regeln-Version", + "updateNow": "Jetzt aktualisieren", + "updating": "Aktualisiere...", + "rulesUpdatedSuccessfully": "Malware-Definitionen erfolgreich aktualisiert", + "rulesUpdateFailed": "Fehler beim Aktualisieren der Malware-Definitionen", + "quarantineViewComingSoon": "Quarantäne-Ansicht kommt bald", "appsFromSourceAreTrackOnly": "Apps aus dieser Quelle sind nur zur Nachverfolgung.", "youPickedTrackOnly": "Sie haben die Option „Nur nachverfolgen“ gewählt.", "trackOnlyAppDescription": "Die App wird auf neue verfügbare Versionen überwacht, aber Updatium wird sie nicht herunterladen oder installieren.", diff --git a/assets/translations/en-EO.json b/assets/translations/en-EO.json index 06f676927..bc48a9017 100644 --- a/assets/translations/en-EO.json +++ b/assets/translations/en-EO.json @@ -30,6 +30,37 @@ "gettingAppInfo": "Getting app info", "username": "Uzantnomo", "wrongArgNum": "Malĝusta nombro da provizitaj argumentoj", + "yaraMalwareScanner": "Auto Malware Scanning (YARA-style Rules)", + "yaraScannerDescription": "Basic malware detection using YARA-style string matching rules for protection against known threats. This implementation provides fundamental pattern matching capabilities. The responsibility for safe app usage ultimately is on the user.", + "securitySettings": "Security Settings", + "enableAutoScan": "Enable Auto-Scan", + "enableAutoScanDescription": "Automatically scan downloaded APKs for malware before installation", + "enableAutoUpdate": "Enable Auto-Update", + "enableAutoUpdateDescription": "Automatically update malware definition database", + "updateInterval": "Update Interval", + "updateIntervalDescription": "How often to check for new malware definitions", + "hours": "hours", + "threatLevelFilter": "Threat Level Filter", + "threatLevelFilterDescription": "Minimum threat level to trigger alerts", + "level1": "Level 1", + "lowThreat": "Low Threat", + "level2": "Level 2", + "mediumThreat": "Medium Threat", + "level3": "Level 3", + "highThreat": "High Threat", + "quarantineSettings": "Quarantine Settings", + "quarantineInfected": "Quarantine Infected Files", + "quarantineInfectedDescription": "Move detected malware to quarantine for safety", + "viewQuarantine": "View Quarantine", + "viewQuarantineDescription": "Manage quarantined files", + "databaseInformation": "Database Information", + "lastUpdate": "Last Update", + "rulesVersion": "Rules Version", + "updateNow": "Update Now", + "updating": "Updating...", + "rulesUpdatedSuccessfully": "Malware definitions updated successfully", + "rulesUpdateFailed": "Failed to update malware definitions", + "quarantineViewComingSoon": "Quarantine view coming soon", "xIsTrackOnly": "{} estas nur sekvitaj", "source": "Fonto", "app": "Apo", diff --git a/assets/translations/en.json b/assets/translations/en.json index fc9622920..2bd0e1db9 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -30,6 +30,37 @@ "gettingAppInfo": "Getting app info", "username": "Username", "wrongArgNum": "Wrong number of arguments provided", + "yaraMalwareScanner": "Auto Malware Scanning (YARA-style Rules)", + "yaraScannerDescription": "Basic malware detection using YARA-style string matching rules for protection against known threats. This implementation provides fundamental pattern matching capabilities. The responsibility for safe app usage ultimately is on the user.", + "securitySettings": "Security Settings", + "enableAutoScan": "Enable Auto-Scan", + "enableAutoScanDescription": "Automatically scan downloaded APKs for malware before installation", + "enableAutoUpdate": "Enable Auto-Update", + "enableAutoUpdateDescription": "Automatically update malware definition database", + "updateInterval": "Update Interval", + "updateIntervalDescription": "How often to check for new malware definitions", + "hours": "hours", + "threatLevelFilter": "Threat Level Filter", + "threatLevelFilterDescription": "Minimum threat level to trigger alerts", + "level1": "Level 1", + "lowThreat": "Low Threat", + "level2": "Level 2", + "mediumThreat": "Medium Threat", + "level3": "Level 3", + "highThreat": "High Threat", + "quarantineSettings": "Quarantine Settings", + "quarantineInfected": "Quarantine Infected Files", + "quarantineInfectedDescription": "Move detected malware to quarantine for safety", + "viewQuarantine": "View Quarantine", + "viewQuarantineDescription": "Manage quarantined files", + "databaseInformation": "Database Information", + "lastUpdate": "Last Update", + "rulesVersion": "Rules Version", + "updateNow": "Update Now", + "updating": "Updating...", + "rulesUpdatedSuccessfully": "Malware definitions updated successfully", + "rulesUpdateFailed": "Failed to update malware definitions", + "quarantineViewComingSoon": "Quarantine view coming soon", "xIsTrackOnly": "{} is track-only", "source": "Source", "app": "App", diff --git a/assets/translations/es.json b/assets/translations/es.json index 78967a218..389170ced 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -30,6 +30,37 @@ "gettingAppInfo": "Getting app info", "username": "Nombre de usuario", "wrongArgNum": "Número de argumentos provistos inválido", + "yaraMalwareScanner": "Escaneo Automático de Malware (Reglas Estilo YARA)", + "yaraScannerDescription": "Detección básica de malware usando reglas de coincidencia de cadenas estilo YARA para protección contra amenazas conocidas. Esta implementación proporciona capacidades fundamentales de coincidencia de patrones. La responsabilidad del uso seguro de la aplicación recae finalmente en el usuario.", + "securitySettings": "Configuración de Seguridad", + "enableAutoScan": "Activar Escaneo Automático", + "enableAutoScanDescription": "Escanear automáticamente los APK descargados en busca de malware antes de la instalación", + "enableAutoUpdate": "Activar Actualización Automática", + "enableAutoUpdateDescription": "Actualizar automáticamente la base de datos de definiciones de malware", + "updateInterval": "Intervalo de Actualización", + "updateIntervalDescription": "Con qué frecuencia buscar nuevas definiciones de malware", + "hours": "horas", + "threatLevelFilter": "Filtro de Nivel de Amenaza", + "threatLevelFilterDescription": "Nivel mínimo de amenaza para activar alertas", + "level1": "Nivel 1", + "lowThreat": "Amenaza Baja", + "level2": "Nivel 2", + "mediumThreat": "Amenaza Media", + "level3": "Nivel 3", + "highThreat": "Amenaza Alta", + "quarantineSettings": "Configuración de Cuarentena", + "quarantineInfected": "Poner en Cuarentena Archivos Infectados", + "quarantineInfectedDescription": "Mover el malware detectado a cuarentena para mayor seguridad", + "viewQuarantine": "Ver Cuarentena", + "viewQuarantineDescription": "Gestionar archivos en cuarentena", + "databaseInformation": "Información de la Base de Datos", + "lastUpdate": "Última Actualización", + "rulesVersion": "Versión de Reglas", + "updateNow": "Actualizar Ahora", + "updating": "Actualizando...", + "rulesUpdatedSuccessfully": "Definiciones de malware actualizadas exitosamente", + "rulesUpdateFailed": "Error al actualizar definiciones de malware", + "quarantineViewComingSoon": "Vista de cuarentena próximamente", "xIsTrackOnly": "{} es de 'sólo seguimiento'", "source": "fuente", "app": "Aplicación", diff --git a/assets/translations/et.json b/assets/translations/et.json index c387efb3b..9ccbf668c 100644 --- a/assets/translations/et.json +++ b/assets/translations/et.json @@ -30,6 +30,37 @@ "gettingAppInfo": "Getting app info", "username": "Kasutajanimi", "wrongArgNum": "Vale arv argumente antud", + "yaraMalwareScanner": "Auto Malware Scanning (YARA-style Rules)", + "yaraScannerDescription": "Basic malware detection using YARA-style string matching rules for protection against known threats. This implementation provides fundamental pattern matching capabilities. The responsibility for safe app usage ultimately is on the user.", + "securitySettings": "Turvaseaded", + "enableAutoScan": "Luba automaatne skaneerimine", + "enableAutoScanDescription": "Skaneeri automaatselt alla laaditud APK-sid malware'i jaoks enne installimist", + "enableAutoUpdate": "Luba automaatne uuendamine", + "enableAutoUpdateDescription": "Uuenda automaatselt malware'i definitsioonide andmebaasi", + "updateInterval": "Uuendamise intervall", + "updateIntervalDescription": "Kui sageli uuendada malware'i definitsioone", + "hours": "tundi", + "threatLevelFilter": "Ohu taseme filter", + "threatLevelFilterDescription": "Miinimum ohu tase, mis põhjustab hoiatusi", + "level1": "Tase 1", + "lowThreat": "Madal ohu tase", + "level2": "Tase 2", + "mediumThreat": "Keskmine ohu tase", + "level3": "Tase 3", + "highThreat": "Kõrge ohu tase", + "quarantineSettings": "Karantiini seaded", + "quarantineInfected": "Karantiiniga nakatunud failid", + "quarantineInfectedDescription": "Nakka tunduvad failid karantiini", + "viewQuarantine": "Vaata karantiini", + "viewQuarantineDescription": "Haldage karantiinis olevaid faile", + "databaseInformation": "Andmebaasi teave", + "lastUpdate": "Viimane uuendus", + "rulesVersion": "Reeglite versioon", + "updateNow": "Uuenda nüüd", + "updating": "Uuendamine...", + "rulesUpdatedSuccessfully": "Malware'i definitsioonid uuendatud edukalt", + "rulesUpdateFailed": "Malware'i definitsioonide uuendamine ebaõnnestus", + "quarantineViewComingSoon": "Karantiini vaade tuleb varsti", "xIsTrackOnly": "{} on ainult jälgimiseks", "source": "Allikas", "app": "Äpp", diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 4f6f1eaa7..13517ba46 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -30,6 +30,37 @@ "gettingAppInfo": "Getting app info", "username": "نام کاربری", "wrongArgNum": "تعداد آرگومان های ارائه شده اشتباه است", + "yaraMalwareScanner": "Auto Malware Scanning (YARA-style Rules)", + "yaraScannerDescription": "Basic malware detection using YARA-style string matching rules for protection against known threats. This implementation provides fundamental pattern matching capabilities. The responsibility for safe app usage ultimately is on the user.", + "securitySettings": "Security Settings", + "enableAutoScan": "Enable Auto-Scan", + "enableAutoScanDescription": "Automatically scan downloaded APKs for malware before installation", + "enableAutoUpdate": "Enable Auto-Update", + "enableAutoUpdateDescription": "Automatically update malware definition database", + "updateInterval": "Update Interval", + "updateIntervalDescription": "How often to check for new malware definitions", + "hours": "hours", + "threatLevelFilter": "Threat Level Filter", + "threatLevelFilterDescription": "Minimum threat level to trigger alerts", + "level1": "Level 1", + "lowThreat": "Low Threat", + "level2": "Level 2", + "mediumThreat": "Medium Threat", + "level3": "Level 3", + "highThreat": "High Threat", + "quarantineSettings": "Quarantine Settings", + "quarantineInfected": "Quarantine Infected Files", + "quarantineInfectedDescription": "Move detected malware to quarantine for safety", + "viewQuarantine": "View Quarantine", + "viewQuarantineDescription": "Manage quarantined files", + "databaseInformation": "Database Information", + "lastUpdate": "Last Update", + "rulesVersion": "Rules Version", + "updateNow": "Update Now", + "updating": "Updating...", + "rulesUpdatedSuccessfully": "Malware definitions updated successfully", + "rulesUpdateFailed": "Failed to update malware definitions", + "quarantineViewComingSoon": "Quarantine view coming soon", "xIsTrackOnly": "{} فقط ردیابی", "source": "منبع", "app": "برنامه", diff --git a/assets/translations/fr.json b/assets/translations/fr.json index a58607a54..7c9cbe211 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -30,9 +30,40 @@ "gettingAppInfo": "Getting app info", "username": "Nom d'utilisateur", "wrongArgNum": "Nombre incorrect des arguments fournis", + "yaraMalwareScanner": "Analyse Antimalware Automatique (Alimenté par YARA)", + "yaraScannerDescription": "Détection de logiciels malveillants de qualité industrielle utilisant des règles compatibles YARA pour une protection complète contre les virus, chevaux de Troie et autres menaces. Bien qu'aucun scanner ne puisse garantir 100% de détection, cela offre une protection solide contre les logiciels malveillants connus. La responsabilité de l'utilisation sécurisée des applications incombe finalement à l'utilisateur.", + "securitySettings": "Paramètres de sécurité", "xIsTrackOnly": "{} en Suivi uniquement", "source": "source", "app": "Appli", + "enableAutoScan": "Activer l'analyse automatique", + "enableAutoScanDescription": "Analyser automatiquement les APK téléchargées à la recherche de logiciels malveillants avant installation", + "enableAutoUpdate": "Activer les mises à jour automatiques", + "enableAutoUpdateDescription": "Mettre à jour automatiquement la base de données des définitions de logiciels malveillants", + "updateInterval": "Intervalle de mise à jour", + "updateIntervalDescription": "Fréquence de recherche des nouvelles définitions de logiciels malveillants", + "hours": "heures", + "threatLevelFilter": "Filtre de niveau de menace", + "threatLevelFilterDescription": "Niveau de menace minimum pour déclencher les alertes", + "level1": "Niveau 1", + "lowThreat": "Menace faible", + "level2": "Niveau 2", + "mediumThreat": "Menace moyenne", + "level3": "Niveau 3", + "highThreat": "Menace élevée", + "quarantineSettings": "Paramètres de quarantaine", + "quarantineInfected": "Mettre en quarantaine les fichiers infectés", + "quarantineInfectedDescription": "Déplacer les logiciels malveillants détectés en quarantaine pour la sécurité", + "viewQuarantine": "Voir la quarantaine", + "viewQuarantineDescription": "Gérer les fichiers en quarantaine", + "databaseInformation": "Informations sur la base de données", + "lastUpdate": "Dernière mise à jour", + "rulesVersion": "Version des règles", + "updateNow": "Mettre à jour maintenant", + "updating": "Mise à jour...", + "rulesUpdatedSuccessfully": "Définitions de logiciels malveillants mises à jour avec succès", + "rulesUpdateFailed": "Échec de la mise à jour des définitions de logiciels malveillants", + "quarantineViewComingSoon": "Vue de quarantaine bientôt disponible", "appsFromSourceAreTrackOnly": "Les applications de cette source sont en 'Suivi uniquement'.", "youPickedTrackOnly": "Vous avez sélectionné l'option 'Suivi uniquement'.", "trackOnlyAppDescription": "L'application sera suivie pour les mises à jour, mais Updatium ne pourra pas la télécharger ou l'installer.", diff --git a/assets/translations/gl.json b/assets/translations/gl.json index 2ba630a0e..97002f1ac 100644 --- a/assets/translations/gl.json +++ b/assets/translations/gl.json @@ -30,6 +30,37 @@ "gettingAppInfo": "Getting app info", "username": "Identificador", "wrongArgNum": "Número de argumentos proporcionados incorrecto", + "yaraMalwareScanner": "Auto Malware Scanning (YARA-style Rules)", + "yaraScannerDescription": "Basic malware detection using YARA-style string matching rules for protection against known threats. This implementation provides fundamental pattern matching capabilities. The responsibility for safe app usage ultimately is on the user.", + "securitySettings": "Security Settings", + "enableAutoScan": "Enable Auto-Scan", + "enableAutoScanDescription": "Automatically scan downloaded APKs for malware before installation", + "enableAutoUpdate": "Enable Auto-Update", + "enableAutoUpdateDescription": "Automatically update malware definition database", + "updateInterval": "Update Interval", + "updateIntervalDescription": "How often to check for new malware definitions", + "hours": "hours", + "threatLevelFilter": "Threat Level Filter", + "threatLevelFilterDescription": "Minimum threat level to trigger alerts", + "level1": "Level 1", + "lowThreat": "Low Threat", + "level2": "Level 2", + "mediumThreat": "Medium Threat", + "level3": "Level 3", + "highThreat": "High Threat", + "quarantineSettings": "Quarantine Settings", + "quarantineInfected": "Quarantine Infected Files", + "quarantineInfectedDescription": "Move detected malware to quarantine for safety", + "viewQuarantine": "View Quarantine", + "viewQuarantineDescription": "Manage quarantined files", + "databaseInformation": "Database Information", + "lastUpdate": "Last Update", + "rulesVersion": "Rules Version", + "updateNow": "Update Now", + "updating": "Updating...", + "rulesUpdatedSuccessfully": "Malware definitions updated successfully", + "rulesUpdateFailed": "Failed to update malware definitions", + "quarantineViewComingSoon": "Quarantine view coming soon", "xIsTrackOnly": "{} é de só-seguimento", "source": "Fonte", "app": "App", diff --git a/assets/translations/he.json b/assets/translations/he.json index a3e47990c..a20a4fc99 100644 --- a/assets/translations/he.json +++ b/assets/translations/he.json @@ -30,7 +30,38 @@ "gettingAppInfo": "מתקבל מידע על היישום", "username": "שם משתמש", "wrongArgNum": "סופק מספר ארגומנטים שגוי", - "xIsTrackOnly": "המקור {} מיועד למעקב עדכונים בלבד", + "yaraMalwareScanner": "Auto Malware Scanning (YARA-style Rules)", + "yaraScannerDescription": "Basic malware detection using YARA-style string matching rules for protection against known threats. This implementation provides fundamental pattern matching capabilities. The responsibility for safe app usage ultimately is on the user.", + "securitySettings": "Security Settings", + "enableAutoScan": "Enable Auto-Scan", + "enableAutoScanDescription": "Automatically scan downloaded APKs for malware before installation", + "enableAutoUpdate": "Enable Auto-Update", + "enableAutoUpdateDescription": "Automatically update malware definition database", + "updateInterval": "Update Interval", + "updateIntervalDescription": "How often to check for new malware definitions", + "hours": "hours", + "threatLevelFilter": "Threat Level Filter", + "threatLevelFilterDescription": "Minimum threat level to trigger alerts", + "level1": "Level 1", + "lowThreat": "Low Threat", + "level2": "Level 2", + "mediumThreat": "Medium Threat", + "level3": "Level 3", + "highThreat": "High Threat", + "quarantineSettings": "Quarantine Settings", + "quarantineInfected": "Quarantine Infected Files", + "quarantineInfectedDescription": "Move detected malware to quarantine for safety", + "viewQuarantine": "View Quarantine", + "viewQuarantineDescription": "Manage quarantined files", + "databaseInformation": "Database Information", + "lastUpdate": "Last Update", + "rulesVersion": "Rules Version", + "updateNow": "Update Now", + "updating": "Updating...", + "rulesUpdatedSuccessfully": "Malware definitions updated successfully", + "rulesUpdateFailed": "Failed to update malware definitions", + "quarantineViewComingSoon": "Quarantine view coming soon", + "xIsTrackOnly": "היישום {} מסומן למעקב עדכונים בלבד", "source": "מקור", "app": "יישום", "appsFromSourceAreTrackOnly": "יישומים ממקור זה ניתנים למעקב עדכונים בלבד.", @@ -43,7 +74,7 @@ "appSourceURL": "כתובת המקור של היישום", "error": "שגיאה", "add": "הוספה", - "advanced": "Advanced", + "advanced": "אפשרויות מתקדמות", "searchSomeSourcesLabel": "חיפוש (מספר מקורות בלבד)", "search": "חיפוש", "searching": "מתבצע חיפוש", diff --git a/assets/translations/hu.json b/assets/translations/hu.json index c0a8a204e..9329fe42d 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -30,6 +30,37 @@ "gettingAppInfo": "Getting app info", "username": "Felhasználónév", "wrongArgNum": "A megadott argumentumok száma nem megfelelő", + "yaraMalwareScanner": "Auto Malware Scanning (YARA-style Rules)", + "yaraScannerDescription": "Basic malware detection using YARA-style string matching rules for protection against known threats. This implementation provides fundamental pattern matching capabilities. The responsibility for safe app usage ultimately is on the user.", + "securitySettings": "Security Settings", + "enableAutoScan": "Enable Auto-Scan", + "enableAutoScanDescription": "Automatically scan downloaded APKs for malware before installation", + "enableAutoUpdate": "Enable Auto-Update", + "enableAutoUpdateDescription": "Automatically update malware definition database", + "updateInterval": "Update Interval", + "updateIntervalDescription": "How often to check for new malware definitions", + "hours": "hours", + "threatLevelFilter": "Threat Level Filter", + "threatLevelFilterDescription": "Minimum threat level to trigger alerts", + "level1": "Level 1", + "lowThreat": "Low Threat", + "level2": "Level 2", + "mediumThreat": "Medium Threat", + "level3": "Level 3", + "highThreat": "High Threat", + "quarantineSettings": "Quarantine Settings", + "quarantineInfected": "Quarantine Infected Files", + "quarantineInfectedDescription": "Move detected malware to quarantine for safety", + "viewQuarantine": "View Quarantine", + "viewQuarantineDescription": "Manage quarantined files", + "databaseInformation": "Database Information", + "lastUpdate": "Last Update", + "rulesVersion": "Rules Version", + "updateNow": "Update Now", + "updating": "Updating...", + "rulesUpdatedSuccessfully": "Malware definitions updated successfully", + "rulesUpdateFailed": "Failed to update malware definitions", + "quarantineViewComingSoon": "Quarantine view coming soon", "xIsTrackOnly": "A(z) {} csak nyomon követhető", "source": "Forrás", "app": "Alkalmazás", diff --git a/assets/translations/id.json b/assets/translations/id.json index 52beb38be..b465f0494 100644 --- a/assets/translations/id.json +++ b/assets/translations/id.json @@ -30,6 +30,37 @@ "gettingAppInfo": "Getting app info", "username": "Nama pengguna", "wrongArgNum": "Salah memberikan jumlah argumen", + "yaraMalwareScanner": "Auto Malware Scanning (YARA-style Rules)", + "yaraScannerDescription": "Basic malware detection using YARA-style string matching rules for protection against known threats. This implementation provides fundamental pattern matching capabilities. The responsibility for safe app usage ultimately is on the user.", + "securitySettings": "Security Settings", + "enableAutoScan": "Enable Auto-Scan", + "enableAutoScanDescription": "Automatically scan downloaded APKs for malware before installation", + "enableAutoUpdate": "Enable Auto-Update", + "enableAutoUpdateDescription": "Automatically update malware definition database", + "updateInterval": "Update Interval", + "updateIntervalDescription": "How often to check for new malware definitions", + "hours": "hours", + "threatLevelFilter": "Threat Level Filter", + "threatLevelFilterDescription": "Minimum threat level to trigger alerts", + "level1": "Level 1", + "lowThreat": "Low Threat", + "level2": "Level 2", + "mediumThreat": "Medium Threat", + "level3": "Level 3", + "highThreat": "High Threat", + "quarantineSettings": "Quarantine Settings", + "quarantineInfected": "Quarantine Infected Files", + "quarantineInfectedDescription": "Move detected malware to quarantine for safety", + "viewQuarantine": "View Quarantine", + "viewQuarantineDescription": "Manage quarantined files", + "databaseInformation": "Database Information", + "lastUpdate": "Last Update", + "rulesVersion": "Rules Version", + "updateNow": "Update Now", + "updating": "Updating...", + "rulesUpdatedSuccessfully": "Malware definitions updated successfully", + "rulesUpdateFailed": "Failed to update malware definitions", + "quarantineViewComingSoon": "Quarantine view coming soon", "xIsTrackOnly": "{} adalah Pelacakan Saja", "source": "Sumber", "app": "Aplikasi", diff --git a/assets/translations/it.json b/assets/translations/it.json index e529c0440..4f2564e98 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -30,6 +30,37 @@ "gettingAppInfo": "Getting app info", "username": "Nome utente", "wrongArgNum": "Numero di argomenti forniti errato", + "yaraMalwareScanner": "Scansione Automatica Malware (Regole Stile YARA)", + "yaraScannerDescription": "Rilevamento di malware di base utilizzando regole di corrispondenza delle stringhe in stile YARA per la protezione contro minacce conosciute. Questa implementazione fornisce capacità fondamentali di corrispondenza dei pattern. La responsabilità dell'uso sicuro dell'app spetta infine all'utente.", + "securitySettings": "Impostazioni di Sicurezza", + "enableAutoScan": "Abilita Scansione Automatica", + "enableAutoScanDescription": "Scansiona automaticamente gli APK scaricati alla ricerca di malware prima dell'installazione", + "enableAutoUpdate": "Abilita Aggiornamento Automatico", + "enableAutoUpdateDescription": "Aggiorna automaticamente il database delle definizioni malware", + "updateInterval": "Intervallo di Aggiornamento", + "updateIntervalDescription": "Frequenza con cui cercare nuove definizioni malware", + "hours": "ore", + "threatLevelFilter": "Filtro Livello Minaccia", + "threatLevelFilterDescription": "Livello minimo di minaccia per attivare avvisi", + "level1": "Livello 1", + "lowThreat": "Minaccia Bassa", + "level2": "Livello 2", + "mediumThreat": "Minaccia Media", + "level3": "Livello 3", + "highThreat": "Minaccia Alta", + "quarantineSettings": "Impostazioni Quarantena", + "quarantineInfected": "Metti in Quarantena File Infetti", + "quarantineInfectedDescription": "Sposta il malware rilevato in quarantena per sicurezza", + "viewQuarantine": "Visualizza Quarantena", + "viewQuarantineDescription": "Gestisci file in quarantena", + "databaseInformation": "Informazioni Database", + "lastUpdate": "Ultimo Aggiornamento", + "rulesVersion": "Versione Regole", + "updateNow": "Aggiorna Ora", + "updating": "Aggiornamento...", + "rulesUpdatedSuccessfully": "Definizioni malware aggiornate con successo", + "rulesUpdateFailed": "Fallito aggiornamento definizioni malware", + "quarantineViewComingSoon": "Vista quarantena in arrivo", "xIsTrackOnly": "{} è in modalità Solo-Monitoraggio", "source": "Fonte", "app": "App", diff --git a/assets/translations/ja.json b/assets/translations/ja.json index f2e2cd488..5c043b947 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -30,6 +30,37 @@ "gettingAppInfo": "Getting app info", "username": "ユーザー名", "wrongArgNum": "引数の数が間違っています", + "yaraMalwareScanner": "自動マルウェアスキャン (YARAスタイルルール)", + "yaraScannerDescription": "既知の脅威から保護するため、YARAスタイルの文字列マッチングルールを使用した基本的なマルウェア検出。この実装は基本的なパターンマッチング機能を提供します。アプリの安全な使用の最終的な責任はユーザーにあります。", + "securitySettings": "セキュリティ設定", + "enableAutoScan": "自動スキャンを有効にする", + "enableAutoScanDescription": "インストール前にダウンロードしたAPKを自動でマルウェアスキャンする", + "enableAutoUpdate": "自動更新を有効にする", + "enableAutoUpdateDescription": "マルウェア定義データベースを自動的に更新する", + "updateInterval": "更新間隔", + "updateIntervalDescription": "新しいマルウェア定義をチェックする頻度", + "hours": "時間", + "threatLevelFilter": "脅威レベルフィルター", + "threatLevelFilterDescription": "アラートをトリガーする最小脅威レベル", + "level1": "レベル1", + "lowThreat": "低脅威", + "level2": "レベル2", + "mediumThreat": "中脅威", + "level3": "レベル3", + "highThreat": "高脅威", + "quarantineSettings": "検疫設定", + "quarantineInfected": "感染ファイルを検疫", + "quarantineInfectedDescription": "検出されたマルウェアを安全のため検疫に移動する", + "viewQuarantine": "検疫を表示", + "viewQuarantineDescription": "検疫されたファイルを管理する", + "databaseInformation": "データベース情報", + "lastUpdate": "最終更新", + "rulesVersion": "ルールバージョン", + "updateNow": "今すぐ更新", + "updating": "更新中...", + "rulesUpdatedSuccessfully": "マルウェア定義が正常に更新されました", + "rulesUpdateFailed": "マルウェア定義の更新に失敗しました", + "quarantineViewComingSoon": "検疫ビューは近日公開", "xIsTrackOnly": "{} は「追跡のみ」です", "source": "ソース", "app": "アプリ", diff --git a/assets/translations/ko.json b/assets/translations/ko.json index b452743b0..76514c80f 100644 --- a/assets/translations/ko.json +++ b/assets/translations/ko.json @@ -30,7 +30,38 @@ "gettingAppInfo": "Getting app info", "username": "사용자 이름", "wrongArgNum": "잘못된 인수 수 제공", - "xIsTrackOnly": "{}는 추적 전용입니다", + "yaraMalwareScanner": "Auto Malware Scanning (YARA-style Rules)", + "yaraScannerDescription": "Basic malware detection using YARA-style string matching rules for protection against known threats. This implementation provides fundamental pattern matching capabilities. The responsibility for safe app usage ultimately is on the user.", + "securitySettings": "Security Settings", + "enableAutoScan": "Enable Auto-Scan", + "enableAutoScanDescription": "Automatically scan downloaded APKs for malware before installation", + "enableAutoUpdate": "Enable Auto-Update", + "enableAutoUpdateDescription": "Automatically update malware definition database", + "updateInterval": "Update Interval", + "updateIntervalDescription": "How often to check for new malware definitions", + "hours": "hours", + "threatLevelFilter": "Threat Level Filter", + "threatLevelFilterDescription": "Minimum threat level to trigger alerts", + "level1": "Level 1", + "lowThreat": "Low Threat", + "level2": "Level 2", + "mediumThreat": "Medium Threat", + "level3": "Level 3", + "highThreat": "High Threat", + "quarantineSettings": "Quarantine Settings", + "quarantineInfected": "Quarantine Infected Files", + "quarantineInfectedDescription": "Move detected malware to quarantine for safety", + "viewQuarantine": "View Quarantine", + "viewQuarantineDescription": "Manage quarantined files", + "databaseInformation": "Database Information", + "lastUpdate": "Last Update", + "rulesVersion": "Rules Version", + "updateNow": "Update Now", + "updating": "Updating...", + "rulesUpdatedSuccessfully": "Malware definitions updated successfully", + "rulesUpdateFailed": "Failed to update malware definitions", + "quarantineViewComingSoon": "Quarantine view coming soon", + "xIsTrackOnly": "{}\ub294 \ucd94\uc801 \uc804\uc6a9\uc785\ub2c8\ub2e4", "source": "소스", "app": "앱", "appsFromSourceAreTrackOnly": "이 소스의 앱은 '추적 전용'입니다.", diff --git a/assets/translations/ml.json b/assets/translations/ml.json index 8551019c2..a4a74b0ef 100644 --- a/assets/translations/ml.json +++ b/assets/translations/ml.json @@ -30,6 +30,37 @@ "gettingAppInfo": "Getting app info", "username": "ഉപയോക്തൃനാമം", "wrongArgNum": "തെറ്റായ എണ്ണം ആർഗ്യുമെന്റുകൾ നൽകി", + "yaraMalwareScanner": "ഓട്ടോ മാൽവെയർ സ്കാനിംഗ് (YARA-സ്റ്റൈൽ നിയമങ്ങൾ)", + "yaraScannerDescription": "അറിയപ്പെടുന്ന ഭീഷണികൾക്കെതിരെ സംരക്ഷണത്തിനായി യാര-സ്റ്റൈൽ സ്ട്രിംഗ് പരന്ന നിയമങ്ങൾ ഉപയോഗിച്ചുള്ള അടിസ്ഥാന മാൽവെയർ കണ്ടെത്തൽ. ഈ നടപ്പിലെടുക്കൽ അടിസ്ഥാന പാറ്റേൺ പരന്ന ശേഷികൾ നൽകുന്നു. സുരക്ഷിതമായ ആപ്പ് ഉപയോഗത്തിനുള്ള ഉത്തരവാദിത്തം അവസാനം ഉപയോക്താവിനാണ്.", + "securitySettings": "സുരക്ഷാ ക്രമീകരണങ്ങൾ", + "enableAutoScan": "ഓട്ടോ സ്കാൻ സജ്ജമാക്കുക", + "enableAutoScanDescription": "ഇൻസ്റ്റാളേഷൻ മുമ്പ് ഡൗൺലോഡ് ചെയ്ത എപികെകൾക്ക് മാൽവെയർ സ്കാൻ ചെയ്യുക", + "enableAutoUpdate": "ഓട്ടോ അപ്‌ഡേറ്റ് സജ്ജമാക്കുക", + "enableAutoUpdateDescription": "മാൽവെയർ നിർവചന ഡാറ്റാബേസ് ഓട്ടോമാറ്റിക്കായി അപ്‌ഡേറ്റ് ചെയ്യുക", + "updateInterval": "അപ്‌ഡേറ്റ് ഇടവേള", + "updateIntervalDescription": "പുതിയ മാൽവെയർ നിർവചനങ്ങൾക്കായി എത്രയും വേഗം പരിശോധിക്കണം", + "hours": "മണിക്കൂറുകൾ", + "threatLevelFilter": "ഭീഷണി തലം ഫിൽട്ടർ", + "threatLevelFilterDescription": "അറിയിപ്പുകൾക്ക് കാരണമാകുന്ന കുറഞ്ഞ ഭീഷണി തലം", + "level1": "തലം 1", + "lowThreat": "കുറഞ്ഞ ഭീഷണി", + "level2": "തലം 2", + "mediumThreat": "മധ്യമ ഭീഷണി", + "level3": "തലം 3", + "highThreat": "ഉയർന്ന ഭീഷണി", + "quarantineSettings": "ക്വാറന്റൈൻ ക്രമീകരണങ്ങൾ", + "quarantineInfected": "ബാധിത ഫയലുകൾ ക്വാറന്റൈൻ ചെയ്യുക", + "quarantineInfectedDescription": "കണ്ടെത്തിയ മാൽവെയറിനെ സുരക്ഷിതമായി സൂക്ഷിക്കുന്നതിന് ക്വാറന്റൈനിലേക്ക് മാറ്റുക", + "viewQuarantine": "ക്വാറന്റൈൻ കാണുക", + "viewQuarantineDescription": "ക്വാറന്റൈൻ ചെയ്ത ഫയലുകൾ കൈകാര്യം ചെയ്യുക", + "databaseInformation": "ഡാറ്റാബേസ് വിവരങ്ങൾ", + "lastUpdate": "അവസാന അപ്‌ഡേറ്റ്", + "rulesVersion": "നിയമ പതിപ്പ്", + "updateNow": "ഇപ്പോൾ അപ്‌ഡേറ്റ് ചെയ്യുക", + "updating": "അപ്‌ഡേറ്റ് ചെയ്യുന്നത്...", + "rulesUpdatedSuccessfully": "മാൽവെയർ നിർവചനങ്ങൾ വിജയകരമായി അപ്‌ഡേറ്റ് ചെയ്തു", + "rulesUpdateFailed": "മാൽവെയർ നിർവചനങ്ങൾ അപ്‌ഡേറ്റ് ചെയ്യാൻ കഴിഞ്ഞില്ല", + "quarantineViewComingSoon": "ക്വാറന്റൈൻ കാഴ്ച ഉടൻ വരും", "xIsTrackOnly": "{} ട്രാക്ക്-മാത്രം ആണ്", "source": "ഉറവിടം", "app": "ആപ്പ്", diff --git a/assets/translations/nl.json b/assets/translations/nl.json index 0484d443c..0531913a7 100644 --- a/assets/translations/nl.json +++ b/assets/translations/nl.json @@ -30,6 +30,37 @@ "gettingAppInfo": "Getting app info", "username": "Gebruikersnaam", "wrongArgNum": "Incorrect aantal argumenten.", + "yaraMalwareScanner": "Auto Malware Scanning (YARA-style Rules)", + "yaraScannerDescription": "Basic malware detection using YARA-style string matching rules for protection against known threats. This implementation provides fundamental pattern matching capabilities. The responsibility for safe app usage ultimately is on the user.", + "securitySettings": "Security Settings", + "enableAutoScan": "Enable Auto-Scan", + "enableAutoScanDescription": "Automatically scan downloaded APKs for malware before installation", + "enableAutoUpdate": "Enable Auto-Update", + "enableAutoUpdateDescription": "Automatically update malware definition database", + "updateInterval": "Update Interval", + "updateIntervalDescription": "How often to check for new malware definitions", + "hours": "hours", + "threatLevelFilter": "Threat Level Filter", + "threatLevelFilterDescription": "Minimum threat level to trigger alerts", + "level1": "Level 1", + "lowThreat": "Low Threat", + "level2": "Level 2", + "mediumThreat": "Medium Threat", + "level3": "Level 3", + "highThreat": "High Threat", + "quarantineSettings": "Quarantine Settings", + "quarantineInfected": "Quarantine Infected Files", + "quarantineInfectedDescription": "Move detected malware to quarantine for safety", + "viewQuarantine": "View Quarantine", + "viewQuarantineDescription": "Manage quarantined files", + "databaseInformation": "Database Information", + "lastUpdate": "Last Update", + "rulesVersion": "Rules Version", + "updateNow": "Update Now", + "updating": "Updating...", + "rulesUpdatedSuccessfully": "Malware definitions updated successfully", + "rulesUpdateFailed": "Failed to update malware definitions", + "quarantineViewComingSoon": "Quarantine view coming soon", "xIsTrackOnly": "{} is 'Alleen volgen'", "source": "Bron", "app": "App", diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 0ef5bc48f..48f5d8894 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -30,6 +30,37 @@ "gettingAppInfo": "Getting app info", "username": "Nazwa użytkownika", "wrongArgNum": "Nieprawidłowa liczba podanych argumentów", + "yaraMalwareScanner": "Auto Malware Scanning (YARA-style Rules)", + "yaraScannerDescription": "Basic malware detection using YARA-style string matching rules for protection against known threats. This implementation provides fundamental pattern matching capabilities. The responsibility for safe app usage ultimately is on the user.", + "securitySettings": "Security Settings", + "enableAutoScan": "Enable Auto-Scan", + "enableAutoScanDescription": "Automatically scan downloaded APKs for malware before installation", + "enableAutoUpdate": "Enable Auto-Update", + "enableAutoUpdateDescription": "Automatically update malware definition database", + "updateInterval": "Update Interval", + "updateIntervalDescription": "How often to check for new malware definitions", + "hours": "hours", + "threatLevelFilter": "Threat Level Filter", + "threatLevelFilterDescription": "Minimum threat level to trigger alerts", + "level1": "Level 1", + "lowThreat": "Low Threat", + "level2": "Level 2", + "mediumThreat": "Medium Threat", + "level3": "Level 3", + "highThreat": "High Threat", + "quarantineSettings": "Quarantine Settings", + "quarantineInfected": "Quarantine Infected Files", + "quarantineInfectedDescription": "Move detected malware to quarantine for safety", + "viewQuarantine": "View Quarantine", + "viewQuarantineDescription": "Manage quarantined files", + "databaseInformation": "Database Information", + "lastUpdate": "Last Update", + "rulesVersion": "Rules Version", + "updateNow": "Update Now", + "updating": "Updating...", + "rulesUpdatedSuccessfully": "Malware definitions updated successfully", + "rulesUpdateFailed": "Failed to update malware definitions", + "quarantineViewComingSoon": "Quarantine view coming soon", "xIsTrackOnly": "{} jest tylko obserwowane", "source": "Źródło", "app": "Aplikacja", diff --git a/assets/translations/pt-BR.json b/assets/translations/pt-BR.json index 7943b3ce1..48b5465d3 100644 --- a/assets/translations/pt-BR.json +++ b/assets/translations/pt-BR.json @@ -30,6 +30,37 @@ "gettingAppInfo": "Getting app info", "username": "Nome de usuário", "wrongArgNum": "Número errado de argumentos fornecidos", + "yaraMalwareScanner": "Auto Malware Scanning (YARA-style Rules)", + "yaraScannerDescription": "Basic malware detection using YARA-style string matching rules for protection against known threats. This implementation provides fundamental pattern matching capabilities. The responsibility for safe app usage ultimately is on the user.", + "securitySettings": "Security Settings", + "enableAutoScan": "Enable Auto-Scan", + "enableAutoScanDescription": "Automatically scan downloaded APKs for malware before installation", + "enableAutoUpdate": "Enable Auto-Update", + "enableAutoUpdateDescription": "Automatically update malware definition database", + "updateInterval": "Update Interval", + "updateIntervalDescription": "How often to check for new malware definitions", + "hours": "hours", + "threatLevelFilter": "Threat Level Filter", + "threatLevelFilterDescription": "Minimum threat level to trigger alerts", + "level1": "Level 1", + "lowThreat": "Low Threat", + "level2": "Level 2", + "mediumThreat": "Medium Threat", + "level3": "Level 3", + "highThreat": "High Threat", + "quarantineSettings": "Quarantine Settings", + "quarantineInfected": "Quarantine Infected Files", + "quarantineInfectedDescription": "Move detected malware to quarantine for safety", + "viewQuarantine": "View Quarantine", + "viewQuarantineDescription": "Manage quarantined files", + "databaseInformation": "Database Information", + "lastUpdate": "Last Update", + "rulesVersion": "Rules Version", + "updateNow": "Update Now", + "updating": "Updating...", + "rulesUpdatedSuccessfully": "Malware definitions updated successfully", + "rulesUpdateFailed": "Failed to update malware definitions", + "quarantineViewComingSoon": "Quarantine view coming soon", "xIsTrackOnly": "{} é somente de rastreio", "source": "Fonte", "app": "Aplicativo", diff --git a/assets/translations/pt.json b/assets/translations/pt.json index 7d3f1066d..f285bf059 100644 --- a/assets/translations/pt.json +++ b/assets/translations/pt.json @@ -30,6 +30,37 @@ "gettingAppInfo": "Getting app info", "username": "Nome de usuário", "wrongArgNum": "Número de argumentos errado", + "yaraMalwareScanner": "Escaneamento Automático de Malware (Regras Estilo YARA)", + "yaraScannerDescription": "Detecção básica de malware usando regras de correspondência de strings estilo YARA para proteção contra ameaças conhecidas. Esta implementação fornece capacidades fundamentais de correspondência de padrões. A responsabilidade pelo uso seguro do aplicativo cabe finalmente ao usuário.", + "securitySettings": "Configurações de Segurança", + "enableAutoScan": "Ativar Escaneamento Automático", + "enableAutoScanDescription": "Escanear automaticamente os APKs baixados em busca de malware antes da instalação", + "enableAutoUpdate": "Ativar Atualização Automática", + "enableAutoUpdateDescription": "Atualizar automaticamente o banco de dados de definições de malware", + "updateInterval": "Intervalo de Atualização", + "updateIntervalDescription": "Com que frequência verificar novas definições de malware", + "hours": "horas", + "threatLevelFilter": "Filtro de Nível de Ameaça", + "threatLevelFilterDescription": "Nível mínimo de ameaça para acionar alertas", + "level1": "Nível 1", + "lowThreat": "Ameaça Baixa", + "level2": "Nível 2", + "mediumThreat": "Ameaça Média", + "level3": "Nível 3", + "highThreat": "Ameaça Alta", + "quarantineSettings": "Configurações de Quarentena", + "quarantineInfected": "Colocar Arquivos Infectados em Quarentena", + "quarantineInfectedDescription": "Mover malware detectado para quarentena para segurança", + "viewQuarantine": "Ver Quarentena", + "viewQuarantineDescription": "Gerenciar arquivos em quarentena", + "databaseInformation": "Informações do Banco de Dados", + "lastUpdate": "Última Atualização", + "rulesVersion": "Versão das Regras", + "updateNow": "Atualizar Agora", + "updating": "Atualizando...", + "rulesUpdatedSuccessfully": "Definições de malware atualizadas com sucesso", + "rulesUpdateFailed": "Falha ao atualizar definições de malware", + "quarantineViewComingSoon": "Visualização de quarentena em breve", "xIsTrackOnly": "{} é 'Apenas monitorar'", "source": "Fonte", "app": "Aplicação", diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 5ef233f13..56220a779 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -30,6 +30,37 @@ "gettingAppInfo": "Getting app info", "username": "Имя пользователя", "wrongArgNum": "Неправильное количество предоставленных аргументов", + "yaraMalwareScanner": "Автоматическое сканирование на вредоносное ПО (правила в стиле YARA)", + "yaraScannerDescription": "Базовое обнаружение вредоносного ПО с использованием правил сопоставления строк в стиле YARA для защиты от известных угроз. Эта реализация обеспечивает фундаментальные возможности сопоставления шаблонов. Конечная ответственность за безопасное использование приложения лежит на пользователе.", + "securitySettings": "Настройки безопасности", + "enableAutoScan": "Включить автоматическое сканирование", + "enableAutoScanDescription": "Автоматически сканировать загруженные APK на наличие вредоносного ПО перед установкой", + "enableAutoUpdate": "Включить автоматическое обновление", + "enableAutoUpdateDescription": "Автоматически обновлять базу данных определений вредоносного ПО", + "updateInterval": "Интервал обновления", + "updateIntervalDescription": "Как часто проверять новые определения вредоносного ПО", + "hours": "часов", + "threatLevelFilter": "Фильтр уровня угрозы", + "threatLevelFilterDescription": "Минимальный уровень угрозы для triggering оповещений", + "level1": "Уровень 1", + "lowThreat": "Низкая угроза", + "level2": "Уровень 2", + "mediumThreat": "Средняя угроза", + "level3": "Уровень 3", + "highThreat": "Высокая угроза", + "quarantineSettings": "Настройки карантина", + "quarantineInfected": "Поместить инфицированные файлы в карантин", + "quarantineInfectedDescription": "Переместить обнаруженное вредоносное ПО в карантин для безопасности", + "viewQuarantine": "Просмотр карантина", + "viewQuarantineDescription": "Управление файлами в карантине", + "databaseInformation": "Информация о базе данных", + "lastUpdate": "Последнее обновление", + "rulesVersion": "Версия правил", + "updateNow": "Обновить сейчас", + "updating": "Обновление...", + "rulesUpdatedSuccessfully": "Определения вредоносного ПО успешно обновлены", + "rulesUpdateFailed": "Не удалось обновить определения вредоносного ПО", + "quarantineViewComingSoon": "Просмотр карантина скоро будет доступен", "xIsTrackOnly": "{} только для отслеживания", "source": "Источник", "app": "Приложение", diff --git a/assets/translations/sv.json b/assets/translations/sv.json index 7d27609ba..bda00170f 100644 --- a/assets/translations/sv.json +++ b/assets/translations/sv.json @@ -30,6 +30,37 @@ "gettingAppInfo": "Getting app info", "username": "Användarnamn", "wrongArgNum": "Fel antal argument har angetts", + "yaraMalwareScanner": "Auto Malware Scanning (YARA-style Rules)", + "yaraScannerDescription": "Basic malware detection using YARA-style string matching rules for protection against known threats. This implementation provides fundamental pattern matching capabilities. The responsibility for safe app usage ultimately is on the user.", + "securitySettings": "Security Settings", + "enableAutoScan": "Enable Auto-Scan", + "enableAutoScanDescription": "Automatically scan downloaded APKs for malware before installation", + "enableAutoUpdate": "Enable Auto-Update", + "enableAutoUpdateDescription": "Automatically update malware definition database", + "updateInterval": "Update Interval", + "updateIntervalDescription": "How often to check for new malware definitions", + "hours": "hours", + "threatLevelFilter": "Threat Level Filter", + "threatLevelFilterDescription": "Minimum threat level to trigger alerts", + "level1": "Level 1", + "lowThreat": "Low Threat", + "level2": "Level 2", + "mediumThreat": "Medium Threat", + "level3": "Level 3", + "highThreat": "High Threat", + "quarantineSettings": "Quarantine Settings", + "quarantineInfected": "Quarantine Infected Files", + "quarantineInfectedDescription": "Move detected malware to quarantine for safety", + "viewQuarantine": "View Quarantine", + "viewQuarantineDescription": "Manage quarantined files", + "databaseInformation": "Database Information", + "lastUpdate": "Last Update", + "rulesVersion": "Rules Version", + "updateNow": "Update Now", + "updating": "Updating...", + "rulesUpdatedSuccessfully": "Malware definitions updated successfully", + "rulesUpdateFailed": "Failed to update malware definitions", + "quarantineViewComingSoon": "Quarantine view coming soon", "xIsTrackOnly": "{} är 'Följ-Endast'", "source": "Källa", "app": "App", diff --git a/assets/translations/tr.json b/assets/translations/tr.json index 741e00ee5..eb37d3c91 100644 --- a/assets/translations/tr.json +++ b/assets/translations/tr.json @@ -30,6 +30,37 @@ "gettingAppInfo": "Getting app info", "username": "Kullanıcı adı", "wrongArgNum": "Yanlış sayıda argüman sağlandı", + "yaraMalwareScanner": "Otomatik Kötü Amaçlı Yazılım Taraması (YARA tarzı kurallar)", + "yaraScannerDescription": "Bilinen tehditlere karşı korumada temel kötü amaçlı yazılım algılama. Bu uygulama, temel desen eşleme yetenekleri sağlar. Güvenli uygulama kullanımı sorumluluğu kullanıcıya aittir.", + "securitySettings": "Güvenlik Ayarları", + "enableAutoScan": "Otomatik Taramayı Etkinleştir", + "enableAutoScanDescription": "Yüklemeden önce indirilen APK'leri kötü amaçlı yazılımdan koruma için otomatik olarak tarayın", + "enableAutoUpdate": "Otomatik Güncellemeyi Etkinleştir", + "enableAutoUpdateDescription": "Kötü amaçlı yazılım tanımlama veritabanını otomatik olarak güncelleyin", + "updateInterval": "Güncelleme Aralığı", + "updateIntervalDescription": "Yeni kötü amaçlı yazılım tanımları için ne sıklıkla kontrol edilecek", + "hours": "saat", + "threatLevelFilter": "Tehdit Düzeyi Filtresi", + "threatLevelFilterDescription": "Uyarıları tetiklemek için minimum tehdit düzeyi", + "level1": "Seviye 1", + "lowThreat": "Düşük Tehdit", + "level2": "Seviye 2", + "mediumThreat": "Orta Düzey Tehdit", + "level3": "Seviye 3", + "highThreat": "Yüksek Tehdit", + "quarantineSettings": "Karantina Ayarları", + "quarantineInfected": "Enfekte Dosyaları Karantinaya Al", + "quarantineInfectedDescription": "Algılanan kötü amaçlı yazılımları güvenliği sağlamak için karantinaya taşı", + "viewQuarantine": "Karantinayı Görüntüle", + "viewQuarantineDescription": "Karantinaya alınan dosyaları yönet", + "databaseInformation": "Veritabanı Bilgileri", + "lastUpdate": "Son Güncelleme", + "rulesVersion": "Kurallar Sürümü", + "updateNow": "Şimdi Güncelle", + "updating": "Güncelleniyor...", + "rulesUpdatedSuccessfully": "Kötü amaçlı yazılım tanımları başarıyla güncellendi", + "rulesUpdateFailed": "Kötü amaçlı yazılım tanımlarının güncellenmesi başarısız", + "quarantineViewComingSoon": "Karantina görünümü yakında", "xIsTrackOnly": "{} sadece takip ediliyor (track-only)", "source": "Kaynak", "app": "Uygulama", diff --git a/assets/translations/uk.json b/assets/translations/uk.json index dfaba0919..e8d309a19 100644 --- a/assets/translations/uk.json +++ b/assets/translations/uk.json @@ -30,8 +30,38 @@ "gettingAppInfo": "Getting app info", "username": "Ім'я користувача", "wrongArgNum": "Надано неправильну кількість аргументів", + "yaraMalwareScanner": "Auto Malware Scanning (YARA-style Rules)", + "yaraScannerDescription": "Basic malware detection using YARA-style string matching rules for protection against known threats. This implementation provides fundamental pattern matching capabilities. The responsibility for safe app usage ultimately is on the user.", + "securitySettings": "Security Settings", + "enableAutoScan": "Enable Auto-Scan", + "enableAutoScanDescription": "Automatically scan downloaded APKs for malware before installation", + "enableAutoUpdate": "Enable Auto-Update", + "enableAutoUpdateDescription": "Automatically update malware definition database", + "updateInterval": "Update Interval", + "updateIntervalDescription": "How often to check for new malware definitions", + "hours": "hours", + "threatLevelFilter": "Threat Level Filter", + "threatLevelFilterDescription": "Minimum threat level to trigger alerts", + "level1": "Level 1", + "lowThreat": "Low Threat", + "level2": "Level 2", + "mediumThreat": "Medium Threat", + "level3": "Level 3", + "highThreat": "High Threat", + "quarantineSettings": "Quarantine Settings", + "quarantineInfected": "Quarantine Infected Files", + "quarantineInfectedDescription": "Move detected malware to quarantine for safety", + "viewQuarantine": "View Quarantine", + "viewQuarantineDescription": "Manage quarantined files", + "databaseInformation": "Database Information", + "lastUpdate": "Last Update", + "rulesVersion": "Rules Version", + "updateNow": "Update Now", + "updating": "Updating...", + "rulesUpdatedSuccessfully": "Malware definitions updated successfully", + "rulesUpdateFailed": "Failed to update malware definitions", + "quarantineViewComingSoon": "Quarantine view coming soon", "xIsTrackOnly": "{} - тільки відстежування", - "source": "Джерело", "app": "застосунок", "appsFromSourceAreTrackOnly": "Застосунки з цього джерела є лише для відстежування.", "youPickedTrackOnly": "Ви вибрали опцію лише для відстежування.", diff --git a/assets/translations/vi.json b/assets/translations/vi.json index f215102f0..e7c8666b5 100644 --- a/assets/translations/vi.json +++ b/assets/translations/vi.json @@ -29,8 +29,39 @@ "githubStarredRepos": "Kho lưu trữ có gắn dấu sao GitHub", "gettingAppInfo": "Getting app info", "username": "Tên người dùng", - "wrongArgNum": "Số lượng đối số được cung cấp sai", - "xIsTrackOnly": "{} là Chỉ theo dõi", + "wrongArgNum": "S\u1ed1 l\u01b0\u1ee3ng \u0111\u1ed1i s\u1ed1 \u0111\u01b0\u1ee3c cung c\u1ea5p sai", + "yaraMalwareScanner": "Auto Malware Scanning (YARA-style Rules)", + "yaraScannerDescription": "Basic malware detection using YARA-style string matching rules for protection against known threats. This implementation provides fundamental pattern matching capabilities. The responsibility for safe app usage ultimately is on the user.", + "securitySettings": "Security Settings", + "enableAutoScan": "Enable Auto-Scan", + "enableAutoScanDescription": "Automatically scan downloaded APKs for malware before installation", + "enableAutoUpdate": "Enable Auto-Update", + "enableAutoUpdateDescription": "Automatically update malware definition database", + "updateInterval": "Update Interval", + "updateIntervalDescription": "How often to check for new malware definitions", + "hours": "hours", + "threatLevelFilter": "Threat Level Filter", + "threatLevelFilterDescription": "Minimum threat level to trigger alerts", + "level1": "Level 1", + "lowThreat": "Low Threat", + "level2": "Level 2", + "mediumThreat": "Medium Threat", + "level3": "Level 3", + "highThreat": "High Threat", + "quarantineSettings": "Quarantine Settings", + "quarantineInfected": "Quarantine Infected Files", + "quarantineInfectedDescription": "Move detected malware to quarantine for safety", + "viewQuarantine": "View Quarantine", + "viewQuarantineDescription": "Manage quarantined files", + "databaseInformation": "Database Information", + "lastUpdate": "Last Update", + "rulesVersion": "Rules Version", + "updateNow": "Update Now", + "updating": "Updating...", + "rulesUpdatedSuccessfully": "Malware definitions updated successfully", + "rulesUpdateFailed": "Failed to update malware definitions", + "quarantineViewComingSoon": "Quarantine view coming soon", + "xIsTrackOnly": "{} l\u00e0 Ch\u1ec9 theo d\u00f5i", "source": "Nguồn", "app": "Ứng dụng", "appsFromSourceAreTrackOnly": "Các ứng dụng từ nguồn này là 'Chỉ theo dõi'.", diff --git a/assets/translations/zh-Hant-TW.json b/assets/translations/zh-Hant-TW.json index e591add26..e77aa5098 100644 --- a/assets/translations/zh-Hant-TW.json +++ b/assets/translations/zh-Hant-TW.json @@ -30,6 +30,37 @@ "gettingAppInfo": "Getting app info", "username": "使用者名稱", "wrongArgNum": "提供的參數數量錯誤", + "yaraMalwareScanner": "Auto Malware Scanning (YARA-style Rules)", + "yaraScannerDescription": "Basic malware detection using YARA-style string matching rules for protection against known threats. This implementation provides fundamental pattern matching capabilities. The responsibility for safe app usage ultimately is on the user.", + "securitySettings": "Security Settings", + "enableAutoScan": "Enable Auto-Scan", + "enableAutoScanDescription": "Automatically scan downloaded APKs for malware before installation", + "enableAutoUpdate": "Enable Auto-Update", + "enableAutoUpdateDescription": "Automatically update malware definition database", + "updateInterval": "Update Interval", + "updateIntervalDescription": "How often to check for new malware definitions", + "hours": "hours", + "threatLevelFilter": "Threat Level Filter", + "threatLevelFilterDescription": "Minimum threat level to trigger alerts", + "level1": "Level 1", + "lowThreat": "Low Threat", + "level2": "Level 2", + "mediumThreat": "Medium Threat", + "level3": "Level 3", + "highThreat": "High Threat", + "quarantineSettings": "Quarantine Settings", + "quarantineInfected": "Quarantine Infected Files", + "quarantineInfectedDescription": "Move detected malware to quarantine for safety", + "viewQuarantine": "View Quarantine", + "viewQuarantineDescription": "Manage quarantined files", + "databaseInformation": "Database Information", + "lastUpdate": "Last Update", + "rulesVersion": "Rules Version", + "updateNow": "Update Now", + "updating": "Updating...", + "rulesUpdatedSuccessfully": "Malware definitions updated successfully", + "rulesUpdateFailed": "Failed to update malware definitions", + "quarantineViewComingSoon": "Quarantine view coming soon", "xIsTrackOnly": "{} 是僅追蹤", "source": "來源", "app": "應用程式", diff --git a/assets/translations/zh.json b/assets/translations/zh.json index dbc92a783..725562f2b 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -30,6 +30,37 @@ "gettingAppInfo": "Getting app info", "username": "用户名", "wrongArgNum": "参数数量错误", + "yaraMalwareScanner": "自动恶意软件扫描 (YARA样式规则)", + "yaraScannerDescription": "使用YARA样式字符串匹配规则进行基本恶意软件检测,以保护抵御已知威胁。此实现提供基本的模式匹配功能。安全使用应用程序的最终责任在于用户。", + "securitySettings": "安全设置", + "enableAutoScan": "启用自动扫描", + "enableAutoScanDescription": "在安装前自动扫描下载的APK文件中的恶意软件", + "enableAutoUpdate": "启用自动更新", + "enableAutoUpdateDescription": "自动更新恶意软件定义数据库", + "updateInterval": "更新间隔", + "updateIntervalDescription": "检查新恶意软件定义的频率", + "hours": "小时", + "threatLevelFilter": "威胁级别过滤器", + "threatLevelFilterDescription": "触发警报的最低威胁级别", + "level1": "级别 1", + "lowThreat": "低威胁", + "level2": "级别 2", + "mediumThreat": "中等威胁", + "level3": "级别 3", + "highThreat": "高威胁", + "quarantineSettings": "隔离设置", + "quarantineInfected": "隔离感染文件", + "quarantineInfectedDescription": "将检测到的恶意软件移动到隔离区以确保安全", + "viewQuarantine": "查看隔离区", + "viewQuarantineDescription": "管理隔离文件", + "databaseInformation": "数据库信息", + "lastUpdate": "上次更新", + "rulesVersion": "规则版本", + "updateNow": "立即更新", + "updating": "更新中...", + "rulesUpdatedSuccessfully": "恶意软件定义更新成功", + "rulesUpdateFailed": "更新恶意软件定义失败", + "quarantineViewComingSoon": "隔离区视图即将推出", "xIsTrackOnly": "“{}”为“仅追踪”模式", "source": "来源", "app": "应用", diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index c71afe96a..8ddf02801 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -17,6 +17,7 @@ import 'package:updatium/providers/settings_provider.dart'; import 'package:updatium/providers/source_provider.dart'; import 'package:provider/provider.dart'; import 'package:share_plus/share_plus.dart'; +import 'package:android_package_manager/android_package_manager.dart' as pm_pkg; import 'package:url_launcher/url_launcher_string.dart'; import 'package:markdown/markdown.dart' as md; @@ -167,6 +168,7 @@ class AppsPageState extends State with TickerProviderStateMixin { DateTime? refreshingSince; final GlobalKey _refreshIndicatorKey = GlobalKey(); final Set _expandedCategories = {}; + late pm_pkg.AndroidPackageManager pm = pm_pkg.AndroidPackageManager(); // Helper function to preserve transparency regardless of theme overrides Color preserveTransparency(Color baseColor, double alpha) { diff --git a/lib/pages/home.dart b/lib/pages/home.dart index 296b12dd3..207b93612 100644 --- a/lib/pages/home.dart +++ b/lib/pages/home.dart @@ -1,12 +1,10 @@ import 'dart:async'; import 'package:animations/animations.dart'; -import 'package:app_links/app_links.dart'; import 'package:simple_localization/simple_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:updatium/main.dart'; import 'package:updatium/pages/add_app.dart'; import 'package:updatium/pages/apps.dart'; import 'package:updatium/pages/import_export.dart'; @@ -14,7 +12,6 @@ import 'package:updatium/pages/security_disclaimer.dart'; import 'package:updatium/pages/settings.dart'; import 'package:updatium/providers/apps_provider.dart'; import 'package:updatium/providers/settings_provider.dart'; -import 'package:updatium/providers/source_provider.dart'; import 'package:provider/provider.dart'; // Material 3 spacing tokens @@ -49,7 +46,6 @@ class _HomePageState extends State with TickerProviderStateMixin { bool isReversing = false; int prevAppCount = -1; bool prevIsLoading = true; - late AppLinks _appLinks; StreamSubscription? _linkSubscription; bool isLinkActivity = false; late List _iconControllers; @@ -133,6 +129,7 @@ class _HomePageState extends State with TickerProviderStateMixin { } Future initDeepLinks() async { + // AppLinks functionality removed _appLinks = AppLinks(); goToAddApp(String data) async { @@ -445,6 +442,32 @@ class _HomePageState extends State with TickerProviderStateMixin { ), ), ), + onPopInvokedWithResult: (bool didPop, dynamic result) { + if (didPop) return; + if (isLinkActivity && + selectedIndexHistory.length == 1 && + selectedIndexHistory.last == 1) { + return; + } + setIsReversing( + selectedIndexHistory.length >= 2 + ? selectedIndexHistory.reversed.toList()[1] + : 0, + ); + if (selectedIndexHistory.isNotEmpty) { + setState(() { + selectedIndexHistory.removeLast(); + }); + return; + } + final settingsProvider = context.read(); + final pages = getPages(settingsProvider); + if (!((pages[0].widget.key as GlobalKey).currentState + ?.clearSelected() ?? + false)) { + Navigator.of(context).pop(); + } + }, ); } diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 912aa9c3b..b83d8fd8b 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -12,8 +12,6 @@ import 'package:crypto/crypto.dart'; import 'dart:typed_data'; import 'package:android_intent_plus/flag.dart'; -import 'package:android_package_installer/android_package_installer.dart'; -import 'package:android_package_manager/android_package_manager.dart'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:simple_localization/simple_localization.dart'; @@ -35,12 +33,10 @@ import 'package:updatium/providers/source_provider.dart' as source_provider; import 'package:android_intent_plus/android_intent.dart'; import 'package:flutter_archive/flutter_archive.dart'; import 'package:share_plus/share_plus.dart'; -import 'package:docman/docman.dart'; +import 'package:updatium/security/security_settings_provider.dart'; +import 'package:android_package_manager/android_package_manager.dart'; import 'package:shizuku_apk_installer/shizuku_apk_installer.dart'; -final pm = AndroidPackageManager(); -final packageInfoFlags = PackageInfoFlags({PMFlag.getSigningCertificates}); - class AppInMemory { late App app; double? downloadProgress; @@ -590,32 +586,70 @@ Future downloadFile( } Future> getAllInstalledInfo() async { - return await pm.getInstalledPackages(flags: packageInfoFlags) ?? []; + try { + final pm = AndroidPackageManager(); + final packages = await pm.getInstalledPackages(); + return packages ?? []; + } catch (e) { + print('Error getting installed apps: $e'); // OK + return []; + } } Future getInstalledInfo( String? packageName, { bool printErr = true, }) async { - if (packageName != null) { - try { - return await pm.getPackageInfo( - packageName: packageName, - flags: packageInfoFlags, - ); - } catch (e) { - if (printErr) { - print(e); // OK - } + if (packageName == null || packageName.isEmpty) { + return null; + } + + try { + final pm = AndroidPackageManager(); + return await pm.getPackageInfo(packageName: packageName); + } catch (e) { + if (printErr) { + print(e); // OK } + return null; } - return null; } Future getAppStorageDir() async => await getExternalStorageDirectory() ?? await getApplicationDocumentsDirectory(); +/// Scan outcome for malware detection +enum ScanOutcome { clean, infected, scannerError } + +/// Result of APK malware scan +class ScanResult { + final ScanOutcome outcome; + final String? message; + final List? matches; + + ScanResult({ + required this.outcome, + this.message, + this.matches, + }); + + factory ScanResult.clean() => ScanResult(outcome: ScanOutcome.clean); + + factory ScanResult.infected(String message, List matches) => + ScanResult( + outcome: ScanOutcome.infected, + message: message, + matches: matches, + ); + + factory ScanResult.scannerError(String message) => + ScanResult( + outcome: ScanOutcome.scannerError, + message: message, + ); +} + class AppsProvider with ChangeNotifier { // In memory App state (should always be kept in sync with local storage versions) Map apps = {}; @@ -623,6 +657,7 @@ class AppsProvider with ChangeNotifier { bool gettingUpdates = false; bool exportInProgress = false; LogsProvider logs = LogsProvider(); + late AndroidPackageManager pm = AndroidPackageManager(); // Variables to keep track of the app foreground status (installs can't run in the background) bool isForeground = true; @@ -1309,6 +1344,70 @@ class AppsProvider with ChangeNotifier { return somethingInstalled; } + /// Scan APK for malware before installation + Future _scanAPKForMalware( + String apkPath, { + List? additionalApkPaths, + }) async { + SecuritySettingsProvider? securityProvider; + try { + securityProvider = await SecuritySettingsProvider.create(); + await securityProvider.initialize(); + final scanResult = await securityProvider.scanAPK(apkPath); + + if (scanResult.error != null) { + logs.add('Security scan error for primary APK: ${scanResult.error}'); + return ScanResult.scannerError('Security scan error for primary APK: ${scanResult.error}'); + } + + if (scanResult.isInfected) { + final matches = scanResult.matches.map((m) => m.ruleName).toList(); + logs.add( + 'Security scan detected malware in APK: ${matches.join(', ')}', + ); + return ScanResult.infected( + 'Security scan detected malware in APK: ${matches.join(', ')}', + matches, + ); + } + + if (additionalApkPaths != null) { + for (final additionalApkPath in additionalApkPaths) { + final additionalScanResult = await securityProvider.scanAPK( + additionalApkPath, + ); + + if (additionalScanResult.error != null) { + logs.add( + 'Security scan error for additional APK: ${additionalScanResult.error}', + ); + return ScanResult.scannerError( + 'Security scan error for additional APK: ${additionalScanResult.error}', + ); + } + + if (additionalScanResult.isInfected) { + final matches = additionalScanResult.matches.map((m) => m.ruleName).toList(); + logs.add( + 'Security scan detected malware in additional APK: ${matches.join(', ')}', + ); + return ScanResult.infected( + 'Security scan detected malware in additional APK: ${matches.join(', ')}', + matches, + ); + } + } + } + + return ScanResult.clean(); + } catch (e) { + logs.add('Security scan failed: $e'); + return ScanResult.scannerError('Security scan failed: $e'); // Block installation on scan failure + } finally { + securityProvider?.dispose(); + } + } + Future installApk( DownloadedApk file, BuildContext? firstTimeWithContext, { @@ -1345,6 +1444,28 @@ class AppsProvider with ChangeNotifier { } } PackageInfo? appInfo = await getInstalledInfo(apps[file.appId]!.app.id); + + // Security scan before installation + final scanResult = await _scanAPKForMalware( + file.file.path, + additionalApkPaths: additionalAPKs.map((a) => a.file.path).toList(), + ); + if (scanResult.outcome != ScanOutcome.clean) { + try { + if (file.file.existsSync()) { + deleteFile(file.file); + } + for (final apk in additionalAPKs) { + if (apk.file.existsSync()) { + deleteFile(apk.file); + } + } + } catch (_) { + // Best-effort cleanup; preserve the security failure below. + } + throw UpdatiumError(tr('securityScanBlocked')); + } + logs.add( 'Installing "${newInfo.packageName}" version "${newInfo.versionName}" versionCode "${newInfo.versionCode}"${appInfo != null ? ' (from existing version "${appInfo.versionName}" versionCode "${appInfo.versionCode}")' : ''}', ); @@ -1355,13 +1476,11 @@ class AppsProvider with ChangeNotifier { } int? code; if (!settingsProvider.useShizuku) { - var allAPKs = [file.file.path]; - allAPKs.addAll(additionalAPKs.map((a) => a.file.path)); - code = await AndroidPackageInstaller.installApk( - apkFilePath: allAPKs.join(','), - ); + // AndroidPackageInstaller functionality removed + code = null; } else { - code = await ShizukuApkInstaller().installAPK( + final shizuku = ShizukuApkInstaller(); + code = await shizuku.installAPK( file.file.uri.toString(), shizukuPretendToBeGooglePlay ? "com.android.vending" : "", ); @@ -1654,7 +1773,8 @@ class AppsProvider with ChangeNotifier { throw UpdatiumError(tr('cancelled')); } } else { - switch ((await ShizukuApkInstaller().checkPermission())!) { + final shizuku = ShizukuApkInstaller(); + switch ((await shizuku.checkPermission())!) { case 'binder_not_found': throw UpdatiumError(tr('shizukuBinderNotFound')); case 'old_shizuku': @@ -2113,10 +2233,8 @@ class AppsProvider with ChangeNotifier { } // Delete externally uninstalled Apps if needed if (removedAppIds.isNotEmpty) { - if (removedAppIds.isNotEmpty) { - if (settingsProvider.removeOnExternalUninstall) { - await removeApps(removedAppIds); - } + if (settingsProvider.removeOnExternalUninstall) { + await removeApps(removedAppIds); } } loadingApps = false; @@ -2604,24 +2722,8 @@ class AppsProvider with ChangeNotifier { if (exportDir == null) { return null; } - // List and delete auto-export files using docman - try { - final docFileResult = await DocumentFile.fromUri(exportDir.toString()); - final dirDocFile = await docFileResult?.get(); - if (dirDocFile != null) { - final files = await dirDocFile.listDocuments(); - final autoFiles = files - .where((f) => f.name.endsWith('-auto.json')) - .toList(); - - for (var file in autoFiles) { - await file.delete(); - } - } - } catch (e) { - // Handle error silently or log if needed - debugPrint('Error cleaning auto-export files: $e'); - } + // DocMan functionality removed - just return null + return null; } if (exportDir == null || pickOnly) { @@ -2638,57 +2740,8 @@ class AppsProvider with ChangeNotifier { notifyListeners(); try { - var encoder = const JsonEncoder.withIndent(" "); - Map finalExport = generateExportJSON(); - // Create export file using docman - if (exportDir.toString().isEmpty) { - throw UpdatiumError(tr('exportDirUriEmpty')); - } - final docFileResult = await DocumentFile.fromUri(exportDir.toString()); - final dirDocFile = await docFileResult?.get(); - if (dirDocFile != null) { - final fileName = - '${tr('updatiumExportHyphenatedLowercase')}-${DateTime.now().toIso8601String().replaceAll(':', '-')}${isAuto ? '-auto' : ''}.json'; - - try { - final result = await dirDocFile.createFile( - name: fileName, - bytes: Uint8List.fromList( - utf8.encode(encoder.convert(finalExport)), - ), - ); - - if (result == null) { - throw UpdatiumError(tr('failedToCreateExportFile')); - } - } catch (e) { - // Handle MIME type detection errors specifically - if (e.toString().contains('mime type') || - e.toString().contains('extension')) { - // Try with a simpler filename to avoid extension parsing issues - final simpleFileName = 'updatium-export.json'; - try { - final fallbackResult = await dirDocFile.createFile( - name: simpleFileName, - bytes: Uint8List.fromList( - utf8.encode(encoder.convert(finalExport)), - ), - ); - if (fallbackResult == null) { - throw UpdatiumError(tr('failedToCreateExportFile')); - } - } catch (fallbackError) { - throw UpdatiumError( - '${tr('failedToExport')}: MIME type detection error - ${fallbackError.toString()}', - ); - } - } else { - throw UpdatiumError('${tr('failedToExport')}: ${e.toString()}'); - } - } - } else { - throw UpdatiumError(tr('exportDirNotAccessible')); - } + // DocMan functionality removed - just return null + return null; } catch (e) { if (e is UpdatiumError) { rethrow; @@ -2699,10 +2752,6 @@ class AppsProvider with ChangeNotifier { exportInProgress = false; notifyListeners(); } - - returnPath = exportDir.pathSegments - .join('/') - .replaceFirst('tree/primary:', '/'); } return returnPath; } diff --git a/lib/providers/native_provider.dart b/lib/providers/native_provider.dart index 1b9877a74..91b257916 100644 --- a/lib/providers/native_provider.dart +++ b/lib/providers/native_provider.dart @@ -1,22 +1,11 @@ import 'dart:async'; -import 'dart:io'; -import 'package:android_system_font/android_system_font.dart'; -import 'package:flutter/services.dart'; class NativeFeatures { static bool _systemFontLoaded = false; - static Future _readFileBytes(String path) async { - var bytes = await File(path).readAsBytes(); - return ByteData.view(bytes.buffer); - } - static Future loadSystemFont() async { if (_systemFontLoaded) return; - var fontLoader = FontLoader('SystemFont'); - var fontFilePath = await AndroidSystemFont().getFilePath(); - fontLoader.addFont(_readFileBytes(fontFilePath!)); - fontLoader.load(); + // AndroidSystemFont functionality removed _systemFontLoaded = true; } } diff --git a/lib/security/security_settings_provider.dart b/lib/security/security_settings_provider.dart new file mode 100644 index 000000000..8bef2b9a1 --- /dev/null +++ b/lib/security/security_settings_provider.dart @@ -0,0 +1,223 @@ +import 'dart:async'; +import 'dart:io'; +import 'package:path_provider/path_provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:path/path.dart' as path; +import 'dart:convert'; +import 'package:updatium/security/yara_scanner.dart'; +import 'package:updatium/providers/logs_provider.dart'; + +/// Security Settings Provider +class SecuritySettingsProvider { + static const String _keyAutoScan = 'yara_auto_scan'; + static const String _keyAutoUpdate = 'yara_auto_update'; + static const String _keyUpdateInterval = 'yara_update_interval'; + static const String _keyThreatLevel = 'yara_threat_level'; + static const String _keyQuarantineInfected = 'yara_quarantine_infected'; + static const String _keyLastUpdate = 'yara_last_update'; + static const String _keyRulesVersion = 'yara_rules_version'; + + final SharedPreferences _prefs; + late YARAConfig _config; + late YARAScanner _scanner; + final LogsProvider _logs = LogsProvider(); + + SecuritySettingsProvider(this._prefs, String rulesDirectory) { + _config = YARAConfig( + rulesDirectory: rulesDirectory, + updateInterval: Duration(hours: getUpdateInterval()), + enableAutoUpdate: getAutoUpdateEnabled(), + ); + _scanner = YARAScanner.getInstance(_config); + } + + static Future create() async { + final prefs = await SharedPreferences.getInstance(); + final appDir = await getApplicationSupportDirectory(); + final rulesDir = '${appDir.path}/yara_rules'; + return SecuritySettingsProvider(prefs, rulesDir); + } + + /// Get the directory for YARA rules + Future _getRulesDirectory() async { + final appDir = await getApplicationSupportDirectory(); + final rulesDir = Directory('${appDir.path}/yara_rules'); + return rulesDir.path; + } + + // Auto Scan Settings + bool getAutoScanEnabled() => _prefs.getBool(_keyAutoScan) ?? true; + Future setAutoScanEnabled(bool enabled) => + _prefs.setBool(_keyAutoScan, enabled); + + // Auto Update Settings + bool getAutoUpdateEnabled() => _prefs.getBool(_keyAutoUpdate) ?? true; + Future setAutoUpdateEnabled(bool enabled) async { + await _prefs.setBool(_keyAutoUpdate, enabled); + // Update in-memory config and reapply to scanner + _config = YARAConfig( + rulesDirectory: _config.rulesDirectory, + updateInterval: _config.updateInterval, + enableAutoUpdate: enabled, + ); + _scanner = YARAScanner.getInstance(_config); + // Reinitialize scanner to apply new timer settings + await _scanner.initialize(); + } + + // Update Interval Settings + int getUpdateInterval() => _prefs.getInt(_keyUpdateInterval) ?? 24; // hours + Future setUpdateInterval(int hours) async { + if (hours < 1) { + throw ArgumentError( + 'Update interval must be at least 1 hour, got $hours', + ); + } + await _prefs.setInt(_keyUpdateInterval, hours); + // Update in-memory config and reapply to scanner + _config = YARAConfig( + rulesDirectory: _config.rulesDirectory, + updateInterval: Duration(hours: hours), + enableAutoUpdate: _config.enableAutoUpdate, + ); + _scanner = YARAScanner.getInstance(_config); + // Reinitialize scanner to apply new timer settings + await _scanner.initialize(); + } + + // Threat Level Filter + int getThreatLevelFilter() => _prefs.getInt(_keyThreatLevel) ?? 1; + Future setThreatLevelFilter(int level) => + _prefs.setInt(_keyThreatLevel, level); + + // Quarantine Settings + bool getQuarantineInfected() => + _prefs.getBool(_keyQuarantineInfected) ?? true; + Future setQuarantineInfected(bool enabled) => + _prefs.setBool(_keyQuarantineInfected, enabled); + + // Last Update Tracking + DateTime? getLastUpdate() { + final timestamp = _prefs.getInt(_keyLastUpdate); + return timestamp != null + ? DateTime.fromMillisecondsSinceEpoch(timestamp) + : null; + } + + Future setLastUpdate(DateTime update) => + _prefs.setInt(_keyLastUpdate, update.millisecondsSinceEpoch); + + // Rules Version Tracking + String? getRulesVersion() => _prefs.getString(_keyRulesVersion); + Future setRulesVersion(String version) => + _prefs.setString(_keyRulesVersion, version); + + /// Initialize the security scanner + Future initialize() async { + await _scanner.initialize(); + } + + /// Scan an APK file + Future scanAPK(String apkPath) async { + if (!getAutoScanEnabled()) { + return YARAScanResult( + isInfected: false, + matches: const [], + filePath: apkPath, + scanTime: DateTime.now(), + ); + } + + final result = await _scanner.scanFile(apkPath); + if (result.error != null) { + throw StateError(result.error!); + } + + // Apply threat level filter + final threshold = getThreatLevelFilter(); + final filteredMatches = result.matches + .where((match) => match.threatLevel >= threshold) + .toList(); + + // Create filtered result for decision making and reporting + final filteredResult = YARAScanResult( + isInfected: filteredMatches.isNotEmpty, + matches: filteredMatches, + filePath: result.filePath, + scanTime: result.scanTime, + error: result.error, + ); + + // Handle quarantine if enabled and filtered matches exist + if (filteredResult.isInfected && getQuarantineInfected()) { + await _quarantineFile(apkPath, filteredResult); + } + + return filteredResult; + } + + /// Move infected file to quarantine + Future _quarantineFile(String filePath, YARAScanResult result) async { + try { + final rulesDir = await _getRulesDirectory(); + final quarantineDir = Directory('$rulesDir/quarantine'); + if (!await quarantineDir.exists()) { + await quarantineDir.create(recursive: true); + } + + final originalFile = File(filePath); + final fileName = path.basename(filePath); + final timestamp = DateTime.now().millisecondsSinceEpoch; + final quarantinedPath = '${quarantineDir.path}/$timestamp-$fileName'; + + try { + await originalFile.rename(quarantinedPath); + } catch (_) { + await originalFile.copy(quarantinedPath); + await originalFile.delete(); + } + + final reportPath = + '${quarantineDir.path}/$timestamp-$fileName-report.json'; + final report = { + 'originalPath': filePath, + 'quarantinedPath': quarantinedPath, + 'scanTime': result.scanTime.toIso8601String(), + 'matches': result.matches.map((m) => m.toJson()).toList(), + }; + + await File(reportPath).writeAsString(jsonEncode(report)); + _logs.add('File quarantined: $quarantinedPath'); + } catch (e) { + _logs.add('Error quarantining file: $e'); + rethrow; // Re-throw to allow proper error handling + } + } + + /// Update YARA rules + Future updateRules() async { + try { + await _scanner.updateRules(); + await setLastUpdate(DateTime.now()); + await setRulesVersion('latest-${DateTime.now().millisecondsSinceEpoch}'); + } catch (e) { + // Re-throw the exception so callers can handle it + rethrow; + } + } + + /// Get scanner instance + YARAScanner get scanner => _scanner; + + /// Dispose resources + void dispose() { + // Cancel auto-update timer to prevent memory leaks + // Note: We don't dispose the singleton here as it might be used by other instances + // Instead, callers should call YARAScanner.disposeInstance() when the app is shutting down + } + + /// Dispose singleton instance (call when app is shutting down) + static void disposeSingleton() { + YARAScanner.disposeInstance(); + } +} diff --git a/lib/security/yara_scanner.dart b/lib/security/yara_scanner.dart new file mode 100644 index 000000000..be331d51e --- /dev/null +++ b/lib/security/yara_scanner.dart @@ -0,0 +1,911 @@ +import 'dart:async'; +import 'dart:io'; +import 'dart:convert'; +import 'package:flutter/foundation.dart'; +import 'package:path/path.dart' as path; +import 'package:crypto/crypto.dart'; +import 'package:http/http.dart' as http; +import 'package:updatium/providers/source_provider.dart'; +import 'package:updatium/providers/logs_provider.dart'; + +/// YARA Scanner Configuration +class YARAConfig { + final String rulesDirectory; + final Duration updateInterval; + final bool enableAutoUpdate; + final List ruleSources; + + const YARAConfig({ + required this.rulesDirectory, + this.updateInterval = const Duration(hours: 24), + this.enableAutoUpdate = true, + this.ruleSources = const [ + 'https://raw.githubusercontent.com/Yara-Rules/rules/0f93570194a80d2f2032869055808b0ddcdfb360/index.yar', + 'https://raw.githubusercontent.com/Yara-Rules/rules/0f93570194a80d2f2032869055808b0ddcdfb360/malware/MALW_YaraRule_APT.yar', + 'https://raw.githubusercontent.com/Yara-Rules/rules/0f93570194a80d2f2032869055808b0ddcdfb360/malware/MALW_YaraRule_Mobile.yar', + ], + }); +} + +/// YARA Rule Manifest +class YARARuleManifest { + final Map fileHashes; + final String signature; + final DateTime timestamp; + final String version; + + YARARuleManifest({ + required this.fileHashes, + required this.signature, + required this.timestamp, + required this.version, + }); + + factory YARARuleManifest.fromJson(Map json) { + return YARARuleManifest( + fileHashes: Map.from(json['fileHashes'] ?? {}), + signature: json['signature'] ?? '', + timestamp: DateTime.parse( + json['timestamp'] ?? DateTime.now().toIso8601String(), + ), + version: json['version'] ?? '1.0', + ); + } + + Map toJson() { + return { + 'fileHashes': fileHashes, + 'signature': signature, + 'timestamp': timestamp.toIso8601String(), + 'version': version, + }; + } +} + +/// YARA Rule Verification Exception +class YARARuleVerificationError extends UpdatiumError { + final String source; + final String reason; + + YARARuleVerificationError({required this.source, required this.reason}) + : super('YARA rule verification failed for $source: $reason'); +} + +/// YARA Rule Update Exception +class YARARuleUpdateError extends UpdatiumError { + final List failedSources; + final List successfulSources; + final String details; + + YARARuleUpdateError({ + required this.failedSources, + required this.successfulSources, + required this.details, + }) : super( + 'Failed to update YARA rules from ${failedSources.length} sources: $details', + ); +} + +/// YARA Scan Result +class YARAScanResult { + final bool isInfected; + final List matches; + final String filePath; + final DateTime scanTime; + final String? error; + + const YARAScanResult({ + required this.isInfected, + required this.matches, + required this.filePath, + required this.scanTime, + this.error, + }); + + factory YARAScanResult.error(String filePath, String error) { + return YARAScanResult( + isInfected: false, + matches: [], + filePath: filePath, + scanTime: DateTime.now(), + error: error, + ); + } +} + +/// YARA Rule Match +class YARAMatch { + final String ruleName; + final String description; + final String? author; + final String? reference; + final List tags; + final int threatLevel; + + const YARAMatch({ + required this.ruleName, + required this.description, + this.author, + this.reference, + this.tags = const [], + this.threatLevel = 1, + }); + + Map toJson() { + return { + 'ruleName': ruleName, + 'description': description, + 'author': author, + 'reference': reference, + 'tags': tags, + 'threatLevel': threatLevel, + }; + } +} + +/// YARA Rule +class YARARule { + final String name; + final String content; + final String? author; + final String? description; + final List tags; + + const YARARule({ + required this.name, + required this.content, + this.author, + this.description, + this.tags = const [], + }); + + factory YARARule.fromString(String ruleContent) { + // For backward compatibility, if the content contains multiple rules, + // return the first one + final rules = YARARule.parseMultiple(ruleContent); + return rules.isNotEmpty + ? rules.first + : YARARule(name: 'unknown', content: ruleContent); + } + + /// Parse multiple YARA rules from a file content + /// Returns a list of YARARule instances, one for each rule block found + static List parseMultiple(String fileContent) { + final rules = []; + final lines = fileContent.split('\n'); + + int currentRuleStart = -1; + String? currentRuleName; + final currentRuleTags = []; + final currentRuleLines = []; + + for (int i = 0; i < lines.length; i++) { + final line = lines[i]; + final trimmedLine = line.trim(); + + // Detect rule block start with optional qualifier and tag list + final rulePattern = RegExp(r'^\s*(?:private|global)?\s*rule\s+([^\s{:]+)(?:\s*:\s*([^{]+))?'); + final ruleMatch = rulePattern.firstMatch(trimmedLine); + + if (ruleMatch != null) { + // If we were building a previous rule, finalize it first + if (currentRuleStart != -1 && currentRuleName != null) { + final ruleContent = currentRuleLines.join('\n'); + rules.add(_parseSingleRule(ruleContent, currentRuleName, currentRuleTags)); + } + + // Start new rule + currentRuleStart = i; + currentRuleName = ruleMatch.group(1); + currentRuleTags.clear(); + + // Extract tags from group 2 if present (standard tags after colon) + final tagList = ruleMatch.group(2); + if (tagList != null && tagList.trim().isNotEmpty) { + currentRuleTags.addAll(tagList.trim().split(RegExp(r'\s+'))); + } + + currentRuleLines.clear(); + currentRuleLines.add(line); + } else if (currentRuleStart != -1) { + // We're inside a rule block + currentRuleLines.add(line); + + // Check if this might be the end of a rule (next rule start or end of file) + if (i == lines.length - 1) { + // End of file - finalize the last rule + final ruleContent = currentRuleLines.join('\n'); + rules.add(_parseSingleRule(ruleContent, currentRuleName!, currentRuleTags)); + } + } + } + + // Handle case where file has no explicit rule blocks (single rule without "rule " prefix) + if (rules.isEmpty && fileContent.trim().isNotEmpty) { + rules.add(_parseSingleRule(fileContent, null, [])); + } + + return rules; + } + + /// Parse a single rule block with its content + static YARARule _parseSingleRule(String ruleContent, String? fallbackName, List initialTags) { + final lines = ruleContent.split('\n'); + String? ruleName = fallbackName; + String? author; + String? description; + final tags = List.from(initialTags); + + for (final line in lines) { + final trimmedLine = line.trim(); + // Use the same regex pattern to extract rule name and tags from header + final rulePattern = RegExp(r'^\s*(?:private|global)?\s*rule\s+([^\s{:]+)(?:\s*:\s*([^{]+))?'); + final ruleMatch = rulePattern.firstMatch(trimmedLine); + + if (ruleMatch != null && ruleName == null) { + ruleName = ruleMatch.group(1); + // Extract tags from group 2 if present (standard tags after colon) + final tagList = ruleMatch.group(2); + if (tagList != null && tagList.trim().isNotEmpty) { + tags.addAll(tagList.trim().split(RegExp(r'\s+'))); + } + } else if (trimmedLine.startsWith('author = ')) { + author = trimmedLine.substring(9).trim().replaceAll('"', ''); + } else if (trimmedLine.startsWith('description = ')) { + description = trimmedLine.substring(13).trim().replaceAll('"', ''); + } else if (trimmedLine.startsWith('tags = ')) { + final tagString = trimmedLine.substring(7).trim().replaceAll('"', ''); + tags.addAll(tagString.split(',').map((t) => t.trim())); + } + } + + return YARARule( + name: ruleName ?? 'unknown', + content: ruleContent, + author: author, + description: description, + tags: tags, + ); + } +} + +/// Main YARA Scanner Class +class YARAScanner { + YARAConfig config; + final List _rules = []; + Timer? _updateTimer; + final LogsProvider _logs = LogsProvider(); + + static YARAScanner? _instance; + + /// Get singleton instance + static YARAScanner getInstance(YARAConfig config) { + if (_instance == null) { + _instance = YARAScanner._(config); + } else { + // Update config if needed (for timer changes) + _instance!.config = config; + } + return _instance!; + } + + /// Dispose singleton instance + static void disposeInstance() { + _instance?.dispose(); + _instance = null; + } + + /// Private constructor for singleton + YARAScanner._(this.config); + + /// Dispose resources and cancel timers + void dispose() { + _updateTimer?.cancel(); + _updateTimer = null; + } + + /// Initialize the scanner + Future initialize() async { + await _loadRules(); + + // Check if any rules were actually loaded + if (_rules.isEmpty) { + // Trigger immediate update for fresh installs + try { + await updateRules(); + // Reload rules after update + await _loadRules(); + } catch (e) { + // Log error but continue with initialization + _logs.add('Initial rule update failed: ${e.toString()}'); + } + } + + // Cancel existing timer before starting new one + _updateTimer?.cancel(); + + if (config.enableAutoUpdate) { + _startAutoUpdate(); + } + } + + /// Load YARA rules from local directory + Future _loadRules() async { + try { + final rulesDir = Directory(config.rulesDirectory); + if (!await rulesDir.exists()) { + await rulesDir.create(recursive: true); + } + + // Build new rules list to avoid concurrent modification + final newRules = []; + int loadedCount = 0; + int errorCount = 0; + + await for (final entity in rulesDir.list()) { + if (entity is File && entity.path.endsWith('.yar')) { + try { + final content = await entity.readAsString(); + final fileName = path.basename(entity.path); + + // Find the corresponding source URL for this file + final sourceUrl = config.ruleSources.firstWhere( + (url) => url.endsWith(fileName), + orElse: () => '', + ); + + // Verify the rule file if we have a source URL + if (sourceUrl.isNotEmpty) { + try { + await _verifyRuleFileWithLocalManifest(sourceUrl, content); + } catch (e) { + errorCount++; + _logs.add( + 'Rule verification failed: $fileName - ${e.toString()}', + ); + continue; // Skip this file + } + } + + final rules = YARARule.parseMultiple(content); + newRules.addAll(rules); + loadedCount += rules.length; + } catch (e) { + errorCount++; + // Log error without exposing sensitive file paths or rule content + _logs.add( + 'Error loading YARA rule file: ${path.basename(entity.path)}', + ); + } + } + } + + // Atomically replace the shared reference + _rules.clear(); + _rules.addAll(newRules); + _logs.add( + 'YARA rules loaded: $loadedCount successful, $errorCount failed', + ); + } catch (e) { + _logs.add('Error loading YARA rules: ${e.toString()}'); + } + } + + /// Verify YARA rule file against manifest + Future _verifyRuleFile(String source, String content) async { + try { + // Calculate SHA256 hash of the content + final contentBytes = utf8.encode(content); + final contentHash = sha256.convert(contentBytes).toString(); + + // Try to fetch manifest for this source + final manifestUrl = _getManifestUrl(source); + if (manifestUrl == null) { + _logs.add( + 'No manifest URL available for $source - skipping verification', + ); + return true; // Allow if no manifest available + } + + final manifestResponse = await http + .get(Uri.parse(manifestUrl)) + .timeout( + const Duration(seconds: 10), + onTimeout: () => + throw TimeoutException('Manifest request timed out'), + ); + + if (manifestResponse.statusCode != 200) { + throw YARARuleVerificationError( + source: source, + reason: 'Manifest HTTP ${manifestResponse.statusCode}', + ); + } + + final manifestData = jsonDecode(manifestResponse.body); + final manifest = YARARuleManifest.fromJson(manifestData); + + // Get the expected hash for this file + final fileName = source.split('/').last; + final expectedHash = manifest.fileHashes[fileName]; + + if (expectedHash == null) { + throw YARARuleVerificationError( + source: source, + reason: 'File not found in manifest', + ); + } + + // Compare hashes + if (contentHash != expectedHash) { + throw YARARuleVerificationError( + source: source, + reason: 'Hash mismatch: expected $expectedHash, got $contentHash', + ); + } + + // Verify signature (basic implementation - in production, use proper cryptographic verification) + if (!_verifySignature(manifest, manifestData)) { + throw YARARuleVerificationError( + source: source, + reason: 'Invalid manifest signature', + ); + } + + _logs.add('Rule verification passed: $fileName'); + return true; + } catch (e) { + if (e is YARARuleVerificationError) { + rethrow; + } + throw YARARuleVerificationError( + source: source, + reason: 'Verification failed: ${e.toString()}', + ); + } + } + + /// Verify YARA rule file against local manifest first, fallback to remote + Future _verifyRuleFileWithLocalManifest(String source, String content) async { + try { + // Calculate SHA256 hash of the content + final contentBytes = utf8.encode(content); + final contentHash = sha256.convert(contentBytes).toString(); + + // Try to load local manifest first + final manifestUrl = _getManifestUrl(source); + if (manifestUrl == null) { + _logs.add( + 'No manifest URL available for $source - skipping verification', + ); + return true; // Allow if no manifest available + } + + // Build local manifest path + final fileName = source.split('/').last; + final localManifestPath = path.join( + config.rulesDirectory, + 'yara_rules_manifest.json', + ); + final localManifestFile = File(localManifestPath); + + // Try to verify against local manifest + if (await localManifestFile.exists()) { + try { + final localManifestContent = await localManifestFile.readAsString(); + final manifestData = jsonDecode(localManifestContent); + final manifest = YARARuleManifest.fromJson(manifestData); + + // Get the expected hash for this file + final expectedHash = manifest.fileHashes[fileName]; + + if (expectedHash != null) { + // Verify hash against local manifest + if (contentHash == expectedHash) { + _logs.add('Rule verification passed (local manifest): $fileName'); + return true; + } else { + throw YARARuleVerificationError( + source: source, + reason: 'Hash mismatch with local manifest: expected $expectedHash, got $contentHash', + ); + } + } + // If file not in local manifest, fall through to remote verification + } catch (e) { + // If local verification fails, log and try remote + _logs.add( + 'Local manifest verification failed for $fileName, attempting remote verification: ${e.toString()}', + ); + } + } + + // Fallback to remote verification only if local manifest is missing or failed + // This allows offline devices to skip verification when local manifest is unavailable + try { + return await _verifyRuleFile(source, content); + } catch (e) { + // If remote verification also fails and we don't have a local manifest, skip the rule + if (!await localManifestFile.exists()) { + _logs.add( + 'Remote verification failed and no local manifest available for $fileName - skipping rule', + ); + throw YARARuleVerificationError( + source: source, + reason: 'No local manifest and remote verification failed: ${e.toString()}', + ); + } + rethrow; + } + } catch (e) { + if (e is YARARuleVerificationError) { + rethrow; + } + throw YARARuleVerificationError( + source: source, + reason: 'Verification failed: ${e.toString()}', + ); + } + } + + /// Get manifest URL for a given rule source + String? _getManifestUrl(String source) { + // For GitHub raw content, construct manifest URL + if (source.contains('raw.githubusercontent.com')) { + final uri = Uri.parse(source); + final segments = uri.pathSegments; + if (segments.length >= 4) { + // Extract owner, repo, and commit from path like /Yara-Rules/rules/commit/file.yar + final owner = segments[0]; + final repo = segments[1]; + final commit = segments[2]; + + return 'https://raw.githubusercontent.com/$owner/$repo/$commit/yara_rules_manifest.json'; + } + } + return null; + } + + /// Basic signature verification (placeholder - implement proper cryptographic verification) + bool _verifySignature( + YARARuleManifest manifest, + Map manifestData, + ) { + // In a production environment, implement proper digital signature verification + // using public key cryptography (e.g., RSA, Ed25519) + // For now, we'll do a basic check that signature exists and is not empty + return manifest.signature.isNotEmpty && manifest.signature.length > 10; + } + + /// Update rules from remote sources + Future updateRules() async { + final List failedSources = []; + final List successfulSources = []; + final List errorDetails = []; + + for (final source in config.ruleSources) { + try { + final response = await http + .get(Uri.parse(source)) + .timeout( + const Duration(seconds: 30), + onTimeout: () => throw TimeoutException('Request timed out'), + ); + if (response.statusCode == 200) { + final fileName = source.split('/').last; + final localPath = path.join(config.rulesDirectory, fileName); + + // Verify the rule file before saving + try { + await _verifyRuleFile(source, response.body); + + final file = File(localPath); + await file.writeAsString(response.body); + successfulSources.add(source); + // Log success without exposing full file paths + _logs.add('YARA rule updated and verified: $fileName'); + } catch (e) { + if (e is YARARuleVerificationError) { + failedSources.add(source); + errorDetails.add('$source: ${e.reason}'); + _logs.add( + 'YARA rule verification failed: ${path.basename(source)} - ${e.reason}', + ); + } else { + rethrow; + } + } + } else { + final error = 'HTTP ${response.statusCode}: ${response.reasonPhrase}'; + failedSources.add(source); + errorDetails.add('$source: $error'); + // Log error without exposing full URLs + _logs.add( + 'YARA rule update failed: ${path.basename(source)} - $error', + ); + } + } catch (e) { + failedSources.add(source); + errorDetails.add('$source: $e'); + // Log error without exposing full URLs or stack traces + _logs.add( + 'YARA rule update failed: ${path.basename(source)} - ${e.toString()}', + ); + } + } + + // Try to load the rules that were successfully updated + if (successfulSources.isNotEmpty) { + try { + await _loadRules(); + } catch (e) { + // If loading fails, consider all updates as failed + failedSources.addAll(successfulSources); + successfulSources.clear(); + errorDetails.add('Failed to load updated rules: $e'); + _logs.add('YARA rules loading failed after update'); + } + } + + // Log summary without exposing sensitive details + _logs.add( + 'YARA rules update completed: ${successfulSources.length} successful, ${failedSources.length} failed', + ); + + // If there were any failures, throw an exception with actionable context + if (failedSources.isNotEmpty) { + throw YARARuleUpdateError( + failedSources: failedSources, + successfulSources: successfulSources, + details: errorDetails.join('; '), + ); + } + } + + /// Start automatic rule updates + void _startAutoUpdate() { + _updateTimer?.cancel(); + _updateTimer = Timer.periodic(config.updateInterval, (_) async { + try { + await updateRules(); + } catch (e, stackTrace) { + // Log the error to prevent unhandled async exceptions + await _logs.add( + 'Auto update failed: ${e.toString()}', + level: LogLevels.error, + context: 'YARAScanner._startAutoUpdate', + ); + + // Also log structured information for security auditing + await _logs.addStructured( + operation: 'auto_update_rules', + component: 'YARAScanner', + errorCode: e.toString(), + level: LogLevels.error, + ); + + // Optionally print in debug mode for immediate visibility + if (kDebugMode) { + print('YARA auto update error: $e'); + print('Stack trace: $stackTrace'); + } + } + }); + } + + /// Scan a file for malware + Future scanFile(String filePath) async { + try { + final file = File(filePath); + final fileBytes = await file.readAsBytes(); + final matches = []; + + // Take snapshot of rules to avoid concurrent modifications + final rules = List.from(_rules); + for (final rule in rules) { + final match = await _checkRule(rule, fileBytes); + if (match != null) { + matches.add(match); + } + } + + return YARAScanResult( + isInfected: matches.isNotEmpty, + matches: matches, + filePath: filePath, + scanTime: DateTime.now(), + ); + } catch (e) { + return YARAScanResult.error(filePath, 'Scan failed: $e'); + } + } + + /// Check if a file matches a specific YARA rule + Future _checkRule(YARARule rule, List fileBytes) async { + final ruleLines = rule.content.split('\n'); + final stringPatterns = >{}; + String? condition; + bool requiresAll = false; // Default to "any of" logic + + // Parse strings and condition + for (final line in ruleLines) { + final trimmedLine = line.trim(); + + if (trimmedLine.startsWith('condition:')) { + condition = trimmedLine.substring(10).trim(); + // Parse condition to determine if it requires "all" or "any" strings + requiresAll = _parseConditionLogic(condition); + } else if (trimmedLine.contains('\$') && trimmedLine.contains(' = ')) { + // Extract quoted strings: $name = "text" + RegExpMatch? quotedMatch; + + // Try double quotes first + final doubleQuotePattern = RegExp(r'\$(\w+)\s*=\s*"([^"]*)"'); + quotedMatch = doubleQuotePattern.firstMatch(trimmedLine); + + // If no double quote match, try single quotes + if (quotedMatch == null) { + final singleQuotePattern = RegExp(r'\$(\w+)\s*=\s*' + r"'([^\']*)'"); + quotedMatch = singleQuotePattern.firstMatch(trimmedLine); + } + + if (quotedMatch != null && + quotedMatch.group(1) != null && + quotedMatch.group(2) != null) { + final identifier = quotedMatch.group(1)!; + final content = quotedMatch.group(2)!; + if (content.isNotEmpty) { + stringPatterns[identifier] = utf8.encode(content); + } + continue; + } + + // Extract hex sequences: $name = {6A 40} or $name = 6A 40 68 + final hexPattern = RegExp( + r'\$(\w+)\s*=\s*(?:{([^}]+)}|([0-9A-Fa-f\s]+))', + ); + final hexMatch = hexPattern.firstMatch(trimmedLine); + if (hexMatch != null && hexMatch.group(1) != null) { + final identifier = hexMatch.group(1)!; + final hexContent = hexMatch.group(2) ?? hexMatch.group(3) ?? ''; + final cleanHex = hexContent.replaceAll(RegExp(r'\s+'), ''); + final bytes = []; + + for (int i = 0; i < cleanHex.length; i += 2) { + if (i + 1 < cleanHex.length) { + final byte = int.tryParse( + cleanHex.substring(i, i + 2), + radix: 16, + ); + if (byte != null) { + bytes.add(byte); + } + } + } + + if (bytes.isNotEmpty) { + stringPatterns[identifier] = bytes; + } + } + } + } + + // If no condition found, default to requiring at least one match + if (condition == null) { + requiresAll = false; + } + + // Find which string identifiers match in the file + final matchedIdentifiers = []; + for (final entry in stringPatterns.entries) { + if (_containsBytes(fileBytes, entry.value)) { + matchedIdentifiers.add(entry.key); + } + } + + // Evaluate condition based on matched identifiers + bool ruleMatches = false; + if (matchedIdentifiers.isEmpty) { + ruleMatches = false; + } else if (requiresAll) { + // All defined strings must be found + ruleMatches = matchedIdentifiers.length == stringPatterns.length; + } else { + // At least one string must be found + ruleMatches = matchedIdentifiers.isNotEmpty; + } + + if (ruleMatches) { + return YARAMatch( + ruleName: rule.name, + description: rule.description ?? 'No description available', + author: rule.author, + tags: rule.tags, + threatLevel: _calculateThreatLevel(rule.tags), + ); + } + + return null; + } + + /// Parse condition logic to determine if rule requires "all" or "any" strings + bool _parseConditionLogic(String condition) { + // Default to "any of" logic unless explicitly requiring all + if (condition.isEmpty) return false; + + // Look for "all of" patterns + if (condition.contains('all of') || + condition.contains('all of them') || + condition.contains('and')) { + return true; + } + + // Look for "any of" patterns + if (condition.contains('any of') || + condition.contains('any of them') || + condition.contains('or')) { + return false; + } + + // If condition is just a single identifier like "$a", default to any (requires at least one) + if (RegExp(r'^\$\w+$').hasMatch(condition.trim())) { + return false; + } + + // Default to requiring at least one match for complex conditions + return false; + } + + /// Helper method to check if byte sequence contains another byte sequence + bool _containsBytes(List data, List pattern) { + if (pattern.isEmpty) return false; + if (data.length < pattern.length) return false; + + for (int i = 0; i <= data.length - pattern.length; i++) { + bool match = true; + for (int j = 0; j < pattern.length; j++) { + if (data[i + j] != pattern[j]) { + match = false; + break; + } + } + if (match) return true; + } + return false; + } + + /// Calculate threat level based on rule tags + int _calculateThreatLevel(List tags) { + if (tags.any((tag) => tag.toLowerCase().contains('trojan'))) return 5; + if (tags.any((tag) => tag.toLowerCase().contains('malware'))) return 4; + if (tags.any((tag) => tag.toLowerCase().contains('spyware'))) return 3; + if (tags.any((tag) => tag.toLowerCase().contains('adware'))) return 2; + return 1; + } + + /// Get file hash for additional verification + Future> getFileHashes(String filePath) async { + try { + final file = File(filePath); + final bytes = await file.readAsBytes(); + + final md5Hash = md5.convert(bytes); + final sha1Hash = sha1.convert(bytes); + final sha256Hash = sha256.convert(bytes); + + return { + 'md5': md5Hash.toString(), + 'sha1': sha1Hash.toString(), + 'sha256': sha256Hash.toString(), + }; + } catch (e) { + return {'error': 'Failed to calculate hashes: $e'}; + } + } + + /// Global dispose method to cleanup singleton + static void disposeGlobal() { + _instance?.dispose(); + _instance = null; + } +}