Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b9474521d | ||
|
|
78c3f2c9b8 | ||
|
|
ad256abb7c | ||
|
|
86d160ae5f | ||
|
|
fde6afb39e | ||
|
|
7c3e78296a | ||
|
|
9cc06ff767 |
No files matched your search
+203
-82
@@ -68,18 +68,14 @@ window.AppI18n = {
|
||||
"update_check": "檢查更新",
|
||||
"update_check_desc": "此選項可以檢查可用更新",
|
||||
"search_proc": "搜尋進程...",
|
||||
"btn_view": "查看",
|
||||
"btn_end": "結束",
|
||||
"manage_white": "白名單管理",
|
||||
"search_file": "搜尋檔案...",
|
||||
"btn_add": "加入",
|
||||
"btn_remove": "移除",
|
||||
"manage_quarantine": "隔離區管理",
|
||||
"btn_scan": "掃描",
|
||||
"search_window": "搜尋窗口...",
|
||||
"search_rule": "搜尋規則...",
|
||||
"search_log": "搜尋日誌...",
|
||||
"btn_export": "導出",
|
||||
"btn_export": "導出項目",
|
||||
"msg_init": "正在初始化中",
|
||||
"msg_update_fail": "檢查更新失敗",
|
||||
"msg_new_version": "發現新版本",
|
||||
@@ -98,7 +94,6 @@ window.AppI18n = {
|
||||
"msg_click_target": "請在5秒內點擊目標視窗...",
|
||||
"msg_confirm_block": "確認攔截",
|
||||
"msg_repaired": "已修復選取項目",
|
||||
"btn_repair": "修復",
|
||||
"title_prompt": "提示",
|
||||
"title_error": "錯誤",
|
||||
"path_unknown": "未知路徑",
|
||||
@@ -141,12 +136,28 @@ window.AppI18n = {
|
||||
"col_status": "狀態",
|
||||
"status_enabled": "已啟用",
|
||||
"status_disabled": "已禁用",
|
||||
"btn_enable": "啟用",
|
||||
"btn_disable": "禁用",
|
||||
"search_item": "搜尋項目...",
|
||||
"type_reg": "登錄檔",
|
||||
"type_srv": "服務",
|
||||
"type_tsk": "排程任務",
|
||||
"btn_view_item": "查看項目",
|
||||
"btn_end": "結束進程",
|
||||
"btn_enable_item": "啟用項目",
|
||||
"btn_disable_item": "禁用項目",
|
||||
"btn_delete_item": "刪除項目",
|
||||
"btn_repair_item": "修復項目",
|
||||
"btn_add_item": "新增項目",
|
||||
"btn_remove_item": "移除項目",
|
||||
"btn_add_file": "新增檔案",
|
||||
"btn_add_path": "新增路徑",
|
||||
"manage_netmon": "流量監控",
|
||||
"manage_netmon_desc": "此選項可以實時監控網路流量",
|
||||
"col_down_speed": "下載速度",
|
||||
"col_up_speed": "上傳速度",
|
||||
"col_conn_count": "連接數",
|
||||
"btn_extract_item": "提取項目",
|
||||
"msg_extract_success": "成功提取選取項目",
|
||||
"msg_key_activated": "產品金鑰已啟用"
|
||||
},
|
||||
"simplified_switch": {
|
||||
"app_name": "PYAS Security",
|
||||
@@ -216,18 +227,14 @@ window.AppI18n = {
|
||||
"update_check": "检查更新",
|
||||
"update_check_desc": "此选项可以检查可用更新",
|
||||
"search_proc": "搜索进程...",
|
||||
"btn_view": "查看",
|
||||
"btn_end": "结束",
|
||||
"manage_white": "白名单管理",
|
||||
"search_file": "搜索文件...",
|
||||
"btn_add": "加入",
|
||||
"btn_remove": "移除",
|
||||
"manage_quarantine": "隔离区管理",
|
||||
"btn_scan": "扫描",
|
||||
"search_window": "搜索窗口...",
|
||||
"search_rule": "搜索规则...",
|
||||
"search_log": "搜索日志...",
|
||||
"btn_export": "导出",
|
||||
"btn_export": "导出项目",
|
||||
"msg_init": "正在初始化中",
|
||||
"msg_update_fail": "检查更新失败",
|
||||
"msg_new_version": "发现新版本",
|
||||
@@ -246,7 +253,6 @@ window.AppI18n = {
|
||||
"msg_click_target": "请在5秒内点击目标窗口...",
|
||||
"msg_confirm_block": "确认拦截",
|
||||
"msg_repaired": "已修复选取项目",
|
||||
"btn_repair": "修复",
|
||||
"title_prompt": "提示",
|
||||
"title_error": "错误",
|
||||
"path_unknown": "未知路径",
|
||||
@@ -289,12 +295,28 @@ window.AppI18n = {
|
||||
"col_status": "状态",
|
||||
"status_enabled": "已启用",
|
||||
"status_disabled": "已禁用",
|
||||
"btn_enable": "启用",
|
||||
"btn_disable": "禁用",
|
||||
"search_item": "搜索项目...",
|
||||
"type_reg": "注册表",
|
||||
"type_srv": "服务",
|
||||
"type_tsk": "计划任务",
|
||||
"btn_view_item": "查看项目",
|
||||
"btn_end": "结束进程",
|
||||
"btn_enable_item": "启用项目",
|
||||
"btn_disable_item": "禁用项目",
|
||||
"btn_delete_item": "删除项目",
|
||||
"btn_repair_item": "修复项目",
|
||||
"btn_add_item": "新增项目",
|
||||
"btn_remove_item": "移除项目",
|
||||
"btn_add_file": "新增文件",
|
||||
"btn_add_path": "新增路径",
|
||||
"manage_netmon": "流量监控",
|
||||
"manage_netmon_desc": "此选项可以实时监控网络流量",
|
||||
"col_down_speed": "下载速度",
|
||||
"col_up_speed": "上传速度",
|
||||
"col_conn_count": "连接数",
|
||||
"btn_extract_item": "提取项目",
|
||||
"msg_extract_success": "成功提取选取项目",
|
||||
"msg_key_activated": "产品密钥已启用"
|
||||
},
|
||||
"english_switch": {
|
||||
"app_name": "PYAS Security",
|
||||
@@ -364,18 +386,14 @@ window.AppI18n = {
|
||||
"update_check": "Check for Updates",
|
||||
"update_check_desc": "Check for the latest updates",
|
||||
"search_proc": "Search processes...",
|
||||
"btn_view": "View",
|
||||
"btn_end": "End Task",
|
||||
"manage_white": "Whitelist Manager",
|
||||
"search_file": "Search files...",
|
||||
"btn_add": "Add",
|
||||
"btn_remove": "Remove",
|
||||
"manage_quarantine": "Quarantine Manager",
|
||||
"btn_scan": "Scan",
|
||||
"search_window": "Search windows...",
|
||||
"search_rule": "Search rules...",
|
||||
"search_log": "Search logs...",
|
||||
"btn_export": "Export",
|
||||
"btn_export": "Export Items",
|
||||
"msg_init": "Initializing...",
|
||||
"msg_update_fail": "Update check failed",
|
||||
"msg_new_version": "New version found",
|
||||
@@ -394,7 +412,6 @@ window.AppI18n = {
|
||||
"msg_click_target": "Click the target window within 5s...",
|
||||
"msg_confirm_block": "Confirm Block",
|
||||
"msg_repaired": "Selected items repaired",
|
||||
"btn_repair": "Repair",
|
||||
"title_prompt": "Prompt",
|
||||
"title_error": "Error",
|
||||
"path_unknown": "Unknown Path",
|
||||
@@ -437,12 +454,28 @@ window.AppI18n = {
|
||||
"col_status": "Status",
|
||||
"status_enabled": "Enabled",
|
||||
"status_disabled": "Disabled",
|
||||
"btn_enable": "Enable",
|
||||
"btn_disable": "Disable",
|
||||
"search_item": "Search items...",
|
||||
"type_reg": "Registry",
|
||||
"type_srv": "Service",
|
||||
"type_tsk": "Task",
|
||||
"btn_view_item": "View Item",
|
||||
"btn_end": "End Process",
|
||||
"btn_enable_item": "Enable Item",
|
||||
"btn_disable_item": "Disable Item",
|
||||
"btn_delete_item": "Delete Item",
|
||||
"btn_repair_item": "Repair Item",
|
||||
"btn_add_item": "Add Item",
|
||||
"btn_remove_item": "Remove Item",
|
||||
"btn_add_file": "Add File",
|
||||
"btn_add_path": "Add Path",
|
||||
"manage_netmon": "Traffic Monitor",
|
||||
"manage_netmon_desc": "Monitor network traffic in real-time",
|
||||
"col_down_speed": "Download Speed",
|
||||
"col_up_speed": "Upload Speed",
|
||||
"col_conn_count": "Connections",
|
||||
"btn_extract_item": "Extract Item",
|
||||
"msg_extract_success": "Successfully extracted selected items",
|
||||
"msg_key_activated": "Product key activated"
|
||||
},
|
||||
"japanese_switch": {
|
||||
"app_name": "PYAS Security",
|
||||
@@ -512,12 +545,8 @@ window.AppI18n = {
|
||||
"update_check": "アップデートの確認",
|
||||
"update_check_desc": "利用可能なアップデートを確認します",
|
||||
"search_proc": "プロセスを検索...",
|
||||
"btn_view": "表示",
|
||||
"btn_end": "タスクの終了",
|
||||
"manage_white": "ホワイトリスト管理",
|
||||
"search_file": "ファイルを検索...",
|
||||
"btn_add": "追加",
|
||||
"btn_remove": "削除",
|
||||
"manage_quarantine": "隔離管理",
|
||||
"btn_scan": "スキャン",
|
||||
"search_window": "ウィンドウを検索...",
|
||||
@@ -542,7 +571,6 @@ window.AppI18n = {
|
||||
"msg_click_target": "5秒以内にターゲットウィンドウをクリックしてください...",
|
||||
"msg_confirm_block": "ブロックの確認",
|
||||
"msg_repaired": "選択された項目が修復されました",
|
||||
"btn_repair": "修復",
|
||||
"title_prompt": "プロンプト",
|
||||
"title_error": "エラー",
|
||||
"path_unknown": "不明なパス",
|
||||
@@ -585,12 +613,28 @@ window.AppI18n = {
|
||||
"col_status": "ステータス",
|
||||
"status_enabled": "有効",
|
||||
"status_disabled": "無効",
|
||||
"btn_enable": "有効化",
|
||||
"btn_disable": "無効化",
|
||||
"search_item": "項目を検索...",
|
||||
"type_reg": "レジストリ",
|
||||
"type_srv": "サービス",
|
||||
"type_tsk": "タスク",
|
||||
"btn_view_item": "項目を表示",
|
||||
"btn_end": "プロセスを終了",
|
||||
"btn_enable_item": "項目を有効化",
|
||||
"btn_disable_item": "項目を無効化",
|
||||
"btn_delete_item": "項目を削除",
|
||||
"btn_repair_item": "項目を修復",
|
||||
"btn_add_item": "項目を追加",
|
||||
"btn_remove_item": "項目を削除",
|
||||
"btn_add_file": "ファイルを追加",
|
||||
"btn_add_path": "パスを追加",
|
||||
"manage_netmon": "トラフィック監視",
|
||||
"manage_netmon_desc": "ネットワークトラフィックをリアルタイムで監視します",
|
||||
"col_down_speed": "ダウンロード速度",
|
||||
"col_up_speed": "アップロード速度",
|
||||
"col_conn_count": "接続数",
|
||||
"btn_extract_item": "アイテムを抽出",
|
||||
"msg_extract_success": "選択したアイテムを正常に抽出しました",
|
||||
"msg_key_activated": "プロダクトキーが有効化されました"
|
||||
},
|
||||
"korean_switch": {
|
||||
"app_name": "PYAS Security",
|
||||
@@ -660,12 +704,8 @@ window.AppI18n = {
|
||||
"update_check": "업데이트 확인",
|
||||
"update_check_desc": "사용 가능한 최신 업데이트를 확인합니다",
|
||||
"search_proc": "프로세스 검색...",
|
||||
"btn_view": "보기",
|
||||
"btn_end": "작업 끝내기",
|
||||
"manage_white": "화이트리스트 관리",
|
||||
"search_file": "파일 검색...",
|
||||
"btn_add": "추가",
|
||||
"btn_remove": "제거",
|
||||
"manage_quarantine": "격리소 관리",
|
||||
"btn_scan": "스캔",
|
||||
"search_window": "창 검색...",
|
||||
@@ -690,7 +730,6 @@ window.AppI18n = {
|
||||
"msg_click_target": "5초 이내에 대상 창을 클릭하십시오...",
|
||||
"msg_confirm_block": "차단 확인",
|
||||
"msg_repaired": "선택한 항목이 복구되었습니다",
|
||||
"btn_repair": "복구",
|
||||
"title_prompt": "프롬프트",
|
||||
"title_error": "오류",
|
||||
"path_unknown": "알 수 없는 경로",
|
||||
@@ -733,12 +772,28 @@ window.AppI18n = {
|
||||
"col_status": "상태",
|
||||
"status_enabled": "사용",
|
||||
"status_disabled": "사용 안 함",
|
||||
"btn_enable": "사용",
|
||||
"btn_disable": "사용 안 함",
|
||||
"search_item": "항목 검색...",
|
||||
"type_reg": "레지스트리",
|
||||
"type_srv": "서비스",
|
||||
"type_tsk": "작업",
|
||||
"btn_view_item": "항목 보기",
|
||||
"btn_end": "프로세스 종료",
|
||||
"btn_enable_item": "항목 사용",
|
||||
"btn_disable_item": "항목 사용 안 함",
|
||||
"btn_delete_item": "항목 삭제",
|
||||
"btn_repair_item": "항목 복구",
|
||||
"btn_add_item": "항목 추가",
|
||||
"btn_remove_item": "항목 제거",
|
||||
"btn_add_file": "파일 추가",
|
||||
"btn_add_path": "경로 추가",
|
||||
"manage_netmon": "트래픽 모니터링",
|
||||
"manage_netmon_desc": "실시간으로 네트워크 트래픽을 모니터링합니다",
|
||||
"col_down_speed": "다운로드 속도",
|
||||
"col_up_speed": "업로드 속도",
|
||||
"col_conn_count": "연결 수",
|
||||
"btn_extract_item": "항목 추출",
|
||||
"msg_extract_success": "선택한 항목을 성공적으로 추출했습니다",
|
||||
"msg_key_activated": "제품 키가 활성화되었습니다"
|
||||
},
|
||||
"french_switch": {
|
||||
"app_name": "PYAS Security",
|
||||
@@ -808,12 +863,8 @@ window.AppI18n = {
|
||||
"update_check": "Vérifier les mises à jour",
|
||||
"update_check_desc": "Vérifier les dernières mises à jour",
|
||||
"search_proc": "Rechercher des processus...",
|
||||
"btn_view": "Voir",
|
||||
"btn_end": "Fin de tâche",
|
||||
"manage_white": "Gestionnaire de liste blanche",
|
||||
"search_file": "Rechercher des fichiers...",
|
||||
"btn_add": "Ajouter",
|
||||
"btn_remove": "Retirer",
|
||||
"manage_quarantine": "Gestionnaire de quarantaine",
|
||||
"btn_scan": "Analyser",
|
||||
"search_window": "Rechercher des fenêtres...",
|
||||
@@ -838,7 +889,6 @@ window.AppI18n = {
|
||||
"msg_click_target": "Cliquez sur la fenêtre cible dans les 5s...",
|
||||
"msg_confirm_block": "Confirmer le blocage",
|
||||
"msg_repaired": "Éléments sélectionnés réparés",
|
||||
"btn_repair": "Réparer",
|
||||
"title_prompt": "Indication",
|
||||
"title_error": "Erreur",
|
||||
"path_unknown": "Chemin inconnu",
|
||||
@@ -881,12 +931,28 @@ window.AppI18n = {
|
||||
"col_status": "Statut",
|
||||
"status_enabled": "Activé",
|
||||
"status_disabled": "Désactivé",
|
||||
"btn_enable": "Activer",
|
||||
"btn_disable": "Désactiver",
|
||||
"search_item": "Rechercher des éléments...",
|
||||
"type_reg": "Registre",
|
||||
"type_srv": "Service",
|
||||
"type_tsk": "Tâche",
|
||||
"btn_view_item": "Afficher l'élément",
|
||||
"btn_end": "Terminer le processus",
|
||||
"btn_enable_item": "Activer l'élément",
|
||||
"btn_disable_item": "Désactiver l'élément",
|
||||
"btn_delete_item": "Supprimer l'élément",
|
||||
"btn_repair_item": "Réparer l'élément",
|
||||
"btn_add_item": "Ajouter l'élément",
|
||||
"btn_remove_item": "Retirer l'élément",
|
||||
"btn_add_file": "Ajouter un fichier",
|
||||
"btn_add_path": "Ajouter un chemin",
|
||||
"manage_netmon": "Moniteur de trafic",
|
||||
"manage_netmon_desc": "Surveille le trafic réseau en temps réel",
|
||||
"col_down_speed": "Vitesse de téléchargement",
|
||||
"col_up_speed": "Vitesse de téléversement",
|
||||
"col_conn_count": "Connexions",
|
||||
"btn_extract_item": "Extraire l'élément",
|
||||
"msg_extract_success": "Éléments sélectionnés extraits avec succès",
|
||||
"msg_key_activated": "Clé de produit activée"
|
||||
},
|
||||
"spanish_switch": {
|
||||
"app_name": "PYAS Security",
|
||||
@@ -894,7 +960,7 @@ window.AppI18n = {
|
||||
"scan_smart": "Escaneo inteligente",
|
||||
"scan_smart_desc": "Escanear rápidamente la seguridad del dispositivo",
|
||||
"log_export": "Exportar registros",
|
||||
"log_export_desc": "Filtrar registros y exportar a un archivo",
|
||||
"log_export_desc": "Filtrer registros y exportar a un archivo",
|
||||
"scan_virus": "Escaneo de virus",
|
||||
"scan_virus_desc": "Seleccione un método de escaneo avanzado",
|
||||
"btn_delete": "Eliminar",
|
||||
@@ -956,12 +1022,8 @@ window.AppI18n = {
|
||||
"update_check": "Buscar actualizaciones",
|
||||
"update_check_desc": "Comprobar las últimas actualizaciones",
|
||||
"search_proc": "Buscar procesos...",
|
||||
"btn_view": "Ver",
|
||||
"btn_end": "Finalizar tarea",
|
||||
"manage_white": "Gestor de lista blanca",
|
||||
"search_file": "Buscar archivos...",
|
||||
"btn_add": "Añadir",
|
||||
"btn_remove": "Eliminar",
|
||||
"manage_quarantine": "Gestor de cuarentena",
|
||||
"btn_scan": "Escanear",
|
||||
"search_window": "Buscar ventanas...",
|
||||
@@ -986,7 +1048,6 @@ window.AppI18n = {
|
||||
"msg_click_target": "Haga clic en la ventana objetivo en 5s...",
|
||||
"msg_confirm_block": "Confirmar bloqueo",
|
||||
"msg_repaired": "Elementos seleccionados reparados",
|
||||
"btn_repair": "Reparar",
|
||||
"title_prompt": "Aviso",
|
||||
"title_error": "Error",
|
||||
"path_unknown": "Ruta desconocida",
|
||||
@@ -1029,12 +1090,28 @@ window.AppI18n = {
|
||||
"col_status": "Estado",
|
||||
"status_enabled": "Habilitado",
|
||||
"status_disabled": "Deshabilitado",
|
||||
"btn_enable": "Habilitar",
|
||||
"btn_disable": "Deshabilitar",
|
||||
"search_item": "Buscar elementos...",
|
||||
"type_reg": "Registro",
|
||||
"type_srv": "Servicio",
|
||||
"type_tsk": "Tarea",
|
||||
"btn_view_item": "Ver elemento",
|
||||
"btn_end": "Terminar proceso",
|
||||
"btn_enable_item": "Habilitar elemento",
|
||||
"btn_disable_item": "Deshabilitar elemento",
|
||||
"btn_delete_item": "Eliminar elemento",
|
||||
"btn_repair_item": "Reparar elemento",
|
||||
"btn_add_item": "Añadir elemento",
|
||||
"btn_remove_item": "Eliminar elemento",
|
||||
"btn_add_file": "Añadir archivo",
|
||||
"btn_add_path": "Añadir ruta",
|
||||
"manage_netmon": "Monitor de tráfico",
|
||||
"manage_netmon_desc": "Monitorea el tráfico de red en tiempo real",
|
||||
"col_down_speed": "Velocidad de descarga",
|
||||
"col_up_speed": "Velocidad de subida",
|
||||
"col_conn_count": "Conexiones",
|
||||
"btn_extract_item": "Extraer elemento",
|
||||
"msg_extract_success": "Elementos seleccionados extraídos con éxito",
|
||||
"msg_key_activated": "Clave de producto activada"
|
||||
},
|
||||
"hindi_switch": {
|
||||
"app_name": "PYAS Security",
|
||||
@@ -1104,12 +1181,8 @@ window.AppI18n = {
|
||||
"update_check": "अद्यतन जाँचे",
|
||||
"update_check_desc": "नवीनतम अपडेट के लिए जाँचें",
|
||||
"search_proc": "प्रक्रियाएँ खोजें...",
|
||||
"btn_view": "देखें",
|
||||
"btn_end": "कार्य समाप्त करें",
|
||||
"manage_white": "श्वेतसूची प्रबंधक",
|
||||
"search_file": "फ़ाइलें खोजें...",
|
||||
"btn_add": "जोड़ें",
|
||||
"btn_remove": "निकालें",
|
||||
"manage_quarantine": "संगरोध प्रबंधक",
|
||||
"btn_scan": "स्कैन",
|
||||
"search_window": "विंडोज़ खोजें...",
|
||||
@@ -1134,7 +1207,6 @@ window.AppI18n = {
|
||||
"msg_click_target": "5 सेकंड के भीतर लक्ष्य विंडो पर क्लिक करें...",
|
||||
"msg_confirm_block": "ब्लॉक की पुष्टि करें",
|
||||
"msg_repaired": "चयनित आइटम मरम्मत किए गए",
|
||||
"btn_repair": "मरम्मत",
|
||||
"title_prompt": "सुझाव",
|
||||
"title_error": "त्रुटि",
|
||||
"path_unknown": "अज्ञात पथ",
|
||||
@@ -1177,12 +1249,28 @@ window.AppI18n = {
|
||||
"col_status": "स्थिति",
|
||||
"status_enabled": "सक्षम",
|
||||
"status_disabled": "अक्षम",
|
||||
"btn_enable": "सक्षम करें",
|
||||
"btn_disable": "अक्षम करें",
|
||||
"search_item": "आइटम खोजें...",
|
||||
"type_reg": "रजिस्ट्री",
|
||||
"type_srv": "सेवा",
|
||||
"type_tsk": "कार्य",
|
||||
"btn_view_item": "आइटम देखें",
|
||||
"btn_end": "प्रक्रिया समाप्त करें",
|
||||
"btn_enable_item": "आइटम सक्षम करें",
|
||||
"btn_disable_item": "आइटम अक्षम करें",
|
||||
"btn_delete_item": "आइटम हटाएं",
|
||||
"btn_repair_item": "आइटम की मरम्मत करें",
|
||||
"btn_add_item": "आइटम जोड़ें",
|
||||
"btn_remove_item": "आइटम निकालें",
|
||||
"btn_add_file": "फ़ाइल जोड़ें",
|
||||
"btn_add_path": "पथ जोड़ें",
|
||||
"manage_netmon": "ट्रैफ़िक मॉनिटर",
|
||||
"manage_netmon_desc": "रीयल-टाइम में नेटवर्क ट्रैफ़िक की निगरानी करें",
|
||||
"col_down_speed": "डाउनलोड गति",
|
||||
"col_up_speed": "अपलोड गति",
|
||||
"col_conn_count": "कनेक्शन",
|
||||
"btn_extract_item": "आइटम निकालें",
|
||||
"msg_extract_success": "चयनित आइटम सफलतापूर्वक निकाले गए",
|
||||
"msg_key_activated": "उत्पाद कुंजी सक्रिय हो गई"
|
||||
},
|
||||
"arabic_switch": {
|
||||
"app_name": "PYAS Security",
|
||||
@@ -1252,12 +1340,8 @@ window.AppI18n = {
|
||||
"update_check": "التحقق من التحديثات",
|
||||
"update_check_desc": "التحقق من أحدث التحديثات",
|
||||
"search_proc": "البحث في العمليات...",
|
||||
"btn_view": "عرض",
|
||||
"btn_end": "إنهاء المهمة",
|
||||
"manage_white": "مدير القائمة البيضاء",
|
||||
"search_file": "البحث عن الملفات...",
|
||||
"btn_add": "إضافة",
|
||||
"btn_remove": "إزالة",
|
||||
"manage_quarantine": "مدير الحجر الصحي",
|
||||
"btn_scan": "فحص",
|
||||
"search_window": "البحث عن النوافذ...",
|
||||
@@ -1282,7 +1366,6 @@ window.AppI18n = {
|
||||
"msg_click_target": "انقر على النافذة المستهدفة خلال 5 ثوانٍ...",
|
||||
"msg_confirm_block": "تأكيد الحظر",
|
||||
"msg_repaired": "تم إصلاح العناصر المحددة",
|
||||
"btn_repair": "إصلاح",
|
||||
"title_prompt": "تلميح",
|
||||
"title_error": "خطأ",
|
||||
"path_unknown": "مسار غير معروف",
|
||||
@@ -1325,12 +1408,28 @@ window.AppI18n = {
|
||||
"col_status": "الحالة",
|
||||
"status_enabled": "مُمكّن",
|
||||
"status_disabled": "مُعطّل",
|
||||
"btn_enable": "تمكين",
|
||||
"btn_disable": "تعطيل",
|
||||
"search_item": "البحث في العناصر...",
|
||||
"type_reg": "التسجيل",
|
||||
"type_srv": "خدمة",
|
||||
"type_tsk": "مهمة",
|
||||
"btn_view_item": "عرض العنصر",
|
||||
"btn_end": "إنهاء العملية",
|
||||
"btn_enable_item": "تمكين العنصر",
|
||||
"btn_disable_item": "تعطيل العنصر",
|
||||
"btn_delete_item": "حذف العنصر",
|
||||
"btn_repair_item": "إصلاح العنصر",
|
||||
"btn_add_item": "إضافة عنصر",
|
||||
"btn_remove_item": "إزالة العنصر",
|
||||
"btn_add_file": "إضافة ملف",
|
||||
"btn_add_path": "إضافة مسار",
|
||||
"manage_netmon": "مراقبة حركة المرور",
|
||||
"manage_netmon_desc": "مراقبة حركة مرور الشبكة في الوقت الفعلي",
|
||||
"col_down_speed": "سرعة التنزيل",
|
||||
"col_up_speed": "سرعة الرفع",
|
||||
"col_conn_count": "الاتصالات",
|
||||
"btn_extract_item": "استخراج العنصر",
|
||||
"msg_extract_success": "تم استخراج العناصر المحددة بنجاح",
|
||||
"msg_key_activated": "تم تنشيط مفتاح المنتج"
|
||||
},
|
||||
"russian_switch": {
|
||||
"app_name": "PYAS Security",
|
||||
@@ -1380,7 +1479,7 @@ window.AppI18n = {
|
||||
"scan_context": "Сканирование из контекстного меню",
|
||||
"scan_context_desc": "Включить функцию сканирования по правому клику",
|
||||
"theme_color": "Цветовая тема",
|
||||
"theme_color_desc": "Выберите цветовую тему приложения",
|
||||
"theme_color_desc": "Выберите цветовой тему приложения",
|
||||
"theme_system": "Системная тема",
|
||||
"theme_white": "Светлый режим",
|
||||
"theme_red": "Красная тема",
|
||||
@@ -1400,12 +1499,8 @@ window.AppI18n = {
|
||||
"update_check": "Проверить обновления",
|
||||
"update_check_desc": "Проверить наличие последних обновлений",
|
||||
"search_proc": "Поиск процессов...",
|
||||
"btn_view": "Просмотр",
|
||||
"btn_end": "Завершить",
|
||||
"manage_white": "Управление белым списком",
|
||||
"search_file": "Поиск файлов...",
|
||||
"btn_add": "Добавить",
|
||||
"btn_remove": "Удалить",
|
||||
"manage_quarantine": "Управление карантином",
|
||||
"btn_scan": "Сканировать",
|
||||
"search_window": "Поиск окон...",
|
||||
@@ -1430,7 +1525,6 @@ window.AppI18n = {
|
||||
"msg_click_target": "Нажмите на целевое окно в течение 5 сек...",
|
||||
"msg_confirm_block": "Подтвердить блокировку",
|
||||
"msg_repaired": "Выбранные элементы восстановлены",
|
||||
"btn_repair": "Восстановить",
|
||||
"title_prompt": "Подсказка",
|
||||
"title_error": "Ошибка",
|
||||
"path_unknown": "Неизвестный путь",
|
||||
@@ -1473,12 +1567,28 @@ window.AppI18n = {
|
||||
"col_status": "Статус",
|
||||
"status_enabled": "Включено",
|
||||
"status_disabled": "Отключено",
|
||||
"btn_enable": "Включить",
|
||||
"btn_disable": "Отключить",
|
||||
"search_item": "Поиск элементов...",
|
||||
"type_reg": "Реестр",
|
||||
"type_srv": "Служба",
|
||||
"type_tsk": "Задача",
|
||||
"btn_view_item": "Просмотр элемента",
|
||||
"btn_end": "Завершить процесс",
|
||||
"btn_enable_item": "Включить элемент",
|
||||
"btn_disable_item": "Отключить элемент",
|
||||
"btn_delete_item": "Удалить элемент",
|
||||
"btn_repair_item": "Восстановить элемент",
|
||||
"btn_add_item": "Добавить элемент",
|
||||
"btn_remove_item": "Удалить элемент",
|
||||
"btn_add_file": "Добавить файл",
|
||||
"btn_add_path": "Добавить путь",
|
||||
"manage_netmon": "Монитор трафика",
|
||||
"manage_netmon_desc": "Мониторинг сетевого трафика в реальном времени",
|
||||
"col_down_speed": "Скорость скачивания",
|
||||
"col_up_speed": "Скорость загрузки",
|
||||
"col_conn_count": "Соединения",
|
||||
"btn_extract_item": "Извлечь элемент",
|
||||
"msg_extract_success": "Выбранные элементы успешно извлечены",
|
||||
"msg_key_activated": "Ключ продукта активирован"
|
||||
},
|
||||
"slovenian_switch": {
|
||||
"app_name": "PYAS Security",
|
||||
@@ -1548,12 +1658,8 @@ window.AppI18n = {
|
||||
"update_check": "Preveri posodobitve",
|
||||
"update_check_desc": "Preveri zadnje posodobitve",
|
||||
"search_proc": "Išči procese...",
|
||||
"btn_view": "Poglej",
|
||||
"btn_end": "Končaj opravilo",
|
||||
"manage_white": "Upravitelj seznama dovoljenih",
|
||||
"search_file": "Išči datoteke...",
|
||||
"btn_add": "Dodaj",
|
||||
"btn_remove": "Odstrani",
|
||||
"manage_quarantine": "Upravitelj karantene",
|
||||
"btn_scan": "Skeniraj",
|
||||
"search_window": "Išči okna...",
|
||||
@@ -1578,7 +1684,6 @@ window.AppI18n = {
|
||||
"msg_click_target": "Kliknite na ciljno okno v 5s...",
|
||||
"msg_confirm_block": "Potrdi blokado",
|
||||
"msg_repaired": "Izbrani predmeti popravljeni",
|
||||
"btn_repair": "Popravi",
|
||||
"title_prompt": "Namig",
|
||||
"title_error": "Napaka",
|
||||
"path_unknown": "Neznana pot",
|
||||
@@ -1621,12 +1726,28 @@ window.AppI18n = {
|
||||
"col_status": "Stanje",
|
||||
"status_enabled": "Omogočeno",
|
||||
"status_disabled": "Onemogočeno",
|
||||
"btn_enable": "Omogoči",
|
||||
"btn_disable": "Onemogoči",
|
||||
"search_item": "Išči elemente...",
|
||||
"type_reg": "Register",
|
||||
"type_srv": "Storitev",
|
||||
"type_tsk": "Opravilo",
|
||||
"btn_view_item": "Ogled elementa",
|
||||
"btn_end": "Končaj proces",
|
||||
"btn_enable_item": "Omogoči element",
|
||||
"btn_disable_item": "Onemogoči element",
|
||||
"btn_delete_item": "Izbriši element",
|
||||
"btn_repair_item": "Popravi element",
|
||||
"btn_add_item": "Dodaj element",
|
||||
"btn_remove_item": "Odstrani element",
|
||||
"btn_add_file": "Dodaj datoteko",
|
||||
"btn_add_path": "Dodaj pot",
|
||||
"manage_netmon": "Nadzor prometa",
|
||||
"manage_netmon_desc": "Spremlja omrežni promet v realnem času",
|
||||
"col_down_speed": "Hitrost prenosa",
|
||||
"col_up_speed": "Hitrost nalaganja",
|
||||
"col_conn_count": "Povezave",
|
||||
"btn_extract_item": "Izvleči element",
|
||||
"msg_extract_success": "Izbrani elementi so bili uspešno izvlečeni",
|
||||
"msg_key_activated": "Ključ izdelka je aktiviran"
|
||||
}
|
||||
},
|
||||
langMap: {
|
||||
|
||||
+237
-111
@@ -14,6 +14,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
firstLaunch: false,
|
||||
taskmgrTimer: null,
|
||||
taskmgrActive: false,
|
||||
netmonTimer: null,
|
||||
netmonActive: false,
|
||||
virusMap: new Map(),
|
||||
virusResults: [],
|
||||
junkList: []
|
||||
@@ -85,7 +87,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
pathOnly: [{key: 'path', label: 'col_path', flex: 1}],
|
||||
junk: [{key: 'path', label: 'col_path', flex: 3}, {key: 'sizeStr', label: 'col_size', flex: 1}],
|
||||
popup: [{key: 'exe', label: 'col_prog', flex: 1}, {key: 'class', label: 'col_class', flex: 1}, {key: 'title', label: 'col_title', flex: 2}],
|
||||
repair: [{key: 'display', label: 'col_repair', flex: 1, isI18n: true}, {key: 'path', label: 'col_path', flex: 3}]
|
||||
repair: [{key: 'display', label: 'col_repair', flex: 1, isI18n: true}, {key: 'path', label: 'col_path', flex: 3}],
|
||||
netmon: [{key: 'name', label: 'col_name', flex: 1.5}, {key: 'pid', label: 'col_pid', flex: 0.5}, {key: 'downStr', label: 'col_down_speed', flex: 1}, {key: 'upStr', label: 'col_up_speed', flex: 1}, {key: 'connCount', label: 'col_conn_count', flex: 0.8}]
|
||||
};
|
||||
|
||||
const buildCustomSelectElement = (select) => {
|
||||
@@ -342,7 +345,13 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
displayData.sort((a, b) => {
|
||||
const valA = a[state.sortKey] ?? '', valB = b[state.sortKey] ?? '';
|
||||
if (state.sortKey === 'sizeStr' && 'size' in a && 'size' in b) return state.sortAsc ? a.size - b.size : b.size - a.size;
|
||||
|
||||
const rawKeyMap = { 'sizeStr': 'size', 'downStr': 'down', 'upStr': 'up' };
|
||||
if (rawKeyMap[state.sortKey] && rawKeyMap[state.sortKey] in a && rawKeyMap[state.sortKey] in b) {
|
||||
const rawKey = rawKeyMap[state.sortKey];
|
||||
return state.sortAsc ? a[rawKey] - b[rawKey] : b[rawKey] - a[rawKey];
|
||||
}
|
||||
|
||||
const numA = parseFloat(valA), numB = parseFloat(valB);
|
||||
if (!isNaN(numA) && !isNaN(numB) && String(valA).trim() !== '' && String(valB).trim() !== '') return state.sortAsc ? numA - numB : numB - numA;
|
||||
return state.sortAsc ? String(valA).localeCompare(String(valB)) : String(valB).localeCompare(String(valA));
|
||||
@@ -507,10 +516,35 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
window.pywebview.api.get_process_list().then(procs => {
|
||||
const mapped = procs.map(p => ({ name: p.name, pid: p.pid, path: (p.path && p.path !== "None" && p.path !== "Unknown") ? p.path : "path_unknown" }));
|
||||
renderDataGrid('#taskmgr_window', mapped, cols.process, 'pid', false);
|
||||
if (appState.taskmgrActive) appState.taskmgrTimer = setTimeout(fetchProcs, 2000);
|
||||
}).catch(() => { if (appState.taskmgrActive) appState.taskmgrTimer = setTimeout(fetchProcs, 2000); });
|
||||
if (appState.taskmgrActive) appState.taskmgrTimer = setTimeout(fetchProcs, 1000);
|
||||
}).catch(() => { if (appState.taskmgrActive) appState.taskmgrTimer = setTimeout(fetchProcs, 1000); });
|
||||
} else {
|
||||
if (appState.taskmgrActive) appState.taskmgrTimer = setTimeout(fetchProcs, 2000);
|
||||
if (appState.taskmgrActive) appState.taskmgrTimer = setTimeout(fetchProcs, 1000);
|
||||
}
|
||||
};
|
||||
|
||||
const fetchNetmon = () => {
|
||||
if (!appState.netmonActive || !window.pywebview) return;
|
||||
const widget = document.querySelector('#netmon_window .manage-widget');
|
||||
const blockFetch = widget && (widget.gridState?.checkedSet.size > 0 || widget.matches(':hover')) || document.querySelector('.custom-context-menu.show') || document.body.classList.contains('resizing-active');
|
||||
|
||||
if (!blockFetch) {
|
||||
window.pywebview.api.get_traffic_list().then(list => {
|
||||
const mapped = list.map(item => ({
|
||||
name: item.name,
|
||||
pid: item.pid,
|
||||
downStr: formatSize(item.down) + '/s',
|
||||
down: item.down,
|
||||
upStr: formatSize(item.up) + '/s',
|
||||
up: item.up,
|
||||
connCount: item.conn,
|
||||
path: (item.path && item.path !== "None" && item.path !== "Unknown") ? item.path : "path_unknown"
|
||||
}));
|
||||
renderDataGrid('#netmon_window', mapped, cols.netmon, 'pid', false);
|
||||
if (appState.netmonActive) appState.netmonTimer = setTimeout(fetchNetmon, 1000);
|
||||
}).catch(() => { if (appState.netmonActive) appState.netmonTimer = setTimeout(fetchNetmon, 1000); });
|
||||
} else {
|
||||
if (appState.netmonActive) appState.netmonTimer = setTimeout(fetchNetmon, 1000);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -526,33 +560,28 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
};
|
||||
|
||||
document.querySelector('#startup_window .primary-btn')?.addEventListener('click', () => {
|
||||
const checked = getCheckedValues('#startup_window');
|
||||
if (checked.length > 0 && window.pywebview) {
|
||||
const widget = document.querySelector('#startup_window .manage-widget');
|
||||
if (widget && widget.gridState && widget.gridState.lastDisplayData) {
|
||||
widget.gridState.lastDisplayData.forEach(item => {
|
||||
if (checked.includes(item.id)) item.status = 'status_enabled';
|
||||
});
|
||||
widget.renderData();
|
||||
}
|
||||
window.pywebview.api.manage_startup(checked, 'enable').then(fetchStartup);
|
||||
const fetchJunk = () => {
|
||||
if (!window.pywebview) return;
|
||||
const widget = document.querySelector('#junk_window .manage-widget');
|
||||
if (widget?.gridState) widget.gridState.checkedSet.clear();
|
||||
const listUl = document.querySelector('#junk_window .manage-list');
|
||||
if (listUl && !listUl.children.length) {
|
||||
listUl.innerHTML = `<li class="manage-list-item" style="pointer-events: none; justify-content: center; height: 100%; border: none;"><div style="color: var(--text-secondary); padding: 40px; font-size: 15px;">${getMsg('msg_init')}</div></li>`;
|
||||
}
|
||||
});
|
||||
window.pywebview.api.scan_system_junk().then(list => {
|
||||
appState.junkList = list.map(item => ({ path: item.path, sizeStr: formatSize(item.size), size: item.size }));
|
||||
renderDataGrid('#junk_window', appState.junkList, cols.junk, 'path', true);
|
||||
});
|
||||
};
|
||||
|
||||
document.querySelector('#startup_window .danger-btn')?.addEventListener('click', () => {
|
||||
const checked = getCheckedValues('#startup_window');
|
||||
if (checked.length > 0 && window.pywebview) {
|
||||
const widget = document.querySelector('#startup_window .manage-widget');
|
||||
if (widget && widget.gridState && widget.gridState.lastDisplayData) {
|
||||
widget.gridState.lastDisplayData.forEach(item => {
|
||||
if (checked.includes(item.id)) item.status = 'status_disabled';
|
||||
});
|
||||
widget.renderData();
|
||||
}
|
||||
window.pywebview.api.manage_startup(checked, 'disable').then(fetchStartup);
|
||||
const fetchRepair = () => {
|
||||
if (!window.pywebview) return;
|
||||
const listUl = document.querySelector('#repair_window .manage-list');
|
||||
if (listUl && !listUl.children.length) {
|
||||
listUl.innerHTML = `<li class="manage-list-item" style="pointer-events: none; justify-content: center; height: 100%; border: none;"><div style="color: var(--text-secondary); padding: 40px; font-size: 15px;">${getMsg('msg_init')}</div></li>`;
|
||||
}
|
||||
});
|
||||
window.pywebview.api.scan_system_repair().then(list => renderDataGrid('#repair_window', list, cols.repair, 'id', true));
|
||||
};
|
||||
|
||||
const refreshConfigLists = () => {
|
||||
if (!window.pywebview) return;
|
||||
@@ -586,7 +615,13 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
if (appState.taskmgrActive) fetchProcs();
|
||||
else if (appState.taskmgrTimer) { clearTimeout(appState.taskmgrTimer); appState.taskmgrTimer = null; }
|
||||
|
||||
appState.netmonActive = targetId === 'netmon_window';
|
||||
if (appState.netmonActive) fetchNetmon();
|
||||
else if (appState.netmonTimer) { clearTimeout(appState.netmonTimer); appState.netmonTimer = null; }
|
||||
|
||||
if (targetId === 'startup_window') fetchStartup();
|
||||
if (targetId === 'junk_window') fetchJunk();
|
||||
if (targetId === 'repair_window') fetchRepair();
|
||||
|
||||
if (['whitelist_window', 'quarantine_window', 'popup_window', 'custom_protect_window'].includes(targetId)) refreshConfigLists();
|
||||
|
||||
@@ -736,41 +771,97 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelector('#junk_window .primary-btn')?.addEventListener('click', (e) => {
|
||||
if (!window.pywebview) return;
|
||||
e.target.setAttribute('data-i18n', 'msg_init'); e.target.textContent = getMsg('msg_init');
|
||||
const widget = document.querySelector('#junk_window .manage-widget');
|
||||
if (widget?.gridState) widget.gridState.checkedSet.clear();
|
||||
|
||||
window.pywebview.api.scan_system_junk().then(list => {
|
||||
appState.junkList = list.map(item => ({ path: item.path, sizeStr: formatSize(item.size), size: item.size }));
|
||||
renderDataGrid('#junk_window', appState.junkList, cols.junk, 'path', true);
|
||||
e.target.setAttribute('data-i18n', 'btn_scan'); e.target.textContent = getMsg('btn_scan');
|
||||
});
|
||||
document.getElementById('taskmgr_select')?.addEventListener('change', (e) => {
|
||||
const val = e.target.value;
|
||||
const checkedCbs = document.querySelectorAll('#taskmgr_window .manage-list-item input[type="checkbox"]:checked');
|
||||
if (checkedCbs.length === 0 || !window.pywebview) return updateCustomSelectUI('taskmgr_select', 'none');
|
||||
|
||||
if (val === 'view') {
|
||||
checkedCbs.forEach(cb => {
|
||||
if (cb.dataset.path && cb.dataset.path !== "path_unknown") window.pywebview.api.open_file_location(cb.dataset.path);
|
||||
});
|
||||
} else if (val === 'end') {
|
||||
window.pywebview.api.show_confirm(getMsg("msg_end_proc_title"), getMsg("msg_end_proc_confirm")).then(res => {
|
||||
if (res) Promise.all(Array.from(checkedCbs).map(cb => window.pywebview.api.kill_process(parseInt(cb.value)))).then(() => fetchProcs());
|
||||
});
|
||||
} else if (val === 'quarantine' || val === 'whitelist') {
|
||||
const paths = Array.from(checkedCbs).map(cb => cb.dataset.path).filter(p => p && p !== "path_unknown");
|
||||
if (paths.length > 0) {
|
||||
const listKey = val === 'quarantine' ? 'quarantine' : 'white_list';
|
||||
window.pywebview.api.manage_named_list(listKey, paths, 'add').then(() => {
|
||||
Promise.all(Array.from(checkedCbs).map(cb => window.pywebview.api.kill_process(parseInt(cb.value)))).then(() => fetchProcs());
|
||||
});
|
||||
}
|
||||
}
|
||||
updateCustomSelectUI('taskmgr_select', 'none');
|
||||
});
|
||||
|
||||
document.getElementById('netmon_select')?.addEventListener('change', (e) => {
|
||||
const val = e.target.value;
|
||||
const checkedCbs = document.querySelectorAll('#netmon_window .manage-list-item input[type="checkbox"]:checked');
|
||||
if (checkedCbs.length === 0 || !window.pywebview) return updateCustomSelectUI('netmon_select', 'none');
|
||||
|
||||
if (val === 'view') {
|
||||
checkedCbs.forEach(cb => {
|
||||
if (cb.dataset.path && cb.dataset.path !== "path_unknown") window.pywebview.api.open_file_location(cb.dataset.path);
|
||||
});
|
||||
} else if (val === 'end') {
|
||||
window.pywebview.api.show_confirm(getMsg("msg_end_proc_title"), getMsg("msg_end_proc_confirm")).then(res => {
|
||||
if (res) Promise.all(Array.from(checkedCbs).map(cb => window.pywebview.api.kill_process(parseInt(cb.value)))).then(() => fetchNetmon());
|
||||
});
|
||||
}
|
||||
updateCustomSelectUI('netmon_select', 'none');
|
||||
});
|
||||
|
||||
document.querySelector('#junk_window .danger-btn')?.addEventListener('click', () => {
|
||||
document.getElementById('startup_select')?.addEventListener('change', (e) => {
|
||||
const val = e.target.value;
|
||||
const checked = getCheckedValues('#startup_window');
|
||||
if (checked.length > 0 && window.pywebview) {
|
||||
if (val === 'enable' || val === 'disable') {
|
||||
const widget = document.querySelector('#startup_window .manage-widget');
|
||||
if (widget && widget.gridState && widget.gridState.lastDisplayData) {
|
||||
widget.gridState.lastDisplayData.forEach(item => {
|
||||
if (checked.includes(item.id)) item.status = val === 'enable' ? 'status_enabled' : 'status_disabled';
|
||||
});
|
||||
widget.renderData();
|
||||
}
|
||||
}
|
||||
window.pywebview.api.manage_startup(checked, val).then(fetchStartup);
|
||||
}
|
||||
updateCustomSelectUI('startup_select', 'none');
|
||||
});
|
||||
|
||||
document.getElementById('junk_select')?.addEventListener('change', (e) => {
|
||||
const val = e.target.value;
|
||||
const checked = getCheckedValues('#junk_window');
|
||||
if (checked.length === 0 || !window.pywebview) return;
|
||||
window.pywebview.api.clean_system_junk(checked).then(size => {
|
||||
window.pywebview.api.show_alert(getMsg("title_prompt"), `${getMsg("msg_cleaned")}${formatSize(size)}`, "info");
|
||||
appState.junkList = appState.junkList.filter(item => !checked.includes(item.path));
|
||||
renderDataGrid('#junk_window', appState.junkList, cols.junk, 'path', true);
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelector('#repair_window .primary-btn')?.addEventListener('click', () => {
|
||||
if (!window.pywebview) return;
|
||||
window.pywebview.api.scan_system_repair().then(list => renderDataGrid('#repair_window', list, cols.repair, 'id', true));
|
||||
|
||||
if (val === 'view') {
|
||||
checked.forEach(path => window.pywebview.api.open_file_location(path));
|
||||
} else if (val === 'delete') {
|
||||
if (checked.length > 0) {
|
||||
window.pywebview.api.clean_system_junk(checked).then(size => {
|
||||
window.pywebview.api.show_alert(getMsg("title_prompt"), `${getMsg("msg_cleaned")}${formatSize(size)}`, "info");
|
||||
appState.junkList = appState.junkList.filter(item => !checked.includes(item.path));
|
||||
renderDataGrid('#junk_window', appState.junkList, cols.junk, 'path', true);
|
||||
});
|
||||
}
|
||||
}
|
||||
updateCustomSelectUI('junk_select', 'none');
|
||||
});
|
||||
|
||||
document.querySelector('#repair_window .danger-btn')?.addEventListener('click', () => {
|
||||
const checked = getCheckedValues('#repair_window');
|
||||
if (checked.length === 0 || !window.pywebview) return;
|
||||
window.pywebview.api.execute_system_repair(checked).then(() => {
|
||||
window.pywebview.api.show_alert(getMsg("title_prompt"), getMsg("msg_repaired"), "info");
|
||||
renderDataGrid('#repair_window', [], cols.repair, 'id', true);
|
||||
});
|
||||
document.getElementById('repair_select')?.addEventListener('change', (e) => {
|
||||
const val = e.target.value;
|
||||
if (val === 'repair') {
|
||||
const checked = getCheckedValues('#repair_window');
|
||||
if (checked.length > 0 && window.pywebview) {
|
||||
window.pywebview.api.execute_system_repair(checked).then(() => {
|
||||
window.pywebview.api.show_alert(getMsg("title_prompt"), getMsg("msg_repaired"), "info");
|
||||
renderDataGrid('#repair_window', [], cols.repair, 'id', true);
|
||||
});
|
||||
}
|
||||
}
|
||||
updateCustomSelectUI('repair_select', 'none');
|
||||
});
|
||||
|
||||
['whitelist_window', 'quarantine_window', 'popup_window', 'custom_protect_window'].forEach(id => {
|
||||
@@ -781,65 +872,87 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
'quarantine_window': 'quarantine'
|
||||
};
|
||||
const listKey = listKeyMap[id];
|
||||
const selectId = id.replace('_window', '_select');
|
||||
|
||||
document.querySelector(`#${id} .modern-btn:not(.primary-btn)`)?.addEventListener('click', () => {
|
||||
const checked = getCheckedValues(`#${id}`);
|
||||
if (checked.length > 0 && window.pywebview) window.pywebview.api.remove_list_items(listKey, checked).then(refreshConfigLists);
|
||||
});
|
||||
|
||||
if (id !== 'popup_window') {
|
||||
document.querySelector(`#${id} .primary-btn`)?.addEventListener('click', () => {
|
||||
window.pywebview?.api.select_files().then(files => {
|
||||
document.getElementById(selectId)?.addEventListener('change', (e) => {
|
||||
const val = e.target.value;
|
||||
if (!window.pywebview) return;
|
||||
|
||||
if (val === 'add') {
|
||||
if (id === 'popup_window') {
|
||||
const wrapper = document.getElementById(selectId).nextElementSibling;
|
||||
const triggerText = wrapper.querySelector('.custom-select-text');
|
||||
const originalI18n = triggerText.getAttribute('data-i18n');
|
||||
const originalText = triggerText.textContent;
|
||||
|
||||
triggerText.setAttribute('data-i18n', 'msg_click_target');
|
||||
triggerText.textContent = getMsg('msg_click_target');
|
||||
|
||||
window.pywebview.api.capture_popup_window().then(rule => {
|
||||
triggerText.setAttribute('data-i18n', originalI18n || 'btn_select');
|
||||
triggerText.textContent = originalText;
|
||||
if (rule) window.pywebview.api.add_popup_rule(rule).then(ok => ok && refreshConfigLists());
|
||||
});
|
||||
} else {
|
||||
window.pywebview.api.select_files().then(files => {
|
||||
if (files?.length > 0) window.pywebview.api.manage_named_list(listKey, files, 'add').then(refreshConfigLists);
|
||||
});
|
||||
}
|
||||
} else if (val === 'add_file') {
|
||||
window.pywebview.api.select_files().then(files => {
|
||||
if (files?.length > 0) window.pywebview.api.manage_named_list(listKey, files, 'add').then(refreshConfigLists);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
document.querySelector('#popup_window .primary-btn')?.addEventListener('click', (e) => {
|
||||
if (!window.pywebview) return;
|
||||
e.target.setAttribute('data-i18n', 'msg_click_target'); e.target.textContent = getMsg('msg_click_target'); e.target.disabled = true;
|
||||
window.pywebview.api.capture_popup_window().then(rule => {
|
||||
e.target.setAttribute('data-i18n', 'btn_add'); e.target.textContent = getMsg('btn_add'); e.target.disabled = false;
|
||||
if (rule) window.pywebview.api.add_popup_rule(rule).then(ok => ok && refreshConfigLists());
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelector('#taskmgr_window .primary-btn')?.addEventListener('click', () => {
|
||||
if (!window.pywebview) return;
|
||||
document.querySelectorAll('#taskmgr_window .manage-list-item input[type="checkbox"]:checked').forEach(cb => {
|
||||
if (cb.dataset.path && cb.dataset.path !== "path_unknown") window.pywebview.api.open_file_location(cb.dataset.path);
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelector('#taskmgr_window .danger-btn')?.addEventListener('click', () => {
|
||||
const cbs = document.querySelectorAll('#taskmgr_window .manage-list-item input[type="checkbox"]:checked');
|
||||
if (cbs.length > 0 && window.pywebview) {
|
||||
window.pywebview.api.show_confirm(getMsg("msg_end_proc_title"), getMsg("msg_end_proc_confirm")).then(res => {
|
||||
if (res) Promise.all(Array.from(cbs).map(cb => window.pywebview.api.kill_process(parseInt(cb.value)))).then(() => {
|
||||
window.pywebview.api.get_process_list().then(procs => renderDataGrid('#taskmgr_window', procs.map(p => ({ name: p.name, pid: p.pid, path: (p.path && p.path !== "None" && p.path !== "Unknown") ? p.path : "path_unknown" })), cols.process, 'pid', false));
|
||||
} else if (val === 'add_path') {
|
||||
window.pywebview.api.select_folder().then(folder => {
|
||||
if (folder?.length > 0) window.pywebview.api.manage_named_list(listKey, folder, 'add').then(refreshConfigLists);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
document.querySelector('#log_export_window .primary-btn')?.addEventListener('click', () => {
|
||||
const checked = getCheckedValues('#log_export_window');
|
||||
if (checked.length === 0) return window.pywebview?.api.show_alert(getMsg("title_prompt"), getMsg("msg_sel_log_export"), "warning");
|
||||
window.pywebview?.api.export_logs(checked).then(res => res && window.pywebview.api.show_alert(getMsg("title_prompt"), getMsg("msg_export_success"), "info"));
|
||||
});
|
||||
|
||||
document.querySelector('#log_export_window .danger-btn')?.addEventListener('click', () => {
|
||||
const checked = getCheckedValues('#log_export_window');
|
||||
if (checked.length === 0 || !window.pywebview) return;
|
||||
window.pywebview.api.show_confirm(getMsg("title_prompt"), getMsg("msg_del_log_confirm")).then(res => {
|
||||
if (res) window.pywebview.api.clear_logs(checked).then(() => {
|
||||
window.pywebview.api.get_logs().then(logs => renderDataGrid('#log_export_window', logs.reverse().map(log => ({ time_str: `[${log.time_str}]`, level: log.level, action: log.action, source: log.source || '-', id: log.id })), cols.log, 'id', true));
|
||||
window.pywebview.api.show_alert(getMsg("title_prompt"), getMsg("msg_log_deleted"), "info");
|
||||
});
|
||||
} else if (val === 'extract') {
|
||||
const checked = getCheckedValues(`#${id}`);
|
||||
if (checked.length > 0) {
|
||||
window.pywebview.api.select_folder().then(folder => {
|
||||
if (folder?.length > 0) {
|
||||
window.pywebview.api.extract_list_items(checked, folder[0]).then(success => {
|
||||
if (success) window.pywebview.api.show_alert(getMsg("title_prompt"), getMsg("msg_extract_success"), "info");
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (val === 'remove') {
|
||||
const checked = getCheckedValues(`#${id}`);
|
||||
if (checked.length > 0) window.pywebview.api.remove_list_items(listKey, checked).then(refreshConfigLists);
|
||||
} else if (val === 'quarantine' || val === 'whitelist') {
|
||||
const checked = getCheckedValues(`#${id}`);
|
||||
if (checked.length > 0) {
|
||||
const targetKey = val === 'quarantine' ? 'quarantine' : 'white_list';
|
||||
window.pywebview.api.manage_named_list(targetKey, checked, 'add').then(() => refreshConfigLists());
|
||||
}
|
||||
}
|
||||
updateCustomSelectUI(selectId, 'none');
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById('log_export_select')?.addEventListener('change', (e) => {
|
||||
const val = e.target.value;
|
||||
const checked = getCheckedValues('#log_export_window');
|
||||
if (val === 'export') {
|
||||
if (checked.length === 0) {
|
||||
window.pywebview?.api.show_alert(getMsg("title_prompt"), getMsg("msg_sel_log_export"), "warning");
|
||||
} else {
|
||||
window.pywebview?.api.export_logs(checked).then(res => res && window.pywebview.api.show_alert(getMsg("title_prompt"), getMsg("msg_export_success"), "info"));
|
||||
}
|
||||
} else if (val === 'delete') {
|
||||
if (checked.length > 0 && window.pywebview) {
|
||||
window.pywebview.api.show_confirm(getMsg("title_prompt"), getMsg("msg_del_log_confirm")).then(res => {
|
||||
if (res) window.pywebview.api.clear_logs(checked).then(() => {
|
||||
window.pywebview.api.get_logs().then(logs => renderDataGrid('#log_export_window', logs.reverse().map(log => ({ time_str: `[${log.time_str}]`, level: log.level, action: log.action, source: log.source || '-', id: log.id })), cols.log, 'id', true));
|
||||
window.pywebview.api.show_alert(getMsg("title_prompt"), getMsg("msg_log_deleted"), "info");
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
updateCustomSelectUI('log_export_select', 'none');
|
||||
});
|
||||
|
||||
document.getElementById('minimize_button')?.addEventListener('click', () => window.pywebview?.api.minimize());
|
||||
document.getElementById('close_button')?.addEventListener('click', () => window.pywebview?.api.hide_window());
|
||||
|
||||
@@ -897,7 +1010,18 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
};
|
||||
|
||||
bindSettingAction('key_product', async () => {
|
||||
if (!window.pywebview) return;
|
||||
try {
|
||||
const cfg = await window.pywebview.api.get_config();
|
||||
if (cfg && cfg.api_key && cfg.api_key.trim() !== "") {
|
||||
window.pywebview.api.show_alert(getMsg("title_prompt"), getMsg("msg_key_activated"), "info");
|
||||
}
|
||||
} catch (e) {}
|
||||
});
|
||||
|
||||
bindSettingAction('web_official', () => window.pywebview?.api.open_website());
|
||||
|
||||
bindSettingAction('update_check', () => {
|
||||
window.pywebview?.api.check_update().then(res => {
|
||||
if (res.error) window.pywebview.api.show_alert(getMsg("title_error"), getMsg("msg_update_fail"), "error");
|
||||
@@ -905,6 +1029,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
else window.pywebview.api.show_alert(getMsg("title_prompt"), `${getMsg("msg_latest_version")} ${res.current}`, "info");
|
||||
});
|
||||
});
|
||||
|
||||
bindSettingAction('opt_reset', () => {
|
||||
window.pywebview?.api.show_confirm(getMsg("title_prompt"), getMsg("opt_reset_desc")).then(res => {
|
||||
if (res) window.pywebview.api.reset_config().then(() => window.pywebview.api.show_alert(getMsg("title_prompt"), getMsg("msg_reset_success"), "info"));
|
||||
@@ -922,6 +1047,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
renderDataGrid('#custom_protect_window', [], cols.pathOnly, 'path', false);
|
||||
renderDataGrid('#popup_window', [], cols.popup, 'value', false);
|
||||
renderDataGrid('#log_export_window', [], cols.log, 'id', true);
|
||||
renderDataGrid('#netmon_window', [], cols.netmon, 'pid', false);
|
||||
|
||||
window.addEventListener('pywebviewready', () => {
|
||||
window.pywebview.api.get_config().then(cfg => {
|
||||
@@ -967,7 +1093,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
if (res !== undefined && res !== null) toggle.checked = res;
|
||||
} catch { toggle.checked = false; }
|
||||
finally { toggle.disabled = false; }
|
||||
await new Promise(r => setTimeout(r, 200));
|
||||
await new Promise(r => setTimeout(r, 100));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,6 +174,12 @@
|
||||
</div>
|
||||
<button class="icon-action-btn"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg></button>
|
||||
</div>
|
||||
<div class="list-item" style="cursor: pointer;" data-target="netmon_window">
|
||||
<div class="item-info">
|
||||
<h2 data-i18n>流量監控</h2><p data-i18n>此選項可以實時監控網路流量</p>
|
||||
</div>
|
||||
<button class="icon-action-btn"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg></button>
|
||||
</div>
|
||||
<div class="list-item" style="cursor: pointer;" data-target="whitelist_window">
|
||||
<div class="item-info">
|
||||
<h2 data-i18n>白名單</h2><p data-i18n>此選項可以查看並管理白名單</p>
|
||||
@@ -321,8 +327,15 @@ Last updated: 2025-12-19
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
|
||||
<input type="text" data-i18n-placeholder="搜尋進程..." placeholder="搜尋進程...">
|
||||
</div>
|
||||
<button class="action-btn modern-btn primary-btn" data-i18n>查看</button>
|
||||
<button class="action-btn modern-btn danger-btn" data-i18n>結束</button>
|
||||
<div class="action-group modern-action-group">
|
||||
<select id="taskmgr_select" class="modern-select">
|
||||
<option value="none" selected disabled data-i18n="btn_select">選擇</option>
|
||||
<option value="view" data-i18n="btn_view_item">查看項目</option>
|
||||
<option value="end" data-i18n="btn_end">結束進程</option>
|
||||
<option value="quarantine" data-i18n="act_quarantine">加入隔離區</option>
|
||||
<option value="whitelist" data-i18n="act_white">加入白名單</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="manage-widget flex-grow"><ul class="manage-list"></ul></div>
|
||||
</section>
|
||||
@@ -336,8 +349,14 @@ Last updated: 2025-12-19
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
|
||||
<input type="text" data-i18n-placeholder="搜尋項目..." placeholder="搜尋項目...">
|
||||
</div>
|
||||
<button class="action-btn modern-btn primary-btn" data-i18n>啟用</button>
|
||||
<button class="action-btn modern-btn danger-btn" data-i18n>禁用</button>
|
||||
<div class="action-group modern-action-group">
|
||||
<select id="startup_select" class="modern-select">
|
||||
<option value="none" selected disabled data-i18n="btn_select">選擇</option>
|
||||
<option value="enable" data-i18n="btn_enable_item">啟用項目</option>
|
||||
<option value="disable" data-i18n="btn_disable_item">禁用項目</option>
|
||||
<option value="delete" data-i18n="btn_delete_item">刪除項目</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="manage-widget flex-grow"><ul class="manage-list"></ul></div>
|
||||
</section>
|
||||
@@ -351,8 +370,16 @@ Last updated: 2025-12-19
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
|
||||
<input type="text" data-i18n-placeholder="搜尋檔案..." placeholder="搜尋檔案...">
|
||||
</div>
|
||||
<button class="action-btn modern-btn primary-btn" data-i18n>加入</button>
|
||||
<button class="action-btn modern-btn" data-i18n>移除</button>
|
||||
<div class="action-group modern-action-group">
|
||||
<select id="whitelist_select" class="modern-select">
|
||||
<option value="none" selected disabled data-i18n="btn_select">選擇</option>
|
||||
<option value="add_file" data-i18n="btn_add_file">新增檔案</option>
|
||||
<option value="add_path" data-i18n="btn_add_path">新增路徑</option>
|
||||
<option value="extract" data-i18n="btn_extract_item">提取項目</option>
|
||||
<option value="remove" data-i18n="btn_remove_item">移除項目</option>
|
||||
<option value="quarantine" data-i18n="act_quarantine">加入隔離區</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="manage-widget flex-grow"><ul class="manage-list"></ul></div>
|
||||
</section>
|
||||
@@ -366,8 +393,16 @@ Last updated: 2025-12-19
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
|
||||
<input type="text" data-i18n-placeholder="搜尋檔案..." placeholder="搜尋檔案...">
|
||||
</div>
|
||||
<button class="action-btn modern-btn primary-btn" data-i18n>加入</button>
|
||||
<button class="action-btn modern-btn" data-i18n>移除</button>
|
||||
<div class="action-group modern-action-group">
|
||||
<select id="quarantine_select" class="modern-select">
|
||||
<option value="none" selected disabled data-i18n="btn_select">選擇</option>
|
||||
<option value="add_file" data-i18n="btn_add_file">新增檔案</option>
|
||||
<option value="add_path" data-i18n="btn_add_path">新增路徑</option>
|
||||
<option value="extract" data-i18n="btn_extract_item">提取項目</option>
|
||||
<option value="remove" data-i18n="btn_remove_item">移除項目</option>
|
||||
<option value="whitelist" data-i18n="act_white">加入白名單</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="manage-widget flex-grow"><ul class="manage-list"></ul></div>
|
||||
</section>
|
||||
@@ -381,8 +416,13 @@ Last updated: 2025-12-19
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
|
||||
<input type="text" data-i18n-placeholder="搜尋檔案..." placeholder="搜尋檔案...">
|
||||
</div>
|
||||
<button class="action-btn modern-btn primary-btn" data-i18n>掃描</button>
|
||||
<button class="action-btn modern-btn danger-btn" data-i18n>刪除</button>
|
||||
<div class="action-group modern-action-group">
|
||||
<select id="junk_select" class="modern-select">
|
||||
<option value="none" selected disabled data-i18n="btn_select">選擇</option>
|
||||
<option value="view" data-i18n="btn_view_item">查看項目</option>
|
||||
<option value="delete" data-i18n="btn_delete_item">刪除項目</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="manage-widget flex-grow"><ul class="manage-list"></ul></div>
|
||||
</section>
|
||||
@@ -392,8 +432,12 @@ Last updated: 2025-12-19
|
||||
<button class="icon-btn" data-target="tool_window"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"></polyline></svg></button>
|
||||
<h2 data-i18n>系統修復</h2>
|
||||
<div class="spacer"></div>
|
||||
<button class="action-btn modern-btn primary-btn" data-i18n>掃描</button>
|
||||
<button class="action-btn modern-btn danger-btn" data-i18n>修復</button>
|
||||
<div class="action-group modern-action-group">
|
||||
<select id="repair_select" class="modern-select">
|
||||
<option value="none" selected disabled data-i18n="btn_select">選擇</option>
|
||||
<option value="repair" data-i18n="btn_repair_item">修復項目</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="manage-widget flex-grow"><ul class="manage-list"></ul></div>
|
||||
</section>
|
||||
@@ -407,8 +451,33 @@ Last updated: 2025-12-19
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
|
||||
<input type="text" data-i18n-placeholder="搜尋窗口..." placeholder="搜尋窗口...">
|
||||
</div>
|
||||
<button class="action-btn modern-btn primary-btn" data-i18n>加入</button>
|
||||
<button class="action-btn modern-btn" data-i18n>移除</button>
|
||||
<div class="action-group modern-action-group">
|
||||
<select id="popup_select" class="modern-select">
|
||||
<option value="none" selected disabled data-i18n="btn_select">選擇</option>
|
||||
<option value="add" data-i18n="btn_add_item">新增項目</option>
|
||||
<option value="remove" data-i18n="btn_remove_item">移除項目</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="manage-widget flex-grow"><ul class="manage-list"></ul></div>
|
||||
</section>
|
||||
|
||||
<section id="netmon_window" class="page sub-page">
|
||||
<div class="sub-header-toolbar">
|
||||
<button class="icon-btn" data-target="tool_window"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"></polyline></svg></button>
|
||||
<h2 data-i18n>流量監控</h2>
|
||||
<div class="spacer"></div>
|
||||
<div class="search-box">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
|
||||
<input type="text" data-i18n-placeholder="搜尋進程..." placeholder="搜尋進程...">
|
||||
</div>
|
||||
<div class="action-group modern-action-group">
|
||||
<select id="netmon_select" class="modern-select">
|
||||
<option value="none" selected disabled data-i18n="btn_select">選擇</option>
|
||||
<option value="view" data-i18n="btn_view_item">查看項目</option>
|
||||
<option value="end" data-i18n="btn_end">結束進程</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="manage-widget flex-grow"><ul class="manage-list"></ul></div>
|
||||
</section>
|
||||
@@ -422,8 +491,13 @@ Last updated: 2025-12-19
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
|
||||
<input type="text" data-i18n-placeholder="搜尋規則..." placeholder="搜尋規則...">
|
||||
</div>
|
||||
<button class="action-btn modern-btn primary-btn" data-i18n>加入</button>
|
||||
<button class="action-btn modern-btn" data-i18n>移除</button>
|
||||
<div class="action-group modern-action-group">
|
||||
<select id="custom_protect_select" class="modern-select">
|
||||
<option value="none" selected disabled data-i18n="btn_select">選擇</option>
|
||||
<option value="add" data-i18n="btn_add_item">新增項目</option>
|
||||
<option value="remove" data-i18n="btn_remove_item">移除項目</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="manage-widget flex-grow"><ul class="manage-list"></ul></div>
|
||||
</section>
|
||||
@@ -437,8 +511,13 @@ Last updated: 2025-12-19
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
|
||||
<input type="text" data-i18n-placeholder="搜尋日誌..." placeholder="搜尋日誌...">
|
||||
</div>
|
||||
<button class="action-btn modern-btn primary-btn" data-i18n>導出</button>
|
||||
<button class="action-btn modern-btn danger-btn" data-i18n>刪除</button>
|
||||
<div class="action-group modern-action-group">
|
||||
<select id="log_export_select" class="modern-select">
|
||||
<option value="none" selected disabled data-i18n="btn_select">選擇</option>
|
||||
<option value="export" data-i18n="btn_export">導出項目</option>
|
||||
<option value="delete" data-i18n="btn_remove_item">移除項目</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="manage-widget flex-grow"><ul class="manage-list"></ul></div>
|
||||
</section>
|
||||
|
||||
@@ -115,6 +115,16 @@ class COPYDATASTRUCT(ctypes.Structure):
|
||||
("lpData", ctypes.c_void_p)
|
||||
]
|
||||
|
||||
class IO_COUNTERS(ctypes.Structure):
|
||||
_fields_ = [
|
||||
("ReadOperationCount", ctypes.c_ulonglong),
|
||||
("WriteOperationCount", ctypes.c_ulonglong),
|
||||
("OtherOperationCount", ctypes.c_ulonglong),
|
||||
("ReadTransferCount", ctypes.c_ulonglong),
|
||||
("WriteTransferCount", ctypes.c_ulonglong),
|
||||
("OtherTransferCount", ctypes.c_ulonglong)
|
||||
]
|
||||
|
||||
####################################################################################################
|
||||
|
||||
class WindowAPI:
|
||||
@@ -285,6 +295,8 @@ class WindowAPI:
|
||||
self.kernel32.ReadProcessMemory.argtypes = [ctypes.wintypes.HANDLE, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t, ctypes.POINTER(ctypes.c_size_t)]
|
||||
self.kernel32.QueryFullProcessImageNameW.restype = ctypes.wintypes.BOOL
|
||||
self.kernel32.QueryFullProcessImageNameW.argtypes = [ctypes.wintypes.HANDLE, ctypes.wintypes.DWORD, ctypes.c_wchar_p, ctypes.POINTER(ctypes.wintypes.DWORD)]
|
||||
self.kernel32.GetProcessIoCounters.argtypes = [ctypes.wintypes.HANDLE, ctypes.POINTER(IO_COUNTERS)]
|
||||
self.kernel32.GetProcessIoCounters.restype = ctypes.wintypes.BOOL
|
||||
|
||||
def init_variables(self):
|
||||
self.python = sys.executable
|
||||
@@ -295,6 +307,9 @@ class WindowAPI:
|
||||
self.cloud = cloud_scanner()
|
||||
self.cloud_queue = queue.Queue()
|
||||
|
||||
self.ui_queue = queue.Queue()
|
||||
self.start_daemon_thread(self.ui_dispatcher_thread)
|
||||
|
||||
self.lock_driver = threading.RLock()
|
||||
self.lock_update = threading.RLock()
|
||||
self.driver_port = None
|
||||
@@ -312,13 +327,16 @@ class WindowAPI:
|
||||
self.lock_proc = threading.RLock()
|
||||
self.lock_net = threading.RLock()
|
||||
self.lock_file_ops = threading.RLock()
|
||||
self.lock_io = threading.RLock()
|
||||
self.last_io_counters = {}
|
||||
self.last_io_time = time.time()
|
||||
|
||||
self.scan_events = {}
|
||||
self.scan_cache = {}
|
||||
self.cloud_pending = set()
|
||||
|
||||
self.pyas_default = {
|
||||
"version": "3.5.7",
|
||||
"version": "3.5.8",
|
||||
"api_host": "https://pyas-security.com/",
|
||||
"api_key": "fBRZxYS1UxykM-qzNOlKOEl63WILzlvgNMn6QfsG6FXCAAIktCrOPTAfY5_hEyuZ",
|
||||
"suffix": [".exe", ".dll", ".sys", ".ocx", ".scr", ".efi", ".acm", ".ax", ".cpl", ".drv", ".com", ".mui", ".pyd", ".wfx", ".api", ".awx", ".rll", ".winmd", ".ax"],
|
||||
@@ -355,6 +373,35 @@ class WindowAPI:
|
||||
for _ in range(2):
|
||||
self.start_daemon_thread(self.cloud_worker)
|
||||
|
||||
def ui_dispatcher_thread(self):
|
||||
batch = []
|
||||
while True:
|
||||
try:
|
||||
task = self.ui_queue.get(timeout=0.1)
|
||||
batch.append(task)
|
||||
|
||||
while not self.ui_queue.empty() and len(batch) < 50:
|
||||
try:
|
||||
batch.append(self.ui_queue.get_nowait())
|
||||
except queue.Empty:
|
||||
break
|
||||
|
||||
if self._window and batch:
|
||||
js_script = "".join(batch)
|
||||
try:
|
||||
self._window.evaluate_js(js_script)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
for _ in batch:
|
||||
self.ui_queue.task_done()
|
||||
batch.clear()
|
||||
|
||||
except queue.Empty:
|
||||
continue
|
||||
except Exception:
|
||||
batch.clear()
|
||||
|
||||
def _loc(self, text_dict):
|
||||
with self.lock_config:
|
||||
lang = self.pyas_config.get("language", "traditional_switch") if hasattr(self, 'pyas_config') else "traditional_switch"
|
||||
@@ -515,7 +562,8 @@ class WindowAPI:
|
||||
self.logs_dirty = True
|
||||
|
||||
if self._window:
|
||||
self._window.evaluate_js(f"if(window.updateLogs) window.updateLogs({json.dumps(entry)});")
|
||||
js_cmd = f"if(window.updateLogs) window.updateLogs({json.dumps(entry)});"
|
||||
self.ui_queue.put(js_cmd)
|
||||
|
||||
if level == "BLOCK" and self.tray_icon:
|
||||
self.trigger_block_notification(action, source, target, code)
|
||||
@@ -563,7 +611,7 @@ class WindowAPI:
|
||||
if list_key == "quarantine" and lock_func is None:
|
||||
lock_func = self.lock_file
|
||||
|
||||
norm_paths = self.norm_path(files or [], must_exist=True)
|
||||
norm_paths = self.norm_path(files or [], must_exist=False)
|
||||
if isinstance(norm_paths, str):
|
||||
norm_paths = [norm_paths] if norm_paths else []
|
||||
|
||||
@@ -582,7 +630,15 @@ class WindowAPI:
|
||||
|
||||
if action == "add":
|
||||
for path in norm_paths:
|
||||
exists = any(self.norm_path(item.get("file", "")) == path for item in target_list if isinstance(item, dict))
|
||||
path_case = os.path.normcase(path)
|
||||
exists = False
|
||||
for item in target_list:
|
||||
if isinstance(item, dict):
|
||||
val = item.get("file", "")
|
||||
np = self.norm_path(val, must_exist=False)
|
||||
if np and os.path.normcase(np) == path_case:
|
||||
exists = True
|
||||
break
|
||||
if not exists:
|
||||
if lock_func:
|
||||
lock_func(path, True)
|
||||
@@ -591,15 +647,21 @@ class WindowAPI:
|
||||
if list_key == "white_list":
|
||||
self.sync_driver_whitelist(path, True)
|
||||
elif action == "remove":
|
||||
for item in list(target_list):
|
||||
file_path = self.norm_path(item.get("file", ""))
|
||||
if isinstance(item, dict) and file_path in norm_paths:
|
||||
if lock_func:
|
||||
lock_func(file_path, False)
|
||||
target_list.remove(item)
|
||||
acted_items.append(file_path)
|
||||
if list_key == "white_list":
|
||||
self.sync_driver_whitelist(file_path, False)
|
||||
norm_paths_case = {os.path.normcase(p) for p in norm_paths}
|
||||
new_list = []
|
||||
for item in target_list:
|
||||
val = item.get("file", "") if isinstance(item, dict) else item
|
||||
if val:
|
||||
np = self.norm_path(val, must_exist=False)
|
||||
if np and os.path.normcase(np) in norm_paths_case:
|
||||
if lock_func:
|
||||
lock_func(val, False)
|
||||
acted_items.append(val)
|
||||
if list_key == "white_list":
|
||||
self.sync_driver_whitelist(val, False)
|
||||
continue
|
||||
new_list.append(item)
|
||||
target_list[:] = new_list
|
||||
|
||||
if acted_items:
|
||||
self.write_log("INFO", "Config Update", detail=f"List [{list_key}] {action}: {acted_items}")
|
||||
@@ -611,29 +673,32 @@ class WindowAPI:
|
||||
target_list = self.pyas_config.get(list_key, [])
|
||||
original_len = len(target_list)
|
||||
|
||||
norm_paths_to_remove = set()
|
||||
for p in paths_to_remove:
|
||||
np = self.norm_path(p, must_exist=False)
|
||||
if np:
|
||||
norm_paths_to_remove.add(os.path.normcase(np))
|
||||
|
||||
if list_key == "quarantine":
|
||||
for item in target_list:
|
||||
if isinstance(item, dict) and item.get("file") in paths_to_remove:
|
||||
self.lock_file(item["file"], False)
|
||||
val = item.get("file") if isinstance(item, dict) else item
|
||||
if val:
|
||||
np = self.norm_path(val, must_exist=False)
|
||||
if np and os.path.normcase(np) in norm_paths_to_remove:
|
||||
self.lock_file(val, False)
|
||||
|
||||
new_list = []
|
||||
removed_items = []
|
||||
for item in target_list:
|
||||
if isinstance(item, dict):
|
||||
val = item.get("file") or item.get("exe") or item.get("title")
|
||||
if val not in paths_to_remove:
|
||||
new_list.append(item)
|
||||
else:
|
||||
val = item.get("file") or item.get("exe") or item.get("title") if isinstance(item, dict) else item
|
||||
if val:
|
||||
np = self.norm_path(val, must_exist=False)
|
||||
if np and os.path.normcase(np) in norm_paths_to_remove:
|
||||
removed_items.append(val)
|
||||
if list_key == "white_list":
|
||||
self.sync_driver_whitelist(val, False)
|
||||
else:
|
||||
if item not in paths_to_remove:
|
||||
new_list.append(item)
|
||||
else:
|
||||
removed_items.append(item)
|
||||
if list_key == "white_list":
|
||||
self.sync_driver_whitelist(item, False)
|
||||
continue
|
||||
new_list.append(item)
|
||||
|
||||
self.pyas_config[list_key] = new_list
|
||||
|
||||
@@ -643,6 +708,35 @@ class WindowAPI:
|
||||
return True
|
||||
return False
|
||||
|
||||
def extract_list_items(self, paths, dest_dir):
|
||||
if not dest_dir or not os.path.exists(dest_dir):
|
||||
return False
|
||||
extracted_count = 0
|
||||
for raw_path in paths:
|
||||
src = self.norm_path(raw_path, must_exist=True)
|
||||
if not src:
|
||||
continue
|
||||
base_name = os.path.basename(src)
|
||||
target_path = os.path.join(dest_dir, base_name)
|
||||
|
||||
if os.path.exists(target_path):
|
||||
name, ext = os.path.splitext(base_name)
|
||||
counter = 1
|
||||
while os.path.exists(target_path):
|
||||
target_path = os.path.join(dest_dir, f"{name} ({counter}){ext}")
|
||||
counter += 1
|
||||
|
||||
try:
|
||||
if os.path.isdir(src):
|
||||
shutil.copytree(src, target_path)
|
||||
else:
|
||||
shutil.copy2(src, target_path)
|
||||
extracted_count += 1
|
||||
self.write_log("INFO", "File Extract", source=src, target=target_path, operate=True)
|
||||
except Exception as e:
|
||||
self.write_log("WARN", "extract_list_items", source=src, detail=str(e), success=False)
|
||||
return extracted_count > 0
|
||||
|
||||
####################################################################################################
|
||||
|
||||
def set_window(self, window):
|
||||
@@ -676,6 +770,12 @@ class WindowAPI:
|
||||
"spanish_switch": "Abrir PYAS", "hindi_switch": "PYAS खोलें", "arabic_switch": "فتح PYAS",
|
||||
"russian_switch": "Открыть PYAS", "slovenian_switch": "Odpri PYAS"
|
||||
},
|
||||
"check_update": {
|
||||
"traditional_switch": "檢查更新", "simplified_switch": "检查更新", "english_switch": "Check Update",
|
||||
"japanese_switch": "更新を確認", "korean_switch": "업데이트 확인", "french_switch": "Vérifier la mise à jour",
|
||||
"spanish_switch": "Buscar actualizaciones", "hindi_switch": "अद्यतन जाँचे", "arabic_switch": "التحقق من التحديثات",
|
||||
"russian_switch": "Проверить обновления", "slovenian_switch": "Preveri posodobitve"
|
||||
},
|
||||
"exit_app": {
|
||||
"traditional_switch": "退出防護", "simplified_switch": "退出防护", "english_switch": "Exit Security",
|
||||
"japanese_switch": "保護を終了", "korean_switch": "보호 종료", "french_switch": "Quitter la sécurité",
|
||||
@@ -690,11 +790,34 @@ class WindowAPI:
|
||||
return
|
||||
menu = pystray.Menu(
|
||||
pystray.MenuItem(lambda item: self.get_tray_text("open_ui"), self.restore_from_tray, default=True),
|
||||
pystray.MenuItem(lambda item: self.get_tray_text("check_update"), self.tray_check_update),
|
||||
pystray.MenuItem(lambda item: self.get_tray_text("exit_app"), self.close)
|
||||
)
|
||||
self.tray_icon = pystray.Icon("PYAS", self.get_app_icon(), "PYAS Security", menu)
|
||||
self.tray_icon.run_detached()
|
||||
|
||||
def tray_check_update(self, icon=None, item=None):
|
||||
def _check():
|
||||
res = self.check_update()
|
||||
|
||||
title_error = self._loc({"traditional_switch": "錯誤", "simplified_switch": "错误", "english_switch": "Error", "japanese_switch": "エラー", "korean_switch": "오류", "french_switch": "Erreur", "spanish_switch": "Error", "hindi_switch": "त्रुटि", "arabic_switch": "خطأ", "russian_switch": "Ошибка", "slovenian_switch": "Napaka"})
|
||||
title_prompt = self._loc({"traditional_switch": "提示", "simplified_switch": "提示", "english_switch": "Prompt", "japanese_switch": "プロンプト", "korean_switch": "프롬프트", "french_switch": "Indication", "spanish_switch": "Aviso", "hindi_switch": "सुझाव", "arabic_switch": "تلميح", "russian_switch": "Подсказка", "slovenian_switch": "Namig"})
|
||||
msg_fail = self._loc({"traditional_switch": "檢查更新失敗", "simplified_switch": "检查更新失败", "english_switch": "Update check failed", "japanese_switch": "アップデートの確認に失敗しました", "korean_switch": "업데이트 확인 실패", "french_switch": "Échec de la vérification des mises à jour", "spanish_switch": "Fallo al buscar actualizaciones", "hindi_switch": "अपडेट की जाँच विफल रही", "arabic_switch": "فشل التحقق من التحديثات", "russian_switch": "Ошибка проверки обновлений", "slovenian_switch": "Preverjanje posodobitev ni uspelo"})
|
||||
msg_new = self._loc({"traditional_switch": "發現新版本", "simplified_switch": "发现新版本", "english_switch": "New version found", "japanese_switch": "新しいバージョンが見つかりました", "korean_switch": "새 버전을 찾았습니다", "french_switch": "Nouvelle version trouvée", "spanish_switch": "Nueva versión encontrada", "hindi_switch": "नया संस्करण मिला", "arabic_switch": "تم العثور على إصدار جديد", "russian_switch": "Найдена новая версия", "slovenian_switch": "Najdena nova različica"})
|
||||
msg_latest = self._loc({"traditional_switch": "當前已是最新版本", "simplified_switch": "当前已是最新版本", "english_switch": "Currently at latest version", "japanese_switch": "現在は最新バージョンです", "korean_switch": "현재 최신 버전입니다", "french_switch": "Actuellement à la dernière version", "spanish_switch": "Actualmente en la última versión", "hindi_switch": "वर्तमान में नवीनतम संस्करण है", "arabic_switch": "أنت تستخدم أحدث إصدار حاليًا", "russian_switch": "Установлена последняя версия", "slovenian_switch": "Trenutno imate najnovejšo različico"})
|
||||
|
||||
if res.get("error"):
|
||||
self.show_alert(title_error, msg_fail, "error")
|
||||
elif res.get("has_update"):
|
||||
msg = f"{msg_new} {res.get('latest')}\n({res.get('current')} -> {res.get('latest')})"
|
||||
if self.show_confirm(title_prompt, msg):
|
||||
self.open_url(res.get("url"))
|
||||
else:
|
||||
msg = f"{msg_latest} {res.get('current')}"
|
||||
self.show_alert(title_prompt, msg, "info")
|
||||
|
||||
threading.Thread(target=_check, daemon=True).start()
|
||||
|
||||
def restore_from_tray(self, icon=None, item=None):
|
||||
if self._window:
|
||||
self._window.restore()
|
||||
@@ -825,11 +948,13 @@ class WindowAPI:
|
||||
threading.Thread(target=_process_drop, daemon=True).start()
|
||||
|
||||
def select_files(self):
|
||||
if self._window: return self._window.create_file_dialog(webview.FileDialog.OPEN, allow_multiple=True) or []
|
||||
if self._window:
|
||||
return self._window.create_file_dialog(getattr(webview, 'OPEN_DIALOG', 10), allow_multiple=True) or []
|
||||
return []
|
||||
|
||||
def select_folder(self):
|
||||
if self._window: return self._window.create_file_dialog(webview.FileDialog.FOLDER) or []
|
||||
if self._window:
|
||||
return self._window.create_file_dialog(getattr(webview, 'FOLDER_DIALOG', 20)) or []
|
||||
return []
|
||||
|
||||
def open_file_location(self, file_path):
|
||||
@@ -1054,6 +1179,59 @@ class WindowAPI:
|
||||
except Exception: pass
|
||||
return connections
|
||||
|
||||
def get_traffic_list(self):
|
||||
conns = self.get_connections_list()
|
||||
conn_map = {}
|
||||
for pid, _, _ in conns:
|
||||
conn_map[pid] = conn_map.get(pid, 0) + 1
|
||||
|
||||
current_io = {}
|
||||
current_time = time.time()
|
||||
|
||||
with self.lock_io:
|
||||
time_diff = current_time - self.last_io_time
|
||||
if time_diff <= 0: time_diff = 1
|
||||
self.last_io_time = current_time
|
||||
old_counters = self.last_io_counters.copy()
|
||||
|
||||
result = []
|
||||
exist_process = self.get_process_list_pids()
|
||||
|
||||
for pid in exist_process:
|
||||
name, file_path = "Unknown", ""
|
||||
if pid > 4: name, file_path = self.get_exe_info(pid)
|
||||
else: name = "System"
|
||||
|
||||
down_speed, up_speed = 0, 0
|
||||
h = self.kernel32.OpenProcess(0x1000, False, pid)
|
||||
if h:
|
||||
try:
|
||||
io = IO_COUNTERS()
|
||||
if self.kernel32.GetProcessIoCounters(h, ctypes.byref(io)):
|
||||
current_io[pid] = (io.ReadTransferCount, io.WriteTransferCount)
|
||||
if pid in old_counters:
|
||||
old_read, old_write = old_counters[pid]
|
||||
down_speed = max(0, (io.ReadTransferCount - old_read) / time_diff)
|
||||
up_speed = max(0, (io.WriteTransferCount - old_write) / time_diff)
|
||||
finally:
|
||||
self.kernel32.CloseHandle(h)
|
||||
|
||||
count = conn_map.get(pid, 0)
|
||||
if count > 0 or down_speed > 0 or up_speed > 0:
|
||||
result.append({
|
||||
"pid": pid,
|
||||
"name": name,
|
||||
"path": file_path or "None",
|
||||
"down": int(down_speed),
|
||||
"up": int(up_speed),
|
||||
"conn": count
|
||||
})
|
||||
|
||||
with self.lock_io:
|
||||
self.last_io_counters = current_io
|
||||
|
||||
return result
|
||||
|
||||
def _traverse_delete(self, path):
|
||||
deleted = 0
|
||||
if not os.path.exists(path): return deleted
|
||||
@@ -1246,20 +1424,29 @@ class WindowAPI:
|
||||
stype = parts[0]
|
||||
if stype == "reg":
|
||||
root, old_path, name = int(parts[1]), parts[2], parts[3]
|
||||
new_path = old_path.replace("_Disabled", "") if action == "enable" else (old_path if "_Disabled" in old_path else old_path + "_Disabled")
|
||||
if old_path != new_path:
|
||||
val = self._reg_read(root, old_path, name)
|
||||
if val:
|
||||
self._reg_write(root, new_path, name, winreg.REG_SZ, val)
|
||||
self._reg_delete(root, old_path, name)
|
||||
if action == "delete":
|
||||
self._reg_delete(root, old_path, name)
|
||||
else:
|
||||
new_path = old_path.replace("_Disabled", "") if action == "enable" else (old_path if "_Disabled" in old_path else old_path + "_Disabled")
|
||||
if old_path != new_path:
|
||||
val = self._reg_read(root, old_path, name)
|
||||
if val:
|
||||
self._reg_write(root, new_path, name, winreg.REG_SZ, val)
|
||||
self._reg_delete(root, old_path, name)
|
||||
elif stype == "srv":
|
||||
name = parts[1]
|
||||
mode = "auto" if action == "enable" else "disabled"
|
||||
subprocess.run(["sc", "config", name, f"start=", mode], capture_output=True, creationflags=0x08000000)
|
||||
if action == "delete":
|
||||
subprocess.run(["sc", "delete", name], capture_output=True, creationflags=0x08000000)
|
||||
else:
|
||||
mode = "auto" if action == "enable" else "disabled"
|
||||
subprocess.run(["sc", "config", name, f"start=", mode], capture_output=True, creationflags=0x08000000)
|
||||
elif stype == "tsk":
|
||||
name = parts[1]
|
||||
cmd = "/enable" if action == "enable" else "/disable"
|
||||
subprocess.run(["schtasks", "/change", "/tn", name, cmd], capture_output=True, creationflags=0x08000000)
|
||||
if action == "delete":
|
||||
subprocess.run(["schtasks", "/delete", "/tn", name, "/f"], capture_output=True, creationflags=0x08000000)
|
||||
else:
|
||||
cmd = "/enable" if action == "enable" else "/disable"
|
||||
subprocess.run(["schtasks", "/change", "/tn", name, cmd], capture_output=True, creationflags=0x08000000)
|
||||
except Exception as e:
|
||||
self.write_log("WARN", "manage_startup", detail=str(e), success=False)
|
||||
|
||||
@@ -1398,7 +1585,8 @@ class WindowAPI:
|
||||
current_time = time.time()
|
||||
if current_time - last_update >= 0.05:
|
||||
if self._window:
|
||||
self._window.evaluate_js(f"if(window.updateScanProgress) window.updateScanProgress({json.dumps(norm_path.replace(os.sep, '/'))});")
|
||||
js_cmd = f"if(window.updateScanProgress) window.updateScanProgress({json.dumps(norm_path.replace(os.sep, '/'))});"
|
||||
self.ui_queue.put(js_cmd)
|
||||
last_update = current_time
|
||||
|
||||
was_locked = False
|
||||
@@ -1418,7 +1606,9 @@ class WindowAPI:
|
||||
result = self.safe_scan_engine(norm_path)
|
||||
if result:
|
||||
with self.lock_virus: self.virus_results.append(norm_path)
|
||||
if self._window: self._window.evaluate_js(f"if(window.addVirusResult) window.addVirusResult({json.dumps(result)}, {json.dumps(norm_path.replace(os.sep, '/'))});")
|
||||
if self._window:
|
||||
js_cmd = f"if(window.addVirusResult) window.addVirusResult({json.dumps(result)}, {json.dumps(norm_path.replace(os.sep, '/'))});"
|
||||
self.ui_queue.put(js_cmd)
|
||||
self.write_log("SCAN", "Virus Detected", source=norm_path, file_hash=self.calc_file_hash(norm_path))
|
||||
|
||||
self.cloud_check(norm_path)
|
||||
@@ -1445,7 +1635,9 @@ class WindowAPI:
|
||||
"russian_switch": f"Найдено {count} вирусов, проверено {scanned} файлов, время {elapsed}с",
|
||||
"slovenian_switch": f"Najdenih {count} virusov, skeniranih {scanned} datotek, čas {elapsed}s"
|
||||
}
|
||||
if self._window: self._window.evaluate_js(f"if(window.finishScan) window.finishScan({json.dumps(messages)}, {count});")
|
||||
if self._window:
|
||||
js_cmd = f"if(window.finishScan) window.finishScan({json.dumps(messages)}, {count});"
|
||||
self.ui_queue.put(js_cmd)
|
||||
self.write_log("INFO", "Scan Completed", detail=f"Found {count} viruses, scanned {scanned} files, time {elapsed}s")
|
||||
|
||||
def stop_scan(self):
|
||||
@@ -1596,11 +1788,34 @@ class WindowAPI:
|
||||
####################################################################################################
|
||||
|
||||
def is_in_whitelist(self, file_path):
|
||||
p = self.norm_path(file_path)
|
||||
if not p: return False
|
||||
with self.lock_config: whitelist = self.pyas_config.get("white_list", [])
|
||||
p = self.norm_path(file_path, must_exist=False)
|
||||
if not p:
|
||||
return False
|
||||
|
||||
p_norm = os.path.normcase(p)
|
||||
return any(os.path.normcase(item.get("file", "")) == p_norm for item in whitelist if isinstance(item, dict))
|
||||
|
||||
with self.lock_config:
|
||||
whitelist = self.pyas_config.get("white_list", [])
|
||||
|
||||
for item in whitelist:
|
||||
if isinstance(item, dict):
|
||||
wl_path = item.get("file", "")
|
||||
wl_norm = self.norm_path(wl_path, must_exist=False)
|
||||
if not wl_norm:
|
||||
continue
|
||||
|
||||
wl_norm = os.path.normcase(wl_norm)
|
||||
|
||||
if p_norm == wl_norm:
|
||||
return True
|
||||
|
||||
if not wl_norm.endswith(os.sep):
|
||||
wl_norm += os.sep
|
||||
|
||||
if p_norm.startswith(wl_norm):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def init_whitelist(self):
|
||||
self.manage_named_list("white_list", [self.file_pyas], action="add")
|
||||
@@ -1618,30 +1833,60 @@ class WindowAPI:
|
||||
try: return self.fltlib.FilterSendMessage(self.driver_port, ctypes.byref(msg), ctypes.sizeof(msg), None, 0, ctypes.byref(bytes_returned)) == 0
|
||||
except Exception: return False
|
||||
|
||||
def lock_file(self, file, lock):
|
||||
def lock_file(self, target_path, lock):
|
||||
with self.lock_file_ops:
|
||||
try:
|
||||
if lock:
|
||||
if file not in self.virus_lock:
|
||||
fd = os.open(file, os.O_RDWR | os.O_BINARY)
|
||||
if lock:
|
||||
if not os.path.exists(target_path):
|
||||
return
|
||||
|
||||
paths_to_lock = []
|
||||
if os.path.isdir(target_path):
|
||||
for root, _, files in os.walk(target_path):
|
||||
for f in files:
|
||||
paths_to_lock.append(os.path.join(root, f))
|
||||
else:
|
||||
paths_to_lock.append(target_path)
|
||||
|
||||
for file_path in paths_to_lock:
|
||||
if file_path in self.virus_lock:
|
||||
continue
|
||||
try:
|
||||
fd = os.open(file_path, os.O_RDWR | os.O_BINARY)
|
||||
try:
|
||||
try: size = os.path.getsize(file)
|
||||
except Exception: size = 1
|
||||
try:
|
||||
size = os.path.getsize(file_path)
|
||||
except Exception:
|
||||
size = 1
|
||||
lock_size = size if size > 0 else 1
|
||||
msvcrt.locking(fd, msvcrt.LK_NBRLCK, lock_size)
|
||||
self.virus_lock[file] = (fd, lock_size)
|
||||
self.virus_lock[file_path] = (fd, lock_size)
|
||||
except Exception:
|
||||
os.close(fd)
|
||||
raise
|
||||
else:
|
||||
if file in self.virus_lock:
|
||||
fd, lock_size = self.virus_lock[file]
|
||||
try: msvcrt.locking(fd, msvcrt.LK_UNLCK, lock_size)
|
||||
finally:
|
||||
except Exception as e:
|
||||
self.write_log("WARN", "lock_file", source=file_path, detail=str(e), success=False)
|
||||
else:
|
||||
target_norm = os.path.normcase(target_path)
|
||||
target_dir = target_norm + os.sep
|
||||
keys_to_unlock = []
|
||||
|
||||
for locked_path in self.virus_lock:
|
||||
locked_norm = os.path.normcase(locked_path)
|
||||
if locked_norm == target_norm or locked_norm.startswith(target_dir):
|
||||
keys_to_unlock.append(locked_path)
|
||||
|
||||
for file_path in keys_to_unlock:
|
||||
fd, lock_size = self.virus_lock[file_path]
|
||||
try:
|
||||
msvcrt.locking(fd, msvcrt.LK_UNLCK, lock_size)
|
||||
except Exception as e:
|
||||
self.write_log("WARN", "unlock_file", source=file_path, detail=str(e), success=False)
|
||||
finally:
|
||||
try:
|
||||
os.close(fd)
|
||||
del self.virus_lock[file]
|
||||
except Exception as e:
|
||||
self.write_log("WARN", "lock_file", source=file, detail=str(e), success=False)
|
||||
except Exception:
|
||||
pass
|
||||
del self.virus_lock[file_path]
|
||||
|
||||
def relock_file(self):
|
||||
with self.lock_config: quarantine_list = self.pyas_config.get("quarantine", [])
|
||||
@@ -2019,12 +2264,13 @@ class WindowAPI:
|
||||
return True
|
||||
|
||||
def popup_intercept_thread(self):
|
||||
WNDENUMPROC = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.c_int, ctypes.c_int)
|
||||
hwnd_list = []
|
||||
def enum_windows_callback(hWnd, lParam):
|
||||
if self.user32.IsWindowVisible(hWnd): hwnd_list.append(hWnd)
|
||||
return True
|
||||
enum_cb = WNDENUMPROC(enum_windows_callback)
|
||||
|
||||
WNDENUMPROC = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.c_int, ctypes.c_int)
|
||||
self._enum_cb_keepalive = WNDENUMPROC(enum_windows_callback)
|
||||
|
||||
while True:
|
||||
try:
|
||||
@@ -2033,7 +2279,8 @@ class WindowAPI:
|
||||
if not rules: continue
|
||||
|
||||
hwnd_list.clear()
|
||||
self.user32.EnumWindows(enum_cb, 0)
|
||||
self.user32.EnumWindows(self._enum_cb_keepalive, 0)
|
||||
|
||||
for hWnd in list(hwnd_list):
|
||||
pid = ctypes.c_ulong(0)
|
||||
self.user32.GetWindowThreadProcessId(hWnd, ctypes.byref(pid))
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import os, re, yara, time, math, json, numpy, base64, datetime, requests, zlib
|
||||
import os, re, yara, time, math, json, zlib, numpy, base64, requests, datetime
|
||||
import ctypes, ctypes.wintypes, hashlib, pefile, threading, onnxruntime
|
||||
|
||||
####################################################################################################
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ import pyinstaller_versionfile
|
||||
|
||||
pyinstaller_versionfile.create_versionfile(
|
||||
output_file="versionfile.txt",
|
||||
version='3.5.7.0',
|
||||
version='3.5.8.0',
|
||||
company_name="PYAS Security",
|
||||
file_description="PYAS Security Antivirus",
|
||||
internal_name="PYAS",
|
||||
|
||||
+231
-226
@@ -1,228 +1,233 @@
|
||||
{
|
||||
"Rule_Registry_BlockList": [
|
||||
"\\REGISTRY\\MACHINE\\BCD00000000",
|
||||
"\\REGISTRY\\MACHINE\\BCD00000000\\*",
|
||||
|
||||
"*\\Classes\\.exe",
|
||||
"*\\Classes\\.bat",
|
||||
"*\\Classes\\.cmd",
|
||||
"*\\Classes\\.com",
|
||||
"*\\Classes\\exefile\\*",
|
||||
"*\\Classes\\batfile\\*",
|
||||
"*\\Classes\\cmdfile\\*",
|
||||
"*\\Classes\\comfile\\*",
|
||||
|
||||
"*\\mouclass",
|
||||
"*\\kbdclass",
|
||||
"*\\DisableAntiSpyware",
|
||||
"*\\DisableWindowsUpdateAccess",
|
||||
"*\\EnableLUA",
|
||||
"*\\ConsentPromptBehaviorAdmin",
|
||||
"*\\NoControlPanel",
|
||||
"*\\NoDrives",
|
||||
"*\\NoFileMenu",
|
||||
"*\\NoFind",
|
||||
"*\\NoStartMenuPinnedList",
|
||||
"*\\NoSetFolders",
|
||||
"*\\NoSetFolderOptions",
|
||||
"*\\NoViewOnDrive",
|
||||
"*\\NoClose",
|
||||
"*\\NoDesktop",
|
||||
"*\\NoLogoff",
|
||||
"*\\NoFolderOptions",
|
||||
"*\\RestrictRun",
|
||||
"*\\NoViewContextMenu",
|
||||
"*\\HideClock",
|
||||
"*\\NoStartMenuMyGames",
|
||||
"*\\NoStartMenuMyMusic",
|
||||
"*\\DisableCMD",
|
||||
"*\\NoAddingComponents",
|
||||
"*\\NoWinKeys",
|
||||
"*\\NoStartMenuLogOff",
|
||||
"*\\NoSimpleNetIDList",
|
||||
"*\\NoLowDiskSpaceChecks",
|
||||
"*\\DisableLockWorkstation",
|
||||
"*\\Restrict_Run",
|
||||
"*\\DisableTaskMgr",
|
||||
"*\\DisableRegistryTools",
|
||||
"*\\DisableChangePassword",
|
||||
"*\\NoComponents",
|
||||
"*\\NoStartMenuMorePrograms",
|
||||
"*\\NoActiveDesktop",
|
||||
"*\\NoSetActiveDesktop",
|
||||
"*\\NoRecentDocsMenu",
|
||||
"*\\NoWindowsUpdate",
|
||||
"*\\NoChangeStartMenu",
|
||||
"*\\NoFavoritesMenu",
|
||||
"*\\NoRecentDocsHistory",
|
||||
"*\\NoSetTaskbar",
|
||||
"*\\NoSMHelp",
|
||||
"*\\NoTrayContextMenu",
|
||||
"*\\NoManageMyComputerVerb",
|
||||
"*\\NoRealMode",
|
||||
"*\\NoRun",
|
||||
"*\\ClearRecentDocsOnExit",
|
||||
"*\\NoActiveDesktopChanges",
|
||||
"*\\NoStartMenuNetworkPlaces",
|
||||
"*\\NoLockScreen",
|
||||
"*\\HideFastUserSwitching",
|
||||
"*\\ConsentPromptBehaviorUser",
|
||||
"*\\EnableSecureUIAPaths",
|
||||
"*\\NoSRM",
|
||||
"*\\NoInteractiveServices",
|
||||
"*\\ShutdownWithoutLogon",
|
||||
"*\\AutoAdminLogon",
|
||||
"*\\BootExecute",
|
||||
"*\\SubSystems",
|
||||
"*\\FirmwareBootDevice",
|
||||
"*\\BootDriverFlags",
|
||||
"*\\SystemStartOptions",
|
||||
"*\\DisableAutomaticRestartOnFailure",
|
||||
"*\\SystemBiosVersion",
|
||||
"*\\NoTheme",
|
||||
"*\\SystemSetupInProgress",
|
||||
"*\\SetupType",
|
||||
"*\\AutoReboot",
|
||||
"*\\Userinit",
|
||||
"*\\UIHost",
|
||||
"*\\Debugger",
|
||||
"*\\DefaultUserName",
|
||||
"*\\DefaultPassword",
|
||||
"*\\AltDefaultUserName",
|
||||
"*\\AltDefaultPassword",
|
||||
"*\\DisableCAD",
|
||||
"*\\LegalNoticeCaption",
|
||||
"*\\LegalNoticeText",
|
||||
],
|
||||
"Rule_Registry_TrustedList": [
|
||||
],
|
||||
"Rule_Process_TrustedPaths": [
|
||||
"\\Device\\HarddiskVolume*\\Windows\\*",
|
||||
"\\Device\\HarddiskVolume*\\Program Files\\*",
|
||||
"\\Device\\HarddiskVolume*\\Program Files (x86)\\*",
|
||||
|
||||
"\\Device\\HarddiskVolume*\\ProgramData\\Microsoft\\Windows Defender\\*",
|
||||
"\\Device\\HarddiskVolume*\\ProgramData\\Microsoft\\Windows Defender Advanced Threat Protection\\*",
|
||||
"*\\Sources\\SetupHost.exe",
|
||||
"*\\Work\\*\\DismHost.exe",
|
||||
|
||||
"*\\Google\\Chrome\\Application\\chrome.exe",
|
||||
"*\\Microsoft\\Edge\\Application\\msedge.exe",
|
||||
"*\\Mozilla Firefox\\firefox.exe",
|
||||
"*\\Thorium\\Application\\thorium.exe",
|
||||
|
||||
"*\\Steam\\steam.exe",
|
||||
"*\\steam\\*\\steam.exe",
|
||||
"*\\Battle.net\\*\\Battle.net.exe",
|
||||
"*\\Epic Games\\Launcher\\Portal\\Binaries\\*\\EpicGamesLauncher.exe",
|
||||
|
||||
"*\\resources\\bin\\SDK\\DownloadSDKServer.exe",
|
||||
"*\\ThunderEv.exe",
|
||||
"*\\ThunderStart.exe",
|
||||
"*\\KuGou.exe",
|
||||
"*\\XLGame.exe",
|
||||
"*\\XLLiveUD.exe",
|
||||
|
||||
"*\\hrkill-*.exe",
|
||||
"*\\bin\\HipsDaemon.exe",
|
||||
"*\\360Safe.exe",
|
||||
"*\\bilibili\\bilibili.exe",
|
||||
|
||||
"*\\Kingsoft\\WPS Office\\ksolaunch.exe",
|
||||
"*\\Kingsoft\\WPS Office\\*\\wps.exe",
|
||||
|
||||
"*\\PC4399_WPFLauncher.exe",
|
||||
"*\\bin\\APlayer.exe",
|
||||
"*\\Neverness To Everness\\NTELauncher.exe",
|
||||
"*\\Application\\AndrowsLauncher.exe",
|
||||
"*\\bin\\*\\codex.exe",
|
||||
"*\\bin\\codex.exe",
|
||||
],
|
||||
"Rule_Process_ExploitableBlacklist": [
|
||||
"*\\cmd.exe",
|
||||
"*\\powershell.exe",
|
||||
"*\\pwsh.exe",
|
||||
"*\\wscript.exe",
|
||||
"*\\cscript.exe",
|
||||
"*\\mshta.exe",
|
||||
"*\\regsvr32.exe",
|
||||
"*\\certutil.exe",
|
||||
"*\\bitsadmin.exe",
|
||||
"*\\wmic.exe",
|
||||
"*\\hh.exe",
|
||||
"*\\cmstp.exe",
|
||||
"*\\installutil.exe",
|
||||
"*\\regasm.exe",
|
||||
"*\\regsvcs.exe",
|
||||
"*\\msbuild.exe",
|
||||
"*\\csc.exe",
|
||||
"*\\vbc.exe",
|
||||
"*\\jsc.exe",
|
||||
"*\\bash.exe",
|
||||
"*\\scrcons.exe",
|
||||
"*\\schtasks.exe",
|
||||
"*\\at.exe",
|
||||
"*\\reg.exe",
|
||||
"*\\sc.exe",
|
||||
"*\\net.exe",
|
||||
"*\\net1.exe",
|
||||
"*\\whoami.exe",
|
||||
"*\\ipconfig.exe",
|
||||
"*\\taskkill.exe",
|
||||
"*\\ProcessHacker.exe",
|
||||
"*\\procmon.exe",
|
||||
"*\\procexp.exe",
|
||||
],
|
||||
"Rule_File_ProtectedPaths": [
|
||||
"*\\PYAS.exe",
|
||||
"*\\Plugins\\Filter\\PYAS_Driver.sys",
|
||||
"*\\Plugins\\Rules\\Rules_Driver_P1.json",
|
||||
"*\\ProgramData\\PYAS\\*.json",
|
||||
"*\\Engine\\Pattern\\*.onnx",
|
||||
"*\\Engine\\Properties\\*.onnx",
|
||||
|
||||
"\\Device\\HarddiskVolume*\\bootmgr",
|
||||
"\\Device\\HarddiskVolume*\\boot.ini",
|
||||
"\\Device\\HarddiskVolume*\\BOOTNXT",
|
||||
"\\Device\\HarddiskVolume*\\EFI\\*",
|
||||
"\\Device\\HarddiskVolume*\\Boot\\*",
|
||||
"\\Device\\HarddiskVolume*\\Recovery\\*",
|
||||
"\\Device\\HarddiskVolume*\\System Volume Information\\*",
|
||||
"\\Device\\HarddiskVolume*\\Windows\\System32\\config\\*",
|
||||
|
||||
"*\\CON",
|
||||
"*\\CON\\*",
|
||||
"*\\PRN",
|
||||
"*\\PRN\\*",
|
||||
"*\\AUX",
|
||||
"*\\AUX\\*",
|
||||
"*\\NUL",
|
||||
"*\\NUL\\*",
|
||||
"*\\COM?",
|
||||
"*\\COM?\\*",
|
||||
"*\\LPT?",
|
||||
"*\\LPT?\\*",
|
||||
"*\\OSDATA",
|
||||
"*\\OSDATA\\*",
|
||||
"*\\*<*",
|
||||
"*\\*>*",
|
||||
],
|
||||
"Rule_File_ExceptionPaths": [
|
||||
"*\\Users\\*\\steam\\*",
|
||||
"*\\AppData\\*",
|
||||
"*\\Temp\\*",
|
||||
"*\\Local\\Temp\\*",
|
||||
"*\\ventoy\\Boot\\*",
|
||||
"*\\AdminRegionConfig.*",
|
||||
"*\\nt_qq\\nt_*\\*",
|
||||
"*\\cache\\*",
|
||||
],
|
||||
"Rule_File_RansomwareExtensions": [
|
||||
".zip", ".7z", ".rar", ".tar", ".gz",
|
||||
".ppt", ".pptx", ".wps", ".txt", ".rtf",
|
||||
".pdf", ".xls", ".xlsx", ".doc", ".docx",
|
||||
".jpg", ".jpeg", ".png", ".webp", ".gif",
|
||||
".mp3", ".wav", ".aac", ".ogg", ".flac",
|
||||
".mp4", ".avi", ".mov", ".wmv", ".mkv",
|
||||
]
|
||||
"Rule_Registry_BlockList": [
|
||||
"\\REGISTRY\\MACHINE\\BCD00000000",
|
||||
"\\REGISTRY\\MACHINE\\BCD00000000\\*",
|
||||
|
||||
"*\\Classes\\.exe",
|
||||
"*\\Classes\\.bat",
|
||||
"*\\Classes\\.cmd",
|
||||
"*\\Classes\\.com",
|
||||
"*\\Classes\\exefile\\*",
|
||||
"*\\Classes\\batfile\\*",
|
||||
"*\\Classes\\cmdfile\\*",
|
||||
"*\\Classes\\comfile\\*",
|
||||
|
||||
"*\\mouclass",
|
||||
"*\\kbdclass",
|
||||
"*\\DisableAntiSpyware",
|
||||
"*\\DisableWindowsUpdateAccess",
|
||||
"*\\EnableLUA",
|
||||
"*\\ConsentPromptBehaviorAdmin",
|
||||
"*\\NoControlPanel",
|
||||
"*\\NoDrives",
|
||||
"*\\NoFileMenu",
|
||||
"*\\NoFind",
|
||||
"*\\NoStartMenuPinnedList",
|
||||
"*\\NoSetFolders",
|
||||
"*\\NoSetFolderOptions",
|
||||
"*\\NoViewOnDrive",
|
||||
"*\\NoClose",
|
||||
"*\\NoDesktop",
|
||||
"*\\NoLogoff",
|
||||
"*\\NoFolderOptions",
|
||||
"*\\RestrictRun",
|
||||
"*\\NoViewContextMenu",
|
||||
"*\\HideClock",
|
||||
"*\\NoStartMenuMyGames",
|
||||
"*\\NoStartMenuMyMusic",
|
||||
"*\\DisableCMD",
|
||||
"*\\NoAddingComponents",
|
||||
"*\\NoWinKeys",
|
||||
"*\\NoStartMenuLogOff",
|
||||
"*\\NoSimpleNetIDList",
|
||||
"*\\NoLowDiskSpaceChecks",
|
||||
"*\\DisableLockWorkstation",
|
||||
"*\\Restrict_Run",
|
||||
"*\\DisableTaskMgr",
|
||||
"*\\DisableRegistryTools",
|
||||
"*\\DisableChangePassword",
|
||||
"*\\NoComponents",
|
||||
"*\\NoStartMenuMorePrograms",
|
||||
"*\\NoActiveDesktop",
|
||||
"*\\NoSetActiveDesktop",
|
||||
"*\\NoRecentDocsMenu",
|
||||
"*\\NoWindowsUpdate",
|
||||
"*\\NoChangeStartMenu",
|
||||
"*\\NoFavoritesMenu",
|
||||
"*\\NoRecentDocsHistory",
|
||||
"*\\NoSetTaskbar",
|
||||
"*\\NoSMHelp",
|
||||
"*\\NoTrayContextMenu",
|
||||
"*\\NoManageMyComputerVerb",
|
||||
"*\\NoRealMode",
|
||||
"*\\NoRun",
|
||||
"*\\ClearRecentDocsOnExit",
|
||||
"*\\NoActiveDesktopChanges",
|
||||
"*\\NoStartMenuNetworkPlaces",
|
||||
"*\\NoLockScreen",
|
||||
"*\\HideFastUserSwitching",
|
||||
"*\\ConsentPromptBehaviorUser",
|
||||
"*\\EnableSecureUIAPaths",
|
||||
"*\\NoSRM",
|
||||
"*\\NoInteractiveServices",
|
||||
"*\\ShutdownWithoutLogon",
|
||||
"*\\AutoAdminLogon",
|
||||
"*\\BootExecute",
|
||||
"*\\SubSystems",
|
||||
"*\\FirmwareBootDevice",
|
||||
"*\\BootDriverFlags",
|
||||
"*\\SystemStartOptions",
|
||||
"*\\DisableAutomaticRestartOnFailure",
|
||||
"*\\SystemBiosVersion",
|
||||
"*\\NoTheme",
|
||||
"*\\SystemSetupInProgress",
|
||||
"*\\SetupType",
|
||||
"*\\AutoReboot",
|
||||
"*\\Userinit",
|
||||
"*\\UIHost",
|
||||
"*\\Debugger",
|
||||
"*\\DefaultUserName",
|
||||
"*\\DefaultPassword",
|
||||
"*\\AltDefaultUserName",
|
||||
"*\\AltDefaultPassword",
|
||||
"*\\DisableCAD",
|
||||
"*\\LegalNoticeCaption",
|
||||
"*\\LegalNoticeText",
|
||||
],
|
||||
"Rule_Registry_TrustedList": [
|
||||
],
|
||||
"Rule_Process_TrustedPaths": [
|
||||
"\\Device\\HarddiskVolume*\\Windows\\*",
|
||||
"\\Device\\HarddiskVolume*\\Program Files\\*",
|
||||
"\\Device\\HarddiskVolume*\\Program Files (x86)\\*",
|
||||
|
||||
"\\Device\\HarddiskVolume*\\ProgramData\\Microsoft\\Windows Defender\\*",
|
||||
"\\Device\\HarddiskVolume*\\ProgramData\\Microsoft\\Windows Defender Advanced Threat Protection\\*",
|
||||
"*\\Sources\\SetupHost.exe",
|
||||
"*\\Work\\*\\DismHost.exe",
|
||||
|
||||
"*\\Google\\Chrome\\Application\\chrome.exe",
|
||||
"*\\Microsoft\\Edge\\Application\\msedge.exe",
|
||||
"*\\Mozilla Firefox\\firefox.exe",
|
||||
"*\\Thorium\\Application\\thorium.exe",
|
||||
|
||||
"*\\Steam\\steam.exe",
|
||||
"*\\steam\\*\\steam.exe",
|
||||
"*\\Battle.net\\*\\Battle.net.exe",
|
||||
"*\\Epic Games\\Launcher\\Portal\\Binaries\\*\\EpicGamesLauncher.exe",
|
||||
|
||||
"*\\resources\\bin\\SDK\\DownloadSDKServer.exe",
|
||||
"*\\ThunderEv.exe",
|
||||
"*\\ThunderStart.exe",
|
||||
"*\\KuGou.exe",
|
||||
"*\\XLGame.exe",
|
||||
"*\\XLLiveUD.exe",
|
||||
|
||||
"*\\hrkill-*.exe",
|
||||
"*\\bin\\HipsDaemon.exe",
|
||||
"*\\360Safe.exe",
|
||||
"*\\bilibili\\bilibili.exe",
|
||||
|
||||
"*\\Kingsoft\\WPS Office\\ksolaunch.exe",
|
||||
"*\\Kingsoft\\WPS Office\\*\\wps.exe",
|
||||
"*\\Kingsoft\\WPS Office\\*\\*.exe",
|
||||
|
||||
"*\\PC4399_WPFLauncher.exe",
|
||||
"*\\bin\\APlayer.exe",
|
||||
"*\\Neverness To Everness\\NTELauncher.exe",
|
||||
"*\\Application\\AndrowsLauncher.exe",
|
||||
"*\\bin\\*\\codex.exe",
|
||||
"*\\bin\\codex.exe",
|
||||
],
|
||||
"Rule_Process_ExploitableBlacklist": [
|
||||
"*\\cmd.exe",
|
||||
"*\\powershell.exe",
|
||||
"*\\pwsh.exe",
|
||||
"*\\wscript.exe",
|
||||
"*\\cscript.exe",
|
||||
"*\\mshta.exe",
|
||||
"*\\regsvr32.exe",
|
||||
"*\\certutil.exe",
|
||||
"*\\bitsadmin.exe",
|
||||
"*\\wmic.exe",
|
||||
"*\\hh.exe",
|
||||
"*\\cmstp.exe",
|
||||
"*\\installutil.exe",
|
||||
"*\\regasm.exe",
|
||||
"*\\regsvcs.exe",
|
||||
"*\\msbuild.exe",
|
||||
"*\\csc.exe",
|
||||
"*\\vbc.exe",
|
||||
"*\\jsc.exe",
|
||||
"*\\bash.exe",
|
||||
"*\\scrcons.exe",
|
||||
"*\\schtasks.exe",
|
||||
"*\\at.exe",
|
||||
"*\\reg.exe",
|
||||
"*\\sc.exe",
|
||||
"*\\net.exe",
|
||||
"*\\net1.exe",
|
||||
"*\\whoami.exe",
|
||||
"*\\ipconfig.exe",
|
||||
"*\\taskkill.exe",
|
||||
"*\\ProcessHacker.exe",
|
||||
"*\\procmon.exe",
|
||||
"*\\procexp.exe",
|
||||
],
|
||||
"Rule_File_ProtectedPaths": [
|
||||
"*\\PYAS.exe",
|
||||
"*\\Plugins\\Filter\\PYAS_Driver.sys",
|
||||
"*\\Plugins\\Rules\\Rules_Driver_P1.json",
|
||||
"*\\ProgramData\\PYAS\\*.json",
|
||||
"*\\Engine\\Pattern\\*.onnx",
|
||||
"*\\Engine\\Properties\\*.onnx",
|
||||
|
||||
"\\Device\\HarddiskVolume*\\bootmgr",
|
||||
"\\Device\\HarddiskVolume*\\boot.ini",
|
||||
"\\Device\\HarddiskVolume*\\BOOTNXT",
|
||||
"\\Device\\HarddiskVolume*\\EFI\\*",
|
||||
"\\Device\\HarddiskVolume*\\Boot\\*",
|
||||
"\\Device\\HarddiskVolume*\\Recovery\\*",
|
||||
"\\Device\\HarddiskVolume*\\System Volume Information\\*",
|
||||
"\\Device\\HarddiskVolume*\\Windows\\System32\\config\\*",
|
||||
|
||||
"*\\CON",
|
||||
"*\\CON\\*",
|
||||
"*\\PRN",
|
||||
"*\\PRN\\*",
|
||||
"*\\AUX",
|
||||
"*\\AUX\\*",
|
||||
"*\\NUL",
|
||||
"*\\NUL\\*",
|
||||
"*\\COM?",
|
||||
"*\\COM?\\*",
|
||||
"*\\LPT?",
|
||||
"*\\LPT?\\*",
|
||||
"*\\OSDATA",
|
||||
"*\\OSDATA\\*",
|
||||
"*\\*<*",
|
||||
"*\\*>*",
|
||||
],
|
||||
"Rule_File_ExceptionPaths": [
|
||||
"*\\Users\\*\\steam\\*",
|
||||
"*\\AppData\\*",
|
||||
"*\\Temp\\*",
|
||||
"*\\Local\\Temp\\*",
|
||||
"*\\ventoy\\Boot\\*",
|
||||
"*\\AdminRegionConfig.*",
|
||||
"*\\nt_qq\\nt_*\\*",
|
||||
"*\\cache\\*",
|
||||
"*\\Documents\\My Games\\*",
|
||||
"*\\Documents\\Tencent Files\\*",
|
||||
"*\\Documents\\WeChat Files\\*",
|
||||
"*\\Documents\\WPS Cloud Files\\*"
|
||||
],
|
||||
"Rule_File_RansomwareExtensions": [
|
||||
".zip", ".7z", ".rar", ".tar", ".gz",
|
||||
".ppt", ".pptx", ".wps", ".txt", ".rtf",
|
||||
".pdf", ".xls", ".xlsx", ".doc", ".docx",
|
||||
".jpg", ".jpeg", ".png", ".webp", ".gif",
|
||||
".mp3", ".wav", ".aac", ".ogg", ".flac",
|
||||
".mp4", ".avi", ".mov", ".wmv", ".mkv",
|
||||
]
|
||||
}
|
||||
Reference in new issue
Block a user